negotium 0.22.6 → 0.22.8
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 +1369 -413
- package/dist/agent-helpers.js.map +8 -8
- package/dist/background-bash.js +12 -12
- package/dist/background-bash.js.map +2 -2
- package/dist/browser-runtime.js +81 -52
- package/dist/browser-runtime.js.map +4 -4
- package/dist/canonical-mcp-bridge.js +9 -8
- package/dist/canonical-mcp-bridge.js.map +1 -1
- package/dist/chunk-2mx7fq49.js +6 -0
- package/dist/{chunk-bnyvxss3.js.map → chunk-2mx7fq49.js.map} +1 -1
- package/dist/{chunk-e59kzyvy.js → chunk-5czvhd0g.js} +5 -4
- package/dist/{chunk-e59kzyvy.js.map → chunk-5czvhd0g.js.map} +2 -2
- package/dist/{chunk-1mba9m1j.js → chunk-9zn0bkc9.js} +116 -77
- package/dist/{chunk-1mba9m1j.js.map → chunk-9zn0bkc9.js.map} +2 -2
- package/dist/{chunk-ww8a4ej4.js → chunk-f7p0h1gs.js} +5 -5
- package/dist/{chunk-ww8a4ej4.js.map → chunk-f7p0h1gs.js.map} +2 -2
- package/dist/{chunk-9a50csg6.js → chunk-pr8p6pap.js} +125 -116
- package/dist/{chunk-9a50csg6.js.map → chunk-pr8p6pap.js.map} +7 -7
- package/dist/chunk-q5djsg78.js +200 -0
- package/dist/chunk-q5djsg78.js.map +9 -0
- package/dist/{chunk-1e0nxy7p.js → chunk-z4r7tt2p.js} +12 -12
- package/dist/{chunk-1e0nxy7p.js.map → chunk-z4r7tt2p.js.map} +2 -2
- package/dist/hosted-agent.js +128 -120
- package/dist/hosted-agent.js.map +4 -4
- package/dist/main.js +5191 -3270
- package/dist/main.js.map +12 -12
- package/dist/mcp-catalog.js +4 -4
- package/dist/mcp-catalog.js.map +1 -1
- package/dist/mcp-factories.js +1583 -635
- package/dist/mcp-factories.js.map +8 -8
- 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 +18 -16
- package/dist/query-runtime.js.map +2 -2
- package/dist/registry.js +20 -19
- package/dist/registry.js.map +2 -2
- package/dist/rollout.js +41 -41
- package/dist/rollout.js.map +2 -2
- package/dist/runtime/src/mcp-runtime-host.ts +1 -0
- package/dist/runtime/src/platform/playwright/manager.ts +77 -15
- package/dist/runtime/src/runtime/visuals.ts +47 -11
- package/dist/runtime/src/storage/api-topics.ts +6 -0
- package/dist/runtime/src/storage/browser-profiles.ts +18 -0
- package/dist/runtime/src/topics/lifecycle.ts +2 -5
- package/dist/runtime/src/topics/update.ts +17 -0
- package/dist/runtime/src/types/api.ts +6 -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 +54 -52
- package/dist/runtime-helpers.js.map +2 -2
- package/dist/sqlite.js +5 -3
- package/dist/sqlite.js.map +2 -2
- package/dist/storage.js +640 -664
- package/dist/storage.js.map +3 -3
- package/dist/types/packages/core/src/platform/playwright/manager.d.ts +8 -0
- package/dist/types/packages/core/src/runtime/visuals.d.ts +9 -2
- package/dist/types/packages/core/src/storage/api-topics.d.ts +1 -0
- package/dist/types/packages/core/src/storage/browser-profiles.d.ts +4 -0
- package/dist/types/packages/core/src/types/api.d.ts +6 -0
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/dist/vault.js +22 -20
- package/dist/vault.js.map +2 -2
- package/package.json +1 -1
- package/dist/chunk-bnyvxss3.js +0 -77
package/dist/agent-helpers.js
CHANGED
|
@@ -13,18 +13,9 @@ var __export = (target, all) => {
|
|
|
13
13
|
set: __exportSetter.bind(all, name)
|
|
14
14
|
});
|
|
15
15
|
};
|
|
16
|
-
var __esm = (fn, res
|
|
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
|
-
};
|
|
16
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
27
17
|
var __promiseAll = (args) => Promise.all(args);
|
|
18
|
+
var __require = import.meta.require;
|
|
28
19
|
|
|
29
20
|
// ../../packages/core/src/platform/paths.ts
|
|
30
21
|
import { existsSync, realpathSync } from "fs";
|
|
@@ -193,6 +184,105 @@ var init_logger = __esm(() => {
|
|
|
193
184
|
});
|
|
194
185
|
|
|
195
186
|
// ../../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
|
+
});
|
|
196
286
|
import { execFileSync } from "child_process";
|
|
197
287
|
import { randomBytes } from "crypto";
|
|
198
288
|
import {
|
|
@@ -342,6 +432,9 @@ function safeWorkspaceSegment(value, fallback) {
|
|
|
342
432
|
function resolveTopicWorkspaceDir(topicId) {
|
|
343
433
|
return join(TOPIC_WORKSPACE_DIR, safeWorkspaceSegment(topicId, "topic"));
|
|
344
434
|
}
|
|
435
|
+
function isProductionEnv() {
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
345
438
|
function loadOrCreateLocalSecret(envKey, filename, options = {}) {
|
|
346
439
|
const envValue = envText(envKey);
|
|
347
440
|
const secretFile = resolve3(SECRETS_DIR, filename);
|
|
@@ -376,13 +469,18 @@ function loadOrCreateLocalSecret(envKey, filename, options = {}) {
|
|
|
376
469
|
return stored;
|
|
377
470
|
}
|
|
378
471
|
}
|
|
472
|
+
function getCleanEnv() {
|
|
473
|
+
const env = { ...process.env };
|
|
474
|
+
delete env.CLAUDECODE;
|
|
475
|
+
return env;
|
|
476
|
+
}
|
|
379
477
|
function resolveWhisperBackend() {
|
|
380
478
|
return envText("WHISPER_BACKEND") === "mlx-whisper" ? "mlx-whisper" : "faster-whisper";
|
|
381
479
|
}
|
|
382
480
|
function codexAuthFilePath() {
|
|
383
481
|
return process.env.NEGOTIUM_CODEX_AUTH_FILE || join(process.env.CODEX_HOME || join(homedir(), ".codex"), "auth.json");
|
|
384
482
|
}
|
|
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;
|
|
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, RUNTIME_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_HAIKU = "claude-haiku-4-5-20251001", MODEL_FABLE = "claude-fable-5-1", MODEL_DEEPSEEK_V4_PRO = "deepseek-v4-pro", MODEL_DEEPSEEK_V4_FLASH = "deepseek-v4-flash", 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;
|
|
386
484
|
var init_config = __esm(() => {
|
|
387
485
|
init_config_helpers();
|
|
388
486
|
init_logger();
|
|
@@ -438,6 +536,7 @@ var init_config = __esm(() => {
|
|
|
438
536
|
DEBUG_FILE = resolve3(DATA_DIR, "debug-users.json");
|
|
439
537
|
USERS_LOG_DIR = resolve3(DATA_DIR, "users");
|
|
440
538
|
RUN_DIR = resolveLocalStateDir("NEGOTIUM_RUN_DIR", "runtime");
|
|
539
|
+
RUNTIME_DIR = RUN_DIR;
|
|
441
540
|
PROGRESS_DIR = resolve3(RUN_DIR, "progress");
|
|
442
541
|
DM_CMD_DIR = resolve3(RUN_DIR, "dm-commands");
|
|
443
542
|
DM_RESP_DIR = resolve3(RUN_DIR, "dm-responses");
|
|
@@ -670,6 +769,13 @@ function validateActorTopicScope(value) {
|
|
|
670
769
|
}
|
|
671
770
|
return { ok: true, scope };
|
|
672
771
|
}
|
|
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
|
+
}
|
|
673
779
|
function intersectActorTopicScopes(scopes) {
|
|
674
780
|
if (scopes.length === 0 || scopes.some((scope) => scope === undefined))
|
|
675
781
|
return;
|
|
@@ -780,6 +886,13 @@ function validateRemoteSessionGrant(value) {
|
|
|
780
886
|
}
|
|
781
887
|
return { ok: true, grant: { hubUrl: hubUrl.url, capability } };
|
|
782
888
|
}
|
|
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
|
+
}
|
|
783
896
|
function remoteSessionGrantExpiry(grant) {
|
|
784
897
|
const payload = grant.capability.split(".")[1];
|
|
785
898
|
if (!payload)
|
|
@@ -818,7 +931,7 @@ function encodeRemoteSessionGrantArg(grant) {
|
|
|
818
931
|
throw new Error("remoteSession is required");
|
|
819
932
|
return Buffer.from(JSON.stringify(validated.grant), "utf-8").toString("base64url");
|
|
820
933
|
}
|
|
821
|
-
var REMOTE_SESSION_GRANT_LIMITS, GRANT_KEYS, LOOPBACK_HOSTS, MAX_REMOTE_SESSION_REPLY_TOKEN_LENGTH;
|
|
934
|
+
var REMOTE_SESSION_GRANT_LIMITS, GRANT_KEYS, LOOPBACK_HOSTS, REMOTE_SESSION_REPLY_TOKEN_PATTERN, MAX_REMOTE_SESSION_REPLY_TOKEN_LENGTH;
|
|
822
935
|
var init_remote_session_grant = __esm(() => {
|
|
823
936
|
REMOTE_SESSION_GRANT_LIMITS = Object.freeze({
|
|
824
937
|
maxHubUrlLength: 512,
|
|
@@ -827,6 +940,7 @@ var init_remote_session_grant = __esm(() => {
|
|
|
827
940
|
});
|
|
828
941
|
GRANT_KEYS = ["hubUrl", "capability"];
|
|
829
942
|
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_-]+$/;
|
|
830
944
|
MAX_REMOTE_SESSION_REPLY_TOKEN_LENGTH = REMOTE_SESSION_GRANT_LIMITS.maxCapabilityLength;
|
|
831
945
|
});
|
|
832
946
|
|
|
@@ -1171,12 +1285,12 @@ function createBackgroundBashManager(options = {}) {
|
|
|
1171
1285
|
usedPorts.clear();
|
|
1172
1286
|
knownContexts.clear();
|
|
1173
1287
|
const deadline = now() + 3000;
|
|
1174
|
-
await Promise.all(entries.map((instance) => new Promise((
|
|
1288
|
+
await Promise.all(entries.map((instance) => new Promise((resolve4) => {
|
|
1175
1289
|
if (instance.process.exitCode !== null || instance.process.killed)
|
|
1176
|
-
return
|
|
1177
|
-
instance.process.once("exit",
|
|
1178
|
-
instance.process.once("error",
|
|
1179
|
-
const timer = setTimeout(
|
|
1290
|
+
return resolve4();
|
|
1291
|
+
instance.process.once("exit", resolve4);
|
|
1292
|
+
instance.process.once("error", resolve4);
|
|
1293
|
+
const timer = setTimeout(resolve4, Math.max(0, deadline - now()));
|
|
1180
1294
|
timer.unref?.();
|
|
1181
1295
|
})));
|
|
1182
1296
|
}
|
|
@@ -1878,7 +1992,7 @@ var init_api_messages = __esm(async () => {
|
|
|
1878
1992
|
|
|
1879
1993
|
// ../../packages/core/src/storage/topic-link-records.ts
|
|
1880
1994
|
function topicLinkSchemaIsCurrent(database, nodeId) {
|
|
1881
|
-
const objects = new Map(database.query("SELECT name, sql FROM sqlite_master WHERE type IN ('table','index','trigger')").all().map((
|
|
1995
|
+
const objects = new Map(database.query("SELECT name, sql FROM sqlite_master WHERE type IN ('table','index','trigger')").all().map((row2) => [row2.name, row2.sql ?? ""]));
|
|
1882
1996
|
for (const name of [...SCHEMA_TABLES, ...SCHEMA_INDEXES, ...SCHEMA_INDEXES_TOMBSTONES]) {
|
|
1883
1997
|
if (!objects.has(name))
|
|
1884
1998
|
return false;
|
|
@@ -1895,7 +2009,7 @@ function topicLinkSchemaIsCurrent(database, nodeId) {
|
|
|
1895
2009
|
return false;
|
|
1896
2010
|
}
|
|
1897
2011
|
const identity = database.query("SELECT node_id, epoch_id FROM api_node_identity WHERE singleton = 1").all();
|
|
1898
|
-
if (identity.some((
|
|
2012
|
+
if (identity.some((row2) => row2.epoch_id === null))
|
|
1899
2013
|
return false;
|
|
1900
2014
|
if (nodeId && identity[0]?.node_id !== nodeId)
|
|
1901
2015
|
return false;
|
|
@@ -2369,6 +2483,7 @@ function initializeApiTopicsSchema() {
|
|
|
2369
2483
|
surface_scope TEXT,
|
|
2370
2484
|
browser_profile TEXT NOT NULL DEFAULT 'default',
|
|
2371
2485
|
browser_profile_owner TEXT,
|
|
2486
|
+
browser_connect_port INTEGER,
|
|
2372
2487
|
session_id TEXT,
|
|
2373
2488
|
CHECK (
|
|
2374
2489
|
(kind = 'channel' AND response_policy = 'off' AND agent IS NULL) OR
|
|
@@ -2486,6 +2601,9 @@ function initializeApiTopicsSchema() {
|
|
|
2486
2601
|
if (!tableColumns("api_topics").has("browser_profile_owner")) {
|
|
2487
2602
|
db.exec("ALTER TABLE api_topics ADD COLUMN browser_profile_owner TEXT");
|
|
2488
2603
|
}
|
|
2604
|
+
if (!tableColumns("api_topics").has("browser_connect_port")) {
|
|
2605
|
+
db.exec("ALTER TABLE api_topics ADD COLUMN browser_connect_port INTEGER");
|
|
2606
|
+
}
|
|
2489
2607
|
if (!tableColumns("api_topics").has("subagent_report_mode")) {
|
|
2490
2608
|
db.exec("ALTER TABLE api_topics ADD COLUMN subagent_report_mode TEXT NOT NULL DEFAULT 'auto'");
|
|
2491
2609
|
}
|
|
@@ -2723,12 +2841,16 @@ function rowToDto2(r, participants = getTopicParticipants(r.id), tellTargets) {
|
|
|
2723
2841
|
} : {},
|
|
2724
2842
|
visibility: normalizeTopicVisibility(r.visibility),
|
|
2725
2843
|
surface: normalizeTopicSurface(r.surface),
|
|
2726
|
-
surfaceScope: normalizeSurfaceScope(r.surface_scope)
|
|
2844
|
+
surfaceScope: normalizeSurfaceScope(r.surface_scope),
|
|
2845
|
+
...r.browser_connect_port != null ? { browserConnectPort: r.browser_connect_port } : {}
|
|
2727
2846
|
};
|
|
2728
2847
|
}
|
|
2729
2848
|
function normalizeTopicVisibility(value) {
|
|
2730
2849
|
return value === "hidden" ? "hidden" : "visible";
|
|
2731
2850
|
}
|
|
2851
|
+
function isTopicVisible(topic) {
|
|
2852
|
+
return topic.visibility !== "hidden";
|
|
2853
|
+
}
|
|
2732
2854
|
function normalizeTopicKind(value) {
|
|
2733
2855
|
return value === "channel" || value === "agent" || value === "manager" ? value : null;
|
|
2734
2856
|
}
|
|
@@ -5119,7 +5241,7 @@ var init_codex = __esm(async () => {
|
|
|
5119
5241
|
});
|
|
5120
5242
|
|
|
5121
5243
|
// ../../packages/core/src/version.ts
|
|
5122
|
-
var NEGOTIUM_VERSION = "0.22.
|
|
5244
|
+
var NEGOTIUM_VERSION = "0.22.8";
|
|
5123
5245
|
|
|
5124
5246
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
5125
5247
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -5195,7 +5317,7 @@ async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
|
5195
5317
|
stdio: ["pipe", "pipe", "pipe"],
|
|
5196
5318
|
windowsHide: true
|
|
5197
5319
|
});
|
|
5198
|
-
const refreshed = new Promise((
|
|
5320
|
+
const refreshed = new Promise((resolve7, reject) => {
|
|
5199
5321
|
let settled = false;
|
|
5200
5322
|
let stdoutBuffer = "";
|
|
5201
5323
|
let stderr = "";
|
|
@@ -5214,7 +5336,7 @@ async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
|
5214
5336
|
else if (!existsSync6(cachePath))
|
|
5215
5337
|
reject(new Error("Codex did not create its model cache"));
|
|
5216
5338
|
else
|
|
5217
|
-
|
|
5339
|
+
resolve7();
|
|
5218
5340
|
};
|
|
5219
5341
|
const send = (message) => {
|
|
5220
5342
|
child.stdin.write(`${JSON.stringify(message)}
|
|
@@ -5280,12 +5402,12 @@ async function bootstrapCodexModelCache(codexHome, cachePath) {
|
|
|
5280
5402
|
function waitForChildExit(child, timeoutMs) {
|
|
5281
5403
|
if (child.exitCode !== null || child.signalCode !== null)
|
|
5282
5404
|
return Promise.resolve();
|
|
5283
|
-
return new Promise((
|
|
5284
|
-
const timer = setTimeout(
|
|
5405
|
+
return new Promise((resolve7) => {
|
|
5406
|
+
const timer = setTimeout(resolve7, timeoutMs);
|
|
5285
5407
|
timer.unref?.();
|
|
5286
5408
|
child.once("exit", () => {
|
|
5287
5409
|
clearTimeout(timer);
|
|
5288
|
-
|
|
5410
|
+
resolve7();
|
|
5289
5411
|
});
|
|
5290
5412
|
});
|
|
5291
5413
|
}
|
|
@@ -5375,11 +5497,16 @@ var init_codex_native_multi_agent = __esm(() => {
|
|
|
5375
5497
|
});
|
|
5376
5498
|
|
|
5377
5499
|
// ../../packages/core/src/agents/codex-app-server.ts
|
|
5500
|
+
var exports_codex_app_server = {};
|
|
5501
|
+
__export(exports_codex_app_server, {
|
|
5502
|
+
forkCodexSession: () => forkCodexSession,
|
|
5503
|
+
createCodexAppServerForker: () => createCodexAppServerForker
|
|
5504
|
+
});
|
|
5378
5505
|
import { spawn as spawn3 } from "child_process";
|
|
5379
5506
|
function createCodexAppServerForker(host) {
|
|
5380
5507
|
return async (parentThreadId) => {
|
|
5381
5508
|
const child = host.spawnServer();
|
|
5382
|
-
return await new Promise((
|
|
5509
|
+
return await new Promise((resolve7, reject) => {
|
|
5383
5510
|
let settled = false;
|
|
5384
5511
|
let stdoutBuffer = "";
|
|
5385
5512
|
let stderr = "";
|
|
@@ -5396,7 +5523,7 @@ function createCodexAppServerForker(host) {
|
|
|
5396
5523
|
if (error)
|
|
5397
5524
|
reject(error);
|
|
5398
5525
|
else if (result)
|
|
5399
|
-
|
|
5526
|
+
resolve7(result);
|
|
5400
5527
|
else
|
|
5401
5528
|
reject(new Error("Codex thread fork returned no result"));
|
|
5402
5529
|
};
|
|
@@ -5533,8 +5660,8 @@ var init_codex_registry = __esm(async () => {
|
|
|
5533
5660
|
return { sessionId: threadId, rolloutPath };
|
|
5534
5661
|
},
|
|
5535
5662
|
async forkSession({ parentSessionId }) {
|
|
5536
|
-
await init_codex_app_server();
|
|
5537
|
-
return await
|
|
5663
|
+
const { forkCodexSession: forkCodexSession2 } = await init_codex_app_server().then(() => exports_codex_app_server);
|
|
5664
|
+
return await forkCodexSession2(parentSessionId);
|
|
5538
5665
|
},
|
|
5539
5666
|
async cleanupRollouts({ sessionIds }) {
|
|
5540
5667
|
if (sessionIds.length === 0)
|
|
@@ -5715,6 +5842,11 @@ var init_maestro_registry = __esm(() => {
|
|
|
5715
5842
|
});
|
|
5716
5843
|
|
|
5717
5844
|
// ../../packages/core/src/agents/registry.ts
|
|
5845
|
+
var exports_registry = {};
|
|
5846
|
+
__export(exports_registry, {
|
|
5847
|
+
getRegistryOperations: () => getRegistryOperations,
|
|
5848
|
+
getRegistry: () => getRegistry
|
|
5849
|
+
});
|
|
5718
5850
|
function getRegistry(agent) {
|
|
5719
5851
|
return REGISTRIES[agent];
|
|
5720
5852
|
}
|
|
@@ -6101,11 +6233,11 @@ var DEFAULT_CONTEXT_WARNING_RATIO = 0.8;
|
|
|
6101
6233
|
// ../../packages/core/src/agents/claude-provider.ts
|
|
6102
6234
|
var exports_claude_provider = {};
|
|
6103
6235
|
__export(exports_claude_provider, {
|
|
6104
|
-
|
|
6105
|
-
claudeBuiltInTools: () => claudeBuiltInTools,
|
|
6106
|
-
claudeProvider: () => claudeProvider,
|
|
6236
|
+
substituteClaudeToolInput: () => substituteClaudeToolInput,
|
|
6107
6237
|
spawnClaudeCodeProcessWithTreeKill: () => spawnClaudeCodeProcessWithTreeKill,
|
|
6108
|
-
|
|
6238
|
+
claudeProvider: () => claudeProvider,
|
|
6239
|
+
claudeBuiltInTools: () => claudeBuiltInTools,
|
|
6240
|
+
buildClaudeDisallowedTools: () => buildClaudeDisallowedTools
|
|
6109
6241
|
});
|
|
6110
6242
|
import { spawn as spawn4 } from "child_process";
|
|
6111
6243
|
import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
|
|
@@ -6186,8 +6318,8 @@ function buildClaudePrompt(opts) {
|
|
|
6186
6318
|
}
|
|
6187
6319
|
function watchClaudeProcessExit(signal) {
|
|
6188
6320
|
let listener;
|
|
6189
|
-
const exited = new Promise((
|
|
6190
|
-
listener =
|
|
6321
|
+
const exited = new Promise((resolve8) => {
|
|
6322
|
+
listener = resolve8;
|
|
6191
6323
|
const listeners = claudeProcessExitListeners.get(signal) ?? new Set;
|
|
6192
6324
|
listeners.add(listener);
|
|
6193
6325
|
claudeProcessExitListeners.set(signal, listeners);
|
|
@@ -6712,12 +6844,12 @@ function createCodexTreeManager(host, options = {}) {
|
|
|
6712
6844
|
const previous = spawnChain;
|
|
6713
6845
|
let release;
|
|
6714
6846
|
let released = false;
|
|
6715
|
-
spawnChain = new Promise((
|
|
6847
|
+
spawnChain = new Promise((resolve8) => {
|
|
6716
6848
|
release = () => {
|
|
6717
6849
|
if (released)
|
|
6718
6850
|
return;
|
|
6719
6851
|
released = true;
|
|
6720
|
-
|
|
6852
|
+
resolve8();
|
|
6721
6853
|
};
|
|
6722
6854
|
});
|
|
6723
6855
|
await previous;
|
|
@@ -6824,7 +6956,7 @@ function createCodexTreeManager(host, options = {}) {
|
|
|
6824
6956
|
return;
|
|
6825
6957
|
const deadline = Date.now() + Math.max(0, graceMs);
|
|
6826
6958
|
while (Date.now() < deadline && hasSurvivors(plan.targets)) {
|
|
6827
|
-
await new Promise((
|
|
6959
|
+
await new Promise((resolve8) => setTimeout(resolve8, Math.min(100, Math.max(1, deadline - Date.now()))));
|
|
6828
6960
|
}
|
|
6829
6961
|
killStragglers(plan);
|
|
6830
6962
|
}
|
|
@@ -7152,8 +7284,8 @@ async function createCodexVaultHookBridge(userId) {
|
|
|
7152
7284
|
});
|
|
7153
7285
|
restrictIpcEndpoint(socketPath);
|
|
7154
7286
|
if (IS_WINDOWS2) {
|
|
7155
|
-
await Promise.resolve().then(() => init_config());
|
|
7156
|
-
const cached = await ensureCodexWindowsWrapperExe(join13(
|
|
7287
|
+
const { BINARIES_DIR: BINARIES_DIR2 } = await Promise.resolve().then(() => (init_config(), exports_config));
|
|
7288
|
+
const cached = await ensureCodexWindowsWrapperExe(join13(BINARIES_DIR2, "codex-hook-wrapper"));
|
|
7157
7289
|
await copyFile(cached, wrapperPath);
|
|
7158
7290
|
await writeFile2(join13(root, "codex-with-hooks.cfg"), [process.execPath, codexCliScriptPath(), socketPath, token].join(`
|
|
7159
7291
|
`), { encoding: "utf8", mode: 384 });
|
|
@@ -7725,9 +7857,9 @@ var init_tool_format = __esm(() => {
|
|
|
7725
7857
|
// ../../packages/core/src/agents/codex-provider.ts
|
|
7726
7858
|
var exports_codex_provider = {};
|
|
7727
7859
|
__export(exports_codex_provider, {
|
|
7728
|
-
|
|
7860
|
+
toCodexMcpServers: () => toCodexMcpServers,
|
|
7729
7861
|
normalizeCodexTurnUsage: () => normalizeCodexTurnUsage,
|
|
7730
|
-
|
|
7862
|
+
codexProvider: () => codexProvider
|
|
7731
7863
|
});
|
|
7732
7864
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
7733
7865
|
import { existsSync as existsSync14, readFileSync as readFileSync11, realpathSync as realpathSync4, statSync as statSync5 } from "fs";
|
|
@@ -8027,9 +8159,9 @@ async function startStreamedWithTracking(thread, prompt, abortSignal, trackedPid
|
|
|
8027
8159
|
nextP.catch(() => {});
|
|
8028
8160
|
first = await Promise.race([nextP, startupTimeout]);
|
|
8029
8161
|
} catch (err) {
|
|
8030
|
-
const
|
|
8031
|
-
if (
|
|
8032
|
-
killCodexTrees(
|
|
8162
|
+
const novel2 = findNewCodexChildren(baseline);
|
|
8163
|
+
if (novel2.length > 0) {
|
|
8164
|
+
killCodexTrees(novel2);
|
|
8033
8165
|
}
|
|
8034
8166
|
await closeIterator(iter);
|
|
8035
8167
|
throw err;
|
|
@@ -8447,11 +8579,11 @@ var init_maestro_bootstrap_env = __esm(() => {
|
|
|
8447
8579
|
// ../../packages/core/src/agents/maestro-provider.ts
|
|
8448
8580
|
var exports_maestro_provider = {};
|
|
8449
8581
|
__export(exports_maestro_provider, {
|
|
8450
|
-
|
|
8451
|
-
buildMaestroToolHooks: () => buildMaestroToolHooks,
|
|
8452
|
-
buildMaestroToolResultTruncation: () => buildMaestroToolResultTruncation,
|
|
8582
|
+
resolveMaestroApiKeyOverrides: () => resolveMaestroApiKeyOverrides,
|
|
8453
8583
|
maestroProvider: () => maestroProvider,
|
|
8454
|
-
|
|
8584
|
+
buildMaestroToolResultTruncation: () => buildMaestroToolResultTruncation,
|
|
8585
|
+
buildMaestroToolHooks: () => buildMaestroToolHooks,
|
|
8586
|
+
buildMaestroDisallowedTools: () => buildMaestroDisallowedTools
|
|
8455
8587
|
});
|
|
8456
8588
|
import { resolve as resolve11 } from "path";
|
|
8457
8589
|
import { maestroProvider as sdkMaestroProvider, setMcpResolver } from "maestro-agent-sdk";
|
|
@@ -8579,18 +8711,18 @@ import { join as join15 } from "path";
|
|
|
8579
8711
|
async function* dispatchAgent(opts) {
|
|
8580
8712
|
switch (opts.agent) {
|
|
8581
8713
|
case "claude": {
|
|
8582
|
-
const { claudeProvider } = await loadClaudeProvider();
|
|
8583
|
-
yield*
|
|
8714
|
+
const { claudeProvider: claudeProvider2 } = await loadClaudeProvider();
|
|
8715
|
+
yield* claudeProvider2(opts);
|
|
8584
8716
|
return;
|
|
8585
8717
|
}
|
|
8586
8718
|
case "codex": {
|
|
8587
|
-
const { codexProvider } = await loadCodexProvider();
|
|
8588
|
-
yield*
|
|
8719
|
+
const { codexProvider: codexProvider2 } = await loadCodexProvider();
|
|
8720
|
+
yield* codexProvider2(opts);
|
|
8589
8721
|
return;
|
|
8590
8722
|
}
|
|
8591
8723
|
case "maestro": {
|
|
8592
|
-
const { maestroProvider } = await loadMaestroProvider();
|
|
8593
|
-
yield*
|
|
8724
|
+
const { maestroProvider: maestroProvider2 } = await loadMaestroProvider();
|
|
8725
|
+
yield* maestroProvider2(opts);
|
|
8594
8726
|
return;
|
|
8595
8727
|
}
|
|
8596
8728
|
default: {
|
|
@@ -8621,8 +8753,8 @@ async function resolveSessionFileMissing(agent, sessionId, cwd) {
|
|
|
8621
8753
|
return true;
|
|
8622
8754
|
}
|
|
8623
8755
|
case "maestro": {
|
|
8624
|
-
const { hasActiveMaestroSession, maestroSessionPath } = await import("maestro-agent-sdk");
|
|
8625
|
-
return !existsSync15(
|
|
8756
|
+
const { hasActiveMaestroSession, maestroSessionPath: maestroSessionPath2 } = await import("maestro-agent-sdk");
|
|
8757
|
+
return !existsSync15(maestroSessionPath2(sessionId)) && !hasActiveMaestroSession(sessionId);
|
|
8626
8758
|
}
|
|
8627
8759
|
default: {
|
|
8628
8760
|
const _exhaustive = agent;
|
|
@@ -8701,6 +8833,24 @@ var init_agents = __esm(async () => {
|
|
|
8701
8833
|
});
|
|
8702
8834
|
|
|
8703
8835
|
// ../../packages/core/src/agents/model-catalog.ts
|
|
8836
|
+
var exports_model_catalog = {};
|
|
8837
|
+
__export(exports_model_catalog, {
|
|
8838
|
+
selectableModel: () => selectableModel,
|
|
8839
|
+
resolveWorkerModel: () => resolveWorkerModel,
|
|
8840
|
+
resolveWorkerDefaultModel: () => resolveWorkerDefaultModel,
|
|
8841
|
+
resolveModelForAgent: () => resolveModelForAgent,
|
|
8842
|
+
resolveDefaultModel: () => resolveDefaultModel,
|
|
8843
|
+
resolveCompactionExecution: () => resolveCompactionExecution,
|
|
8844
|
+
modelOwner: () => modelOwner,
|
|
8845
|
+
formatSelectableModel: () => formatSelectableModel,
|
|
8846
|
+
canonicalModelId: () => canonicalModelId,
|
|
8847
|
+
SELECTABLE_MODELS: () => SELECTABLE_MODELS,
|
|
8848
|
+
MODEL_OWNER: () => MODEL_OWNER,
|
|
8849
|
+
MODEL_COST_ROUTING_SUMMARY: () => MODEL_COST_ROUTING_SUMMARY,
|
|
8850
|
+
MODEL_COST_RESEARCHED_AT: () => MODEL_COST_RESEARCHED_AT,
|
|
8851
|
+
FALLBACK_ORDER: () => FALLBACK_ORDER,
|
|
8852
|
+
AGENT_DISPLAY_NAME: () => AGENT_DISPLAY_NAME
|
|
8853
|
+
});
|
|
8704
8854
|
function canonicalModelId(value) {
|
|
8705
8855
|
const trimmed = value.trim();
|
|
8706
8856
|
const lower = trimmed.toLowerCase();
|
|
@@ -8710,6 +8860,10 @@ function formatSelectableModel(candidate) {
|
|
|
8710
8860
|
const tier = `${candidate.intelligenceTier[0].toUpperCase()}${candidate.intelligenceTier.slice(1)}`;
|
|
8711
8861
|
return `${candidate.agent} / \`${candidate.model}\` [${tier}-level]: ${candidate.routingSummary}`;
|
|
8712
8862
|
}
|
|
8863
|
+
function selectableModel(value) {
|
|
8864
|
+
const canonical = canonicalModelId(value).toLowerCase();
|
|
8865
|
+
return SELECTABLE_MODELS.find((candidate) => candidate.model === canonical);
|
|
8866
|
+
}
|
|
8713
8867
|
function modelOwner(model) {
|
|
8714
8868
|
const lower = model.toLowerCase();
|
|
8715
8869
|
if (lower.startsWith("claude-"))
|
|
@@ -8762,7 +8916,7 @@ function resolveCompactionExecution(agent, registry) {
|
|
|
8762
8916
|
const effort = registry.validateEffort("medium") ? "medium" : registry.defaultEffort;
|
|
8763
8917
|
return { model, ...effort ? { effort } : {} };
|
|
8764
8918
|
}
|
|
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;
|
|
8919
|
+
var MODEL_OWNER, MODEL_COST_RESEARCHED_AT = "2026-09-05", 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, FALLBACK_ORDER, AGENT_DISPLAY_NAME;
|
|
8766
8920
|
var init_model_catalog = __esm(() => {
|
|
8767
8921
|
init_config();
|
|
8768
8922
|
MODEL_OWNER = {
|
|
@@ -8934,6 +9088,20 @@ var init_model_catalog = __esm(() => {
|
|
|
8934
9088
|
"glm-flash": "glm-5.3-flash"
|
|
8935
9089
|
};
|
|
8936
9090
|
CANONICAL_MODEL_CASING = Object.fromEntries(SELECTABLE_MODELS.map((candidate) => [candidate.model.toLowerCase(), candidate.model]));
|
|
9091
|
+
FALLBACK_ORDER = {
|
|
9092
|
+
claude: [
|
|
9093
|
+
{ agent: "maestro", model: "deepseek-pro" },
|
|
9094
|
+
{ agent: "codex", model: "gpt-6-luna" }
|
|
9095
|
+
],
|
|
9096
|
+
codex: [
|
|
9097
|
+
{ agent: "maestro", model: "deepseek-pro" },
|
|
9098
|
+
{ agent: "claude", model: "sonnet" }
|
|
9099
|
+
],
|
|
9100
|
+
maestro: [
|
|
9101
|
+
{ agent: "codex", model: "gpt-6-luna" },
|
|
9102
|
+
{ agent: "claude", model: "sonnet" }
|
|
9103
|
+
]
|
|
9104
|
+
};
|
|
8937
9105
|
AGENT_DISPLAY_NAME = {
|
|
8938
9106
|
claude: "Claude",
|
|
8939
9107
|
codex: "Codex",
|
|
@@ -9682,9 +9850,9 @@ function resolveTopicBrief(topicId, legacyTitle) {
|
|
|
9682
9850
|
const titleBrief = getTopicBrief(titleKey);
|
|
9683
9851
|
if (titleBrief)
|
|
9684
9852
|
return { brief: titleBrief, storageKey: titleKey };
|
|
9685
|
-
const
|
|
9686
|
-
if (
|
|
9687
|
-
return { brief:
|
|
9853
|
+
const current2 = getTopicBrief(topicId);
|
|
9854
|
+
if (current2)
|
|
9855
|
+
return { brief: current2, storageKey: topicId };
|
|
9688
9856
|
const legacy = titleKey === legacyTitle ? null : getTopicBrief(legacyTitle);
|
|
9689
9857
|
return legacy ? { brief: legacy, storageKey: legacyTitle } : null;
|
|
9690
9858
|
}
|
|
@@ -10304,6 +10472,11 @@ var init_archiver = __esm(async () => {
|
|
|
10304
10472
|
});
|
|
10305
10473
|
|
|
10306
10474
|
// ../../packages/core/src/agents/auth-check.ts
|
|
10475
|
+
var exports_auth_check = {};
|
|
10476
|
+
__export(exports_auth_check, {
|
|
10477
|
+
checkAgentModelAuth: () => checkAgentModelAuth,
|
|
10478
|
+
checkAgentAuth: () => checkAgentAuth
|
|
10479
|
+
});
|
|
10307
10480
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
10308
10481
|
import { existsSync as existsSync17 } from "fs";
|
|
10309
10482
|
import { homedir as homedir8, platform } from "os";
|
|
@@ -10635,8 +10808,8 @@ function createRoomQueryRegistry(host) {
|
|
|
10635
10808
|
clearInterval(previousMonitor);
|
|
10636
10809
|
activeByRoom.set(roomId, control);
|
|
10637
10810
|
const monitor = setInterval(() => {
|
|
10638
|
-
const
|
|
10639
|
-
if (!
|
|
10811
|
+
const current2 = activeByRoom.get(roomId);
|
|
10812
|
+
if (!current2 || current2.queryId !== control.queryId) {
|
|
10640
10813
|
clearInterval(monitor);
|
|
10641
10814
|
if (leaseMonitors.get(roomId) === monitor)
|
|
10642
10815
|
leaseMonitors.delete(roomId);
|
|
@@ -10658,8 +10831,8 @@ function createRoomQueryRegistry(host) {
|
|
|
10658
10831
|
return true;
|
|
10659
10832
|
}
|
|
10660
10833
|
function clear(roomId, queryId) {
|
|
10661
|
-
const
|
|
10662
|
-
if (
|
|
10834
|
+
const current2 = activeByRoom.get(roomId);
|
|
10835
|
+
if (current2?.queryId === queryId) {
|
|
10663
10836
|
activeByRoom.delete(roomId);
|
|
10664
10837
|
const monitor = leaseMonitors.get(roomId);
|
|
10665
10838
|
if (monitor)
|
|
@@ -10722,12 +10895,43 @@ var init_room_query_registry = () => {};
|
|
|
10722
10895
|
var init_types2 = () => {};
|
|
10723
10896
|
|
|
10724
10897
|
// ../../packages/core/src/query/active-rooms.ts
|
|
10898
|
+
var exports_active_rooms = {};
|
|
10899
|
+
__export(exports_active_rooms, {
|
|
10900
|
+
wsAbortReason: () => wsAbortReason,
|
|
10901
|
+
takeDeferredInject: () => takeDeferredInject,
|
|
10902
|
+
setRoomQuery: () => setRoomQuery,
|
|
10903
|
+
listRunningTopicQueries: () => listRunningTopicQueries,
|
|
10904
|
+
listRunningTopicIds: () => listRunningTopicIds,
|
|
10905
|
+
isolatedTurnRoomId: () => isolatedTurnRoomId,
|
|
10906
|
+
isUserOrigin: () => isUserOrigin,
|
|
10907
|
+
isTopicRunning: () => isTopicRunning,
|
|
10908
|
+
interSessionQueue: () => interSessionQueue,
|
|
10909
|
+
getRoomQueryStatus: () => getRoomQueryStatus,
|
|
10910
|
+
getRoomQuery: () => getRoomQuery,
|
|
10911
|
+
deferInject: () => deferInject,
|
|
10912
|
+
decideNewQuery: () => decideNewQuery,
|
|
10913
|
+
clearRoomQuery: () => clearRoomQuery,
|
|
10914
|
+
cancelDeferredInject: () => cancelDeferredInject,
|
|
10915
|
+
abortRoom: () => abortRoom,
|
|
10916
|
+
abortAllRooms: () => abortAllRooms,
|
|
10917
|
+
InterSessionQueue: () => InterSessionQueue,
|
|
10918
|
+
DeferredInjectBatcher: () => DeferredInjectBatcher
|
|
10919
|
+
});
|
|
10725
10920
|
function getRoomQuery(roomId) {
|
|
10726
10921
|
return roomQueryRegistry.get(roomId);
|
|
10727
10922
|
}
|
|
10923
|
+
function listRunningTopicQueries() {
|
|
10924
|
+
return roomQueryRegistry.listRunningTopicQueries();
|
|
10925
|
+
}
|
|
10926
|
+
function listRunningTopicIds() {
|
|
10927
|
+
return roomQueryRegistry.listRunningTopicIds();
|
|
10928
|
+
}
|
|
10728
10929
|
function isTopicRunning(topicId) {
|
|
10729
10930
|
return roomQueryRegistry.isTopicRunning(topicId);
|
|
10730
10931
|
}
|
|
10932
|
+
function getRoomQueryStatus(topicId, queryId) {
|
|
10933
|
+
return roomQueryRegistry.status(topicId, queryId);
|
|
10934
|
+
}
|
|
10731
10935
|
function setRoomQuery(control) {
|
|
10732
10936
|
return roomQueryRegistry.set(control);
|
|
10733
10937
|
}
|
|
@@ -10737,6 +10941,9 @@ function clearRoomQuery(roomId, queryId) {
|
|
|
10737
10941
|
function abortRoom(roomId, reason = "external" /* External */) {
|
|
10738
10942
|
return roomQueryRegistry.abort(roomId, reason);
|
|
10739
10943
|
}
|
|
10944
|
+
function abortAllRooms(reason = "external" /* External */) {
|
|
10945
|
+
return roomQueryRegistry.abortAll(reason);
|
|
10946
|
+
}
|
|
10740
10947
|
function decideNewQuery(topicId, incomingOrigin) {
|
|
10741
10948
|
return roomQueryRegistry.decide(topicId, incomingOrigin);
|
|
10742
10949
|
}
|
|
@@ -10902,6 +11109,9 @@ function deferInject(inject) {
|
|
|
10902
11109
|
function takeDeferredInject(topicId) {
|
|
10903
11110
|
return interSessionQueue.dequeueAll(topicId);
|
|
10904
11111
|
}
|
|
11112
|
+
function cancelDeferredInject(topicId, requestId) {
|
|
11113
|
+
return interSessionQueue.remove(topicId, requestId) !== undefined;
|
|
11114
|
+
}
|
|
10905
11115
|
function wsAbortReason(reason) {
|
|
10906
11116
|
return reason === "internal" /* Internal */ ? "superseded" : "stopped";
|
|
10907
11117
|
}
|
|
@@ -11194,8 +11404,8 @@ function settleTopicArchiveJob(topicId, archivePath, success) {
|
|
|
11194
11404
|
db.query("UPDATE api_topic_archive_jobs SET status = 'pending', updated_at = ? WHERE topic_id = ? AND archive_path = ?").run(new Date().toISOString(), topicId, archivePath);
|
|
11195
11405
|
return;
|
|
11196
11406
|
}
|
|
11197
|
-
const
|
|
11198
|
-
setTopicArchiveState(topicId, Math.max(
|
|
11407
|
+
const current2 = getTopicArchiveState(topicId)?.lastArchivedRowid ?? 0;
|
|
11408
|
+
setTopicArchiveState(topicId, Math.max(current2, job.last_rowid), job.archive_path);
|
|
11199
11409
|
db.query("DELETE FROM api_topic_archive_jobs WHERE topic_id = ? AND archive_path = ?").run(topicId, archivePath);
|
|
11200
11410
|
})();
|
|
11201
11411
|
}
|
|
@@ -11867,7 +12077,7 @@ function createAskUserRuntime(host) {
|
|
|
11867
12077
|
if (ask.expired || ask.selectedLabel) {
|
|
11868
12078
|
return { ok: false, error: "This question is no longer awaiting an answer." };
|
|
11869
12079
|
}
|
|
11870
|
-
if (!ask.choices.some((
|
|
12080
|
+
if (!ask.choices.some((choice2) => choice2.label === label)) {
|
|
11871
12081
|
return { ok: false, error: "Invalid choice." };
|
|
11872
12082
|
}
|
|
11873
12083
|
const pending = pendingAsks.get(messageId);
|
|
@@ -12020,8 +12230,8 @@ function createAskUserRuntime(host) {
|
|
|
12020
12230
|
return errorResult(`Error: failed to persist ask_user_question: ${error instanceof Error ? error.message : String(error)}`);
|
|
12021
12231
|
}
|
|
12022
12232
|
let resolveAnswer;
|
|
12023
|
-
const promise = new Promise((
|
|
12024
|
-
resolveAnswer =
|
|
12233
|
+
const promise = new Promise((resolve13) => {
|
|
12234
|
+
resolveAnswer = resolve13;
|
|
12025
12235
|
});
|
|
12026
12236
|
pendingAsks.set(message.id, {
|
|
12027
12237
|
topicId: ctx.topicId,
|
|
@@ -12223,8 +12433,8 @@ var init_self_schedules = __esm(async () => {
|
|
|
12223
12433
|
});
|
|
12224
12434
|
|
|
12225
12435
|
// ../../packages/core/src/platform/playwright/manager-utils.ts
|
|
12226
|
-
function isLiveOwnedChildProcess(
|
|
12227
|
-
return
|
|
12436
|
+
function isLiveOwnedChildProcess(current2, expected) {
|
|
12437
|
+
return current2?.process === expected && expected.exitCode === null && expected.signalCode === null && !expected.killed;
|
|
12228
12438
|
}
|
|
12229
12439
|
function matchesSpawnedBrowserHealth(health, expectedSpawnNonce) {
|
|
12230
12440
|
if (!health || typeof health !== "object")
|
|
@@ -12468,10 +12678,10 @@ function findExecutableOnPath(command, environment = process.env) {
|
|
|
12468
12678
|
return null;
|
|
12469
12679
|
}
|
|
12470
12680
|
function resolveHeadedPlaywrightSpawn(command, args, options = {}) {
|
|
12471
|
-
const
|
|
12681
|
+
const platform2 = options.platform ?? process.platform;
|
|
12472
12682
|
const environment = options.environment ?? process.env;
|
|
12473
12683
|
const hasDisplay = Boolean(environment.DISPLAY?.trim() || environment.WAYLAND_DISPLAY?.trim());
|
|
12474
|
-
if (
|
|
12684
|
+
if (platform2 !== "linux" || hasDisplay) {
|
|
12475
12685
|
return { command, args: [...args], virtualDisplay: false };
|
|
12476
12686
|
}
|
|
12477
12687
|
const xvfbRun = (options.findExecutable ?? findExecutableOnPath)("xvfb-run", environment);
|
|
@@ -12520,7 +12730,7 @@ async function probeMcpTransport(transport, options = {}) {
|
|
|
12520
12730
|
}
|
|
12521
12731
|
}
|
|
12522
12732
|
async function probePlaywrightMcpTransports(port, capability, fetchImpl = fetch) {
|
|
12523
|
-
const
|
|
12733
|
+
const query2 = new URLSearchParams({ owner: PROBE_OWNER });
|
|
12524
12734
|
const baseUrl = `http://127.0.0.1:${port}`;
|
|
12525
12735
|
const ownerCapability = browserOwnerCapability(capability, PROBE_OWNER);
|
|
12526
12736
|
const capabilityHeaders = { "X-Browser-Capability": ownerCapability };
|
|
@@ -12529,14 +12739,14 @@ async function probePlaywrightMcpTransports(port, capability, fetchImpl = fetch)
|
|
|
12529
12739
|
headers.set("X-Browser-Capability", ownerCapability);
|
|
12530
12740
|
return fetchImpl(input, { ...init, headers });
|
|
12531
12741
|
};
|
|
12532
|
-
const sseTransport = new SSEClientTransport(new URL(`${baseUrl}/sse?${
|
|
12742
|
+
const sseTransport = new SSEClientTransport(new URL(`${baseUrl}/sse?${query2}`), {
|
|
12533
12743
|
fetch: authenticatedFetch,
|
|
12534
12744
|
eventSourceInit: { fetch: authenticatedFetch },
|
|
12535
12745
|
requestInit: { headers: capabilityHeaders }
|
|
12536
12746
|
});
|
|
12537
12747
|
if (!await probeMcpTransport(sseTransport))
|
|
12538
12748
|
return false;
|
|
12539
|
-
const streamableTransport = new StreamableHTTPClientTransport(new URL(`${baseUrl}/mcp?${
|
|
12749
|
+
const streamableTransport = new StreamableHTTPClientTransport(new URL(`${baseUrl}/mcp?${query2}`), {
|
|
12540
12750
|
fetch: authenticatedFetch,
|
|
12541
12751
|
requestInit: { headers: capabilityHeaders }
|
|
12542
12752
|
});
|
|
@@ -12666,9 +12876,9 @@ async function createBrowserVaultBroker(userId) {
|
|
|
12666
12876
|
if (typeof request.tool !== "string")
|
|
12667
12877
|
return { id, ok: false, error: "invalid tool" };
|
|
12668
12878
|
const leaseCutoff = Date.now() - LEASE_TTL_MS;
|
|
12669
|
-
for (const [
|
|
12879
|
+
for (const [lease2, binding] of leases) {
|
|
12670
12880
|
if (binding.createdAt < leaseCutoff)
|
|
12671
|
-
leases.delete(
|
|
12881
|
+
leases.delete(lease2);
|
|
12672
12882
|
}
|
|
12673
12883
|
if (leases.size >= MAX_ACTIVE_LEASES) {
|
|
12674
12884
|
return { id, ok: false, error: "too many active leases" };
|
|
@@ -12802,6 +13012,16 @@ function getTopicBrowserProfile(topicId) {
|
|
|
12802
13012
|
const value = db.query("SELECT browser_profile FROM api_topics WHERE id = ?").get(topicId)?.browser_profile;
|
|
12803
13013
|
return value || DEFAULT_BROWSER_PROFILE;
|
|
12804
13014
|
}
|
|
13015
|
+
function isBrowserConnectPort(value) {
|
|
13016
|
+
return Number.isInteger(value) && value >= 1024 && value <= 65535;
|
|
13017
|
+
}
|
|
13018
|
+
function getTopicBrowserConnectPort(topicId) {
|
|
13019
|
+
const value = db.query("SELECT browser_connect_port FROM api_topics WHERE id = ?").get(topicId)?.browser_connect_port;
|
|
13020
|
+
return isBrowserConnectPort(value) ? value : undefined;
|
|
13021
|
+
}
|
|
13022
|
+
function setTopicBrowserConnectPort(topicId, port) {
|
|
13023
|
+
db.query("UPDATE api_topics SET browser_connect_port = ? WHERE id = ?").run(port, topicId);
|
|
13024
|
+
}
|
|
12805
13025
|
function hasBrowserProfileTopic(topicId) {
|
|
12806
13026
|
return Boolean(db.query("SELECT id FROM api_topics WHERE id = ?").get(topicId));
|
|
12807
13027
|
}
|
|
@@ -12878,6 +13098,9 @@ function resolvePlaywrightTopicBinding(userId, topic) {
|
|
|
12878
13098
|
function defaultTopicBinding(userId, topic) {
|
|
12879
13099
|
if (!topic)
|
|
12880
13100
|
return managerHost.resolveNamedBinding(userId, "default");
|
|
13101
|
+
const connectPort = getTopicBrowserConnectPort(topic);
|
|
13102
|
+
if (connectPort !== undefined)
|
|
13103
|
+
return connectBinding(connectPort);
|
|
12881
13104
|
const ownerId = getBrowserProfileOwner(topic, userId);
|
|
12882
13105
|
const profile = getTopicBrowserProfile(topic);
|
|
12883
13106
|
return managerHost.resolveNamedBinding(ownerId, profile);
|
|
@@ -12891,6 +13114,26 @@ function validateProfileBinding(binding) {
|
|
|
12891
13114
|
}
|
|
12892
13115
|
return Object.freeze({ ...binding });
|
|
12893
13116
|
}
|
|
13117
|
+
function connectBinding(port) {
|
|
13118
|
+
return { instanceKey: `connect:${port}`, ownerId: "local", profile: `connect-${port}` };
|
|
13119
|
+
}
|
|
13120
|
+
function parseConnectInstanceKey(instanceKey) {
|
|
13121
|
+
const match = /^connect:(\d+)$/.exec(instanceKey);
|
|
13122
|
+
return match ? Number(match[1]) : undefined;
|
|
13123
|
+
}
|
|
13124
|
+
function browserRsArgs(instanceKey, port, userDataDir) {
|
|
13125
|
+
const connectPort = parseConnectInstanceKey(instanceKey);
|
|
13126
|
+
return [
|
|
13127
|
+
"--port",
|
|
13128
|
+
String(port),
|
|
13129
|
+
"--host",
|
|
13130
|
+
"127.0.0.1",
|
|
13131
|
+
"--headed",
|
|
13132
|
+
"--user-data-dir",
|
|
13133
|
+
userDataDir,
|
|
13134
|
+
...connectPort === undefined ? [] : ["--connect", String(connectPort)]
|
|
13135
|
+
];
|
|
13136
|
+
}
|
|
12894
13137
|
function defaultNamedBinding(_ownerId, rawProfile) {
|
|
12895
13138
|
const profile = normalizeBrowserProfileName(rawProfile);
|
|
12896
13139
|
const instanceKey = `profile:${profile}`;
|
|
@@ -12910,6 +13153,9 @@ function defaultChildEnvironment(context) {
|
|
|
12910
13153
|
return childEnvironment;
|
|
12911
13154
|
}
|
|
12912
13155
|
function parseInstanceKey(instanceKey) {
|
|
13156
|
+
const connectPort = parseConnectInstanceKey(instanceKey);
|
|
13157
|
+
if (connectPort !== undefined)
|
|
13158
|
+
return { ownerId: "local", profile: `_connect-${connectPort}` };
|
|
12913
13159
|
const shared = /^profile:(.+)$/.exec(instanceKey);
|
|
12914
13160
|
if (shared && !shared[1].includes(":")) {
|
|
12915
13161
|
return { ownerId: "local", profile: normalizeBrowserProfileName(shared[1]) };
|
|
@@ -13137,15 +13383,7 @@ async function spawnPlaywright(instanceKey, ownerId, reservedPort, browserBin =
|
|
|
13137
13383
|
const userDataDir = resolveUserDataDir(instanceKey);
|
|
13138
13384
|
const port = reservedPort ?? await allocatePort();
|
|
13139
13385
|
mkdirSync11(userDataDir, { recursive: true });
|
|
13140
|
-
const mcpArgs =
|
|
13141
|
-
"--port",
|
|
13142
|
-
String(port),
|
|
13143
|
-
"--host",
|
|
13144
|
-
"127.0.0.1",
|
|
13145
|
-
"--headed",
|
|
13146
|
-
"--user-data-dir",
|
|
13147
|
-
userDataDir
|
|
13148
|
-
];
|
|
13386
|
+
const mcpArgs = browserRsArgs(instanceKey, port, userDataDir);
|
|
13149
13387
|
const proxy = managerHost.resolveProxy();
|
|
13150
13388
|
if (proxy) {
|
|
13151
13389
|
releasePort(port);
|
|
@@ -13201,9 +13439,9 @@ async function spawnPlaywright(instanceKey, ownerId, reservedPort, browserBin =
|
|
|
13201
13439
|
const stderrTail = captureBoundedStderr(proc);
|
|
13202
13440
|
const startup = watchChildStartup(proc, stderrTail);
|
|
13203
13441
|
const reapCrashedBrowser = () => {
|
|
13204
|
-
const
|
|
13205
|
-
managerHost.cleanupBrowserProcessesForDataDir(
|
|
13206
|
-
cleanSingletonFiles(
|
|
13442
|
+
const userDataDir2 = resolveUserDataDir(instanceKey);
|
|
13443
|
+
managerHost.cleanupBrowserProcessesForDataDir(userDataDir2);
|
|
13444
|
+
cleanSingletonFiles(userDataDir2);
|
|
13207
13445
|
};
|
|
13208
13446
|
proc.once("error", (err) => {
|
|
13209
13447
|
logger.error({ err, instanceKey, stderr: stderrTail() || undefined }, "Playwright MCP error");
|
|
@@ -13272,8 +13510,8 @@ ${stderrTail()}` : ""));
|
|
|
13272
13510
|
}
|
|
13273
13511
|
async function supportsOwnerCleanup(port, capability) {
|
|
13274
13512
|
try {
|
|
13275
|
-
const
|
|
13276
|
-
const response = await fetch(`http://127.0.0.1:${port}/owners?${
|
|
13513
|
+
const query2 = new URLSearchParams({ owner: "__negotium_capability_probe__" });
|
|
13514
|
+
const response = await fetch(`http://127.0.0.1:${port}/owners?${query2}`, {
|
|
13277
13515
|
method: "DELETE",
|
|
13278
13516
|
headers: {
|
|
13279
13517
|
"X-Browser-Capability": capability
|
|
@@ -13333,8 +13571,12 @@ async function waitForPortRelease(port, timeoutMs = 3000) {
|
|
|
13333
13571
|
await delay(200);
|
|
13334
13572
|
}
|
|
13335
13573
|
}
|
|
13336
|
-
|
|
13337
|
-
const
|
|
13574
|
+
function closeTopicBrowserTabs(userId, topicId) {
|
|
13575
|
+
const connectPort = getTopicBrowserConnectPort(topicId);
|
|
13576
|
+
const binding = connectPort === undefined ? resolvePlaywrightProfileBinding(getBrowserProfileOwner(topicId, userId), getTopicBrowserProfile(topicId)) : connectBinding(connectPort);
|
|
13577
|
+
return closeBindingOwnerTabs(binding, `topic:${topicId}`);
|
|
13578
|
+
}
|
|
13579
|
+
async function closeBindingOwnerTabs(binding, owner) {
|
|
13338
13580
|
const instanceKey = binding.instanceKey;
|
|
13339
13581
|
const inProgress = spawning.get(instanceKey);
|
|
13340
13582
|
if (inProgress)
|
|
@@ -13344,8 +13586,8 @@ async function closeBrowserOwnerTabs(ownerId, rawProfile, owner) {
|
|
|
13344
13586
|
if (!instance)
|
|
13345
13587
|
return 0;
|
|
13346
13588
|
const port = instance.port;
|
|
13347
|
-
const
|
|
13348
|
-
const response = await fetch(`http://127.0.0.1:${port}/owners?${
|
|
13589
|
+
const query2 = new URLSearchParams({ owner });
|
|
13590
|
+
const response = await fetch(`http://127.0.0.1:${port}/owners?${query2}`, {
|
|
13349
13591
|
method: "DELETE",
|
|
13350
13592
|
headers: {
|
|
13351
13593
|
"X-Browser-Capability": instance.capability
|
|
@@ -13408,6 +13650,7 @@ async function cloneProfileForChild(opts) {
|
|
|
13408
13650
|
if (srcOwner === dstOwner && hasBrowserProfileTopic(opts.dstTopic)) {
|
|
13409
13651
|
const profile = getTopicBrowserProfile(opts.srcTopic);
|
|
13410
13652
|
assignTopicBrowserProfile({ topicId: opts.dstTopic, actorUserId: dstOwner, profile });
|
|
13653
|
+
setTopicBrowserConnectPort(opts.dstTopic, getTopicBrowserConnectPort(opts.srcTopic) ?? null);
|
|
13411
13654
|
const binding = resolvePlaywrightProfileBinding(srcOwner, profile);
|
|
13412
13655
|
const sharedDir = resolveUserDataDir(binding.instanceKey);
|
|
13413
13656
|
return {
|
|
@@ -13424,6 +13667,9 @@ async function cloneProfileForChild(opts) {
|
|
|
13424
13667
|
if (srcDir === dstDir) {
|
|
13425
13668
|
return { copied: false, srcDir, dstDir, reason: "same-dir" };
|
|
13426
13669
|
}
|
|
13670
|
+
if (parseConnectInstanceKey(srcKey) !== undefined || parseConnectInstanceKey(dstKey) !== undefined) {
|
|
13671
|
+
return { copied: false, srcDir, dstDir, reason: "connect-binding" };
|
|
13672
|
+
}
|
|
13427
13673
|
return withPlaywrightInstanceMaintenance([srcKey, dstKey], async () => {
|
|
13428
13674
|
const parentWasLive = instances.has(srcKey);
|
|
13429
13675
|
if (parentWasLive) {
|
|
@@ -14040,7 +14286,7 @@ async function runIdleCompactForTopic(topicId, userId, options = {}) {
|
|
|
14040
14286
|
return "below-threshold";
|
|
14041
14287
|
}
|
|
14042
14288
|
const compact = options.compact ?? (async (id, actorId, reason) => {
|
|
14043
|
-
await init_session();
|
|
14289
|
+
const { compactTopicSession } = await init_session().then(() => exports_session);
|
|
14044
14290
|
return compactTopicSession(id, actorId, reason, { preemptive: false });
|
|
14045
14291
|
});
|
|
14046
14292
|
try {
|
|
@@ -14240,40 +14486,40 @@ function beginTransientBackgroundSession(userId, session) {
|
|
|
14240
14486
|
update(status, step) {
|
|
14241
14487
|
if (finished)
|
|
14242
14488
|
return;
|
|
14243
|
-
const
|
|
14244
|
-
if (
|
|
14489
|
+
const current2 = transientSessions.get(record.id);
|
|
14490
|
+
if (current2 !== record)
|
|
14245
14491
|
return;
|
|
14246
14492
|
const nextStatus = text(status, 160);
|
|
14247
14493
|
if (nextStatus)
|
|
14248
|
-
|
|
14494
|
+
current2.status = nextStatus;
|
|
14249
14495
|
const nextStep = text(step);
|
|
14250
|
-
if (nextStep &&
|
|
14251
|
-
|
|
14496
|
+
if (nextStep && current2.steps.at(-1) !== nextStep) {
|
|
14497
|
+
current2.steps.push(nextStep);
|
|
14252
14498
|
}
|
|
14253
14499
|
},
|
|
14254
14500
|
setOutput(output) {
|
|
14255
14501
|
if (finished)
|
|
14256
14502
|
return;
|
|
14257
|
-
const
|
|
14258
|
-
if (
|
|
14503
|
+
const current2 = transientSessions.get(record.id);
|
|
14504
|
+
if (current2 !== record)
|
|
14259
14505
|
return;
|
|
14260
|
-
|
|
14506
|
+
current2.output = output;
|
|
14261
14507
|
},
|
|
14262
14508
|
finish(status, step) {
|
|
14263
14509
|
if (finished)
|
|
14264
14510
|
return;
|
|
14265
14511
|
this.update(status ?? record.status, step);
|
|
14266
14512
|
finished = true;
|
|
14267
|
-
const
|
|
14268
|
-
if (
|
|
14513
|
+
const current2 = transientSessions.get(record.id);
|
|
14514
|
+
if (current2 !== record)
|
|
14269
14515
|
return;
|
|
14270
|
-
|
|
14271
|
-
|
|
14272
|
-
|
|
14516
|
+
current2.active = false;
|
|
14517
|
+
current2.expiresAt = Date.now() + Math.max(0, retentionMs);
|
|
14518
|
+
current2.expiryTimer = setTimeout(() => {
|
|
14273
14519
|
if (transientSessions.get(record.id) === record)
|
|
14274
14520
|
transientSessions.delete(record.id);
|
|
14275
14521
|
}, Math.max(0, retentionMs));
|
|
14276
|
-
|
|
14522
|
+
current2.expiryTimer.unref?.();
|
|
14277
14523
|
}
|
|
14278
14524
|
};
|
|
14279
14525
|
}
|
|
@@ -14531,8 +14777,8 @@ function markRuntimeUserTurnMessagesLogged(topicId, requestId, ownerId, loggedUs
|
|
|
14531
14777
|
return false;
|
|
14532
14778
|
return db.transaction(() => {
|
|
14533
14779
|
const requests = db.query("SELECT * FROM runtime_user_turn_requests WHERE topic_id = ? ORDER BY created_at ASC, rowid ASC").all(topicId).map(rowToRequest);
|
|
14534
|
-
const hasLoggedPrefix = (
|
|
14535
|
-
const candidate =
|
|
14780
|
+
const hasLoggedPrefix = (request2) => loggedUserMessages.length <= request2.userMessages.length && loggedUserMessages.every((message, index) => {
|
|
14781
|
+
const candidate = request2.userMessages[index];
|
|
14536
14782
|
return candidate?.prompt === message.prompt && candidate.actorUserId === message.actorUserId && candidate.actorLabel === message.actorLabel && JSON.stringify(candidate.attachments ?? []) === JSON.stringify(message.attachments ?? []);
|
|
14537
14783
|
});
|
|
14538
14784
|
const request = requests.find((candidate) => candidate.requestId === requestId && candidate.claimedBy === ownerId && hasLoggedPrefix(candidate)) ?? requests.find((candidate) => candidate.execution?.supersededRequestIds?.includes(requestId) && hasLoggedPrefix(candidate));
|
|
@@ -14550,6 +14796,60 @@ function markRuntimeUserTurnMessagesLogged(topicId, requestId, ownerId, loggedUs
|
|
|
14550
14796
|
return result.changes === 1;
|
|
14551
14797
|
}).immediate();
|
|
14552
14798
|
}
|
|
14799
|
+
function claimNextRuntimeUserTurnRequest(ownerId, now = Date.now()) {
|
|
14800
|
+
return db.transaction(() => {
|
|
14801
|
+
const row = db.query(`SELECT r.*
|
|
14802
|
+
FROM runtime_user_turn_requests r
|
|
14803
|
+
LEFT JOIN runtime_turn_leases l ON l.topic_id = r.topic_id
|
|
14804
|
+
LEFT JOIN runtime_topic_state s ON s.topic_id = r.topic_id
|
|
14805
|
+
WHERE (l.topic_id IS NULL OR l.heartbeat_at < ?)
|
|
14806
|
+
AND (s.topic_id IS NULL OR s.maintenance = 0 OR s.heartbeat_at < ?)
|
|
14807
|
+
AND r.topic_epoch = COALESCE(s.epoch, 0)
|
|
14808
|
+
AND NOT EXISTS (
|
|
14809
|
+
SELECT 1
|
|
14810
|
+
FROM runtime_user_turn_requests active
|
|
14811
|
+
WHERE active.topic_id = r.topic_id
|
|
14812
|
+
AND active.request_id <> r.request_id
|
|
14813
|
+
AND active.claimed_at IS NOT NULL
|
|
14814
|
+
AND active.claimed_at >= ?
|
|
14815
|
+
)
|
|
14816
|
+
AND (
|
|
14817
|
+
(r.status = 'pending' AND (r.claimed_at IS NULL OR r.claimed_at < ?))
|
|
14818
|
+
OR (r.status = 'running' AND (r.claimed_at IS NULL OR r.claimed_at < ?))
|
|
14819
|
+
)
|
|
14820
|
+
ORDER BY r.created_at ASC, r.rowid ASC
|
|
14821
|
+
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);
|
|
14822
|
+
if (!row)
|
|
14823
|
+
return null;
|
|
14824
|
+
const updated = db.query(`UPDATE runtime_user_turn_requests
|
|
14825
|
+
SET claimed_by = ?, claimed_at = ?
|
|
14826
|
+
WHERE request_id = ? AND topic_id = ?
|
|
14827
|
+
AND (
|
|
14828
|
+
(status = 'pending' AND (claimed_at IS NULL OR claimed_at < ?))
|
|
14829
|
+
OR (status = 'running' AND (claimed_at IS NULL OR claimed_at < ?))
|
|
14830
|
+
)`).run(ownerId, now, row.request_id, row.topic_id, now - REQUEST_CLAIM_STALE_MS, now - REQUEST_CLAIM_STALE_MS);
|
|
14831
|
+
if (Number(updated.changes ?? 0) === 0)
|
|
14832
|
+
return null;
|
|
14833
|
+
return rowToRequest({ ...row, claimed_by: ownerId, claimed_at: now });
|
|
14834
|
+
}).immediate();
|
|
14835
|
+
}
|
|
14836
|
+
function markRuntimeUserTurnRunning(topicId, requestId, ownerId, queryId) {
|
|
14837
|
+
const result = db.query(`UPDATE runtime_user_turn_requests
|
|
14838
|
+
SET status = 'running', running_query_id = ?, claimed_at = ?
|
|
14839
|
+
WHERE topic_id = ? AND request_id = ? AND claimed_by = ?`).run(queryId, Date.now(), topicId, requestId, ownerId);
|
|
14840
|
+
return Number(result.changes ?? 0) > 0;
|
|
14841
|
+
}
|
|
14842
|
+
function releaseRuntimeUserTurnClaim(topicId, requestId, ownerId) {
|
|
14843
|
+
const result = db.query(`UPDATE runtime_user_turn_requests
|
|
14844
|
+
SET status = 'pending', claimed_by = NULL, claimed_at = NULL, running_query_id = NULL
|
|
14845
|
+
WHERE topic_id = ? AND request_id = ? AND claimed_by = ?`).run(topicId, requestId, ownerId);
|
|
14846
|
+
return Number(result.changes ?? 0) > 0;
|
|
14847
|
+
}
|
|
14848
|
+
function completeRuntimeUserTurnRequest(topicId, requestId, ownerId) {
|
|
14849
|
+
const result = db.query(`DELETE FROM runtime_user_turn_requests
|
|
14850
|
+
WHERE topic_id = ? AND request_id = ? AND claimed_by = ?`).run(topicId, requestId, ownerId);
|
|
14851
|
+
return Number(result.changes ?? 0) > 0;
|
|
14852
|
+
}
|
|
14553
14853
|
function cancelRuntimeUserTurnRequestsBeforeEpoch(topicId, epoch) {
|
|
14554
14854
|
const rows = db.query("SELECT request_id FROM runtime_user_turn_requests WHERE topic_id = ? AND topic_epoch < ?").all(topicId, epoch);
|
|
14555
14855
|
db.query("DELETE FROM runtime_user_turn_requests WHERE topic_id = ? AND topic_epoch < ?").run(topicId, epoch);
|
|
@@ -14587,10 +14887,36 @@ var init_runtime_turn_requests = __esm(async () => {
|
|
|
14587
14887
|
});
|
|
14588
14888
|
|
|
14589
14889
|
// ../../packages/core/src/topics/session.ts
|
|
14890
|
+
var exports_session = {};
|
|
14891
|
+
__export(exports_session, {
|
|
14892
|
+
splitCompactionPairs: () => splitCompactionPairs,
|
|
14893
|
+
shouldUseCompactionLog: () => shouldUseCompactionLog,
|
|
14894
|
+
shouldCompactForkEntries: () => shouldCompactForkEntries,
|
|
14895
|
+
restartTopicSession: () => restartTopicSession,
|
|
14896
|
+
createCompactedRolloutEntries: () => createCompactedRolloutEntries,
|
|
14897
|
+
compactTopicSession: () => compactTopicSession,
|
|
14898
|
+
COMPACTION_RETAINED_TAIL_TOKENS: () => COMPACTION_RETAINED_TAIL_TOKENS,
|
|
14899
|
+
AUTO_FORK_COMPACTION_TOKENS: () => AUTO_FORK_COMPACTION_TOKENS
|
|
14900
|
+
});
|
|
14590
14901
|
import { randomUUID as randomUUID12 } from "crypto";
|
|
14591
14902
|
import { mkdtempSync as mkdtempSync2, rmSync as rmSync4, writeFileSync as writeFileSync12 } from "fs";
|
|
14592
14903
|
import { tmpdir as tmpdir4 } from "os";
|
|
14593
14904
|
import { join as join23 } from "path";
|
|
14905
|
+
async function waitForMemoryArchive(settled, timeoutMs) {
|
|
14906
|
+
let timer;
|
|
14907
|
+
try {
|
|
14908
|
+
return await Promise.race([
|
|
14909
|
+
settled.then(() => true),
|
|
14910
|
+
new Promise((resolve17) => {
|
|
14911
|
+
timer = setTimeout(() => resolve17(false), timeoutMs);
|
|
14912
|
+
timer.unref?.();
|
|
14913
|
+
})
|
|
14914
|
+
]);
|
|
14915
|
+
} finally {
|
|
14916
|
+
if (timer)
|
|
14917
|
+
clearTimeout(timer);
|
|
14918
|
+
}
|
|
14919
|
+
}
|
|
14594
14920
|
async function fenceTopicWork(topicId, maintenance) {
|
|
14595
14921
|
for (const queryId of cancelRuntimeUserTurnRequestsBeforeEpoch(topicId, maintenance.epoch)) {
|
|
14596
14922
|
WsHub.get().broadcastAborted(topicId, queryId, "stopped");
|
|
@@ -14615,6 +14941,97 @@ function hasTopicWorkInFlight(topicId) {
|
|
|
14615
14941
|
function topicIsQuiescedForNonPreemptiveWork(topicId) {
|
|
14616
14942
|
return !hasTopicWorkInFlight(topicId);
|
|
14617
14943
|
}
|
|
14944
|
+
async function restartTopicSession(topicId, userId, reason = "topic-session-restart", options = {}) {
|
|
14945
|
+
const topic = getTopic(topicId);
|
|
14946
|
+
if (!topic)
|
|
14947
|
+
return { text: "Topic not found.", isError: true };
|
|
14948
|
+
if (isLegacySharedGeneral(topic.id)) {
|
|
14949
|
+
return { text: "The legacy shared General session cannot be reset.", isError: true };
|
|
14950
|
+
}
|
|
14951
|
+
const owner = topic.participants.some((participant) => participant.userId === userId && participant.role === "owner");
|
|
14952
|
+
if (!owner)
|
|
14953
|
+
return { text: "Only the topic owner can reset the session.", isError: true };
|
|
14954
|
+
const maintenance = beginRuntimeTopicMaintenance(topicId);
|
|
14955
|
+
if (!maintenance)
|
|
14956
|
+
return { text: "Topic maintenance is already in progress.", isError: true };
|
|
14957
|
+
try {
|
|
14958
|
+
const fenceError = await fenceTopicWork(topicId, maintenance);
|
|
14959
|
+
if (fenceError)
|
|
14960
|
+
return { text: fenceError, isError: true };
|
|
14961
|
+
cancelIdleArchiveForTopic(topicId);
|
|
14962
|
+
cancelIdleCompactForTopic(topicId);
|
|
14963
|
+
const rawArchivePaths = [];
|
|
14964
|
+
try {
|
|
14965
|
+
for (const participantUserId of new Set([
|
|
14966
|
+
userId,
|
|
14967
|
+
...topic.participants.map((participant) => participant.userId)
|
|
14968
|
+
])) {
|
|
14969
|
+
const archived = archiveConversationEvents(topicId, topic.title, participantUserId, {
|
|
14970
|
+
reason: "reset"
|
|
14971
|
+
});
|
|
14972
|
+
if (archived)
|
|
14973
|
+
rawArchivePaths.push(archived.path);
|
|
14974
|
+
}
|
|
14975
|
+
} catch (error) {
|
|
14976
|
+
return {
|
|
14977
|
+
text: `Session reset could not archive the raw conversation: ${error instanceof Error ? error.message : String(error)}`,
|
|
14978
|
+
isError: true
|
|
14979
|
+
};
|
|
14980
|
+
}
|
|
14981
|
+
let settleMemoryArchive;
|
|
14982
|
+
const memoryArchiveSettled = new Promise((resolve17) => {
|
|
14983
|
+
settleMemoryArchive = resolve17;
|
|
14984
|
+
});
|
|
14985
|
+
const archiveStatus = (options.archiveMemory ?? archiveActiveTopicForMemory)(topicId, options.memoryUserId ?? userId, {
|
|
14986
|
+
reason: "reset",
|
|
14987
|
+
minMessages: 1,
|
|
14988
|
+
minExchanges: MIN_MEMORY_ARCHIVE_EXCHANGES,
|
|
14989
|
+
allowMentionOnly: true,
|
|
14990
|
+
skipBusyCheck: true,
|
|
14991
|
+
rawArchivePaths,
|
|
14992
|
+
onSettled: () => settleMemoryArchive?.()
|
|
14993
|
+
});
|
|
14994
|
+
if (archiveStatus === "archived") {
|
|
14995
|
+
const archiveFinished = await waitForMemoryArchive(memoryArchiveSettled, options.memoryArchiveWaitMs ?? RESET_MEMORY_ARCHIVE_WAIT_MS);
|
|
14996
|
+
if (!archiveFinished) {
|
|
14997
|
+
return {
|
|
14998
|
+
text: "Memory archiving did not finish in time. The session was not reset.",
|
|
14999
|
+
isError: true
|
|
15000
|
+
};
|
|
15001
|
+
}
|
|
15002
|
+
}
|
|
15003
|
+
if (!maintenance.isOwned()) {
|
|
15004
|
+
return { text: "Topic maintenance ownership was lost. Try again.", isError: true };
|
|
15005
|
+
}
|
|
15006
|
+
const sessionId = getTopicSessionId(topicId);
|
|
15007
|
+
const purgeLogs = options.purgeLogs ?? purgeTopicLogs;
|
|
15008
|
+
const participantUserIds = Array.from(new Set([userId, ...topic.participants.map((participant) => participant.userId)]));
|
|
15009
|
+
for (const [index, participantUserId] of participantUserIds.entries()) {
|
|
15010
|
+
let purged = false;
|
|
15011
|
+
try {
|
|
15012
|
+
purged = await purgeLogs({
|
|
15013
|
+
userId: participantUserId,
|
|
15014
|
+
topicName: topic.title,
|
|
15015
|
+
cwd: resolveTopicWorkspaceDir(topicId),
|
|
15016
|
+
extraSessions: index === 0 && topic.agent && sessionId ? [{ agent: topic.agent, sessionId }] : []
|
|
15017
|
+
});
|
|
15018
|
+
} catch (error) {
|
|
15019
|
+
logger.warn({ err: error, topicId, userId: participantUserId }, "restartTopicSession: participant context cleanup failed");
|
|
15020
|
+
}
|
|
15021
|
+
if (!purged) {
|
|
15022
|
+
return {
|
|
15023
|
+
text: "Session reset could not remove all provider context. The current session was kept.",
|
|
15024
|
+
isError: true
|
|
15025
|
+
};
|
|
15026
|
+
}
|
|
15027
|
+
}
|
|
15028
|
+
clearTopicSessionId(topicId, reason);
|
|
15029
|
+
clearQueryUsageAlert(userId, topicId);
|
|
15030
|
+
return { text: `Session reset for "${topic.title}". The next message starts fresh.` };
|
|
15031
|
+
} finally {
|
|
15032
|
+
maintenance.finish();
|
|
15033
|
+
}
|
|
15034
|
+
}
|
|
14618
15035
|
function previousCompactedSummary(entries) {
|
|
14619
15036
|
for (let index = entries.length - 2;index >= 0; index -= 1) {
|
|
14620
15037
|
const request = entries[index]?.event;
|
|
@@ -14629,9 +15046,9 @@ The assistant response is the authoritative summary of all earlier context.` &&
|
|
|
14629
15046
|
function withoutCompactionSentinels(entries) {
|
|
14630
15047
|
const filtered = [];
|
|
14631
15048
|
for (let index = 0;index < entries.length; index++) {
|
|
14632
|
-
const
|
|
15049
|
+
const current2 = entries[index]?.event;
|
|
14633
15050
|
const next = entries[index + 1]?.event;
|
|
14634
|
-
if (
|
|
15051
|
+
if (current2?.type === "user_message" && current2.synthetic === "compaction" && next?.type === "result") {
|
|
14635
15052
|
index += 1;
|
|
14636
15053
|
continue;
|
|
14637
15054
|
}
|
|
@@ -14681,18 +15098,18 @@ function retainedPairEntries(agent, pairs) {
|
|
|
14681
15098
|
}
|
|
14682
15099
|
return entries;
|
|
14683
15100
|
}
|
|
14684
|
-
function fitCompactionChunk(
|
|
14685
|
-
if (
|
|
14686
|
-
return
|
|
15101
|
+
function fitCompactionChunk(text2, limit) {
|
|
15102
|
+
if (text2.length <= limit)
|
|
15103
|
+
return text2;
|
|
14687
15104
|
const marker = `
|
|
14688
15105
|
[\u2026]
|
|
14689
15106
|
`;
|
|
14690
15107
|
if (limit <= marker.length)
|
|
14691
|
-
return
|
|
15108
|
+
return text2.slice(0, limit);
|
|
14692
15109
|
const available = limit - marker.length;
|
|
14693
15110
|
const headChars = Math.ceil(available * 0.6);
|
|
14694
15111
|
const tailChars = available - headChars;
|
|
14695
|
-
return `${
|
|
15112
|
+
return `${text2.slice(0, headChars)}${marker}${text2.slice(-tailChars)}`;
|
|
14696
15113
|
}
|
|
14697
15114
|
function buildCompactionSource(topicId, userId, entries, visibleMessages, providerPairs) {
|
|
14698
15115
|
const sections = [];
|
|
@@ -15093,9 +15510,9 @@ async function compactTopicSession(topicId, userId, reason = "topic-session-comp
|
|
|
15093
15510
|
const compactionExecution = resolveCompactionExecution(agent, registry);
|
|
15094
15511
|
const cwd = resolveTopicWorkspaceDir(topicId);
|
|
15095
15512
|
const oldEntries = readConversation(userId, topic.title);
|
|
15096
|
-
let
|
|
15513
|
+
let compactEntries2;
|
|
15097
15514
|
try {
|
|
15098
|
-
|
|
15515
|
+
compactEntries2 = await createCompactedRolloutEntries({
|
|
15099
15516
|
topicId,
|
|
15100
15517
|
topicTitle: topic.title,
|
|
15101
15518
|
userId,
|
|
@@ -15121,7 +15538,7 @@ async function compactTopicSession(topicId, userId, reason = "topic-session-comp
|
|
|
15121
15538
|
try {
|
|
15122
15539
|
replacement = getRegistryOperations(agent).writeRollout({
|
|
15123
15540
|
cwd,
|
|
15124
|
-
entries:
|
|
15541
|
+
entries: compactEntries2,
|
|
15125
15542
|
model,
|
|
15126
15543
|
...effort ? { effort } : {}
|
|
15127
15544
|
});
|
|
@@ -15151,7 +15568,7 @@ async function compactTopicSession(topicId, userId, reason = "topic-session-comp
|
|
|
15151
15568
|
}
|
|
15152
15569
|
try {
|
|
15153
15570
|
replaceConversationStrict(userId, topic.title, [
|
|
15154
|
-
...
|
|
15571
|
+
...compactEntries2,
|
|
15155
15572
|
...priorSessionEntries,
|
|
15156
15573
|
replacementSessionEntry
|
|
15157
15574
|
]);
|
|
@@ -15188,7 +15605,7 @@ async function compactTopicSession(topicId, userId, reason = "topic-session-comp
|
|
|
15188
15605
|
} else {
|
|
15189
15606
|
try {
|
|
15190
15607
|
replaceConversationStrict(userId, topic.title, [
|
|
15191
|
-
...
|
|
15608
|
+
...compactEntries2,
|
|
15192
15609
|
replacementSessionEntry
|
|
15193
15610
|
]);
|
|
15194
15611
|
} catch (manifestError) {
|
|
@@ -15242,11 +15659,45 @@ var init_session = __esm(async () => {
|
|
|
15242
15659
|
});
|
|
15243
15660
|
|
|
15244
15661
|
// ../../packages/core/src/topics/derive.ts
|
|
15662
|
+
var exports_derive = {};
|
|
15663
|
+
__export(exports_derive, {
|
|
15664
|
+
updateTopic: () => updateTopic,
|
|
15665
|
+
isParticipant: () => isParticipant,
|
|
15666
|
+
getVisibleTopics: () => getVisibleTopics,
|
|
15667
|
+
getTopics: () => getTopics,
|
|
15668
|
+
createDerivedTopic: () => createDerivedTopic,
|
|
15669
|
+
TopicTitleConflictError: () => TopicTitleConflictError,
|
|
15670
|
+
TopicForkCompactionError: () => TopicForkCompactionError,
|
|
15671
|
+
TopicDeriveBusyError: () => TopicDeriveBusyError
|
|
15672
|
+
});
|
|
15245
15673
|
import { createHash as createHash9, randomUUID as randomUUID13 } from "crypto";
|
|
15246
15674
|
import { mkdirSync as mkdirSync14, rmSync as rmSync5, unlinkSync as unlinkSync13 } from "fs";
|
|
15247
15675
|
function getTopics(opts = {}) {
|
|
15248
15676
|
return listTopics(opts).filter((topic) => !isLegacySharedGeneral(topic.id));
|
|
15249
15677
|
}
|
|
15678
|
+
function getVisibleTopics(opts = {}) {
|
|
15679
|
+
return getTopics(opts).filter(isTopicVisible).map((topic) => {
|
|
15680
|
+
if (!topic.agent)
|
|
15681
|
+
return topic;
|
|
15682
|
+
const registry = getRegistry(topic.agent);
|
|
15683
|
+
const config = getApiTopicConfig(topic.id);
|
|
15684
|
+
const requestedEffort = config?.effort ?? topic.defaultEffort;
|
|
15685
|
+
return {
|
|
15686
|
+
...topic,
|
|
15687
|
+
effectiveModel: resolveModelForAgent(topic.agent, config?.model ?? topic.defaultModel, registry),
|
|
15688
|
+
effectiveEffort: requestedEffort && registry.validateEffort(requestedEffort) ? requestedEffort : registry.defaultEffort
|
|
15689
|
+
};
|
|
15690
|
+
});
|
|
15691
|
+
}
|
|
15692
|
+
function updateTopic(topicId, patch) {
|
|
15693
|
+
const topic = getTopic(topicId);
|
|
15694
|
+
if (!topic)
|
|
15695
|
+
return false;
|
|
15696
|
+
Object.assign(topic, patch);
|
|
15697
|
+
upsertTopic(topic);
|
|
15698
|
+
WsHub.get().broadcastTopicUpdated(topicId);
|
|
15699
|
+
return true;
|
|
15700
|
+
}
|
|
15250
15701
|
function isParticipant(topic, userId) {
|
|
15251
15702
|
return topic.participants.some((p) => p.userId === userId);
|
|
15252
15703
|
}
|
|
@@ -15662,9 +16113,9 @@ function subagentLineageTopicIds(currentTopicId) {
|
|
|
15662
16113
|
const children = new Set;
|
|
15663
16114
|
if (!currentTopicId)
|
|
15664
16115
|
return { reachable, children };
|
|
15665
|
-
const
|
|
15666
|
-
if (
|
|
15667
|
-
reachable.add(
|
|
16116
|
+
const current2 = getTopic(currentTopicId);
|
|
16117
|
+
if (current2?.isSubagent && current2.parentTopicId) {
|
|
16118
|
+
reachable.add(current2.parentTopicId);
|
|
15668
16119
|
for (const id of listSubagentTellTargetIds(currentTopicId))
|
|
15669
16120
|
reachable.add(id);
|
|
15670
16121
|
}
|
|
@@ -15790,9 +16241,9 @@ function cleanupSessionInboxFiles(userId, topicId, legacyTopicTitle) {
|
|
|
15790
16241
|
try {
|
|
15791
16242
|
unlinkSync15(path);
|
|
15792
16243
|
deleted++;
|
|
15793
|
-
} catch (
|
|
15794
|
-
if (
|
|
15795
|
-
logger.warn({ err, path, topicId, userId }, "topic cleanup: inbox unlink failed");
|
|
16244
|
+
} catch (err2) {
|
|
16245
|
+
if (err2?.code !== "ENOENT") {
|
|
16246
|
+
logger.warn({ err: err2, path, topicId, userId }, "topic cleanup: inbox unlink failed");
|
|
15796
16247
|
}
|
|
15797
16248
|
}
|
|
15798
16249
|
}
|
|
@@ -15917,9 +16368,9 @@ function hubHeaders(bearer) {
|
|
|
15917
16368
|
};
|
|
15918
16369
|
}
|
|
15919
16370
|
function errorText(status, body, fallback) {
|
|
15920
|
-
const
|
|
15921
|
-
if (typeof
|
|
15922
|
-
return
|
|
16371
|
+
const text2 = body?.error;
|
|
16372
|
+
if (typeof text2 === "string" && text2.trim())
|
|
16373
|
+
return text2.trim();
|
|
15923
16374
|
return `${fallback} (hub answered ${status})`;
|
|
15924
16375
|
}
|
|
15925
16376
|
function describeFailure(status, body) {
|
|
@@ -16015,6 +16466,19 @@ var init_actor_policy = __esm(async () => {
|
|
|
16015
16466
|
await init_actor_topic_reach();
|
|
16016
16467
|
});
|
|
16017
16468
|
// ../../packages/core/src/storage/session-asks.ts
|
|
16469
|
+
var exports_session_asks = {};
|
|
16470
|
+
__export(exports_session_asks, {
|
|
16471
|
+
releasePendingAsk: () => releasePendingAsk,
|
|
16472
|
+
markPendingAskState: () => markPendingAskState,
|
|
16473
|
+
markPendingAskSources: () => markPendingAskSources,
|
|
16474
|
+
listPendingAsksForCaller: () => listPendingAsksForCaller,
|
|
16475
|
+
describePendingAskState: () => describePendingAskState,
|
|
16476
|
+
deletePendingAsksForTopic: () => deletePendingAsksForTopic,
|
|
16477
|
+
createPendingAsk: () => createPendingAsk,
|
|
16478
|
+
clearPendingAskSources: () => clearPendingAskSources,
|
|
16479
|
+
clearPendingAsk: () => clearPendingAsk,
|
|
16480
|
+
PENDING_ASK_TTL_MS: () => PENDING_ASK_TTL_MS
|
|
16481
|
+
});
|
|
16018
16482
|
import { createHash as createHash10 } from "crypto";
|
|
16019
16483
|
import {
|
|
16020
16484
|
closeSync as closeSync2,
|
|
@@ -16036,8 +16500,8 @@ function encodeAskKey(key) {
|
|
|
16036
16500
|
return JSON.stringify([key.from, key.to]);
|
|
16037
16501
|
}
|
|
16038
16502
|
function pendingAskPath(key) {
|
|
16039
|
-
const
|
|
16040
|
-
return join28(pendingAskDir(key.userId), `${ASK_FILENAME_PREFIX}${
|
|
16503
|
+
const digest2 = createHash10("sha256").update(encodeAskKey(key)).digest("hex");
|
|
16504
|
+
return join28(pendingAskDir(key.userId), `${ASK_FILENAME_PREFIX}${digest2}.pending`);
|
|
16041
16505
|
}
|
|
16042
16506
|
function v2PendingAskPath(key) {
|
|
16043
16507
|
const encoded = Buffer.from(encodeAskKey(key), "utf8").toString("base64url");
|
|
@@ -16063,10 +16527,10 @@ function parsePendingAskFilename(fileName) {
|
|
|
16063
16527
|
}
|
|
16064
16528
|
} catch {}
|
|
16065
16529
|
}
|
|
16066
|
-
const
|
|
16067
|
-
if (
|
|
16530
|
+
const sep3 = raw.indexOf("___");
|
|
16531
|
+
if (sep3 < 0)
|
|
16068
16532
|
return null;
|
|
16069
|
-
return { from: raw.slice(0,
|
|
16533
|
+
return { from: raw.slice(0, sep3), to: raw.slice(sep3 + 3) };
|
|
16070
16534
|
}
|
|
16071
16535
|
function readPendingAskFile(path, fallback) {
|
|
16072
16536
|
try {
|
|
@@ -16109,6 +16573,16 @@ function readPendingAskFile(path, fallback) {
|
|
|
16109
16573
|
return null;
|
|
16110
16574
|
}
|
|
16111
16575
|
}
|
|
16576
|
+
function isStale(record, path) {
|
|
16577
|
+
const ts = record ? Date.parse(record.updatedAt || record.createdAt) : Number.NaN;
|
|
16578
|
+
if (Number.isFinite(ts))
|
|
16579
|
+
return Date.now() - ts > PENDING_ASK_TTL_MS;
|
|
16580
|
+
try {
|
|
16581
|
+
return Date.now() - statSync8(path).mtimeMs > PENDING_ASK_TTL_MS;
|
|
16582
|
+
} catch {
|
|
16583
|
+
return false;
|
|
16584
|
+
}
|
|
16585
|
+
}
|
|
16112
16586
|
function writePendingAsk(record) {
|
|
16113
16587
|
const path = pendingAskPath(record);
|
|
16114
16588
|
mkdirSync16(pendingAskDir(record.userId), { recursive: true });
|
|
@@ -16134,10 +16608,10 @@ function writePendingAskIfAbsent(record) {
|
|
|
16134
16608
|
}
|
|
16135
16609
|
}
|
|
16136
16610
|
function readPendingAsk(key) {
|
|
16137
|
-
const
|
|
16138
|
-
const canonical = readPendingAskFile(
|
|
16611
|
+
const canonicalPath2 = pendingAskPath(key);
|
|
16612
|
+
const canonical = readPendingAskFile(canonicalPath2, key);
|
|
16139
16613
|
if (canonical && canonical.from === key.from && canonical.to === key.to) {
|
|
16140
|
-
return { path:
|
|
16614
|
+
return { path: canonicalPath2, record: canonical };
|
|
16141
16615
|
}
|
|
16142
16616
|
for (const compatibilityPath of [v2PendingAskPath(key), legacyPendingAskPath(key)]) {
|
|
16143
16617
|
if (!compatibilityPath)
|
|
@@ -16146,17 +16620,67 @@ function readPendingAsk(key) {
|
|
|
16146
16620
|
if (!legacy || legacy.from !== key.from || legacy.to !== key.to)
|
|
16147
16621
|
continue;
|
|
16148
16622
|
const migrated = writePendingAskIfAbsent(legacy);
|
|
16149
|
-
const next = migrated ? legacy : readPendingAskFile(
|
|
16623
|
+
const next = migrated ? legacy : readPendingAskFile(canonicalPath2, key);
|
|
16150
16624
|
if (next && next.from === key.from && next.to === key.to) {
|
|
16151
16625
|
try {
|
|
16152
16626
|
unlinkSync16(compatibilityPath);
|
|
16153
16627
|
} catch {}
|
|
16154
|
-
return { path:
|
|
16628
|
+
return { path: canonicalPath2, record: next };
|
|
16155
16629
|
}
|
|
16156
16630
|
return { path: compatibilityPath, record: legacy };
|
|
16157
16631
|
}
|
|
16158
16632
|
return null;
|
|
16159
16633
|
}
|
|
16634
|
+
function createPendingAsk(args) {
|
|
16635
|
+
const migrated = readPendingAsk(args);
|
|
16636
|
+
if (migrated && !isStale(migrated.record, migrated.path)) {
|
|
16637
|
+
return { ok: false, existing: migrated.record, stale: false };
|
|
16638
|
+
}
|
|
16639
|
+
if (migrated) {
|
|
16640
|
+
try {
|
|
16641
|
+
unlinkSync16(migrated.path);
|
|
16642
|
+
} catch {
|
|
16643
|
+
return { ok: false, existing: migrated.record, stale: true };
|
|
16644
|
+
}
|
|
16645
|
+
}
|
|
16646
|
+
const path = pendingAskPath(args);
|
|
16647
|
+
const now = new Date().toISOString();
|
|
16648
|
+
const record = {
|
|
16649
|
+
userId: args.userId,
|
|
16650
|
+
from: args.from,
|
|
16651
|
+
to: args.to,
|
|
16652
|
+
requestId: args.requestId,
|
|
16653
|
+
contextId: args.contextId,
|
|
16654
|
+
state: "requested",
|
|
16655
|
+
createdAt: now,
|
|
16656
|
+
updatedAt: now
|
|
16657
|
+
};
|
|
16658
|
+
mkdirSync16(pendingAskDir(args.userId), { recursive: true });
|
|
16659
|
+
for (let attempt = 0;attempt < 2; attempt++) {
|
|
16660
|
+
let fd = null;
|
|
16661
|
+
try {
|
|
16662
|
+
fd = openSync2(path, "wx");
|
|
16663
|
+
writeFileSync14(fd, `${JSON.stringify(record)}
|
|
16664
|
+
`);
|
|
16665
|
+
return { ok: true, record };
|
|
16666
|
+
} catch (err2) {
|
|
16667
|
+
if (err2.code !== "EEXIST")
|
|
16668
|
+
throw err2;
|
|
16669
|
+
const existing = readPendingAskFile(path, args);
|
|
16670
|
+
if (!isStale(existing, path))
|
|
16671
|
+
return { ok: false, existing, stale: false };
|
|
16672
|
+
try {
|
|
16673
|
+
unlinkSync16(path);
|
|
16674
|
+
} catch {
|
|
16675
|
+
return { ok: false, existing, stale: true };
|
|
16676
|
+
}
|
|
16677
|
+
} finally {
|
|
16678
|
+
if (fd !== null)
|
|
16679
|
+
closeSync2(fd);
|
|
16680
|
+
}
|
|
16681
|
+
}
|
|
16682
|
+
return { ok: false, existing: readPendingAskFile(path, args), stale: true };
|
|
16683
|
+
}
|
|
16160
16684
|
function markPendingAskState(args) {
|
|
16161
16685
|
const pending = readPendingAsk(args);
|
|
16162
16686
|
if (!pending)
|
|
@@ -16190,6 +16714,83 @@ function clearPendingAsk(args) {
|
|
|
16190
16714
|
return false;
|
|
16191
16715
|
}
|
|
16192
16716
|
}
|
|
16717
|
+
function releasePendingAsk(args) {
|
|
16718
|
+
if (clearPendingAsk(args))
|
|
16719
|
+
return true;
|
|
16720
|
+
const still = readPendingAsk(args);
|
|
16721
|
+
return !still || still.record.requestId !== args.requestId;
|
|
16722
|
+
}
|
|
16723
|
+
function markPendingAskSources(args) {
|
|
16724
|
+
for (const source of args.sources ?? []) {
|
|
16725
|
+
if (!source.from)
|
|
16726
|
+
continue;
|
|
16727
|
+
markPendingAskState({
|
|
16728
|
+
userId: args.userId,
|
|
16729
|
+
from: args.callerTopic,
|
|
16730
|
+
to: source.from,
|
|
16731
|
+
requestId: source.requestId,
|
|
16732
|
+
state: args.state
|
|
16733
|
+
});
|
|
16734
|
+
}
|
|
16735
|
+
}
|
|
16736
|
+
function clearPendingAskSources(args) {
|
|
16737
|
+
for (const source of args.sources ?? []) {
|
|
16738
|
+
if (!source.from)
|
|
16739
|
+
continue;
|
|
16740
|
+
clearPendingAsk({
|
|
16741
|
+
userId: args.userId,
|
|
16742
|
+
from: args.callerTopic,
|
|
16743
|
+
to: source.from,
|
|
16744
|
+
requestId: source.requestId
|
|
16745
|
+
});
|
|
16746
|
+
}
|
|
16747
|
+
}
|
|
16748
|
+
function listPendingAsksForCaller(args) {
|
|
16749
|
+
const dir = pendingAskDir(args.userId);
|
|
16750
|
+
let files;
|
|
16751
|
+
try {
|
|
16752
|
+
files = readdirSync4(dir);
|
|
16753
|
+
} catch {
|
|
16754
|
+
return [];
|
|
16755
|
+
}
|
|
16756
|
+
const records = new Map;
|
|
16757
|
+
for (const fileName of files) {
|
|
16758
|
+
const isV3 = fileName.startsWith(ASK_FILENAME_PREFIX);
|
|
16759
|
+
const parsed = isV3 ? { from: args.from, to: "" } : parsePendingAskFilename(fileName);
|
|
16760
|
+
if (!parsed)
|
|
16761
|
+
continue;
|
|
16762
|
+
const path = join28(dir, fileName);
|
|
16763
|
+
const record = readPendingAskFile(path, {
|
|
16764
|
+
userId: args.userId,
|
|
16765
|
+
from: parsed.from,
|
|
16766
|
+
to: parsed.to
|
|
16767
|
+
});
|
|
16768
|
+
if (!record || record.from !== args.from)
|
|
16769
|
+
continue;
|
|
16770
|
+
if (isStale(record, path)) {
|
|
16771
|
+
try {
|
|
16772
|
+
unlinkSync16(path);
|
|
16773
|
+
} catch {}
|
|
16774
|
+
continue;
|
|
16775
|
+
}
|
|
16776
|
+
const canonical = readPendingAsk(record);
|
|
16777
|
+
if (!canonical || canonical.record.from !== args.from)
|
|
16778
|
+
continue;
|
|
16779
|
+
if (path !== canonical.path) {
|
|
16780
|
+
try {
|
|
16781
|
+
unlinkSync16(path);
|
|
16782
|
+
} catch {}
|
|
16783
|
+
}
|
|
16784
|
+
if (isStale(canonical.record, canonical.path)) {
|
|
16785
|
+
try {
|
|
16786
|
+
unlinkSync16(canonical.path);
|
|
16787
|
+
} catch {}
|
|
16788
|
+
continue;
|
|
16789
|
+
}
|
|
16790
|
+
records.set(encodeAskKey(canonical.record), canonical.record);
|
|
16791
|
+
}
|
|
16792
|
+
return [...records.values()];
|
|
16793
|
+
}
|
|
16193
16794
|
function deletePendingAsksForTopic(args) {
|
|
16194
16795
|
const dir = pendingAskDir(args.userId);
|
|
16195
16796
|
let files;
|
|
@@ -16218,6 +16819,18 @@ function deletePendingAsksForTopic(args) {
|
|
|
16218
16819
|
}
|
|
16219
16820
|
return deleted;
|
|
16220
16821
|
}
|
|
16822
|
+
function describePendingAskState(state) {
|
|
16823
|
+
switch (state) {
|
|
16824
|
+
case "requested":
|
|
16825
|
+
return "\uB300\uC0C1 \uC138\uC158 \uCC98\uB9AC \uC911";
|
|
16826
|
+
case "reply_ready":
|
|
16827
|
+
return "\uC751\uB2F5 \uC0DD\uC131 \uC644\uB8CC, \uC774 \uC138\uC158 \uC8FC\uC785 \uC900\uBE44 \uC911";
|
|
16828
|
+
case "queued_for_caller":
|
|
16829
|
+
return "\uC751\uB2F5 \uC0DD\uC131 \uC644\uB8CC, \uC774 \uC138\uC158 \uC2E4\uD589 \uC885\uB8CC \uD6C4 \uC8FC\uC785 \uB300\uAE30 \uC911";
|
|
16830
|
+
case "injecting_to_caller":
|
|
16831
|
+
return "\uC751\uB2F5\uC744 \uC774 \uC138\uC158\uC5D0 \uC8FC\uC785 \uC911";
|
|
16832
|
+
}
|
|
16833
|
+
}
|
|
16221
16834
|
var PENDING_ASK_TTL_MS, ASK_FILENAME_PREFIX = "v3-", V2_ASK_FILENAME_PREFIX = "v2-";
|
|
16222
16835
|
var init_session_asks = __esm(async () => {
|
|
16223
16836
|
await init_storage_host();
|
|
@@ -16319,10 +16932,10 @@ function deferRemoteSessionReplyOutbox(args) {
|
|
|
16319
16932
|
if (!row)
|
|
16320
16933
|
return;
|
|
16321
16934
|
const attempts = Number(row.attempts) + 1;
|
|
16322
|
-
const
|
|
16935
|
+
const delay2 = args.retryMs ?? remoteSessionRetryDelayMs(attempts, args.random);
|
|
16323
16936
|
db.query(`UPDATE remote_session_reply_outbox
|
|
16324
16937
|
SET attempts = ?, next_attempt_at = ?, last_error = ?
|
|
16325
|
-
WHERE request_id = ?`).run(attempts, now +
|
|
16938
|
+
WHERE request_id = ?`).run(attempts, now + delay2, args.error.slice(0, 500), args.requestId);
|
|
16326
16939
|
})();
|
|
16327
16940
|
}
|
|
16328
16941
|
function purgeExpiredRemoteSessionReplyOutbox(now = Date.now()) {
|
|
@@ -16493,9 +17106,37 @@ var init_remote_session_reply_outbox = __esm(async () => {
|
|
|
16493
17106
|
});
|
|
16494
17107
|
|
|
16495
17108
|
// ../../packages/core/src/mcp/session-comm/peer-forward.ts
|
|
17109
|
+
var exports_peer_forward = {};
|
|
17110
|
+
__export(exports_peer_forward, {
|
|
17111
|
+
registerPeerSessionBridge: () => registerPeerSessionBridge,
|
|
17112
|
+
peerSessionsForUser: () => peerSessionsForUser,
|
|
17113
|
+
parseHubRemoteReplyRoute: () => parseHubRemoteReplyRoute,
|
|
17114
|
+
isHubRemoteReplyRoute: () => isHubRemoteReplyRoute,
|
|
17115
|
+
forwardToPeer: () => forwardToPeer,
|
|
17116
|
+
deliverPeerReply: () => deliverPeerReply
|
|
17117
|
+
});
|
|
16496
17118
|
function isHubRemoteReplyRoute(route) {
|
|
16497
17119
|
return route.via === "hub";
|
|
16498
17120
|
}
|
|
17121
|
+
function parseHubRemoteReplyRoute(value) {
|
|
17122
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
17123
|
+
return null;
|
|
17124
|
+
const route = value;
|
|
17125
|
+
if (route.via !== "hub" || typeof route.hubUrl !== "string" || typeof route.token !== "string" || typeof route.nodeName !== "string" || typeof route.topicId !== "string" || typeof route.requestId !== "string") {
|
|
17126
|
+
return null;
|
|
17127
|
+
}
|
|
17128
|
+
const requestId = route.requestId.trim();
|
|
17129
|
+
const nodeName = route.nodeName.trim();
|
|
17130
|
+
const topicId = route.topicId.trim();
|
|
17131
|
+
const token = route.token.trim();
|
|
17132
|
+
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)) {
|
|
17133
|
+
return null;
|
|
17134
|
+
}
|
|
17135
|
+
const hubUrl = normalizeHubUrl(route.hubUrl.trim(), "remoteReply.hubUrl");
|
|
17136
|
+
if ("error" in hubUrl)
|
|
17137
|
+
return null;
|
|
17138
|
+
return { via: "hub", hubUrl: hubUrl.url, token, nodeName, topicId, requestId };
|
|
17139
|
+
}
|
|
16499
17140
|
function loopbackBridgeConfig() {
|
|
16500
17141
|
const rawUrl = process.env[PEER_BRIDGE_URL_ENV]?.trim();
|
|
16501
17142
|
const token = process.env[PEER_BRIDGE_TOKEN_ENV]?.trim();
|
|
@@ -16532,6 +17173,39 @@ async function callLoopbackBridge(request) {
|
|
|
16532
17173
|
return { configured: true, result: null };
|
|
16533
17174
|
}
|
|
16534
17175
|
}
|
|
17176
|
+
function registerPeerSessionBridge(bridge) {
|
|
17177
|
+
activeBridge = bridge;
|
|
17178
|
+
return () => {
|
|
17179
|
+
if (activeBridge === bridge)
|
|
17180
|
+
activeBridge = null;
|
|
17181
|
+
};
|
|
17182
|
+
}
|
|
17183
|
+
async function forwardToPeer(args) {
|
|
17184
|
+
if (activeBridge)
|
|
17185
|
+
return activeBridge.forward(args);
|
|
17186
|
+
const forwarded = await callLoopbackBridge({ action: "forward", args });
|
|
17187
|
+
if (forwarded.result)
|
|
17188
|
+
return forwarded.result;
|
|
17189
|
+
return {
|
|
17190
|
+
ok: false,
|
|
17191
|
+
error: forwarded.configured ? "remote session bridge is configured but unavailable" : "remote nodes are not connected on this negotium node (standalone mode)"
|
|
17192
|
+
};
|
|
17193
|
+
}
|
|
17194
|
+
async function peerSessionsForUser(userId, sourceQueryId, fromTopicId) {
|
|
17195
|
+
if (activeBridge)
|
|
17196
|
+
return activeBridge.sessions(userId, sourceQueryId, fromTopicId);
|
|
17197
|
+
const sessions = await callLoopbackBridge({
|
|
17198
|
+
action: "sessions",
|
|
17199
|
+
userId,
|
|
17200
|
+
sourceQueryId,
|
|
17201
|
+
fromTopicId
|
|
17202
|
+
});
|
|
17203
|
+
if (sessions.result)
|
|
17204
|
+
return sessions.result;
|
|
17205
|
+
if (sessions.configured)
|
|
17206
|
+
return { ok: false, nodes: [] };
|
|
17207
|
+
return { ok: true, nodes: [] };
|
|
17208
|
+
}
|
|
16535
17209
|
async function deliverPeerReply(route, sourceTitle, replyText, kind) {
|
|
16536
17210
|
if (isHubRemoteReplyRoute(route)) {
|
|
16537
17211
|
return deliverHubRemoteReply(route, sourceTitle, replyText, kind);
|
|
@@ -16546,13 +17220,40 @@ async function deliverPeerReply(route, sourceTitle, replyText, kind) {
|
|
|
16546
17220
|
kind
|
|
16547
17221
|
})).result ?? false;
|
|
16548
17222
|
}
|
|
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;
|
|
17223
|
+
var MAX_ROUTE_REQUEST_ID_LENGTH = 200, MAX_ROUTE_LABEL_LENGTH = 300, 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;
|
|
16550
17224
|
var init_peer_forward = __esm(async () => {
|
|
16551
17225
|
init_remote_session_grant();
|
|
16552
17226
|
await init_remote_session_reply_outbox();
|
|
16553
17227
|
});
|
|
16554
17228
|
|
|
16555
17229
|
// ../../packages/core/src/runtime/ask-callbacks.ts
|
|
17230
|
+
var exports_ask_callbacks = {};
|
|
17231
|
+
__export(exports_ask_callbacks, {
|
|
17232
|
+
resolveAskCallback: () => resolveAskCallback,
|
|
17233
|
+
registerAskCallback: () => registerAskCallback,
|
|
17234
|
+
purgeStaleAsks: () => purgeStaleAsks,
|
|
17235
|
+
failInterruptedRemoteAskCallbacks: () => failInterruptedRemoteAskCallbacks,
|
|
17236
|
+
deleteHubRemoteAskCallbackRow: () => deleteHubRemoteAskCallbackRow,
|
|
17237
|
+
cancelAskCallbacksForTopic: () => cancelAskCallbacksForTopic
|
|
17238
|
+
});
|
|
17239
|
+
function registerAskCallback(entry) {
|
|
17240
|
+
pendingAsks.set(entry.targetQueryId, entry);
|
|
17241
|
+
if (entry.remoteReply) {
|
|
17242
|
+
const route = entry.remoteReply;
|
|
17243
|
+
const hub = isHubRemoteReplyRoute(route);
|
|
17244
|
+
db.query(`INSERT INTO remote_ask_callbacks
|
|
17245
|
+
(target_query_id, request_id, node_name, node_cell_id, topic_id, user_id, created_at, route_json)
|
|
17246
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
17247
|
+
ON CONFLICT(target_query_id) DO UPDATE SET
|
|
17248
|
+
request_id = excluded.request_id,
|
|
17249
|
+
node_name = excluded.node_name,
|
|
17250
|
+
node_cell_id = excluded.node_cell_id,
|
|
17251
|
+
topic_id = excluded.topic_id,
|
|
17252
|
+
user_id = excluded.user_id,
|
|
17253
|
+
created_at = excluded.created_at,
|
|
17254
|
+
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);
|
|
17255
|
+
}
|
|
17256
|
+
}
|
|
16556
17257
|
function resolveAskCallback(queryId) {
|
|
16557
17258
|
const entry = pendingAsks.get(queryId);
|
|
16558
17259
|
if (!entry)
|
|
@@ -16569,6 +17270,13 @@ function resolveAskCallback(queryId) {
|
|
|
16569
17270
|
function deleteHubRemoteAskCallbackRow(requestId) {
|
|
16570
17271
|
db.query("DELETE FROM remote_ask_callbacks WHERE request_id = ? AND route_json IS NOT NULL").run(requestId);
|
|
16571
17272
|
}
|
|
17273
|
+
function purgeStaleAsks(now = Date.now()) {
|
|
17274
|
+
for (const [id, entry] of pendingAsks) {
|
|
17275
|
+
if (now - entry.createdAt > MAX_ASK_AGE_MS)
|
|
17276
|
+
pendingAsks.delete(id);
|
|
17277
|
+
}
|
|
17278
|
+
db.query("DELETE FROM remote_ask_callbacks WHERE created_at < ?").run(now - MAX_ASK_AGE_MS);
|
|
17279
|
+
}
|
|
16572
17280
|
function cancelAskCallbacksForTopic(topicId) {
|
|
16573
17281
|
let cancelled = 0;
|
|
16574
17282
|
for (const [queryId, entry] of pendingAsks) {
|
|
@@ -16580,6 +17288,43 @@ function cancelAskCallbacksForTopic(topicId) {
|
|
|
16580
17288
|
}
|
|
16581
17289
|
return cancelled;
|
|
16582
17290
|
}
|
|
17291
|
+
function durableRoute(row) {
|
|
17292
|
+
if (row.route_json) {
|
|
17293
|
+
try {
|
|
17294
|
+
return parseHubRemoteReplyRoute(JSON.parse(row.route_json));
|
|
17295
|
+
} catch {
|
|
17296
|
+
return null;
|
|
17297
|
+
}
|
|
17298
|
+
}
|
|
17299
|
+
return {
|
|
17300
|
+
nodeName: row.node_name,
|
|
17301
|
+
nodeCellId: row.node_cell_id,
|
|
17302
|
+
topicId: row.topic_id,
|
|
17303
|
+
userId: row.user_id,
|
|
17304
|
+
requestId: row.request_id
|
|
17305
|
+
};
|
|
17306
|
+
}
|
|
17307
|
+
async function failInterruptedRemoteAskCallbacks(options = {}) {
|
|
17308
|
+
const rows = db.query(`SELECT target_query_id, request_id, node_name, node_cell_id, topic_id, user_id, route_json
|
|
17309
|
+
FROM remote_ask_callbacks
|
|
17310
|
+
ORDER BY created_at ASC`).all();
|
|
17311
|
+
let failed = 0;
|
|
17312
|
+
for (const row of rows) {
|
|
17313
|
+
const route = durableRoute(row);
|
|
17314
|
+
if (!route) {
|
|
17315
|
+
db.query("DELETE FROM remote_ask_callbacks WHERE target_query_id = ?").run(row.target_query_id);
|
|
17316
|
+
continue;
|
|
17317
|
+
}
|
|
17318
|
+
if (options.routes === "hub" && !isHubRemoteReplyRoute(route))
|
|
17319
|
+
continue;
|
|
17320
|
+
const delivered = await deliverPeerReply(route, "peer", "The remote worker restarted before this ask completed. Please retry the request.", "error");
|
|
17321
|
+
if (!delivered)
|
|
17322
|
+
continue;
|
|
17323
|
+
db.query("DELETE FROM remote_ask_callbacks WHERE target_query_id = ?").run(row.target_query_id);
|
|
17324
|
+
failed++;
|
|
17325
|
+
}
|
|
17326
|
+
return failed;
|
|
17327
|
+
}
|
|
16583
17328
|
var pendingAsks, MAX_ASK_AGE_MS;
|
|
16584
17329
|
var init_ask_callbacks = __esm(async () => {
|
|
16585
17330
|
await __promiseAll([
|
|
@@ -17005,6 +17750,14 @@ var init_topic_tool_capabilities = __esm(async () => {
|
|
|
17005
17750
|
});
|
|
17006
17751
|
|
|
17007
17752
|
// ../../packages/core/src/topics/lifecycle.ts
|
|
17753
|
+
var exports_lifecycle = {};
|
|
17754
|
+
__export(exports_lifecycle, {
|
|
17755
|
+
deleteTopicCascade: () => deleteTopicCascade,
|
|
17756
|
+
TopicTurnStillActiveError: () => TopicTurnStillActiveError,
|
|
17757
|
+
TopicDeleteVetoedError: () => TopicDeleteVetoedError,
|
|
17758
|
+
TopicCleanupRequiredError: () => TopicCleanupRequiredError,
|
|
17759
|
+
TopicArchiveRequiredError: () => TopicArchiveRequiredError
|
|
17760
|
+
});
|
|
17008
17761
|
import { rmSync as rmSync6 } from "fs";
|
|
17009
17762
|
async function abortAndWaitForTopic(topicId) {
|
|
17010
17763
|
interSessionQueue.drop(topicId);
|
|
@@ -17037,8 +17790,8 @@ async function cleanupParticipantResources(topic, userIds, sessionId, cwd, purge
|
|
|
17037
17790
|
cwd,
|
|
17038
17791
|
extraSessions: index === 0 ? currentSessionRef(topic, sessionId) : []
|
|
17039
17792
|
});
|
|
17040
|
-
} catch (
|
|
17041
|
-
logger.warn({ err, topicId: topic.id, userId: participantUserId }, "deleteTopicCascade: participant rollout cleanup failed");
|
|
17793
|
+
} catch (err2) {
|
|
17794
|
+
logger.warn({ err: err2, topicId: topic.id, userId: participantUserId }, "deleteTopicCascade: participant rollout cleanup failed");
|
|
17042
17795
|
}
|
|
17043
17796
|
if (!purged)
|
|
17044
17797
|
return false;
|
|
@@ -17094,12 +17847,12 @@ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorId
|
|
|
17094
17847
|
if (rawArchive)
|
|
17095
17848
|
rawArchives.push(rawArchive.path);
|
|
17096
17849
|
}
|
|
17097
|
-
} catch (
|
|
17850
|
+
} catch (err2) {
|
|
17098
17851
|
if (!force) {
|
|
17099
|
-
logger.warn({ err, topicId }, "deleteTopicCascade: archive failed - blocking delete unless force=true");
|
|
17100
|
-
throw new TopicArchiveRequiredError(topicId,
|
|
17852
|
+
logger.warn({ err: err2, topicId }, "deleteTopicCascade: archive failed - blocking delete unless force=true");
|
|
17853
|
+
throw new TopicArchiveRequiredError(topicId, err2);
|
|
17101
17854
|
}
|
|
17102
|
-
logger.warn({ err, topicId }, "deleteTopicCascade: archive failed but force=true - continuing with hard delete");
|
|
17855
|
+
logger.warn({ err: err2, topicId }, "deleteTopicCascade: archive failed but force=true - continuing with hard delete");
|
|
17103
17856
|
}
|
|
17104
17857
|
}
|
|
17105
17858
|
if (archived && meetsMemoryArchiveExchangeThreshold(archived.exchangeCount, MIN_MEMORY_ARCHIVE_EXCHANGES, topic)) {
|
|
@@ -17115,8 +17868,8 @@ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorId
|
|
|
17115
17868
|
...rawArchives.length > 0 ? { rawArchivePaths: rawArchives } : {},
|
|
17116
17869
|
messageCount: archived.messageCount
|
|
17117
17870
|
});
|
|
17118
|
-
} catch (
|
|
17119
|
-
logger.warn({ err, topicId, archive: archived.path }, "deleteTopicCascade: background archiver launch failed - raw archive preserved");
|
|
17871
|
+
} catch (err2) {
|
|
17872
|
+
logger.warn({ err: err2, topicId, archive: archived.path }, "deleteTopicCascade: background archiver launch failed - raw archive preserved");
|
|
17120
17873
|
}
|
|
17121
17874
|
}
|
|
17122
17875
|
const sessionId = getTopicSessionId(topicId);
|
|
@@ -17131,25 +17884,23 @@ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorId
|
|
|
17131
17884
|
await deleteTopicCascadeImpl(child, userId, childOptions, deletingTopicIds);
|
|
17132
17885
|
}
|
|
17133
17886
|
killBgBash(userId, topicId);
|
|
17134
|
-
const browserProfileOwner = getBrowserProfileOwner(topicId, userId);
|
|
17135
|
-
const browserProfile = getTopicBrowserProfile(topicId);
|
|
17136
17887
|
try {
|
|
17137
|
-
await
|
|
17138
|
-
} catch (
|
|
17139
|
-
logger.warn({ err, topicId }, "deleteTopicCascade: browser owner cleanup failed");
|
|
17888
|
+
await closeTopicBrowserTabs(userId, topicId);
|
|
17889
|
+
} catch (err2) {
|
|
17890
|
+
logger.warn({ err: err2, topicId }, "deleteTopicCascade: browser owner cleanup failed");
|
|
17140
17891
|
}
|
|
17141
17892
|
deleteTopicProfileDir(userId, topicId);
|
|
17142
17893
|
cancelAskCallbacksForTopic(topicId);
|
|
17143
17894
|
deleteSelfSchedulesForTopic(topicId);
|
|
17144
17895
|
try {
|
|
17145
17896
|
await deleteFilesForTopic(topicId);
|
|
17146
|
-
} catch (
|
|
17147
|
-
logger.warn({ err, topicId }, "deleteTopicCascade: host file cleanup failed");
|
|
17897
|
+
} catch (err2) {
|
|
17898
|
+
logger.warn({ err: err2, topicId }, "deleteTopicCascade: host file cleanup failed");
|
|
17148
17899
|
}
|
|
17149
17900
|
try {
|
|
17150
17901
|
rmSync6(cwd, { recursive: true, force: true });
|
|
17151
|
-
} catch (
|
|
17152
|
-
logger.warn({ err, topicId, cwd }, "deleteTopicCascade: workspace cleanup failed");
|
|
17902
|
+
} catch (err2) {
|
|
17903
|
+
logger.warn({ err: err2, topicId, cwd }, "deleteTopicCascade: workspace cleanup failed");
|
|
17153
17904
|
}
|
|
17154
17905
|
deleteTopicVisuals(topicId);
|
|
17155
17906
|
deleteTopicHostMcpGrant(topicId);
|
|
@@ -17191,7 +17942,7 @@ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorId
|
|
|
17191
17942
|
}
|
|
17192
17943
|
}
|
|
17193
17944
|
}
|
|
17194
|
-
var DELETE_TURN_WAIT_MS = 5000, TopicArchiveRequiredError, TopicTurnStillActiveError, TopicCleanupRequiredError;
|
|
17945
|
+
var DELETE_TURN_WAIT_MS = 5000, TopicArchiveRequiredError, TopicTurnStillActiveError, TopicCleanupRequiredError, TopicDeleteVetoedError;
|
|
17195
17946
|
var init_lifecycle = __esm(async () => {
|
|
17196
17947
|
init_manager();
|
|
17197
17948
|
init_config();
|
|
@@ -17216,7 +17967,6 @@ var init_lifecycle = __esm(async () => {
|
|
|
17216
17967
|
init_api_topic_brief(),
|
|
17217
17968
|
init_api_topic_config(),
|
|
17218
17969
|
init_api_topics(),
|
|
17219
|
-
init_browser_profiles(),
|
|
17220
17970
|
init_forum_db(),
|
|
17221
17971
|
init_runtime_leases(),
|
|
17222
17972
|
init_runtime_topic_state(),
|
|
@@ -17258,9 +18008,19 @@ var init_lifecycle = __esm(async () => {
|
|
|
17258
18008
|
this.topicId = topicId;
|
|
17259
18009
|
}
|
|
17260
18010
|
};
|
|
18011
|
+
TopicDeleteVetoedError = class TopicDeleteVetoedError extends Error {
|
|
18012
|
+
code = "TOPIC_DELETE_VETOED";
|
|
18013
|
+
topicId;
|
|
18014
|
+
constructor(topicId, reason) {
|
|
18015
|
+
super(`Topic delete was vetoed: ${reason}`);
|
|
18016
|
+
this.name = "TopicDeleteVetoedError";
|
|
18017
|
+
this.topicId = topicId;
|
|
18018
|
+
}
|
|
18019
|
+
};
|
|
17261
18020
|
});
|
|
17262
18021
|
|
|
17263
18022
|
// ../../packages/core/src/runtime/attachments.ts
|
|
18023
|
+
import { randomUUID as randomUUID16 } from "crypto";
|
|
17264
18024
|
import { copyFileSync as copyFileSync2, mkdirSync as mkdirSync17, writeFileSync as writeFileSync15 } from "fs";
|
|
17265
18025
|
import { basename as basename6, join as join29 } from "path";
|
|
17266
18026
|
function workspaceCwdFor(topicId) {
|
|
@@ -17302,8 +18062,8 @@ function materializePromptAttachments(topicId, queryId, attachmentIds) {
|
|
|
17302
18062
|
sizeBytes: attachment.sizeBytes,
|
|
17303
18063
|
path: destPath
|
|
17304
18064
|
});
|
|
17305
|
-
} catch (
|
|
17306
|
-
logger.warn({ topicId, queryId, fileId, err }, "ai: failed to materialize attachment");
|
|
18065
|
+
} catch (err2) {
|
|
18066
|
+
logger.warn({ topicId, queryId, fileId, err: err2 }, "ai: failed to materialize attachment");
|
|
17307
18067
|
}
|
|
17308
18068
|
}
|
|
17309
18069
|
return out;
|
|
@@ -17321,6 +18081,24 @@ function composeAttachmentPrompt(prompt, promptLines) {
|
|
|
17321
18081
|
function promptWithAttachments(prompt, attachments) {
|
|
17322
18082
|
return composeAttachmentPrompt(prompt, attachments.map(({ filename, path }) => attachmentPromptLine(filename, path)));
|
|
17323
18083
|
}
|
|
18084
|
+
function ingestAttachment(args) {
|
|
18085
|
+
const destDir = join29(UPLOADS_DIR, args.topicId);
|
|
18086
|
+
mkdirSync17(destDir, { recursive: true });
|
|
18087
|
+
const safeName = safeAttachmentFilename(args.filename, "upload");
|
|
18088
|
+
const destPath = join29(destDir, `${Date.now()}-${randomUUID16().slice(0, 8)}-${safeName}`);
|
|
18089
|
+
if (args.sourcePath !== undefined) {
|
|
18090
|
+
copyFileSync2(args.sourcePath, destPath);
|
|
18091
|
+
} else if (args.bytes !== undefined) {
|
|
18092
|
+
writeFileSync15(destPath, args.bytes);
|
|
18093
|
+
} else {
|
|
18094
|
+
throw new Error("ingestAttachment: provide sourcePath or bytes");
|
|
18095
|
+
}
|
|
18096
|
+
return {
|
|
18097
|
+
path: destPath,
|
|
18098
|
+
filename: args.filename,
|
|
18099
|
+
promptLine: attachmentPromptLine(args.filename, destPath)
|
|
18100
|
+
};
|
|
18101
|
+
}
|
|
17324
18102
|
function parseAttachmentNames(raw) {
|
|
17325
18103
|
if (!raw)
|
|
17326
18104
|
return [];
|
|
@@ -17361,13 +18139,13 @@ function isLikelyCurrentChannelTrigger(row, userId, prompt) {
|
|
|
17361
18139
|
return Number.isFinite(createdMs) && Date.now() - createdMs <= CHANNEL_CONTEXT_CURRENT_MESSAGE_MATCH_MS;
|
|
17362
18140
|
}
|
|
17363
18141
|
function formatChannelTranscriptLine(row) {
|
|
17364
|
-
const
|
|
18142
|
+
const text2 = row.text.trim();
|
|
17365
18143
|
const attachments = parseAttachmentNames(row.attachments);
|
|
17366
18144
|
const attachmentSuffix = attachments.length > 0 ? `
|
|
17367
18145
|
[attachments: ${attachments.join(", ")}]` : "";
|
|
17368
18146
|
const edited = row.edited_at ? " (edited)" : "";
|
|
17369
18147
|
const thread = row.thread_root_id ? ` (in thread ${threadTag(row.thread_root_id)})` : "";
|
|
17370
|
-
return `[${row.created_at}] ${channelTranscriptSpeaker(row)}${edited}${thread}: ${
|
|
18148
|
+
return `[${row.created_at}] ${channelTranscriptSpeaker(row)}${edited}${thread}: ${text2}${attachmentSuffix}`;
|
|
17371
18149
|
}
|
|
17372
18150
|
function buildMentionOnlyChannelPrompt(params) {
|
|
17373
18151
|
const rows = getAllMessagesForTopic(params.topicId).filter((row) => {
|
|
@@ -17412,6 +18190,14 @@ function buildMentionOnlyChannelPrompt(params) {
|
|
|
17412
18190
|
].filter((line) => line !== undefined).join(`
|
|
17413
18191
|
`);
|
|
17414
18192
|
}
|
|
18193
|
+
function escapeRegExp3(s) {
|
|
18194
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
18195
|
+
}
|
|
18196
|
+
function mentionsAi(text2, label) {
|
|
18197
|
+
const names = ["ai", "bot", "\uBD07", label.trim()].filter(Boolean);
|
|
18198
|
+
const alt = names.map(escapeRegExp3).join("|");
|
|
18199
|
+
return new RegExp(`(^|\\s)@(${alt})(?![\\p{L}\\p{N}])`, "iu").test(text2);
|
|
18200
|
+
}
|
|
17415
18201
|
var CHANNEL_CONTEXT_CURRENT_MESSAGE_MATCH_MS, CHANNEL_CONTEXT_MAX_MESSAGES = 500, CHANNEL_CONTEXT_MAX_CHARS = 120000;
|
|
17416
18202
|
var init_channel_context = __esm(async () => {
|
|
17417
18203
|
init_attachments();
|
|
@@ -17420,13 +18206,13 @@ var init_channel_context = __esm(async () => {
|
|
|
17420
18206
|
});
|
|
17421
18207
|
|
|
17422
18208
|
// ../../packages/core/src/runtime/errors.ts
|
|
17423
|
-
function stringifyError(
|
|
17424
|
-
if (
|
|
17425
|
-
return
|
|
17426
|
-
if (typeof
|
|
17427
|
-
return
|
|
18209
|
+
function stringifyError(err2) {
|
|
18210
|
+
if (err2 instanceof Error)
|
|
18211
|
+
return err2.message;
|
|
18212
|
+
if (typeof err2 === "string")
|
|
18213
|
+
return err2;
|
|
17428
18214
|
try {
|
|
17429
|
-
return JSON.stringify(
|
|
18215
|
+
return JSON.stringify(err2) ?? String(err2);
|
|
17430
18216
|
} catch {
|
|
17431
18217
|
return "Unknown agent error";
|
|
17432
18218
|
}
|
|
@@ -17441,19 +18227,19 @@ function authRecoveryHint(agent) {
|
|
|
17441
18227
|
return "Please check the DEEPSEEK_API_KEY, MOONSHOT_API_KEY, or GLM_API_KEY environment variable";
|
|
17442
18228
|
}
|
|
17443
18229
|
}
|
|
17444
|
-
function classifyAgentError(
|
|
18230
|
+
function classifyAgentError(err2, agent) {
|
|
17445
18231
|
const name = AGENT_DISPLAY_NAME[agent];
|
|
17446
18232
|
const hint = authRecoveryHint(agent);
|
|
17447
|
-
const ctor = typeof
|
|
18233
|
+
const ctor = typeof err2 === "object" && err2 !== null ? err2.constructor?.name : undefined;
|
|
17448
18234
|
if (ctor === "AuthenticationError")
|
|
17449
18235
|
return `${name} authentication expired. ${hint}. (401)`;
|
|
17450
18236
|
if (ctor === "RateLimitError")
|
|
17451
18237
|
return `${name} request limit exceeded. Please try again in a moment. (429)`;
|
|
17452
18238
|
if (ctor === "InternalServerError") {
|
|
17453
|
-
const status =
|
|
18239
|
+
const status = err2.status;
|
|
17454
18240
|
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)`;
|
|
17455
18241
|
}
|
|
17456
|
-
const s = stringifyError(
|
|
18242
|
+
const s = stringifyError(err2);
|
|
17457
18243
|
if (/401|authentication.error|invalid.*api.key|not logged|ANTHROPIC_API_KEY|DEEPSEEK_API_KEY|MOONSHOT_API_KEY|GLM_API_KEY/i.test(s)) {
|
|
17458
18244
|
return `${name} authentication expired. ${hint}. (401)`;
|
|
17459
18245
|
}
|
|
@@ -17476,12 +18262,12 @@ var init_errors = __esm(() => {
|
|
|
17476
18262
|
|
|
17477
18263
|
// ../../packages/core/src/runtime/event-heartbeat.ts
|
|
17478
18264
|
function nextOrHeartbeat(pending, intervalMs) {
|
|
17479
|
-
return new Promise((
|
|
17480
|
-
const timer = setTimeout(() =>
|
|
18265
|
+
return new Promise((resolve17, reject) => {
|
|
18266
|
+
const timer = setTimeout(() => resolve17({ kind: "heartbeat" }), intervalMs);
|
|
17481
18267
|
timer.unref?.();
|
|
17482
18268
|
pending.then((result) => {
|
|
17483
18269
|
clearTimeout(timer);
|
|
17484
|
-
|
|
18270
|
+
resolve17({ kind: "event", result });
|
|
17485
18271
|
}, (error) => {
|
|
17486
18272
|
clearTimeout(timer);
|
|
17487
18273
|
reject(error);
|
|
@@ -17775,7 +18561,7 @@ var init_vault_request_gates = __esm(async () => {
|
|
|
17775
18561
|
});
|
|
17776
18562
|
|
|
17777
18563
|
// ../../packages/core/src/agents/mcp-tools/request-vault.ts
|
|
17778
|
-
import { createHash as createHash12, randomUUID as
|
|
18564
|
+
import { createHash as createHash12, randomUUID as randomUUID17 } from "crypto";
|
|
17779
18565
|
import { z as z4 } from "zod";
|
|
17780
18566
|
function requestBodyHash(key, description) {
|
|
17781
18567
|
return createHash12("sha256").update(JSON.stringify({ key, description })).digest("hex");
|
|
@@ -18011,8 +18797,8 @@ function createRequestVaultRuntime(host) {
|
|
|
18011
18797
|
return errorResult(`Error: failed to persist request_vault_secret: ${error instanceof Error ? error.message : String(error)}`);
|
|
18012
18798
|
}
|
|
18013
18799
|
let resolveAnswer;
|
|
18014
|
-
const promise = new Promise((
|
|
18015
|
-
resolveAnswer =
|
|
18800
|
+
const promise = new Promise((resolve17) => {
|
|
18801
|
+
resolveAnswer = resolve17;
|
|
18016
18802
|
});
|
|
18017
18803
|
pendingRequests.set(message.id, {
|
|
18018
18804
|
topicId: ctx.topicId,
|
|
@@ -18073,7 +18859,7 @@ var init_request_vault = __esm(async () => {
|
|
|
18073
18859
|
init_vault_request_gates()
|
|
18074
18860
|
]);
|
|
18075
18861
|
MAX_DESCRIPTION_CHARS = VAULT_DESCRIPTION_MAX_LENGTH;
|
|
18076
|
-
VAULT_GATE_OWNER_ID = `request-vault-${process.pid}-${
|
|
18862
|
+
VAULT_GATE_OWNER_ID = `request-vault-${process.pid}-${randomUUID17()}`;
|
|
18077
18863
|
defaultRequestVaultDurabilityHost = {
|
|
18078
18864
|
gates: {
|
|
18079
18865
|
prepare: prepareVaultRequestGate,
|
|
@@ -18114,7 +18900,7 @@ var init_request_vault = __esm(async () => {
|
|
|
18114
18900
|
durability: defaultRequestVaultDurabilityHost,
|
|
18115
18901
|
runtime: {
|
|
18116
18902
|
ownerId: VAULT_GATE_OWNER_ID,
|
|
18117
|
-
createId:
|
|
18903
|
+
createId: randomUUID17,
|
|
18118
18904
|
now: () => new Date().toISOString()
|
|
18119
18905
|
}
|
|
18120
18906
|
});
|
|
@@ -18151,24 +18937,24 @@ function taskPanelMessageId(queryId) {
|
|
|
18151
18937
|
// ../../packages/core/src/runtime/tasks.ts
|
|
18152
18938
|
function upsertTaskPanelMessage(topicId, queryId, tasks, lastRenderedText) {
|
|
18153
18939
|
if (tasks.length === 0) {
|
|
18154
|
-
const
|
|
18155
|
-
for (const
|
|
18156
|
-
|
|
18940
|
+
const hub2 = WsHub.get();
|
|
18941
|
+
for (const messageId2 of softDeleteApiMessagesByIdPrefix(topicId, "tasks-")) {
|
|
18942
|
+
hub2.broadcastMessageUpdated(topicId, messageId2, { deleted: true, text: "" });
|
|
18157
18943
|
}
|
|
18158
18944
|
return null;
|
|
18159
18945
|
}
|
|
18160
|
-
const
|
|
18161
|
-
if (
|
|
18946
|
+
const text2 = renderTaskPanel(tasks);
|
|
18947
|
+
if (text2 === lastRenderedText)
|
|
18162
18948
|
return lastRenderedText;
|
|
18163
18949
|
const hub = WsHub.get();
|
|
18164
18950
|
const messageId = taskPanelMessageId(queryId);
|
|
18165
18951
|
const existing = getApiMessage(topicId, messageId);
|
|
18166
18952
|
if (existing && !existing.deleted) {
|
|
18167
18953
|
const editedAt = new Date().toISOString();
|
|
18168
|
-
const updated = updateApiMessageText(topicId, messageId,
|
|
18954
|
+
const updated = updateApiMessageText(topicId, messageId, text2, editedAt);
|
|
18169
18955
|
if (updated) {
|
|
18170
|
-
hub.broadcastMessageUpdated(topicId, messageId, { text, editedAt });
|
|
18171
|
-
return
|
|
18956
|
+
hub.broadcastMessageUpdated(topicId, messageId, { text: text2, editedAt });
|
|
18957
|
+
return text2;
|
|
18172
18958
|
}
|
|
18173
18959
|
}
|
|
18174
18960
|
const createdAt = new Date().toISOString();
|
|
@@ -18176,12 +18962,12 @@ function upsertTaskPanelMessage(topicId, queryId, tasks, lastRenderedText) {
|
|
|
18176
18962
|
id: messageId,
|
|
18177
18963
|
topicId,
|
|
18178
18964
|
authorId: "system",
|
|
18179
|
-
text,
|
|
18965
|
+
text: text2,
|
|
18180
18966
|
createdAt
|
|
18181
18967
|
};
|
|
18182
18968
|
appendApiMessage(message, { notify: false });
|
|
18183
18969
|
hub.broadcastMessage(topicId, message);
|
|
18184
|
-
return
|
|
18970
|
+
return text2;
|
|
18185
18971
|
}
|
|
18186
18972
|
var init_tasks2 = __esm(async () => {
|
|
18187
18973
|
await __promiseAll([
|
|
@@ -18432,7 +19218,7 @@ function buildVideoHtml(mimeType) {
|
|
|
18432
19218
|
<body><video controls playsinline preload="metadata" src="${VISUAL_MEDIA_URL_PLACEHOLDER}" data-mime="${escapeHtml2(mimeType)}"></video></body>
|
|
18433
19219
|
</html>`;
|
|
18434
19220
|
}
|
|
18435
|
-
function
|
|
19221
|
+
function locateVisualMediaInput(topicId, input) {
|
|
18436
19222
|
if (typeof input.file_id === "string" && input.file_id.trim()) {
|
|
18437
19223
|
const fileId = input.file_id.trim().toLowerCase();
|
|
18438
19224
|
if (!isUploadFileId(fileId))
|
|
@@ -18444,11 +19230,7 @@ function resolveVisualMediaInput(topicId, input) {
|
|
|
18444
19230
|
const filePath = resolveUploadedFilePathByFileId(fileId);
|
|
18445
19231
|
if (!attachment || !filePath)
|
|
18446
19232
|
return { error: `uploaded file not found: ${fileId}` };
|
|
18447
|
-
return {
|
|
18448
|
-
fileId: attachment.id,
|
|
18449
|
-
mimeType: attachment.mimeType,
|
|
18450
|
-
source: `file_id:${attachment.id}`
|
|
18451
|
-
};
|
|
19233
|
+
return { kind: "upload", fileId: attachment.id, mimeType: attachment.mimeType };
|
|
18452
19234
|
}
|
|
18453
19235
|
if (typeof input.file_path !== "string" || !input.file_path.trim()) {
|
|
18454
19236
|
return { error: "file_path or file_id is required" };
|
|
@@ -18456,18 +19238,38 @@ function resolveVisualMediaInput(topicId, input) {
|
|
|
18456
19238
|
const rawPath = input.file_path.trim();
|
|
18457
19239
|
const cwd = workspaceCwdFor(topicId);
|
|
18458
19240
|
const candidate = isAbsolute6(rawPath) ? rawPath : resolve17(cwd, rawPath);
|
|
18459
|
-
if (!isPathInside(cwd, candidate)) {
|
|
18460
|
-
return { error: "file_path must be inside the topic workspace" };
|
|
18461
|
-
}
|
|
18462
19241
|
let realCandidate;
|
|
18463
19242
|
try {
|
|
18464
19243
|
realCandidate = realpathSync5(candidate);
|
|
18465
19244
|
} catch {
|
|
18466
19245
|
return { error: `file not found: ${rawPath}` };
|
|
18467
19246
|
}
|
|
19247
|
+
if (!isPathInside(cwd, realCandidate)) {
|
|
19248
|
+
return {
|
|
19249
|
+
error: `file_path must be inside the topic workspace (${cwd}); copy the file into it and pass the copy`
|
|
19250
|
+
};
|
|
19251
|
+
}
|
|
18468
19252
|
if (isSensitivePath(realCandidate)) {
|
|
18469
19253
|
return { error: "file_path matches the sensitive-file blacklist" };
|
|
18470
19254
|
}
|
|
19255
|
+
return { kind: "file", path: realCandidate, rawPath };
|
|
19256
|
+
}
|
|
19257
|
+
function visualMediaInputError(topicId, input) {
|
|
19258
|
+
const located = locateVisualMediaInput(topicId, input);
|
|
19259
|
+
return "error" in located ? located.error : null;
|
|
19260
|
+
}
|
|
19261
|
+
function resolveVisualMediaInput(topicId, input) {
|
|
19262
|
+
const located = locateVisualMediaInput(topicId, input);
|
|
19263
|
+
if ("error" in located)
|
|
19264
|
+
return located;
|
|
19265
|
+
if (located.kind === "upload") {
|
|
19266
|
+
return {
|
|
19267
|
+
fileId: located.fileId,
|
|
19268
|
+
mimeType: located.mimeType,
|
|
19269
|
+
source: `file_id:${located.fileId}`
|
|
19270
|
+
};
|
|
19271
|
+
}
|
|
19272
|
+
const { path: realCandidate, rawPath } = located;
|
|
18471
19273
|
const attachment = storeLocalFileAsUpload(realCandidate, { topicId });
|
|
18472
19274
|
if (!attachment)
|
|
18473
19275
|
return { error: `failed to store media file: ${rawPath}` };
|
|
@@ -18494,7 +19296,7 @@ var init_visuals = __esm(async () => {
|
|
|
18494
19296
|
});
|
|
18495
19297
|
|
|
18496
19298
|
// ../../packages/core/src/runtime/turn-event-stream.ts
|
|
18497
|
-
import { randomUUID as
|
|
19299
|
+
import { randomUUID as randomUUID18 } from "crypto";
|
|
18498
19300
|
import { realpathSync as realpathSync6, statSync as statSync9 } from "fs";
|
|
18499
19301
|
import { isAbsolute as isAbsolute7, resolve as resolve18 } from "path";
|
|
18500
19302
|
function sessionEventMatchesCurrentExecution(topicId, queryId, agent, model) {
|
|
@@ -18563,9 +19365,9 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
18563
19365
|
const existing = providerToolIds.get(providerId);
|
|
18564
19366
|
if (existing)
|
|
18565
19367
|
return existing;
|
|
18566
|
-
const
|
|
18567
|
-
providerToolIds.set(providerId,
|
|
18568
|
-
return
|
|
19368
|
+
const clientId2 = fallback ?? providerId;
|
|
19369
|
+
providerToolIds.set(providerId, clientId2);
|
|
19370
|
+
return clientId2;
|
|
18569
19371
|
}
|
|
18570
19372
|
const clientId = fallback ?? nextSyntheticToolUseId();
|
|
18571
19373
|
anonymousToolIds.push(clientId);
|
|
@@ -18596,15 +19398,15 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
18596
19398
|
return providerId ? handledVisualToolResultIds.has(providerId) : false;
|
|
18597
19399
|
};
|
|
18598
19400
|
const emitPendingAssistantMessage = (usage) => {
|
|
18599
|
-
const
|
|
19401
|
+
const text2 = pendingText.trimEnd();
|
|
18600
19402
|
pendingText = "";
|
|
18601
|
-
if (silent || !
|
|
19403
|
+
if (silent || !text2.trim())
|
|
18602
19404
|
return null;
|
|
18603
19405
|
const message = {
|
|
18604
|
-
id:
|
|
19406
|
+
id: randomUUID18(),
|
|
18605
19407
|
topicId,
|
|
18606
19408
|
authorId: "ai",
|
|
18607
|
-
text,
|
|
19409
|
+
text: text2,
|
|
18608
19410
|
queryId,
|
|
18609
19411
|
agentType,
|
|
18610
19412
|
model,
|
|
@@ -18824,8 +19626,8 @@ ${JSON.stringify(event.input ?? {})}`);
|
|
|
18824
19626
|
hub.broadcastVisual(topicId, queryId, url, vizId, title ?? null, kind);
|
|
18825
19627
|
hub.broadcastToolOutput(topicId, queryId, toolUseId, `Displayed: ${url}`);
|
|
18826
19628
|
markVisualToolResultHandled(event.toolUseId);
|
|
18827
|
-
} catch (
|
|
18828
|
-
const reason =
|
|
19629
|
+
} catch (err2) {
|
|
19630
|
+
const reason = err2 instanceof Error ? err2.message : String(err2);
|
|
18829
19631
|
failMediaVisual(reason);
|
|
18830
19632
|
}
|
|
18831
19633
|
} else {
|
|
@@ -18936,8 +19738,8 @@ ${JSON.stringify(event.input ?? {})}`);
|
|
|
18936
19738
|
}
|
|
18937
19739
|
terminalEmitted = true;
|
|
18938
19740
|
{
|
|
18939
|
-
await init_ask_callbacks();
|
|
18940
|
-
const pending =
|
|
19741
|
+
const { resolveAskCallback: resolveAskCallback2 } = await init_ask_callbacks().then(() => exports_ask_callbacks);
|
|
19742
|
+
const pending = resolveAskCallback2(queryId);
|
|
18941
19743
|
if (pending) {
|
|
18942
19744
|
const sourceLabel = pending.sourceLabel ?? topicTitle;
|
|
18943
19745
|
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)";
|
|
@@ -19010,8 +19812,8 @@ ${JSON.stringify(event.input ?? {})}`);
|
|
|
19010
19812
|
if (control.injectParams)
|
|
19011
19813
|
control.injectParams.sessionId = event.sessionId;
|
|
19012
19814
|
onSessionId(event.sessionId);
|
|
19013
|
-
} catch (
|
|
19014
|
-
logger.warn({ err, topicId, queryId, agentType }, "ai: isolated session owner rejected provider session id");
|
|
19815
|
+
} catch (err2) {
|
|
19816
|
+
logger.warn({ err: err2, topicId, queryId, agentType }, "ai: isolated session owner rejected provider session id");
|
|
19015
19817
|
}
|
|
19016
19818
|
} else if (!silent && sessionEventMatchesCurrentExecution(topicId, queryId, agentType, model)) {
|
|
19017
19819
|
setTopicSessionId(topicId, event.sessionId, {
|
|
@@ -19044,14 +19846,14 @@ ${JSON.stringify(event.input ?? {})}`);
|
|
|
19044
19846
|
settleSubagentFailure(queryId, "\uC911\uC9C0\uB428 (\uC0AC\uC6A9\uC790\uAC00 \uC2E4\uD589\uC744 \uBA48\uCDC4\uC2B5\uB2C8\uB2E4)");
|
|
19045
19847
|
} else {
|
|
19046
19848
|
if (control.abortReason === "internal" /* Internal */) {
|
|
19047
|
-
await init_ask_callbacks();
|
|
19048
|
-
|
|
19849
|
+
const { resolveAskCallback: resolveAskCallback2 } = await init_ask_callbacks().then(() => exports_ask_callbacks);
|
|
19850
|
+
resolveAskCallback2(queryId);
|
|
19049
19851
|
}
|
|
19050
19852
|
}
|
|
19051
19853
|
}
|
|
19052
|
-
} catch (
|
|
19053
|
-
const msg = stringifyError(
|
|
19054
|
-
logger.warn({ err, topicId, queryId, agentType, model, silent }, "ai: stream failed");
|
|
19854
|
+
} catch (err2) {
|
|
19855
|
+
const msg = stringifyError(err2) || "Unknown agent error";
|
|
19856
|
+
logger.warn({ err: err2, topicId, queryId, agentType, model, silent }, "ai: stream failed");
|
|
19055
19857
|
terminalEmitted = true;
|
|
19056
19858
|
if (retryableSessionExpired && isSessionExpiredError(msg)) {
|
|
19057
19859
|
outcome = { kind: "session-expired", error: msg };
|
|
@@ -19202,7 +20004,86 @@ var init_app_settings = __esm(async () => {
|
|
|
19202
20004
|
});
|
|
19203
20005
|
|
|
19204
20006
|
// ../../packages/core/src/runtime/turn-runner.ts
|
|
19205
|
-
|
|
20007
|
+
var exports_turn_runner = {};
|
|
20008
|
+
__export(exports_turn_runner, {
|
|
20009
|
+
workspaceCwdFor: () => workspaceCwdFor,
|
|
20010
|
+
withDefaultPlaywright: () => withDefaultPlaywright,
|
|
20011
|
+
wasLocallyRequeuedAfterUserPreemption: () => wasLocallyRequeuedAfterUserPreemption,
|
|
20012
|
+
visualMediaInputError: () => visualMediaInputError,
|
|
20013
|
+
userConversationPromptsToRecord: () => userConversationPromptsToRecord,
|
|
20014
|
+
upsertTaskPanelMessage: () => upsertTaskPanelMessage,
|
|
20015
|
+
tryReconstructTopicRollout: () => tryReconstructTopicRollout,
|
|
20016
|
+
triggerTopicAiTurn: () => triggerTopicAiTurn,
|
|
20017
|
+
topicAllowsVisualFileId: () => topicAllowsVisualFileId,
|
|
20018
|
+
taskPanelMessageId: () => taskPanelMessageId,
|
|
20019
|
+
stripMermaidFence: () => stripMermaidFence,
|
|
20020
|
+
stringifyError: () => stringifyError,
|
|
20021
|
+
streamAgentEvents: () => streamAgentEvents,
|
|
20022
|
+
startDurableTurnRequestWorker: () => startDurableTurnRequestWorker,
|
|
20023
|
+
startAiTurn: () => startAiTurn,
|
|
20024
|
+
selectableModel: () => selectableModel,
|
|
20025
|
+
sameTurnActor: () => sameTurnActor,
|
|
20026
|
+
safeAttachmentFilename: () => safeAttachmentFilename,
|
|
20027
|
+
resolveWorkerModel: () => resolveWorkerModel,
|
|
20028
|
+
resolveWorkerDefaultModel: () => resolveWorkerDefaultModel,
|
|
20029
|
+
resolveWikiMirrorPath: () => resolveWikiMirrorPath,
|
|
20030
|
+
resolveWikiMemoryMirror: () => resolveWikiMemoryMirror,
|
|
20031
|
+
resolveVisualMediaInput: () => resolveVisualMediaInput,
|
|
20032
|
+
resolveTurnToolCapabilities: () => resolveTurnToolCapabilities,
|
|
20033
|
+
resolveTurnHostMcpServers: () => resolveTurnHostMcpServers,
|
|
20034
|
+
resolveTopicTurnSession: () => resolveTopicTurnSession,
|
|
20035
|
+
resolveTopicTurnExecution: () => resolveTopicTurnExecution,
|
|
20036
|
+
resolveSessionRetry: () => resolveSessionRetry,
|
|
20037
|
+
resolveModelForAgent: () => resolveModelForAgent,
|
|
20038
|
+
resolveInitialTurnSessionId: () => resolveInitialTurnSessionId,
|
|
20039
|
+
resolveDefaultModel: () => resolveDefaultModel,
|
|
20040
|
+
resolveCompactionExecution: () => resolveCompactionExecution,
|
|
20041
|
+
renderUserTurnBatch: () => renderUserTurnBatch,
|
|
20042
|
+
renderUserPromptBatch: () => renderUserPromptBatch,
|
|
20043
|
+
renderTaskPanel: () => renderTaskPanel,
|
|
20044
|
+
promptWithAttachments: () => promptWithAttachments,
|
|
20045
|
+
prepareInjectReplayAfterUserPreemption: () => prepareInjectReplayAfterUserPreemption,
|
|
20046
|
+
parseAttachmentNames: () => parseAttachmentNames,
|
|
20047
|
+
normalizeToolUseId: () => normalizeToolUseId,
|
|
20048
|
+
normalizeMermaidTheme: () => normalizeMermaidTheme,
|
|
20049
|
+
modelOwner: () => modelOwner,
|
|
20050
|
+
mergeSupersedingUserTurn: () => mergeSupersedingUserTurn,
|
|
20051
|
+
mentionsAi: () => mentionsAi,
|
|
20052
|
+
materializePromptAttachments: () => materializePromptAttachments,
|
|
20053
|
+
isVisualsShowMermaidTool: () => isVisualsShowMermaidTool,
|
|
20054
|
+
isVisualsShowImageTool: () => isVisualsShowImageTool,
|
|
20055
|
+
isVisualsShowHtmlTool: () => isVisualsShowHtmlTool,
|
|
20056
|
+
isSessionExpiredError: () => isSessionExpiredError,
|
|
20057
|
+
isRuntimeTool: () => isRuntimeTool,
|
|
20058
|
+
isPathInside: () => isPathInside,
|
|
20059
|
+
isLikelyCurrentChannelTrigger: () => isLikelyCurrentChannelTrigger,
|
|
20060
|
+
ingestAttachment: () => ingestAttachment,
|
|
20061
|
+
formatSelectableModel: () => formatSelectableModel,
|
|
20062
|
+
formatChannelTranscriptLine: () => formatChannelTranscriptLine,
|
|
20063
|
+
escapeRegExp: () => escapeRegExp3,
|
|
20064
|
+
escapeHtml: () => escapeHtml2,
|
|
20065
|
+
deliverAskCallbackToCaller: () => deliverAskCallbackToCaller,
|
|
20066
|
+
composeAttachmentPrompt: () => composeAttachmentPrompt,
|
|
20067
|
+
classifyAgentError: () => classifyAgentError,
|
|
20068
|
+
channelTranscriptSpeaker: () => channelTranscriptSpeaker,
|
|
20069
|
+
canonicalModelId: () => canonicalModelId,
|
|
20070
|
+
buildVideoHtml: () => buildVideoHtml,
|
|
20071
|
+
buildTurnReminderQuery: () => buildTurnReminderQuery,
|
|
20072
|
+
buildMermaidHtml: () => buildMermaidHtml,
|
|
20073
|
+
buildMentionOnlyChannelPrompt: () => buildMentionOnlyChannelPrompt,
|
|
20074
|
+
buildImageHtml: () => buildImageHtml,
|
|
20075
|
+
authRecoveryHint: () => authRecoveryHint,
|
|
20076
|
+
attachmentPromptLine: () => attachmentPromptLine,
|
|
20077
|
+
activeVisualHtmlForPrompt: () => activeVisualHtmlForPrompt,
|
|
20078
|
+
SESSION_EXPIRED_MSG: () => SESSION_EXPIRED_MSG,
|
|
20079
|
+
SELECTABLE_MODELS: () => SELECTABLE_MODELS,
|
|
20080
|
+
MODEL_OWNER: () => MODEL_OWNER,
|
|
20081
|
+
MODEL_COST_ROUTING_SUMMARY: () => MODEL_COST_ROUTING_SUMMARY,
|
|
20082
|
+
MODEL_COST_RESEARCHED_AT: () => MODEL_COST_RESEARCHED_AT,
|
|
20083
|
+
FALLBACK_ORDER: () => FALLBACK_ORDER,
|
|
20084
|
+
AGENT_DISPLAY_NAME: () => AGENT_DISPLAY_NAME
|
|
20085
|
+
});
|
|
20086
|
+
import { randomUUID as randomUUID19 } from "crypto";
|
|
19206
20087
|
import { existsSync as existsSync22, mkdirSync as mkdirSync19, readdirSync as readdirSync5, statSync as statSync10 } from "fs";
|
|
19207
20088
|
import { join as join31 } from "path";
|
|
19208
20089
|
function withDefaultPlaywright(configuredMcp, isManager) {
|
|
@@ -19225,12 +20106,12 @@ function buildTurnReminderQuery(agent, prompt, reminders) {
|
|
|
19225
20106
|
|
|
19226
20107
|
${reminderPrompt}` };
|
|
19227
20108
|
}
|
|
19228
|
-
function appendSystemMessage(topicId,
|
|
20109
|
+
function appendSystemMessage(topicId, text2, threadRootId) {
|
|
19229
20110
|
const message = {
|
|
19230
|
-
id:
|
|
20111
|
+
id: randomUUID19(),
|
|
19231
20112
|
topicId,
|
|
19232
20113
|
authorId: "system",
|
|
19233
|
-
text,
|
|
20114
|
+
text: text2,
|
|
19234
20115
|
...threadRootId ? { threadRootId } : {},
|
|
19235
20116
|
createdAt: new Date().toISOString()
|
|
19236
20117
|
};
|
|
@@ -19247,12 +20128,12 @@ function notifyPlaywrightUnavailable(topicId) {
|
|
|
19247
20128
|
appendSystemMessage(topicId, "Playwright browser tools are unavailable this turn. Browser automation was removed from the tool catalog; retry shortly if browser interaction is required.");
|
|
19248
20129
|
WsHub.get().broadcastTopicNotice(topicId, "info", "Playwright \uC0AC\uC6A9 \uBD88\uAC00");
|
|
19249
20130
|
}
|
|
19250
|
-
function appendAskReplyMessage(topicId,
|
|
20131
|
+
function appendAskReplyMessage(topicId, text2, sourceLabel, body, kind, agentType, threadRootId) {
|
|
19251
20132
|
const message = {
|
|
19252
|
-
id:
|
|
20133
|
+
id: randomUUID19(),
|
|
19253
20134
|
topicId,
|
|
19254
20135
|
authorId: "ai",
|
|
19255
|
-
text,
|
|
20136
|
+
text: text2,
|
|
19256
20137
|
kind: "tell",
|
|
19257
20138
|
tellCard: {
|
|
19258
20139
|
fromLabel: sourceLabel,
|
|
@@ -19313,8 +20194,8 @@ function redispatchInject(inject) {
|
|
|
19313
20194
|
kind: "error",
|
|
19314
20195
|
error: "topic gone or AI no longer invited"
|
|
19315
20196
|
});
|
|
19316
|
-
} catch (
|
|
19317
|
-
logger.warn({ err, topicId: inject.topicId }, "ai: deferred settlement hook failed");
|
|
20197
|
+
} catch (err2) {
|
|
20198
|
+
logger.warn({ err: err2, topicId: inject.topicId }, "ai: deferred settlement hook failed");
|
|
19318
20199
|
}
|
|
19319
20200
|
if (inject.forkHandle)
|
|
19320
20201
|
cleanupAgentFork(inject.forkHandle);
|
|
@@ -19372,28 +20253,28 @@ async function clearPendingAskFile(pending, state) {
|
|
|
19372
20253
|
if (!pending.pendingAsk)
|
|
19373
20254
|
return;
|
|
19374
20255
|
try {
|
|
19375
|
-
await init_session_asks();
|
|
20256
|
+
const { clearPendingAsk: clearPendingAsk2, markPendingAskState: markPendingAskState2 } = await init_session_asks().then(() => exports_session_asks);
|
|
19376
20257
|
if (state)
|
|
19377
|
-
|
|
19378
|
-
|
|
19379
|
-
} catch (
|
|
19380
|
-
logger.warn({ err, pendingAsk: pending.pendingAsk }, "sessions: pending ask cleanup failed");
|
|
20258
|
+
markPendingAskState2({ ...pending.pendingAsk, state });
|
|
20259
|
+
clearPendingAsk2(pending.pendingAsk);
|
|
20260
|
+
} catch (err2) {
|
|
20261
|
+
logger.warn({ err: err2, pendingAsk: pending.pendingAsk }, "sessions: pending ask cleanup failed");
|
|
19381
20262
|
}
|
|
19382
20263
|
}
|
|
19383
20264
|
async function markPendingAskFile(pending, state) {
|
|
19384
20265
|
if (!pending.pendingAsk)
|
|
19385
20266
|
return;
|
|
19386
20267
|
try {
|
|
19387
|
-
await init_session_asks();
|
|
19388
|
-
|
|
19389
|
-
} catch (
|
|
19390
|
-
logger.warn({ err, pendingAsk: pending.pendingAsk, state }, "sessions: pending ask mark failed");
|
|
20268
|
+
const { markPendingAskState: markPendingAskState2 } = await init_session_asks().then(() => exports_session_asks);
|
|
20269
|
+
markPendingAskState2({ ...pending.pendingAsk, state });
|
|
20270
|
+
} catch (err2) {
|
|
20271
|
+
logger.warn({ err: err2, pendingAsk: pending.pendingAsk, state }, "sessions: pending ask mark failed");
|
|
19391
20272
|
}
|
|
19392
20273
|
}
|
|
19393
20274
|
async function deliverAskCallbackToCaller(pending, sourceLabel, body, kind, options = {}) {
|
|
19394
20275
|
if (pending.remoteReply) {
|
|
19395
|
-
await init_peer_forward();
|
|
19396
|
-
const delivered = await
|
|
20276
|
+
const { deliverPeerReply: deliverPeerReply2 } = await init_peer_forward().then(() => exports_peer_forward);
|
|
20277
|
+
const delivered = await deliverPeerReply2(pending.remoteReply, sourceLabel, body, kind);
|
|
19397
20278
|
if (delivered)
|
|
19398
20279
|
options.onRecorded?.();
|
|
19399
20280
|
return delivered;
|
|
@@ -19413,8 +20294,8 @@ ${body}`;
|
|
|
19413
20294
|
record(undefined);
|
|
19414
20295
|
await clearPendingAskFile(pending);
|
|
19415
20296
|
return true;
|
|
19416
|
-
} catch (
|
|
19417
|
-
logger.warn({ err, requestId: pending.requestId, callerTopicId: pending.callerTopicId }, "sessions: ask callback direct delivery failed");
|
|
20297
|
+
} catch (err2) {
|
|
20298
|
+
logger.warn({ err: err2, requestId: pending.requestId, callerTopicId: pending.callerTopicId }, "sessions: ask callback direct delivery failed");
|
|
19418
20299
|
return false;
|
|
19419
20300
|
}
|
|
19420
20301
|
}
|
|
@@ -19443,9 +20324,9 @@ ${body}`;
|
|
|
19443
20324
|
if (queued) {
|
|
19444
20325
|
try {
|
|
19445
20326
|
record(callerTopic.agent);
|
|
19446
|
-
} catch (
|
|
20327
|
+
} catch (err2) {
|
|
19447
20328
|
interSessionQueue.remove(pending.callerTopicId, pending.requestId);
|
|
19448
|
-
logger.warn({ err, requestId: pending.requestId, callerTopicId: pending.callerTopicId }, "sessions: ask callback record failed after enqueue; queue entry withdrawn");
|
|
20329
|
+
logger.warn({ err: err2, requestId: pending.requestId, callerTopicId: pending.callerTopicId }, "sessions: ask callback record failed after enqueue; queue entry withdrawn");
|
|
19449
20330
|
return false;
|
|
19450
20331
|
}
|
|
19451
20332
|
await markPendingAskFile(pending, "queued_for_caller");
|
|
@@ -19465,8 +20346,8 @@ ${body}`;
|
|
|
19465
20346
|
}
|
|
19466
20347
|
async function deliverAskError(queryId, sourceLabel, error) {
|
|
19467
20348
|
try {
|
|
19468
|
-
await init_ask_callbacks();
|
|
19469
|
-
const pending =
|
|
20349
|
+
const { resolveAskCallback: resolveAskCallback2 } = await init_ask_callbacks().then(() => exports_ask_callbacks);
|
|
20350
|
+
const pending = resolveAskCallback2(queryId);
|
|
19470
20351
|
if (pending) {
|
|
19471
20352
|
const prefix = pending.timedOut ? `\u26A0\uFE0F [Timeout - error notification was dropped]
|
|
19472
20353
|
|
|
@@ -19496,9 +20377,9 @@ function tryReconstructTopicRollout(opts) {
|
|
|
19496
20377
|
entries: entries.length
|
|
19497
20378
|
}, sessionId ? "ai: session expired \u2014 rollout reconstructed from unified log" : "ai: provider session bridged from shared conversation log");
|
|
19498
20379
|
return { kind: "rebuilt", sessionId: result.sessionId };
|
|
19499
|
-
} catch (
|
|
19500
|
-
logger.warn({ err, topicId, agent, sessionId }, "ai: session reconstruct failed");
|
|
19501
|
-
return { kind: "failed", error: stringifyError(
|
|
20380
|
+
} catch (err2) {
|
|
20381
|
+
logger.warn({ err: err2, topicId, agent, sessionId }, "ai: session reconstruct failed");
|
|
20382
|
+
return { kind: "failed", error: stringifyError(err2) };
|
|
19502
20383
|
}
|
|
19503
20384
|
}
|
|
19504
20385
|
function resolveSessionRetry(opts) {
|
|
@@ -19607,8 +20488,8 @@ function waitToStartRemoteUserTurn(params, queryId, options) {
|
|
|
19607
20488
|
function announceQueuedUserTurn(params, queryId) {
|
|
19608
20489
|
try {
|
|
19609
20490
|
params.onDispatched?.(queryId);
|
|
19610
|
-
} catch (
|
|
19611
|
-
logger.warn({ err, topicId: params.topic.id, queryId }, "ai: queued dispatch hook failed");
|
|
20491
|
+
} catch (err2) {
|
|
20492
|
+
logger.warn({ err: err2, topicId: params.topic.id, queryId }, "ai: queued dispatch hook failed");
|
|
19612
20493
|
}
|
|
19613
20494
|
if (!params.silent)
|
|
19614
20495
|
WsHub.get().broadcastAiActive(params.topic.id, queryId);
|
|
@@ -19629,6 +20510,81 @@ function waitToDrainRemoteInject(topicId) {
|
|
|
19629
20510
|
timer.unref?.();
|
|
19630
20511
|
remoteInjectWaiters.set(topicId, timer);
|
|
19631
20512
|
}
|
|
20513
|
+
async function drainOneDurableUserTurn() {
|
|
20514
|
+
if (durableTurnWorkerBusy)
|
|
20515
|
+
return;
|
|
20516
|
+
durableTurnWorkerBusy = true;
|
|
20517
|
+
try {
|
|
20518
|
+
const request = claimNextRuntimeUserTurnRequest(RUNTIME_INSTANCE_ID);
|
|
20519
|
+
if (!request)
|
|
20520
|
+
return;
|
|
20521
|
+
const topic = getTopic(request.topicId);
|
|
20522
|
+
if (!topic?.agent) {
|
|
20523
|
+
completeRuntimeUserTurnRequest(request.topicId, request.requestId, RUNTIME_INSTANCE_ID);
|
|
20524
|
+
return;
|
|
20525
|
+
}
|
|
20526
|
+
const execution = request.execution;
|
|
20527
|
+
const queryId = startAiTurn({
|
|
20528
|
+
topic,
|
|
20529
|
+
userId: request.userId,
|
|
20530
|
+
actorUserId: execution?.actorUserId,
|
|
20531
|
+
actorTopicScope: actorTopicScopeFrom(execution?.actorTopicScope),
|
|
20532
|
+
remoteSession: remoteSessionGrantFrom(execution?.remoteSession),
|
|
20533
|
+
vaultUserId: execution?.vaultUserId,
|
|
20534
|
+
prompt: request.prompt,
|
|
20535
|
+
_userMessages: request.userMessages,
|
|
20536
|
+
_conversationPrompts: execution?.conversationPrompts ?? [request.prompt],
|
|
20537
|
+
_loggedUserMessageCount: execution?.loggedUserMessageCount ?? Math.max(0, request.userMessages.length - (execution?.conversationPrompts?.length ?? 1)),
|
|
20538
|
+
_durableRequestIds: [request.requestId],
|
|
20539
|
+
attachments: request.attachments,
|
|
20540
|
+
allowAutoContinue: request.allowAutoContinue,
|
|
20541
|
+
origin: "user",
|
|
20542
|
+
requestId: execution?.sourceRequestId,
|
|
20543
|
+
agentOverride: execution?.agentOverride,
|
|
20544
|
+
modelOverride: execution?.modelOverride,
|
|
20545
|
+
effortOverride: execution?.effortOverride,
|
|
20546
|
+
...execution?.sessionIdSpecified ? { sessionId: execution.sessionId } : {},
|
|
20547
|
+
sessionScope: execution?.sessionScope,
|
|
20548
|
+
cwd: execution?.cwd,
|
|
20549
|
+
sessionName: execution?.sessionName,
|
|
20550
|
+
sessionType: execution?.sessionType,
|
|
20551
|
+
visualTools: execution?.visualTools,
|
|
20552
|
+
fileDeliveryTools: execution?.fileDeliveryTools,
|
|
20553
|
+
silent: execution?.silent,
|
|
20554
|
+
bridgeSessionFromHistory: execution?.bridgeSessionFromHistory,
|
|
20555
|
+
peerBridge: execution?.peerBridge,
|
|
20556
|
+
from: execution?.from,
|
|
20557
|
+
threadRootId: execution?.threadRootId,
|
|
20558
|
+
_queryId: request.requestId,
|
|
20559
|
+
_runtimeEpoch: execution?.runtimeEpoch ?? request.topicEpoch,
|
|
20560
|
+
onSettled: () => {
|
|
20561
|
+
completeRuntimeUserTurnRequest(request.topicId, request.requestId, RUNTIME_INSTANCE_ID);
|
|
20562
|
+
}
|
|
20563
|
+
});
|
|
20564
|
+
if (!queryId) {
|
|
20565
|
+
releaseRuntimeUserTurnClaim(request.topicId, request.requestId, RUNTIME_INSTANCE_ID);
|
|
20566
|
+
return;
|
|
20567
|
+
}
|
|
20568
|
+
markRuntimeUserTurnRunning(request.topicId, request.requestId, RUNTIME_INSTANCE_ID, queryId);
|
|
20569
|
+
} finally {
|
|
20570
|
+
durableTurnWorkerBusy = false;
|
|
20571
|
+
}
|
|
20572
|
+
}
|
|
20573
|
+
function startDurableTurnRequestWorker() {
|
|
20574
|
+
if (durableTurnWorker)
|
|
20575
|
+
return () => {};
|
|
20576
|
+
durableTurnWorker = setInterval(() => {
|
|
20577
|
+
drainOneDurableUserTurn();
|
|
20578
|
+
}, 100);
|
|
20579
|
+
durableTurnWorker.unref?.();
|
|
20580
|
+
drainOneDurableUserTurn();
|
|
20581
|
+
return () => {
|
|
20582
|
+
if (!durableTurnWorker)
|
|
20583
|
+
return;
|
|
20584
|
+
clearInterval(durableTurnWorker);
|
|
20585
|
+
durableTurnWorker = null;
|
|
20586
|
+
};
|
|
20587
|
+
}
|
|
19632
20588
|
function startAiTurn(params) {
|
|
19633
20589
|
const storedTopic = getTopic(params.topic.id);
|
|
19634
20590
|
if (!storedTopic || !storedTopic.agent && !params.agentOverride) {
|
|
@@ -19640,8 +20596,8 @@ function startAiTurn(params) {
|
|
|
19640
20596
|
kind: "error",
|
|
19641
20597
|
error: storedTopic ? "topic no longer has an AI agent" : "topic no longer exists"
|
|
19642
20598
|
});
|
|
19643
|
-
} catch (
|
|
19644
|
-
logger.warn({ err, topicId: params.topic.id }, "ai: rejected-turn settlement hook failed");
|
|
20599
|
+
} catch (err2) {
|
|
20600
|
+
logger.warn({ err: err2, topicId: params.topic.id }, "ai: rejected-turn settlement hook failed");
|
|
19645
20601
|
}
|
|
19646
20602
|
return null;
|
|
19647
20603
|
}
|
|
@@ -19697,7 +20653,7 @@ function startAiTurn(params) {
|
|
|
19697
20653
|
const askReplySources = params.askReplySources;
|
|
19698
20654
|
const sessionRetried = params._sessionRetried === true;
|
|
19699
20655
|
const emptyResponseRetried = params._emptyResponseRetried === true;
|
|
19700
|
-
const queryId = asTurnId(params._queryId ??
|
|
20656
|
+
const queryId = asTurnId(params._queryId ?? randomUUID19());
|
|
19701
20657
|
const roomId = turnConcurrency === "isolated" ? isolatedTurnRoomId(topicId, queryId) : asTurnSlotKey(topicId);
|
|
19702
20658
|
const currentRuntimeEpoch = getRuntimeTopicEpoch(topic.id);
|
|
19703
20659
|
const runtimeEpoch = params._runtimeEpoch ?? currentRuntimeEpoch;
|
|
@@ -19709,8 +20665,8 @@ function startAiTurn(params) {
|
|
|
19709
20665
|
}
|
|
19710
20666
|
try {
|
|
19711
20667
|
params.onSettled?.({ queryId, kind: "aborted", abortReason: "external" /* External */ });
|
|
19712
|
-
} catch (
|
|
19713
|
-
logger.warn({ err, topicId: topic.id, queryId }, "ai: stale-turn settlement hook failed");
|
|
20668
|
+
} catch (err2) {
|
|
20669
|
+
logger.warn({ err: err2, topicId: topic.id, queryId }, "ai: stale-turn settlement hook failed");
|
|
19714
20670
|
}
|
|
19715
20671
|
logger.info({ topicId: topic.id, queryId, queuedEpoch: params._runtimeEpoch, currentRuntimeEpoch }, "ai: dropped work queued before topic reset");
|
|
19716
20672
|
return null;
|
|
@@ -19760,8 +20716,8 @@ function startAiTurn(params) {
|
|
|
19760
20716
|
cleanupAgentFork(forkHandle);
|
|
19761
20717
|
try {
|
|
19762
20718
|
onSettled?.({ queryId: "", kind: "error", error });
|
|
19763
|
-
} catch (
|
|
19764
|
-
logger.warn({ err, topicId, queryId }, "ai: isolated-turn rejection hook failed");
|
|
20719
|
+
} catch (err2) {
|
|
20720
|
+
logger.warn({ err: err2, topicId, queryId }, "ai: isolated-turn rejection hook failed");
|
|
19765
20721
|
}
|
|
19766
20722
|
return null;
|
|
19767
20723
|
};
|
|
@@ -19808,7 +20764,7 @@ function startAiTurn(params) {
|
|
|
19808
20764
|
if (decision.action === "abort-replace") {
|
|
19809
20765
|
const running = decision.running;
|
|
19810
20766
|
if (isUserOrigin(running.origin) && !sameTurnActor(running.actorUserId, params.actorUserId)) {
|
|
19811
|
-
const
|
|
20767
|
+
const queuedQueryId2 = waitToStartRemoteUserTurn({
|
|
19812
20768
|
...params,
|
|
19813
20769
|
topic,
|
|
19814
20770
|
prompt,
|
|
@@ -19820,9 +20776,9 @@ function startAiTurn(params) {
|
|
|
19820
20776
|
_durableRequestIds: durableRequestIds,
|
|
19821
20777
|
_runtimeEpoch: runtimeEpoch
|
|
19822
20778
|
}, queryId);
|
|
19823
|
-
announceQueuedUserTurn({ ...params, topic },
|
|
19824
|
-
logger.info({ topicId, queryId:
|
|
19825
|
-
return
|
|
20779
|
+
announceQueuedUserTurn({ ...params, topic }, queuedQueryId2);
|
|
20780
|
+
logger.info({ topicId, queryId: queuedQueryId2, runningQueryId: running.queryId }, "ai: user turn from another actor queued behind the running turn");
|
|
20781
|
+
return queuedQueryId2;
|
|
19826
20782
|
}
|
|
19827
20783
|
let omitRequestIds;
|
|
19828
20784
|
if (isUserOrigin(running.origin)) {
|
|
@@ -19954,14 +20910,14 @@ function startAiTurn(params) {
|
|
|
19954
20910
|
if (turnConcurrency === "topic") {
|
|
19955
20911
|
try {
|
|
19956
20912
|
writeQueryState(userId, topic.id, topic.title, prompt);
|
|
19957
|
-
} catch (
|
|
19958
|
-
logger.warn({ err, topicId, userId }, "ai: failed to write active query state");
|
|
20913
|
+
} catch (err2) {
|
|
20914
|
+
logger.warn({ err: err2, topicId, userId }, "ai: failed to write active query state");
|
|
19959
20915
|
}
|
|
19960
20916
|
}
|
|
19961
20917
|
try {
|
|
19962
20918
|
onDispatched?.(queryId);
|
|
19963
|
-
} catch (
|
|
19964
|
-
logger.warn({ err, topicId, queryId }, "ai: dispatch hook failed");
|
|
20919
|
+
} catch (err2) {
|
|
20920
|
+
logger.warn({ err: err2, topicId, queryId }, "ai: dispatch hook failed");
|
|
19965
20921
|
}
|
|
19966
20922
|
const override = getTopicConfig(topicId);
|
|
19967
20923
|
const agentKind = execution.agent;
|
|
@@ -19988,8 +20944,8 @@ function startAiTurn(params) {
|
|
|
19988
20944
|
control.injectParams.sessionId = bridge.sessionId;
|
|
19989
20945
|
try {
|
|
19990
20946
|
onSessionId?.(bridge.sessionId);
|
|
19991
|
-
} catch (
|
|
19992
|
-
logger.warn({ err, topicId, queryId, agent: agentKind }, "ai: isolated session owner rejected bridged provider session id");
|
|
20947
|
+
} catch (err2) {
|
|
20948
|
+
logger.warn({ err: err2, topicId, queryId, agent: agentKind }, "ai: isolated session owner rejected bridged provider session id");
|
|
19993
20949
|
}
|
|
19994
20950
|
} else if (bridge.kind === "failed") {
|
|
19995
20951
|
historyBridgeError = "Conversation history could not be encoded into a provider session; no fresh session was started.";
|
|
@@ -20058,8 +21014,8 @@ function startAiTurn(params) {
|
|
|
20058
21014
|
const wikiDir = getSharedWikiDir();
|
|
20059
21015
|
const { latestSummaryFile } = resolveWikiMemoryMirror(wikiDir, memoryTopic.id, memoryTitle);
|
|
20060
21016
|
hasMemoryArchive = Boolean(resolvedBrief?.brief.latestSummaryMd || latestSummaryFile);
|
|
20061
|
-
} catch (
|
|
20062
|
-
logger.warn({ topicId, err }, "ai: failed to inject topic brief");
|
|
21017
|
+
} catch (err2) {
|
|
21018
|
+
logger.warn({ topicId, err: err2 }, "ai: failed to inject topic brief");
|
|
20063
21019
|
}
|
|
20064
21020
|
systemPrompt += buildMemoryPromptSection({
|
|
20065
21021
|
topicTitle: topic.title,
|
|
@@ -20135,8 +21091,8 @@ function startAiTurn(params) {
|
|
|
20135
21091
|
control.injectParams.sessionId = prepared.forkId;
|
|
20136
21092
|
control.injectParams.forkHandle = prepared;
|
|
20137
21093
|
}
|
|
20138
|
-
} catch (
|
|
20139
|
-
throw new Error(`failed to prepare isolated session: ${stringifyError(
|
|
21094
|
+
} catch (err2) {
|
|
21095
|
+
throw new Error(`failed to prepare isolated session: ${stringifyError(err2)}`);
|
|
20140
21096
|
}
|
|
20141
21097
|
if (abortController.signal.aborted)
|
|
20142
21098
|
return;
|
|
@@ -20155,8 +21111,8 @@ function startAiTurn(params) {
|
|
|
20155
21111
|
throw new Error("browser MCP capability was not registered");
|
|
20156
21112
|
}
|
|
20157
21113
|
trackPlaywrightTurn(playwrightInstanceKey, control);
|
|
20158
|
-
} catch (
|
|
20159
|
-
logger.warn({ topicId, err }, "ai: ensurePlaywright failed \u2014 proceeding without browser tools");
|
|
21114
|
+
} catch (err2) {
|
|
21115
|
+
logger.warn({ topicId, err: err2 }, "ai: ensurePlaywright failed \u2014 proceeding without browser tools");
|
|
20160
21116
|
markPlaywrightUnavailable({
|
|
20161
21117
|
userId,
|
|
20162
21118
|
topic: topic.title,
|
|
@@ -20169,8 +21125,8 @@ function startAiTurn(params) {
|
|
|
20169
21125
|
if (wantsBgBash) {
|
|
20170
21126
|
try {
|
|
20171
21127
|
bgBashPort = await ensureBgBash(userId, topic.id);
|
|
20172
|
-
} catch (
|
|
20173
|
-
logger.warn({ topicId, err }, "ai: ensureBgBash failed \u2014 proceeding without background bash tools");
|
|
21128
|
+
} catch (err2) {
|
|
21129
|
+
logger.warn({ topicId, err: err2 }, "ai: ensureBgBash failed \u2014 proceeding without background bash tools");
|
|
20174
21130
|
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>");
|
|
20175
21131
|
}
|
|
20176
21132
|
}
|
|
@@ -20383,8 +21339,8 @@ function startAiTurn(params) {
|
|
|
20383
21339
|
await settleSubagentFailure(queryId, error);
|
|
20384
21340
|
try {
|
|
20385
21341
|
onSettled?.({ queryId, kind: "error", error });
|
|
20386
|
-
} catch (
|
|
20387
|
-
logger.warn({ err, topicId, queryId }, "ai: turn settlement hook failed");
|
|
21342
|
+
} catch (err2) {
|
|
21343
|
+
logger.warn({ err: err2, topicId, queryId }, "ai: turn settlement hook failed");
|
|
20388
21344
|
}
|
|
20389
21345
|
return;
|
|
20390
21346
|
}
|
|
@@ -20400,8 +21356,8 @@ function startAiTurn(params) {
|
|
|
20400
21356
|
await settleSubagentFailure(queryId, classifyAgentError(outcome.error, agentKind));
|
|
20401
21357
|
try {
|
|
20402
21358
|
onSettled?.({ queryId, kind: "error", error: outcome.error });
|
|
20403
|
-
} catch (
|
|
20404
|
-
logger.warn({ err, topicId, queryId }, "ai: turn settlement hook failed");
|
|
21359
|
+
} catch (err2) {
|
|
21360
|
+
logger.warn({ err: err2, topicId, queryId }, "ai: turn settlement hook failed");
|
|
20405
21361
|
}
|
|
20406
21362
|
return;
|
|
20407
21363
|
}
|
|
@@ -20414,12 +21370,12 @@ function startAiTurn(params) {
|
|
|
20414
21370
|
kind: outcome.kind === "aborted" ? "aborted" : "completed",
|
|
20415
21371
|
...outcome.kind === "aborted" ? { abortReason: control.abortReason } : {}
|
|
20416
21372
|
});
|
|
20417
|
-
} catch (
|
|
20418
|
-
logger.warn({ err, topicId, queryId }, "ai: turn settlement hook failed");
|
|
21373
|
+
} catch (err2) {
|
|
21374
|
+
logger.warn({ err: err2, topicId, queryId }, "ai: turn settlement hook failed");
|
|
20419
21375
|
}
|
|
20420
|
-
}).catch(async (
|
|
20421
|
-
const error =
|
|
20422
|
-
logger.warn({ err, topicId, queryId, agent: agentKind, model: resolvedModel, silent }, "ai: background stream task failed");
|
|
21376
|
+
}).catch(async (err2) => {
|
|
21377
|
+
const error = err2 instanceof Error ? err2.message : "Agent process crashed";
|
|
21378
|
+
logger.warn({ err: err2, topicId, queryId, agent: agentKind, model: resolvedModel, silent }, "ai: background stream task failed");
|
|
20423
21379
|
if (!silent) {
|
|
20424
21380
|
WsHub.get().broadcastError(topicId, queryId, error);
|
|
20425
21381
|
WsHub.get().broadcastTopicNotice(topicId, "error", "\uC751\uB2F5 \uC2E4\uD328");
|
|
@@ -20468,7 +21424,7 @@ function triggerTopicAiTurn(topicId, userId, prompt, agentType, opts) {
|
|
|
20468
21424
|
if (!opts?.silent && !opts?.hideInjectMessage) {
|
|
20469
21425
|
const now = new Date().toISOString();
|
|
20470
21426
|
const injectMsg = {
|
|
20471
|
-
id: opts?.requestId ? `tell-${opts.requestId}` : `tell-${
|
|
21427
|
+
id: opts?.requestId ? `tell-${opts.requestId}` : `tell-${randomUUID19()}`,
|
|
20472
21428
|
topicId,
|
|
20473
21429
|
authorId: opts?.injectAuthorId ?? userId,
|
|
20474
21430
|
sourceAdapter: opts?.injectSourceAdapter,
|
|
@@ -20525,7 +21481,7 @@ function triggerTopicAiTurn(topicId, userId, prompt, agentType, opts) {
|
|
|
20525
21481
|
from: opts?.from
|
|
20526
21482
|
});
|
|
20527
21483
|
}
|
|
20528
|
-
var PLAYWRIGHT_UNAVAILABLE_NOTICE_COOLDOWN_MS, ASK_REPLY_INJECT_BATCH_MS = 500, playwrightUnavailableNoticeAt, askReplyInjectBatcher, remoteInjectWaiters;
|
|
21484
|
+
var PLAYWRIGHT_UNAVAILABLE_NOTICE_COOLDOWN_MS, ASK_REPLY_INJECT_BATCH_MS = 500, playwrightUnavailableNoticeAt, askReplyInjectBatcher, remoteInjectWaiters, durableTurnWorker = null, durableTurnWorkerBusy = false;
|
|
20529
21485
|
var init_turn_runner = __esm(async () => {
|
|
20530
21486
|
init_manager();
|
|
20531
21487
|
init_constants();
|
|
@@ -20656,29 +21612,29 @@ function createSubagentLifecycle(host) {
|
|
|
20656
21612
|
}
|
|
20657
21613
|
function computeSubagentDepth(topicId) {
|
|
20658
21614
|
let depth = 0;
|
|
20659
|
-
let
|
|
21615
|
+
let current3 = host.storage.getTopic(topicId);
|
|
20660
21616
|
const visited = new Set;
|
|
20661
|
-
while (
|
|
20662
|
-
if (visited.has(
|
|
21617
|
+
while (current3) {
|
|
21618
|
+
if (visited.has(current3.id))
|
|
20663
21619
|
return limits.maxDepth;
|
|
20664
|
-
visited.add(
|
|
20665
|
-
if (
|
|
21620
|
+
visited.add(current3.id);
|
|
21621
|
+
if (current3.isSubagent)
|
|
20666
21622
|
depth += 1;
|
|
20667
|
-
if (!
|
|
21623
|
+
if (!current3.parentTopicId || current3.parentTopicId === current3.id)
|
|
20668
21624
|
break;
|
|
20669
|
-
|
|
21625
|
+
current3 = host.storage.getTopic(current3.parentTopicId);
|
|
20670
21626
|
}
|
|
20671
21627
|
return depth;
|
|
20672
21628
|
}
|
|
20673
|
-
function
|
|
21629
|
+
function canSpawnSubagentsFromTopic2(topicId) {
|
|
20674
21630
|
const topic = host.storage.getTopic(topicId);
|
|
20675
21631
|
return topic?.kind === "agent" && computeSubagentDepth(topicId) < limits.maxDepth;
|
|
20676
21632
|
}
|
|
20677
21633
|
function patchSubagentCard(parentTopicId, cardMessageId, patch) {
|
|
20678
|
-
const
|
|
20679
|
-
if (!
|
|
21634
|
+
const current3 = host.storage.getMessage(parentTopicId, cardMessageId)?.subagentCard;
|
|
21635
|
+
if (!current3)
|
|
20680
21636
|
return;
|
|
20681
|
-
const next = { ...
|
|
21637
|
+
const next = { ...current3, ...patch };
|
|
20682
21638
|
const editedAt = host.runtime.now();
|
|
20683
21639
|
if (!host.storage.updateSubagentCard(parentTopicId, cardMessageId, next, editedAt))
|
|
20684
21640
|
return;
|
|
@@ -20698,7 +21654,7 @@ function createSubagentLifecycle(host) {
|
|
|
20698
21654
|
patchSubagentCard(watch.parentTopicId, watch.cardMessageId, { status: "running" });
|
|
20699
21655
|
}
|
|
20700
21656
|
}
|
|
20701
|
-
function
|
|
21657
|
+
function takeSubagentWatch2(queryId) {
|
|
20702
21658
|
const childTopicId = childByQueryId.get(queryId);
|
|
20703
21659
|
if (!childTopicId)
|
|
20704
21660
|
return recoverPersistedSubagentWatch(queryId);
|
|
@@ -20742,7 +21698,7 @@ function createSubagentLifecycle(host) {
|
|
|
20742
21698
|
if (watch.queryId)
|
|
20743
21699
|
childByQueryId.delete(watch.queryId);
|
|
20744
21700
|
}
|
|
20745
|
-
function
|
|
21701
|
+
function cancelSubagentWatchForDeletedTopic2(childTopicId) {
|
|
20746
21702
|
const watch = watchesByChild.get(childTopicId);
|
|
20747
21703
|
if (!watch)
|
|
20748
21704
|
return;
|
|
@@ -20772,8 +21728,8 @@ function createSubagentLifecycle(host) {
|
|
|
20772
21728
|
if (!await host.sessionCommunication.notifyParent({ watch, prompt, requestId })) {
|
|
20773
21729
|
appendParentSystemNote(watch, prompt);
|
|
20774
21730
|
}
|
|
20775
|
-
} catch (
|
|
20776
|
-
logger.warn({ err, parentTopicId: watch.parentTopicId, childTopicId: watch.childTopicId, noteKind }, "subagent: parent AI notify failed \u2014 falling back to system message");
|
|
21731
|
+
} catch (err2) {
|
|
21732
|
+
logger.warn({ err: err2, parentTopicId: watch.parentTopicId, childTopicId: watch.childTopicId, noteKind }, "subagent: parent AI notify failed \u2014 falling back to system message");
|
|
20777
21733
|
try {
|
|
20778
21734
|
appendParentSystemNote(watch, prompt);
|
|
20779
21735
|
} catch (fallbackErr) {
|
|
@@ -20785,7 +21741,7 @@ function createSubagentLifecycle(host) {
|
|
|
20785
21741
|
}
|
|
20786
21742
|
}
|
|
20787
21743
|
}
|
|
20788
|
-
async function
|
|
21744
|
+
async function settleSubagentSuccess2(watch, finalText) {
|
|
20789
21745
|
const summary = finalText.replace(/\s+/g, " ").trim().slice(0, RESULT_SUMMARY_CHARS);
|
|
20790
21746
|
try {
|
|
20791
21747
|
patchSubagentCard(watch.parentTopicId, watch.cardMessageId, {
|
|
@@ -20793,8 +21749,8 @@ function createSubagentLifecycle(host) {
|
|
|
20793
21749
|
resultSummary: summary || "(no text response)",
|
|
20794
21750
|
finishedAt: host.runtime.now()
|
|
20795
21751
|
});
|
|
20796
|
-
} catch (
|
|
20797
|
-
logger.warn({ err, parentTopicId: watch.parentTopicId, cardMessageId: watch.cardMessageId }, "subagent: completed-card update failed");
|
|
21752
|
+
} catch (err2) {
|
|
21753
|
+
logger.warn({ err: err2, parentTopicId: watch.parentTopicId, cardMessageId: watch.cardMessageId }, "subagent: completed-card update failed");
|
|
20798
21754
|
}
|
|
20799
21755
|
if (watch.reportMode === "auto") {
|
|
20800
21756
|
await notifyParent(watch, `[Subagent completed \u2190 ${watch.name}]
|
|
@@ -20803,8 +21759,8 @@ function createSubagentLifecycle(host) {
|
|
|
20803
21759
|
${finalText || "(no text response)"}`, "done");
|
|
20804
21760
|
}
|
|
20805
21761
|
}
|
|
20806
|
-
async function
|
|
20807
|
-
const watch =
|
|
21762
|
+
async function settleSubagentFailure2(queryId, reason) {
|
|
21763
|
+
const watch = takeSubagentWatch2(queryId);
|
|
20808
21764
|
if (!watch)
|
|
20809
21765
|
return;
|
|
20810
21766
|
try {
|
|
@@ -20813,8 +21769,8 @@ ${finalText || "(no text response)"}`, "done");
|
|
|
20813
21769
|
errorMessage: reason,
|
|
20814
21770
|
finishedAt: host.runtime.now()
|
|
20815
21771
|
});
|
|
20816
|
-
} catch (
|
|
20817
|
-
logger.warn({ err, parentTopicId: watch.parentTopicId, cardMessageId: watch.cardMessageId }, "subagent: failed-card update failed");
|
|
21772
|
+
} catch (err2) {
|
|
21773
|
+
logger.warn({ err: err2, parentTopicId: watch.parentTopicId, cardMessageId: watch.cardMessageId }, "subagent: failed-card update failed");
|
|
20818
21774
|
}
|
|
20819
21775
|
if (watch.reportMode === "auto") {
|
|
20820
21776
|
await notifyParent(watch, `[Subagent failed \u2190 ${watch.name}]
|
|
@@ -20851,7 +21807,7 @@ spawn_subagent\uB85C \uC704\uC784\uD55C \uC791\uC5C5\uC774 \uC2E4\uD328\uD588\uC
|
|
|
20851
21807
|
function findSubagentCardMessage(childTopicId) {
|
|
20852
21808
|
return host.storage.listSubagentMessages().filter((message) => message.subagentCard?.subagentTopicId === childTopicId).at(-1);
|
|
20853
21809
|
}
|
|
20854
|
-
function
|
|
21810
|
+
function subagentReportMode2(childTopicId) {
|
|
20855
21811
|
return host.storage.getTopic(childTopicId)?.subagentReportMode ?? findSubagentCardMessage(childTopicId)?.subagentCard?.reportMode ?? "auto";
|
|
20856
21812
|
}
|
|
20857
21813
|
async function startSubagentCard(ctx, cardMessage) {
|
|
@@ -21059,7 +22015,7 @@ ${card.task}${reportInstruction}`;
|
|
|
21059
22015
|
for (const siblings of byParent.values()) {
|
|
21060
22016
|
siblings.sort((a, b) => a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id));
|
|
21061
22017
|
}
|
|
21062
|
-
const
|
|
22018
|
+
const descendants2 = [];
|
|
21063
22019
|
const visited = new Set([ctx.topicId]);
|
|
21064
22020
|
const visit = (parentId) => {
|
|
21065
22021
|
for (const child of byParent.get(parentId) ?? []) {
|
|
@@ -21069,12 +22025,12 @@ ${card.task}${reportInstruction}`;
|
|
|
21069
22025
|
if (!child.participants.some((participant) => participant.userId === rootOwnerId && participant.role === "owner")) {
|
|
21070
22026
|
continue;
|
|
21071
22027
|
}
|
|
21072
|
-
|
|
22028
|
+
descendants2.push(child);
|
|
21073
22029
|
visit(child.id);
|
|
21074
22030
|
}
|
|
21075
22031
|
};
|
|
21076
22032
|
visit(ctx.topicId);
|
|
21077
|
-
return
|
|
22033
|
+
return descendants2;
|
|
21078
22034
|
})() : [];
|
|
21079
22035
|
const children = actorScope ? descendants.filter((child) => actorScope.visible.has(child.id)) : descendants;
|
|
21080
22036
|
return {
|
|
@@ -21098,10 +22054,10 @@ ${card.task}${reportInstruction}`;
|
|
|
21098
22054
|
return card?.status ?? "unknown";
|
|
21099
22055
|
}
|
|
21100
22056
|
function listMemoryTopicNames(ctx) {
|
|
21101
|
-
const
|
|
21102
|
-
if (!
|
|
22057
|
+
const current3 = host.storage.getTopic(ctx.topicId);
|
|
22058
|
+
if (!current3)
|
|
21103
22059
|
return { error: `Error: topic '${ctx.topicId}' not found.` };
|
|
21104
|
-
if (!
|
|
22060
|
+
if (!current3.participants.some((participant) => participant.userId === ctx.userId)) {
|
|
21105
22061
|
return { error: "Error: user is not a member of this topic." };
|
|
21106
22062
|
}
|
|
21107
22063
|
const sources = new Map;
|
|
@@ -21191,8 +22147,8 @@ ${card.task}${reportInstruction}`;
|
|
|
21191
22147
|
try {
|
|
21192
22148
|
await host.topic.delete(child, ctx.userId);
|
|
21193
22149
|
return textResult(`Subagent deleted: ${child.title} (${child.id})`);
|
|
21194
|
-
} catch (
|
|
21195
|
-
const message =
|
|
22150
|
+
} catch (err2) {
|
|
22151
|
+
const message = err2 instanceof Error ? err2.message : String(err2);
|
|
21196
22152
|
return errorResult(`Error: failed to delete subagent '${child.title}': ${message}`);
|
|
21197
22153
|
}
|
|
21198
22154
|
}
|
|
@@ -21289,13 +22245,13 @@ ${card.task}${reportInstruction}`;
|
|
|
21289
22245
|
}
|
|
21290
22246
|
return {
|
|
21291
22247
|
computeSubagentDepth,
|
|
21292
|
-
canSpawnSubagentsFromTopic,
|
|
21293
|
-
takeSubagentWatch,
|
|
21294
|
-
cancelSubagentWatchForDeletedTopic,
|
|
21295
|
-
settleSubagentSuccess,
|
|
21296
|
-
settleSubagentFailure,
|
|
22248
|
+
canSpawnSubagentsFromTopic: canSpawnSubagentsFromTopic2,
|
|
22249
|
+
takeSubagentWatch: takeSubagentWatch2,
|
|
22250
|
+
cancelSubagentWatchForDeletedTopic: cancelSubagentWatchForDeletedTopic2,
|
|
22251
|
+
settleSubagentSuccess: settleSubagentSuccess2,
|
|
22252
|
+
settleSubagentFailure: settleSubagentFailure2,
|
|
21297
22253
|
sweepStaleSubagentCards,
|
|
21298
|
-
subagentReportMode,
|
|
22254
|
+
subagentReportMode: subagentReportMode2,
|
|
21299
22255
|
createSubagentManagementToolDefinitions,
|
|
21300
22256
|
createSpawnSubagentToolDefinition,
|
|
21301
22257
|
createPrepareSubagentToolDefinition
|
|
@@ -21342,9 +22298,9 @@ var init_spawn_subagent = __esm(async () => {
|
|
|
21342
22298
|
},
|
|
21343
22299
|
topic: {
|
|
21344
22300
|
async createDerived(input) {
|
|
21345
|
-
await init_derive();
|
|
22301
|
+
const { createDerivedTopic: createDerivedTopic2, TopicDeriveBusyError: TopicDeriveBusyError2, TopicTitleConflictError: TopicTitleConflictError2 } = await init_derive().then(() => exports_derive);
|
|
21346
22302
|
try {
|
|
21347
|
-
const topic = await
|
|
22303
|
+
const topic = await createDerivedTopic2(input.parentTopicId, input.userId, false, {
|
|
21348
22304
|
name: input.name,
|
|
21349
22305
|
subagent: {
|
|
21350
22306
|
agent: input.agent,
|
|
@@ -21354,30 +22310,30 @@ var init_spawn_subagent = __esm(async () => {
|
|
|
21354
22310
|
});
|
|
21355
22311
|
return { ok: true, topic };
|
|
21356
22312
|
} catch (error) {
|
|
21357
|
-
if (error instanceof
|
|
22313
|
+
if (error instanceof TopicTitleConflictError2) {
|
|
21358
22314
|
return { ok: false, reason: "title-conflict", message: error.message };
|
|
21359
22315
|
}
|
|
21360
|
-
if (error instanceof
|
|
22316
|
+
if (error instanceof TopicDeriveBusyError2)
|
|
21361
22317
|
return { ok: false, reason: "busy" };
|
|
21362
22318
|
throw error;
|
|
21363
22319
|
}
|
|
21364
22320
|
},
|
|
21365
22321
|
async delete(topic, userId) {
|
|
21366
|
-
await init_lifecycle();
|
|
21367
|
-
await
|
|
22322
|
+
const { deleteTopicCascade: deleteTopicCascade2 } = await init_lifecycle().then(() => exports_lifecycle);
|
|
22323
|
+
await deleteTopicCascade2(topic, userId);
|
|
21368
22324
|
}
|
|
21369
22325
|
},
|
|
21370
22326
|
task: {
|
|
21371
22327
|
async dispatch(input) {
|
|
21372
|
-
await init_turn_runner();
|
|
21373
|
-
await init_active_rooms();
|
|
21374
|
-
const queryId =
|
|
22328
|
+
const { triggerTopicAiTurn: triggerTopicAiTurn2 } = await init_turn_runner().then(() => exports_turn_runner);
|
|
22329
|
+
const { getRoomQuery: getRoomQuery2 } = await init_active_rooms().then(() => exports_active_rooms);
|
|
22330
|
+
const queryId = triggerTopicAiTurn2(input.child.id, input.userId, input.prompt, undefined, {
|
|
21375
22331
|
origin: `subagent-task:${input.parent.title}`,
|
|
21376
22332
|
requestId: input.requestId,
|
|
21377
22333
|
injectAuthorId: "ai",
|
|
21378
22334
|
onDispatched: input.onDispatched
|
|
21379
22335
|
});
|
|
21380
|
-
return { accepted: Boolean(queryId ||
|
|
22336
|
+
return { accepted: Boolean(queryId || getRoomQuery2(input.child.id)) };
|
|
21381
22337
|
}
|
|
21382
22338
|
},
|
|
21383
22339
|
sessionCommunication: {
|
|
@@ -21385,16 +22341,16 @@ var init_spawn_subagent = __esm(async () => {
|
|
|
21385
22341
|
const parent = getTopic(watch.parentTopicId);
|
|
21386
22342
|
if (!parent)
|
|
21387
22343
|
return true;
|
|
21388
|
-
await init_turn_runner();
|
|
21389
|
-
const queryId = parent.agent ?
|
|
22344
|
+
const { triggerTopicAiTurn: triggerTopicAiTurn2 } = await init_turn_runner().then(() => exports_turn_runner);
|
|
22345
|
+
const queryId = parent.agent ? triggerTopicAiTurn2(watch.parentTopicId, watch.userId, prompt, undefined, {
|
|
21390
22346
|
origin: `subagent:${watch.name}`,
|
|
21391
22347
|
requestId,
|
|
21392
22348
|
hideInjectMessage: true
|
|
21393
22349
|
}) : null;
|
|
21394
22350
|
if (queryId)
|
|
21395
22351
|
return true;
|
|
21396
|
-
await init_active_rooms();
|
|
21397
|
-
return Boolean(parent.agent &&
|
|
22352
|
+
const { interSessionQueue: interSessionQueue2 } = await init_active_rooms().then(() => exports_active_rooms);
|
|
22353
|
+
return Boolean(parent.agent && interSessionQueue2.hasRequest(parent.id, requestId));
|
|
21398
22354
|
},
|
|
21399
22355
|
listTellTargetIds: listSubagentTellTargetIds,
|
|
21400
22356
|
grantTellTarget: grantSubagentTellTarget,
|
|
@@ -21423,19 +22379,19 @@ var init_spawn_subagent = __esm(async () => {
|
|
|
21423
22379
|
async resolveAgentModel({ context, agent, model, hasOverride }) {
|
|
21424
22380
|
let resolvedModel = model;
|
|
21425
22381
|
if (model) {
|
|
21426
|
-
await Promise.resolve().then(() => init_model_catalog());
|
|
21427
|
-
await init_registry();
|
|
21428
|
-
const registry =
|
|
22382
|
+
const { resolveModelForAgent: resolveModelForAgent2 } = await Promise.resolve().then(() => (init_model_catalog(), exports_model_catalog));
|
|
22383
|
+
const { getRegistry: getRegistry2 } = await init_registry().then(() => exports_registry);
|
|
22384
|
+
const registry = getRegistry2(agent);
|
|
21429
22385
|
if (!registry.validateModel(model)) {
|
|
21430
22386
|
return { error: `Error: model '${model}' is not valid for agent '${agent}'.` };
|
|
21431
22387
|
}
|
|
21432
|
-
resolvedModel =
|
|
22388
|
+
resolvedModel = resolveModelForAgent2(agent, model, registry);
|
|
21433
22389
|
}
|
|
21434
22390
|
if (hasOverride) {
|
|
21435
|
-
await init_auth_check();
|
|
21436
|
-
await init_registry();
|
|
21437
|
-
const targetModel = resolvedModel ??
|
|
21438
|
-
const auth =
|
|
22391
|
+
const { checkAgentModelAuth: checkAgentModelAuth2 } = await init_auth_check().then(() => exports_auth_check);
|
|
22392
|
+
const { getRegistry: getRegistry2 } = await init_registry().then(() => exports_registry);
|
|
22393
|
+
const targetModel = resolvedModel ?? getRegistry2(agent).defaultModel;
|
|
22394
|
+
const auth = checkAgentModelAuth2(agent, targetModel, undefined, context.userId);
|
|
21439
22395
|
if (!auth.ok) {
|
|
21440
22396
|
return { error: `Error: agent '${agent}' is not available: ${auth.error}` };
|
|
21441
22397
|
}
|
|
@@ -21865,11 +22821,11 @@ var DEFAULT_SELF_CONFIG_PRODUCT = {
|
|
|
21865
22821
|
derivedTopicLimit: SELF_CONFIG_DERIVED_TOPIC_LIMIT,
|
|
21866
22822
|
toolDescriptions: {}
|
|
21867
22823
|
};
|
|
21868
|
-
function ok(
|
|
21869
|
-
return { text };
|
|
22824
|
+
function ok(text2) {
|
|
22825
|
+
return { text: text2 };
|
|
21870
22826
|
}
|
|
21871
|
-
function err(
|
|
21872
|
-
return { text, isError: true };
|
|
22827
|
+
function err(text2) {
|
|
22828
|
+
return { text: text2, isError: true };
|
|
21873
22829
|
}
|
|
21874
22830
|
function errorMessage(error) {
|
|
21875
22831
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -22186,8 +23142,8 @@ var defaultSelfConfigHost = {
|
|
|
22186
23142
|
},
|
|
22187
23143
|
derivedTopics: {
|
|
22188
23144
|
async create(sourceTopicId, userId, copyHistory, options) {
|
|
22189
|
-
await init_derive();
|
|
22190
|
-
return
|
|
23145
|
+
const { createDerivedTopic: createDerivedTopic2 } = await init_derive().then(() => exports_derive);
|
|
23146
|
+
return createDerivedTopic2(sourceTopicId, userId, copyHistory, options);
|
|
22191
23147
|
},
|
|
22192
23148
|
link: topicMarkdownLink,
|
|
22193
23149
|
isTitleConflict: (error) => error instanceof Error && error.name === "TopicTitleConflictError",
|
|
@@ -22467,58 +23423,58 @@ await __promiseAll([
|
|
|
22467
23423
|
init_topic_cleanup()
|
|
22468
23424
|
]);
|
|
22469
23425
|
export {
|
|
22470
|
-
|
|
22471
|
-
MIN_MEMORY_ARCHIVE_EXCHANGES,
|
|
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,
|
|
23426
|
+
withTaskSnapshots,
|
|
22520
23427
|
withCodexSpawnSerial,
|
|
22521
|
-
|
|
23428
|
+
visualToolDefinitions,
|
|
23429
|
+
unregisterOwnedCodexPids,
|
|
23430
|
+
summarizeToolInput,
|
|
23431
|
+
summarizeShellCommand,
|
|
23432
|
+
summarizeDisplayText,
|
|
23433
|
+
snapshotCodexChildren,
|
|
23434
|
+
showPngTool,
|
|
23435
|
+
showMermaidTool,
|
|
23436
|
+
showImageTool,
|
|
23437
|
+
showHtmlTool,
|
|
23438
|
+
rotateTopicLogs,
|
|
23439
|
+
resolveTaskEventScope,
|
|
23440
|
+
registerOwnedCodexPids,
|
|
23441
|
+
purgeTopicLogs,
|
|
23442
|
+
otiumVisualToolDefinitions,
|
|
23443
|
+
normalizeAskUserQuestionInput,
|
|
23444
|
+
normalizeAskUserChoices,
|
|
23445
|
+
killOwnedCodexTreesForShutdown,
|
|
23446
|
+
killCodexTrees,
|
|
23447
|
+
isExplicitAgentSwitchTargets,
|
|
23448
|
+
hasExplicitAgentSwitchRequest,
|
|
23449
|
+
formatToolUse,
|
|
23450
|
+
forkAgentSession,
|
|
23451
|
+
findNewCodexChildren,
|
|
23452
|
+
explicitAgentSwitchTargets,
|
|
23453
|
+
defaultAskUserDurabilityHost,
|
|
23454
|
+
createTopicLogMaintenance,
|
|
23455
|
+
createSubagentLifecycle,
|
|
23456
|
+
createSelfConfigToolDefinitionsForCore,
|
|
23457
|
+
createSelfConfigRuntime,
|
|
23458
|
+
createSelfConfigCore,
|
|
23459
|
+
createPublishHtmlToolDefinitions,
|
|
23460
|
+
createCodexTreeManager,
|
|
23461
|
+
createAskUserRuntime,
|
|
23462
|
+
createArchiverRuntime,
|
|
23463
|
+
createAgentForkHelpers,
|
|
23464
|
+
cleanupTopicRolloutsFromEntries,
|
|
23465
|
+
cleanupTopicRollouts,
|
|
23466
|
+
cleanupAgentFork,
|
|
23467
|
+
classifyShellToolName,
|
|
23468
|
+
checkAgentModelAuth,
|
|
23469
|
+
checkAgentAuth,
|
|
23470
|
+
buildNumberedDiffSummary,
|
|
23471
|
+
archiveActiveTopicForMemory,
|
|
23472
|
+
applySelfConfigCapabilityFilter,
|
|
23473
|
+
acquireCodexSpawnLock,
|
|
23474
|
+
VISUALS_MCP_KEY,
|
|
23475
|
+
SELF_CONFIG_CAPABILITIES,
|
|
23476
|
+
MIN_MEMORY_ARCHIVE_EXCHANGES,
|
|
23477
|
+
DEFAULT_SELF_CONFIG_PRODUCT
|
|
22522
23478
|
};
|
|
22523
23479
|
|
|
22524
|
-
//# debugId=
|
|
23480
|
+
//# debugId=160F1D6909B0DA3364756E2164756E21
|