@covro/covro 0.2.0-beta.1 → 0.2.0
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/README.md +21 -9
- package/README.zh-CN.md +21 -9
- package/dist/cli/background.js +103 -0
- package/dist/cli/background.js.map +7 -0
- package/dist/cli/daemon.js +6 -1
- package/dist/cli/daemon.js.map +2 -2
- package/dist/cli/doctor.js +92 -0
- package/dist/cli/doctor.js.map +7 -0
- package/dist/cli/launch-environment.js +85 -0
- package/dist/cli/launch-environment.js.map +7 -0
- package/dist/cli/launchd.js +172 -0
- package/dist/cli/launchd.js.map +7 -0
- package/dist/cli/main.js +7 -35
- package/dist/cli/main.js.map +2 -2
- package/dist/cli/service.js +23 -49
- package/dist/cli/service.js.map +2 -2
- package/dist/codex/adapter.js +68 -1
- package/dist/codex/adapter.js.map +2 -2
- package/dist/server/auth.js +1 -1
- package/dist/server/auth.js.map +2 -2
- package/dist/server/http.js +21 -0
- package/dist/server/http.js.map +2 -2
- package/dist/server/service.js +17 -2
- package/dist/server/service.js.map +2 -2
- package/dist/update-worker.cjs +419 -168
- package/dist/updates/worker.js +7 -61
- package/dist/updates/worker.js.map +2 -2
- package/dist/web/assets/index-B9_AU2Fw.js +140 -0
- package/dist/web/assets/index-BmbPtei8.css +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +6 -4
- package/dist/web/assets/index-Dr0Qkixk.css +0 -1
- package/dist/web/assets/index-z5RGzL8u.js +0 -138
package/dist/updates/worker.js
CHANGED
|
@@ -7,77 +7,23 @@ import { execFile } from "node:child_process";
|
|
|
7
7
|
import { promisify } from "node:util";
|
|
8
8
|
import { createRequire } from "node:module";
|
|
9
9
|
import { createHash } from "node:crypto";
|
|
10
|
-
import { access, readFile, mkdir,
|
|
10
|
+
import { access, readFile, mkdir, readdir, rm, rename } from "node:fs/promises";
|
|
11
11
|
import { constants } from "node:fs";
|
|
12
12
|
import { dirname, join } from "node:path";
|
|
13
13
|
import { setTimeout } from "node:timers/promises";
|
|
14
|
-
import { spawn } from "node:child_process";
|
|
15
|
-
import { homedir } from "node:os";
|
|
16
14
|
import lockfile from "proper-lockfile";
|
|
17
|
-
import { control, isNotRunning
|
|
15
|
+
import { control, isNotRunning } from "../cli/control.js";
|
|
16
|
+
import { startBackground, stopBackground } from "../cli/background.js";
|
|
18
17
|
import { copyDurable, readJson, saveJson } from "./files.js";
|
|
19
18
|
import { activateUpdate, transactionPaths } from "./transaction.js";
|
|
20
19
|
import { inspectInstallation, registry } from "./registry.js";
|
|
21
20
|
const exec = promisify(execFile);
|
|
22
21
|
const message = (error) => error instanceof Error ? error.message : String(error);
|
|
23
|
-
async function startService(context
|
|
24
|
-
|
|
25
|
-
join(context.location.state, "service.json")
|
|
26
|
-
);
|
|
27
|
-
if (installed) {
|
|
28
|
-
if (installed.platform === "darwin")
|
|
29
|
-
await exec("launchctl", [
|
|
30
|
-
"bootstrap",
|
|
31
|
-
`gui/${process.getuid()}`,
|
|
32
|
-
join(homedir(), "Library/LaunchAgents", `${installed.label}.plist`)
|
|
33
|
-
]);
|
|
34
|
-
else await exec("systemctl", ["--user", "start", `${installed.label}.service`]);
|
|
35
|
-
} else {
|
|
36
|
-
const log = await open(context.location.log, "a", 384);
|
|
37
|
-
try {
|
|
38
|
-
const child = spawn(
|
|
39
|
-
process.execPath,
|
|
40
|
-
[join(context.root, "bin/covro.mjs"), "run", "--config", context.location.config],
|
|
41
|
-
{
|
|
42
|
-
detached: true,
|
|
43
|
-
stdio: ["ignore", log.fd, log.fd],
|
|
44
|
-
windowsHide: true,
|
|
45
|
-
env: {
|
|
46
|
-
...process.env,
|
|
47
|
-
COVRO_HOME: context.location.home,
|
|
48
|
-
...activation ? { COVRO_ACTIVATING: activation } : {}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
);
|
|
52
|
-
await new Promise((done, reject) => {
|
|
53
|
-
child.once("spawn", done);
|
|
54
|
-
child.once("error", reject);
|
|
55
|
-
});
|
|
56
|
-
child.unref();
|
|
57
|
-
} finally {
|
|
58
|
-
await log.close();
|
|
59
|
-
}
|
|
60
|
-
}
|
|
22
|
+
async function startService(context) {
|
|
23
|
+
await startBackground(context.location, join(context.root, "bin/covro.mjs"));
|
|
61
24
|
}
|
|
62
25
|
async function stopService(context) {
|
|
63
|
-
await
|
|
64
|
-
const installed = await readJson(
|
|
65
|
-
join(context.location.state, "service.json")
|
|
66
|
-
);
|
|
67
|
-
if (installed?.platform === "linux")
|
|
68
|
-
await exec("systemctl", ["--user", "stop", `${installed.label}.service`]);
|
|
69
|
-
else if (installed?.platform === "darwin") {
|
|
70
|
-
const target = `gui/${process.getuid()}/${installed.label}`;
|
|
71
|
-
try {
|
|
72
|
-
await exec("launchctl", ["bootout", target]);
|
|
73
|
-
} catch (error) {
|
|
74
|
-
const stillLoaded = await exec("launchctl", ["print", target]).then(
|
|
75
|
-
() => true,
|
|
76
|
-
() => false
|
|
77
|
-
);
|
|
78
|
-
if (stillLoaded) throw error;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
26
|
+
await stopBackground(context.location);
|
|
81
27
|
}
|
|
82
28
|
async function verifyRestoredService(context, version) {
|
|
83
29
|
for (let attempt = 0; attempt < 240; attempt++) {
|
|
@@ -289,7 +235,7 @@ async function worker(directory) {
|
|
|
289
235
|
},
|
|
290
236
|
stop: () => stopService(context),
|
|
291
237
|
start: async (candidate2) => {
|
|
292
|
-
await startService(context
|
|
238
|
+
await startService(context);
|
|
293
239
|
if (!candidate2) await verifyRestoredService(context, record.from);
|
|
294
240
|
},
|
|
295
241
|
verify: async () => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/updates/worker.ts"],
|
|
4
|
-
"sourcesContent": ["import { npmPackageName } from '../shared/package.js';\nimport {\n codexCompatibilitySchema,\n requireCodexCompatibility,\n} from '../shared/codex-compatibility.js';\n// Bundled with its pure JavaScript dependencies and copied outside the installation before launch.\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { createRequire } from 'node:module';\nimport { createHash } from 'node:crypto';\nimport { access, readFile, mkdir, open, readdir, rm, rename } from 'node:fs/promises';\nimport { constants } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { setTimeout } from 'node:timers/promises';\nimport { spawn } from 'node:child_process';\nimport { homedir } from 'node:os';\nimport lockfile from 'proper-lockfile';\nimport type Database from 'better-sqlite3';\nimport type { UpdateRun } from '../shared/updates.js';\nimport type { UpdateContext } from './manager.js';\nimport { control, isNotRunning, stopAndWait } from '../cli/control.js';\nimport { copyDurable, readJson, saveJson } from './files.js';\nimport { activateUpdate, transactionPaths } from './transaction.js';\nimport { inspectInstallation, registry } from './registry.js';\n\nconst exec = promisify(execFile);\nconst message = (error: unknown) => (error instanceof Error ? error.message : String(error));\ntype DaemonStatus = {\n version: string;\n pid: number;\n maintenance?: boolean;\n codexVersion?: string | null;\n codexReady?: boolean;\n};\n\nasync function startService(context: UpdateContext, activation?: string) {\n const installed = await readJson<{ platform: string; label: string }>(\n join(context.location.state, 'service.json'),\n );\n if (installed) {\n // The activation run is durable; a service does not need to inherit transient shell variables.\n if (installed.platform === 'darwin')\n await exec('launchctl', [\n 'bootstrap',\n `gui/${process.getuid!()}`,\n join(homedir(), 'Library/LaunchAgents', `${installed.label}.plist`),\n ]);\n else await exec('systemctl', ['--user', 'start', `${installed.label}.service`]);\n } else {\n const log = await open(context.location.log, 'a', 0o600);\n try {\n const child = spawn(\n process.execPath,\n [join(context.root, 'bin/covro.mjs'), 'run', '--config', context.location.config],\n {\n detached: true,\n stdio: ['ignore', log.fd, log.fd],\n windowsHide: true,\n env: {\n ...process.env,\n COVRO_HOME: context.location.home,\n ...(activation ? { COVRO_ACTIVATING: activation } : {}),\n },\n },\n );\n await new Promise<void>((done, reject) => {\n child.once('spawn', done);\n child.once('error', reject);\n });\n child.unref();\n } finally {\n await log.close();\n }\n }\n}\nasync function stopService(context: UpdateContext) {\n await stopAndWait(context.location);\n const installed = await readJson<{ platform: string; label: string }>(\n join(context.location.state, 'service.json'),\n );\n if (installed?.platform === 'linux')\n await exec('systemctl', ['--user', 'stop', `${installed.label}.service`]);\n else if (installed?.platform === 'darwin') {\n const target = `gui/${process.getuid!()}/${installed.label}`;\n try {\n await exec('launchctl', ['bootout', target]);\n } catch (error) {\n const stillLoaded = await exec('launchctl', ['print', target]).then(\n () => true,\n () => false,\n );\n if (stillLoaded) throw error;\n }\n }\n}\n\nasync function verifyRestoredService(context: UpdateContext, version: string) {\n for (let attempt = 0; attempt < 240; attempt++) {\n try {\n const restored = await control<DaemonStatus>(context.location, 'status');\n if (restored.version !== version || restored.maintenance)\n throw new Error('\u65E7\u7248\u6062\u590D\u8EAB\u4EFD\u4E0D\u5339\u914D');\n return;\n } catch (error) {\n if (attempt === 239) throw error;\n }\n await setTimeout(250);\n }\n}\n\nasync function verifyMigrations(context: UpdateContext, candidate: string) {\n // Loading the existing native addon happens before any package path is replaced.\n const require = createRequire(join(context.root, 'package.json'));\n const Sqlite = require('better-sqlite3') as typeof Database;\n const filename = join(context.dataDir, 'app.sqlite');\n try {\n await access(filename);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return;\n throw error;\n }\n const db = new Sqlite(filename, { readonly: true, fileMustExist: true });\n try {\n const table = db\n .prepare(\"SELECT name FROM sqlite_master WHERE name = '__drizzle_migrations'\")\n .get();\n if (!table) return;\n const applied = db\n .prepare('SELECT hash FROM __drizzle_migrations ORDER BY created_at')\n .all() as { hash: string }[];\n const journal = JSON.parse(\n await readFile(join(candidate, 'dist/drizzle/meta/_journal.json'), 'utf8'),\n ) as { entries: { tag: string }[] };\n const hashes = await Promise.all(\n journal.entries.map(async (entry) => {\n if (!/^[a-zA-Z0-9_-]+$/.test(entry.tag)) throw new Error('\u5019\u9009\u5305\u5305\u542B\u65E0\u6548\u8FC1\u79FB\u8DEF\u5F84');\n return createHash('sha256')\n .update(await readFile(join(candidate, 'dist/drizzle', `${entry.tag}.sql`)))\n .digest('hex');\n }),\n );\n if (applied.some((entry, i) => entry.hash !== hashes[i]))\n throw new Error('\u76EE\u6807\u7248\u672C\u4E0D\u517C\u5BB9\u5F53\u524D\u6570\u636E\u5E93\u8FC1\u79FB\u5386\u53F2\u3002\u8BF7\u7B49\u5F85\u517C\u5BB9\u7248\u672C\uFF0C\u6216\u4F7F\u7528\u72EC\u7ACB\u6D4B\u8BD5\u6570\u636E\u76EE\u5F55\u3002');\n } finally {\n db.close();\n }\n}\n\nasync function worker(directory: string) {\n await mkdir(directory, { recursive: true, mode: 0o700 });\n const release = await lockfile.lock(directory, {\n stale: 10_000,\n update: 2_000,\n retries: { retries: 30, minTimeout: 100, maxTimeout: 500 },\n });\n let record = await readJson<UpdateRun>(join(directory, 'run.json'));\n const context = await readJson<UpdateContext>(join(directory, 'context.json'));\n if (!record || !context) {\n await release();\n throw new Error('\u7F3A\u5C11\u5347\u7EA7\u8BB0\u5F55');\n }\n const update = async (phase: UpdateRun['phase'], detail: string) => {\n record = { ...record!, phase, message: detail, updatedAt: Date.now() };\n await saveJson(join(directory, 'run.json'), record);\n };\n const paths = transactionPaths(\n context.root,\n record.id,\n context.dataDir,\n context.location.config,\n join(directory, `backup-${record.id}`),\n );\n try {\n if (process.argv[3] === '--repair') {\n const active = await control<DaemonStatus>(context.location, 'status').catch(\n (error: unknown) => {\n if (isNotRunning(error)) return undefined;\n throw error;\n },\n );\n if (record.committed) return;\n if (active && !active.maintenance && active.version !== record.from)\n throw new Error('\u5F53\u524D\u670D\u52A1\u53EF\u80FD\u5DF2\u63A5\u53D7\u65B0\u7248\u4E1A\u52A1\u6570\u636E\uFF1B\u62D2\u7EDD\u6062\u590D\u65E7\u5FEB\u7167\uFF0C\u8BF7\u4F7F\u7528\u517C\u5BB9\u7248\u672C\u68C0\u67E5\u3002');\n const previous = await readJson<{ version: string; name: string }>(\n join(paths.previous, 'package.json'),\n );\n if (previous) {\n if (active && !active.maintenance)\n throw new Error('\u65E7\u670D\u52A1\u5DF2\u6062\u590D\u4E1A\u52A1\u5199\u5165\uFF1B\u62D2\u7EDD\u7528\u5347\u7EA7\u524D\u5FEB\u7167\u8986\u76D6\u73B0\u6709\u6570\u636E\uFF0C\u8BF7\u4FDD\u7559\u73B0\u573A\u68C0\u67E5\u3002');\n if (previous.name !== npmPackageName || previous.version !== record.from)\n throw new Error('\u65E7\u7248\u5907\u4EFD\u8EAB\u4EFD\u4E0D\u5339\u914D');\n const snapshot = await readJson<{ complete: boolean }>(join(paths.backup, 'snapshot.json'));\n if (!snapshot?.complete) throw new Error('\u6570\u636E\u5E93\u5907\u4EFD\u4E0D\u5B8C\u6574\uFF0C\u4FDD\u7559\u5168\u90E8\u73B0\u573A\u4F9B\u68C0\u67E5');\n } else {\n const original = await readJson<{ name: string; version: string }>(\n join(paths.root, 'package.json'),\n );\n if (original?.name !== npmPackageName || original.version !== record.from)\n throw new Error('\u672A\u627E\u5230\u5B8C\u6574\u7684\u4E0A\u4E00\u7248\u672C\u5B89\u88C5');\n }\n if (active && !active.maintenance) {\n const admission = await control<{ ready: boolean }>(context.location, 'prepare-update');\n if (!admission.ready) throw new Error('\u4ECD\u6709\u4EFB\u52A1\u3001\u5BA1\u6279\u6216\u5F85\u6838\u5BF9\u64CD\u4F5C\uFF0C\u4E0D\u80FD\u6062\u590D\u65E7\u5B89\u88C5');\n }\n await stopService(context);\n if (previous) {\n await rm(paths.root, { recursive: true, force: true });\n await rename(paths.previous, paths.root);\n for (const name of ['app.sqlite', 'app.sqlite-wal', 'app.sqlite-shm']) {\n await rm(join(paths.dataDir, name), { force: true });\n try {\n await copyDurable(join(paths.backup, name), join(paths.dataDir, name));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n }\n await copyDurable(join(paths.backup, 'config.json'), paths.config);\n }\n const restored = await readJson<{ name: string; version: string }>(\n join(paths.root, 'package.json'),\n );\n if (restored?.name !== npmPackageName || restored.version !== record.from)\n throw new Error('\u672A\u627E\u5230\u5B8C\u6574\u7684\u4E0A\u4E00\u7248\u672C\u5B89\u88C5');\n await update('rolledBack', '\u5DF2\u6062\u590D\u4E0A\u6B21\u672A\u5B8C\u6210\u7684\u5347\u7EA7\uFF0C\u6B63\u5728\u542F\u52A8\u4E0A\u4E00\u7248\u672C');\n try {\n await startService(context);\n await verifyRestoredService(context, record.from);\n await update('rolledBack', '\u5DF2\u6062\u590D\u4E0A\u6B21\u672A\u5B8C\u6210\u7684\u5347\u7EA7\uFF0C\u4E0A\u4E00\u7248\u672C\u5DF2\u5C31\u7EEA');\n } catch (error) {\n await update('failed', `\u65E7\u7248\u6062\u590D\u542F\u52A8\u5931\u8D25\uFF0C\u4FDD\u7559\u5907\u4EFD\uFF1A${message(error)}`);\n throw error;\n }\n return;\n }\n const reason = await inspectInstallation(context.root);\n if (reason) throw new Error(reason);\n // A second managed configuration must be stopped before replacing their shared npm package.\n for (const key of await readdir(join(context.location.home, 'instances'))) {\n if (key === context.location.key) continue;\n const instance = await readJson<{ root: string; config: string; socket: string }>(\n join(context.location.home, 'instances', key, 'instance.json'),\n );\n if (instance?.root !== context.root) continue;\n try {\n await control({ ...context.location, socket: instance.socket }, 'status');\n throw new Error('\u540C\u4E00 npm \u5B89\u88C5\u8FD8\u6709\u5176\u4ED6 Covro \u5B9E\u4F8B\uFF0C\u8BF7\u5148\u505C\u6B62\u5176\u4ED6\u5B9E\u4F8B\u518D\u5347\u7EA7\u3002');\n } catch (error) {\n if (!isNotRunning(error)) throw error;\n }\n }\n await access(dirname(context.root), constants.W_OK);\n // npm global layout keeps production dependencies nested in the package being swapped.\n await exec(\n 'npm',\n [\n 'install',\n '--global',\n '--prefix',\n paths.prefix,\n '--omit=dev',\n '--no-audit',\n '--no-fund',\n `--registry=${registry}`,\n '--allow-scripts=better-sqlite3',\n `${npmPackageName}@${record.target}`,\n ],\n { timeout: 10 * 60_000, maxBuffer: 2 * 1024 * 1024 },\n );\n const candidate = await readJson<{ name: string; version: string; covroCodex?: unknown }>(\n join(paths.candidate, 'package.json'),\n );\n if (candidate?.name !== npmPackageName || candidate.version !== record.target)\n throw new Error('\u5019\u9009\u5305\u8EAB\u4EFD\u6216\u7248\u672C\u4E0D\u5339\u914D');\n if (!record.codex) throw new Error('\u7F3A\u5C11 Codex \u5347\u7EA7\u6821\u9A8C\u8BB0\u5F55\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0');\n const manifest = codexCompatibilitySchema.parse(candidate.covroCodex);\n if (JSON.stringify(manifest) !== JSON.stringify(record.codex.manifest))\n throw new Error('\u5019\u9009\u5305\u7684 Codex \u517C\u5BB9\u58F0\u660E\u4E0E\u68C0\u67E5\u65F6\u4E0D\u4E00\u81F4\uFF0C\u62D2\u7EDD\u5207\u6362');\n const checkCodex = async (current?: DaemonStatus) => {\n const state = current ?? (await control<DaemonStatus>(context.location, 'status'));\n if (state.codexVersion !== record!.codex!.version)\n throw new Error('Codex \u7248\u672C\u5728\u7B49\u5F85\u5347\u7EA7\u671F\u95F4\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0');\n requireCodexCompatibility(\n manifest,\n state.codexVersion ?? null,\n record!.codex!.confirmedUnverified,\n );\n };\n await checkCodex();\n await exec(process.execPath, [join(paths.candidate, 'bin/covro.mjs'), '--version'], {\n timeout: 30_000,\n });\n const nativeProbe =\n 'const {createRequire}=await import(\"node:module\"); const r=createRequire(process.argv[1]); const DB=r(\"better-sqlite3\"); const db=new DB(\":memory:\"); db.close();';\n await exec(\n process.execPath,\n ['--input-type=module', '-e', nativeProbe, join(paths.candidate, 'package.json')],\n { timeout: 30_000 },\n );\n await verifyMigrations(context, paths.candidate);\n await activateUpdate(paths, {\n phase: update,\n waitForIdle: async () => {\n // Queue without blocking normal work; admission closes atomically only after all blockers clear.\n for (;;) {\n await checkCodex();\n const result = await control<{ ready: boolean; reason?: string }>(\n context.location,\n 'prepare-update',\n );\n if (result.ready) {\n await checkCodex();\n return;\n }\n await update('waiting', result.reason ?? '\u7B49\u5F85\u6240\u6709\u4EFB\u52A1\u7ED3\u675F');\n await setTimeout(2_000);\n }\n },\n stop: () => stopService(context),\n start: async (candidate) => {\n await startService(context, candidate ? record!.id : undefined);\n if (!candidate) await verifyRestoredService(context, record!.from);\n },\n verify: async () => {\n for (let attempt = 0; attempt < 240; attempt++) {\n const current = await control<DaemonStatus>(context.location, 'status').catch(\n () => undefined,\n );\n if (current) {\n if (current.version !== record!.target || !current.maintenance)\n throw new Error('\u65B0\u7248\u670D\u52A1\u8EAB\u4EFD\u6216\u7EF4\u62A4\u72B6\u6001\u4E0D\u5339\u914D');\n await checkCodex(current);\n if (current.codexReady) return;\n }\n await setTimeout(250);\n }\n throw new Error('\u65B0\u7248\u670D\u52A1\u6216 Codex \u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u62D2\u7EDD\u6FC0\u6D3B');\n },\n commit: async () => {\n // Gateway commits the durable result before reopening task admission.\n await control(context.location, 'activate-update', {\n id: record!.id,\n channel: record!.channel,\n });\n const final = await readJson<UpdateRun>(join(directory, 'run.json'));\n if (!final?.committed) throw new Error('\u65B0\u7248\u5C1A\u672A\u786E\u8BA4\u5347\u7EA7\u63D0\u4EA4');\n record = final;\n },\n hasCommitted: async () =>\n Boolean((await readJson<UpdateRun>(join(directory, 'run.json')))?.committed),\n resume: async () => {\n await control(context.location, 'cancel-update').catch(() => {});\n },\n });\n } catch (error) {\n const latest = await readJson<UpdateRun>(join(directory, 'run.json'));\n if (latest?.committed) {\n // A lost commit response cannot authorize restoring older data.\n record = latest;\n } else if (!['rolledBack', 'failed'].includes(record.phase))\n await update('failed', message(error));\n console.error(message(error));\n process.exitCode = record.committed || record.phase === 'rolledBack' ? 0 : 1;\n } finally {\n await release();\n // Keep the last good installation and database backup for explicit recovery.\n if (record.phase === 'succeeded' || record.phase === 'rolledBack') {\n await rm(paths.prefix, { recursive: true, force: true });\n }\n }\n}\n\nif (process.argv[2])\n void worker(process.argv[2]).catch((error: unknown) => {\n console.error(message(error));\n process.exitCode = 1;\n });\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,sBAAsB;AAC/B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEP,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAC1B,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB;AAC3B,SAAS,QAAQ,UAAU,OAAO,
|
|
4
|
+
"sourcesContent": ["import { npmPackageName } from '../shared/package.js';\nimport {\n codexCompatibilitySchema,\n requireCodexCompatibility,\n} from '../shared/codex-compatibility.js';\n// Bundled with its pure JavaScript dependencies and copied outside the installation before launch.\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { createRequire } from 'node:module';\nimport { createHash } from 'node:crypto';\nimport { access, readFile, mkdir, readdir, rm, rename } from 'node:fs/promises';\nimport { constants } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { setTimeout } from 'node:timers/promises';\nimport lockfile from 'proper-lockfile';\nimport type Database from 'better-sqlite3';\nimport type { UpdateRun } from '../shared/updates.js';\nimport type { UpdateContext } from './manager.js';\nimport { control, isNotRunning } from '../cli/control.js';\nimport { startBackground, stopBackground } from '../cli/background.js';\nimport { copyDurable, readJson, saveJson } from './files.js';\nimport { activateUpdate, transactionPaths } from './transaction.js';\nimport { inspectInstallation, registry } from './registry.js';\n\nconst exec = promisify(execFile);\nconst message = (error: unknown) => (error instanceof Error ? error.message : String(error));\ntype DaemonStatus = {\n version: string;\n pid: number;\n maintenance?: boolean;\n codexVersion?: string | null;\n codexReady?: boolean;\n};\n\nasync function startService(context: UpdateContext) {\n // Shared with `covro start`: never inherit a Background security session on macOS.\n // Activation is checked from the durable update record by the daemon.\n await startBackground(context.location, join(context.root, 'bin/covro.mjs'));\n}\nasync function stopService(context: UpdateContext) {\n await stopBackground(context.location);\n}\n\nasync function verifyRestoredService(context: UpdateContext, version: string) {\n for (let attempt = 0; attempt < 240; attempt++) {\n try {\n const restored = await control<DaemonStatus>(context.location, 'status');\n if (restored.version !== version || restored.maintenance)\n throw new Error('\u65E7\u7248\u6062\u590D\u8EAB\u4EFD\u4E0D\u5339\u914D');\n return;\n } catch (error) {\n if (attempt === 239) throw error;\n }\n await setTimeout(250);\n }\n}\n\nasync function verifyMigrations(context: UpdateContext, candidate: string) {\n // Loading the existing native addon happens before any package path is replaced.\n const require = createRequire(join(context.root, 'package.json'));\n const Sqlite = require('better-sqlite3') as typeof Database;\n const filename = join(context.dataDir, 'app.sqlite');\n try {\n await access(filename);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return;\n throw error;\n }\n const db = new Sqlite(filename, { readonly: true, fileMustExist: true });\n try {\n const table = db\n .prepare(\"SELECT name FROM sqlite_master WHERE name = '__drizzle_migrations'\")\n .get();\n if (!table) return;\n const applied = db\n .prepare('SELECT hash FROM __drizzle_migrations ORDER BY created_at')\n .all() as { hash: string }[];\n const journal = JSON.parse(\n await readFile(join(candidate, 'dist/drizzle/meta/_journal.json'), 'utf8'),\n ) as { entries: { tag: string }[] };\n const hashes = await Promise.all(\n journal.entries.map(async (entry) => {\n if (!/^[a-zA-Z0-9_-]+$/.test(entry.tag)) throw new Error('\u5019\u9009\u5305\u5305\u542B\u65E0\u6548\u8FC1\u79FB\u8DEF\u5F84');\n return createHash('sha256')\n .update(await readFile(join(candidate, 'dist/drizzle', `${entry.tag}.sql`)))\n .digest('hex');\n }),\n );\n if (applied.some((entry, i) => entry.hash !== hashes[i]))\n throw new Error('\u76EE\u6807\u7248\u672C\u4E0D\u517C\u5BB9\u5F53\u524D\u6570\u636E\u5E93\u8FC1\u79FB\u5386\u53F2\u3002\u8BF7\u7B49\u5F85\u517C\u5BB9\u7248\u672C\uFF0C\u6216\u4F7F\u7528\u72EC\u7ACB\u6D4B\u8BD5\u6570\u636E\u76EE\u5F55\u3002');\n } finally {\n db.close();\n }\n}\n\nasync function worker(directory: string) {\n await mkdir(directory, { recursive: true, mode: 0o700 });\n const release = await lockfile.lock(directory, {\n stale: 10_000,\n update: 2_000,\n retries: { retries: 30, minTimeout: 100, maxTimeout: 500 },\n });\n let record = await readJson<UpdateRun>(join(directory, 'run.json'));\n const context = await readJson<UpdateContext>(join(directory, 'context.json'));\n if (!record || !context) {\n await release();\n throw new Error('\u7F3A\u5C11\u5347\u7EA7\u8BB0\u5F55');\n }\n const update = async (phase: UpdateRun['phase'], detail: string) => {\n record = { ...record!, phase, message: detail, updatedAt: Date.now() };\n await saveJson(join(directory, 'run.json'), record);\n };\n const paths = transactionPaths(\n context.root,\n record.id,\n context.dataDir,\n context.location.config,\n join(directory, `backup-${record.id}`),\n );\n try {\n if (process.argv[3] === '--repair') {\n const active = await control<DaemonStatus>(context.location, 'status').catch(\n (error: unknown) => {\n if (isNotRunning(error)) return undefined;\n throw error;\n },\n );\n if (record.committed) return;\n if (active && !active.maintenance && active.version !== record.from)\n throw new Error('\u5F53\u524D\u670D\u52A1\u53EF\u80FD\u5DF2\u63A5\u53D7\u65B0\u7248\u4E1A\u52A1\u6570\u636E\uFF1B\u62D2\u7EDD\u6062\u590D\u65E7\u5FEB\u7167\uFF0C\u8BF7\u4F7F\u7528\u517C\u5BB9\u7248\u672C\u68C0\u67E5\u3002');\n const previous = await readJson<{ version: string; name: string }>(\n join(paths.previous, 'package.json'),\n );\n if (previous) {\n if (active && !active.maintenance)\n throw new Error('\u65E7\u670D\u52A1\u5DF2\u6062\u590D\u4E1A\u52A1\u5199\u5165\uFF1B\u62D2\u7EDD\u7528\u5347\u7EA7\u524D\u5FEB\u7167\u8986\u76D6\u73B0\u6709\u6570\u636E\uFF0C\u8BF7\u4FDD\u7559\u73B0\u573A\u68C0\u67E5\u3002');\n if (previous.name !== npmPackageName || previous.version !== record.from)\n throw new Error('\u65E7\u7248\u5907\u4EFD\u8EAB\u4EFD\u4E0D\u5339\u914D');\n const snapshot = await readJson<{ complete: boolean }>(join(paths.backup, 'snapshot.json'));\n if (!snapshot?.complete) throw new Error('\u6570\u636E\u5E93\u5907\u4EFD\u4E0D\u5B8C\u6574\uFF0C\u4FDD\u7559\u5168\u90E8\u73B0\u573A\u4F9B\u68C0\u67E5');\n } else {\n const original = await readJson<{ name: string; version: string }>(\n join(paths.root, 'package.json'),\n );\n if (original?.name !== npmPackageName || original.version !== record.from)\n throw new Error('\u672A\u627E\u5230\u5B8C\u6574\u7684\u4E0A\u4E00\u7248\u672C\u5B89\u88C5');\n }\n if (active && !active.maintenance) {\n const admission = await control<{ ready: boolean }>(context.location, 'prepare-update');\n if (!admission.ready) throw new Error('\u4ECD\u6709\u4EFB\u52A1\u3001\u5BA1\u6279\u6216\u5F85\u6838\u5BF9\u64CD\u4F5C\uFF0C\u4E0D\u80FD\u6062\u590D\u65E7\u5B89\u88C5');\n }\n await stopService(context);\n if (previous) {\n await rm(paths.root, { recursive: true, force: true });\n await rename(paths.previous, paths.root);\n for (const name of ['app.sqlite', 'app.sqlite-wal', 'app.sqlite-shm']) {\n await rm(join(paths.dataDir, name), { force: true });\n try {\n await copyDurable(join(paths.backup, name), join(paths.dataDir, name));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n }\n await copyDurable(join(paths.backup, 'config.json'), paths.config);\n }\n const restored = await readJson<{ name: string; version: string }>(\n join(paths.root, 'package.json'),\n );\n if (restored?.name !== npmPackageName || restored.version !== record.from)\n throw new Error('\u672A\u627E\u5230\u5B8C\u6574\u7684\u4E0A\u4E00\u7248\u672C\u5B89\u88C5');\n await update('rolledBack', '\u5DF2\u6062\u590D\u4E0A\u6B21\u672A\u5B8C\u6210\u7684\u5347\u7EA7\uFF0C\u6B63\u5728\u542F\u52A8\u4E0A\u4E00\u7248\u672C');\n try {\n await startService(context);\n await verifyRestoredService(context, record.from);\n await update('rolledBack', '\u5DF2\u6062\u590D\u4E0A\u6B21\u672A\u5B8C\u6210\u7684\u5347\u7EA7\uFF0C\u4E0A\u4E00\u7248\u672C\u5DF2\u5C31\u7EEA');\n } catch (error) {\n await update('failed', `\u65E7\u7248\u6062\u590D\u542F\u52A8\u5931\u8D25\uFF0C\u4FDD\u7559\u5907\u4EFD\uFF1A${message(error)}`);\n throw error;\n }\n return;\n }\n const reason = await inspectInstallation(context.root);\n if (reason) throw new Error(reason);\n // A second managed configuration must be stopped before replacing their shared npm package.\n for (const key of await readdir(join(context.location.home, 'instances'))) {\n if (key === context.location.key) continue;\n const instance = await readJson<{ root: string; config: string; socket: string }>(\n join(context.location.home, 'instances', key, 'instance.json'),\n );\n if (instance?.root !== context.root) continue;\n try {\n await control({ ...context.location, socket: instance.socket }, 'status');\n throw new Error('\u540C\u4E00 npm \u5B89\u88C5\u8FD8\u6709\u5176\u4ED6 Covro \u5B9E\u4F8B\uFF0C\u8BF7\u5148\u505C\u6B62\u5176\u4ED6\u5B9E\u4F8B\u518D\u5347\u7EA7\u3002');\n } catch (error) {\n if (!isNotRunning(error)) throw error;\n }\n }\n await access(dirname(context.root), constants.W_OK);\n // npm global layout keeps production dependencies nested in the package being swapped.\n await exec(\n 'npm',\n [\n 'install',\n '--global',\n '--prefix',\n paths.prefix,\n '--omit=dev',\n '--no-audit',\n '--no-fund',\n `--registry=${registry}`,\n '--allow-scripts=better-sqlite3',\n `${npmPackageName}@${record.target}`,\n ],\n { timeout: 10 * 60_000, maxBuffer: 2 * 1024 * 1024 },\n );\n const candidate = await readJson<{ name: string; version: string; covroCodex?: unknown }>(\n join(paths.candidate, 'package.json'),\n );\n if (candidate?.name !== npmPackageName || candidate.version !== record.target)\n throw new Error('\u5019\u9009\u5305\u8EAB\u4EFD\u6216\u7248\u672C\u4E0D\u5339\u914D');\n if (!record.codex) throw new Error('\u7F3A\u5C11 Codex \u5347\u7EA7\u6821\u9A8C\u8BB0\u5F55\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0');\n const manifest = codexCompatibilitySchema.parse(candidate.covroCodex);\n if (JSON.stringify(manifest) !== JSON.stringify(record.codex.manifest))\n throw new Error('\u5019\u9009\u5305\u7684 Codex \u517C\u5BB9\u58F0\u660E\u4E0E\u68C0\u67E5\u65F6\u4E0D\u4E00\u81F4\uFF0C\u62D2\u7EDD\u5207\u6362');\n const checkCodex = async (current?: DaemonStatus) => {\n const state = current ?? (await control<DaemonStatus>(context.location, 'status'));\n if (state.codexVersion !== record!.codex!.version)\n throw new Error('Codex \u7248\u672C\u5728\u7B49\u5F85\u5347\u7EA7\u671F\u95F4\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0');\n requireCodexCompatibility(\n manifest,\n state.codexVersion ?? null,\n record!.codex!.confirmedUnverified,\n );\n };\n await checkCodex();\n await exec(process.execPath, [join(paths.candidate, 'bin/covro.mjs'), '--version'], {\n timeout: 30_000,\n });\n const nativeProbe =\n 'const {createRequire}=await import(\"node:module\"); const r=createRequire(process.argv[1]); const DB=r(\"better-sqlite3\"); const db=new DB(\":memory:\"); db.close();';\n await exec(\n process.execPath,\n ['--input-type=module', '-e', nativeProbe, join(paths.candidate, 'package.json')],\n { timeout: 30_000 },\n );\n await verifyMigrations(context, paths.candidate);\n await activateUpdate(paths, {\n phase: update,\n waitForIdle: async () => {\n // Queue without blocking normal work; admission closes atomically only after all blockers clear.\n for (;;) {\n await checkCodex();\n const result = await control<{ ready: boolean; reason?: string }>(\n context.location,\n 'prepare-update',\n );\n if (result.ready) {\n await checkCodex();\n return;\n }\n await update('waiting', result.reason ?? '\u7B49\u5F85\u6240\u6709\u4EFB\u52A1\u7ED3\u675F');\n await setTimeout(2_000);\n }\n },\n stop: () => stopService(context),\n start: async (candidate) => {\n await startService(context);\n if (!candidate) await verifyRestoredService(context, record!.from);\n },\n verify: async () => {\n for (let attempt = 0; attempt < 240; attempt++) {\n const current = await control<DaemonStatus>(context.location, 'status').catch(\n () => undefined,\n );\n if (current) {\n if (current.version !== record!.target || !current.maintenance)\n throw new Error('\u65B0\u7248\u670D\u52A1\u8EAB\u4EFD\u6216\u7EF4\u62A4\u72B6\u6001\u4E0D\u5339\u914D');\n await checkCodex(current);\n if (current.codexReady) return;\n }\n await setTimeout(250);\n }\n throw new Error('\u65B0\u7248\u670D\u52A1\u6216 Codex \u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u62D2\u7EDD\u6FC0\u6D3B');\n },\n commit: async () => {\n // Gateway commits the durable result before reopening task admission.\n await control(context.location, 'activate-update', {\n id: record!.id,\n channel: record!.channel,\n });\n const final = await readJson<UpdateRun>(join(directory, 'run.json'));\n if (!final?.committed) throw new Error('\u65B0\u7248\u5C1A\u672A\u786E\u8BA4\u5347\u7EA7\u63D0\u4EA4');\n record = final;\n },\n hasCommitted: async () =>\n Boolean((await readJson<UpdateRun>(join(directory, 'run.json')))?.committed),\n resume: async () => {\n await control(context.location, 'cancel-update').catch(() => {});\n },\n });\n } catch (error) {\n const latest = await readJson<UpdateRun>(join(directory, 'run.json'));\n if (latest?.committed) {\n // A lost commit response cannot authorize restoring older data.\n record = latest;\n } else if (!['rolledBack', 'failed'].includes(record.phase))\n await update('failed', message(error));\n console.error(message(error));\n process.exitCode = record.committed || record.phase === 'rolledBack' ? 0 : 1;\n } finally {\n await release();\n // Keep the last good installation and database backup for explicit recovery.\n if (record.phase === 'succeeded' || record.phase === 'rolledBack') {\n await rm(paths.prefix, { recursive: true, force: true });\n }\n }\n}\n\nif (process.argv[2])\n void worker(process.argv[2]).catch((error: unknown) => {\n console.error(message(error));\n process.exitCode = 1;\n });\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["require", "candidate"]
|
|
7
7
|
}
|