@tea-agent/loop-agent 0.42.0-next.9 → 0.42.1
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 +111 -45
- package/dist/application/dag/run-dag.js +8 -2
- package/dist/application/evaluation/budget.js +19 -1
- package/dist/application/task-lifecycle/advance.js +26 -8
- package/dist/application/task-lifecycle/observe.js +43 -29
- package/dist/application/task-lifecycle/plan-transitions.js +5 -4
- package/dist/build-stamp.json +3 -3
- package/dist/cli/program.js +1 -1
- package/dist/commands/dag-rerun-task.js +2 -0
- package/dist/commands/task-source-prepare.js +3 -1
- package/dist/executors/dag-pi-executor.js +2584 -600
- package/dist/executors/pi-executor.js +22 -1
- package/dist/executors/pi-extension-resolver.js +14 -2
- package/dist/executors/pi-sdk-executor.js +140 -39
- package/dist/executors/shell-executor.js +135 -55
- package/dist/shared/dag-failure-category.js +6 -0
- package/dist/shared/frontend-execution-policy.js +23 -0
- package/dist/task/config-types.js +4 -0
- package/dist/task/contract/apply.js +36 -2
- package/dist/task/source-prepare/ledger-reconciliation.js +2 -2
- package/dist/task/source-prepare/ledger-review.js +6 -9
- package/dist/task/source-prepare/parse-intent.js +7 -0
- package/dist/task/source-prepare/semantic-intake.js +16 -26
- package/dist/task/source-prepare/source-fidelity-pi.js +28 -9
- package/dist/task/source-references.js +48 -23
- package/dist/worker/console/chat/assistant-content.js +23 -2
- package/dist/worker/console/chat/browser-policy.js +143 -0
- package/dist/worker/console/chat/browser-routes.js +148 -0
- package/dist/worker/console/chat/chat-event-store.js +4 -2
- package/dist/worker/console/chat/explore-tools.js +13 -0
- package/dist/worker/console/chat/pi-runtime.js +173 -94
- package/dist/worker/console/chat/resource-loader.js +4 -1
- package/dist/worker/console/chat/routes.js +208 -66
- package/dist/worker/console/chat/scm-routes.js +217 -0
- package/dist/worker/console/chat/scm-service.js +283 -0
- package/dist/worker/console/chat/scm-tools.js +111 -0
- package/dist/worker/console/chat/sdd-data-alignment.js +78 -11
- package/dist/worker/console/chat/session-catalog.js +32 -0
- package/dist/worker/console/chat/session-mode-view.js +48 -0
- package/dist/worker/console/chat/session-mode.js +218 -0
- package/dist/worker/console/chat/session-store.js +27 -7
- package/dist/worker/console/chat/shortcuts.js +6 -0
- package/dist/worker/console/chat/subagents/agent-tool.js +62 -0
- package/dist/worker/console/chat/subagents/explore-agent.js +169 -0
- package/dist/worker/console/chat/subagents/index.js +5 -0
- package/dist/worker/console/chat/subagents/orchestrator.js +273 -0
- package/dist/worker/console/chat/subagents/tool-policy.js +53 -0
- package/dist/worker/console/chat/subagents/types.js +13 -0
- package/dist/worker/console/chat/terminal-routes.js +216 -0
- package/dist/worker/console/chat/terminal-sessions.js +284 -0
- package/dist/worker/console/chat/terminal-tools.js +199 -0
- package/dist/worker/console/chat/tool-preview.js +21 -0
- package/dist/worker/console/chat/tools.js +13 -1
- package/dist/worker/console/chat/turn-process.js +1 -0
- package/dist/worker/console/interview/tools.js +1 -0
- package/dist/worker/console/server.js +2 -28
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-C6n9_m0P.js → abnfDiagram-N423BO3Z-C9eI7nEo.js} +1 -1
- package/dist/worker/console/static/assets/{arc-DQh-IfZ1.js → arc-VJWsxWhB.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-54NnrwUC.js → architectureDiagram-T3A2C74G-BGcyiMSo.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-pivRALGK.js → blockDiagram-VBNYF7ZC-BScnFwyi.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-BR7OV2NJ.js → c4Diagram-5PPSVZJV-Bl9_BsLi.js} +1 -1
- package/dist/worker/console/static/assets/channel-B6sQYuOE.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-B1Aq6BcK.js → chunk-2GRJ4B5K-F1uKxiUt.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-CbdU0rjo.js → chunk-2Q5K7J3B-rSRMynVu.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-Dqi2GJeD.js → chunk-5RXB4S5H-DAsJm1WD.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-BYn1Hu4R.js → chunk-5VM5RSS4-DQIdVI0a.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DRLjDL0k.js → chunk-6Q2QTUOP-4A_8rJ-Q.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CY9Xx2jV.js → chunk-GF5L2VYU-BHnT-vjh.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BNCZs7_z.js → chunk-JWPE2WC7-Rq7QKBkn.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-DZ8AStLL.js → chunk-KBJHAD2P-BXh-AI2u.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-DsxjYrzz.js → chunk-RYQCIY6F-BblcLy8m.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-Ddx1KC1l.js → chunk-XXDRQBXY-zHZmVnB6.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-Z6s5QoeI.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-Z6s5QoeI.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-W9TveCnK.js → cose-bilkent-JH36ORCC-Cmwz0Wi4.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-l9j_ztZH.js → cynefin-VYW2F7L2-Dq76MHQU.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-BMJMKi4G.js → cynefinDiagram-MW4NZA55-zPahV1fM.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-Bb4mG9pH.js → dagre-VZM6K2ZE-DQJ3xPc_.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-BMgL_Qv0.js → diagram-7IWD3JNH-BwX7u6fv.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-Bvo2T4OQ.js → diagram-B4RE2ZJO-CodnDCco.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-_5kWRN9c.js → diagram-LBJQPF4R-gAjtWkxG.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-DqdMrltM.js → diagram-Q27KOJAE-CGCqz0cS.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-CDDYsNkp.js → diagram-UB23O5K3-RHwYEywd.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-c4nfnZUV.js → ebnfDiagram-BXEA7PRR-B6seb_p_.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DnkUcNMs.js → erDiagram-JOGREHBK-CmwCKYe8.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-Dz0KGLZE.js → flowDiagram-UKHOOZJN-BfNsaZ0V.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-Cj1t1uka.js → ganttDiagram-PKOTCBZU-zmYgi_Z3.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-tp2FrBHd.js → gitGraphDiagram-DS77QQ5N-BDEzzSKF.js} +1 -1
- package/dist/worker/console/static/assets/index-DgenUAfc.js +468 -0
- package/dist/worker/console/static/assets/index-aF4u-Y__.css +1 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DQwJS8DH.js → infoDiagram-6WML65LV-DeSz8l42.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-eimCQWD4.js → ishikawaDiagram-WSZJBQD7-B1LV29aH.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-Dd9Gbwgv.js → journeyDiagram-NVQOT4AX-CCw4W2oU.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-Qve3cyft.js → kanban-definition-27J2QSJJ-BozaMoRJ.js} +1 -1
- package/dist/worker/console/static/assets/{linear-UXKSe36Z.js → linear-G1JR40SX.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-CWhj4JXN.js → mermaid.core-CCgPF0oA.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-yTcwf4SJ.js → mindmap-definition-FAOFIHXS-CEqnCHnD.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-_7qToaZP.js → pegDiagram-VL7TDLO6-DpmQPKuI.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-CXmrKmDm.js → pieDiagram-7S7Q4E2Y-BP501AxR.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-hMmrJyaS.js → quadrantDiagram-CIZ2JOQS-D1dBhl_A.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-BXw8tCBe.js → railroadDiagram-AXF67PYL-DgZDS5pY.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-BmjgnLZl.js → requirementDiagram-LRYGKXZP-BzB3pyIq.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-Bj77SPpN.js → sankeyDiagram-W5VNT64P-B9ZprFFP.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-B2FDVysL.js → sequenceDiagram-SI44F4Z6-CC2-_XrA.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-UChNY9ZZ.js → sizeCapture-X5ZJPWSS-UVtAUqgB.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-wbAEkbd7.js → stateDiagram-OKZ733FA-CWcS5JYG.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BooX8u1Q.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-DCEkU8HR.js → swimlanes-SLNWSIFB-C4p-dn06.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-D64_eqqE.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-BGp7H06U.js → timeline-definition-Z64GVDOM-Dnz52OHX.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-DsCIQuWR.js → vennDiagram-T6HMQDX7-CzTE0Nfu.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-cRZLP4Xe.js → wardleyDiagram-T6FBY63Y-NAR9cjQQ.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CP0xLR9Y.js → xychartDiagram-ELKLHX3M-DVMk8413.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/chat-view-types.js +1 -1
- package/dist/worker/console/static-src/operator-chat/chat-link.js +94 -0
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +142 -7
- package/dist/worker/console/static-src/operator-chat/pending-user-message.js +44 -0
- package/dist/worker/console/static-src/operator-chat/process-label.js +41 -0
- package/dist/worker/console/static-src/operator-chat/tools-catalog.js +21 -2
- package/dist/worker/console/static-src/operator-chat/turn-group-equality.js +13 -0
- package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +2 -0
- package/dist/worker/console/static-src/operator-chat/use-searchable-hidden.js +51 -0
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +33 -18
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +48 -16
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +170 -7
- package/dist/worker/console/static-src/operator-chat/useComposer.js +13 -7
- package/dist/worker/console/static-src/operator-chat/user-turn-anchor-equality.js +21 -0
- package/dist/worker/console/static-src/shell/workspace-route.js +4 -0
- package/dist/worker/console/workspace-context.js +15 -1
- package/dist/worker/observe/node-transparency.js +81 -72
- package/dist/worker/observe/routes.js +20 -1
- package/dist/worker/observe/static/constants.js +22 -22
- package/dist/worker/observe/static/dag-context-reason-labels.js +19 -0
- package/dist/worker/observe/static/dag-history-labels.js +1 -0
- package/dist/worker/observe/static/dag-inspector-humanize.d.ts +16 -0
- package/dist/worker/observe/static/dag-inspector-humanize.js +342 -0
- package/dist/worker/observe/static/dag-node-purpose.js +10 -10
- package/dist/worker/observe/static/dom.js +20 -1
- package/dist/worker/observe/static/format-pool.d.ts +2 -0
- package/dist/worker/observe/static/format-pool.js +6 -0
- package/dist/worker/observe/static/format.js +7 -0
- package/dist/worker/observe/static/index.html +4 -4
- package/dist/worker/observe/static/inspect-workspace.js +34 -7
- package/dist/worker/observe/static/inspector-submission.js +32 -0
- package/dist/worker/observe/static/kpi.js +1 -0
- package/dist/worker/observe/static/prompt-restart-candidates.js +4 -2
- package/dist/worker/observe/static/relations.js +7 -5
- package/dist/worker/observe/static/router.js +13 -0
- package/dist/worker/observe/static/run-processing.js +2 -0
- package/dist/worker/observe/static/shell-chrome.js +36 -3
- package/dist/worker/observe/static/state.js +35 -2
- package/dist/worker/observe/static/styles.css +431 -39
- package/dist/worker/observe/static/task-failure-labels.d.ts +4 -0
- package/dist/worker/observe/static/task-failure-labels.js +67 -0
- package/dist/worker/observe/static/task-history.js +12 -0
- package/dist/worker/observe/static/views/batch.js +6 -13
- package/dist/worker/observe/static/views/dag-graph.js +51 -4
- package/dist/worker/observe/static/views/dag-inspector.js +1069 -426
- package/dist/worker/observe/static/views/dag-trajectory.js +3 -0
- package/dist/worker/observe/static/views/dag.d.ts +6 -0
- package/dist/worker/observe/static/views/dag.js +64 -22
- package/dist/worker/observe/static/views/dags.js +2 -0
- package/dist/worker/observe/static/views/dashboard.js +21 -12
- package/dist/worker/observe/static/views/failures.js +21 -11
- package/dist/worker/observe/static/views/feature.js +11 -29
- package/dist/worker/observe/static/views/pool.js +37 -28
- package/dist/worker/observe/static/views/run.js +48 -5
- package/dist/worker/observe/static/views/session-timeline.js +194 -243
- package/dist/worker/observe/static/views/task.js +81 -62
- package/dist/workflows/dag/backend-test-plan-protocol.js +104 -0
- package/dist/workflows/dag/budget-enforcement.js +53 -3
- package/dist/workflows/dag/dag-retry-schema.js +3 -0
- package/dist/workflows/dag/frontend-capacity.js +9 -0
- package/dist/workflows/dag/frontend-contract-facts.js +130 -0
- package/dist/workflows/dag/frontend-design-policy.js +103 -17
- package/dist/workflows/dag/frontend-durable-tools.js +193 -0
- package/dist/workflows/dag/frontend-execution-groups.js +24 -0
- package/dist/workflows/dag/frontend-implementation-contract.js +423 -41
- package/dist/workflows/dag/frontend-input-projection.js +76 -0
- package/dist/workflows/dag/frontend-plan-completeness.js +186 -0
- package/dist/workflows/dag/frontend-plan-recovery-policy.js +18 -0
- package/dist/workflows/dag/frontend-plan-render.js +21 -3
- package/dist/workflows/dag/frontend-prewrite-gate.js +1 -1
- package/dist/workflows/dag/frontend-recovery-controller.js +32 -8
- package/dist/workflows/dag/frontend-recovery-lineage.js +13 -0
- package/dist/workflows/dag/frontend-recovery-plan.js +4 -1
- package/dist/workflows/dag/frontend-recovery-run.js +146 -16
- package/dist/workflows/dag/frontend-review-scopes.js +139 -0
- package/dist/workflows/dag/frontend-risk.js +2 -0
- package/dist/workflows/dag/frontend-session-budget.js +249 -0
- package/dist/workflows/dag/frontend-shadow-dual-write.js +37 -3
- package/dist/workflows/dag/frontend-shape-facts.js +12 -2
- package/dist/workflows/dag/frontend-shape.js +46 -7
- package/dist/workflows/dag/frontend-test-execution-evidence.js +49 -0
- package/dist/workflows/dag/frontend-typed-event-store.js +14 -0
- package/dist/workflows/dag/frontend-verification-trace.js +38 -4
- package/dist/workflows/dag/frontend-writer-admission.js +2 -2
- package/dist/workflows/dag/init-hybrid.js +70 -35
- package/dist/workflows/dag/node-execution.js +225 -226
- package/dist/workflows/dag/prompt.js +4 -0
- package/dist/workflows/dag/recovery-lease.js +106 -16
- package/dist/workflows/dag/rerun-feedback.js +1 -0
- package/dist/workflows/dag/rerun-plan.js +96 -4
- package/dist/workflows/dag/rerun-run.js +28 -6
- package/dist/workflows/dag/rerun-task.js +221 -18
- package/dist/workflows/dag/retry-policy.js +27 -10
- package/dist/workflows/dag/runner-exit-diagnostics.js +125 -0
- package/dist/workflows/dag/runner.js +246 -19
- package/dist/workflows/dag/structured-output-repair.js +4 -1
- package/dist/workflows/dag/types.js +10 -3
- package/dist/workflows/dag/validate.js +10 -8
- package/dist/workflows/dag/workspace-checkpoint.js +66 -0
- package/docs/operations/README.md +2 -0
- package/docs/templates/agent-dag.schema.json +2 -2
- package/docs/templates/backend-test-dag.json +6 -4
- package/docs/templates/frontend-design-contract.md +4 -4
- package/docs/templates/frontend-implementation-contract.schema.json +68 -4
- package/docs/templates/frontend-implementation-dag.json +5 -5
- package/harness.json +1 -1
- package/package.json +8 -6
- package/skills/frontend-contract/SKILL.md +2 -1
- package/skills/frontend-contract/references/contract-protocol.md +19 -3
- package/skills/frontend-design-review/SKILL.md +12 -11
- package/skills/frontend-plan/SKILL.md +22 -2
- package/skills/frontend-plan/references/decision-contract.md +114 -5
- package/skills/frontend-plan/references/design-decisions.md +32 -0
- package/skills/frontend-review/SKILL.md +10 -11
- package/skills/frontend-scout/references/scout-evidence.md +4 -0
- package/dist/worker/console/static/assets/channel-DsZxrgqe.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-CuToPeGV.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-CuToPeGV.js +0 -1
- package/dist/worker/console/static/assets/index-D9Sc0f0y.js +0 -449
- package/dist/worker/console/static/assets/index-DDQc5a50.css +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-yPoT19ft.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-VWdarchG.js +0 -8
|
@@ -33,6 +33,8 @@ import { parseProviderError, } from "./provider-error.js";
|
|
|
33
33
|
import { projectCompactSnapshot, } from "./chat-event-store.js";
|
|
34
34
|
import { extractUsageSample } from "./usage.js";
|
|
35
35
|
import { OPERATOR_CHAT_ALLOWED_TOOLS, authorizeOperatorChatTool, assertNoWriteToolInList, } from "./tools.js";
|
|
36
|
+
import { authorizeChatSessionTool, DEFAULT_CONSOLE_CHAT_SESSION_MODE, PI_TODO_WRITE_DESCRIPTION, chatActiveToolBaseline, composeChatSystemPrompt, composeChatSystemPromptParts, computeChatActiveToolNames, shouldInjectGoalContinuation, shouldLoadWorkflowBusinessTools, } from "./session-mode.js";
|
|
37
|
+
import { buildAgentCustomTool, ExploreOrchestrator, } from "./subagents/index.js";
|
|
36
38
|
import { createOperatorChatResourceLoader, } from "./resource-loader.js";
|
|
37
39
|
import { applySkillAutoInvocationPreferences, isAutoInvocationEnabled, loadResourcePreferences, skillResourceId, } from "./resource-preferences-store.js";
|
|
38
40
|
import { buildModelCallableToolSchemas } from "./tool-adapter.js";
|
|
@@ -42,6 +44,8 @@ import { resolveDefaultChatModel, resolveLowChatModel, } from "./model-resolver.
|
|
|
42
44
|
import { filterActiveInterviewTools } from "../interview/tools.js";
|
|
43
45
|
import { RUNTIME_CONTEXT_TEXT_MAX, redactRuntimeText, } from "./runtime-context.js";
|
|
44
46
|
import { buildTodoContinuationContext, } from "./todos.js";
|
|
47
|
+
import { buildPersistentTerminalTools } from "./terminal-tools.js";
|
|
48
|
+
import { buildScmTools } from "./scm-tools.js";
|
|
45
49
|
import { buildGoalContinuationContext, } from "./goals.js";
|
|
46
50
|
import { injectWizardLocalHeaders, } from "./sdd-data-alignment.js";
|
|
47
51
|
/**
|
|
@@ -74,15 +78,6 @@ export const OPERATOR_CHAT_SYSTEM_PROMPT_BASE = [
|
|
|
74
78
|
"Continue until success, user stop, or no safe recovery remains; then stop and report failure/evidence. Never create a new task for a transient failure or replace repair-pi with direct edits.",
|
|
75
79
|
"Narrate long-DAG progress briefly at start, meaningful phase changes/findings, verification failure/recovery, prolonged quiet and terminal state: say what finished and what is next. Never narrate unchanged operationWait polls or heartbeats, or claim beyond structured facts.",
|
|
76
80
|
].join("\n");
|
|
77
|
-
/** Compose the inspectable system prompt actually injected into Operator Chat. */
|
|
78
|
-
export function composeOperatorChatSystemPrompt(input) {
|
|
79
|
-
return [
|
|
80
|
-
OPERATOR_CHAT_SYSTEM_PROMPT_BASE,
|
|
81
|
-
...(input.systemPromptSuffix?.trim()
|
|
82
|
-
? [input.systemPromptSuffix.trim()]
|
|
83
|
-
: []),
|
|
84
|
-
].join("\n\n");
|
|
85
|
-
}
|
|
86
81
|
/**
|
|
87
82
|
* Built-in SDK tool names registered for every Chat session (ADR 0011).
|
|
88
83
|
* Full Pi builtins: read/write/edit/bash/grep/find/ls. safe-* custom tools
|
|
@@ -111,26 +106,8 @@ export const OPERATOR_CHAT_SAFE_EXPLORE_TOOL_IDS = Object.freeze([
|
|
|
111
106
|
"git-diff",
|
|
112
107
|
]);
|
|
113
108
|
export function OPERATOR_CHAT_ACTIVE_TOOL_NAMES() {
|
|
114
|
-
return
|
|
115
|
-
...OPERATOR_CHAT_ALLOWED_TOOLS,
|
|
116
|
-
...OPERATOR_CHAT_BUILTIN_EXPLORE_TOOLS,
|
|
117
|
-
...OPERATOR_CHAT_SAFE_EXPLORE_TOOL_IDS,
|
|
118
|
-
];
|
|
109
|
+
return chatActiveToolBaseline("workflow");
|
|
119
110
|
}
|
|
120
|
-
/**
|
|
121
|
-
* Non-Pi write / coding channels that must never be activated in Operator
|
|
122
|
-
* Chat even when a user/project extension registers them (ADR 0011 / 0012).
|
|
123
|
-
* Mirrors the NON_PI_WRITE_CHANNELS guard in tools.ts for the Gate 2 pin.
|
|
124
|
-
*/
|
|
125
|
-
const OPERATOR_CHAT_EXTENSION_DENIED_TOOL_IDS = new Set([
|
|
126
|
-
"apply_patch",
|
|
127
|
-
"apply-patch",
|
|
128
|
-
"full-tools",
|
|
129
|
-
"full_tools",
|
|
130
|
-
"coding-chat",
|
|
131
|
-
"coding_chat",
|
|
132
|
-
"shell",
|
|
133
|
-
].map((t) => t.toLowerCase()));
|
|
134
111
|
/**
|
|
135
112
|
* Gate 2 active-tool set for a live session (ADR 0012): the operator-chat
|
|
136
113
|
* baseline (operator actions + Pi builtins + safe explore) PLUS extension
|
|
@@ -141,24 +118,8 @@ const OPERATOR_CHAT_EXTENSION_DENIED_TOOL_IDS = new Set([
|
|
|
141
118
|
* coding-chat). Unknown/denied names are never activated; Gate 3 still
|
|
142
119
|
* re-authorizes every tool call per invocation.
|
|
143
120
|
*/
|
|
144
|
-
export function computeOperatorChatActiveToolNames(session) {
|
|
145
|
-
|
|
146
|
-
if (!session?.getAllTools)
|
|
147
|
-
return baseline;
|
|
148
|
-
const baselineLower = new Set(baseline.map((t) => t.toLowerCase()));
|
|
149
|
-
const extras = [];
|
|
150
|
-
for (const tool of session.getAllTools()) {
|
|
151
|
-
const name = tool?.name;
|
|
152
|
-
if (!name || typeof name !== "string")
|
|
153
|
-
continue;
|
|
154
|
-
const lower = name.toLowerCase();
|
|
155
|
-
if (baselineLower.has(lower))
|
|
156
|
-
continue;
|
|
157
|
-
if (OPERATOR_CHAT_EXTENSION_DENIED_TOOL_IDS.has(lower))
|
|
158
|
-
continue;
|
|
159
|
-
extras.push(name);
|
|
160
|
-
}
|
|
161
|
-
return extras.length > 0 ? [...baseline, ...extras] : baseline;
|
|
121
|
+
export function computeOperatorChatActiveToolNames(session, sessionMode = DEFAULT_CONSOLE_CHAT_SESSION_MODE) {
|
|
122
|
+
return computeChatActiveToolNames(session, sessionMode);
|
|
162
123
|
}
|
|
163
124
|
const OPERATOR_CHAT_SESSION_EXCLUDE_TOOLS = Object.freeze([
|
|
164
125
|
"apply_patch",
|
|
@@ -214,8 +175,8 @@ async function bindSessionExtensions(session) {
|
|
|
214
175
|
return;
|
|
215
176
|
await session.bindExtensions(createConsoleExtensionBindings());
|
|
216
177
|
}
|
|
217
|
-
function pinOperatorChatTools(session) {
|
|
218
|
-
session.setActiveToolsByName(
|
|
178
|
+
function pinOperatorChatTools(session, sessionMode = DEFAULT_CONSOLE_CHAT_SESSION_MODE) {
|
|
179
|
+
session.setActiveToolsByName(computeChatActiveToolNames(session, sessionMode));
|
|
219
180
|
}
|
|
220
181
|
/**
|
|
221
182
|
* Pi has no hook result that merely appends instructions to its built-in
|
|
@@ -367,7 +328,7 @@ async function buildCustomOperatorTools(options) {
|
|
|
367
328
|
promptSnippet: schema.description,
|
|
368
329
|
parameters: parameters,
|
|
369
330
|
async execute(toolCallId, params) {
|
|
370
|
-
const decision =
|
|
331
|
+
const decision = authorizeChatSessionTool(schema.toolId, options.sessionMode ?? DEFAULT_CONSOLE_CHAT_SESSION_MODE);
|
|
371
332
|
if (!decision.ok) {
|
|
372
333
|
return {
|
|
373
334
|
content: [
|
|
@@ -384,7 +345,7 @@ async function buildCustomOperatorTools(options) {
|
|
|
384
345
|
}
|
|
385
346
|
// Defer require to avoid circular import at module load.
|
|
386
347
|
const { dispatchChatToolCall } = await import("./session-store.js");
|
|
387
|
-
const result = await dispatchChatToolCall(ctx, decision.toolId, params, toolCallId);
|
|
348
|
+
const result = await dispatchChatToolCall(ctx, decision.toolId, params, toolCallId, options.sessionMode);
|
|
388
349
|
const payload = result.ok
|
|
389
350
|
? result.result
|
|
390
351
|
: { error: result.message, code: result.errorCode };
|
|
@@ -442,11 +403,14 @@ async function buildTodoWriteTool(options) {
|
|
|
442
403
|
import("typebox"),
|
|
443
404
|
import("@earendil-works/pi-coding-agent"),
|
|
444
405
|
]);
|
|
406
|
+
const description = options.sessionMode === "pi"
|
|
407
|
+
? PI_TODO_WRITE_DESCRIPTION
|
|
408
|
+
: TODO_WRITE_DESCRIPTION;
|
|
445
409
|
return defineTool({
|
|
446
410
|
name: "todo_write",
|
|
447
411
|
label: "Update todo list",
|
|
448
|
-
description
|
|
449
|
-
promptSnippet:
|
|
412
|
+
description,
|
|
413
|
+
promptSnippet: description,
|
|
450
414
|
parameters: Type.Object({
|
|
451
415
|
todos: Type.Array(Type.Object({
|
|
452
416
|
content: Type.String({ description: "Short imperative task description." }),
|
|
@@ -1019,19 +983,43 @@ export class ConsolePiRuntime {
|
|
|
1019
983
|
sessionInit = new Map();
|
|
1020
984
|
/** Resolved model binding after materialization (create may return before this is known). */
|
|
1021
985
|
sessionModels = new Map();
|
|
986
|
+
/** Durable session mode; record is the source of truth, this is the live handle cache. */
|
|
987
|
+
sessionModes = new Map();
|
|
1022
988
|
/** SessionIds disposed while materialization was still in flight. */
|
|
1023
989
|
disposedSessions = new Set();
|
|
1024
990
|
compactionControllers = new Map();
|
|
1025
991
|
siftStates = new Map();
|
|
1026
992
|
/** Session-less tool definition caches (no AgentSession state). */
|
|
1027
|
-
|
|
1028
|
-
operatorCustomToolsPromise;
|
|
993
|
+
operatorCustomToolsByMode = new Map();
|
|
1029
994
|
exploreCustomToolsPromise;
|
|
995
|
+
exploreOrchestrator;
|
|
1030
996
|
bindings;
|
|
1031
997
|
constructor(options) {
|
|
1032
998
|
this.options = options;
|
|
1033
999
|
this.loader = createOperatorChatResourceLoader();
|
|
1034
1000
|
this.bindings = options.bindings ?? createDefaultPiSdkBindings();
|
|
1001
|
+
this.exploreOrchestrator = new ExploreOrchestrator({
|
|
1002
|
+
cwd: this.options.cwd,
|
|
1003
|
+
bindings: this.bindings,
|
|
1004
|
+
loadSafeExploreCustomTools: () => this.loadExploreCustomTools(),
|
|
1005
|
+
// Fallback when the parent session's model is unknown at Agent-call
|
|
1006
|
+
// time (e.g. turn started before materialization finished): resolve
|
|
1007
|
+
// the default Chat model from the child services' modelRuntime.
|
|
1008
|
+
resolveModel: async (modelRuntime) => {
|
|
1009
|
+
const available = this.bindings.listAvailableModels({ modelRuntime });
|
|
1010
|
+
const descriptor = await resolveDefaultChatModel(this.options.cwd, available);
|
|
1011
|
+
if (!descriptor)
|
|
1012
|
+
return undefined;
|
|
1013
|
+
return this.bindings.resolveModel({
|
|
1014
|
+
modelRuntime,
|
|
1015
|
+
provider: descriptor.provider,
|
|
1016
|
+
modelId: descriptor.modelId,
|
|
1017
|
+
});
|
|
1018
|
+
},
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
1021
|
+
async syncAimaxAuthToken() {
|
|
1022
|
+
await this.options.sddDataAlignment?.auth?.getToken();
|
|
1035
1023
|
}
|
|
1036
1024
|
/** Absolute path for repo-scoped resource preferences (may be undefined in unit tests). */
|
|
1037
1025
|
get resourcePreferencesPath() {
|
|
@@ -1061,10 +1049,20 @@ export class ConsolePiRuntime {
|
|
|
1061
1049
|
* after a PATCH sees the latest resource-preferences.json (not create-time
|
|
1062
1050
|
* closure state).
|
|
1063
1051
|
*/
|
|
1052
|
+
sessionModeOf(sessionId) {
|
|
1053
|
+
if (!sessionId)
|
|
1054
|
+
return DEFAULT_CONSOLE_CHAT_SESSION_MODE;
|
|
1055
|
+
return this.sessionModes.get(sessionId) ?? DEFAULT_CONSOLE_CHAT_SESSION_MODE;
|
|
1056
|
+
}
|
|
1057
|
+
rememberSessionMode(sessionId, sessionMode = DEFAULT_CONSOLE_CHAT_SESSION_MODE) {
|
|
1058
|
+
this.sessionModes.set(sessionId, sessionMode);
|
|
1059
|
+
return sessionMode;
|
|
1060
|
+
}
|
|
1064
1061
|
async buildResourceLoaderOptions(base = {}, sessionId) {
|
|
1065
1062
|
const inheritedFactories = Array.isArray(base.extensionFactories)
|
|
1066
1063
|
? base.extensionFactories
|
|
1067
1064
|
: [];
|
|
1065
|
+
const sessionMode = this.sessionModeOf(sessionId);
|
|
1068
1066
|
const todoContextExtension = sessionId && this.options.todoRegistry
|
|
1069
1067
|
? createTodoCompactionContextExtension({
|
|
1070
1068
|
sessionId,
|
|
@@ -1074,7 +1072,9 @@ export class ConsolePiRuntime {
|
|
|
1074
1072
|
const pressureExtension = sessionId
|
|
1075
1073
|
? this.createContextPressureInlineExtension(sessionId)
|
|
1076
1074
|
: undefined;
|
|
1077
|
-
const goalContextExtension = sessionId &&
|
|
1075
|
+
const goalContextExtension = sessionId &&
|
|
1076
|
+
this.options.goalRegistry &&
|
|
1077
|
+
shouldInjectGoalContinuation(sessionMode)
|
|
1078
1078
|
? createGoalCompactionContextExtension({
|
|
1079
1079
|
sessionId,
|
|
1080
1080
|
registry: this.options.goalRegistry,
|
|
@@ -1320,8 +1320,10 @@ export class ConsolePiRuntime {
|
|
|
1320
1320
|
* `initializing: true`; dependent routes wait on the same promise.
|
|
1321
1321
|
*/
|
|
1322
1322
|
async createSession(init) {
|
|
1323
|
+
await this.syncAimaxAuthToken();
|
|
1323
1324
|
const sessionId = `operator-chat-${randomBytes(12).toString("hex")}`;
|
|
1324
1325
|
this.disposedSessions.delete(sessionId);
|
|
1326
|
+
const sessionMode = this.rememberSessionMode(sessionId, init?.sessionMode ?? DEFAULT_CONSOLE_CHAT_SESSION_MODE);
|
|
1325
1327
|
const sessionManager = await this.bindings.createSessionManager({
|
|
1326
1328
|
cwd: this.options.cwd,
|
|
1327
1329
|
sessionDir: this.options.sessionDir,
|
|
@@ -1347,6 +1349,7 @@ export class ConsolePiRuntime {
|
|
|
1347
1349
|
sessionManager,
|
|
1348
1350
|
model: init?.model,
|
|
1349
1351
|
systemPromptSuffix: init?.systemPromptSuffix,
|
|
1352
|
+
sessionMode,
|
|
1350
1353
|
// Create path must resolve default model from the SAME services object
|
|
1351
1354
|
// used for formal materialization (no throwaway createServices).
|
|
1352
1355
|
resolveDefaultModel: !init?.model,
|
|
@@ -1356,7 +1359,8 @@ export class ConsolePiRuntime {
|
|
|
1356
1359
|
sessionFile,
|
|
1357
1360
|
createdAt: new Date().toISOString(),
|
|
1358
1361
|
model: init?.model,
|
|
1359
|
-
activeTools:
|
|
1362
|
+
activeTools: chatActiveToolBaseline(sessionMode),
|
|
1363
|
+
sessionMode,
|
|
1360
1364
|
initializing: true,
|
|
1361
1365
|
};
|
|
1362
1366
|
}
|
|
@@ -1417,14 +1421,17 @@ export class ConsolePiRuntime {
|
|
|
1417
1421
|
async materializeSession(sessionId, init) {
|
|
1418
1422
|
if (this.disposedSessions.has(sessionId))
|
|
1419
1423
|
return;
|
|
1424
|
+
await this.syncAimaxAuthToken();
|
|
1425
|
+
const sessionMode = this.rememberSessionMode(sessionId, init.sessionMode ?? this.sessionModeOf(sessionId));
|
|
1420
1426
|
const agentDir = await safeGetAgentDir(this.bindings);
|
|
1421
1427
|
// Capture before services parse models.json. A concurrent edit can therefore
|
|
1422
1428
|
// cause at most one harmless extra refresh, never a missed next-turn refresh.
|
|
1423
1429
|
const modelConfigFile = await captureModelConfigFile(agentDir);
|
|
1424
|
-
const appendSystemPrompt =
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1430
|
+
const appendSystemPrompt = composeChatSystemPromptParts({
|
|
1431
|
+
sessionMode,
|
|
1432
|
+
workflowPrompt: OPERATOR_CHAT_SYSTEM_PROMPT_BASE,
|
|
1433
|
+
systemPromptSuffix: init.systemPromptSuffix,
|
|
1434
|
+
});
|
|
1428
1435
|
// Single services construction for formal materialization (+ optional
|
|
1429
1436
|
// default-model resolve from the same modelRuntime). Repo-scoped skill
|
|
1430
1437
|
// auto-invocation prefs inject skillsOverride without touching SKILL.md.
|
|
@@ -1475,7 +1482,7 @@ export class ConsolePiRuntime {
|
|
|
1475
1482
|
return;
|
|
1476
1483
|
}
|
|
1477
1484
|
await bindSessionExtensions(session);
|
|
1478
|
-
pinOperatorChatTools(session);
|
|
1485
|
+
pinOperatorChatTools(session, sessionMode);
|
|
1479
1486
|
// Register then re-check dispose race: a concurrent dispose must win.
|
|
1480
1487
|
this.sessions.set(sessionId, session);
|
|
1481
1488
|
this.sessionManagers.set(sessionId, init.sessionManager);
|
|
@@ -1503,6 +1510,7 @@ export class ConsolePiRuntime {
|
|
|
1503
1510
|
this.modelRuntimes.delete(sessionId);
|
|
1504
1511
|
this.modelConfigFiles.delete(sessionId);
|
|
1505
1512
|
this.sessionModels.delete(sessionId);
|
|
1513
|
+
this.sessionModes.delete(sessionId);
|
|
1506
1514
|
this.serviceScopes.delete(sessionId);
|
|
1507
1515
|
this.revisions.delete(sessionId);
|
|
1508
1516
|
this.thinkingSelections.delete(sessionId);
|
|
@@ -1510,8 +1518,12 @@ export class ConsolePiRuntime {
|
|
|
1510
1518
|
}
|
|
1511
1519
|
/** Cached session-less custom tool definitions (operator + explore). */
|
|
1512
1520
|
async loadCustomTools(sessionId) {
|
|
1521
|
+
const sessionMode = this.sessionModeOf(sessionId);
|
|
1522
|
+
const loadWorkflowTools = shouldLoadWorkflowBusinessTools(sessionMode);
|
|
1513
1523
|
const [operatorCustomTools, exploreCustomTools] = await Promise.all([
|
|
1514
|
-
|
|
1524
|
+
loadWorkflowTools
|
|
1525
|
+
? this.loadOperatorCustomTools(sessionMode)
|
|
1526
|
+
: Promise.resolve([]),
|
|
1515
1527
|
this.loadExploreCustomTools(),
|
|
1516
1528
|
]);
|
|
1517
1529
|
const questionTool = this.options.questionRegistry
|
|
@@ -1521,33 +1533,77 @@ export class ConsolePiRuntime {
|
|
|
1521
1533
|
})
|
|
1522
1534
|
: undefined;
|
|
1523
1535
|
const todoTool = this.options.todoRegistry
|
|
1524
|
-
? await buildTodoWriteTool({
|
|
1536
|
+
? await buildTodoWriteTool({
|
|
1537
|
+
sessionId,
|
|
1538
|
+
registry: this.options.todoRegistry,
|
|
1539
|
+
sessionMode,
|
|
1540
|
+
})
|
|
1525
1541
|
: undefined;
|
|
1526
|
-
const goalTools = this.options.goalRegistry
|
|
1542
|
+
const goalTools = loadWorkflowTools && this.options.goalRegistry
|
|
1527
1543
|
? await buildGoalTools({ sessionId, registry: this.options.goalRegistry })
|
|
1528
1544
|
: [];
|
|
1545
|
+
const terminalTools = this.options.terminalRegistry
|
|
1546
|
+
? await buildPersistentTerminalTools({
|
|
1547
|
+
ownerSessionId: sessionId,
|
|
1548
|
+
registry: this.options.terminalRegistry,
|
|
1549
|
+
defaultCwd: this.options.cwd,
|
|
1550
|
+
}).catch((error) => {
|
|
1551
|
+
process.stderr.write(`[console] chat terminal-tools build failed: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
1552
|
+
return [];
|
|
1553
|
+
})
|
|
1554
|
+
: [];
|
|
1555
|
+
const scmTools = this.options.scmService
|
|
1556
|
+
? await buildScmTools({ scm: this.options.scmService }).catch((error) => {
|
|
1557
|
+
process.stderr.write(`[console] chat scm-tools build failed: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
1558
|
+
return [];
|
|
1559
|
+
})
|
|
1560
|
+
: [];
|
|
1561
|
+
const agentTool = await buildAgentCustomTool({
|
|
1562
|
+
parentSessionId: sessionId,
|
|
1563
|
+
orchestrator: this.exploreOrchestrator,
|
|
1564
|
+
resolveModel: () => {
|
|
1565
|
+
const model = this.sessionModels.get(sessionId);
|
|
1566
|
+
const modelRuntime = this.modelRuntimes.get(sessionId);
|
|
1567
|
+
if (!model || !modelRuntime)
|
|
1568
|
+
return undefined;
|
|
1569
|
+
return this.bindings.resolveModel({
|
|
1570
|
+
modelRuntime,
|
|
1571
|
+
provider: model.provider,
|
|
1572
|
+
modelId: model.modelId,
|
|
1573
|
+
});
|
|
1574
|
+
},
|
|
1575
|
+
}).catch((error) => {
|
|
1576
|
+
process.stderr.write(`[console] chat Agent tool build failed: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
1577
|
+
return undefined;
|
|
1578
|
+
});
|
|
1529
1579
|
return [
|
|
1530
1580
|
...operatorCustomTools,
|
|
1531
1581
|
...exploreCustomTools,
|
|
1532
1582
|
...(questionTool ? [questionTool] : []),
|
|
1533
1583
|
...(todoTool ? [todoTool] : []),
|
|
1534
1584
|
...goalTools,
|
|
1585
|
+
...terminalTools,
|
|
1586
|
+
...scmTools,
|
|
1587
|
+
...(agentTool ? [agentTool] : []),
|
|
1535
1588
|
];
|
|
1536
1589
|
}
|
|
1537
|
-
loadOperatorCustomTools() {
|
|
1590
|
+
loadOperatorCustomTools(sessionMode) {
|
|
1538
1591
|
if (!this.options.actionContext)
|
|
1539
1592
|
return Promise.resolve([]);
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1593
|
+
const cached = this.operatorCustomToolsByMode.get(sessionMode);
|
|
1594
|
+
if (cached)
|
|
1595
|
+
return cached;
|
|
1596
|
+
const promise = buildCustomOperatorTools({
|
|
1597
|
+
actionContext: this.options.actionContext,
|
|
1598
|
+
sessionMode,
|
|
1599
|
+
}).catch((error) => {
|
|
1600
|
+
process.stderr.write(`[console] chat custom-tools build failed: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
1601
|
+
// Allow a later create/reopen to retry after a transient failure.
|
|
1602
|
+
this.operatorCustomToolsByMode.delete(sessionMode);
|
|
1603
|
+
return [];
|
|
1604
|
+
});
|
|
1605
|
+
this.operatorCustomToolsByMode.set(sessionMode, promise);
|
|
1606
|
+
return promise;
|
|
1551
1607
|
}
|
|
1552
1608
|
loadExploreCustomTools() {
|
|
1553
1609
|
if (!this.exploreCustomToolsPromise) {
|
|
@@ -1565,6 +1621,7 @@ export class ConsolePiRuntime {
|
|
|
1565
1621
|
if (!this.bindings.forkSessionManager)
|
|
1566
1622
|
throw new Error("SESSION_FORK_UNSUPPORTED");
|
|
1567
1623
|
const sessionId = `operator-chat-${randomBytes(12).toString("hex")}`;
|
|
1624
|
+
const sessionMode = this.rememberSessionMode(sessionId, init.sessionMode ?? DEFAULT_CONSOLE_CHAT_SESSION_MODE);
|
|
1568
1625
|
const sessionManager = await this.bindings.forkSessionManager({
|
|
1569
1626
|
sourcePath: init.sourceSessionFile,
|
|
1570
1627
|
targetCwd: this.options.cwd,
|
|
@@ -1575,8 +1632,8 @@ export class ConsolePiRuntime {
|
|
|
1575
1632
|
sessionId,
|
|
1576
1633
|
sessionManager,
|
|
1577
1634
|
model: init.model,
|
|
1635
|
+
sessionMode,
|
|
1578
1636
|
});
|
|
1579
|
-
built.session.setActiveToolsByName(computeOperatorChatActiveToolNames(built.session));
|
|
1580
1637
|
this.sessions.set(sessionId, built.session);
|
|
1581
1638
|
this.sessionManagers.set(sessionId, sessionManager);
|
|
1582
1639
|
this.modelRuntimes.set(sessionId, built.modelRuntime);
|
|
@@ -1592,6 +1649,7 @@ export class ConsolePiRuntime {
|
|
|
1592
1649
|
createdAt: new Date().toISOString(),
|
|
1593
1650
|
model: init.model,
|
|
1594
1651
|
activeTools: built.session.getActiveToolNames(),
|
|
1652
|
+
sessionMode,
|
|
1595
1653
|
};
|
|
1596
1654
|
}
|
|
1597
1655
|
async branchSession(input) {
|
|
@@ -1770,15 +1828,22 @@ export class ConsolePiRuntime {
|
|
|
1770
1828
|
async getRuntimeSystemPrompt(sessionId) {
|
|
1771
1829
|
await this.ensureSessionReady(sessionId).catch(() => undefined);
|
|
1772
1830
|
const session = this.sessions.get(sessionId);
|
|
1773
|
-
if (!session)
|
|
1774
|
-
return
|
|
1831
|
+
if (!session) {
|
|
1832
|
+
return composeChatSystemPrompt({
|
|
1833
|
+
sessionMode: this.sessionModeOf(sessionId),
|
|
1834
|
+
workflowPrompt: OPERATOR_CHAT_SYSTEM_PROMPT_BASE,
|
|
1835
|
+
});
|
|
1836
|
+
}
|
|
1775
1837
|
const fromState = session.state?.systemPrompt;
|
|
1776
1838
|
const fromGetter = session.systemPrompt;
|
|
1777
1839
|
const loader = this.serviceScopes.get(sessionId)?.resourceLoader;
|
|
1778
1840
|
return (fromState ||
|
|
1779
1841
|
fromGetter ||
|
|
1780
1842
|
loader?.getSystemPrompt?.() ||
|
|
1781
|
-
|
|
1843
|
+
composeChatSystemPrompt({
|
|
1844
|
+
sessionMode: this.sessionModeOf(sessionId),
|
|
1845
|
+
workflowPrompt: OPERATOR_CHAT_SYSTEM_PROMPT_BASE,
|
|
1846
|
+
}));
|
|
1782
1847
|
}
|
|
1783
1848
|
/**
|
|
1784
1849
|
* Read the RAW system prompt for the snapshot, converting any projection
|
|
@@ -1871,6 +1936,7 @@ export class ConsolePiRuntime {
|
|
|
1871
1936
|
if (services)
|
|
1872
1937
|
this.applySessionCompactionOverride(sessionId, services, session);
|
|
1873
1938
|
await this.refreshModelConfiguration(sessionId, "force");
|
|
1939
|
+
pinOperatorChatTools(session, this.sessionModeOf(sessionId));
|
|
1874
1940
|
}
|
|
1875
1941
|
catch (error) {
|
|
1876
1942
|
return {
|
|
@@ -2307,7 +2373,9 @@ export class ConsolePiRuntime {
|
|
|
2307
2373
|
* than silently creating a fresh empty session and losing prior context.
|
|
2308
2374
|
*/
|
|
2309
2375
|
async reopenSession(init) {
|
|
2376
|
+
await this.syncAimaxAuthToken();
|
|
2310
2377
|
const sessionId = init.sessionId;
|
|
2378
|
+
const sessionMode = this.rememberSessionMode(sessionId, init.sessionMode ?? this.sessionModeOf(sessionId));
|
|
2311
2379
|
// Wait for in-flight create materialization rather than racing reopen.
|
|
2312
2380
|
const initState = this.sessionInit.get(sessionId);
|
|
2313
2381
|
if (initState?.status === "initializing") {
|
|
@@ -2384,6 +2452,7 @@ export class ConsolePiRuntime {
|
|
|
2384
2452
|
sessionManager,
|
|
2385
2453
|
model: init.model,
|
|
2386
2454
|
systemPromptSuffix: init.systemPromptSuffix,
|
|
2455
|
+
sessionMode,
|
|
2387
2456
|
});
|
|
2388
2457
|
const session = built.session;
|
|
2389
2458
|
// Prefer the SessionManager id (from the JSONL header). Some SDK
|
|
@@ -2406,7 +2475,6 @@ export class ConsolePiRuntime {
|
|
|
2406
2475
|
message: `reopened Pi sessionId mismatch: expected ${sessionId}, got ${reportedId}`,
|
|
2407
2476
|
};
|
|
2408
2477
|
}
|
|
2409
|
-
session.setActiveToolsByName(computeOperatorChatActiveToolNames(session));
|
|
2410
2478
|
this.sessions.set(sessionId, session);
|
|
2411
2479
|
this.sessionManagers.set(sessionId, sessionManager);
|
|
2412
2480
|
this.modelRuntimes.set(sessionId, built.modelRuntime);
|
|
@@ -2424,6 +2492,7 @@ export class ConsolePiRuntime {
|
|
|
2424
2492
|
createdAt: new Date().toISOString(),
|
|
2425
2493
|
model: init.model,
|
|
2426
2494
|
activeTools: session.getActiveToolNames(),
|
|
2495
|
+
sessionMode,
|
|
2427
2496
|
},
|
|
2428
2497
|
};
|
|
2429
2498
|
}
|
|
@@ -2455,6 +2524,7 @@ export class ConsolePiRuntime {
|
|
|
2455
2524
|
createdAt: new Date().toISOString(),
|
|
2456
2525
|
model,
|
|
2457
2526
|
activeTools: session.getActiveToolNames(),
|
|
2527
|
+
sessionMode: this.sessionModeOf(sessionId),
|
|
2458
2528
|
};
|
|
2459
2529
|
}
|
|
2460
2530
|
/**
|
|
@@ -2463,12 +2533,14 @@ export class ConsolePiRuntime {
|
|
|
2463
2533
|
* before AgentSession is ready. Tool definitions reuse runtime-level caches.
|
|
2464
2534
|
*/
|
|
2465
2535
|
async buildSessionWithServices(init) {
|
|
2536
|
+
const sessionMode = this.rememberSessionMode(init.sessionId, init.sessionMode ?? this.sessionModeOf(init.sessionId));
|
|
2466
2537
|
const agentDir = await safeGetAgentDir(this.bindings);
|
|
2467
2538
|
const modelConfigFile = await captureModelConfigFile(agentDir);
|
|
2468
|
-
const appendSystemPrompt =
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2539
|
+
const appendSystemPrompt = composeChatSystemPromptParts({
|
|
2540
|
+
sessionMode,
|
|
2541
|
+
workflowPrompt: OPERATOR_CHAT_SYSTEM_PROMPT_BASE,
|
|
2542
|
+
systemPromptSuffix: init.systemPromptSuffix,
|
|
2543
|
+
});
|
|
2472
2544
|
await this.refreshSkillPrefsCache().catch(() => undefined);
|
|
2473
2545
|
const { services } = await this.bindings.createServices({
|
|
2474
2546
|
cwd: this.options.cwd,
|
|
@@ -2493,7 +2565,7 @@ export class ConsolePiRuntime {
|
|
|
2493
2565
|
...(resolvedModel ? { model: resolvedModel } : {}),
|
|
2494
2566
|
});
|
|
2495
2567
|
await bindSessionExtensions(session);
|
|
2496
|
-
pinOperatorChatTools(session);
|
|
2568
|
+
pinOperatorChatTools(session, sessionMode);
|
|
2497
2569
|
this.applySessionCompactionOverride(init.sessionId, services, session);
|
|
2498
2570
|
return {
|
|
2499
2571
|
session,
|
|
@@ -2562,7 +2634,7 @@ export class ConsolePiRuntime {
|
|
|
2562
2634
|
}
|
|
2563
2635
|
/**
|
|
2564
2636
|
* Send a prompt and stream events. Gate 3: each tool invocation is
|
|
2565
|
-
* re-authorized by
|
|
2637
|
+
* re-authorized by authorizeChatSessionTool(mode) before the dispatcher runs it
|
|
2566
2638
|
* (the dispatcher is wired by the HTTP layer, see chat-session.ts).
|
|
2567
2639
|
*
|
|
2568
2640
|
* Prompt ownership is acquired synchronously before the first await so two
|
|
@@ -2595,6 +2667,7 @@ export class ConsolePiRuntime {
|
|
|
2595
2667
|
catch {
|
|
2596
2668
|
// ignore
|
|
2597
2669
|
}
|
|
2670
|
+
void this.exploreOrchestrator.abortByParent(sessionId);
|
|
2598
2671
|
};
|
|
2599
2672
|
try {
|
|
2600
2673
|
if (options?.turnId && this.options.questionRegistry) {
|
|
@@ -2603,7 +2676,8 @@ export class ConsolePiRuntime {
|
|
|
2603
2676
|
if (options?.turnId && this.options.todoRegistry) {
|
|
2604
2677
|
this.options.todoRegistry.startTurn(sessionId, options.turnId);
|
|
2605
2678
|
}
|
|
2606
|
-
if (this.options.goalRegistry
|
|
2679
|
+
if (this.options.goalRegistry &&
|
|
2680
|
+
shouldInjectGoalContinuation(this.sessionModeOf(sessionId))) {
|
|
2607
2681
|
this.options.goalRegistry.startTurn(sessionId, text);
|
|
2608
2682
|
}
|
|
2609
2683
|
// AC-FIX-002: if Stop already fired before readiness, never start model work.
|
|
@@ -2624,10 +2698,11 @@ export class ConsolePiRuntime {
|
|
|
2624
2698
|
// existing closed interview allow/deny registry. The next ordinary turn
|
|
2625
2699
|
// explicitly restores the normal Operator Chat set (baseline + extension
|
|
2626
2700
|
// tools, ADR 0012).
|
|
2627
|
-
const
|
|
2628
|
-
const
|
|
2701
|
+
const sessionMode = this.sessionModeOf(sessionId);
|
|
2702
|
+
const requestedTools = chatActiveToolBaseline(sessionMode);
|
|
2703
|
+
const activeTools = options?.mode === "requirement-interview" && sessionMode === "workflow"
|
|
2629
2704
|
? filterActiveInterviewTools(requestedTools).allowed
|
|
2630
|
-
:
|
|
2705
|
+
: computeChatActiveToolNames(session, sessionMode);
|
|
2631
2706
|
session.setActiveToolsByName(activeTools);
|
|
2632
2707
|
// Final pre-prompt fence: abort after tool pin must still skip session.prompt.
|
|
2633
2708
|
if (options?.signal?.aborted) {
|
|
@@ -2965,15 +3040,18 @@ export class ConsolePiRuntime {
|
|
|
2965
3040
|
this.modelRuntimes.delete(sessionId);
|
|
2966
3041
|
this.modelConfigFiles.delete(sessionId);
|
|
2967
3042
|
this.sessionModels.delete(sessionId);
|
|
3043
|
+
this.sessionModes.delete(sessionId);
|
|
2968
3044
|
this.serviceScopes.delete(sessionId);
|
|
2969
3045
|
this.revisions.delete(sessionId);
|
|
2970
3046
|
this.thinkingSelections.delete(sessionId);
|
|
2971
3047
|
this.reloadInFlight.delete(sessionId);
|
|
2972
3048
|
this.pendingSteering.delete(sessionId);
|
|
3049
|
+
void this.exploreOrchestrator.abortByParent(sessionId);
|
|
2973
3050
|
}
|
|
2974
3051
|
disposeAll() {
|
|
2975
3052
|
for (const id of [...this.sessions.keys()])
|
|
2976
3053
|
this.dispose(id);
|
|
3054
|
+
void this.exploreOrchestrator.abortAll();
|
|
2977
3055
|
}
|
|
2978
3056
|
}
|
|
2979
3057
|
function mapAssistantMessageEvent(type, sessionId, message) {
|
|
@@ -3278,7 +3356,8 @@ export function createDefaultPiSdkBindings() {
|
|
|
3278
3356
|
};
|
|
3279
3357
|
}
|
|
3280
3358
|
/**
|
|
3281
|
-
* Re-export the tool
|
|
3282
|
-
* (Gate 3) lives in exactly one place.
|
|
3359
|
+
* Re-export the tool gates for the dispatcher layer so the per-tool-call gate
|
|
3360
|
+
* (Gate 3) lives in exactly one place. authorizeChatSessionTool is the
|
|
3361
|
+
* mode-aware gate; the legacy name stays for workflow-only callers.
|
|
3283
3362
|
*/
|
|
3284
|
-
export { authorizeOperatorChatTool, assertNoWriteToolInList, OPERATOR_CHAT_ALLOWED_TOOLS, };
|
|
3363
|
+
export { authorizeChatSessionTool, authorizeOperatorChatTool, assertNoWriteToolInList, OPERATOR_CHAT_ALLOWED_TOOLS, };
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* The three-gate authorization (authorizeOperatorChatTool) is the actual
|
|
16
16
|
* enforcement; this adapter describes what that gate admits.
|
|
17
17
|
*/
|
|
18
|
-
import { OPERATOR_CHAT_ALLOWED_TOOLS, OPERATOR_CHAT_DENIED_TOOLS, OPERATOR_CHAT_DENIED_OPERATOR_ACTIONS, OPERATOR_CHAT_PI_BUILTIN_TOOLS, authorizeOperatorChatTool, filterOperatorChatTools, assertNoWriteToolInList, } from "./tools.js";
|
|
18
|
+
import { OPERATOR_CHAT_ALLOWED_TOOLS, OPERATOR_CHAT_DENIED_TOOLS, OPERATOR_CHAT_DENIED_OPERATOR_ACTIONS, OPERATOR_CHAT_PI_BUILTIN_TOOLS, OPERATOR_CHAT_BUILTIN_CUSTOM_TOOLS, authorizeOperatorChatTool, filterOperatorChatTools, assertNoWriteToolInList, } from "./tools.js";
|
|
19
19
|
/** Built-in Pi tool names allowed in every Chat session (ADR 0011). */
|
|
20
20
|
export const OPERATOR_CHAT_BUILTIN_EXPLORE_TOOL_IDS = Object.freeze([
|
|
21
21
|
...OPERATOR_CHAT_PI_BUILTIN_TOOLS,
|
|
@@ -42,6 +42,9 @@ export function createOperatorChatResourceLoader() {
|
|
|
42
42
|
if (explore) {
|
|
43
43
|
return { ok: true, toolId };
|
|
44
44
|
}
|
|
45
|
+
if (OPERATOR_CHAT_BUILTIN_CUSTOM_TOOLS.includes(toolId)) {
|
|
46
|
+
return { ok: true, toolId };
|
|
47
|
+
}
|
|
45
48
|
const decision = authorizeOperatorChatTool(toolId);
|
|
46
49
|
if (decision.ok)
|
|
47
50
|
active.add(decision.toolId);
|