@seqyuan/annovibe 0.8.12 → 0.8.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +8 -5
- package/.next/build-manifest.json +3 -3
- package/.next/prerender-manifest.json +3 -3
- package/.next/react-loadable-manifest.json +6 -6
- package/.next/required-server-files.js +1 -1
- package/.next/required-server-files.json +1 -1
- package/.next/routes-manifest.json +18 -0
- package/.next/server/app/_global-error/page.js +3 -3
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page.js +2 -2
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +2 -2
- package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/api/agent/[id]/events/route.js +2 -2
- package/.next/server/app/api/agent/[id]/route.js +1 -1
- package/.next/server/app/api/agent/new/route.js +1 -1
- package/.next/server/app/api/auth/all-providers/route.js +1 -1
- package/.next/server/app/api/auth/api-key/[provider]/route.js +1 -1
- package/.next/server/app/api/auth/login/[provider]/route.js +2 -2
- package/.next/server/app/api/auth/login/route.js +1 -1
- package/.next/server/app/api/auth/logout/[provider]/route.js +1 -1
- package/.next/server/app/api/auth/providers/route.js +1 -1
- package/.next/server/app/api/auth/status/route.js +1 -1
- package/.next/server/app/api/default-cwd/route.js +1 -1
- package/.next/server/app/api/files/[...path]/route.js +2 -2
- package/.next/server/app/api/harness/route.js +1 -1
- package/.next/server/app/api/home/route.js +1 -1
- package/.next/server/app/api/internal/runtime/route.js +1 -0
- package/.next/server/app/api/internal/runtime/route.js.nft.json +1 -0
- package/.next/server/app/api/internal/runtime/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/models/route.js +1 -1
- package/.next/server/app/api/models-config/discover/route.js +1 -1
- package/.next/server/app/api/models-config/route.js +1 -1
- package/.next/server/app/api/models-config/test/route.js +1 -1
- package/.next/server/app/api/plot-kernels/route.js +1 -1
- package/.next/server/app/api/plot-kernels/status/route.js +1 -1
- package/.next/server/app/api/plot-kernels/stop/route.js +1 -1
- package/.next/server/app/api/projects/browse/route.js +1 -0
- package/.next/server/app/api/projects/browse/route.js.nft.json +1 -0
- package/.next/server/app/api/projects/browse/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/projects/route.js +3 -0
- package/.next/server/app/api/projects/route.js.nft.json +1 -0
- package/.next/server/app/api/projects/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/reports/[id]/route.js +7 -4
- package/.next/server/app/api/search/route.js +2 -2
- package/.next/server/app/api/sessions/[id]/context/route.js +2 -2
- package/.next/server/app/api/sessions/[id]/route.js +1 -1
- package/.next/server/app/api/sessions/new/route.js +1 -1
- package/.next/server/app/api/sessions/route.js +2 -2
- package/.next/server/app/api/settings/route.js +1 -1
- package/.next/server/app/api/skills/install/route.js +1 -1
- package/.next/server/app/api/skills/route.js +2 -2
- package/.next/server/app/api/skills/search/route.js +1 -1
- package/.next/server/app/api/soul/route.js +1 -1
- package/.next/server/app/api/version/route.js +1 -1
- package/.next/server/app/favicon.ico/route.js +1 -1
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +3 -3
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login/page.js +2 -2
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login.html +1 -1
- package/.next/server/app/login.rsc +2 -2
- package/.next/server/app/login.segments/_full.segment.rsc +2 -2
- package/.next/server/app/login.segments/_head.segment.rsc +1 -1
- package/.next/server/app/login.segments/_index.segment.rsc +2 -2
- package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/login.segments/login.segment.rsc +1 -1
- package/.next/server/app/page.js +13 -13
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +8 -5
- package/.next/server/chunks/1688.js +45 -0
- package/.next/server/chunks/7601.js +54 -12
- package/.next/server/chunks/static/media/pdf.worker.min.c476e1a0.mjs +6 -0
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/QvZYZknhDLA2wQJwpT60o/_buildManifest.js +1 -0
- package/.next/static/chunks/51fb665c.9f0b013f33bf4f6d.js +45 -0
- package/.next/static/chunks/8771-3e14b6810486df1f.js +1 -0
- package/.next/static/chunks/app/_global-error/page-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/events/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/agent/new/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/auth/all-providers/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/auth/api-key/[provider]/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/auth/login/[provider]/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/auth/login/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/auth/logout/[provider]/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/auth/providers/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/auth/status/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/default-cwd/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/files/[...path]/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/harness/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/home/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/internal/runtime/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/models/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/models-config/discover/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/models-config/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/models-config/test/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/plot-kernels/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/plot-kernels/status/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/plot-kernels/stop/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/projects/browse/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/projects/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/reports/[id]/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/search/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/context/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/sessions/new/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/sessions/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/settings/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/skills/install/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/skills/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/skills/search/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/soul/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/api/version/route-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/app/page-e0ad11ee7003214a.js +270 -0
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-7222ee8be0d45596.js +1 -0
- package/.next/static/chunks/{webpack-5e677f60fa366b60.js → webpack-c223a77d0c5e1b9e.js} +1 -1
- package/.next/static/css/8026433d69e690e2.css +3 -0
- package/.next/static/media/pdf.worker.min.29aaf158.mjs +6 -0
- package/.next/trace +75 -74
- package/.next/trace-build +1 -1
- package/.next/types/app/api/internal/runtime/route.ts +351 -0
- package/.next/types/app/api/projects/browse/route.ts +351 -0
- package/.next/types/app/api/projects/route.ts +351 -0
- package/.next/types/routes.d.ts +4 -1
- package/.next/types/validator.ts +27 -0
- package/README.md +2 -0
- package/bin/pi-web.js +293 -16
- package/package.json +1 -1
- package/.next/server/chunks/7270.js +0 -45
- package/.next/server/chunks/static/media/pdf.worker.min.9df6854a.mjs +0 -6
- package/.next/static/chunks/7355-29eaa714eb390050.js +0 -1
- package/.next/static/chunks/9b0008ae.2918095672924572.js +0 -45
- package/.next/static/chunks/app/_global-error/page-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/events/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/agent/new/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/auth/all-providers/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/auth/api-key/[provider]/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/auth/login/[provider]/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/auth/login/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/auth/logout/[provider]/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/auth/providers/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/auth/status/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/default-cwd/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/files/[...path]/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/harness/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/home/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/models/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/models-config/discover/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/models-config/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/models-config/test/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/plot-kernels/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/plot-kernels/status/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/plot-kernels/stop/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/reports/[id]/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/search/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/context/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/sessions/new/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/sessions/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/settings/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/skills/install/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/skills/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/skills/search/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/soul/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/api/version/route-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/app/page-dc03bbb33a1d438c.js +0 -270
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-3edd3886076a73cb.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-3edd3886076a73cb.js +0 -1
- package/.next/static/css/d830cdea1c9a03c6.css +0 -3
- package/.next/static/ixA4-CDguO8ne_SD2W8sd/_buildManifest.js +0 -1
- package/.next/static/media/pdf.worker.min.5f98222a.mjs +0 -6
- /package/.next/static/{ixA4-CDguO8ne_SD2W8sd → QvZYZknhDLA2wQJwpT60o}/_ssgManifest.js +0 -0
package/bin/pi-web.js
CHANGED
|
@@ -12,6 +12,10 @@ const fs = require("fs");
|
|
|
12
12
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
13
13
|
const os = require("os");
|
|
14
14
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
15
|
+
const http = require("http");
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
17
|
+
const net = require("net");
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
15
19
|
const readline = require("readline");
|
|
16
20
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
17
21
|
const { parseArgs } = require("util");
|
|
@@ -19,6 +23,8 @@ const { parseArgs } = require("util");
|
|
|
19
23
|
const bcrypt = require("bcryptjs");
|
|
20
24
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
21
25
|
const https = require("https");
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
27
|
+
const { randomBytes } = require("crypto");
|
|
22
28
|
|
|
23
29
|
const pkgDir = path.join(__dirname, "..");
|
|
24
30
|
const nextDir = path.join(pkgDir, ".next");
|
|
@@ -35,6 +41,12 @@ const STOP_TERM_TIMEOUT_MS = 6000;
|
|
|
35
41
|
const STOP_KILL_TIMEOUT_MS = 2000;
|
|
36
42
|
const PROCESS_TITLE = "annovibe";
|
|
37
43
|
const NEXT_PROCESS_TITLE = "annovibe-next";
|
|
44
|
+
const AUTO_RESTART_ENABLED = !/^(0|false|no)$/i.test(process.env.ANNOVIBE_AUTO_RESTART ?? "1");
|
|
45
|
+
const AUTO_RESTART_POLL_MS = parsePositiveInt(process.env.ANNOVIBE_AUTO_RESTART_POLL_MS, 60_000);
|
|
46
|
+
const AUTO_RESTART_IDLE_GRACE_MS = parsePositiveInt(process.env.ANNOVIBE_AUTO_RESTART_IDLE_GRACE_MS, 10_000);
|
|
47
|
+
const AUTO_RESTART_MAX_WAIT_MS = parsePositiveInt(process.env.ANNOVIBE_AUTO_RESTART_MAX_WAIT_MS, 30 * 60_000);
|
|
48
|
+
const AUTO_RESTART_WAIT_FOR_PORT_MS = parsePositiveInt(process.env.ANNOVIBE_AUTO_RESTART_WAIT_FOR_PORT_MS, 30_000);
|
|
49
|
+
const INTERNAL_RUNTIME_TIMEOUT_MS = 3000;
|
|
38
50
|
|
|
39
51
|
// Resolve next's CLI entry
|
|
40
52
|
let nextBin;
|
|
@@ -79,10 +91,132 @@ function getUrl(host, listenPort) {
|
|
|
79
91
|
return `http://${host ?? "localhost"}:${listenPort}`;
|
|
80
92
|
}
|
|
81
93
|
|
|
94
|
+
function getServerArgs() {
|
|
95
|
+
return [getCommandPath(), "__server", "--port", String(port), ...(hostname ? ["--hostname", hostname] : [])];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function getServerCommand() {
|
|
99
|
+
return `${getCommandPath()} __server --port ${port}${hostname ? ` --hostname ${hostname}` : ""}`;
|
|
100
|
+
}
|
|
101
|
+
|
|
82
102
|
function nowIso() {
|
|
83
103
|
return new Date().toISOString();
|
|
84
104
|
}
|
|
85
105
|
|
|
106
|
+
function parsePositiveInt(value, fallback) {
|
|
107
|
+
const n = Number(value);
|
|
108
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : fallback;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function sleep(ms) {
|
|
112
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function readPackageVersion(packageDir) {
|
|
116
|
+
try {
|
|
117
|
+
const installedPkg = JSON.parse(fs.readFileSync(path.join(packageDir, "package.json"), "utf8"));
|
|
118
|
+
return typeof installedPkg.version === "string" ? installedPkg.version : null;
|
|
119
|
+
} catch {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function getInstalledPackageDir() {
|
|
125
|
+
try {
|
|
126
|
+
return path.resolve(path.dirname(fs.realpathSync(getCommandPath())), "..");
|
|
127
|
+
} catch {
|
|
128
|
+
return pkgDir;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function readInstalledVersion() {
|
|
133
|
+
const dirs = [getInstalledPackageDir(), pkgDir];
|
|
134
|
+
for (const dir of dirs) {
|
|
135
|
+
const version = readPackageVersion(dir);
|
|
136
|
+
if (version) return version;
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function getRuntimeConnectHost(host) {
|
|
142
|
+
if (!host || host === "0.0.0.0") return "127.0.0.1";
|
|
143
|
+
if (host === "::" || host === "[::]") return "::1";
|
|
144
|
+
return String(host).replace(/^\[(.*)\]$/, "$1");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function canBindPort(listenPort, host) {
|
|
148
|
+
return new Promise((resolve) => {
|
|
149
|
+
const server = net.createServer();
|
|
150
|
+
let settled = false;
|
|
151
|
+
const done = (available) => {
|
|
152
|
+
if (settled) return;
|
|
153
|
+
settled = true;
|
|
154
|
+
resolve(available);
|
|
155
|
+
};
|
|
156
|
+
server.unref();
|
|
157
|
+
server.once("error", () => done(false));
|
|
158
|
+
server.once("listening", () => {
|
|
159
|
+
server.close(() => done(true));
|
|
160
|
+
});
|
|
161
|
+
server.listen(Number(listenPort), host ? String(host) : undefined);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async function waitForPortAvailable(listenPort, host, timeoutMs) {
|
|
166
|
+
const startedAt = Date.now();
|
|
167
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
168
|
+
if (await canBindPort(listenPort, host)) return true;
|
|
169
|
+
await sleep(250);
|
|
170
|
+
}
|
|
171
|
+
return canBindPort(listenPort, host);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function fetchRuntimeStatus(internalToken) {
|
|
175
|
+
return new Promise((resolve) => {
|
|
176
|
+
let settled = false;
|
|
177
|
+
const finish = (status) => {
|
|
178
|
+
if (settled) return;
|
|
179
|
+
settled = true;
|
|
180
|
+
resolve(status);
|
|
181
|
+
};
|
|
182
|
+
const req = http.request({
|
|
183
|
+
hostname: getRuntimeConnectHost(hostname),
|
|
184
|
+
port: Number(port),
|
|
185
|
+
path: "/api/internal/runtime",
|
|
186
|
+
method: "GET",
|
|
187
|
+
timeout: INTERNAL_RUNTIME_TIMEOUT_MS,
|
|
188
|
+
headers: {
|
|
189
|
+
"x-annovibe-internal-token": internalToken,
|
|
190
|
+
},
|
|
191
|
+
}, (res) => {
|
|
192
|
+
if (res.statusCode !== 200) {
|
|
193
|
+
res.resume();
|
|
194
|
+
finish(null);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
let data = "";
|
|
198
|
+
res.setEncoding("utf8");
|
|
199
|
+
res.on("data", (chunk) => {
|
|
200
|
+
data += chunk;
|
|
201
|
+
if (data.length > 1024 * 1024) req.destroy();
|
|
202
|
+
});
|
|
203
|
+
res.on("end", () => {
|
|
204
|
+
try {
|
|
205
|
+
finish(JSON.parse(data));
|
|
206
|
+
} catch {
|
|
207
|
+
finish(null);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
req.on("error", () => finish(null));
|
|
212
|
+
req.on("timeout", () => {
|
|
213
|
+
req.destroy();
|
|
214
|
+
finish(null);
|
|
215
|
+
});
|
|
216
|
+
req.end();
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
86
220
|
function setStableProcessTitle(title) {
|
|
87
221
|
process.title = title;
|
|
88
222
|
try {
|
|
@@ -338,6 +472,10 @@ function renderState(state, json = false) {
|
|
|
338
472
|
supervisorPid: supervisorAlive ? state.supervisorPid : null,
|
|
339
473
|
nextPid: nextAlive ? state.nextPid : null,
|
|
340
474
|
startedAt: supervisorAlive ? state.startedAt ?? null : null,
|
|
475
|
+
restartPending: !!state?.restartPending,
|
|
476
|
+
installedVersion: state?.installedVersion ?? null,
|
|
477
|
+
restartDetectedAt: state?.restartDetectedAt ?? null,
|
|
478
|
+
restartStartedAt: state?.restartStartedAt ?? null,
|
|
341
479
|
logFile,
|
|
342
480
|
stateFile,
|
|
343
481
|
};
|
|
@@ -357,6 +495,9 @@ function renderState(state, json = false) {
|
|
|
357
495
|
`supervisor pid: ${payload.supervisorPid ?? "not running"}`,
|
|
358
496
|
`next pid: ${payload.nextPid ?? "unknown"}`,
|
|
359
497
|
`started: ${payload.startedAt ?? "unknown"}`,
|
|
498
|
+
...(payload.restartPending ? [
|
|
499
|
+
`restart: pending${payload.installedVersion ? ` for v${payload.installedVersion}` : ""}`,
|
|
500
|
+
] : []),
|
|
360
501
|
`log: ${payload.logFile}`,
|
|
361
502
|
].join("\n");
|
|
362
503
|
}
|
|
@@ -433,17 +574,7 @@ async function startManagedServer({ quiet = false } = {}) {
|
|
|
433
574
|
removeState();
|
|
434
575
|
}
|
|
435
576
|
ensureAgentDir();
|
|
436
|
-
const
|
|
437
|
-
const child = spawn(process.execPath, [getCommandPath(), "__server", "--port", String(port), ...(hostname ? ["--hostname", hostname] : [])], {
|
|
438
|
-
cwd: pkgDir,
|
|
439
|
-
detached: true,
|
|
440
|
-
stdio: ["ignore", fd, fd],
|
|
441
|
-
env: {
|
|
442
|
-
...process.env,
|
|
443
|
-
ANNOVIBE_MANAGED: "1",
|
|
444
|
-
},
|
|
445
|
-
});
|
|
446
|
-
fs.closeSync(fd);
|
|
577
|
+
const child = spawnDetachedServer();
|
|
447
578
|
if (!child.pid) {
|
|
448
579
|
throw new Error("failed to start annovibe server");
|
|
449
580
|
}
|
|
@@ -451,7 +582,7 @@ async function startManagedServer({ quiet = false } = {}) {
|
|
|
451
582
|
const state = {
|
|
452
583
|
schemaVersion: 1,
|
|
453
584
|
version: VERSION,
|
|
454
|
-
command:
|
|
585
|
+
command: getServerCommand(),
|
|
455
586
|
supervisorPid: child.pid,
|
|
456
587
|
nextPid: null,
|
|
457
588
|
port: String(port),
|
|
@@ -470,6 +601,23 @@ async function startManagedServer({ quiet = false } = {}) {
|
|
|
470
601
|
return 0;
|
|
471
602
|
}
|
|
472
603
|
|
|
604
|
+
function spawnDetachedServer(extraEnv = {}) {
|
|
605
|
+
ensureAgentDir();
|
|
606
|
+
const fd = fs.openSync(logFile, "a");
|
|
607
|
+
const child = spawn(process.execPath, getServerArgs(), {
|
|
608
|
+
cwd: fs.existsSync(getInstalledPackageDir()) ? getInstalledPackageDir() : pkgDir,
|
|
609
|
+
detached: true,
|
|
610
|
+
stdio: ["ignore", fd, fd],
|
|
611
|
+
env: {
|
|
612
|
+
...process.env,
|
|
613
|
+
ANNOVIBE_MANAGED: "1",
|
|
614
|
+
...extraEnv,
|
|
615
|
+
},
|
|
616
|
+
});
|
|
617
|
+
fs.closeSync(fd);
|
|
618
|
+
return child;
|
|
619
|
+
}
|
|
620
|
+
|
|
473
621
|
if (cliArgs.version) {
|
|
474
622
|
console.log(VERSION);
|
|
475
623
|
process.exit(0);
|
|
@@ -500,6 +648,7 @@ Options:
|
|
|
500
648
|
Environment:
|
|
501
649
|
PORT Server port
|
|
502
650
|
ANNOVIBE_PASSWORD Set password on first start
|
|
651
|
+
ANNOVIBE_AUTO_RESTART Set 0/false/no to disable idle auto-restart after update
|
|
503
652
|
PI_CODING_AGENT_DIR Custom pi agent data directory
|
|
504
653
|
`);
|
|
505
654
|
process.exit(0);
|
|
@@ -718,6 +867,115 @@ function openBrowser(url) {
|
|
|
718
867
|
openChild.unref();
|
|
719
868
|
}
|
|
720
869
|
|
|
870
|
+
function startAutoRestartWatcher({ child, internalToken, writeCurrentState, markRestarting }) {
|
|
871
|
+
if (!AUTO_RESTART_ENABLED) return () => {};
|
|
872
|
+
|
|
873
|
+
let pending = null;
|
|
874
|
+
let idleSince = null;
|
|
875
|
+
let restarting = false;
|
|
876
|
+
let lastWaitLogAt = 0;
|
|
877
|
+
|
|
878
|
+
const poll = async () => {
|
|
879
|
+
if (restarting) return;
|
|
880
|
+
const installedVersion = readInstalledVersion();
|
|
881
|
+
if (!installedVersion || installedVersion === VERSION) {
|
|
882
|
+
if (pending) {
|
|
883
|
+
pending = null;
|
|
884
|
+
idleSince = null;
|
|
885
|
+
writeCurrentState({ restartPending: false, installedVersion: null, restartDetectedAt: null, restartStartedAt: null });
|
|
886
|
+
}
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
if (!pending || pending.installedVersion !== installedVersion) {
|
|
891
|
+
pending = {
|
|
892
|
+
installedVersion,
|
|
893
|
+
detectedAt: nowIso(),
|
|
894
|
+
detectedAtMs: Date.now(),
|
|
895
|
+
};
|
|
896
|
+
idleSince = null;
|
|
897
|
+
lastWaitLogAt = 0;
|
|
898
|
+
console.log(`annovibe auto-restart: detected installed version ${installedVersion}; current runtime is ${VERSION}`);
|
|
899
|
+
writeCurrentState({
|
|
900
|
+
restartPending: true,
|
|
901
|
+
installedVersion,
|
|
902
|
+
restartDetectedAt: pending.detectedAt,
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
const status = await fetchRuntimeStatus(internalToken);
|
|
907
|
+
if (!status || typeof status.busy !== "boolean") {
|
|
908
|
+
idleSince = null;
|
|
909
|
+
if (Date.now() - lastWaitLogAt >= 5 * 60_000) {
|
|
910
|
+
lastWaitLogAt = Date.now();
|
|
911
|
+
console.log("annovibe auto-restart: waiting for runtime status before restarting");
|
|
912
|
+
}
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
if (status.busy) {
|
|
917
|
+
idleSince = null;
|
|
918
|
+
const waitedMs = Date.now() - pending.detectedAtMs;
|
|
919
|
+
if (Date.now() - lastWaitLogAt >= 5 * 60_000) {
|
|
920
|
+
lastWaitLogAt = Date.now();
|
|
921
|
+
const busyCount = Array.isArray(status.busySessions) ? status.busySessions.length : 0;
|
|
922
|
+
const suffix = waitedMs >= AUTO_RESTART_MAX_WAIT_MS ? "; max wait reached, still waiting for graceful idle" : "";
|
|
923
|
+
console.log(`annovibe auto-restart: update pending, waiting for ${busyCount} busy session${busyCount === 1 ? "" : "s"}${suffix}`);
|
|
924
|
+
}
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
idleSince ??= Date.now();
|
|
929
|
+
if (Date.now() - idleSince < AUTO_RESTART_IDLE_GRACE_MS) return;
|
|
930
|
+
|
|
931
|
+
restarting = true;
|
|
932
|
+
let replacement;
|
|
933
|
+
try {
|
|
934
|
+
replacement = spawnDetachedServer({
|
|
935
|
+
ANNOVIBE_NO_OPEN: "1",
|
|
936
|
+
ANNOVIBE_WAIT_FOR_PORT: "1",
|
|
937
|
+
});
|
|
938
|
+
} catch (error) {
|
|
939
|
+
console.error(`annovibe auto-restart: failed to start replacement supervisor: ${error instanceof Error ? error.message : String(error)}`);
|
|
940
|
+
restarting = false;
|
|
941
|
+
return;
|
|
942
|
+
}
|
|
943
|
+
if (!replacement.pid) {
|
|
944
|
+
console.error("annovibe auto-restart: failed to start replacement supervisor");
|
|
945
|
+
restarting = false;
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
markRestarting();
|
|
949
|
+
writeCurrentState({
|
|
950
|
+
restartPending: true,
|
|
951
|
+
installedVersion: pending.installedVersion,
|
|
952
|
+
restartDetectedAt: pending.detectedAt,
|
|
953
|
+
restartStartedAt: nowIso(),
|
|
954
|
+
});
|
|
955
|
+
console.log(`annovibe auto-restart: installed ${VERSION} -> ${pending.installedVersion}; restarting now`);
|
|
956
|
+
replacement.unref();
|
|
957
|
+
console.log(`annovibe auto-restart: replacement supervisor pid ${replacement.pid}`);
|
|
958
|
+
|
|
959
|
+
if (!(await terminatePid(child.pid))) {
|
|
960
|
+
console.error(`annovibe auto-restart: failed to stop old next pid ${child.pid}`);
|
|
961
|
+
restarting = false;
|
|
962
|
+
markRestarting(false);
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
process.exit(0);
|
|
966
|
+
};
|
|
967
|
+
|
|
968
|
+
const timer = setInterval(() => {
|
|
969
|
+
poll().catch((error) => {
|
|
970
|
+
console.error(`annovibe auto-restart: ${error instanceof Error ? error.message : String(error)}`);
|
|
971
|
+
});
|
|
972
|
+
}, AUTO_RESTART_POLL_MS);
|
|
973
|
+
timer.unref();
|
|
974
|
+
|
|
975
|
+
poll().catch(() => {});
|
|
976
|
+
return () => clearInterval(timer);
|
|
977
|
+
}
|
|
978
|
+
|
|
721
979
|
async function runServerProcess() {
|
|
722
980
|
setStableProcessTitle(PROCESS_TITLE);
|
|
723
981
|
await maybeSetupAuth();
|
|
@@ -728,26 +986,37 @@ async function runServerProcess() {
|
|
|
728
986
|
|
|
729
987
|
checkVersion();
|
|
730
988
|
|
|
989
|
+
if (process.env.ANNOVIBE_WAIT_FOR_PORT === "1") {
|
|
990
|
+
const available = await waitForPortAvailable(port, hostname, AUTO_RESTART_WAIT_FOR_PORT_MS);
|
|
991
|
+
if (!available) {
|
|
992
|
+
console.error(`annovibe server: port ${port} was not released within ${AUTO_RESTART_WAIT_FOR_PORT_MS}ms`);
|
|
993
|
+
process.exit(1);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
|
|
731
997
|
const url = getUrl(hostname, port);
|
|
732
998
|
const nextArgs = [getCommandPath(), "__next", "--port", String(port)];
|
|
733
999
|
if (hostname) nextArgs.push("--hostname", hostname);
|
|
1000
|
+
const internalToken = process.env.ANNOVIBE_INTERNAL_TOKEN || randomBytes(24).toString("hex");
|
|
734
1001
|
|
|
735
1002
|
const child = spawn(process.execPath, nextArgs, {
|
|
736
1003
|
cwd: pkgDir,
|
|
737
1004
|
stdio: ["ignore", "pipe", "pipe"],
|
|
738
1005
|
env: {
|
|
739
1006
|
...process.env,
|
|
1007
|
+
ANNOVIBE_INTERNAL_TOKEN: internalToken,
|
|
740
1008
|
ANNOVIBE_SUPERVISOR_PID: String(process.pid),
|
|
741
1009
|
ANNOVIBE_NEXT_WRAPPER: "1",
|
|
742
1010
|
},
|
|
743
1011
|
});
|
|
1012
|
+
let restarting = false;
|
|
744
1013
|
|
|
745
1014
|
const writeCurrentState = (patch = {}) => {
|
|
746
1015
|
const current = readState() ?? {};
|
|
747
1016
|
writeState({
|
|
748
1017
|
schemaVersion: 1,
|
|
749
1018
|
version: VERSION,
|
|
750
|
-
command:
|
|
1019
|
+
command: getServerCommand(),
|
|
751
1020
|
supervisorPid: process.pid,
|
|
752
1021
|
nextPid: child.pid ?? null,
|
|
753
1022
|
port: String(port),
|
|
@@ -761,6 +1030,12 @@ async function runServerProcess() {
|
|
|
761
1030
|
};
|
|
762
1031
|
|
|
763
1032
|
writeCurrentState();
|
|
1033
|
+
const stopAutoRestartWatcher = startAutoRestartWatcher({
|
|
1034
|
+
child,
|
|
1035
|
+
internalToken,
|
|
1036
|
+
writeCurrentState,
|
|
1037
|
+
markRestarting: (value = true) => { restarting = value; },
|
|
1038
|
+
});
|
|
764
1039
|
|
|
765
1040
|
let browserOpened = false;
|
|
766
1041
|
child.stdout.on("data", (chunk) => {
|
|
@@ -768,7 +1043,7 @@ async function runServerProcess() {
|
|
|
768
1043
|
process.stdout.write(text);
|
|
769
1044
|
if (!browserOpened && text.includes("Ready")) {
|
|
770
1045
|
browserOpened = true;
|
|
771
|
-
openBrowser(url);
|
|
1046
|
+
if (process.env.ANNOVIBE_NO_OPEN !== "1") openBrowser(url);
|
|
772
1047
|
console.log(`\n annovibe running at ${url}\n`);
|
|
773
1048
|
writeCurrentState({ readyAt: nowIso() });
|
|
774
1049
|
}
|
|
@@ -776,15 +1051,17 @@ async function runServerProcess() {
|
|
|
776
1051
|
child.stderr.on("data", (chunk) => process.stderr.write(chunk));
|
|
777
1052
|
|
|
778
1053
|
const shutdown = async () => {
|
|
1054
|
+
stopAutoRestartWatcher();
|
|
779
1055
|
await terminatePid(child.pid);
|
|
780
|
-
removeState();
|
|
1056
|
+
if (!restarting) removeState();
|
|
781
1057
|
process.exit(0);
|
|
782
1058
|
};
|
|
783
1059
|
process.on("SIGTERM", () => { void shutdown(); });
|
|
784
1060
|
process.on("SIGINT", () => { void shutdown(); });
|
|
785
1061
|
|
|
786
1062
|
child.on("exit", (code) => {
|
|
787
|
-
|
|
1063
|
+
stopAutoRestartWatcher();
|
|
1064
|
+
if (!restarting) removeState();
|
|
788
1065
|
process.exit(code ?? 0);
|
|
789
1066
|
});
|
|
790
1067
|
}
|