@tea-agent/loop-agent 0.44.0-next.2 → 0.44.0-next.4
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/CHANGELOG.md +5 -3
- package/dist/build-stamp.json +3 -3
- package/dist/executors/dag-pi-executor.js +2 -2
- package/dist/task/config-types.js +2 -1
- package/dist/task/contract/schema.js +1 -0
- package/dist/worker/console/chat/chat-event-store.js +32 -0
- package/dist/worker/console/chat/conversation-nodes.js +383 -0
- package/dist/worker/console/chat/db-connections.js +48 -16
- package/dist/worker/console/chat/pi-runtime.js +131 -15
- package/dist/worker/console/chat/provider-error.js +0 -12
- package/dist/worker/console/chat/routes.js +136 -3
- package/dist/worker/console/chat/turn-process.js +128 -7
- package/dist/worker/console/prd-intake-bridge.js +3 -0
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-B8EdIjdl.js → abnfDiagram-N423BO3Z-B_lmJjOm.js} +1 -1
- package/dist/worker/console/static/assets/{arc-CUaduV17.js → arc-pymM4Qeh.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-bYAcxRaf.js → architectureDiagram-T3A2C74G-Bw9EPAhi.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-FfhFUEMJ.js → blockDiagram-VBNYF7ZC-C7_oXJp2.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-0Rqwn2_U.js → c4Diagram-5PPSVZJV-LnLWDbh8.js} +1 -1
- package/dist/worker/console/static/assets/channel-Ym13M3Lb.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-D4FbDmsM.js → chunk-2GRJ4B5K-BBiu3sCW.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-C2nu32ml.js → chunk-2Q5K7J3B-DiXqDQml.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-G2tHSClK.js → chunk-5RXB4S5H-lmNq9nYk.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-181nyzuH.js → chunk-5VM5RSS4-boBu74dU.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-D091VbiQ.js → chunk-6Q2QTUOP-CjxqoJLQ.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-BjrMCKTH.js → chunk-GF5L2VYU-DL0vQ9MG.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-T3zFHTpb.js → chunk-JWPE2WC7-DGPqE-O0.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-CIB7wrYq.js → chunk-KBJHAD2P-v4BbT_r2.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-HwnAsgDw.js → chunk-RYQCIY6F-Ci0ynvyL.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CQSdQAqo.js → chunk-XXDRQBXY-CGsbJoTV.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BeFR1wGo.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BeFR1wGo.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CyBVLpjP.js → cose-bilkent-JH36ORCC-CzoRDEI7.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-D2Pf3U7m.js → cynefin-VYW2F7L2-BOwFwbX4.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-CzXuQ1a2.js → cynefinDiagram-MW4NZA55-2Cfg451l.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-9cMmcOsQ.js → dagre-VZM6K2ZE-DbT0D6Y5.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-DTOr8GLs.js → diagram-7IWD3JNH-Dfd_JoMs.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-B8saqFHU.js → diagram-B4RE2ZJO-DaGm82kh.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-Bvygp--w.js → diagram-LBJQPF4R-DMoI8Ibc.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-CJyLwBhZ.js → diagram-Q27KOJAE-BtIFA3aY.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-CkR1FDRN.js → diagram-UB23O5K3-D_2X1DTZ.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BsbNtwvi.js → ebnfDiagram-BXEA7PRR-yFW5ZYlZ.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-EVZo9AKy.js → erDiagram-JOGREHBK-DBXh5Svj.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-C1x91tWN.js → flowDiagram-UKHOOZJN-C4ycm8KM.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-CiNBUsrJ.js → ganttDiagram-PKOTCBZU-qr-_Pekr.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-CSd50p3d.js → gitGraphDiagram-DS77QQ5N-DzOSLv_A.js} +1 -1
- package/dist/worker/console/static/assets/index-PFjB6g6l.js +482 -0
- package/dist/worker/console/static/assets/index-ZtyB6Ol-.css +1 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-1JDiYCuA.js → infoDiagram-6WML65LV-C7Hl8D7l.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-BZLE6zpm.js → ishikawaDiagram-WSZJBQD7-fBxVlr6t.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-Cg0nDmbe.js → journeyDiagram-NVQOT4AX-CoiJEVCl.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-DcwEdKjq.js → kanban-definition-27J2QSJJ-TJXpxNuV.js} +1 -1
- package/dist/worker/console/static/assets/{linear-CXvVge5x.js → linear-CjQWz1pG.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-5R4WTYSN.js → mermaid.core-DY9_apIE.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-By9pSeeq.js → mindmap-definition-FAOFIHXS-HB0Id8gM.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-DzbVZTqW.js → pegDiagram-VL7TDLO6-0OSWgr6v.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-B9nbfnAq.js → pieDiagram-7S7Q4E2Y-Cei1GGC2.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-D268jfWH.js → quadrantDiagram-CIZ2JOQS-CDy0Adfu.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-oNOXPRNn.js → railroadDiagram-AXF67PYL-BwqzUWwN.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-DXdr8K-4.js → requirementDiagram-LRYGKXZP-Bif2IBRL.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-Dtm4uOJ0.js → sankeyDiagram-W5VNT64P-CYIoNMLg.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-CeeFiof4.js → sequenceDiagram-SI44F4Z6-BDS7Y0aQ.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-CK1gARll.js → sizeCapture-X5ZJPWSS-lZic-_Bp.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-3jMoAcZw.js → stateDiagram-OKZ733FA-WCVlCqSd.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-cj5UUB6m.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-Div6kwoD.js → swimlanes-SLNWSIFB-pGccxTw_.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-C_Qp6bnh.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-B7P_6Up9.js → timeline-definition-Z64GVDOM-D29RlrQA.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-eOPaGUOX.js → vennDiagram-T6HMQDX7-01fEM1NU.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-tAcDnb31.js → wardleyDiagram-T6FBY63Y-C4GeB6dq.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-Dg_r_785.js → xychartDiagram-ELKLHX3M-BXHrXHps.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/operator-chat/animation-frame-batcher.js +38 -0
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +97 -3
- package/dist/worker/console/static-src/operator-chat/process-label.js +11 -2
- package/dist/worker/console/static-src/operator-chat/turn-group-equality.js +2 -1
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +2 -0
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +9 -0
- package/dist/worker/console/workspace-context.js +1 -0
- package/dist/worker/observe/static/console-theme.css +174 -0
- package/dist/worker/observe/static/console-theme.js +36 -0
- package/dist/worker/observe/static/operator-chrome.css +85 -0
- package/dist/worker/observe/static/operator-chrome.js +51 -0
- package/dist/workflows/dag/frontend-implementation-contract.js +3 -1
- package/dist/workflows/dag/frontend-plan-completeness.js +13 -3
- package/dist/workflows/dag/frontend-recovery-plan.js +10 -6
- package/dist/workflows/dag/frontend-typed-event-store.js +5 -0
- package/dist/workflows/dag/frontend-writer-admission.js +1 -0
- package/dist/workflows/dag/output-protocol.js +1 -0
- package/dist/workflows/dag/rerun-task.js +1 -0
- package/docs/governance/harness-methodology-verification.md +11 -0
- package/package.json +1 -1
- package/dist/worker/console/static/assets/channel-ICokO4I1.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C0c0PBcA.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C0c0PBcA.js +0 -1
- package/dist/worker/console/static/assets/index-DHBWEwz_.css +0 -1
- package/dist/worker/console/static/assets/index-RFWQLUE-.js +0 -478
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Cr_kaxrX.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Bl4fQmZh.js +0 -8
|
@@ -297,6 +297,35 @@ export function createWizardLocalHeadersExtension(options) {
|
|
|
297
297
|
export { THINKING_LEVELS, RuntimeSnapshotUnavailableError, projectRuntimeSnapshot, };
|
|
298
298
|
export { createDefaultPiSdkBindings } from "./pi-runtime/sdk-bindings.js";
|
|
299
299
|
export { extractAssistantContentBlocks, extractAssistantText, isAssistantSdkMessage };
|
|
300
|
+
export function buildRequestContextEvent(input) {
|
|
301
|
+
const systemPrompt = input.session.state?.systemPrompt ?? input.session.systemPrompt ?? "";
|
|
302
|
+
const activeTools = input.session.getActiveToolNames()
|
|
303
|
+
.filter((name) => typeof name === "string" && name.trim())
|
|
304
|
+
.slice(0, 256);
|
|
305
|
+
const provider = input.session.model?.provider;
|
|
306
|
+
const modelId = input.session.model?.modelId ?? input.session.model?.id;
|
|
307
|
+
const sources = ["system", "conversation"];
|
|
308
|
+
if (activeTools.length > 0)
|
|
309
|
+
sources.push("tools");
|
|
310
|
+
if (input.imageCount > 0)
|
|
311
|
+
sources.push("images");
|
|
312
|
+
return {
|
|
313
|
+
type: "request_context",
|
|
314
|
+
sessionId: input.sessionId,
|
|
315
|
+
requestId: `${input.turnId}:request:1`,
|
|
316
|
+
step: 1,
|
|
317
|
+
...(provider && modelId ? { model: { provider, modelId } } : {}),
|
|
318
|
+
...(input.session.thinkingLevel
|
|
319
|
+
? { thinkingLevel: input.session.thinkingLevel }
|
|
320
|
+
: {}),
|
|
321
|
+
systemPromptHash: createHash("sha256").update(systemPrompt).digest("hex"),
|
|
322
|
+
systemPromptChars: systemPrompt.length,
|
|
323
|
+
activeTools,
|
|
324
|
+
inputChars: input.text.length,
|
|
325
|
+
imageCount: input.imageCount,
|
|
326
|
+
sources,
|
|
327
|
+
};
|
|
328
|
+
}
|
|
300
329
|
function readSessionManagerId(manager) {
|
|
301
330
|
if (!manager || typeof manager !== "object")
|
|
302
331
|
return undefined;
|
|
@@ -438,12 +467,12 @@ export class ConsolePiRuntime {
|
|
|
438
467
|
downloadsDir: path.join(this.options.sessionDir, "..", "browser-downloads"),
|
|
439
468
|
screenshotsDir: path.join(this.options.sessionDir, "..", "browser-screenshots"),
|
|
440
469
|
});
|
|
441
|
-
// Governed DB connections
|
|
442
|
-
//
|
|
470
|
+
// Governed DB connections are Console-global, not repository-scoped.
|
|
471
|
+
// This keeps named connections available when the user switches folders.
|
|
443
472
|
this.ownsDbConnections = options.dbConnections === undefined;
|
|
444
473
|
this.dbConnections =
|
|
445
474
|
options.dbConnections ??
|
|
446
|
-
new DbConnectionRegistry(path.join(this.options.sessionDir, "..", "db"));
|
|
475
|
+
new DbConnectionRegistry(path.join(options.globalAppDataRoot ?? path.resolve(this.options.sessionDir, ".."), "db"), undefined, undefined, path.join(this.options.sessionDir, "..", "db"));
|
|
447
476
|
this.exploreOrchestrator = new ExploreOrchestrator({
|
|
448
477
|
cwd: this.options.cwd,
|
|
449
478
|
bindings: this.bindings,
|
|
@@ -1977,6 +2006,14 @@ export class ConsolePiRuntime {
|
|
|
1977
2006
|
};
|
|
1978
2007
|
emitContextUsage();
|
|
1979
2008
|
await this.runPrePromptCompaction(sessionId, session, text, options?.images?.length ?? 0, onEvent);
|
|
2009
|
+
onEvent(buildRequestContextEvent({
|
|
2010
|
+
sessionId,
|
|
2011
|
+
turnId: options?.turnId ?? `${sessionId}:active`,
|
|
2012
|
+
session,
|
|
2013
|
+
text,
|
|
2014
|
+
imageCount: options?.images?.length ?? 0,
|
|
2015
|
+
}));
|
|
2016
|
+
let step = 0;
|
|
1980
2017
|
let stepStartedAt;
|
|
1981
2018
|
let firstTokenAt;
|
|
1982
2019
|
let pendingProviderError;
|
|
@@ -1985,12 +2022,24 @@ export class ConsolePiRuntime {
|
|
|
1985
2022
|
const emitPendingProviderError = () => {
|
|
1986
2023
|
if (!pendingProviderError)
|
|
1987
2024
|
return;
|
|
1988
|
-
|
|
2025
|
+
const error = pendingProviderError;
|
|
2026
|
+
onEvent(error);
|
|
2027
|
+
onEvent({
|
|
2028
|
+
type: "turn_error",
|
|
2029
|
+
sessionId,
|
|
2030
|
+
step: Math.max(1, step),
|
|
2031
|
+
...(error.providerError.code === undefined
|
|
2032
|
+
? {}
|
|
2033
|
+
: { code: String(error.providerError.code) }),
|
|
2034
|
+
message: error.message,
|
|
2035
|
+
});
|
|
1989
2036
|
pendingProviderError = undefined;
|
|
1990
2037
|
providerErrorEmitted = true;
|
|
1991
2038
|
};
|
|
1992
2039
|
unsub = session.subscribe((event) => {
|
|
1993
2040
|
const observedAt = Date.now();
|
|
2041
|
+
if (event.type === "turn_start")
|
|
2042
|
+
step += 1;
|
|
1994
2043
|
if (event.type === "message_start" && isUserSdkMessage(event.message)) {
|
|
1995
2044
|
if (!initialUserMessageStarted) {
|
|
1996
2045
|
// The first user message_start belongs to session.prompt(text), not
|
|
@@ -2021,7 +2070,7 @@ export class ConsolePiRuntime {
|
|
|
2021
2070
|
const compactionId = event.type === "compaction_start" || event.type === "compaction_end"
|
|
2022
2071
|
? activeCompaction?.compactionId ?? newCompactionId(sessionId)
|
|
2023
2072
|
: undefined;
|
|
2024
|
-
const mapped = mapSdkEvent(sessionId, event, compactionId);
|
|
2073
|
+
const mapped = mapSdkEvent(sessionId, event, compactionId, Math.max(1, step));
|
|
2025
2074
|
if (event.type === "compaction_end")
|
|
2026
2075
|
activeCompaction = undefined;
|
|
2027
2076
|
if (mapped?.type === "error") {
|
|
@@ -2046,7 +2095,7 @@ export class ConsolePiRuntime {
|
|
|
2046
2095
|
if (mapped?.type === "agent_settled") {
|
|
2047
2096
|
emitPendingProviderError();
|
|
2048
2097
|
}
|
|
2049
|
-
if (mapped?.type === "agent_start") {
|
|
2098
|
+
if (mapped?.type === "step_start" || mapped?.type === "agent_start") {
|
|
2050
2099
|
stepStartedAt = observedAt;
|
|
2051
2100
|
firstTokenAt = undefined;
|
|
2052
2101
|
}
|
|
@@ -2074,6 +2123,13 @@ export class ConsolePiRuntime {
|
|
|
2074
2123
|
: { outputTokens: usage.outputTokens }),
|
|
2075
2124
|
};
|
|
2076
2125
|
onEvent({ ...mapped, ...(timing ? { timing } : {}) });
|
|
2126
|
+
if (mapped.stopReason === "length") {
|
|
2127
|
+
onEvent({
|
|
2128
|
+
type: "turn_max_tokens",
|
|
2129
|
+
sessionId,
|
|
2130
|
+
step: mapped.step ?? Math.max(1, step),
|
|
2131
|
+
});
|
|
2132
|
+
}
|
|
2077
2133
|
if (usage)
|
|
2078
2134
|
onEvent({ type: "usage", sessionId, usage });
|
|
2079
2135
|
emitContextUsage();
|
|
@@ -2331,7 +2387,7 @@ export class ConsolePiRuntime {
|
|
|
2331
2387
|
this.dbConnections.dispose();
|
|
2332
2388
|
}
|
|
2333
2389
|
}
|
|
2334
|
-
function mapAssistantMessageEvent(type, sessionId, message) {
|
|
2390
|
+
function mapAssistantMessageEvent(type, sessionId, message, step) {
|
|
2335
2391
|
const record = message !== null && typeof message === "object"
|
|
2336
2392
|
? message
|
|
2337
2393
|
: undefined;
|
|
@@ -2355,6 +2411,10 @@ function mapAssistantMessageEvent(type, sessionId, message) {
|
|
|
2355
2411
|
sessionId,
|
|
2356
2412
|
text: extractAssistantText(message),
|
|
2357
2413
|
...(content.length > 0 ? { content } : {}),
|
|
2414
|
+
step,
|
|
2415
|
+
...(type === "message_end" && typeof record?.stopReason === "string"
|
|
2416
|
+
? { stopReason: record.stopReason }
|
|
2417
|
+
: {}),
|
|
2358
2418
|
};
|
|
2359
2419
|
}
|
|
2360
2420
|
function isUserSdkMessage(message) {
|
|
@@ -2362,10 +2422,12 @@ function isUserSdkMessage(message) {
|
|
|
2362
2422
|
typeof message === "object" &&
|
|
2363
2423
|
message.role === "user");
|
|
2364
2424
|
}
|
|
2365
|
-
function mapSdkEvent(sessionId, event, compactionId) {
|
|
2425
|
+
export function mapSdkEvent(sessionId, event, compactionId, step = 1) {
|
|
2366
2426
|
switch (event.type) {
|
|
2367
2427
|
case "agent_start":
|
|
2368
2428
|
return { type: "agent_start", sessionId };
|
|
2429
|
+
case "turn_start":
|
|
2430
|
+
return { type: "step_start", sessionId, step };
|
|
2369
2431
|
case "agent_end":
|
|
2370
2432
|
return {
|
|
2371
2433
|
type: "agent_end",
|
|
@@ -2375,15 +2437,50 @@ function mapSdkEvent(sessionId, event, compactionId) {
|
|
|
2375
2437
|
case "message_update":
|
|
2376
2438
|
if (!isAssistantSdkMessage(event.message))
|
|
2377
2439
|
return undefined;
|
|
2378
|
-
return mapAssistantMessageEvent("message_update", sessionId, event.message);
|
|
2440
|
+
return mapAssistantMessageEvent("message_update", sessionId, event.message, step);
|
|
2379
2441
|
case "message_end":
|
|
2380
2442
|
if (!isAssistantSdkMessage(event.message))
|
|
2381
2443
|
return undefined;
|
|
2382
|
-
return mapAssistantMessageEvent("message_end", sessionId, event.message);
|
|
2383
|
-
case "turn_end":
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2444
|
+
return mapAssistantMessageEvent("message_end", sessionId, event.message, step);
|
|
2445
|
+
case "turn_end": {
|
|
2446
|
+
const record = event.message && typeof event.message === "object"
|
|
2447
|
+
? event.message
|
|
2448
|
+
: undefined;
|
|
2449
|
+
const reason = record?.stopReason;
|
|
2450
|
+
return {
|
|
2451
|
+
type: "step_end",
|
|
2452
|
+
sessionId,
|
|
2453
|
+
step,
|
|
2454
|
+
outcome: reason === "error"
|
|
2455
|
+
? "failed"
|
|
2456
|
+
: reason === "aborted"
|
|
2457
|
+
? "interrupted"
|
|
2458
|
+
: "completed",
|
|
2459
|
+
};
|
|
2460
|
+
}
|
|
2461
|
+
case "auto_retry_start":
|
|
2462
|
+
return {
|
|
2463
|
+
type: "model_retry",
|
|
2464
|
+
sessionId,
|
|
2465
|
+
step,
|
|
2466
|
+
attempt: event.attempt,
|
|
2467
|
+
maxAttempts: event.maxAttempts,
|
|
2468
|
+
delayMs: event.delayMs,
|
|
2469
|
+
errorMessage: redactRuntimeText(event.errorMessage, 600),
|
|
2470
|
+
state: "scheduled",
|
|
2471
|
+
};
|
|
2472
|
+
case "auto_retry_end":
|
|
2473
|
+
return {
|
|
2474
|
+
type: "model_retry",
|
|
2475
|
+
sessionId,
|
|
2476
|
+
step,
|
|
2477
|
+
attempt: event.attempt,
|
|
2478
|
+
state: event.success ? "completed" : "failed",
|
|
2479
|
+
success: event.success,
|
|
2480
|
+
...(event.finalError
|
|
2481
|
+
? { errorMessage: redactRuntimeText(event.finalError, 600) }
|
|
2482
|
+
: {}),
|
|
2483
|
+
};
|
|
2387
2484
|
case "tool_execution_start":
|
|
2388
2485
|
return {
|
|
2389
2486
|
type: "tool_call",
|
|
@@ -2391,6 +2488,10 @@ function mapSdkEvent(sessionId, event, compactionId) {
|
|
|
2391
2488
|
toolCallId: event.toolCallId,
|
|
2392
2489
|
toolName: event.toolName,
|
|
2393
2490
|
args: event.args,
|
|
2491
|
+
step,
|
|
2492
|
+
...(event.parentToolCallId
|
|
2493
|
+
? { parentToolCallId: event.parentToolCallId }
|
|
2494
|
+
: {}),
|
|
2394
2495
|
};
|
|
2395
2496
|
case "tool_execution_end":
|
|
2396
2497
|
return {
|
|
@@ -2400,6 +2501,10 @@ function mapSdkEvent(sessionId, event, compactionId) {
|
|
|
2400
2501
|
toolName: event.toolName,
|
|
2401
2502
|
result: event.result,
|
|
2402
2503
|
isError: event.isError,
|
|
2504
|
+
step,
|
|
2505
|
+
...(event.parentToolCallId
|
|
2506
|
+
? { parentToolCallId: event.parentToolCallId }
|
|
2507
|
+
: {}),
|
|
2403
2508
|
};
|
|
2404
2509
|
case "agent_settled":
|
|
2405
2510
|
return { type: "agent_settled", sessionId };
|
|
@@ -2446,8 +2551,19 @@ function mapSdkEvent(sessionId, event, compactionId) {
|
|
|
2446
2551
|
: {}),
|
|
2447
2552
|
};
|
|
2448
2553
|
}
|
|
2449
|
-
|
|
2554
|
+
case "message_start":
|
|
2555
|
+
case "queue_update":
|
|
2450
2556
|
return undefined;
|
|
2557
|
+
default:
|
|
2558
|
+
{
|
|
2559
|
+
const unknownEvent = event;
|
|
2560
|
+
return {
|
|
2561
|
+
type: "unknown",
|
|
2562
|
+
sessionId,
|
|
2563
|
+
eventType: String(unknownEvent.type ?? "unknown"),
|
|
2564
|
+
value: unknownEvent,
|
|
2565
|
+
};
|
|
2566
|
+
}
|
|
2451
2567
|
}
|
|
2452
2568
|
}
|
|
2453
2569
|
function newCompactionId(sessionId) {
|
|
@@ -85,15 +85,3 @@ export function parseProviderError(value) {
|
|
|
85
85
|
category: classify({ message, raw, code }),
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
|
-
export function providerErrorTitle(category) {
|
|
89
|
-
switch (category) {
|
|
90
|
-
case "authentication":
|
|
91
|
-
return "认证失败";
|
|
92
|
-
case "context-overflow":
|
|
93
|
-
return "上下文过大";
|
|
94
|
-
case "rate-limit":
|
|
95
|
-
return "请求过于频繁";
|
|
96
|
-
default:
|
|
97
|
-
return "Provider 请求失败";
|
|
98
|
-
}
|
|
99
|
-
}
|
|
@@ -19,7 +19,7 @@ import { OPERATOR_CHAT_ALLOWED_TOOLS, OPERATOR_CHAT_DENIED_TOOLS, OPERATOR_CHAT_
|
|
|
19
19
|
import { InvalidChatSessionModeError, SESSION_MODE_ACTION_DENIED_CODE, SESSION_MODE_ACTION_DENIED_MESSAGE, SESSION_MODE_IMMUTABLE_CODE, UnknownChatSessionModeError, isWorkflowSessionMode, parseCreateSessionMode, readStoredSessionMode, shouldAcceptOperatorSnapshot, } from "./session-mode.js";
|
|
20
20
|
import { buildModelCallableToolSchemas } from "./tool-adapter.js";
|
|
21
21
|
import { cleanChatTitle, acceptedOperationIdFromResult, isBlankChatSession } from "./session-store.js";
|
|
22
|
-
import { hashChatTurnPayload, projectChatToolEventPayload, projectCompactSnapshot, } from "./chat-event-store.js";
|
|
22
|
+
import { hashChatTurnPayload, projectChatToolEventPayload, projectUnknownChatEventPayload, projectCompactSnapshot, } from "./chat-event-store.js";
|
|
23
23
|
import { projectDeferredTurnSummary, projectDeferredTurnSummaries, } from "./deferred-turn.js";
|
|
24
24
|
import { THINKING_LEVELS, RuntimeSnapshotUnavailableError, } from "./pi-runtime.js";
|
|
25
25
|
import { ResourcePreferencesError, setSkillAutoInvocationPreference, } from "./resource-preferences-store.js";
|
|
@@ -197,6 +197,16 @@ export function projectStoredMessagesWithEventOrder(messages, events) {
|
|
|
197
197
|
...(finish
|
|
198
198
|
? { finishedSeq: finish.seq, finishedAt: finish.at }
|
|
199
199
|
: {}),
|
|
200
|
+
...(start && typeof start.data.step === "number"
|
|
201
|
+
? { step: start.data.step }
|
|
202
|
+
: {}),
|
|
203
|
+
...(start &&
|
|
204
|
+
typeof start.data.parentToolCallId ===
|
|
205
|
+
"string"
|
|
206
|
+
? {
|
|
207
|
+
parentToolCallId: start.data.parentToolCallId,
|
|
208
|
+
}
|
|
209
|
+
: {}),
|
|
200
210
|
};
|
|
201
211
|
});
|
|
202
212
|
}
|
|
@@ -243,10 +253,99 @@ function writeChatSse(res, event) {
|
|
|
243
253
|
/** Map a runtime ChatTurnEvent to the persisted event-store partial.
|
|
244
254
|
*
|
|
245
255
|
* Returns undefined for heartbeat (not persisted — keep-alive only). */
|
|
246
|
-
function turnEventToStorePartial(event) {
|
|
256
|
+
export function turnEventToStorePartial(event) {
|
|
247
257
|
switch (event.type) {
|
|
248
258
|
case "agent_start":
|
|
249
259
|
return { kind: "agent_start", data: {} };
|
|
260
|
+
case "step_start":
|
|
261
|
+
case "step_end":
|
|
262
|
+
return {
|
|
263
|
+
kind: event.type,
|
|
264
|
+
data: {
|
|
265
|
+
step: Number(event.step ?? 1),
|
|
266
|
+
...(event.type === "step_end"
|
|
267
|
+
? { outcome: String(event.outcome ?? "completed") }
|
|
268
|
+
: {}),
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
case "model_retry":
|
|
272
|
+
{
|
|
273
|
+
const retryState = event.state === "completed" || event.state === "failed"
|
|
274
|
+
? event.state
|
|
275
|
+
: "scheduled";
|
|
276
|
+
return {
|
|
277
|
+
kind: "model_retry",
|
|
278
|
+
data: {
|
|
279
|
+
step: Number(event.step ?? 1),
|
|
280
|
+
attempt: Number(event.attempt ?? 1),
|
|
281
|
+
...(typeof event.maxAttempts === "number"
|
|
282
|
+
? { maxAttempts: event.maxAttempts }
|
|
283
|
+
: {}),
|
|
284
|
+
...(typeof event.delayMs === "number" ? { delayMs: event.delayMs } : {}),
|
|
285
|
+
...(typeof event.errorMessage === "string"
|
|
286
|
+
? { errorMessage: event.errorMessage }
|
|
287
|
+
: {}),
|
|
288
|
+
state: retryState,
|
|
289
|
+
...(typeof event.success === "boolean" ? { success: event.success } : {}),
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
case "turn_max_tokens":
|
|
294
|
+
return {
|
|
295
|
+
kind: "turn_max_tokens",
|
|
296
|
+
data: { step: Number(event.step ?? 1) },
|
|
297
|
+
};
|
|
298
|
+
case "turn_error":
|
|
299
|
+
return {
|
|
300
|
+
kind: "turn_error",
|
|
301
|
+
data: {
|
|
302
|
+
...(typeof event.step === "number" ? { step: event.step } : {}),
|
|
303
|
+
...(typeof event.code === "string" ? { code: event.code } : {}),
|
|
304
|
+
message: String(event.message ?? "模型请求失败"),
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
case "request_context":
|
|
308
|
+
return {
|
|
309
|
+
kind: "request_context",
|
|
310
|
+
data: {
|
|
311
|
+
requestId: String(event.requestId ?? ""),
|
|
312
|
+
step: Number(event.step ?? 1),
|
|
313
|
+
...(event.model && typeof event.model === "object"
|
|
314
|
+
? { model: event.model }
|
|
315
|
+
: {}),
|
|
316
|
+
...(typeof event.thinkingLevel === "string"
|
|
317
|
+
? { thinkingLevel: event.thinkingLevel }
|
|
318
|
+
: {}),
|
|
319
|
+
systemPromptHash: String(event.systemPromptHash ?? ""),
|
|
320
|
+
systemPromptChars: Number(event.systemPromptChars ?? 0),
|
|
321
|
+
activeTools: Array.isArray(event.activeTools) ? event.activeTools : [],
|
|
322
|
+
inputChars: Number(event.inputChars ?? 0),
|
|
323
|
+
imageCount: Number(event.imageCount ?? 0),
|
|
324
|
+
sources: Array.isArray(event.sources) ? event.sources : [],
|
|
325
|
+
},
|
|
326
|
+
};
|
|
327
|
+
case "command":
|
|
328
|
+
return {
|
|
329
|
+
kind: "command",
|
|
330
|
+
data: {
|
|
331
|
+
commandId: String(event.commandId ?? ""),
|
|
332
|
+
name: String(event.name ?? "unknown"),
|
|
333
|
+
...(typeof event.argsPreview === "string"
|
|
334
|
+
? { argsPreview: event.argsPreview }
|
|
335
|
+
: {}),
|
|
336
|
+
...(typeof event.action === "string" ? { action: event.action } : {}),
|
|
337
|
+
outcome: event.outcome === "failed" ? "failed" : "completed",
|
|
338
|
+
...(typeof event.message === "string" ? { message: event.message } : {}),
|
|
339
|
+
},
|
|
340
|
+
};
|
|
341
|
+
case "unknown":
|
|
342
|
+
return {
|
|
343
|
+
kind: "unknown",
|
|
344
|
+
data: projectUnknownChatEventPayload({
|
|
345
|
+
eventType: String(event.eventType ?? "unknown"),
|
|
346
|
+
value: event.value,
|
|
347
|
+
}),
|
|
348
|
+
};
|
|
250
349
|
case "message_update":
|
|
251
350
|
case "message_end": {
|
|
252
351
|
const content = parseAssistantContent(event.content);
|
|
@@ -291,6 +390,10 @@ function turnEventToStorePartial(event) {
|
|
|
291
390
|
event.messageId
|
|
292
391
|
? { messageId: event.messageId }
|
|
293
392
|
: {}),
|
|
393
|
+
...(typeof event.step === "number" ? { step: event.step } : {}),
|
|
394
|
+
...(typeof event.stopReason === "string"
|
|
395
|
+
? { stopReason: event.stopReason }
|
|
396
|
+
: {}),
|
|
294
397
|
},
|
|
295
398
|
};
|
|
296
399
|
}
|
|
@@ -304,6 +407,10 @@ function turnEventToStorePartial(event) {
|
|
|
304
407
|
toolCallId: String(event.toolCallId ?? ""),
|
|
305
408
|
toolName: String(event.toolName ?? ""),
|
|
306
409
|
value: event.args,
|
|
410
|
+
...(typeof event.step === "number" ? { step: event.step } : {}),
|
|
411
|
+
...(typeof event.parentToolCallId === "string"
|
|
412
|
+
? { parentToolCallId: event.parentToolCallId }
|
|
413
|
+
: {}),
|
|
307
414
|
}),
|
|
308
415
|
};
|
|
309
416
|
case "tool_result": {
|
|
@@ -318,6 +425,10 @@ function turnEventToStorePartial(event) {
|
|
|
318
425
|
toolName: String(event.toolName ?? ""),
|
|
319
426
|
value: event.result,
|
|
320
427
|
isError: Boolean(event.isError),
|
|
428
|
+
...(typeof event.step === "number" ? { step: event.step } : {}),
|
|
429
|
+
...(typeof event.parentToolCallId === "string"
|
|
430
|
+
? { parentToolCallId: event.parentToolCallId }
|
|
431
|
+
: {}),
|
|
321
432
|
...(resultOperationId ? { operationId: resultOperationId } : {}),
|
|
322
433
|
}),
|
|
323
434
|
};
|
|
@@ -1029,6 +1140,16 @@ export async function handleGetChatSession(_req, res, deps, sessionId) {
|
|
|
1029
1140
|
turnId: event.turnId,
|
|
1030
1141
|
data: event.data,
|
|
1031
1142
|
})),
|
|
1143
|
+
conversationEvents: snapshot.filter((event) => [
|
|
1144
|
+
"step_start",
|
|
1145
|
+
"step_end",
|
|
1146
|
+
"model_retry",
|
|
1147
|
+
"turn_error",
|
|
1148
|
+
"turn_max_tokens",
|
|
1149
|
+
"request_context",
|
|
1150
|
+
"command",
|
|
1151
|
+
"unknown",
|
|
1152
|
+
].includes(event.kind)),
|
|
1032
1153
|
lastEventId: lastEvent?.eventId ?? null,
|
|
1033
1154
|
lastEventSeq: lastEvent?.seq ?? 0,
|
|
1034
1155
|
});
|
|
@@ -2982,7 +3103,8 @@ async function handleSddBingo(req, res, deps, sessionId) {
|
|
|
2982
3103
|
throw new SddDataAlignmentError("SDD_INVALID_SKILL_NAME", "请求体只允许 skillName 字段", 400);
|
|
2983
3104
|
}
|
|
2984
3105
|
const result = await deps.sddDataAlignment.report(sessionId, body.skillName);
|
|
2985
|
-
|
|
3106
|
+
const turnId = deps.events.latestTurnId(sessionId) ?? `${sessionId}:operator-action`;
|
|
3107
|
+
deps.events.append(sessionId, turnId, {
|
|
2986
3108
|
kind: "operator-action",
|
|
2987
3109
|
data: {
|
|
2988
3110
|
schemaVersion: 1,
|
|
@@ -2991,6 +3113,17 @@ async function handleSddBingo(req, res, deps, sessionId) {
|
|
|
2991
3113
|
telemetrySessionId: result.telemetrySessionId,
|
|
2992
3114
|
},
|
|
2993
3115
|
});
|
|
3116
|
+
deps.events.append(sessionId, `${sessionId}:command:${result.telemetrySessionId}`, {
|
|
3117
|
+
kind: "command",
|
|
3118
|
+
data: {
|
|
3119
|
+
commandId: `sdd-bingo:${result.telemetrySessionId}`,
|
|
3120
|
+
name: "sdd-bingo",
|
|
3121
|
+
...(result.skillName ? { argsPreview: result.skillName } : {}),
|
|
3122
|
+
action: "sdd-bingo",
|
|
3123
|
+
outcome: "completed",
|
|
3124
|
+
message: `Session: ${result.telemetrySessionId}`,
|
|
3125
|
+
},
|
|
3126
|
+
});
|
|
2994
3127
|
sendJson(res, 200, {
|
|
2995
3128
|
ok: true,
|
|
2996
3129
|
skillName: result.skillName,
|
|
@@ -3,7 +3,89 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { getDisplayableAssistantBlocks, joinAssistantText, parseAssistantContent, splitFinalAssistantBlocks, } from "./assistant-content.js";
|
|
5
5
|
import { dagProgressActivityForTool, semanticActivityForTool, } from "./semantic-activity.js";
|
|
6
|
+
import { compareChatOrder } from "./turn-order.js";
|
|
6
7
|
import { ensureLinkedSubmissionOrder } from "./timeline-message-order.js";
|
|
8
|
+
function conversationNodeOrder(node) {
|
|
9
|
+
return { eventSeq: node.anchorSeq, createdAt: node.at };
|
|
10
|
+
}
|
|
11
|
+
function processItemOrder(item, group) {
|
|
12
|
+
const createdAt = item.createdAt ??
|
|
13
|
+
(item.kind === "tool" ? item.tool.createdAt : undefined) ??
|
|
14
|
+
group.assistants[0]?.createdAt ??
|
|
15
|
+
0;
|
|
16
|
+
const eventSeq = item.eventSeq ?? (item.kind === "tool" ? item.tool.eventSeq : undefined);
|
|
17
|
+
return eventSeq === undefined ? { createdAt } : { eventSeq, createdAt };
|
|
18
|
+
}
|
|
19
|
+
function compareFlowEntries(a, b) {
|
|
20
|
+
return compareChatOrder(a.order, b.order);
|
|
21
|
+
}
|
|
22
|
+
/** Base identity for a rendered process row. Content is deliberately excluded
|
|
23
|
+
* so streaming text updates keep the same React instance. */
|
|
24
|
+
function processItemKey(item, order) {
|
|
25
|
+
if (item.kind === "tool")
|
|
26
|
+
return `tool:${item.tool.id}`;
|
|
27
|
+
if (item.kind === "activity")
|
|
28
|
+
return `activity:${item.activity.id}`;
|
|
29
|
+
if (item.kind === "dag-progress")
|
|
30
|
+
return `dag-progress:${item.progress.id}`;
|
|
31
|
+
const anchor = order.eventSeq ?? order.createdAt;
|
|
32
|
+
return `${item.kind}:${anchor}`;
|
|
33
|
+
}
|
|
34
|
+
export function turnProcessItemKey(item, occurrence = 0) {
|
|
35
|
+
const order = {
|
|
36
|
+
...(item.eventSeq === undefined ? {} : { eventSeq: item.eventSeq }),
|
|
37
|
+
createdAt: item.createdAt ?? (item.kind === "tool" ? item.tool.createdAt : 0),
|
|
38
|
+
};
|
|
39
|
+
const base = processItemKey(item, order);
|
|
40
|
+
return occurrence === 0 ? base : `${base}:${occurrence}`;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Project one turn into the same ordered buckets used by the main timeline and
|
|
44
|
+
* the trajectory view. Only existing request/running-step nodes are prelude;
|
|
45
|
+
* retry and other lifecycle nodes stay in the collapsible process window.
|
|
46
|
+
*/
|
|
47
|
+
export function projectTurnFlow(group) {
|
|
48
|
+
const conversationItems = group.conversationItems ?? [];
|
|
49
|
+
const prelude = conversationItems
|
|
50
|
+
.filter((item) => item.kind === "request" ||
|
|
51
|
+
(item.kind === "step" && item.node.status === "running"))
|
|
52
|
+
.sort((a, b) => compareChatOrder(conversationNodeOrder(a.node), conversationNodeOrder(b.node)));
|
|
53
|
+
const postAnswer = conversationItems
|
|
54
|
+
.filter((item) => item.kind === "max-tokens")
|
|
55
|
+
.sort((a, b) => compareChatOrder(conversationNodeOrder(a.node), conversationNodeOrder(b.node)));
|
|
56
|
+
const preludeKeys = new Set(prelude.map((item) => item.node.key));
|
|
57
|
+
const postAnswerKeys = new Set(postAnswer.map((item) => item.node.key));
|
|
58
|
+
const process = [];
|
|
59
|
+
for (const item of group.processItems) {
|
|
60
|
+
process.push({
|
|
61
|
+
source: "process",
|
|
62
|
+
key: "",
|
|
63
|
+
item,
|
|
64
|
+
order: processItemOrder(item, group),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
for (const item of conversationItems) {
|
|
68
|
+
if (preludeKeys.has(item.node.key) || postAnswerKeys.has(item.node.key))
|
|
69
|
+
continue;
|
|
70
|
+
process.push({
|
|
71
|
+
source: "conversation",
|
|
72
|
+
key: `conversation:${item.node.key}`,
|
|
73
|
+
item,
|
|
74
|
+
order: conversationNodeOrder(item.node),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
process.sort(compareFlowEntries);
|
|
78
|
+
const occurrences = new Map();
|
|
79
|
+
for (const entry of process) {
|
|
80
|
+
const base = entry.source === "conversation"
|
|
81
|
+
? entry.key
|
|
82
|
+
: processItemKey(entry.item, entry.order);
|
|
83
|
+
const occurrence = occurrences.get(base) ?? 0;
|
|
84
|
+
occurrences.set(base, occurrence + 1);
|
|
85
|
+
entry.key = occurrence === 0 ? base : `${base}:${occurrence}`;
|
|
86
|
+
}
|
|
87
|
+
return { prelude, process, postAnswer };
|
|
88
|
+
}
|
|
7
89
|
function emptyGroup(key, turnId) {
|
|
8
90
|
return {
|
|
9
91
|
key,
|
|
@@ -11,6 +93,7 @@ function emptyGroup(key, turnId) {
|
|
|
11
93
|
assistants: [],
|
|
12
94
|
tools: [],
|
|
13
95
|
processItems: [],
|
|
96
|
+
conversationItems: [],
|
|
14
97
|
live: false,
|
|
15
98
|
};
|
|
16
99
|
}
|
|
@@ -92,6 +175,10 @@ export function hydrateSessionThread(raw) {
|
|
|
92
175
|
? finishedAtMs
|
|
93
176
|
: createdAt,
|
|
94
177
|
turnId: item.turnId ?? turnId,
|
|
178
|
+
...(item.step === undefined ? {} : { step: item.step }),
|
|
179
|
+
...(item.parentToolCallId
|
|
180
|
+
? { parentToolCallId: item.parentToolCallId }
|
|
181
|
+
: {}),
|
|
95
182
|
...(item.eventSeq === undefined ? {} : { eventSeq: item.eventSeq }),
|
|
96
183
|
...(item.finishedSeq === undefined
|
|
97
184
|
? {}
|
|
@@ -132,17 +219,21 @@ function flushToolBuffer(processItems, buffer) {
|
|
|
132
219
|
return;
|
|
133
220
|
const sorted = sortToolsStable(buffer);
|
|
134
221
|
for (const tool of sorted) {
|
|
222
|
+
const order = {
|
|
223
|
+
...(tool.eventSeq === undefined ? {} : { eventSeq: tool.eventSeq }),
|
|
224
|
+
createdAt: tool.createdAt,
|
|
225
|
+
};
|
|
135
226
|
const dagProgress = dagProgressActivityForTool(tool);
|
|
136
227
|
if (dagProgress) {
|
|
137
|
-
processItems.push({ kind: "dag-progress", progress: dagProgress });
|
|
228
|
+
processItems.push({ kind: "dag-progress", progress: dagProgress, ...order });
|
|
138
229
|
continue;
|
|
139
230
|
}
|
|
140
231
|
const activity = semanticActivityForTool(tool);
|
|
141
232
|
if (activity) {
|
|
142
|
-
processItems.push({ kind: "activity", activity });
|
|
233
|
+
processItems.push({ kind: "activity", activity, ...order });
|
|
143
234
|
}
|
|
144
235
|
else {
|
|
145
|
-
processItems.push({ kind: "tool", tool });
|
|
236
|
+
processItems.push({ kind: "tool", tool, ...order });
|
|
146
237
|
}
|
|
147
238
|
}
|
|
148
239
|
}
|
|
@@ -185,12 +276,23 @@ function fillProcessDetails(group) {
|
|
|
185
276
|
};
|
|
186
277
|
for (const block of blocks) {
|
|
187
278
|
if (block.type === "thinking") {
|
|
188
|
-
items.push({
|
|
279
|
+
items.push({
|
|
280
|
+
kind: "thinking",
|
|
281
|
+
thinking: block.thinking,
|
|
282
|
+
...(anchorSeq === undefined ? {} : { eventSeq: anchorSeq }),
|
|
283
|
+
createdAt: anchorAt,
|
|
284
|
+
});
|
|
189
285
|
continue;
|
|
190
286
|
}
|
|
191
287
|
if (block.type === "text") {
|
|
192
|
-
if (block.text.trim())
|
|
193
|
-
items.push({
|
|
288
|
+
if (block.text.trim()) {
|
|
289
|
+
items.push({
|
|
290
|
+
kind: "text",
|
|
291
|
+
text: block.text,
|
|
292
|
+
...(anchorSeq === undefined ? {} : { eventSeq: anchorSeq }),
|
|
293
|
+
createdAt: anchorAt,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
194
296
|
continue;
|
|
195
297
|
}
|
|
196
298
|
const tool = group.tools.find((entry) => entry.id === block.toolCallId);
|
|
@@ -213,7 +315,12 @@ function fillProcessDetails(group) {
|
|
|
213
315
|
anchorAt = tool.createdAt;
|
|
214
316
|
}
|
|
215
317
|
if (includeProviderError && assistant.providerError) {
|
|
216
|
-
items.push({
|
|
318
|
+
items.push({
|
|
319
|
+
kind: "provider-error",
|
|
320
|
+
error: assistant.providerError,
|
|
321
|
+
...(anchorSeq === undefined ? {} : { eventSeq: anchorSeq }),
|
|
322
|
+
createdAt: anchorAt,
|
|
323
|
+
});
|
|
217
324
|
}
|
|
218
325
|
flushItems();
|
|
219
326
|
// Preserve the old-data fallback after this stage. Sequenced unmatched
|
|
@@ -401,6 +508,14 @@ export function buildTurnProcessGroups(input) {
|
|
|
401
508
|
assigned.add(tool.id);
|
|
402
509
|
}
|
|
403
510
|
}
|
|
511
|
+
for (const node of input.conversationNodes ?? []) {
|
|
512
|
+
if (node.location.kind === "session")
|
|
513
|
+
continue;
|
|
514
|
+
const turnId = node.location.turnId;
|
|
515
|
+
if (!groups.some((group) => group.turnId === turnId)) {
|
|
516
|
+
startGroup(`turn-${turnId}`, turnId);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
404
519
|
for (const group of groups) {
|
|
405
520
|
group.tools.sort((a, b) => {
|
|
406
521
|
if (a.eventSeq !== undefined && b.eventSeq !== undefined) {
|
|
@@ -413,6 +528,12 @@ export function buildTurnProcessGroups(input) {
|
|
|
413
528
|
input.activeAssistantId !== null &&
|
|
414
529
|
group.assistants.some((a) => a.id === input.activeAssistantId);
|
|
415
530
|
fillProcessDetails(group);
|
|
531
|
+
group.conversationItems = (input.conversationNodes ?? [])
|
|
532
|
+
.filter((node) => node.location.kind !== "session" && node.location.turnId === group.turnId)
|
|
533
|
+
.map((node) => ({ kind: node.kind, node }));
|
|
534
|
+
if (group.conversationItems.some((item) => item.kind === "turn-error")) {
|
|
535
|
+
group.processItems = group.processItems.filter((item) => item.kind !== "provider-error");
|
|
536
|
+
}
|
|
416
537
|
}
|
|
417
538
|
return groups;
|
|
418
539
|
}
|