@tea-agent/loop-agent 0.40.0-next.7 → 0.40.0-next.9
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 +106 -140
- package/dist/build-stamp.json +3 -3
- package/dist/executors/dag-pi-executor.js +3 -0
- package/dist/executors/pi-executor.js +4 -2
- package/dist/executors/pi-sdk-executor.js +46 -1
- package/dist/worker/console/chat/chat-event-store.js +13 -1
- package/dist/worker/console/chat/pi-runtime.js +70 -5
- package/dist/worker/console/chat/routes.js +99 -29
- package/dist/worker/console/chat/workspace-landing.js +65 -0
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-DGt5TRsk.js → abnfDiagram-N423BO3Z-Bs-CDAXM.js} +1 -1
- package/dist/worker/console/static/assets/{arc-DKBSJsXm.js → arc-CAkA3We3.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-BnhooRBs.js → architectureDiagram-T3A2C74G-DEmI_zqr.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-Bm9qkrJP.js → blockDiagram-VBNYF7ZC-uDHANebE.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-B2cFh4bO.js → c4Diagram-5PPSVZJV-Bv97b4_B.js} +1 -1
- package/dist/worker/console/static/assets/channel-amxUpk7o.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-DhvWRI03.js → chunk-2GRJ4B5K-shmQKsFz.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-chzTP_2w.js → chunk-2Q5K7J3B-BAraNvcN.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-SdWIR12m.js → chunk-5RXB4S5H-BirhxUop.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-C2-8Eo_A.js → chunk-5VM5RSS4-C9LgUJpR.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DvbE1yQW.js → chunk-6Q2QTUOP-DrU-s-t7.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CEenyPTz.js → chunk-GF5L2VYU-Tx-H_FA2.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-CcaZrq0k.js → chunk-JWPE2WC7-BjLtNFrR.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-FGngOTto.js → chunk-KBJHAD2P-UNLVwSsy.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-jT_yX3sf.js → chunk-RYQCIY6F-CBEUX8XD.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CjE9LQOM.js → chunk-XXDRQBXY-WTL7IZOq.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-bejwBVIz.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-bejwBVIz.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-GQWns1tb.js → cose-bilkent-JH36ORCC-CkHG6W3s.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-CGRpxWNJ.js → cynefin-VYW2F7L2-BRzFqTaL.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-Cd3uFGE4.js → cynefinDiagram-MW4NZA55-2_CFp_i7.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-DmDHuUW0.js → dagre-VZM6K2ZE-BJtsmdkE.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-kAr--hF3.js → diagram-7IWD3JNH-DNEFFo6w.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-woahL2Oh.js → diagram-B4RE2ZJO-B_IWV7eo.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-7syNVaNf.js → diagram-LBJQPF4R-DvvRx2dz.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-BELPXiaY.js → diagram-Q27KOJAE-CsibsWLg.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-CrPa4aXi.js → diagram-UB23O5K3-les_djBQ.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-B48u2VVe.js → ebnfDiagram-BXEA7PRR-BEm2n7qJ.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DhBTfwTF.js → erDiagram-JOGREHBK-BI7vHHVm.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CAeZ5nDU.js → flowDiagram-UKHOOZJN-CUFCERrB.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-CkIFeFLN.js → ganttDiagram-PKOTCBZU-wxyLiGWt.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-t0HGYDel.js → gitGraphDiagram-DS77QQ5N-Bt897K8Z.js} +1 -1
- package/dist/worker/console/static/assets/index-BHhUOTri.css +1 -0
- package/dist/worker/console/static/assets/index-DqJbO3-p.js +407 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-WM0HZhe4.js → infoDiagram-6WML65LV-DYNx_IPv.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-CV5byHe0.js → ishikawaDiagram-WSZJBQD7-CzpLNEu6.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-lIyWkgnw.js → journeyDiagram-NVQOT4AX-97f9owNU.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BIH4YNRY.js → kanban-definition-27J2QSJJ-BxM9hyBn.js} +1 -1
- package/dist/worker/console/static/assets/{linear-lQ0ZGrWc.js → linear-ByuxcHvp.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-BYdXtke8.js → mermaid.core-DwPGvpCv.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-k93vkIa4.js → mindmap-definition-FAOFIHXS-DCoqG9RT.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-Bm6AqvSy.js → pegDiagram-VL7TDLO6-BLSBmBMx.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-DnJW6Xpf.js → pieDiagram-7S7Q4E2Y-B0t_0oJW.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-CMzm4ObL.js → quadrantDiagram-CIZ2JOQS-sTzDk7Nt.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-fwFF5dFQ.js → railroadDiagram-AXF67PYL-B3jRdATC.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-tzl9VDUc.js → requirementDiagram-LRYGKXZP-D-cTtXEN.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-B26V09DD.js → sankeyDiagram-W5VNT64P-B25igJRE.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-D2npyCeP.js → sequenceDiagram-SI44F4Z6-jW_lM1_D.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-CTJtkRU2.js → sizeCapture-X5ZJPWSS-CrzTgsHE.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-B8lk4Lzu.js → stateDiagram-OKZ733FA-B01MvlqE.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BvFKEtm2.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-C3yP53hH.js → swimlanes-SLNWSIFB-YcF12FiU.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DIB2eVg-.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-Bck7xjhe.js → timeline-definition-Z64GVDOM-ClnRcg2s.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-CCntr1w7.js → vennDiagram-T6HMQDX7-B6gr_z-q.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DsCqCBZz.js → wardleyDiagram-T6FBY63Y-CvSgguGH.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-Br2l90OM.js → xychartDiagram-ELKLHX3M-23OtSZCb.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +33 -32
- package/dist/worker/console/static-src/operator-chat/compaction-message.js +79 -0
- package/dist/worker/console/static-src/operator-chat/spatial-overlay.js +1 -2
- package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +25 -0
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +54 -56
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +81 -27
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +14 -25
- package/dist/worker/console/static-src/shell/workspace-route.js +7 -5
- package/dist/workflows/dag/backend-test-writer-completeness.js +7 -12
- package/dist/workflows/dag/init-hybrid.js +27 -5
- package/dist/workflows/dag/types.js +13 -0
- package/docs/templates/agent-dag.schema.json +18 -0
- package/docs/templates/backend-test-dag.json +22 -5
- package/package.json +1 -1
- package/dist/worker/console/static/assets/channel-DSgFX07x.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-unJObRls.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-unJObRls.js +0 -1
- package/dist/worker/console/static/assets/index-B4l5ag79.js +0 -407
- package/dist/worker/console/static/assets/index-CwVHWB71.css +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BmOcMTJE.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Beah-dq0.js +0 -8
- package/dist/worker/console/static-src/operator-chat/activity-rail-presentation.js +0 -73
- package/dist/worker/console/static-src/operator-chat/useActivityRailTransition.js +0 -59
|
@@ -376,7 +376,7 @@ async function buildAskUserQuestionTool(options) {
|
|
|
376
376
|
},
|
|
377
377
|
});
|
|
378
378
|
}
|
|
379
|
-
const TODO_WRITE_DESCRIPTION = "Record and update a structured task list for the current work. Send the ENTIRE list every call — it REPLACES the previous list.
|
|
379
|
+
const TODO_WRITE_DESCRIPTION = "Record and update a structured task list for the current work. Send the ENTIRE list every call — it REPLACES the previous list (no partial updates, no per-item edits). Before starting multi-step work, add one todo per concrete step. Keep at least one todo `in_progress` while work remains. Mark a todo `completed` immediately when it is done (do not batch completions) and resend the full list as progress or DAG state advances. Skip the list for simple Q&A, read-only lookups, and single-step tasks. Use it for multi-step implementation and whenever you prepare, run, or supervise a DAG — call `todo_write` before entering the DAG tool chain. Phrase DAG todos as user-facing phases users can understand, not copies of internal DAG nodes. Statuses: `pending` / `in_progress` / `completed`.";
|
|
380
380
|
async function buildTodoWriteTool(options) {
|
|
381
381
|
const [{ Type }, { defineTool }] = await Promise.all([
|
|
382
382
|
import("typebox"),
|
|
@@ -2216,6 +2216,7 @@ export class ConsolePiRuntime {
|
|
|
2216
2216
|
let firstTokenAt;
|
|
2217
2217
|
let pendingProviderError;
|
|
2218
2218
|
let providerErrorEmitted = false;
|
|
2219
|
+
let activeCompaction;
|
|
2219
2220
|
const emitPendingProviderError = () => {
|
|
2220
2221
|
if (!pendingProviderError)
|
|
2221
2222
|
return;
|
|
@@ -2225,7 +2226,18 @@ export class ConsolePiRuntime {
|
|
|
2225
2226
|
};
|
|
2226
2227
|
unsub = session.subscribe((event) => {
|
|
2227
2228
|
const observedAt = Date.now();
|
|
2228
|
-
|
|
2229
|
+
if (event.type === "compaction_start") {
|
|
2230
|
+
activeCompaction = {
|
|
2231
|
+
compactionId: newCompactionId(sessionId),
|
|
2232
|
+
reason: event.reason,
|
|
2233
|
+
};
|
|
2234
|
+
}
|
|
2235
|
+
const compactionId = event.type === "compaction_start" || event.type === "compaction_end"
|
|
2236
|
+
? activeCompaction?.compactionId ?? newCompactionId(sessionId)
|
|
2237
|
+
: undefined;
|
|
2238
|
+
const mapped = mapSdkEvent(sessionId, event, compactionId);
|
|
2239
|
+
if (event.type === "compaction_end")
|
|
2240
|
+
activeCompaction = undefined;
|
|
2229
2241
|
if (mapped?.type === "error") {
|
|
2230
2242
|
// Pi represents provider failures as an assistant message_end and may
|
|
2231
2243
|
// retry internally. Hold the candidate until the SDK says the attempt
|
|
@@ -2237,8 +2249,15 @@ export class ConsolePiRuntime {
|
|
|
2237
2249
|
}
|
|
2238
2250
|
if (mapped?.type === "message_end")
|
|
2239
2251
|
pendingProviderError = undefined;
|
|
2240
|
-
if (
|
|
2241
|
-
mapped
|
|
2252
|
+
if (mapped?.type === "compaction_end" &&
|
|
2253
|
+
mapped.reason === "overflow" &&
|
|
2254
|
+
mapped.status === "completed" &&
|
|
2255
|
+
mapped.willRetry) {
|
|
2256
|
+
// The overflow error was a recoverable attempt fact. Pi has already
|
|
2257
|
+
// committed the compacted session and scheduled the continuation.
|
|
2258
|
+
pendingProviderError = undefined;
|
|
2259
|
+
}
|
|
2260
|
+
if (mapped?.type === "agent_settled") {
|
|
2242
2261
|
emitPendingProviderError();
|
|
2243
2262
|
}
|
|
2244
2263
|
if (mapped?.type === "agent_start") {
|
|
@@ -2499,7 +2518,7 @@ function mapAssistantMessageEvent(type, sessionId, message) {
|
|
|
2499
2518
|
...(content.length > 0 ? { content } : {}),
|
|
2500
2519
|
};
|
|
2501
2520
|
}
|
|
2502
|
-
function mapSdkEvent(sessionId, event) {
|
|
2521
|
+
function mapSdkEvent(sessionId, event, compactionId) {
|
|
2503
2522
|
switch (event.type) {
|
|
2504
2523
|
case "agent_start":
|
|
2505
2524
|
return { type: "agent_start", sessionId };
|
|
@@ -2540,10 +2559,56 @@ function mapSdkEvent(sessionId, event) {
|
|
|
2540
2559
|
};
|
|
2541
2560
|
case "agent_settled":
|
|
2542
2561
|
return { type: "agent_settled", sessionId };
|
|
2562
|
+
case "compaction_start":
|
|
2563
|
+
return {
|
|
2564
|
+
type: "compaction_start",
|
|
2565
|
+
sessionId,
|
|
2566
|
+
compactionId: compactionId ?? newCompactionId(sessionId),
|
|
2567
|
+
reason: event.reason,
|
|
2568
|
+
};
|
|
2569
|
+
case "compaction_end": {
|
|
2570
|
+
const snapshot = event.result
|
|
2571
|
+
? projectCompactSnapshot(event.result)
|
|
2572
|
+
: undefined;
|
|
2573
|
+
return {
|
|
2574
|
+
type: "compaction_end",
|
|
2575
|
+
sessionId,
|
|
2576
|
+
compactionId: compactionId ?? newCompactionId(sessionId),
|
|
2577
|
+
reason: event.reason,
|
|
2578
|
+
status: event.aborted
|
|
2579
|
+
? "aborted"
|
|
2580
|
+
: snapshot
|
|
2581
|
+
? "completed"
|
|
2582
|
+
: "failed",
|
|
2583
|
+
...(snapshot
|
|
2584
|
+
? {
|
|
2585
|
+
summary: snapshot.summary,
|
|
2586
|
+
...(snapshot.firstKeptEntryId
|
|
2587
|
+
? { firstKeptEntryId: snapshot.firstKeptEntryId }
|
|
2588
|
+
: {}),
|
|
2589
|
+
...(snapshot.tokensBefore === undefined
|
|
2590
|
+
? {}
|
|
2591
|
+
: { tokensBefore: snapshot.tokensBefore }),
|
|
2592
|
+
...(snapshot.estimatedTokensAfter === undefined
|
|
2593
|
+
? {}
|
|
2594
|
+
: {
|
|
2595
|
+
estimatedTokensAfter: snapshot.estimatedTokensAfter,
|
|
2596
|
+
}),
|
|
2597
|
+
}
|
|
2598
|
+
: {}),
|
|
2599
|
+
willRetry: Boolean(event.willRetry),
|
|
2600
|
+
...(event.errorMessage
|
|
2601
|
+
? { errorMessage: redactRuntimeText(event.errorMessage, 600) }
|
|
2602
|
+
: {}),
|
|
2603
|
+
};
|
|
2604
|
+
}
|
|
2543
2605
|
default:
|
|
2544
2606
|
return undefined;
|
|
2545
2607
|
}
|
|
2546
2608
|
}
|
|
2609
|
+
function newCompactionId(sessionId) {
|
|
2610
|
+
return `${sessionId}:compaction:${randomBytes(8).toString("hex")}`;
|
|
2611
|
+
}
|
|
2547
2612
|
async function waitForIdle(session, options) {
|
|
2548
2613
|
// Default 45s — shorter than the previous 120s so a stuck SDK session does
|
|
2549
2614
|
// not pin an HTTP connection for two full minutes. The SDK agent turn
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* Mutation routes go through the Console mutation gate (boot token + Origin).
|
|
13
13
|
* Read routes (GET capabilities / sessions) are open to loopback.
|
|
14
14
|
*/
|
|
15
|
+
import { randomUUID } from "node:crypto";
|
|
15
16
|
import { parseAssistantContent } from "./assistant-content.js";
|
|
16
17
|
import { OPERATOR_CHAT_ALLOWED_TOOLS, OPERATOR_CHAT_DENIED_TOOLS, OPERATOR_CHAT_DENIED_OPERATOR_ACTIONS, } from "./tools.js";
|
|
17
18
|
import { buildModelCallableToolSchemas } from "./tool-adapter.js";
|
|
@@ -54,7 +55,6 @@ function turnSummary(turn) {
|
|
|
54
55
|
function isTerminalTurnState(state) {
|
|
55
56
|
return state === "settled" || state === "aborted" || state === "failed";
|
|
56
57
|
}
|
|
57
|
-
const DEFAULT_ABORT_WAIT_MS = 2_500;
|
|
58
58
|
/** Parse Chat's `<epoch>:<seq>` SSE cursor. Legacy `<sessionId>:<seq>` has
|
|
59
59
|
* the same wire shape; its prefix intentionally fails the current process
|
|
60
60
|
* epoch comparison and triggers safe snapshot recovery (M5.1). */
|
|
@@ -162,6 +162,40 @@ function turnEventToStorePartial(event) {
|
|
|
162
162
|
};
|
|
163
163
|
case "agent_settled":
|
|
164
164
|
return { kind: "agent_settled", data: {} };
|
|
165
|
+
case "compaction_start":
|
|
166
|
+
case "compaction_end": {
|
|
167
|
+
const reason = event.reason === "threshold" || event.reason === "overflow"
|
|
168
|
+
? event.reason
|
|
169
|
+
: "manual";
|
|
170
|
+
const status = event.type === "compaction_start"
|
|
171
|
+
? "running"
|
|
172
|
+
: event.status === "aborted" || event.status === "failed"
|
|
173
|
+
? event.status
|
|
174
|
+
: "completed";
|
|
175
|
+
const data = {
|
|
176
|
+
schemaVersion: 1,
|
|
177
|
+
compactionId: String(event.compactionId ?? ""),
|
|
178
|
+
reason,
|
|
179
|
+
status,
|
|
180
|
+
...(typeof event.summary === "string"
|
|
181
|
+
? { summary: event.summary }
|
|
182
|
+
: {}),
|
|
183
|
+
...(typeof event.firstKeptEntryId === "string"
|
|
184
|
+
? { firstKeptEntryId: event.firstKeptEntryId }
|
|
185
|
+
: {}),
|
|
186
|
+
...(typeof event.tokensBefore === "number"
|
|
187
|
+
? { tokensBefore: event.tokensBefore }
|
|
188
|
+
: {}),
|
|
189
|
+
...(typeof event.estimatedTokensAfter === "number"
|
|
190
|
+
? { estimatedTokensAfter: event.estimatedTokensAfter }
|
|
191
|
+
: {}),
|
|
192
|
+
willRetry: Boolean(event.willRetry),
|
|
193
|
+
...(typeof event.errorMessage === "string"
|
|
194
|
+
? { errorMessage: event.errorMessage }
|
|
195
|
+
: {}),
|
|
196
|
+
};
|
|
197
|
+
return { kind: event.type, data };
|
|
198
|
+
}
|
|
165
199
|
case "error": {
|
|
166
200
|
const content = parseAssistantContent(event.content);
|
|
167
201
|
return {
|
|
@@ -726,9 +760,12 @@ export async function handleGetChatSession(_req, res, deps, sessionId) {
|
|
|
726
760
|
sessionStats: telemetry.stats,
|
|
727
761
|
usage: telemetry.usage,
|
|
728
762
|
compactions: snapshot
|
|
729
|
-
.filter((event) => event.kind === "compact"
|
|
763
|
+
.filter((event) => event.kind === "compact" ||
|
|
764
|
+
event.kind === "compaction_start" ||
|
|
765
|
+
event.kind === "compaction_end")
|
|
730
766
|
.map((event) => ({
|
|
731
767
|
eventId: event.eventId,
|
|
768
|
+
kind: event.kind,
|
|
732
769
|
at: event.at,
|
|
733
770
|
data: event.data,
|
|
734
771
|
})),
|
|
@@ -1975,35 +2012,24 @@ export async function handleAbortChatTurn(req, res, deps, sessionId, turnId) {
|
|
|
1975
2012
|
});
|
|
1976
2013
|
return;
|
|
1977
2014
|
}
|
|
1978
|
-
deps.events.markAbortRequested?.(sessionId, turnId);
|
|
1979
|
-
|
|
2015
|
+
const stopping = deps.events.markAbortRequested?.(sessionId, turnId) ?? turn;
|
|
2016
|
+
// DSH-style acknowledgement: deliver the AbortSignal synchronously, then let
|
|
2017
|
+
// the detached Turn closeout own SDK/process cleanup and terminal persistence.
|
|
2018
|
+
// The HTTP request reports that Stop was accepted; it does not wait for Pi to
|
|
2019
|
+
// become idle. This keeps cancellation latency independent of slow providers,
|
|
2020
|
+
// tools and process-tree cleanup while preserving the active-Turn lease.
|
|
1980
2021
|
if (!execution.controller.signal.aborted)
|
|
1981
2022
|
execution.controller.abort();
|
|
1982
|
-
const
|
|
1983
|
-
if (
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
...turn,
|
|
1987
|
-
state: waited.outcome.state,
|
|
1988
|
-
};
|
|
1989
|
-
sendJson(res, 200, {
|
|
1990
|
-
ok: true,
|
|
1991
|
-
accepted: true,
|
|
1992
|
-
idempotent: false,
|
|
1993
|
-
turn: turnSummary(finalTurn),
|
|
1994
|
-
});
|
|
1995
|
-
return;
|
|
1996
|
-
}
|
|
1997
|
-
// Timeout or missing completion: keep non-terminal; client reconciles via /state.
|
|
1998
|
-
const pending = deps.events.getTurn(sessionId, turnId) ?? turn;
|
|
2023
|
+
const questionCancellation = deps.questionRegistry?.cancelForSession(sessionId, "TURN_ABORTED");
|
|
2024
|
+
if (questionCancellation)
|
|
2025
|
+
void questionCancellation.catch(() => undefined);
|
|
2026
|
+
const acceptedTurn = deps.events.getTurn(sessionId, turnId) ?? stopping;
|
|
1999
2027
|
sendJson(res, 202, {
|
|
2000
|
-
ok:
|
|
2001
|
-
accepted:
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
},
|
|
2006
|
-
turn: turnSummary(pending),
|
|
2028
|
+
ok: true,
|
|
2029
|
+
accepted: true,
|
|
2030
|
+
idempotent: false,
|
|
2031
|
+
cleanupPending: !isTerminalTurnState(acceptedTurn.state),
|
|
2032
|
+
turn: turnSummary(acceptedTurn),
|
|
2007
2033
|
});
|
|
2008
2034
|
}
|
|
2009
2035
|
export async function handleGetChatTurn(_req, res, deps, sessionId, turnId) {
|
|
@@ -3487,13 +3513,57 @@ export async function handleChatCompact(req, res, deps, sessionId) {
|
|
|
3487
3513
|
const rawInstructions = typeof body.instructions === "string" ? body.instructions : undefined;
|
|
3488
3514
|
const currentTodos = projectCurrentTodos(deps.events.snapshot(sessionId));
|
|
3489
3515
|
const customInstructions = buildTodoCompactionInstructions(rawInstructions, currentTodos);
|
|
3516
|
+
const turnId = deps.events.latestTurnId(sessionId) ?? `${sessionId}:compact`;
|
|
3517
|
+
const compactionId = `${sessionId}:compaction:${randomUUID()}`;
|
|
3518
|
+
deps.events.append(sessionId, turnId, {
|
|
3519
|
+
kind: "compaction_start",
|
|
3520
|
+
data: {
|
|
3521
|
+
schemaVersion: 1,
|
|
3522
|
+
compactionId,
|
|
3523
|
+
reason: "manual",
|
|
3524
|
+
status: "running",
|
|
3525
|
+
willRetry: false,
|
|
3526
|
+
},
|
|
3527
|
+
});
|
|
3490
3528
|
try {
|
|
3491
3529
|
const snapshot = await deps.runtime.compact(sessionId, customInstructions);
|
|
3492
|
-
const event = deps.events.append(sessionId,
|
|
3530
|
+
const event = deps.events.append(sessionId, turnId, {
|
|
3531
|
+
kind: "compaction_end",
|
|
3532
|
+
data: {
|
|
3533
|
+
schemaVersion: 1,
|
|
3534
|
+
compactionId,
|
|
3535
|
+
reason: "manual",
|
|
3536
|
+
status: "completed",
|
|
3537
|
+
summary: snapshot.summary,
|
|
3538
|
+
...(snapshot.firstKeptEntryId
|
|
3539
|
+
? { firstKeptEntryId: snapshot.firstKeptEntryId }
|
|
3540
|
+
: {}),
|
|
3541
|
+
...(snapshot.tokensBefore === undefined
|
|
3542
|
+
? {}
|
|
3543
|
+
: { tokensBefore: snapshot.tokensBefore }),
|
|
3544
|
+
...(snapshot.estimatedTokensAfter === undefined
|
|
3545
|
+
? {}
|
|
3546
|
+
: { estimatedTokensAfter: snapshot.estimatedTokensAfter }),
|
|
3547
|
+
willRetry: false,
|
|
3548
|
+
},
|
|
3549
|
+
});
|
|
3493
3550
|
sendJson(res, 200, { ok: true, snapshot, eventId: event.eventId });
|
|
3494
3551
|
}
|
|
3495
3552
|
catch (error) {
|
|
3496
3553
|
const classified = classifyChatCompactionFailure(error);
|
|
3554
|
+
const aborted = error instanceof Error &&
|
|
3555
|
+
(error.name === "AbortError" || /cancel(?:led|ed)|aborted/i.test(error.message));
|
|
3556
|
+
deps.events.append(sessionId, turnId, {
|
|
3557
|
+
kind: "compaction_end",
|
|
3558
|
+
data: {
|
|
3559
|
+
schemaVersion: 1,
|
|
3560
|
+
compactionId,
|
|
3561
|
+
reason: "manual",
|
|
3562
|
+
status: aborted ? "aborted" : "failed",
|
|
3563
|
+
willRetry: false,
|
|
3564
|
+
...(aborted ? {} : { errorMessage: classified.message }),
|
|
3565
|
+
},
|
|
3566
|
+
});
|
|
3497
3567
|
sendJson(res, classified.status, {
|
|
3498
3568
|
ok: false,
|
|
3499
3569
|
error: { code: classified.code, message: classified.message },
|
|
@@ -1,5 +1,70 @@
|
|
|
1
1
|
export const ACTIVE_CHAT_SESSION_STORAGE_KEY = "loop-console.operator-chat.active-session.v1";
|
|
2
|
+
export const ACTIVE_CHAT_SESSION_BY_WORKSPACE_STORAGE_KEY = "loop-console.operator-chat.active-session-by-workspace.v1";
|
|
2
3
|
export const DEFAULT_LANDING_STORAGE_KEY = "loop-console.operator-chat.default-landing.v1";
|
|
4
|
+
function readWorkspaceSessionMap(storage) {
|
|
5
|
+
try {
|
|
6
|
+
const parsed = JSON.parse(storage.getItem(ACTIVE_CHAT_SESSION_BY_WORKSPACE_STORAGE_KEY) ?? "{}");
|
|
7
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
8
|
+
return {};
|
|
9
|
+
return Object.fromEntries(Object.entries(parsed).filter((entry) => Boolean(entry[0].trim()) &&
|
|
10
|
+
typeof entry[1] === "string" &&
|
|
11
|
+
Boolean(entry[1].trim())));
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return {};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/** Resolve the selected Chat session from client state. The workspace map is
|
|
18
|
+
* authoritative; the former global key is only a safe, server-validated
|
|
19
|
+
* migration fallback for users upgrading from the single-selection layout. */
|
|
20
|
+
export function readActiveChatSessionId(storage, workspaceId) {
|
|
21
|
+
const scope = workspaceId?.trim();
|
|
22
|
+
if (scope) {
|
|
23
|
+
const map = readWorkspaceSessionMap(storage);
|
|
24
|
+
const scoped = map[scope]?.trim();
|
|
25
|
+
if (scoped)
|
|
26
|
+
return scoped;
|
|
27
|
+
// Once the map exists, an absent workspace means "no selected session";
|
|
28
|
+
// never fall back to another workspace's global legacy selection.
|
|
29
|
+
if (Object.keys(map).length > 0)
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
return storage.getItem(ACTIVE_CHAT_SESSION_STORAGE_KEY)?.trim() || null;
|
|
33
|
+
}
|
|
34
|
+
/** Remember the active session for its owning workspace while retaining the
|
|
35
|
+
* global key for existing non-Chat consumers that refer to the visible session. */
|
|
36
|
+
export function rememberActiveChatSession(storage, workspaceId, sessionId) {
|
|
37
|
+
const id = sessionId.trim();
|
|
38
|
+
if (!id)
|
|
39
|
+
return;
|
|
40
|
+
storage.setItem(ACTIVE_CHAT_SESSION_STORAGE_KEY, id);
|
|
41
|
+
const scope = workspaceId?.trim();
|
|
42
|
+
if (!scope)
|
|
43
|
+
return;
|
|
44
|
+
const map = readWorkspaceSessionMap(storage);
|
|
45
|
+
map[scope] = id;
|
|
46
|
+
storage.setItem(ACTIVE_CHAT_SESSION_BY_WORKSPACE_STORAGE_KEY, JSON.stringify(map));
|
|
47
|
+
}
|
|
48
|
+
/** Forget one workspace's invalid/deleted selection without disturbing the
|
|
49
|
+
* last session remembered for any other workspace. */
|
|
50
|
+
export function forgetActiveChatSession(storage, workspaceId, sessionId) {
|
|
51
|
+
const scope = workspaceId?.trim();
|
|
52
|
+
if (scope) {
|
|
53
|
+
const map = readWorkspaceSessionMap(storage);
|
|
54
|
+
if (!sessionId || map[scope] === sessionId)
|
|
55
|
+
delete map[scope];
|
|
56
|
+
if (Object.keys(map).length > 0) {
|
|
57
|
+
storage.setItem(ACTIVE_CHAT_SESSION_BY_WORKSPACE_STORAGE_KEY, JSON.stringify(map));
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
storage.removeItem(ACTIVE_CHAT_SESSION_BY_WORKSPACE_STORAGE_KEY);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const global = storage.getItem(ACTIVE_CHAT_SESSION_STORAGE_KEY)?.trim();
|
|
64
|
+
if (!sessionId || global === sessionId) {
|
|
65
|
+
storage.removeItem(ACTIVE_CHAT_SESSION_STORAGE_KEY);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
3
68
|
function configuredLanding(value) {
|
|
4
69
|
const normalized = value?.trim().toLowerCase();
|
|
5
70
|
if (normalized === "chat")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-
|
|
1
|
+
import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-DrU-s-t7.js";import{p as f}from"./chunk-JWPE2WC7-BjLtNFrR.js";import{_ as n,l as o}from"./mermaid.core-DwPGvpCv.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-BRzFqTaL.js";import"./index-DqJbO3-p.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-
|
|
1
|
+
import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-DwPGvpCv.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
|