@covro/covro 0.0.0-stage → 0.1.0-dev.1
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/LICENSE +21 -0
- package/README.md +173 -2
- package/README.zh-CN.md +174 -0
- package/bin/covro.mjs +8 -0
- package/dist/cli/control.js +66 -0
- package/dist/cli/control.js.map +7 -0
- package/dist/cli/daemon.js +118 -0
- package/dist/cli/daemon.js.map +7 -0
- package/dist/cli/main.js +152 -0
- package/dist/cli/main.js.map +7 -0
- package/dist/cli/paths.js +60 -0
- package/dist/cli/paths.js.map +7 -0
- package/dist/cli/service.js +87 -0
- package/dist/cli/service.js.map +7 -0
- package/dist/codex/adapter.js +1195 -0
- package/dist/codex/adapter.js.map +7 -0
- package/dist/codex/auto-review.js +102 -0
- package/dist/codex/auto-review.js.map +7 -0
- package/dist/codex/compatibility.js +7 -0
- package/dist/codex/compatibility.js.map +7 -0
- package/dist/codex/mapping.js +210 -0
- package/dist/codex/mapping.js.map +7 -0
- package/dist/codex/permissions.js +51 -0
- package/dist/codex/permissions.js.map +7 -0
- package/dist/codex/thread-title-policy.js +52 -0
- package/dist/codex/thread-title-policy.js.map +7 -0
- package/dist/codex/thread-titles.js +259 -0
- package/dist/codex/thread-titles.js.map +7 -0
- package/dist/codex/transport.js +236 -0
- package/dist/codex/transport.js.map +7 -0
- package/dist/codex/turn-token-usage.js +46 -0
- package/dist/codex/turn-token-usage.js.map +7 -0
- package/dist/codex/types.js +1 -0
- package/dist/codex/types.js.map +7 -0
- package/dist/drizzle/0000_past_wildside.sql +45 -0
- package/dist/drizzle/0001_shocking_ender_wiggin.sql +2 -0
- package/dist/drizzle/0002_allow_parallel_threads.sql +1 -0
- package/dist/drizzle/0003_project_registrations.sql +11 -0
- package/dist/drizzle/0004_turn_usage.sql +6 -0
- package/dist/drizzle/meta/0000_snapshot.json +309 -0
- package/dist/drizzle/meta/0001_snapshot.json +323 -0
- package/dist/drizzle/meta/0002_snapshot.json +315 -0
- package/dist/drizzle/meta/0003_snapshot.json +381 -0
- package/dist/drizzle/meta/0004_snapshot.json +420 -0
- package/dist/drizzle/meta/_journal.json +41 -0
- package/dist/server/auth.js +47 -0
- package/dist/server/auth.js.map +7 -0
- package/dist/server/compaction.js +40 -0
- package/dist/server/compaction.js.map +7 -0
- package/dist/server/config-store.js +147 -0
- package/dist/server/config-store.js.map +7 -0
- package/dist/server/config.js +124 -0
- package/dist/server/config.js.map +7 -0
- package/dist/server/db/index.js +21 -0
- package/dist/server/db/index.js.map +7 -0
- package/dist/server/db/migrate.js +26 -0
- package/dist/server/db/migrate.js.map +7 -0
- package/dist/server/db/operations.js +201 -0
- package/dist/server/db/operations.js.map +7 -0
- package/dist/server/db/schema.js +99 -0
- package/dist/server/db/schema.js.map +7 -0
- package/dist/server/db/turn-usage.js +31 -0
- package/dist/server/db/turn-usage.js.map +7 -0
- package/dist/server/events.js +123 -0
- package/dist/server/events.js.map +7 -0
- package/dist/server/http.js +305 -0
- package/dist/server/http.js.map +7 -0
- package/dist/server/images.js +49 -0
- package/dist/server/images.js.map +7 -0
- package/dist/server/instance-lock.js +25 -0
- package/dist/server/instance-lock.js.map +7 -0
- package/dist/server/local-files.js +100 -0
- package/dist/server/local-files.js.map +7 -0
- package/dist/server/main.js +125 -0
- package/dist/server/main.js.map +7 -0
- package/dist/server/markdown.js +28 -0
- package/dist/server/markdown.js.map +7 -0
- package/dist/server/projection.js +348 -0
- package/dist/server/projection.js.map +7 -0
- package/dist/server/projects.js +230 -0
- package/dist/server/projects.js.map +7 -0
- package/dist/server/service.js +1221 -0
- package/dist/server/service.js.map +7 -0
- package/dist/server/snapshot.js +98 -0
- package/dist/server/snapshot.js.map +7 -0
- package/dist/server/thread-export.js +97 -0
- package/dist/server/thread-export.js.map +7 -0
- package/dist/server/websocket.js +126 -0
- package/dist/server/websocket.js.map +7 -0
- package/dist/shared/async-questions.js +39 -0
- package/dist/shared/async-questions.js.map +7 -0
- package/dist/shared/codex-compatibility.js +56 -0
- package/dist/shared/codex-compatibility.js.map +7 -0
- package/dist/shared/elicitation.js +314 -0
- package/dist/shared/elicitation.js.map +7 -0
- package/dist/shared/errors.js +24 -0
- package/dist/shared/errors.js.map +7 -0
- package/dist/shared/gateway-config.js +1 -0
- package/dist/shared/gateway-config.js.map +7 -0
- package/dist/shared/images.js +21 -0
- package/dist/shared/images.js.map +7 -0
- package/dist/shared/package.js +5 -0
- package/dist/shared/package.js.map +7 -0
- package/dist/shared/permissions.js +63 -0
- package/dist/shared/permissions.js.map +7 -0
- package/dist/shared/thread-name.js +14 -0
- package/dist/shared/thread-name.js.map +7 -0
- package/dist/shared/thread-summary.js +24 -0
- package/dist/shared/thread-summary.js.map +7 -0
- package/dist/shared/types.js +1 -0
- package/dist/shared/types.js.map +7 -0
- package/dist/shared/updates.js +7 -0
- package/dist/shared/updates.js.map +7 -0
- package/dist/shared/validation.js +116 -0
- package/dist/shared/validation.js.map +7 -0
- package/dist/shared/versions.js +36 -0
- package/dist/shared/versions.js.map +7 -0
- package/dist/update-worker.cjs +21968 -0
- package/dist/updates/files.js +54 -0
- package/dist/updates/files.js.map +7 -0
- package/dist/updates/manager.js +315 -0
- package/dist/updates/manager.js.map +7 -0
- package/dist/updates/registry.js +71 -0
- package/dist/updates/registry.js.map +7 -0
- package/dist/updates/transaction.js +96 -0
- package/dist/updates/transaction.js.map +7 -0
- package/dist/updates/worker.js +345 -0
- package/dist/updates/worker.js.map +7 -0
- package/dist/web/assets/index-BW9afH_Y.js +83 -0
- package/dist/web/assets/index-L3S1ZiO0.css +1 -0
- package/dist/web/covro.svg +6 -0
- package/dist/web/index.html +15 -0
- package/package.json +88 -4
package/dist/cli/main.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { mkdir, open } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { setTimeout } from "node:timers/promises";
|
|
5
|
+
import { control, isNotRunning, stopAndWait } from "./control.js";
|
|
6
|
+
import { randomUUID } from "node:crypto";
|
|
7
|
+
import { ensureConfig, packageInfo, packageRoot, paths } from "./paths.js";
|
|
8
|
+
import { runDaemon } from "./daemon.js";
|
|
9
|
+
import { service } from "./service.js";
|
|
10
|
+
import { UpdateManager } from "../updates/manager.js";
|
|
11
|
+
import { loadConfig } from "../server/config.js";
|
|
12
|
+
function parseArguments(args) {
|
|
13
|
+
const positional = [];
|
|
14
|
+
let configPath;
|
|
15
|
+
let channel;
|
|
16
|
+
let allowDowngrade = false;
|
|
17
|
+
let allowUnverifiedCodex = false;
|
|
18
|
+
for (let i = 0; i < args.length; i++) {
|
|
19
|
+
const arg = args[i];
|
|
20
|
+
if (arg === "--config" && args[i + 1]) configPath = args[++i];
|
|
21
|
+
else if (arg === "--channel" && ["stable", "beta", "dev"].includes(args[i + 1] ?? ""))
|
|
22
|
+
channel = args[++i];
|
|
23
|
+
else if (arg === "--allow-downgrade") allowDowngrade = true;
|
|
24
|
+
else if (arg === "--allow-unverified-codex") allowUnverifiedCodex = true;
|
|
25
|
+
else if (arg.startsWith("-") && arg !== "--help" && arg !== "--version")
|
|
26
|
+
throw new Error(`Unknown argument: ${arg}`);
|
|
27
|
+
else positional.push(arg);
|
|
28
|
+
}
|
|
29
|
+
const [command = "start", subcommand] = positional;
|
|
30
|
+
if (positional.length > (["service", "update"].includes(command) ? 2 : 1))
|
|
31
|
+
throw new Error("Too many arguments");
|
|
32
|
+
if ((channel || allowDowngrade || allowUnverifiedCodex) && command !== "update")
|
|
33
|
+
throw new Error("\u5347\u7EA7\u9009\u9879\u4EC5\u7528\u4E8E update");
|
|
34
|
+
return {
|
|
35
|
+
command,
|
|
36
|
+
subcommand,
|
|
37
|
+
channel,
|
|
38
|
+
allowDowngrade,
|
|
39
|
+
allowUnverifiedCodex,
|
|
40
|
+
location: paths(configPath)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
async function startBackground(location) {
|
|
44
|
+
try {
|
|
45
|
+
return await control(location, "status");
|
|
46
|
+
} catch (error) {
|
|
47
|
+
if (!isNotRunning(error)) throw error;
|
|
48
|
+
}
|
|
49
|
+
await ensureConfig(location);
|
|
50
|
+
await mkdir(location.state, { recursive: true, mode: 448 });
|
|
51
|
+
const log = await open(location.log, "a", 384);
|
|
52
|
+
const child = spawn(
|
|
53
|
+
process.execPath,
|
|
54
|
+
[join(packageRoot, "bin/covro.mjs"), "run", "--config", location.config],
|
|
55
|
+
{
|
|
56
|
+
detached: true,
|
|
57
|
+
stdio: ["ignore", log.fd, log.fd],
|
|
58
|
+
windowsHide: true
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
let failure;
|
|
62
|
+
child.once("error", (error) => {
|
|
63
|
+
failure = error;
|
|
64
|
+
});
|
|
65
|
+
child.unref();
|
|
66
|
+
await log.close();
|
|
67
|
+
for (let i = 0; i < 240; i++) {
|
|
68
|
+
if (failure) throw failure;
|
|
69
|
+
try {
|
|
70
|
+
return await control(location, "status");
|
|
71
|
+
} catch (error) {
|
|
72
|
+
if (!isNotRunning(error)) throw error;
|
|
73
|
+
}
|
|
74
|
+
if (child.exitCode !== null) throw new Error(`Covro \u542F\u52A8\u5931\u8D25\uFF0C\u8BF7\u67E5\u770B ${location.log}`);
|
|
75
|
+
await setTimeout(250);
|
|
76
|
+
}
|
|
77
|
+
throw new Error(`Covro \u5C1A\u672A\u786E\u8BA4\u542F\u52A8\uFF0C\u8BF7\u8FD0\u884C covro status \u5E76\u67E5\u770B ${location.log}`);
|
|
78
|
+
}
|
|
79
|
+
async function main(args = process.argv.slice(2)) {
|
|
80
|
+
const { command, subcommand, channel, allowDowngrade, allowUnverifiedCodex, location } = parseArguments(args);
|
|
81
|
+
if (command === "--version") {
|
|
82
|
+
console.log(packageInfo.version);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (command === "--help" || command === "help") {
|
|
86
|
+
console.log(
|
|
87
|
+
"Covro\n\ncovro [start|run|stop|status|logs] [--config FILE]\ncovro update [status|repair] [--channel stable|beta|dev] [--allow-downgrade] [--allow-unverified-codex]\ncovro service install|uninstall [--config FILE]\n\n\u9ED8\u8BA4\u540E\u53F0\u8FD0\u884C\uFF1Bservice install \u5355\u72EC\u542F\u7528\u767B\u5F55\u81EA\u542F\u3002"
|
|
88
|
+
);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (command === "start") console.log(JSON.stringify(await startBackground(location), null, 2));
|
|
92
|
+
else if (command === "run") {
|
|
93
|
+
await ensureConfig(location);
|
|
94
|
+
await runDaemon(location.config);
|
|
95
|
+
} else if (command === "update") {
|
|
96
|
+
if (subcommand === "repair") {
|
|
97
|
+
const config = await loadConfig({ configPath: location.config, development: false });
|
|
98
|
+
const manager = new UpdateManager(location, config.dataDir);
|
|
99
|
+
console.log(JSON.stringify(await manager.repair(), null, 2));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (subcommand && subcommand !== "status") throw new Error("\u672A\u77E5\u5347\u7EA7\u547D\u4EE4");
|
|
103
|
+
await startBackground(location);
|
|
104
|
+
let codexConfirmation;
|
|
105
|
+
if (allowUnverifiedCodex && !subcommand) {
|
|
106
|
+
const checked = await control(location, "update-check", { channel });
|
|
107
|
+
const candidate = checked.available;
|
|
108
|
+
if (candidate?.codex.status === "unverified" && candidate.codex.version)
|
|
109
|
+
codexConfirmation = { version: candidate.codex.version, target: candidate.version };
|
|
110
|
+
}
|
|
111
|
+
console.log(
|
|
112
|
+
JSON.stringify(
|
|
113
|
+
await control(
|
|
114
|
+
location,
|
|
115
|
+
subcommand === "status" ? "update-check" : "update",
|
|
116
|
+
subcommand === "status" ? { channel } : { clientOperationId: randomUUID(), channel, allowDowngrade, codexConfirmation }
|
|
117
|
+
),
|
|
118
|
+
null,
|
|
119
|
+
2
|
|
120
|
+
)
|
|
121
|
+
);
|
|
122
|
+
} else if (command === "status" || command === "stop") {
|
|
123
|
+
try {
|
|
124
|
+
if (command === "stop") {
|
|
125
|
+
await stopAndWait(location);
|
|
126
|
+
console.log("Covro \u5DF2\u505C\u6B62");
|
|
127
|
+
} else console.log(JSON.stringify(await control(location, command), null, 2));
|
|
128
|
+
} catch (error) {
|
|
129
|
+
if (!isNotRunning(error)) throw error;
|
|
130
|
+
console.log("Covro \u672A\u8FD0\u884C");
|
|
131
|
+
}
|
|
132
|
+
} else if (command === "logs") {
|
|
133
|
+
const handle = await open(location.log, "r");
|
|
134
|
+
try {
|
|
135
|
+
const { size } = await handle.stat();
|
|
136
|
+
const buffer = Buffer.alloc(Math.min(size, 64 * 1024));
|
|
137
|
+
await handle.read(buffer, 0, buffer.length, Math.max(0, size - buffer.length));
|
|
138
|
+
console.log(buffer.toString("utf8"));
|
|
139
|
+
} finally {
|
|
140
|
+
await handle.close();
|
|
141
|
+
}
|
|
142
|
+
} else if (command === "service" && ["install", "uninstall"].includes(subcommand ?? "")) {
|
|
143
|
+
await service(location, subcommand === "install");
|
|
144
|
+
console.log(subcommand === "install" ? "\u5DF2\u542F\u7528 Covro \u767B\u5F55\u81EA\u542F" : "\u5DF2\u53D6\u6D88 Covro \u767B\u5F55\u81EA\u542F");
|
|
145
|
+
} else throw new Error("\u672A\u77E5\u547D\u4EE4\uFF0C\u8FD0\u884C covro --help \u67E5\u770B\u7528\u6CD5");
|
|
146
|
+
}
|
|
147
|
+
export {
|
|
148
|
+
main,
|
|
149
|
+
parseArguments,
|
|
150
|
+
startBackground
|
|
151
|
+
};
|
|
152
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/cli/main.ts"],
|
|
4
|
+
"sourcesContent": ["import type { UpdateStatus } from '../shared/updates.js';\nimport { spawn } from 'node:child_process';\nimport { mkdir, open } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { setTimeout } from 'node:timers/promises';\nimport { control, isNotRunning, stopAndWait } from './control.js';\nimport { randomUUID } from 'node:crypto';\nimport { ensureConfig, packageInfo, packageRoot, paths, type CovroPaths } from './paths.js';\nimport { runDaemon } from './daemon.js';\nimport { service } from './service.js';\nimport { UpdateManager } from '../updates/manager.js';\nimport { loadConfig } from '../server/config.js';\n\nexport function parseArguments(args: string[]) {\n const positional: string[] = [];\n let configPath: string | undefined;\n let channel: 'stable' | 'beta' | 'dev' | undefined;\n let allowDowngrade = false;\n let allowUnverifiedCodex = false;\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n if (arg === '--config' && args[i + 1]) configPath = args[++i];\n else if (arg === '--channel' && ['stable', 'beta', 'dev'].includes(args[i + 1] ?? ''))\n channel = args[++i] as typeof channel;\n else if (arg === '--allow-downgrade') allowDowngrade = true;\n else if (arg === '--allow-unverified-codex') allowUnverifiedCodex = true;\n else if (arg.startsWith('-') && arg !== '--help' && arg !== '--version')\n throw new Error(`Unknown argument: ${arg}`);\n else positional.push(arg);\n }\n const [command = 'start', subcommand] = positional;\n if (positional.length > (['service', 'update'].includes(command) ? 2 : 1))\n throw new Error('Too many arguments');\n if ((channel || allowDowngrade || allowUnverifiedCodex) && command !== 'update')\n throw new Error('\u5347\u7EA7\u9009\u9879\u4EC5\u7528\u4E8E update');\n return {\n command,\n subcommand,\n channel,\n allowDowngrade,\n allowUnverifiedCodex,\n location: paths(configPath),\n };\n}\n\nexport async function startBackground(location: CovroPaths) {\n try {\n return await control(location, 'status');\n } catch (error) {\n if (!isNotRunning(error)) throw error;\n }\n await ensureConfig(location);\n await mkdir(location.state, { recursive: true, mode: 0o700 });\n const log = await open(location.log, 'a', 0o600);\n const child = spawn(\n process.execPath,\n [join(packageRoot, 'bin/covro.mjs'), 'run', '--config', location.config],\n {\n detached: true,\n stdio: ['ignore', log.fd, log.fd],\n windowsHide: true,\n },\n );\n let failure: Error | undefined;\n child.once('error', (error) => {\n failure = error;\n });\n child.unref();\n await log.close();\n for (let i = 0; i < 240; i++) {\n if (failure) throw failure;\n try {\n return await control(location, 'status');\n } catch (error) {\n if (!isNotRunning(error)) throw error;\n }\n if (child.exitCode !== null) throw new Error(`Covro \u542F\u52A8\u5931\u8D25\uFF0C\u8BF7\u67E5\u770B ${location.log}`);\n await setTimeout(250);\n }\n throw new Error(`Covro \u5C1A\u672A\u786E\u8BA4\u542F\u52A8\uFF0C\u8BF7\u8FD0\u884C covro status \u5E76\u67E5\u770B ${location.log}`);\n}\n\nexport async function main(args = process.argv.slice(2)) {\n const { command, subcommand, channel, allowDowngrade, allowUnverifiedCodex, location } =\n parseArguments(args);\n if (command === '--version') {\n console.log(packageInfo.version);\n return;\n }\n if (command === '--help' || command === 'help') {\n console.log(\n 'Covro\\n\\ncovro [start|run|stop|status|logs] [--config FILE]\\ncovro update [status|repair] [--channel stable|beta|dev] [--allow-downgrade] [--allow-unverified-codex]\\ncovro service install|uninstall [--config FILE]\\n\\n\u9ED8\u8BA4\u540E\u53F0\u8FD0\u884C\uFF1Bservice install \u5355\u72EC\u542F\u7528\u767B\u5F55\u81EA\u542F\u3002',\n );\n return;\n }\n if (command === 'start') console.log(JSON.stringify(await startBackground(location), null, 2));\n else if (command === 'run') {\n await ensureConfig(location);\n await runDaemon(location.config);\n } else if (command === 'update') {\n if (subcommand === 'repair') {\n const config = await loadConfig({ configPath: location.config, development: false });\n const manager = new UpdateManager(location, config.dataDir);\n console.log(JSON.stringify(await manager.repair(), null, 2));\n return;\n }\n if (subcommand && subcommand !== 'status') throw new Error('\u672A\u77E5\u5347\u7EA7\u547D\u4EE4');\n await startBackground(location);\n let codexConfirmation;\n if (allowUnverifiedCodex && !subcommand) {\n const checked = await control<UpdateStatus>(location, 'update-check', { channel });\n const candidate = checked.available;\n if (candidate?.codex.status === 'unverified' && candidate.codex.version)\n codexConfirmation = { version: candidate.codex.version, target: candidate.version };\n }\n console.log(\n JSON.stringify(\n await control(\n location,\n subcommand === 'status' ? 'update-check' : 'update',\n subcommand === 'status'\n ? { channel }\n : { clientOperationId: randomUUID(), channel, allowDowngrade, codexConfirmation },\n ),\n null,\n 2,\n ),\n );\n } else if (command === 'status' || command === 'stop') {\n try {\n if (command === 'stop') {\n await stopAndWait(location);\n console.log('Covro \u5DF2\u505C\u6B62');\n } else console.log(JSON.stringify(await control(location, command), null, 2));\n } catch (error) {\n if (!isNotRunning(error)) throw error;\n console.log('Covro \u672A\u8FD0\u884C');\n }\n } else if (command === 'logs') {\n const handle = await open(location.log, 'r');\n try {\n const { size } = await handle.stat();\n const buffer = Buffer.alloc(Math.min(size, 64 * 1024));\n await handle.read(buffer, 0, buffer.length, Math.max(0, size - buffer.length));\n console.log(buffer.toString('utf8'));\n } finally {\n await handle.close();\n }\n } else if (command === 'service' && ['install', 'uninstall'].includes(subcommand ?? '')) {\n await service(location, subcommand === 'install');\n console.log(subcommand === 'install' ? '\u5DF2\u542F\u7528 Covro \u767B\u5F55\u81EA\u542F' : '\u5DF2\u53D6\u6D88 Covro \u767B\u5F55\u81EA\u542F');\n } else throw new Error('\u672A\u77E5\u547D\u4EE4\uFF0C\u8FD0\u884C covro --help \u67E5\u770B\u7528\u6CD5');\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, join, resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { readFileSync } from "node:fs";
|
|
6
|
+
import { chmod, mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
7
|
+
const packageRoot = fileURLToPath(new URL("../../", import.meta.url));
|
|
8
|
+
const packageInfo = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8"));
|
|
9
|
+
function paths(configPath) {
|
|
10
|
+
const home = resolve(process.env.COVRO_HOME ?? join(homedir(), ".covro"));
|
|
11
|
+
const config = resolve(configPath ?? join(home, "config.json"));
|
|
12
|
+
const key = createHash("sha256").update(config).digest("hex").slice(0, 16);
|
|
13
|
+
const state = join(home, "instances", key);
|
|
14
|
+
const socket = process.platform === "win32" ? `\\\\.\\pipe\\covro-${key}` : join(home, `c-${key}.sock`);
|
|
15
|
+
return { home, config, key, state, socket, log: join(state, "covro.log") };
|
|
16
|
+
}
|
|
17
|
+
async function writeJson(filename, value) {
|
|
18
|
+
await mkdir(dirname(filename), { recursive: true, mode: 448 });
|
|
19
|
+
const temporary = `${filename}.${randomUUID()}.tmp`;
|
|
20
|
+
await writeFile(temporary, `${JSON.stringify(value, null, 2)}
|
|
21
|
+
`, { mode: 384 });
|
|
22
|
+
await rename(temporary, filename);
|
|
23
|
+
}
|
|
24
|
+
async function ensureConfig(location) {
|
|
25
|
+
await mkdir(location.home, { recursive: true, mode: 448 });
|
|
26
|
+
await chmod(location.home, 448);
|
|
27
|
+
await mkdir(dirname(location.config), { recursive: true, mode: 448 });
|
|
28
|
+
try {
|
|
29
|
+
await readFile(location.config);
|
|
30
|
+
} catch (error) {
|
|
31
|
+
if (error.code !== "ENOENT") throw error;
|
|
32
|
+
await writeFile(
|
|
33
|
+
location.config,
|
|
34
|
+
`${JSON.stringify(
|
|
35
|
+
{
|
|
36
|
+
host: "127.0.0.1",
|
|
37
|
+
port: 8787,
|
|
38
|
+
publicOrigin: ["http://127.0.0.1:8787", "http://localhost:8787"],
|
|
39
|
+
dataDir: "./data",
|
|
40
|
+
codex: { binary: process.env.COVRO_CODEX_BINARY ?? "codex" },
|
|
41
|
+
projects: []
|
|
42
|
+
},
|
|
43
|
+
null,
|
|
44
|
+
2
|
|
45
|
+
)}
|
|
46
|
+
`,
|
|
47
|
+
{ flag: "wx", mode: 384 }
|
|
48
|
+
).catch((failure) => {
|
|
49
|
+
if (failure.code !== "EEXIST") throw failure;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
ensureConfig,
|
|
55
|
+
packageInfo,
|
|
56
|
+
packageRoot,
|
|
57
|
+
paths,
|
|
58
|
+
writeJson
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/cli/paths.ts"],
|
|
4
|
+
"sourcesContent": ["import { createHash, randomUUID } from 'node:crypto';\nimport { homedir } from 'node:os';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { readFileSync } from 'node:fs';\nimport { chmod, mkdir, readFile, rename, writeFile } from 'node:fs/promises';\n\nexport const packageRoot = fileURLToPath(new URL('../../', import.meta.url));\nexport const packageInfo = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8')) as {\n name: string;\n version: string;\n engines: { node: string };\n covroCodex?: unknown;\n covroCommit?: string;\n covroChannel?: 'stable' | 'beta' | 'dev';\n};\nexport function paths(configPath?: string) {\n const home = resolve(process.env.COVRO_HOME ?? join(homedir(), '.covro'));\n const config = resolve(configPath ?? join(home, 'config.json'));\n const key = createHash('sha256').update(config).digest('hex').slice(0, 16);\n const state = join(home, 'instances', key);\n const socket =\n process.platform === 'win32' ? `\\\\\\\\.\\\\pipe\\\\covro-${key}` : join(home, `c-${key}.sock`);\n return { home, config, key, state, socket, log: join(state, 'covro.log') };\n}\nexport type CovroPaths = ReturnType<typeof paths>;\nexport async function writeJson(filename: string, value: unknown) {\n await mkdir(dirname(filename), { recursive: true, mode: 0o700 });\n const temporary = `${filename}.${randomUUID()}.tmp`;\n await writeFile(temporary, `${JSON.stringify(value, null, 2)}\\n`, { mode: 0o600 });\n await rename(temporary, filename);\n}\nexport async function ensureConfig(location: CovroPaths) {\n await mkdir(location.home, { recursive: true, mode: 0o700 });\n await chmod(location.home, 0o700);\n await mkdir(dirname(location.config), { recursive: true, mode: 0o700 });\n try {\n await readFile(location.config);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n await writeFile(\n location.config,\n `${JSON.stringify(\n {\n host: '127.0.0.1',\n port: 8787,\n publicOrigin: ['http://127.0.0.1:8787', 'http://localhost:8787'],\n dataDir: './data',\n codex: { binary: process.env.COVRO_CODEX_BINARY ?? 'codex' },\n projects: [],\n },\n null,\n 2,\n )}\\n`,\n { flag: 'wx', mode: 0o600 },\n ).catch((failure: NodeJS.ErrnoException) => {\n if (failure.code !== 'EEXIST') throw failure;\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,YAAY,kBAAkB;AACvC,SAAS,eAAe;AACxB,SAAS,SAAS,MAAM,eAAe;AACvC,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B,SAAS,OAAO,OAAO,UAAU,QAAQ,iBAAiB;AAEnD,MAAM,cAAc,cAAc,IAAI,IAAI,UAAU,YAAY,GAAG,CAAC;AACpE,MAAM,cAAc,KAAK,MAAM,aAAa,KAAK,aAAa,cAAc,GAAG,MAAM,CAAC;AAQtF,SAAS,MAAM,YAAqB;AACzC,QAAM,OAAO,QAAQ,QAAQ,IAAI,cAAc,KAAK,QAAQ,GAAG,QAAQ,CAAC;AACxE,QAAM,SAAS,QAAQ,cAAc,KAAK,MAAM,aAAa,CAAC;AAC9D,QAAM,MAAM,WAAW,QAAQ,EAAE,OAAO,MAAM,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AACzE,QAAM,QAAQ,KAAK,MAAM,aAAa,GAAG;AACzC,QAAM,SACJ,QAAQ,aAAa,UAAU,sBAAsB,GAAG,KAAK,KAAK,MAAM,KAAK,GAAG,OAAO;AACzF,SAAO,EAAE,MAAM,QAAQ,KAAK,OAAO,QAAQ,KAAK,KAAK,OAAO,WAAW,EAAE;AAC3E;AAEA,eAAsB,UAAU,UAAkB,OAAgB;AAChE,QAAM,MAAM,QAAQ,QAAQ,GAAG,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAC/D,QAAM,YAAY,GAAG,QAAQ,IAAI,WAAW,CAAC;AAC7C,QAAM,UAAU,WAAW,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,GAAM,EAAE,MAAM,IAAM,CAAC;AACjF,QAAM,OAAO,WAAW,QAAQ;AAClC;AACA,eAAsB,aAAa,UAAsB;AACvD,QAAM,MAAM,SAAS,MAAM,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAC3D,QAAM,MAAM,SAAS,MAAM,GAAK;AAChC,QAAM,MAAM,QAAQ,SAAS,MAAM,GAAG,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AACtE,MAAI;AACF,UAAM,SAAS,SAAS,MAAM;AAAA,EAChC,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,SAAU,OAAM;AAC9D,UAAM;AAAA,MACJ,SAAS;AAAA,MACT,GAAG,KAAK;AAAA,QACN;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,cAAc,CAAC,yBAAyB,uBAAuB;AAAA,UAC/D,SAAS;AAAA,UACT,OAAO,EAAE,QAAQ,QAAQ,IAAI,sBAAsB,QAAQ;AAAA,UAC3D,UAAU,CAAC;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA;AAAA,MACD,EAAE,MAAM,MAAM,MAAM,IAAM;AAAA,IAC5B,EAAE,MAAM,CAAC,YAAmC;AAC1C,UAAI,QAAQ,SAAS,SAAU,OAAM;AAAA,IACvC,CAAC;AAAA,EACH;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
6
|
+
import { stopAndWait } from "./control.js";
|
|
7
|
+
import { saveJson } from "../updates/files.js";
|
|
8
|
+
import { packageRoot } from "./paths.js";
|
|
9
|
+
const exec = promisify(execFile);
|
|
10
|
+
const xml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
|
11
|
+
const unit = (value) => `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"').replaceAll("%", "%%")}"`;
|
|
12
|
+
async function service(location, install) {
|
|
13
|
+
if (!["darwin", "linux"].includes(process.platform))
|
|
14
|
+
throw new Error(
|
|
15
|
+
"\u767B\u5F55\u81EA\u542F\u76EE\u524D\u652F\u6301 macOS launchd \u548C Linux systemd --user\uFF1B\u53EF\u4F7F\u7528 covro start \u540E\u53F0\u8FD0\u884C\u3002"
|
|
16
|
+
);
|
|
17
|
+
const label = `dev.covro.${location.key}`;
|
|
18
|
+
const entry = join(packageRoot, "bin/covro.mjs");
|
|
19
|
+
if (install) {
|
|
20
|
+
await stopAndWait(location);
|
|
21
|
+
await mkdir(location.state, { recursive: true, mode: 448 });
|
|
22
|
+
}
|
|
23
|
+
if (process.platform === "darwin") {
|
|
24
|
+
const directory = join(homedir(), "Library/LaunchAgents");
|
|
25
|
+
const filename = join(directory, `${label}.plist`);
|
|
26
|
+
const domain = `gui/${process.getuid()}`;
|
|
27
|
+
if (!install) {
|
|
28
|
+
await exec("launchctl", ["bootout", domain, filename]);
|
|
29
|
+
await rm(filename);
|
|
30
|
+
await rm(join(location.state, "service.json"), { force: true });
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
await mkdir(directory, { recursive: true });
|
|
34
|
+
const args = [process.execPath, entry, "run", "--config", location.config];
|
|
35
|
+
await writeFile(
|
|
36
|
+
filename,
|
|
37
|
+
`<?xml version="1.0" encoding="UTF-8"?>
|
|
38
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
39
|
+
<plist version="1.0"><dict>
|
|
40
|
+
<key>Label</key><string>${label}</string>
|
|
41
|
+
<key>ProgramArguments</key><array>${args.map((arg) => `<string>${xml(arg)}</string>`).join("")}</array>
|
|
42
|
+
<key>RunAtLoad</key><true/><key>KeepAlive</key><dict><key>SuccessfulExit</key><false/></dict><key>ThrottleInterval</key><integer>30</integer>
|
|
43
|
+
<key>EnvironmentVariables</key><dict><key>PATH</key><string>${xml(process.env.PATH ?? "/usr/bin:/bin")}</string><key>COVRO_HOME</key><string>${xml(location.home)}</string></dict>
|
|
44
|
+
<key>StandardOutPath</key><string>${xml(location.log)}</string><key>StandardErrorPath</key><string>${xml(location.log)}</string>
|
|
45
|
+
</dict></plist>
|
|
46
|
+
`,
|
|
47
|
+
{ mode: 384 }
|
|
48
|
+
);
|
|
49
|
+
await exec("launchctl", ["enable", `${domain}/${label}`]);
|
|
50
|
+
await exec("launchctl", ["bootstrap", domain, filename]);
|
|
51
|
+
await saveJson(join(location.state, "service.json"), { platform: "darwin", label });
|
|
52
|
+
} else {
|
|
53
|
+
const directory = join(homedir(), ".config/systemd/user");
|
|
54
|
+
const filename = join(directory, `${label}.service`);
|
|
55
|
+
if (install) {
|
|
56
|
+
await mkdir(directory, { recursive: true });
|
|
57
|
+
if (/[\r\n]/.test([entry, location.config, location.home, process.env.PATH].join("")))
|
|
58
|
+
throw new Error("\u670D\u52A1\u8DEF\u5F84\u548C PATH \u4E0D\u80FD\u5305\u542B\u6362\u884C");
|
|
59
|
+
await writeFile(
|
|
60
|
+
filename,
|
|
61
|
+
`[Unit]
|
|
62
|
+
Description=Covro
|
|
63
|
+
[Service]
|
|
64
|
+
ExecStart=${[process.execPath, entry, "run", "--config", location.config].map(unit).join(" ")}
|
|
65
|
+
Environment=${unit(`COVRO_HOME=${location.home}`)} ${unit(`PATH=${process.env.PATH ?? "/usr/bin:/bin"}`)}
|
|
66
|
+
Restart=on-failure
|
|
67
|
+
RestartSec=30
|
|
68
|
+
[Install]
|
|
69
|
+
WantedBy=default.target
|
|
70
|
+
`,
|
|
71
|
+
{ mode: 384 }
|
|
72
|
+
);
|
|
73
|
+
await exec("systemctl", ["--user", "daemon-reload"]);
|
|
74
|
+
await exec("systemctl", ["--user", "enable", "--now", `${label}.service`]);
|
|
75
|
+
await saveJson(join(location.state, "service.json"), { platform: "linux", label });
|
|
76
|
+
} else {
|
|
77
|
+
await exec("systemctl", ["--user", "disable", "--now", `${label}.service`]);
|
|
78
|
+
await rm(filename);
|
|
79
|
+
await rm(join(location.state, "service.json"), { force: true });
|
|
80
|
+
await exec("systemctl", ["--user", "daemon-reload"]);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
export {
|
|
85
|
+
service
|
|
86
|
+
};
|
|
87
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/cli/service.ts"],
|
|
4
|
+
"sourcesContent": ["import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { mkdir, rm, writeFile } from 'node:fs/promises';\nimport { stopAndWait } from './control.js';\nimport { saveJson } from '../updates/files.js';\nimport { packageRoot, type CovroPaths } from './paths.js';\n\nconst exec = promisify(execFile);\nconst xml = (value: string) =>\n value\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"');\nconst unit = (value: string) =>\n `\"${value.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"').replaceAll('%', '%%')}\"`;\n\nexport async function service(location: CovroPaths, install: boolean) {\n if (!['darwin', 'linux'].includes(process.platform))\n throw new Error(\n '\u767B\u5F55\u81EA\u542F\u76EE\u524D\u652F\u6301 macOS launchd \u548C Linux systemd --user\uFF1B\u53EF\u4F7F\u7528 covro start \u540E\u53F0\u8FD0\u884C\u3002',\n );\n const label = `dev.covro.${location.key}`;\n const entry = join(packageRoot, 'bin/covro.mjs');\n if (install) {\n await stopAndWait(location);\n await mkdir(location.state, { recursive: true, mode: 0o700 });\n }\n if (process.platform === 'darwin') {\n const directory = join(homedir(), 'Library/LaunchAgents');\n const filename = join(directory, `${label}.plist`);\n const domain = `gui/${process.getuid!()}`;\n if (!install) {\n await exec('launchctl', ['bootout', domain, filename]);\n await rm(filename);\n await rm(join(location.state, 'service.json'), { force: true });\n return;\n }\n await mkdir(directory, { recursive: true });\n const args = [process.execPath, entry, 'run', '--config', location.config];\n await writeFile(\n filename,\n `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\\n<plist version=\"1.0\"><dict>\n<key>Label</key><string>${label}</string>\n<key>ProgramArguments</key><array>${args.map((arg) => `<string>${xml(arg)}</string>`).join('')}</array>\n<key>RunAtLoad</key><true/><key>KeepAlive</key><dict><key>SuccessfulExit</key><false/></dict><key>ThrottleInterval</key><integer>30</integer>\n<key>EnvironmentVariables</key><dict><key>PATH</key><string>${xml(process.env.PATH ?? '/usr/bin:/bin')}</string><key>COVRO_HOME</key><string>${xml(location.home)}</string></dict>\n<key>StandardOutPath</key><string>${xml(location.log)}</string><key>StandardErrorPath</key><string>${xml(location.log)}</string>\n</dict></plist>\\n`,\n { mode: 0o600 },\n );\n await exec('launchctl', ['enable', `${domain}/${label}`]);\n await exec('launchctl', ['bootstrap', domain, filename]);\n await saveJson(join(location.state, 'service.json'), { platform: 'darwin', label });\n } else {\n const directory = join(homedir(), '.config/systemd/user');\n const filename = join(directory, `${label}.service`);\n if (install) {\n await mkdir(directory, { recursive: true });\n if (/[\\r\\n]/.test([entry, location.config, location.home, process.env.PATH].join('')))\n throw new Error('\u670D\u52A1\u8DEF\u5F84\u548C PATH \u4E0D\u80FD\u5305\u542B\u6362\u884C');\n await writeFile(\n filename,\n `[Unit]\\nDescription=Covro\\n[Service]\\nExecStart=${[process.execPath, entry, 'run', '--config', location.config].map(unit).join(' ')}\\nEnvironment=${unit(`COVRO_HOME=${location.home}`)} ${unit(`PATH=${process.env.PATH ?? '/usr/bin:/bin'}`)}\\nRestart=on-failure\\nRestartSec=30\\n[Install]\\nWantedBy=default.target\\n`,\n { mode: 0o600 },\n );\n await exec('systemctl', ['--user', 'daemon-reload']);\n await exec('systemctl', ['--user', 'enable', '--now', `${label}.service`]);\n await saveJson(join(location.state, 'service.json'), { platform: 'linux', label });\n } else {\n await exec('systemctl', ['--user', 'disable', '--now', `${label}.service`]);\n await rm(filename);\n await rm(join(location.state, 'service.json'), { force: true });\n await exec('systemctl', ['--user', 'daemon-reload']);\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|