perf: faster plugin updates, half-size first bundle, images from the chat attach on Windows
- Chat view: an attached image's path is pasted on its own after the text (promptForPane). claude turns a paste that is only an image path into [Image #n], but left a Windows path inside a paste of text as a plain path. Other files and @-mentions stay in the text as before. - Plugin bootstrap: depsHash covers only what npm installs (no release version), so a version bump no longer reinstalls runtime deps; the client's installed tree is kept while its manifests are unchanged (no npm ci per update); the user-side build runs vite only (tsc -b cost ~25 s / ~900 MB); clientBuild is recorded only after a build that did not fail, so a failed one is retried; npm output goes to runtime/npm-install.log. - Server: a port held by another program ends with a clear message and exit 1 instead of an uncaught 'error' stack trace. - Client: the onboarding wizard is lazy and rendered only before onboarding; usePrefersReducedMotion moved to hooks/ so PetSettings no longer pulls the Sagi chat/pane stack into the entry chunk (884 KB -> 431 KB, gzip 268 -> 133 KB).
This commit is contained in:
+30
-7
@@ -33,6 +33,20 @@ if (process.env.GIT_EDITOR === "true") delete process.env.GIT_EDITOR;
|
||||
// server/lib/settings-env.js. Only when this
|
||||
// file IS the process: the test suite requires it dozens of times, and a
|
||||
// developer's real settings file pins DASHBOARD_DATA_DIR at their live database.
|
||||
/** What to tell the user when the dashboard cannot bind its port. The health
|
||||
* probe above already turned away a port held by a running dashboard, so a
|
||||
* port in use here belongs to some other program. */
|
||||
function listenFailure(err, port) {
|
||||
if (err?.code === "EADDRINUSE")
|
||||
return (
|
||||
`Port ${port} is already in use by another program, so AgentHub cannot start there. ` +
|
||||
`Stop that program, or run AgentHub on another port with DASHBOARD_PORT (for example DASHBOARD_PORT=4821).`
|
||||
);
|
||||
if (err?.code === "EACCES")
|
||||
return `Not allowed to listen on port ${port}. Pick a port above 1024 with DASHBOARD_PORT.`;
|
||||
return `AgentHub could not start its server: ${err?.stack || err}`;
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
const settingsEnv = require("./lib/settings-env");
|
||||
settingsEnv.loadEnvFiles({
|
||||
@@ -337,8 +351,12 @@ function startServer(app, port) {
|
||||
const host = resolveHost();
|
||||
const boundLoopback = isLoopbackHostname(host);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// A port another program holds fails here, not as an uncaught 'error'
|
||||
// event: the caller says what happened instead of a bare stack trace.
|
||||
server.once("error", reject);
|
||||
server.listen(port, host, () => {
|
||||
server.off("error", reject);
|
||||
// Publish the live port so the Claude Code hook handler can find this
|
||||
// server even when it bound a non-default port (the desktop app falls
|
||||
// back off 4820 when that port is already taken).
|
||||
@@ -1210,12 +1228,17 @@ if (require.main === module) {
|
||||
return;
|
||||
}
|
||||
const app = createApp();
|
||||
startServer(app, PORT).then((server) => {
|
||||
httpServer = server;
|
||||
startBackgroundServices();
|
||||
// The status-area icon (server/lib/tray.js) — production servers only.
|
||||
require("./lib/tray").startTrayWatch();
|
||||
});
|
||||
startServer(app, PORT)
|
||||
.then((server) => {
|
||||
httpServer = server;
|
||||
startBackgroundServices();
|
||||
// The status-area icon (server/lib/tray.js) — production servers only.
|
||||
require("./lib/tray").startTrayWatch();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(listenFailure(err, PORT));
|
||||
process.exit(1);
|
||||
});
|
||||
});
|
||||
|
||||
// Graceful shutdown — close connections and DB cleanly
|
||||
|
||||
Reference in New Issue
Block a user