@tea-agent/loop-agent 0.43.0-next.17 → 0.43.0-next.3
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 +9 -140
- package/dist/application/task-lifecycle/advance.js +4 -17
- package/dist/application/task-lifecycle/observe.js +29 -43
- package/dist/application/task-lifecycle/plan-transitions.js +4 -5
- package/dist/build-stamp.json +3 -3
- package/dist/commands/client-recovery.js +55 -20
- package/dist/commands/new-task.js +5 -0
- package/dist/commands/status.js +57 -0
- package/dist/commands/task-contract.js +269 -0
- package/dist/executors/dag-pi-executor.js +230 -269
- package/dist/executors/pi-executor.js +0 -2
- package/dist/executors/pi-sdk-executor.js +39 -77
- package/dist/executors/shell-executor.js +2 -3
- package/dist/executors/shell-write-guard.js +32 -27
- package/dist/shared/pi-context-pressure/extension.js +16 -26
- package/dist/shared/pi-retry-settings.js +0 -40
- package/dist/shared/prompts.js +26 -0
- package/dist/task/config.js +2 -0
- package/dist/task/contract/validate-draft.js +106 -0
- package/dist/task/goal.js +3 -0
- package/dist/task/index.js +12 -0
- package/dist/task/lifecycle.js +1 -0
- package/dist/task/operator/capabilities.js +6 -0
- package/dist/task/operator/envelope.js +2 -0
- package/dist/task/operator/index.js +5 -0
- package/dist/task/operator/registry.js +2 -0
- package/dist/task/operator/types.js +1 -0
- package/dist/task/paths.js +1 -0
- package/dist/task/source-prepare/source-fidelity-pi.js +2 -2
- package/dist/task/source-references.js +23 -48
- package/dist/task/source-state.js +1 -0
- package/dist/task/subagent-guidance.js +1 -0
- package/dist/worker/console/chat/assistant-content.js +2 -23
- package/dist/worker/console/chat/explore-tools.js +0 -13
- package/dist/worker/console/chat/pi-runtime.js +1182 -221
- package/dist/worker/console/chat/routes.js +71 -213
- package/dist/worker/console/chat/sdd-data-alignment.js +9 -65
- package/dist/worker/console/chat/session-catalog.js +0 -32
- package/dist/worker/console/chat/session-store.js +6 -22
- package/dist/worker/console/chat/shortcuts.js +0 -6
- package/dist/worker/console/chat/sift-bridge.js +1 -0
- package/dist/worker/console/chat/tool-preview.js +0 -11
- package/dist/worker/console/chat/tools.js +0 -6
- package/dist/worker/console/console-update-and-init.js +19 -1
- package/dist/worker/console/console-update-runtime.js +20 -5
- package/dist/worker/console/index.js +20 -0
- package/dist/worker/console/operator-actions.js +1 -13
- package/dist/worker/console/routes.js +0 -8
- package/dist/worker/console/server.js +29 -11
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-C4NXyedy.js → abnfDiagram-N423BO3Z-hUmM_GRf.js} +1 -1
- package/dist/worker/console/static/assets/{arc-NZ3qXvBI.js → arc-Bt-xuieW.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-COZSRvml.js → architectureDiagram-T3A2C74G-DTqkL4DJ.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-Ck0Gxi9C.js → blockDiagram-VBNYF7ZC-Cy0MNnzV.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-BX5HQ4Ox.js → c4Diagram-5PPSVZJV-DDdlT0Pd.js} +1 -1
- package/dist/worker/console/static/assets/channel-BpzRnZmU.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-CoviemSL.js → chunk-2GRJ4B5K-3JawwNZ6.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-DbOdOkbZ.js → chunk-2Q5K7J3B-DoTp7Cri.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BsG2pmdQ.js → chunk-5RXB4S5H-CcirhZaS.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-DGdvrNm8.js → chunk-5VM5RSS4-VrG21gnP.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-BAy7Yd6y.js → chunk-6Q2QTUOP-DDOgIS70.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-D9UA7hUb.js → chunk-GF5L2VYU-CBjmgvJ_.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-DPz7SZ8V.js → chunk-JWPE2WC7-CCQSht8M.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BmuEOIh7.js → chunk-KBJHAD2P-BpGMkUUV.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-CIhBWnd8.js → chunk-RYQCIY6F-DNDT41QL.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CScR6mDD.js → chunk-XXDRQBXY-euXnDFbn.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BhlMVqCc.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BhlMVqCc.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-BjpfWaUr.js → cose-bilkent-JH36ORCC-BJ6NAeql.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BFQohJgT.js → cynefin-VYW2F7L2-F5JKIvIq.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-D3gzRJnS.js → cynefinDiagram-MW4NZA55-Cwmkl_Gi.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-5eojkhoA.js → dagre-VZM6K2ZE-BmCZ8815.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-CpD8LWu_.js → diagram-7IWD3JNH-zWA3hUnX.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-B8_4qJ2a.js → diagram-B4RE2ZJO-BzA-888F.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-HOsXf0eu.js → diagram-LBJQPF4R-tPNheoch.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-BqwRwiWP.js → diagram-Q27KOJAE-Cdi7Fyqp.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-BRVCNZe1.js → diagram-UB23O5K3-DFK9VBf1.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-Cvb1TgGh.js → ebnfDiagram-BXEA7PRR-xCUr1kpg.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DS0O0qG9.js → erDiagram-JOGREHBK-BANQHY_A.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-BHIRvRr3.js → flowDiagram-UKHOOZJN-VHJYEMkP.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DcCJ1JWx.js → ganttDiagram-PKOTCBZU-DiyZQ0C6.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-B9ia5ony.js → gitGraphDiagram-DS77QQ5N-CZtIeBBa.js} +1 -1
- package/dist/worker/console/static/assets/index-BlN6ytLr.css +1 -0
- package/dist/worker/console/static/assets/index-CA-jfWlE.js +449 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-3ogpgegn.js → infoDiagram-6WML65LV-BuSspC0X.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-4tgpQ5SL.js → ishikawaDiagram-WSZJBQD7-DRJZyPFy.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DNfgHqFx.js → journeyDiagram-NVQOT4AX-DIfXIVuE.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-Dz7ngC8z.js → kanban-definition-27J2QSJJ-CT10_7Lt.js} +1 -1
- package/dist/worker/console/static/assets/{linear-DI7Jv62E.js → linear-ufemj74H.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-CQA4Nzmo.js → mermaid.core-DEQe8-_m.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-CtsMc8Mf.js → mindmap-definition-FAOFIHXS-BRLUrbrC.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-ByppE9yH.js → pegDiagram-VL7TDLO6-BgibKtiF.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-B5PtgFgt.js → pieDiagram-7S7Q4E2Y-D3eyfdV9.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-Cq4p0k2K.js → quadrantDiagram-CIZ2JOQS-DXeTk5Px.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-DjfkyljN.js → railroadDiagram-AXF67PYL-BgXdFEe7.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-DzynNRSl.js → requirementDiagram-LRYGKXZP-CseC2A7R.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-Cj7TCpTJ.js → sankeyDiagram-W5VNT64P-D80PFzfJ.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-C73C6ykA.js → sequenceDiagram-SI44F4Z6-BWzHW7LS.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-BiNLgN2x.js → sizeCapture-X5ZJPWSS-xWQYTLAn.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-UwvjS64-.js → stateDiagram-OKZ733FA-CLxtpZeL.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-CiVoq4G-.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-CC7DH98r.js → swimlanes-SLNWSIFB-DwugtmWV.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BkdgdpfR.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-LSBXTR70.js → timeline-definition-Z64GVDOM-DHEOwHIe.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-BAuxWwGP.js → vennDiagram-T6HMQDX7-pmbZKlBK.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y--E5_gjZx.js → wardleyDiagram-T6FBY63Y-CivHoM5q.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-dJWNmyzF.js → xychartDiagram-ELKLHX3M-BfHIE7o6.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +10 -122
- package/dist/worker/console/static-src/operator-chat/compaction-message.js +0 -7
- package/dist/worker/console/static-src/operator-chat/pending-user-message.js +15 -35
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +62 -136
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +68 -159
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +56 -75
- package/dist/worker/console/static-src/operator-chat/useComposer.js +78 -206
- package/dist/worker/console/workspace-context.js +1 -21
- package/dist/worker/observe/static/router.js +1 -1
- package/dist/worker/observe/static/styles.css +4 -7
- package/dist/worker/observe/static/views/dag-inspector.js +19 -12
- package/dist/worker/observe/static/views/dag.js +2 -2
- package/dist/worker/scheduler/index.js +25 -0
- package/dist/workflows/dag/facts.js +4 -0
- package/dist/workflows/dag/frontend-closeout.js +1 -1
- package/dist/workflows/dag/frontend-design-policy.js +1 -2
- package/dist/workflows/dag/frontend-implementation-contract.js +4 -8
- package/dist/workflows/dag/frontend-prewrite-gate.js +3 -3
- package/dist/workflows/dag/frontend-repair.js +76 -55
- package/dist/workflows/dag/frontend-review-context.js +1 -2
- package/dist/workflows/dag/frontend-review-scopes.js +12 -34
- package/dist/workflows/dag/frontend-shape-facts.js +2 -12
- package/dist/workflows/dag/frontend-verification-trace.js +42 -8
- package/dist/workflows/dag/index.js +6 -0
- package/dist/workflows/dag/init-hybrid.js +160 -97
- package/dist/workflows/dynamic/index.js +7 -0
- package/docs/architecture/runtime-boundaries.md +3 -3
- package/docs/templates/frontend-implementation-dag.json +8 -9
- package/package.json +3 -7
- package/skills/frontend-bounded-implement/SKILL.md +3 -4
- package/skills/frontend-bounded-implement/references/code-standards.md +3 -3
- package/skills/frontend-contract/references/contract-protocol.md +1 -3
- package/skills/frontend-design-review/SKILL.md +7 -12
- package/skills/frontend-design-review/references/review-checklist.md +7 -7
- package/skills/frontend-plan/SKILL.md +0 -19
- package/skills/frontend-plan/references/decision-contract.md +19 -26
- package/skills/frontend-review/SKILL.md +18 -12
- package/skills/frontend-review/references/review-findings.md +43 -24
- package/dist/shared/pi-provider-recovery.js +0 -182
- package/dist/worker/console/chat/browser-automation.js +0 -363
- package/dist/worker/console/chat/browser-policy.js +0 -113
- package/dist/worker/console/chat/browser-routes.js +0 -162
- package/dist/worker/console/chat/pi-runtime/custom-tools/ask-user-question.js +0 -44
- package/dist/worker/console/chat/pi-runtime/custom-tools/browser-tools.js +0 -89
- package/dist/worker/console/chat/pi-runtime/custom-tools/explore-tools.js +0 -202
- package/dist/worker/console/chat/pi-runtime/custom-tools/goal-tools.js +0 -79
- package/dist/worker/console/chat/pi-runtime/custom-tools/operator-tools.js +0 -86
- package/dist/worker/console/chat/pi-runtime/custom-tools/todo-write.js +0 -38
- package/dist/worker/console/chat/pi-runtime/inspection-types.js +0 -28
- package/dist/worker/console/chat/pi-runtime/inspection.js +0 -439
- package/dist/worker/console/chat/pi-runtime/sdk-bindings.js +0 -153
- package/dist/worker/console/chat/pi-runtime/sdk-session.js +0 -5
- package/dist/worker/console/chat/scm-routes.js +0 -217
- package/dist/worker/console/chat/scm-service.js +0 -283
- package/dist/worker/console/chat/scm-tools.js +0 -111
- package/dist/worker/console/chat/session-mode-view.js +0 -49
- package/dist/worker/console/chat/session-mode.js +0 -220
- package/dist/worker/console/chat/terminal-routes.js +0 -216
- package/dist/worker/console/chat/terminal-sessions.js +0 -348
- package/dist/worker/console/chat/terminal-tools.js +0 -211
- package/dist/worker/console/static/assets/channel-BxdTlb_5.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-_ByA1Nf8.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-_ByA1Nf8.js +0 -1
- package/dist/worker/console/static/assets/index-B9goN3S5.css +0 -1
- package/dist/worker/console/static/assets/index-wXlQohNs.js +0 -469
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-nLgMZ0D3.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BcYqTady.js +0 -8
- package/dist/worker/console/static-src/operator-chat/active-turn-tail.js +0 -10
- package/dist/worker/console/static-src/operator-chat/chat-link.js +0 -94
- package/dist/worker/console/static-src/operator-chat/chat-scroll-position.js +0 -24
- package/dist/worker/console/static-src/operator-chat/composer-session-ledger.js +0 -192
- package/dist/worker/console/static-src/operator-chat/process-label.js +0 -41
- package/dist/worker/console/static-src/operator-chat/turn-group-equality.js +0 -13
- package/dist/worker/console/static-src/operator-chat/turn-process-disclosure.js +0 -10
- package/dist/worker/console/static-src/operator-chat/use-searchable-hidden.js +0 -51
- package/dist/worker/console/static-src/operator-chat/user-turn-anchor-equality.js +0 -21
- package/dist/worker/console/workspace-initialization.js +0 -209
- package/dist/workflows/dag/frontend-capacity.js +0 -9
- package/dist/workflows/dag/frontend-plan-completeness.js +0 -186
- package/dist/workflows/dag/frontend-plan-recovery-policy.js +0 -18
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Console Chat session modes (workflow | pi).
|
|
3
|
-
*
|
|
4
|
-
* sessionMode is a durable session identity, independent of per-turn
|
|
5
|
-
* operator | requirement-interview and of UI layout mode. Record is the
|
|
6
|
-
* source of truth; runtime, catalog, list/detail and the browser cache
|
|
7
|
-
* all project this field.
|
|
8
|
-
*/
|
|
9
|
-
import { OPERATOR_CHAT_ALLOWED_TOOLS, OPERATOR_CHAT_BUILTIN_CUSTOM_TOOLS, OPERATOR_CHAT_PI_BUILTIN_TOOLS, authorizeOperatorChatTool, isOperatorChatToolDenied, } from "./tools.js";
|
|
10
|
-
import { OPERATOR_CHAT_AGENT_TOOL_NAME } from "./subagents/types.js";
|
|
11
|
-
import { CONSOLE_CHAT_SESSION_MODES, DEFAULT_CONSOLE_CHAT_SESSION_MODE, } from "./session-mode-view.js";
|
|
12
|
-
export { CONSOLE_CHAT_SESSION_MODES, DEFAULT_CONSOLE_CHAT_SESSION_MODE, SESSION_MODE_COPY, } from "./session-mode-view.js";
|
|
13
|
-
export const SESSION_MODE_INVALID_CODE = "INVALID_SESSION_MODE";
|
|
14
|
-
export const SESSION_MODE_UNKNOWN_CODE = "UNKNOWN_SESSION_MODE";
|
|
15
|
-
export const SESSION_MODE_ACTION_DENIED_CODE = "SESSION_MODE_ACTION_DENIED";
|
|
16
|
-
export const SESSION_MODE_IMMUTABLE_CODE = "SESSION_MODE_IMMUTABLE";
|
|
17
|
-
export class InvalidChatSessionModeError extends Error {
|
|
18
|
-
value;
|
|
19
|
-
code = SESSION_MODE_INVALID_CODE;
|
|
20
|
-
constructor(value) {
|
|
21
|
-
super(`sessionMode must be "workflow" or "pi"${value === undefined || value === null || value === ""
|
|
22
|
-
? ""
|
|
23
|
-
: `; got ${String(value)}`}`);
|
|
24
|
-
this.value = value;
|
|
25
|
-
this.name = "InvalidChatSessionModeError";
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
export class UnknownChatSessionModeError extends Error {
|
|
29
|
-
value;
|
|
30
|
-
code = SESSION_MODE_UNKNOWN_CODE;
|
|
31
|
-
constructor(value) {
|
|
32
|
-
super(`chat session record has unknown sessionMode ${JSON.stringify(value)}; refusing to run as workflow`);
|
|
33
|
-
this.value = value;
|
|
34
|
-
this.name = "UnknownChatSessionModeError";
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
const MODE_SET = new Set(CONSOLE_CHAT_SESSION_MODES);
|
|
38
|
-
function isSessionMode(value) {
|
|
39
|
-
return typeof value === "string" && MODE_SET.has(value);
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Create-path parser. Missing / null / "" → workflow. Explicit illegal
|
|
43
|
-
* values fail closed and must not silently degrade.
|
|
44
|
-
*/
|
|
45
|
-
export function parseCreateSessionMode(value) {
|
|
46
|
-
if (value === undefined || value === null || value === "") {
|
|
47
|
-
return DEFAULT_CONSOLE_CHAT_SESSION_MODE;
|
|
48
|
-
}
|
|
49
|
-
if (isSessionMode(value))
|
|
50
|
-
return value;
|
|
51
|
-
throw new InvalidChatSessionModeError(value);
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Restore-path parser. Missing field → workflow (stock-data rule, not a
|
|
55
|
-
* compatibility shim). Present but unknown → fail closed.
|
|
56
|
-
*/
|
|
57
|
-
export function readStoredSessionMode(value) {
|
|
58
|
-
if (value === undefined || value === null || value === "") {
|
|
59
|
-
return DEFAULT_CONSOLE_CHAT_SESSION_MODE;
|
|
60
|
-
}
|
|
61
|
-
if (isSessionMode(value))
|
|
62
|
-
return value;
|
|
63
|
-
throw new UnknownChatSessionModeError(value);
|
|
64
|
-
}
|
|
65
|
-
export function isWorkflowSessionMode(mode) {
|
|
66
|
-
return mode === "workflow";
|
|
67
|
-
}
|
|
68
|
-
export function isPiSessionMode(mode) {
|
|
69
|
-
return mode === "pi";
|
|
70
|
-
}
|
|
71
|
-
/** Shared Console foundations that both modes keep. Not a native-only prompt. */
|
|
72
|
-
export const PI_CHAT_SYSTEM_PROMPT_BASE = [
|
|
73
|
-
"You are Console Chat in Pi mode: a coding assistant with Pi tools plus Console shared foundations.",
|
|
74
|
-
"Use read/write/edit/bash/grep/find/ls to inspect and change the workspace. apply_patch, full-tools, shell and coding-chat are denied.",
|
|
75
|
-
"Agent (Explore) is a built-in read-only subagent for path-uncertain codebase search. Do not use it for a known single-file read. Prefer safe-read/safe-grep for secret-safe probes.",
|
|
76
|
-
"ask_user_question pauses for a real user answer. todo_write tracks the current work and is restored after compression; it is not a workflow auto-continue signal. The persistent terminal tool is available.",
|
|
77
|
-
"Sidebar browser tools (browser_navigate/search/inspect/act) drive the visible Browser panel for user-requested web research and static automation; they never edit workspace files or execute page scripts.",
|
|
78
|
-
"Goal tools (get_goal / create_goal / update_goal) track the session's durable cross-turn objective. Create a Goal only when the user explicitly asks to start one; iterate in bounded rounds until complete or blocked.",
|
|
79
|
-
"This session keeps Console compression (L0/L1/L2, sift, strict checkpoint) and existing Aimax / SDD access. Do not create tasks, run DAGs, or start requirement interviews from this session.",
|
|
80
|
-
"Obey repository AGENTS.md, skills and extensions when they apply. Choosing Pi mode is not extra write authorization and does not bypass Console access control or output scrubbing.",
|
|
81
|
-
].join("\n");
|
|
82
|
-
export const CHAT_SAFE_EXPLORE_TOOL_IDS = Object.freeze([
|
|
83
|
-
"safe-read",
|
|
84
|
-
"safe-grep",
|
|
85
|
-
"git-status",
|
|
86
|
-
"git-diff",
|
|
87
|
-
]);
|
|
88
|
-
export const PI_CHAT_GENERIC_HELPER_TOOLS = Object.freeze([
|
|
89
|
-
"ask_user_question",
|
|
90
|
-
"todo_write",
|
|
91
|
-
]);
|
|
92
|
-
/** Durable cross-turn Goal tools. Shared by both session modes since
|
|
93
|
-
* 2026-09-10 (exec-plan 2026-09-10-console-chat-goal-for-pi-mode); they are
|
|
94
|
-
* NOT workflow business tools and are registered whenever a GoalRegistry
|
|
95
|
-
* is present. */
|
|
96
|
-
export const GOAL_TOOL_IDS = Object.freeze([
|
|
97
|
-
"get_goal",
|
|
98
|
-
"create_goal",
|
|
99
|
-
"update_goal",
|
|
100
|
-
]);
|
|
101
|
-
const CHAT_EXTENSION_DENIED_TOOL_IDS = new Set([
|
|
102
|
-
"apply_patch",
|
|
103
|
-
"apply-patch",
|
|
104
|
-
"full-tools",
|
|
105
|
-
"full_tools",
|
|
106
|
-
"coding-chat",
|
|
107
|
-
"coding_chat",
|
|
108
|
-
"shell",
|
|
109
|
-
].map((name) => name.toLowerCase()));
|
|
110
|
-
const WORKFLOW_OPERATOR_TOOL_IDS = new Set(OPERATOR_CHAT_ALLOWED_TOOLS.map((name) => name.toLowerCase()));
|
|
111
|
-
export function workflowActiveToolBaseline() {
|
|
112
|
-
return [
|
|
113
|
-
...OPERATOR_CHAT_ALLOWED_TOOLS,
|
|
114
|
-
...OPERATOR_CHAT_PI_BUILTIN_TOOLS,
|
|
115
|
-
...CHAT_SAFE_EXPLORE_TOOL_IDS,
|
|
116
|
-
...OPERATOR_CHAT_BUILTIN_CUSTOM_TOOLS,
|
|
117
|
-
];
|
|
118
|
-
}
|
|
119
|
-
export function piActiveToolBaseline() {
|
|
120
|
-
return [
|
|
121
|
-
...OPERATOR_CHAT_PI_BUILTIN_TOOLS,
|
|
122
|
-
...CHAT_SAFE_EXPLORE_TOOL_IDS,
|
|
123
|
-
...OPERATOR_CHAT_BUILTIN_CUSTOM_TOOLS,
|
|
124
|
-
...PI_CHAT_GENERIC_HELPER_TOOLS,
|
|
125
|
-
...GOAL_TOOL_IDS,
|
|
126
|
-
];
|
|
127
|
-
}
|
|
128
|
-
export function chatActiveToolBaseline(sessionMode) {
|
|
129
|
-
return sessionMode === "pi"
|
|
130
|
-
? piActiveToolBaseline()
|
|
131
|
-
: workflowActiveToolBaseline();
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Gate 2 pin: mode baseline plus user/project extension tools. Pi mode must
|
|
135
|
-
* not re-add operator actions via the extras pass (Goal tools are shared and
|
|
136
|
-
* part of the Pi baseline since 2026-09-10).
|
|
137
|
-
*/
|
|
138
|
-
export function computeChatActiveToolNames(session, sessionMode) {
|
|
139
|
-
const baseline = chatActiveToolBaseline(sessionMode);
|
|
140
|
-
if (!session?.getAllTools)
|
|
141
|
-
return baseline;
|
|
142
|
-
const baselineLower = new Set(baseline.map((name) => name.toLowerCase()));
|
|
143
|
-
const extras = [];
|
|
144
|
-
for (const tool of session.getAllTools()) {
|
|
145
|
-
const name = tool?.name;
|
|
146
|
-
if (!name || typeof name !== "string")
|
|
147
|
-
continue;
|
|
148
|
-
const lower = name.toLowerCase();
|
|
149
|
-
if (baselineLower.has(lower))
|
|
150
|
-
continue;
|
|
151
|
-
if (CHAT_EXTENSION_DENIED_TOOL_IDS.has(lower))
|
|
152
|
-
continue;
|
|
153
|
-
if (sessionMode === "pi" && WORKFLOW_OPERATOR_TOOL_IDS.has(lower))
|
|
154
|
-
continue;
|
|
155
|
-
extras.push(name);
|
|
156
|
-
}
|
|
157
|
-
return extras.length > 0 ? [...baseline, ...extras] : baseline;
|
|
158
|
-
}
|
|
159
|
-
export function authorizeChatSessionTool(toolId, sessionMode) {
|
|
160
|
-
if (sessionMode === "workflow")
|
|
161
|
-
return authorizeOperatorChatTool(toolId);
|
|
162
|
-
const id = toolId.trim();
|
|
163
|
-
if (!id) {
|
|
164
|
-
return {
|
|
165
|
-
ok: false,
|
|
166
|
-
code: "tool-unknown",
|
|
167
|
-
toolId: id,
|
|
168
|
-
message: "empty tool id is not allowed in Pi mode",
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
if (isOperatorChatToolDenied(id)) {
|
|
172
|
-
return {
|
|
173
|
-
ok: false,
|
|
174
|
-
code: "tool-denied",
|
|
175
|
-
toolId: id,
|
|
176
|
-
message: `tool "${id}" is denied in Pi mode (no apply_patch/full-tools/shell/coding-chat)`,
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
const lower = id.toLowerCase();
|
|
180
|
-
if (WORKFLOW_OPERATOR_TOOL_IDS.has(lower)) {
|
|
181
|
-
return {
|
|
182
|
-
ok: false,
|
|
183
|
-
code: "tool-denied",
|
|
184
|
-
toolId: id,
|
|
185
|
-
message: `tool "${id}" is a workflow action and is not available in Pi mode`,
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
const authorized = new Set(piActiveToolBaseline().map((name) => name.toLowerCase()));
|
|
189
|
-
if (authorized.has(lower))
|
|
190
|
-
return { ok: true, toolId: id };
|
|
191
|
-
return {
|
|
192
|
-
ok: false,
|
|
193
|
-
code: "tool-unknown",
|
|
194
|
-
toolId: id,
|
|
195
|
-
message: `tool "${id}" is not registered for Pi mode`,
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
export function composeChatSystemPromptParts(input) {
|
|
199
|
-
const base = input.sessionMode === "pi"
|
|
200
|
-
? PI_CHAT_SYSTEM_PROMPT_BASE
|
|
201
|
-
: input.workflowPrompt;
|
|
202
|
-
const suffix = input.sessionMode === "workflow" ? input.systemPromptSuffix?.trim() : "";
|
|
203
|
-
return suffix ? [base, suffix] : [base];
|
|
204
|
-
}
|
|
205
|
-
export function composeChatSystemPrompt(input) {
|
|
206
|
-
return composeChatSystemPromptParts(input).join("\n\n");
|
|
207
|
-
}
|
|
208
|
-
export const PI_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 advances. Skip the list for simple Q&A, read-only lookups, and single-step tasks. Statuses: `pending` / `in_progress` / `completed`.";
|
|
209
|
-
// Slash gating lives in the browser-safe view module (shortcuts.ts is in the
|
|
210
|
-
// UI bundle); re-export here for Node-side consumers.
|
|
211
|
-
export { WORKFLOW_EXCLUSIVE_SLASH_ACTIONS, isWorkflowExclusiveSlashAction, } from "./session-mode-view.js";
|
|
212
|
-
export function shouldLoadWorkflowBusinessTools(sessionMode) {
|
|
213
|
-
return sessionMode === "workflow";
|
|
214
|
-
}
|
|
215
|
-
export function shouldAcceptOperatorSnapshot(sessionMode) {
|
|
216
|
-
return sessionMode === "workflow";
|
|
217
|
-
}
|
|
218
|
-
export const SESSION_MODE_ACTION_DENIED_MESSAGE = "this action is only available in workflow sessions";
|
|
219
|
-
/** Stable tool name used by tests and catalogs for the Explore subagent. */
|
|
220
|
-
export const PI_CHAT_AGENT_TOOL_NAME = OPERATOR_CHAT_AGENT_TOOL_NAME;
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Operator Chat — terminal management HTTP API (Console UI side).
|
|
3
|
-
*
|
|
4
|
-
* Endpoints (all under /api/operator/v1/chat):
|
|
5
|
-
* GET /terminals list terminal sessions (all owners)
|
|
6
|
-
* POST /terminals spawn { shell, name?, cwd?, ownerSessionId? }
|
|
7
|
-
* GET /terminals/:id session info + buffered output
|
|
8
|
-
* POST /terminals/:id/input { data } write to the PTY
|
|
9
|
-
* POST /terminals/:id/resize { cols, rows }
|
|
10
|
-
* POST /terminals/:id/interrupt send Ctrl+C
|
|
11
|
-
* POST /terminals/:id/kill stop and await full exit
|
|
12
|
-
* GET /terminals/:id/stream SSE: buffered replay + live chunks
|
|
13
|
-
*
|
|
14
|
-
* Mutating routes require the Console boot token (same gate as other chat
|
|
15
|
-
* mutations). The stream is read-only and uses the same origin checks as the
|
|
16
|
-
* chat event stream.
|
|
17
|
-
*/
|
|
18
|
-
import { TerminalSessionError, availableShellKinds, } from "./terminal-sessions.js";
|
|
19
|
-
function sendJson(res, status, body) {
|
|
20
|
-
const payload = JSON.stringify(body);
|
|
21
|
-
res.writeHead(status, {
|
|
22
|
-
"content-type": "application/json; charset=utf-8",
|
|
23
|
-
"cache-control": "no-store",
|
|
24
|
-
});
|
|
25
|
-
res.end(payload);
|
|
26
|
-
}
|
|
27
|
-
function mapTerminalError(res, error) {
|
|
28
|
-
if (error instanceof TerminalSessionError) {
|
|
29
|
-
const status = error.code === "TERMINAL_NOT_FOUND"
|
|
30
|
-
? 404
|
|
31
|
-
: error.code === "TERMINAL_EXITED" || error.code === "TERMINAL_SEND_ACTIVE"
|
|
32
|
-
? 409
|
|
33
|
-
: 500;
|
|
34
|
-
sendJson(res, status, {
|
|
35
|
-
ok: false,
|
|
36
|
-
error: { code: error.code, message: error.message },
|
|
37
|
-
});
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
sendJson(res, 500, {
|
|
41
|
-
ok: false,
|
|
42
|
-
error: {
|
|
43
|
-
code: "TERMINAL_INTERNAL",
|
|
44
|
-
message: error instanceof Error ? error.message : String(error),
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
async function readJsonBody(req, maxBytes = 512 * 1024) {
|
|
49
|
-
const chunks = [];
|
|
50
|
-
let total = 0;
|
|
51
|
-
for await (const chunk of req) {
|
|
52
|
-
const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
53
|
-
total += buf.length;
|
|
54
|
-
if (total > maxBytes)
|
|
55
|
-
throw new Error("request body too large");
|
|
56
|
-
chunks.push(buf);
|
|
57
|
-
}
|
|
58
|
-
if (chunks.length === 0)
|
|
59
|
-
return {};
|
|
60
|
-
const raw = Buffer.concat(chunks).toString("utf8");
|
|
61
|
-
if (!raw.trim())
|
|
62
|
-
return {};
|
|
63
|
-
return JSON.parse(raw);
|
|
64
|
-
}
|
|
65
|
-
/** Route dispatcher; returns true when the request was handled. */
|
|
66
|
-
export async function handleTerminalRequest(req, res, deps, pathname) {
|
|
67
|
-
if (!pathname.startsWith("/api/operator/v1/chat/terminals"))
|
|
68
|
-
return false;
|
|
69
|
-
const method = (req.method ?? "GET").toUpperCase();
|
|
70
|
-
const rest = pathname.slice("/api/operator/v1/chat/terminals".length);
|
|
71
|
-
const parts = rest.split("/").filter(Boolean);
|
|
72
|
-
try {
|
|
73
|
-
// GET /terminals — list (+ available shell kinds for this platform)
|
|
74
|
-
if (method === "GET" && parts.length === 0) {
|
|
75
|
-
sendJson(res, 200, {
|
|
76
|
-
ok: true,
|
|
77
|
-
data: {
|
|
78
|
-
terminals: deps.terminals.list(),
|
|
79
|
-
availableShells: availableShellKinds().kinds,
|
|
80
|
-
},
|
|
81
|
-
});
|
|
82
|
-
return true;
|
|
83
|
-
}
|
|
84
|
-
// POST /terminals — spawn
|
|
85
|
-
if (method === "POST" && parts.length === 0) {
|
|
86
|
-
const gate = deps.gateMutation(req);
|
|
87
|
-
if (!gate.ok) {
|
|
88
|
-
sendJson(res, gate.status, { ok: false, error: { code: gate.code, message: gate.message } });
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
const body = await readJsonBody(req);
|
|
92
|
-
const kinds = availableShellKinds().kinds;
|
|
93
|
-
const shell = kinds.includes(body.shell)
|
|
94
|
-
? body.shell
|
|
95
|
-
: undefined;
|
|
96
|
-
if (!shell) {
|
|
97
|
-
sendJson(res, 400, {
|
|
98
|
-
ok: false,
|
|
99
|
-
error: {
|
|
100
|
-
code: "INVALID_INPUT",
|
|
101
|
-
message: `shell must be one of: ${kinds.join(", ")} (available on this platform)`,
|
|
102
|
-
},
|
|
103
|
-
});
|
|
104
|
-
return true;
|
|
105
|
-
}
|
|
106
|
-
const info = deps.terminals.spawn({
|
|
107
|
-
ownerSessionId: typeof body.ownerSessionId === "string" && body.ownerSessionId
|
|
108
|
-
? body.ownerSessionId
|
|
109
|
-
: "console-ui",
|
|
110
|
-
name: typeof body.name === "string" && body.name ? body.name : `${shell}-ui`,
|
|
111
|
-
shell: shell,
|
|
112
|
-
cwd: typeof body.cwd === "string" && body.cwd
|
|
113
|
-
? body.cwd
|
|
114
|
-
: (deps.defaultCwd ?? undefined),
|
|
115
|
-
cols: typeof body.cols === "number" ? body.cols : undefined,
|
|
116
|
-
rows: typeof body.rows === "number" ? body.rows : undefined,
|
|
117
|
-
});
|
|
118
|
-
sendJson(res, 201, { ok: true, data: info });
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
const sessionId = parts[0];
|
|
122
|
-
if (!sessionId)
|
|
123
|
-
return false;
|
|
124
|
-
const sub = parts[1] ?? "";
|
|
125
|
-
// GET /terminals/:id — info + buffered output
|
|
126
|
-
if (method === "GET" && parts.length === 1) {
|
|
127
|
-
const info = deps.terminals.get(sessionId);
|
|
128
|
-
const output = deps.terminals.readAll(sessionId);
|
|
129
|
-
sendJson(res, 200, { ok: true, data: { ...info, output } });
|
|
130
|
-
return true;
|
|
131
|
-
}
|
|
132
|
-
// GET /terminals/:id/stream — SSE
|
|
133
|
-
if (method === "GET" && sub === "stream") {
|
|
134
|
-
// Validate existence first (404 before opening the stream).
|
|
135
|
-
const info = deps.terminals.get(sessionId);
|
|
136
|
-
void info;
|
|
137
|
-
res.writeHead(200, {
|
|
138
|
-
"content-type": "text/event-stream; charset=utf-8",
|
|
139
|
-
"cache-control": "no-cache, no-store",
|
|
140
|
-
connection: "keep-alive",
|
|
141
|
-
"x-accel-buffering": "no",
|
|
142
|
-
});
|
|
143
|
-
const writeFrame = (event, data) => {
|
|
144
|
-
if (res.writableEnded)
|
|
145
|
-
return;
|
|
146
|
-
res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
|
|
147
|
-
};
|
|
148
|
-
const buffered = deps.terminals.readAll(sessionId);
|
|
149
|
-
writeFrame("snapshot", {
|
|
150
|
-
truncated: buffered.truncated,
|
|
151
|
-
totalOutputChars: buffered.totalOutputChars,
|
|
152
|
-
text: buffered.text,
|
|
153
|
-
info: deps.terminals.get(sessionId),
|
|
154
|
-
});
|
|
155
|
-
const unsubscribe = deps.terminals.subscribe(sessionId, (chunk) => {
|
|
156
|
-
writeFrame("data", { chunk });
|
|
157
|
-
});
|
|
158
|
-
const heartbeat = setInterval(() => {
|
|
159
|
-
if (!res.writableEnded)
|
|
160
|
-
res.write(": heartbeat\n\n");
|
|
161
|
-
}, 15_000);
|
|
162
|
-
res.once("close", () => {
|
|
163
|
-
clearInterval(heartbeat);
|
|
164
|
-
unsubscribe();
|
|
165
|
-
});
|
|
166
|
-
return true;
|
|
167
|
-
}
|
|
168
|
-
// Everything else mutates → gate first.
|
|
169
|
-
const gate = deps.gateMutation(req);
|
|
170
|
-
if (!gate.ok) {
|
|
171
|
-
sendJson(res, gate.status, { ok: false, error: { code: gate.code, message: gate.message } });
|
|
172
|
-
return true;
|
|
173
|
-
}
|
|
174
|
-
if (method === "POST" && sub === "input" && parts.length === 2) {
|
|
175
|
-
const body = await readJsonBody(req);
|
|
176
|
-
if (typeof body.data !== "string") {
|
|
177
|
-
sendJson(res, 400, { ok: false, error: { code: "INVALID_INPUT", message: "data (string) is required" } });
|
|
178
|
-
return true;
|
|
179
|
-
}
|
|
180
|
-
deps.terminals.send(sessionId, body.data);
|
|
181
|
-
sendJson(res, 200, { ok: true });
|
|
182
|
-
return true;
|
|
183
|
-
}
|
|
184
|
-
if (method === "POST" && sub === "resize" && parts.length === 2) {
|
|
185
|
-
const body = await readJsonBody(req);
|
|
186
|
-
const cols = Number(body.cols);
|
|
187
|
-
const rows = Number(body.rows);
|
|
188
|
-
if (!Number.isInteger(cols) || !Number.isInteger(rows) || cols < 2 || rows < 2 || cols > 500 || rows > 200) {
|
|
189
|
-
sendJson(res, 400, { ok: false, error: { code: "INVALID_INPUT", message: "cols and rows (integers 2..500/200) are required" } });
|
|
190
|
-
return true;
|
|
191
|
-
}
|
|
192
|
-
deps.terminals.resize(sessionId, cols, rows);
|
|
193
|
-
sendJson(res, 200, { ok: true });
|
|
194
|
-
return true;
|
|
195
|
-
}
|
|
196
|
-
if (method === "POST" && sub === "interrupt" && parts.length === 2) {
|
|
197
|
-
deps.terminals.interrupt(sessionId);
|
|
198
|
-
sendJson(res, 200, { ok: true });
|
|
199
|
-
return true;
|
|
200
|
-
}
|
|
201
|
-
if (method === "POST" && sub === "kill" && parts.length === 2) {
|
|
202
|
-
await deps.terminals.kill(sessionId);
|
|
203
|
-
sendJson(res, 200, { ok: true });
|
|
204
|
-
return true;
|
|
205
|
-
}
|
|
206
|
-
sendJson(res, 404, { ok: false, error: { code: "NOT_FOUND", message: `unknown terminal route: ${method} ${pathname}` } });
|
|
207
|
-
return true;
|
|
208
|
-
}
|
|
209
|
-
catch (error) {
|
|
210
|
-
if (!res.headersSent)
|
|
211
|
-
mapTerminalError(res, error);
|
|
212
|
-
else
|
|
213
|
-
res.end();
|
|
214
|
-
return true;
|
|
215
|
-
}
|
|
216
|
-
}
|