@tea-agent/loop-agent 0.44.0-next.1 → 0.44.0-next.11
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 +379 -416
- package/dist/application/evaluation/budget.js +21 -0
- package/dist/application/evaluation/corpus-hash.js +10 -15
- package/dist/application/evaluation/corpus.js +2 -1
- package/dist/application/evaluation/frontend-browser-acceptance.js +77 -0
- package/dist/application/evaluation/frontend-corpus-browser-acceptance.js +175 -0
- package/dist/application/evaluation/frontend-gateway-evidence.js +226 -0
- package/dist/application/evaluation/frontend-pair-registration.js +143 -0
- package/dist/application/evaluation/frontend-paired-summary.js +150 -0
- package/dist/application/evaluation/frontend-run-observation.js +144 -0
- package/dist/application/evaluation/frontend-shared-evidence.js +105 -0
- package/dist/application/evaluation/types.js +45 -12
- package/dist/application/task-lifecycle/observe.js +26 -1
- package/dist/build-stamp.json +3 -3
- package/dist/cli/command-definitions.js +11 -0
- package/dist/cli/program.js +4 -0
- package/dist/commands/task-advance.js +3 -5
- package/dist/commands/task-source-prepare.js +13 -1
- package/dist/executors/dag-pi/guards.js +4 -0
- package/dist/executors/dag-pi/model-config.js +30 -0
- package/dist/executors/dag-pi/plan/fact-adoption.js +55 -0
- package/dist/{workflows/dag/frontend-plan-completeness.js → executors/dag-pi/plan/facts.js} +22 -28
- package/dist/executors/dag-pi/plan/finalize-tools.js +259 -0
- package/dist/executors/dag-pi/plan/ledger-contract.js +55 -0
- package/dist/executors/dag-pi/plan/record-tools.js +861 -0
- package/dist/executors/dag-pi/plan/schema.js +129 -0
- package/dist/executors/dag-pi/plan/session.js +1 -0
- package/dist/executors/dag-pi/plan/tool-helpers.js +16 -0
- package/dist/executors/dag-pi/sessions/index.js +6 -0
- package/dist/executors/dag-pi/sessions/plan-batches.js +280 -0
- package/dist/executors/dag-pi/sessions/plan-prompts.js +367 -0
- package/dist/executors/dag-pi/sessions/scout-parallel.js +197 -0
- package/dist/executors/dag-pi/sessions/segmented-plan.js +1184 -0
- package/dist/executors/dag-pi/sessions/writer-evidence.js +60 -0
- package/dist/executors/dag-pi/tools/contract-tools.js +515 -0
- package/dist/executors/dag-pi/tools/design-terminal-tools.js +159 -0
- package/dist/executors/dag-pi/tools/plan-decision-tools.js +529 -0
- package/dist/executors/dag-pi/tools/review-terminal-tools.js +159 -0
- package/dist/executors/dag-pi/tools/scout-evidence-tools.js +270 -0
- package/dist/executors/dag-pi-executor.js +733 -5782
- package/dist/executors/pi-executor.js +6 -1
- package/dist/executors/pi-sdk-executor.js +112 -19
- package/dist/executors/shell-executor.js +88 -12
- package/dist/executors/shell-presets.js +1 -1
- package/dist/executors/shell-write-guard.js +26 -3
- package/dist/infrastructure/console/operation-store.js +48 -14
- package/dist/infrastructure/evaluation/corpus-store.js +37 -12
- package/dist/shared/file-identity.js +23 -0
- package/dist/shared/git-workspace-status.js +482 -0
- package/dist/shared/operator/capabilities.js +10 -5
- package/dist/shared/path-safety.js +2 -2
- package/dist/shared/wizard-local-telemetry.js +51 -0
- package/dist/task/config-types.js +22 -8
- package/dist/task/contract/project.js +13 -0
- package/dist/task/contract/schema.js +2 -7
- package/dist/task/frontend-preflight.js +1 -1
- package/dist/task/source-prepare/parse-intent.js +124 -5
- package/dist/task/source-prepare/prepare.js +6 -1
- package/dist/task/source-prepare/semantic-intake.js +18 -3
- package/dist/task/source-prepare/source-execution.js +65 -0
- package/dist/task/source-prepare/source-fidelity-pi.js +22 -9
- package/dist/task/source-prepare/source-provider-budget.js +290 -0
- package/dist/worker/console/chat/assistant-content.js +5 -34
- package/dist/worker/console/chat/chat-event-store.js +62 -10
- package/dist/worker/console/chat/context-insights.js +723 -0
- package/dist/worker/console/chat/conversation-nodes.js +383 -0
- package/dist/worker/console/chat/db-connections.js +854 -0
- package/dist/worker/console/chat/pi-runtime/custom-tools/operator-tools.js +1 -1
- package/dist/worker/console/chat/pi-runtime/custom-tools/sql-tools.js +655 -0
- package/dist/worker/console/chat/pi-runtime.js +445 -36
- package/dist/worker/console/chat/provider-error.js +0 -12
- package/dist/worker/console/chat/repo-browser.js +52 -4
- package/dist/worker/console/chat/routes.js +577 -72
- package/dist/worker/console/chat/sdd-data-alignment.js +8 -31
- package/dist/worker/console/chat/session-store.js +147 -19
- package/dist/worker/console/chat/shortcuts.js +7 -0
- package/dist/worker/console/chat/timeline-message-order.js +22 -0
- package/dist/worker/console/chat/tools.js +34 -0
- package/dist/worker/console/chat/turn-process.js +237 -66
- package/dist/worker/console/chat/user-turn-outline.js +19 -0
- package/dist/worker/console/console-update-runtime.js +2 -2
- package/dist/worker/console/dag-confirmation.js +3 -0
- package/dist/worker/console/dag-execution-receipt.js +3 -0
- package/dist/worker/console/operator-actions.js +32 -3
- package/dist/worker/console/operator-user-error.js +28 -1
- package/dist/worker/console/pi-readiness.js +4 -4
- package/dist/worker/console/prd-intake-bridge.js +5 -12
- package/dist/worker/console/recovery-cta.js +14 -14
- package/dist/worker/console/server.js +5 -1
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-8-j6y-sd.js → abnfDiagram-N423BO3Z-r1NAPU_5.js} +1 -1
- package/dist/worker/console/static/assets/{arc-eoQiMvuk.js → arc-dT5T4sVL.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-C4A3uMcI.js → architectureDiagram-T3A2C74G-CP_cOq46.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-D4zD2F-Q.js → blockDiagram-VBNYF7ZC-sToEZxEf.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-j1RkJziL.js → c4Diagram-5PPSVZJV-DSxwwi2m.js} +1 -1
- package/dist/worker/console/static/assets/channel-CyBY_yGk.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-YBHmhik1.js → chunk-2GRJ4B5K-B9fh0IkF.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-COfWyo9P.js → chunk-2Q5K7J3B-CAUNl-A6.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-I99OUkHY.js → chunk-5RXB4S5H-BomeqbNX.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-XKxoJNJ4.js → chunk-5VM5RSS4-BNAuTOLE.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DLT_cYx1.js → chunk-6Q2QTUOP-DfzjRD5y.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CxcKZ9mV.js → chunk-GF5L2VYU-C3uE-yc2.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-V1EqXdjY.js → chunk-JWPE2WC7-C3sQMMYr.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-DebTtdFp.js → chunk-KBJHAD2P-D_AtEYQL.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-B-ivNRDf.js → chunk-RYQCIY6F-DW4TwhKv.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-DC_Ds11b.js → chunk-XXDRQBXY-CTQDmJcp.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-D5lN4E_E.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-D5lN4E_E.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-sWEqKwIb.js → cose-bilkent-JH36ORCC-iMqPuBsL.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BXa_dcu4.js → cynefin-VYW2F7L2-DktIuDWs.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-C-Mle84F.js → cynefinDiagram-MW4NZA55-BgVnjyEs.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-CXPDBITe.js → dagre-VZM6K2ZE-CR25E4bu.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-CC-WJQfa.js → diagram-7IWD3JNH-CPM2h5HY.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-CDAV5Vs4.js → diagram-B4RE2ZJO-DqF0x2g1.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-CmFiAcNz.js → diagram-LBJQPF4R-G8BYp2eb.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-DPBZHuyn.js → diagram-Q27KOJAE-BbC4kT_D.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-jUlm_Ds3.js → diagram-UB23O5K3-CKZwZ-G5.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-DWhQ3mfY.js → ebnfDiagram-BXEA7PRR-kJDmheia.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-Tr2gMqet.js → erDiagram-JOGREHBK-DFTVHyxB.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-DJjVQHPA.js → flowDiagram-UKHOOZJN-BqdN5_os.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-D74dQ4u0.js → ganttDiagram-PKOTCBZU-SYDjVakh.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-DwW0tZ0X.js → gitGraphDiagram-DS77QQ5N-Bf8bNpGA.js} +1 -1
- package/dist/worker/console/static/assets/index-B28Onmfy.css +1 -0
- package/dist/worker/console/static/assets/index-CTMZsDmh.js +486 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-ILCbxJyb.js → infoDiagram-6WML65LV-DIeAmJ45.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-DeuWBQ89.js → ishikawaDiagram-WSZJBQD7-oikqUAlo.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-CF5ih8Fk.js → journeyDiagram-NVQOT4AX-mKEF_xYT.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-C7yOSuRO.js → kanban-definition-27J2QSJJ-BdWJHPnN.js} +1 -1
- package/dist/worker/console/static/assets/{linear-BDZ9riWi.js → linear-DGRlieMH.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-7pKqYtpZ.js → mermaid.core-4P9yPC9c.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-LeJDybSU.js → mindmap-definition-FAOFIHXS-5PTSkos6.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BJvT3pMD.js → pegDiagram-VL7TDLO6-DONIFpG5.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-_rGqpMan.js → pieDiagram-7S7Q4E2Y-D_Z4S70M.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-DPcSv5aA.js → quadrantDiagram-CIZ2JOQS-CAsjh8iY.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-Drxx4hkJ.js → railroadDiagram-AXF67PYL-Cx4Dd6ac.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-BCTUdU4z.js → requirementDiagram-LRYGKXZP-cQb7mwyH.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-B6wzbZmB.js → sankeyDiagram-W5VNT64P-Cd-DhUdf.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-BGt8d3QQ.js → sequenceDiagram-SI44F4Z6-AlKYRgIk.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-7nlhJKo7.js → sizeCapture-X5ZJPWSS-CUy_ET4e.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-Cv2stqMA.js → stateDiagram-OKZ733FA-CTuVe6Sa.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BsWhs8O7.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-qDAo4Yc1.js → swimlanes-SLNWSIFB-ChFLJb-v.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-CJcioYGH.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-CKbDNKTr.js → timeline-definition-Z64GVDOM-DZZeiAPr.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-DI-9EHic.js → vennDiagram-T6HMQDX7-t4O91cZU.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-BrzzRDpX.js → wardleyDiagram-T6FBY63Y-CV5qGHZu.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-BclH5hGh.js → xychartDiagram-ELKLHX3M-DyXbytUI.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/app/console-types.js +9 -1
- package/dist/worker/console/static-src/operator-chat/animation-frame-batcher.js +38 -0
- package/dist/worker/console/static-src/operator-chat/chat-link.js +20 -0
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +186 -5
- package/dist/worker/console/static-src/operator-chat/chat-stream-continuity.js +101 -0
- package/dist/worker/console/static-src/operator-chat/compaction-message.js +18 -3
- package/dist/worker/console/static-src/operator-chat/context-insights-store.js +64 -0
- package/dist/worker/console/static-src/operator-chat/details-rail-surfaces.js +98 -0
- package/dist/worker/console/static-src/operator-chat/file-palette-nav.js +81 -0
- package/dist/worker/console/static-src/operator-chat/pending-user-message.js +17 -3
- package/dist/worker/console/static-src/operator-chat/process-label.js +27 -5
- package/dist/worker/console/static-src/operator-chat/tools-catalog.js +16 -7
- package/dist/worker/console/static-src/operator-chat/transcript-mode.js +21 -0
- package/dist/worker/console/static-src/operator-chat/turn-group-equality.js +4 -1
- package/dist/worker/console/static-src/operator-chat/turn-process-disclosure.js +13 -5
- package/dist/worker/console/static-src/operator-chat/turn-state-projection.js +166 -0
- package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +56 -2
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +211 -40
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +124 -27
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +88 -20
- package/dist/worker/console/static-src/operator-chat/useComposer.js +80 -6
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +13 -3
- package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +36 -17
- package/dist/worker/console/static-src/operator-chat/useRuntimeSnapshot.js +18 -0
- package/dist/worker/console/static-src/operator-chat/useWorkspaceBrowserGate.js +4 -0
- package/dist/worker/console/static-src/shell/console-update-reload.js +1 -1
- package/dist/worker/console/workspace-context.js +2 -0
- package/dist/worker/console/workspace-initialization.js +3 -3
- package/dist/worker/observability/read-model.js +23 -2
- package/dist/worker/observe/node-context-insights.js +479 -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/worker/scheduler/scheduled-goal-dispatch.js +3 -2
- package/dist/worker/scheduler/scheduled-goal-evidence.js +66 -3
- package/dist/worker/scheduler/scheduled-goal-store.js +10 -0
- package/dist/workflows/dag/budget-enforcement.js +31 -2
- package/dist/workflows/dag/checkpoint.js +686 -0
- package/dist/workflows/dag/frontend-closeout.js +3 -1
- package/dist/workflows/dag/frontend-contract-facts.js +11 -8
- package/dist/workflows/dag/frontend-design-policy.js +6 -6
- package/dist/workflows/dag/frontend-durable-tools.js +90 -70
- package/dist/workflows/dag/frontend-implementation-contract.js +146 -57
- package/dist/workflows/dag/frontend-plan-canary.js +66 -16
- package/dist/workflows/dag/frontend-plan-decision-contract.js +13 -21
- package/dist/workflows/dag/frontend-plan-progress.js +92 -0
- package/dist/workflows/dag/frontend-recovery-plan.js +10 -5
- package/dist/workflows/dag/frontend-recovery-run.js +51 -46
- package/dist/workflows/dag/frontend-repair-assertions.js +36 -0
- package/dist/workflows/dag/frontend-review-context.js +29 -1
- package/dist/workflows/dag/frontend-review-scopes.js +92 -2
- package/dist/workflows/dag/frontend-risk.js +8 -3
- package/dist/workflows/dag/frontend-root-observation.js +261 -0
- package/dist/workflows/dag/frontend-session-budget.js +52 -39
- package/dist/workflows/dag/frontend-session-context.js +10 -0
- package/dist/workflows/dag/frontend-test-execution-evidence.js +206 -48
- package/dist/workflows/dag/frontend-typed-event-store.js +11 -1
- package/dist/workflows/dag/frontend-verification-trace.js +6 -0
- package/dist/workflows/dag/frontend-writer-admission.js +3 -1
- package/dist/workflows/dag/hybrid/sources.js +1812 -0
- package/dist/workflows/dag/hybrid/templates/backend-test.js +1807 -0
- package/dist/workflows/dag/hybrid/templates/frontend-test.js +702 -0
- package/dist/workflows/dag/hybrid/templates/frontend.js +1529 -0
- package/dist/workflows/dag/hybrid/templates/index.js +8 -0
- package/dist/workflows/dag/hybrid/templates/kg-bootstrap.js +449 -0
- package/dist/workflows/dag/hybrid/templates/knowledge-sync.js +495 -0
- package/dist/workflows/dag/hybrid/templates/shared.js +101 -0
- package/dist/workflows/dag/hybrid/templates/standard.js +265 -0
- package/dist/workflows/dag/hybrid/types.js +32 -0
- package/dist/workflows/dag/init-hybrid.js +57 -7106
- package/dist/workflows/dag/node-execution.js +11 -11
- package/dist/workflows/dag/output-protocol.js +1 -0
- package/dist/workflows/dag/rerun-feedback.js +35 -4
- package/dist/workflows/dag/rerun-task.js +62 -66
- package/dist/workflows/dag/runner.js +38 -1159
- package/dist/workflows/dag/terminal-status.js +502 -0
- package/dist/workflows/dag/types.js +15 -8
- package/dist/workflows/loop/benchmark.js +11 -8
- package/docs/README.md +1 -1
- package/docs/architecture/dag-execution.md +1 -1
- package/docs/architecture/runtime-boundaries.md +1 -1
- package/docs/governance/harness-methodology-verification.md +11 -0
- package/docs/templates/backend-test-dag.json +5 -4
- package/docs/templates/frontend-implementation-contract.schema.json +31 -11
- package/package.json +6 -4
- package/skills/frontend-design-review/SKILL.md +8 -11
- package/skills/frontend-design-review/references/review-checklist.md +3 -4
- package/skills/frontend-review/SKILL.md +5 -1
- package/skills/loop-agent/references/command-reference.md +8 -0
- package/skills/loop-agent/references/hybrid-dag.md +1 -1
- package/dist/worker/console/static/assets/channel-ChE7y-cx.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C01TCf2X.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C01TCf2X.js +0 -1
- package/dist/worker/console/static/assets/index-BWkIfcrK.css +0 -1
- package/dist/worker/console/static/assets/index-Cdkvw_H6.js +0 -469
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DC7V5vcq.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Bwy4QUTO.js +0 -8
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
function finiteStep(data) {
|
|
2
|
+
return typeof data.step === "number" && Number.isSafeInteger(data.step) && data.step >= 0
|
|
3
|
+
? data.step
|
|
4
|
+
: undefined;
|
|
5
|
+
}
|
|
6
|
+
function locationFor(event, step = finiteStep(event.data)) {
|
|
7
|
+
return step === undefined
|
|
8
|
+
? { kind: "turn", turnId: event.turnId }
|
|
9
|
+
: { kind: "step", turnId: event.turnId, step };
|
|
10
|
+
}
|
|
11
|
+
function status(value) {
|
|
12
|
+
return value === "scheduled" ||
|
|
13
|
+
value === "started" ||
|
|
14
|
+
value === "cancelled" ||
|
|
15
|
+
value === "running" ||
|
|
16
|
+
value === "completed" ||
|
|
17
|
+
value === "failed" ||
|
|
18
|
+
value === "interrupted"
|
|
19
|
+
? value
|
|
20
|
+
: undefined;
|
|
21
|
+
}
|
|
22
|
+
function positiveInteger(value) {
|
|
23
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value > 0
|
|
24
|
+
? value
|
|
25
|
+
: undefined;
|
|
26
|
+
}
|
|
27
|
+
function nonNegativeNumber(value) {
|
|
28
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0
|
|
29
|
+
? value
|
|
30
|
+
: undefined;
|
|
31
|
+
}
|
|
32
|
+
function nonEmptyString(value) {
|
|
33
|
+
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
34
|
+
}
|
|
35
|
+
function unknownRetryNode(event, base) {
|
|
36
|
+
return {
|
|
37
|
+
...base,
|
|
38
|
+
key: `unknown:${event.eventId}`,
|
|
39
|
+
kind: "unknown",
|
|
40
|
+
location: locationFor(event),
|
|
41
|
+
data: {
|
|
42
|
+
eventType: "model_retry",
|
|
43
|
+
preview: "Incomplete model retry lifecycle event",
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function retryStateFromEvent(data) {
|
|
48
|
+
if (data.state === "scheduled")
|
|
49
|
+
return "scheduled";
|
|
50
|
+
return data.success === false || data.state === "failed"
|
|
51
|
+
? "cancelled"
|
|
52
|
+
: "started";
|
|
53
|
+
}
|
|
54
|
+
function isRetryAttempt(value) {
|
|
55
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
56
|
+
return false;
|
|
57
|
+
const attempt = value;
|
|
58
|
+
return (positiveInteger(attempt.attempt) !== undefined &&
|
|
59
|
+
positiveInteger(attempt.maxAttempts) !== undefined &&
|
|
60
|
+
nonNegativeNumber(attempt.delayMs) !== undefined &&
|
|
61
|
+
nonEmptyString(attempt.errorMessage) !== undefined &&
|
|
62
|
+
(attempt.state === "scheduled" ||
|
|
63
|
+
attempt.state === "started" ||
|
|
64
|
+
attempt.state === "cancelled") &&
|
|
65
|
+
typeof attempt.seq === "number" &&
|
|
66
|
+
typeof attempt.at === "number");
|
|
67
|
+
}
|
|
68
|
+
/** Read the current complete attempt from a projected retry-chain node. */
|
|
69
|
+
export function modelRetryCurrent(node) {
|
|
70
|
+
if (node.kind !== "retry")
|
|
71
|
+
return undefined;
|
|
72
|
+
return isRetryAttempt(node.data.current) ? node.data.current : undefined;
|
|
73
|
+
}
|
|
74
|
+
function modelRetryAttempts(node) {
|
|
75
|
+
return Array.isArray(node.data.attempts)
|
|
76
|
+
? node.data.attempts.filter(isRetryAttempt)
|
|
77
|
+
: [];
|
|
78
|
+
}
|
|
79
|
+
function retryUpdate(node) {
|
|
80
|
+
const value = node.data.retryUpdate;
|
|
81
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
82
|
+
return undefined;
|
|
83
|
+
const candidate = value;
|
|
84
|
+
if (positiveInteger(candidate.attempt) === undefined ||
|
|
85
|
+
(candidate.state !== "started" && candidate.state !== "cancelled"))
|
|
86
|
+
return undefined;
|
|
87
|
+
return candidate;
|
|
88
|
+
}
|
|
89
|
+
/** Convert one already-redacted durable event into a stable UI node. */
|
|
90
|
+
export function conversationNodeFromEvent(event) {
|
|
91
|
+
const at = Date.parse(event.at);
|
|
92
|
+
const base = {
|
|
93
|
+
anchorSeq: event.seq,
|
|
94
|
+
updatedSeq: event.seq,
|
|
95
|
+
at: Number.isFinite(at) ? at : 0,
|
|
96
|
+
data: event.data,
|
|
97
|
+
};
|
|
98
|
+
const step = finiteStep(event.data);
|
|
99
|
+
switch (event.kind) {
|
|
100
|
+
case "step_start":
|
|
101
|
+
case "step_end": {
|
|
102
|
+
if (step === undefined)
|
|
103
|
+
return undefined;
|
|
104
|
+
const outcome = status(event.data.outcome);
|
|
105
|
+
return {
|
|
106
|
+
...base,
|
|
107
|
+
key: `step:${event.turnId}:${step}`,
|
|
108
|
+
kind: "step",
|
|
109
|
+
location: { kind: "step", turnId: event.turnId, step },
|
|
110
|
+
status: event.kind === "step_start" ? "running" : (outcome ?? "completed"),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
case "model_retry": {
|
|
114
|
+
const attempt = positiveInteger(event.data.attempt);
|
|
115
|
+
if (attempt === undefined)
|
|
116
|
+
return unknownRetryNode(event, base);
|
|
117
|
+
const retryState = retryStateFromEvent(event.data);
|
|
118
|
+
const key = `retry:${event.turnId}:${step ?? 0}`;
|
|
119
|
+
if (retryState !== "scheduled") {
|
|
120
|
+
return {
|
|
121
|
+
...base,
|
|
122
|
+
key,
|
|
123
|
+
kind: "retry",
|
|
124
|
+
location: locationFor(event),
|
|
125
|
+
status: retryState,
|
|
126
|
+
data: {
|
|
127
|
+
retryUpdate: {
|
|
128
|
+
attempt,
|
|
129
|
+
state: retryState,
|
|
130
|
+
seq: event.seq,
|
|
131
|
+
at: base.at,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
const maxAttempts = positiveInteger(event.data.maxAttempts);
|
|
137
|
+
const delayMs = nonNegativeNumber(event.data.delayMs);
|
|
138
|
+
const errorMessage = nonEmptyString(event.data.errorMessage);
|
|
139
|
+
if (maxAttempts === undefined || delayMs === undefined || !errorMessage) {
|
|
140
|
+
return unknownRetryNode(event, base);
|
|
141
|
+
}
|
|
142
|
+
const current = {
|
|
143
|
+
attempt,
|
|
144
|
+
maxAttempts,
|
|
145
|
+
delayMs,
|
|
146
|
+
errorMessage,
|
|
147
|
+
state: "scheduled",
|
|
148
|
+
seq: event.seq,
|
|
149
|
+
at: base.at,
|
|
150
|
+
};
|
|
151
|
+
return {
|
|
152
|
+
...base,
|
|
153
|
+
key,
|
|
154
|
+
kind: "retry",
|
|
155
|
+
location: locationFor(event),
|
|
156
|
+
status: "scheduled",
|
|
157
|
+
data: { attempts: [current], current },
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
case "turn_error":
|
|
161
|
+
return {
|
|
162
|
+
...base,
|
|
163
|
+
key: `turn-error:${event.turnId}`,
|
|
164
|
+
kind: "turn-error",
|
|
165
|
+
location: locationFor(event),
|
|
166
|
+
status: "failed",
|
|
167
|
+
};
|
|
168
|
+
case "turn_max_tokens":
|
|
169
|
+
return {
|
|
170
|
+
...base,
|
|
171
|
+
key: `max-tokens:${event.turnId}:${step ?? 0}`,
|
|
172
|
+
kind: "max-tokens",
|
|
173
|
+
location: locationFor(event),
|
|
174
|
+
status: "completed",
|
|
175
|
+
};
|
|
176
|
+
case "request_context": {
|
|
177
|
+
const requestId = typeof event.data.requestId === "string" && event.data.requestId
|
|
178
|
+
? event.data.requestId
|
|
179
|
+
: event.eventId;
|
|
180
|
+
return {
|
|
181
|
+
...base,
|
|
182
|
+
key: `request:${requestId}`,
|
|
183
|
+
kind: "request",
|
|
184
|
+
location: locationFor(event),
|
|
185
|
+
status: "completed",
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
case "command": {
|
|
189
|
+
const commandId = typeof event.data.commandId === "string" && event.data.commandId
|
|
190
|
+
? event.data.commandId
|
|
191
|
+
: event.eventId;
|
|
192
|
+
return {
|
|
193
|
+
...base,
|
|
194
|
+
key: `command:${commandId}`,
|
|
195
|
+
kind: "command",
|
|
196
|
+
location: { kind: "turn", turnId: event.turnId },
|
|
197
|
+
status: status(event.data.outcome) ?? "completed",
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
case "unknown":
|
|
201
|
+
return {
|
|
202
|
+
...base,
|
|
203
|
+
key: `unknown:${event.eventId}`,
|
|
204
|
+
kind: "unknown",
|
|
205
|
+
location: locationFor(event),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
export function conversationNodesFromEvents(events) {
|
|
210
|
+
let nodes = [];
|
|
211
|
+
for (const event of events) {
|
|
212
|
+
const node = conversationNodeFromEvent(event);
|
|
213
|
+
if (node)
|
|
214
|
+
nodes = upsertConversationNode(nodes, node);
|
|
215
|
+
}
|
|
216
|
+
return nodes;
|
|
217
|
+
}
|
|
218
|
+
/** Keyed upsert that preserves the first structural anchor and location. */
|
|
219
|
+
export function upsertConversationNode(nodes, next) {
|
|
220
|
+
if (next.kind === "retry")
|
|
221
|
+
return upsertRetryNode(nodes, next);
|
|
222
|
+
const merged = upsertBase(nodes, next);
|
|
223
|
+
if (next.kind === "step" && next.location.kind === "step") {
|
|
224
|
+
const { step: nextStep, turnId } = next.location;
|
|
225
|
+
if (next.status === "running") {
|
|
226
|
+
return transitionScheduledRetries(merged, (node) => node.location.kind === "step" &&
|
|
227
|
+
node.location.turnId === turnId &&
|
|
228
|
+
node.location.step < nextStep, "started", next.updatedSeq);
|
|
229
|
+
}
|
|
230
|
+
return transitionScheduledRetries(merged, (node) => node.location.kind === "step" &&
|
|
231
|
+
node.location.turnId === turnId &&
|
|
232
|
+
node.location.step === nextStep &&
|
|
233
|
+
node.anchorSeq < next.updatedSeq, "cancelled", next.updatedSeq);
|
|
234
|
+
}
|
|
235
|
+
if (next.kind === "turn-error") {
|
|
236
|
+
return transitionScheduledRetries(merged, (node) => node.location.kind !== "session" &&
|
|
237
|
+
next.location.kind !== "session" &&
|
|
238
|
+
node.location.turnId === next.location.turnId, "cancelled", next.updatedSeq);
|
|
239
|
+
}
|
|
240
|
+
return merged;
|
|
241
|
+
}
|
|
242
|
+
function upsertBase(nodes, next) {
|
|
243
|
+
const index = nodes.findIndex((node) => node.key === next.key);
|
|
244
|
+
if (index < 0) {
|
|
245
|
+
return [...nodes, next].sort((left, right) => left.anchorSeq - right.anchorSeq || left.key.localeCompare(right.key));
|
|
246
|
+
}
|
|
247
|
+
const previous = nodes[index];
|
|
248
|
+
if (next.updatedSeq < previous.updatedSeq)
|
|
249
|
+
return [...nodes];
|
|
250
|
+
const merged = {
|
|
251
|
+
...previous,
|
|
252
|
+
...next,
|
|
253
|
+
anchorSeq: previous.anchorSeq,
|
|
254
|
+
at: previous.at,
|
|
255
|
+
location: previous.location,
|
|
256
|
+
data: { ...previous.data, ...next.data },
|
|
257
|
+
};
|
|
258
|
+
const result = [...nodes];
|
|
259
|
+
result[index] = merged;
|
|
260
|
+
return result;
|
|
261
|
+
}
|
|
262
|
+
function retryTurnId(node) {
|
|
263
|
+
return node.location.kind === "session" ? undefined : node.location.turnId;
|
|
264
|
+
}
|
|
265
|
+
function retryCandidateIndex(nodes, next) {
|
|
266
|
+
const exact = nodes.findIndex((node) => node.key === next.key);
|
|
267
|
+
if (exact >= 0)
|
|
268
|
+
return exact;
|
|
269
|
+
const update = retryUpdate(next);
|
|
270
|
+
const nextCurrent = modelRetryCurrent(next);
|
|
271
|
+
const attempt = update?.attempt ?? nextCurrent?.attempt;
|
|
272
|
+
const turnId = retryTurnId(next);
|
|
273
|
+
if (attempt === undefined || !turnId)
|
|
274
|
+
return -1;
|
|
275
|
+
for (let index = nodes.length - 1; index >= 0; index -= 1) {
|
|
276
|
+
const candidate = nodes[index];
|
|
277
|
+
const current = modelRetryCurrent(candidate);
|
|
278
|
+
if (candidate.kind !== "retry" || retryTurnId(candidate) !== turnId || !current)
|
|
279
|
+
continue;
|
|
280
|
+
if (current.attempt === attempt)
|
|
281
|
+
return index;
|
|
282
|
+
if (nextCurrent?.state === "scheduled" && current.attempt + 1 === attempt)
|
|
283
|
+
return index;
|
|
284
|
+
}
|
|
285
|
+
return -1;
|
|
286
|
+
}
|
|
287
|
+
function upsertRetryNode(nodes, next) {
|
|
288
|
+
const index = retryCandidateIndex(nodes, next);
|
|
289
|
+
const nextCurrent = modelRetryCurrent(next);
|
|
290
|
+
const update = retryUpdate(next);
|
|
291
|
+
if (index < 0) {
|
|
292
|
+
if (nextCurrent)
|
|
293
|
+
return upsertBase(nodes, next);
|
|
294
|
+
return upsertBase(nodes, {
|
|
295
|
+
...next,
|
|
296
|
+
key: `unknown:${next.key}:${next.updatedSeq}`,
|
|
297
|
+
kind: "unknown",
|
|
298
|
+
status: undefined,
|
|
299
|
+
data: {
|
|
300
|
+
eventType: "model_retry",
|
|
301
|
+
preview: "Orphan model retry lifecycle update",
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
const previous = nodes[index];
|
|
306
|
+
if (next.updatedSeq < previous.updatedSeq)
|
|
307
|
+
return [...nodes];
|
|
308
|
+
let attempts = modelRetryAttempts(previous);
|
|
309
|
+
if (nextCurrent) {
|
|
310
|
+
attempts = attempts.map((attempt) => attempt.state === "scheduled" && attempt.attempt < nextCurrent.attempt
|
|
311
|
+
? { ...attempt, state: "started" }
|
|
312
|
+
: attempt);
|
|
313
|
+
const existing = attempts.findIndex((attempt) => attempt.attempt === nextCurrent.attempt);
|
|
314
|
+
if (existing >= 0)
|
|
315
|
+
attempts[existing] = { ...attempts[existing], ...nextCurrent };
|
|
316
|
+
else
|
|
317
|
+
attempts = [...attempts, nextCurrent];
|
|
318
|
+
}
|
|
319
|
+
else if (update) {
|
|
320
|
+
attempts = attempts.map((attempt) => attempt.attempt === update.attempt
|
|
321
|
+
? { ...attempt, state: update.state }
|
|
322
|
+
: attempt);
|
|
323
|
+
}
|
|
324
|
+
const current = attempts.at(-1);
|
|
325
|
+
if (!current)
|
|
326
|
+
return [...nodes];
|
|
327
|
+
const result = [...nodes];
|
|
328
|
+
result[index] = {
|
|
329
|
+
...previous,
|
|
330
|
+
updatedSeq: next.updatedSeq,
|
|
331
|
+
status: current.state,
|
|
332
|
+
data: { attempts, current },
|
|
333
|
+
};
|
|
334
|
+
return result;
|
|
335
|
+
}
|
|
336
|
+
function transitionScheduledRetries(nodes, predicate, state, updatedSeq) {
|
|
337
|
+
return nodes.map((node) => {
|
|
338
|
+
const current = modelRetryCurrent(node);
|
|
339
|
+
if (node.kind !== "retry" || current?.state !== "scheduled" || !predicate(node)) {
|
|
340
|
+
return node;
|
|
341
|
+
}
|
|
342
|
+
const attempts = modelRetryAttempts(node).map((attempt) => attempt.attempt === current.attempt
|
|
343
|
+
? { ...attempt, state }
|
|
344
|
+
: attempt);
|
|
345
|
+
const nextCurrent = attempts.at(-1);
|
|
346
|
+
return {
|
|
347
|
+
...node,
|
|
348
|
+
updatedSeq: Math.max(node.updatedSeq, updatedSeq),
|
|
349
|
+
status: state,
|
|
350
|
+
data: { attempts, current: nextCurrent },
|
|
351
|
+
};
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
/** Resolve explicit parent links only. Cycles and excessive chains fail flat. */
|
|
355
|
+
export function toolNestingDepths(tools, maxDepth = 32) {
|
|
356
|
+
const byId = new Map(tools.map((tool) => [tool.id, tool]));
|
|
357
|
+
const depths = new Map();
|
|
358
|
+
const cyclic = new Set();
|
|
359
|
+
const resolve = (id, path) => {
|
|
360
|
+
const cached = depths.get(id);
|
|
361
|
+
if (cached !== undefined)
|
|
362
|
+
return cached;
|
|
363
|
+
const cycleAt = path.indexOf(id);
|
|
364
|
+
if (cycleAt >= 0) {
|
|
365
|
+
for (const key of path.slice(cycleAt))
|
|
366
|
+
cyclic.add(key);
|
|
367
|
+
return 0;
|
|
368
|
+
}
|
|
369
|
+
if (path.length >= maxDepth)
|
|
370
|
+
return 0;
|
|
371
|
+
const tool = byId.get(id);
|
|
372
|
+
const parent = tool?.parentToolCallId;
|
|
373
|
+
if (!parent || !byId.has(parent) || parent === id)
|
|
374
|
+
return 0;
|
|
375
|
+
const depth = Math.min(maxDepth, resolve(parent, [...path, id]) + 1);
|
|
376
|
+
return cyclic.has(id) ? 0 : depth;
|
|
377
|
+
};
|
|
378
|
+
for (const tool of tools)
|
|
379
|
+
depths.set(tool.id, resolve(tool.id, []));
|
|
380
|
+
for (const id of cyclic)
|
|
381
|
+
depths.set(id, 0);
|
|
382
|
+
return depths;
|
|
383
|
+
}
|