@kingcrab/pi-imessage 0.0.42 → 1.0.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 +101 -108
- package/dist/agent/behavior.js +79 -0
- package/dist/agent/chats.js +67 -0
- package/dist/agent/commands.js +163 -0
- package/dist/agent/compaction.js +51 -0
- package/dist/agent/deliver.js +139 -0
- package/dist/agent/direct-send.js +68 -0
- package/dist/agent/harness.js +79 -0
- package/dist/agent/health.js +32 -0
- package/dist/agent/models.js +69 -0
- package/dist/agent/progress-format.js +87 -0
- package/dist/agent/progress.js +135 -0
- package/dist/agent/prompt.js +79 -0
- package/dist/agent/replies.js +9 -0
- package/dist/agent/run.js +159 -0
- package/dist/agent/scheduling.js +290 -0
- package/dist/agent/time.js +18 -0
- package/dist/cli.js +88 -191
- package/dist/config/settings.js +60 -0
- package/dist/extensions/browser.js +326 -0
- package/dist/extensions/final-text.js +23 -0
- package/dist/extensions/memory.js +109 -0
- package/dist/extensions/message.js +33 -0
- package/dist/extensions/read-image.js +72 -0
- package/dist/extensions/schedules.js +41 -0
- package/dist/extensions/subagent.js +54 -0
- package/dist/extensions/web.js +99 -0
- package/dist/extensions/workspace.js +98 -0
- package/dist/main.js +571 -74
- package/dist/transport/attachments.js +37 -0
- package/dist/transport/http.js +110 -0
- package/dist/{rich-text.js → transport/rich-text.js} +25 -13
- package/dist/{send.js → transport/send.js} +13 -13
- package/dist/transport/watch.js +124 -0
- package/dist/web/app.js +748 -0
- package/dist/web/history.js +87 -0
- package/dist/web/memory.js +81 -0
- package/dist/web/page.js +28 -0
- package/dist/web/schedules.js +74 -0
- package/dist/web/server.js +348 -0
- package/dist/web/style.css +543 -0
- package/dist/web/tasks.js +63 -0
- package/docs/adr/0001-durable-owns-state.md +11 -0
- package/docs/adr/0002-module-layering.md +11 -0
- package/docs/adr/0003-replies-at-most-once.md +11 -0
- package/docs/adr/0004-native-extensions.md +11 -0
- package/docs/adr/0005-history-migration.md +11 -0
- package/docs/adr/0006-jsonl-storage.md +11 -0
- package/docs/adr/0007-images-by-path.md +11 -0
- package/docs/adr/0008-compaction-and-run.md +11 -0
- package/docs/adr/0009-one-shot-cutover.md +11 -0
- package/docs/adr/0010-test-budget.md +11 -0
- package/docs/adr/0011-reconcile-unsent-answers.md +24 -0
- package/docs/adr/0012-run-in-owned-conversation.md +22 -0
- package/docs/adr/0013-thin-adapters-around-durable.md +18 -0
- package/docs/adr/0014-ephemeral-private-storage.md +13 -0
- package/docs/adr/0015-ordinary-stop-keeps-native-inbox.md +21 -0
- package/docs/adr/0016-process-http-transport.md +21 -0
- package/docs/adr/0017-browser-cli-owned-scope.md +22 -0
- package/docs/adr/0018-tasks-without-prompt-api.md +19 -0
- package/docs/adr/0019-remove-scheduled-services.md +41 -0
- package/docs/adr/0020-chat-task-progress.md +41 -0
- package/docs/adr/0021-readable-progress-without-link-previews.md +33 -0
- package/docs/adr/0022-progress-admission-and-settlement.md +35 -0
- package/docs/adr/0023-retain-progress-type-prefixes.md +18 -0
- package/docs/adr/0024-status-marker-before-type-prefix.md +13 -0
- package/docs/adr/0025-reusable-progress-and-command-preview.md +49 -0
- package/docs/adr/0026-inline-command-only-requests.md +16 -0
- package/docs/adr/0027-command-preview-width.md +10 -0
- package/docs/adr/0028-command-preview-120.md +8 -0
- package/docs/adr/0030-shared-web-read-cache.md +33 -0
- package/docs/adr/0031-quiet-compaction-progress.md +32 -0
- package/docs/adr/0032-native-background-schedules.md +58 -0
- package/docs/adr/0033-operator-scheduled-run.md +23 -0
- package/docs/adr/0034-machine-local-schedule-time.md +36 -0
- package/docs/adr/0035-external-business-task-extensions.md +56 -0
- package/docs/adr/0036-workspace-policy-and-neutral-service-id.md +37 -0
- package/docs/adr/0037-restart-during-in-flight-work.md +30 -0
- package/docs/adr/0038-restart-any-time.md +25 -0
- package/docs/adr/0039-rerun-interrupted-tools.md +24 -0
- package/docs/adr/0040-chat-progress-notices.md +44 -0
- package/docs/adr/0041-restart-and-recovery.md +28 -0
- package/docs/adr/0042-background-schedules-and-workspace-extensions.md +44 -0
- package/docs/adr/0043-remove-legacy-migration.md +23 -0
- package/docs/adr/0044-message-channels.md +32 -0
- package/docs/adr/0045-chat-scheduling-tools.md +51 -0
- package/docs/adr/0046-selective-command-redaction.md +31 -0
- package/docs/adr/0047-one-scheduling-path.md +158 -0
- package/docs/adr/README.md +50 -0
- package/docs/api.md +92 -0
- package/docs/architecture.md +164 -0
- package/docs/browser.md +93 -0
- package/docs/memory.md +27 -0
- package/docs/screenshot.png +0 -0
- package/docs/workspace-extensions.md +133 -0
- package/examples/workspace-extensions/system-context/index.ts +69 -0
- package/examples/workspace-extensions/system-context/package.json +3 -0
- package/ops/README.md +267 -0
- package/ops/preflight.mjs +28 -0
- package/package.json +33 -45
- package/dist/agent.d.ts +0 -60
- package/dist/agent.d.ts.map +0 -1
- package/dist/agent.js +0 -715
- package/dist/agent.js.map +0 -1
- package/dist/cli.d.ts +0 -15
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/imessage.d.ts +0 -33
- package/dist/imessage.d.ts.map +0 -1
- package/dist/imessage.js +0 -76
- package/dist/imessage.js.map +0 -1
- package/dist/logger.d.ts +0 -33
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -104
- package/dist/logger.js.map +0 -1
- package/dist/main.d.ts +0 -5
- package/dist/main.d.ts.map +0 -1
- package/dist/main.js.map +0 -1
- package/dist/memory.d.ts +0 -53
- package/dist/memory.d.ts.map +0 -1
- package/dist/memory.js +0 -196
- package/dist/memory.js.map +0 -1
- package/dist/model-health.d.ts +0 -11
- package/dist/model-health.d.ts.map +0 -1
- package/dist/model-health.js +0 -67
- package/dist/model-health.js.map +0 -1
- package/dist/pipeline.d.ts +0 -27
- package/dist/pipeline.d.ts.map +0 -1
- package/dist/pipeline.js +0 -59
- package/dist/pipeline.js.map +0 -1
- package/dist/queue.d.ts +0 -23
- package/dist/queue.d.ts.map +0 -1
- package/dist/queue.js +0 -89
- package/dist/queue.js.map +0 -1
- package/dist/rich-text.d.ts +0 -26
- package/dist/rich-text.d.ts.map +0 -1
- package/dist/rich-text.js.map +0 -1
- package/dist/self-echo.d.ts +0 -19
- package/dist/self-echo.d.ts.map +0 -1
- package/dist/self-echo.js +0 -54
- package/dist/self-echo.js.map +0 -1
- package/dist/send.d.ts +0 -24
- package/dist/send.d.ts.map +0 -1
- package/dist/send.js.map +0 -1
- package/dist/settings.d.ts +0 -44
- package/dist/settings.d.ts.map +0 -1
- package/dist/settings.js +0 -80
- package/dist/settings.js.map +0 -1
- package/dist/store.d.ts +0 -57
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js +0 -124
- package/dist/store.js.map +0 -1
- package/dist/tasks.d.ts +0 -95
- package/dist/tasks.d.ts.map +0 -1
- package/dist/tasks.js +0 -384
- package/dist/tasks.js.map +0 -1
- package/dist/types.d.ts +0 -93
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -38
- package/dist/types.js.map +0 -1
- package/dist/watch.d.ts +0 -21
- package/dist/watch.d.ts.map +0 -1
- package/dist/watch.js +0 -219
- package/dist/watch.js.map +0 -1
- package/dist/web/data.d.ts +0 -11
- package/dist/web/data.d.ts.map +0 -1
- package/dist/web/data.js +0 -56
- package/dist/web/data.js.map +0 -1
- package/dist/web/html.d.ts +0 -5
- package/dist/web/html.d.ts.map +0 -1
- package/dist/web/html.js +0 -16
- package/dist/web/html.js.map +0 -1
- package/dist/web/index.d.ts +0 -23
- package/dist/web/index.d.ts.map +0 -1
- package/dist/web/index.js +0 -279
- package/dist/web/index.js.map +0 -1
- package/dist/web/render.d.ts +0 -11
- package/dist/web/render.d.ts.map +0 -1
- package/dist/web/render.js +0 -56
- package/dist/web/render.js.map +0 -1
- package/dist/web/templates/logs.eta +0 -75
- package/dist/web/templates/memory.eta +0 -91
- package/dist/web/templates/page.eta +0 -98
package/dist/cli.js
CHANGED
|
@@ -1,199 +1,96 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*
|
|
5
|
-
* Usage:
|
|
6
|
-
* pi-imessage Run in foreground
|
|
7
|
-
* pi-imessage install Install + start launchd service (auto-starts on boot)
|
|
8
|
-
* pi-imessage uninstall Stop + remove launchd service
|
|
9
|
-
* pi-imessage start Start the service
|
|
10
|
-
* pi-imessage stop Stop the service
|
|
11
|
-
* pi-imessage restart Restart the service
|
|
12
|
-
* pi-imessage logs Tail service logs
|
|
13
|
-
*/
|
|
14
|
-
import { execSync, fork } from "node:child_process";
|
|
15
|
-
import { existsSync, mkdirSync, unlinkSync, writeFileSync } from "node:fs";
|
|
16
|
-
import { createRequire } from "node:module";
|
|
1
|
+
#!/usr/bin/env -S node --use-env-proxy --experimental-strip-types
|
|
2
|
+
import { realpathSync } from "node:fs";
|
|
3
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
17
4
|
import { homedir } from "node:os";
|
|
18
|
-
import { join } from "node:path";
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
function getNodePath() {
|
|
29
|
-
try {
|
|
30
|
-
return execSync("which node", { encoding: "utf-8" }).trim();
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
return "/usr/local/bin/node";
|
|
5
|
+
import { join, resolve } from "node:path";
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
7
|
+
import { parseEnv } from "node:util";
|
|
8
|
+
import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
9
|
+
import { startApplication } from "./main.js";
|
|
10
|
+
import { createMessageSender } from "./transport/send.js";
|
|
11
|
+
export async function main(args = process.argv.slice(2)) {
|
|
12
|
+
if (args.includes("--help") || args[0] === "help") {
|
|
13
|
+
console.log("pi-imessage [serve]\npi-imessage install (write launchd job only)\nSee ops/README.md for operator-only installation, deployment and restart.");
|
|
14
|
+
return;
|
|
34
15
|
}
|
|
35
|
-
}
|
|
36
|
-
function buildPlist() {
|
|
37
|
-
const nodePath = getNodePath();
|
|
38
|
-
const stdoutLog = join(LOG_DIR, "stdout.log");
|
|
39
|
-
const stderrLog = join(LOG_DIR, "stderr.log");
|
|
40
|
-
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
41
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
42
|
-
<plist version="1.0">
|
|
43
|
-
<dict>
|
|
44
|
-
<key>Label</key>
|
|
45
|
-
<string>${LABEL}</string>
|
|
46
|
-
<key>ProgramArguments</key>
|
|
47
|
-
<array>
|
|
48
|
-
<string>${nodePath}</string>
|
|
49
|
-
<string>${MAIN_JS}</string>
|
|
50
|
-
</array>
|
|
51
|
-
<key>RunAtLoad</key>
|
|
52
|
-
<true/>
|
|
53
|
-
<key>KeepAlive</key>
|
|
54
|
-
<true/>
|
|
55
|
-
<key>StandardOutPath</key>
|
|
56
|
-
<string>${stdoutLog}</string>
|
|
57
|
-
<key>StandardErrorPath</key>
|
|
58
|
-
<string>${stderrLog}</string>
|
|
59
|
-
<key>EnvironmentVariables</key>
|
|
60
|
-
<dict>
|
|
61
|
-
<key>PATH</key>
|
|
62
|
-
<string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>
|
|
63
|
-
<key>WORKING_DIR</key>
|
|
64
|
-
<string>${WORKING_DIR}</string>
|
|
65
|
-
<key>WEB_HOST</key>
|
|
66
|
-
<string>${WEB_HOST}</string>
|
|
67
|
-
<key>WEB_PORT</key>
|
|
68
|
-
<string>${WEB_PORT}</string>
|
|
69
|
-
<key>WEB_ENABLED</key>
|
|
70
|
-
<string>${WEB_ENABLED}</string>
|
|
71
|
-
</dict>
|
|
72
|
-
</dict>
|
|
73
|
-
</plist>`;
|
|
74
|
-
}
|
|
75
|
-
function isLoaded() {
|
|
76
16
|
try {
|
|
77
|
-
|
|
78
|
-
|
|
17
|
+
// Like the old dotenv entry point: cwd .env, with existing environment values taking priority.
|
|
18
|
+
for (const [name, value] of Object.entries(parseEnv(await readFile(process.env.DOTENV_CONFIG_PATH ?? ".env", "utf8"))))
|
|
19
|
+
if (process.env[name] === undefined && value !== undefined)
|
|
20
|
+
process.env[name] = value;
|
|
79
21
|
}
|
|
80
|
-
catch {
|
|
81
|
-
|
|
22
|
+
catch (error) {
|
|
23
|
+
if (error.code !== "ENOENT")
|
|
24
|
+
throw new Error("Unable to load environment configuration", { cause: error });
|
|
82
25
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
execSync(`launchctl start ${LABEL}`, { stdio: "inherit" });
|
|
114
|
-
console.log("[pi-imessage] Service started");
|
|
115
|
-
}
|
|
116
|
-
function stop() {
|
|
117
|
-
if (!isLoaded()) {
|
|
118
|
-
console.log("[pi-imessage] Service is not running");
|
|
26
|
+
const workingDir = resolve(process.env.WORKING_DIR ?? join(homedir(), ".pi", "imessage"));
|
|
27
|
+
const agentDir = resolve(getAgentDir());
|
|
28
|
+
if (args[0] === "install") {
|
|
29
|
+
const directory = join(homedir(), "Library", "LaunchAgents");
|
|
30
|
+
await mkdir(directory, { recursive: true });
|
|
31
|
+
await mkdir(workingDir, { recursive: true, mode: 0o700 });
|
|
32
|
+
const xml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
33
|
+
const path = join(directory, "org.pi-imessage.service.plist");
|
|
34
|
+
const environment = [
|
|
35
|
+
"WEB_HOST",
|
|
36
|
+
"WEB_PORT",
|
|
37
|
+
"WEB_ENABLED",
|
|
38
|
+
"MESSAGES_DB_PATH",
|
|
39
|
+
"BRAVE_API_KEY",
|
|
40
|
+
"BRAVE_SEARCH_API_KEY",
|
|
41
|
+
"HTTP_PROXY",
|
|
42
|
+
"HTTPS_PROXY",
|
|
43
|
+
"NO_PROXY",
|
|
44
|
+
"http_proxy",
|
|
45
|
+
"https_proxy",
|
|
46
|
+
"no_proxy",
|
|
47
|
+
"NODE_OPTIONS",
|
|
48
|
+
"TZ",
|
|
49
|
+
"DOTENV_CONFIG_PATH",
|
|
50
|
+
]
|
|
51
|
+
.filter((key) => process.env[key] !== undefined)
|
|
52
|
+
.map((key) => `<key>${key}</key><string>${xml(process.env[key] ?? "")}</string>`)
|
|
53
|
+
.join("");
|
|
54
|
+
await writeFile(path, `<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>Label</key><string>org.pi-imessage.service</string><key>ProgramArguments</key><array><string>${xml(process.execPath)}</string><string>--use-env-proxy</string><string>--experimental-strip-types</string><string>${xml(fileURLToPath(import.meta.url))}</string><string>serve</string></array><key>WorkingDirectory</key><string>${xml(process.cwd())}</string><key>EnvironmentVariables</key><dict><key>PI_CODING_AGENT_DIR</key><string>${xml(agentDir)}</string><key>WORKING_DIR</key><string>${xml(workingDir)}</string><key>PATH</key><string>${xml(process.env.PATH ?? "/usr/bin:/bin")}</string>${environment}</dict><key>RunAtLoad</key><true/><key>KeepAlive</key><true/><key>StandardOutPath</key><string>${xml(join(workingDir, "service.log"))}</string><key>StandardErrorPath</key><string>${xml(join(workingDir, "service.log"))}</string></dict></plist>`, { flag: "wx", mode: 0o600 });
|
|
55
|
+
console.log(`Wrote ${path}. Not loaded. Follow ops/README.md for controller handover; never run two services.`);
|
|
119
56
|
return;
|
|
120
57
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
Usage: pi-imessage [command]
|
|
155
|
-
|
|
156
|
-
Commands:
|
|
157
|
-
(none) Run in foreground
|
|
158
|
-
install Install + start launchd service (auto-starts on boot)
|
|
159
|
-
uninstall Stop + remove launchd service
|
|
160
|
-
start Start the service
|
|
161
|
-
stop Stop the service
|
|
162
|
-
restart Restart the service
|
|
163
|
-
logs Tail service logs
|
|
164
|
-
help Show this help message`);
|
|
165
|
-
}
|
|
166
|
-
const command = process.argv[2];
|
|
167
|
-
switch (command) {
|
|
168
|
-
case "install":
|
|
169
|
-
install();
|
|
170
|
-
break;
|
|
171
|
-
case "uninstall":
|
|
172
|
-
uninstall();
|
|
173
|
-
break;
|
|
174
|
-
case "start":
|
|
175
|
-
start();
|
|
176
|
-
break;
|
|
177
|
-
case "stop":
|
|
178
|
-
stop();
|
|
179
|
-
break;
|
|
180
|
-
case "restart":
|
|
181
|
-
restart();
|
|
182
|
-
break;
|
|
183
|
-
case "logs":
|
|
184
|
-
logs();
|
|
185
|
-
break;
|
|
186
|
-
case "help":
|
|
187
|
-
case "--help":
|
|
188
|
-
case "-h":
|
|
189
|
-
help();
|
|
190
|
-
break;
|
|
191
|
-
case undefined:
|
|
192
|
-
runForeground();
|
|
193
|
-
break;
|
|
194
|
-
default:
|
|
195
|
-
console.error(`Unknown command: ${command}\n`);
|
|
196
|
-
help();
|
|
197
|
-
process.exit(1);
|
|
58
|
+
if (args.length && args[0] !== "serve")
|
|
59
|
+
throw new Error("Unknown command; see --help");
|
|
60
|
+
if (args.length > 1)
|
|
61
|
+
throw new Error("Unknown serve arguments; use workspace configuration and reload_extensions");
|
|
62
|
+
const dbPath = process.env.MESSAGES_DB_PATH ?? join(homedir(), "Library", "Messages", "chat.db");
|
|
63
|
+
// Incoming archives stay in the workspace; outgoing staging uses Messages' readable root.
|
|
64
|
+
const sender = createMessageSender({ dbPath });
|
|
65
|
+
const app = await startApplication({
|
|
66
|
+
workingDir,
|
|
67
|
+
agentDir,
|
|
68
|
+
dbPath,
|
|
69
|
+
send: sender.sendMessage,
|
|
70
|
+
sendAttachment: sender.sendAttachment,
|
|
71
|
+
onError: (error) => console.error(new Date().toISOString(), "Messaging poll failed", error),
|
|
72
|
+
web: process.env.WEB_ENABLED === "false"
|
|
73
|
+
? false
|
|
74
|
+
: { host: process.env.WEB_HOST ?? "localhost", port: Number(process.env.WEB_PORT ?? 7750) },
|
|
75
|
+
});
|
|
76
|
+
let closing = false;
|
|
77
|
+
const stop = (signal) => {
|
|
78
|
+
if (closing)
|
|
79
|
+
return;
|
|
80
|
+
closing = true;
|
|
81
|
+
console.log(new Date().toISOString(), "Shutdown requested", { signal });
|
|
82
|
+
void app.close().then(() => {
|
|
83
|
+
console.log(new Date().toISOString(), "pi-imessage stopped");
|
|
84
|
+
}, (error) => {
|
|
85
|
+
console.error(new Date().toISOString(), "Shutdown failed", error);
|
|
86
|
+
process.exitCode = 1;
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
process.once("SIGINT", () => stop("SIGINT"));
|
|
90
|
+
process.once("SIGTERM", () => stop("SIGTERM"));
|
|
198
91
|
}
|
|
199
|
-
|
|
92
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href)
|
|
93
|
+
void main().catch((error) => {
|
|
94
|
+
console.error(new Date().toISOString(), "Command failed", error instanceof Error ? error.message : error);
|
|
95
|
+
process.exitCode = 1;
|
|
96
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
export async function readSettings(workingDir) {
|
|
4
|
+
let raw = {};
|
|
5
|
+
try {
|
|
6
|
+
raw = JSON.parse(await readFile(join(workingDir, "settings.json"), "utf8")) ?? {};
|
|
7
|
+
}
|
|
8
|
+
catch (error) {
|
|
9
|
+
if (!(error instanceof SyntaxError) && error.code !== "ENOENT")
|
|
10
|
+
throw error;
|
|
11
|
+
}
|
|
12
|
+
const allowlist = raw.chatAllowlist;
|
|
13
|
+
const richText = raw.richText;
|
|
14
|
+
const value = raw.modelPolicy ?? {};
|
|
15
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
16
|
+
throw new Error("Invalid modelPolicy");
|
|
17
|
+
const policy = value;
|
|
18
|
+
const modelPolicy = {};
|
|
19
|
+
if (policy.fallback !== undefined) {
|
|
20
|
+
const fallback = policy.fallback;
|
|
21
|
+
if (!fallback ||
|
|
22
|
+
typeof fallback.provider !== "string" ||
|
|
23
|
+
!fallback.provider.trim() ||
|
|
24
|
+
typeof fallback.modelId !== "string" ||
|
|
25
|
+
!fallback.modelId.trim())
|
|
26
|
+
throw new Error("modelPolicy.fallback requires provider and modelId");
|
|
27
|
+
modelPolicy.fallback = { provider: fallback.provider, modelId: fallback.modelId };
|
|
28
|
+
}
|
|
29
|
+
if (policy.codexServiceTier !== undefined) {
|
|
30
|
+
if (policy.codexServiceTier !== "default" && policy.codexServiceTier !== "priority")
|
|
31
|
+
throw new Error("Invalid modelPolicy.codexServiceTier");
|
|
32
|
+
modelPolicy.codexServiceTier = policy.codexServiceTier;
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
// Preserve opaque workspace-owned settings in read-only configuration projections.
|
|
36
|
+
...raw,
|
|
37
|
+
modelPolicy,
|
|
38
|
+
progressMessages: raw.progressMessages === true,
|
|
39
|
+
chatAllowlist: {
|
|
40
|
+
whitelist: Array.isArray(allowlist?.whitelist)
|
|
41
|
+
? allowlist.whitelist.filter((v) => typeof v === "string")
|
|
42
|
+
: [],
|
|
43
|
+
blacklist: Array.isArray(allowlist?.blacklist)
|
|
44
|
+
? allowlist.blacklist.filter((v) => typeof v === "string")
|
|
45
|
+
: ["*"],
|
|
46
|
+
},
|
|
47
|
+
richText: {
|
|
48
|
+
enabled: typeof richText?.enabled === "boolean" ? richText.enabled : false,
|
|
49
|
+
markdown: typeof richText?.markdown === "boolean" ? richText.markdown : true,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export function isReplyEnabled(settings, chatGuid) {
|
|
54
|
+
const { whitelist, blacklist } = settings.chatAllowlist;
|
|
55
|
+
if (blacklist.includes(chatGuid))
|
|
56
|
+
return false;
|
|
57
|
+
if (whitelist.includes(chatGuid))
|
|
58
|
+
return true;
|
|
59
|
+
return !blacklist.includes("*") && whitelist.includes("*");
|
|
60
|
+
}
|