negotium 0.2.18 → 0.2.20
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/dist/agent-helpers.js +367 -313
- package/dist/agent-helpers.js.map +18 -18
- package/dist/background-bash.js +3 -2
- package/dist/background-bash.js.map +3 -3
- package/dist/browser-runtime.js +60 -36
- package/dist/browser-runtime.js.map +6 -6
- package/dist/{chunk-fc58cqry.js → chunk-g2kqfdwm.js} +154 -24
- package/dist/{chunk-fc58cqry.js.map → chunk-g2kqfdwm.js.map} +7 -6
- package/dist/hosted-agent.js +183 -53
- package/dist/hosted-agent.js.map +8 -7
- package/dist/main.js +1395 -626
- package/dist/main.js.map +27 -26
- package/dist/mcp-factories.js +1204 -624
- package/dist/mcp-factories.js.map +21 -20
- package/dist/prompts.js +3 -2
- package/dist/prompts.js.map +3 -3
- package/dist/query-runtime.js +47 -26
- package/dist/query-runtime.js.map +4 -4
- package/dist/registry.js +3 -3
- package/dist/registry.js.map +2 -2
- package/dist/rollout.js +1 -1
- package/dist/runtime/src/agents/archiver.ts +4 -3
- package/dist/runtime/src/application/switch-topic-access-mode.ts +81 -8
- package/dist/runtime/src/bus.ts +19 -2
- package/dist/runtime/src/mcp/canonical-proxy-server.ts +13 -14
- package/dist/runtime/src/mcp/session-comm/runtime.ts +16 -0
- package/dist/runtime/src/mcp/wiki-search-index.ts +359 -0
- package/dist/runtime/src/mcp/wiki-server.ts +559 -98
- package/dist/runtime/src/platform/config.ts +13 -1
- package/dist/runtime/src/platform/mcp-config.ts +1 -1
- package/dist/runtime/src/prompts/agents/wiki-archiver.md +62 -47
- package/dist/runtime/src/runtime/ask-callbacks.ts +19 -11
- package/dist/runtime/src/runtime/background-sessions.ts +9 -7
- package/dist/runtime/src/runtime/visual-store.ts +31 -23
- package/dist/runtime/src/storage/api-topics.ts +26 -0
- package/dist/runtime/src/storage/browser-profiles.ts +16 -8
- package/dist/runtime/src/storage/runtime-events.ts +30 -20
- package/dist/runtime/src/storage/runtime-gateway-submissions.ts +24 -16
- package/dist/runtime/src/storage/runtime-turn-requests.ts +9 -1
- package/dist/runtime/src/storage/self-schedules.ts +32 -24
- package/dist/runtime/src/storage/storage-host.ts +105 -43
- package/dist/runtime/src/storage/vault.ts +12 -3
- package/dist/runtime/src/version.ts +1 -1
- package/dist/runtime-helpers.js +47 -26
- package/dist/runtime-helpers.js.map +4 -4
- package/dist/storage.js +76 -41
- package/dist/storage.js.map +4 -4
- package/dist/types/packages/core/src/agents/archiver.d.ts +1 -1
- package/dist/types/packages/core/src/mcp/wiki-search-index.d.ts +59 -0
- package/dist/types/packages/core/src/storage/api-topics.d.ts +15 -0
- package/dist/types/packages/core/src/storage/storage-host.d.ts +10 -0
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/dist/vault.js +140 -10
- package/dist/vault.js.map +6 -5
- package/package.json +1 -1
package/dist/mcp-factories.js
CHANGED
|
@@ -29,6 +29,59 @@ var init_types = __esm(() => {
|
|
|
29
29
|
MAESTRO_EFFORT_VALUES = ["low", "medium", "high", "xhigh", "max"];
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
+
// ../../packages/core/src/storage/sqlite.ts
|
|
33
|
+
var isBun, Database;
|
|
34
|
+
var init_sqlite = __esm(async () => {
|
|
35
|
+
isBun = typeof process.versions.bun === "string";
|
|
36
|
+
if (isBun) {
|
|
37
|
+
({ Database } = await import("bun:sqlite"));
|
|
38
|
+
} else {
|
|
39
|
+
const nodeSqliteSpecifier = ["node", "sqlite"].join(":");
|
|
40
|
+
const { DatabaseSync } = await import(nodeSqliteSpecifier);
|
|
41
|
+
|
|
42
|
+
class NodeDatabase {
|
|
43
|
+
#db;
|
|
44
|
+
constructor(path, options = {}) {
|
|
45
|
+
this.#db = options.readonly ? new DatabaseSync(path, { readOnly: true }) : new DatabaseSync(path);
|
|
46
|
+
}
|
|
47
|
+
query(sql) {
|
|
48
|
+
return this.#db.prepare(sql);
|
|
49
|
+
}
|
|
50
|
+
prepare(sql) {
|
|
51
|
+
return this.#db.prepare(sql);
|
|
52
|
+
}
|
|
53
|
+
exec(sql) {
|
|
54
|
+
this.#db.exec(sql);
|
|
55
|
+
}
|
|
56
|
+
run(sql, ...params) {
|
|
57
|
+
return this.#db.prepare(sql).run(...params);
|
|
58
|
+
}
|
|
59
|
+
transaction(fn) {
|
|
60
|
+
const run = (begin) => (...args) => {
|
|
61
|
+
this.#db.exec(begin);
|
|
62
|
+
try {
|
|
63
|
+
const result = fn(...args);
|
|
64
|
+
this.#db.exec("COMMIT");
|
|
65
|
+
return result;
|
|
66
|
+
} catch (err) {
|
|
67
|
+
this.#db.exec("ROLLBACK");
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const tx = run("BEGIN");
|
|
72
|
+
tx.deferred = run("BEGIN DEFERRED");
|
|
73
|
+
tx.immediate = run("BEGIN IMMEDIATE");
|
|
74
|
+
tx.exclusive = run("BEGIN EXCLUSIVE");
|
|
75
|
+
return tx;
|
|
76
|
+
}
|
|
77
|
+
close() {
|
|
78
|
+
this.#db.close();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
Database = NodeDatabase;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
32
85
|
// ../../packages/core/src/platform/config-helpers.ts
|
|
33
86
|
function readEnvText(env, key) {
|
|
34
87
|
const value2 = env[key]?.trim();
|
|
@@ -72,11 +125,11 @@ import { execFileSync } from "child_process";
|
|
|
72
125
|
import { randomBytes } from "crypto";
|
|
73
126
|
import {
|
|
74
127
|
accessSync,
|
|
75
|
-
chmodSync,
|
|
128
|
+
chmodSync as chmodSync2,
|
|
76
129
|
constants,
|
|
77
|
-
existsSync,
|
|
130
|
+
existsSync as existsSync2,
|
|
78
131
|
mkdirSync,
|
|
79
|
-
readFileSync,
|
|
132
|
+
readFileSync as readFileSync2,
|
|
80
133
|
writeFileSync
|
|
81
134
|
} from "fs";
|
|
82
135
|
import { createRequire } from "module";
|
|
@@ -93,7 +146,7 @@ function resolveAgentEnv(envKey, fallback, legacyEnvKey) {
|
|
|
93
146
|
function resolveProjectRoot() {
|
|
94
147
|
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
95
148
|
const packagedRuntime = resolve(moduleDir, "runtime");
|
|
96
|
-
if (
|
|
149
|
+
if (existsSync2(resolve(packagedRuntime, "src")))
|
|
97
150
|
return packagedRuntime;
|
|
98
151
|
return resolve(moduleDir, "../..");
|
|
99
152
|
}
|
|
@@ -101,7 +154,7 @@ function resolveDependencyBin(name) {
|
|
|
101
154
|
let dir = PROJECT_ROOT;
|
|
102
155
|
while (true) {
|
|
103
156
|
const candidate = resolve(dir, "node_modules", ".bin", name);
|
|
104
|
-
if (
|
|
157
|
+
if (existsSync2(candidate))
|
|
105
158
|
return candidate;
|
|
106
159
|
const parent = dirname(dir);
|
|
107
160
|
if (parent === dir)
|
|
@@ -139,7 +192,7 @@ function browserRsMeetsMinimumVersion(candidate) {
|
|
|
139
192
|
try {
|
|
140
193
|
const output = execFileSync(candidate, ["--version"], {
|
|
141
194
|
encoding: "utf8",
|
|
142
|
-
timeout:
|
|
195
|
+
timeout: BROWSER_RS_VERSION_PROBE_TIMEOUT_MS,
|
|
143
196
|
stdio: ["ignore", "pipe", "ignore"]
|
|
144
197
|
}).trim();
|
|
145
198
|
const match = output.match(/^browser-rs (\d+)\.(\d+)\.(\d+)$/);
|
|
@@ -215,14 +268,14 @@ function loadOrCreateLocalSecret(envKey, filename, options = {}) {
|
|
|
215
268
|
if (options.persistEnvValue) {
|
|
216
269
|
writeFileSync(secretFile, `${envValue}
|
|
217
270
|
`, { mode: 384 });
|
|
218
|
-
|
|
271
|
+
chmodSync2(secretFile, 384);
|
|
219
272
|
}
|
|
220
273
|
return envValue;
|
|
221
274
|
}
|
|
222
|
-
if (
|
|
223
|
-
const stored =
|
|
275
|
+
if (existsSync2(secretFile)) {
|
|
276
|
+
const stored = readFileSync2(secretFile, "utf-8").trim();
|
|
224
277
|
if (stored) {
|
|
225
|
-
|
|
278
|
+
chmodSync2(secretFile, 384);
|
|
226
279
|
return stored;
|
|
227
280
|
}
|
|
228
281
|
}
|
|
@@ -234,10 +287,10 @@ function loadOrCreateLocalSecret(envKey, filename, options = {}) {
|
|
|
234
287
|
} catch (error) {
|
|
235
288
|
if (error.code !== "EEXIST")
|
|
236
289
|
throw error;
|
|
237
|
-
const stored =
|
|
290
|
+
const stored = readFileSync2(secretFile, "utf-8").trim();
|
|
238
291
|
if (!stored)
|
|
239
292
|
throw new Error(`Secret file exists but is empty: ${secretFile}`);
|
|
240
|
-
|
|
293
|
+
chmodSync2(secretFile, 384);
|
|
241
294
|
return stored;
|
|
242
295
|
}
|
|
243
296
|
}
|
|
@@ -250,7 +303,7 @@ function resolveDefaultModel(agent, registryDefaultModel) {
|
|
|
250
303
|
function codexAuthFilePath() {
|
|
251
304
|
return process.env.NEGOTIUM_CODEX_AUTH_FILE || join(process.env.CODEX_HOME || join(homedir(), ".codex"), "auth.json");
|
|
252
305
|
}
|
|
253
|
-
var HOME, PROJECT_ROOT, STATE_DIR_ENV, STATE_DIR, WORKSPACE_DIR, TOPIC_WORKSPACE_DIR, SHARED_WIKI_DIR, CRON_WORKSPACE_DIR, BROWSER_DIR, BROWSER_PROFILES_DIR, BINARIES_DIR, SECRETS_DIR, DM_WORKSPACE_DIR, SESSION_WORKSPACE_DIR, CLAUDE_EXECUTABLE_ENV, CLAUDE_EXECUTABLE, DEFAULT_OUTPUT_LANGUAGE = "English", BROWSER_RS_VERSION = "v0.1.19", BROWSER_RS_MIN_SECURE_VERSION = "0.1.15", SNIPPETS_API_URL, BROWSER_RS_BIN, BASH_RS_VERSION = "v0.1.5", BASH_RS_BIN, PLAYWRIGHT_MCP_BIN, TSX_BIN, TSX_LOADER, TSCONFIG_PATH, SESSION_COMM_SERVER, TASK_SERVER, BROWSER_MCP_SSE_PROXY_SERVER, CANONICAL_MCP_PROXY_SERVER, WIKI_SERVER, TOKEN_STATS_SERVER, COMPACTION_LOG_SERVER, SYSTEM_HEALTH_SERVER, AGENT_HEALTH_SERVER, VAULT_SERVER, BG_BASH_BASE_PORT, BG_BASH_MAX_PORT, RUNTIME_MCP_SECRET, NODE_CONTROL_TOKEN, VAULT_MASTER_KEY, NEGOTIUM_PORT, hostname, DATA_DIR, LOG_DIR, UPLOADS_DIR, VAULT_DIR, SESSIONS_DB, DEBUG_FILE, USERS_LOG_DIR, RUN_DIR, PROGRESS_DIR, DM_CMD_DIR, DM_RESP_DIR, SESSION_INBOX_DIR, SESSION_ASKS_DIR, BASHRS_SPILL_ROOT, PLAYWRIGHT_BASE_PORT, PLAYWRIGHT_MAX_PORT, PLAYWRIGHT_PORTS_DIR, ACTIVE_QUERY_STALE_MS, AGENTS_PROMPTS_DIR, RESOURCES_DIR, FILE_TAG_REGEX, MODEL_SONNET = "claude-sonnet-5", MODEL_OPUS = "claude-opus-5", MODEL_FABLE = "claude-fable-5", FALLBACK_AGENT, SESSION_AGENT, GATEWAY_AGENT, FALLBACK_MODEL, SESSION_MODEL, GATEWAY_MODEL, FFMPEG_BIN, FFPROBE_BIN, PYTHON_BIN, FASTER_WHISPER_WRAPPER, WHISPER_MODEL, TESSERACT_BIN, PDFTOTEXT_BIN, _envMaxTellDepth, MAX_TELL_DEPTH;
|
|
306
|
+
var HOME, PROJECT_ROOT, STATE_DIR_ENV, STATE_DIR, WORKSPACE_DIR, TOPIC_WORKSPACE_DIR, SHARED_WIKI_DIR, CRON_WORKSPACE_DIR, BROWSER_DIR, BROWSER_PROFILES_DIR, BINARIES_DIR, SECRETS_DIR, DM_WORKSPACE_DIR, SESSION_WORKSPACE_DIR, CLAUDE_EXECUTABLE_ENV, CLAUDE_EXECUTABLE, DEFAULT_OUTPUT_LANGUAGE = "English", BROWSER_RS_VERSION = "v0.1.19", BROWSER_RS_MIN_SECURE_VERSION = "0.1.15", BROWSER_RS_VERSION_PROBE_TIMEOUT_MS = 15000, SNIPPETS_API_URL, BROWSER_RS_BIN, BASH_RS_VERSION = "v0.1.5", BASH_RS_BIN, PLAYWRIGHT_MCP_BIN, TSX_BIN, TSX_LOADER, TSCONFIG_PATH, SESSION_COMM_SERVER, TASK_SERVER, BROWSER_MCP_SSE_PROXY_SERVER, CANONICAL_MCP_PROXY_SERVER, WIKI_SERVER, TOKEN_STATS_SERVER, COMPACTION_LOG_SERVER, SYSTEM_HEALTH_SERVER, AGENT_HEALTH_SERVER, VAULT_SERVER, BG_BASH_BASE_PORT, BG_BASH_MAX_PORT, RUNTIME_MCP_SECRET, NODE_CONTROL_TOKEN, VAULT_MASTER_KEY, NEGOTIUM_PORT, hostname, DATA_DIR, LOG_DIR, UPLOADS_DIR, VAULT_DIR, SESSIONS_DB, DEBUG_FILE, USERS_LOG_DIR, RUN_DIR, PROGRESS_DIR, DM_CMD_DIR, DM_RESP_DIR, SESSION_INBOX_DIR, SESSION_ASKS_DIR, BASHRS_SPILL_ROOT, PLAYWRIGHT_BASE_PORT, PLAYWRIGHT_MAX_PORT, PLAYWRIGHT_PORTS_DIR, ACTIVE_QUERY_STALE_MS, AGENTS_PROMPTS_DIR, RESOURCES_DIR, FILE_TAG_REGEX, MODEL_SONNET = "claude-sonnet-5", MODEL_OPUS = "claude-opus-5", MODEL_FABLE = "claude-fable-5", FALLBACK_AGENT, SESSION_AGENT, GATEWAY_AGENT, FALLBACK_MODEL, SESSION_MODEL, GATEWAY_MODEL, FFMPEG_BIN, FFPROBE_BIN, PYTHON_BIN, FASTER_WHISPER_WRAPPER, WHISPER_MODEL, TESSERACT_BIN, PDFTOTEXT_BIN, _envMaxTellDepth, MAX_TELL_DEPTH;
|
|
254
307
|
var init_config = __esm(() => {
|
|
255
308
|
init_config_helpers();
|
|
256
309
|
init_logger();
|
|
@@ -569,7 +622,7 @@ var init_shared = __esm(() => {
|
|
|
569
622
|
});
|
|
570
623
|
|
|
571
624
|
// ../../packages/core/src/platform/file-utils.ts
|
|
572
|
-
import { unlinkSync as
|
|
625
|
+
import { unlinkSync as unlinkSync3 } from "fs";
|
|
573
626
|
function createSafeUnlink(host) {
|
|
574
627
|
return (path, warnLabel) => {
|
|
575
628
|
try {
|
|
@@ -589,7 +642,7 @@ var defaultSafeUnlink;
|
|
|
589
642
|
var init_file_utils = __esm(() => {
|
|
590
643
|
init_logger();
|
|
591
644
|
defaultSafeUnlink = createSafeUnlink({
|
|
592
|
-
unlink:
|
|
645
|
+
unlink: unlinkSync3,
|
|
593
646
|
warn: (context, message) => logger.warn(context, message)
|
|
594
647
|
});
|
|
595
648
|
});
|
|
@@ -601,15 +654,15 @@ import {
|
|
|
601
654
|
fsyncSync,
|
|
602
655
|
mkdirSync as mkdirSync4,
|
|
603
656
|
openSync as openSync2,
|
|
604
|
-
readFileSync as
|
|
657
|
+
readFileSync as readFileSync4,
|
|
605
658
|
renameSync as renameSync2,
|
|
606
659
|
statSync as statSync2,
|
|
607
|
-
unlinkSync as
|
|
660
|
+
unlinkSync as unlinkSync4,
|
|
608
661
|
writeFileSync as writeFileSync3
|
|
609
662
|
} from "fs";
|
|
610
663
|
import { dirname as dirname3 } from "path";
|
|
611
664
|
function readJsonlLines(filePath) {
|
|
612
|
-
return
|
|
665
|
+
return readFileSync4(filePath, "utf-8").trim().split(`
|
|
613
666
|
`).filter(Boolean);
|
|
614
667
|
}
|
|
615
668
|
function parseJsonlText(raw) {
|
|
@@ -618,7 +671,7 @@ function parseJsonlText(raw) {
|
|
|
618
671
|
}
|
|
619
672
|
function readJsonFile(filePath) {
|
|
620
673
|
try {
|
|
621
|
-
return JSON.parse(
|
|
674
|
+
return JSON.parse(readFileSync4(filePath, "utf-8"));
|
|
622
675
|
} catch {
|
|
623
676
|
return null;
|
|
624
677
|
}
|
|
@@ -708,7 +761,7 @@ function writeJsonlFile(filePath, entries) {
|
|
|
708
761
|
} catch {}
|
|
709
762
|
}
|
|
710
763
|
try {
|
|
711
|
-
|
|
764
|
+
unlinkSync4(tmpPath);
|
|
712
765
|
} catch {}
|
|
713
766
|
throw err;
|
|
714
767
|
}
|
|
@@ -744,13 +797,13 @@ var init_jsonl = __esm(() => {
|
|
|
744
797
|
|
|
745
798
|
// ../../packages/core/src/agents/rollout/claude.ts
|
|
746
799
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
747
|
-
import { existsSync as
|
|
800
|
+
import { existsSync as existsSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
748
801
|
import { homedir as homedir2 } from "os";
|
|
749
802
|
import { join as join3 } from "path";
|
|
750
803
|
function loadClaudeAttachments() {
|
|
751
804
|
if (_attachmentsCache)
|
|
752
805
|
return _attachmentsCache;
|
|
753
|
-
const raw =
|
|
806
|
+
const raw = readFileSync5(join3(FIXTURES_DIR, "claude-attachments.jsonl"), "utf8");
|
|
754
807
|
const lines = parseJsonlText(raw);
|
|
755
808
|
if (lines.length < 2) {
|
|
756
809
|
throw new Error(`loadClaudeAttachments: expected >=2 entries in claude-attachments.jsonl, got ${lines.length}`);
|
|
@@ -865,7 +918,7 @@ var init_claude = __esm(() => {
|
|
|
865
918
|
});
|
|
866
919
|
|
|
867
920
|
// ../../packages/core/src/agents/claude-registry.ts
|
|
868
|
-
import { existsSync as
|
|
921
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync5, readdirSync as readdirSync2, renameSync as renameSync3, unlinkSync as unlinkSync5 } from "fs";
|
|
869
922
|
import { homedir as homedir3 } from "os";
|
|
870
923
|
import { join as join4 } from "path";
|
|
871
924
|
var ALIAS_MAP, VALID_ALIASES, VALID_EFFORTS, claudeRegistry, claudeRegistryOperations;
|
|
@@ -917,8 +970,8 @@ var init_claude_registry = __esm(() => {
|
|
|
917
970
|
const projectsRoot = join4(homedir3(), ".claude", "projects");
|
|
918
971
|
const destDir = join4(projectsRoot, encodeClaudeCwd(cwd));
|
|
919
972
|
const destPath = join4(destDir, `${result.sessionId}.jsonl`);
|
|
920
|
-
if (!
|
|
921
|
-
const sourcePath = readdirSync2(projectsRoot).map((d) => join4(projectsRoot, d, `${result.sessionId}.jsonl`)).find((p) =>
|
|
973
|
+
if (!existsSync5(destPath)) {
|
|
974
|
+
const sourcePath = readdirSync2(projectsRoot).map((d) => join4(projectsRoot, d, `${result.sessionId}.jsonl`)).find((p) => existsSync5(p));
|
|
922
975
|
if (!sourcePath) {
|
|
923
976
|
throw new Error(`claude forkSession: fork rollout ${result.sessionId}.jsonl not found under ${projectsRoot}`);
|
|
924
977
|
}
|
|
@@ -936,7 +989,7 @@ var init_claude_registry = __esm(() => {
|
|
|
936
989
|
for (const sid of sessionIds) {
|
|
937
990
|
const path = join4(projectsDir, `${sid}.jsonl`);
|
|
938
991
|
try {
|
|
939
|
-
|
|
992
|
+
unlinkSync5(path);
|
|
940
993
|
} catch (e) {
|
|
941
994
|
if (e?.code !== "ENOENT") {
|
|
942
995
|
logger.warn({ err: e, path }, "claude cleanupRollouts: unlink failed");
|
|
@@ -952,27 +1005,27 @@ var init_claude_registry = __esm(() => {
|
|
|
952
1005
|
});
|
|
953
1006
|
|
|
954
1007
|
// ../../packages/core/src/version.ts
|
|
955
|
-
var NEGOTIUM_VERSION = "0.2.
|
|
1008
|
+
var NEGOTIUM_VERSION = "0.2.20";
|
|
956
1009
|
|
|
957
1010
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
958
1011
|
import { spawn as spawn2 } from "child_process";
|
|
959
1012
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
960
1013
|
import {
|
|
961
|
-
chmodSync as
|
|
1014
|
+
chmodSync as chmodSync3,
|
|
962
1015
|
copyFileSync,
|
|
963
|
-
existsSync as
|
|
1016
|
+
existsSync as existsSync6,
|
|
964
1017
|
mkdtempSync,
|
|
965
|
-
readFileSync as
|
|
1018
|
+
readFileSync as readFileSync6,
|
|
966
1019
|
renameSync as renameSync4,
|
|
967
1020
|
rmSync,
|
|
968
|
-
unlinkSync as
|
|
1021
|
+
unlinkSync as unlinkSync6,
|
|
969
1022
|
writeFileSync as writeFileSync5
|
|
970
1023
|
} from "fs";
|
|
971
1024
|
import { createRequire as createRequire2 } from "module";
|
|
972
1025
|
import { tmpdir } from "os";
|
|
973
1026
|
import { dirname as dirname4, join as join5 } from "path";
|
|
974
1027
|
function readPackageVersion(packageJsonPath) {
|
|
975
|
-
const parsed = JSON.parse(
|
|
1028
|
+
const parsed = JSON.parse(readFileSync6(packageJsonPath, "utf8"));
|
|
976
1029
|
if (typeof parsed.version !== "string" || !parsed.version.trim()) {
|
|
977
1030
|
throw new Error(`Codex package has no valid version: ${packageJsonPath}`);
|
|
978
1031
|
}
|
|
@@ -994,7 +1047,7 @@ function parseCodexModelCache(contents, sourcePath) {
|
|
|
994
1047
|
return parsed;
|
|
995
1048
|
}
|
|
996
1049
|
function readCodexModelCache(cachePath) {
|
|
997
|
-
const contents =
|
|
1050
|
+
const contents = readFileSync6(cachePath, "utf8");
|
|
998
1051
|
return { contents, parsed: parseCodexModelCache(contents, cachePath) };
|
|
999
1052
|
}
|
|
1000
1053
|
function readCompatibleCodexModelCache(cachePath) {
|
|
@@ -1006,16 +1059,16 @@ function readCompatibleCodexModelCache(cachePath) {
|
|
|
1006
1059
|
return cache;
|
|
1007
1060
|
}
|
|
1008
1061
|
function writePrivateFileAtomic(path, contents) {
|
|
1009
|
-
if (
|
|
1062
|
+
if (existsSync6(path) && readFileSync6(path, "utf8") === contents)
|
|
1010
1063
|
return;
|
|
1011
1064
|
const tempPath = `${path}.${process.pid}.${randomUUID3()}.tmp`;
|
|
1012
1065
|
try {
|
|
1013
1066
|
writeFileSync5(tempPath, contents, { encoding: "utf8", mode: 384 });
|
|
1014
1067
|
renameSync4(tempPath, path);
|
|
1015
|
-
|
|
1068
|
+
chmodSync3(path, 384);
|
|
1016
1069
|
} finally {
|
|
1017
1070
|
try {
|
|
1018
|
-
|
|
1071
|
+
unlinkSync6(tempPath);
|
|
1019
1072
|
} catch {}
|
|
1020
1073
|
}
|
|
1021
1074
|
}
|
|
@@ -1043,7 +1096,7 @@ async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
|
1043
1096
|
} catch {}
|
|
1044
1097
|
if (error)
|
|
1045
1098
|
reject(error);
|
|
1046
|
-
else if (!
|
|
1099
|
+
else if (!existsSync6(cachePath))
|
|
1047
1100
|
reject(new Error("Codex did not create its model cache"));
|
|
1048
1101
|
else
|
|
1049
1102
|
resolve4();
|
|
@@ -1111,12 +1164,12 @@ async function bootstrapIsolatedCodexModelCache(authFilePath, bootstrap) {
|
|
|
1111
1164
|
try {
|
|
1112
1165
|
const isolatedAuthPath = join5(isolatedHome, "auth.json");
|
|
1113
1166
|
copyFileSync(authFilePath, isolatedAuthPath);
|
|
1114
|
-
|
|
1167
|
+
chmodSync3(isolatedAuthPath, 384);
|
|
1115
1168
|
const sourceConfigPath = join5(sourceHome, "config.toml");
|
|
1116
|
-
if (
|
|
1169
|
+
if (existsSync6(sourceConfigPath)) {
|
|
1117
1170
|
const isolatedConfigPath = join5(isolatedHome, "config.toml");
|
|
1118
1171
|
copyFileSync(sourceConfigPath, isolatedConfigPath);
|
|
1119
|
-
|
|
1172
|
+
chmodSync3(isolatedConfigPath, 384);
|
|
1120
1173
|
}
|
|
1121
1174
|
await bootstrap(isolatedHome, isolatedCachePath);
|
|
1122
1175
|
return readCompatibleCodexModelCache(isolatedCachePath).contents;
|
|
@@ -1128,7 +1181,7 @@ async function ensureCodexModelCache(authFilePath, bootstrap = bootstrapCodexMod
|
|
|
1128
1181
|
const codexHome = dirname4(authFilePath);
|
|
1129
1182
|
const configuredCachePath = process.env.NEGOTIUM_CODEX_MODELS_CACHE_FILE;
|
|
1130
1183
|
if (configuredCachePath) {
|
|
1131
|
-
if (!
|
|
1184
|
+
if (!existsSync6(configuredCachePath)) {
|
|
1132
1185
|
throw new Error(`Configured Codex model cache does not exist: ${configuredCachePath}`);
|
|
1133
1186
|
}
|
|
1134
1187
|
readCompatibleCodexModelCache(configuredCachePath);
|
|
@@ -1136,14 +1189,14 @@ async function ensureCodexModelCache(authFilePath, bootstrap = bootstrapCodexMod
|
|
|
1136
1189
|
}
|
|
1137
1190
|
const bundledCachePath = bundledCodexModelCachePath(authFilePath);
|
|
1138
1191
|
const sharedCachePath = join5(codexHome, "models_cache.json");
|
|
1139
|
-
if (
|
|
1192
|
+
if (existsSync6(sharedCachePath)) {
|
|
1140
1193
|
try {
|
|
1141
1194
|
const shared = readCompatibleCodexModelCache(sharedCachePath);
|
|
1142
1195
|
writePrivateFileAtomic(bundledCachePath, shared.contents);
|
|
1143
1196
|
return bundledCachePath;
|
|
1144
1197
|
} catch {}
|
|
1145
1198
|
}
|
|
1146
|
-
if (
|
|
1199
|
+
if (existsSync6(bundledCachePath)) {
|
|
1147
1200
|
try {
|
|
1148
1201
|
readCompatibleCodexModelCache(bundledCachePath);
|
|
1149
1202
|
return bundledCachePath;
|
|
@@ -2188,57 +2241,161 @@ var init_mcp_config = __esm(() => {
|
|
|
2188
2241
|
nodeMcpEntries = [];
|
|
2189
2242
|
});
|
|
2190
2243
|
|
|
2191
|
-
// ../../packages/core/src/storage/
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2244
|
+
// ../../packages/core/src/storage/storage-host.ts
|
|
2245
|
+
import { mkdirSync as mkdirSync6 } from "fs";
|
|
2246
|
+
import { homedir as homedir4 } from "os";
|
|
2247
|
+
import { dirname as dirname5, join as join6, resolve as resolve5 } from "path";
|
|
2248
|
+
function storageState() {
|
|
2249
|
+
const holder = globalThis;
|
|
2250
|
+
const existing = holder[STORAGE_HOST_STATE];
|
|
2251
|
+
if (existing)
|
|
2252
|
+
return existing;
|
|
2253
|
+
const created = {
|
|
2254
|
+
configuredHost: {},
|
|
2255
|
+
fallbackDatabase: null,
|
|
2256
|
+
fallbackDatabasePath: null,
|
|
2257
|
+
frames: [],
|
|
2258
|
+
schemaInitializers: [],
|
|
2259
|
+
initializedSchemas: new WeakMap,
|
|
2260
|
+
initializingDatabases: new WeakSet
|
|
2261
|
+
};
|
|
2262
|
+
Object.defineProperty(holder, STORAGE_HOST_STATE, {
|
|
2263
|
+
value: created,
|
|
2264
|
+
enumerable: false,
|
|
2265
|
+
writable: false,
|
|
2266
|
+
configurable: false
|
|
2267
|
+
});
|
|
2268
|
+
return created;
|
|
2269
|
+
}
|
|
2270
|
+
function envPath(name, fallback) {
|
|
2271
|
+
const value2 = process.env[name]?.trim();
|
|
2272
|
+
return resolve5(value2 || fallback);
|
|
2273
|
+
}
|
|
2274
|
+
function defaultStateDir() {
|
|
2275
|
+
return envPath("NEGOTIUM_STATE_DIR", join6(homedir4(), ".negotium"));
|
|
2276
|
+
}
|
|
2277
|
+
function defaultDataDir() {
|
|
2278
|
+
return envPath("NEGOTIUM_DATA_DIR", join6(defaultStateDir(), "data"));
|
|
2279
|
+
}
|
|
2280
|
+
function defaultLogDir() {
|
|
2281
|
+
return envPath("NEGOTIUM_LOG_DIR", join6(defaultStateDir(), "logs"));
|
|
2282
|
+
}
|
|
2283
|
+
function defaultWorkspaceDir() {
|
|
2284
|
+
return envPath("NEGOTIUM_WORKSPACE_DIR", join6(defaultStateDir(), "workspace"));
|
|
2285
|
+
}
|
|
2286
|
+
function defaultSessionAsksDir() {
|
|
2287
|
+
const runDir = envPath("NEGOTIUM_RUN_DIR", join6(defaultStateDir(), "runtime"));
|
|
2288
|
+
return join6(runDir, "session-asks");
|
|
2289
|
+
}
|
|
2290
|
+
function defaultSessionsDatabasePath() {
|
|
2291
|
+
return envPath("SESSIONS_DB_PATH", join6(resolveStorageDataDir(), "sessions.db"));
|
|
2292
|
+
}
|
|
2293
|
+
function isSqliteBusy(error) {
|
|
2294
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2295
|
+
return /database is (?:locked|busy)|SQLITE_(?:BUSY|LOCKED)/i.test(message);
|
|
2296
|
+
}
|
|
2297
|
+
function execWithBusyRetry(database, sql, timeoutMs = SQLITE_INIT_TIMEOUT_MS) {
|
|
2298
|
+
const deadline = Date.now() + timeoutMs;
|
|
2299
|
+
while (true) {
|
|
2300
|
+
try {
|
|
2301
|
+
database.exec(sql);
|
|
2302
|
+
return;
|
|
2303
|
+
} catch (error) {
|
|
2304
|
+
if (!isSqliteBusy(error) || Date.now() >= deadline)
|
|
2305
|
+
throw error;
|
|
2306
|
+
Atomics.wait(SQLITE_INIT_SLEEP, 0, 0, Math.min(SQLITE_INIT_RETRY_MS, deadline - Date.now()));
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
function initializeDatabase(database) {
|
|
2311
|
+
database.exec("PRAGMA busy_timeout = 5000");
|
|
2312
|
+
execWithBusyRetry(database, "PRAGMA journal_mode = WAL");
|
|
2313
|
+
database.exec("PRAGMA foreign_keys = ON");
|
|
2314
|
+
database.exec("PRAGMA wal_autocheckpoint = 1000");
|
|
2315
|
+
try {
|
|
2316
|
+
database.exec("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
2317
|
+
} catch {}
|
|
2318
|
+
}
|
|
2319
|
+
function defaultDatabase() {
|
|
2320
|
+
const path = defaultSessionsDatabasePath();
|
|
2321
|
+
const state = storageState();
|
|
2322
|
+
if (state.fallbackDatabase && state.fallbackDatabasePath === path)
|
|
2323
|
+
return state.fallbackDatabase;
|
|
2324
|
+
if (state.fallbackDatabase)
|
|
2325
|
+
state.fallbackDatabase.close();
|
|
2326
|
+
mkdirSync6(dirname5(path), { recursive: true });
|
|
2327
|
+
state.fallbackDatabase = new Database(path, { create: true });
|
|
2328
|
+
state.fallbackDatabasePath = path;
|
|
2329
|
+
initializeDatabase(state.fallbackDatabase);
|
|
2330
|
+
return state.fallbackDatabase;
|
|
2331
|
+
}
|
|
2332
|
+
function resolveStorageDatabase() {
|
|
2333
|
+
return storageState().configuredHost.database ?? defaultDatabase();
|
|
2334
|
+
}
|
|
2335
|
+
function resolveStorageDataDir() {
|
|
2336
|
+
return storageState().configuredHost.dataDir ?? defaultDataDir();
|
|
2337
|
+
}
|
|
2338
|
+
function resolveStorageLogDir() {
|
|
2339
|
+
return storageState().configuredHost.logDir ?? defaultLogDir();
|
|
2340
|
+
}
|
|
2341
|
+
function resolveStorageSessionAsksDir() {
|
|
2342
|
+
return storageState().configuredHost.sessionAsksDir ?? defaultSessionAsksDir();
|
|
2343
|
+
}
|
|
2344
|
+
function resolveStorageWorkspaceDir() {
|
|
2345
|
+
return storageState().configuredHost.workspaceDir ?? defaultWorkspaceDir();
|
|
2346
|
+
}
|
|
2347
|
+
function resolveStorageSharedWikiDir() {
|
|
2348
|
+
return storageState().configuredHost.sharedWikiDir ?? join6(resolveStorageWorkspaceDir(), "wiki");
|
|
2349
|
+
}
|
|
2350
|
+
function registerStorageSchemaInitializer(initialize, priority = 100) {
|
|
2351
|
+
const initializers = storageState().schemaInitializers;
|
|
2352
|
+
initializers.push({ initialize, priority });
|
|
2353
|
+
initializers.sort((a, b) => a.priority - b.priority);
|
|
2354
|
+
}
|
|
2355
|
+
function ensureStorageSchemas(database = resolveStorageDatabase()) {
|
|
2356
|
+
const state = storageState();
|
|
2357
|
+
if (state.initializingDatabases.has(database))
|
|
2358
|
+
return;
|
|
2359
|
+
let initialized = state.initializedSchemas.get(database);
|
|
2360
|
+
if (!initialized) {
|
|
2361
|
+
initialized = new Set;
|
|
2362
|
+
state.initializedSchemas.set(database, initialized);
|
|
2363
|
+
}
|
|
2364
|
+
state.initializingDatabases.add(database);
|
|
2365
|
+
try {
|
|
2366
|
+
for (const entry of state.schemaInitializers) {
|
|
2367
|
+
if (initialized.has(entry.initialize))
|
|
2368
|
+
continue;
|
|
2369
|
+
initialized.add(entry.initialize);
|
|
2370
|
+
try {
|
|
2371
|
+
entry.initialize(database);
|
|
2372
|
+
} catch (error) {
|
|
2373
|
+
initialized.delete(entry.initialize);
|
|
2374
|
+
throw error;
|
|
2238
2375
|
}
|
|
2239
2376
|
}
|
|
2240
|
-
|
|
2377
|
+
} finally {
|
|
2378
|
+
state.initializingDatabases.delete(database);
|
|
2241
2379
|
}
|
|
2380
|
+
}
|
|
2381
|
+
var STORAGE_HOST_STATE, SQLITE_INIT_RETRY_MS = 25, SQLITE_INIT_TIMEOUT_MS = 5000, SQLITE_INIT_SLEEP, internalStorageDatabase;
|
|
2382
|
+
var init_storage_host = __esm(async () => {
|
|
2383
|
+
await init_sqlite();
|
|
2384
|
+
STORAGE_HOST_STATE = Symbol.for("negotium.storage-host.state.v1");
|
|
2385
|
+
SQLITE_INIT_SLEEP = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
|
2386
|
+
internalStorageDatabase = new Proxy({}, {
|
|
2387
|
+
get(_target, property) {
|
|
2388
|
+
const database = resolveStorageDatabase();
|
|
2389
|
+
ensureStorageSchemas(database);
|
|
2390
|
+
const value2 = Reflect.get(database, property, database);
|
|
2391
|
+
return typeof value2 === "function" ? value2.bind(database) : value2;
|
|
2392
|
+
},
|
|
2393
|
+
set(_target, property, value2) {
|
|
2394
|
+
const database = resolveStorageDatabase();
|
|
2395
|
+
ensureStorageSchemas(database);
|
|
2396
|
+
return Reflect.set(database, property, value2, database);
|
|
2397
|
+
}
|
|
2398
|
+
});
|
|
2242
2399
|
});
|
|
2243
2400
|
|
|
2244
2401
|
// ../../packages/core/src/storage/vault-crypto-core.ts
|
|
@@ -2297,8 +2454,8 @@ var init_vault_crypto = __esm(() => {
|
|
|
2297
2454
|
});
|
|
2298
2455
|
|
|
2299
2456
|
// ../../packages/core/src/storage/vault.ts
|
|
2300
|
-
import { chmodSync as
|
|
2301
|
-
import { join as
|
|
2457
|
+
import { chmodSync as chmodSync4, mkdirSync as mkdirSync7 } from "fs";
|
|
2458
|
+
import { join as join7 } from "path";
|
|
2302
2459
|
function initializeVaultDatabase(database) {
|
|
2303
2460
|
database.exec("PRAGMA journal_mode = WAL");
|
|
2304
2461
|
database.exec("PRAGMA busy_timeout = 5000");
|
|
@@ -2333,17 +2490,18 @@ function initializeVaultDatabase(database) {
|
|
|
2333
2490
|
}
|
|
2334
2491
|
}
|
|
2335
2492
|
function openVaultDatabase(dataDir) {
|
|
2336
|
-
const vaultDir =
|
|
2337
|
-
const path =
|
|
2338
|
-
|
|
2493
|
+
const vaultDir = join7(dataDir, "vault");
|
|
2494
|
+
const path = join7(vaultDir, "vault.db");
|
|
2495
|
+
mkdirSync7(vaultDir, { recursive: true, mode: 448 });
|
|
2339
2496
|
const database = new Database(path, { create: true });
|
|
2340
|
-
|
|
2497
|
+
chmodSync4(path, 384);
|
|
2341
2498
|
initializeVaultDatabase(database);
|
|
2342
2499
|
return database;
|
|
2343
2500
|
}
|
|
2344
2501
|
function activeVaultDatabase() {
|
|
2345
|
-
if (!vaultDb)
|
|
2346
|
-
vaultDb = openVaultDatabase(
|
|
2502
|
+
if (!vaultDb) {
|
|
2503
|
+
vaultDb = openVaultDatabase(resolveStorageDataDir());
|
|
2504
|
+
}
|
|
2347
2505
|
return vaultDb;
|
|
2348
2506
|
}
|
|
2349
2507
|
function normalizeVaultKey(key) {
|
|
@@ -2433,14 +2591,17 @@ var vaultDb, vaultMasterKey, VAULT_VALUE_MAX_BYTES;
|
|
|
2433
2591
|
var init_vault = __esm(async () => {
|
|
2434
2592
|
init_config();
|
|
2435
2593
|
init_vault_crypto();
|
|
2436
|
-
await
|
|
2594
|
+
await __promiseAll([
|
|
2595
|
+
init_sqlite(),
|
|
2596
|
+
init_storage_host()
|
|
2597
|
+
]);
|
|
2437
2598
|
vaultMasterKey = VAULT_MASTER_KEY;
|
|
2438
2599
|
VAULT_VALUE_MAX_BYTES = 64 * 1024;
|
|
2439
2600
|
});
|
|
2440
2601
|
|
|
2441
2602
|
// ../../packages/core/src/agents/execution-host.ts
|
|
2442
2603
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
2443
|
-
import { dirname as
|
|
2604
|
+
import { dirname as dirname6 } from "path";
|
|
2444
2605
|
function activeHost() {
|
|
2445
2606
|
const scoped = scopedHost.getStore();
|
|
2446
2607
|
if (scoped)
|
|
@@ -2475,7 +2636,7 @@ function hostedCodexAuthFilePath() {
|
|
|
2475
2636
|
return activeHost().codexAuthFilePath();
|
|
2476
2637
|
}
|
|
2477
2638
|
function hostedCodexHomePath() {
|
|
2478
|
-
return
|
|
2639
|
+
return dirname6(hostedCodexAuthFilePath());
|
|
2479
2640
|
}
|
|
2480
2641
|
var defaultHost, hostRegistrations, scopedHost;
|
|
2481
2642
|
var init_execution_host = __esm(async () => {
|
|
@@ -2498,15 +2659,15 @@ var init_execution_host = __esm(async () => {
|
|
|
2498
2659
|
|
|
2499
2660
|
// ../../packages/core/src/agents/rollout/codex.ts
|
|
2500
2661
|
import { randomBytes as randomBytes4 } from "crypto";
|
|
2501
|
-
import { existsSync as
|
|
2502
|
-
import { basename as basename2, dirname as
|
|
2662
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7, realpathSync as realpathSync2, statSync as statSync3, unlinkSync as unlinkSync7 } from "fs";
|
|
2663
|
+
import { basename as basename2, dirname as dirname7, join as join8, resolve as resolve6 } from "path";
|
|
2503
2664
|
function codexSessionsDir() {
|
|
2504
|
-
return
|
|
2665
|
+
return join8(hostedCodexHomePath(), "sessions");
|
|
2505
2666
|
}
|
|
2506
2667
|
function loadCodexShell() {
|
|
2507
2668
|
if (_shellCache)
|
|
2508
2669
|
return _shellCache;
|
|
2509
|
-
const raw =
|
|
2670
|
+
const raw = readFileSync7(join8(FIXTURES_DIR, "codex-shell.jsonl"), "utf8");
|
|
2510
2671
|
const lines = parseJsonlText(raw);
|
|
2511
2672
|
if (lines.length < 5) {
|
|
2512
2673
|
throw new Error(`loadCodexShell: expected >=5 entries in codex-shell.jsonl, got ${lines.length}`);
|
|
@@ -2573,16 +2734,16 @@ function codexRolloutPath(threadId, fallback) {
|
|
|
2573
2734
|
const hh = String(createdAt.getHours()).padStart(2, "0");
|
|
2574
2735
|
const min = String(createdAt.getMinutes()).padStart(2, "0");
|
|
2575
2736
|
const ss = String(createdAt.getSeconds()).padStart(2, "0");
|
|
2576
|
-
const dir =
|
|
2577
|
-
return
|
|
2737
|
+
const dir = join8(codexSessionsDir(), yyyy, mm, dd);
|
|
2738
|
+
return join8(dir, `rollout-${yyyy}-${mm}-${dd}T${hh}-${min}-${ss}-${threadId}.jsonl`);
|
|
2578
2739
|
}
|
|
2579
2740
|
function canonicalFilePath(path) {
|
|
2580
|
-
const absolute =
|
|
2741
|
+
const absolute = resolve6(path);
|
|
2581
2742
|
try {
|
|
2582
2743
|
return realpathSync2(absolute);
|
|
2583
2744
|
} catch {
|
|
2584
2745
|
try {
|
|
2585
|
-
return
|
|
2746
|
+
return join8(realpathSync2(dirname7(absolute)), basename2(absolute));
|
|
2586
2747
|
} catch {
|
|
2587
2748
|
return absolute;
|
|
2588
2749
|
}
|
|
@@ -2692,7 +2853,7 @@ function readCodexPatchCallIds(threadId) {
|
|
|
2692
2853
|
if (!path)
|
|
2693
2854
|
return [];
|
|
2694
2855
|
try {
|
|
2695
|
-
return extractCodexPatchCallIds(
|
|
2856
|
+
return extractCodexPatchCallIds(readFileSync7(path, "utf8"));
|
|
2696
2857
|
} catch (error) {
|
|
2697
2858
|
logger.debug({ error, threadId }, "codex patch ids: rollout read failed");
|
|
2698
2859
|
return [];
|
|
@@ -2703,7 +2864,7 @@ function readLatestCodexPatchPreview(threadId, expectedPaths, consumedCallIds =
|
|
|
2703
2864
|
if (!path)
|
|
2704
2865
|
return;
|
|
2705
2866
|
try {
|
|
2706
|
-
return extractLatestCodexPatchPreview(
|
|
2867
|
+
return extractLatestCodexPatchPreview(readFileSync7(path, "utf8"), expectedPaths, consumedCallIds, expectedCallId);
|
|
2707
2868
|
} catch (error) {
|
|
2708
2869
|
logger.debug({ error, threadId }, "codex patch preview: rollout read failed");
|
|
2709
2870
|
return;
|
|
@@ -2761,7 +2922,7 @@ function readLatestCodexContextUsage(threadId) {
|
|
|
2761
2922
|
if (!path)
|
|
2762
2923
|
return;
|
|
2763
2924
|
try {
|
|
2764
|
-
return extractLatestCodexContextUsage(
|
|
2925
|
+
return extractLatestCodexContextUsage(readFileSync7(path, "utf8"));
|
|
2765
2926
|
} catch (error) {
|
|
2766
2927
|
logger.debug({ error, threadId }, "codex context usage: rollout read failed");
|
|
2767
2928
|
return;
|
|
@@ -2772,7 +2933,7 @@ function readLatestCodexTokenTotals(threadId) {
|
|
|
2772
2933
|
if (!path)
|
|
2773
2934
|
return;
|
|
2774
2935
|
try {
|
|
2775
|
-
return extractLatestCodexTokenTotals(
|
|
2936
|
+
return extractLatestCodexTokenTotals(readFileSync7(path, "utf8"));
|
|
2776
2937
|
} catch (error) {
|
|
2777
2938
|
logger.debug({ error, threadId }, "codex token totals: rollout read failed");
|
|
2778
2939
|
return;
|
|
@@ -2783,7 +2944,7 @@ function migrateCodexRolloutNativeMultiAgentMetadata(threadId) {
|
|
|
2783
2944
|
if (!path)
|
|
2784
2945
|
return false;
|
|
2785
2946
|
try {
|
|
2786
|
-
const entries = parseJsonlText(
|
|
2947
|
+
const entries = parseJsonlText(readFileSync7(path, "utf8"));
|
|
2787
2948
|
let changed = false;
|
|
2788
2949
|
for (const entry of entries) {
|
|
2789
2950
|
if (entry.type !== "session_meta" && entry.type !== "turn_context")
|
|
@@ -2812,19 +2973,19 @@ function latestCodexRolloutPath(threadId) {
|
|
|
2812
2973
|
try {
|
|
2813
2974
|
if (buckets) {
|
|
2814
2975
|
for (const bucket of buckets) {
|
|
2815
|
-
const dir =
|
|
2816
|
-
if (!
|
|
2976
|
+
const dir = join8(sessionsDir, bucket);
|
|
2977
|
+
if (!existsSync7(dir))
|
|
2817
2978
|
continue;
|
|
2818
2979
|
const glob = new Bun.Glob(`rollout-*-${threadId}.jsonl`);
|
|
2819
2980
|
for (const rel of glob.scanSync({ cwd: dir, onlyFiles: true })) {
|
|
2820
|
-
candidates.push(
|
|
2981
|
+
candidates.push(join8(dir, rel));
|
|
2821
2982
|
}
|
|
2822
2983
|
}
|
|
2823
2984
|
}
|
|
2824
2985
|
if (candidates.length === 0) {
|
|
2825
2986
|
const glob = new Bun.Glob(`**/rollout-*-${threadId}.jsonl`);
|
|
2826
2987
|
for (const rel of glob.scanSync({ cwd: sessionsDir, onlyFiles: true })) {
|
|
2827
|
-
candidates.push(
|
|
2988
|
+
candidates.push(join8(sessionsDir, rel));
|
|
2828
2989
|
}
|
|
2829
2990
|
}
|
|
2830
2991
|
return candidates.sort((a, b) => statSync3(b).mtimeMs - statSync3(a).mtimeMs)[0];
|
|
@@ -2945,15 +3106,15 @@ function sweepPriorRolloutsForThread(threadId) {
|
|
|
2945
3106
|
return;
|
|
2946
3107
|
}
|
|
2947
3108
|
for (const bucket of buckets) {
|
|
2948
|
-
const dir =
|
|
2949
|
-
if (!
|
|
3109
|
+
const dir = join8(sessionsDir, bucket);
|
|
3110
|
+
if (!existsSync7(dir))
|
|
2950
3111
|
continue;
|
|
2951
3112
|
try {
|
|
2952
3113
|
const glob = new Bun.Glob(`rollout-*-${threadId}.jsonl`);
|
|
2953
3114
|
for (const rel of glob.scanSync({ cwd: dir, onlyFiles: true })) {
|
|
2954
|
-
const fullPath =
|
|
3115
|
+
const fullPath = join8(dir, rel);
|
|
2955
3116
|
try {
|
|
2956
|
-
|
|
3117
|
+
unlinkSync7(fullPath);
|
|
2957
3118
|
} catch (e) {
|
|
2958
3119
|
if (e?.code !== "ENOENT") {
|
|
2959
3120
|
logger.warn({ err: e, path: fullPath }, "writeCodexRollout: prior-rollout unlink failed (continuing)");
|
|
@@ -2969,9 +3130,9 @@ function sweepPriorRolloutsFullTree(threadId, sessionsDir) {
|
|
|
2969
3130
|
try {
|
|
2970
3131
|
const glob = new Bun.Glob(`**/rollout-*-${threadId}.jsonl`);
|
|
2971
3132
|
for (const rel of glob.scanSync({ cwd: sessionsDir, onlyFiles: true })) {
|
|
2972
|
-
const fullPath =
|
|
3133
|
+
const fullPath = join8(sessionsDir, rel);
|
|
2973
3134
|
try {
|
|
2974
|
-
|
|
3135
|
+
unlinkSync7(fullPath);
|
|
2975
3136
|
} catch (e) {
|
|
2976
3137
|
if (e?.code !== "ENOENT") {
|
|
2977
3138
|
logger.warn({ err: e, path: fullPath }, "writeCodexRollout: prior-rollout unlink failed (continuing)");
|
|
@@ -3035,7 +3196,7 @@ import { spawn as spawn4 } from "child_process";
|
|
|
3035
3196
|
function createCodexAppServerForker(host) {
|
|
3036
3197
|
return async (parentThreadId) => {
|
|
3037
3198
|
const child = host.spawnServer();
|
|
3038
|
-
return await new Promise((
|
|
3199
|
+
return await new Promise((resolve7, reject) => {
|
|
3039
3200
|
let settled = false;
|
|
3040
3201
|
let stdoutBuffer = "";
|
|
3041
3202
|
let stderr = "";
|
|
@@ -3052,7 +3213,7 @@ function createCodexAppServerForker(host) {
|
|
|
3052
3213
|
if (error)
|
|
3053
3214
|
reject(error);
|
|
3054
3215
|
else if (result)
|
|
3055
|
-
|
|
3216
|
+
resolve7(result);
|
|
3056
3217
|
else
|
|
3057
3218
|
reject(new Error("Codex thread fork returned no result"));
|
|
3058
3219
|
};
|
|
@@ -3148,8 +3309,8 @@ var init_codex_app_server = __esm(async () => {
|
|
|
3148
3309
|
});
|
|
3149
3310
|
|
|
3150
3311
|
// ../../packages/core/src/agents/codex-registry.ts
|
|
3151
|
-
import { existsSync as
|
|
3152
|
-
import { join as
|
|
3312
|
+
import { existsSync as existsSync8, unlinkSync as unlinkSync8 } from "fs";
|
|
3313
|
+
import { join as join9 } from "path";
|
|
3153
3314
|
var VALID_EFFORTS2, codexRegistry, codexRegistryOperations;
|
|
3154
3315
|
var init_codex_registry = __esm(async () => {
|
|
3155
3316
|
init_logger();
|
|
@@ -3194,17 +3355,17 @@ var init_codex_registry = __esm(async () => {
|
|
|
3194
3355
|
async cleanupRollouts({ sessionIds }) {
|
|
3195
3356
|
if (sessionIds.length === 0)
|
|
3196
3357
|
return;
|
|
3197
|
-
const sessionsDir =
|
|
3198
|
-
if (!
|
|
3358
|
+
const sessionsDir = join9(hostedCodexHomePath(), "sessions");
|
|
3359
|
+
if (!existsSync8(sessionsDir))
|
|
3199
3360
|
return;
|
|
3200
3361
|
const failures = [];
|
|
3201
3362
|
for (const tid of sessionIds) {
|
|
3202
3363
|
try {
|
|
3203
3364
|
const glob = new Bun.Glob(`**/rollout-*-${tid}.jsonl`);
|
|
3204
3365
|
for await (const rel of glob.scan({ cwd: sessionsDir, onlyFiles: true })) {
|
|
3205
|
-
const path =
|
|
3366
|
+
const path = join9(sessionsDir, rel);
|
|
3206
3367
|
try {
|
|
3207
|
-
|
|
3368
|
+
unlinkSync8(path);
|
|
3208
3369
|
} catch (e) {
|
|
3209
3370
|
if (e?.code !== "ENOENT") {
|
|
3210
3371
|
logger.warn({ err: e, path }, "codex cleanupRollouts: unlink failed");
|
|
@@ -3226,23 +3387,23 @@ var init_codex_registry = __esm(async () => {
|
|
|
3226
3387
|
|
|
3227
3388
|
// ../../packages/core/src/agents/maestro-registry.ts
|
|
3228
3389
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
3229
|
-
import { existsSync as
|
|
3230
|
-
import { homedir as
|
|
3231
|
-
import { join as
|
|
3390
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync8, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
|
|
3391
|
+
import { homedir as homedir5 } from "os";
|
|
3392
|
+
import { join as join10, resolve as resolve7 } from "path";
|
|
3232
3393
|
function maestroSessionsDir() {
|
|
3233
|
-
return
|
|
3394
|
+
return join10(process.env.MAESTRO_DATA_DIR ? resolve7(process.env.MAESTRO_DATA_DIR) : join10(homedir5(), ".maestro"), "sessions");
|
|
3234
3395
|
}
|
|
3235
3396
|
function maestroSessionPath(sessionId) {
|
|
3236
|
-
return
|
|
3397
|
+
return join10(maestroSessionsDir(), `${sessionId}.jsonl`);
|
|
3237
3398
|
}
|
|
3238
3399
|
function maestroActiveSessionPath(sessionId) {
|
|
3239
|
-
return
|
|
3400
|
+
return join10(maestroSessionsDir(), `${sessionId}.active.jsonl`);
|
|
3240
3401
|
}
|
|
3241
3402
|
function existingCreatedAt(path) {
|
|
3242
|
-
if (!
|
|
3403
|
+
if (!existsSync9(path))
|
|
3243
3404
|
return;
|
|
3244
3405
|
try {
|
|
3245
|
-
const firstLine =
|
|
3406
|
+
const firstLine = readFileSync8(path, "utf8").split(`
|
|
3246
3407
|
`, 1)[0];
|
|
3247
3408
|
const parsed = JSON.parse(firstLine);
|
|
3248
3409
|
return typeof parsed._meta?.createdAt === "string" ? parsed._meta.createdAt : undefined;
|
|
@@ -3258,7 +3419,7 @@ function writeRollout(options) {
|
|
|
3258
3419
|
assertUuidLike("sessionId", sessionId);
|
|
3259
3420
|
ensureCwdExists(options.cwd);
|
|
3260
3421
|
const path = maestroSessionPath(sessionId);
|
|
3261
|
-
|
|
3422
|
+
mkdirSync8(maestroSessionsDir(), { recursive: true });
|
|
3262
3423
|
const messages = extractChatPairs(options.entries).flatMap((pair) => [
|
|
3263
3424
|
{ role: "user", content: nonEmptyTurnText(pair.userText) },
|
|
3264
3425
|
{ role: "assistant", content: nonEmptyTurnText(pair.assistantText) }
|
|
@@ -3323,7 +3484,7 @@ var init_maestro_registry = __esm(() => {
|
|
|
3323
3484
|
if (!parentMessages) {
|
|
3324
3485
|
throw new Error(`Maestro parent session not found: ${options.parentSessionId}`);
|
|
3325
3486
|
}
|
|
3326
|
-
const parentHasActiveProjection =
|
|
3487
|
+
const parentHasActiveProjection = existsSync9(maestroActiveSessionPath(options.parentSessionId));
|
|
3327
3488
|
const fork = forkSessionAt({
|
|
3328
3489
|
parentSessionId: options.parentSessionId,
|
|
3329
3490
|
messageIndex: parentMessages.length,
|
|
@@ -3338,7 +3499,7 @@ var init_maestro_registry = __esm(() => {
|
|
|
3338
3499
|
return {
|
|
3339
3500
|
forkId: fork.sessionId,
|
|
3340
3501
|
rolloutPath: fork.rolloutPath,
|
|
3341
|
-
...
|
|
3502
|
+
...existsSync9(activePath) ? { cleanupPaths: [activePath] } : {}
|
|
3342
3503
|
};
|
|
3343
3504
|
},
|
|
3344
3505
|
async cleanupRollouts(options) {
|
|
@@ -3350,7 +3511,7 @@ var init_maestro_registry = __esm(() => {
|
|
|
3350
3511
|
const remaining = [
|
|
3351
3512
|
maestroSessionPath(sessionId),
|
|
3352
3513
|
maestroActiveSessionPath(sessionId)
|
|
3353
|
-
].filter(
|
|
3514
|
+
].filter(existsSync9);
|
|
3354
3515
|
if (remaining.length > 0) {
|
|
3355
3516
|
throw new Error(`Maestro session files remain after cleanup: ${remaining.join(", ")}`);
|
|
3356
3517
|
}
|
|
@@ -3394,176 +3555,41 @@ var init_common = __esm(() => {
|
|
|
3394
3555
|
init_mcp_helpers();
|
|
3395
3556
|
});
|
|
3396
3557
|
|
|
3397
|
-
// ../../packages/core/src/storage/
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
function
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3558
|
+
// ../../packages/core/src/storage/forum-db.ts
|
|
3559
|
+
var db;
|
|
3560
|
+
var init_forum_db = __esm(async () => {
|
|
3561
|
+
await init_storage_host();
|
|
3562
|
+
db = internalStorageDatabase;
|
|
3563
|
+
});
|
|
3564
|
+
|
|
3565
|
+
// ../../packages/core/src/storage/runtime-events.ts
|
|
3566
|
+
function rowToEvent(row) {
|
|
3567
|
+
if (!types.has(row.event_type))
|
|
3568
|
+
return null;
|
|
3569
|
+
try {
|
|
3570
|
+
return {
|
|
3571
|
+
seq: Number(row.seq),
|
|
3572
|
+
sourceId: row.source_id,
|
|
3573
|
+
type: row.event_type,
|
|
3574
|
+
topicId: row.topic_id,
|
|
3575
|
+
payload: JSON.parse(row.payload_json),
|
|
3576
|
+
createdAt: row.created_at
|
|
3577
|
+
};
|
|
3578
|
+
} catch {
|
|
3579
|
+
return null;
|
|
3580
|
+
}
|
|
3413
3581
|
}
|
|
3414
|
-
function
|
|
3415
|
-
|
|
3582
|
+
function latestRuntimeEventSeq() {
|
|
3583
|
+
const row = db.query("SELECT MAX(seq) AS seq FROM runtime_events").get();
|
|
3584
|
+
return Number(row?.seq ?? 0);
|
|
3416
3585
|
}
|
|
3417
|
-
function
|
|
3418
|
-
const
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
}
|
|
3424
|
-
function isSqliteBusy(error) {
|
|
3425
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
3426
|
-
return /database is (?:locked|busy)|SQLITE_(?:BUSY|LOCKED)/i.test(message);
|
|
3427
|
-
}
|
|
3428
|
-
function execWithBusyRetry(database, sql, timeoutMs = SQLITE_INIT_TIMEOUT_MS) {
|
|
3429
|
-
const deadline = Date.now() + timeoutMs;
|
|
3430
|
-
while (true) {
|
|
3431
|
-
try {
|
|
3432
|
-
database.exec(sql);
|
|
3433
|
-
return;
|
|
3434
|
-
} catch (error) {
|
|
3435
|
-
if (!isSqliteBusy(error) || Date.now() >= deadline)
|
|
3436
|
-
throw error;
|
|
3437
|
-
Atomics.wait(SQLITE_INIT_SLEEP, 0, 0, Math.min(SQLITE_INIT_RETRY_MS, deadline - Date.now()));
|
|
3438
|
-
}
|
|
3439
|
-
}
|
|
3440
|
-
}
|
|
3441
|
-
function initializeDatabase(database) {
|
|
3442
|
-
database.exec("PRAGMA busy_timeout = 5000");
|
|
3443
|
-
execWithBusyRetry(database, "PRAGMA journal_mode = WAL");
|
|
3444
|
-
database.exec("PRAGMA foreign_keys = ON");
|
|
3445
|
-
database.exec("PRAGMA wal_autocheckpoint = 1000");
|
|
3446
|
-
try {
|
|
3447
|
-
database.exec("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
3448
|
-
} catch {}
|
|
3449
|
-
}
|
|
3450
|
-
function defaultDatabase() {
|
|
3451
|
-
const path = defaultSessionsDatabasePath();
|
|
3452
|
-
if (fallbackDatabase && fallbackDatabasePath === path)
|
|
3453
|
-
return fallbackDatabase;
|
|
3454
|
-
if (fallbackDatabase)
|
|
3455
|
-
fallbackDatabase.close();
|
|
3456
|
-
mkdirSync8(dirname7(path), { recursive: true });
|
|
3457
|
-
fallbackDatabase = new Database(path, { create: true });
|
|
3458
|
-
fallbackDatabasePath = path;
|
|
3459
|
-
initializeDatabase(fallbackDatabase);
|
|
3460
|
-
return fallbackDatabase;
|
|
3461
|
-
}
|
|
3462
|
-
function resolveStorageDatabase() {
|
|
3463
|
-
return configuredHost.database ?? defaultDatabase();
|
|
3464
|
-
}
|
|
3465
|
-
function resolveStorageDataDir() {
|
|
3466
|
-
return configuredHost.dataDir ?? defaultDataDir();
|
|
3467
|
-
}
|
|
3468
|
-
function resolveStorageLogDir() {
|
|
3469
|
-
return configuredHost.logDir ?? defaultLogDir();
|
|
3470
|
-
}
|
|
3471
|
-
function resolveStorageSessionAsksDir() {
|
|
3472
|
-
return configuredHost.sessionAsksDir ?? defaultSessionAsksDir();
|
|
3473
|
-
}
|
|
3474
|
-
function resolveStorageWorkspaceDir() {
|
|
3475
|
-
return configuredHost.workspaceDir ?? defaultWorkspaceDir();
|
|
3476
|
-
}
|
|
3477
|
-
function resolveStorageSharedWikiDir() {
|
|
3478
|
-
return configuredHost.sharedWikiDir ?? join11(resolveStorageWorkspaceDir(), "wiki");
|
|
3479
|
-
}
|
|
3480
|
-
function registerStorageSchemaInitializer(initialize, priority = 100) {
|
|
3481
|
-
schemaInitializers.push({ initialize, priority });
|
|
3482
|
-
schemaInitializers.sort((a, b) => a.priority - b.priority);
|
|
3483
|
-
}
|
|
3484
|
-
function ensureStorageSchemas(database = resolveStorageDatabase()) {
|
|
3485
|
-
if (initializingDatabases.has(database))
|
|
3486
|
-
return;
|
|
3487
|
-
let initialized = initializedSchemas.get(database);
|
|
3488
|
-
if (!initialized) {
|
|
3489
|
-
initialized = new Set;
|
|
3490
|
-
initializedSchemas.set(database, initialized);
|
|
3491
|
-
}
|
|
3492
|
-
initializingDatabases.add(database);
|
|
3493
|
-
try {
|
|
3494
|
-
for (const entry of schemaInitializers) {
|
|
3495
|
-
if (initialized.has(entry.initialize))
|
|
3496
|
-
continue;
|
|
3497
|
-
initialized.add(entry.initialize);
|
|
3498
|
-
try {
|
|
3499
|
-
entry.initialize(database);
|
|
3500
|
-
} catch (error) {
|
|
3501
|
-
initialized.delete(entry.initialize);
|
|
3502
|
-
throw error;
|
|
3503
|
-
}
|
|
3504
|
-
}
|
|
3505
|
-
} finally {
|
|
3506
|
-
initializingDatabases.delete(database);
|
|
3507
|
-
}
|
|
3508
|
-
}
|
|
3509
|
-
var configuredHost, fallbackDatabase = null, fallbackDatabasePath = null, schemaInitializers, initializedSchemas, initializingDatabases, SQLITE_INIT_RETRY_MS = 25, SQLITE_INIT_TIMEOUT_MS = 5000, SQLITE_INIT_SLEEP, internalStorageDatabase;
|
|
3510
|
-
var init_storage_host = __esm(async () => {
|
|
3511
|
-
await init_sqlite();
|
|
3512
|
-
configuredHost = {};
|
|
3513
|
-
schemaInitializers = [];
|
|
3514
|
-
initializedSchemas = new WeakMap;
|
|
3515
|
-
initializingDatabases = new WeakSet;
|
|
3516
|
-
SQLITE_INIT_SLEEP = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
|
3517
|
-
internalStorageDatabase = new Proxy({}, {
|
|
3518
|
-
get(_target, property) {
|
|
3519
|
-
const database = resolveStorageDatabase();
|
|
3520
|
-
ensureStorageSchemas(database);
|
|
3521
|
-
const value2 = Reflect.get(database, property, database);
|
|
3522
|
-
return typeof value2 === "function" ? value2.bind(database) : value2;
|
|
3523
|
-
},
|
|
3524
|
-
set(_target, property, value2) {
|
|
3525
|
-
const database = resolveStorageDatabase();
|
|
3526
|
-
ensureStorageSchemas(database);
|
|
3527
|
-
return Reflect.set(database, property, value2, database);
|
|
3528
|
-
}
|
|
3529
|
-
});
|
|
3530
|
-
});
|
|
3531
|
-
|
|
3532
|
-
// ../../packages/core/src/storage/forum-db.ts
|
|
3533
|
-
var db;
|
|
3534
|
-
var init_forum_db = __esm(async () => {
|
|
3535
|
-
await init_storage_host();
|
|
3536
|
-
db = internalStorageDatabase;
|
|
3537
|
-
});
|
|
3538
|
-
|
|
3539
|
-
// ../../packages/core/src/storage/runtime-events.ts
|
|
3540
|
-
function rowToEvent(row) {
|
|
3541
|
-
if (!types.has(row.event_type))
|
|
3542
|
-
return null;
|
|
3543
|
-
try {
|
|
3544
|
-
return {
|
|
3545
|
-
seq: Number(row.seq),
|
|
3546
|
-
sourceId: row.source_id,
|
|
3547
|
-
type: row.event_type,
|
|
3548
|
-
topicId: row.topic_id,
|
|
3549
|
-
payload: JSON.parse(row.payload_json),
|
|
3550
|
-
createdAt: row.created_at
|
|
3551
|
-
};
|
|
3552
|
-
} catch {
|
|
3553
|
-
return null;
|
|
3554
|
-
}
|
|
3555
|
-
}
|
|
3556
|
-
function latestRuntimeEventSeq() {
|
|
3557
|
-
const row = db.query("SELECT MAX(seq) AS seq FROM runtime_events").get();
|
|
3558
|
-
return Number(row?.seq ?? 0);
|
|
3559
|
-
}
|
|
3560
|
-
function appendRuntimeEvent(sourceId, event) {
|
|
3561
|
-
const createdAt = new Date().toISOString();
|
|
3562
|
-
const result = db.query(`INSERT INTO runtime_events
|
|
3563
|
-
(source_id, event_type, topic_id, payload_json, created_at)
|
|
3564
|
-
VALUES (?, ?, ?, ?, ?)`).run(sourceId, event.type, event.topicId, JSON.stringify(event.payload ?? null), createdAt);
|
|
3565
|
-
const seq = Number(result.lastInsertRowid);
|
|
3566
|
-
return { seq, sourceId, ...event, createdAt };
|
|
3586
|
+
function appendRuntimeEvent(sourceId, event) {
|
|
3587
|
+
const createdAt = new Date().toISOString();
|
|
3588
|
+
const result = db.query(`INSERT INTO runtime_events
|
|
3589
|
+
(source_id, event_type, topic_id, payload_json, created_at)
|
|
3590
|
+
VALUES (?, ?, ?, ?, ?)`).run(sourceId, event.type, event.topicId, JSON.stringify(event.payload ?? null), createdAt);
|
|
3591
|
+
const seq = Number(result.lastInsertRowid);
|
|
3592
|
+
return { seq, sourceId, ...event, createdAt };
|
|
3567
3593
|
}
|
|
3568
3594
|
function listRuntimeEventsAfter(seq, limit = 500) {
|
|
3569
3595
|
const rows = db.query(`SELECT seq, source_id, event_type, topic_id, payload_json, created_at
|
|
@@ -3575,7 +3601,10 @@ function listRuntimeEventsAfter(seq, limit = 500) {
|
|
|
3575
3601
|
}
|
|
3576
3602
|
var RUNTIME_EVENT_TYPES, types;
|
|
3577
3603
|
var init_runtime_events = __esm(async () => {
|
|
3578
|
-
await
|
|
3604
|
+
await __promiseAll([
|
|
3605
|
+
init_forum_db(),
|
|
3606
|
+
init_storage_host()
|
|
3607
|
+
]);
|
|
3579
3608
|
RUNTIME_EVENT_TYPES = [
|
|
3580
3609
|
"message",
|
|
3581
3610
|
"message-updated",
|
|
@@ -3584,26 +3613,28 @@ var init_runtime_events = __esm(async () => {
|
|
|
3584
3613
|
"topic-updated",
|
|
3585
3614
|
"topic-deleted"
|
|
3586
3615
|
];
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
event_type
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3616
|
+
registerStorageSchemaInitializer((database) => {
|
|
3617
|
+
database.exec(`
|
|
3618
|
+
CREATE TABLE IF NOT EXISTS runtime_events (
|
|
3619
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
3620
|
+
source_id TEXT NOT NULL,
|
|
3621
|
+
event_type TEXT NOT NULL CHECK (
|
|
3622
|
+
event_type IN (
|
|
3623
|
+
'message',
|
|
3624
|
+
'message-updated',
|
|
3625
|
+
'ai-status',
|
|
3626
|
+
'topic-created',
|
|
3627
|
+
'topic-updated',
|
|
3628
|
+
'topic-deleted'
|
|
3629
|
+
)
|
|
3630
|
+
),
|
|
3631
|
+
topic_id TEXT NOT NULL,
|
|
3632
|
+
payload_json TEXT NOT NULL,
|
|
3633
|
+
created_at TEXT NOT NULL
|
|
3634
|
+
)
|
|
3635
|
+
`);
|
|
3636
|
+
database.exec("CREATE INDEX IF NOT EXISTS idx_runtime_events_topic_seq ON runtime_events(topic_id, seq)");
|
|
3637
|
+
});
|
|
3607
3638
|
types = new Set(RUNTIME_EVENT_TYPES);
|
|
3608
3639
|
});
|
|
3609
3640
|
|
|
@@ -3763,13 +3794,17 @@ class SqliteRuntimeBus {
|
|
|
3763
3794
|
};
|
|
3764
3795
|
}
|
|
3765
3796
|
}
|
|
3766
|
-
|
|
3797
|
+
function runtimeBus() {
|
|
3798
|
+
if (!current)
|
|
3799
|
+
current = new SqliteRuntimeBus;
|
|
3800
|
+
return current;
|
|
3801
|
+
}
|
|
3802
|
+
var current = null, WsHub;
|
|
3767
3803
|
var init_bus = __esm(async () => {
|
|
3768
3804
|
await init_runtime_events();
|
|
3769
|
-
current = new SqliteRuntimeBus;
|
|
3770
3805
|
WsHub = {
|
|
3771
3806
|
get() {
|
|
3772
|
-
return
|
|
3807
|
+
return runtimeBus();
|
|
3773
3808
|
}
|
|
3774
3809
|
};
|
|
3775
3810
|
});
|
|
@@ -5068,10 +5103,11 @@ var init_runtime_turn_requests = __esm(async () => {
|
|
|
5068
5103
|
await __promiseAll([
|
|
5069
5104
|
init_forum_db(),
|
|
5070
5105
|
init_runtime_leases(),
|
|
5071
|
-
init_runtime_topic_state()
|
|
5106
|
+
init_runtime_topic_state(),
|
|
5107
|
+
init_storage_host()
|
|
5072
5108
|
]);
|
|
5073
5109
|
REQUEST_CLAIM_STALE_MS = TURN_LEASE_STALE_MS;
|
|
5074
|
-
ensureRuntimeUserTurnRequestsSchema(
|
|
5110
|
+
registerStorageSchemaInitializer((database) => ensureRuntimeUserTurnRequestsSchema(database));
|
|
5075
5111
|
});
|
|
5076
5112
|
|
|
5077
5113
|
// ../../packages/core/src/agents/registry.ts
|
|
@@ -5104,7 +5140,7 @@ var init_registry = __esm(async () => {
|
|
|
5104
5140
|
});
|
|
5105
5141
|
|
|
5106
5142
|
// ../../packages/core/src/agents/fork.ts
|
|
5107
|
-
import { existsSync as
|
|
5143
|
+
import { existsSync as existsSync11, unlinkSync as unlinkSync9 } from "fs";
|
|
5108
5144
|
function createAgentForkHelpers(host) {
|
|
5109
5145
|
return {
|
|
5110
5146
|
async forkAgentSession(options) {
|
|
@@ -5141,8 +5177,8 @@ var init_fork = __esm(async () => {
|
|
|
5141
5177
|
await init_registry();
|
|
5142
5178
|
defaultForkHelpers = createAgentForkHelpers({
|
|
5143
5179
|
forkSession: (agent, options) => getRegistryOperations(agent).forkSession(options),
|
|
5144
|
-
exists:
|
|
5145
|
-
unlink:
|
|
5180
|
+
exists: existsSync11,
|
|
5181
|
+
unlink: unlinkSync9,
|
|
5146
5182
|
warn: (details, message) => logger.warn(details, message)
|
|
5147
5183
|
});
|
|
5148
5184
|
});
|
|
@@ -5541,7 +5577,7 @@ var init_runtime_process_leases = __esm(async () => {
|
|
|
5541
5577
|
|
|
5542
5578
|
// ../../packages/core/src/platform/playwright/browser-processes.ts
|
|
5543
5579
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
5544
|
-
import { readdirSync as readdirSync4, unlinkSync as
|
|
5580
|
+
import { readdirSync as readdirSync4, unlinkSync as unlinkSync10 } from "fs";
|
|
5545
5581
|
import { createServer } from "net";
|
|
5546
5582
|
import { resolve as resolve8, sep } from "path";
|
|
5547
5583
|
function isPortInUse(port) {
|
|
@@ -5670,7 +5706,7 @@ function cleanSingletonFiles(userDataDir) {
|
|
|
5670
5706
|
for (const f of files) {
|
|
5671
5707
|
if (f.startsWith("Singleton")) {
|
|
5672
5708
|
try {
|
|
5673
|
-
|
|
5709
|
+
unlinkSync10(resolve8(userDataDir, f));
|
|
5674
5710
|
logger.info({ file: f, userDataDir }, "Removed stale Singleton file");
|
|
5675
5711
|
} catch (e) {
|
|
5676
5712
|
logger.warn({ err: e, file: f }, "Failed to remove stale Chrome Singleton file");
|
|
@@ -5811,7 +5847,7 @@ var init_vault_public = __esm(async () => {
|
|
|
5811
5847
|
|
|
5812
5848
|
// ../../packages/core/src/platform/playwright/vault-broker.ts
|
|
5813
5849
|
import { randomBytes as randomBytes5, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
5814
|
-
import { chmodSync as
|
|
5850
|
+
import { chmodSync as chmodSync5 } from "fs";
|
|
5815
5851
|
import { createServer as createServer2 } from "net";
|
|
5816
5852
|
import { tmpdir as tmpdir2 } from "os";
|
|
5817
5853
|
import { join as join12 } from "path";
|
|
@@ -6007,7 +6043,7 @@ async function createBrowserVaultBroker(userId) {
|
|
|
6007
6043
|
server.once("error", reject);
|
|
6008
6044
|
server.listen(socketPath, resolveListen);
|
|
6009
6045
|
});
|
|
6010
|
-
|
|
6046
|
+
chmodSync5(socketPath, 384);
|
|
6011
6047
|
let closed = false;
|
|
6012
6048
|
return {
|
|
6013
6049
|
socketPath,
|
|
@@ -6099,15 +6135,20 @@ function assignTopicBrowserProfile(opts) {
|
|
|
6099
6135
|
}
|
|
6100
6136
|
var DEFAULT_BROWSER_PROFILE = "default";
|
|
6101
6137
|
var init_browser_profiles = __esm(async () => {
|
|
6102
|
-
await
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6138
|
+
await __promiseAll([
|
|
6139
|
+
init_forum_db(),
|
|
6140
|
+
init_storage_host()
|
|
6141
|
+
]);
|
|
6142
|
+
registerStorageSchemaInitializer((database) => {
|
|
6143
|
+
database.exec(`
|
|
6144
|
+
CREATE TABLE IF NOT EXISTS browser_profiles (
|
|
6145
|
+
owner_id TEXT NOT NULL,
|
|
6146
|
+
name TEXT NOT NULL,
|
|
6147
|
+
created_at TEXT NOT NULL,
|
|
6148
|
+
PRIMARY KEY (owner_id, name)
|
|
6149
|
+
)
|
|
6150
|
+
`);
|
|
6151
|
+
});
|
|
6111
6152
|
});
|
|
6112
6153
|
|
|
6113
6154
|
// ../../packages/core/src/platform/playwright/manager.ts
|
|
@@ -6115,11 +6156,11 @@ import { execFileSync as execFileSync4, spawn as spawn6 } from "child_process";
|
|
|
6115
6156
|
import { createHash as createHash3, randomBytes as randomBytes6, timingSafeEqual as timingSafeEqual3 } from "crypto";
|
|
6116
6157
|
import {
|
|
6117
6158
|
cpSync,
|
|
6118
|
-
existsSync as
|
|
6159
|
+
existsSync as existsSync12,
|
|
6119
6160
|
mkdirSync as mkdirSync9,
|
|
6120
|
-
readFileSync as
|
|
6161
|
+
readFileSync as readFileSync10,
|
|
6121
6162
|
rmSync as rmSync2,
|
|
6122
|
-
unlinkSync as
|
|
6163
|
+
unlinkSync as unlinkSync11,
|
|
6123
6164
|
writeFileSync as writeFileSync7
|
|
6124
6165
|
} from "fs";
|
|
6125
6166
|
import { dirname as dirname8, join as join13, resolve as resolve10 } from "path";
|
|
@@ -6129,7 +6170,7 @@ function removeDefaultProfileDataDir(userDataDir) {
|
|
|
6129
6170
|
if (dirname8(target) !== root) {
|
|
6130
6171
|
throw new Error(`Refusing to delete browser profile outside managed root: ${target}`);
|
|
6131
6172
|
}
|
|
6132
|
-
const existed =
|
|
6173
|
+
const existed = existsSync12(target);
|
|
6133
6174
|
rmSync2(target, { recursive: true, force: true });
|
|
6134
6175
|
return existed;
|
|
6135
6176
|
}
|
|
@@ -6219,7 +6260,7 @@ function writePortFile(instanceKey, port) {
|
|
|
6219
6260
|
}
|
|
6220
6261
|
function deletePortFile(instanceKey) {
|
|
6221
6262
|
try {
|
|
6222
|
-
|
|
6263
|
+
unlinkSync11(join13(managerHost.portsDir, portFileName(instanceKey)));
|
|
6223
6264
|
} catch (e) {
|
|
6224
6265
|
if (e.code === "ENOENT")
|
|
6225
6266
|
return;
|
|
@@ -6704,11 +6745,11 @@ async function cloneProfileForChild(opts) {
|
|
|
6704
6745
|
killInstance(dstKey);
|
|
6705
6746
|
await delay(500);
|
|
6706
6747
|
}
|
|
6707
|
-
if (!
|
|
6748
|
+
if (!existsSync12(srcDir)) {
|
|
6708
6749
|
return { copied: false, srcDir, dstDir, reason: "src-missing" };
|
|
6709
6750
|
}
|
|
6710
6751
|
try {
|
|
6711
|
-
if (
|
|
6752
|
+
if (existsSync12(dstDir)) {
|
|
6712
6753
|
rmSync2(dstDir, { recursive: true, force: true });
|
|
6713
6754
|
}
|
|
6714
6755
|
mkdirSync9(dirname8(dstDir), { recursive: true });
|
|
@@ -6729,7 +6770,7 @@ async function cloneProfileForChild(opts) {
|
|
|
6729
6770
|
cleanSingletonFiles(dstDir);
|
|
6730
6771
|
for (const f of ["DevToolsActivePort", "LOCK"]) {
|
|
6731
6772
|
try {
|
|
6732
|
-
|
|
6773
|
+
unlinkSync11(resolve10(dstDir, f));
|
|
6733
6774
|
} catch {}
|
|
6734
6775
|
}
|
|
6735
6776
|
logger.info({ srcKey, dstKey, srcDir, dstDir }, "Cloned Playwright profile for child topic");
|
|
@@ -7277,11 +7318,11 @@ var init_api_topic_config = __esm(async () => {
|
|
|
7277
7318
|
|
|
7278
7319
|
// ../../packages/core/src/storage/conversations.ts
|
|
7279
7320
|
import {
|
|
7280
|
-
existsSync as
|
|
7321
|
+
existsSync as existsSync13,
|
|
7281
7322
|
mkdirSync as mkdirSync10,
|
|
7282
|
-
readFileSync as
|
|
7323
|
+
readFileSync as readFileSync11,
|
|
7283
7324
|
renameSync as renameSync5,
|
|
7284
|
-
unlinkSync as
|
|
7325
|
+
unlinkSync as unlinkSync12,
|
|
7285
7326
|
writeFileSync as writeFileSync8
|
|
7286
7327
|
} from "fs";
|
|
7287
7328
|
import { dirname as dirname9, join as join14 } from "path";
|
|
@@ -7300,7 +7341,7 @@ function getActiveConversationPath(userId, topicName) {
|
|
|
7300
7341
|
return rawPath.endsWith(".jsonl") ? `${rawPath.slice(0, -".jsonl".length)}.active.jsonl` : `${rawPath}.active`;
|
|
7301
7342
|
}
|
|
7302
7343
|
function hasActiveConversation(userId, topicName) {
|
|
7303
|
-
return
|
|
7344
|
+
return existsSync13(getActiveConversationPath(userId, topicName));
|
|
7304
7345
|
}
|
|
7305
7346
|
function appendConversationEvent(userId, topicName, agent, event) {
|
|
7306
7347
|
try {
|
|
@@ -7322,7 +7363,7 @@ function appendConversationEventStrict(userId, topicName, agent, event) {
|
|
|
7322
7363
|
mkdirSync10(dirname9(path), { recursive: true });
|
|
7323
7364
|
appendJsonlLine(path, line);
|
|
7324
7365
|
const activePath = getActiveConversationPath(userId, topicName);
|
|
7325
|
-
if (
|
|
7366
|
+
if (existsSync13(activePath)) {
|
|
7326
7367
|
try {
|
|
7327
7368
|
appendJsonlLine(activePath, line);
|
|
7328
7369
|
} catch (cause) {
|
|
@@ -7332,11 +7373,11 @@ function appendConversationEventStrict(userId, topicName, agent, event) {
|
|
|
7332
7373
|
}
|
|
7333
7374
|
function readConversationPath(path) {
|
|
7334
7375
|
const out = [];
|
|
7335
|
-
if (!
|
|
7376
|
+
if (!existsSync13(path))
|
|
7336
7377
|
return out;
|
|
7337
7378
|
let raw;
|
|
7338
7379
|
try {
|
|
7339
|
-
raw =
|
|
7380
|
+
raw = readFileSync11(path, "utf8");
|
|
7340
7381
|
} catch (err) {
|
|
7341
7382
|
logger.warn({ err, path }, "readConversation: read failed");
|
|
7342
7383
|
return out;
|
|
@@ -7355,7 +7396,7 @@ function readConversationPath(path) {
|
|
|
7355
7396
|
}
|
|
7356
7397
|
function readConversation(userId, topicName) {
|
|
7357
7398
|
const activePath = getActiveConversationPath(userId, topicName);
|
|
7358
|
-
return readConversationPath(
|
|
7399
|
+
return readConversationPath(existsSync13(activePath) ? activePath : getConversationPath(userId, topicName));
|
|
7359
7400
|
}
|
|
7360
7401
|
function readRawConversation(userId, topicName) {
|
|
7361
7402
|
return readConversationPath(getConversationPath(userId, topicName));
|
|
@@ -7376,7 +7417,7 @@ function replaceConversationPathStrict(path, entries) {
|
|
|
7376
7417
|
renameSync5(tempPath, path);
|
|
7377
7418
|
} catch (error) {
|
|
7378
7419
|
try {
|
|
7379
|
-
|
|
7420
|
+
unlinkSync12(tempPath);
|
|
7380
7421
|
} catch {}
|
|
7381
7422
|
throw error;
|
|
7382
7423
|
}
|
|
@@ -7513,7 +7554,7 @@ RULES:
|
|
|
7513
7554
|
- Keep the entire summary under 1500 words.`, CHARS_PER_TEXT_TOKEN = 3.5, CHARS_PER_CJK_TOKEN = 0.9;
|
|
7514
7555
|
|
|
7515
7556
|
// ../../packages/core/src/storage/tasks.ts
|
|
7516
|
-
import { existsSync as
|
|
7557
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync12, renameSync as renameSync6, statSync as statSync4, writeFileSync as writeFileSync9 } from "fs";
|
|
7517
7558
|
import { dirname as dirname10, join as join15 } from "path";
|
|
7518
7559
|
function safeTaskScopeKey(scopeKey) {
|
|
7519
7560
|
const safe = sanitizeFileName(scopeKey);
|
|
@@ -7530,10 +7571,10 @@ function getTaskFilePath(userId, scopeKey) {
|
|
|
7530
7571
|
}
|
|
7531
7572
|
function readTasks(userId, scopeKey) {
|
|
7532
7573
|
const path = getTaskFilePath(userId, scopeKey);
|
|
7533
|
-
if (!
|
|
7574
|
+
if (!existsSync14(path))
|
|
7534
7575
|
return [];
|
|
7535
7576
|
try {
|
|
7536
|
-
const parsed = JSON.parse(
|
|
7577
|
+
const parsed = JSON.parse(readFileSync12(path, "utf-8"));
|
|
7537
7578
|
return Array.isArray(parsed?.tasks) ? parsed.tasks : [];
|
|
7538
7579
|
} catch (e) {
|
|
7539
7580
|
logger.warn({ err: e, path }, "tasks: failed to read task store");
|
|
@@ -7788,7 +7829,7 @@ __export(exports_claude_provider, {
|
|
|
7788
7829
|
buildClaudeDisallowedTools: () => buildClaudeDisallowedTools
|
|
7789
7830
|
});
|
|
7790
7831
|
import { spawn as spawn7 } from "child_process";
|
|
7791
|
-
import { existsSync as
|
|
7832
|
+
import { existsSync as existsSync15, readFileSync as readFileSync13 } from "fs";
|
|
7792
7833
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
7793
7834
|
function claudeBuiltInTools(opts) {
|
|
7794
7835
|
return opts.toolPolicy ? [] : undefined;
|
|
@@ -7841,7 +7882,7 @@ function buildClaudePrompt(opts) {
|
|
|
7841
7882
|
source: {
|
|
7842
7883
|
type: "base64",
|
|
7843
7884
|
media_type: attachment.mimeType,
|
|
7844
|
-
data:
|
|
7885
|
+
data: readFileSync13(attachment.path).toString("base64")
|
|
7845
7886
|
}
|
|
7846
7887
|
});
|
|
7847
7888
|
} catch (err) {
|
|
@@ -7969,7 +8010,7 @@ function isAbortError(err) {
|
|
|
7969
8010
|
}
|
|
7970
8011
|
async function* claudeProvider(opts) {
|
|
7971
8012
|
const claudeExecutable = hostedClaudeCodeExecutablePath();
|
|
7972
|
-
if (claudeExecutable && !
|
|
8013
|
+
if (claudeExecutable && !existsSync15(claudeExecutable)) {
|
|
7973
8014
|
yield {
|
|
7974
8015
|
type: "error",
|
|
7975
8016
|
content: `Claude CLI not found at ${claudeExecutable}. Install Claude Code or configure the executable path.`
|
|
@@ -8489,7 +8530,7 @@ var init_codex_tree_kill = __esm(() => {
|
|
|
8489
8530
|
});
|
|
8490
8531
|
|
|
8491
8532
|
// ../../packages/core/src/agents/tool-format.ts
|
|
8492
|
-
import { readFileSync as
|
|
8533
|
+
import { readFileSync as readFileSync14, statSync as statSync5 } from "fs";
|
|
8493
8534
|
import { isAbsolute as isAbsolute2, resolve as resolve11 } from "path";
|
|
8494
8535
|
import { diffLines as computeLineDiff } from "diff";
|
|
8495
8536
|
function summarizeDisplayText(value2) {
|
|
@@ -8818,7 +8859,7 @@ function sourceStartLine(input, before, after, cwd) {
|
|
|
8818
8859
|
try {
|
|
8819
8860
|
if (statSync5(path).size > TOOL_DIFF_SOURCE_MAX_BYTES)
|
|
8820
8861
|
return 1;
|
|
8821
|
-
const source =
|
|
8862
|
+
const source = readFileSync14(path, "utf8").replace(/\r\n?/g, `
|
|
8822
8863
|
`);
|
|
8823
8864
|
for (const candidate of [before, after].filter(Boolean)) {
|
|
8824
8865
|
const index = source.indexOf(candidate);
|
|
@@ -9012,7 +9053,7 @@ __export(exports_codex_provider, {
|
|
|
9012
9053
|
codexProvider: () => codexProvider
|
|
9013
9054
|
});
|
|
9014
9055
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
9015
|
-
import { existsSync as
|
|
9056
|
+
import { existsSync as existsSync16, readFileSync as readFileSync15, realpathSync as realpathSync4, statSync as statSync6 } from "fs";
|
|
9016
9057
|
import { homedir as homedir6 } from "os";
|
|
9017
9058
|
import { dirname as dirname11, isAbsolute as isAbsolute3, join as join16, relative as relative2, resolve as resolve12 } from "path";
|
|
9018
9059
|
import { Codex } from "@openai/codex-sdk";
|
|
@@ -9043,11 +9084,11 @@ function codexMcpServerName(name) {
|
|
|
9043
9084
|
}
|
|
9044
9085
|
function globalCodexMcpServerNames(authFilePath) {
|
|
9045
9086
|
const configPath = join16(dirname11(authFilePath), "config.toml");
|
|
9046
|
-
if (!
|
|
9087
|
+
if (!existsSync16(configPath))
|
|
9047
9088
|
return [];
|
|
9048
9089
|
try {
|
|
9049
9090
|
const names = new Set;
|
|
9050
|
-
for (const line of
|
|
9091
|
+
for (const line of readFileSync15(configPath, "utf8").split(`
|
|
9051
9092
|
`)) {
|
|
9052
9093
|
const match = line.match(/^\s*\[\s*mcp_servers\.((?:"(?:\\.|[^"])*")|(?:'[^']*')|[^.\]\s]+)(?:[.\]])/);
|
|
9053
9094
|
const raw = match?.[1];
|
|
@@ -9144,13 +9185,13 @@ function canonicalPath(path) {
|
|
|
9144
9185
|
}
|
|
9145
9186
|
}
|
|
9146
9187
|
function textFile(path, maxBytes = CODEX_DIFF_FILE_LIMIT) {
|
|
9147
|
-
if (!
|
|
9188
|
+
if (!existsSync16(path))
|
|
9148
9189
|
return null;
|
|
9149
9190
|
try {
|
|
9150
9191
|
const byteLimit = Math.min(CODEX_DIFF_FILE_LIMIT, Math.max(0, maxBytes));
|
|
9151
9192
|
if (statSync6(path).size > byteLimit)
|
|
9152
9193
|
return;
|
|
9153
|
-
const content =
|
|
9194
|
+
const content = readFileSync15(path);
|
|
9154
9195
|
if (content.byteLength > byteLimit || content.includes(0))
|
|
9155
9196
|
return;
|
|
9156
9197
|
return content.toString("utf8");
|
|
@@ -9356,7 +9397,7 @@ async function* codexProvider(opts) {
|
|
|
9356
9397
|
const filePreviews = new CodexFilePreviewTracker(opts.cwd);
|
|
9357
9398
|
const consumedPatchCallIds = new Set(opts.sessionId ? readCodexPatchCallIds(opts.sessionId) : []);
|
|
9358
9399
|
const codexAuthPath = hostedCodexAuthFilePath();
|
|
9359
|
-
if (!
|
|
9400
|
+
if (!existsSync16(codexAuthPath)) {
|
|
9360
9401
|
yield {
|
|
9361
9402
|
type: "error",
|
|
9362
9403
|
content: `Codex auth file not found at ${codexAuthPath}. Run \`codex login\` to authenticate.`
|
|
@@ -9395,7 +9436,7 @@ async function* codexProvider(opts) {
|
|
|
9395
9436
|
model: opts.model ?? "(sdk default)",
|
|
9396
9437
|
effort: opts.effort ?? "(off)",
|
|
9397
9438
|
cwd: opts.cwd,
|
|
9398
|
-
cwdExists:
|
|
9439
|
+
cwdExists: existsSync16(opts.cwd),
|
|
9399
9440
|
resume: Boolean(opts.sessionId),
|
|
9400
9441
|
mcpServerCount: Object.keys(codexMcpServers).length
|
|
9401
9442
|
}, "codexProvider: starting turn");
|
|
@@ -9847,7 +9888,7 @@ var init_maestro_provider = __esm(async () => {
|
|
|
9847
9888
|
});
|
|
9848
9889
|
|
|
9849
9890
|
// ../../packages/core/src/agents/index.ts
|
|
9850
|
-
import { existsSync as
|
|
9891
|
+
import { existsSync as existsSync17 } from "fs";
|
|
9851
9892
|
import { homedir as homedir7 } from "os";
|
|
9852
9893
|
import { join as join17 } from "path";
|
|
9853
9894
|
async function* dispatchAgent(opts) {
|
|
@@ -9884,7 +9925,7 @@ async function resolveSessionFileMissing(agent, sessionId, cwd) {
|
|
|
9884
9925
|
case "claude": {
|
|
9885
9926
|
const encodedCwd = encodeClaudeCwd(cwd);
|
|
9886
9927
|
const path = join17(homedir7(), ".claude", "projects", encodedCwd, `${sessionId}.jsonl`);
|
|
9887
|
-
return !
|
|
9928
|
+
return !existsSync17(path);
|
|
9888
9929
|
}
|
|
9889
9930
|
case "codex": {
|
|
9890
9931
|
const sessionsDir = join17(hostedCodexHomePath(), "sessions");
|
|
@@ -9896,7 +9937,7 @@ async function resolveSessionFileMissing(agent, sessionId, cwd) {
|
|
|
9896
9937
|
}
|
|
9897
9938
|
case "maestro": {
|
|
9898
9939
|
const { hasActiveMaestroSession, maestroSessionPath: maestroSessionPath2 } = await import("maestro-agent-sdk");
|
|
9899
|
-
return !
|
|
9940
|
+
return !existsSync17(maestroSessionPath2(sessionId)) && !hasActiveMaestroSession(sessionId);
|
|
9900
9941
|
}
|
|
9901
9942
|
default: {
|
|
9902
9943
|
const _exhaustive = agent;
|
|
@@ -9969,10 +10010,10 @@ var init_agents = __esm(async () => {
|
|
|
9969
10010
|
});
|
|
9970
10011
|
|
|
9971
10012
|
// ../../packages/core/src/prompts/builders.ts
|
|
9972
|
-
import { readFileSync as
|
|
10013
|
+
import { readFileSync as readFileSync16 } from "fs";
|
|
9973
10014
|
import { resolve as resolve14 } from "path";
|
|
9974
10015
|
function loadPrompt(filename, dir = SESSIONS_DIR) {
|
|
9975
|
-
const raw =
|
|
10016
|
+
const raw = readFileSync16(resolve14(dir, filename), "utf-8");
|
|
9976
10017
|
return raw.replace(/\{\{RESOURCES_DIR\}\}/g, RESOURCES_DIR);
|
|
9977
10018
|
}
|
|
9978
10019
|
function replaceVars(template, vars) {
|
|
@@ -10021,7 +10062,7 @@ function visualDesignGuide() {
|
|
|
10021
10062
|
return _visualDesignGuide;
|
|
10022
10063
|
}
|
|
10023
10064
|
function loadAgentPrompt(filename) {
|
|
10024
|
-
const raw =
|
|
10065
|
+
const raw = readFileSync16(resolve14(AGENTS_PROMPTS_DIR, filename), "utf-8");
|
|
10025
10066
|
const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
10026
10067
|
if (!match)
|
|
10027
10068
|
throw new Error(`Agent prompt ${filename} is missing frontmatter`);
|
|
@@ -10420,7 +10461,7 @@ var init_wiki = __esm(async () => {
|
|
|
10420
10461
|
|
|
10421
10462
|
// ../../packages/core/src/agents/archiver.ts
|
|
10422
10463
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
10423
|
-
import { existsSync as
|
|
10464
|
+
import { existsSync as existsSync18, readdirSync as readdirSync5, readFileSync as readFileSync17, statSync as statSync7 } from "fs";
|
|
10424
10465
|
import { join as join19 } from "path";
|
|
10425
10466
|
function resolveMemoryLanguage() {
|
|
10426
10467
|
const override = process.env.NEGOTIUM_MEMORY_LANG?.trim();
|
|
@@ -10440,9 +10481,9 @@ function formatArchiverBytes(bytes) {
|
|
|
10440
10481
|
function formatArchiverTool(name, input) {
|
|
10441
10482
|
const params = Object.entries(input).map(([key, value2]) => {
|
|
10442
10483
|
const rendered = typeof value2 === "string" ? value2 : JSON.stringify(value2);
|
|
10443
|
-
return `${key}: ${sessionText(rendered ?? "")}`;
|
|
10484
|
+
return `${key}: ${summarizeDisplayText(sessionText(rendered ?? ""))}`;
|
|
10444
10485
|
}).join(", ");
|
|
10445
|
-
return `${name}${params ? `(${params})` : ""}
|
|
10486
|
+
return summarizeDisplayText(`${name}${params ? `(${params})` : ""}`);
|
|
10446
10487
|
}
|
|
10447
10488
|
function createArchiverRuntime(host) {
|
|
10448
10489
|
const activeSessions = new Map;
|
|
@@ -10749,6 +10790,7 @@ function runArchiverTurn(params) {
|
|
|
10749
10790
|
}
|
|
10750
10791
|
var MAX_BRIEF_ENTRIES = 8, defaultArchiverRuntime;
|
|
10751
10792
|
var init_archiver = __esm(async () => {
|
|
10793
|
+
init_tool_format();
|
|
10752
10794
|
init_config();
|
|
10753
10795
|
init_logger();
|
|
10754
10796
|
init_builders();
|
|
@@ -10765,9 +10807,9 @@ var init_archiver = __esm(async () => {
|
|
|
10765
10807
|
defaultArchiverRuntime = createArchiverRuntime({
|
|
10766
10808
|
storage: {
|
|
10767
10809
|
getWikiDir: getSharedWikiDir,
|
|
10768
|
-
fileExists:
|
|
10810
|
+
fileExists: existsSync18,
|
|
10769
10811
|
listDirectory: readdirSync5,
|
|
10770
|
-
readTextFile: (path) =>
|
|
10812
|
+
readTextFile: (path) => readFileSync17(path, "utf-8"),
|
|
10771
10813
|
fileSize: (path) => statSync7(path).size,
|
|
10772
10814
|
fileModifiedAt: (path) => statSync7(path).mtimeMs,
|
|
10773
10815
|
getGeneralTopicId: (userId) => ensurePersonalGeneral(userId).id,
|
|
@@ -11304,7 +11346,7 @@ var init_idle_archiver = __esm(async () => {
|
|
|
11304
11346
|
});
|
|
11305
11347
|
|
|
11306
11348
|
// ../../packages/core/src/agents/topic-cleanup.ts
|
|
11307
|
-
import { mkdirSync as mkdirSync13, renameSync as renameSync7, unlinkSync as
|
|
11349
|
+
import { mkdirSync as mkdirSync13, renameSync as renameSync7, unlinkSync as unlinkSync13, writeFileSync as writeFileSync11 } from "fs";
|
|
11308
11350
|
import { dirname as dirname13 } from "path";
|
|
11309
11351
|
function collectSessionIdsByAgent(entries, extraSessions = []) {
|
|
11310
11352
|
const out = new Map;
|
|
@@ -11378,7 +11420,7 @@ function createTopicLogMaintenance(host) {
|
|
|
11378
11420
|
renameSync7(tempPath, path);
|
|
11379
11421
|
} catch (e) {
|
|
11380
11422
|
try {
|
|
11381
|
-
|
|
11423
|
+
unlinkSync13(tempPath);
|
|
11382
11424
|
} catch {}
|
|
11383
11425
|
runtimeHost.warn({ err: e, path }, "rotateTopicLogs: conversation replacement failed");
|
|
11384
11426
|
return {
|
|
@@ -11408,7 +11450,7 @@ function createTopicLogMaintenance(host) {
|
|
|
11408
11450
|
runtimeHost.rawConversationPath(userId, topicName)
|
|
11409
11451
|
]) {
|
|
11410
11452
|
try {
|
|
11411
|
-
|
|
11453
|
+
unlinkSync13(path);
|
|
11412
11454
|
} catch (e) {
|
|
11413
11455
|
if (e?.code !== "ENOENT") {
|
|
11414
11456
|
runtimeHost.warn({ err: e, path }, "purgeTopicLogs: conversation log unlink failed");
|
|
@@ -11510,6 +11552,7 @@ function text(value2, maxLen) {
|
|
|
11510
11552
|
}
|
|
11511
11553
|
var providers, transientSessions;
|
|
11512
11554
|
var init_background_sessions = __esm(async () => {
|
|
11555
|
+
init_tool_format();
|
|
11513
11556
|
init_background_session_policy();
|
|
11514
11557
|
await __promiseAll([
|
|
11515
11558
|
init_archiver(),
|
|
@@ -11960,7 +12003,7 @@ __export(exports_derive, {
|
|
|
11960
12003
|
TopicDeriveBusyError: () => TopicDeriveBusyError
|
|
11961
12004
|
});
|
|
11962
12005
|
import { createHash as createHash4, randomUUID as randomUUID11 } from "crypto";
|
|
11963
|
-
import { mkdirSync as mkdirSync14, rmSync as rmSync5, unlinkSync as
|
|
12006
|
+
import { mkdirSync as mkdirSync14, rmSync as rmSync5, unlinkSync as unlinkSync14 } from "fs";
|
|
11964
12007
|
function getTopics() {
|
|
11965
12008
|
return listTopics().filter((topic) => !isLegacySharedGeneral(topic.id));
|
|
11966
12009
|
}
|
|
@@ -12255,7 +12298,7 @@ async function createDerivedTopicImpl(topic, sourceTopicId, userId, copyHistory,
|
|
|
12255
12298
|
getConversationPath(userId, derived.title)
|
|
12256
12299
|
]) {
|
|
12257
12300
|
try {
|
|
12258
|
-
|
|
12301
|
+
unlinkSync14(path);
|
|
12259
12302
|
} catch {}
|
|
12260
12303
|
}
|
|
12261
12304
|
}
|
|
@@ -12327,7 +12370,7 @@ var init_session_inbox_path = __esm(() => {
|
|
|
12327
12370
|
});
|
|
12328
12371
|
|
|
12329
12372
|
// ../../packages/core/src/query/session-inbox-cleanup.ts
|
|
12330
|
-
import { unlinkSync as
|
|
12373
|
+
import { unlinkSync as unlinkSync15 } from "fs";
|
|
12331
12374
|
import { basename as basename4, join as join23 } from "path";
|
|
12332
12375
|
function cleanupSessionInboxFiles(userId, topicId, legacyTopicTitle) {
|
|
12333
12376
|
const live = sessionInboxPath(userId, topicId);
|
|
@@ -12342,7 +12385,7 @@ function cleanupSessionInboxFiles(userId, topicId, legacyTopicTitle) {
|
|
|
12342
12385
|
let deleted = 0;
|
|
12343
12386
|
for (const path of candidates) {
|
|
12344
12387
|
try {
|
|
12345
|
-
|
|
12388
|
+
unlinkSync15(path);
|
|
12346
12389
|
deleted++;
|
|
12347
12390
|
} catch (err) {
|
|
12348
12391
|
if (err?.code !== "ENOENT") {
|
|
@@ -12359,7 +12402,7 @@ var init_session_inbox_cleanup = __esm(() => {
|
|
|
12359
12402
|
});
|
|
12360
12403
|
|
|
12361
12404
|
// ../../packages/core/src/query/state.ts
|
|
12362
|
-
import { mkdirSync as mkdirSync15, renameSync as renameSync8, unlinkSync as
|
|
12405
|
+
import { mkdirSync as mkdirSync15, renameSync as renameSync8, unlinkSync as unlinkSync16, writeFileSync as writeFileSync13 } from "fs";
|
|
12363
12406
|
import { basename as basename5, join as join24 } from "path";
|
|
12364
12407
|
function createQueryStateStore(options) {
|
|
12365
12408
|
const sanitize = options.sanitizeTopicId ?? sanitizeId;
|
|
@@ -12390,7 +12433,7 @@ function createQueryStateStore(options) {
|
|
|
12390
12433
|
].filter((path) => Boolean(path));
|
|
12391
12434
|
for (const path of new Set(paths)) {
|
|
12392
12435
|
try {
|
|
12393
|
-
|
|
12436
|
+
unlinkSync16(path);
|
|
12394
12437
|
} catch (error) {
|
|
12395
12438
|
if (error?.code !== "ENOENT") {
|
|
12396
12439
|
options.logger?.warn({ err: error, userId, topicId, path }, "Failed to clear query state file");
|
|
@@ -12524,9 +12567,9 @@ import {
|
|
|
12524
12567
|
mkdirSync as mkdirSync16,
|
|
12525
12568
|
openSync as openSync3,
|
|
12526
12569
|
readdirSync as readdirSync6,
|
|
12527
|
-
readFileSync as
|
|
12570
|
+
readFileSync as readFileSync18,
|
|
12528
12571
|
statSync as statSync8,
|
|
12529
|
-
unlinkSync as
|
|
12572
|
+
unlinkSync as unlinkSync17,
|
|
12530
12573
|
writeFileSync as writeFileSync14
|
|
12531
12574
|
} from "fs";
|
|
12532
12575
|
import { dirname as dirname14, join as join25 } from "path";
|
|
@@ -12573,7 +12616,7 @@ function parsePendingAskFilename(fileName) {
|
|
|
12573
12616
|
}
|
|
12574
12617
|
function readPendingAskFile(path, fallback) {
|
|
12575
12618
|
try {
|
|
12576
|
-
const raw =
|
|
12619
|
+
const raw = readFileSync18(path, "utf8").trim();
|
|
12577
12620
|
if (!raw)
|
|
12578
12621
|
return null;
|
|
12579
12622
|
if (!raw.startsWith("{")) {
|
|
@@ -12662,7 +12705,7 @@ function readPendingAsk(key) {
|
|
|
12662
12705
|
const next = migrated ? legacy : readPendingAskFile(canonicalPath2, key);
|
|
12663
12706
|
if (next && next.from === key.from && next.to === key.to) {
|
|
12664
12707
|
try {
|
|
12665
|
-
|
|
12708
|
+
unlinkSync17(compatibilityPath);
|
|
12666
12709
|
} catch {}
|
|
12667
12710
|
return { path: canonicalPath2, record: next };
|
|
12668
12711
|
}
|
|
@@ -12677,7 +12720,7 @@ function createPendingAsk(args) {
|
|
|
12677
12720
|
}
|
|
12678
12721
|
if (migrated) {
|
|
12679
12722
|
try {
|
|
12680
|
-
|
|
12723
|
+
unlinkSync17(migrated.path);
|
|
12681
12724
|
} catch {
|
|
12682
12725
|
return { ok: false, existing: migrated.record, stale: true };
|
|
12683
12726
|
}
|
|
@@ -12709,7 +12752,7 @@ function createPendingAsk(args) {
|
|
|
12709
12752
|
if (!isStale(existing, path))
|
|
12710
12753
|
return { ok: false, existing, stale: false };
|
|
12711
12754
|
try {
|
|
12712
|
-
|
|
12755
|
+
unlinkSync17(path);
|
|
12713
12756
|
} catch {
|
|
12714
12757
|
return { ok: false, existing, stale: true };
|
|
12715
12758
|
}
|
|
@@ -12735,7 +12778,7 @@ function markPendingAskState(args) {
|
|
|
12735
12778
|
writePendingAsk(next);
|
|
12736
12779
|
if (pending.path !== pendingAskPath(next)) {
|
|
12737
12780
|
try {
|
|
12738
|
-
|
|
12781
|
+
unlinkSync17(pending.path);
|
|
12739
12782
|
} catch {}
|
|
12740
12783
|
}
|
|
12741
12784
|
return next;
|
|
@@ -12747,7 +12790,7 @@ function clearPendingAsk(args) {
|
|
|
12747
12790
|
if (args.requestId && record && record.requestId !== args.requestId)
|
|
12748
12791
|
return false;
|
|
12749
12792
|
try {
|
|
12750
|
-
|
|
12793
|
+
unlinkSync17(path);
|
|
12751
12794
|
return true;
|
|
12752
12795
|
} catch {
|
|
12753
12796
|
return false;
|
|
@@ -12802,7 +12845,7 @@ function listPendingAsksForCaller(args) {
|
|
|
12802
12845
|
continue;
|
|
12803
12846
|
if (isStale(record, path)) {
|
|
12804
12847
|
try {
|
|
12805
|
-
|
|
12848
|
+
unlinkSync17(path);
|
|
12806
12849
|
} catch {}
|
|
12807
12850
|
continue;
|
|
12808
12851
|
}
|
|
@@ -12811,12 +12854,12 @@ function listPendingAsksForCaller(args) {
|
|
|
12811
12854
|
continue;
|
|
12812
12855
|
if (path !== canonical.path) {
|
|
12813
12856
|
try {
|
|
12814
|
-
|
|
12857
|
+
unlinkSync17(path);
|
|
12815
12858
|
} catch {}
|
|
12816
12859
|
}
|
|
12817
12860
|
if (isStale(canonical.record, canonical.path)) {
|
|
12818
12861
|
try {
|
|
12819
|
-
|
|
12862
|
+
unlinkSync17(canonical.path);
|
|
12820
12863
|
} catch {}
|
|
12821
12864
|
continue;
|
|
12822
12865
|
}
|
|
@@ -12846,7 +12889,7 @@ function deletePendingAsksForTopic(args) {
|
|
|
12846
12889
|
if (from !== args.topicName && to !== args.topicName)
|
|
12847
12890
|
continue;
|
|
12848
12891
|
try {
|
|
12849
|
-
|
|
12892
|
+
unlinkSync17(path);
|
|
12850
12893
|
deleted++;
|
|
12851
12894
|
} catch {}
|
|
12852
12895
|
}
|
|
@@ -12947,19 +12990,22 @@ var pendingAsks, MAX_ASK_AGE_MS;
|
|
|
12947
12990
|
var init_ask_callbacks = __esm(async () => {
|
|
12948
12991
|
await __promiseAll([
|
|
12949
12992
|
init_forum_db(),
|
|
12950
|
-
init_session_asks()
|
|
12993
|
+
init_session_asks(),
|
|
12994
|
+
init_storage_host()
|
|
12951
12995
|
]);
|
|
12952
|
-
|
|
12953
|
-
|
|
12954
|
-
|
|
12955
|
-
|
|
12956
|
-
|
|
12957
|
-
|
|
12958
|
-
|
|
12959
|
-
|
|
12960
|
-
|
|
12961
|
-
|
|
12962
|
-
|
|
12996
|
+
registerStorageSchemaInitializer((database) => {
|
|
12997
|
+
database.exec(`
|
|
12998
|
+
CREATE TABLE IF NOT EXISTS remote_ask_callbacks (
|
|
12999
|
+
target_query_id TEXT PRIMARY KEY,
|
|
13000
|
+
request_id TEXT NOT NULL,
|
|
13001
|
+
node_name TEXT NOT NULL,
|
|
13002
|
+
node_cell_id TEXT NOT NULL,
|
|
13003
|
+
topic_id TEXT NOT NULL,
|
|
13004
|
+
user_id TEXT NOT NULL,
|
|
13005
|
+
created_at INTEGER NOT NULL
|
|
13006
|
+
)
|
|
13007
|
+
`);
|
|
13008
|
+
});
|
|
12963
13009
|
pendingAsks = new Map;
|
|
12964
13010
|
MAX_ASK_AGE_MS = PENDING_ASK_TTL_MS;
|
|
12965
13011
|
});
|
|
@@ -13172,30 +13218,35 @@ paint();document.body.appendChild(b)}
|
|
|
13172
13218
|
if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",init);else init()})();
|
|
13173
13219
|
</script>`;
|
|
13174
13220
|
var init_visual_store = __esm(async () => {
|
|
13175
|
-
await
|
|
13176
|
-
|
|
13177
|
-
|
|
13178
|
-
|
|
13179
|
-
|
|
13180
|
-
|
|
13181
|
-
|
|
13182
|
-
|
|
13183
|
-
|
|
13184
|
-
|
|
13185
|
-
|
|
13186
|
-
|
|
13187
|
-
|
|
13188
|
-
|
|
13189
|
-
|
|
13190
|
-
|
|
13191
|
-
|
|
13192
|
-
|
|
13193
|
-
|
|
13194
|
-
|
|
13195
|
-
|
|
13196
|
-
|
|
13197
|
-
|
|
13198
|
-
|
|
13221
|
+
await __promiseAll([
|
|
13222
|
+
init_forum_db(),
|
|
13223
|
+
init_storage_host()
|
|
13224
|
+
]);
|
|
13225
|
+
registerStorageSchemaInitializer((database) => {
|
|
13226
|
+
database.exec(`
|
|
13227
|
+
CREATE TABLE IF NOT EXISTS api_topic_visuals (
|
|
13228
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
13229
|
+
topic_id TEXT NOT NULL,
|
|
13230
|
+
html TEXT NOT NULL,
|
|
13231
|
+
title TEXT,
|
|
13232
|
+
created_at INTEGER NOT NULL,
|
|
13233
|
+
kind TEXT NOT NULL DEFAULT 'html',
|
|
13234
|
+
source TEXT,
|
|
13235
|
+
file_id TEXT,
|
|
13236
|
+
mime_type TEXT,
|
|
13237
|
+
media_token TEXT
|
|
13238
|
+
);
|
|
13239
|
+
CREATE INDEX IF NOT EXISTS idx_api_topic_visuals_topic
|
|
13240
|
+
ON api_topic_visuals(topic_id, created_at DESC);
|
|
13241
|
+
|
|
13242
|
+
CREATE TABLE IF NOT EXISTS api_topic_visual_views (
|
|
13243
|
+
topic_id TEXT NOT NULL,
|
|
13244
|
+
user_id TEXT NOT NULL,
|
|
13245
|
+
visual_id INTEGER NOT NULL,
|
|
13246
|
+
PRIMARY KEY (topic_id, user_id)
|
|
13247
|
+
);
|
|
13248
|
+
`);
|
|
13249
|
+
});
|
|
13199
13250
|
for (const statement of [
|
|
13200
13251
|
"ALTER TABLE api_topic_visuals ADD COLUMN kind TEXT NOT NULL DEFAULT 'html'",
|
|
13201
13252
|
"ALTER TABLE api_topic_visuals ADD COLUMN source TEXT",
|
|
@@ -13236,32 +13287,35 @@ var init_self_schedules = __esm(async () => {
|
|
|
13236
13287
|
await __promiseAll([
|
|
13237
13288
|
init_forum_db(),
|
|
13238
13289
|
init_runtime_leases(),
|
|
13239
|
-
init_runtime_topic_state()
|
|
13290
|
+
init_runtime_topic_state(),
|
|
13291
|
+
init_storage_host()
|
|
13240
13292
|
]);
|
|
13241
|
-
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
|
|
13246
|
-
|
|
13247
|
-
|
|
13248
|
-
|
|
13249
|
-
|
|
13250
|
-
|
|
13251
|
-
|
|
13252
|
-
|
|
13253
|
-
|
|
13254
|
-
|
|
13255
|
-
|
|
13256
|
-
|
|
13257
|
-
|
|
13258
|
-
|
|
13259
|
-
|
|
13260
|
-
|
|
13261
|
-
|
|
13262
|
-
|
|
13263
|
-
|
|
13264
|
-
|
|
13293
|
+
registerStorageSchemaInitializer((database) => {
|
|
13294
|
+
database.exec(`
|
|
13295
|
+
CREATE TABLE IF NOT EXISTS runtime_self_schedules (
|
|
13296
|
+
id TEXT PRIMARY KEY,
|
|
13297
|
+
topic_id TEXT NOT NULL,
|
|
13298
|
+
user_id TEXT NOT NULL,
|
|
13299
|
+
message TEXT NOT NULL,
|
|
13300
|
+
deliver_at INTEGER NOT NULL,
|
|
13301
|
+
created_at INTEGER NOT NULL,
|
|
13302
|
+
updated_at INTEGER NOT NULL,
|
|
13303
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'running')),
|
|
13304
|
+
claimed_by TEXT,
|
|
13305
|
+
claimed_at INTEGER,
|
|
13306
|
+
running_query_id TEXT
|
|
13307
|
+
)
|
|
13308
|
+
`);
|
|
13309
|
+
database.exec(`
|
|
13310
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_runtime_self_schedules_one_pending
|
|
13311
|
+
ON runtime_self_schedules(topic_id)
|
|
13312
|
+
WHERE status = 'pending'
|
|
13313
|
+
`);
|
|
13314
|
+
database.exec(`
|
|
13315
|
+
CREATE INDEX IF NOT EXISTS idx_runtime_self_schedules_due
|
|
13316
|
+
ON runtime_self_schedules(status, deliver_at)
|
|
13317
|
+
`);
|
|
13318
|
+
});
|
|
13265
13319
|
});
|
|
13266
13320
|
|
|
13267
13321
|
// ../../packages/core/src/topics/lifecycle.ts
|
|
@@ -15506,7 +15560,7 @@ var init_turn_session = __esm(async () => {
|
|
|
15506
15560
|
});
|
|
15507
15561
|
|
|
15508
15562
|
// ../../packages/core/src/storage/app-settings.ts
|
|
15509
|
-
import { existsSync as
|
|
15563
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync19, readFileSync as readFileSync19, writeFileSync as writeFileSync16 } from "fs";
|
|
15510
15564
|
import { dirname as dirname15, join as join28 } from "path";
|
|
15511
15565
|
function settingsFile() {
|
|
15512
15566
|
return join28(resolveStorageDataDir(), "otium-settings.json");
|
|
@@ -15518,8 +15572,8 @@ function ensureSettingsLoaded() {
|
|
|
15518
15572
|
loadedSettingsFile = path;
|
|
15519
15573
|
aiName = DEFAULT_AI_NAME;
|
|
15520
15574
|
try {
|
|
15521
|
-
if (
|
|
15522
|
-
const data = JSON.parse(
|
|
15575
|
+
if (existsSync19(path)) {
|
|
15576
|
+
const data = JSON.parse(readFileSync19(path, "utf8"));
|
|
15523
15577
|
if (typeof data.aiName === "string" && data.aiName.trim()) {
|
|
15524
15578
|
aiName = data.aiName.trim();
|
|
15525
15579
|
}
|
|
@@ -15612,7 +15666,7 @@ __export(exports_turn_runner, {
|
|
|
15612
15666
|
AGENT_DISPLAY_NAME: () => AGENT_DISPLAY_NAME
|
|
15613
15667
|
});
|
|
15614
15668
|
import { randomUUID as randomUUID16 } from "crypto";
|
|
15615
|
-
import { existsSync as
|
|
15669
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync20, readdirSync as readdirSync7, statSync as statSync10 } from "fs";
|
|
15616
15670
|
import { join as join29 } from "path";
|
|
15617
15671
|
function withDefaultPlaywright(configuredMcp, isManager) {
|
|
15618
15672
|
if (isManager)
|
|
@@ -15669,7 +15723,7 @@ function appendAskReplyMessage(topicId, text2, agentType) {
|
|
|
15669
15723
|
}
|
|
15670
15724
|
function resolveWikiMirrorPath(directory, preferredFilename, matchesLegacyId, matchesTitle, preferExact = true) {
|
|
15671
15725
|
const preferred = join29(directory, preferredFilename);
|
|
15672
|
-
if (preferExact &&
|
|
15726
|
+
if (preferExact && existsSync20(preferred))
|
|
15673
15727
|
return preferred;
|
|
15674
15728
|
let newestLegacyId = null;
|
|
15675
15729
|
let newestTitle = null;
|
|
@@ -15694,9 +15748,9 @@ function resolveWikiMirrorPath(directory, preferredFilename, matchesLegacyId, ma
|
|
|
15694
15748
|
}
|
|
15695
15749
|
function resolveWikiMemoryMirror(wikiDir, topicId, topicTitle) {
|
|
15696
15750
|
const briefFile = resolveWikiMirrorPath(join29(wikiDir, "topic"), `${wikiBriefStorageKey(topicTitle, topicId)}.md`, (filename) => isTopicBriefFile(filename, topicId), (filename) => isTopicBriefFile(filename, topicId, topicTitle));
|
|
15697
|
-
const hasBriefFile =
|
|
15751
|
+
const hasBriefFile = existsSync20(briefFile) && statSync10(briefFile).isFile();
|
|
15698
15752
|
const latestSummaryCandidate = resolveWikiMirrorPath(join29(wikiDir, "summaries"), `__missing__-${wikiSummaryFilename("0000-00-00", topicTitle, topicId)}`, (filename) => isTopicSummaryFile(filename, topicId), (filename) => isTopicSummaryFile(filename, topicId, topicTitle), false);
|
|
15699
|
-
const latestSummaryFile =
|
|
15753
|
+
const latestSummaryFile = existsSync20(latestSummaryCandidate) && statSync10(latestSummaryCandidate).isFile() ? latestSummaryCandidate : null;
|
|
15700
15754
|
return { briefFile, hasBriefFile, latestSummaryFile };
|
|
15701
15755
|
}
|
|
15702
15756
|
async function streamAgentEvents(topicId, topicTitle, queryId, events, control, agentType, model, effort, userId, retryableSessionExpired = true, onSessionId, execution) {
|
|
@@ -16892,7 +16946,7 @@ __export(exports_auth_check, {
|
|
|
16892
16946
|
checkAgentAuth: () => checkAgentAuth
|
|
16893
16947
|
});
|
|
16894
16948
|
import { execFileSync as execFileSync7 } from "child_process";
|
|
16895
|
-
import { existsSync as
|
|
16949
|
+
import { existsSync as existsSync21 } from "fs";
|
|
16896
16950
|
import { homedir as homedir8, platform } from "os";
|
|
16897
16951
|
import { join as join30 } from "path";
|
|
16898
16952
|
function hasMaestroCredential(host, key, userId) {
|
|
@@ -16965,7 +17019,7 @@ var init_auth_check = __esm(async () => {
|
|
|
16965
17019
|
await init_vault();
|
|
16966
17020
|
defaultAgentAuthHost = {
|
|
16967
17021
|
codexAuthFilePath,
|
|
16968
|
-
exists:
|
|
17022
|
+
exists: existsSync21,
|
|
16969
17023
|
environment: process.env,
|
|
16970
17024
|
homeDirectory: homedir8,
|
|
16971
17025
|
operatingSystem: platform,
|
|
@@ -18196,25 +18250,238 @@ import { AsyncLocalStorage } from "async_hooks";
|
|
|
18196
18250
|
import { randomUUID } from "crypto";
|
|
18197
18251
|
import {
|
|
18198
18252
|
closeSync,
|
|
18199
|
-
existsSync as
|
|
18253
|
+
existsSync as existsSync3,
|
|
18200
18254
|
mkdirSync as mkdirSync2,
|
|
18201
18255
|
openSync,
|
|
18202
18256
|
readdirSync,
|
|
18203
|
-
readFileSync as
|
|
18257
|
+
readFileSync as readFileSync3,
|
|
18204
18258
|
renameSync,
|
|
18205
18259
|
statSync,
|
|
18206
|
-
unlinkSync,
|
|
18260
|
+
unlinkSync as unlinkSync2,
|
|
18207
18261
|
writeFileSync as writeFileSync2
|
|
18208
18262
|
} from "fs";
|
|
18209
18263
|
import { basename, dirname as dirname2, join as join2, relative, resolve as resolve2 } from "path";
|
|
18210
|
-
init_config();
|
|
18211
|
-
init_wiki_summary_names();
|
|
18212
18264
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
18213
18265
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
18214
18266
|
import {
|
|
18215
18267
|
CallToolRequestSchema,
|
|
18216
18268
|
ListToolsRequestSchema
|
|
18217
18269
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
18270
|
+
|
|
18271
|
+
// ../../packages/core/src/mcp/wiki-search-index.ts
|
|
18272
|
+
await init_sqlite();
|
|
18273
|
+
import { chmodSync, existsSync, readFileSync, unlinkSync } from "fs";
|
|
18274
|
+
var SEARCH_INDEX_SCHEMA_VERSION = 3;
|
|
18275
|
+
function documentId(source) {
|
|
18276
|
+
return `${source.kind}:${source.key}`;
|
|
18277
|
+
}
|
|
18278
|
+
function ensureSchema(database) {
|
|
18279
|
+
const version = database.query("PRAGMA user_version").get()?.user_version;
|
|
18280
|
+
if (version !== 0 && version !== SEARCH_INDEX_SCHEMA_VERSION) {
|
|
18281
|
+
throw new Error(`Unsupported wiki search index schema: ${version}`);
|
|
18282
|
+
}
|
|
18283
|
+
database.exec(`
|
|
18284
|
+
CREATE TABLE IF NOT EXISTS wiki_search_documents (
|
|
18285
|
+
id TEXT PRIMARY KEY,
|
|
18286
|
+
kind TEXT NOT NULL,
|
|
18287
|
+
key TEXT NOT NULL,
|
|
18288
|
+
path TEXT NOT NULL,
|
|
18289
|
+
mtime_ms REAL NOT NULL,
|
|
18290
|
+
size INTEGER NOT NULL,
|
|
18291
|
+
title TEXT NOT NULL,
|
|
18292
|
+
text TEXT NOT NULL,
|
|
18293
|
+
date TEXT,
|
|
18294
|
+
family TEXT
|
|
18295
|
+
);
|
|
18296
|
+
CREATE UNIQUE INDEX IF NOT EXISTS wiki_search_documents_kind_key
|
|
18297
|
+
ON wiki_search_documents(kind, key);
|
|
18298
|
+
CREATE INDEX IF NOT EXISTS wiki_search_documents_kind_date
|
|
18299
|
+
ON wiki_search_documents(kind, date);
|
|
18300
|
+
CREATE INDEX IF NOT EXISTS wiki_search_documents_kind_family_date
|
|
18301
|
+
ON wiki_search_documents(kind, family, date);
|
|
18302
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS wiki_search_fts USING fts5(
|
|
18303
|
+
document_id UNINDEXED,
|
|
18304
|
+
kind UNINDEXED,
|
|
18305
|
+
tokens,
|
|
18306
|
+
tokenize = 'unicode61'
|
|
18307
|
+
);
|
|
18308
|
+
PRAGMA user_version = ${SEARCH_INDEX_SCHEMA_VERSION};
|
|
18309
|
+
`);
|
|
18310
|
+
}
|
|
18311
|
+
|
|
18312
|
+
class WikiSearchIndex {
|
|
18313
|
+
path;
|
|
18314
|
+
#database;
|
|
18315
|
+
constructor(path) {
|
|
18316
|
+
this.path = path;
|
|
18317
|
+
this.#database = new Database(path, { create: true });
|
|
18318
|
+
try {
|
|
18319
|
+
this.#database.exec("PRAGMA foreign_keys = ON; PRAGMA journal_mode = DELETE;");
|
|
18320
|
+
ensureSchema(this.#database);
|
|
18321
|
+
chmodSync(path, 384);
|
|
18322
|
+
} catch (error) {
|
|
18323
|
+
this.#database.close();
|
|
18324
|
+
throw error;
|
|
18325
|
+
}
|
|
18326
|
+
}
|
|
18327
|
+
close() {
|
|
18328
|
+
this.#database.close();
|
|
18329
|
+
}
|
|
18330
|
+
upsert(source, document) {
|
|
18331
|
+
const id = documentId(source);
|
|
18332
|
+
const apply = this.#database.transaction(() => {
|
|
18333
|
+
this.#database.query("DELETE FROM wiki_search_fts WHERE document_id = ?").run(id);
|
|
18334
|
+
this.#database.query("DELETE FROM wiki_search_documents WHERE id = ?").run(id);
|
|
18335
|
+
this.#database.query(`
|
|
18336
|
+
INSERT INTO wiki_search_documents
|
|
18337
|
+
(id, kind, key, path, mtime_ms, size, title, text, date, family)
|
|
18338
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
18339
|
+
`).run(id, source.kind, source.key, source.path, source.mtimeMs, source.size, document.title, document.text, document.date ?? null, document.family ?? null);
|
|
18340
|
+
this.#database.query("INSERT INTO wiki_search_fts(document_id, kind, tokens) VALUES (?, ?, ?)").run(id, source.kind, document.tokens.join(" "));
|
|
18341
|
+
});
|
|
18342
|
+
apply.immediate();
|
|
18343
|
+
}
|
|
18344
|
+
sync(sources, prepare) {
|
|
18345
|
+
const result = { added: 0, updated: 0, removed: 0 };
|
|
18346
|
+
const existingRows = this.#database.query("SELECT id, path, mtime_ms, size FROM wiki_search_documents ORDER BY id").all();
|
|
18347
|
+
const existing = new Map(existingRows.map((row) => [row.id, row]));
|
|
18348
|
+
const present = new Set;
|
|
18349
|
+
const changed = [];
|
|
18350
|
+
for (const source of sources) {
|
|
18351
|
+
const id = documentId(source);
|
|
18352
|
+
present.add(id);
|
|
18353
|
+
const stored = existing.get(id);
|
|
18354
|
+
if (stored && stored.path === source.path && stored.mtime_ms === source.mtimeMs && stored.size === source.size) {
|
|
18355
|
+
continue;
|
|
18356
|
+
}
|
|
18357
|
+
try {
|
|
18358
|
+
const text = readFileSync(source.path, "utf-8");
|
|
18359
|
+
changed.push({ source, document: prepare(source, text), added: !stored });
|
|
18360
|
+
} catch {}
|
|
18361
|
+
}
|
|
18362
|
+
const removed = existingRows.filter((row) => !present.has(row.id));
|
|
18363
|
+
const apply = this.#database.transaction(() => {
|
|
18364
|
+
const deleteTerms = this.#database.query("DELETE FROM wiki_search_fts WHERE document_id = ?");
|
|
18365
|
+
const deleteDocument = this.#database.query("DELETE FROM wiki_search_documents WHERE id = ?");
|
|
18366
|
+
const insertDocument = this.#database.query(`
|
|
18367
|
+
INSERT INTO wiki_search_documents
|
|
18368
|
+
(id, kind, key, path, mtime_ms, size, title, text, date, family)
|
|
18369
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
18370
|
+
`);
|
|
18371
|
+
const insertTerms = this.#database.query(`
|
|
18372
|
+
INSERT INTO wiki_search_fts(document_id, kind, tokens)
|
|
18373
|
+
VALUES (?, ?, ?)
|
|
18374
|
+
`);
|
|
18375
|
+
for (const row of removed) {
|
|
18376
|
+
deleteTerms.run(row.id);
|
|
18377
|
+
deleteDocument.run(row.id);
|
|
18378
|
+
result.removed += 1;
|
|
18379
|
+
}
|
|
18380
|
+
for (const { source, document, added } of changed) {
|
|
18381
|
+
const id = documentId(source);
|
|
18382
|
+
deleteTerms.run(id);
|
|
18383
|
+
deleteDocument.run(id);
|
|
18384
|
+
insertDocument.run(id, source.kind, source.key, source.path, source.mtimeMs, source.size, document.title, document.text, document.date ?? null, document.family ?? null);
|
|
18385
|
+
insertTerms.run(id, source.kind, document.tokens.join(" "));
|
|
18386
|
+
if (added)
|
|
18387
|
+
result.added += 1;
|
|
18388
|
+
else
|
|
18389
|
+
result.updated += 1;
|
|
18390
|
+
}
|
|
18391
|
+
});
|
|
18392
|
+
apply.immediate();
|
|
18393
|
+
return result;
|
|
18394
|
+
}
|
|
18395
|
+
metadata(kinds) {
|
|
18396
|
+
if (kinds.length === 0)
|
|
18397
|
+
return [];
|
|
18398
|
+
const placeholders = kinds.map(() => "?").join(", ");
|
|
18399
|
+
const rows = this.#database.query(`SELECT id, kind, key, title, date
|
|
18400
|
+
FROM wiki_search_documents
|
|
18401
|
+
WHERE kind IN (${placeholders})`).all(...kinds);
|
|
18402
|
+
return rows.map((row) => ({
|
|
18403
|
+
id: row.id,
|
|
18404
|
+
kind: row.kind,
|
|
18405
|
+
key: row.key,
|
|
18406
|
+
title: row.title,
|
|
18407
|
+
...row.date ? { date: row.date } : {}
|
|
18408
|
+
}));
|
|
18409
|
+
}
|
|
18410
|
+
summaryMetadataByDate(query) {
|
|
18411
|
+
const conditions = ["kind = 'summary'", "date IS NOT NULL"];
|
|
18412
|
+
const parameters = [];
|
|
18413
|
+
if (query.year && query.month) {
|
|
18414
|
+
const month = Number(query.month);
|
|
18415
|
+
const nextYear = month === 12 ? String(Number(query.year) + 1) : query.year;
|
|
18416
|
+
const nextMonth = String(month === 12 ? 1 : month + 1).padStart(2, "0");
|
|
18417
|
+
conditions.push("date >= ?", "date < ?");
|
|
18418
|
+
parameters.push(`${query.year}-${query.month}-01`, `${nextYear}-${nextMonth}-01`);
|
|
18419
|
+
} else if (query.year) {
|
|
18420
|
+
conditions.push("date >= ?", "date < ?");
|
|
18421
|
+
parameters.push(`${query.year}-01-01`, `${Number(query.year) + 1}-01-01`);
|
|
18422
|
+
} else if (query.month) {
|
|
18423
|
+
conditions.push("substr(date, 6, 2) = ?");
|
|
18424
|
+
parameters.push(query.month);
|
|
18425
|
+
}
|
|
18426
|
+
parameters.push(query.limit);
|
|
18427
|
+
const rows = this.#database.query(`SELECT id, kind, key, title, date
|
|
18428
|
+
FROM wiki_search_documents
|
|
18429
|
+
WHERE ${conditions.join(" AND ")}
|
|
18430
|
+
ORDER BY date ${query.direction === "oldest" ? "ASC" : "DESC"}, key ASC
|
|
18431
|
+
LIMIT ?`).all(...parameters);
|
|
18432
|
+
return rows.map((row) => ({
|
|
18433
|
+
id: row.id,
|
|
18434
|
+
kind: row.kind,
|
|
18435
|
+
key: row.key,
|
|
18436
|
+
title: row.title,
|
|
18437
|
+
...row.date ? { date: row.date } : {}
|
|
18438
|
+
}));
|
|
18439
|
+
}
|
|
18440
|
+
matchingDocumentIds(kinds, terms) {
|
|
18441
|
+
if (kinds.length === 0 || terms.length === 0)
|
|
18442
|
+
return new Set;
|
|
18443
|
+
const kindPlaceholders = kinds.map(() => "?").join(", ");
|
|
18444
|
+
const match = terms.map((term) => `"${term.replaceAll('"', '""')}"`).join(" OR ");
|
|
18445
|
+
const rows = this.#database.query(`SELECT DISTINCT document_id
|
|
18446
|
+
FROM wiki_search_fts
|
|
18447
|
+
WHERE wiki_search_fts MATCH ? AND kind IN (${kindPlaceholders})`).all(match, ...kinds);
|
|
18448
|
+
return new Set(rows.map((row) => row.document_id));
|
|
18449
|
+
}
|
|
18450
|
+
documents(ids) {
|
|
18451
|
+
if (ids.size === 0)
|
|
18452
|
+
return [];
|
|
18453
|
+
const values = [...ids];
|
|
18454
|
+
const rows = [];
|
|
18455
|
+
for (let offset = 0;offset < values.length; offset += 500) {
|
|
18456
|
+
const chunk = values.slice(offset, offset + 500);
|
|
18457
|
+
const placeholders = chunk.map(() => "?").join(", ");
|
|
18458
|
+
rows.push(...this.#database.query(`SELECT id, kind, key, path, title, text, date
|
|
18459
|
+
FROM wiki_search_documents
|
|
18460
|
+
WHERE id IN (${placeholders})`).all(...chunk));
|
|
18461
|
+
}
|
|
18462
|
+
return rows.map((row) => ({
|
|
18463
|
+
id: row.id,
|
|
18464
|
+
kind: row.kind,
|
|
18465
|
+
key: row.key,
|
|
18466
|
+
path: row.path,
|
|
18467
|
+
title: row.title,
|
|
18468
|
+
text: row.text,
|
|
18469
|
+
tokens: [],
|
|
18470
|
+
...row.date ? { date: row.date } : {}
|
|
18471
|
+
}));
|
|
18472
|
+
}
|
|
18473
|
+
}
|
|
18474
|
+
function resetCorruptWikiSearchIndex(path) {
|
|
18475
|
+
for (const candidate of [path, `${path}-journal`, `${path}-wal`, `${path}-shm`]) {
|
|
18476
|
+
if (!existsSync(candidate))
|
|
18477
|
+
continue;
|
|
18478
|
+
unlinkSync(candidate);
|
|
18479
|
+
}
|
|
18480
|
+
}
|
|
18481
|
+
|
|
18482
|
+
// ../../packages/core/src/mcp/wiki-server.ts
|
|
18483
|
+
init_config();
|
|
18484
|
+
init_wiki_summary_names();
|
|
18218
18485
|
var wikiRuntime = new AsyncLocalStorage;
|
|
18219
18486
|
function runtime() {
|
|
18220
18487
|
const current = wikiRuntime.getStore();
|
|
@@ -18241,15 +18508,15 @@ function acquireRecoveryGuard(lockPath) {
|
|
|
18241
18508
|
} catch (error) {
|
|
18242
18509
|
closeSync(fd);
|
|
18243
18510
|
try {
|
|
18244
|
-
|
|
18511
|
+
unlinkSync2(guardPath);
|
|
18245
18512
|
} catch {}
|
|
18246
18513
|
throw error;
|
|
18247
18514
|
}
|
|
18248
18515
|
return () => {
|
|
18249
18516
|
closeSync(fd);
|
|
18250
18517
|
try {
|
|
18251
|
-
if (
|
|
18252
|
-
|
|
18518
|
+
if (readFileSync3(guardPath, "utf-8") === ownerToken)
|
|
18519
|
+
unlinkSync2(guardPath);
|
|
18253
18520
|
} catch {}
|
|
18254
18521
|
};
|
|
18255
18522
|
} catch (error) {
|
|
@@ -18274,7 +18541,7 @@ function acquireFileLock(path) {
|
|
|
18274
18541
|
} catch (error) {
|
|
18275
18542
|
closeSync(fd);
|
|
18276
18543
|
try {
|
|
18277
|
-
|
|
18544
|
+
unlinkSync2(lockPath);
|
|
18278
18545
|
} catch {}
|
|
18279
18546
|
throw error;
|
|
18280
18547
|
}
|
|
@@ -18282,8 +18549,8 @@ function acquireFileLock(path) {
|
|
|
18282
18549
|
closeSync(fd);
|
|
18283
18550
|
const releaseGuard = acquireRecoveryGuard(lockPath);
|
|
18284
18551
|
try {
|
|
18285
|
-
if (
|
|
18286
|
-
|
|
18552
|
+
if (readFileSync3(lockPath, "utf-8") === ownerToken)
|
|
18553
|
+
unlinkSync2(lockPath);
|
|
18287
18554
|
} catch {} finally {
|
|
18288
18555
|
releaseGuard();
|
|
18289
18556
|
}
|
|
@@ -18294,9 +18561,9 @@ function acquireFileLock(path) {
|
|
|
18294
18561
|
const releaseGuard = acquireRecoveryGuard(lockPath);
|
|
18295
18562
|
try {
|
|
18296
18563
|
try {
|
|
18297
|
-
const staleToken =
|
|
18298
|
-
if (Date.now() - statSync(lockPath).mtimeMs > FILE_LOCK_STALE_MS &&
|
|
18299
|
-
|
|
18564
|
+
const staleToken = readFileSync3(lockPath, "utf-8");
|
|
18565
|
+
if (Date.now() - statSync(lockPath).mtimeMs > FILE_LOCK_STALE_MS && readFileSync3(lockPath, "utf-8") === staleToken) {
|
|
18566
|
+
unlinkSync2(lockPath);
|
|
18300
18567
|
continue;
|
|
18301
18568
|
}
|
|
18302
18569
|
} catch {
|
|
@@ -18319,7 +18586,7 @@ function atomicWriteFile(path, content) {
|
|
|
18319
18586
|
renameSync(temporaryPath, path);
|
|
18320
18587
|
} catch (error) {
|
|
18321
18588
|
try {
|
|
18322
|
-
|
|
18589
|
+
unlinkSync2(temporaryPath);
|
|
18323
18590
|
} catch {}
|
|
18324
18591
|
throw error;
|
|
18325
18592
|
}
|
|
@@ -18506,10 +18773,91 @@ function trigramSimilarity(left, right) {
|
|
|
18506
18773
|
overlap += 1;
|
|
18507
18774
|
return 2 * overlap / (a.size + b.size);
|
|
18508
18775
|
}
|
|
18776
|
+
var WIKI_SEARCH_INDEX_FILENAME = ".wiki-search-index.sqlite";
|
|
18777
|
+
function openWikiSearchIndex() {
|
|
18778
|
+
const path = resolve2(runtime().wikiDir, WIKI_SEARCH_INDEX_FILENAME);
|
|
18779
|
+
try {
|
|
18780
|
+
return new WikiSearchIndex(path);
|
|
18781
|
+
} catch (error) {
|
|
18782
|
+
if (!/malformed|not a database|schema/i.test(String(error)))
|
|
18783
|
+
return;
|
|
18784
|
+
try {
|
|
18785
|
+
resetCorruptWikiSearchIndex(path);
|
|
18786
|
+
return new WikiSearchIndex(path);
|
|
18787
|
+
} catch {
|
|
18788
|
+
return;
|
|
18789
|
+
}
|
|
18790
|
+
}
|
|
18791
|
+
}
|
|
18792
|
+
function prepareWikiSearchDocument(kind, key, text) {
|
|
18793
|
+
const titleLine = text.split(`
|
|
18794
|
+
`).find((line) => /^#+\s*/.test(line)) ?? "";
|
|
18795
|
+
const title = titleLine ? titleLine.replace(/^#+\s*/, "") : basename(key);
|
|
18796
|
+
return {
|
|
18797
|
+
title,
|
|
18798
|
+
text,
|
|
18799
|
+
tokens: canonicalSearchTokens(`${key} ${title} ${text}`),
|
|
18800
|
+
...kind === "summary" && /^\d{4}-\d{2}-\d{2}/.test(key) ? { date: key.slice(0, 10), family: summaryTopicIdentity(key) } : {}
|
|
18801
|
+
};
|
|
18802
|
+
}
|
|
18803
|
+
function indexWikiSearchDocument(kind, key, text) {
|
|
18804
|
+
const root = kind === "article" ? runtime().articlesDir : runtime().summariesDir;
|
|
18805
|
+
const path = resolve2(root, `${key}.md`);
|
|
18806
|
+
const index = openWikiSearchIndex();
|
|
18807
|
+
if (!index)
|
|
18808
|
+
return false;
|
|
18809
|
+
try {
|
|
18810
|
+
const stat = statSync(path);
|
|
18811
|
+
index.upsert({ kind, key, path, mtimeMs: stat.mtimeMs, size: stat.size }, prepareWikiSearchDocument(kind, key, text));
|
|
18812
|
+
return true;
|
|
18813
|
+
} catch {
|
|
18814
|
+
return false;
|
|
18815
|
+
} finally {
|
|
18816
|
+
index.close();
|
|
18817
|
+
}
|
|
18818
|
+
}
|
|
18819
|
+
var WIKI_INDEX_FILENAMES = {
|
|
18820
|
+
article: "article-index.md",
|
|
18821
|
+
summary: "summary-index.md",
|
|
18822
|
+
topic: "topic-index.md",
|
|
18823
|
+
skill: "skill-index.md"
|
|
18824
|
+
};
|
|
18825
|
+
var WIKI_INDEX_NAMESPACES = {
|
|
18826
|
+
article: "articles",
|
|
18827
|
+
summary: "summaries",
|
|
18828
|
+
topic: "topic",
|
|
18829
|
+
skill: "skills"
|
|
18830
|
+
};
|
|
18831
|
+
function wikiIndexPath(kind) {
|
|
18832
|
+
return resolve2(runtime().wikiDir, WIKI_INDEX_FILENAMES[kind]);
|
|
18833
|
+
}
|
|
18834
|
+
var MAX_INDEX_DESCRIPTION_LENGTH = 400;
|
|
18835
|
+
function normalizeIndexDescription(raw) {
|
|
18836
|
+
const description = raw.replaceAll(/\s+/g, " ").trim();
|
|
18837
|
+
if (!description)
|
|
18838
|
+
return { error: "A non-empty one-line description is required." };
|
|
18839
|
+
if (description.length > MAX_INDEX_DESCRIPTION_LENGTH) {
|
|
18840
|
+
return {
|
|
18841
|
+
error: `Description must be at most ${MAX_INDEX_DESCRIPTION_LENGTH} characters (got ${description.length}).`
|
|
18842
|
+
};
|
|
18843
|
+
}
|
|
18844
|
+
return { description };
|
|
18845
|
+
}
|
|
18846
|
+
function normalizeWikiSlug(raw) {
|
|
18847
|
+
const slug = raw.trim().replace(/\.md$/i, "").replace(/^\/+/, "");
|
|
18848
|
+
if (!slug)
|
|
18849
|
+
return { error: "A non-empty slug is required." };
|
|
18850
|
+
if (/[[\]|\\]/.test(slug))
|
|
18851
|
+
return { error: "Slug must not contain [ ] | or backslashes." };
|
|
18852
|
+
if (slug.split("/").some((segment) => segment === "" || segment === "." || segment === "..")) {
|
|
18853
|
+
return { error: "Slug must not contain empty or relative path segments." };
|
|
18854
|
+
}
|
|
18855
|
+
return { slug };
|
|
18856
|
+
}
|
|
18509
18857
|
function parseWikiIndex(path) {
|
|
18510
18858
|
let text;
|
|
18511
18859
|
try {
|
|
18512
|
-
text =
|
|
18860
|
+
text = readFileSync3(path, "utf-8");
|
|
18513
18861
|
} catch {
|
|
18514
18862
|
return [];
|
|
18515
18863
|
}
|
|
@@ -18663,7 +19011,7 @@ function wikiQuery(args) {
|
|
|
18663
19011
|
continue;
|
|
18664
19012
|
const fp = join2(sub, f.name);
|
|
18665
19013
|
try {
|
|
18666
|
-
const text =
|
|
19014
|
+
const text = readFileSync3(fp, "utf-8");
|
|
18667
19015
|
const key = `${entry.name}/${f.name.replace(/\.md$/i, "")}`;
|
|
18668
19016
|
scored.push({
|
|
18669
19017
|
kind: label === "articles" ? "article" : "skill",
|
|
@@ -18684,7 +19032,7 @@ function wikiQuery(args) {
|
|
|
18684
19032
|
}
|
|
18685
19033
|
const fp = join2(dir, entry.name);
|
|
18686
19034
|
try {
|
|
18687
|
-
const text =
|
|
19035
|
+
const text = readFileSync3(fp, "utf-8");
|
|
18688
19036
|
const key = entry.name.replace(/\.md$/i, "");
|
|
18689
19037
|
const resultKind = label === "articles" ? "article" : label === "topic" ? "topic" : label === "summaries" ? "summary" : "skill";
|
|
18690
19038
|
scored.push({
|
|
@@ -18798,14 +19146,45 @@ function wikiQuery(args) {
|
|
|
18798
19146
|
return 0;
|
|
18799
19147
|
return score;
|
|
18800
19148
|
}
|
|
18801
|
-
|
|
18802
|
-
|
|
19149
|
+
const bodyKinds = [
|
|
19150
|
+
...kind === "all" || kind === "article" ? ["article"] : [],
|
|
19151
|
+
...kind === "all" || kind === "summary" ? ["summary"] : []
|
|
19152
|
+
];
|
|
19153
|
+
if (bodyKinds.length > 0) {
|
|
19154
|
+
const searchIndex = openWikiSearchIndex();
|
|
19155
|
+
if (searchIndex) {
|
|
19156
|
+
try {
|
|
19157
|
+
const terms = canonicalSearchTokens(normalizedQuery);
|
|
19158
|
+
const ids = searchIndex.matchingDocumentIds(bodyKinds, terms);
|
|
19159
|
+
if (temporalDirection && bodyKinds.includes("summary")) {
|
|
19160
|
+
for (const item of searchIndex.summaryMetadataByDate({
|
|
19161
|
+
direction: temporalDirection === "newest" ? "latest" : "oldest",
|
|
19162
|
+
limit
|
|
19163
|
+
})) {
|
|
19164
|
+
ids.add(item.id);
|
|
19165
|
+
}
|
|
19166
|
+
}
|
|
19167
|
+
for (const document of searchIndex.documents(ids)) {
|
|
19168
|
+
scored.push({
|
|
19169
|
+
kind: document.kind,
|
|
19170
|
+
key: document.key,
|
|
19171
|
+
keyScore: scoreIndexKey(question, document.key),
|
|
19172
|
+
score: scoreMatch(document.text, document.key, document.kind),
|
|
19173
|
+
path: `${document.kind === "article" ? "articles" : "summaries"}/${document.key}.md`,
|
|
19174
|
+
text: document.text,
|
|
19175
|
+
title: document.title,
|
|
19176
|
+
...document.date ? { date: document.date } : {}
|
|
19177
|
+
});
|
|
19178
|
+
}
|
|
19179
|
+
} catch {} finally {
|
|
19180
|
+
searchIndex.close();
|
|
19181
|
+
}
|
|
19182
|
+
}
|
|
19183
|
+
}
|
|
18803
19184
|
if (kind === "all" && runtime().surface === "all")
|
|
18804
19185
|
scan(runtime().skillsDir, "skills");
|
|
18805
19186
|
if (kind === "all" || kind === "topic")
|
|
18806
19187
|
scan(runtime().topicsDir, "topic");
|
|
18807
|
-
if (kind === "all" || kind === "summary")
|
|
18808
|
-
scan(runtime().summariesDir, "summaries");
|
|
18809
19188
|
const merged = new Map;
|
|
18810
19189
|
for (const { candidate, keyScore, score } of indexCandidates) {
|
|
18811
19190
|
merged.set(`${candidate.kind}:${candidate.key}`, {
|
|
@@ -18937,7 +19316,7 @@ function wikiTopicBrief(args) {
|
|
|
18937
19316
|
const topicKey = wikiSummarySlug(rawTopic.replace(/^topic\//, "").replace(/\.md$/i, ""));
|
|
18938
19317
|
const filePath = resolve2(runtime().topicsDir, `${topicKey}.md`);
|
|
18939
19318
|
try {
|
|
18940
|
-
const content =
|
|
19319
|
+
const content = readFileSync3(filePath, "utf-8");
|
|
18941
19320
|
return {
|
|
18942
19321
|
content: [{ type: "text", text: `# Topic Brief: ${topicKey}
|
|
18943
19322
|
|
|
@@ -18989,7 +19368,7 @@ Adopted topic memory: ${memoryKey}` }]
|
|
|
18989
19368
|
return { content: [{ type: "text", text: "Invalid wiki document key." }], isError: true };
|
|
18990
19369
|
}
|
|
18991
19370
|
try {
|
|
18992
|
-
const content =
|
|
19371
|
+
const content = readFileSync3(filePath, "utf-8");
|
|
18993
19372
|
return {
|
|
18994
19373
|
content: [{ type: "text", text: `# Wiki ${kind}: ${key}
|
|
18995
19374
|
|
|
@@ -19009,18 +19388,18 @@ function wikiLastConversation(args) {
|
|
|
19009
19388
|
const name = slugify(topicNameFrom(rawTopic));
|
|
19010
19389
|
const archiveDir = resolve2(runtime().archiveDir, name);
|
|
19011
19390
|
try {
|
|
19012
|
-
let files =
|
|
19391
|
+
let files = existsSync3(archiveDir) ? readdirSync(archiveDir).filter((f) => f.endsWith(".jsonl")).sort().reverse() : [];
|
|
19013
19392
|
if (files.length === 0) {
|
|
19014
|
-
files =
|
|
19393
|
+
files = existsSync3(runtime().archiveDir) ? readdirSync(runtime().archiveDir).filter((f) => f.startsWith(name) && f.endsWith(".jsonl")).sort().reverse() : [];
|
|
19015
19394
|
}
|
|
19016
19395
|
if (files.length === 0) {
|
|
19017
19396
|
return {
|
|
19018
19397
|
content: [{ type: "text", text: `No archive found for topic: ${rawTopic}` }]
|
|
19019
19398
|
};
|
|
19020
19399
|
}
|
|
19021
|
-
const actualPath = files[0].includes("/") ? files[0] : resolve2(
|
|
19400
|
+
const actualPath = files[0].includes("/") ? files[0] : resolve2(existsSync3(archiveDir) && readdirSync(archiveDir).includes(files[0]) ? archiveDir : runtime().archiveDir, files[0]);
|
|
19022
19401
|
try {
|
|
19023
|
-
const raw =
|
|
19402
|
+
const raw = readFileSync3(actualPath, "utf-8");
|
|
19024
19403
|
const lines = raw.trim().split(`
|
|
19025
19404
|
`).filter(Boolean);
|
|
19026
19405
|
const turns2 = [];
|
|
@@ -19093,7 +19472,7 @@ function skillQuery(args) {
|
|
|
19093
19472
|
continue;
|
|
19094
19473
|
const skillFile = resolve2(runtime().skillsDir, entry.name, "skill.md");
|
|
19095
19474
|
try {
|
|
19096
|
-
const text =
|
|
19475
|
+
const text = readFileSync3(skillFile, "utf-8");
|
|
19097
19476
|
const lower = text.toLowerCase();
|
|
19098
19477
|
let score = 0;
|
|
19099
19478
|
for (const w of query.split(/\s+/).filter(Boolean)) {
|
|
@@ -19164,7 +19543,7 @@ ${fresh.join(`
|
|
|
19164
19543
|
const skillPath = resolve2(skillDir, "skill.md");
|
|
19165
19544
|
let finalContent = content;
|
|
19166
19545
|
try {
|
|
19167
|
-
const existing =
|
|
19546
|
+
const existing = readFileSync3(skillPath, "utf-8");
|
|
19168
19547
|
finalContent = mergeGotchas(content, extractGotchas(existing));
|
|
19169
19548
|
} catch {}
|
|
19170
19549
|
writeFileSync2(skillPath, finalContent, "utf-8");
|
|
@@ -19177,15 +19556,7 @@ ${fresh.join(`
|
|
|
19177
19556
|
]
|
|
19178
19557
|
};
|
|
19179
19558
|
}
|
|
19180
|
-
function
|
|
19181
|
-
const rawTopic = safeExt(args, ["topic", "topicName"], "");
|
|
19182
|
-
const content = safeExt(args, ["content", "text", "body"], "");
|
|
19183
|
-
if (!rawTopic)
|
|
19184
|
-
return { content: [{ type: "text", text: "Missing topic." }] };
|
|
19185
|
-
if (!content)
|
|
19186
|
-
return { content: [{ type: "text", text: "Missing content." }] };
|
|
19187
|
-
const now = new Date;
|
|
19188
|
-
const dateStr = now.toISOString().slice(0, 10);
|
|
19559
|
+
function writeSummaryDocument(rawTopic, content, dateStr) {
|
|
19189
19560
|
const topicId = runtime().topicId;
|
|
19190
19561
|
const fileSlug = wikiBriefStorageKey(rawTopic, topicId);
|
|
19191
19562
|
ensureDir(runtime().summariesDir);
|
|
@@ -19212,7 +19583,7 @@ function saveWikiEntry(args) {
|
|
|
19212
19583
|
if (topicId && setTopicBrief) {
|
|
19213
19584
|
try {
|
|
19214
19585
|
const briefPath = resolve2(runtime().topicsDir, `${fileSlug}.md`);
|
|
19215
|
-
let briefMd =
|
|
19586
|
+
let briefMd = existsSync3(briefPath) ? readFileSync3(briefPath, "utf-8") : undefined;
|
|
19216
19587
|
if (briefMd === undefined && getTopicBrief && !getTopicBrief(fileSlug)?.briefMd) {
|
|
19217
19588
|
const legacy = getTopicBrief(topicId)?.briefMd;
|
|
19218
19589
|
if (legacy)
|
|
@@ -19226,28 +19597,14 @@ function saveWikiEntry(args) {
|
|
|
19226
19597
|
sqliteUpdated = true;
|
|
19227
19598
|
} catch {}
|
|
19228
19599
|
}
|
|
19229
|
-
return {
|
|
19230
|
-
content: [
|
|
19231
|
-
{
|
|
19232
|
-
type: "text",
|
|
19233
|
-
text: `Saved summary: summaries/${summaryName}` + (sqliteUpdated ? `
|
|
19234
|
-
SQLite latest-summary also updated.` : "")
|
|
19235
|
-
}
|
|
19236
|
-
]
|
|
19237
|
-
};
|
|
19600
|
+
return { slug: summaryName.replace(/\.md$/i, ""), sqliteUpdated };
|
|
19238
19601
|
}
|
|
19239
|
-
function
|
|
19240
|
-
const rawTopic = safeExt(args, ["topic", "topicName"], "");
|
|
19241
|
-
const content = safeExt(args, ["content", "brief", "text", "body"], "");
|
|
19242
|
-
if (!rawTopic)
|
|
19243
|
-
return { content: [{ type: "text", text: "Missing topic." }] };
|
|
19244
|
-
if (!content)
|
|
19245
|
-
return { content: [{ type: "text", text: "Missing content." }] };
|
|
19602
|
+
function writeTopicDocument(rawTopic, content) {
|
|
19246
19603
|
const topicId = runtime().topicId;
|
|
19247
19604
|
const fileSlug = wikiBriefStorageKey(rawTopic, topicId);
|
|
19248
19605
|
const briefPath = resolve2(runtime().topicsDir, `${fileSlug}.md`);
|
|
19249
19606
|
ensureDir(dirname2(briefPath));
|
|
19250
|
-
const existed =
|
|
19607
|
+
const existed = existsSync3(briefPath);
|
|
19251
19608
|
writeFileSync2(briefPath, content, "utf-8");
|
|
19252
19609
|
const setTopicBrief = runtime().host.setTopicBrief;
|
|
19253
19610
|
let sqliteUpdated = false;
|
|
@@ -19257,68 +19614,228 @@ function saveTopicBrief(args) {
|
|
|
19257
19614
|
sqliteUpdated = true;
|
|
19258
19615
|
} catch {}
|
|
19259
19616
|
}
|
|
19617
|
+
return { slug: fileSlug, existed, sqliteUpdated };
|
|
19618
|
+
}
|
|
19619
|
+
function writeArticleDocument(slug, content) {
|
|
19620
|
+
const articlePath = resolve2(runtime().articlesDir, `${slug}.md`);
|
|
19621
|
+
ensureDir(dirname2(articlePath));
|
|
19622
|
+
const existed = existsSync3(articlePath);
|
|
19623
|
+
atomicWriteFile(articlePath, content);
|
|
19624
|
+
return { existed };
|
|
19625
|
+
}
|
|
19626
|
+
function wikiWrite(args) {
|
|
19627
|
+
const rawKind = safeExt(args, ["kind", "type"], "");
|
|
19628
|
+
const content = safeExt(args, ["content", "text", "body", "brief"], "");
|
|
19629
|
+
const rawDescription = safeExt(args, ["description", "desc"], "");
|
|
19630
|
+
const rawTopic = safeExt(args, ["topic", "topicName"], "");
|
|
19631
|
+
const rawSlug = safeExt(args, ["slug", "id"], "");
|
|
19632
|
+
const section = safeExt(args, ["section", "category"], undefined);
|
|
19633
|
+
const rawDate = safeExt(args, ["date", "created"], undefined);
|
|
19634
|
+
if (rawKind !== "summary" && rawKind !== "article" && rawKind !== "topic") {
|
|
19635
|
+
return {
|
|
19636
|
+
content: [{ type: "text", text: 'kind must be one of "summary", "article", "topic".' }],
|
|
19637
|
+
isError: true
|
|
19638
|
+
};
|
|
19639
|
+
}
|
|
19640
|
+
if (!content.trim()) {
|
|
19641
|
+
return { content: [{ type: "text", text: "Missing content." }], isError: true };
|
|
19642
|
+
}
|
|
19643
|
+
const descriptionResult = normalizeIndexDescription(rawDescription);
|
|
19644
|
+
if ("error" in descriptionResult) {
|
|
19645
|
+
return { content: [{ type: "text", text: descriptionResult.error }], isError: true };
|
|
19646
|
+
}
|
|
19647
|
+
const { description } = descriptionResult;
|
|
19648
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
19649
|
+
if (rawKind === "article") {
|
|
19650
|
+
const slugResult = normalizeWikiSlug(rawSlug);
|
|
19651
|
+
if ("error" in slugResult) {
|
|
19652
|
+
return { content: [{ type: "text", text: slugResult.error }], isError: true };
|
|
19653
|
+
}
|
|
19654
|
+
if (!section?.trim()) {
|
|
19655
|
+
return {
|
|
19656
|
+
content: [
|
|
19657
|
+
{ type: "text", text: "An article requires a section so the catalog stays navigable." }
|
|
19658
|
+
],
|
|
19659
|
+
isError: true
|
|
19660
|
+
};
|
|
19661
|
+
}
|
|
19662
|
+
const { existed } = writeArticleDocument(slugResult.slug, content);
|
|
19663
|
+
const link2 = indexRowOrPartialWrite("article", {
|
|
19664
|
+
kind: "article",
|
|
19665
|
+
slug: slugResult.slug,
|
|
19666
|
+
description,
|
|
19667
|
+
date: rawDate ?? today,
|
|
19668
|
+
section: section.trim()
|
|
19669
|
+
});
|
|
19670
|
+
if (typeof link2 !== "string")
|
|
19671
|
+
return link2;
|
|
19672
|
+
const searched = indexWikiSearchDocument("article", slugResult.slug, content);
|
|
19673
|
+
return {
|
|
19674
|
+
content: [
|
|
19675
|
+
{
|
|
19676
|
+
type: "text",
|
|
19677
|
+
text: `Saved article: articles/${slugResult.slug}.md (${existed ? "updated" : "created"})
|
|
19678
|
+
Indexed: ${link2}` + (searched ? "" : `
|
|
19679
|
+
${SEARCH_CACHE_SKIPPED_NOTE}`)
|
|
19680
|
+
}
|
|
19681
|
+
]
|
|
19682
|
+
};
|
|
19683
|
+
}
|
|
19684
|
+
const topic = rawTopic.trim();
|
|
19685
|
+
if (!topic) {
|
|
19686
|
+
return { content: [{ type: "text", text: "Missing topic." }], isError: true };
|
|
19687
|
+
}
|
|
19688
|
+
if (rawKind === "summary") {
|
|
19689
|
+
const dateStr = rawDate ?? today;
|
|
19690
|
+
const written2 = writeSummaryDocument(topic, content, dateStr);
|
|
19691
|
+
const link2 = indexRowOrPartialWrite("summary", {
|
|
19692
|
+
kind: "summary",
|
|
19693
|
+
slug: written2.slug,
|
|
19694
|
+
description,
|
|
19695
|
+
date: dateStr
|
|
19696
|
+
});
|
|
19697
|
+
if (typeof link2 !== "string")
|
|
19698
|
+
return link2;
|
|
19699
|
+
const searched = indexWikiSearchDocument("summary", written2.slug, content);
|
|
19700
|
+
return {
|
|
19701
|
+
content: [
|
|
19702
|
+
{
|
|
19703
|
+
type: "text",
|
|
19704
|
+
text: `Saved summary: summaries/${written2.slug}.md
|
|
19705
|
+
Indexed: ${link2}` + (written2.sqliteUpdated ? `
|
|
19706
|
+
SQLite latest-summary also updated.` : "") + (searched ? "" : `
|
|
19707
|
+
${SEARCH_CACHE_SKIPPED_NOTE}`)
|
|
19708
|
+
}
|
|
19709
|
+
]
|
|
19710
|
+
};
|
|
19711
|
+
}
|
|
19712
|
+
const written = writeTopicDocument(topic, content);
|
|
19713
|
+
const link = indexRowOrPartialWrite("topic", {
|
|
19714
|
+
kind: "topic",
|
|
19715
|
+
slug: written.slug,
|
|
19716
|
+
description,
|
|
19717
|
+
date: rawDate ?? today
|
|
19718
|
+
});
|
|
19719
|
+
if (typeof link !== "string")
|
|
19720
|
+
return link;
|
|
19260
19721
|
return {
|
|
19261
19722
|
content: [
|
|
19262
19723
|
{
|
|
19263
19724
|
type: "text",
|
|
19264
|
-
text: `Saved brief: topic/${
|
|
19725
|
+
text: `Saved brief: topic/${written.slug}.md (${written.existed ? "updated" : "created"})
|
|
19726
|
+
Indexed: ${link}` + (written.sqliteUpdated ? `
|
|
19265
19727
|
SQLite brief also updated.` : "")
|
|
19266
19728
|
}
|
|
19267
19729
|
]
|
|
19268
19730
|
};
|
|
19269
19731
|
}
|
|
19270
|
-
function
|
|
19271
|
-
const
|
|
19272
|
-
|
|
19273
|
-
|
|
19274
|
-
|
|
19275
|
-
|
|
19276
|
-
|
|
19277
|
-
|
|
19278
|
-
|
|
19279
|
-
|
|
19280
|
-
const
|
|
19281
|
-
|
|
19282
|
-
|
|
19283
|
-
|
|
19284
|
-
|
|
19285
|
-
|
|
19286
|
-
|
|
19732
|
+
function collectIndexableDocuments() {
|
|
19733
|
+
const sources = [];
|
|
19734
|
+
function add(kind, key, path) {
|
|
19735
|
+
try {
|
|
19736
|
+
const stat = statSync(path);
|
|
19737
|
+
if (!stat.isFile())
|
|
19738
|
+
return;
|
|
19739
|
+
sources.push({ kind, key, path, mtimeMs: stat.mtimeMs, size: stat.size });
|
|
19740
|
+
} catch {}
|
|
19741
|
+
}
|
|
19742
|
+
for (const [root, kind, allowSubdirectories] of [
|
|
19743
|
+
[runtime().articlesDir, "article", true],
|
|
19744
|
+
[runtime().summariesDir, "summary", false]
|
|
19745
|
+
]) {
|
|
19746
|
+
let entries;
|
|
19747
|
+
try {
|
|
19748
|
+
entries = readdirSync(root, { withFileTypes: true });
|
|
19749
|
+
} catch {
|
|
19750
|
+
continue;
|
|
19751
|
+
}
|
|
19752
|
+
for (const entry of entries) {
|
|
19753
|
+
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
19754
|
+
add(kind, entry.name.replace(/\.md$/i, ""), join2(root, entry.name));
|
|
19755
|
+
continue;
|
|
19756
|
+
}
|
|
19757
|
+
if (!entry.isDirectory() || !allowSubdirectories)
|
|
19758
|
+
continue;
|
|
19759
|
+
let nested;
|
|
19760
|
+
try {
|
|
19761
|
+
nested = readdirSync(join2(root, entry.name), { withFileTypes: true });
|
|
19762
|
+
} catch {
|
|
19763
|
+
continue;
|
|
19764
|
+
}
|
|
19765
|
+
for (const file of nested) {
|
|
19766
|
+
if (!file.isFile() || !file.name.endsWith(".md"))
|
|
19767
|
+
continue;
|
|
19768
|
+
add(kind, `${entry.name}/${file.name.replace(/\.md$/i, "")}`, join2(root, entry.name, file.name));
|
|
19769
|
+
}
|
|
19770
|
+
}
|
|
19771
|
+
}
|
|
19772
|
+
return sources;
|
|
19773
|
+
}
|
|
19774
|
+
function wikiReindex() {
|
|
19775
|
+
const documents = collectIndexableDocuments();
|
|
19776
|
+
const index = openWikiSearchIndex();
|
|
19777
|
+
if (!index) {
|
|
19778
|
+
return {
|
|
19779
|
+
content: [{ type: "text", text: "Could not open the wiki search index." }],
|
|
19780
|
+
isError: true
|
|
19781
|
+
};
|
|
19782
|
+
}
|
|
19783
|
+
let synced;
|
|
19784
|
+
try {
|
|
19785
|
+
synced = index.sync(documents, (source, text) => prepareWikiSearchDocument(source.kind, source.key, text));
|
|
19786
|
+
} catch (error) {
|
|
19787
|
+
return {
|
|
19788
|
+
content: [{ type: "text", text: `Failed to rebuild the search index: ${String(error)}` }],
|
|
19789
|
+
isError: true
|
|
19790
|
+
};
|
|
19791
|
+
} finally {
|
|
19792
|
+
index.close();
|
|
19793
|
+
}
|
|
19794
|
+
const lines = [
|
|
19795
|
+
`Search index: ${synced.added} added, ${synced.updated} updated, ${synced.removed} removed (${documents.length} documents).`
|
|
19796
|
+
];
|
|
19797
|
+
for (const kind of ["article", "summary"]) {
|
|
19798
|
+
const rows = new Set(parseWikiIndex(wikiIndexPath(kind)).filter((candidate) => candidate.kind === kind).map((candidate) => candidate.key));
|
|
19799
|
+
const keys = documents.filter((source) => source.kind === kind).map((source) => source.key);
|
|
19800
|
+
const unindexed = keys.filter((key) => !rows.has(key));
|
|
19801
|
+
const tombstones = [...rows].filter((key) => !keys.includes(key));
|
|
19802
|
+
lines.push(`${WIKI_INDEX_FILENAMES[kind]}: ${rows.size} rows for ${keys.length} documents` + (unindexed.length > 0 ? `; missing rows: ${unindexed.join(", ")}` : "") + (tombstones.length > 0 ? `; tombstones: ${tombstones.join(", ")}` : ""));
|
|
19803
|
+
}
|
|
19804
|
+
return { content: [{ type: "text", text: lines.join(`
|
|
19805
|
+
`) }] };
|
|
19806
|
+
}
|
|
19807
|
+
var SEARCH_CACHE_SKIPPED_NOTE = "Body-search cache was not updated; catalog retrieval still works. Run wiki_reindex to refill it.";
|
|
19808
|
+
function indexRowOrPartialWrite(label, options) {
|
|
19809
|
+
try {
|
|
19810
|
+
return upsertIndexRow(options);
|
|
19811
|
+
} catch (error) {
|
|
19812
|
+
return {
|
|
19813
|
+
content: [
|
|
19814
|
+
{
|
|
19815
|
+
type: "text",
|
|
19816
|
+
text: `Wrote the ${label} document but failed to index it (${String(error)}). Retry the same wiki_write call: both writes are idempotent.`
|
|
19817
|
+
}
|
|
19818
|
+
],
|
|
19819
|
+
isError: true
|
|
19820
|
+
};
|
|
19821
|
+
}
|
|
19822
|
+
}
|
|
19823
|
+
function upsertIndexRow(options) {
|
|
19824
|
+
const { kind, slug, description, date, section } = options;
|
|
19825
|
+
const indexPath = wikiIndexPath(kind);
|
|
19287
19826
|
ensureDir(dirname2(indexPath));
|
|
19288
19827
|
const releaseLock = acquireFileLock(indexPath);
|
|
19289
19828
|
try {
|
|
19290
19829
|
let index;
|
|
19291
19830
|
try {
|
|
19292
|
-
index =
|
|
19831
|
+
index = readFileSync3(indexPath, "utf-8");
|
|
19293
19832
|
} catch {
|
|
19294
19833
|
index = "";
|
|
19295
19834
|
}
|
|
19296
19835
|
const lines = index.split(`
|
|
19297
19836
|
`);
|
|
19298
|
-
const
|
|
19299
|
-
|
|
19300
|
-
case "summary":
|
|
19301
|
-
return `- [[summaries/${slug}]] ${desc} (${dateStr})`;
|
|
19302
|
-
case "topic":
|
|
19303
|
-
return `- [[topic/${slug}]] ${desc} (${dateStr})`;
|
|
19304
|
-
case "skill":
|
|
19305
|
-
return `- [[skills/${slug}]] ${desc} (${dateStr})`;
|
|
19306
|
-
default:
|
|
19307
|
-
return `- [[articles/${slug}]] ${desc} (${dateStr})`;
|
|
19308
|
-
}
|
|
19309
|
-
})();
|
|
19310
|
-
const target = (() => {
|
|
19311
|
-
switch (kind) {
|
|
19312
|
-
case "summary":
|
|
19313
|
-
return `summaries/${slug}`;
|
|
19314
|
-
case "topic":
|
|
19315
|
-
return `topic/${slug}`;
|
|
19316
|
-
case "skill":
|
|
19317
|
-
return `skills/${slug}`;
|
|
19318
|
-
default:
|
|
19319
|
-
return `articles/${slug}`;
|
|
19320
|
-
}
|
|
19321
|
-
})();
|
|
19837
|
+
const target = `${WIKI_INDEX_NAMESPACES[kind]}/${slug}`;
|
|
19838
|
+
const link = `- [[${target}]] ${description} (${date})`;
|
|
19322
19839
|
const slugPattern = `[[${target}]]`;
|
|
19323
19840
|
let replaced = false;
|
|
19324
19841
|
for (let i = lines.length - 1;i >= 0; i--) {
|
|
@@ -19356,11 +19873,63 @@ function indexUpsert(args) {
|
|
|
19356
19873
|
}
|
|
19357
19874
|
atomicWriteFile(indexPath, lines.join(`
|
|
19358
19875
|
`));
|
|
19359
|
-
return
|
|
19876
|
+
return link;
|
|
19360
19877
|
} finally {
|
|
19361
19878
|
releaseLock();
|
|
19362
19879
|
}
|
|
19363
19880
|
}
|
|
19881
|
+
function wikiDocumentExists(kind, slug) {
|
|
19882
|
+
const root = kind === "article" ? runtime().articlesDir : kind === "summary" ? runtime().summariesDir : kind === "topic" ? runtime().topicsDir : runtime().skillsDir;
|
|
19883
|
+
const filePath = resolve2(root, `${slug}.md`);
|
|
19884
|
+
if (relative(root, filePath).startsWith(".."))
|
|
19885
|
+
return false;
|
|
19886
|
+
try {
|
|
19887
|
+
return statSync(filePath).isFile();
|
|
19888
|
+
} catch {
|
|
19889
|
+
return false;
|
|
19890
|
+
}
|
|
19891
|
+
}
|
|
19892
|
+
function indexUpsert(args) {
|
|
19893
|
+
const rawSlug = safeExt(args, ["slug", "id"], "");
|
|
19894
|
+
const rawDescription = safeExt(args, ["description", "desc", "text"], "");
|
|
19895
|
+
const rawKind = safeExt(args, ["kind", "type"], "article");
|
|
19896
|
+
const section = safeExt(args, ["section", "category"], undefined);
|
|
19897
|
+
const date = safeExt(args, ["date", "created"], undefined);
|
|
19898
|
+
if (!(rawKind in WIKI_INDEX_FILENAMES)) {
|
|
19899
|
+
return {
|
|
19900
|
+
content: [{ type: "text", text: `Unsupported kind: ${rawKind}` }],
|
|
19901
|
+
isError: true
|
|
19902
|
+
};
|
|
19903
|
+
}
|
|
19904
|
+
const kind = rawKind;
|
|
19905
|
+
const slugResult = normalizeWikiSlug(rawSlug);
|
|
19906
|
+
if ("error" in slugResult) {
|
|
19907
|
+
return { content: [{ type: "text", text: slugResult.error }], isError: true };
|
|
19908
|
+
}
|
|
19909
|
+
const descriptionResult = normalizeIndexDescription(rawDescription);
|
|
19910
|
+
if ("error" in descriptionResult) {
|
|
19911
|
+
return { content: [{ type: "text", text: descriptionResult.error }], isError: true };
|
|
19912
|
+
}
|
|
19913
|
+
if (kind !== "topic" && !wikiDocumentExists(kind, slugResult.slug)) {
|
|
19914
|
+
return {
|
|
19915
|
+
content: [
|
|
19916
|
+
{
|
|
19917
|
+
type: "text",
|
|
19918
|
+
text: `No ${kind} document named ${slugResult.slug}. Use wiki_write to create the document and its catalog row together.`
|
|
19919
|
+
}
|
|
19920
|
+
],
|
|
19921
|
+
isError: true
|
|
19922
|
+
};
|
|
19923
|
+
}
|
|
19924
|
+
const link = upsertIndexRow({
|
|
19925
|
+
kind,
|
|
19926
|
+
slug: slugResult.slug,
|
|
19927
|
+
description: descriptionResult.description,
|
|
19928
|
+
date: date ?? new Date().toISOString().slice(0, 10),
|
|
19929
|
+
section
|
|
19930
|
+
});
|
|
19931
|
+
return { content: [{ type: "text", text: `Index updated: ${link}` }] };
|
|
19932
|
+
}
|
|
19364
19933
|
var WIKI_TOOLS = [
|
|
19365
19934
|
{
|
|
19366
19935
|
name: "wiki_query",
|
|
@@ -19442,35 +20011,46 @@ var WIKI_TOOLS = [
|
|
|
19442
20011
|
}
|
|
19443
20012
|
},
|
|
19444
20013
|
{
|
|
19445
|
-
name: "
|
|
19446
|
-
description: "
|
|
20014
|
+
name: "wiki_write",
|
|
20015
|
+
description: "Write a wiki document and its catalog row together. The only way to create a summary, article, or topic brief: summaries go to wiki/summaries/ + summary-index.md, articles to wiki/articles/ + article-index.md, briefs to wiki/topic/ + topic-index.md (also mirrored into SQLite for next-session injection). Never write wiki files by any other means.",
|
|
19447
20016
|
inputSchema: {
|
|
19448
20017
|
type: "object",
|
|
19449
20018
|
properties: {
|
|
19450
|
-
|
|
19451
|
-
|
|
20019
|
+
kind: {
|
|
20020
|
+
type: "string",
|
|
20021
|
+
enum: ["summary", "article", "topic"],
|
|
20022
|
+
description: "Which document to write"
|
|
20023
|
+
},
|
|
20024
|
+
content: { type: "string", description: "Document body in markdown" },
|
|
20025
|
+
description: {
|
|
20026
|
+
type: "string",
|
|
20027
|
+
description: "Single-line catalog description; required so the index stays useful"
|
|
20028
|
+
},
|
|
20029
|
+
topic: {
|
|
20030
|
+
type: "string",
|
|
20031
|
+
description: "Topic name; required for kind=summary and kind=topic"
|
|
20032
|
+
},
|
|
20033
|
+
slug: {
|
|
20034
|
+
type: "string",
|
|
20035
|
+
description: "Article slug in kebab-case; required for kind=article"
|
|
20036
|
+
},
|
|
20037
|
+
section: {
|
|
20038
|
+
type: "string",
|
|
20039
|
+
description: "H2 catalog section; required for kind=article"
|
|
20040
|
+
},
|
|
20041
|
+
date: { type: "string", description: "Override entry date YYYY-MM-DD (default: today)" }
|
|
19452
20042
|
},
|
|
19453
|
-
required: ["
|
|
20043
|
+
required: ["kind", "content", "description"]
|
|
19454
20044
|
}
|
|
19455
20045
|
},
|
|
19456
20046
|
{
|
|
19457
|
-
name: "
|
|
19458
|
-
description: "
|
|
19459
|
-
inputSchema: {
|
|
19460
|
-
type: "object",
|
|
19461
|
-
properties: {
|
|
19462
|
-
topic: { type: "string", description: "Topic name of the session" },
|
|
19463
|
-
content: {
|
|
19464
|
-
type: "string",
|
|
19465
|
-
description: "Full accumulated topic brief in markdown (persona layer + recent work)"
|
|
19466
|
-
}
|
|
19467
|
-
},
|
|
19468
|
-
required: ["topic", "content"]
|
|
19469
|
-
}
|
|
20047
|
+
name: "wiki_reindex",
|
|
20048
|
+
description: "Rebuild the derived body-search cache from the documents on disk and report catalog gaps. Run this once after adding documents outside wiki_write; retrieval itself never scans the wiki.",
|
|
20049
|
+
inputSchema: { type: "object", properties: {} }
|
|
19470
20050
|
},
|
|
19471
20051
|
{
|
|
19472
20052
|
name: "index_upsert",
|
|
19473
|
-
description: "
|
|
20053
|
+
description: "Correct the description or section of an entry that already exists. Cannot create an entry \u2014 use wiki_write for that.",
|
|
19474
20054
|
inputSchema: {
|
|
19475
20055
|
type: "object",
|
|
19476
20056
|
properties: {
|
|
@@ -19574,8 +20154,8 @@ function createWikiMcpServer(context, host) {
|
|
|
19574
20154
|
wiki_last_conversation: wikiLastConversation,
|
|
19575
20155
|
skill_query: skillQuery,
|
|
19576
20156
|
skill_save: skillSave,
|
|
19577
|
-
|
|
19578
|
-
|
|
20157
|
+
wiki_write: wikiWrite,
|
|
20158
|
+
wiki_reindex: wikiReindex,
|
|
19579
20159
|
index_upsert: indexUpsert
|
|
19580
20160
|
};
|
|
19581
20161
|
const handler = tools.some((tool) => tool.name === name) ? handlers[name] : undefined;
|
|
@@ -19593,8 +20173,8 @@ init_jsonl();
|
|
|
19593
20173
|
init_mcp_helpers();
|
|
19594
20174
|
await init_codex_registry();
|
|
19595
20175
|
import { spawn as spawn5 } from "child_process";
|
|
19596
|
-
import { existsSync as
|
|
19597
|
-
import { join as
|
|
20176
|
+
import { existsSync as existsSync10, readdirSync as readdirSync3 } from "fs";
|
|
20177
|
+
import { join as join11 } from "path";
|
|
19598
20178
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
19599
20179
|
import { z } from "zod";
|
|
19600
20180
|
function signalProcessTree(child, signal) {
|
|
@@ -19610,7 +20190,7 @@ function signalProcessTree(child, signal) {
|
|
|
19610
20190
|
}
|
|
19611
20191
|
}
|
|
19612
20192
|
function spawnCapture(cmd, args, timeoutMs, signal, env) {
|
|
19613
|
-
return new Promise((
|
|
20193
|
+
return new Promise((resolve8, reject) => {
|
|
19614
20194
|
const child = spawn5(cmd, args, {
|
|
19615
20195
|
env: env ?? process.env,
|
|
19616
20196
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -19668,7 +20248,7 @@ function spawnCapture(cmd, args, timeoutMs, signal, env) {
|
|
|
19668
20248
|
if (killTimer)
|
|
19669
20249
|
clearTimeout(killTimer);
|
|
19670
20250
|
if (code === 0)
|
|
19671
|
-
|
|
20251
|
+
resolve8({ stdout, stderr });
|
|
19672
20252
|
else
|
|
19673
20253
|
reject(new Error(stderr.trim() || `${cmd} exited with ${code ?? exitSignal}`));
|
|
19674
20254
|
});
|
|
@@ -19746,11 +20326,11 @@ async function checkMaestro(model, timeoutMs, signal) {
|
|
|
19746
20326
|
const remaining = deadline - Date.now();
|
|
19747
20327
|
if (remaining <= 0)
|
|
19748
20328
|
throw new Error("timeout");
|
|
19749
|
-
const eventResult = await new Promise((
|
|
20329
|
+
const eventResult = await new Promise((resolve8, reject) => {
|
|
19750
20330
|
const timeout = setTimeout(() => reject(new Error("timeout")), remaining);
|
|
19751
20331
|
const onAbort = () => reject(new Error("aborted"));
|
|
19752
20332
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
19753
|
-
activeIterator.next().then(
|
|
20333
|
+
activeIterator.next().then(resolve8, reject).finally(() => {
|
|
19754
20334
|
clearTimeout(timeout);
|
|
19755
20335
|
signal.removeEventListener("abort", onAbort);
|
|
19756
20336
|
});
|
|
@@ -19789,7 +20369,7 @@ var checkWaiters = [];
|
|
|
19789
20369
|
var activeCheckAllUsers = new Set;
|
|
19790
20370
|
async function withCheckSlot(operation) {
|
|
19791
20371
|
if (activeChecks >= MAX_CONCURRENT_CHECKS) {
|
|
19792
|
-
await new Promise((
|
|
20372
|
+
await new Promise((resolve8) => checkWaiters.push(resolve8));
|
|
19793
20373
|
}
|
|
19794
20374
|
activeChecks += 1;
|
|
19795
20375
|
try {
|
|
@@ -19847,8 +20427,8 @@ ${results.every((result) => result.ok) ? "All agents healthy" : "Some agents fai
|
|
|
19847
20427
|
server.tool("list_active_queries", "\uD604\uC7AC \uC0AC\uC6A9\uC790 \uBC94\uC704\uC5D0\uC11C \uC2E4\uD589 \uC911\uC778 \uD1A0\uD53D \uCFFC\uB9AC \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4.", {}, async () => {
|
|
19848
20428
|
if (!context.userId)
|
|
19849
20429
|
return mcpOk("\uC2E4\uD589 \uC911\uC778 \uCFFC\uB9AC \uC870\uD68C \uBD88\uAC00 (user context \uC5C6\uC74C)");
|
|
19850
|
-
const stateDir =
|
|
19851
|
-
if (!
|
|
20430
|
+
const stateDir = join11(USERS_LOG_DIR, context.userId, "active-queries");
|
|
20431
|
+
if (!existsSync10(stateDir))
|
|
19852
20432
|
return mcpOk("\uC2E4\uD589 \uC911\uC778 \uCFFC\uB9AC \uC5C6\uC74C");
|
|
19853
20433
|
let files;
|
|
19854
20434
|
try {
|
|
@@ -19860,7 +20440,7 @@ ${results.every((result) => result.ok) ? "All agents healthy" : "Some agents fai
|
|
|
19860
20440
|
const entries = files.flatMap((file) => {
|
|
19861
20441
|
if (!file.endsWith(".json"))
|
|
19862
20442
|
return [];
|
|
19863
|
-
const state = readJsonFile(
|
|
20443
|
+
const state = readJsonFile(join11(stateDir, file));
|
|
19864
20444
|
if (!state)
|
|
19865
20445
|
return [];
|
|
19866
20446
|
const sinceMs = new Date(state.since).getTime();
|
|
@@ -19885,7 +20465,7 @@ ${lines.join(`
|
|
|
19885
20465
|
}
|
|
19886
20466
|
// ../../packages/core/src/mcp/factories/compaction-log.ts
|
|
19887
20467
|
init_mcp_helpers();
|
|
19888
|
-
import { readFileSync as
|
|
20468
|
+
import { readFileSync as readFileSync9, realpathSync as realpathSync3 } from "fs";
|
|
19889
20469
|
import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
19890
20470
|
import { z as z2 } from "zod";
|
|
19891
20471
|
var DEFAULT_MAX_CALLS = 12;
|
|
@@ -19918,7 +20498,7 @@ function createCompactionLogMcpServer(context) {
|
|
|
19918
20498
|
if (!context.filePath)
|
|
19919
20499
|
throw new Error("compaction-log MCP requires filePath");
|
|
19920
20500
|
const filePath = realpathSync3(context.filePath);
|
|
19921
|
-
const lines =
|
|
20501
|
+
const lines = readFileSync9(filePath, "utf8").split(`
|
|
19922
20502
|
`);
|
|
19923
20503
|
const maxCalls = positiveInt(context.maxCalls, DEFAULT_MAX_CALLS);
|
|
19924
20504
|
const maxTotalBytes = positiveInt(context.maxTotalBytes, DEFAULT_MAX_TOTAL_BYTES);
|
|
@@ -20511,4 +21091,4 @@ export {
|
|
|
20511
21091
|
createAgentHealthMcpServer
|
|
20512
21092
|
};
|
|
20513
21093
|
|
|
20514
|
-
//# debugId=
|
|
21094
|
+
//# debugId=B2D00F1A1BBBDD6C64756E2164756E21
|