negotium 0.22.5 → 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 +394 -1295
- package/dist/agent-helpers.js.map +3 -3
- 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-a3me2mje.js → chunk-1e0nxy7p.js} +12 -12
- package/dist/{chunk-a3me2mje.js.map → chunk-1e0nxy7p.js.map} +2 -2
- 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-vh8px000.js → chunk-9a50csg6.js} +115 -119
- package/dist/{chunk-vh8px000.js.map → chunk-9a50csg6.js.map} +6 -6
- package/dist/chunk-bnyvxss3.js +77 -0
- package/dist/{chunk-q5djsg78.js.map → chunk-bnyvxss3.js.map} +1 -1
- package/dist/{chunk-7rpbcn1j.js → chunk-e59kzyvy.js} +4 -5
- package/dist/{chunk-7rpbcn1j.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 +119 -122
- package/dist/hosted-agent.js.map +3 -3
- package/dist/main.js +3303 -5132
- package/dist/main.js.map +5 -5
- package/dist/mcp-catalog.js +4 -4
- package/dist/mcp-catalog.js.map +1 -1
- package/dist/mcp-factories.js +616 -1509
- package/dist/mcp-factories.js.map +3 -3
- 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/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/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/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
|
}
|
|
@@ -5236,7 +5119,7 @@ var init_codex = __esm(async () => {
|
|
|
5236
5119
|
});
|
|
5237
5120
|
|
|
5238
5121
|
// ../../packages/core/src/version.ts
|
|
5239
|
-
var NEGOTIUM_VERSION = "0.22.
|
|
5122
|
+
var NEGOTIUM_VERSION = "0.22.6";
|
|
5240
5123
|
|
|
5241
5124
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
5242
5125
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -5312,7 +5195,7 @@ async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
|
5312
5195
|
stdio: ["pipe", "pipe", "pipe"],
|
|
5313
5196
|
windowsHide: true
|
|
5314
5197
|
});
|
|
5315
|
-
const refreshed = new Promise((
|
|
5198
|
+
const refreshed = new Promise((resolve, reject) => {
|
|
5316
5199
|
let settled = false;
|
|
5317
5200
|
let stdoutBuffer = "";
|
|
5318
5201
|
let stderr = "";
|
|
@@ -5331,7 +5214,7 @@ async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
|
5331
5214
|
else if (!existsSync6(cachePath))
|
|
5332
5215
|
reject(new Error("Codex did not create its model cache"));
|
|
5333
5216
|
else
|
|
5334
|
-
|
|
5217
|
+
resolve();
|
|
5335
5218
|
};
|
|
5336
5219
|
const send = (message) => {
|
|
5337
5220
|
child.stdin.write(`${JSON.stringify(message)}
|
|
@@ -5397,12 +5280,12 @@ async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
|
5397
5280
|
function waitForChildExit(child, timeoutMs) {
|
|
5398
5281
|
if (child.exitCode !== null || child.signalCode !== null)
|
|
5399
5282
|
return Promise.resolve();
|
|
5400
|
-
return new Promise((
|
|
5401
|
-
const timer = setTimeout(
|
|
5283
|
+
return new Promise((resolve) => {
|
|
5284
|
+
const timer = setTimeout(resolve, timeoutMs);
|
|
5402
5285
|
timer.unref?.();
|
|
5403
5286
|
child.once("exit", () => {
|
|
5404
5287
|
clearTimeout(timer);
|
|
5405
|
-
|
|
5288
|
+
resolve();
|
|
5406
5289
|
});
|
|
5407
5290
|
});
|
|
5408
5291
|
}
|
|
@@ -5492,16 +5375,11 @@ var init_codex_native_multi_agent = __esm(() => {
|
|
|
5492
5375
|
});
|
|
5493
5376
|
|
|
5494
5377
|
// ../../packages/core/src/agents/codex-app-server.ts
|
|
5495
|
-
var exports_codex_app_server = {};
|
|
5496
|
-
__export(exports_codex_app_server, {
|
|
5497
|
-
forkCodexSession: () => forkCodexSession,
|
|
5498
|
-
createCodexAppServerForker: () => createCodexAppServerForker
|
|
5499
|
-
});
|
|
5500
5378
|
import { spawn as spawn3 } from "child_process";
|
|
5501
5379
|
function createCodexAppServerForker(host) {
|
|
5502
5380
|
return async (parentThreadId) => {
|
|
5503
5381
|
const child = host.spawnServer();
|
|
5504
|
-
return await new Promise((
|
|
5382
|
+
return await new Promise((resolve, reject) => {
|
|
5505
5383
|
let settled = false;
|
|
5506
5384
|
let stdoutBuffer = "";
|
|
5507
5385
|
let stderr = "";
|
|
@@ -5518,7 +5396,7 @@ function createCodexAppServerForker(host) {
|
|
|
5518
5396
|
if (error)
|
|
5519
5397
|
reject(error);
|
|
5520
5398
|
else if (result)
|
|
5521
|
-
|
|
5399
|
+
resolve(result);
|
|
5522
5400
|
else
|
|
5523
5401
|
reject(new Error("Codex thread fork returned no result"));
|
|
5524
5402
|
};
|
|
@@ -5655,8 +5533,8 @@ var init_codex_registry = __esm(async () => {
|
|
|
5655
5533
|
return { sessionId: threadId, rolloutPath };
|
|
5656
5534
|
},
|
|
5657
5535
|
async forkSession({ parentSessionId }) {
|
|
5658
|
-
|
|
5659
|
-
return await
|
|
5536
|
+
await init_codex_app_server();
|
|
5537
|
+
return await forkCodexSession(parentSessionId);
|
|
5660
5538
|
},
|
|
5661
5539
|
async cleanupRollouts({ sessionIds }) {
|
|
5662
5540
|
if (sessionIds.length === 0)
|
|
@@ -5837,11 +5715,6 @@ var init_maestro_registry = __esm(() => {
|
|
|
5837
5715
|
});
|
|
5838
5716
|
|
|
5839
5717
|
// ../../packages/core/src/agents/registry.ts
|
|
5840
|
-
var exports_registry = {};
|
|
5841
|
-
__export(exports_registry, {
|
|
5842
|
-
getRegistryOperations: () => getRegistryOperations,
|
|
5843
|
-
getRegistry: () => getRegistry
|
|
5844
|
-
});
|
|
5845
5718
|
function getRegistry(agent) {
|
|
5846
5719
|
return REGISTRIES[agent];
|
|
5847
5720
|
}
|
|
@@ -6228,11 +6101,11 @@ var DEFAULT_CONTEXT_WARNING_RATIO = 0.8;
|
|
|
6228
6101
|
// ../../packages/core/src/agents/claude-provider.ts
|
|
6229
6102
|
var exports_claude_provider = {};
|
|
6230
6103
|
__export(exports_claude_provider, {
|
|
6231
|
-
|
|
6232
|
-
spawnClaudeCodeProcessWithTreeKill: () => spawnClaudeCodeProcessWithTreeKill,
|
|
6233
|
-
claudeProvider: () => claudeProvider,
|
|
6104
|
+
buildClaudeDisallowedTools: () => buildClaudeDisallowedTools,
|
|
6234
6105
|
claudeBuiltInTools: () => claudeBuiltInTools,
|
|
6235
|
-
|
|
6106
|
+
claudeProvider: () => claudeProvider,
|
|
6107
|
+
spawnClaudeCodeProcessWithTreeKill: () => spawnClaudeCodeProcessWithTreeKill,
|
|
6108
|
+
substituteClaudeToolInput: () => substituteClaudeToolInput
|
|
6236
6109
|
});
|
|
6237
6110
|
import { spawn as spawn4 } from "child_process";
|
|
6238
6111
|
import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
|
|
@@ -6313,8 +6186,8 @@ function buildClaudePrompt(opts) {
|
|
|
6313
6186
|
}
|
|
6314
6187
|
function watchClaudeProcessExit(signal) {
|
|
6315
6188
|
let listener;
|
|
6316
|
-
const exited = new Promise((
|
|
6317
|
-
listener =
|
|
6189
|
+
const exited = new Promise((resolve) => {
|
|
6190
|
+
listener = resolve;
|
|
6318
6191
|
const listeners = claudeProcessExitListeners.get(signal) ?? new Set;
|
|
6319
6192
|
listeners.add(listener);
|
|
6320
6193
|
claudeProcessExitListeners.set(signal, listeners);
|
|
@@ -6839,12 +6712,12 @@ function createCodexTreeManager(host, options = {}) {
|
|
|
6839
6712
|
const previous = spawnChain;
|
|
6840
6713
|
let release;
|
|
6841
6714
|
let released = false;
|
|
6842
|
-
spawnChain = new Promise((
|
|
6715
|
+
spawnChain = new Promise((resolve) => {
|
|
6843
6716
|
release = () => {
|
|
6844
6717
|
if (released)
|
|
6845
6718
|
return;
|
|
6846
6719
|
released = true;
|
|
6847
|
-
|
|
6720
|
+
resolve();
|
|
6848
6721
|
};
|
|
6849
6722
|
});
|
|
6850
6723
|
await previous;
|
|
@@ -6951,7 +6824,7 @@ function createCodexTreeManager(host, options = {}) {
|
|
|
6951
6824
|
return;
|
|
6952
6825
|
const deadline = Date.now() + Math.max(0, graceMs);
|
|
6953
6826
|
while (Date.now() < deadline && hasSurvivors(plan.targets)) {
|
|
6954
|
-
await new Promise((
|
|
6827
|
+
await new Promise((resolve) => setTimeout(resolve, Math.min(100, Math.max(1, deadline - Date.now()))));
|
|
6955
6828
|
}
|
|
6956
6829
|
killStragglers(plan);
|
|
6957
6830
|
}
|
|
@@ -7279,8 +7152,8 @@ async function createCodexVaultHookBridge(userId) {
|
|
|
7279
7152
|
});
|
|
7280
7153
|
restrictIpcEndpoint(socketPath);
|
|
7281
7154
|
if (IS_WINDOWS2) {
|
|
7282
|
-
|
|
7283
|
-
const cached = await ensureCodexWindowsWrapperExe(join13(
|
|
7155
|
+
await Promise.resolve().then(() => init_config());
|
|
7156
|
+
const cached = await ensureCodexWindowsWrapperExe(join13(BINARIES_DIR, "codex-hook-wrapper"));
|
|
7284
7157
|
await copyFile(cached, wrapperPath);
|
|
7285
7158
|
await writeFile2(join13(root, "codex-with-hooks.cfg"), [process.execPath, codexCliScriptPath(), socketPath, token].join(`
|
|
7286
7159
|
`), { encoding: "utf8", mode: 384 });
|
|
@@ -7852,9 +7725,9 @@ var init_tool_format = __esm(() => {
|
|
|
7852
7725
|
// ../../packages/core/src/agents/codex-provider.ts
|
|
7853
7726
|
var exports_codex_provider = {};
|
|
7854
7727
|
__export(exports_codex_provider, {
|
|
7855
|
-
|
|
7728
|
+
codexProvider: () => codexProvider,
|
|
7856
7729
|
normalizeCodexTurnUsage: () => normalizeCodexTurnUsage,
|
|
7857
|
-
|
|
7730
|
+
toCodexMcpServers: () => toCodexMcpServers
|
|
7858
7731
|
});
|
|
7859
7732
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
7860
7733
|
import { existsSync as existsSync14, readFileSync as readFileSync11, realpathSync as realpathSync4, statSync as statSync5 } from "fs";
|
|
@@ -8154,9 +8027,9 @@ async function startStreamedWithTracking(thread, prompt, abortSignal, trackedPid
|
|
|
8154
8027
|
nextP.catch(() => {});
|
|
8155
8028
|
first = await Promise.race([nextP, startupTimeout]);
|
|
8156
8029
|
} catch (err) {
|
|
8157
|
-
const
|
|
8158
|
-
if (
|
|
8159
|
-
killCodexTrees(
|
|
8030
|
+
const novel = findNewCodexChildren(baseline);
|
|
8031
|
+
if (novel.length > 0) {
|
|
8032
|
+
killCodexTrees(novel);
|
|
8160
8033
|
}
|
|
8161
8034
|
await closeIterator(iter);
|
|
8162
8035
|
throw err;
|
|
@@ -8574,11 +8447,11 @@ var init_maestro_bootstrap_env = __esm(() => {
|
|
|
8574
8447
|
// ../../packages/core/src/agents/maestro-provider.ts
|
|
8575
8448
|
var exports_maestro_provider = {};
|
|
8576
8449
|
__export(exports_maestro_provider, {
|
|
8577
|
-
|
|
8578
|
-
maestroProvider: () => maestroProvider,
|
|
8579
|
-
buildMaestroToolResultTruncation: () => buildMaestroToolResultTruncation,
|
|
8450
|
+
buildMaestroDisallowedTools: () => buildMaestroDisallowedTools,
|
|
8580
8451
|
buildMaestroToolHooks: () => buildMaestroToolHooks,
|
|
8581
|
-
|
|
8452
|
+
buildMaestroToolResultTruncation: () => buildMaestroToolResultTruncation,
|
|
8453
|
+
maestroProvider: () => maestroProvider,
|
|
8454
|
+
resolveMaestroApiKeyOverrides: () => resolveMaestroApiKeyOverrides
|
|
8582
8455
|
});
|
|
8583
8456
|
import { resolve as resolve11 } from "path";
|
|
8584
8457
|
import { maestroProvider as sdkMaestroProvider, setMcpResolver } from "maestro-agent-sdk";
|
|
@@ -8706,18 +8579,18 @@ import { join as join15 } from "path";
|
|
|
8706
8579
|
async function* dispatchAgent(opts) {
|
|
8707
8580
|
switch (opts.agent) {
|
|
8708
8581
|
case "claude": {
|
|
8709
|
-
const { claudeProvider
|
|
8710
|
-
yield*
|
|
8582
|
+
const { claudeProvider } = await loadClaudeProvider();
|
|
8583
|
+
yield* claudeProvider(opts);
|
|
8711
8584
|
return;
|
|
8712
8585
|
}
|
|
8713
8586
|
case "codex": {
|
|
8714
|
-
const { codexProvider
|
|
8715
|
-
yield*
|
|
8587
|
+
const { codexProvider } = await loadCodexProvider();
|
|
8588
|
+
yield* codexProvider(opts);
|
|
8716
8589
|
return;
|
|
8717
8590
|
}
|
|
8718
8591
|
case "maestro": {
|
|
8719
|
-
const { maestroProvider
|
|
8720
|
-
yield*
|
|
8592
|
+
const { maestroProvider } = await loadMaestroProvider();
|
|
8593
|
+
yield* maestroProvider(opts);
|
|
8721
8594
|
return;
|
|
8722
8595
|
}
|
|
8723
8596
|
default: {
|
|
@@ -8748,8 +8621,8 @@ async function resolveSessionFileMissing(agent, sessionId, cwd) {
|
|
|
8748
8621
|
return true;
|
|
8749
8622
|
}
|
|
8750
8623
|
case "maestro": {
|
|
8751
|
-
const { hasActiveMaestroSession, maestroSessionPath
|
|
8752
|
-
return !existsSync15(
|
|
8624
|
+
const { hasActiveMaestroSession, maestroSessionPath } = await import("maestro-agent-sdk");
|
|
8625
|
+
return !existsSync15(maestroSessionPath(sessionId)) && !hasActiveMaestroSession(sessionId);
|
|
8753
8626
|
}
|
|
8754
8627
|
default: {
|
|
8755
8628
|
const _exhaustive = agent;
|
|
@@ -8828,24 +8701,6 @@ var init_agents = __esm(async () => {
|
|
|
8828
8701
|
});
|
|
8829
8702
|
|
|
8830
8703
|
// ../../packages/core/src/agents/model-catalog.ts
|
|
8831
|
-
var exports_model_catalog = {};
|
|
8832
|
-
__export(exports_model_catalog, {
|
|
8833
|
-
selectableModel: () => selectableModel,
|
|
8834
|
-
resolveWorkerModel: () => resolveWorkerModel,
|
|
8835
|
-
resolveWorkerDefaultModel: () => resolveWorkerDefaultModel,
|
|
8836
|
-
resolveModelForAgent: () => resolveModelForAgent,
|
|
8837
|
-
resolveDefaultModel: () => resolveDefaultModel,
|
|
8838
|
-
resolveCompactionExecution: () => resolveCompactionExecution,
|
|
8839
|
-
modelOwner: () => modelOwner,
|
|
8840
|
-
formatSelectableModel: () => formatSelectableModel,
|
|
8841
|
-
canonicalModelId: () => canonicalModelId,
|
|
8842
|
-
SELECTABLE_MODELS: () => SELECTABLE_MODELS,
|
|
8843
|
-
MODEL_OWNER: () => MODEL_OWNER,
|
|
8844
|
-
MODEL_COST_ROUTING_SUMMARY: () => MODEL_COST_ROUTING_SUMMARY,
|
|
8845
|
-
MODEL_COST_RESEARCHED_AT: () => MODEL_COST_RESEARCHED_AT,
|
|
8846
|
-
FALLBACK_ORDER: () => FALLBACK_ORDER,
|
|
8847
|
-
AGENT_DISPLAY_NAME: () => AGENT_DISPLAY_NAME
|
|
8848
|
-
});
|
|
8849
8704
|
function canonicalModelId(value) {
|
|
8850
8705
|
const trimmed = value.trim();
|
|
8851
8706
|
const lower = trimmed.toLowerCase();
|
|
@@ -8855,10 +8710,6 @@ function formatSelectableModel(candidate) {
|
|
|
8855
8710
|
const tier = `${candidate.intelligenceTier[0].toUpperCase()}${candidate.intelligenceTier.slice(1)}`;
|
|
8856
8711
|
return `${candidate.agent} / \`${candidate.model}\` [${tier}-level]: ${candidate.routingSummary}`;
|
|
8857
8712
|
}
|
|
8858
|
-
function selectableModel(value) {
|
|
8859
|
-
const canonical = canonicalModelId(value).toLowerCase();
|
|
8860
|
-
return SELECTABLE_MODELS.find((candidate) => candidate.model === canonical);
|
|
8861
|
-
}
|
|
8862
8713
|
function modelOwner(model) {
|
|
8863
8714
|
const lower = model.toLowerCase();
|
|
8864
8715
|
if (lower.startsWith("claude-"))
|
|
@@ -8911,7 +8762,7 @@ function resolveCompactionExecution(agent, registry) {
|
|
|
8911
8762
|
const effort = registry.validateEffort("medium") ? "medium" : registry.defaultEffort;
|
|
8912
8763
|
return { model, ...effort ? { effort } : {} };
|
|
8913
8764
|
}
|
|
8914
|
-
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;
|
|
8915
8766
|
var init_model_catalog = __esm(() => {
|
|
8916
8767
|
init_config();
|
|
8917
8768
|
MODEL_OWNER = {
|
|
@@ -9083,20 +8934,6 @@ var init_model_catalog = __esm(() => {
|
|
|
9083
8934
|
"glm-flash": "glm-5.3-flash"
|
|
9084
8935
|
};
|
|
9085
8936
|
CANONICAL_MODEL_CASING = Object.fromEntries(SELECTABLE_MODELS.map((candidate) => [candidate.model.toLowerCase(), candidate.model]));
|
|
9086
|
-
FALLBACK_ORDER = {
|
|
9087
|
-
claude: [
|
|
9088
|
-
{ agent: "maestro", model: "deepseek-pro" },
|
|
9089
|
-
{ agent: "codex", model: "gpt-6-luna" }
|
|
9090
|
-
],
|
|
9091
|
-
codex: [
|
|
9092
|
-
{ agent: "maestro", model: "deepseek-pro" },
|
|
9093
|
-
{ agent: "claude", model: "sonnet" }
|
|
9094
|
-
],
|
|
9095
|
-
maestro: [
|
|
9096
|
-
{ agent: "codex", model: "gpt-6-luna" },
|
|
9097
|
-
{ agent: "claude", model: "sonnet" }
|
|
9098
|
-
]
|
|
9099
|
-
};
|
|
9100
8937
|
AGENT_DISPLAY_NAME = {
|
|
9101
8938
|
claude: "Claude",
|
|
9102
8939
|
codex: "Codex",
|
|
@@ -9845,9 +9682,9 @@ function resolveTopicBrief(topicId, legacyTitle) {
|
|
|
9845
9682
|
const titleBrief = getTopicBrief(titleKey);
|
|
9846
9683
|
if (titleBrief)
|
|
9847
9684
|
return { brief: titleBrief, storageKey: titleKey };
|
|
9848
|
-
const
|
|
9849
|
-
if (
|
|
9850
|
-
return { brief:
|
|
9685
|
+
const current = getTopicBrief(topicId);
|
|
9686
|
+
if (current)
|
|
9687
|
+
return { brief: current, storageKey: topicId };
|
|
9851
9688
|
const legacy = titleKey === legacyTitle ? null : getTopicBrief(legacyTitle);
|
|
9852
9689
|
return legacy ? { brief: legacy, storageKey: legacyTitle } : null;
|
|
9853
9690
|
}
|
|
@@ -10467,11 +10304,6 @@ var init_archiver = __esm(async () => {
|
|
|
10467
10304
|
});
|
|
10468
10305
|
|
|
10469
10306
|
// ../../packages/core/src/agents/auth-check.ts
|
|
10470
|
-
var exports_auth_check = {};
|
|
10471
|
-
__export(exports_auth_check, {
|
|
10472
|
-
checkAgentModelAuth: () => checkAgentModelAuth,
|
|
10473
|
-
checkAgentAuth: () => checkAgentAuth
|
|
10474
|
-
});
|
|
10475
10307
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
10476
10308
|
import { existsSync as existsSync17 } from "fs";
|
|
10477
10309
|
import { homedir as homedir8, platform } from "os";
|
|
@@ -10803,8 +10635,8 @@ function createRoomQueryRegistry(host) {
|
|
|
10803
10635
|
clearInterval(previousMonitor);
|
|
10804
10636
|
activeByRoom.set(roomId, control);
|
|
10805
10637
|
const monitor = setInterval(() => {
|
|
10806
|
-
const
|
|
10807
|
-
if (!
|
|
10638
|
+
const current = activeByRoom.get(roomId);
|
|
10639
|
+
if (!current || current.queryId !== control.queryId) {
|
|
10808
10640
|
clearInterval(monitor);
|
|
10809
10641
|
if (leaseMonitors.get(roomId) === monitor)
|
|
10810
10642
|
leaseMonitors.delete(roomId);
|
|
@@ -10826,8 +10658,8 @@ function createRoomQueryRegistry(host) {
|
|
|
10826
10658
|
return true;
|
|
10827
10659
|
}
|
|
10828
10660
|
function clear(roomId, queryId) {
|
|
10829
|
-
const
|
|
10830
|
-
if (
|
|
10661
|
+
const current = activeByRoom.get(roomId);
|
|
10662
|
+
if (current?.queryId === queryId) {
|
|
10831
10663
|
activeByRoom.delete(roomId);
|
|
10832
10664
|
const monitor = leaseMonitors.get(roomId);
|
|
10833
10665
|
if (monitor)
|
|
@@ -10890,43 +10722,12 @@ var init_room_query_registry = () => {};
|
|
|
10890
10722
|
var init_types2 = () => {};
|
|
10891
10723
|
|
|
10892
10724
|
// ../../packages/core/src/query/active-rooms.ts
|
|
10893
|
-
var exports_active_rooms = {};
|
|
10894
|
-
__export(exports_active_rooms, {
|
|
10895
|
-
wsAbortReason: () => wsAbortReason,
|
|
10896
|
-
takeDeferredInject: () => takeDeferredInject,
|
|
10897
|
-
setRoomQuery: () => setRoomQuery,
|
|
10898
|
-
listRunningTopicQueries: () => listRunningTopicQueries,
|
|
10899
|
-
listRunningTopicIds: () => listRunningTopicIds,
|
|
10900
|
-
isolatedTurnRoomId: () => isolatedTurnRoomId,
|
|
10901
|
-
isUserOrigin: () => isUserOrigin,
|
|
10902
|
-
isTopicRunning: () => isTopicRunning,
|
|
10903
|
-
interSessionQueue: () => interSessionQueue,
|
|
10904
|
-
getRoomQueryStatus: () => getRoomQueryStatus,
|
|
10905
|
-
getRoomQuery: () => getRoomQuery,
|
|
10906
|
-
deferInject: () => deferInject,
|
|
10907
|
-
decideNewQuery: () => decideNewQuery,
|
|
10908
|
-
clearRoomQuery: () => clearRoomQuery,
|
|
10909
|
-
cancelDeferredInject: () => cancelDeferredInject,
|
|
10910
|
-
abortRoom: () => abortRoom,
|
|
10911
|
-
abortAllRooms: () => abortAllRooms,
|
|
10912
|
-
InterSessionQueue: () => InterSessionQueue,
|
|
10913
|
-
DeferredInjectBatcher: () => DeferredInjectBatcher
|
|
10914
|
-
});
|
|
10915
10725
|
function getRoomQuery(roomId) {
|
|
10916
10726
|
return roomQueryRegistry.get(roomId);
|
|
10917
10727
|
}
|
|
10918
|
-
function listRunningTopicQueries() {
|
|
10919
|
-
return roomQueryRegistry.listRunningTopicQueries();
|
|
10920
|
-
}
|
|
10921
|
-
function listRunningTopicIds() {
|
|
10922
|
-
return roomQueryRegistry.listRunningTopicIds();
|
|
10923
|
-
}
|
|
10924
10728
|
function isTopicRunning(topicId) {
|
|
10925
10729
|
return roomQueryRegistry.isTopicRunning(topicId);
|
|
10926
10730
|
}
|
|
10927
|
-
function getRoomQueryStatus(topicId, queryId) {
|
|
10928
|
-
return roomQueryRegistry.status(topicId, queryId);
|
|
10929
|
-
}
|
|
10930
10731
|
function setRoomQuery(control) {
|
|
10931
10732
|
return roomQueryRegistry.set(control);
|
|
10932
10733
|
}
|
|
@@ -10936,9 +10737,6 @@ function clearRoomQuery(roomId, queryId) {
|
|
|
10936
10737
|
function abortRoom(roomId, reason = "external" /* External */) {
|
|
10937
10738
|
return roomQueryRegistry.abort(roomId, reason);
|
|
10938
10739
|
}
|
|
10939
|
-
function abortAllRooms(reason = "external" /* External */) {
|
|
10940
|
-
return roomQueryRegistry.abortAll(reason);
|
|
10941
|
-
}
|
|
10942
10740
|
function decideNewQuery(topicId, incomingOrigin) {
|
|
10943
10741
|
return roomQueryRegistry.decide(topicId, incomingOrigin);
|
|
10944
10742
|
}
|
|
@@ -11104,9 +10902,6 @@ function deferInject(inject) {
|
|
|
11104
10902
|
function takeDeferredInject(topicId) {
|
|
11105
10903
|
return interSessionQueue.dequeueAll(topicId);
|
|
11106
10904
|
}
|
|
11107
|
-
function cancelDeferredInject(topicId, requestId) {
|
|
11108
|
-
return interSessionQueue.remove(topicId, requestId) !== undefined;
|
|
11109
|
-
}
|
|
11110
10905
|
function wsAbortReason(reason) {
|
|
11111
10906
|
return reason === "internal" /* Internal */ ? "superseded" : "stopped";
|
|
11112
10907
|
}
|
|
@@ -11399,8 +11194,8 @@ function settleTopicArchiveJob(topicId, archivePath, success) {
|
|
|
11399
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);
|
|
11400
11195
|
return;
|
|
11401
11196
|
}
|
|
11402
|
-
const
|
|
11403
|
-
setTopicArchiveState(topicId, Math.max(
|
|
11197
|
+
const current = getTopicArchiveState(topicId)?.lastArchivedRowid ?? 0;
|
|
11198
|
+
setTopicArchiveState(topicId, Math.max(current, job.last_rowid), job.archive_path);
|
|
11404
11199
|
db.query("DELETE FROM api_topic_archive_jobs WHERE topic_id = ? AND archive_path = ?").run(topicId, archivePath);
|
|
11405
11200
|
})();
|
|
11406
11201
|
}
|
|
@@ -12072,7 +11867,7 @@ function createAskUserRuntime(host) {
|
|
|
12072
11867
|
if (ask.expired || ask.selectedLabel) {
|
|
12073
11868
|
return { ok: false, error: "This question is no longer awaiting an answer." };
|
|
12074
11869
|
}
|
|
12075
|
-
if (!ask.choices.some((
|
|
11870
|
+
if (!ask.choices.some((choice) => choice.label === label)) {
|
|
12076
11871
|
return { ok: false, error: "Invalid choice." };
|
|
12077
11872
|
}
|
|
12078
11873
|
const pending = pendingAsks.get(messageId);
|
|
@@ -12225,8 +12020,8 @@ function createAskUserRuntime(host) {
|
|
|
12225
12020
|
return errorResult(`Error: failed to persist ask_user_question: ${error instanceof Error ? error.message : String(error)}`);
|
|
12226
12021
|
}
|
|
12227
12022
|
let resolveAnswer;
|
|
12228
|
-
const promise = new Promise((
|
|
12229
|
-
resolveAnswer =
|
|
12023
|
+
const promise = new Promise((resolve) => {
|
|
12024
|
+
resolveAnswer = resolve;
|
|
12230
12025
|
});
|
|
12231
12026
|
pendingAsks.set(message.id, {
|
|
12232
12027
|
topicId: ctx.topicId,
|
|
@@ -12428,8 +12223,8 @@ var init_self_schedules = __esm(async () => {
|
|
|
12428
12223
|
});
|
|
12429
12224
|
|
|
12430
12225
|
// ../../packages/core/src/platform/playwright/manager-utils.ts
|
|
12431
|
-
function isLiveOwnedChildProcess(
|
|
12432
|
-
return
|
|
12226
|
+
function isLiveOwnedChildProcess(current, expected) {
|
|
12227
|
+
return current?.process === expected && expected.exitCode === null && expected.signalCode === null && !expected.killed;
|
|
12433
12228
|
}
|
|
12434
12229
|
function matchesSpawnedBrowserHealth(health, expectedSpawnNonce) {
|
|
12435
12230
|
if (!health || typeof health !== "object")
|
|
@@ -12673,10 +12468,10 @@ function findExecutableOnPath(command, environment = process.env) {
|
|
|
12673
12468
|
return null;
|
|
12674
12469
|
}
|
|
12675
12470
|
function resolveHeadedPlaywrightSpawn(command, args, options = {}) {
|
|
12676
|
-
const
|
|
12471
|
+
const platform = options.platform ?? process.platform;
|
|
12677
12472
|
const environment = options.environment ?? process.env;
|
|
12678
12473
|
const hasDisplay = Boolean(environment.DISPLAY?.trim() || environment.WAYLAND_DISPLAY?.trim());
|
|
12679
|
-
if (
|
|
12474
|
+
if (platform !== "linux" || hasDisplay) {
|
|
12680
12475
|
return { command, args: [...args], virtualDisplay: false };
|
|
12681
12476
|
}
|
|
12682
12477
|
const xvfbRun = (options.findExecutable ?? findExecutableOnPath)("xvfb-run", environment);
|
|
@@ -12725,7 +12520,7 @@ async function probeMcpTransport(transport, options = {}) {
|
|
|
12725
12520
|
}
|
|
12726
12521
|
}
|
|
12727
12522
|
async function probePlaywrightMcpTransports(port, capability, fetchImpl = fetch) {
|
|
12728
|
-
const
|
|
12523
|
+
const query = new URLSearchParams({ owner: PROBE_OWNER });
|
|
12729
12524
|
const baseUrl = `http://127.0.0.1:${port}`;
|
|
12730
12525
|
const ownerCapability = browserOwnerCapability(capability, PROBE_OWNER);
|
|
12731
12526
|
const capabilityHeaders = { "X-Browser-Capability": ownerCapability };
|
|
@@ -12734,14 +12529,14 @@ async function probePlaywrightMcpTransports(port, capability, fetchImpl = fetch)
|
|
|
12734
12529
|
headers.set("X-Browser-Capability", ownerCapability);
|
|
12735
12530
|
return fetchImpl(input, { ...init, headers });
|
|
12736
12531
|
};
|
|
12737
|
-
const sseTransport = new SSEClientTransport(new URL(`${baseUrl}/sse?${
|
|
12532
|
+
const sseTransport = new SSEClientTransport(new URL(`${baseUrl}/sse?${query}`), {
|
|
12738
12533
|
fetch: authenticatedFetch,
|
|
12739
12534
|
eventSourceInit: { fetch: authenticatedFetch },
|
|
12740
12535
|
requestInit: { headers: capabilityHeaders }
|
|
12741
12536
|
});
|
|
12742
12537
|
if (!await probeMcpTransport(sseTransport))
|
|
12743
12538
|
return false;
|
|
12744
|
-
const streamableTransport = new StreamableHTTPClientTransport(new URL(`${baseUrl}/mcp?${
|
|
12539
|
+
const streamableTransport = new StreamableHTTPClientTransport(new URL(`${baseUrl}/mcp?${query}`), {
|
|
12745
12540
|
fetch: authenticatedFetch,
|
|
12746
12541
|
requestInit: { headers: capabilityHeaders }
|
|
12747
12542
|
});
|
|
@@ -12871,9 +12666,9 @@ async function createBrowserVaultBroker(userId) {
|
|
|
12871
12666
|
if (typeof request.tool !== "string")
|
|
12872
12667
|
return { id, ok: false, error: "invalid tool" };
|
|
12873
12668
|
const leaseCutoff = Date.now() - LEASE_TTL_MS;
|
|
12874
|
-
for (const [
|
|
12669
|
+
for (const [lease, binding] of leases) {
|
|
12875
12670
|
if (binding.createdAt < leaseCutoff)
|
|
12876
|
-
leases.delete(
|
|
12671
|
+
leases.delete(lease);
|
|
12877
12672
|
}
|
|
12878
12673
|
if (leases.size >= MAX_ACTIVE_LEASES) {
|
|
12879
12674
|
return { id, ok: false, error: "too many active leases" };
|
|
@@ -13406,9 +13201,9 @@ async function spawnPlaywright(instanceKey, ownerId, reservedPort, browserBin =
|
|
|
13406
13201
|
const stderrTail = captureBoundedStderr(proc);
|
|
13407
13202
|
const startup = watchChildStartup(proc, stderrTail);
|
|
13408
13203
|
const reapCrashedBrowser = () => {
|
|
13409
|
-
const
|
|
13410
|
-
managerHost.cleanupBrowserProcessesForDataDir(
|
|
13411
|
-
cleanSingletonFiles(
|
|
13204
|
+
const userDataDir = resolveUserDataDir(instanceKey);
|
|
13205
|
+
managerHost.cleanupBrowserProcessesForDataDir(userDataDir);
|
|
13206
|
+
cleanSingletonFiles(userDataDir);
|
|
13412
13207
|
};
|
|
13413
13208
|
proc.once("error", (err) => {
|
|
13414
13209
|
logger.error({ err, instanceKey, stderr: stderrTail() || undefined }, "Playwright MCP error");
|
|
@@ -13477,8 +13272,8 @@ ${stderrTail()}` : ""));
|
|
|
13477
13272
|
}
|
|
13478
13273
|
async function supportsOwnerCleanup(port, capability) {
|
|
13479
13274
|
try {
|
|
13480
|
-
const
|
|
13481
|
-
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}`, {
|
|
13482
13277
|
method: "DELETE",
|
|
13483
13278
|
headers: {
|
|
13484
13279
|
"X-Browser-Capability": capability
|
|
@@ -13549,8 +13344,8 @@ async function closeBrowserOwnerTabs(ownerId, rawProfile, owner) {
|
|
|
13549
13344
|
if (!instance)
|
|
13550
13345
|
return 0;
|
|
13551
13346
|
const port = instance.port;
|
|
13552
|
-
const
|
|
13553
|
-
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}`, {
|
|
13554
13349
|
method: "DELETE",
|
|
13555
13350
|
headers: {
|
|
13556
13351
|
"X-Browser-Capability": instance.capability
|
|
@@ -14245,7 +14040,7 @@ async function runIdleCompactForTopic(topicId, userId, options = {}) {
|
|
|
14245
14040
|
return "below-threshold";
|
|
14246
14041
|
}
|
|
14247
14042
|
const compact = options.compact ?? (async (id, actorId, reason) => {
|
|
14248
|
-
|
|
14043
|
+
await init_session();
|
|
14249
14044
|
return compactTopicSession(id, actorId, reason, { preemptive: false });
|
|
14250
14045
|
});
|
|
14251
14046
|
try {
|
|
@@ -14445,40 +14240,40 @@ function beginTransientBackgroundSession(userId, session) {
|
|
|
14445
14240
|
update(status, step) {
|
|
14446
14241
|
if (finished)
|
|
14447
14242
|
return;
|
|
14448
|
-
const
|
|
14449
|
-
if (
|
|
14243
|
+
const current = transientSessions.get(record.id);
|
|
14244
|
+
if (current !== record)
|
|
14450
14245
|
return;
|
|
14451
14246
|
const nextStatus = text(status, 160);
|
|
14452
14247
|
if (nextStatus)
|
|
14453
|
-
|
|
14248
|
+
current.status = nextStatus;
|
|
14454
14249
|
const nextStep = text(step);
|
|
14455
|
-
if (nextStep &&
|
|
14456
|
-
|
|
14250
|
+
if (nextStep && current.steps.at(-1) !== nextStep) {
|
|
14251
|
+
current.steps.push(nextStep);
|
|
14457
14252
|
}
|
|
14458
14253
|
},
|
|
14459
14254
|
setOutput(output) {
|
|
14460
14255
|
if (finished)
|
|
14461
14256
|
return;
|
|
14462
|
-
const
|
|
14463
|
-
if (
|
|
14257
|
+
const current = transientSessions.get(record.id);
|
|
14258
|
+
if (current !== record)
|
|
14464
14259
|
return;
|
|
14465
|
-
|
|
14260
|
+
current.output = output;
|
|
14466
14261
|
},
|
|
14467
14262
|
finish(status, step) {
|
|
14468
14263
|
if (finished)
|
|
14469
14264
|
return;
|
|
14470
14265
|
this.update(status ?? record.status, step);
|
|
14471
14266
|
finished = true;
|
|
14472
|
-
const
|
|
14473
|
-
if (
|
|
14267
|
+
const current = transientSessions.get(record.id);
|
|
14268
|
+
if (current !== record)
|
|
14474
14269
|
return;
|
|
14475
|
-
|
|
14476
|
-
|
|
14477
|
-
|
|
14270
|
+
current.active = false;
|
|
14271
|
+
current.expiresAt = Date.now() + Math.max(0, retentionMs);
|
|
14272
|
+
current.expiryTimer = setTimeout(() => {
|
|
14478
14273
|
if (transientSessions.get(record.id) === record)
|
|
14479
14274
|
transientSessions.delete(record.id);
|
|
14480
14275
|
}, Math.max(0, retentionMs));
|
|
14481
|
-
|
|
14276
|
+
current.expiryTimer.unref?.();
|
|
14482
14277
|
}
|
|
14483
14278
|
};
|
|
14484
14279
|
}
|
|
@@ -14736,8 +14531,8 @@ function markRuntimeUserTurnMessagesLogged(topicId, requestId, ownerId, loggedUs
|
|
|
14736
14531
|
return false;
|
|
14737
14532
|
return db.transaction(() => {
|
|
14738
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);
|
|
14739
|
-
const hasLoggedPrefix = (
|
|
14740
|
-
const candidate =
|
|
14534
|
+
const hasLoggedPrefix = (request) => loggedUserMessages.length <= request.userMessages.length && loggedUserMessages.every((message, index) => {
|
|
14535
|
+
const candidate = request.userMessages[index];
|
|
14741
14536
|
return candidate?.prompt === message.prompt && candidate.actorUserId === message.actorUserId && candidate.actorLabel === message.actorLabel && JSON.stringify(candidate.attachments ?? []) === JSON.stringify(message.attachments ?? []);
|
|
14742
14537
|
});
|
|
14743
14538
|
const request = requests.find((candidate) => candidate.requestId === requestId && candidate.claimedBy === ownerId && hasLoggedPrefix(candidate)) ?? requests.find((candidate) => candidate.execution?.supersededRequestIds?.includes(requestId) && hasLoggedPrefix(candidate));
|
|
@@ -14755,60 +14550,6 @@ function markRuntimeUserTurnMessagesLogged(topicId, requestId, ownerId, loggedUs
|
|
|
14755
14550
|
return result.changes === 1;
|
|
14756
14551
|
}).immediate();
|
|
14757
14552
|
}
|
|
14758
|
-
function claimNextRuntimeUserTurnRequest(ownerId, now = Date.now()) {
|
|
14759
|
-
return db.transaction(() => {
|
|
14760
|
-
const row = db.query(`SELECT r.*
|
|
14761
|
-
FROM runtime_user_turn_requests r
|
|
14762
|
-
LEFT JOIN runtime_turn_leases l ON l.topic_id = r.topic_id
|
|
14763
|
-
LEFT JOIN runtime_topic_state s ON s.topic_id = r.topic_id
|
|
14764
|
-
WHERE (l.topic_id IS NULL OR l.heartbeat_at < ?)
|
|
14765
|
-
AND (s.topic_id IS NULL OR s.maintenance = 0 OR s.heartbeat_at < ?)
|
|
14766
|
-
AND r.topic_epoch = COALESCE(s.epoch, 0)
|
|
14767
|
-
AND NOT EXISTS (
|
|
14768
|
-
SELECT 1
|
|
14769
|
-
FROM runtime_user_turn_requests active
|
|
14770
|
-
WHERE active.topic_id = r.topic_id
|
|
14771
|
-
AND active.request_id <> r.request_id
|
|
14772
|
-
AND active.claimed_at IS NOT NULL
|
|
14773
|
-
AND active.claimed_at >= ?
|
|
14774
|
-
)
|
|
14775
|
-
AND (
|
|
14776
|
-
(r.status = 'pending' AND (r.claimed_at IS NULL OR r.claimed_at < ?))
|
|
14777
|
-
OR (r.status = 'running' AND (r.claimed_at IS NULL OR r.claimed_at < ?))
|
|
14778
|
-
)
|
|
14779
|
-
ORDER BY r.created_at ASC, r.rowid ASC
|
|
14780
|
-
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);
|
|
14781
|
-
if (!row)
|
|
14782
|
-
return null;
|
|
14783
|
-
const updated = db.query(`UPDATE runtime_user_turn_requests
|
|
14784
|
-
SET claimed_by = ?, claimed_at = ?
|
|
14785
|
-
WHERE request_id = ? AND topic_id = ?
|
|
14786
|
-
AND (
|
|
14787
|
-
(status = 'pending' AND (claimed_at IS NULL OR claimed_at < ?))
|
|
14788
|
-
OR (status = 'running' AND (claimed_at IS NULL OR claimed_at < ?))
|
|
14789
|
-
)`).run(ownerId, now, row.request_id, row.topic_id, now - REQUEST_CLAIM_STALE_MS, now - REQUEST_CLAIM_STALE_MS);
|
|
14790
|
-
if (Number(updated.changes ?? 0) === 0)
|
|
14791
|
-
return null;
|
|
14792
|
-
return rowToRequest({ ...row, claimed_by: ownerId, claimed_at: now });
|
|
14793
|
-
}).immediate();
|
|
14794
|
-
}
|
|
14795
|
-
function markRuntimeUserTurnRunning(topicId, requestId, ownerId, queryId) {
|
|
14796
|
-
const result = db.query(`UPDATE runtime_user_turn_requests
|
|
14797
|
-
SET status = 'running', running_query_id = ?, claimed_at = ?
|
|
14798
|
-
WHERE topic_id = ? AND request_id = ? AND claimed_by = ?`).run(queryId, Date.now(), topicId, requestId, ownerId);
|
|
14799
|
-
return Number(result.changes ?? 0) > 0;
|
|
14800
|
-
}
|
|
14801
|
-
function releaseRuntimeUserTurnClaim(topicId, requestId, ownerId) {
|
|
14802
|
-
const result = db.query(`UPDATE runtime_user_turn_requests
|
|
14803
|
-
SET status = 'pending', claimed_by = NULL, claimed_at = NULL, running_query_id = NULL
|
|
14804
|
-
WHERE topic_id = ? AND request_id = ? AND claimed_by = ?`).run(topicId, requestId, ownerId);
|
|
14805
|
-
return Number(result.changes ?? 0) > 0;
|
|
14806
|
-
}
|
|
14807
|
-
function completeRuntimeUserTurnRequest(topicId, requestId, ownerId) {
|
|
14808
|
-
const result = db.query(`DELETE FROM runtime_user_turn_requests
|
|
14809
|
-
WHERE topic_id = ? AND request_id = ? AND claimed_by = ?`).run(topicId, requestId, ownerId);
|
|
14810
|
-
return Number(result.changes ?? 0) > 0;
|
|
14811
|
-
}
|
|
14812
14553
|
function cancelRuntimeUserTurnRequestsBeforeEpoch(topicId, epoch) {
|
|
14813
14554
|
const rows = db.query("SELECT request_id FROM runtime_user_turn_requests WHERE topic_id = ? AND topic_epoch < ?").all(topicId, epoch);
|
|
14814
14555
|
db.query("DELETE FROM runtime_user_turn_requests WHERE topic_id = ? AND topic_epoch < ?").run(topicId, epoch);
|
|
@@ -14846,36 +14587,10 @@ var init_runtime_turn_requests = __esm(async () => {
|
|
|
14846
14587
|
});
|
|
14847
14588
|
|
|
14848
14589
|
// ../../packages/core/src/topics/session.ts
|
|
14849
|
-
var exports_session = {};
|
|
14850
|
-
__export(exports_session, {
|
|
14851
|
-
splitCompactionPairs: () => splitCompactionPairs,
|
|
14852
|
-
shouldUseCompactionLog: () => shouldUseCompactionLog,
|
|
14853
|
-
shouldCompactForkEntries: () => shouldCompactForkEntries,
|
|
14854
|
-
restartTopicSession: () => restartTopicSession,
|
|
14855
|
-
createCompactedRolloutEntries: () => createCompactedRolloutEntries,
|
|
14856
|
-
compactTopicSession: () => compactTopicSession,
|
|
14857
|
-
COMPACTION_RETAINED_TAIL_TOKENS: () => COMPACTION_RETAINED_TAIL_TOKENS,
|
|
14858
|
-
AUTO_FORK_COMPACTION_TOKENS: () => AUTO_FORK_COMPACTION_TOKENS
|
|
14859
|
-
});
|
|
14860
14590
|
import { randomUUID as randomUUID12 } from "crypto";
|
|
14861
14591
|
import { mkdtempSync as mkdtempSync2, rmSync as rmSync4, writeFileSync as writeFileSync12 } from "fs";
|
|
14862
14592
|
import { tmpdir as tmpdir4 } from "os";
|
|
14863
14593
|
import { join as join23 } from "path";
|
|
14864
|
-
async function waitForMemoryArchive(settled, timeoutMs) {
|
|
14865
|
-
let timer;
|
|
14866
|
-
try {
|
|
14867
|
-
return await Promise.race([
|
|
14868
|
-
settled.then(() => true),
|
|
14869
|
-
new Promise((resolve17) => {
|
|
14870
|
-
timer = setTimeout(() => resolve17(false), timeoutMs);
|
|
14871
|
-
timer.unref?.();
|
|
14872
|
-
})
|
|
14873
|
-
]);
|
|
14874
|
-
} finally {
|
|
14875
|
-
if (timer)
|
|
14876
|
-
clearTimeout(timer);
|
|
14877
|
-
}
|
|
14878
|
-
}
|
|
14879
14594
|
async function fenceTopicWork(topicId, maintenance) {
|
|
14880
14595
|
for (const queryId of cancelRuntimeUserTurnRequestsBeforeEpoch(topicId, maintenance.epoch)) {
|
|
14881
14596
|
WsHub.get().broadcastAborted(topicId, queryId, "stopped");
|
|
@@ -14900,97 +14615,6 @@ function hasTopicWorkInFlight(topicId) {
|
|
|
14900
14615
|
function topicIsQuiescedForNonPreemptiveWork(topicId) {
|
|
14901
14616
|
return !hasTopicWorkInFlight(topicId);
|
|
14902
14617
|
}
|
|
14903
|
-
async function restartTopicSession(topicId, userId, reason = "topic-session-restart", options = {}) {
|
|
14904
|
-
const topic = getTopic(topicId);
|
|
14905
|
-
if (!topic)
|
|
14906
|
-
return { text: "Topic not found.", isError: true };
|
|
14907
|
-
if (isLegacySharedGeneral(topic.id)) {
|
|
14908
|
-
return { text: "The legacy shared General session cannot be reset.", isError: true };
|
|
14909
|
-
}
|
|
14910
|
-
const owner = topic.participants.some((participant) => participant.userId === userId && participant.role === "owner");
|
|
14911
|
-
if (!owner)
|
|
14912
|
-
return { text: "Only the topic owner can reset the session.", isError: true };
|
|
14913
|
-
const maintenance = beginRuntimeTopicMaintenance(topicId);
|
|
14914
|
-
if (!maintenance)
|
|
14915
|
-
return { text: "Topic maintenance is already in progress.", isError: true };
|
|
14916
|
-
try {
|
|
14917
|
-
const fenceError = await fenceTopicWork(topicId, maintenance);
|
|
14918
|
-
if (fenceError)
|
|
14919
|
-
return { text: fenceError, isError: true };
|
|
14920
|
-
cancelIdleArchiveForTopic(topicId);
|
|
14921
|
-
cancelIdleCompactForTopic(topicId);
|
|
14922
|
-
const rawArchivePaths = [];
|
|
14923
|
-
try {
|
|
14924
|
-
for (const participantUserId of new Set([
|
|
14925
|
-
userId,
|
|
14926
|
-
...topic.participants.map((participant) => participant.userId)
|
|
14927
|
-
])) {
|
|
14928
|
-
const archived = archiveConversationEvents(topicId, topic.title, participantUserId, {
|
|
14929
|
-
reason: "reset"
|
|
14930
|
-
});
|
|
14931
|
-
if (archived)
|
|
14932
|
-
rawArchivePaths.push(archived.path);
|
|
14933
|
-
}
|
|
14934
|
-
} catch (error) {
|
|
14935
|
-
return {
|
|
14936
|
-
text: `Session reset could not archive the raw conversation: ${error instanceof Error ? error.message : String(error)}`,
|
|
14937
|
-
isError: true
|
|
14938
|
-
};
|
|
14939
|
-
}
|
|
14940
|
-
let settleMemoryArchive;
|
|
14941
|
-
const memoryArchiveSettled = new Promise((resolve17) => {
|
|
14942
|
-
settleMemoryArchive = resolve17;
|
|
14943
|
-
});
|
|
14944
|
-
const archiveStatus = (options.archiveMemory ?? archiveActiveTopicForMemory)(topicId, options.memoryUserId ?? userId, {
|
|
14945
|
-
reason: "reset",
|
|
14946
|
-
minMessages: 1,
|
|
14947
|
-
minExchanges: MIN_MEMORY_ARCHIVE_EXCHANGES,
|
|
14948
|
-
allowMentionOnly: true,
|
|
14949
|
-
skipBusyCheck: true,
|
|
14950
|
-
rawArchivePaths,
|
|
14951
|
-
onSettled: () => settleMemoryArchive?.()
|
|
14952
|
-
});
|
|
14953
|
-
if (archiveStatus === "archived") {
|
|
14954
|
-
const archiveFinished = await waitForMemoryArchive(memoryArchiveSettled, options.memoryArchiveWaitMs ?? RESET_MEMORY_ARCHIVE_WAIT_MS);
|
|
14955
|
-
if (!archiveFinished) {
|
|
14956
|
-
return {
|
|
14957
|
-
text: "Memory archiving did not finish in time. The session was not reset.",
|
|
14958
|
-
isError: true
|
|
14959
|
-
};
|
|
14960
|
-
}
|
|
14961
|
-
}
|
|
14962
|
-
if (!maintenance.isOwned()) {
|
|
14963
|
-
return { text: "Topic maintenance ownership was lost. Try again.", isError: true };
|
|
14964
|
-
}
|
|
14965
|
-
const sessionId = getTopicSessionId(topicId);
|
|
14966
|
-
const purgeLogs = options.purgeLogs ?? purgeTopicLogs;
|
|
14967
|
-
const participantUserIds = Array.from(new Set([userId, ...topic.participants.map((participant) => participant.userId)]));
|
|
14968
|
-
for (const [index, participantUserId] of participantUserIds.entries()) {
|
|
14969
|
-
let purged = false;
|
|
14970
|
-
try {
|
|
14971
|
-
purged = await purgeLogs({
|
|
14972
|
-
userId: participantUserId,
|
|
14973
|
-
topicName: topic.title,
|
|
14974
|
-
cwd: resolveTopicWorkspaceDir(topicId),
|
|
14975
|
-
extraSessions: index === 0 && topic.agent && sessionId ? [{ agent: topic.agent, sessionId }] : []
|
|
14976
|
-
});
|
|
14977
|
-
} catch (error) {
|
|
14978
|
-
logger.warn({ err: error, topicId, userId: participantUserId }, "restartTopicSession: participant context cleanup failed");
|
|
14979
|
-
}
|
|
14980
|
-
if (!purged) {
|
|
14981
|
-
return {
|
|
14982
|
-
text: "Session reset could not remove all provider context. The current session was kept.",
|
|
14983
|
-
isError: true
|
|
14984
|
-
};
|
|
14985
|
-
}
|
|
14986
|
-
}
|
|
14987
|
-
clearTopicSessionId(topicId, reason);
|
|
14988
|
-
clearQueryUsageAlert(userId, topicId);
|
|
14989
|
-
return { text: `Session reset for "${topic.title}". The next message starts fresh.` };
|
|
14990
|
-
} finally {
|
|
14991
|
-
maintenance.finish();
|
|
14992
|
-
}
|
|
14993
|
-
}
|
|
14994
14618
|
function previousCompactedSummary(entries) {
|
|
14995
14619
|
for (let index = entries.length - 2;index >= 0; index -= 1) {
|
|
14996
14620
|
const request = entries[index]?.event;
|
|
@@ -15005,9 +14629,9 @@ The assistant response is the authoritative summary of all earlier context.` &&
|
|
|
15005
14629
|
function withoutCompactionSentinels(entries) {
|
|
15006
14630
|
const filtered = [];
|
|
15007
14631
|
for (let index = 0;index < entries.length; index++) {
|
|
15008
|
-
const
|
|
14632
|
+
const current = entries[index]?.event;
|
|
15009
14633
|
const next = entries[index + 1]?.event;
|
|
15010
|
-
if (
|
|
14634
|
+
if (current?.type === "user_message" && current.synthetic === "compaction" && next?.type === "result") {
|
|
15011
14635
|
index += 1;
|
|
15012
14636
|
continue;
|
|
15013
14637
|
}
|
|
@@ -15057,18 +14681,18 @@ function retainedPairEntries(agent, pairs) {
|
|
|
15057
14681
|
}
|
|
15058
14682
|
return entries;
|
|
15059
14683
|
}
|
|
15060
|
-
function fitCompactionChunk(
|
|
15061
|
-
if (
|
|
15062
|
-
return
|
|
14684
|
+
function fitCompactionChunk(text, limit) {
|
|
14685
|
+
if (text.length <= limit)
|
|
14686
|
+
return text;
|
|
15063
14687
|
const marker = `
|
|
15064
14688
|
[\u2026]
|
|
15065
14689
|
`;
|
|
15066
14690
|
if (limit <= marker.length)
|
|
15067
|
-
return
|
|
14691
|
+
return text.slice(0, limit);
|
|
15068
14692
|
const available = limit - marker.length;
|
|
15069
14693
|
const headChars = Math.ceil(available * 0.6);
|
|
15070
14694
|
const tailChars = available - headChars;
|
|
15071
|
-
return `${
|
|
14695
|
+
return `${text.slice(0, headChars)}${marker}${text.slice(-tailChars)}`;
|
|
15072
14696
|
}
|
|
15073
14697
|
function buildCompactionSource(topicId, userId, entries, visibleMessages, providerPairs) {
|
|
15074
14698
|
const sections = [];
|
|
@@ -15469,9 +15093,9 @@ async function compactTopicSession(topicId, userId, reason = "topic-session-comp
|
|
|
15469
15093
|
const compactionExecution = resolveCompactionExecution(agent, registry);
|
|
15470
15094
|
const cwd = resolveTopicWorkspaceDir(topicId);
|
|
15471
15095
|
const oldEntries = readConversation(userId, topic.title);
|
|
15472
|
-
let
|
|
15096
|
+
let compactEntries;
|
|
15473
15097
|
try {
|
|
15474
|
-
|
|
15098
|
+
compactEntries = await createCompactedRolloutEntries({
|
|
15475
15099
|
topicId,
|
|
15476
15100
|
topicTitle: topic.title,
|
|
15477
15101
|
userId,
|
|
@@ -15497,7 +15121,7 @@ async function compactTopicSession(topicId, userId, reason = "topic-session-comp
|
|
|
15497
15121
|
try {
|
|
15498
15122
|
replacement = getRegistryOperations(agent).writeRollout({
|
|
15499
15123
|
cwd,
|
|
15500
|
-
entries:
|
|
15124
|
+
entries: compactEntries,
|
|
15501
15125
|
model,
|
|
15502
15126
|
...effort ? { effort } : {}
|
|
15503
15127
|
});
|
|
@@ -15527,7 +15151,7 @@ async function compactTopicSession(topicId, userId, reason = "topic-session-comp
|
|
|
15527
15151
|
}
|
|
15528
15152
|
try {
|
|
15529
15153
|
replaceConversationStrict(userId, topic.title, [
|
|
15530
|
-
...
|
|
15154
|
+
...compactEntries,
|
|
15531
15155
|
...priorSessionEntries,
|
|
15532
15156
|
replacementSessionEntry
|
|
15533
15157
|
]);
|
|
@@ -15564,7 +15188,7 @@ async function compactTopicSession(topicId, userId, reason = "topic-session-comp
|
|
|
15564
15188
|
} else {
|
|
15565
15189
|
try {
|
|
15566
15190
|
replaceConversationStrict(userId, topic.title, [
|
|
15567
|
-
...
|
|
15191
|
+
...compactEntries,
|
|
15568
15192
|
replacementSessionEntry
|
|
15569
15193
|
]);
|
|
15570
15194
|
} catch (manifestError) {
|
|
@@ -15618,45 +15242,11 @@ var init_session = __esm(async () => {
|
|
|
15618
15242
|
});
|
|
15619
15243
|
|
|
15620
15244
|
// ../../packages/core/src/topics/derive.ts
|
|
15621
|
-
var exports_derive = {};
|
|
15622
|
-
__export(exports_derive, {
|
|
15623
|
-
updateTopic: () => updateTopic,
|
|
15624
|
-
isParticipant: () => isParticipant,
|
|
15625
|
-
getVisibleTopics: () => getVisibleTopics,
|
|
15626
|
-
getTopics: () => getTopics,
|
|
15627
|
-
createDerivedTopic: () => createDerivedTopic,
|
|
15628
|
-
TopicTitleConflictError: () => TopicTitleConflictError,
|
|
15629
|
-
TopicForkCompactionError: () => TopicForkCompactionError,
|
|
15630
|
-
TopicDeriveBusyError: () => TopicDeriveBusyError
|
|
15631
|
-
});
|
|
15632
15245
|
import { createHash as createHash9, randomUUID as randomUUID13 } from "crypto";
|
|
15633
15246
|
import { mkdirSync as mkdirSync14, rmSync as rmSync5, unlinkSync as unlinkSync13 } from "fs";
|
|
15634
15247
|
function getTopics(opts = {}) {
|
|
15635
15248
|
return listTopics(opts).filter((topic) => !isLegacySharedGeneral(topic.id));
|
|
15636
15249
|
}
|
|
15637
|
-
function getVisibleTopics(opts = {}) {
|
|
15638
|
-
return getTopics(opts).filter(isTopicVisible).map((topic) => {
|
|
15639
|
-
if (!topic.agent)
|
|
15640
|
-
return topic;
|
|
15641
|
-
const registry = getRegistry(topic.agent);
|
|
15642
|
-
const config = getApiTopicConfig(topic.id);
|
|
15643
|
-
const requestedEffort = config?.effort ?? topic.defaultEffort;
|
|
15644
|
-
return {
|
|
15645
|
-
...topic,
|
|
15646
|
-
effectiveModel: resolveModelForAgent(topic.agent, config?.model ?? topic.defaultModel, registry),
|
|
15647
|
-
effectiveEffort: requestedEffort && registry.validateEffort(requestedEffort) ? requestedEffort : registry.defaultEffort
|
|
15648
|
-
};
|
|
15649
|
-
});
|
|
15650
|
-
}
|
|
15651
|
-
function updateTopic(topicId, patch) {
|
|
15652
|
-
const topic = getTopic(topicId);
|
|
15653
|
-
if (!topic)
|
|
15654
|
-
return false;
|
|
15655
|
-
Object.assign(topic, patch);
|
|
15656
|
-
upsertTopic(topic);
|
|
15657
|
-
WsHub.get().broadcastTopicUpdated(topicId);
|
|
15658
|
-
return true;
|
|
15659
|
-
}
|
|
15660
15250
|
function isParticipant(topic, userId) {
|
|
15661
15251
|
return topic.participants.some((p) => p.userId === userId);
|
|
15662
15252
|
}
|
|
@@ -16072,9 +15662,9 @@ function subagentLineageTopicIds(currentTopicId) {
|
|
|
16072
15662
|
const children = new Set;
|
|
16073
15663
|
if (!currentTopicId)
|
|
16074
15664
|
return { reachable, children };
|
|
16075
|
-
const
|
|
16076
|
-
if (
|
|
16077
|
-
reachable.add(
|
|
15665
|
+
const current = getTopic(currentTopicId);
|
|
15666
|
+
if (current?.isSubagent && current.parentTopicId) {
|
|
15667
|
+
reachable.add(current.parentTopicId);
|
|
16078
15668
|
for (const id of listSubagentTellTargetIds(currentTopicId))
|
|
16079
15669
|
reachable.add(id);
|
|
16080
15670
|
}
|
|
@@ -16200,9 +15790,9 @@ function cleanupSessionInboxFiles(userId, topicId, legacyTopicTitle) {
|
|
|
16200
15790
|
try {
|
|
16201
15791
|
unlinkSync15(path);
|
|
16202
15792
|
deleted++;
|
|
16203
|
-
} catch (
|
|
16204
|
-
if (
|
|
16205
|
-
logger.warn({ err
|
|
15793
|
+
} catch (err) {
|
|
15794
|
+
if (err?.code !== "ENOENT") {
|
|
15795
|
+
logger.warn({ err, path, topicId, userId }, "topic cleanup: inbox unlink failed");
|
|
16206
15796
|
}
|
|
16207
15797
|
}
|
|
16208
15798
|
}
|
|
@@ -16327,9 +15917,9 @@ function hubHeaders(bearer) {
|
|
|
16327
15917
|
};
|
|
16328
15918
|
}
|
|
16329
15919
|
function errorText(status, body, fallback) {
|
|
16330
|
-
const
|
|
16331
|
-
if (typeof
|
|
16332
|
-
return
|
|
15920
|
+
const text = body?.error;
|
|
15921
|
+
if (typeof text === "string" && text.trim())
|
|
15922
|
+
return text.trim();
|
|
16333
15923
|
return `${fallback} (hub answered ${status})`;
|
|
16334
15924
|
}
|
|
16335
15925
|
function describeFailure(status, body) {
|
|
@@ -16425,19 +16015,6 @@ var init_actor_policy = __esm(async () => {
|
|
|
16425
16015
|
await init_actor_topic_reach();
|
|
16426
16016
|
});
|
|
16427
16017
|
// ../../packages/core/src/storage/session-asks.ts
|
|
16428
|
-
var exports_session_asks = {};
|
|
16429
|
-
__export(exports_session_asks, {
|
|
16430
|
-
releasePendingAsk: () => releasePendingAsk,
|
|
16431
|
-
markPendingAskState: () => markPendingAskState,
|
|
16432
|
-
markPendingAskSources: () => markPendingAskSources,
|
|
16433
|
-
listPendingAsksForCaller: () => listPendingAsksForCaller,
|
|
16434
|
-
describePendingAskState: () => describePendingAskState,
|
|
16435
|
-
deletePendingAsksForTopic: () => deletePendingAsksForTopic,
|
|
16436
|
-
createPendingAsk: () => createPendingAsk,
|
|
16437
|
-
clearPendingAskSources: () => clearPendingAskSources,
|
|
16438
|
-
clearPendingAsk: () => clearPendingAsk,
|
|
16439
|
-
PENDING_ASK_TTL_MS: () => PENDING_ASK_TTL_MS
|
|
16440
|
-
});
|
|
16441
16018
|
import { createHash as createHash10 } from "crypto";
|
|
16442
16019
|
import {
|
|
16443
16020
|
closeSync as closeSync2,
|
|
@@ -16459,8 +16036,8 @@ function encodeAskKey(key) {
|
|
|
16459
16036
|
return JSON.stringify([key.from, key.to]);
|
|
16460
16037
|
}
|
|
16461
16038
|
function pendingAskPath(key) {
|
|
16462
|
-
const
|
|
16463
|
-
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`);
|
|
16464
16041
|
}
|
|
16465
16042
|
function v2PendingAskPath(key) {
|
|
16466
16043
|
const encoded = Buffer.from(encodeAskKey(key), "utf8").toString("base64url");
|
|
@@ -16486,10 +16063,10 @@ function parsePendingAskFilename(fileName) {
|
|
|
16486
16063
|
}
|
|
16487
16064
|
} catch {}
|
|
16488
16065
|
}
|
|
16489
|
-
const
|
|
16490
|
-
if (
|
|
16066
|
+
const sep = raw.indexOf("___");
|
|
16067
|
+
if (sep < 0)
|
|
16491
16068
|
return null;
|
|
16492
|
-
return { from: raw.slice(0,
|
|
16069
|
+
return { from: raw.slice(0, sep), to: raw.slice(sep + 3) };
|
|
16493
16070
|
}
|
|
16494
16071
|
function readPendingAskFile(path, fallback) {
|
|
16495
16072
|
try {
|
|
@@ -16532,16 +16109,6 @@ function readPendingAskFile(path, fallback) {
|
|
|
16532
16109
|
return null;
|
|
16533
16110
|
}
|
|
16534
16111
|
}
|
|
16535
|
-
function isStale(record, path) {
|
|
16536
|
-
const ts = record ? Date.parse(record.updatedAt || record.createdAt) : Number.NaN;
|
|
16537
|
-
if (Number.isFinite(ts))
|
|
16538
|
-
return Date.now() - ts > PENDING_ASK_TTL_MS;
|
|
16539
|
-
try {
|
|
16540
|
-
return Date.now() - statSync8(path).mtimeMs > PENDING_ASK_TTL_MS;
|
|
16541
|
-
} catch {
|
|
16542
|
-
return false;
|
|
16543
|
-
}
|
|
16544
|
-
}
|
|
16545
16112
|
function writePendingAsk(record) {
|
|
16546
16113
|
const path = pendingAskPath(record);
|
|
16547
16114
|
mkdirSync16(pendingAskDir(record.userId), { recursive: true });
|
|
@@ -16567,10 +16134,10 @@ function writePendingAskIfAbsent(record) {
|
|
|
16567
16134
|
}
|
|
16568
16135
|
}
|
|
16569
16136
|
function readPendingAsk(key) {
|
|
16570
|
-
const
|
|
16571
|
-
const canonical = readPendingAskFile(
|
|
16137
|
+
const canonicalPath = pendingAskPath(key);
|
|
16138
|
+
const canonical = readPendingAskFile(canonicalPath, key);
|
|
16572
16139
|
if (canonical && canonical.from === key.from && canonical.to === key.to) {
|
|
16573
|
-
return { path:
|
|
16140
|
+
return { path: canonicalPath, record: canonical };
|
|
16574
16141
|
}
|
|
16575
16142
|
for (const compatibilityPath of [v2PendingAskPath(key), legacyPendingAskPath(key)]) {
|
|
16576
16143
|
if (!compatibilityPath)
|
|
@@ -16579,67 +16146,17 @@ function readPendingAsk(key) {
|
|
|
16579
16146
|
if (!legacy || legacy.from !== key.from || legacy.to !== key.to)
|
|
16580
16147
|
continue;
|
|
16581
16148
|
const migrated = writePendingAskIfAbsent(legacy);
|
|
16582
|
-
const next = migrated ? legacy : readPendingAskFile(
|
|
16149
|
+
const next = migrated ? legacy : readPendingAskFile(canonicalPath, key);
|
|
16583
16150
|
if (next && next.from === key.from && next.to === key.to) {
|
|
16584
16151
|
try {
|
|
16585
16152
|
unlinkSync16(compatibilityPath);
|
|
16586
16153
|
} catch {}
|
|
16587
|
-
return { path:
|
|
16154
|
+
return { path: canonicalPath, record: next };
|
|
16588
16155
|
}
|
|
16589
16156
|
return { path: compatibilityPath, record: legacy };
|
|
16590
16157
|
}
|
|
16591
16158
|
return null;
|
|
16592
16159
|
}
|
|
16593
|
-
function createPendingAsk(args) {
|
|
16594
|
-
const migrated = readPendingAsk(args);
|
|
16595
|
-
if (migrated && !isStale(migrated.record, migrated.path)) {
|
|
16596
|
-
return { ok: false, existing: migrated.record, stale: false };
|
|
16597
|
-
}
|
|
16598
|
-
if (migrated) {
|
|
16599
|
-
try {
|
|
16600
|
-
unlinkSync16(migrated.path);
|
|
16601
|
-
} catch {
|
|
16602
|
-
return { ok: false, existing: migrated.record, stale: true };
|
|
16603
|
-
}
|
|
16604
|
-
}
|
|
16605
|
-
const path = pendingAskPath(args);
|
|
16606
|
-
const now = new Date().toISOString();
|
|
16607
|
-
const record = {
|
|
16608
|
-
userId: args.userId,
|
|
16609
|
-
from: args.from,
|
|
16610
|
-
to: args.to,
|
|
16611
|
-
requestId: args.requestId,
|
|
16612
|
-
contextId: args.contextId,
|
|
16613
|
-
state: "requested",
|
|
16614
|
-
createdAt: now,
|
|
16615
|
-
updatedAt: now
|
|
16616
|
-
};
|
|
16617
|
-
mkdirSync16(pendingAskDir(args.userId), { recursive: true });
|
|
16618
|
-
for (let attempt = 0;attempt < 2; attempt++) {
|
|
16619
|
-
let fd = null;
|
|
16620
|
-
try {
|
|
16621
|
-
fd = openSync2(path, "wx");
|
|
16622
|
-
writeFileSync14(fd, `${JSON.stringify(record)}
|
|
16623
|
-
`);
|
|
16624
|
-
return { ok: true, record };
|
|
16625
|
-
} catch (err2) {
|
|
16626
|
-
if (err2.code !== "EEXIST")
|
|
16627
|
-
throw err2;
|
|
16628
|
-
const existing = readPendingAskFile(path, args);
|
|
16629
|
-
if (!isStale(existing, path))
|
|
16630
|
-
return { ok: false, existing, stale: false };
|
|
16631
|
-
try {
|
|
16632
|
-
unlinkSync16(path);
|
|
16633
|
-
} catch {
|
|
16634
|
-
return { ok: false, existing, stale: true };
|
|
16635
|
-
}
|
|
16636
|
-
} finally {
|
|
16637
|
-
if (fd !== null)
|
|
16638
|
-
closeSync2(fd);
|
|
16639
|
-
}
|
|
16640
|
-
}
|
|
16641
|
-
return { ok: false, existing: readPendingAskFile(path, args), stale: true };
|
|
16642
|
-
}
|
|
16643
16160
|
function markPendingAskState(args) {
|
|
16644
16161
|
const pending = readPendingAsk(args);
|
|
16645
16162
|
if (!pending)
|
|
@@ -16673,83 +16190,6 @@ function clearPendingAsk(args) {
|
|
|
16673
16190
|
return false;
|
|
16674
16191
|
}
|
|
16675
16192
|
}
|
|
16676
|
-
function releasePendingAsk(args) {
|
|
16677
|
-
if (clearPendingAsk(args))
|
|
16678
|
-
return true;
|
|
16679
|
-
const still = readPendingAsk(args);
|
|
16680
|
-
return !still || still.record.requestId !== args.requestId;
|
|
16681
|
-
}
|
|
16682
|
-
function markPendingAskSources(args) {
|
|
16683
|
-
for (const source of args.sources ?? []) {
|
|
16684
|
-
if (!source.from)
|
|
16685
|
-
continue;
|
|
16686
|
-
markPendingAskState({
|
|
16687
|
-
userId: args.userId,
|
|
16688
|
-
from: args.callerTopic,
|
|
16689
|
-
to: source.from,
|
|
16690
|
-
requestId: source.requestId,
|
|
16691
|
-
state: args.state
|
|
16692
|
-
});
|
|
16693
|
-
}
|
|
16694
|
-
}
|
|
16695
|
-
function clearPendingAskSources(args) {
|
|
16696
|
-
for (const source of args.sources ?? []) {
|
|
16697
|
-
if (!source.from)
|
|
16698
|
-
continue;
|
|
16699
|
-
clearPendingAsk({
|
|
16700
|
-
userId: args.userId,
|
|
16701
|
-
from: args.callerTopic,
|
|
16702
|
-
to: source.from,
|
|
16703
|
-
requestId: source.requestId
|
|
16704
|
-
});
|
|
16705
|
-
}
|
|
16706
|
-
}
|
|
16707
|
-
function listPendingAsksForCaller(args) {
|
|
16708
|
-
const dir = pendingAskDir(args.userId);
|
|
16709
|
-
let files;
|
|
16710
|
-
try {
|
|
16711
|
-
files = readdirSync4(dir);
|
|
16712
|
-
} catch {
|
|
16713
|
-
return [];
|
|
16714
|
-
}
|
|
16715
|
-
const records = new Map;
|
|
16716
|
-
for (const fileName of files) {
|
|
16717
|
-
const isV3 = fileName.startsWith(ASK_FILENAME_PREFIX);
|
|
16718
|
-
const parsed = isV3 ? { from: args.from, to: "" } : parsePendingAskFilename(fileName);
|
|
16719
|
-
if (!parsed)
|
|
16720
|
-
continue;
|
|
16721
|
-
const path = join28(dir, fileName);
|
|
16722
|
-
const record = readPendingAskFile(path, {
|
|
16723
|
-
userId: args.userId,
|
|
16724
|
-
from: parsed.from,
|
|
16725
|
-
to: parsed.to
|
|
16726
|
-
});
|
|
16727
|
-
if (!record || record.from !== args.from)
|
|
16728
|
-
continue;
|
|
16729
|
-
if (isStale(record, path)) {
|
|
16730
|
-
try {
|
|
16731
|
-
unlinkSync16(path);
|
|
16732
|
-
} catch {}
|
|
16733
|
-
continue;
|
|
16734
|
-
}
|
|
16735
|
-
const canonical = readPendingAsk(record);
|
|
16736
|
-
if (!canonical || canonical.record.from !== args.from)
|
|
16737
|
-
continue;
|
|
16738
|
-
if (path !== canonical.path) {
|
|
16739
|
-
try {
|
|
16740
|
-
unlinkSync16(path);
|
|
16741
|
-
} catch {}
|
|
16742
|
-
}
|
|
16743
|
-
if (isStale(canonical.record, canonical.path)) {
|
|
16744
|
-
try {
|
|
16745
|
-
unlinkSync16(canonical.path);
|
|
16746
|
-
} catch {}
|
|
16747
|
-
continue;
|
|
16748
|
-
}
|
|
16749
|
-
records.set(encodeAskKey(canonical.record), canonical.record);
|
|
16750
|
-
}
|
|
16751
|
-
return [...records.values()];
|
|
16752
|
-
}
|
|
16753
16193
|
function deletePendingAsksForTopic(args) {
|
|
16754
16194
|
const dir = pendingAskDir(args.userId);
|
|
16755
16195
|
let files;
|
|
@@ -16778,18 +16218,6 @@ function deletePendingAsksForTopic(args) {
|
|
|
16778
16218
|
}
|
|
16779
16219
|
return deleted;
|
|
16780
16220
|
}
|
|
16781
|
-
function describePendingAskState(state) {
|
|
16782
|
-
switch (state) {
|
|
16783
|
-
case "requested":
|
|
16784
|
-
return "\uB300\uC0C1 \uC138\uC158 \uCC98\uB9AC \uC911";
|
|
16785
|
-
case "reply_ready":
|
|
16786
|
-
return "\uC751\uB2F5 \uC0DD\uC131 \uC644\uB8CC, \uC774 \uC138\uC158 \uC8FC\uC785 \uC900\uBE44 \uC911";
|
|
16787
|
-
case "queued_for_caller":
|
|
16788
|
-
return "\uC751\uB2F5 \uC0DD\uC131 \uC644\uB8CC, \uC774 \uC138\uC158 \uC2E4\uD589 \uC885\uB8CC \uD6C4 \uC8FC\uC785 \uB300\uAE30 \uC911";
|
|
16789
|
-
case "injecting_to_caller":
|
|
16790
|
-
return "\uC751\uB2F5\uC744 \uC774 \uC138\uC158\uC5D0 \uC8FC\uC785 \uC911";
|
|
16791
|
-
}
|
|
16792
|
-
}
|
|
16793
16221
|
var PENDING_ASK_TTL_MS, ASK_FILENAME_PREFIX = "v3-", V2_ASK_FILENAME_PREFIX = "v2-";
|
|
16794
16222
|
var init_session_asks = __esm(async () => {
|
|
16795
16223
|
await init_storage_host();
|
|
@@ -16891,10 +16319,10 @@ function deferRemoteSessionReplyOutbox(args) {
|
|
|
16891
16319
|
if (!row)
|
|
16892
16320
|
return;
|
|
16893
16321
|
const attempts = Number(row.attempts) + 1;
|
|
16894
|
-
const
|
|
16322
|
+
const delay = args.retryMs ?? remoteSessionRetryDelayMs(attempts, args.random);
|
|
16895
16323
|
db.query(`UPDATE remote_session_reply_outbox
|
|
16896
16324
|
SET attempts = ?, next_attempt_at = ?, last_error = ?
|
|
16897
|
-
WHERE request_id = ?`).run(attempts, now +
|
|
16325
|
+
WHERE request_id = ?`).run(attempts, now + delay, args.error.slice(0, 500), args.requestId);
|
|
16898
16326
|
})();
|
|
16899
16327
|
}
|
|
16900
16328
|
function purgeExpiredRemoteSessionReplyOutbox(now = Date.now()) {
|
|
@@ -17065,37 +16493,9 @@ var init_remote_session_reply_outbox = __esm(async () => {
|
|
|
17065
16493
|
});
|
|
17066
16494
|
|
|
17067
16495
|
// ../../packages/core/src/mcp/session-comm/peer-forward.ts
|
|
17068
|
-
var exports_peer_forward = {};
|
|
17069
|
-
__export(exports_peer_forward, {
|
|
17070
|
-
registerPeerSessionBridge: () => registerPeerSessionBridge,
|
|
17071
|
-
peerSessionsForUser: () => peerSessionsForUser,
|
|
17072
|
-
parseHubRemoteReplyRoute: () => parseHubRemoteReplyRoute,
|
|
17073
|
-
isHubRemoteReplyRoute: () => isHubRemoteReplyRoute,
|
|
17074
|
-
forwardToPeer: () => forwardToPeer,
|
|
17075
|
-
deliverPeerReply: () => deliverPeerReply
|
|
17076
|
-
});
|
|
17077
16496
|
function isHubRemoteReplyRoute(route) {
|
|
17078
16497
|
return route.via === "hub";
|
|
17079
16498
|
}
|
|
17080
|
-
function parseHubRemoteReplyRoute(value) {
|
|
17081
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
17082
|
-
return null;
|
|
17083
|
-
const route = value;
|
|
17084
|
-
if (route.via !== "hub" || typeof route.hubUrl !== "string" || typeof route.token !== "string" || typeof route.nodeName !== "string" || typeof route.topicId !== "string" || typeof route.requestId !== "string") {
|
|
17085
|
-
return null;
|
|
17086
|
-
}
|
|
17087
|
-
const requestId = route.requestId.trim();
|
|
17088
|
-
const nodeName = route.nodeName.trim();
|
|
17089
|
-
const topicId = route.topicId.trim();
|
|
17090
|
-
const token = route.token.trim();
|
|
17091
|
-
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)) {
|
|
17092
|
-
return null;
|
|
17093
|
-
}
|
|
17094
|
-
const hubUrl = normalizeHubUrl(route.hubUrl.trim(), "remoteReply.hubUrl");
|
|
17095
|
-
if ("error" in hubUrl)
|
|
17096
|
-
return null;
|
|
17097
|
-
return { via: "hub", hubUrl: hubUrl.url, token, nodeName, topicId, requestId };
|
|
17098
|
-
}
|
|
17099
16499
|
function loopbackBridgeConfig() {
|
|
17100
16500
|
const rawUrl = process.env[PEER_BRIDGE_URL_ENV]?.trim();
|
|
17101
16501
|
const token = process.env[PEER_BRIDGE_TOKEN_ENV]?.trim();
|
|
@@ -17132,39 +16532,6 @@ async function callLoopbackBridge(request) {
|
|
|
17132
16532
|
return { configured: true, result: null };
|
|
17133
16533
|
}
|
|
17134
16534
|
}
|
|
17135
|
-
function registerPeerSessionBridge(bridge) {
|
|
17136
|
-
activeBridge = bridge;
|
|
17137
|
-
return () => {
|
|
17138
|
-
if (activeBridge === bridge)
|
|
17139
|
-
activeBridge = null;
|
|
17140
|
-
};
|
|
17141
|
-
}
|
|
17142
|
-
async function forwardToPeer(args) {
|
|
17143
|
-
if (activeBridge)
|
|
17144
|
-
return activeBridge.forward(args);
|
|
17145
|
-
const forwarded = await callLoopbackBridge({ action: "forward", args });
|
|
17146
|
-
if (forwarded.result)
|
|
17147
|
-
return forwarded.result;
|
|
17148
|
-
return {
|
|
17149
|
-
ok: false,
|
|
17150
|
-
error: forwarded.configured ? "remote session bridge is configured but unavailable" : "remote nodes are not connected on this negotium node (standalone mode)"
|
|
17151
|
-
};
|
|
17152
|
-
}
|
|
17153
|
-
async function peerSessionsForUser(userId, sourceQueryId, fromTopicId) {
|
|
17154
|
-
if (activeBridge)
|
|
17155
|
-
return activeBridge.sessions(userId, sourceQueryId, fromTopicId);
|
|
17156
|
-
const sessions = await callLoopbackBridge({
|
|
17157
|
-
action: "sessions",
|
|
17158
|
-
userId,
|
|
17159
|
-
sourceQueryId,
|
|
17160
|
-
fromTopicId
|
|
17161
|
-
});
|
|
17162
|
-
if (sessions.result)
|
|
17163
|
-
return sessions.result;
|
|
17164
|
-
if (sessions.configured)
|
|
17165
|
-
return { ok: false, nodes: [] };
|
|
17166
|
-
return { ok: true, nodes: [] };
|
|
17167
|
-
}
|
|
17168
16535
|
async function deliverPeerReply(route, sourceTitle, replyText, kind) {
|
|
17169
16536
|
if (isHubRemoteReplyRoute(route)) {
|
|
17170
16537
|
return deliverHubRemoteReply(route, sourceTitle, replyText, kind);
|
|
@@ -17179,40 +16546,13 @@ async function deliverPeerReply(route, sourceTitle, replyText, kind) {
|
|
|
17179
16546
|
kind
|
|
17180
16547
|
})).result ?? false;
|
|
17181
16548
|
}
|
|
17182
|
-
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;
|
|
17183
16550
|
var init_peer_forward = __esm(async () => {
|
|
17184
16551
|
init_remote_session_grant();
|
|
17185
16552
|
await init_remote_session_reply_outbox();
|
|
17186
16553
|
});
|
|
17187
16554
|
|
|
17188
16555
|
// ../../packages/core/src/runtime/ask-callbacks.ts
|
|
17189
|
-
var exports_ask_callbacks = {};
|
|
17190
|
-
__export(exports_ask_callbacks, {
|
|
17191
|
-
resolveAskCallback: () => resolveAskCallback,
|
|
17192
|
-
registerAskCallback: () => registerAskCallback,
|
|
17193
|
-
purgeStaleAsks: () => purgeStaleAsks,
|
|
17194
|
-
failInterruptedRemoteAskCallbacks: () => failInterruptedRemoteAskCallbacks,
|
|
17195
|
-
deleteHubRemoteAskCallbackRow: () => deleteHubRemoteAskCallbackRow,
|
|
17196
|
-
cancelAskCallbacksForTopic: () => cancelAskCallbacksForTopic
|
|
17197
|
-
});
|
|
17198
|
-
function registerAskCallback(entry) {
|
|
17199
|
-
pendingAsks.set(entry.targetQueryId, entry);
|
|
17200
|
-
if (entry.remoteReply) {
|
|
17201
|
-
const route = entry.remoteReply;
|
|
17202
|
-
const hub = isHubRemoteReplyRoute(route);
|
|
17203
|
-
db.query(`INSERT INTO remote_ask_callbacks
|
|
17204
|
-
(target_query_id, request_id, node_name, node_cell_id, topic_id, user_id, created_at, route_json)
|
|
17205
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
17206
|
-
ON CONFLICT(target_query_id) DO UPDATE SET
|
|
17207
|
-
request_id = excluded.request_id,
|
|
17208
|
-
node_name = excluded.node_name,
|
|
17209
|
-
node_cell_id = excluded.node_cell_id,
|
|
17210
|
-
topic_id = excluded.topic_id,
|
|
17211
|
-
user_id = excluded.user_id,
|
|
17212
|
-
created_at = excluded.created_at,
|
|
17213
|
-
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);
|
|
17214
|
-
}
|
|
17215
|
-
}
|
|
17216
16556
|
function resolveAskCallback(queryId) {
|
|
17217
16557
|
const entry = pendingAsks.get(queryId);
|
|
17218
16558
|
if (!entry)
|
|
@@ -17229,13 +16569,6 @@ function resolveAskCallback(queryId) {
|
|
|
17229
16569
|
function deleteHubRemoteAskCallbackRow(requestId) {
|
|
17230
16570
|
db.query("DELETE FROM remote_ask_callbacks WHERE request_id = ? AND route_json IS NOT NULL").run(requestId);
|
|
17231
16571
|
}
|
|
17232
|
-
function purgeStaleAsks(now = Date.now()) {
|
|
17233
|
-
for (const [id, entry] of pendingAsks) {
|
|
17234
|
-
if (now - entry.createdAt > MAX_ASK_AGE_MS)
|
|
17235
|
-
pendingAsks.delete(id);
|
|
17236
|
-
}
|
|
17237
|
-
db.query("DELETE FROM remote_ask_callbacks WHERE created_at < ?").run(now - MAX_ASK_AGE_MS);
|
|
17238
|
-
}
|
|
17239
16572
|
function cancelAskCallbacksForTopic(topicId) {
|
|
17240
16573
|
let cancelled = 0;
|
|
17241
16574
|
for (const [queryId, entry] of pendingAsks) {
|
|
@@ -17247,43 +16580,6 @@ function cancelAskCallbacksForTopic(topicId) {
|
|
|
17247
16580
|
}
|
|
17248
16581
|
return cancelled;
|
|
17249
16582
|
}
|
|
17250
|
-
function durableRoute(row) {
|
|
17251
|
-
if (row.route_json) {
|
|
17252
|
-
try {
|
|
17253
|
-
return parseHubRemoteReplyRoute(JSON.parse(row.route_json));
|
|
17254
|
-
} catch {
|
|
17255
|
-
return null;
|
|
17256
|
-
}
|
|
17257
|
-
}
|
|
17258
|
-
return {
|
|
17259
|
-
nodeName: row.node_name,
|
|
17260
|
-
nodeCellId: row.node_cell_id,
|
|
17261
|
-
topicId: row.topic_id,
|
|
17262
|
-
userId: row.user_id,
|
|
17263
|
-
requestId: row.request_id
|
|
17264
|
-
};
|
|
17265
|
-
}
|
|
17266
|
-
async function failInterruptedRemoteAskCallbacks(options = {}) {
|
|
17267
|
-
const rows = db.query(`SELECT target_query_id, request_id, node_name, node_cell_id, topic_id, user_id, route_json
|
|
17268
|
-
FROM remote_ask_callbacks
|
|
17269
|
-
ORDER BY created_at ASC`).all();
|
|
17270
|
-
let failed = 0;
|
|
17271
|
-
for (const row of rows) {
|
|
17272
|
-
const route = durableRoute(row);
|
|
17273
|
-
if (!route) {
|
|
17274
|
-
db.query("DELETE FROM remote_ask_callbacks WHERE target_query_id = ?").run(row.target_query_id);
|
|
17275
|
-
continue;
|
|
17276
|
-
}
|
|
17277
|
-
if (options.routes === "hub" && !isHubRemoteReplyRoute(route))
|
|
17278
|
-
continue;
|
|
17279
|
-
const delivered = await deliverPeerReply(route, "peer", "The remote worker restarted before this ask completed. Please retry the request.", "error");
|
|
17280
|
-
if (!delivered)
|
|
17281
|
-
continue;
|
|
17282
|
-
db.query("DELETE FROM remote_ask_callbacks WHERE target_query_id = ?").run(row.target_query_id);
|
|
17283
|
-
failed++;
|
|
17284
|
-
}
|
|
17285
|
-
return failed;
|
|
17286
|
-
}
|
|
17287
16583
|
var pendingAsks, MAX_ASK_AGE_MS;
|
|
17288
16584
|
var init_ask_callbacks = __esm(async () => {
|
|
17289
16585
|
await __promiseAll([
|
|
@@ -17709,14 +17005,6 @@ var init_topic_tool_capabilities = __esm(async () => {
|
|
|
17709
17005
|
});
|
|
17710
17006
|
|
|
17711
17007
|
// ../../packages/core/src/topics/lifecycle.ts
|
|
17712
|
-
var exports_lifecycle = {};
|
|
17713
|
-
__export(exports_lifecycle, {
|
|
17714
|
-
deleteTopicCascade: () => deleteTopicCascade,
|
|
17715
|
-
TopicTurnStillActiveError: () => TopicTurnStillActiveError,
|
|
17716
|
-
TopicDeleteVetoedError: () => TopicDeleteVetoedError,
|
|
17717
|
-
TopicCleanupRequiredError: () => TopicCleanupRequiredError,
|
|
17718
|
-
TopicArchiveRequiredError: () => TopicArchiveRequiredError
|
|
17719
|
-
});
|
|
17720
17008
|
import { rmSync as rmSync6 } from "fs";
|
|
17721
17009
|
async function abortAndWaitForTopic(topicId) {
|
|
17722
17010
|
interSessionQueue.drop(topicId);
|
|
@@ -17749,8 +17037,8 @@ async function cleanupParticipantResources(topic, userIds, sessionId, cwd, purge
|
|
|
17749
17037
|
cwd,
|
|
17750
17038
|
extraSessions: index === 0 ? currentSessionRef(topic, sessionId) : []
|
|
17751
17039
|
});
|
|
17752
|
-
} catch (
|
|
17753
|
-
logger.warn({ err
|
|
17040
|
+
} catch (err) {
|
|
17041
|
+
logger.warn({ err, topicId: topic.id, userId: participantUserId }, "deleteTopicCascade: participant rollout cleanup failed");
|
|
17754
17042
|
}
|
|
17755
17043
|
if (!purged)
|
|
17756
17044
|
return false;
|
|
@@ -17806,12 +17094,12 @@ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorId
|
|
|
17806
17094
|
if (rawArchive)
|
|
17807
17095
|
rawArchives.push(rawArchive.path);
|
|
17808
17096
|
}
|
|
17809
|
-
} catch (
|
|
17097
|
+
} catch (err) {
|
|
17810
17098
|
if (!force) {
|
|
17811
|
-
logger.warn({ err
|
|
17812
|
-
throw new TopicArchiveRequiredError(topicId,
|
|
17099
|
+
logger.warn({ err, topicId }, "deleteTopicCascade: archive failed - blocking delete unless force=true");
|
|
17100
|
+
throw new TopicArchiveRequiredError(topicId, err);
|
|
17813
17101
|
}
|
|
17814
|
-
logger.warn({ err
|
|
17102
|
+
logger.warn({ err, topicId }, "deleteTopicCascade: archive failed but force=true - continuing with hard delete");
|
|
17815
17103
|
}
|
|
17816
17104
|
}
|
|
17817
17105
|
if (archived && meetsMemoryArchiveExchangeThreshold(archived.exchangeCount, MIN_MEMORY_ARCHIVE_EXCHANGES, topic)) {
|
|
@@ -17827,8 +17115,8 @@ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorId
|
|
|
17827
17115
|
...rawArchives.length > 0 ? { rawArchivePaths: rawArchives } : {},
|
|
17828
17116
|
messageCount: archived.messageCount
|
|
17829
17117
|
});
|
|
17830
|
-
} catch (
|
|
17831
|
-
logger.warn({ err
|
|
17118
|
+
} catch (err) {
|
|
17119
|
+
logger.warn({ err, topicId, archive: archived.path }, "deleteTopicCascade: background archiver launch failed - raw archive preserved");
|
|
17832
17120
|
}
|
|
17833
17121
|
}
|
|
17834
17122
|
const sessionId = getTopicSessionId(topicId);
|
|
@@ -17847,21 +17135,21 @@ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorId
|
|
|
17847
17135
|
const browserProfile = getTopicBrowserProfile(topicId);
|
|
17848
17136
|
try {
|
|
17849
17137
|
await closeBrowserOwnerTabs(browserProfileOwner, browserProfile, `topic:${topicId}`);
|
|
17850
|
-
} catch (
|
|
17851
|
-
logger.warn({ err
|
|
17138
|
+
} catch (err) {
|
|
17139
|
+
logger.warn({ err, topicId }, "deleteTopicCascade: browser owner cleanup failed");
|
|
17852
17140
|
}
|
|
17853
17141
|
deleteTopicProfileDir(userId, topicId);
|
|
17854
17142
|
cancelAskCallbacksForTopic(topicId);
|
|
17855
17143
|
deleteSelfSchedulesForTopic(topicId);
|
|
17856
17144
|
try {
|
|
17857
17145
|
await deleteFilesForTopic(topicId);
|
|
17858
|
-
} catch (
|
|
17859
|
-
logger.warn({ err
|
|
17146
|
+
} catch (err) {
|
|
17147
|
+
logger.warn({ err, topicId }, "deleteTopicCascade: host file cleanup failed");
|
|
17860
17148
|
}
|
|
17861
17149
|
try {
|
|
17862
17150
|
rmSync6(cwd, { recursive: true, force: true });
|
|
17863
|
-
} catch (
|
|
17864
|
-
logger.warn({ err
|
|
17151
|
+
} catch (err) {
|
|
17152
|
+
logger.warn({ err, topicId, cwd }, "deleteTopicCascade: workspace cleanup failed");
|
|
17865
17153
|
}
|
|
17866
17154
|
deleteTopicVisuals(topicId);
|
|
17867
17155
|
deleteTopicHostMcpGrant(topicId);
|
|
@@ -17903,7 +17191,7 @@ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorId
|
|
|
17903
17191
|
}
|
|
17904
17192
|
}
|
|
17905
17193
|
}
|
|
17906
|
-
var DELETE_TURN_WAIT_MS = 5000, TopicArchiveRequiredError, TopicTurnStillActiveError, TopicCleanupRequiredError
|
|
17194
|
+
var DELETE_TURN_WAIT_MS = 5000, TopicArchiveRequiredError, TopicTurnStillActiveError, TopicCleanupRequiredError;
|
|
17907
17195
|
var init_lifecycle = __esm(async () => {
|
|
17908
17196
|
init_manager();
|
|
17909
17197
|
init_config();
|
|
@@ -17970,19 +17258,9 @@ var init_lifecycle = __esm(async () => {
|
|
|
17970
17258
|
this.topicId = topicId;
|
|
17971
17259
|
}
|
|
17972
17260
|
};
|
|
17973
|
-
TopicDeleteVetoedError = class TopicDeleteVetoedError extends Error {
|
|
17974
|
-
code = "TOPIC_DELETE_VETOED";
|
|
17975
|
-
topicId;
|
|
17976
|
-
constructor(topicId, reason) {
|
|
17977
|
-
super(`Topic delete was vetoed: ${reason}`);
|
|
17978
|
-
this.name = "TopicDeleteVetoedError";
|
|
17979
|
-
this.topicId = topicId;
|
|
17980
|
-
}
|
|
17981
|
-
};
|
|
17982
17261
|
});
|
|
17983
17262
|
|
|
17984
17263
|
// ../../packages/core/src/runtime/attachments.ts
|
|
17985
|
-
import { randomUUID as randomUUID16 } from "crypto";
|
|
17986
17264
|
import { copyFileSync as copyFileSync2, mkdirSync as mkdirSync17, writeFileSync as writeFileSync15 } from "fs";
|
|
17987
17265
|
import { basename as basename6, join as join29 } from "path";
|
|
17988
17266
|
function workspaceCwdFor(topicId) {
|
|
@@ -18024,8 +17302,8 @@ function materializePromptAttachments(topicId, queryId, attachmentIds) {
|
|
|
18024
17302
|
sizeBytes: attachment.sizeBytes,
|
|
18025
17303
|
path: destPath
|
|
18026
17304
|
});
|
|
18027
|
-
} catch (
|
|
18028
|
-
logger.warn({ topicId, queryId, fileId, err
|
|
17305
|
+
} catch (err) {
|
|
17306
|
+
logger.warn({ topicId, queryId, fileId, err }, "ai: failed to materialize attachment");
|
|
18029
17307
|
}
|
|
18030
17308
|
}
|
|
18031
17309
|
return out;
|
|
@@ -18043,24 +17321,6 @@ function composeAttachmentPrompt(prompt, promptLines) {
|
|
|
18043
17321
|
function promptWithAttachments(prompt, attachments) {
|
|
18044
17322
|
return composeAttachmentPrompt(prompt, attachments.map(({ filename, path }) => attachmentPromptLine(filename, path)));
|
|
18045
17323
|
}
|
|
18046
|
-
function ingestAttachment(args) {
|
|
18047
|
-
const destDir = join29(UPLOADS_DIR, args.topicId);
|
|
18048
|
-
mkdirSync17(destDir, { recursive: true });
|
|
18049
|
-
const safeName = safeAttachmentFilename(args.filename, "upload");
|
|
18050
|
-
const destPath = join29(destDir, `${Date.now()}-${randomUUID16().slice(0, 8)}-${safeName}`);
|
|
18051
|
-
if (args.sourcePath !== undefined) {
|
|
18052
|
-
copyFileSync2(args.sourcePath, destPath);
|
|
18053
|
-
} else if (args.bytes !== undefined) {
|
|
18054
|
-
writeFileSync15(destPath, args.bytes);
|
|
18055
|
-
} else {
|
|
18056
|
-
throw new Error("ingestAttachment: provide sourcePath or bytes");
|
|
18057
|
-
}
|
|
18058
|
-
return {
|
|
18059
|
-
path: destPath,
|
|
18060
|
-
filename: args.filename,
|
|
18061
|
-
promptLine: attachmentPromptLine(args.filename, destPath)
|
|
18062
|
-
};
|
|
18063
|
-
}
|
|
18064
17324
|
function parseAttachmentNames(raw) {
|
|
18065
17325
|
if (!raw)
|
|
18066
17326
|
return [];
|
|
@@ -18101,13 +17361,13 @@ function isLikelyCurrentChannelTrigger(row, userId, prompt) {
|
|
|
18101
17361
|
return Number.isFinite(createdMs) && Date.now() - createdMs <= CHANNEL_CONTEXT_CURRENT_MESSAGE_MATCH_MS;
|
|
18102
17362
|
}
|
|
18103
17363
|
function formatChannelTranscriptLine(row) {
|
|
18104
|
-
const
|
|
17364
|
+
const text = row.text.trim();
|
|
18105
17365
|
const attachments = parseAttachmentNames(row.attachments);
|
|
18106
17366
|
const attachmentSuffix = attachments.length > 0 ? `
|
|
18107
17367
|
[attachments: ${attachments.join(", ")}]` : "";
|
|
18108
17368
|
const edited = row.edited_at ? " (edited)" : "";
|
|
18109
17369
|
const thread = row.thread_root_id ? ` (in thread ${threadTag(row.thread_root_id)})` : "";
|
|
18110
|
-
return `[${row.created_at}] ${channelTranscriptSpeaker(row)}${edited}${thread}: ${
|
|
17370
|
+
return `[${row.created_at}] ${channelTranscriptSpeaker(row)}${edited}${thread}: ${text}${attachmentSuffix}`;
|
|
18111
17371
|
}
|
|
18112
17372
|
function buildMentionOnlyChannelPrompt(params) {
|
|
18113
17373
|
const rows = getAllMessagesForTopic(params.topicId).filter((row) => {
|
|
@@ -18152,14 +17412,6 @@ function buildMentionOnlyChannelPrompt(params) {
|
|
|
18152
17412
|
].filter((line) => line !== undefined).join(`
|
|
18153
17413
|
`);
|
|
18154
17414
|
}
|
|
18155
|
-
function escapeRegExp3(s) {
|
|
18156
|
-
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
18157
|
-
}
|
|
18158
|
-
function mentionsAi(text2, label) {
|
|
18159
|
-
const names = ["ai", "bot", "\uBD07", label.trim()].filter(Boolean);
|
|
18160
|
-
const alt = names.map(escapeRegExp3).join("|");
|
|
18161
|
-
return new RegExp(`(^|\\s)@(${alt})(?![\\p{L}\\p{N}])`, "iu").test(text2);
|
|
18162
|
-
}
|
|
18163
17415
|
var CHANNEL_CONTEXT_CURRENT_MESSAGE_MATCH_MS, CHANNEL_CONTEXT_MAX_MESSAGES = 500, CHANNEL_CONTEXT_MAX_CHARS = 120000;
|
|
18164
17416
|
var init_channel_context = __esm(async () => {
|
|
18165
17417
|
init_attachments();
|
|
@@ -18168,13 +17420,13 @@ var init_channel_context = __esm(async () => {
|
|
|
18168
17420
|
});
|
|
18169
17421
|
|
|
18170
17422
|
// ../../packages/core/src/runtime/errors.ts
|
|
18171
|
-
function stringifyError(
|
|
18172
|
-
if (
|
|
18173
|
-
return
|
|
18174
|
-
if (typeof
|
|
18175
|
-
return
|
|
17423
|
+
function stringifyError(err) {
|
|
17424
|
+
if (err instanceof Error)
|
|
17425
|
+
return err.message;
|
|
17426
|
+
if (typeof err === "string")
|
|
17427
|
+
return err;
|
|
18176
17428
|
try {
|
|
18177
|
-
return JSON.stringify(
|
|
17429
|
+
return JSON.stringify(err) ?? String(err);
|
|
18178
17430
|
} catch {
|
|
18179
17431
|
return "Unknown agent error";
|
|
18180
17432
|
}
|
|
@@ -18189,19 +17441,19 @@ function authRecoveryHint(agent) {
|
|
|
18189
17441
|
return "Please check the DEEPSEEK_API_KEY, MOONSHOT_API_KEY, or GLM_API_KEY environment variable";
|
|
18190
17442
|
}
|
|
18191
17443
|
}
|
|
18192
|
-
function classifyAgentError(
|
|
17444
|
+
function classifyAgentError(err, agent) {
|
|
18193
17445
|
const name = AGENT_DISPLAY_NAME[agent];
|
|
18194
17446
|
const hint = authRecoveryHint(agent);
|
|
18195
|
-
const ctor = typeof
|
|
17447
|
+
const ctor = typeof err === "object" && err !== null ? err.constructor?.name : undefined;
|
|
18196
17448
|
if (ctor === "AuthenticationError")
|
|
18197
17449
|
return `${name} authentication expired. ${hint}. (401)`;
|
|
18198
17450
|
if (ctor === "RateLimitError")
|
|
18199
17451
|
return `${name} request limit exceeded. Please try again in a moment. (429)`;
|
|
18200
17452
|
if (ctor === "InternalServerError") {
|
|
18201
|
-
const status =
|
|
17453
|
+
const status = err.status;
|
|
18202
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)`;
|
|
18203
17455
|
}
|
|
18204
|
-
const s = stringifyError(
|
|
17456
|
+
const s = stringifyError(err);
|
|
18205
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)) {
|
|
18206
17458
|
return `${name} authentication expired. ${hint}. (401)`;
|
|
18207
17459
|
}
|
|
@@ -18224,12 +17476,12 @@ var init_errors = __esm(() => {
|
|
|
18224
17476
|
|
|
18225
17477
|
// ../../packages/core/src/runtime/event-heartbeat.ts
|
|
18226
17478
|
function nextOrHeartbeat(pending, intervalMs) {
|
|
18227
|
-
return new Promise((
|
|
18228
|
-
const timer = setTimeout(() =>
|
|
17479
|
+
return new Promise((resolve, reject) => {
|
|
17480
|
+
const timer = setTimeout(() => resolve({ kind: "heartbeat" }), intervalMs);
|
|
18229
17481
|
timer.unref?.();
|
|
18230
17482
|
pending.then((result) => {
|
|
18231
17483
|
clearTimeout(timer);
|
|
18232
|
-
|
|
17484
|
+
resolve({ kind: "event", result });
|
|
18233
17485
|
}, (error) => {
|
|
18234
17486
|
clearTimeout(timer);
|
|
18235
17487
|
reject(error);
|
|
@@ -18523,7 +17775,7 @@ var init_vault_request_gates = __esm(async () => {
|
|
|
18523
17775
|
});
|
|
18524
17776
|
|
|
18525
17777
|
// ../../packages/core/src/agents/mcp-tools/request-vault.ts
|
|
18526
|
-
import { createHash as createHash12, randomUUID as
|
|
17778
|
+
import { createHash as createHash12, randomUUID as randomUUID16 } from "crypto";
|
|
18527
17779
|
import { z as z4 } from "zod";
|
|
18528
17780
|
function requestBodyHash(key, description) {
|
|
18529
17781
|
return createHash12("sha256").update(JSON.stringify({ key, description })).digest("hex");
|
|
@@ -18759,8 +18011,8 @@ function createRequestVaultRuntime(host) {
|
|
|
18759
18011
|
return errorResult(`Error: failed to persist request_vault_secret: ${error instanceof Error ? error.message : String(error)}`);
|
|
18760
18012
|
}
|
|
18761
18013
|
let resolveAnswer;
|
|
18762
|
-
const promise = new Promise((
|
|
18763
|
-
resolveAnswer =
|
|
18014
|
+
const promise = new Promise((resolve) => {
|
|
18015
|
+
resolveAnswer = resolve;
|
|
18764
18016
|
});
|
|
18765
18017
|
pendingRequests.set(message.id, {
|
|
18766
18018
|
topicId: ctx.topicId,
|
|
@@ -18821,7 +18073,7 @@ var init_request_vault = __esm(async () => {
|
|
|
18821
18073
|
init_vault_request_gates()
|
|
18822
18074
|
]);
|
|
18823
18075
|
MAX_DESCRIPTION_CHARS = VAULT_DESCRIPTION_MAX_LENGTH;
|
|
18824
|
-
VAULT_GATE_OWNER_ID = `request-vault-${process.pid}-${
|
|
18076
|
+
VAULT_GATE_OWNER_ID = `request-vault-${process.pid}-${randomUUID16()}`;
|
|
18825
18077
|
defaultRequestVaultDurabilityHost = {
|
|
18826
18078
|
gates: {
|
|
18827
18079
|
prepare: prepareVaultRequestGate,
|
|
@@ -18862,7 +18114,7 @@ var init_request_vault = __esm(async () => {
|
|
|
18862
18114
|
durability: defaultRequestVaultDurabilityHost,
|
|
18863
18115
|
runtime: {
|
|
18864
18116
|
ownerId: VAULT_GATE_OWNER_ID,
|
|
18865
|
-
createId:
|
|
18117
|
+
createId: randomUUID16,
|
|
18866
18118
|
now: () => new Date().toISOString()
|
|
18867
18119
|
}
|
|
18868
18120
|
});
|
|
@@ -18899,24 +18151,24 @@ function taskPanelMessageId(queryId) {
|
|
|
18899
18151
|
// ../../packages/core/src/runtime/tasks.ts
|
|
18900
18152
|
function upsertTaskPanelMessage(topicId, queryId, tasks, lastRenderedText) {
|
|
18901
18153
|
if (tasks.length === 0) {
|
|
18902
|
-
const
|
|
18903
|
-
for (const
|
|
18904
|
-
|
|
18154
|
+
const hub = WsHub.get();
|
|
18155
|
+
for (const messageId of softDeleteApiMessagesByIdPrefix(topicId, "tasks-")) {
|
|
18156
|
+
hub.broadcastMessageUpdated(topicId, messageId, { deleted: true, text: "" });
|
|
18905
18157
|
}
|
|
18906
18158
|
return null;
|
|
18907
18159
|
}
|
|
18908
|
-
const
|
|
18909
|
-
if (
|
|
18160
|
+
const text = renderTaskPanel(tasks);
|
|
18161
|
+
if (text === lastRenderedText)
|
|
18910
18162
|
return lastRenderedText;
|
|
18911
18163
|
const hub = WsHub.get();
|
|
18912
18164
|
const messageId = taskPanelMessageId(queryId);
|
|
18913
18165
|
const existing = getApiMessage(topicId, messageId);
|
|
18914
18166
|
if (existing && !existing.deleted) {
|
|
18915
18167
|
const editedAt = new Date().toISOString();
|
|
18916
|
-
const updated = updateApiMessageText(topicId, messageId,
|
|
18168
|
+
const updated = updateApiMessageText(topicId, messageId, text, editedAt);
|
|
18917
18169
|
if (updated) {
|
|
18918
|
-
hub.broadcastMessageUpdated(topicId, messageId, { text
|
|
18919
|
-
return
|
|
18170
|
+
hub.broadcastMessageUpdated(topicId, messageId, { text, editedAt });
|
|
18171
|
+
return text;
|
|
18920
18172
|
}
|
|
18921
18173
|
}
|
|
18922
18174
|
const createdAt = new Date().toISOString();
|
|
@@ -18924,12 +18176,12 @@ function upsertTaskPanelMessage(topicId, queryId, tasks, lastRenderedText) {
|
|
|
18924
18176
|
id: messageId,
|
|
18925
18177
|
topicId,
|
|
18926
18178
|
authorId: "system",
|
|
18927
|
-
text
|
|
18179
|
+
text,
|
|
18928
18180
|
createdAt
|
|
18929
18181
|
};
|
|
18930
18182
|
appendApiMessage(message, { notify: false });
|
|
18931
18183
|
hub.broadcastMessage(topicId, message);
|
|
18932
|
-
return
|
|
18184
|
+
return text;
|
|
18933
18185
|
}
|
|
18934
18186
|
var init_tasks2 = __esm(async () => {
|
|
18935
18187
|
await __promiseAll([
|
|
@@ -19188,14 +18440,14 @@ function resolveVisualMediaInput(topicId, input) {
|
|
|
19188
18440
|
if (!topicAllowsVisualFileId(topicId, fileId)) {
|
|
19189
18441
|
return { error: "file_id is not attached to this topic" };
|
|
19190
18442
|
}
|
|
19191
|
-
const
|
|
19192
|
-
const
|
|
19193
|
-
if (!
|
|
18443
|
+
const attachment = resolveAttachmentByFileId(fileId);
|
|
18444
|
+
const filePath = resolveUploadedFilePathByFileId(fileId);
|
|
18445
|
+
if (!attachment || !filePath)
|
|
19194
18446
|
return { error: `uploaded file not found: ${fileId}` };
|
|
19195
18447
|
return {
|
|
19196
|
-
fileId:
|
|
19197
|
-
mimeType:
|
|
19198
|
-
source: `file_id:${
|
|
18448
|
+
fileId: attachment.id,
|
|
18449
|
+
mimeType: attachment.mimeType,
|
|
18450
|
+
source: `file_id:${attachment.id}`
|
|
19199
18451
|
};
|
|
19200
18452
|
}
|
|
19201
18453
|
if (typeof input.file_path !== "string" || !input.file_path.trim()) {
|
|
@@ -19242,7 +18494,7 @@ var init_visuals = __esm(async () => {
|
|
|
19242
18494
|
});
|
|
19243
18495
|
|
|
19244
18496
|
// ../../packages/core/src/runtime/turn-event-stream.ts
|
|
19245
|
-
import { randomUUID as
|
|
18497
|
+
import { randomUUID as randomUUID17 } from "crypto";
|
|
19246
18498
|
import { realpathSync as realpathSync6, statSync as statSync9 } from "fs";
|
|
19247
18499
|
import { isAbsolute as isAbsolute7, resolve as resolve18 } from "path";
|
|
19248
18500
|
function sessionEventMatchesCurrentExecution(topicId, queryId, agent, model) {
|
|
@@ -19311,9 +18563,9 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
19311
18563
|
const existing = providerToolIds.get(providerId);
|
|
19312
18564
|
if (existing)
|
|
19313
18565
|
return existing;
|
|
19314
|
-
const
|
|
19315
|
-
providerToolIds.set(providerId,
|
|
19316
|
-
return
|
|
18566
|
+
const clientId = fallback ?? providerId;
|
|
18567
|
+
providerToolIds.set(providerId, clientId);
|
|
18568
|
+
return clientId;
|
|
19317
18569
|
}
|
|
19318
18570
|
const clientId = fallback ?? nextSyntheticToolUseId();
|
|
19319
18571
|
anonymousToolIds.push(clientId);
|
|
@@ -19344,15 +18596,15 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
19344
18596
|
return providerId ? handledVisualToolResultIds.has(providerId) : false;
|
|
19345
18597
|
};
|
|
19346
18598
|
const emitPendingAssistantMessage = (usage) => {
|
|
19347
|
-
const
|
|
18599
|
+
const text = pendingText.trimEnd();
|
|
19348
18600
|
pendingText = "";
|
|
19349
|
-
if (silent || !
|
|
18601
|
+
if (silent || !text.trim())
|
|
19350
18602
|
return null;
|
|
19351
18603
|
const message = {
|
|
19352
|
-
id:
|
|
18604
|
+
id: randomUUID17(),
|
|
19353
18605
|
topicId,
|
|
19354
18606
|
authorId: "ai",
|
|
19355
|
-
text
|
|
18607
|
+
text,
|
|
19356
18608
|
queryId,
|
|
19357
18609
|
agentType,
|
|
19358
18610
|
model,
|
|
@@ -19572,8 +18824,8 @@ ${JSON.stringify(event.input ?? {})}`);
|
|
|
19572
18824
|
hub.broadcastVisual(topicId, queryId, url, vizId, title ?? null, kind);
|
|
19573
18825
|
hub.broadcastToolOutput(topicId, queryId, toolUseId, `Displayed: ${url}`);
|
|
19574
18826
|
markVisualToolResultHandled(event.toolUseId);
|
|
19575
|
-
} catch (
|
|
19576
|
-
const reason =
|
|
18827
|
+
} catch (err) {
|
|
18828
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
19577
18829
|
failMediaVisual(reason);
|
|
19578
18830
|
}
|
|
19579
18831
|
} else {
|
|
@@ -19684,8 +18936,8 @@ ${JSON.stringify(event.input ?? {})}`);
|
|
|
19684
18936
|
}
|
|
19685
18937
|
terminalEmitted = true;
|
|
19686
18938
|
{
|
|
19687
|
-
|
|
19688
|
-
const pending =
|
|
18939
|
+
await init_ask_callbacks();
|
|
18940
|
+
const pending = resolveAskCallback(queryId);
|
|
19689
18941
|
if (pending) {
|
|
19690
18942
|
const sourceLabel = pending.sourceLabel ?? topicTitle;
|
|
19691
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)";
|
|
@@ -19758,8 +19010,8 @@ ${JSON.stringify(event.input ?? {})}`);
|
|
|
19758
19010
|
if (control.injectParams)
|
|
19759
19011
|
control.injectParams.sessionId = event.sessionId;
|
|
19760
19012
|
onSessionId(event.sessionId);
|
|
19761
|
-
} catch (
|
|
19762
|
-
logger.warn({ err
|
|
19013
|
+
} catch (err) {
|
|
19014
|
+
logger.warn({ err, topicId, queryId, agentType }, "ai: isolated session owner rejected provider session id");
|
|
19763
19015
|
}
|
|
19764
19016
|
} else if (!silent && sessionEventMatchesCurrentExecution(topicId, queryId, agentType, model)) {
|
|
19765
19017
|
setTopicSessionId(topicId, event.sessionId, {
|
|
@@ -19792,14 +19044,14 @@ ${JSON.stringify(event.input ?? {})}`);
|
|
|
19792
19044
|
settleSubagentFailure(queryId, "\uC911\uC9C0\uB428 (\uC0AC\uC6A9\uC790\uAC00 \uC2E4\uD589\uC744 \uBA48\uCDC4\uC2B5\uB2C8\uB2E4)");
|
|
19793
19045
|
} else {
|
|
19794
19046
|
if (control.abortReason === "internal" /* Internal */) {
|
|
19795
|
-
|
|
19796
|
-
|
|
19047
|
+
await init_ask_callbacks();
|
|
19048
|
+
resolveAskCallback(queryId);
|
|
19797
19049
|
}
|
|
19798
19050
|
}
|
|
19799
19051
|
}
|
|
19800
|
-
} catch (
|
|
19801
|
-
const msg = stringifyError(
|
|
19802
|
-
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");
|
|
19803
19055
|
terminalEmitted = true;
|
|
19804
19056
|
if (retryableSessionExpired && isSessionExpiredError(msg)) {
|
|
19805
19057
|
outcome = { kind: "session-expired", error: msg };
|
|
@@ -19950,85 +19202,7 @@ var init_app_settings = __esm(async () => {
|
|
|
19950
19202
|
});
|
|
19951
19203
|
|
|
19952
19204
|
// ../../packages/core/src/runtime/turn-runner.ts
|
|
19953
|
-
|
|
19954
|
-
__export(exports_turn_runner, {
|
|
19955
|
-
workspaceCwdFor: () => workspaceCwdFor,
|
|
19956
|
-
withDefaultPlaywright: () => withDefaultPlaywright,
|
|
19957
|
-
wasLocallyRequeuedAfterUserPreemption: () => wasLocallyRequeuedAfterUserPreemption,
|
|
19958
|
-
userConversationPromptsToRecord: () => userConversationPromptsToRecord,
|
|
19959
|
-
upsertTaskPanelMessage: () => upsertTaskPanelMessage,
|
|
19960
|
-
tryReconstructTopicRollout: () => tryReconstructTopicRollout,
|
|
19961
|
-
triggerTopicAiTurn: () => triggerTopicAiTurn,
|
|
19962
|
-
topicAllowsVisualFileId: () => topicAllowsVisualFileId,
|
|
19963
|
-
taskPanelMessageId: () => taskPanelMessageId,
|
|
19964
|
-
stripMermaidFence: () => stripMermaidFence,
|
|
19965
|
-
stringifyError: () => stringifyError,
|
|
19966
|
-
streamAgentEvents: () => streamAgentEvents,
|
|
19967
|
-
startDurableTurnRequestWorker: () => startDurableTurnRequestWorker,
|
|
19968
|
-
startAiTurn: () => startAiTurn,
|
|
19969
|
-
selectableModel: () => selectableModel,
|
|
19970
|
-
sameTurnActor: () => sameTurnActor,
|
|
19971
|
-
safeAttachmentFilename: () => safeAttachmentFilename,
|
|
19972
|
-
resolveWorkerModel: () => resolveWorkerModel,
|
|
19973
|
-
resolveWorkerDefaultModel: () => resolveWorkerDefaultModel,
|
|
19974
|
-
resolveWikiMirrorPath: () => resolveWikiMirrorPath,
|
|
19975
|
-
resolveWikiMemoryMirror: () => resolveWikiMemoryMirror,
|
|
19976
|
-
resolveVisualMediaInput: () => resolveVisualMediaInput,
|
|
19977
|
-
resolveTurnToolCapabilities: () => resolveTurnToolCapabilities,
|
|
19978
|
-
resolveTurnHostMcpServers: () => resolveTurnHostMcpServers,
|
|
19979
|
-
resolveTopicTurnSession: () => resolveTopicTurnSession,
|
|
19980
|
-
resolveTopicTurnExecution: () => resolveTopicTurnExecution,
|
|
19981
|
-
resolveSessionRetry: () => resolveSessionRetry,
|
|
19982
|
-
resolveModelForAgent: () => resolveModelForAgent,
|
|
19983
|
-
resolveInitialTurnSessionId: () => resolveInitialTurnSessionId,
|
|
19984
|
-
resolveDefaultModel: () => resolveDefaultModel,
|
|
19985
|
-
resolveCompactionExecution: () => resolveCompactionExecution,
|
|
19986
|
-
renderUserTurnBatch: () => renderUserTurnBatch,
|
|
19987
|
-
renderUserPromptBatch: () => renderUserPromptBatch,
|
|
19988
|
-
renderTaskPanel: () => renderTaskPanel,
|
|
19989
|
-
promptWithAttachments: () => promptWithAttachments,
|
|
19990
|
-
prepareInjectReplayAfterUserPreemption: () => prepareInjectReplayAfterUserPreemption,
|
|
19991
|
-
parseAttachmentNames: () => parseAttachmentNames,
|
|
19992
|
-
normalizeToolUseId: () => normalizeToolUseId,
|
|
19993
|
-
normalizeMermaidTheme: () => normalizeMermaidTheme,
|
|
19994
|
-
modelOwner: () => modelOwner,
|
|
19995
|
-
mergeSupersedingUserTurn: () => mergeSupersedingUserTurn,
|
|
19996
|
-
mentionsAi: () => mentionsAi,
|
|
19997
|
-
materializePromptAttachments: () => materializePromptAttachments,
|
|
19998
|
-
isVisualsShowMermaidTool: () => isVisualsShowMermaidTool,
|
|
19999
|
-
isVisualsShowImageTool: () => isVisualsShowImageTool,
|
|
20000
|
-
isVisualsShowHtmlTool: () => isVisualsShowHtmlTool,
|
|
20001
|
-
isSessionExpiredError: () => isSessionExpiredError,
|
|
20002
|
-
isRuntimeTool: () => isRuntimeTool,
|
|
20003
|
-
isPathInside: () => isPathInside,
|
|
20004
|
-
isLikelyCurrentChannelTrigger: () => isLikelyCurrentChannelTrigger,
|
|
20005
|
-
ingestAttachment: () => ingestAttachment,
|
|
20006
|
-
formatSelectableModel: () => formatSelectableModel,
|
|
20007
|
-
formatChannelTranscriptLine: () => formatChannelTranscriptLine,
|
|
20008
|
-
escapeRegExp: () => escapeRegExp3,
|
|
20009
|
-
escapeHtml: () => escapeHtml2,
|
|
20010
|
-
deliverAskCallbackToCaller: () => deliverAskCallbackToCaller,
|
|
20011
|
-
composeAttachmentPrompt: () => composeAttachmentPrompt,
|
|
20012
|
-
classifyAgentError: () => classifyAgentError,
|
|
20013
|
-
channelTranscriptSpeaker: () => channelTranscriptSpeaker,
|
|
20014
|
-
canonicalModelId: () => canonicalModelId,
|
|
20015
|
-
buildVideoHtml: () => buildVideoHtml,
|
|
20016
|
-
buildTurnReminderQuery: () => buildTurnReminderQuery,
|
|
20017
|
-
buildMermaidHtml: () => buildMermaidHtml,
|
|
20018
|
-
buildMentionOnlyChannelPrompt: () => buildMentionOnlyChannelPrompt,
|
|
20019
|
-
buildImageHtml: () => buildImageHtml,
|
|
20020
|
-
authRecoveryHint: () => authRecoveryHint,
|
|
20021
|
-
attachmentPromptLine: () => attachmentPromptLine,
|
|
20022
|
-
activeVisualHtmlForPrompt: () => activeVisualHtmlForPrompt,
|
|
20023
|
-
SESSION_EXPIRED_MSG: () => SESSION_EXPIRED_MSG,
|
|
20024
|
-
SELECTABLE_MODELS: () => SELECTABLE_MODELS,
|
|
20025
|
-
MODEL_OWNER: () => MODEL_OWNER,
|
|
20026
|
-
MODEL_COST_ROUTING_SUMMARY: () => MODEL_COST_ROUTING_SUMMARY,
|
|
20027
|
-
MODEL_COST_RESEARCHED_AT: () => MODEL_COST_RESEARCHED_AT,
|
|
20028
|
-
FALLBACK_ORDER: () => FALLBACK_ORDER,
|
|
20029
|
-
AGENT_DISPLAY_NAME: () => AGENT_DISPLAY_NAME
|
|
20030
|
-
});
|
|
20031
|
-
import { randomUUID as randomUUID19 } from "crypto";
|
|
19205
|
+
import { randomUUID as randomUUID18 } from "crypto";
|
|
20032
19206
|
import { existsSync as existsSync22, mkdirSync as mkdirSync19, readdirSync as readdirSync5, statSync as statSync10 } from "fs";
|
|
20033
19207
|
import { join as join31 } from "path";
|
|
20034
19208
|
function withDefaultPlaywright(configuredMcp, isManager) {
|
|
@@ -20051,12 +19225,12 @@ function buildTurnReminderQuery(agent, prompt, reminders) {
|
|
|
20051
19225
|
|
|
20052
19226
|
${reminderPrompt}` };
|
|
20053
19227
|
}
|
|
20054
|
-
function appendSystemMessage(topicId,
|
|
19228
|
+
function appendSystemMessage(topicId, text, threadRootId) {
|
|
20055
19229
|
const message = {
|
|
20056
|
-
id:
|
|
19230
|
+
id: randomUUID18(),
|
|
20057
19231
|
topicId,
|
|
20058
19232
|
authorId: "system",
|
|
20059
|
-
text
|
|
19233
|
+
text,
|
|
20060
19234
|
...threadRootId ? { threadRootId } : {},
|
|
20061
19235
|
createdAt: new Date().toISOString()
|
|
20062
19236
|
};
|
|
@@ -20073,12 +19247,12 @@ function notifyPlaywrightUnavailable(topicId) {
|
|
|
20073
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.");
|
|
20074
19248
|
WsHub.get().broadcastTopicNotice(topicId, "info", "Playwright \uC0AC\uC6A9 \uBD88\uAC00");
|
|
20075
19249
|
}
|
|
20076
|
-
function appendAskReplyMessage(topicId,
|
|
19250
|
+
function appendAskReplyMessage(topicId, text, sourceLabel, body, kind, agentType, threadRootId) {
|
|
20077
19251
|
const message = {
|
|
20078
|
-
id:
|
|
19252
|
+
id: randomUUID18(),
|
|
20079
19253
|
topicId,
|
|
20080
19254
|
authorId: "ai",
|
|
20081
|
-
text
|
|
19255
|
+
text,
|
|
20082
19256
|
kind: "tell",
|
|
20083
19257
|
tellCard: {
|
|
20084
19258
|
fromLabel: sourceLabel,
|
|
@@ -20139,8 +19313,8 @@ function redispatchInject(inject) {
|
|
|
20139
19313
|
kind: "error",
|
|
20140
19314
|
error: "topic gone or AI no longer invited"
|
|
20141
19315
|
});
|
|
20142
|
-
} catch (
|
|
20143
|
-
logger.warn({ err
|
|
19316
|
+
} catch (err) {
|
|
19317
|
+
logger.warn({ err, topicId: inject.topicId }, "ai: deferred settlement hook failed");
|
|
20144
19318
|
}
|
|
20145
19319
|
if (inject.forkHandle)
|
|
20146
19320
|
cleanupAgentFork(inject.forkHandle);
|
|
@@ -20198,28 +19372,28 @@ async function clearPendingAskFile(pending, state) {
|
|
|
20198
19372
|
if (!pending.pendingAsk)
|
|
20199
19373
|
return;
|
|
20200
19374
|
try {
|
|
20201
|
-
|
|
19375
|
+
await init_session_asks();
|
|
20202
19376
|
if (state)
|
|
20203
|
-
|
|
20204
|
-
|
|
20205
|
-
} catch (
|
|
20206
|
-
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");
|
|
20207
19381
|
}
|
|
20208
19382
|
}
|
|
20209
19383
|
async function markPendingAskFile(pending, state) {
|
|
20210
19384
|
if (!pending.pendingAsk)
|
|
20211
19385
|
return;
|
|
20212
19386
|
try {
|
|
20213
|
-
|
|
20214
|
-
|
|
20215
|
-
} catch (
|
|
20216
|
-
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");
|
|
20217
19391
|
}
|
|
20218
19392
|
}
|
|
20219
19393
|
async function deliverAskCallbackToCaller(pending, sourceLabel, body, kind, options = {}) {
|
|
20220
19394
|
if (pending.remoteReply) {
|
|
20221
|
-
|
|
20222
|
-
const delivered = await
|
|
19395
|
+
await init_peer_forward();
|
|
19396
|
+
const delivered = await deliverPeerReply(pending.remoteReply, sourceLabel, body, kind);
|
|
20223
19397
|
if (delivered)
|
|
20224
19398
|
options.onRecorded?.();
|
|
20225
19399
|
return delivered;
|
|
@@ -20239,8 +19413,8 @@ ${body}`;
|
|
|
20239
19413
|
record(undefined);
|
|
20240
19414
|
await clearPendingAskFile(pending);
|
|
20241
19415
|
return true;
|
|
20242
|
-
} catch (
|
|
20243
|
-
logger.warn({ err
|
|
19416
|
+
} catch (err) {
|
|
19417
|
+
logger.warn({ err, requestId: pending.requestId, callerTopicId: pending.callerTopicId }, "sessions: ask callback direct delivery failed");
|
|
20244
19418
|
return false;
|
|
20245
19419
|
}
|
|
20246
19420
|
}
|
|
@@ -20269,9 +19443,9 @@ ${body}`;
|
|
|
20269
19443
|
if (queued) {
|
|
20270
19444
|
try {
|
|
20271
19445
|
record(callerTopic.agent);
|
|
20272
|
-
} catch (
|
|
19446
|
+
} catch (err) {
|
|
20273
19447
|
interSessionQueue.remove(pending.callerTopicId, pending.requestId);
|
|
20274
|
-
logger.warn({ err
|
|
19448
|
+
logger.warn({ err, requestId: pending.requestId, callerTopicId: pending.callerTopicId }, "sessions: ask callback record failed after enqueue; queue entry withdrawn");
|
|
20275
19449
|
return false;
|
|
20276
19450
|
}
|
|
20277
19451
|
await markPendingAskFile(pending, "queued_for_caller");
|
|
@@ -20291,8 +19465,8 @@ ${body}`;
|
|
|
20291
19465
|
}
|
|
20292
19466
|
async function deliverAskError(queryId, sourceLabel, error) {
|
|
20293
19467
|
try {
|
|
20294
|
-
|
|
20295
|
-
const pending =
|
|
19468
|
+
await init_ask_callbacks();
|
|
19469
|
+
const pending = resolveAskCallback(queryId);
|
|
20296
19470
|
if (pending) {
|
|
20297
19471
|
const prefix = pending.timedOut ? `\u26A0\uFE0F [Timeout - error notification was dropped]
|
|
20298
19472
|
|
|
@@ -20322,9 +19496,9 @@ function tryReconstructTopicRollout(opts) {
|
|
|
20322
19496
|
entries: entries.length
|
|
20323
19497
|
}, sessionId ? "ai: session expired \u2014 rollout reconstructed from unified log" : "ai: provider session bridged from shared conversation log");
|
|
20324
19498
|
return { kind: "rebuilt", sessionId: result.sessionId };
|
|
20325
|
-
} catch (
|
|
20326
|
-
logger.warn({ err
|
|
20327
|
-
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) };
|
|
20328
19502
|
}
|
|
20329
19503
|
}
|
|
20330
19504
|
function resolveSessionRetry(opts) {
|
|
@@ -20433,8 +19607,8 @@ function waitToStartRemoteUserTurn(params, queryId, options) {
|
|
|
20433
19607
|
function announceQueuedUserTurn(params, queryId) {
|
|
20434
19608
|
try {
|
|
20435
19609
|
params.onDispatched?.(queryId);
|
|
20436
|
-
} catch (
|
|
20437
|
-
logger.warn({ err
|
|
19610
|
+
} catch (err) {
|
|
19611
|
+
logger.warn({ err, topicId: params.topic.id, queryId }, "ai: queued dispatch hook failed");
|
|
20438
19612
|
}
|
|
20439
19613
|
if (!params.silent)
|
|
20440
19614
|
WsHub.get().broadcastAiActive(params.topic.id, queryId);
|
|
@@ -20455,81 +19629,6 @@ function waitToDrainRemoteInject(topicId) {
|
|
|
20455
19629
|
timer.unref?.();
|
|
20456
19630
|
remoteInjectWaiters.set(topicId, timer);
|
|
20457
19631
|
}
|
|
20458
|
-
async function drainOneDurableUserTurn() {
|
|
20459
|
-
if (durableTurnWorkerBusy)
|
|
20460
|
-
return;
|
|
20461
|
-
durableTurnWorkerBusy = true;
|
|
20462
|
-
try {
|
|
20463
|
-
const request = claimNextRuntimeUserTurnRequest(RUNTIME_INSTANCE_ID);
|
|
20464
|
-
if (!request)
|
|
20465
|
-
return;
|
|
20466
|
-
const topic = getTopic(request.topicId);
|
|
20467
|
-
if (!topic?.agent) {
|
|
20468
|
-
completeRuntimeUserTurnRequest(request.topicId, request.requestId, RUNTIME_INSTANCE_ID);
|
|
20469
|
-
return;
|
|
20470
|
-
}
|
|
20471
|
-
const execution = request.execution;
|
|
20472
|
-
const queryId = startAiTurn({
|
|
20473
|
-
topic,
|
|
20474
|
-
userId: request.userId,
|
|
20475
|
-
actorUserId: execution?.actorUserId,
|
|
20476
|
-
actorTopicScope: actorTopicScopeFrom(execution?.actorTopicScope),
|
|
20477
|
-
remoteSession: remoteSessionGrantFrom(execution?.remoteSession),
|
|
20478
|
-
vaultUserId: execution?.vaultUserId,
|
|
20479
|
-
prompt: request.prompt,
|
|
20480
|
-
_userMessages: request.userMessages,
|
|
20481
|
-
_conversationPrompts: execution?.conversationPrompts ?? [request.prompt],
|
|
20482
|
-
_loggedUserMessageCount: execution?.loggedUserMessageCount ?? Math.max(0, request.userMessages.length - (execution?.conversationPrompts?.length ?? 1)),
|
|
20483
|
-
_durableRequestIds: [request.requestId],
|
|
20484
|
-
attachments: request.attachments,
|
|
20485
|
-
allowAutoContinue: request.allowAutoContinue,
|
|
20486
|
-
origin: "user",
|
|
20487
|
-
requestId: execution?.sourceRequestId,
|
|
20488
|
-
agentOverride: execution?.agentOverride,
|
|
20489
|
-
modelOverride: execution?.modelOverride,
|
|
20490
|
-
effortOverride: execution?.effortOverride,
|
|
20491
|
-
...execution?.sessionIdSpecified ? { sessionId: execution.sessionId } : {},
|
|
20492
|
-
sessionScope: execution?.sessionScope,
|
|
20493
|
-
cwd: execution?.cwd,
|
|
20494
|
-
sessionName: execution?.sessionName,
|
|
20495
|
-
sessionType: execution?.sessionType,
|
|
20496
|
-
visualTools: execution?.visualTools,
|
|
20497
|
-
fileDeliveryTools: execution?.fileDeliveryTools,
|
|
20498
|
-
silent: execution?.silent,
|
|
20499
|
-
bridgeSessionFromHistory: execution?.bridgeSessionFromHistory,
|
|
20500
|
-
peerBridge: execution?.peerBridge,
|
|
20501
|
-
from: execution?.from,
|
|
20502
|
-
threadRootId: execution?.threadRootId,
|
|
20503
|
-
_queryId: request.requestId,
|
|
20504
|
-
_runtimeEpoch: execution?.runtimeEpoch ?? request.topicEpoch,
|
|
20505
|
-
onSettled: () => {
|
|
20506
|
-
completeRuntimeUserTurnRequest(request.topicId, request.requestId, RUNTIME_INSTANCE_ID);
|
|
20507
|
-
}
|
|
20508
|
-
});
|
|
20509
|
-
if (!queryId) {
|
|
20510
|
-
releaseRuntimeUserTurnClaim(request.topicId, request.requestId, RUNTIME_INSTANCE_ID);
|
|
20511
|
-
return;
|
|
20512
|
-
}
|
|
20513
|
-
markRuntimeUserTurnRunning(request.topicId, request.requestId, RUNTIME_INSTANCE_ID, queryId);
|
|
20514
|
-
} finally {
|
|
20515
|
-
durableTurnWorkerBusy = false;
|
|
20516
|
-
}
|
|
20517
|
-
}
|
|
20518
|
-
function startDurableTurnRequestWorker() {
|
|
20519
|
-
if (durableTurnWorker)
|
|
20520
|
-
return () => {};
|
|
20521
|
-
durableTurnWorker = setInterval(() => {
|
|
20522
|
-
drainOneDurableUserTurn();
|
|
20523
|
-
}, 100);
|
|
20524
|
-
durableTurnWorker.unref?.();
|
|
20525
|
-
drainOneDurableUserTurn();
|
|
20526
|
-
return () => {
|
|
20527
|
-
if (!durableTurnWorker)
|
|
20528
|
-
return;
|
|
20529
|
-
clearInterval(durableTurnWorker);
|
|
20530
|
-
durableTurnWorker = null;
|
|
20531
|
-
};
|
|
20532
|
-
}
|
|
20533
19632
|
function startAiTurn(params) {
|
|
20534
19633
|
const storedTopic = getTopic(params.topic.id);
|
|
20535
19634
|
if (!storedTopic || !storedTopic.agent && !params.agentOverride) {
|
|
@@ -20541,8 +19640,8 @@ function startAiTurn(params) {
|
|
|
20541
19640
|
kind: "error",
|
|
20542
19641
|
error: storedTopic ? "topic no longer has an AI agent" : "topic no longer exists"
|
|
20543
19642
|
});
|
|
20544
|
-
} catch (
|
|
20545
|
-
logger.warn({ err
|
|
19643
|
+
} catch (err) {
|
|
19644
|
+
logger.warn({ err, topicId: params.topic.id }, "ai: rejected-turn settlement hook failed");
|
|
20546
19645
|
}
|
|
20547
19646
|
return null;
|
|
20548
19647
|
}
|
|
@@ -20598,7 +19697,7 @@ function startAiTurn(params) {
|
|
|
20598
19697
|
const askReplySources = params.askReplySources;
|
|
20599
19698
|
const sessionRetried = params._sessionRetried === true;
|
|
20600
19699
|
const emptyResponseRetried = params._emptyResponseRetried === true;
|
|
20601
|
-
const queryId = asTurnId(params._queryId ??
|
|
19700
|
+
const queryId = asTurnId(params._queryId ?? randomUUID18());
|
|
20602
19701
|
const roomId = turnConcurrency === "isolated" ? isolatedTurnRoomId(topicId, queryId) : asTurnSlotKey(topicId);
|
|
20603
19702
|
const currentRuntimeEpoch = getRuntimeTopicEpoch(topic.id);
|
|
20604
19703
|
const runtimeEpoch = params._runtimeEpoch ?? currentRuntimeEpoch;
|
|
@@ -20610,8 +19709,8 @@ function startAiTurn(params) {
|
|
|
20610
19709
|
}
|
|
20611
19710
|
try {
|
|
20612
19711
|
params.onSettled?.({ queryId, kind: "aborted", abortReason: "external" /* External */ });
|
|
20613
|
-
} catch (
|
|
20614
|
-
logger.warn({ err
|
|
19712
|
+
} catch (err) {
|
|
19713
|
+
logger.warn({ err, topicId: topic.id, queryId }, "ai: stale-turn settlement hook failed");
|
|
20615
19714
|
}
|
|
20616
19715
|
logger.info({ topicId: topic.id, queryId, queuedEpoch: params._runtimeEpoch, currentRuntimeEpoch }, "ai: dropped work queued before topic reset");
|
|
20617
19716
|
return null;
|
|
@@ -20661,8 +19760,8 @@ function startAiTurn(params) {
|
|
|
20661
19760
|
cleanupAgentFork(forkHandle);
|
|
20662
19761
|
try {
|
|
20663
19762
|
onSettled?.({ queryId: "", kind: "error", error });
|
|
20664
|
-
} catch (
|
|
20665
|
-
logger.warn({ err
|
|
19763
|
+
} catch (err) {
|
|
19764
|
+
logger.warn({ err, topicId, queryId }, "ai: isolated-turn rejection hook failed");
|
|
20666
19765
|
}
|
|
20667
19766
|
return null;
|
|
20668
19767
|
};
|
|
@@ -20709,7 +19808,7 @@ function startAiTurn(params) {
|
|
|
20709
19808
|
if (decision.action === "abort-replace") {
|
|
20710
19809
|
const running = decision.running;
|
|
20711
19810
|
if (isUserOrigin(running.origin) && !sameTurnActor(running.actorUserId, params.actorUserId)) {
|
|
20712
|
-
const
|
|
19811
|
+
const queuedQueryId = waitToStartRemoteUserTurn({
|
|
20713
19812
|
...params,
|
|
20714
19813
|
topic,
|
|
20715
19814
|
prompt,
|
|
@@ -20721,9 +19820,9 @@ function startAiTurn(params) {
|
|
|
20721
19820
|
_durableRequestIds: durableRequestIds,
|
|
20722
19821
|
_runtimeEpoch: runtimeEpoch
|
|
20723
19822
|
}, queryId);
|
|
20724
|
-
announceQueuedUserTurn({ ...params, topic },
|
|
20725
|
-
logger.info({ topicId, queryId:
|
|
20726
|
-
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;
|
|
20727
19826
|
}
|
|
20728
19827
|
let omitRequestIds;
|
|
20729
19828
|
if (isUserOrigin(running.origin)) {
|
|
@@ -20855,14 +19954,14 @@ function startAiTurn(params) {
|
|
|
20855
19954
|
if (turnConcurrency === "topic") {
|
|
20856
19955
|
try {
|
|
20857
19956
|
writeQueryState(userId, topic.id, topic.title, prompt);
|
|
20858
|
-
} catch (
|
|
20859
|
-
logger.warn({ err
|
|
19957
|
+
} catch (err) {
|
|
19958
|
+
logger.warn({ err, topicId, userId }, "ai: failed to write active query state");
|
|
20860
19959
|
}
|
|
20861
19960
|
}
|
|
20862
19961
|
try {
|
|
20863
19962
|
onDispatched?.(queryId);
|
|
20864
|
-
} catch (
|
|
20865
|
-
logger.warn({ err
|
|
19963
|
+
} catch (err) {
|
|
19964
|
+
logger.warn({ err, topicId, queryId }, "ai: dispatch hook failed");
|
|
20866
19965
|
}
|
|
20867
19966
|
const override = getTopicConfig(topicId);
|
|
20868
19967
|
const agentKind = execution.agent;
|
|
@@ -20889,8 +19988,8 @@ function startAiTurn(params) {
|
|
|
20889
19988
|
control.injectParams.sessionId = bridge.sessionId;
|
|
20890
19989
|
try {
|
|
20891
19990
|
onSessionId?.(bridge.sessionId);
|
|
20892
|
-
} catch (
|
|
20893
|
-
logger.warn({ err
|
|
19991
|
+
} catch (err) {
|
|
19992
|
+
logger.warn({ err, topicId, queryId, agent: agentKind }, "ai: isolated session owner rejected bridged provider session id");
|
|
20894
19993
|
}
|
|
20895
19994
|
} else if (bridge.kind === "failed") {
|
|
20896
19995
|
historyBridgeError = "Conversation history could not be encoded into a provider session; no fresh session was started.";
|
|
@@ -20959,8 +20058,8 @@ function startAiTurn(params) {
|
|
|
20959
20058
|
const wikiDir = getSharedWikiDir();
|
|
20960
20059
|
const { latestSummaryFile } = resolveWikiMemoryMirror(wikiDir, memoryTopic.id, memoryTitle);
|
|
20961
20060
|
hasMemoryArchive = Boolean(resolvedBrief?.brief.latestSummaryMd || latestSummaryFile);
|
|
20962
|
-
} catch (
|
|
20963
|
-
logger.warn({ topicId, err
|
|
20061
|
+
} catch (err) {
|
|
20062
|
+
logger.warn({ topicId, err }, "ai: failed to inject topic brief");
|
|
20964
20063
|
}
|
|
20965
20064
|
systemPrompt += buildMemoryPromptSection({
|
|
20966
20065
|
topicTitle: topic.title,
|
|
@@ -21036,8 +20135,8 @@ function startAiTurn(params) {
|
|
|
21036
20135
|
control.injectParams.sessionId = prepared.forkId;
|
|
21037
20136
|
control.injectParams.forkHandle = prepared;
|
|
21038
20137
|
}
|
|
21039
|
-
} catch (
|
|
21040
|
-
throw new Error(`failed to prepare isolated session: ${stringifyError(
|
|
20138
|
+
} catch (err) {
|
|
20139
|
+
throw new Error(`failed to prepare isolated session: ${stringifyError(err)}`);
|
|
21041
20140
|
}
|
|
21042
20141
|
if (abortController.signal.aborted)
|
|
21043
20142
|
return;
|
|
@@ -21056,8 +20155,8 @@ function startAiTurn(params) {
|
|
|
21056
20155
|
throw new Error("browser MCP capability was not registered");
|
|
21057
20156
|
}
|
|
21058
20157
|
trackPlaywrightTurn(playwrightInstanceKey, control);
|
|
21059
|
-
} catch (
|
|
21060
|
-
logger.warn({ topicId, err
|
|
20158
|
+
} catch (err) {
|
|
20159
|
+
logger.warn({ topicId, err }, "ai: ensurePlaywright failed \u2014 proceeding without browser tools");
|
|
21061
20160
|
markPlaywrightUnavailable({
|
|
21062
20161
|
userId,
|
|
21063
20162
|
topic: topic.title,
|
|
@@ -21070,8 +20169,8 @@ function startAiTurn(params) {
|
|
|
21070
20169
|
if (wantsBgBash) {
|
|
21071
20170
|
try {
|
|
21072
20171
|
bgBashPort = await ensureBgBash(userId, topic.id);
|
|
21073
|
-
} catch (
|
|
21074
|
-
logger.warn({ topicId, err
|
|
20172
|
+
} catch (err) {
|
|
20173
|
+
logger.warn({ topicId, err }, "ai: ensureBgBash failed \u2014 proceeding without background bash tools");
|
|
21075
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>");
|
|
21076
20175
|
}
|
|
21077
20176
|
}
|
|
@@ -21284,8 +20383,8 @@ function startAiTurn(params) {
|
|
|
21284
20383
|
await settleSubagentFailure(queryId, error);
|
|
21285
20384
|
try {
|
|
21286
20385
|
onSettled?.({ queryId, kind: "error", error });
|
|
21287
|
-
} catch (
|
|
21288
|
-
logger.warn({ err
|
|
20386
|
+
} catch (err) {
|
|
20387
|
+
logger.warn({ err, topicId, queryId }, "ai: turn settlement hook failed");
|
|
21289
20388
|
}
|
|
21290
20389
|
return;
|
|
21291
20390
|
}
|
|
@@ -21301,8 +20400,8 @@ function startAiTurn(params) {
|
|
|
21301
20400
|
await settleSubagentFailure(queryId, classifyAgentError(outcome.error, agentKind));
|
|
21302
20401
|
try {
|
|
21303
20402
|
onSettled?.({ queryId, kind: "error", error: outcome.error });
|
|
21304
|
-
} catch (
|
|
21305
|
-
logger.warn({ err
|
|
20403
|
+
} catch (err) {
|
|
20404
|
+
logger.warn({ err, topicId, queryId }, "ai: turn settlement hook failed");
|
|
21306
20405
|
}
|
|
21307
20406
|
return;
|
|
21308
20407
|
}
|
|
@@ -21315,12 +20414,12 @@ function startAiTurn(params) {
|
|
|
21315
20414
|
kind: outcome.kind === "aborted" ? "aborted" : "completed",
|
|
21316
20415
|
...outcome.kind === "aborted" ? { abortReason: control.abortReason } : {}
|
|
21317
20416
|
});
|
|
21318
|
-
} catch (
|
|
21319
|
-
logger.warn({ err
|
|
20417
|
+
} catch (err) {
|
|
20418
|
+
logger.warn({ err, topicId, queryId }, "ai: turn settlement hook failed");
|
|
21320
20419
|
}
|
|
21321
|
-
}).catch(async (
|
|
21322
|
-
const error =
|
|
21323
|
-
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");
|
|
21324
20423
|
if (!silent) {
|
|
21325
20424
|
WsHub.get().broadcastError(topicId, queryId, error);
|
|
21326
20425
|
WsHub.get().broadcastTopicNotice(topicId, "error", "\uC751\uB2F5 \uC2E4\uD328");
|
|
@@ -21369,7 +20468,7 @@ function triggerTopicAiTurn(topicId, userId, prompt, agentType, opts) {
|
|
|
21369
20468
|
if (!opts?.silent && !opts?.hideInjectMessage) {
|
|
21370
20469
|
const now = new Date().toISOString();
|
|
21371
20470
|
const injectMsg = {
|
|
21372
|
-
id: opts?.requestId ? `tell-${opts.requestId}` : `tell-${
|
|
20471
|
+
id: opts?.requestId ? `tell-${opts.requestId}` : `tell-${randomUUID18()}`,
|
|
21373
20472
|
topicId,
|
|
21374
20473
|
authorId: opts?.injectAuthorId ?? userId,
|
|
21375
20474
|
sourceAdapter: opts?.injectSourceAdapter,
|
|
@@ -21426,7 +20525,7 @@ function triggerTopicAiTurn(topicId, userId, prompt, agentType, opts) {
|
|
|
21426
20525
|
from: opts?.from
|
|
21427
20526
|
});
|
|
21428
20527
|
}
|
|
21429
|
-
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;
|
|
21430
20529
|
var init_turn_runner = __esm(async () => {
|
|
21431
20530
|
init_manager();
|
|
21432
20531
|
init_constants();
|
|
@@ -21557,29 +20656,29 @@ function createSubagentLifecycle(host) {
|
|
|
21557
20656
|
}
|
|
21558
20657
|
function computeSubagentDepth(topicId) {
|
|
21559
20658
|
let depth = 0;
|
|
21560
|
-
let
|
|
20659
|
+
let current = host.storage.getTopic(topicId);
|
|
21561
20660
|
const visited = new Set;
|
|
21562
|
-
while (
|
|
21563
|
-
if (visited.has(
|
|
20661
|
+
while (current) {
|
|
20662
|
+
if (visited.has(current.id))
|
|
21564
20663
|
return limits.maxDepth;
|
|
21565
|
-
visited.add(
|
|
21566
|
-
if (
|
|
20664
|
+
visited.add(current.id);
|
|
20665
|
+
if (current.isSubagent)
|
|
21567
20666
|
depth += 1;
|
|
21568
|
-
if (!
|
|
20667
|
+
if (!current.parentTopicId || current.parentTopicId === current.id)
|
|
21569
20668
|
break;
|
|
21570
|
-
|
|
20669
|
+
current = host.storage.getTopic(current.parentTopicId);
|
|
21571
20670
|
}
|
|
21572
20671
|
return depth;
|
|
21573
20672
|
}
|
|
21574
|
-
function
|
|
20673
|
+
function canSpawnSubagentsFromTopic(topicId) {
|
|
21575
20674
|
const topic = host.storage.getTopic(topicId);
|
|
21576
20675
|
return topic?.kind === "agent" && computeSubagentDepth(topicId) < limits.maxDepth;
|
|
21577
20676
|
}
|
|
21578
20677
|
function patchSubagentCard(parentTopicId, cardMessageId, patch) {
|
|
21579
|
-
const
|
|
21580
|
-
if (!
|
|
20678
|
+
const current = host.storage.getMessage(parentTopicId, cardMessageId)?.subagentCard;
|
|
20679
|
+
if (!current)
|
|
21581
20680
|
return;
|
|
21582
|
-
const next = { ...
|
|
20681
|
+
const next = { ...current, ...patch };
|
|
21583
20682
|
const editedAt = host.runtime.now();
|
|
21584
20683
|
if (!host.storage.updateSubagentCard(parentTopicId, cardMessageId, next, editedAt))
|
|
21585
20684
|
return;
|
|
@@ -21599,7 +20698,7 @@ function createSubagentLifecycle(host) {
|
|
|
21599
20698
|
patchSubagentCard(watch.parentTopicId, watch.cardMessageId, { status: "running" });
|
|
21600
20699
|
}
|
|
21601
20700
|
}
|
|
21602
|
-
function
|
|
20701
|
+
function takeSubagentWatch(queryId) {
|
|
21603
20702
|
const childTopicId = childByQueryId.get(queryId);
|
|
21604
20703
|
if (!childTopicId)
|
|
21605
20704
|
return recoverPersistedSubagentWatch(queryId);
|
|
@@ -21643,7 +20742,7 @@ function createSubagentLifecycle(host) {
|
|
|
21643
20742
|
if (watch.queryId)
|
|
21644
20743
|
childByQueryId.delete(watch.queryId);
|
|
21645
20744
|
}
|
|
21646
|
-
function
|
|
20745
|
+
function cancelSubagentWatchForDeletedTopic(childTopicId) {
|
|
21647
20746
|
const watch = watchesByChild.get(childTopicId);
|
|
21648
20747
|
if (!watch)
|
|
21649
20748
|
return;
|
|
@@ -21673,8 +20772,8 @@ function createSubagentLifecycle(host) {
|
|
|
21673
20772
|
if (!await host.sessionCommunication.notifyParent({ watch, prompt, requestId })) {
|
|
21674
20773
|
appendParentSystemNote(watch, prompt);
|
|
21675
20774
|
}
|
|
21676
|
-
} catch (
|
|
21677
|
-
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");
|
|
21678
20777
|
try {
|
|
21679
20778
|
appendParentSystemNote(watch, prompt);
|
|
21680
20779
|
} catch (fallbackErr) {
|
|
@@ -21686,7 +20785,7 @@ function createSubagentLifecycle(host) {
|
|
|
21686
20785
|
}
|
|
21687
20786
|
}
|
|
21688
20787
|
}
|
|
21689
|
-
async function
|
|
20788
|
+
async function settleSubagentSuccess(watch, finalText) {
|
|
21690
20789
|
const summary = finalText.replace(/\s+/g, " ").trim().slice(0, RESULT_SUMMARY_CHARS);
|
|
21691
20790
|
try {
|
|
21692
20791
|
patchSubagentCard(watch.parentTopicId, watch.cardMessageId, {
|
|
@@ -21694,8 +20793,8 @@ function createSubagentLifecycle(host) {
|
|
|
21694
20793
|
resultSummary: summary || "(no text response)",
|
|
21695
20794
|
finishedAt: host.runtime.now()
|
|
21696
20795
|
});
|
|
21697
|
-
} catch (
|
|
21698
|
-
logger.warn({ err
|
|
20796
|
+
} catch (err) {
|
|
20797
|
+
logger.warn({ err, parentTopicId: watch.parentTopicId, cardMessageId: watch.cardMessageId }, "subagent: completed-card update failed");
|
|
21699
20798
|
}
|
|
21700
20799
|
if (watch.reportMode === "auto") {
|
|
21701
20800
|
await notifyParent(watch, `[Subagent completed \u2190 ${watch.name}]
|
|
@@ -21704,8 +20803,8 @@ function createSubagentLifecycle(host) {
|
|
|
21704
20803
|
${finalText || "(no text response)"}`, "done");
|
|
21705
20804
|
}
|
|
21706
20805
|
}
|
|
21707
|
-
async function
|
|
21708
|
-
const watch =
|
|
20806
|
+
async function settleSubagentFailure(queryId, reason) {
|
|
20807
|
+
const watch = takeSubagentWatch(queryId);
|
|
21709
20808
|
if (!watch)
|
|
21710
20809
|
return;
|
|
21711
20810
|
try {
|
|
@@ -21714,8 +20813,8 @@ ${finalText || "(no text response)"}`, "done");
|
|
|
21714
20813
|
errorMessage: reason,
|
|
21715
20814
|
finishedAt: host.runtime.now()
|
|
21716
20815
|
});
|
|
21717
|
-
} catch (
|
|
21718
|
-
logger.warn({ err
|
|
20816
|
+
} catch (err) {
|
|
20817
|
+
logger.warn({ err, parentTopicId: watch.parentTopicId, cardMessageId: watch.cardMessageId }, "subagent: failed-card update failed");
|
|
21719
20818
|
}
|
|
21720
20819
|
if (watch.reportMode === "auto") {
|
|
21721
20820
|
await notifyParent(watch, `[Subagent failed \u2190 ${watch.name}]
|
|
@@ -21752,7 +20851,7 @@ spawn_subagent\uB85C \uC704\uC784\uD55C \uC791\uC5C5\uC774 \uC2E4\uD328\uD588\uC
|
|
|
21752
20851
|
function findSubagentCardMessage(childTopicId) {
|
|
21753
20852
|
return host.storage.listSubagentMessages().filter((message) => message.subagentCard?.subagentTopicId === childTopicId).at(-1);
|
|
21754
20853
|
}
|
|
21755
|
-
function
|
|
20854
|
+
function subagentReportMode(childTopicId) {
|
|
21756
20855
|
return host.storage.getTopic(childTopicId)?.subagentReportMode ?? findSubagentCardMessage(childTopicId)?.subagentCard?.reportMode ?? "auto";
|
|
21757
20856
|
}
|
|
21758
20857
|
async function startSubagentCard(ctx, cardMessage) {
|
|
@@ -21960,7 +21059,7 @@ ${card.task}${reportInstruction}`;
|
|
|
21960
21059
|
for (const siblings of byParent.values()) {
|
|
21961
21060
|
siblings.sort((a, b) => a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id));
|
|
21962
21061
|
}
|
|
21963
|
-
const
|
|
21062
|
+
const descendants = [];
|
|
21964
21063
|
const visited = new Set([ctx.topicId]);
|
|
21965
21064
|
const visit = (parentId) => {
|
|
21966
21065
|
for (const child of byParent.get(parentId) ?? []) {
|
|
@@ -21970,12 +21069,12 @@ ${card.task}${reportInstruction}`;
|
|
|
21970
21069
|
if (!child.participants.some((participant) => participant.userId === rootOwnerId && participant.role === "owner")) {
|
|
21971
21070
|
continue;
|
|
21972
21071
|
}
|
|
21973
|
-
|
|
21072
|
+
descendants.push(child);
|
|
21974
21073
|
visit(child.id);
|
|
21975
21074
|
}
|
|
21976
21075
|
};
|
|
21977
21076
|
visit(ctx.topicId);
|
|
21978
|
-
return
|
|
21077
|
+
return descendants;
|
|
21979
21078
|
})() : [];
|
|
21980
21079
|
const children = actorScope ? descendants.filter((child) => actorScope.visible.has(child.id)) : descendants;
|
|
21981
21080
|
return {
|
|
@@ -21999,10 +21098,10 @@ ${card.task}${reportInstruction}`;
|
|
|
21999
21098
|
return card?.status ?? "unknown";
|
|
22000
21099
|
}
|
|
22001
21100
|
function listMemoryTopicNames(ctx) {
|
|
22002
|
-
const
|
|
22003
|
-
if (!
|
|
21101
|
+
const current = host.storage.getTopic(ctx.topicId);
|
|
21102
|
+
if (!current)
|
|
22004
21103
|
return { error: `Error: topic '${ctx.topicId}' not found.` };
|
|
22005
|
-
if (!
|
|
21104
|
+
if (!current.participants.some((participant) => participant.userId === ctx.userId)) {
|
|
22006
21105
|
return { error: "Error: user is not a member of this topic." };
|
|
22007
21106
|
}
|
|
22008
21107
|
const sources = new Map;
|
|
@@ -22092,8 +21191,8 @@ ${card.task}${reportInstruction}`;
|
|
|
22092
21191
|
try {
|
|
22093
21192
|
await host.topic.delete(child, ctx.userId);
|
|
22094
21193
|
return textResult(`Subagent deleted: ${child.title} (${child.id})`);
|
|
22095
|
-
} catch (
|
|
22096
|
-
const message =
|
|
21194
|
+
} catch (err) {
|
|
21195
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
22097
21196
|
return errorResult(`Error: failed to delete subagent '${child.title}': ${message}`);
|
|
22098
21197
|
}
|
|
22099
21198
|
}
|
|
@@ -22190,13 +21289,13 @@ ${card.task}${reportInstruction}`;
|
|
|
22190
21289
|
}
|
|
22191
21290
|
return {
|
|
22192
21291
|
computeSubagentDepth,
|
|
22193
|
-
canSpawnSubagentsFromTopic
|
|
22194
|
-
takeSubagentWatch
|
|
22195
|
-
cancelSubagentWatchForDeletedTopic
|
|
22196
|
-
settleSubagentSuccess
|
|
22197
|
-
settleSubagentFailure
|
|
21292
|
+
canSpawnSubagentsFromTopic,
|
|
21293
|
+
takeSubagentWatch,
|
|
21294
|
+
cancelSubagentWatchForDeletedTopic,
|
|
21295
|
+
settleSubagentSuccess,
|
|
21296
|
+
settleSubagentFailure,
|
|
22198
21297
|
sweepStaleSubagentCards,
|
|
22199
|
-
subagentReportMode
|
|
21298
|
+
subagentReportMode,
|
|
22200
21299
|
createSubagentManagementToolDefinitions,
|
|
22201
21300
|
createSpawnSubagentToolDefinition,
|
|
22202
21301
|
createPrepareSubagentToolDefinition
|
|
@@ -22243,9 +21342,9 @@ var init_spawn_subagent = __esm(async () => {
|
|
|
22243
21342
|
},
|
|
22244
21343
|
topic: {
|
|
22245
21344
|
async createDerived(input) {
|
|
22246
|
-
|
|
21345
|
+
await init_derive();
|
|
22247
21346
|
try {
|
|
22248
|
-
const topic = await
|
|
21347
|
+
const topic = await createDerivedTopic(input.parentTopicId, input.userId, false, {
|
|
22249
21348
|
name: input.name,
|
|
22250
21349
|
subagent: {
|
|
22251
21350
|
agent: input.agent,
|
|
@@ -22255,30 +21354,30 @@ var init_spawn_subagent = __esm(async () => {
|
|
|
22255
21354
|
});
|
|
22256
21355
|
return { ok: true, topic };
|
|
22257
21356
|
} catch (error) {
|
|
22258
|
-
if (error instanceof
|
|
21357
|
+
if (error instanceof TopicTitleConflictError) {
|
|
22259
21358
|
return { ok: false, reason: "title-conflict", message: error.message };
|
|
22260
21359
|
}
|
|
22261
|
-
if (error instanceof
|
|
21360
|
+
if (error instanceof TopicDeriveBusyError)
|
|
22262
21361
|
return { ok: false, reason: "busy" };
|
|
22263
21362
|
throw error;
|
|
22264
21363
|
}
|
|
22265
21364
|
},
|
|
22266
21365
|
async delete(topic, userId) {
|
|
22267
|
-
|
|
22268
|
-
await
|
|
21366
|
+
await init_lifecycle();
|
|
21367
|
+
await deleteTopicCascade(topic, userId);
|
|
22269
21368
|
}
|
|
22270
21369
|
},
|
|
22271
21370
|
task: {
|
|
22272
21371
|
async dispatch(input) {
|
|
22273
|
-
|
|
22274
|
-
|
|
22275
|
-
const queryId =
|
|
21372
|
+
await init_turn_runner();
|
|
21373
|
+
await init_active_rooms();
|
|
21374
|
+
const queryId = triggerTopicAiTurn(input.child.id, input.userId, input.prompt, undefined, {
|
|
22276
21375
|
origin: `subagent-task:${input.parent.title}`,
|
|
22277
21376
|
requestId: input.requestId,
|
|
22278
21377
|
injectAuthorId: "ai",
|
|
22279
21378
|
onDispatched: input.onDispatched
|
|
22280
21379
|
});
|
|
22281
|
-
return { accepted: Boolean(queryId ||
|
|
21380
|
+
return { accepted: Boolean(queryId || getRoomQuery(input.child.id)) };
|
|
22282
21381
|
}
|
|
22283
21382
|
},
|
|
22284
21383
|
sessionCommunication: {
|
|
@@ -22286,16 +21385,16 @@ var init_spawn_subagent = __esm(async () => {
|
|
|
22286
21385
|
const parent = getTopic(watch.parentTopicId);
|
|
22287
21386
|
if (!parent)
|
|
22288
21387
|
return true;
|
|
22289
|
-
|
|
22290
|
-
const queryId = parent.agent ?
|
|
21388
|
+
await init_turn_runner();
|
|
21389
|
+
const queryId = parent.agent ? triggerTopicAiTurn(watch.parentTopicId, watch.userId, prompt, undefined, {
|
|
22291
21390
|
origin: `subagent:${watch.name}`,
|
|
22292
21391
|
requestId,
|
|
22293
21392
|
hideInjectMessage: true
|
|
22294
21393
|
}) : null;
|
|
22295
21394
|
if (queryId)
|
|
22296
21395
|
return true;
|
|
22297
|
-
|
|
22298
|
-
return Boolean(parent.agent &&
|
|
21396
|
+
await init_active_rooms();
|
|
21397
|
+
return Boolean(parent.agent && interSessionQueue.hasRequest(parent.id, requestId));
|
|
22299
21398
|
},
|
|
22300
21399
|
listTellTargetIds: listSubagentTellTargetIds,
|
|
22301
21400
|
grantTellTarget: grantSubagentTellTarget,
|
|
@@ -22324,19 +21423,19 @@ var init_spawn_subagent = __esm(async () => {
|
|
|
22324
21423
|
async resolveAgentModel({ context, agent, model, hasOverride }) {
|
|
22325
21424
|
let resolvedModel = model;
|
|
22326
21425
|
if (model) {
|
|
22327
|
-
|
|
22328
|
-
|
|
22329
|
-
const registry =
|
|
21426
|
+
await Promise.resolve().then(() => init_model_catalog());
|
|
21427
|
+
await init_registry();
|
|
21428
|
+
const registry = getRegistry(agent);
|
|
22330
21429
|
if (!registry.validateModel(model)) {
|
|
22331
21430
|
return { error: `Error: model '${model}' is not valid for agent '${agent}'.` };
|
|
22332
21431
|
}
|
|
22333
|
-
resolvedModel =
|
|
21432
|
+
resolvedModel = resolveModelForAgent(agent, model, registry);
|
|
22334
21433
|
}
|
|
22335
21434
|
if (hasOverride) {
|
|
22336
|
-
|
|
22337
|
-
|
|
22338
|
-
const targetModel = resolvedModel ??
|
|
22339
|
-
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);
|
|
22340
21439
|
if (!auth.ok) {
|
|
22341
21440
|
return { error: `Error: agent '${agent}' is not available: ${auth.error}` };
|
|
22342
21441
|
}
|
|
@@ -22766,11 +21865,11 @@ var DEFAULT_SELF_CONFIG_PRODUCT = {
|
|
|
22766
21865
|
derivedTopicLimit: SELF_CONFIG_DERIVED_TOPIC_LIMIT,
|
|
22767
21866
|
toolDescriptions: {}
|
|
22768
21867
|
};
|
|
22769
|
-
function ok(
|
|
22770
|
-
return { text
|
|
21868
|
+
function ok(text) {
|
|
21869
|
+
return { text };
|
|
22771
21870
|
}
|
|
22772
|
-
function err(
|
|
22773
|
-
return { text
|
|
21871
|
+
function err(text) {
|
|
21872
|
+
return { text, isError: true };
|
|
22774
21873
|
}
|
|
22775
21874
|
function errorMessage(error) {
|
|
22776
21875
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -23087,8 +22186,8 @@ var defaultSelfConfigHost = {
|
|
|
23087
22186
|
},
|
|
23088
22187
|
derivedTopics: {
|
|
23089
22188
|
async create(sourceTopicId, userId, copyHistory, options) {
|
|
23090
|
-
|
|
23091
|
-
return
|
|
22189
|
+
await init_derive();
|
|
22190
|
+
return createDerivedTopic(sourceTopicId, userId, copyHistory, options);
|
|
23092
22191
|
},
|
|
23093
22192
|
link: topicMarkdownLink,
|
|
23094
22193
|
isTitleConflict: (error) => error instanceof Error && error.name === "TopicTitleConflictError",
|
|
@@ -23368,58 +22467,58 @@ await __promiseAll([
|
|
|
23368
22467
|
init_topic_cleanup()
|
|
23369
22468
|
]);
|
|
23370
22469
|
export {
|
|
23371
|
-
|
|
23372
|
-
withCodexSpawnSerial,
|
|
23373
|
-
visualToolDefinitions,
|
|
23374
|
-
unregisterOwnedCodexPids,
|
|
23375
|
-
summarizeToolInput,
|
|
23376
|
-
summarizeShellCommand,
|
|
23377
|
-
summarizeDisplayText,
|
|
23378
|
-
snapshotCodexChildren,
|
|
23379
|
-
showPngTool,
|
|
23380
|
-
showMermaidTool,
|
|
23381
|
-
showImageTool,
|
|
23382
|
-
showHtmlTool,
|
|
23383
|
-
rotateTopicLogs,
|
|
23384
|
-
resolveTaskEventScope,
|
|
23385
|
-
registerOwnedCodexPids,
|
|
23386
|
-
purgeTopicLogs,
|
|
23387
|
-
otiumVisualToolDefinitions,
|
|
23388
|
-
normalizeAskUserQuestionInput,
|
|
23389
|
-
normalizeAskUserChoices,
|
|
23390
|
-
killOwnedCodexTreesForShutdown,
|
|
23391
|
-
killCodexTrees,
|
|
23392
|
-
isExplicitAgentSwitchTargets,
|
|
23393
|
-
hasExplicitAgentSwitchRequest,
|
|
23394
|
-
formatToolUse,
|
|
23395
|
-
forkAgentSession,
|
|
23396
|
-
findNewCodexChildren,
|
|
23397
|
-
explicitAgentSwitchTargets,
|
|
23398
|
-
defaultAskUserDurabilityHost,
|
|
23399
|
-
createTopicLogMaintenance,
|
|
23400
|
-
createSubagentLifecycle,
|
|
23401
|
-
createSelfConfigToolDefinitionsForCore,
|
|
23402
|
-
createSelfConfigRuntime,
|
|
23403
|
-
createSelfConfigCore,
|
|
23404
|
-
createPublishHtmlToolDefinitions,
|
|
23405
|
-
createCodexTreeManager,
|
|
23406
|
-
createAskUserRuntime,
|
|
23407
|
-
createArchiverRuntime,
|
|
23408
|
-
createAgentForkHelpers,
|
|
23409
|
-
cleanupTopicRolloutsFromEntries,
|
|
23410
|
-
cleanupTopicRollouts,
|
|
23411
|
-
cleanupAgentFork,
|
|
23412
|
-
classifyShellToolName,
|
|
23413
|
-
checkAgentModelAuth,
|
|
23414
|
-
checkAgentAuth,
|
|
23415
|
-
buildNumberedDiffSummary,
|
|
23416
|
-
archiveActiveTopicForMemory,
|
|
23417
|
-
applySelfConfigCapabilityFilter,
|
|
23418
|
-
acquireCodexSpawnLock,
|
|
23419
|
-
VISUALS_MCP_KEY,
|
|
23420
|
-
SELF_CONFIG_CAPABILITIES,
|
|
22470
|
+
DEFAULT_SELF_CONFIG_PRODUCT,
|
|
23421
22471
|
MIN_MEMORY_ARCHIVE_EXCHANGES,
|
|
23422
|
-
|
|
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
|
|
23423
22522
|
};
|
|
23424
22523
|
|
|
23425
|
-
//# debugId=
|
|
22524
|
+
//# debugId=821FEE68439440EC64756E2164756E21
|