negotium 0.2.4 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-helpers.js +241 -127
- package/dist/agent-helpers.js.map +19 -19
- package/dist/background-bash.js +1 -3
- package/dist/background-bash.js.map +4 -4
- package/dist/browser-runtime.js +1 -3
- package/dist/browser-runtime.js.map +4 -4
- package/dist/{chunk-1s9ryz8g.js → chunk-qmbcbhyy.js} +20 -12
- package/dist/chunk-qmbcbhyy.js.map +35 -0
- package/dist/hosted-agent.js +13 -10
- package/dist/hosted-agent.js.map +10 -10
- package/dist/main.js +607 -438
- package/dist/main.js.map +30 -29
- package/dist/mcp-factories.js +238 -123
- package/dist/mcp-factories.js.map +18 -18
- package/dist/prompts.js +1 -3
- package/dist/prompts.js.map +4 -4
- package/dist/query-runtime.js +1 -3
- package/dist/query-runtime.js.map +5 -5
- package/dist/registry.js +3 -3
- package/dist/registry.js.map +2 -2
- package/dist/rollout.js +1 -1
- package/dist/runtime/src/agents/api-topic-agent-switch.ts +6 -12
- package/dist/runtime/src/agents/claude-provider.ts +2 -2
- package/dist/runtime/src/agents/codex-provider.ts +1 -0
- package/dist/runtime/src/agents/index.ts +19 -14
- package/dist/runtime/src/agents/maestro-provider.ts +1 -1
- package/dist/runtime/src/agents/rollout/codex.ts +25 -18
- package/dist/runtime/src/agents/self-config-core.ts +2 -4
- package/dist/runtime/src/agents/topic-agent-switch.ts +4 -10
- package/dist/runtime/src/application/submit-runtime-gateway-turn.ts +91 -19
- package/dist/runtime/src/application/switch-topic-model.ts +7 -10
- package/dist/runtime/src/index.ts +4 -0
- package/dist/runtime/src/mcp/wiki-server.ts +19 -12
- package/dist/runtime/src/platform/config.ts +0 -2
- package/dist/runtime/src/platform/log-rotation.ts +45 -0
- package/dist/runtime/src/platform/mcp-config.ts +9 -3
- package/dist/runtime/src/query/active-rooms.ts +7 -1
- package/dist/runtime/src/runtime/errors.ts +1 -0
- package/dist/runtime/src/runtime/turn-event-stream.ts +46 -1
- package/dist/runtime/src/runtime/turn-runner.ts +176 -100
- package/dist/runtime/src/runtime/user-turn-envelope.ts +19 -0
- package/dist/runtime/src/storage/runtime-gateway-submissions.ts +32 -3
- package/dist/runtime/src/storage/runtime-turn-requests.ts +68 -7
- package/dist/runtime/src/types.ts +2 -0
- package/dist/runtime/src/version.ts +1 -1
- package/dist/runtime-helpers.js +1 -3
- package/dist/runtime-helpers.js.map +4 -4
- package/dist/storage.js.map +1 -1
- package/dist/types/packages/core/src/agents/api-topic-agent-switch.d.ts +1 -1
- package/dist/types/packages/core/src/agents/self-config-core.d.ts +1 -1
- package/dist/types/packages/core/src/platform/config.d.ts +0 -1
- package/dist/types/packages/core/src/platform/mcp-config.d.ts +3 -0
- package/dist/types/packages/core/src/query/active-rooms.d.ts +7 -1
- package/dist/types/packages/core/src/runtime/turn-runner.d.ts +42 -1
- package/dist/types/packages/core/src/runtime/user-turn-envelope.d.ts +7 -0
- package/dist/types/packages/core/src/storage/runtime-turn-requests.d.ts +17 -0
- package/dist/types/packages/core/src/types.d.ts +2 -0
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/dist/vault.js +1 -3
- package/dist/vault.js.map +4 -4
- package/package.json +1 -1
- package/dist/chunk-1s9ryz8g.js.map +0 -35
package/dist/mcp-factories.js
CHANGED
|
@@ -240,7 +240,7 @@ function resolveDefaultModel(agent, registryDefaultModel) {
|
|
|
240
240
|
function codexAuthFilePath() {
|
|
241
241
|
return process.env.NEGOTIUM_CODEX_AUTH_FILE || join(process.env.CODEX_HOME || join(homedir(), ".codex"), "auth.json");
|
|
242
242
|
}
|
|
243
|
-
var HOME, PROJECT_ROOT, STATE_DIR_ENV, STATE_DIR, WORKSPACE_DIR, TOPIC_WORKSPACE_DIR, SHARED_WIKI_DIR, CRON_WORKSPACE_DIR, BROWSER_DIR, BROWSER_PROFILES_DIR, BINARIES_DIR, SECRETS_DIR,
|
|
243
|
+
var HOME, PROJECT_ROOT, STATE_DIR_ENV, STATE_DIR, WORKSPACE_DIR, TOPIC_WORKSPACE_DIR, SHARED_WIKI_DIR, CRON_WORKSPACE_DIR, BROWSER_DIR, BROWSER_PROFILES_DIR, BINARIES_DIR, SECRETS_DIR, DM_WORKSPACE_DIR, SESSION_WORKSPACE_DIR, CLAUDE_EXECUTABLE_ENV, CLAUDE_EXECUTABLE, DEFAULT_OUTPUT_LANGUAGE = "English", BROWSER_RS_VERSION = "v0.1.16", BROWSER_RS_MIN_SECURE_VERSION = "0.1.15", BROWSER_RS_BIN, PLAYWRIGHT_MCP_BIN, TSX_BIN, TSX_LOADER, TSCONFIG_PATH, SESSION_COMM_SERVER, TASK_SERVER, BROWSER_MCP_SSE_PROXY_SERVER, CANONICAL_MCP_PROXY_SERVER, WIKI_SERVER, TOKEN_STATS_SERVER, COMPACTION_LOG_SERVER, SYSTEM_HEALTH_SERVER, AGENT_HEALTH_SERVER, BACKGROUND_BASH_SERVER, VAULT_SERVER, BG_BASH_BASE_PORT, BG_BASH_MAX_PORT, RUNTIME_MCP_SECRET, NODE_CONTROL_TOKEN, VAULT_MASTER_KEY, NEGOTIUM_PORT, hostname, DATA_DIR, LOG_DIR, UPLOADS_DIR, VAULT_DIR, SESSIONS_DB, DEBUG_FILE, USERS_LOG_DIR, RUN_DIR, PROGRESS_DIR, DM_CMD_DIR, DM_RESP_DIR, SESSION_INBOX_DIR, SESSION_ASKS_DIR, PLAYWRIGHT_BASE_PORT, PLAYWRIGHT_MAX_PORT, PLAYWRIGHT_PORTS_DIR, ACTIVE_QUERY_STALE_MS, AGENTS_PROMPTS_DIR, RESOURCES_DIR, FILE_TAG_REGEX, MODEL_SONNET = "claude-sonnet-5", MODEL_OPUS = "claude-opus-5", MODEL_FABLE = "claude-fable-5", FALLBACK_AGENT, SESSION_AGENT, GATEWAY_AGENT, FALLBACK_MODEL, SESSION_MODEL, GATEWAY_MODEL, FFMPEG_BIN, FFPROBE_BIN, PYTHON_BIN, FASTER_WHISPER_WRAPPER, WHISPER_MODEL, TESSERACT_BIN, PDFTOTEXT_BIN, _envMaxTellDepth, MAX_TELL_DEPTH;
|
|
244
244
|
var init_config = __esm(() => {
|
|
245
245
|
init_config_helpers();
|
|
246
246
|
init_logger();
|
|
@@ -257,7 +257,6 @@ var init_config = __esm(() => {
|
|
|
257
257
|
BROWSER_PROFILES_DIR = resolve(BROWSER_DIR, "profiles");
|
|
258
258
|
BINARIES_DIR = resolve(STATE_DIR, "binaries");
|
|
259
259
|
SECRETS_DIR = resolve(STATE_DIR, "secrets");
|
|
260
|
-
CONTEXTS_DIR = resolve(STATE_DIR, "data", "contexts");
|
|
261
260
|
DM_WORKSPACE_DIR = resolve(STATE_DIR, "data", "dm");
|
|
262
261
|
SESSION_WORKSPACE_DIR = resolve(STATE_DIR, "data", "sessions");
|
|
263
262
|
CLAUDE_EXECUTABLE_ENV = envText("NEGOTIUM_CLAUDE_EXECUTABLE");
|
|
@@ -317,7 +316,6 @@ var init_config = __esm(() => {
|
|
|
317
316
|
mkdirSync(TOPIC_WORKSPACE_DIR, { recursive: true });
|
|
318
317
|
mkdirSync(SHARED_WIKI_DIR, { recursive: true });
|
|
319
318
|
mkdirSync(CRON_WORKSPACE_DIR, { recursive: true });
|
|
320
|
-
mkdirSync(CONTEXTS_DIR, { recursive: true });
|
|
321
319
|
mkdirSync(DM_WORKSPACE_DIR, { recursive: true });
|
|
322
320
|
mkdirSync(SESSION_WORKSPACE_DIR, { recursive: true });
|
|
323
321
|
mkdirSync(BROWSER_DIR, { recursive: true });
|
|
@@ -402,6 +400,14 @@ function renderUserPromptBatch(prompts) {
|
|
|
402
400
|
].join(`
|
|
403
401
|
`);
|
|
404
402
|
}
|
|
403
|
+
function renderUserTurnPrompt(message) {
|
|
404
|
+
const rawLabel = message.actorLabel?.trim() || message.actorUserId?.trim();
|
|
405
|
+
const label = rawLabel?.replace(/[\r\n\t]+/g, " ").replace(/\[/g, "(").replace(/\]/g, ")").replace(/\s{2,}/g, " ");
|
|
406
|
+
return label ? `[@${label}]: ${message.prompt}` : message.prompt;
|
|
407
|
+
}
|
|
408
|
+
function renderUserTurnBatch(messages) {
|
|
409
|
+
return renderUserPromptBatch(messages.map(renderUserTurnPrompt));
|
|
410
|
+
}
|
|
405
411
|
|
|
406
412
|
// ../../packages/core/src/agents/rollout/shared.ts
|
|
407
413
|
import { mkdirSync as mkdirSync3 } from "fs";
|
|
@@ -934,7 +940,7 @@ var init_claude_registry = __esm(() => {
|
|
|
934
940
|
});
|
|
935
941
|
|
|
936
942
|
// ../../packages/core/src/version.ts
|
|
937
|
-
var NEGOTIUM_VERSION = "0.2.
|
|
943
|
+
var NEGOTIUM_VERSION = "0.2.6";
|
|
938
944
|
|
|
939
945
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
940
946
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -1761,6 +1767,7 @@ function getManagerMcpServers(opts) {
|
|
|
1761
1767
|
function getForumMcpServers(opts) {
|
|
1762
1768
|
const {
|
|
1763
1769
|
userId,
|
|
1770
|
+
vaultUserId,
|
|
1764
1771
|
session,
|
|
1765
1772
|
topicId,
|
|
1766
1773
|
subagentParentTopicId,
|
|
@@ -1791,6 +1798,7 @@ function getForumMcpServers(opts) {
|
|
|
1791
1798
|
};
|
|
1792
1799
|
const base = buildScope("forum", {
|
|
1793
1800
|
userId,
|
|
1801
|
+
vaultUserId,
|
|
1794
1802
|
session,
|
|
1795
1803
|
topicId,
|
|
1796
1804
|
subagentParentTopicId,
|
|
@@ -1884,6 +1892,7 @@ function getMcpServersForQuery(opts) {
|
|
|
1884
1892
|
}
|
|
1885
1893
|
return getForumMcpServers({
|
|
1886
1894
|
userId: opts.userId || "local",
|
|
1895
|
+
vaultUserId: opts.vaultUserId,
|
|
1887
1896
|
session: opts.session || "default",
|
|
1888
1897
|
topicId: opts.topicId,
|
|
1889
1898
|
subagentParentTopicId: opts.subagentParentTopicId,
|
|
@@ -2085,11 +2094,11 @@ var init_mcp_config = __esm(() => {
|
|
|
2085
2094
|
vault: {
|
|
2086
2095
|
...commonRuntimeMcpPolicy("vault"),
|
|
2087
2096
|
build(ctx) {
|
|
2088
|
-
const { userId, agent } = ctx;
|
|
2089
|
-
const args = [`--user-id=${userId}`];
|
|
2097
|
+
const { userId, vaultUserId, agent } = ctx;
|
|
2098
|
+
const args = [`--user-id=${vaultUserId ?? userId}`];
|
|
2090
2099
|
if (agent !== "codex")
|
|
2091
2100
|
args.push("--list-only=true");
|
|
2092
|
-
return buildBuiltinMcpServer("vault", ctx, () => buildStdioMcpServer(agent, VAULT_SERVER, args));
|
|
2101
|
+
return buildBuiltinMcpServer("vault", { ...ctx, userId: vaultUserId ?? userId }, () => buildStdioMcpServer(agent, VAULT_SERVER, args));
|
|
2093
2102
|
}
|
|
2094
2103
|
}
|
|
2095
2104
|
};
|
|
@@ -2477,6 +2486,18 @@ function patchEnvContext(envContext, cwd, currentDate, timezone) {
|
|
|
2477
2486
|
}
|
|
2478
2487
|
}
|
|
2479
2488
|
}
|
|
2489
|
+
function codexRolloutPath(threadId, fallback) {
|
|
2490
|
+
const threadCreatedAt = decodeUuidV7Timestamp(threadId);
|
|
2491
|
+
const createdAt = threadCreatedAt === null ? fallback : new Date(threadCreatedAt);
|
|
2492
|
+
const yyyy = String(createdAt.getFullYear());
|
|
2493
|
+
const mm = String(createdAt.getMonth() + 1).padStart(2, "0");
|
|
2494
|
+
const dd = String(createdAt.getDate()).padStart(2, "0");
|
|
2495
|
+
const hh = String(createdAt.getHours()).padStart(2, "0");
|
|
2496
|
+
const min = String(createdAt.getMinutes()).padStart(2, "0");
|
|
2497
|
+
const ss = String(createdAt.getSeconds()).padStart(2, "0");
|
|
2498
|
+
const dir = join7(codexSessionsDir(), yyyy, mm, dd);
|
|
2499
|
+
return join7(dir, `rollout-${yyyy}-${mm}-${dd}T${hh}-${min}-${ss}-${threadId}.jsonl`);
|
|
2500
|
+
}
|
|
2480
2501
|
function canonicalFilePath(path) {
|
|
2481
2502
|
const absolute = resolve5(path);
|
|
2482
2503
|
try {
|
|
@@ -2789,12 +2810,7 @@ function writeCodexRollout(opts) {
|
|
|
2789
2810
|
type: "event_msg",
|
|
2790
2811
|
payload: { type: "task_complete" }
|
|
2791
2812
|
});
|
|
2792
|
-
const
|
|
2793
|
-
const mm = String(now.getUTCMonth() + 1).padStart(2, "0");
|
|
2794
|
-
const dd = String(now.getUTCDate()).padStart(2, "0");
|
|
2795
|
-
const tsStr = tsIso.replace(/[:.]/g, "-").slice(0, 19);
|
|
2796
|
-
const dir = join7(codexSessionsDir(), String(yyyy), mm, dd);
|
|
2797
|
-
const path = join7(dir, `rollout-${tsStr}-${threadId}.jsonl`);
|
|
2813
|
+
const path = codexRolloutPath(threadId, now);
|
|
2798
2814
|
if (opts.threadId) {
|
|
2799
2815
|
sweepPriorRolloutsForThread(opts.threadId);
|
|
2800
2816
|
}
|
|
@@ -4711,7 +4727,7 @@ function rowToRequest(row) {
|
|
|
4711
4727
|
if (row.user_messages_json) {
|
|
4712
4728
|
try {
|
|
4713
4729
|
const parsed = JSON.parse(row.user_messages_json);
|
|
4714
|
-
if (Array.isArray(parsed) && parsed.length > 0 && parsed.every((item) => item && typeof item === "object" && typeof item.prompt === "string" && (item.attachments === undefined || Array.isArray(item.attachments) && item.attachments?.every((attachment) => typeof attachment === "string")))) {
|
|
4730
|
+
if (Array.isArray(parsed) && parsed.length > 0 && parsed.every((item) => item && typeof item === "object" && typeof item.prompt === "string" && (item.attachments === undefined || Array.isArray(item.attachments) && item.attachments?.every((attachment) => typeof attachment === "string")) && (item.actorUserId === undefined || typeof item.actorUserId === "string") && (item.actorLabel === undefined || typeof item.actorLabel === "string"))) {
|
|
4715
4731
|
userMessages = parsed;
|
|
4716
4732
|
}
|
|
4717
4733
|
} catch {
|
|
@@ -4763,19 +4779,24 @@ function mergeRuntimeUserTurnRequest(input) {
|
|
|
4763
4779
|
return db.transaction(() => {
|
|
4764
4780
|
const rows = db.query("SELECT * FROM runtime_user_turn_requests WHERE topic_id = ? ORDER BY created_at ASC, rowid ASC").all(input.topicId);
|
|
4765
4781
|
const previous = rows.map(rowToRequest);
|
|
4782
|
+
const omittedRequestIds = new Set([
|
|
4783
|
+
...input.omitRequestIds ?? [],
|
|
4784
|
+
...previous.filter((request) => Boolean(request.execution?.providerSessionId)).map((request) => request.requestId)
|
|
4785
|
+
]);
|
|
4786
|
+
const carried = previous.filter((request) => !omittedRequestIds.has(request.requestId));
|
|
4766
4787
|
const alreadyIncludedRequestIds = new Set(input.alreadyIncludedRequestIds ?? []);
|
|
4767
|
-
const alreadyIncludedMessages =
|
|
4788
|
+
const alreadyIncludedMessages = carried.filter((request) => alreadyIncludedRequestIds.has(request.requestId)).flatMap((request) => request.userMessages);
|
|
4768
4789
|
const includedPrefixMatches = alreadyIncludedMessages.every((message, index) => {
|
|
4769
4790
|
const candidate = input.userMessages[index];
|
|
4770
|
-
return candidate?.prompt === message.prompt && JSON.stringify(candidate.attachments ?? []) === JSON.stringify(message.attachments ?? []);
|
|
4791
|
+
return candidate?.prompt === message.prompt && candidate.actorUserId === message.actorUserId && candidate.actorLabel === message.actorLabel && JSON.stringify(candidate.attachments ?? []) === JSON.stringify(message.attachments ?? []);
|
|
4771
4792
|
});
|
|
4772
4793
|
const alreadyIncludedMessageCount = includedPrefixMatches ? alreadyIncludedMessages.length : 0;
|
|
4773
4794
|
const userMessages = [
|
|
4774
|
-
...
|
|
4795
|
+
...carried.flatMap((request) => request.userMessages),
|
|
4775
4796
|
...input.userMessages.slice(alreadyIncludedMessageCount)
|
|
4776
4797
|
];
|
|
4777
4798
|
const incomingLoggedCount = Math.min(Math.max(0, input.execution.loggedUserMessageCount ?? 0), input.userMessages.length);
|
|
4778
|
-
const loggedUserMessageCount =
|
|
4799
|
+
const loggedUserMessageCount = carried.reduce((count, request) => count + loggedMessageCount(request), 0) + Math.max(0, incomingLoggedCount - alreadyIncludedMessageCount);
|
|
4779
4800
|
const execution = {
|
|
4780
4801
|
...input.execution,
|
|
4781
4802
|
loggedUserMessageCount,
|
|
@@ -4787,7 +4808,7 @@ function mergeRuntimeUserTurnRequest(input) {
|
|
|
4787
4808
|
],
|
|
4788
4809
|
conversationPrompts: userMessages.slice(loggedUserMessageCount).map((message) => message.prompt)
|
|
4789
4810
|
};
|
|
4790
|
-
const sessionBase =
|
|
4811
|
+
const sessionBase = carried.find((request) => request.execution?.sessionIdSpecified)?.execution;
|
|
4791
4812
|
if (sessionBase?.sessionIdSpecified) {
|
|
4792
4813
|
execution.sessionId = sessionBase.sessionId;
|
|
4793
4814
|
execution.sessionIdSpecified = true;
|
|
@@ -4798,13 +4819,29 @@ function mergeRuntimeUserTurnRequest(input) {
|
|
|
4798
4819
|
(request_id, topic_id, user_id, prompt, user_messages_json, attachments_json,
|
|
4799
4820
|
allow_auto_continue, execution_json, topic_epoch, created_at,
|
|
4800
4821
|
status, claimed_by, claimed_at, running_query_id)
|
|
4801
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending', NULL, NULL, NULL)`).run(input.requestId, input.topicId, input.userId,
|
|
4822
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending', NULL, NULL, NULL)`).run(input.requestId, input.topicId, input.userId, renderUserTurnBatch(userMessages), JSON.stringify(userMessages), attachments?.length ? JSON.stringify(attachments) : null, input.allowAutoContinue ? 1 : 0, JSON.stringify(execution), input.topicEpoch, now);
|
|
4802
4823
|
return {
|
|
4803
4824
|
requestId: input.requestId,
|
|
4804
4825
|
supersededRequestIds: previous.map((request) => request.requestId)
|
|
4805
4826
|
};
|
|
4806
4827
|
}).immediate();
|
|
4807
4828
|
}
|
|
4829
|
+
function markRuntimeUserTurnProviderSessionObserved(topicId, requestId, sessionId) {
|
|
4830
|
+
return db.transaction(() => {
|
|
4831
|
+
const row = db.query("SELECT * FROM runtime_user_turn_requests WHERE topic_id = ? AND request_id = ?").get(topicId, requestId);
|
|
4832
|
+
if (!row)
|
|
4833
|
+
return false;
|
|
4834
|
+
const request = rowToRequest(row);
|
|
4835
|
+
const execution = {
|
|
4836
|
+
...request.execution,
|
|
4837
|
+
providerSessionId: sessionId
|
|
4838
|
+
};
|
|
4839
|
+
const result = db.query(`UPDATE runtime_user_turn_requests
|
|
4840
|
+
SET execution_json = ?
|
|
4841
|
+
WHERE topic_id = ? AND request_id = ?`).run(JSON.stringify(execution), topicId, requestId);
|
|
4842
|
+
return result.changes === 1;
|
|
4843
|
+
}).immediate();
|
|
4844
|
+
}
|
|
4808
4845
|
function markRuntimeUserTurnMessagesLogged(topicId, requestId, ownerId, loggedUserMessages) {
|
|
4809
4846
|
if (loggedUserMessages.length === 0)
|
|
4810
4847
|
return false;
|
|
@@ -4812,7 +4849,7 @@ function markRuntimeUserTurnMessagesLogged(topicId, requestId, ownerId, loggedUs
|
|
|
4812
4849
|
const requests = db.query("SELECT * FROM runtime_user_turn_requests WHERE topic_id = ? ORDER BY created_at ASC, rowid ASC").all(topicId).map(rowToRequest);
|
|
4813
4850
|
const hasLoggedPrefix = (request2) => loggedUserMessages.length <= request2.userMessages.length && loggedUserMessages.every((message, index) => {
|
|
4814
4851
|
const candidate = request2.userMessages[index];
|
|
4815
|
-
return candidate?.prompt === message.prompt && JSON.stringify(candidate.attachments ?? []) === JSON.stringify(message.attachments ?? []);
|
|
4852
|
+
return candidate?.prompt === message.prompt && candidate.actorUserId === message.actorUserId && candidate.actorLabel === message.actorLabel && JSON.stringify(candidate.attachments ?? []) === JSON.stringify(message.attachments ?? []);
|
|
4816
4853
|
});
|
|
4817
4854
|
const request = requests.find((candidate) => candidate.requestId === requestId && candidate.claimedBy === ownerId && hasLoggedPrefix(candidate)) ?? requests.find((candidate) => candidate.execution?.supersededRequestIds?.includes(requestId) && hasLoggedPrefix(candidate));
|
|
4818
4855
|
if (!request)
|
|
@@ -7851,7 +7888,7 @@ async function* claudeProvider(opts) {
|
|
|
7851
7888
|
}
|
|
7852
7889
|
};
|
|
7853
7890
|
}
|
|
7854
|
-
const userId = opts.userId ?? "";
|
|
7891
|
+
const userId = opts.vaultUserId ?? opts.userId ?? "";
|
|
7855
7892
|
const withVault = substituteClaudeToolInput(userId, tool_name, tool_input);
|
|
7856
7893
|
if (JSON.stringify(withVault) === JSON.stringify(tool_input)) {
|
|
7857
7894
|
return { continue: true };
|
|
@@ -7871,7 +7908,7 @@ async function* claudeProvider(opts) {
|
|
|
7871
7908
|
hooks: [
|
|
7872
7909
|
async (input) => {
|
|
7873
7910
|
const { tool_response } = input;
|
|
7874
|
-
const userId = opts.userId ?? "";
|
|
7911
|
+
const userId = opts.vaultUserId ?? opts.userId ?? "";
|
|
7875
7912
|
const redacted = deepMapStrings2(tool_response, (value2) => redactHostedSecrets(userId, value2));
|
|
7876
7913
|
if (JSON.stringify(redacted) === JSON.stringify(tool_response)) {
|
|
7877
7914
|
return { continue: true };
|
|
@@ -9285,6 +9322,8 @@ async function* codexProvider(opts) {
|
|
|
9285
9322
|
throw err;
|
|
9286
9323
|
if (!currentSessionId || !isMissingCodexRolloutError(err))
|
|
9287
9324
|
throw err;
|
|
9325
|
+
if (opts.userId && opts.session)
|
|
9326
|
+
throw err;
|
|
9288
9327
|
logger.warn({ staleSessionId: currentSessionId, err: errMsg(err) }, "codexProvider: stale/missing rollout, restarting fresh thread");
|
|
9289
9328
|
thread = codex.startThread(threadOptions);
|
|
9290
9329
|
prompt = promptForThread(opts, true);
|
|
@@ -9584,7 +9623,7 @@ function maestroProvider(opts) {
|
|
|
9584
9623
|
if (opts.agent !== undefined && opts.agent !== "maestro") {
|
|
9585
9624
|
throw new Error(`maestroProvider: unexpected agent "${opts.agent}", expected "maestro"`);
|
|
9586
9625
|
}
|
|
9587
|
-
const userId = opts.userId ?? "";
|
|
9626
|
+
const userId = opts.vaultUserId ?? opts.userId ?? "";
|
|
9588
9627
|
setMcpResolver(hostedMcpServers);
|
|
9589
9628
|
const callerDisallowedTools = opts.disallowedTools ?? [];
|
|
9590
9629
|
const callerToolHooks = opts.toolHooks ?? [];
|
|
@@ -9703,16 +9742,16 @@ async function resolveSessionFileMissing(agent, sessionId, cwd) {
|
|
|
9703
9742
|
}
|
|
9704
9743
|
async function maybeRebuildSession(opts) {
|
|
9705
9744
|
if (!opts.sessionId)
|
|
9706
|
-
return
|
|
9745
|
+
return "ready";
|
|
9707
9746
|
try {
|
|
9708
9747
|
const missing = await resolveSessionFileMissing(opts.agent, opts.sessionId, opts.cwd);
|
|
9709
9748
|
if (!missing)
|
|
9710
|
-
return
|
|
9749
|
+
return "ready";
|
|
9711
9750
|
logger.info({ agent: opts.agent, sessionId: opts.sessionId, topic: opts.session }, "session file missing \u2014 rebuilding from unified log");
|
|
9712
9751
|
const entries = readConversation(opts.userId, opts.session);
|
|
9713
9752
|
if (entries.length === 0) {
|
|
9714
9753
|
logger.info({ agent: opts.agent, sessionId: opts.sessionId }, "no unified log entries to rebuild \u2014 starting fresh session");
|
|
9715
|
-
return
|
|
9754
|
+
return "fresh";
|
|
9716
9755
|
}
|
|
9717
9756
|
const operations = getRegistryOperations(opts.agent);
|
|
9718
9757
|
const result = operations.writeRollout({
|
|
@@ -9723,19 +9762,25 @@ async function maybeRebuildSession(opts) {
|
|
|
9723
9762
|
...opts.effort ? { effort: opts.effort } : {}
|
|
9724
9763
|
});
|
|
9725
9764
|
logger.info({ agent: opts.agent, sessionId: result.sessionId, rolloutPath: result.rolloutPath }, "session rebuilt from unified log");
|
|
9726
|
-
return
|
|
9765
|
+
return "ready";
|
|
9727
9766
|
} catch (err) {
|
|
9728
|
-
logger.warn({ err, agent: opts.agent, sessionId: opts.sessionId }, "session rebuild failed \u2014
|
|
9729
|
-
return
|
|
9767
|
+
logger.warn({ err, agent: opts.agent, sessionId: opts.sessionId }, "session rebuild failed \u2014 preserving resume key");
|
|
9768
|
+
return "failed";
|
|
9730
9769
|
}
|
|
9731
9770
|
}
|
|
9732
9771
|
async function* runAgent(opts) {
|
|
9733
9772
|
const recording = shouldRecordTurn(opts);
|
|
9734
9773
|
const dispatchOpts = { ...opts };
|
|
9735
9774
|
if (hasSessionRepairContext(dispatchOpts)) {
|
|
9736
|
-
const
|
|
9737
|
-
if (
|
|
9775
|
+
const repair = await maybeRebuildSession(dispatchOpts);
|
|
9776
|
+
if (repair === "fresh") {
|
|
9738
9777
|
dispatchOpts.sessionId = undefined;
|
|
9778
|
+
} else if (repair === "failed") {
|
|
9779
|
+
yield {
|
|
9780
|
+
type: "error",
|
|
9781
|
+
content: "Provider session could not be rebuilt from conversation history; the existing session was preserved for retry."
|
|
9782
|
+
};
|
|
9783
|
+
return;
|
|
9739
9784
|
}
|
|
9740
9785
|
}
|
|
9741
9786
|
const taskScope = resolveTaskEventScope(dispatchOpts);
|
|
@@ -13522,7 +13567,7 @@ function classifyAgentError(err, agent) {
|
|
|
13522
13567
|
return `${name} error: ${snippet}`;
|
|
13523
13568
|
}
|
|
13524
13569
|
function isSessionExpiredError(message) {
|
|
13525
|
-
return message.includes(SESSION_EXPIRED_MSG) || /session was recorded with model .+ but is resuming with/i.test(message) || /session.*not found|session.*expired|unknown conversation/i.test(message);
|
|
13570
|
+
return message.includes(SESSION_EXPIRED_MSG) || /session was recorded with model .+ but is resuming with/i.test(message) || /failed to resolve rollout path .+file does not exist/i.test(message) || /session.*not found|session.*expired|unknown conversation/i.test(message);
|
|
13526
13571
|
}
|
|
13527
13572
|
var SESSION_EXPIRED_MSG = "No conversation found with session ID";
|
|
13528
13573
|
var init_errors = __esm(() => {
|
|
@@ -14715,6 +14760,14 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
14715
14760
|
for await (const event of events) {
|
|
14716
14761
|
if (abortController.signal.aborted)
|
|
14717
14762
|
break;
|
|
14763
|
+
if (!control.providerTurnContentObserved && (event.type === "text_delta" || event.type === "text" || event.type === "reasoning" || event.type === "tool_use" || event.type === "tool_result" || event.type === "file" || event.type === "result")) {
|
|
14764
|
+
control.providerTurnContentObserved = true;
|
|
14765
|
+
if (control.sessionId) {
|
|
14766
|
+
for (const requestId of control.durableRequestIds ?? []) {
|
|
14767
|
+
markRuntimeUserTurnProviderSessionObserved(topicId, requestId, control.sessionId);
|
|
14768
|
+
}
|
|
14769
|
+
}
|
|
14770
|
+
}
|
|
14718
14771
|
switch (event.type) {
|
|
14719
14772
|
case "text_delta": {
|
|
14720
14773
|
pendingSawDelta = true;
|
|
@@ -15021,6 +15074,13 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
15021
15074
|
}
|
|
15022
15075
|
break;
|
|
15023
15076
|
case "session":
|
|
15077
|
+
control.sessionId = event.sessionId;
|
|
15078
|
+
control.providerSessionObserved = true;
|
|
15079
|
+
if (control.providerTurnContentObserved) {
|
|
15080
|
+
for (const requestId of control.durableRequestIds ?? []) {
|
|
15081
|
+
markRuntimeUserTurnProviderSessionObserved(topicId, requestId, event.sessionId);
|
|
15082
|
+
}
|
|
15083
|
+
}
|
|
15024
15084
|
if (!silent && onSessionId && getRoomQuery(topicId)?.queryId === queryId) {
|
|
15025
15085
|
try {
|
|
15026
15086
|
if (control.injectParams)
|
|
@@ -15095,7 +15155,9 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
15095
15155
|
if (forkHandle && outcome.kind !== "session-expired" && (!forkRequestId || !interSessionQueue.hasRequest(topicId, forkRequestId))) {
|
|
15096
15156
|
cleanupAgentFork(forkHandle);
|
|
15097
15157
|
}
|
|
15098
|
-
|
|
15158
|
+
const queuedUserTurn = roomId === topicId ? getRuntimeUserTurnRequest(topicId) : null;
|
|
15159
|
+
const hasReplacementUserTurn = queuedUserTurn !== null && queuedUserTurn.requestId !== queryId;
|
|
15160
|
+
if (roomId === topicId && outcome.kind !== "session-expired" && !getRoomQuery(topicId) && !hasReplacementUserTurn) {
|
|
15099
15161
|
const next = takeDeferredInject(topicId);
|
|
15100
15162
|
if (next)
|
|
15101
15163
|
redispatchInject(next);
|
|
@@ -15127,6 +15189,7 @@ var init_turn_event_stream = __esm(async () => {
|
|
|
15127
15189
|
init_visuals(),
|
|
15128
15190
|
init_api_messages(),
|
|
15129
15191
|
init_api_topics(),
|
|
15192
|
+
init_runtime_turn_requests(),
|
|
15130
15193
|
init_token_stats()
|
|
15131
15194
|
]);
|
|
15132
15195
|
});
|
|
@@ -15207,6 +15270,7 @@ __export(exports_turn_runner, {
|
|
|
15207
15270
|
wasLocallyRequeuedAfterUserPreemption: () => wasLocallyRequeuedAfterUserPreemption,
|
|
15208
15271
|
userConversationPromptsToRecord: () => userConversationPromptsToRecord,
|
|
15209
15272
|
upsertTaskPanelMessage: () => upsertTaskPanelMessage,
|
|
15273
|
+
tryReconstructTopicRollout: () => tryReconstructTopicRollout,
|
|
15210
15274
|
triggerTopicAiTurn: () => triggerTopicAiTurn,
|
|
15211
15275
|
topicAllowsVisualFileId: () => topicAllowsVisualFileId,
|
|
15212
15276
|
taskPanelMessageId: () => taskPanelMessageId,
|
|
@@ -15222,9 +15286,11 @@ __export(exports_turn_runner, {
|
|
|
15222
15286
|
resolveVisualMediaInput: () => resolveVisualMediaInput,
|
|
15223
15287
|
resolveTopicTurnSession: () => resolveTopicTurnSession,
|
|
15224
15288
|
resolveTopicTurnExecution: () => resolveTopicTurnExecution,
|
|
15289
|
+
resolveSessionRetry: () => resolveSessionRetry,
|
|
15225
15290
|
resolveModelForAgent: () => resolveModelForAgent,
|
|
15226
15291
|
resolveInitialTurnSessionId: () => resolveInitialTurnSessionId,
|
|
15227
15292
|
resolveCompactionExecution: () => resolveCompactionExecution,
|
|
15293
|
+
renderUserTurnBatch: () => renderUserTurnBatch,
|
|
15228
15294
|
renderUserPromptBatch: () => renderUserPromptBatch,
|
|
15229
15295
|
renderTaskPanel: () => renderTaskPanel,
|
|
15230
15296
|
promptWithAttachments: () => promptWithAttachments,
|
|
@@ -15379,6 +15445,7 @@ function redispatchInject(inject) {
|
|
|
15379
15445
|
aiMention: topic.aiMention
|
|
15380
15446
|
},
|
|
15381
15447
|
userId: inject.userId,
|
|
15448
|
+
vaultUserId: inject.vaultUserId,
|
|
15382
15449
|
prompt: inject.prompt,
|
|
15383
15450
|
allowAutoContinue: false,
|
|
15384
15451
|
origin: inject.origin,
|
|
@@ -15504,12 +15571,10 @@ async function deliverAskError(queryId, sourceLabel, error) {
|
|
|
15504
15571
|
}
|
|
15505
15572
|
function tryReconstructTopicRollout(opts) {
|
|
15506
15573
|
const { topicId, topicTitle, userId, agent, sessionId, cwd, model, effort } = opts;
|
|
15507
|
-
if (!sessionId && !opts.allowFreshSession)
|
|
15508
|
-
return null;
|
|
15509
15574
|
try {
|
|
15510
15575
|
const entries = readConversation(userId, topicTitle);
|
|
15511
15576
|
if (entries.length === 0)
|
|
15512
|
-
return
|
|
15577
|
+
return { kind: "no-history" };
|
|
15513
15578
|
const result = getRegistryOperations(agent).writeRollout({
|
|
15514
15579
|
cwd,
|
|
15515
15580
|
entries,
|
|
@@ -15524,15 +15589,18 @@ function tryReconstructTopicRollout(opts) {
|
|
|
15524
15589
|
rolloutPath: result.rolloutPath,
|
|
15525
15590
|
entries: entries.length
|
|
15526
15591
|
}, sessionId ? "ai: session expired \u2014 rollout reconstructed from unified log" : "ai: provider session bridged from shared conversation log");
|
|
15527
|
-
return result.sessionId;
|
|
15592
|
+
return { kind: "rebuilt", sessionId: result.sessionId };
|
|
15528
15593
|
} catch (err) {
|
|
15529
15594
|
logger.warn({ err, topicId, agent, sessionId }, "ai: session reconstruct failed");
|
|
15530
|
-
return
|
|
15595
|
+
return { kind: "failed", error: stringifyError(err) };
|
|
15531
15596
|
}
|
|
15532
15597
|
}
|
|
15533
|
-
function
|
|
15598
|
+
function resolveSessionRetry(opts) {
|
|
15534
15599
|
const reconstructed = tryReconstructTopicRollout(opts);
|
|
15535
|
-
if (reconstructed)
|
|
15600
|
+
if (reconstructed.kind === "rebuilt") {
|
|
15601
|
+
return { kind: "retry", sessionId: reconstructed.sessionId };
|
|
15602
|
+
}
|
|
15603
|
+
if (reconstructed.kind === "failed")
|
|
15536
15604
|
return reconstructed;
|
|
15537
15605
|
if (opts.onSessionReset)
|
|
15538
15606
|
opts.onSessionReset();
|
|
@@ -15540,7 +15608,7 @@ function resolveSessionRetryId(opts) {
|
|
|
15540
15608
|
clearTopicSessionId(opts.topicId, "session-expired");
|
|
15541
15609
|
}
|
|
15542
15610
|
logger.info({ topicId: opts.topicId, agent: opts.agent, hadSessionId: Boolean(opts.sessionId) }, "ai: session expired \u2014 retrying with fresh session");
|
|
15543
|
-
return null;
|
|
15611
|
+
return { kind: "retry", sessionId: null };
|
|
15544
15612
|
}
|
|
15545
15613
|
function mergeSupersedingUserTurn(running, incoming) {
|
|
15546
15614
|
const userMessages = [
|
|
@@ -15548,7 +15616,7 @@ function mergeSupersedingUserTurn(running, incoming) {
|
|
|
15548
15616
|
...incoming.userMessages ?? [legacyUserTurnEnvelope(incoming.prompt, incoming.attachments)]
|
|
15549
15617
|
];
|
|
15550
15618
|
return {
|
|
15551
|
-
prompt:
|
|
15619
|
+
prompt: renderUserTurnBatch(userMessages),
|
|
15552
15620
|
userMessages,
|
|
15553
15621
|
attachments: flattenUserTurnAttachments(userMessages),
|
|
15554
15622
|
sessionId: running.sessionId
|
|
@@ -15575,11 +15643,12 @@ function serializableUserTurnExecution(params) {
|
|
|
15575
15643
|
bridgeSessionFromHistory: params.bridgeSessionFromHistory,
|
|
15576
15644
|
peerBridge: params.peerBridge,
|
|
15577
15645
|
from: params.from,
|
|
15646
|
+
vaultUserId: params.vaultUserId,
|
|
15578
15647
|
conversationPrompts: params._conversationPrompts ?? params._userMessages?.map((message) => message.prompt) ?? [params.prompt],
|
|
15579
15648
|
loggedUserMessageCount: params._loggedUserMessageCount
|
|
15580
15649
|
};
|
|
15581
15650
|
}
|
|
15582
|
-
function waitToStartRemoteUserTurn(params, queryId) {
|
|
15651
|
+
function waitToStartRemoteUserTurn(params, queryId, options) {
|
|
15583
15652
|
const execution = serializableUserTurnExecution(params);
|
|
15584
15653
|
const incomingUserMessages = params._userMessages ?? [
|
|
15585
15654
|
legacyUserTurnEnvelope(params.prompt, params.attachments)
|
|
@@ -15592,7 +15661,8 @@ function waitToStartRemoteUserTurn(params, queryId) {
|
|
|
15592
15661
|
requestId: queryId,
|
|
15593
15662
|
execution,
|
|
15594
15663
|
topicEpoch: execution.runtimeEpoch ?? getRuntimeTopicEpoch(params.topic.id),
|
|
15595
|
-
alreadyIncludedRequestIds: params._durableRequestIds
|
|
15664
|
+
alreadyIncludedRequestIds: params._durableRequestIds,
|
|
15665
|
+
omitRequestIds: options?.omitRequestIds
|
|
15596
15666
|
});
|
|
15597
15667
|
for (const supersededRequestId of merged.supersededRequestIds) {
|
|
15598
15668
|
if (supersededRequestId !== merged.requestId) {
|
|
@@ -15643,6 +15713,7 @@ async function drainOneDurableUserTurn() {
|
|
|
15643
15713
|
const queryId = startAiTurn({
|
|
15644
15714
|
topic,
|
|
15645
15715
|
userId: request.userId,
|
|
15716
|
+
vaultUserId: execution?.vaultUserId,
|
|
15646
15717
|
prompt: request.prompt,
|
|
15647
15718
|
_userMessages: request.userMessages,
|
|
15648
15719
|
_conversationPrompts: execution?.conversationPrompts ?? [request.prompt],
|
|
@@ -15713,12 +15784,13 @@ function startAiTurn(params) {
|
|
|
15713
15784
|
}
|
|
15714
15785
|
const topic = storedTopic;
|
|
15715
15786
|
const { userId, allowAutoContinue, onDispatched } = params;
|
|
15787
|
+
const vaultUserId = params.vaultUserId ?? userId;
|
|
15716
15788
|
const origin = params.origin ?? "user";
|
|
15717
15789
|
const conversationPrompts = params._conversationPrompts ?? [params.prompt];
|
|
15718
15790
|
let loggedUserMessageCount = params._loggedUserMessageCount;
|
|
15719
15791
|
let durableRequestIds = params._durableRequestIds ?? [];
|
|
15720
15792
|
let userMessages = isUserOrigin(origin) ? params._userMessages ?? [legacyUserTurnEnvelope(params.prompt, params.attachments)] : undefined;
|
|
15721
|
-
let prompt = userMessages ?
|
|
15793
|
+
let prompt = userMessages ? renderUserTurnBatch(userMessages) : params.prompt;
|
|
15722
15794
|
let attachments2 = userMessages ? flattenUserTurnAttachments(userMessages) : params.attachments;
|
|
15723
15795
|
const execution = resolveTopicTurnExecution(topic, params);
|
|
15724
15796
|
const sessionResolution = resolveTopicTurnSession(topic, params.sessionId, {
|
|
@@ -15783,6 +15855,7 @@ function startAiTurn(params) {
|
|
|
15783
15855
|
topicId,
|
|
15784
15856
|
runtimeEpoch,
|
|
15785
15857
|
userId,
|
|
15858
|
+
vaultUserId,
|
|
15786
15859
|
prompt,
|
|
15787
15860
|
origin,
|
|
15788
15861
|
sourceNode,
|
|
@@ -15867,16 +15940,22 @@ function startAiTurn(params) {
|
|
|
15867
15940
|
}
|
|
15868
15941
|
if (decision.action === "abort-replace") {
|
|
15869
15942
|
const running = decision.running;
|
|
15943
|
+
let omitRequestIds;
|
|
15870
15944
|
if (isUserOrigin(running.origin)) {
|
|
15871
|
-
|
|
15872
|
-
|
|
15873
|
-
|
|
15874
|
-
|
|
15875
|
-
|
|
15876
|
-
|
|
15877
|
-
|
|
15878
|
-
|
|
15879
|
-
|
|
15945
|
+
if (running.providerTurnContentObserved && running.sessionId) {
|
|
15946
|
+
sessionId = running.sessionId;
|
|
15947
|
+
omitRequestIds = running.durableRequestIds;
|
|
15948
|
+
} else {
|
|
15949
|
+
const merged = mergeSupersedingUserTurn(running, { prompt, userMessages, attachments: attachments2 });
|
|
15950
|
+
userMessages = merged.userMessages;
|
|
15951
|
+
prompt = merged.prompt;
|
|
15952
|
+
attachments2 = merged.attachments;
|
|
15953
|
+
sessionId = merged.sessionId;
|
|
15954
|
+
loggedUserMessageCount = running.userMessages?.length ?? 1;
|
|
15955
|
+
durableRequestIds = [
|
|
15956
|
+
...new Set([...running.durableRequestIds ?? [], ...durableRequestIds])
|
|
15957
|
+
];
|
|
15958
|
+
}
|
|
15880
15959
|
}
|
|
15881
15960
|
if (running.injectParams) {
|
|
15882
15961
|
const runningInject = running.injectParams;
|
|
@@ -15897,6 +15976,20 @@ function startAiTurn(params) {
|
|
|
15897
15976
|
running.abortReason = "internal" /* Internal */;
|
|
15898
15977
|
running.abortController.abort();
|
|
15899
15978
|
logger.info({ topicId, supersededQueryId: running.queryId, supersededOrigin: running.origin }, "ai: new user message superseded running turn");
|
|
15979
|
+
const queuedQueryId = waitToStartRemoteUserTurn({
|
|
15980
|
+
...params,
|
|
15981
|
+
topic,
|
|
15982
|
+
prompt,
|
|
15983
|
+
attachments: attachments2,
|
|
15984
|
+
sessionId,
|
|
15985
|
+
_userMessages: userMessages,
|
|
15986
|
+
_conversationPrompts: conversationPrompts,
|
|
15987
|
+
_loggedUserMessageCount: loggedUserMessageCount,
|
|
15988
|
+
_durableRequestIds: durableRequestIds,
|
|
15989
|
+
_runtimeEpoch: runtimeEpoch
|
|
15990
|
+
}, queryId, { omitRequestIds });
|
|
15991
|
+
announceQueuedUserTurn({ ...params, topic }, queuedQueryId);
|
|
15992
|
+
return queuedQueryId;
|
|
15900
15993
|
}
|
|
15901
15994
|
const abortController = new AbortController;
|
|
15902
15995
|
const control = {
|
|
@@ -15915,6 +16008,7 @@ function startAiTurn(params) {
|
|
|
15915
16008
|
topicId,
|
|
15916
16009
|
runtimeEpoch,
|
|
15917
16010
|
userId,
|
|
16011
|
+
vaultUserId,
|
|
15918
16012
|
prompt,
|
|
15919
16013
|
origin,
|
|
15920
16014
|
requestId,
|
|
@@ -15988,8 +16082,9 @@ function startAiTurn(params) {
|
|
|
15988
16082
|
const resolvedEffort = execution.effort;
|
|
15989
16083
|
const workspaceCwd = cwd ?? workspaceCwdFor(topicId);
|
|
15990
16084
|
mkdirSync20(workspaceCwd, { recursive: true });
|
|
16085
|
+
let historyBridgeError;
|
|
15991
16086
|
if (bridgeSessionFromHistory && !sessionId) {
|
|
15992
|
-
const
|
|
16087
|
+
const bridge = tryReconstructTopicRollout({
|
|
15993
16088
|
topicId,
|
|
15994
16089
|
topicTitle: sessionName,
|
|
15995
16090
|
userId,
|
|
@@ -15997,25 +16092,32 @@ function startAiTurn(params) {
|
|
|
15997
16092
|
sessionId: null,
|
|
15998
16093
|
cwd: workspaceCwd,
|
|
15999
16094
|
model: resolvedModel,
|
|
16000
|
-
...resolvedEffort ? { effort: resolvedEffort } : {}
|
|
16001
|
-
allowFreshSession: true
|
|
16095
|
+
...resolvedEffort ? { effort: resolvedEffort } : {}
|
|
16002
16096
|
});
|
|
16003
|
-
if (
|
|
16004
|
-
sessionId =
|
|
16005
|
-
control.sessionId =
|
|
16097
|
+
if (bridge.kind === "rebuilt") {
|
|
16098
|
+
sessionId = bridge.sessionId;
|
|
16099
|
+
control.sessionId = bridge.sessionId;
|
|
16006
16100
|
if (control.injectParams)
|
|
16007
|
-
control.injectParams.sessionId =
|
|
16101
|
+
control.injectParams.sessionId = bridge.sessionId;
|
|
16008
16102
|
try {
|
|
16009
|
-
onSessionId?.(
|
|
16103
|
+
onSessionId?.(bridge.sessionId);
|
|
16010
16104
|
} catch (err) {
|
|
16011
16105
|
logger.warn({ err, topicId, queryId, agent: agentKind }, "ai: isolated session owner rejected bridged provider session id");
|
|
16012
16106
|
}
|
|
16107
|
+
} else if (bridge.kind === "failed") {
|
|
16108
|
+
historyBridgeError = "Conversation history could not be encoded into a provider session; no fresh session was started.";
|
|
16013
16109
|
}
|
|
16014
16110
|
}
|
|
16015
16111
|
const messageAttachmentGroups = userMessages?.map((message, index) => materializePromptAttachments(topicId, `${queryId}-${index}`, message.attachments));
|
|
16016
16112
|
const promptAttachments = messageAttachmentGroups?.flat() ?? materializePromptAttachments(topicId, queryId, attachments2);
|
|
16017
|
-
const promptWithFiles = userMessages ?
|
|
16018
|
-
|
|
16113
|
+
const promptWithFiles = userMessages ? renderUserTurnBatch(userMessages.map((message, index) => ({
|
|
16114
|
+
...message,
|
|
16115
|
+
prompt: promptWithAttachments(message.prompt, messageAttachmentGroups?.[index] ?? [])
|
|
16116
|
+
}))) : promptWithAttachments(prompt, promptAttachments);
|
|
16117
|
+
const renderedUserPrompts = userMessages ? userMessages.map((message, index) => renderUserTurnPrompt({
|
|
16118
|
+
...message,
|
|
16119
|
+
prompt: promptWithAttachments(message.prompt, messageAttachmentGroups?.[index] ?? [])
|
|
16120
|
+
})) : undefined;
|
|
16019
16121
|
const agentPrompt = topic.aiMode === "mention" && isUserOrigin(origin) && !silent ? buildMentionOnlyChannelPrompt({
|
|
16020
16122
|
topicId,
|
|
16021
16123
|
userId,
|
|
@@ -16131,6 +16233,10 @@ function startAiTurn(params) {
|
|
|
16131
16233
|
const turnMcpEnabled = browserProfileOwner ? enabledMcp : enabledMcp.filter((name) => name !== "playwright");
|
|
16132
16234
|
const wantsBgBash = !isManager && enabledMcp.includes("background-bash");
|
|
16133
16235
|
async function* runWithPlaywright() {
|
|
16236
|
+
if (historyBridgeError) {
|
|
16237
|
+
yield { type: "error", content: historyBridgeError };
|
|
16238
|
+
return;
|
|
16239
|
+
}
|
|
16134
16240
|
if (prepareSession && !sessionId) {
|
|
16135
16241
|
if (abortController.signal.aborted)
|
|
16136
16242
|
return;
|
|
@@ -16203,6 +16309,7 @@ ${playwrightNote}`;
|
|
|
16203
16309
|
systemPrompt: effectiveSystemPrompt,
|
|
16204
16310
|
sessionId,
|
|
16205
16311
|
userId,
|
|
16312
|
+
vaultUserId,
|
|
16206
16313
|
session: sessionName,
|
|
16207
16314
|
sessionType: sessionType ?? (isManager ? "manager" : "forum"),
|
|
16208
16315
|
abortController,
|
|
@@ -16236,11 +16343,10 @@ ${playwrightNote}`;
|
|
|
16236
16343
|
WsHub.get().broadcastTyping(topicId, "ai");
|
|
16237
16344
|
WsHub.get().broadcastAiActive(topicId, queryId);
|
|
16238
16345
|
}
|
|
16239
|
-
streamAgentEvents(topicId, topic.title, queryId, events, control, agentKind, resolvedModel, resolvedEffort, userId, !sessionRetried, onSessionId, { silent, peerBridge, sourceNode }).then(async (
|
|
16346
|
+
streamAgentEvents(topicId, topic.title, queryId, events, control, agentKind, resolvedModel, resolvedEffort, userId, !sessionRetried, onSessionId, { silent, peerBridge, sourceNode }).then(async (streamOutcome) => {
|
|
16347
|
+
let outcome = streamOutcome;
|
|
16240
16348
|
if (outcome.kind === "session-expired") {
|
|
16241
|
-
|
|
16242
|
-
WsHub.get().broadcastAborted(topicId, queryId, "stopped");
|
|
16243
|
-
const retrySessionId = resolveSessionRetryId({
|
|
16349
|
+
const retry = resolveSessionRetry({
|
|
16244
16350
|
topicId,
|
|
16245
16351
|
topicTitle: sessionName,
|
|
16246
16352
|
userId,
|
|
@@ -16253,55 +16359,66 @@ ${playwrightNote}`;
|
|
|
16253
16359
|
externalSessionOwner: Boolean(onSessionId),
|
|
16254
16360
|
onSessionReset
|
|
16255
16361
|
});
|
|
16256
|
-
|
|
16257
|
-
|
|
16258
|
-
|
|
16259
|
-
|
|
16260
|
-
|
|
16261
|
-
}
|
|
16262
|
-
|
|
16263
|
-
|
|
16264
|
-
|
|
16362
|
+
if (retry.kind === "failed") {
|
|
16363
|
+
outcome = {
|
|
16364
|
+
kind: "provider-error",
|
|
16365
|
+
error: "Provider session expired and conversation history could not be rebuilt; the existing session was preserved for retry."
|
|
16366
|
+
};
|
|
16367
|
+
} else {
|
|
16368
|
+
if (!silent)
|
|
16369
|
+
WsHub.get().broadcastAborted(topicId, queryId, "stopped");
|
|
16370
|
+
const retrySessionId = retry.sessionId;
|
|
16371
|
+
logger.info({
|
|
16372
|
+
topicId,
|
|
16373
|
+
prevQueryId: queryId,
|
|
16374
|
+
agent: agentKind,
|
|
16375
|
+
retrySessionId: retrySessionId ? retrySessionId.slice(0, 8) : null
|
|
16376
|
+
}, "ai: retrying query after session expiry");
|
|
16377
|
+
if (!retrySessionId && prepareSession && forkHandle) {
|
|
16378
|
+
cleanupAgentFork(forkHandle);
|
|
16379
|
+
forkHandle = undefined;
|
|
16380
|
+
}
|
|
16381
|
+
startAiTurn({
|
|
16382
|
+
topic,
|
|
16383
|
+
userId,
|
|
16384
|
+
vaultUserId,
|
|
16385
|
+
prompt,
|
|
16386
|
+
_userMessages: userMessages,
|
|
16387
|
+
_conversationPrompts: conversationPrompts,
|
|
16388
|
+
_loggedUserMessageCount: loggedUserMessageCount,
|
|
16389
|
+
_durableRequestIds: durableRequestIds,
|
|
16390
|
+
attachments: attachments2,
|
|
16391
|
+
allowAutoContinue,
|
|
16392
|
+
origin,
|
|
16393
|
+
onDispatched,
|
|
16394
|
+
requestId,
|
|
16395
|
+
depth,
|
|
16396
|
+
silent,
|
|
16397
|
+
contextId,
|
|
16398
|
+
agentOverride,
|
|
16399
|
+
modelOverride,
|
|
16400
|
+
effortOverride,
|
|
16401
|
+
sessionId: retrySessionId,
|
|
16402
|
+
sessionScope,
|
|
16403
|
+
turnConcurrency,
|
|
16404
|
+
forkHandle,
|
|
16405
|
+
prepareSession,
|
|
16406
|
+
cwd,
|
|
16407
|
+
sessionName,
|
|
16408
|
+
sessionType,
|
|
16409
|
+
visualTools,
|
|
16410
|
+
fileDeliveryTools,
|
|
16411
|
+
onSessionId,
|
|
16412
|
+
onSessionReset,
|
|
16413
|
+
bridgeSessionFromHistory,
|
|
16414
|
+
onSettled,
|
|
16415
|
+
peerBridge,
|
|
16416
|
+
askReplySources,
|
|
16417
|
+
_runtimeEpoch: runtimeEpoch,
|
|
16418
|
+
_sessionRetried: true
|
|
16419
|
+
});
|
|
16420
|
+
return;
|
|
16265
16421
|
}
|
|
16266
|
-
startAiTurn({
|
|
16267
|
-
topic,
|
|
16268
|
-
userId,
|
|
16269
|
-
prompt,
|
|
16270
|
-
_userMessages: userMessages,
|
|
16271
|
-
_conversationPrompts: conversationPrompts,
|
|
16272
|
-
_loggedUserMessageCount: loggedUserMessageCount,
|
|
16273
|
-
_durableRequestIds: durableRequestIds,
|
|
16274
|
-
attachments: attachments2,
|
|
16275
|
-
allowAutoContinue,
|
|
16276
|
-
origin,
|
|
16277
|
-
onDispatched,
|
|
16278
|
-
requestId,
|
|
16279
|
-
depth,
|
|
16280
|
-
silent,
|
|
16281
|
-
contextId,
|
|
16282
|
-
agentOverride,
|
|
16283
|
-
modelOverride,
|
|
16284
|
-
effortOverride,
|
|
16285
|
-
sessionId: retrySessionId,
|
|
16286
|
-
sessionScope,
|
|
16287
|
-
turnConcurrency,
|
|
16288
|
-
forkHandle,
|
|
16289
|
-
prepareSession,
|
|
16290
|
-
cwd,
|
|
16291
|
-
sessionName,
|
|
16292
|
-
sessionType,
|
|
16293
|
-
visualTools,
|
|
16294
|
-
fileDeliveryTools,
|
|
16295
|
-
onSessionId,
|
|
16296
|
-
onSessionReset,
|
|
16297
|
-
bridgeSessionFromHistory,
|
|
16298
|
-
onSettled,
|
|
16299
|
-
peerBridge,
|
|
16300
|
-
askReplySources,
|
|
16301
|
-
_runtimeEpoch: runtimeEpoch,
|
|
16302
|
-
_sessionRetried: true
|
|
16303
|
-
});
|
|
16304
|
-
return;
|
|
16305
16422
|
}
|
|
16306
16423
|
if (outcome.kind === "provider-error") {
|
|
16307
16424
|
if (!silent) {
|
|
@@ -18080,19 +18197,17 @@ function wikiLastConversation(args) {
|
|
|
18080
18197
|
}
|
|
18081
18198
|
const name = slugify(topicNameFrom(rawTopic));
|
|
18082
18199
|
const archiveDir = resolve2(runtime().archiveDir, name);
|
|
18083
|
-
ensureDir(archiveDir);
|
|
18084
18200
|
try {
|
|
18085
|
-
let files = readdirSync(archiveDir).filter((f) => f.endsWith(".jsonl")).sort().reverse();
|
|
18201
|
+
let files = existsSync2(archiveDir) ? readdirSync(archiveDir).filter((f) => f.endsWith(".jsonl")).sort().reverse() : [];
|
|
18086
18202
|
if (files.length === 0) {
|
|
18087
|
-
|
|
18088
|
-
files = readdirSync(runtime().archiveDir).filter((f) => f.startsWith(name) && f.endsWith(".jsonl")).sort().reverse();
|
|
18203
|
+
files = existsSync2(runtime().archiveDir) ? readdirSync(runtime().archiveDir).filter((f) => f.startsWith(name) && f.endsWith(".jsonl")).sort().reverse() : [];
|
|
18089
18204
|
}
|
|
18090
18205
|
if (files.length === 0) {
|
|
18091
18206
|
return {
|
|
18092
18207
|
content: [{ type: "text", text: `No archive found for topic: ${rawTopic}` }]
|
|
18093
18208
|
};
|
|
18094
18209
|
}
|
|
18095
|
-
const actualPath = files[0].includes("/") ? files[0] : resolve2(readdirSync(archiveDir).includes(files[0]) ? archiveDir : runtime().archiveDir, files[0]);
|
|
18210
|
+
const actualPath = files[0].includes("/") ? files[0] : resolve2(existsSync2(archiveDir) && readdirSync(archiveDir).includes(files[0]) ? archiveDir : runtime().archiveDir, files[0]);
|
|
18096
18211
|
try {
|
|
18097
18212
|
const raw = readFileSync2(actualPath, "utf-8");
|
|
18098
18213
|
const lines = raw.trim().split(`
|
|
@@ -19538,4 +19653,4 @@ export {
|
|
|
19538
19653
|
createAgentHealthMcpServer
|
|
19539
19654
|
};
|
|
19540
19655
|
|
|
19541
|
-
//# debugId=
|
|
19656
|
+
//# debugId=09A6616F9F0036C964756E2164756E21
|