negotium 0.22.4 → 0.22.6
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 +408 -1301
- package/dist/agent-helpers.js.map +6 -6
- package/dist/background-bash.js +12 -12
- package/dist/background-bash.js.map +2 -2
- package/dist/browser-runtime.js +42 -44
- package/dist/browser-runtime.js.map +2 -2
- package/dist/canonical-mcp-bridge.js +8 -9
- package/dist/canonical-mcp-bridge.js.map +1 -1
- package/dist/{chunk-y4tyc603.js → chunk-1e0nxy7p.js} +13 -13
- package/dist/chunk-1e0nxy7p.js.map +10 -0
- package/dist/{chunk-9zn0bkc9.js → chunk-1mba9m1j.js} +77 -116
- package/dist/{chunk-9zn0bkc9.js.map → chunk-1mba9m1j.js.map} +2 -2
- package/dist/{chunk-rwj7x5pg.js → chunk-9a50csg6.js} +123 -121
- package/dist/{chunk-rwj7x5pg.js.map → chunk-9a50csg6.js.map} +7 -7
- package/dist/chunk-bnyvxss3.js +77 -0
- package/dist/{chunk-q5djsg78.js.map → chunk-bnyvxss3.js.map} +1 -1
- package/dist/{chunk-0jtan6fd.js → chunk-e59kzyvy.js} +4 -5
- package/dist/{chunk-0jtan6fd.js.map → chunk-e59kzyvy.js.map} +2 -2
- package/dist/{chunk-f7p0h1gs.js → chunk-ww8a4ej4.js} +5 -5
- package/dist/{chunk-f7p0h1gs.js.map → chunk-ww8a4ej4.js.map} +2 -2
- package/dist/hosted-agent.js +127 -124
- package/dist/hosted-agent.js.map +4 -4
- package/dist/main.js +3327 -5138
- package/dist/main.js.map +10 -10
- package/dist/mcp-catalog.js +4 -4
- package/dist/mcp-catalog.js.map +1 -1
- package/dist/mcp-factories.js +630 -1515
- package/dist/mcp-factories.js.map +6 -6
- package/dist/mcp-servers.js +5 -5
- package/dist/mcp-servers.js.map +1 -1
- package/dist/media.js +3 -3
- package/dist/media.js.map +1 -1
- package/dist/outbox.js +15 -15
- package/dist/outbox.js.map +2 -2
- package/dist/platform-runtime.js +7 -7
- package/dist/platform-runtime.js.map +1 -1
- package/dist/prompts.js +6 -6
- package/dist/prompts.js.map +2 -2
- package/dist/query-runtime.js +16 -18
- package/dist/query-runtime.js.map +2 -2
- package/dist/registry.js +19 -20
- package/dist/registry.js.map +2 -2
- package/dist/rollout.js +41 -41
- package/dist/rollout.js.map +2 -2
- package/dist/runtime/src/agents/rollout/claude.ts +6 -1
- package/dist/runtime/src/application/submit-runtime-gateway-turn.ts +6 -4
- package/dist/runtime/src/node-host.ts +1 -0
- package/dist/runtime/src/platform/mcp-config.ts +60 -28
- package/dist/runtime/src/runtime/turn-runner.ts +9 -4
- package/dist/runtime/src/topics/update.ts +20 -0
- package/dist/runtime/src/version.ts +1 -1
- package/dist/runtime-gateway.js +12 -12
- package/dist/runtime-gateway.js.map +2 -2
- package/dist/runtime-helpers.js +52 -54
- package/dist/runtime-helpers.js.map +2 -2
- package/dist/sqlite.js +3 -5
- package/dist/sqlite.js.map +2 -2
- package/dist/storage.js +4831 -4802
- package/dist/storage.js.map +2 -2
- package/dist/types/packages/core/src/agents/rollout/claude.d.ts +5 -0
- package/dist/types/packages/core/src/platform/mcp-config.d.ts +8 -0
- package/dist/types/packages/core/src/runtime/turn-runner.d.ts +6 -2
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/dist/vault.js +20 -22
- package/dist/vault.js.map +2 -2
- package/package.json +1 -1
- package/dist/chunk-2mx7fq49.js +0 -6
- package/dist/chunk-2mx7fq49.js.map +0 -9
- package/dist/chunk-q5djsg78.js +0 -200
- package/dist/chunk-y4tyc603.js.map +0 -10
package/dist/agent-helpers.js
CHANGED
|
@@ -13,9 +13,18 @@ var __export = (target, all) => {
|
|
|
13
13
|
set: __exportSetter.bind(all, name)
|
|
14
14
|
});
|
|
15
15
|
};
|
|
16
|
-
var __esm = (fn, res) => () =>
|
|
16
|
+
var __esm = (fn, res, err) => () => {
|
|
17
|
+
if (fn)
|
|
18
|
+
try {
|
|
19
|
+
res = fn(fn = 0);
|
|
20
|
+
} catch (e) {
|
|
21
|
+
err = [e];
|
|
22
|
+
}
|
|
23
|
+
if (err)
|
|
24
|
+
throw err[0];
|
|
25
|
+
return res;
|
|
26
|
+
};
|
|
17
27
|
var __promiseAll = (args) => Promise.all(args);
|
|
18
|
-
var __require = import.meta.require;
|
|
19
28
|
|
|
20
29
|
// ../../packages/core/src/platform/paths.ts
|
|
21
30
|
import { existsSync, realpathSync } from "fs";
|
|
@@ -184,105 +193,6 @@ var init_logger = __esm(() => {
|
|
|
184
193
|
});
|
|
185
194
|
|
|
186
195
|
// ../../packages/core/src/platform/config.ts
|
|
187
|
-
var exports_config = {};
|
|
188
|
-
__export(exports_config, {
|
|
189
|
-
resolveTopicWorkspaceDir: () => resolveTopicWorkspaceDir,
|
|
190
|
-
resolveOutputLanguage: () => resolveOutputLanguage,
|
|
191
|
-
resolveBrowserRsBin: () => resolveBrowserRsBin,
|
|
192
|
-
resolveBrowserProxy: () => resolveBrowserProxy,
|
|
193
|
-
resolveBrowserMcpBin: () => resolveBrowserMcpBin,
|
|
194
|
-
resolveBashRsBin: () => resolveBashRsBin,
|
|
195
|
-
isProductionEnv: () => isProductionEnv,
|
|
196
|
-
hostname: () => hostname,
|
|
197
|
-
getCleanEnv: () => getCleanEnv,
|
|
198
|
-
envText: () => envText,
|
|
199
|
-
codexAuthFilePath: () => codexAuthFilePath,
|
|
200
|
-
WORKSPACE_DIR: () => WORKSPACE_DIR,
|
|
201
|
-
WIKI_SERVER: () => WIKI_SERVER,
|
|
202
|
-
WHISPER_MODEL_MLX: () => WHISPER_MODEL_MLX,
|
|
203
|
-
WHISPER_MODEL: () => WHISPER_MODEL,
|
|
204
|
-
WHISPER_BACKEND: () => WHISPER_BACKEND,
|
|
205
|
-
VAULT_SERVER: () => VAULT_SERVER,
|
|
206
|
-
VAULT_MASTER_KEY: () => VAULT_MASTER_KEY,
|
|
207
|
-
VAULT_DIR: () => VAULT_DIR,
|
|
208
|
-
USERS_LOG_DIR: () => USERS_LOG_DIR,
|
|
209
|
-
UPLOADS_DIR: () => UPLOADS_DIR,
|
|
210
|
-
TSX_LOADER: () => TSX_LOADER,
|
|
211
|
-
TSX_BIN: () => TSX_BIN,
|
|
212
|
-
TSCONFIG_PATH: () => TSCONFIG_PATH,
|
|
213
|
-
TOPIC_WORKSPACE_DIR: () => TOPIC_WORKSPACE_DIR,
|
|
214
|
-
TOKEN_STATS_SERVER: () => TOKEN_STATS_SERVER,
|
|
215
|
-
TESSERACT_BIN: () => TESSERACT_BIN,
|
|
216
|
-
TASK_SERVER: () => TASK_SERVER,
|
|
217
|
-
SYSTEM_HEALTH_SERVER: () => SYSTEM_HEALTH_SERVER,
|
|
218
|
-
STATE_DIR: () => STATE_DIR,
|
|
219
|
-
SNIPPETS_API_URL: () => SNIPPETS_API_URL,
|
|
220
|
-
SHARED_WIKI_DIR: () => SHARED_WIKI_DIR,
|
|
221
|
-
SESSION_WORKSPACE_DIR: () => SESSION_WORKSPACE_DIR,
|
|
222
|
-
SESSION_INBOX_DIR: () => SESSION_INBOX_DIR,
|
|
223
|
-
SESSION_COMM_SERVER: () => SESSION_COMM_SERVER,
|
|
224
|
-
SESSION_ASKS_DIR: () => SESSION_ASKS_DIR,
|
|
225
|
-
SESSIONS_DB: () => SESSIONS_DB,
|
|
226
|
-
SECRETS_DIR: () => SECRETS_DIR,
|
|
227
|
-
RUN_DIR: () => RUN_DIR,
|
|
228
|
-
RUNTIME_MCP_SECRET: () => RUNTIME_MCP_SECRET,
|
|
229
|
-
RUNTIME_DIR: () => RUNTIME_DIR,
|
|
230
|
-
RESOURCES_DIR: () => RESOURCES_DIR,
|
|
231
|
-
PYTHON_BIN: () => PYTHON_BIN,
|
|
232
|
-
PROJECT_ROOT: () => PROJECT_ROOT,
|
|
233
|
-
PROGRESS_DIR: () => PROGRESS_DIR,
|
|
234
|
-
PLAYWRIGHT_PORTS_DIR: () => PLAYWRIGHT_PORTS_DIR,
|
|
235
|
-
PLAYWRIGHT_MCP_BIN: () => PLAYWRIGHT_MCP_BIN,
|
|
236
|
-
PLAYWRIGHT_MAX_PORT: () => PLAYWRIGHT_MAX_PORT,
|
|
237
|
-
PLAYWRIGHT_BASE_PORT: () => PLAYWRIGHT_BASE_PORT,
|
|
238
|
-
PDFTOTEXT_BIN: () => PDFTOTEXT_BIN,
|
|
239
|
-
NODE_ID: () => NODE_ID,
|
|
240
|
-
NODE_CONTROL_TOKEN: () => NODE_CONTROL_TOKEN,
|
|
241
|
-
NEGOTIUM_PORT: () => NEGOTIUM_PORT,
|
|
242
|
-
MODEL_SONNET: () => MODEL_SONNET,
|
|
243
|
-
MODEL_OPUS: () => MODEL_OPUS,
|
|
244
|
-
MODEL_HAIKU: () => MODEL_HAIKU,
|
|
245
|
-
MODEL_FABLE: () => MODEL_FABLE,
|
|
246
|
-
MODEL_DEEPSEEK_V4_PRO: () => MODEL_DEEPSEEK_V4_PRO,
|
|
247
|
-
MODEL_DEEPSEEK_V4_FLASH: () => MODEL_DEEPSEEK_V4_FLASH,
|
|
248
|
-
MLX_WHISPER_BIN: () => MLX_WHISPER_BIN,
|
|
249
|
-
MAX_TELL_DEPTH: () => MAX_TELL_DEPTH,
|
|
250
|
-
LOG_DIR: () => LOG_DIR,
|
|
251
|
-
FILE_TAG_REGEX: () => FILE_TAG_REGEX,
|
|
252
|
-
FILE_EXTENSIONS_REGEX: () => FILE_EXTENSIONS_REGEX,
|
|
253
|
-
FFPROBE_BIN: () => FFPROBE_BIN,
|
|
254
|
-
FFMPEG_BIN: () => FFMPEG_BIN,
|
|
255
|
-
FASTER_WHISPER_WRAPPER: () => FASTER_WHISPER_WRAPPER,
|
|
256
|
-
FALLBACK_MODEL: () => FALLBACK_MODEL,
|
|
257
|
-
FALLBACK_AGENT: () => FALLBACK_AGENT,
|
|
258
|
-
DM_WORKSPACE_DIR: () => DM_WORKSPACE_DIR,
|
|
259
|
-
DM_RESP_DIR: () => DM_RESP_DIR,
|
|
260
|
-
DM_CMD_DIR: () => DM_CMD_DIR,
|
|
261
|
-
DEFAULT_TOPIC_EFFORT: () => DEFAULT_TOPIC_EFFORT,
|
|
262
|
-
DEFAULT_OUTPUT_LANGUAGE: () => DEFAULT_OUTPUT_LANGUAGE,
|
|
263
|
-
DECISION_SERVER: () => DECISION_SERVER,
|
|
264
|
-
DEBUG_FILE: () => DEBUG_FILE,
|
|
265
|
-
DATA_DIR: () => DATA_DIR,
|
|
266
|
-
CRON_WORKSPACE_DIR: () => CRON_WORKSPACE_DIR,
|
|
267
|
-
COMPACTION_LOG_SERVER: () => COMPACTION_LOG_SERVER,
|
|
268
|
-
CLAUDE_EXECUTABLE: () => CLAUDE_EXECUTABLE,
|
|
269
|
-
CANONICAL_MCP_PROXY_SERVER: () => CANONICAL_MCP_PROXY_SERVER,
|
|
270
|
-
BROWSER_RS_VERSION: () => BROWSER_RS_VERSION,
|
|
271
|
-
BROWSER_RS_MIN_SECURE_VERSION: () => BROWSER_RS_MIN_SECURE_VERSION,
|
|
272
|
-
BROWSER_RS_BIN: () => BROWSER_RS_BIN,
|
|
273
|
-
BROWSER_PROFILES_DIR: () => BROWSER_PROFILES_DIR,
|
|
274
|
-
BROWSER_DIR: () => BROWSER_DIR,
|
|
275
|
-
BINARY_EXTENSION: () => BINARY_EXTENSION,
|
|
276
|
-
BINARIES_DIR: () => BINARIES_DIR,
|
|
277
|
-
BG_BASH_MAX_PORT: () => BG_BASH_MAX_PORT,
|
|
278
|
-
BG_BASH_BASE_PORT: () => BG_BASH_BASE_PORT,
|
|
279
|
-
BASH_RS_VERSION: () => BASH_RS_VERSION,
|
|
280
|
-
BASH_RS_BIN: () => BASH_RS_BIN,
|
|
281
|
-
BASHRS_SPILL_ROOT: () => BASHRS_SPILL_ROOT,
|
|
282
|
-
AGENT_HEALTH_SERVER: () => AGENT_HEALTH_SERVER,
|
|
283
|
-
AGENTS_PROMPTS_DIR: () => AGENTS_PROMPTS_DIR,
|
|
284
|
-
ACTIVE_QUERY_STALE_MS: () => ACTIVE_QUERY_STALE_MS
|
|
285
|
-
});
|
|
286
196
|
import { execFileSync } from "child_process";
|
|
287
197
|
import { randomBytes } from "crypto";
|
|
288
198
|
import {
|
|
@@ -432,9 +342,6 @@ function safeWorkspaceSegment(value, fallback) {
|
|
|
432
342
|
function resolveTopicWorkspaceDir(topicId) {
|
|
433
343
|
return join(TOPIC_WORKSPACE_DIR, safeWorkspaceSegment(topicId, "topic"));
|
|
434
344
|
}
|
|
435
|
-
function isProductionEnv() {
|
|
436
|
-
return false;
|
|
437
|
-
}
|
|
438
345
|
function loadOrCreateLocalSecret(envKey, filename, options = {}) {
|
|
439
346
|
const envValue = envText(envKey);
|
|
440
347
|
const secretFile = resolve3(SECRETS_DIR, filename);
|
|
@@ -469,18 +376,13 @@ function loadOrCreateLocalSecret(envKey, filename, options = {}) {
|
|
|
469
376
|
return stored;
|
|
470
377
|
}
|
|
471
378
|
}
|
|
472
|
-
function getCleanEnv() {
|
|
473
|
-
const env = { ...process.env };
|
|
474
|
-
delete env.CLAUDECODE;
|
|
475
|
-
return env;
|
|
476
|
-
}
|
|
477
379
|
function resolveWhisperBackend() {
|
|
478
380
|
return envText("WHISPER_BACKEND") === "mlx-whisper" ? "mlx-whisper" : "faster-whisper";
|
|
479
381
|
}
|
|
480
382
|
function codexAuthFilePath() {
|
|
481
383
|
return process.env.NEGOTIUM_CODEX_AUTH_FILE || join(process.env.CODEX_HOME || join(homedir(), ".codex"), "auth.json");
|
|
482
384
|
}
|
|
483
|
-
var HOME, PROJECT_ROOT, 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", BINARY_EXTENSION, BROWSER_RS_VERSION = "v0.7.7", BROWSER_RS_MIN_SECURE_VERSION = "0.2.1", BROWSER_RS_VERSION_PROBE_TIMEOUT_MS = 15000, SNIPPETS_API_URL, BROWSER_RS_BIN, BASH_RS_VERSION = "v0.1.10", BASH_RS_BIN, PLAYWRIGHT_MCP_BIN, TSX_BIN, TSX_LOADER_PATH, TSX_LOADER, TSCONFIG_PATH, SESSION_COMM_SERVER, TASK_SERVER, DECISION_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, NODE_ID, VAULT_MASTER_KEY, NEGOTIUM_PORT, hostname, DATA_DIR, LOG_DIR, UPLOADS_DIR, VAULT_DIR, SESSIONS_DB, DEBUG_FILE, USERS_LOG_DIR, RUN_DIR,
|
|
385
|
+
var HOME, PROJECT_ROOT, 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", BINARY_EXTENSION, BROWSER_RS_VERSION = "v0.7.7", BROWSER_RS_MIN_SECURE_VERSION = "0.2.1", BROWSER_RS_VERSION_PROBE_TIMEOUT_MS = 15000, SNIPPETS_API_URL, BROWSER_RS_BIN, BASH_RS_VERSION = "v0.1.10", BASH_RS_BIN, PLAYWRIGHT_MCP_BIN, TSX_BIN, TSX_LOADER_PATH, TSX_LOADER, TSCONFIG_PATH, SESSION_COMM_SERVER, TASK_SERVER, DECISION_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, NODE_ID, 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, ABSOLUTE_PATH_PREFIX, FILE_EXTENSIONS_REGEX, FILE_TAG_REGEX, MODEL_SONNET = "claude-sonnet-5", MODEL_OPUS = "claude-opus-5-5", MODEL_FABLE = "claude-fable-5-1", FALLBACK_AGENT, FALLBACK_MODEL, DEFAULT_TOPIC_EFFORT, FFMPEG_BIN, FFPROBE_BIN, PYTHON_BIN, FASTER_WHISPER_WRAPPER, WHISPER_MODEL, TESSERACT_BIN, PDFTOTEXT_BIN, WHISPER_BACKEND, MLX_WHISPER_BIN, WHISPER_MODEL_MLX, _envMaxTellDepth, MAX_TELL_DEPTH;
|
|
484
386
|
var init_config = __esm(() => {
|
|
485
387
|
init_config_helpers();
|
|
486
388
|
init_logger();
|
|
@@ -536,7 +438,6 @@ var init_config = __esm(() => {
|
|
|
536
438
|
DEBUG_FILE = resolve3(DATA_DIR, "debug-users.json");
|
|
537
439
|
USERS_LOG_DIR = resolve3(DATA_DIR, "users");
|
|
538
440
|
RUN_DIR = resolveLocalStateDir("NEGOTIUM_RUN_DIR", "runtime");
|
|
539
|
-
RUNTIME_DIR = RUN_DIR;
|
|
540
441
|
PROGRESS_DIR = resolve3(RUN_DIR, "progress");
|
|
541
442
|
DM_CMD_DIR = resolve3(RUN_DIR, "dm-commands");
|
|
542
443
|
DM_RESP_DIR = resolve3(RUN_DIR, "dm-responses");
|
|
@@ -769,13 +670,6 @@ function validateActorTopicScope(value) {
|
|
|
769
670
|
}
|
|
770
671
|
return { ok: true, scope };
|
|
771
672
|
}
|
|
772
|
-
function parseActorTopicScope(value) {
|
|
773
|
-
const validated = validateActorTopicScope(value);
|
|
774
|
-
return validated.ok ? validated.scope : null;
|
|
775
|
-
}
|
|
776
|
-
function actorTopicScopeFrom(value) {
|
|
777
|
-
return parseActorTopicScope(value) ?? undefined;
|
|
778
|
-
}
|
|
779
673
|
function intersectActorTopicScopes(scopes) {
|
|
780
674
|
if (scopes.length === 0 || scopes.some((scope) => scope === undefined))
|
|
781
675
|
return;
|
|
@@ -886,13 +780,6 @@ function validateRemoteSessionGrant(value) {
|
|
|
886
780
|
}
|
|
887
781
|
return { ok: true, grant: { hubUrl: hubUrl.url, capability } };
|
|
888
782
|
}
|
|
889
|
-
function parseRemoteSessionGrant(value) {
|
|
890
|
-
const validated = validateRemoteSessionGrant(value);
|
|
891
|
-
return validated.ok ? validated.grant : null;
|
|
892
|
-
}
|
|
893
|
-
function remoteSessionGrantFrom(value) {
|
|
894
|
-
return parseRemoteSessionGrant(value) ?? undefined;
|
|
895
|
-
}
|
|
896
783
|
function remoteSessionGrantExpiry(grant) {
|
|
897
784
|
const payload = grant.capability.split(".")[1];
|
|
898
785
|
if (!payload)
|
|
@@ -931,7 +818,7 @@ function encodeRemoteSessionGrantArg(grant) {
|
|
|
931
818
|
throw new Error("remoteSession is required");
|
|
932
819
|
return Buffer.from(JSON.stringify(validated.grant), "utf-8").toString("base64url");
|
|
933
820
|
}
|
|
934
|
-
var REMOTE_SESSION_GRANT_LIMITS, GRANT_KEYS, LOOPBACK_HOSTS,
|
|
821
|
+
var REMOTE_SESSION_GRANT_LIMITS, GRANT_KEYS, LOOPBACK_HOSTS, MAX_REMOTE_SESSION_REPLY_TOKEN_LENGTH;
|
|
935
822
|
var init_remote_session_grant = __esm(() => {
|
|
936
823
|
REMOTE_SESSION_GRANT_LIMITS = Object.freeze({
|
|
937
824
|
maxHubUrlLength: 512,
|
|
@@ -940,7 +827,6 @@ var init_remote_session_grant = __esm(() => {
|
|
|
940
827
|
});
|
|
941
828
|
GRANT_KEYS = ["hubUrl", "capability"];
|
|
942
829
|
LOOPBACK_HOSTS = new Set(["127.0.0.1", "::1", "[::1]", "localhost"]);
|
|
943
|
-
REMOTE_SESSION_REPLY_TOKEN_PATTERN = /^rsr1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/;
|
|
944
830
|
MAX_REMOTE_SESSION_REPLY_TOKEN_LENGTH = REMOTE_SESSION_GRANT_LIMITS.maxCapabilityLength;
|
|
945
831
|
});
|
|
946
832
|
|
|
@@ -1285,12 +1171,12 @@ function createBackgroundBashManager(options = {}) {
|
|
|
1285
1171
|
usedPorts.clear();
|
|
1286
1172
|
knownContexts.clear();
|
|
1287
1173
|
const deadline = now() + 3000;
|
|
1288
|
-
await Promise.all(entries.map((instance) => new Promise((
|
|
1174
|
+
await Promise.all(entries.map((instance) => new Promise((resolve) => {
|
|
1289
1175
|
if (instance.process.exitCode !== null || instance.process.killed)
|
|
1290
|
-
return
|
|
1291
|
-
instance.process.once("exit",
|
|
1292
|
-
instance.process.once("error",
|
|
1293
|
-
const timer = setTimeout(
|
|
1176
|
+
return resolve();
|
|
1177
|
+
instance.process.once("exit", resolve);
|
|
1178
|
+
instance.process.once("error", resolve);
|
|
1179
|
+
const timer = setTimeout(resolve, Math.max(0, deadline - now()));
|
|
1294
1180
|
timer.unref?.();
|
|
1295
1181
|
})));
|
|
1296
1182
|
}
|
|
@@ -1992,7 +1878,7 @@ var init_api_messages = __esm(async () => {
|
|
|
1992
1878
|
|
|
1993
1879
|
// ../../packages/core/src/storage/topic-link-records.ts
|
|
1994
1880
|
function topicLinkSchemaIsCurrent(database, nodeId) {
|
|
1995
|
-
const objects = new Map(database.query("SELECT name, sql FROM sqlite_master WHERE type IN ('table','index','trigger')").all().map((
|
|
1881
|
+
const objects = new Map(database.query("SELECT name, sql FROM sqlite_master WHERE type IN ('table','index','trigger')").all().map((row) => [row.name, row.sql ?? ""]));
|
|
1996
1882
|
for (const name of [...SCHEMA_TABLES, ...SCHEMA_INDEXES, ...SCHEMA_INDEXES_TOMBSTONES]) {
|
|
1997
1883
|
if (!objects.has(name))
|
|
1998
1884
|
return false;
|
|
@@ -2009,7 +1895,7 @@ function topicLinkSchemaIsCurrent(database, nodeId) {
|
|
|
2009
1895
|
return false;
|
|
2010
1896
|
}
|
|
2011
1897
|
const identity = database.query("SELECT node_id, epoch_id FROM api_node_identity WHERE singleton = 1").all();
|
|
2012
|
-
if (identity.some((
|
|
1898
|
+
if (identity.some((row) => row.epoch_id === null))
|
|
2013
1899
|
return false;
|
|
2014
1900
|
if (nodeId && identity[0]?.node_id !== nodeId)
|
|
2015
1901
|
return false;
|
|
@@ -2843,9 +2729,6 @@ function rowToDto2(r, participants = getTopicParticipants(r.id), tellTargets) {
|
|
|
2843
2729
|
function normalizeTopicVisibility(value) {
|
|
2844
2730
|
return value === "hidden" ? "hidden" : "visible";
|
|
2845
2731
|
}
|
|
2846
|
-
function isTopicVisible(topic) {
|
|
2847
|
-
return topic.visibility !== "hidden";
|
|
2848
|
-
}
|
|
2849
2732
|
function normalizeTopicKind(value) {
|
|
2850
2733
|
return value === "channel" || value === "agent" || value === "manager" ? value : null;
|
|
2851
2734
|
}
|
|
@@ -3244,6 +3127,11 @@ function refreshForumCatalogViews() {
|
|
|
3244
3127
|
function isReservedRuntimeMcpServerName(name) {
|
|
3245
3128
|
return Object.hasOwn(MCP_CATALOG, name) || nodeMcpEntries.some((entry) => entry.key === name);
|
|
3246
3129
|
}
|
|
3130
|
+
function withoutManagerOnlyHostMcpServers(hostMcpServers) {
|
|
3131
|
+
if (!hostMcpServers)
|
|
3132
|
+
return;
|
|
3133
|
+
return Object.fromEntries(Object.entries(hostMcpServers).filter(([name]) => !MANAGER_ONLY_HOST_MCP_NAMES.has(name)));
|
|
3134
|
+
}
|
|
3247
3135
|
function mergeHostMcpServers(base, hostMcpServers) {
|
|
3248
3136
|
if (!hostMcpServers)
|
|
3249
3137
|
return base;
|
|
@@ -3504,7 +3392,7 @@ function getMcpServersForQuery(opts) {
|
|
|
3504
3392
|
fileDeliveryTools: opts.fileDeliveryTools
|
|
3505
3393
|
}), opts.hostMcpServers), opts.topicId);
|
|
3506
3394
|
}
|
|
3507
|
-
return hideProviderIntrospectionForOtium(getForumMcpServers({
|
|
3395
|
+
return hideProviderIntrospectionForOtium(mergeHostMcpServers(getForumMcpServers({
|
|
3508
3396
|
userId: opts.userId || "local",
|
|
3509
3397
|
actorUserId: opts.actorUserId,
|
|
3510
3398
|
actorTopicScope: opts.actorTopicScope,
|
|
@@ -3531,7 +3419,7 @@ function getMcpServersForQuery(opts) {
|
|
|
3531
3419
|
extra: opts.mcpExtra,
|
|
3532
3420
|
silent: opts.silent,
|
|
3533
3421
|
peerBridge: opts.peerBridge
|
|
3534
|
-
}), opts.topicId);
|
|
3422
|
+
}), withoutManagerOnlyHostMcpServers(opts.hostMcpServers)), opts.topicId);
|
|
3535
3423
|
}
|
|
3536
3424
|
function hideProviderIntrospectionForOtium(servers, topicId) {
|
|
3537
3425
|
if (!topicId || getTopic(topicId)?.surface !== "otium")
|
|
@@ -3541,7 +3429,7 @@ function hideProviderIntrospectionForOtium(servers, topicId) {
|
|
|
3541
3429
|
delete filtered["token-stats"];
|
|
3542
3430
|
return filtered;
|
|
3543
3431
|
}
|
|
3544
|
-
var _playwrightUnavailableNotifier, _playwrightUnavailableLastNotifiedAt, _PLAYWRIGHT_UNAVAILABLE_COOLDOWN_MS, _playwrightUnavailableThisTurn, cuaRsMcpPort, cuaRsMcpToken, MCP_CATALOG, nodeMcpEntries, resolvedNodeMcpPorts, allForumMcpServerNames, requiredForumMcpServers, REQUIRED_FORUM_MCP_SERVERS, optionalForumMcpServers;
|
|
3432
|
+
var _playwrightUnavailableNotifier, _playwrightUnavailableLastNotifiedAt, _PLAYWRIGHT_UNAVAILABLE_COOLDOWN_MS, _playwrightUnavailableThisTurn, cuaRsMcpPort, cuaRsMcpToken, MCP_CATALOG, nodeMcpEntries, resolvedNodeMcpPorts, allForumMcpServerNames, requiredForumMcpServers, REQUIRED_FORUM_MCP_SERVERS, optionalForumMcpServers, MANAGER_ONLY_HOST_MCP_NAMES;
|
|
3545
3433
|
var init_mcp_config = __esm(async () => {
|
|
3546
3434
|
init_explicit_agent_switch();
|
|
3547
3435
|
init_canonical_bridge_config();
|
|
@@ -3797,6 +3685,7 @@ var init_mcp_config = __esm(async () => {
|
|
|
3797
3685
|
REQUIRED_FORUM_MCP_SERVERS = requiredForumMcpServers;
|
|
3798
3686
|
optionalForumMcpServers = [];
|
|
3799
3687
|
refreshForumCatalogViews();
|
|
3688
|
+
MANAGER_ONLY_HOST_MCP_NAMES = new Set(["topic-admin"]);
|
|
3800
3689
|
});
|
|
3801
3690
|
|
|
3802
3691
|
// ../../packages/core/src/storage/vault-crypto-core.ts
|
|
@@ -4491,7 +4380,7 @@ function loadClaudeAttachments() {
|
|
|
4491
4380
|
}
|
|
4492
4381
|
function encodeClaudeCwd(cwd) {
|
|
4493
4382
|
const realCwd = cwd.startsWith("/tmp/") ? cwd.replace(/^\/tmp\//, "/private/tmp/") : cwd;
|
|
4494
|
-
return
|
|
4383
|
+
return realCwd.replaceAll(/[^a-zA-Z0-9]/g, "-");
|
|
4495
4384
|
}
|
|
4496
4385
|
function writeClaudeRollout(opts) {
|
|
4497
4386
|
const sessionId = opts.sessionId ?? randomUUID2();
|
|
@@ -5230,7 +5119,7 @@ var init_codex = __esm(async () => {
|
|
|
5230
5119
|
});
|
|
5231
5120
|
|
|
5232
5121
|
// ../../packages/core/src/version.ts
|
|
5233
|
-
var NEGOTIUM_VERSION = "0.22.
|
|
5122
|
+
var NEGOTIUM_VERSION = "0.22.6";
|
|
5234
5123
|
|
|
5235
5124
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
5236
5125
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -5306,7 +5195,7 @@ async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
|
5306
5195
|
stdio: ["pipe", "pipe", "pipe"],
|
|
5307
5196
|
windowsHide: true
|
|
5308
5197
|
});
|
|
5309
|
-
const refreshed = new Promise((
|
|
5198
|
+
const refreshed = new Promise((resolve, reject) => {
|
|
5310
5199
|
let settled = false;
|
|
5311
5200
|
let stdoutBuffer = "";
|
|
5312
5201
|
let stderr = "";
|
|
@@ -5325,7 +5214,7 @@ async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
|
5325
5214
|
else if (!existsSync6(cachePath))
|
|
5326
5215
|
reject(new Error("Codex did not create its model cache"));
|
|
5327
5216
|
else
|
|
5328
|
-
|
|
5217
|
+
resolve();
|
|
5329
5218
|
};
|
|
5330
5219
|
const send = (message) => {
|
|
5331
5220
|
child.stdin.write(`${JSON.stringify(message)}
|
|
@@ -5391,12 +5280,12 @@ async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
|
5391
5280
|
function waitForChildExit(child, timeoutMs) {
|
|
5392
5281
|
if (child.exitCode !== null || child.signalCode !== null)
|
|
5393
5282
|
return Promise.resolve();
|
|
5394
|
-
return new Promise((
|
|
5395
|
-
const timer = setTimeout(
|
|
5283
|
+
return new Promise((resolve) => {
|
|
5284
|
+
const timer = setTimeout(resolve, timeoutMs);
|
|
5396
5285
|
timer.unref?.();
|
|
5397
5286
|
child.once("exit", () => {
|
|
5398
5287
|
clearTimeout(timer);
|
|
5399
|
-
|
|
5288
|
+
resolve();
|
|
5400
5289
|
});
|
|
5401
5290
|
});
|
|
5402
5291
|
}
|
|
@@ -5486,16 +5375,11 @@ var init_codex_native_multi_agent = __esm(() => {
|
|
|
5486
5375
|
});
|
|
5487
5376
|
|
|
5488
5377
|
// ../../packages/core/src/agents/codex-app-server.ts
|
|
5489
|
-
var exports_codex_app_server = {};
|
|
5490
|
-
__export(exports_codex_app_server, {
|
|
5491
|
-
forkCodexSession: () => forkCodexSession,
|
|
5492
|
-
createCodexAppServerForker: () => createCodexAppServerForker
|
|
5493
|
-
});
|
|
5494
5378
|
import { spawn as spawn3 } from "child_process";
|
|
5495
5379
|
function createCodexAppServerForker(host) {
|
|
5496
5380
|
return async (parentThreadId) => {
|
|
5497
5381
|
const child = host.spawnServer();
|
|
5498
|
-
return await new Promise((
|
|
5382
|
+
return await new Promise((resolve, reject) => {
|
|
5499
5383
|
let settled = false;
|
|
5500
5384
|
let stdoutBuffer = "";
|
|
5501
5385
|
let stderr = "";
|
|
@@ -5512,7 +5396,7 @@ function createCodexAppServerForker(host) {
|
|
|
5512
5396
|
if (error)
|
|
5513
5397
|
reject(error);
|
|
5514
5398
|
else if (result)
|
|
5515
|
-
|
|
5399
|
+
resolve(result);
|
|
5516
5400
|
else
|
|
5517
5401
|
reject(new Error("Codex thread fork returned no result"));
|
|
5518
5402
|
};
|
|
@@ -5649,8 +5533,8 @@ var init_codex_registry = __esm(async () => {
|
|
|
5649
5533
|
return { sessionId: threadId, rolloutPath };
|
|
5650
5534
|
},
|
|
5651
5535
|
async forkSession({ parentSessionId }) {
|
|
5652
|
-
|
|
5653
|
-
return await
|
|
5536
|
+
await init_codex_app_server();
|
|
5537
|
+
return await forkCodexSession(parentSessionId);
|
|
5654
5538
|
},
|
|
5655
5539
|
async cleanupRollouts({ sessionIds }) {
|
|
5656
5540
|
if (sessionIds.length === 0)
|
|
@@ -5831,11 +5715,6 @@ var init_maestro_registry = __esm(() => {
|
|
|
5831
5715
|
});
|
|
5832
5716
|
|
|
5833
5717
|
// ../../packages/core/src/agents/registry.ts
|
|
5834
|
-
var exports_registry = {};
|
|
5835
|
-
__export(exports_registry, {
|
|
5836
|
-
getRegistryOperations: () => getRegistryOperations,
|
|
5837
|
-
getRegistry: () => getRegistry
|
|
5838
|
-
});
|
|
5839
5718
|
function getRegistry(agent) {
|
|
5840
5719
|
return REGISTRIES[agent];
|
|
5841
5720
|
}
|
|
@@ -6222,11 +6101,11 @@ var DEFAULT_CONTEXT_WARNING_RATIO = 0.8;
|
|
|
6222
6101
|
// ../../packages/core/src/agents/claude-provider.ts
|
|
6223
6102
|
var exports_claude_provider = {};
|
|
6224
6103
|
__export(exports_claude_provider, {
|
|
6225
|
-
|
|
6226
|
-
spawnClaudeCodeProcessWithTreeKill: () => spawnClaudeCodeProcessWithTreeKill,
|
|
6227
|
-
claudeProvider: () => claudeProvider,
|
|
6104
|
+
buildClaudeDisallowedTools: () => buildClaudeDisallowedTools,
|
|
6228
6105
|
claudeBuiltInTools: () => claudeBuiltInTools,
|
|
6229
|
-
|
|
6106
|
+
claudeProvider: () => claudeProvider,
|
|
6107
|
+
spawnClaudeCodeProcessWithTreeKill: () => spawnClaudeCodeProcessWithTreeKill,
|
|
6108
|
+
substituteClaudeToolInput: () => substituteClaudeToolInput
|
|
6230
6109
|
});
|
|
6231
6110
|
import { spawn as spawn4 } from "child_process";
|
|
6232
6111
|
import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
|
|
@@ -6307,8 +6186,8 @@ function buildClaudePrompt(opts) {
|
|
|
6307
6186
|
}
|
|
6308
6187
|
function watchClaudeProcessExit(signal) {
|
|
6309
6188
|
let listener;
|
|
6310
|
-
const exited = new Promise((
|
|
6311
|
-
listener =
|
|
6189
|
+
const exited = new Promise((resolve) => {
|
|
6190
|
+
listener = resolve;
|
|
6312
6191
|
const listeners = claudeProcessExitListeners.get(signal) ?? new Set;
|
|
6313
6192
|
listeners.add(listener);
|
|
6314
6193
|
claudeProcessExitListeners.set(signal, listeners);
|
|
@@ -6833,12 +6712,12 @@ function createCodexTreeManager(host, options = {}) {
|
|
|
6833
6712
|
const previous = spawnChain;
|
|
6834
6713
|
let release;
|
|
6835
6714
|
let released = false;
|
|
6836
|
-
spawnChain = new Promise((
|
|
6715
|
+
spawnChain = new Promise((resolve) => {
|
|
6837
6716
|
release = () => {
|
|
6838
6717
|
if (released)
|
|
6839
6718
|
return;
|
|
6840
6719
|
released = true;
|
|
6841
|
-
|
|
6720
|
+
resolve();
|
|
6842
6721
|
};
|
|
6843
6722
|
});
|
|
6844
6723
|
await previous;
|
|
@@ -6945,7 +6824,7 @@ function createCodexTreeManager(host, options = {}) {
|
|
|
6945
6824
|
return;
|
|
6946
6825
|
const deadline = Date.now() + Math.max(0, graceMs);
|
|
6947
6826
|
while (Date.now() < deadline && hasSurvivors(plan.targets)) {
|
|
6948
|
-
await new Promise((
|
|
6827
|
+
await new Promise((resolve) => setTimeout(resolve, Math.min(100, Math.max(1, deadline - Date.now()))));
|
|
6949
6828
|
}
|
|
6950
6829
|
killStragglers(plan);
|
|
6951
6830
|
}
|
|
@@ -7273,8 +7152,8 @@ async function createCodexVaultHookBridge(userId) {
|
|
|
7273
7152
|
});
|
|
7274
7153
|
restrictIpcEndpoint(socketPath);
|
|
7275
7154
|
if (IS_WINDOWS2) {
|
|
7276
|
-
|
|
7277
|
-
const cached = await ensureCodexWindowsWrapperExe(join13(
|
|
7155
|
+
await Promise.resolve().then(() => init_config());
|
|
7156
|
+
const cached = await ensureCodexWindowsWrapperExe(join13(BINARIES_DIR, "codex-hook-wrapper"));
|
|
7278
7157
|
await copyFile(cached, wrapperPath);
|
|
7279
7158
|
await writeFile2(join13(root, "codex-with-hooks.cfg"), [process.execPath, codexCliScriptPath(), socketPath, token].join(`
|
|
7280
7159
|
`), { encoding: "utf8", mode: 384 });
|
|
@@ -7846,9 +7725,9 @@ var init_tool_format = __esm(() => {
|
|
|
7846
7725
|
// ../../packages/core/src/agents/codex-provider.ts
|
|
7847
7726
|
var exports_codex_provider = {};
|
|
7848
7727
|
__export(exports_codex_provider, {
|
|
7849
|
-
|
|
7728
|
+
codexProvider: () => codexProvider,
|
|
7850
7729
|
normalizeCodexTurnUsage: () => normalizeCodexTurnUsage,
|
|
7851
|
-
|
|
7730
|
+
toCodexMcpServers: () => toCodexMcpServers
|
|
7852
7731
|
});
|
|
7853
7732
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
7854
7733
|
import { existsSync as existsSync14, readFileSync as readFileSync11, realpathSync as realpathSync4, statSync as statSync5 } from "fs";
|
|
@@ -8148,9 +8027,9 @@ async function startStreamedWithTracking(thread, prompt, abortSignal, trackedPid
|
|
|
8148
8027
|
nextP.catch(() => {});
|
|
8149
8028
|
first = await Promise.race([nextP, startupTimeout]);
|
|
8150
8029
|
} catch (err) {
|
|
8151
|
-
const
|
|
8152
|
-
if (
|
|
8153
|
-
killCodexTrees(
|
|
8030
|
+
const novel = findNewCodexChildren(baseline);
|
|
8031
|
+
if (novel.length > 0) {
|
|
8032
|
+
killCodexTrees(novel);
|
|
8154
8033
|
}
|
|
8155
8034
|
await closeIterator(iter);
|
|
8156
8035
|
throw err;
|
|
@@ -8568,11 +8447,11 @@ var init_maestro_bootstrap_env = __esm(() => {
|
|
|
8568
8447
|
// ../../packages/core/src/agents/maestro-provider.ts
|
|
8569
8448
|
var exports_maestro_provider = {};
|
|
8570
8449
|
__export(exports_maestro_provider, {
|
|
8571
|
-
|
|
8572
|
-
maestroProvider: () => maestroProvider,
|
|
8573
|
-
buildMaestroToolResultTruncation: () => buildMaestroToolResultTruncation,
|
|
8450
|
+
buildMaestroDisallowedTools: () => buildMaestroDisallowedTools,
|
|
8574
8451
|
buildMaestroToolHooks: () => buildMaestroToolHooks,
|
|
8575
|
-
|
|
8452
|
+
buildMaestroToolResultTruncation: () => buildMaestroToolResultTruncation,
|
|
8453
|
+
maestroProvider: () => maestroProvider,
|
|
8454
|
+
resolveMaestroApiKeyOverrides: () => resolveMaestroApiKeyOverrides
|
|
8576
8455
|
});
|
|
8577
8456
|
import { resolve as resolve11 } from "path";
|
|
8578
8457
|
import { maestroProvider as sdkMaestroProvider, setMcpResolver } from "maestro-agent-sdk";
|
|
@@ -8700,18 +8579,18 @@ import { join as join15 } from "path";
|
|
|
8700
8579
|
async function* dispatchAgent(opts) {
|
|
8701
8580
|
switch (opts.agent) {
|
|
8702
8581
|
case "claude": {
|
|
8703
|
-
const { claudeProvider
|
|
8704
|
-
yield*
|
|
8582
|
+
const { claudeProvider } = await loadClaudeProvider();
|
|
8583
|
+
yield* claudeProvider(opts);
|
|
8705
8584
|
return;
|
|
8706
8585
|
}
|
|
8707
8586
|
case "codex": {
|
|
8708
|
-
const { codexProvider
|
|
8709
|
-
yield*
|
|
8587
|
+
const { codexProvider } = await loadCodexProvider();
|
|
8588
|
+
yield* codexProvider(opts);
|
|
8710
8589
|
return;
|
|
8711
8590
|
}
|
|
8712
8591
|
case "maestro": {
|
|
8713
|
-
const { maestroProvider
|
|
8714
|
-
yield*
|
|
8592
|
+
const { maestroProvider } = await loadMaestroProvider();
|
|
8593
|
+
yield* maestroProvider(opts);
|
|
8715
8594
|
return;
|
|
8716
8595
|
}
|
|
8717
8596
|
default: {
|
|
@@ -8742,8 +8621,8 @@ async function resolveSessionFileMissing(agent, sessionId, cwd) {
|
|
|
8742
8621
|
return true;
|
|
8743
8622
|
}
|
|
8744
8623
|
case "maestro": {
|
|
8745
|
-
const { hasActiveMaestroSession, maestroSessionPath
|
|
8746
|
-
return !existsSync15(
|
|
8624
|
+
const { hasActiveMaestroSession, maestroSessionPath } = await import("maestro-agent-sdk");
|
|
8625
|
+
return !existsSync15(maestroSessionPath(sessionId)) && !hasActiveMaestroSession(sessionId);
|
|
8747
8626
|
}
|
|
8748
8627
|
default: {
|
|
8749
8628
|
const _exhaustive = agent;
|
|
@@ -8822,24 +8701,6 @@ var init_agents = __esm(async () => {
|
|
|
8822
8701
|
});
|
|
8823
8702
|
|
|
8824
8703
|
// ../../packages/core/src/agents/model-catalog.ts
|
|
8825
|
-
var exports_model_catalog = {};
|
|
8826
|
-
__export(exports_model_catalog, {
|
|
8827
|
-
selectableModel: () => selectableModel,
|
|
8828
|
-
resolveWorkerModel: () => resolveWorkerModel,
|
|
8829
|
-
resolveWorkerDefaultModel: () => resolveWorkerDefaultModel,
|
|
8830
|
-
resolveModelForAgent: () => resolveModelForAgent,
|
|
8831
|
-
resolveDefaultModel: () => resolveDefaultModel,
|
|
8832
|
-
resolveCompactionExecution: () => resolveCompactionExecution,
|
|
8833
|
-
modelOwner: () => modelOwner,
|
|
8834
|
-
formatSelectableModel: () => formatSelectableModel,
|
|
8835
|
-
canonicalModelId: () => canonicalModelId,
|
|
8836
|
-
SELECTABLE_MODELS: () => SELECTABLE_MODELS,
|
|
8837
|
-
MODEL_OWNER: () => MODEL_OWNER,
|
|
8838
|
-
MODEL_COST_ROUTING_SUMMARY: () => MODEL_COST_ROUTING_SUMMARY,
|
|
8839
|
-
MODEL_COST_RESEARCHED_AT: () => MODEL_COST_RESEARCHED_AT,
|
|
8840
|
-
FALLBACK_ORDER: () => FALLBACK_ORDER,
|
|
8841
|
-
AGENT_DISPLAY_NAME: () => AGENT_DISPLAY_NAME
|
|
8842
|
-
});
|
|
8843
8704
|
function canonicalModelId(value) {
|
|
8844
8705
|
const trimmed = value.trim();
|
|
8845
8706
|
const lower = trimmed.toLowerCase();
|
|
@@ -8849,10 +8710,6 @@ function formatSelectableModel(candidate) {
|
|
|
8849
8710
|
const tier = `${candidate.intelligenceTier[0].toUpperCase()}${candidate.intelligenceTier.slice(1)}`;
|
|
8850
8711
|
return `${candidate.agent} / \`${candidate.model}\` [${tier}-level]: ${candidate.routingSummary}`;
|
|
8851
8712
|
}
|
|
8852
|
-
function selectableModel(value) {
|
|
8853
|
-
const canonical = canonicalModelId(value).toLowerCase();
|
|
8854
|
-
return SELECTABLE_MODELS.find((candidate) => candidate.model === canonical);
|
|
8855
|
-
}
|
|
8856
8713
|
function modelOwner(model) {
|
|
8857
8714
|
const lower = model.toLowerCase();
|
|
8858
8715
|
if (lower.startsWith("claude-"))
|
|
@@ -8905,7 +8762,7 @@ function resolveCompactionExecution(agent, registry) {
|
|
|
8905
8762
|
const effort = registry.validateEffort("medium") ? "medium" : registry.defaultEffort;
|
|
8906
8763
|
return { model, ...effort ? { effort } : {} };
|
|
8907
8764
|
}
|
|
8908
|
-
var MODEL_OWNER,
|
|
8765
|
+
var MODEL_OWNER, MODEL_COST_ROUTING_SUMMARY = "Cost basis (2026-09-05): Codex Pro 20x and Claude Max 20x are each $200/month; Maestro models are pay-per-token. DeepSeek Flash is cheapest. gpt-6-astra and Claude Fable 5.1 are the newest flagships, both priced at $10/M input / $50/M output.", CODEX_PRO_20X_COST = "ChatGPT Pro 20x subscription: $200/month", CODEX_COMMUNITY_WEEKLY = "Community plan-level observation: roughly 2\u20134B raw/cached tokens per week; fresh-input equivalent is much lower and unstable (low confidence)", CLAUDE_MAX_20X_COST = "Claude Max 20x subscription: $200/month", CLAUDE_COMMUNITY_SESSION = "Community observations vary from roughly 220\u2013250K locally displayed tokens per 5-hour session to billions of cache-heavy raw tokens per week; calibrated reports value a full weekly allowance around $680\u2013$1,900 at API rates. Recent heavy-model reports reach the weekly cap after about 4\u20135 full sessions (low confidence; not a token cap)", SELECTABLE_MODELS, SELECTABLE_MODEL_ALIASES, CANONICAL_MODEL_CASING, AGENT_DISPLAY_NAME;
|
|
8909
8766
|
var init_model_catalog = __esm(() => {
|
|
8910
8767
|
init_config();
|
|
8911
8768
|
MODEL_OWNER = {
|
|
@@ -9077,20 +8934,6 @@ var init_model_catalog = __esm(() => {
|
|
|
9077
8934
|
"glm-flash": "glm-5.3-flash"
|
|
9078
8935
|
};
|
|
9079
8936
|
CANONICAL_MODEL_CASING = Object.fromEntries(SELECTABLE_MODELS.map((candidate) => [candidate.model.toLowerCase(), candidate.model]));
|
|
9080
|
-
FALLBACK_ORDER = {
|
|
9081
|
-
claude: [
|
|
9082
|
-
{ agent: "maestro", model: "deepseek-pro" },
|
|
9083
|
-
{ agent: "codex", model: "gpt-6-luna" }
|
|
9084
|
-
],
|
|
9085
|
-
codex: [
|
|
9086
|
-
{ agent: "maestro", model: "deepseek-pro" },
|
|
9087
|
-
{ agent: "claude", model: "sonnet" }
|
|
9088
|
-
],
|
|
9089
|
-
maestro: [
|
|
9090
|
-
{ agent: "codex", model: "gpt-6-luna" },
|
|
9091
|
-
{ agent: "claude", model: "sonnet" }
|
|
9092
|
-
]
|
|
9093
|
-
};
|
|
9094
8937
|
AGENT_DISPLAY_NAME = {
|
|
9095
8938
|
claude: "Claude",
|
|
9096
8939
|
codex: "Codex",
|
|
@@ -9839,9 +9682,9 @@ function resolveTopicBrief(topicId, legacyTitle) {
|
|
|
9839
9682
|
const titleBrief = getTopicBrief(titleKey);
|
|
9840
9683
|
if (titleBrief)
|
|
9841
9684
|
return { brief: titleBrief, storageKey: titleKey };
|
|
9842
|
-
const
|
|
9843
|
-
if (
|
|
9844
|
-
return { brief:
|
|
9685
|
+
const current = getTopicBrief(topicId);
|
|
9686
|
+
if (current)
|
|
9687
|
+
return { brief: current, storageKey: topicId };
|
|
9845
9688
|
const legacy = titleKey === legacyTitle ? null : getTopicBrief(legacyTitle);
|
|
9846
9689
|
return legacy ? { brief: legacy, storageKey: legacyTitle } : null;
|
|
9847
9690
|
}
|
|
@@ -10461,11 +10304,6 @@ var init_archiver = __esm(async () => {
|
|
|
10461
10304
|
});
|
|
10462
10305
|
|
|
10463
10306
|
// ../../packages/core/src/agents/auth-check.ts
|
|
10464
|
-
var exports_auth_check = {};
|
|
10465
|
-
__export(exports_auth_check, {
|
|
10466
|
-
checkAgentModelAuth: () => checkAgentModelAuth,
|
|
10467
|
-
checkAgentAuth: () => checkAgentAuth
|
|
10468
|
-
});
|
|
10469
10307
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
10470
10308
|
import { existsSync as existsSync17 } from "fs";
|
|
10471
10309
|
import { homedir as homedir8, platform } from "os";
|
|
@@ -10797,8 +10635,8 @@ function createRoomQueryRegistry(host) {
|
|
|
10797
10635
|
clearInterval(previousMonitor);
|
|
10798
10636
|
activeByRoom.set(roomId, control);
|
|
10799
10637
|
const monitor = setInterval(() => {
|
|
10800
|
-
const
|
|
10801
|
-
if (!
|
|
10638
|
+
const current = activeByRoom.get(roomId);
|
|
10639
|
+
if (!current || current.queryId !== control.queryId) {
|
|
10802
10640
|
clearInterval(monitor);
|
|
10803
10641
|
if (leaseMonitors.get(roomId) === monitor)
|
|
10804
10642
|
leaseMonitors.delete(roomId);
|
|
@@ -10820,8 +10658,8 @@ function createRoomQueryRegistry(host) {
|
|
|
10820
10658
|
return true;
|
|
10821
10659
|
}
|
|
10822
10660
|
function clear(roomId, queryId) {
|
|
10823
|
-
const
|
|
10824
|
-
if (
|
|
10661
|
+
const current = activeByRoom.get(roomId);
|
|
10662
|
+
if (current?.queryId === queryId) {
|
|
10825
10663
|
activeByRoom.delete(roomId);
|
|
10826
10664
|
const monitor = leaseMonitors.get(roomId);
|
|
10827
10665
|
if (monitor)
|
|
@@ -10884,43 +10722,12 @@ var init_room_query_registry = () => {};
|
|
|
10884
10722
|
var init_types2 = () => {};
|
|
10885
10723
|
|
|
10886
10724
|
// ../../packages/core/src/query/active-rooms.ts
|
|
10887
|
-
var exports_active_rooms = {};
|
|
10888
|
-
__export(exports_active_rooms, {
|
|
10889
|
-
wsAbortReason: () => wsAbortReason,
|
|
10890
|
-
takeDeferredInject: () => takeDeferredInject,
|
|
10891
|
-
setRoomQuery: () => setRoomQuery,
|
|
10892
|
-
listRunningTopicQueries: () => listRunningTopicQueries,
|
|
10893
|
-
listRunningTopicIds: () => listRunningTopicIds,
|
|
10894
|
-
isolatedTurnRoomId: () => isolatedTurnRoomId,
|
|
10895
|
-
isUserOrigin: () => isUserOrigin,
|
|
10896
|
-
isTopicRunning: () => isTopicRunning,
|
|
10897
|
-
interSessionQueue: () => interSessionQueue,
|
|
10898
|
-
getRoomQueryStatus: () => getRoomQueryStatus,
|
|
10899
|
-
getRoomQuery: () => getRoomQuery,
|
|
10900
|
-
deferInject: () => deferInject,
|
|
10901
|
-
decideNewQuery: () => decideNewQuery,
|
|
10902
|
-
clearRoomQuery: () => clearRoomQuery,
|
|
10903
|
-
cancelDeferredInject: () => cancelDeferredInject,
|
|
10904
|
-
abortRoom: () => abortRoom,
|
|
10905
|
-
abortAllRooms: () => abortAllRooms,
|
|
10906
|
-
InterSessionQueue: () => InterSessionQueue,
|
|
10907
|
-
DeferredInjectBatcher: () => DeferredInjectBatcher
|
|
10908
|
-
});
|
|
10909
10725
|
function getRoomQuery(roomId) {
|
|
10910
10726
|
return roomQueryRegistry.get(roomId);
|
|
10911
10727
|
}
|
|
10912
|
-
function listRunningTopicQueries() {
|
|
10913
|
-
return roomQueryRegistry.listRunningTopicQueries();
|
|
10914
|
-
}
|
|
10915
|
-
function listRunningTopicIds() {
|
|
10916
|
-
return roomQueryRegistry.listRunningTopicIds();
|
|
10917
|
-
}
|
|
10918
10728
|
function isTopicRunning(topicId) {
|
|
10919
10729
|
return roomQueryRegistry.isTopicRunning(topicId);
|
|
10920
10730
|
}
|
|
10921
|
-
function getRoomQueryStatus(topicId, queryId) {
|
|
10922
|
-
return roomQueryRegistry.status(topicId, queryId);
|
|
10923
|
-
}
|
|
10924
10731
|
function setRoomQuery(control) {
|
|
10925
10732
|
return roomQueryRegistry.set(control);
|
|
10926
10733
|
}
|
|
@@ -10930,9 +10737,6 @@ function clearRoomQuery(roomId, queryId) {
|
|
|
10930
10737
|
function abortRoom(roomId, reason = "external" /* External */) {
|
|
10931
10738
|
return roomQueryRegistry.abort(roomId, reason);
|
|
10932
10739
|
}
|
|
10933
|
-
function abortAllRooms(reason = "external" /* External */) {
|
|
10934
|
-
return roomQueryRegistry.abortAll(reason);
|
|
10935
|
-
}
|
|
10936
10740
|
function decideNewQuery(topicId, incomingOrigin) {
|
|
10937
10741
|
return roomQueryRegistry.decide(topicId, incomingOrigin);
|
|
10938
10742
|
}
|
|
@@ -11098,9 +10902,6 @@ function deferInject(inject) {
|
|
|
11098
10902
|
function takeDeferredInject(topicId) {
|
|
11099
10903
|
return interSessionQueue.dequeueAll(topicId);
|
|
11100
10904
|
}
|
|
11101
|
-
function cancelDeferredInject(topicId, requestId) {
|
|
11102
|
-
return interSessionQueue.remove(topicId, requestId) !== undefined;
|
|
11103
|
-
}
|
|
11104
10905
|
function wsAbortReason(reason) {
|
|
11105
10906
|
return reason === "internal" /* Internal */ ? "superseded" : "stopped";
|
|
11106
10907
|
}
|
|
@@ -11393,8 +11194,8 @@ function settleTopicArchiveJob(topicId, archivePath, success) {
|
|
|
11393
11194
|
db.query("UPDATE api_topic_archive_jobs SET status = 'pending', updated_at = ? WHERE topic_id = ? AND archive_path = ?").run(new Date().toISOString(), topicId, archivePath);
|
|
11394
11195
|
return;
|
|
11395
11196
|
}
|
|
11396
|
-
const
|
|
11397
|
-
setTopicArchiveState(topicId, Math.max(
|
|
11197
|
+
const current = getTopicArchiveState(topicId)?.lastArchivedRowid ?? 0;
|
|
11198
|
+
setTopicArchiveState(topicId, Math.max(current, job.last_rowid), job.archive_path);
|
|
11398
11199
|
db.query("DELETE FROM api_topic_archive_jobs WHERE topic_id = ? AND archive_path = ?").run(topicId, archivePath);
|
|
11399
11200
|
})();
|
|
11400
11201
|
}
|
|
@@ -12066,7 +11867,7 @@ function createAskUserRuntime(host) {
|
|
|
12066
11867
|
if (ask.expired || ask.selectedLabel) {
|
|
12067
11868
|
return { ok: false, error: "This question is no longer awaiting an answer." };
|
|
12068
11869
|
}
|
|
12069
|
-
if (!ask.choices.some((
|
|
11870
|
+
if (!ask.choices.some((choice) => choice.label === label)) {
|
|
12070
11871
|
return { ok: false, error: "Invalid choice." };
|
|
12071
11872
|
}
|
|
12072
11873
|
const pending = pendingAsks.get(messageId);
|
|
@@ -12219,8 +12020,8 @@ function createAskUserRuntime(host) {
|
|
|
12219
12020
|
return errorResult(`Error: failed to persist ask_user_question: ${error instanceof Error ? error.message : String(error)}`);
|
|
12220
12021
|
}
|
|
12221
12022
|
let resolveAnswer;
|
|
12222
|
-
const promise = new Promise((
|
|
12223
|
-
resolveAnswer =
|
|
12023
|
+
const promise = new Promise((resolve) => {
|
|
12024
|
+
resolveAnswer = resolve;
|
|
12224
12025
|
});
|
|
12225
12026
|
pendingAsks.set(message.id, {
|
|
12226
12027
|
topicId: ctx.topicId,
|
|
@@ -12422,8 +12223,8 @@ var init_self_schedules = __esm(async () => {
|
|
|
12422
12223
|
});
|
|
12423
12224
|
|
|
12424
12225
|
// ../../packages/core/src/platform/playwright/manager-utils.ts
|
|
12425
|
-
function isLiveOwnedChildProcess(
|
|
12426
|
-
return
|
|
12226
|
+
function isLiveOwnedChildProcess(current, expected) {
|
|
12227
|
+
return current?.process === expected && expected.exitCode === null && expected.signalCode === null && !expected.killed;
|
|
12427
12228
|
}
|
|
12428
12229
|
function matchesSpawnedBrowserHealth(health, expectedSpawnNonce) {
|
|
12429
12230
|
if (!health || typeof health !== "object")
|
|
@@ -12667,10 +12468,10 @@ function findExecutableOnPath(command, environment = process.env) {
|
|
|
12667
12468
|
return null;
|
|
12668
12469
|
}
|
|
12669
12470
|
function resolveHeadedPlaywrightSpawn(command, args, options = {}) {
|
|
12670
|
-
const
|
|
12471
|
+
const platform = options.platform ?? process.platform;
|
|
12671
12472
|
const environment = options.environment ?? process.env;
|
|
12672
12473
|
const hasDisplay = Boolean(environment.DISPLAY?.trim() || environment.WAYLAND_DISPLAY?.trim());
|
|
12673
|
-
if (
|
|
12474
|
+
if (platform !== "linux" || hasDisplay) {
|
|
12674
12475
|
return { command, args: [...args], virtualDisplay: false };
|
|
12675
12476
|
}
|
|
12676
12477
|
const xvfbRun = (options.findExecutable ?? findExecutableOnPath)("xvfb-run", environment);
|
|
@@ -12719,7 +12520,7 @@ async function probeMcpTransport(transport, options = {}) {
|
|
|
12719
12520
|
}
|
|
12720
12521
|
}
|
|
12721
12522
|
async function probePlaywrightMcpTransports(port, capability, fetchImpl = fetch) {
|
|
12722
|
-
const
|
|
12523
|
+
const query = new URLSearchParams({ owner: PROBE_OWNER });
|
|
12723
12524
|
const baseUrl = `http://127.0.0.1:${port}`;
|
|
12724
12525
|
const ownerCapability = browserOwnerCapability(capability, PROBE_OWNER);
|
|
12725
12526
|
const capabilityHeaders = { "X-Browser-Capability": ownerCapability };
|
|
@@ -12728,14 +12529,14 @@ async function probePlaywrightMcpTransports(port, capability, fetchImpl = fetch)
|
|
|
12728
12529
|
headers.set("X-Browser-Capability", ownerCapability);
|
|
12729
12530
|
return fetchImpl(input, { ...init, headers });
|
|
12730
12531
|
};
|
|
12731
|
-
const sseTransport = new SSEClientTransport(new URL(`${baseUrl}/sse?${
|
|
12532
|
+
const sseTransport = new SSEClientTransport(new URL(`${baseUrl}/sse?${query}`), {
|
|
12732
12533
|
fetch: authenticatedFetch,
|
|
12733
12534
|
eventSourceInit: { fetch: authenticatedFetch },
|
|
12734
12535
|
requestInit: { headers: capabilityHeaders }
|
|
12735
12536
|
});
|
|
12736
12537
|
if (!await probeMcpTransport(sseTransport))
|
|
12737
12538
|
return false;
|
|
12738
|
-
const streamableTransport = new StreamableHTTPClientTransport(new URL(`${baseUrl}/mcp?${
|
|
12539
|
+
const streamableTransport = new StreamableHTTPClientTransport(new URL(`${baseUrl}/mcp?${query}`), {
|
|
12739
12540
|
fetch: authenticatedFetch,
|
|
12740
12541
|
requestInit: { headers: capabilityHeaders }
|
|
12741
12542
|
});
|
|
@@ -12865,9 +12666,9 @@ async function createBrowserVaultBroker(userId) {
|
|
|
12865
12666
|
if (typeof request.tool !== "string")
|
|
12866
12667
|
return { id, ok: false, error: "invalid tool" };
|
|
12867
12668
|
const leaseCutoff = Date.now() - LEASE_TTL_MS;
|
|
12868
|
-
for (const [
|
|
12669
|
+
for (const [lease, binding] of leases) {
|
|
12869
12670
|
if (binding.createdAt < leaseCutoff)
|
|
12870
|
-
leases.delete(
|
|
12671
|
+
leases.delete(lease);
|
|
12871
12672
|
}
|
|
12872
12673
|
if (leases.size >= MAX_ACTIVE_LEASES) {
|
|
12873
12674
|
return { id, ok: false, error: "too many active leases" };
|
|
@@ -13400,9 +13201,9 @@ async function spawnPlaywright(instanceKey, ownerId, reservedPort, browserBin =
|
|
|
13400
13201
|
const stderrTail = captureBoundedStderr(proc);
|
|
13401
13202
|
const startup = watchChildStartup(proc, stderrTail);
|
|
13402
13203
|
const reapCrashedBrowser = () => {
|
|
13403
|
-
const
|
|
13404
|
-
managerHost.cleanupBrowserProcessesForDataDir(
|
|
13405
|
-
cleanSingletonFiles(
|
|
13204
|
+
const userDataDir = resolveUserDataDir(instanceKey);
|
|
13205
|
+
managerHost.cleanupBrowserProcessesForDataDir(userDataDir);
|
|
13206
|
+
cleanSingletonFiles(userDataDir);
|
|
13406
13207
|
};
|
|
13407
13208
|
proc.once("error", (err) => {
|
|
13408
13209
|
logger.error({ err, instanceKey, stderr: stderrTail() || undefined }, "Playwright MCP error");
|
|
@@ -13471,8 +13272,8 @@ ${stderrTail()}` : ""));
|
|
|
13471
13272
|
}
|
|
13472
13273
|
async function supportsOwnerCleanup(port, capability) {
|
|
13473
13274
|
try {
|
|
13474
|
-
const
|
|
13475
|
-
const response = await fetch(`http://127.0.0.1:${port}/owners?${
|
|
13275
|
+
const query = new URLSearchParams({ owner: "__negotium_capability_probe__" });
|
|
13276
|
+
const response = await fetch(`http://127.0.0.1:${port}/owners?${query}`, {
|
|
13476
13277
|
method: "DELETE",
|
|
13477
13278
|
headers: {
|
|
13478
13279
|
"X-Browser-Capability": capability
|
|
@@ -13543,8 +13344,8 @@ async function closeBrowserOwnerTabs(ownerId, rawProfile, owner) {
|
|
|
13543
13344
|
if (!instance)
|
|
13544
13345
|
return 0;
|
|
13545
13346
|
const port = instance.port;
|
|
13546
|
-
const
|
|
13547
|
-
const response = await fetch(`http://127.0.0.1:${port}/owners?${
|
|
13347
|
+
const query = new URLSearchParams({ owner });
|
|
13348
|
+
const response = await fetch(`http://127.0.0.1:${port}/owners?${query}`, {
|
|
13548
13349
|
method: "DELETE",
|
|
13549
13350
|
headers: {
|
|
13550
13351
|
"X-Browser-Capability": instance.capability
|
|
@@ -14239,7 +14040,7 @@ async function runIdleCompactForTopic(topicId, userId, options = {}) {
|
|
|
14239
14040
|
return "below-threshold";
|
|
14240
14041
|
}
|
|
14241
14042
|
const compact = options.compact ?? (async (id, actorId, reason) => {
|
|
14242
|
-
|
|
14043
|
+
await init_session();
|
|
14243
14044
|
return compactTopicSession(id, actorId, reason, { preemptive: false });
|
|
14244
14045
|
});
|
|
14245
14046
|
try {
|
|
@@ -14439,40 +14240,40 @@ function beginTransientBackgroundSession(userId, session) {
|
|
|
14439
14240
|
update(status, step) {
|
|
14440
14241
|
if (finished)
|
|
14441
14242
|
return;
|
|
14442
|
-
const
|
|
14443
|
-
if (
|
|
14243
|
+
const current = transientSessions.get(record.id);
|
|
14244
|
+
if (current !== record)
|
|
14444
14245
|
return;
|
|
14445
14246
|
const nextStatus = text(status, 160);
|
|
14446
14247
|
if (nextStatus)
|
|
14447
|
-
|
|
14248
|
+
current.status = nextStatus;
|
|
14448
14249
|
const nextStep = text(step);
|
|
14449
|
-
if (nextStep &&
|
|
14450
|
-
|
|
14250
|
+
if (nextStep && current.steps.at(-1) !== nextStep) {
|
|
14251
|
+
current.steps.push(nextStep);
|
|
14451
14252
|
}
|
|
14452
14253
|
},
|
|
14453
14254
|
setOutput(output) {
|
|
14454
14255
|
if (finished)
|
|
14455
14256
|
return;
|
|
14456
|
-
const
|
|
14457
|
-
if (
|
|
14257
|
+
const current = transientSessions.get(record.id);
|
|
14258
|
+
if (current !== record)
|
|
14458
14259
|
return;
|
|
14459
|
-
|
|
14260
|
+
current.output = output;
|
|
14460
14261
|
},
|
|
14461
14262
|
finish(status, step) {
|
|
14462
14263
|
if (finished)
|
|
14463
14264
|
return;
|
|
14464
14265
|
this.update(status ?? record.status, step);
|
|
14465
14266
|
finished = true;
|
|
14466
|
-
const
|
|
14467
|
-
if (
|
|
14267
|
+
const current = transientSessions.get(record.id);
|
|
14268
|
+
if (current !== record)
|
|
14468
14269
|
return;
|
|
14469
|
-
|
|
14470
|
-
|
|
14471
|
-
|
|
14270
|
+
current.active = false;
|
|
14271
|
+
current.expiresAt = Date.now() + Math.max(0, retentionMs);
|
|
14272
|
+
current.expiryTimer = setTimeout(() => {
|
|
14472
14273
|
if (transientSessions.get(record.id) === record)
|
|
14473
14274
|
transientSessions.delete(record.id);
|
|
14474
14275
|
}, Math.max(0, retentionMs));
|
|
14475
|
-
|
|
14276
|
+
current.expiryTimer.unref?.();
|
|
14476
14277
|
}
|
|
14477
14278
|
};
|
|
14478
14279
|
}
|
|
@@ -14730,8 +14531,8 @@ function markRuntimeUserTurnMessagesLogged(topicId, requestId, ownerId, loggedUs
|
|
|
14730
14531
|
return false;
|
|
14731
14532
|
return db.transaction(() => {
|
|
14732
14533
|
const requests = db.query("SELECT * FROM runtime_user_turn_requests WHERE topic_id = ? ORDER BY created_at ASC, rowid ASC").all(topicId).map(rowToRequest);
|
|
14733
|
-
const hasLoggedPrefix = (
|
|
14734
|
-
const candidate =
|
|
14534
|
+
const hasLoggedPrefix = (request) => loggedUserMessages.length <= request.userMessages.length && loggedUserMessages.every((message, index) => {
|
|
14535
|
+
const candidate = request.userMessages[index];
|
|
14735
14536
|
return candidate?.prompt === message.prompt && candidate.actorUserId === message.actorUserId && candidate.actorLabel === message.actorLabel && JSON.stringify(candidate.attachments ?? []) === JSON.stringify(message.attachments ?? []);
|
|
14736
14537
|
});
|
|
14737
14538
|
const request = requests.find((candidate) => candidate.requestId === requestId && candidate.claimedBy === ownerId && hasLoggedPrefix(candidate)) ?? requests.find((candidate) => candidate.execution?.supersededRequestIds?.includes(requestId) && hasLoggedPrefix(candidate));
|
|
@@ -14749,60 +14550,6 @@ function markRuntimeUserTurnMessagesLogged(topicId, requestId, ownerId, loggedUs
|
|
|
14749
14550
|
return result.changes === 1;
|
|
14750
14551
|
}).immediate();
|
|
14751
14552
|
}
|
|
14752
|
-
function claimNextRuntimeUserTurnRequest(ownerId, now = Date.now()) {
|
|
14753
|
-
return db.transaction(() => {
|
|
14754
|
-
const row = db.query(`SELECT r.*
|
|
14755
|
-
FROM runtime_user_turn_requests r
|
|
14756
|
-
LEFT JOIN runtime_turn_leases l ON l.topic_id = r.topic_id
|
|
14757
|
-
LEFT JOIN runtime_topic_state s ON s.topic_id = r.topic_id
|
|
14758
|
-
WHERE (l.topic_id IS NULL OR l.heartbeat_at < ?)
|
|
14759
|
-
AND (s.topic_id IS NULL OR s.maintenance = 0 OR s.heartbeat_at < ?)
|
|
14760
|
-
AND r.topic_epoch = COALESCE(s.epoch, 0)
|
|
14761
|
-
AND NOT EXISTS (
|
|
14762
|
-
SELECT 1
|
|
14763
|
-
FROM runtime_user_turn_requests active
|
|
14764
|
-
WHERE active.topic_id = r.topic_id
|
|
14765
|
-
AND active.request_id <> r.request_id
|
|
14766
|
-
AND active.claimed_at IS NOT NULL
|
|
14767
|
-
AND active.claimed_at >= ?
|
|
14768
|
-
)
|
|
14769
|
-
AND (
|
|
14770
|
-
(r.status = 'pending' AND (r.claimed_at IS NULL OR r.claimed_at < ?))
|
|
14771
|
-
OR (r.status = 'running' AND (r.claimed_at IS NULL OR r.claimed_at < ?))
|
|
14772
|
-
)
|
|
14773
|
-
ORDER BY r.created_at ASC, r.rowid ASC
|
|
14774
|
-
LIMIT 1`).get(now - TURN_LEASE_STALE_MS, now - TOPIC_MAINTENANCE_STALE_MS, now - REQUEST_CLAIM_STALE_MS, now - REQUEST_CLAIM_STALE_MS, now - REQUEST_CLAIM_STALE_MS);
|
|
14775
|
-
if (!row)
|
|
14776
|
-
return null;
|
|
14777
|
-
const updated = db.query(`UPDATE runtime_user_turn_requests
|
|
14778
|
-
SET claimed_by = ?, claimed_at = ?
|
|
14779
|
-
WHERE request_id = ? AND topic_id = ?
|
|
14780
|
-
AND (
|
|
14781
|
-
(status = 'pending' AND (claimed_at IS NULL OR claimed_at < ?))
|
|
14782
|
-
OR (status = 'running' AND (claimed_at IS NULL OR claimed_at < ?))
|
|
14783
|
-
)`).run(ownerId, now, row.request_id, row.topic_id, now - REQUEST_CLAIM_STALE_MS, now - REQUEST_CLAIM_STALE_MS);
|
|
14784
|
-
if (Number(updated.changes ?? 0) === 0)
|
|
14785
|
-
return null;
|
|
14786
|
-
return rowToRequest({ ...row, claimed_by: ownerId, claimed_at: now });
|
|
14787
|
-
}).immediate();
|
|
14788
|
-
}
|
|
14789
|
-
function markRuntimeUserTurnRunning(topicId, requestId, ownerId, queryId) {
|
|
14790
|
-
const result = db.query(`UPDATE runtime_user_turn_requests
|
|
14791
|
-
SET status = 'running', running_query_id = ?, claimed_at = ?
|
|
14792
|
-
WHERE topic_id = ? AND request_id = ? AND claimed_by = ?`).run(queryId, Date.now(), topicId, requestId, ownerId);
|
|
14793
|
-
return Number(result.changes ?? 0) > 0;
|
|
14794
|
-
}
|
|
14795
|
-
function releaseRuntimeUserTurnClaim(topicId, requestId, ownerId) {
|
|
14796
|
-
const result = db.query(`UPDATE runtime_user_turn_requests
|
|
14797
|
-
SET status = 'pending', claimed_by = NULL, claimed_at = NULL, running_query_id = NULL
|
|
14798
|
-
WHERE topic_id = ? AND request_id = ? AND claimed_by = ?`).run(topicId, requestId, ownerId);
|
|
14799
|
-
return Number(result.changes ?? 0) > 0;
|
|
14800
|
-
}
|
|
14801
|
-
function completeRuntimeUserTurnRequest(topicId, requestId, ownerId) {
|
|
14802
|
-
const result = db.query(`DELETE FROM runtime_user_turn_requests
|
|
14803
|
-
WHERE topic_id = ? AND request_id = ? AND claimed_by = ?`).run(topicId, requestId, ownerId);
|
|
14804
|
-
return Number(result.changes ?? 0) > 0;
|
|
14805
|
-
}
|
|
14806
14553
|
function cancelRuntimeUserTurnRequestsBeforeEpoch(topicId, epoch) {
|
|
14807
14554
|
const rows = db.query("SELECT request_id FROM runtime_user_turn_requests WHERE topic_id = ? AND topic_epoch < ?").all(topicId, epoch);
|
|
14808
14555
|
db.query("DELETE FROM runtime_user_turn_requests WHERE topic_id = ? AND topic_epoch < ?").run(topicId, epoch);
|
|
@@ -14840,36 +14587,10 @@ var init_runtime_turn_requests = __esm(async () => {
|
|
|
14840
14587
|
});
|
|
14841
14588
|
|
|
14842
14589
|
// ../../packages/core/src/topics/session.ts
|
|
14843
|
-
var exports_session = {};
|
|
14844
|
-
__export(exports_session, {
|
|
14845
|
-
splitCompactionPairs: () => splitCompactionPairs,
|
|
14846
|
-
shouldUseCompactionLog: () => shouldUseCompactionLog,
|
|
14847
|
-
shouldCompactForkEntries: () => shouldCompactForkEntries,
|
|
14848
|
-
restartTopicSession: () => restartTopicSession,
|
|
14849
|
-
createCompactedRolloutEntries: () => createCompactedRolloutEntries,
|
|
14850
|
-
compactTopicSession: () => compactTopicSession,
|
|
14851
|
-
COMPACTION_RETAINED_TAIL_TOKENS: () => COMPACTION_RETAINED_TAIL_TOKENS,
|
|
14852
|
-
AUTO_FORK_COMPACTION_TOKENS: () => AUTO_FORK_COMPACTION_TOKENS
|
|
14853
|
-
});
|
|
14854
14590
|
import { randomUUID as randomUUID12 } from "crypto";
|
|
14855
14591
|
import { mkdtempSync as mkdtempSync2, rmSync as rmSync4, writeFileSync as writeFileSync12 } from "fs";
|
|
14856
14592
|
import { tmpdir as tmpdir4 } from "os";
|
|
14857
14593
|
import { join as join23 } from "path";
|
|
14858
|
-
async function waitForMemoryArchive(settled, timeoutMs) {
|
|
14859
|
-
let timer;
|
|
14860
|
-
try {
|
|
14861
|
-
return await Promise.race([
|
|
14862
|
-
settled.then(() => true),
|
|
14863
|
-
new Promise((resolve17) => {
|
|
14864
|
-
timer = setTimeout(() => resolve17(false), timeoutMs);
|
|
14865
|
-
timer.unref?.();
|
|
14866
|
-
})
|
|
14867
|
-
]);
|
|
14868
|
-
} finally {
|
|
14869
|
-
if (timer)
|
|
14870
|
-
clearTimeout(timer);
|
|
14871
|
-
}
|
|
14872
|
-
}
|
|
14873
14594
|
async function fenceTopicWork(topicId, maintenance) {
|
|
14874
14595
|
for (const queryId of cancelRuntimeUserTurnRequestsBeforeEpoch(topicId, maintenance.epoch)) {
|
|
14875
14596
|
WsHub.get().broadcastAborted(topicId, queryId, "stopped");
|
|
@@ -14894,97 +14615,6 @@ function hasTopicWorkInFlight(topicId) {
|
|
|
14894
14615
|
function topicIsQuiescedForNonPreemptiveWork(topicId) {
|
|
14895
14616
|
return !hasTopicWorkInFlight(topicId);
|
|
14896
14617
|
}
|
|
14897
|
-
async function restartTopicSession(topicId, userId, reason = "topic-session-restart", options = {}) {
|
|
14898
|
-
const topic = getTopic(topicId);
|
|
14899
|
-
if (!topic)
|
|
14900
|
-
return { text: "Topic not found.", isError: true };
|
|
14901
|
-
if (isLegacySharedGeneral(topic.id)) {
|
|
14902
|
-
return { text: "The legacy shared General session cannot be reset.", isError: true };
|
|
14903
|
-
}
|
|
14904
|
-
const owner = topic.participants.some((participant) => participant.userId === userId && participant.role === "owner");
|
|
14905
|
-
if (!owner)
|
|
14906
|
-
return { text: "Only the topic owner can reset the session.", isError: true };
|
|
14907
|
-
const maintenance = beginRuntimeTopicMaintenance(topicId);
|
|
14908
|
-
if (!maintenance)
|
|
14909
|
-
return { text: "Topic maintenance is already in progress.", isError: true };
|
|
14910
|
-
try {
|
|
14911
|
-
const fenceError = await fenceTopicWork(topicId, maintenance);
|
|
14912
|
-
if (fenceError)
|
|
14913
|
-
return { text: fenceError, isError: true };
|
|
14914
|
-
cancelIdleArchiveForTopic(topicId);
|
|
14915
|
-
cancelIdleCompactForTopic(topicId);
|
|
14916
|
-
const rawArchivePaths = [];
|
|
14917
|
-
try {
|
|
14918
|
-
for (const participantUserId of new Set([
|
|
14919
|
-
userId,
|
|
14920
|
-
...topic.participants.map((participant) => participant.userId)
|
|
14921
|
-
])) {
|
|
14922
|
-
const archived = archiveConversationEvents(topicId, topic.title, participantUserId, {
|
|
14923
|
-
reason: "reset"
|
|
14924
|
-
});
|
|
14925
|
-
if (archived)
|
|
14926
|
-
rawArchivePaths.push(archived.path);
|
|
14927
|
-
}
|
|
14928
|
-
} catch (error) {
|
|
14929
|
-
return {
|
|
14930
|
-
text: `Session reset could not archive the raw conversation: ${error instanceof Error ? error.message : String(error)}`,
|
|
14931
|
-
isError: true
|
|
14932
|
-
};
|
|
14933
|
-
}
|
|
14934
|
-
let settleMemoryArchive;
|
|
14935
|
-
const memoryArchiveSettled = new Promise((resolve17) => {
|
|
14936
|
-
settleMemoryArchive = resolve17;
|
|
14937
|
-
});
|
|
14938
|
-
const archiveStatus = (options.archiveMemory ?? archiveActiveTopicForMemory)(topicId, options.memoryUserId ?? userId, {
|
|
14939
|
-
reason: "reset",
|
|
14940
|
-
minMessages: 1,
|
|
14941
|
-
minExchanges: MIN_MEMORY_ARCHIVE_EXCHANGES,
|
|
14942
|
-
allowMentionOnly: true,
|
|
14943
|
-
skipBusyCheck: true,
|
|
14944
|
-
rawArchivePaths,
|
|
14945
|
-
onSettled: () => settleMemoryArchive?.()
|
|
14946
|
-
});
|
|
14947
|
-
if (archiveStatus === "archived") {
|
|
14948
|
-
const archiveFinished = await waitForMemoryArchive(memoryArchiveSettled, options.memoryArchiveWaitMs ?? RESET_MEMORY_ARCHIVE_WAIT_MS);
|
|
14949
|
-
if (!archiveFinished) {
|
|
14950
|
-
return {
|
|
14951
|
-
text: "Memory archiving did not finish in time. The session was not reset.",
|
|
14952
|
-
isError: true
|
|
14953
|
-
};
|
|
14954
|
-
}
|
|
14955
|
-
}
|
|
14956
|
-
if (!maintenance.isOwned()) {
|
|
14957
|
-
return { text: "Topic maintenance ownership was lost. Try again.", isError: true };
|
|
14958
|
-
}
|
|
14959
|
-
const sessionId = getTopicSessionId(topicId);
|
|
14960
|
-
const purgeLogs = options.purgeLogs ?? purgeTopicLogs;
|
|
14961
|
-
const participantUserIds = Array.from(new Set([userId, ...topic.participants.map((participant) => participant.userId)]));
|
|
14962
|
-
for (const [index, participantUserId] of participantUserIds.entries()) {
|
|
14963
|
-
let purged = false;
|
|
14964
|
-
try {
|
|
14965
|
-
purged = await purgeLogs({
|
|
14966
|
-
userId: participantUserId,
|
|
14967
|
-
topicName: topic.title,
|
|
14968
|
-
cwd: resolveTopicWorkspaceDir(topicId),
|
|
14969
|
-
extraSessions: index === 0 && topic.agent && sessionId ? [{ agent: topic.agent, sessionId }] : []
|
|
14970
|
-
});
|
|
14971
|
-
} catch (error) {
|
|
14972
|
-
logger.warn({ err: error, topicId, userId: participantUserId }, "restartTopicSession: participant context cleanup failed");
|
|
14973
|
-
}
|
|
14974
|
-
if (!purged) {
|
|
14975
|
-
return {
|
|
14976
|
-
text: "Session reset could not remove all provider context. The current session was kept.",
|
|
14977
|
-
isError: true
|
|
14978
|
-
};
|
|
14979
|
-
}
|
|
14980
|
-
}
|
|
14981
|
-
clearTopicSessionId(topicId, reason);
|
|
14982
|
-
clearQueryUsageAlert(userId, topicId);
|
|
14983
|
-
return { text: `Session reset for "${topic.title}". The next message starts fresh.` };
|
|
14984
|
-
} finally {
|
|
14985
|
-
maintenance.finish();
|
|
14986
|
-
}
|
|
14987
|
-
}
|
|
14988
14618
|
function previousCompactedSummary(entries) {
|
|
14989
14619
|
for (let index = entries.length - 2;index >= 0; index -= 1) {
|
|
14990
14620
|
const request = entries[index]?.event;
|
|
@@ -14999,9 +14629,9 @@ The assistant response is the authoritative summary of all earlier context.` &&
|
|
|
14999
14629
|
function withoutCompactionSentinels(entries) {
|
|
15000
14630
|
const filtered = [];
|
|
15001
14631
|
for (let index = 0;index < entries.length; index++) {
|
|
15002
|
-
const
|
|
14632
|
+
const current = entries[index]?.event;
|
|
15003
14633
|
const next = entries[index + 1]?.event;
|
|
15004
|
-
if (
|
|
14634
|
+
if (current?.type === "user_message" && current.synthetic === "compaction" && next?.type === "result") {
|
|
15005
14635
|
index += 1;
|
|
15006
14636
|
continue;
|
|
15007
14637
|
}
|
|
@@ -15051,18 +14681,18 @@ function retainedPairEntries(agent, pairs) {
|
|
|
15051
14681
|
}
|
|
15052
14682
|
return entries;
|
|
15053
14683
|
}
|
|
15054
|
-
function fitCompactionChunk(
|
|
15055
|
-
if (
|
|
15056
|
-
return
|
|
14684
|
+
function fitCompactionChunk(text, limit) {
|
|
14685
|
+
if (text.length <= limit)
|
|
14686
|
+
return text;
|
|
15057
14687
|
const marker = `
|
|
15058
14688
|
[\u2026]
|
|
15059
14689
|
`;
|
|
15060
14690
|
if (limit <= marker.length)
|
|
15061
|
-
return
|
|
14691
|
+
return text.slice(0, limit);
|
|
15062
14692
|
const available = limit - marker.length;
|
|
15063
14693
|
const headChars = Math.ceil(available * 0.6);
|
|
15064
14694
|
const tailChars = available - headChars;
|
|
15065
|
-
return `${
|
|
14695
|
+
return `${text.slice(0, headChars)}${marker}${text.slice(-tailChars)}`;
|
|
15066
14696
|
}
|
|
15067
14697
|
function buildCompactionSource(topicId, userId, entries, visibleMessages, providerPairs) {
|
|
15068
14698
|
const sections = [];
|
|
@@ -15463,9 +15093,9 @@ async function compactTopicSession(topicId, userId, reason = "topic-session-comp
|
|
|
15463
15093
|
const compactionExecution = resolveCompactionExecution(agent, registry);
|
|
15464
15094
|
const cwd = resolveTopicWorkspaceDir(topicId);
|
|
15465
15095
|
const oldEntries = readConversation(userId, topic.title);
|
|
15466
|
-
let
|
|
15096
|
+
let compactEntries;
|
|
15467
15097
|
try {
|
|
15468
|
-
|
|
15098
|
+
compactEntries = await createCompactedRolloutEntries({
|
|
15469
15099
|
topicId,
|
|
15470
15100
|
topicTitle: topic.title,
|
|
15471
15101
|
userId,
|
|
@@ -15491,7 +15121,7 @@ async function compactTopicSession(topicId, userId, reason = "topic-session-comp
|
|
|
15491
15121
|
try {
|
|
15492
15122
|
replacement = getRegistryOperations(agent).writeRollout({
|
|
15493
15123
|
cwd,
|
|
15494
|
-
entries:
|
|
15124
|
+
entries: compactEntries,
|
|
15495
15125
|
model,
|
|
15496
15126
|
...effort ? { effort } : {}
|
|
15497
15127
|
});
|
|
@@ -15521,7 +15151,7 @@ async function compactTopicSession(topicId, userId, reason = "topic-session-comp
|
|
|
15521
15151
|
}
|
|
15522
15152
|
try {
|
|
15523
15153
|
replaceConversationStrict(userId, topic.title, [
|
|
15524
|
-
...
|
|
15154
|
+
...compactEntries,
|
|
15525
15155
|
...priorSessionEntries,
|
|
15526
15156
|
replacementSessionEntry
|
|
15527
15157
|
]);
|
|
@@ -15558,7 +15188,7 @@ async function compactTopicSession(topicId, userId, reason = "topic-session-comp
|
|
|
15558
15188
|
} else {
|
|
15559
15189
|
try {
|
|
15560
15190
|
replaceConversationStrict(userId, topic.title, [
|
|
15561
|
-
...
|
|
15191
|
+
...compactEntries,
|
|
15562
15192
|
replacementSessionEntry
|
|
15563
15193
|
]);
|
|
15564
15194
|
} catch (manifestError) {
|
|
@@ -15612,45 +15242,11 @@ var init_session = __esm(async () => {
|
|
|
15612
15242
|
});
|
|
15613
15243
|
|
|
15614
15244
|
// ../../packages/core/src/topics/derive.ts
|
|
15615
|
-
var exports_derive = {};
|
|
15616
|
-
__export(exports_derive, {
|
|
15617
|
-
updateTopic: () => updateTopic,
|
|
15618
|
-
isParticipant: () => isParticipant,
|
|
15619
|
-
getVisibleTopics: () => getVisibleTopics,
|
|
15620
|
-
getTopics: () => getTopics,
|
|
15621
|
-
createDerivedTopic: () => createDerivedTopic,
|
|
15622
|
-
TopicTitleConflictError: () => TopicTitleConflictError,
|
|
15623
|
-
TopicForkCompactionError: () => TopicForkCompactionError,
|
|
15624
|
-
TopicDeriveBusyError: () => TopicDeriveBusyError
|
|
15625
|
-
});
|
|
15626
15245
|
import { createHash as createHash9, randomUUID as randomUUID13 } from "crypto";
|
|
15627
15246
|
import { mkdirSync as mkdirSync14, rmSync as rmSync5, unlinkSync as unlinkSync13 } from "fs";
|
|
15628
15247
|
function getTopics(opts = {}) {
|
|
15629
15248
|
return listTopics(opts).filter((topic) => !isLegacySharedGeneral(topic.id));
|
|
15630
15249
|
}
|
|
15631
|
-
function getVisibleTopics(opts = {}) {
|
|
15632
|
-
return getTopics(opts).filter(isTopicVisible).map((topic) => {
|
|
15633
|
-
if (!topic.agent)
|
|
15634
|
-
return topic;
|
|
15635
|
-
const registry = getRegistry(topic.agent);
|
|
15636
|
-
const config = getApiTopicConfig(topic.id);
|
|
15637
|
-
const requestedEffort = config?.effort ?? topic.defaultEffort;
|
|
15638
|
-
return {
|
|
15639
|
-
...topic,
|
|
15640
|
-
effectiveModel: resolveModelForAgent(topic.agent, config?.model ?? topic.defaultModel, registry),
|
|
15641
|
-
effectiveEffort: requestedEffort && registry.validateEffort(requestedEffort) ? requestedEffort : registry.defaultEffort
|
|
15642
|
-
};
|
|
15643
|
-
});
|
|
15644
|
-
}
|
|
15645
|
-
function updateTopic(topicId, patch) {
|
|
15646
|
-
const topic = getTopic(topicId);
|
|
15647
|
-
if (!topic)
|
|
15648
|
-
return false;
|
|
15649
|
-
Object.assign(topic, patch);
|
|
15650
|
-
upsertTopic(topic);
|
|
15651
|
-
WsHub.get().broadcastTopicUpdated(topicId);
|
|
15652
|
-
return true;
|
|
15653
|
-
}
|
|
15654
15250
|
function isParticipant(topic, userId) {
|
|
15655
15251
|
return topic.participants.some((p) => p.userId === userId);
|
|
15656
15252
|
}
|
|
@@ -16066,9 +15662,9 @@ function subagentLineageTopicIds(currentTopicId) {
|
|
|
16066
15662
|
const children = new Set;
|
|
16067
15663
|
if (!currentTopicId)
|
|
16068
15664
|
return { reachable, children };
|
|
16069
|
-
const
|
|
16070
|
-
if (
|
|
16071
|
-
reachable.add(
|
|
15665
|
+
const current = getTopic(currentTopicId);
|
|
15666
|
+
if (current?.isSubagent && current.parentTopicId) {
|
|
15667
|
+
reachable.add(current.parentTopicId);
|
|
16072
15668
|
for (const id of listSubagentTellTargetIds(currentTopicId))
|
|
16073
15669
|
reachable.add(id);
|
|
16074
15670
|
}
|
|
@@ -16194,9 +15790,9 @@ function cleanupSessionInboxFiles(userId, topicId, legacyTopicTitle) {
|
|
|
16194
15790
|
try {
|
|
16195
15791
|
unlinkSync15(path);
|
|
16196
15792
|
deleted++;
|
|
16197
|
-
} catch (
|
|
16198
|
-
if (
|
|
16199
|
-
logger.warn({ err
|
|
15793
|
+
} catch (err) {
|
|
15794
|
+
if (err?.code !== "ENOENT") {
|
|
15795
|
+
logger.warn({ err, path, topicId, userId }, "topic cleanup: inbox unlink failed");
|
|
16200
15796
|
}
|
|
16201
15797
|
}
|
|
16202
15798
|
}
|
|
@@ -16321,9 +15917,9 @@ function hubHeaders(bearer) {
|
|
|
16321
15917
|
};
|
|
16322
15918
|
}
|
|
16323
15919
|
function errorText(status, body, fallback) {
|
|
16324
|
-
const
|
|
16325
|
-
if (typeof
|
|
16326
|
-
return
|
|
15920
|
+
const text = body?.error;
|
|
15921
|
+
if (typeof text === "string" && text.trim())
|
|
15922
|
+
return text.trim();
|
|
16327
15923
|
return `${fallback} (hub answered ${status})`;
|
|
16328
15924
|
}
|
|
16329
15925
|
function describeFailure(status, body) {
|
|
@@ -16419,19 +16015,6 @@ var init_actor_policy = __esm(async () => {
|
|
|
16419
16015
|
await init_actor_topic_reach();
|
|
16420
16016
|
});
|
|
16421
16017
|
// ../../packages/core/src/storage/session-asks.ts
|
|
16422
|
-
var exports_session_asks = {};
|
|
16423
|
-
__export(exports_session_asks, {
|
|
16424
|
-
releasePendingAsk: () => releasePendingAsk,
|
|
16425
|
-
markPendingAskState: () => markPendingAskState,
|
|
16426
|
-
markPendingAskSources: () => markPendingAskSources,
|
|
16427
|
-
listPendingAsksForCaller: () => listPendingAsksForCaller,
|
|
16428
|
-
describePendingAskState: () => describePendingAskState,
|
|
16429
|
-
deletePendingAsksForTopic: () => deletePendingAsksForTopic,
|
|
16430
|
-
createPendingAsk: () => createPendingAsk,
|
|
16431
|
-
clearPendingAskSources: () => clearPendingAskSources,
|
|
16432
|
-
clearPendingAsk: () => clearPendingAsk,
|
|
16433
|
-
PENDING_ASK_TTL_MS: () => PENDING_ASK_TTL_MS
|
|
16434
|
-
});
|
|
16435
16018
|
import { createHash as createHash10 } from "crypto";
|
|
16436
16019
|
import {
|
|
16437
16020
|
closeSync as closeSync2,
|
|
@@ -16453,8 +16036,8 @@ function encodeAskKey(key) {
|
|
|
16453
16036
|
return JSON.stringify([key.from, key.to]);
|
|
16454
16037
|
}
|
|
16455
16038
|
function pendingAskPath(key) {
|
|
16456
|
-
const
|
|
16457
|
-
return join28(pendingAskDir(key.userId), `${ASK_FILENAME_PREFIX}${
|
|
16039
|
+
const digest = createHash10("sha256").update(encodeAskKey(key)).digest("hex");
|
|
16040
|
+
return join28(pendingAskDir(key.userId), `${ASK_FILENAME_PREFIX}${digest}.pending`);
|
|
16458
16041
|
}
|
|
16459
16042
|
function v2PendingAskPath(key) {
|
|
16460
16043
|
const encoded = Buffer.from(encodeAskKey(key), "utf8").toString("base64url");
|
|
@@ -16480,10 +16063,10 @@ function parsePendingAskFilename(fileName) {
|
|
|
16480
16063
|
}
|
|
16481
16064
|
} catch {}
|
|
16482
16065
|
}
|
|
16483
|
-
const
|
|
16484
|
-
if (
|
|
16066
|
+
const sep = raw.indexOf("___");
|
|
16067
|
+
if (sep < 0)
|
|
16485
16068
|
return null;
|
|
16486
|
-
return { from: raw.slice(0,
|
|
16069
|
+
return { from: raw.slice(0, sep), to: raw.slice(sep + 3) };
|
|
16487
16070
|
}
|
|
16488
16071
|
function readPendingAskFile(path, fallback) {
|
|
16489
16072
|
try {
|
|
@@ -16526,16 +16109,6 @@ function readPendingAskFile(path, fallback) {
|
|
|
16526
16109
|
return null;
|
|
16527
16110
|
}
|
|
16528
16111
|
}
|
|
16529
|
-
function isStale(record, path) {
|
|
16530
|
-
const ts = record ? Date.parse(record.updatedAt || record.createdAt) : Number.NaN;
|
|
16531
|
-
if (Number.isFinite(ts))
|
|
16532
|
-
return Date.now() - ts > PENDING_ASK_TTL_MS;
|
|
16533
|
-
try {
|
|
16534
|
-
return Date.now() - statSync8(path).mtimeMs > PENDING_ASK_TTL_MS;
|
|
16535
|
-
} catch {
|
|
16536
|
-
return false;
|
|
16537
|
-
}
|
|
16538
|
-
}
|
|
16539
16112
|
function writePendingAsk(record) {
|
|
16540
16113
|
const path = pendingAskPath(record);
|
|
16541
16114
|
mkdirSync16(pendingAskDir(record.userId), { recursive: true });
|
|
@@ -16561,10 +16134,10 @@ function writePendingAskIfAbsent(record) {
|
|
|
16561
16134
|
}
|
|
16562
16135
|
}
|
|
16563
16136
|
function readPendingAsk(key) {
|
|
16564
|
-
const
|
|
16565
|
-
const canonical = readPendingAskFile(
|
|
16137
|
+
const canonicalPath = pendingAskPath(key);
|
|
16138
|
+
const canonical = readPendingAskFile(canonicalPath, key);
|
|
16566
16139
|
if (canonical && canonical.from === key.from && canonical.to === key.to) {
|
|
16567
|
-
return { path:
|
|
16140
|
+
return { path: canonicalPath, record: canonical };
|
|
16568
16141
|
}
|
|
16569
16142
|
for (const compatibilityPath of [v2PendingAskPath(key), legacyPendingAskPath(key)]) {
|
|
16570
16143
|
if (!compatibilityPath)
|
|
@@ -16573,67 +16146,17 @@ function readPendingAsk(key) {
|
|
|
16573
16146
|
if (!legacy || legacy.from !== key.from || legacy.to !== key.to)
|
|
16574
16147
|
continue;
|
|
16575
16148
|
const migrated = writePendingAskIfAbsent(legacy);
|
|
16576
|
-
const next = migrated ? legacy : readPendingAskFile(
|
|
16149
|
+
const next = migrated ? legacy : readPendingAskFile(canonicalPath, key);
|
|
16577
16150
|
if (next && next.from === key.from && next.to === key.to) {
|
|
16578
16151
|
try {
|
|
16579
16152
|
unlinkSync16(compatibilityPath);
|
|
16580
16153
|
} catch {}
|
|
16581
|
-
return { path:
|
|
16154
|
+
return { path: canonicalPath, record: next };
|
|
16582
16155
|
}
|
|
16583
16156
|
return { path: compatibilityPath, record: legacy };
|
|
16584
16157
|
}
|
|
16585
16158
|
return null;
|
|
16586
16159
|
}
|
|
16587
|
-
function createPendingAsk(args) {
|
|
16588
|
-
const migrated = readPendingAsk(args);
|
|
16589
|
-
if (migrated && !isStale(migrated.record, migrated.path)) {
|
|
16590
|
-
return { ok: false, existing: migrated.record, stale: false };
|
|
16591
|
-
}
|
|
16592
|
-
if (migrated) {
|
|
16593
|
-
try {
|
|
16594
|
-
unlinkSync16(migrated.path);
|
|
16595
|
-
} catch {
|
|
16596
|
-
return { ok: false, existing: migrated.record, stale: true };
|
|
16597
|
-
}
|
|
16598
|
-
}
|
|
16599
|
-
const path = pendingAskPath(args);
|
|
16600
|
-
const now = new Date().toISOString();
|
|
16601
|
-
const record = {
|
|
16602
|
-
userId: args.userId,
|
|
16603
|
-
from: args.from,
|
|
16604
|
-
to: args.to,
|
|
16605
|
-
requestId: args.requestId,
|
|
16606
|
-
contextId: args.contextId,
|
|
16607
|
-
state: "requested",
|
|
16608
|
-
createdAt: now,
|
|
16609
|
-
updatedAt: now
|
|
16610
|
-
};
|
|
16611
|
-
mkdirSync16(pendingAskDir(args.userId), { recursive: true });
|
|
16612
|
-
for (let attempt = 0;attempt < 2; attempt++) {
|
|
16613
|
-
let fd = null;
|
|
16614
|
-
try {
|
|
16615
|
-
fd = openSync2(path, "wx");
|
|
16616
|
-
writeFileSync14(fd, `${JSON.stringify(record)}
|
|
16617
|
-
`);
|
|
16618
|
-
return { ok: true, record };
|
|
16619
|
-
} catch (err2) {
|
|
16620
|
-
if (err2.code !== "EEXIST")
|
|
16621
|
-
throw err2;
|
|
16622
|
-
const existing = readPendingAskFile(path, args);
|
|
16623
|
-
if (!isStale(existing, path))
|
|
16624
|
-
return { ok: false, existing, stale: false };
|
|
16625
|
-
try {
|
|
16626
|
-
unlinkSync16(path);
|
|
16627
|
-
} catch {
|
|
16628
|
-
return { ok: false, existing, stale: true };
|
|
16629
|
-
}
|
|
16630
|
-
} finally {
|
|
16631
|
-
if (fd !== null)
|
|
16632
|
-
closeSync2(fd);
|
|
16633
|
-
}
|
|
16634
|
-
}
|
|
16635
|
-
return { ok: false, existing: readPendingAskFile(path, args), stale: true };
|
|
16636
|
-
}
|
|
16637
16160
|
function markPendingAskState(args) {
|
|
16638
16161
|
const pending = readPendingAsk(args);
|
|
16639
16162
|
if (!pending)
|
|
@@ -16667,83 +16190,6 @@ function clearPendingAsk(args) {
|
|
|
16667
16190
|
return false;
|
|
16668
16191
|
}
|
|
16669
16192
|
}
|
|
16670
|
-
function releasePendingAsk(args) {
|
|
16671
|
-
if (clearPendingAsk(args))
|
|
16672
|
-
return true;
|
|
16673
|
-
const still = readPendingAsk(args);
|
|
16674
|
-
return !still || still.record.requestId !== args.requestId;
|
|
16675
|
-
}
|
|
16676
|
-
function markPendingAskSources(args) {
|
|
16677
|
-
for (const source of args.sources ?? []) {
|
|
16678
|
-
if (!source.from)
|
|
16679
|
-
continue;
|
|
16680
|
-
markPendingAskState({
|
|
16681
|
-
userId: args.userId,
|
|
16682
|
-
from: args.callerTopic,
|
|
16683
|
-
to: source.from,
|
|
16684
|
-
requestId: source.requestId,
|
|
16685
|
-
state: args.state
|
|
16686
|
-
});
|
|
16687
|
-
}
|
|
16688
|
-
}
|
|
16689
|
-
function clearPendingAskSources(args) {
|
|
16690
|
-
for (const source of args.sources ?? []) {
|
|
16691
|
-
if (!source.from)
|
|
16692
|
-
continue;
|
|
16693
|
-
clearPendingAsk({
|
|
16694
|
-
userId: args.userId,
|
|
16695
|
-
from: args.callerTopic,
|
|
16696
|
-
to: source.from,
|
|
16697
|
-
requestId: source.requestId
|
|
16698
|
-
});
|
|
16699
|
-
}
|
|
16700
|
-
}
|
|
16701
|
-
function listPendingAsksForCaller(args) {
|
|
16702
|
-
const dir = pendingAskDir(args.userId);
|
|
16703
|
-
let files;
|
|
16704
|
-
try {
|
|
16705
|
-
files = readdirSync4(dir);
|
|
16706
|
-
} catch {
|
|
16707
|
-
return [];
|
|
16708
|
-
}
|
|
16709
|
-
const records = new Map;
|
|
16710
|
-
for (const fileName of files) {
|
|
16711
|
-
const isV3 = fileName.startsWith(ASK_FILENAME_PREFIX);
|
|
16712
|
-
const parsed = isV3 ? { from: args.from, to: "" } : parsePendingAskFilename(fileName);
|
|
16713
|
-
if (!parsed)
|
|
16714
|
-
continue;
|
|
16715
|
-
const path = join28(dir, fileName);
|
|
16716
|
-
const record = readPendingAskFile(path, {
|
|
16717
|
-
userId: args.userId,
|
|
16718
|
-
from: parsed.from,
|
|
16719
|
-
to: parsed.to
|
|
16720
|
-
});
|
|
16721
|
-
if (!record || record.from !== args.from)
|
|
16722
|
-
continue;
|
|
16723
|
-
if (isStale(record, path)) {
|
|
16724
|
-
try {
|
|
16725
|
-
unlinkSync16(path);
|
|
16726
|
-
} catch {}
|
|
16727
|
-
continue;
|
|
16728
|
-
}
|
|
16729
|
-
const canonical = readPendingAsk(record);
|
|
16730
|
-
if (!canonical || canonical.record.from !== args.from)
|
|
16731
|
-
continue;
|
|
16732
|
-
if (path !== canonical.path) {
|
|
16733
|
-
try {
|
|
16734
|
-
unlinkSync16(path);
|
|
16735
|
-
} catch {}
|
|
16736
|
-
}
|
|
16737
|
-
if (isStale(canonical.record, canonical.path)) {
|
|
16738
|
-
try {
|
|
16739
|
-
unlinkSync16(canonical.path);
|
|
16740
|
-
} catch {}
|
|
16741
|
-
continue;
|
|
16742
|
-
}
|
|
16743
|
-
records.set(encodeAskKey(canonical.record), canonical.record);
|
|
16744
|
-
}
|
|
16745
|
-
return [...records.values()];
|
|
16746
|
-
}
|
|
16747
16193
|
function deletePendingAsksForTopic(args) {
|
|
16748
16194
|
const dir = pendingAskDir(args.userId);
|
|
16749
16195
|
let files;
|
|
@@ -16772,18 +16218,6 @@ function deletePendingAsksForTopic(args) {
|
|
|
16772
16218
|
}
|
|
16773
16219
|
return deleted;
|
|
16774
16220
|
}
|
|
16775
|
-
function describePendingAskState(state) {
|
|
16776
|
-
switch (state) {
|
|
16777
|
-
case "requested":
|
|
16778
|
-
return "\uB300\uC0C1 \uC138\uC158 \uCC98\uB9AC \uC911";
|
|
16779
|
-
case "reply_ready":
|
|
16780
|
-
return "\uC751\uB2F5 \uC0DD\uC131 \uC644\uB8CC, \uC774 \uC138\uC158 \uC8FC\uC785 \uC900\uBE44 \uC911";
|
|
16781
|
-
case "queued_for_caller":
|
|
16782
|
-
return "\uC751\uB2F5 \uC0DD\uC131 \uC644\uB8CC, \uC774 \uC138\uC158 \uC2E4\uD589 \uC885\uB8CC \uD6C4 \uC8FC\uC785 \uB300\uAE30 \uC911";
|
|
16783
|
-
case "injecting_to_caller":
|
|
16784
|
-
return "\uC751\uB2F5\uC744 \uC774 \uC138\uC158\uC5D0 \uC8FC\uC785 \uC911";
|
|
16785
|
-
}
|
|
16786
|
-
}
|
|
16787
16221
|
var PENDING_ASK_TTL_MS, ASK_FILENAME_PREFIX = "v3-", V2_ASK_FILENAME_PREFIX = "v2-";
|
|
16788
16222
|
var init_session_asks = __esm(async () => {
|
|
16789
16223
|
await init_storage_host();
|
|
@@ -16885,10 +16319,10 @@ function deferRemoteSessionReplyOutbox(args) {
|
|
|
16885
16319
|
if (!row)
|
|
16886
16320
|
return;
|
|
16887
16321
|
const attempts = Number(row.attempts) + 1;
|
|
16888
|
-
const
|
|
16322
|
+
const delay = args.retryMs ?? remoteSessionRetryDelayMs(attempts, args.random);
|
|
16889
16323
|
db.query(`UPDATE remote_session_reply_outbox
|
|
16890
16324
|
SET attempts = ?, next_attempt_at = ?, last_error = ?
|
|
16891
|
-
WHERE request_id = ?`).run(attempts, now +
|
|
16325
|
+
WHERE request_id = ?`).run(attempts, now + delay, args.error.slice(0, 500), args.requestId);
|
|
16892
16326
|
})();
|
|
16893
16327
|
}
|
|
16894
16328
|
function purgeExpiredRemoteSessionReplyOutbox(now = Date.now()) {
|
|
@@ -17059,37 +16493,9 @@ var init_remote_session_reply_outbox = __esm(async () => {
|
|
|
17059
16493
|
});
|
|
17060
16494
|
|
|
17061
16495
|
// ../../packages/core/src/mcp/session-comm/peer-forward.ts
|
|
17062
|
-
var exports_peer_forward = {};
|
|
17063
|
-
__export(exports_peer_forward, {
|
|
17064
|
-
registerPeerSessionBridge: () => registerPeerSessionBridge,
|
|
17065
|
-
peerSessionsForUser: () => peerSessionsForUser,
|
|
17066
|
-
parseHubRemoteReplyRoute: () => parseHubRemoteReplyRoute,
|
|
17067
|
-
isHubRemoteReplyRoute: () => isHubRemoteReplyRoute,
|
|
17068
|
-
forwardToPeer: () => forwardToPeer,
|
|
17069
|
-
deliverPeerReply: () => deliverPeerReply
|
|
17070
|
-
});
|
|
17071
16496
|
function isHubRemoteReplyRoute(route) {
|
|
17072
16497
|
return route.via === "hub";
|
|
17073
16498
|
}
|
|
17074
|
-
function parseHubRemoteReplyRoute(value) {
|
|
17075
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
17076
|
-
return null;
|
|
17077
|
-
const route = value;
|
|
17078
|
-
if (route.via !== "hub" || typeof route.hubUrl !== "string" || typeof route.token !== "string" || typeof route.nodeName !== "string" || typeof route.topicId !== "string" || typeof route.requestId !== "string") {
|
|
17079
|
-
return null;
|
|
17080
|
-
}
|
|
17081
|
-
const requestId = route.requestId.trim();
|
|
17082
|
-
const nodeName = route.nodeName.trim();
|
|
17083
|
-
const topicId = route.topicId.trim();
|
|
17084
|
-
const token = route.token.trim();
|
|
17085
|
-
if (!requestId || requestId.length > MAX_ROUTE_REQUEST_ID_LENGTH || !nodeName || nodeName.length > MAX_ROUTE_LABEL_LENGTH || !topicId || topicId.length > MAX_ROUTE_LABEL_LENGTH || token.length > MAX_REMOTE_SESSION_REPLY_TOKEN_LENGTH || !REMOTE_SESSION_REPLY_TOKEN_PATTERN.test(token)) {
|
|
17086
|
-
return null;
|
|
17087
|
-
}
|
|
17088
|
-
const hubUrl = normalizeHubUrl(route.hubUrl.trim(), "remoteReply.hubUrl");
|
|
17089
|
-
if ("error" in hubUrl)
|
|
17090
|
-
return null;
|
|
17091
|
-
return { via: "hub", hubUrl: hubUrl.url, token, nodeName, topicId, requestId };
|
|
17092
|
-
}
|
|
17093
16499
|
function loopbackBridgeConfig() {
|
|
17094
16500
|
const rawUrl = process.env[PEER_BRIDGE_URL_ENV]?.trim();
|
|
17095
16501
|
const token = process.env[PEER_BRIDGE_TOKEN_ENV]?.trim();
|
|
@@ -17126,39 +16532,6 @@ async function callLoopbackBridge(request) {
|
|
|
17126
16532
|
return { configured: true, result: null };
|
|
17127
16533
|
}
|
|
17128
16534
|
}
|
|
17129
|
-
function registerPeerSessionBridge(bridge) {
|
|
17130
|
-
activeBridge = bridge;
|
|
17131
|
-
return () => {
|
|
17132
|
-
if (activeBridge === bridge)
|
|
17133
|
-
activeBridge = null;
|
|
17134
|
-
};
|
|
17135
|
-
}
|
|
17136
|
-
async function forwardToPeer(args) {
|
|
17137
|
-
if (activeBridge)
|
|
17138
|
-
return activeBridge.forward(args);
|
|
17139
|
-
const forwarded = await callLoopbackBridge({ action: "forward", args });
|
|
17140
|
-
if (forwarded.result)
|
|
17141
|
-
return forwarded.result;
|
|
17142
|
-
return {
|
|
17143
|
-
ok: false,
|
|
17144
|
-
error: forwarded.configured ? "remote session bridge is configured but unavailable" : "remote nodes are not connected on this negotium node (standalone mode)"
|
|
17145
|
-
};
|
|
17146
|
-
}
|
|
17147
|
-
async function peerSessionsForUser(userId, sourceQueryId, fromTopicId) {
|
|
17148
|
-
if (activeBridge)
|
|
17149
|
-
return activeBridge.sessions(userId, sourceQueryId, fromTopicId);
|
|
17150
|
-
const sessions = await callLoopbackBridge({
|
|
17151
|
-
action: "sessions",
|
|
17152
|
-
userId,
|
|
17153
|
-
sourceQueryId,
|
|
17154
|
-
fromTopicId
|
|
17155
|
-
});
|
|
17156
|
-
if (sessions.result)
|
|
17157
|
-
return sessions.result;
|
|
17158
|
-
if (sessions.configured)
|
|
17159
|
-
return { ok: false, nodes: [] };
|
|
17160
|
-
return { ok: true, nodes: [] };
|
|
17161
|
-
}
|
|
17162
16535
|
async function deliverPeerReply(route, sourceTitle, replyText, kind) {
|
|
17163
16536
|
if (isHubRemoteReplyRoute(route)) {
|
|
17164
16537
|
return deliverHubRemoteReply(route, sourceTitle, replyText, kind);
|
|
@@ -17173,40 +16546,13 @@ async function deliverPeerReply(route, sourceTitle, replyText, kind) {
|
|
|
17173
16546
|
kind
|
|
17174
16547
|
})).result ?? false;
|
|
17175
16548
|
}
|
|
17176
|
-
var
|
|
16549
|
+
var activeBridge = null, PEER_BRIDGE_URL_ENV = "NEGOTIUM_PEER_SESSION_BRIDGE_URL", PEER_BRIDGE_TOKEN_ENV = "NEGOTIUM_PEER_SESSION_BRIDGE_TOKEN", PEER_BRIDGE_TIMEOUT_MS = 5000;
|
|
17177
16550
|
var init_peer_forward = __esm(async () => {
|
|
17178
16551
|
init_remote_session_grant();
|
|
17179
16552
|
await init_remote_session_reply_outbox();
|
|
17180
16553
|
});
|
|
17181
16554
|
|
|
17182
16555
|
// ../../packages/core/src/runtime/ask-callbacks.ts
|
|
17183
|
-
var exports_ask_callbacks = {};
|
|
17184
|
-
__export(exports_ask_callbacks, {
|
|
17185
|
-
resolveAskCallback: () => resolveAskCallback,
|
|
17186
|
-
registerAskCallback: () => registerAskCallback,
|
|
17187
|
-
purgeStaleAsks: () => purgeStaleAsks,
|
|
17188
|
-
failInterruptedRemoteAskCallbacks: () => failInterruptedRemoteAskCallbacks,
|
|
17189
|
-
deleteHubRemoteAskCallbackRow: () => deleteHubRemoteAskCallbackRow,
|
|
17190
|
-
cancelAskCallbacksForTopic: () => cancelAskCallbacksForTopic
|
|
17191
|
-
});
|
|
17192
|
-
function registerAskCallback(entry) {
|
|
17193
|
-
pendingAsks.set(entry.targetQueryId, entry);
|
|
17194
|
-
if (entry.remoteReply) {
|
|
17195
|
-
const route = entry.remoteReply;
|
|
17196
|
-
const hub = isHubRemoteReplyRoute(route);
|
|
17197
|
-
db.query(`INSERT INTO remote_ask_callbacks
|
|
17198
|
-
(target_query_id, request_id, node_name, node_cell_id, topic_id, user_id, created_at, route_json)
|
|
17199
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
17200
|
-
ON CONFLICT(target_query_id) DO UPDATE SET
|
|
17201
|
-
request_id = excluded.request_id,
|
|
17202
|
-
node_name = excluded.node_name,
|
|
17203
|
-
node_cell_id = excluded.node_cell_id,
|
|
17204
|
-
topic_id = excluded.topic_id,
|
|
17205
|
-
user_id = excluded.user_id,
|
|
17206
|
-
created_at = excluded.created_at,
|
|
17207
|
-
route_json = excluded.route_json`).run(entry.targetQueryId, route.requestId, route.nodeName, hub ? "" : route.nodeCellId, route.topicId, hub ? "" : route.userId, entry.createdAt, hub ? JSON.stringify(route) : null);
|
|
17208
|
-
}
|
|
17209
|
-
}
|
|
17210
16556
|
function resolveAskCallback(queryId) {
|
|
17211
16557
|
const entry = pendingAsks.get(queryId);
|
|
17212
16558
|
if (!entry)
|
|
@@ -17223,13 +16569,6 @@ function resolveAskCallback(queryId) {
|
|
|
17223
16569
|
function deleteHubRemoteAskCallbackRow(requestId) {
|
|
17224
16570
|
db.query("DELETE FROM remote_ask_callbacks WHERE request_id = ? AND route_json IS NOT NULL").run(requestId);
|
|
17225
16571
|
}
|
|
17226
|
-
function purgeStaleAsks(now = Date.now()) {
|
|
17227
|
-
for (const [id, entry] of pendingAsks) {
|
|
17228
|
-
if (now - entry.createdAt > MAX_ASK_AGE_MS)
|
|
17229
|
-
pendingAsks.delete(id);
|
|
17230
|
-
}
|
|
17231
|
-
db.query("DELETE FROM remote_ask_callbacks WHERE created_at < ?").run(now - MAX_ASK_AGE_MS);
|
|
17232
|
-
}
|
|
17233
16572
|
function cancelAskCallbacksForTopic(topicId) {
|
|
17234
16573
|
let cancelled = 0;
|
|
17235
16574
|
for (const [queryId, entry] of pendingAsks) {
|
|
@@ -17241,43 +16580,6 @@ function cancelAskCallbacksForTopic(topicId) {
|
|
|
17241
16580
|
}
|
|
17242
16581
|
return cancelled;
|
|
17243
16582
|
}
|
|
17244
|
-
function durableRoute(row) {
|
|
17245
|
-
if (row.route_json) {
|
|
17246
|
-
try {
|
|
17247
|
-
return parseHubRemoteReplyRoute(JSON.parse(row.route_json));
|
|
17248
|
-
} catch {
|
|
17249
|
-
return null;
|
|
17250
|
-
}
|
|
17251
|
-
}
|
|
17252
|
-
return {
|
|
17253
|
-
nodeName: row.node_name,
|
|
17254
|
-
nodeCellId: row.node_cell_id,
|
|
17255
|
-
topicId: row.topic_id,
|
|
17256
|
-
userId: row.user_id,
|
|
17257
|
-
requestId: row.request_id
|
|
17258
|
-
};
|
|
17259
|
-
}
|
|
17260
|
-
async function failInterruptedRemoteAskCallbacks(options = {}) {
|
|
17261
|
-
const rows = db.query(`SELECT target_query_id, request_id, node_name, node_cell_id, topic_id, user_id, route_json
|
|
17262
|
-
FROM remote_ask_callbacks
|
|
17263
|
-
ORDER BY created_at ASC`).all();
|
|
17264
|
-
let failed = 0;
|
|
17265
|
-
for (const row of rows) {
|
|
17266
|
-
const route = durableRoute(row);
|
|
17267
|
-
if (!route) {
|
|
17268
|
-
db.query("DELETE FROM remote_ask_callbacks WHERE target_query_id = ?").run(row.target_query_id);
|
|
17269
|
-
continue;
|
|
17270
|
-
}
|
|
17271
|
-
if (options.routes === "hub" && !isHubRemoteReplyRoute(route))
|
|
17272
|
-
continue;
|
|
17273
|
-
const delivered = await deliverPeerReply(route, "peer", "The remote worker restarted before this ask completed. Please retry the request.", "error");
|
|
17274
|
-
if (!delivered)
|
|
17275
|
-
continue;
|
|
17276
|
-
db.query("DELETE FROM remote_ask_callbacks WHERE target_query_id = ?").run(row.target_query_id);
|
|
17277
|
-
failed++;
|
|
17278
|
-
}
|
|
17279
|
-
return failed;
|
|
17280
|
-
}
|
|
17281
16583
|
var pendingAsks, MAX_ASK_AGE_MS;
|
|
17282
16584
|
var init_ask_callbacks = __esm(async () => {
|
|
17283
16585
|
await __promiseAll([
|
|
@@ -17703,14 +17005,6 @@ var init_topic_tool_capabilities = __esm(async () => {
|
|
|
17703
17005
|
});
|
|
17704
17006
|
|
|
17705
17007
|
// ../../packages/core/src/topics/lifecycle.ts
|
|
17706
|
-
var exports_lifecycle = {};
|
|
17707
|
-
__export(exports_lifecycle, {
|
|
17708
|
-
deleteTopicCascade: () => deleteTopicCascade,
|
|
17709
|
-
TopicTurnStillActiveError: () => TopicTurnStillActiveError,
|
|
17710
|
-
TopicDeleteVetoedError: () => TopicDeleteVetoedError,
|
|
17711
|
-
TopicCleanupRequiredError: () => TopicCleanupRequiredError,
|
|
17712
|
-
TopicArchiveRequiredError: () => TopicArchiveRequiredError
|
|
17713
|
-
});
|
|
17714
17008
|
import { rmSync as rmSync6 } from "fs";
|
|
17715
17009
|
async function abortAndWaitForTopic(topicId) {
|
|
17716
17010
|
interSessionQueue.drop(topicId);
|
|
@@ -17743,8 +17037,8 @@ async function cleanupParticipantResources(topic, userIds, sessionId, cwd, purge
|
|
|
17743
17037
|
cwd,
|
|
17744
17038
|
extraSessions: index === 0 ? currentSessionRef(topic, sessionId) : []
|
|
17745
17039
|
});
|
|
17746
|
-
} catch (
|
|
17747
|
-
logger.warn({ err
|
|
17040
|
+
} catch (err) {
|
|
17041
|
+
logger.warn({ err, topicId: topic.id, userId: participantUserId }, "deleteTopicCascade: participant rollout cleanup failed");
|
|
17748
17042
|
}
|
|
17749
17043
|
if (!purged)
|
|
17750
17044
|
return false;
|
|
@@ -17800,12 +17094,12 @@ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorId
|
|
|
17800
17094
|
if (rawArchive)
|
|
17801
17095
|
rawArchives.push(rawArchive.path);
|
|
17802
17096
|
}
|
|
17803
|
-
} catch (
|
|
17097
|
+
} catch (err) {
|
|
17804
17098
|
if (!force) {
|
|
17805
|
-
logger.warn({ err
|
|
17806
|
-
throw new TopicArchiveRequiredError(topicId,
|
|
17099
|
+
logger.warn({ err, topicId }, "deleteTopicCascade: archive failed - blocking delete unless force=true");
|
|
17100
|
+
throw new TopicArchiveRequiredError(topicId, err);
|
|
17807
17101
|
}
|
|
17808
|
-
logger.warn({ err
|
|
17102
|
+
logger.warn({ err, topicId }, "deleteTopicCascade: archive failed but force=true - continuing with hard delete");
|
|
17809
17103
|
}
|
|
17810
17104
|
}
|
|
17811
17105
|
if (archived && meetsMemoryArchiveExchangeThreshold(archived.exchangeCount, MIN_MEMORY_ARCHIVE_EXCHANGES, topic)) {
|
|
@@ -17821,8 +17115,8 @@ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorId
|
|
|
17821
17115
|
...rawArchives.length > 0 ? { rawArchivePaths: rawArchives } : {},
|
|
17822
17116
|
messageCount: archived.messageCount
|
|
17823
17117
|
});
|
|
17824
|
-
} catch (
|
|
17825
|
-
logger.warn({ err
|
|
17118
|
+
} catch (err) {
|
|
17119
|
+
logger.warn({ err, topicId, archive: archived.path }, "deleteTopicCascade: background archiver launch failed - raw archive preserved");
|
|
17826
17120
|
}
|
|
17827
17121
|
}
|
|
17828
17122
|
const sessionId = getTopicSessionId(topicId);
|
|
@@ -17841,21 +17135,21 @@ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorId
|
|
|
17841
17135
|
const browserProfile = getTopicBrowserProfile(topicId);
|
|
17842
17136
|
try {
|
|
17843
17137
|
await closeBrowserOwnerTabs(browserProfileOwner, browserProfile, `topic:${topicId}`);
|
|
17844
|
-
} catch (
|
|
17845
|
-
logger.warn({ err
|
|
17138
|
+
} catch (err) {
|
|
17139
|
+
logger.warn({ err, topicId }, "deleteTopicCascade: browser owner cleanup failed");
|
|
17846
17140
|
}
|
|
17847
17141
|
deleteTopicProfileDir(userId, topicId);
|
|
17848
17142
|
cancelAskCallbacksForTopic(topicId);
|
|
17849
17143
|
deleteSelfSchedulesForTopic(topicId);
|
|
17850
17144
|
try {
|
|
17851
17145
|
await deleteFilesForTopic(topicId);
|
|
17852
|
-
} catch (
|
|
17853
|
-
logger.warn({ err
|
|
17146
|
+
} catch (err) {
|
|
17147
|
+
logger.warn({ err, topicId }, "deleteTopicCascade: host file cleanup failed");
|
|
17854
17148
|
}
|
|
17855
17149
|
try {
|
|
17856
17150
|
rmSync6(cwd, { recursive: true, force: true });
|
|
17857
|
-
} catch (
|
|
17858
|
-
logger.warn({ err
|
|
17151
|
+
} catch (err) {
|
|
17152
|
+
logger.warn({ err, topicId, cwd }, "deleteTopicCascade: workspace cleanup failed");
|
|
17859
17153
|
}
|
|
17860
17154
|
deleteTopicVisuals(topicId);
|
|
17861
17155
|
deleteTopicHostMcpGrant(topicId);
|
|
@@ -17897,7 +17191,7 @@ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorId
|
|
|
17897
17191
|
}
|
|
17898
17192
|
}
|
|
17899
17193
|
}
|
|
17900
|
-
var DELETE_TURN_WAIT_MS = 5000, TopicArchiveRequiredError, TopicTurnStillActiveError, TopicCleanupRequiredError
|
|
17194
|
+
var DELETE_TURN_WAIT_MS = 5000, TopicArchiveRequiredError, TopicTurnStillActiveError, TopicCleanupRequiredError;
|
|
17901
17195
|
var init_lifecycle = __esm(async () => {
|
|
17902
17196
|
init_manager();
|
|
17903
17197
|
init_config();
|
|
@@ -17964,19 +17258,9 @@ var init_lifecycle = __esm(async () => {
|
|
|
17964
17258
|
this.topicId = topicId;
|
|
17965
17259
|
}
|
|
17966
17260
|
};
|
|
17967
|
-
TopicDeleteVetoedError = class TopicDeleteVetoedError extends Error {
|
|
17968
|
-
code = "TOPIC_DELETE_VETOED";
|
|
17969
|
-
topicId;
|
|
17970
|
-
constructor(topicId, reason) {
|
|
17971
|
-
super(`Topic delete was vetoed: ${reason}`);
|
|
17972
|
-
this.name = "TopicDeleteVetoedError";
|
|
17973
|
-
this.topicId = topicId;
|
|
17974
|
-
}
|
|
17975
|
-
};
|
|
17976
17261
|
});
|
|
17977
17262
|
|
|
17978
17263
|
// ../../packages/core/src/runtime/attachments.ts
|
|
17979
|
-
import { randomUUID as randomUUID16 } from "crypto";
|
|
17980
17264
|
import { copyFileSync as copyFileSync2, mkdirSync as mkdirSync17, writeFileSync as writeFileSync15 } from "fs";
|
|
17981
17265
|
import { basename as basename6, join as join29 } from "path";
|
|
17982
17266
|
function workspaceCwdFor(topicId) {
|
|
@@ -18018,8 +17302,8 @@ function materializePromptAttachments(topicId, queryId, attachmentIds) {
|
|
|
18018
17302
|
sizeBytes: attachment.sizeBytes,
|
|
18019
17303
|
path: destPath
|
|
18020
17304
|
});
|
|
18021
|
-
} catch (
|
|
18022
|
-
logger.warn({ topicId, queryId, fileId, err
|
|
17305
|
+
} catch (err) {
|
|
17306
|
+
logger.warn({ topicId, queryId, fileId, err }, "ai: failed to materialize attachment");
|
|
18023
17307
|
}
|
|
18024
17308
|
}
|
|
18025
17309
|
return out;
|
|
@@ -18037,24 +17321,6 @@ function composeAttachmentPrompt(prompt, promptLines) {
|
|
|
18037
17321
|
function promptWithAttachments(prompt, attachments) {
|
|
18038
17322
|
return composeAttachmentPrompt(prompt, attachments.map(({ filename, path }) => attachmentPromptLine(filename, path)));
|
|
18039
17323
|
}
|
|
18040
|
-
function ingestAttachment(args) {
|
|
18041
|
-
const destDir = join29(UPLOADS_DIR, args.topicId);
|
|
18042
|
-
mkdirSync17(destDir, { recursive: true });
|
|
18043
|
-
const safeName = safeAttachmentFilename(args.filename, "upload");
|
|
18044
|
-
const destPath = join29(destDir, `${Date.now()}-${randomUUID16().slice(0, 8)}-${safeName}`);
|
|
18045
|
-
if (args.sourcePath !== undefined) {
|
|
18046
|
-
copyFileSync2(args.sourcePath, destPath);
|
|
18047
|
-
} else if (args.bytes !== undefined) {
|
|
18048
|
-
writeFileSync15(destPath, args.bytes);
|
|
18049
|
-
} else {
|
|
18050
|
-
throw new Error("ingestAttachment: provide sourcePath or bytes");
|
|
18051
|
-
}
|
|
18052
|
-
return {
|
|
18053
|
-
path: destPath,
|
|
18054
|
-
filename: args.filename,
|
|
18055
|
-
promptLine: attachmentPromptLine(args.filename, destPath)
|
|
18056
|
-
};
|
|
18057
|
-
}
|
|
18058
17324
|
function parseAttachmentNames(raw) {
|
|
18059
17325
|
if (!raw)
|
|
18060
17326
|
return [];
|
|
@@ -18095,13 +17361,13 @@ function isLikelyCurrentChannelTrigger(row, userId, prompt) {
|
|
|
18095
17361
|
return Number.isFinite(createdMs) && Date.now() - createdMs <= CHANNEL_CONTEXT_CURRENT_MESSAGE_MATCH_MS;
|
|
18096
17362
|
}
|
|
18097
17363
|
function formatChannelTranscriptLine(row) {
|
|
18098
|
-
const
|
|
17364
|
+
const text = row.text.trim();
|
|
18099
17365
|
const attachments = parseAttachmentNames(row.attachments);
|
|
18100
17366
|
const attachmentSuffix = attachments.length > 0 ? `
|
|
18101
17367
|
[attachments: ${attachments.join(", ")}]` : "";
|
|
18102
17368
|
const edited = row.edited_at ? " (edited)" : "";
|
|
18103
17369
|
const thread = row.thread_root_id ? ` (in thread ${threadTag(row.thread_root_id)})` : "";
|
|
18104
|
-
return `[${row.created_at}] ${channelTranscriptSpeaker(row)}${edited}${thread}: ${
|
|
17370
|
+
return `[${row.created_at}] ${channelTranscriptSpeaker(row)}${edited}${thread}: ${text}${attachmentSuffix}`;
|
|
18105
17371
|
}
|
|
18106
17372
|
function buildMentionOnlyChannelPrompt(params) {
|
|
18107
17373
|
const rows = getAllMessagesForTopic(params.topicId).filter((row) => {
|
|
@@ -18146,14 +17412,6 @@ function buildMentionOnlyChannelPrompt(params) {
|
|
|
18146
17412
|
].filter((line) => line !== undefined).join(`
|
|
18147
17413
|
`);
|
|
18148
17414
|
}
|
|
18149
|
-
function escapeRegExp3(s) {
|
|
18150
|
-
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
18151
|
-
}
|
|
18152
|
-
function mentionsAi(text2, label) {
|
|
18153
|
-
const names = ["ai", "bot", "\uBD07", label.trim()].filter(Boolean);
|
|
18154
|
-
const alt = names.map(escapeRegExp3).join("|");
|
|
18155
|
-
return new RegExp(`(^|\\s)@(${alt})(?![\\p{L}\\p{N}])`, "iu").test(text2);
|
|
18156
|
-
}
|
|
18157
17415
|
var CHANNEL_CONTEXT_CURRENT_MESSAGE_MATCH_MS, CHANNEL_CONTEXT_MAX_MESSAGES = 500, CHANNEL_CONTEXT_MAX_CHARS = 120000;
|
|
18158
17416
|
var init_channel_context = __esm(async () => {
|
|
18159
17417
|
init_attachments();
|
|
@@ -18162,13 +17420,13 @@ var init_channel_context = __esm(async () => {
|
|
|
18162
17420
|
});
|
|
18163
17421
|
|
|
18164
17422
|
// ../../packages/core/src/runtime/errors.ts
|
|
18165
|
-
function stringifyError(
|
|
18166
|
-
if (
|
|
18167
|
-
return
|
|
18168
|
-
if (typeof
|
|
18169
|
-
return
|
|
17423
|
+
function stringifyError(err) {
|
|
17424
|
+
if (err instanceof Error)
|
|
17425
|
+
return err.message;
|
|
17426
|
+
if (typeof err === "string")
|
|
17427
|
+
return err;
|
|
18170
17428
|
try {
|
|
18171
|
-
return JSON.stringify(
|
|
17429
|
+
return JSON.stringify(err) ?? String(err);
|
|
18172
17430
|
} catch {
|
|
18173
17431
|
return "Unknown agent error";
|
|
18174
17432
|
}
|
|
@@ -18183,19 +17441,19 @@ function authRecoveryHint(agent) {
|
|
|
18183
17441
|
return "Please check the DEEPSEEK_API_KEY, MOONSHOT_API_KEY, or GLM_API_KEY environment variable";
|
|
18184
17442
|
}
|
|
18185
17443
|
}
|
|
18186
|
-
function classifyAgentError(
|
|
17444
|
+
function classifyAgentError(err, agent) {
|
|
18187
17445
|
const name = AGENT_DISPLAY_NAME[agent];
|
|
18188
17446
|
const hint = authRecoveryHint(agent);
|
|
18189
|
-
const ctor = typeof
|
|
17447
|
+
const ctor = typeof err === "object" && err !== null ? err.constructor?.name : undefined;
|
|
18190
17448
|
if (ctor === "AuthenticationError")
|
|
18191
17449
|
return `${name} authentication expired. ${hint}. (401)`;
|
|
18192
17450
|
if (ctor === "RateLimitError")
|
|
18193
17451
|
return `${name} request limit exceeded. Please try again in a moment. (429)`;
|
|
18194
17452
|
if (ctor === "InternalServerError") {
|
|
18195
|
-
const status =
|
|
17453
|
+
const status = err.status;
|
|
18196
17454
|
return status === 529 ? `${name} server is overloaded. Please try again in a moment. (529)` : `${name} server error occurred. Please try again in a moment. (500)`;
|
|
18197
17455
|
}
|
|
18198
|
-
const s = stringifyError(
|
|
17456
|
+
const s = stringifyError(err);
|
|
18199
17457
|
if (/401|authentication.error|invalid.*api.key|not logged|ANTHROPIC_API_KEY|DEEPSEEK_API_KEY|MOONSHOT_API_KEY|GLM_API_KEY/i.test(s)) {
|
|
18200
17458
|
return `${name} authentication expired. ${hint}. (401)`;
|
|
18201
17459
|
}
|
|
@@ -18218,12 +17476,12 @@ var init_errors = __esm(() => {
|
|
|
18218
17476
|
|
|
18219
17477
|
// ../../packages/core/src/runtime/event-heartbeat.ts
|
|
18220
17478
|
function nextOrHeartbeat(pending, intervalMs) {
|
|
18221
|
-
return new Promise((
|
|
18222
|
-
const timer = setTimeout(() =>
|
|
17479
|
+
return new Promise((resolve, reject) => {
|
|
17480
|
+
const timer = setTimeout(() => resolve({ kind: "heartbeat" }), intervalMs);
|
|
18223
17481
|
timer.unref?.();
|
|
18224
17482
|
pending.then((result) => {
|
|
18225
17483
|
clearTimeout(timer);
|
|
18226
|
-
|
|
17484
|
+
resolve({ kind: "event", result });
|
|
18227
17485
|
}, (error) => {
|
|
18228
17486
|
clearTimeout(timer);
|
|
18229
17487
|
reject(error);
|
|
@@ -18517,7 +17775,7 @@ var init_vault_request_gates = __esm(async () => {
|
|
|
18517
17775
|
});
|
|
18518
17776
|
|
|
18519
17777
|
// ../../packages/core/src/agents/mcp-tools/request-vault.ts
|
|
18520
|
-
import { createHash as createHash12, randomUUID as
|
|
17778
|
+
import { createHash as createHash12, randomUUID as randomUUID16 } from "crypto";
|
|
18521
17779
|
import { z as z4 } from "zod";
|
|
18522
17780
|
function requestBodyHash(key, description) {
|
|
18523
17781
|
return createHash12("sha256").update(JSON.stringify({ key, description })).digest("hex");
|
|
@@ -18753,8 +18011,8 @@ function createRequestVaultRuntime(host) {
|
|
|
18753
18011
|
return errorResult(`Error: failed to persist request_vault_secret: ${error instanceof Error ? error.message : String(error)}`);
|
|
18754
18012
|
}
|
|
18755
18013
|
let resolveAnswer;
|
|
18756
|
-
const promise = new Promise((
|
|
18757
|
-
resolveAnswer =
|
|
18014
|
+
const promise = new Promise((resolve) => {
|
|
18015
|
+
resolveAnswer = resolve;
|
|
18758
18016
|
});
|
|
18759
18017
|
pendingRequests.set(message.id, {
|
|
18760
18018
|
topicId: ctx.topicId,
|
|
@@ -18815,7 +18073,7 @@ var init_request_vault = __esm(async () => {
|
|
|
18815
18073
|
init_vault_request_gates()
|
|
18816
18074
|
]);
|
|
18817
18075
|
MAX_DESCRIPTION_CHARS = VAULT_DESCRIPTION_MAX_LENGTH;
|
|
18818
|
-
VAULT_GATE_OWNER_ID = `request-vault-${process.pid}-${
|
|
18076
|
+
VAULT_GATE_OWNER_ID = `request-vault-${process.pid}-${randomUUID16()}`;
|
|
18819
18077
|
defaultRequestVaultDurabilityHost = {
|
|
18820
18078
|
gates: {
|
|
18821
18079
|
prepare: prepareVaultRequestGate,
|
|
@@ -18856,7 +18114,7 @@ var init_request_vault = __esm(async () => {
|
|
|
18856
18114
|
durability: defaultRequestVaultDurabilityHost,
|
|
18857
18115
|
runtime: {
|
|
18858
18116
|
ownerId: VAULT_GATE_OWNER_ID,
|
|
18859
|
-
createId:
|
|
18117
|
+
createId: randomUUID16,
|
|
18860
18118
|
now: () => new Date().toISOString()
|
|
18861
18119
|
}
|
|
18862
18120
|
});
|
|
@@ -18893,24 +18151,24 @@ function taskPanelMessageId(queryId) {
|
|
|
18893
18151
|
// ../../packages/core/src/runtime/tasks.ts
|
|
18894
18152
|
function upsertTaskPanelMessage(topicId, queryId, tasks, lastRenderedText) {
|
|
18895
18153
|
if (tasks.length === 0) {
|
|
18896
|
-
const
|
|
18897
|
-
for (const
|
|
18898
|
-
|
|
18154
|
+
const hub = WsHub.get();
|
|
18155
|
+
for (const messageId of softDeleteApiMessagesByIdPrefix(topicId, "tasks-")) {
|
|
18156
|
+
hub.broadcastMessageUpdated(topicId, messageId, { deleted: true, text: "" });
|
|
18899
18157
|
}
|
|
18900
18158
|
return null;
|
|
18901
18159
|
}
|
|
18902
|
-
const
|
|
18903
|
-
if (
|
|
18160
|
+
const text = renderTaskPanel(tasks);
|
|
18161
|
+
if (text === lastRenderedText)
|
|
18904
18162
|
return lastRenderedText;
|
|
18905
18163
|
const hub = WsHub.get();
|
|
18906
18164
|
const messageId = taskPanelMessageId(queryId);
|
|
18907
18165
|
const existing = getApiMessage(topicId, messageId);
|
|
18908
18166
|
if (existing && !existing.deleted) {
|
|
18909
18167
|
const editedAt = new Date().toISOString();
|
|
18910
|
-
const updated = updateApiMessageText(topicId, messageId,
|
|
18168
|
+
const updated = updateApiMessageText(topicId, messageId, text, editedAt);
|
|
18911
18169
|
if (updated) {
|
|
18912
|
-
hub.broadcastMessageUpdated(topicId, messageId, { text
|
|
18913
|
-
return
|
|
18170
|
+
hub.broadcastMessageUpdated(topicId, messageId, { text, editedAt });
|
|
18171
|
+
return text;
|
|
18914
18172
|
}
|
|
18915
18173
|
}
|
|
18916
18174
|
const createdAt = new Date().toISOString();
|
|
@@ -18918,12 +18176,12 @@ function upsertTaskPanelMessage(topicId, queryId, tasks, lastRenderedText) {
|
|
|
18918
18176
|
id: messageId,
|
|
18919
18177
|
topicId,
|
|
18920
18178
|
authorId: "system",
|
|
18921
|
-
text
|
|
18179
|
+
text,
|
|
18922
18180
|
createdAt
|
|
18923
18181
|
};
|
|
18924
18182
|
appendApiMessage(message, { notify: false });
|
|
18925
18183
|
hub.broadcastMessage(topicId, message);
|
|
18926
|
-
return
|
|
18184
|
+
return text;
|
|
18927
18185
|
}
|
|
18928
18186
|
var init_tasks2 = __esm(async () => {
|
|
18929
18187
|
await __promiseAll([
|
|
@@ -19182,14 +18440,14 @@ function resolveVisualMediaInput(topicId, input) {
|
|
|
19182
18440
|
if (!topicAllowsVisualFileId(topicId, fileId)) {
|
|
19183
18441
|
return { error: "file_id is not attached to this topic" };
|
|
19184
18442
|
}
|
|
19185
|
-
const
|
|
19186
|
-
const
|
|
19187
|
-
if (!
|
|
18443
|
+
const attachment = resolveAttachmentByFileId(fileId);
|
|
18444
|
+
const filePath = resolveUploadedFilePathByFileId(fileId);
|
|
18445
|
+
if (!attachment || !filePath)
|
|
19188
18446
|
return { error: `uploaded file not found: ${fileId}` };
|
|
19189
18447
|
return {
|
|
19190
|
-
fileId:
|
|
19191
|
-
mimeType:
|
|
19192
|
-
source: `file_id:${
|
|
18448
|
+
fileId: attachment.id,
|
|
18449
|
+
mimeType: attachment.mimeType,
|
|
18450
|
+
source: `file_id:${attachment.id}`
|
|
19193
18451
|
};
|
|
19194
18452
|
}
|
|
19195
18453
|
if (typeof input.file_path !== "string" || !input.file_path.trim()) {
|
|
@@ -19236,7 +18494,7 @@ var init_visuals = __esm(async () => {
|
|
|
19236
18494
|
});
|
|
19237
18495
|
|
|
19238
18496
|
// ../../packages/core/src/runtime/turn-event-stream.ts
|
|
19239
|
-
import { randomUUID as
|
|
18497
|
+
import { randomUUID as randomUUID17 } from "crypto";
|
|
19240
18498
|
import { realpathSync as realpathSync6, statSync as statSync9 } from "fs";
|
|
19241
18499
|
import { isAbsolute as isAbsolute7, resolve as resolve18 } from "path";
|
|
19242
18500
|
function sessionEventMatchesCurrentExecution(topicId, queryId, agent, model) {
|
|
@@ -19305,9 +18563,9 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
19305
18563
|
const existing = providerToolIds.get(providerId);
|
|
19306
18564
|
if (existing)
|
|
19307
18565
|
return existing;
|
|
19308
|
-
const
|
|
19309
|
-
providerToolIds.set(providerId,
|
|
19310
|
-
return
|
|
18566
|
+
const clientId = fallback ?? providerId;
|
|
18567
|
+
providerToolIds.set(providerId, clientId);
|
|
18568
|
+
return clientId;
|
|
19311
18569
|
}
|
|
19312
18570
|
const clientId = fallback ?? nextSyntheticToolUseId();
|
|
19313
18571
|
anonymousToolIds.push(clientId);
|
|
@@ -19338,15 +18596,15 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
19338
18596
|
return providerId ? handledVisualToolResultIds.has(providerId) : false;
|
|
19339
18597
|
};
|
|
19340
18598
|
const emitPendingAssistantMessage = (usage) => {
|
|
19341
|
-
const
|
|
18599
|
+
const text = pendingText.trimEnd();
|
|
19342
18600
|
pendingText = "";
|
|
19343
|
-
if (silent || !
|
|
18601
|
+
if (silent || !text.trim())
|
|
19344
18602
|
return null;
|
|
19345
18603
|
const message = {
|
|
19346
|
-
id:
|
|
18604
|
+
id: randomUUID17(),
|
|
19347
18605
|
topicId,
|
|
19348
18606
|
authorId: "ai",
|
|
19349
|
-
text
|
|
18607
|
+
text,
|
|
19350
18608
|
queryId,
|
|
19351
18609
|
agentType,
|
|
19352
18610
|
model,
|
|
@@ -19566,8 +18824,8 @@ ${JSON.stringify(event.input ?? {})}`);
|
|
|
19566
18824
|
hub.broadcastVisual(topicId, queryId, url, vizId, title ?? null, kind);
|
|
19567
18825
|
hub.broadcastToolOutput(topicId, queryId, toolUseId, `Displayed: ${url}`);
|
|
19568
18826
|
markVisualToolResultHandled(event.toolUseId);
|
|
19569
|
-
} catch (
|
|
19570
|
-
const reason =
|
|
18827
|
+
} catch (err) {
|
|
18828
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
19571
18829
|
failMediaVisual(reason);
|
|
19572
18830
|
}
|
|
19573
18831
|
} else {
|
|
@@ -19678,8 +18936,8 @@ ${JSON.stringify(event.input ?? {})}`);
|
|
|
19678
18936
|
}
|
|
19679
18937
|
terminalEmitted = true;
|
|
19680
18938
|
{
|
|
19681
|
-
|
|
19682
|
-
const pending =
|
|
18939
|
+
await init_ask_callbacks();
|
|
18940
|
+
const pending = resolveAskCallback(queryId);
|
|
19683
18941
|
if (pending) {
|
|
19684
18942
|
const sourceLabel = pending.sourceLabel ?? topicTitle;
|
|
19685
18943
|
const replyText = pending.timedOut ? `\u26A0\uFE0F [Timeout - reply from ${sourceLabel} took too long and was dropped]` : accumulatedText.trim() || "(\uCC98\uB9AC\uB428, \uBCC4\uB3C4 \uC751\uB2F5 \uC5C6\uC74C)";
|
|
@@ -19752,8 +19010,8 @@ ${JSON.stringify(event.input ?? {})}`);
|
|
|
19752
19010
|
if (control.injectParams)
|
|
19753
19011
|
control.injectParams.sessionId = event.sessionId;
|
|
19754
19012
|
onSessionId(event.sessionId);
|
|
19755
|
-
} catch (
|
|
19756
|
-
logger.warn({ err
|
|
19013
|
+
} catch (err) {
|
|
19014
|
+
logger.warn({ err, topicId, queryId, agentType }, "ai: isolated session owner rejected provider session id");
|
|
19757
19015
|
}
|
|
19758
19016
|
} else if (!silent && sessionEventMatchesCurrentExecution(topicId, queryId, agentType, model)) {
|
|
19759
19017
|
setTopicSessionId(topicId, event.sessionId, {
|
|
@@ -19786,14 +19044,14 @@ ${JSON.stringify(event.input ?? {})}`);
|
|
|
19786
19044
|
settleSubagentFailure(queryId, "\uC911\uC9C0\uB428 (\uC0AC\uC6A9\uC790\uAC00 \uC2E4\uD589\uC744 \uBA48\uCDC4\uC2B5\uB2C8\uB2E4)");
|
|
19787
19045
|
} else {
|
|
19788
19046
|
if (control.abortReason === "internal" /* Internal */) {
|
|
19789
|
-
|
|
19790
|
-
|
|
19047
|
+
await init_ask_callbacks();
|
|
19048
|
+
resolveAskCallback(queryId);
|
|
19791
19049
|
}
|
|
19792
19050
|
}
|
|
19793
19051
|
}
|
|
19794
|
-
} catch (
|
|
19795
|
-
const msg = stringifyError(
|
|
19796
|
-
logger.warn({ err
|
|
19052
|
+
} catch (err) {
|
|
19053
|
+
const msg = stringifyError(err) || "Unknown agent error";
|
|
19054
|
+
logger.warn({ err, topicId, queryId, agentType, model, silent }, "ai: stream failed");
|
|
19797
19055
|
terminalEmitted = true;
|
|
19798
19056
|
if (retryableSessionExpired && isSessionExpiredError(msg)) {
|
|
19799
19057
|
outcome = { kind: "session-expired", error: msg };
|
|
@@ -19944,85 +19202,7 @@ var init_app_settings = __esm(async () => {
|
|
|
19944
19202
|
});
|
|
19945
19203
|
|
|
19946
19204
|
// ../../packages/core/src/runtime/turn-runner.ts
|
|
19947
|
-
|
|
19948
|
-
__export(exports_turn_runner, {
|
|
19949
|
-
workspaceCwdFor: () => workspaceCwdFor,
|
|
19950
|
-
withDefaultPlaywright: () => withDefaultPlaywright,
|
|
19951
|
-
wasLocallyRequeuedAfterUserPreemption: () => wasLocallyRequeuedAfterUserPreemption,
|
|
19952
|
-
userConversationPromptsToRecord: () => userConversationPromptsToRecord,
|
|
19953
|
-
upsertTaskPanelMessage: () => upsertTaskPanelMessage,
|
|
19954
|
-
tryReconstructTopicRollout: () => tryReconstructTopicRollout,
|
|
19955
|
-
triggerTopicAiTurn: () => triggerTopicAiTurn,
|
|
19956
|
-
topicAllowsVisualFileId: () => topicAllowsVisualFileId,
|
|
19957
|
-
taskPanelMessageId: () => taskPanelMessageId,
|
|
19958
|
-
stripMermaidFence: () => stripMermaidFence,
|
|
19959
|
-
stringifyError: () => stringifyError,
|
|
19960
|
-
streamAgentEvents: () => streamAgentEvents,
|
|
19961
|
-
startDurableTurnRequestWorker: () => startDurableTurnRequestWorker,
|
|
19962
|
-
startAiTurn: () => startAiTurn,
|
|
19963
|
-
selectableModel: () => selectableModel,
|
|
19964
|
-
sameTurnActor: () => sameTurnActor,
|
|
19965
|
-
safeAttachmentFilename: () => safeAttachmentFilename,
|
|
19966
|
-
resolveWorkerModel: () => resolveWorkerModel,
|
|
19967
|
-
resolveWorkerDefaultModel: () => resolveWorkerDefaultModel,
|
|
19968
|
-
resolveWikiMirrorPath: () => resolveWikiMirrorPath,
|
|
19969
|
-
resolveWikiMemoryMirror: () => resolveWikiMemoryMirror,
|
|
19970
|
-
resolveVisualMediaInput: () => resolveVisualMediaInput,
|
|
19971
|
-
resolveTurnToolCapabilities: () => resolveTurnToolCapabilities,
|
|
19972
|
-
resolveTurnHostMcpServers: () => resolveTurnHostMcpServers,
|
|
19973
|
-
resolveTopicTurnSession: () => resolveTopicTurnSession,
|
|
19974
|
-
resolveTopicTurnExecution: () => resolveTopicTurnExecution,
|
|
19975
|
-
resolveSessionRetry: () => resolveSessionRetry,
|
|
19976
|
-
resolveModelForAgent: () => resolveModelForAgent,
|
|
19977
|
-
resolveInitialTurnSessionId: () => resolveInitialTurnSessionId,
|
|
19978
|
-
resolveDefaultModel: () => resolveDefaultModel,
|
|
19979
|
-
resolveCompactionExecution: () => resolveCompactionExecution,
|
|
19980
|
-
renderUserTurnBatch: () => renderUserTurnBatch,
|
|
19981
|
-
renderUserPromptBatch: () => renderUserPromptBatch,
|
|
19982
|
-
renderTaskPanel: () => renderTaskPanel,
|
|
19983
|
-
promptWithAttachments: () => promptWithAttachments,
|
|
19984
|
-
prepareInjectReplayAfterUserPreemption: () => prepareInjectReplayAfterUserPreemption,
|
|
19985
|
-
parseAttachmentNames: () => parseAttachmentNames,
|
|
19986
|
-
normalizeToolUseId: () => normalizeToolUseId,
|
|
19987
|
-
normalizeMermaidTheme: () => normalizeMermaidTheme,
|
|
19988
|
-
modelOwner: () => modelOwner,
|
|
19989
|
-
mergeSupersedingUserTurn: () => mergeSupersedingUserTurn,
|
|
19990
|
-
mentionsAi: () => mentionsAi,
|
|
19991
|
-
materializePromptAttachments: () => materializePromptAttachments,
|
|
19992
|
-
isVisualsShowMermaidTool: () => isVisualsShowMermaidTool,
|
|
19993
|
-
isVisualsShowImageTool: () => isVisualsShowImageTool,
|
|
19994
|
-
isVisualsShowHtmlTool: () => isVisualsShowHtmlTool,
|
|
19995
|
-
isSessionExpiredError: () => isSessionExpiredError,
|
|
19996
|
-
isRuntimeTool: () => isRuntimeTool,
|
|
19997
|
-
isPathInside: () => isPathInside,
|
|
19998
|
-
isLikelyCurrentChannelTrigger: () => isLikelyCurrentChannelTrigger,
|
|
19999
|
-
ingestAttachment: () => ingestAttachment,
|
|
20000
|
-
formatSelectableModel: () => formatSelectableModel,
|
|
20001
|
-
formatChannelTranscriptLine: () => formatChannelTranscriptLine,
|
|
20002
|
-
escapeRegExp: () => escapeRegExp3,
|
|
20003
|
-
escapeHtml: () => escapeHtml2,
|
|
20004
|
-
deliverAskCallbackToCaller: () => deliverAskCallbackToCaller,
|
|
20005
|
-
composeAttachmentPrompt: () => composeAttachmentPrompt,
|
|
20006
|
-
classifyAgentError: () => classifyAgentError,
|
|
20007
|
-
channelTranscriptSpeaker: () => channelTranscriptSpeaker,
|
|
20008
|
-
canonicalModelId: () => canonicalModelId,
|
|
20009
|
-
buildVideoHtml: () => buildVideoHtml,
|
|
20010
|
-
buildTurnReminderQuery: () => buildTurnReminderQuery,
|
|
20011
|
-
buildMermaidHtml: () => buildMermaidHtml,
|
|
20012
|
-
buildMentionOnlyChannelPrompt: () => buildMentionOnlyChannelPrompt,
|
|
20013
|
-
buildImageHtml: () => buildImageHtml,
|
|
20014
|
-
authRecoveryHint: () => authRecoveryHint,
|
|
20015
|
-
attachmentPromptLine: () => attachmentPromptLine,
|
|
20016
|
-
activeVisualHtmlForPrompt: () => activeVisualHtmlForPrompt,
|
|
20017
|
-
SESSION_EXPIRED_MSG: () => SESSION_EXPIRED_MSG,
|
|
20018
|
-
SELECTABLE_MODELS: () => SELECTABLE_MODELS,
|
|
20019
|
-
MODEL_OWNER: () => MODEL_OWNER,
|
|
20020
|
-
MODEL_COST_ROUTING_SUMMARY: () => MODEL_COST_ROUTING_SUMMARY,
|
|
20021
|
-
MODEL_COST_RESEARCHED_AT: () => MODEL_COST_RESEARCHED_AT,
|
|
20022
|
-
FALLBACK_ORDER: () => FALLBACK_ORDER,
|
|
20023
|
-
AGENT_DISPLAY_NAME: () => AGENT_DISPLAY_NAME
|
|
20024
|
-
});
|
|
20025
|
-
import { randomUUID as randomUUID19 } from "crypto";
|
|
19205
|
+
import { randomUUID as randomUUID18 } from "crypto";
|
|
20026
19206
|
import { existsSync as existsSync22, mkdirSync as mkdirSync19, readdirSync as readdirSync5, statSync as statSync10 } from "fs";
|
|
20027
19207
|
import { join as join31 } from "path";
|
|
20028
19208
|
function withDefaultPlaywright(configuredMcp, isManager) {
|
|
@@ -20045,12 +19225,12 @@ function buildTurnReminderQuery(agent, prompt, reminders) {
|
|
|
20045
19225
|
|
|
20046
19226
|
${reminderPrompt}` };
|
|
20047
19227
|
}
|
|
20048
|
-
function appendSystemMessage(topicId,
|
|
19228
|
+
function appendSystemMessage(topicId, text, threadRootId) {
|
|
20049
19229
|
const message = {
|
|
20050
|
-
id:
|
|
19230
|
+
id: randomUUID18(),
|
|
20051
19231
|
topicId,
|
|
20052
19232
|
authorId: "system",
|
|
20053
|
-
text
|
|
19233
|
+
text,
|
|
20054
19234
|
...threadRootId ? { threadRootId } : {},
|
|
20055
19235
|
createdAt: new Date().toISOString()
|
|
20056
19236
|
};
|
|
@@ -20067,12 +19247,12 @@ function notifyPlaywrightUnavailable(topicId) {
|
|
|
20067
19247
|
appendSystemMessage(topicId, "Playwright browser tools are unavailable this turn. Browser automation was removed from the tool catalog; retry shortly if browser interaction is required.");
|
|
20068
19248
|
WsHub.get().broadcastTopicNotice(topicId, "info", "Playwright \uC0AC\uC6A9 \uBD88\uAC00");
|
|
20069
19249
|
}
|
|
20070
|
-
function appendAskReplyMessage(topicId,
|
|
19250
|
+
function appendAskReplyMessage(topicId, text, sourceLabel, body, kind, agentType, threadRootId) {
|
|
20071
19251
|
const message = {
|
|
20072
|
-
id:
|
|
19252
|
+
id: randomUUID18(),
|
|
20073
19253
|
topicId,
|
|
20074
19254
|
authorId: "ai",
|
|
20075
|
-
text
|
|
19255
|
+
text,
|
|
20076
19256
|
kind: "tell",
|
|
20077
19257
|
tellCard: {
|
|
20078
19258
|
fromLabel: sourceLabel,
|
|
@@ -20133,8 +19313,8 @@ function redispatchInject(inject) {
|
|
|
20133
19313
|
kind: "error",
|
|
20134
19314
|
error: "topic gone or AI no longer invited"
|
|
20135
19315
|
});
|
|
20136
|
-
} catch (
|
|
20137
|
-
logger.warn({ err
|
|
19316
|
+
} catch (err) {
|
|
19317
|
+
logger.warn({ err, topicId: inject.topicId }, "ai: deferred settlement hook failed");
|
|
20138
19318
|
}
|
|
20139
19319
|
if (inject.forkHandle)
|
|
20140
19320
|
cleanupAgentFork(inject.forkHandle);
|
|
@@ -20192,28 +19372,28 @@ async function clearPendingAskFile(pending, state) {
|
|
|
20192
19372
|
if (!pending.pendingAsk)
|
|
20193
19373
|
return;
|
|
20194
19374
|
try {
|
|
20195
|
-
|
|
19375
|
+
await init_session_asks();
|
|
20196
19376
|
if (state)
|
|
20197
|
-
|
|
20198
|
-
|
|
20199
|
-
} catch (
|
|
20200
|
-
logger.warn({ err
|
|
19377
|
+
markPendingAskState({ ...pending.pendingAsk, state });
|
|
19378
|
+
clearPendingAsk(pending.pendingAsk);
|
|
19379
|
+
} catch (err) {
|
|
19380
|
+
logger.warn({ err, pendingAsk: pending.pendingAsk }, "sessions: pending ask cleanup failed");
|
|
20201
19381
|
}
|
|
20202
19382
|
}
|
|
20203
19383
|
async function markPendingAskFile(pending, state) {
|
|
20204
19384
|
if (!pending.pendingAsk)
|
|
20205
19385
|
return;
|
|
20206
19386
|
try {
|
|
20207
|
-
|
|
20208
|
-
|
|
20209
|
-
} catch (
|
|
20210
|
-
logger.warn({ err
|
|
19387
|
+
await init_session_asks();
|
|
19388
|
+
markPendingAskState({ ...pending.pendingAsk, state });
|
|
19389
|
+
} catch (err) {
|
|
19390
|
+
logger.warn({ err, pendingAsk: pending.pendingAsk, state }, "sessions: pending ask mark failed");
|
|
20211
19391
|
}
|
|
20212
19392
|
}
|
|
20213
19393
|
async function deliverAskCallbackToCaller(pending, sourceLabel, body, kind, options = {}) {
|
|
20214
19394
|
if (pending.remoteReply) {
|
|
20215
|
-
|
|
20216
|
-
const delivered = await
|
|
19395
|
+
await init_peer_forward();
|
|
19396
|
+
const delivered = await deliverPeerReply(pending.remoteReply, sourceLabel, body, kind);
|
|
20217
19397
|
if (delivered)
|
|
20218
19398
|
options.onRecorded?.();
|
|
20219
19399
|
return delivered;
|
|
@@ -20233,8 +19413,8 @@ ${body}`;
|
|
|
20233
19413
|
record(undefined);
|
|
20234
19414
|
await clearPendingAskFile(pending);
|
|
20235
19415
|
return true;
|
|
20236
|
-
} catch (
|
|
20237
|
-
logger.warn({ err
|
|
19416
|
+
} catch (err) {
|
|
19417
|
+
logger.warn({ err, requestId: pending.requestId, callerTopicId: pending.callerTopicId }, "sessions: ask callback direct delivery failed");
|
|
20238
19418
|
return false;
|
|
20239
19419
|
}
|
|
20240
19420
|
}
|
|
@@ -20263,9 +19443,9 @@ ${body}`;
|
|
|
20263
19443
|
if (queued) {
|
|
20264
19444
|
try {
|
|
20265
19445
|
record(callerTopic.agent);
|
|
20266
|
-
} catch (
|
|
19446
|
+
} catch (err) {
|
|
20267
19447
|
interSessionQueue.remove(pending.callerTopicId, pending.requestId);
|
|
20268
|
-
logger.warn({ err
|
|
19448
|
+
logger.warn({ err, requestId: pending.requestId, callerTopicId: pending.callerTopicId }, "sessions: ask callback record failed after enqueue; queue entry withdrawn");
|
|
20269
19449
|
return false;
|
|
20270
19450
|
}
|
|
20271
19451
|
await markPendingAskFile(pending, "queued_for_caller");
|
|
@@ -20285,8 +19465,8 @@ ${body}`;
|
|
|
20285
19465
|
}
|
|
20286
19466
|
async function deliverAskError(queryId, sourceLabel, error) {
|
|
20287
19467
|
try {
|
|
20288
|
-
|
|
20289
|
-
const pending =
|
|
19468
|
+
await init_ask_callbacks();
|
|
19469
|
+
const pending = resolveAskCallback(queryId);
|
|
20290
19470
|
if (pending) {
|
|
20291
19471
|
const prefix = pending.timedOut ? `\u26A0\uFE0F [Timeout - error notification was dropped]
|
|
20292
19472
|
|
|
@@ -20316,9 +19496,9 @@ function tryReconstructTopicRollout(opts) {
|
|
|
20316
19496
|
entries: entries.length
|
|
20317
19497
|
}, sessionId ? "ai: session expired \u2014 rollout reconstructed from unified log" : "ai: provider session bridged from shared conversation log");
|
|
20318
19498
|
return { kind: "rebuilt", sessionId: result.sessionId };
|
|
20319
|
-
} catch (
|
|
20320
|
-
logger.warn({ err
|
|
20321
|
-
return { kind: "failed", error: stringifyError(
|
|
19499
|
+
} catch (err) {
|
|
19500
|
+
logger.warn({ err, topicId, agent, sessionId }, "ai: session reconstruct failed");
|
|
19501
|
+
return { kind: "failed", error: stringifyError(err) };
|
|
20322
19502
|
}
|
|
20323
19503
|
}
|
|
20324
19504
|
function resolveSessionRetry(opts) {
|
|
@@ -20344,8 +19524,10 @@ function resolveTurnToolCapabilities(topicId, params) {
|
|
|
20344
19524
|
};
|
|
20345
19525
|
}
|
|
20346
19526
|
function resolveTurnHostMcpServers(topic, sessionType) {
|
|
20347
|
-
|
|
20348
|
-
|
|
19527
|
+
if (topic.isSubagent)
|
|
19528
|
+
return;
|
|
19529
|
+
const ownScope = topic.kind === "manager" ? "manager" : "forum";
|
|
19530
|
+
if ((sessionType ?? ownScope) !== ownScope)
|
|
20349
19531
|
return;
|
|
20350
19532
|
return getTopicHostMcpGrant(topic.id) ?? undefined;
|
|
20351
19533
|
}
|
|
@@ -20425,8 +19607,8 @@ function waitToStartRemoteUserTurn(params, queryId, options) {
|
|
|
20425
19607
|
function announceQueuedUserTurn(params, queryId) {
|
|
20426
19608
|
try {
|
|
20427
19609
|
params.onDispatched?.(queryId);
|
|
20428
|
-
} catch (
|
|
20429
|
-
logger.warn({ err
|
|
19610
|
+
} catch (err) {
|
|
19611
|
+
logger.warn({ err, topicId: params.topic.id, queryId }, "ai: queued dispatch hook failed");
|
|
20430
19612
|
}
|
|
20431
19613
|
if (!params.silent)
|
|
20432
19614
|
WsHub.get().broadcastAiActive(params.topic.id, queryId);
|
|
@@ -20447,81 +19629,6 @@ function waitToDrainRemoteInject(topicId) {
|
|
|
20447
19629
|
timer.unref?.();
|
|
20448
19630
|
remoteInjectWaiters.set(topicId, timer);
|
|
20449
19631
|
}
|
|
20450
|
-
async function drainOneDurableUserTurn() {
|
|
20451
|
-
if (durableTurnWorkerBusy)
|
|
20452
|
-
return;
|
|
20453
|
-
durableTurnWorkerBusy = true;
|
|
20454
|
-
try {
|
|
20455
|
-
const request = claimNextRuntimeUserTurnRequest(RUNTIME_INSTANCE_ID);
|
|
20456
|
-
if (!request)
|
|
20457
|
-
return;
|
|
20458
|
-
const topic = getTopic(request.topicId);
|
|
20459
|
-
if (!topic?.agent) {
|
|
20460
|
-
completeRuntimeUserTurnRequest(request.topicId, request.requestId, RUNTIME_INSTANCE_ID);
|
|
20461
|
-
return;
|
|
20462
|
-
}
|
|
20463
|
-
const execution = request.execution;
|
|
20464
|
-
const queryId = startAiTurn({
|
|
20465
|
-
topic,
|
|
20466
|
-
userId: request.userId,
|
|
20467
|
-
actorUserId: execution?.actorUserId,
|
|
20468
|
-
actorTopicScope: actorTopicScopeFrom(execution?.actorTopicScope),
|
|
20469
|
-
remoteSession: remoteSessionGrantFrom(execution?.remoteSession),
|
|
20470
|
-
vaultUserId: execution?.vaultUserId,
|
|
20471
|
-
prompt: request.prompt,
|
|
20472
|
-
_userMessages: request.userMessages,
|
|
20473
|
-
_conversationPrompts: execution?.conversationPrompts ?? [request.prompt],
|
|
20474
|
-
_loggedUserMessageCount: execution?.loggedUserMessageCount ?? Math.max(0, request.userMessages.length - (execution?.conversationPrompts?.length ?? 1)),
|
|
20475
|
-
_durableRequestIds: [request.requestId],
|
|
20476
|
-
attachments: request.attachments,
|
|
20477
|
-
allowAutoContinue: request.allowAutoContinue,
|
|
20478
|
-
origin: "user",
|
|
20479
|
-
requestId: execution?.sourceRequestId,
|
|
20480
|
-
agentOverride: execution?.agentOverride,
|
|
20481
|
-
modelOverride: execution?.modelOverride,
|
|
20482
|
-
effortOverride: execution?.effortOverride,
|
|
20483
|
-
...execution?.sessionIdSpecified ? { sessionId: execution.sessionId } : {},
|
|
20484
|
-
sessionScope: execution?.sessionScope,
|
|
20485
|
-
cwd: execution?.cwd,
|
|
20486
|
-
sessionName: execution?.sessionName,
|
|
20487
|
-
sessionType: execution?.sessionType,
|
|
20488
|
-
visualTools: execution?.visualTools,
|
|
20489
|
-
fileDeliveryTools: execution?.fileDeliveryTools,
|
|
20490
|
-
silent: execution?.silent,
|
|
20491
|
-
bridgeSessionFromHistory: execution?.bridgeSessionFromHistory,
|
|
20492
|
-
peerBridge: execution?.peerBridge,
|
|
20493
|
-
from: execution?.from,
|
|
20494
|
-
threadRootId: execution?.threadRootId,
|
|
20495
|
-
_queryId: request.requestId,
|
|
20496
|
-
_runtimeEpoch: execution?.runtimeEpoch ?? request.topicEpoch,
|
|
20497
|
-
onSettled: () => {
|
|
20498
|
-
completeRuntimeUserTurnRequest(request.topicId, request.requestId, RUNTIME_INSTANCE_ID);
|
|
20499
|
-
}
|
|
20500
|
-
});
|
|
20501
|
-
if (!queryId) {
|
|
20502
|
-
releaseRuntimeUserTurnClaim(request.topicId, request.requestId, RUNTIME_INSTANCE_ID);
|
|
20503
|
-
return;
|
|
20504
|
-
}
|
|
20505
|
-
markRuntimeUserTurnRunning(request.topicId, request.requestId, RUNTIME_INSTANCE_ID, queryId);
|
|
20506
|
-
} finally {
|
|
20507
|
-
durableTurnWorkerBusy = false;
|
|
20508
|
-
}
|
|
20509
|
-
}
|
|
20510
|
-
function startDurableTurnRequestWorker() {
|
|
20511
|
-
if (durableTurnWorker)
|
|
20512
|
-
return () => {};
|
|
20513
|
-
durableTurnWorker = setInterval(() => {
|
|
20514
|
-
drainOneDurableUserTurn();
|
|
20515
|
-
}, 100);
|
|
20516
|
-
durableTurnWorker.unref?.();
|
|
20517
|
-
drainOneDurableUserTurn();
|
|
20518
|
-
return () => {
|
|
20519
|
-
if (!durableTurnWorker)
|
|
20520
|
-
return;
|
|
20521
|
-
clearInterval(durableTurnWorker);
|
|
20522
|
-
durableTurnWorker = null;
|
|
20523
|
-
};
|
|
20524
|
-
}
|
|
20525
19632
|
function startAiTurn(params) {
|
|
20526
19633
|
const storedTopic = getTopic(params.topic.id);
|
|
20527
19634
|
if (!storedTopic || !storedTopic.agent && !params.agentOverride) {
|
|
@@ -20533,8 +19640,8 @@ function startAiTurn(params) {
|
|
|
20533
19640
|
kind: "error",
|
|
20534
19641
|
error: storedTopic ? "topic no longer has an AI agent" : "topic no longer exists"
|
|
20535
19642
|
});
|
|
20536
|
-
} catch (
|
|
20537
|
-
logger.warn({ err
|
|
19643
|
+
} catch (err) {
|
|
19644
|
+
logger.warn({ err, topicId: params.topic.id }, "ai: rejected-turn settlement hook failed");
|
|
20538
19645
|
}
|
|
20539
19646
|
return null;
|
|
20540
19647
|
}
|
|
@@ -20590,7 +19697,7 @@ function startAiTurn(params) {
|
|
|
20590
19697
|
const askReplySources = params.askReplySources;
|
|
20591
19698
|
const sessionRetried = params._sessionRetried === true;
|
|
20592
19699
|
const emptyResponseRetried = params._emptyResponseRetried === true;
|
|
20593
|
-
const queryId = asTurnId(params._queryId ??
|
|
19700
|
+
const queryId = asTurnId(params._queryId ?? randomUUID18());
|
|
20594
19701
|
const roomId = turnConcurrency === "isolated" ? isolatedTurnRoomId(topicId, queryId) : asTurnSlotKey(topicId);
|
|
20595
19702
|
const currentRuntimeEpoch = getRuntimeTopicEpoch(topic.id);
|
|
20596
19703
|
const runtimeEpoch = params._runtimeEpoch ?? currentRuntimeEpoch;
|
|
@@ -20602,8 +19709,8 @@ function startAiTurn(params) {
|
|
|
20602
19709
|
}
|
|
20603
19710
|
try {
|
|
20604
19711
|
params.onSettled?.({ queryId, kind: "aborted", abortReason: "external" /* External */ });
|
|
20605
|
-
} catch (
|
|
20606
|
-
logger.warn({ err
|
|
19712
|
+
} catch (err) {
|
|
19713
|
+
logger.warn({ err, topicId: topic.id, queryId }, "ai: stale-turn settlement hook failed");
|
|
20607
19714
|
}
|
|
20608
19715
|
logger.info({ topicId: topic.id, queryId, queuedEpoch: params._runtimeEpoch, currentRuntimeEpoch }, "ai: dropped work queued before topic reset");
|
|
20609
19716
|
return null;
|
|
@@ -20653,8 +19760,8 @@ function startAiTurn(params) {
|
|
|
20653
19760
|
cleanupAgentFork(forkHandle);
|
|
20654
19761
|
try {
|
|
20655
19762
|
onSettled?.({ queryId: "", kind: "error", error });
|
|
20656
|
-
} catch (
|
|
20657
|
-
logger.warn({ err
|
|
19763
|
+
} catch (err) {
|
|
19764
|
+
logger.warn({ err, topicId, queryId }, "ai: isolated-turn rejection hook failed");
|
|
20658
19765
|
}
|
|
20659
19766
|
return null;
|
|
20660
19767
|
};
|
|
@@ -20701,7 +19808,7 @@ function startAiTurn(params) {
|
|
|
20701
19808
|
if (decision.action === "abort-replace") {
|
|
20702
19809
|
const running = decision.running;
|
|
20703
19810
|
if (isUserOrigin(running.origin) && !sameTurnActor(running.actorUserId, params.actorUserId)) {
|
|
20704
|
-
const
|
|
19811
|
+
const queuedQueryId = waitToStartRemoteUserTurn({
|
|
20705
19812
|
...params,
|
|
20706
19813
|
topic,
|
|
20707
19814
|
prompt,
|
|
@@ -20713,9 +19820,9 @@ function startAiTurn(params) {
|
|
|
20713
19820
|
_durableRequestIds: durableRequestIds,
|
|
20714
19821
|
_runtimeEpoch: runtimeEpoch
|
|
20715
19822
|
}, queryId);
|
|
20716
|
-
announceQueuedUserTurn({ ...params, topic },
|
|
20717
|
-
logger.info({ topicId, queryId:
|
|
20718
|
-
return
|
|
19823
|
+
announceQueuedUserTurn({ ...params, topic }, queuedQueryId);
|
|
19824
|
+
logger.info({ topicId, queryId: queuedQueryId, runningQueryId: running.queryId }, "ai: user turn from another actor queued behind the running turn");
|
|
19825
|
+
return queuedQueryId;
|
|
20719
19826
|
}
|
|
20720
19827
|
let omitRequestIds;
|
|
20721
19828
|
if (isUserOrigin(running.origin)) {
|
|
@@ -20847,14 +19954,14 @@ function startAiTurn(params) {
|
|
|
20847
19954
|
if (turnConcurrency === "topic") {
|
|
20848
19955
|
try {
|
|
20849
19956
|
writeQueryState(userId, topic.id, topic.title, prompt);
|
|
20850
|
-
} catch (
|
|
20851
|
-
logger.warn({ err
|
|
19957
|
+
} catch (err) {
|
|
19958
|
+
logger.warn({ err, topicId, userId }, "ai: failed to write active query state");
|
|
20852
19959
|
}
|
|
20853
19960
|
}
|
|
20854
19961
|
try {
|
|
20855
19962
|
onDispatched?.(queryId);
|
|
20856
|
-
} catch (
|
|
20857
|
-
logger.warn({ err
|
|
19963
|
+
} catch (err) {
|
|
19964
|
+
logger.warn({ err, topicId, queryId }, "ai: dispatch hook failed");
|
|
20858
19965
|
}
|
|
20859
19966
|
const override = getTopicConfig(topicId);
|
|
20860
19967
|
const agentKind = execution.agent;
|
|
@@ -20881,8 +19988,8 @@ function startAiTurn(params) {
|
|
|
20881
19988
|
control.injectParams.sessionId = bridge.sessionId;
|
|
20882
19989
|
try {
|
|
20883
19990
|
onSessionId?.(bridge.sessionId);
|
|
20884
|
-
} catch (
|
|
20885
|
-
logger.warn({ err
|
|
19991
|
+
} catch (err) {
|
|
19992
|
+
logger.warn({ err, topicId, queryId, agent: agentKind }, "ai: isolated session owner rejected bridged provider session id");
|
|
20886
19993
|
}
|
|
20887
19994
|
} else if (bridge.kind === "failed") {
|
|
20888
19995
|
historyBridgeError = "Conversation history could not be encoded into a provider session; no fresh session was started.";
|
|
@@ -20951,8 +20058,8 @@ function startAiTurn(params) {
|
|
|
20951
20058
|
const wikiDir = getSharedWikiDir();
|
|
20952
20059
|
const { latestSummaryFile } = resolveWikiMemoryMirror(wikiDir, memoryTopic.id, memoryTitle);
|
|
20953
20060
|
hasMemoryArchive = Boolean(resolvedBrief?.brief.latestSummaryMd || latestSummaryFile);
|
|
20954
|
-
} catch (
|
|
20955
|
-
logger.warn({ topicId, err
|
|
20061
|
+
} catch (err) {
|
|
20062
|
+
logger.warn({ topicId, err }, "ai: failed to inject topic brief");
|
|
20956
20063
|
}
|
|
20957
20064
|
systemPrompt += buildMemoryPromptSection({
|
|
20958
20065
|
topicTitle: topic.title,
|
|
@@ -21028,8 +20135,8 @@ function startAiTurn(params) {
|
|
|
21028
20135
|
control.injectParams.sessionId = prepared.forkId;
|
|
21029
20136
|
control.injectParams.forkHandle = prepared;
|
|
21030
20137
|
}
|
|
21031
|
-
} catch (
|
|
21032
|
-
throw new Error(`failed to prepare isolated session: ${stringifyError(
|
|
20138
|
+
} catch (err) {
|
|
20139
|
+
throw new Error(`failed to prepare isolated session: ${stringifyError(err)}`);
|
|
21033
20140
|
}
|
|
21034
20141
|
if (abortController.signal.aborted)
|
|
21035
20142
|
return;
|
|
@@ -21048,8 +20155,8 @@ function startAiTurn(params) {
|
|
|
21048
20155
|
throw new Error("browser MCP capability was not registered");
|
|
21049
20156
|
}
|
|
21050
20157
|
trackPlaywrightTurn(playwrightInstanceKey, control);
|
|
21051
|
-
} catch (
|
|
21052
|
-
logger.warn({ topicId, err
|
|
20158
|
+
} catch (err) {
|
|
20159
|
+
logger.warn({ topicId, err }, "ai: ensurePlaywright failed \u2014 proceeding without browser tools");
|
|
21053
20160
|
markPlaywrightUnavailable({
|
|
21054
20161
|
userId,
|
|
21055
20162
|
topic: topic.title,
|
|
@@ -21062,8 +20169,8 @@ function startAiTurn(params) {
|
|
|
21062
20169
|
if (wantsBgBash) {
|
|
21063
20170
|
try {
|
|
21064
20171
|
bgBashPort = await ensureBgBash(userId, topic.id);
|
|
21065
|
-
} catch (
|
|
21066
|
-
logger.warn({ topicId, err
|
|
20172
|
+
} catch (err) {
|
|
20173
|
+
logger.warn({ topicId, err }, "ai: ensureBgBash failed \u2014 proceeding without background bash tools");
|
|
21067
20174
|
turnReminders.push("<system-reminder>Background bash tools are UNAVAILABLE this turn. The `background_bash_*` tools could not be prepared, most often because the bash-rs binary is not installed on this host. Do not attempt to call them; run short commands in the foreground instead, and tell the user if the work genuinely needs a background job.</system-reminder>");
|
|
21068
20175
|
}
|
|
21069
20176
|
}
|
|
@@ -21276,8 +20383,8 @@ function startAiTurn(params) {
|
|
|
21276
20383
|
await settleSubagentFailure(queryId, error);
|
|
21277
20384
|
try {
|
|
21278
20385
|
onSettled?.({ queryId, kind: "error", error });
|
|
21279
|
-
} catch (
|
|
21280
|
-
logger.warn({ err
|
|
20386
|
+
} catch (err) {
|
|
20387
|
+
logger.warn({ err, topicId, queryId }, "ai: turn settlement hook failed");
|
|
21281
20388
|
}
|
|
21282
20389
|
return;
|
|
21283
20390
|
}
|
|
@@ -21293,8 +20400,8 @@ function startAiTurn(params) {
|
|
|
21293
20400
|
await settleSubagentFailure(queryId, classifyAgentError(outcome.error, agentKind));
|
|
21294
20401
|
try {
|
|
21295
20402
|
onSettled?.({ queryId, kind: "error", error: outcome.error });
|
|
21296
|
-
} catch (
|
|
21297
|
-
logger.warn({ err
|
|
20403
|
+
} catch (err) {
|
|
20404
|
+
logger.warn({ err, topicId, queryId }, "ai: turn settlement hook failed");
|
|
21298
20405
|
}
|
|
21299
20406
|
return;
|
|
21300
20407
|
}
|
|
@@ -21307,12 +20414,12 @@ function startAiTurn(params) {
|
|
|
21307
20414
|
kind: outcome.kind === "aborted" ? "aborted" : "completed",
|
|
21308
20415
|
...outcome.kind === "aborted" ? { abortReason: control.abortReason } : {}
|
|
21309
20416
|
});
|
|
21310
|
-
} catch (
|
|
21311
|
-
logger.warn({ err
|
|
20417
|
+
} catch (err) {
|
|
20418
|
+
logger.warn({ err, topicId, queryId }, "ai: turn settlement hook failed");
|
|
21312
20419
|
}
|
|
21313
|
-
}).catch(async (
|
|
21314
|
-
const error =
|
|
21315
|
-
logger.warn({ err
|
|
20420
|
+
}).catch(async (err) => {
|
|
20421
|
+
const error = err instanceof Error ? err.message : "Agent process crashed";
|
|
20422
|
+
logger.warn({ err, topicId, queryId, agent: agentKind, model: resolvedModel, silent }, "ai: background stream task failed");
|
|
21316
20423
|
if (!silent) {
|
|
21317
20424
|
WsHub.get().broadcastError(topicId, queryId, error);
|
|
21318
20425
|
WsHub.get().broadcastTopicNotice(topicId, "error", "\uC751\uB2F5 \uC2E4\uD328");
|
|
@@ -21361,7 +20468,7 @@ function triggerTopicAiTurn(topicId, userId, prompt, agentType, opts) {
|
|
|
21361
20468
|
if (!opts?.silent && !opts?.hideInjectMessage) {
|
|
21362
20469
|
const now = new Date().toISOString();
|
|
21363
20470
|
const injectMsg = {
|
|
21364
|
-
id: opts?.requestId ? `tell-${opts.requestId}` : `tell-${
|
|
20471
|
+
id: opts?.requestId ? `tell-${opts.requestId}` : `tell-${randomUUID18()}`,
|
|
21365
20472
|
topicId,
|
|
21366
20473
|
authorId: opts?.injectAuthorId ?? userId,
|
|
21367
20474
|
sourceAdapter: opts?.injectSourceAdapter,
|
|
@@ -21418,7 +20525,7 @@ function triggerTopicAiTurn(topicId, userId, prompt, agentType, opts) {
|
|
|
21418
20525
|
from: opts?.from
|
|
21419
20526
|
});
|
|
21420
20527
|
}
|
|
21421
|
-
var PLAYWRIGHT_UNAVAILABLE_NOTICE_COOLDOWN_MS, ASK_REPLY_INJECT_BATCH_MS = 500, playwrightUnavailableNoticeAt, askReplyInjectBatcher, remoteInjectWaiters
|
|
20528
|
+
var PLAYWRIGHT_UNAVAILABLE_NOTICE_COOLDOWN_MS, ASK_REPLY_INJECT_BATCH_MS = 500, playwrightUnavailableNoticeAt, askReplyInjectBatcher, remoteInjectWaiters;
|
|
21422
20529
|
var init_turn_runner = __esm(async () => {
|
|
21423
20530
|
init_manager();
|
|
21424
20531
|
init_constants();
|
|
@@ -21549,29 +20656,29 @@ function createSubagentLifecycle(host) {
|
|
|
21549
20656
|
}
|
|
21550
20657
|
function computeSubagentDepth(topicId) {
|
|
21551
20658
|
let depth = 0;
|
|
21552
|
-
let
|
|
20659
|
+
let current = host.storage.getTopic(topicId);
|
|
21553
20660
|
const visited = new Set;
|
|
21554
|
-
while (
|
|
21555
|
-
if (visited.has(
|
|
20661
|
+
while (current) {
|
|
20662
|
+
if (visited.has(current.id))
|
|
21556
20663
|
return limits.maxDepth;
|
|
21557
|
-
visited.add(
|
|
21558
|
-
if (
|
|
20664
|
+
visited.add(current.id);
|
|
20665
|
+
if (current.isSubagent)
|
|
21559
20666
|
depth += 1;
|
|
21560
|
-
if (!
|
|
20667
|
+
if (!current.parentTopicId || current.parentTopicId === current.id)
|
|
21561
20668
|
break;
|
|
21562
|
-
|
|
20669
|
+
current = host.storage.getTopic(current.parentTopicId);
|
|
21563
20670
|
}
|
|
21564
20671
|
return depth;
|
|
21565
20672
|
}
|
|
21566
|
-
function
|
|
20673
|
+
function canSpawnSubagentsFromTopic(topicId) {
|
|
21567
20674
|
const topic = host.storage.getTopic(topicId);
|
|
21568
20675
|
return topic?.kind === "agent" && computeSubagentDepth(topicId) < limits.maxDepth;
|
|
21569
20676
|
}
|
|
21570
20677
|
function patchSubagentCard(parentTopicId, cardMessageId, patch) {
|
|
21571
|
-
const
|
|
21572
|
-
if (!
|
|
20678
|
+
const current = host.storage.getMessage(parentTopicId, cardMessageId)?.subagentCard;
|
|
20679
|
+
if (!current)
|
|
21573
20680
|
return;
|
|
21574
|
-
const next = { ...
|
|
20681
|
+
const next = { ...current, ...patch };
|
|
21575
20682
|
const editedAt = host.runtime.now();
|
|
21576
20683
|
if (!host.storage.updateSubagentCard(parentTopicId, cardMessageId, next, editedAt))
|
|
21577
20684
|
return;
|
|
@@ -21591,7 +20698,7 @@ function createSubagentLifecycle(host) {
|
|
|
21591
20698
|
patchSubagentCard(watch.parentTopicId, watch.cardMessageId, { status: "running" });
|
|
21592
20699
|
}
|
|
21593
20700
|
}
|
|
21594
|
-
function
|
|
20701
|
+
function takeSubagentWatch(queryId) {
|
|
21595
20702
|
const childTopicId = childByQueryId.get(queryId);
|
|
21596
20703
|
if (!childTopicId)
|
|
21597
20704
|
return recoverPersistedSubagentWatch(queryId);
|
|
@@ -21635,7 +20742,7 @@ function createSubagentLifecycle(host) {
|
|
|
21635
20742
|
if (watch.queryId)
|
|
21636
20743
|
childByQueryId.delete(watch.queryId);
|
|
21637
20744
|
}
|
|
21638
|
-
function
|
|
20745
|
+
function cancelSubagentWatchForDeletedTopic(childTopicId) {
|
|
21639
20746
|
const watch = watchesByChild.get(childTopicId);
|
|
21640
20747
|
if (!watch)
|
|
21641
20748
|
return;
|
|
@@ -21665,8 +20772,8 @@ function createSubagentLifecycle(host) {
|
|
|
21665
20772
|
if (!await host.sessionCommunication.notifyParent({ watch, prompt, requestId })) {
|
|
21666
20773
|
appendParentSystemNote(watch, prompt);
|
|
21667
20774
|
}
|
|
21668
|
-
} catch (
|
|
21669
|
-
logger.warn({ err
|
|
20775
|
+
} catch (err) {
|
|
20776
|
+
logger.warn({ err, parentTopicId: watch.parentTopicId, childTopicId: watch.childTopicId, noteKind }, "subagent: parent AI notify failed \u2014 falling back to system message");
|
|
21670
20777
|
try {
|
|
21671
20778
|
appendParentSystemNote(watch, prompt);
|
|
21672
20779
|
} catch (fallbackErr) {
|
|
@@ -21678,7 +20785,7 @@ function createSubagentLifecycle(host) {
|
|
|
21678
20785
|
}
|
|
21679
20786
|
}
|
|
21680
20787
|
}
|
|
21681
|
-
async function
|
|
20788
|
+
async function settleSubagentSuccess(watch, finalText) {
|
|
21682
20789
|
const summary = finalText.replace(/\s+/g, " ").trim().slice(0, RESULT_SUMMARY_CHARS);
|
|
21683
20790
|
try {
|
|
21684
20791
|
patchSubagentCard(watch.parentTopicId, watch.cardMessageId, {
|
|
@@ -21686,8 +20793,8 @@ function createSubagentLifecycle(host) {
|
|
|
21686
20793
|
resultSummary: summary || "(no text response)",
|
|
21687
20794
|
finishedAt: host.runtime.now()
|
|
21688
20795
|
});
|
|
21689
|
-
} catch (
|
|
21690
|
-
logger.warn({ err
|
|
20796
|
+
} catch (err) {
|
|
20797
|
+
logger.warn({ err, parentTopicId: watch.parentTopicId, cardMessageId: watch.cardMessageId }, "subagent: completed-card update failed");
|
|
21691
20798
|
}
|
|
21692
20799
|
if (watch.reportMode === "auto") {
|
|
21693
20800
|
await notifyParent(watch, `[Subagent completed \u2190 ${watch.name}]
|
|
@@ -21696,8 +20803,8 @@ function createSubagentLifecycle(host) {
|
|
|
21696
20803
|
${finalText || "(no text response)"}`, "done");
|
|
21697
20804
|
}
|
|
21698
20805
|
}
|
|
21699
|
-
async function
|
|
21700
|
-
const watch =
|
|
20806
|
+
async function settleSubagentFailure(queryId, reason) {
|
|
20807
|
+
const watch = takeSubagentWatch(queryId);
|
|
21701
20808
|
if (!watch)
|
|
21702
20809
|
return;
|
|
21703
20810
|
try {
|
|
@@ -21706,8 +20813,8 @@ ${finalText || "(no text response)"}`, "done");
|
|
|
21706
20813
|
errorMessage: reason,
|
|
21707
20814
|
finishedAt: host.runtime.now()
|
|
21708
20815
|
});
|
|
21709
|
-
} catch (
|
|
21710
|
-
logger.warn({ err
|
|
20816
|
+
} catch (err) {
|
|
20817
|
+
logger.warn({ err, parentTopicId: watch.parentTopicId, cardMessageId: watch.cardMessageId }, "subagent: failed-card update failed");
|
|
21711
20818
|
}
|
|
21712
20819
|
if (watch.reportMode === "auto") {
|
|
21713
20820
|
await notifyParent(watch, `[Subagent failed \u2190 ${watch.name}]
|
|
@@ -21744,7 +20851,7 @@ spawn_subagent\uB85C \uC704\uC784\uD55C \uC791\uC5C5\uC774 \uC2E4\uD328\uD588\uC
|
|
|
21744
20851
|
function findSubagentCardMessage(childTopicId) {
|
|
21745
20852
|
return host.storage.listSubagentMessages().filter((message) => message.subagentCard?.subagentTopicId === childTopicId).at(-1);
|
|
21746
20853
|
}
|
|
21747
|
-
function
|
|
20854
|
+
function subagentReportMode(childTopicId) {
|
|
21748
20855
|
return host.storage.getTopic(childTopicId)?.subagentReportMode ?? findSubagentCardMessage(childTopicId)?.subagentCard?.reportMode ?? "auto";
|
|
21749
20856
|
}
|
|
21750
20857
|
async function startSubagentCard(ctx, cardMessage) {
|
|
@@ -21952,7 +21059,7 @@ ${card.task}${reportInstruction}`;
|
|
|
21952
21059
|
for (const siblings of byParent.values()) {
|
|
21953
21060
|
siblings.sort((a, b) => a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id));
|
|
21954
21061
|
}
|
|
21955
|
-
const
|
|
21062
|
+
const descendants = [];
|
|
21956
21063
|
const visited = new Set([ctx.topicId]);
|
|
21957
21064
|
const visit = (parentId) => {
|
|
21958
21065
|
for (const child of byParent.get(parentId) ?? []) {
|
|
@@ -21962,12 +21069,12 @@ ${card.task}${reportInstruction}`;
|
|
|
21962
21069
|
if (!child.participants.some((participant) => participant.userId === rootOwnerId && participant.role === "owner")) {
|
|
21963
21070
|
continue;
|
|
21964
21071
|
}
|
|
21965
|
-
|
|
21072
|
+
descendants.push(child);
|
|
21966
21073
|
visit(child.id);
|
|
21967
21074
|
}
|
|
21968
21075
|
};
|
|
21969
21076
|
visit(ctx.topicId);
|
|
21970
|
-
return
|
|
21077
|
+
return descendants;
|
|
21971
21078
|
})() : [];
|
|
21972
21079
|
const children = actorScope ? descendants.filter((child) => actorScope.visible.has(child.id)) : descendants;
|
|
21973
21080
|
return {
|
|
@@ -21991,10 +21098,10 @@ ${card.task}${reportInstruction}`;
|
|
|
21991
21098
|
return card?.status ?? "unknown";
|
|
21992
21099
|
}
|
|
21993
21100
|
function listMemoryTopicNames(ctx) {
|
|
21994
|
-
const
|
|
21995
|
-
if (!
|
|
21101
|
+
const current = host.storage.getTopic(ctx.topicId);
|
|
21102
|
+
if (!current)
|
|
21996
21103
|
return { error: `Error: topic '${ctx.topicId}' not found.` };
|
|
21997
|
-
if (!
|
|
21104
|
+
if (!current.participants.some((participant) => participant.userId === ctx.userId)) {
|
|
21998
21105
|
return { error: "Error: user is not a member of this topic." };
|
|
21999
21106
|
}
|
|
22000
21107
|
const sources = new Map;
|
|
@@ -22084,8 +21191,8 @@ ${card.task}${reportInstruction}`;
|
|
|
22084
21191
|
try {
|
|
22085
21192
|
await host.topic.delete(child, ctx.userId);
|
|
22086
21193
|
return textResult(`Subagent deleted: ${child.title} (${child.id})`);
|
|
22087
|
-
} catch (
|
|
22088
|
-
const message =
|
|
21194
|
+
} catch (err) {
|
|
21195
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
22089
21196
|
return errorResult(`Error: failed to delete subagent '${child.title}': ${message}`);
|
|
22090
21197
|
}
|
|
22091
21198
|
}
|
|
@@ -22182,13 +21289,13 @@ ${card.task}${reportInstruction}`;
|
|
|
22182
21289
|
}
|
|
22183
21290
|
return {
|
|
22184
21291
|
computeSubagentDepth,
|
|
22185
|
-
canSpawnSubagentsFromTopic
|
|
22186
|
-
takeSubagentWatch
|
|
22187
|
-
cancelSubagentWatchForDeletedTopic
|
|
22188
|
-
settleSubagentSuccess
|
|
22189
|
-
settleSubagentFailure
|
|
21292
|
+
canSpawnSubagentsFromTopic,
|
|
21293
|
+
takeSubagentWatch,
|
|
21294
|
+
cancelSubagentWatchForDeletedTopic,
|
|
21295
|
+
settleSubagentSuccess,
|
|
21296
|
+
settleSubagentFailure,
|
|
22190
21297
|
sweepStaleSubagentCards,
|
|
22191
|
-
subagentReportMode
|
|
21298
|
+
subagentReportMode,
|
|
22192
21299
|
createSubagentManagementToolDefinitions,
|
|
22193
21300
|
createSpawnSubagentToolDefinition,
|
|
22194
21301
|
createPrepareSubagentToolDefinition
|
|
@@ -22235,9 +21342,9 @@ var init_spawn_subagent = __esm(async () => {
|
|
|
22235
21342
|
},
|
|
22236
21343
|
topic: {
|
|
22237
21344
|
async createDerived(input) {
|
|
22238
|
-
|
|
21345
|
+
await init_derive();
|
|
22239
21346
|
try {
|
|
22240
|
-
const topic = await
|
|
21347
|
+
const topic = await createDerivedTopic(input.parentTopicId, input.userId, false, {
|
|
22241
21348
|
name: input.name,
|
|
22242
21349
|
subagent: {
|
|
22243
21350
|
agent: input.agent,
|
|
@@ -22247,30 +21354,30 @@ var init_spawn_subagent = __esm(async () => {
|
|
|
22247
21354
|
});
|
|
22248
21355
|
return { ok: true, topic };
|
|
22249
21356
|
} catch (error) {
|
|
22250
|
-
if (error instanceof
|
|
21357
|
+
if (error instanceof TopicTitleConflictError) {
|
|
22251
21358
|
return { ok: false, reason: "title-conflict", message: error.message };
|
|
22252
21359
|
}
|
|
22253
|
-
if (error instanceof
|
|
21360
|
+
if (error instanceof TopicDeriveBusyError)
|
|
22254
21361
|
return { ok: false, reason: "busy" };
|
|
22255
21362
|
throw error;
|
|
22256
21363
|
}
|
|
22257
21364
|
},
|
|
22258
21365
|
async delete(topic, userId) {
|
|
22259
|
-
|
|
22260
|
-
await
|
|
21366
|
+
await init_lifecycle();
|
|
21367
|
+
await deleteTopicCascade(topic, userId);
|
|
22261
21368
|
}
|
|
22262
21369
|
},
|
|
22263
21370
|
task: {
|
|
22264
21371
|
async dispatch(input) {
|
|
22265
|
-
|
|
22266
|
-
|
|
22267
|
-
const queryId =
|
|
21372
|
+
await init_turn_runner();
|
|
21373
|
+
await init_active_rooms();
|
|
21374
|
+
const queryId = triggerTopicAiTurn(input.child.id, input.userId, input.prompt, undefined, {
|
|
22268
21375
|
origin: `subagent-task:${input.parent.title}`,
|
|
22269
21376
|
requestId: input.requestId,
|
|
22270
21377
|
injectAuthorId: "ai",
|
|
22271
21378
|
onDispatched: input.onDispatched
|
|
22272
21379
|
});
|
|
22273
|
-
return { accepted: Boolean(queryId ||
|
|
21380
|
+
return { accepted: Boolean(queryId || getRoomQuery(input.child.id)) };
|
|
22274
21381
|
}
|
|
22275
21382
|
},
|
|
22276
21383
|
sessionCommunication: {
|
|
@@ -22278,16 +21385,16 @@ var init_spawn_subagent = __esm(async () => {
|
|
|
22278
21385
|
const parent = getTopic(watch.parentTopicId);
|
|
22279
21386
|
if (!parent)
|
|
22280
21387
|
return true;
|
|
22281
|
-
|
|
22282
|
-
const queryId = parent.agent ?
|
|
21388
|
+
await init_turn_runner();
|
|
21389
|
+
const queryId = parent.agent ? triggerTopicAiTurn(watch.parentTopicId, watch.userId, prompt, undefined, {
|
|
22283
21390
|
origin: `subagent:${watch.name}`,
|
|
22284
21391
|
requestId,
|
|
22285
21392
|
hideInjectMessage: true
|
|
22286
21393
|
}) : null;
|
|
22287
21394
|
if (queryId)
|
|
22288
21395
|
return true;
|
|
22289
|
-
|
|
22290
|
-
return Boolean(parent.agent &&
|
|
21396
|
+
await init_active_rooms();
|
|
21397
|
+
return Boolean(parent.agent && interSessionQueue.hasRequest(parent.id, requestId));
|
|
22291
21398
|
},
|
|
22292
21399
|
listTellTargetIds: listSubagentTellTargetIds,
|
|
22293
21400
|
grantTellTarget: grantSubagentTellTarget,
|
|
@@ -22316,19 +21423,19 @@ var init_spawn_subagent = __esm(async () => {
|
|
|
22316
21423
|
async resolveAgentModel({ context, agent, model, hasOverride }) {
|
|
22317
21424
|
let resolvedModel = model;
|
|
22318
21425
|
if (model) {
|
|
22319
|
-
|
|
22320
|
-
|
|
22321
|
-
const registry =
|
|
21426
|
+
await Promise.resolve().then(() => init_model_catalog());
|
|
21427
|
+
await init_registry();
|
|
21428
|
+
const registry = getRegistry(agent);
|
|
22322
21429
|
if (!registry.validateModel(model)) {
|
|
22323
21430
|
return { error: `Error: model '${model}' is not valid for agent '${agent}'.` };
|
|
22324
21431
|
}
|
|
22325
|
-
resolvedModel =
|
|
21432
|
+
resolvedModel = resolveModelForAgent(agent, model, registry);
|
|
22326
21433
|
}
|
|
22327
21434
|
if (hasOverride) {
|
|
22328
|
-
|
|
22329
|
-
|
|
22330
|
-
const targetModel = resolvedModel ??
|
|
22331
|
-
const auth =
|
|
21435
|
+
await init_auth_check();
|
|
21436
|
+
await init_registry();
|
|
21437
|
+
const targetModel = resolvedModel ?? getRegistry(agent).defaultModel;
|
|
21438
|
+
const auth = checkAgentModelAuth(agent, targetModel, undefined, context.userId);
|
|
22332
21439
|
if (!auth.ok) {
|
|
22333
21440
|
return { error: `Error: agent '${agent}' is not available: ${auth.error}` };
|
|
22334
21441
|
}
|
|
@@ -22758,11 +21865,11 @@ var DEFAULT_SELF_CONFIG_PRODUCT = {
|
|
|
22758
21865
|
derivedTopicLimit: SELF_CONFIG_DERIVED_TOPIC_LIMIT,
|
|
22759
21866
|
toolDescriptions: {}
|
|
22760
21867
|
};
|
|
22761
|
-
function ok(
|
|
22762
|
-
return { text
|
|
21868
|
+
function ok(text) {
|
|
21869
|
+
return { text };
|
|
22763
21870
|
}
|
|
22764
|
-
function err(
|
|
22765
|
-
return { text
|
|
21871
|
+
function err(text) {
|
|
21872
|
+
return { text, isError: true };
|
|
22766
21873
|
}
|
|
22767
21874
|
function errorMessage(error) {
|
|
22768
21875
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -23079,8 +22186,8 @@ var defaultSelfConfigHost = {
|
|
|
23079
22186
|
},
|
|
23080
22187
|
derivedTopics: {
|
|
23081
22188
|
async create(sourceTopicId, userId, copyHistory, options) {
|
|
23082
|
-
|
|
23083
|
-
return
|
|
22189
|
+
await init_derive();
|
|
22190
|
+
return createDerivedTopic(sourceTopicId, userId, copyHistory, options);
|
|
23084
22191
|
},
|
|
23085
22192
|
link: topicMarkdownLink,
|
|
23086
22193
|
isTitleConflict: (error) => error instanceof Error && error.name === "TopicTitleConflictError",
|
|
@@ -23360,58 +22467,58 @@ await __promiseAll([
|
|
|
23360
22467
|
init_topic_cleanup()
|
|
23361
22468
|
]);
|
|
23362
22469
|
export {
|
|
23363
|
-
|
|
23364
|
-
withCodexSpawnSerial,
|
|
23365
|
-
visualToolDefinitions,
|
|
23366
|
-
unregisterOwnedCodexPids,
|
|
23367
|
-
summarizeToolInput,
|
|
23368
|
-
summarizeShellCommand,
|
|
23369
|
-
summarizeDisplayText,
|
|
23370
|
-
snapshotCodexChildren,
|
|
23371
|
-
showPngTool,
|
|
23372
|
-
showMermaidTool,
|
|
23373
|
-
showImageTool,
|
|
23374
|
-
showHtmlTool,
|
|
23375
|
-
rotateTopicLogs,
|
|
23376
|
-
resolveTaskEventScope,
|
|
23377
|
-
registerOwnedCodexPids,
|
|
23378
|
-
purgeTopicLogs,
|
|
23379
|
-
otiumVisualToolDefinitions,
|
|
23380
|
-
normalizeAskUserQuestionInput,
|
|
23381
|
-
normalizeAskUserChoices,
|
|
23382
|
-
killOwnedCodexTreesForShutdown,
|
|
23383
|
-
killCodexTrees,
|
|
23384
|
-
isExplicitAgentSwitchTargets,
|
|
23385
|
-
hasExplicitAgentSwitchRequest,
|
|
23386
|
-
formatToolUse,
|
|
23387
|
-
forkAgentSession,
|
|
23388
|
-
findNewCodexChildren,
|
|
23389
|
-
explicitAgentSwitchTargets,
|
|
23390
|
-
defaultAskUserDurabilityHost,
|
|
23391
|
-
createTopicLogMaintenance,
|
|
23392
|
-
createSubagentLifecycle,
|
|
23393
|
-
createSelfConfigToolDefinitionsForCore,
|
|
23394
|
-
createSelfConfigRuntime,
|
|
23395
|
-
createSelfConfigCore,
|
|
23396
|
-
createPublishHtmlToolDefinitions,
|
|
23397
|
-
createCodexTreeManager,
|
|
23398
|
-
createAskUserRuntime,
|
|
23399
|
-
createArchiverRuntime,
|
|
23400
|
-
createAgentForkHelpers,
|
|
23401
|
-
cleanupTopicRolloutsFromEntries,
|
|
23402
|
-
cleanupTopicRollouts,
|
|
23403
|
-
cleanupAgentFork,
|
|
23404
|
-
classifyShellToolName,
|
|
23405
|
-
checkAgentModelAuth,
|
|
23406
|
-
checkAgentAuth,
|
|
23407
|
-
buildNumberedDiffSummary,
|
|
23408
|
-
archiveActiveTopicForMemory,
|
|
23409
|
-
applySelfConfigCapabilityFilter,
|
|
23410
|
-
acquireCodexSpawnLock,
|
|
23411
|
-
VISUALS_MCP_KEY,
|
|
23412
|
-
SELF_CONFIG_CAPABILITIES,
|
|
22470
|
+
DEFAULT_SELF_CONFIG_PRODUCT,
|
|
23413
22471
|
MIN_MEMORY_ARCHIVE_EXCHANGES,
|
|
23414
|
-
|
|
22472
|
+
SELF_CONFIG_CAPABILITIES,
|
|
22473
|
+
VISUALS_MCP_KEY,
|
|
22474
|
+
acquireCodexSpawnLock,
|
|
22475
|
+
applySelfConfigCapabilityFilter,
|
|
22476
|
+
archiveActiveTopicForMemory,
|
|
22477
|
+
buildNumberedDiffSummary,
|
|
22478
|
+
checkAgentAuth,
|
|
22479
|
+
checkAgentModelAuth,
|
|
22480
|
+
classifyShellToolName,
|
|
22481
|
+
cleanupAgentFork,
|
|
22482
|
+
cleanupTopicRollouts,
|
|
22483
|
+
cleanupTopicRolloutsFromEntries,
|
|
22484
|
+
createAgentForkHelpers,
|
|
22485
|
+
createArchiverRuntime,
|
|
22486
|
+
createAskUserRuntime,
|
|
22487
|
+
createCodexTreeManager,
|
|
22488
|
+
createPublishHtmlToolDefinitions,
|
|
22489
|
+
createSelfConfigCore,
|
|
22490
|
+
createSelfConfigRuntime,
|
|
22491
|
+
createSelfConfigToolDefinitionsForCore,
|
|
22492
|
+
createSubagentLifecycle,
|
|
22493
|
+
createTopicLogMaintenance,
|
|
22494
|
+
defaultAskUserDurabilityHost,
|
|
22495
|
+
explicitAgentSwitchTargets,
|
|
22496
|
+
findNewCodexChildren,
|
|
22497
|
+
forkAgentSession,
|
|
22498
|
+
formatToolUse,
|
|
22499
|
+
hasExplicitAgentSwitchRequest,
|
|
22500
|
+
isExplicitAgentSwitchTargets,
|
|
22501
|
+
killCodexTrees,
|
|
22502
|
+
killOwnedCodexTreesForShutdown,
|
|
22503
|
+
normalizeAskUserChoices,
|
|
22504
|
+
normalizeAskUserQuestionInput,
|
|
22505
|
+
otiumVisualToolDefinitions,
|
|
22506
|
+
purgeTopicLogs,
|
|
22507
|
+
registerOwnedCodexPids,
|
|
22508
|
+
resolveTaskEventScope,
|
|
22509
|
+
rotateTopicLogs,
|
|
22510
|
+
showHtmlTool,
|
|
22511
|
+
showImageTool,
|
|
22512
|
+
showMermaidTool,
|
|
22513
|
+
showPngTool,
|
|
22514
|
+
snapshotCodexChildren,
|
|
22515
|
+
summarizeDisplayText,
|
|
22516
|
+
summarizeShellCommand,
|
|
22517
|
+
summarizeToolInput,
|
|
22518
|
+
unregisterOwnedCodexPids,
|
|
22519
|
+
visualToolDefinitions,
|
|
22520
|
+
withCodexSpawnSerial,
|
|
22521
|
+
withTaskSnapshots
|
|
23415
22522
|
};
|
|
23416
22523
|
|
|
23417
|
-
//# debugId=
|
|
22524
|
+
//# debugId=821FEE68439440EC64756E2164756E21
|