@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
|
@@ -16,7 +16,6 @@ import { randomUUID } from "node:crypto";
|
|
|
16
16
|
import { access } from "node:fs/promises";
|
|
17
17
|
import { parseAssistantContent } from "./assistant-content.js";
|
|
18
18
|
import { OPERATOR_CHAT_ALLOWED_TOOLS, OPERATOR_CHAT_DENIED_TOOLS, OPERATOR_CHAT_DENIED_OPERATOR_ACTIONS, } from "./tools.js";
|
|
19
|
-
import { InvalidChatSessionModeError, SESSION_MODE_ACTION_DENIED_CODE, SESSION_MODE_ACTION_DENIED_MESSAGE, SESSION_MODE_IMMUTABLE_CODE, UnknownChatSessionModeError, isWorkflowSessionMode, parseCreateSessionMode, readStoredSessionMode, shouldAcceptOperatorSnapshot, } from "./session-mode.js";
|
|
20
19
|
import { buildModelCallableToolSchemas } from "./tool-adapter.js";
|
|
21
20
|
import { cleanChatTitle, acceptedOperationIdFromResult, isBlankChatSession } from "./session-store.js";
|
|
22
21
|
import { hashChatTurnPayload, projectChatToolEventPayload, projectCompactSnapshot, } from "./chat-event-store.js";
|
|
@@ -45,80 +44,11 @@ import { buildGoalCompactionInstructions, buildGoalContinuationContext, } from "
|
|
|
45
44
|
import { classifyGoalRoundAdmission, } from "./goal-round-driver.js";
|
|
46
45
|
import { isTerminalOperationState } from "../../../infrastructure/console/operation-store.js";
|
|
47
46
|
import { SddDataAlignmentError, } from "./sdd-data-alignment.js";
|
|
48
|
-
import { TerminalSessionRegistry } from "./terminal-sessions.js";
|
|
49
|
-
import { handleTerminalRequest } from "./terminal-routes.js";
|
|
50
|
-
import { handleScmRequest } from "./scm-routes.js";
|
|
51
|
-
import { handleBrowserRequest } from "./browser-routes.js";
|
|
52
47
|
function projectBrowserChatSession(record) {
|
|
53
48
|
const { telemetrySessionId, ...projected } = record;
|
|
54
49
|
void telemetrySessionId;
|
|
55
50
|
return projected;
|
|
56
51
|
}
|
|
57
|
-
function reopenInitFromRecord(record) {
|
|
58
|
-
return {
|
|
59
|
-
sessionId: record.sessionId,
|
|
60
|
-
sessionFile: record.sessionFile,
|
|
61
|
-
...(record.modelProvider && record.modelId
|
|
62
|
-
? { model: { provider: record.modelProvider, modelId: record.modelId } }
|
|
63
|
-
: {}),
|
|
64
|
-
sessionMode: record.sessionMode,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
async function readChatSessionMode(deps, sessionId) {
|
|
68
|
-
let record;
|
|
69
|
-
try {
|
|
70
|
-
record = await deps.store.get(sessionId);
|
|
71
|
-
}
|
|
72
|
-
catch (error) {
|
|
73
|
-
if (error instanceof UnknownChatSessionModeError) {
|
|
74
|
-
return {
|
|
75
|
-
ok: false,
|
|
76
|
-
status: 409,
|
|
77
|
-
code: error.code,
|
|
78
|
-
message: error.message,
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
throw error;
|
|
82
|
-
}
|
|
83
|
-
if (!record) {
|
|
84
|
-
return {
|
|
85
|
-
ok: false,
|
|
86
|
-
status: 404,
|
|
87
|
-
code: "NOT_FOUND",
|
|
88
|
-
message: `chat session not found: ${sessionId}`,
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
// Normalize: the store contract always fills sessionMode, but handler-level
|
|
92
|
-
// fakes / partial records may omit it — treat missing as workflow (the
|
|
93
|
-
// stock-record read rule), while a present-but-unknown value still fails
|
|
94
|
-
// closed in the store layer.
|
|
95
|
-
return {
|
|
96
|
-
ok: true,
|
|
97
|
-
record,
|
|
98
|
-
sessionMode: readStoredSessionMode(record.sessionMode),
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
async function requireWorkflowSession(res, deps, sessionId) {
|
|
102
|
-
const resolved = await readChatSessionMode(deps, sessionId);
|
|
103
|
-
if (!resolved.ok) {
|
|
104
|
-
sendJson(res, resolved.status, {
|
|
105
|
-
ok: false,
|
|
106
|
-
error: { code: resolved.code, message: resolved.message },
|
|
107
|
-
});
|
|
108
|
-
return undefined;
|
|
109
|
-
}
|
|
110
|
-
if (!isWorkflowSessionMode(resolved.sessionMode)) {
|
|
111
|
-
sendJson(res, 409, {
|
|
112
|
-
ok: false,
|
|
113
|
-
error: {
|
|
114
|
-
code: SESSION_MODE_ACTION_DENIED_CODE,
|
|
115
|
-
message: SESSION_MODE_ACTION_DENIED_MESSAGE,
|
|
116
|
-
},
|
|
117
|
-
});
|
|
118
|
-
return undefined;
|
|
119
|
-
}
|
|
120
|
-
return resolved.record;
|
|
121
|
-
}
|
|
122
52
|
/**
|
|
123
53
|
* Reattach the durable event-ring order to session-store rows. The session
|
|
124
54
|
* store remains the content authority; the ring only supplies chronology.
|
|
@@ -635,22 +565,6 @@ workspaceId) {
|
|
|
635
565
|
});
|
|
636
566
|
return;
|
|
637
567
|
}
|
|
638
|
-
let sessionMode;
|
|
639
|
-
try {
|
|
640
|
-
sessionMode = parseCreateSessionMode(body.sessionMode);
|
|
641
|
-
}
|
|
642
|
-
catch (error) {
|
|
643
|
-
sendJson(res, 400, {
|
|
644
|
-
ok: false,
|
|
645
|
-
error: {
|
|
646
|
-
code: error instanceof InvalidChatSessionModeError
|
|
647
|
-
? error.code
|
|
648
|
-
: "INVALID_SESSION_MODE",
|
|
649
|
-
message: error instanceof Error ? error.message : String(error),
|
|
650
|
-
},
|
|
651
|
-
});
|
|
652
|
-
return;
|
|
653
|
-
}
|
|
654
568
|
const provider = typeof body.modelProvider === "string" ? body.modelProvider : undefined;
|
|
655
569
|
const modelId = typeof body.modelId === "string" ? body.modelId : undefined;
|
|
656
570
|
const snapshotInput = body.snapshot;
|
|
@@ -672,16 +586,6 @@ workspaceId) {
|
|
|
672
586
|
let createdSessionId;
|
|
673
587
|
let persisted = false;
|
|
674
588
|
try {
|
|
675
|
-
if (snapshotInput !== undefined && !shouldAcceptOperatorSnapshot(sessionMode)) {
|
|
676
|
-
sendJson(res, 409, {
|
|
677
|
-
ok: false,
|
|
678
|
-
error: {
|
|
679
|
-
code: SESSION_MODE_ACTION_DENIED_CODE,
|
|
680
|
-
message: "Operator snapshots cannot be imported into Pi sessions",
|
|
681
|
-
},
|
|
682
|
-
});
|
|
683
|
-
return;
|
|
684
|
-
}
|
|
685
589
|
const snapshot = snapshotInput === undefined ? undefined : projectCompactSnapshot(snapshotInput);
|
|
686
590
|
// A Console record promises that its Pi JSONL can be reopened after a
|
|
687
591
|
// Console restart. Do not make that promise until Pi has finished
|
|
@@ -689,7 +593,6 @@ workspaceId) {
|
|
|
689
593
|
// future JSONL path, leaving an unrecoverable orphan when init failed or
|
|
690
594
|
// the process restarted in that window.
|
|
691
595
|
const handle = await deps.runtime.createSession({
|
|
692
|
-
sessionMode,
|
|
693
596
|
...(provider && modelId ? { model: { provider, modelId } } : {}),
|
|
694
597
|
...(snapshot
|
|
695
598
|
? {
|
|
@@ -716,7 +619,6 @@ workspaceId) {
|
|
|
716
619
|
sessionFile: handle.sessionFile,
|
|
717
620
|
modelProvider: selection.model?.provider ?? handle.model?.provider,
|
|
718
621
|
modelId: selection.model?.modelId ?? handle.model?.modelId,
|
|
719
|
-
sessionMode,
|
|
720
622
|
// AC-R7-002: explicit parameter from the dispatcher — the runtime
|
|
721
623
|
// store.create wrapper is gone; body workspaceId (if any) only acts as
|
|
722
624
|
// a fallback for direct (non-dispatcher) handler tests.
|
|
@@ -787,7 +689,6 @@ export async function handleForkChatSession(req, res, deps, sourceSessionId) {
|
|
|
787
689
|
try {
|
|
788
690
|
const handle = await deps.runtime.forkSession({
|
|
789
691
|
sourceSessionFile: source.sessionFile ?? "",
|
|
790
|
-
sessionMode: source.sessionMode,
|
|
791
692
|
...(source.modelProvider && source.modelId
|
|
792
693
|
? { model: { provider: source.modelProvider, modelId: source.modelId } }
|
|
793
694
|
: {}),
|
|
@@ -854,7 +755,10 @@ export async function handleBranchChatSession(req, res, deps, sessionId) {
|
|
|
854
755
|
}
|
|
855
756
|
try {
|
|
856
757
|
if (!deps.runtime.hasSession(sessionId)) {
|
|
857
|
-
const reopened = await deps.runtime.reopenSession(
|
|
758
|
+
const reopened = await deps.runtime.reopenSession({
|
|
759
|
+
sessionId,
|
|
760
|
+
sessionFile: record.sessionFile,
|
|
761
|
+
});
|
|
858
762
|
if (!reopened.ok) {
|
|
859
763
|
const mapped = await mapFailedReopen(deps, sessionId, reopened);
|
|
860
764
|
sendJson(res, mapped.status, {
|
|
@@ -1327,8 +1231,13 @@ export async function handleChatGoal(req, res, deps, sessionId) {
|
|
|
1327
1231
|
});
|
|
1328
1232
|
return;
|
|
1329
1233
|
}
|
|
1330
|
-
if (!(await
|
|
1234
|
+
if (!(await deps.store.get(sessionId))) {
|
|
1235
|
+
sendJson(res, 404, {
|
|
1236
|
+
ok: false,
|
|
1237
|
+
error: { code: "NOT_FOUND", message: `chat session not found: ${sessionId}` },
|
|
1238
|
+
});
|
|
1331
1239
|
return;
|
|
1240
|
+
}
|
|
1332
1241
|
if (req.method === "GET") {
|
|
1333
1242
|
sendJson(res, 200, { ok: true, goal: registry.get(sessionId) });
|
|
1334
1243
|
return;
|
|
@@ -1542,7 +1451,6 @@ export async function listChatSessionSummaries(deps, ownerWorkspaceId) {
|
|
|
1542
1451
|
...(session.thinkingLevel !== undefined
|
|
1543
1452
|
? { thinkingLevel: session.thinkingLevel }
|
|
1544
1453
|
: {}),
|
|
1545
|
-
sessionMode: session.sessionMode,
|
|
1546
1454
|
activeTurnId: active?.turnId,
|
|
1547
1455
|
turnPhase: active?.abortRequestedAt
|
|
1548
1456
|
? "stopping"
|
|
@@ -1566,16 +1474,6 @@ export async function handlePatchChatSession(req, res, deps, sessionId) {
|
|
|
1566
1474
|
}
|
|
1567
1475
|
try {
|
|
1568
1476
|
const body = await readJsonBody(req);
|
|
1569
|
-
if ("sessionMode" in body) {
|
|
1570
|
-
sendJson(res, 409, {
|
|
1571
|
-
ok: false,
|
|
1572
|
-
error: {
|
|
1573
|
-
code: SESSION_MODE_IMMUTABLE_CODE,
|
|
1574
|
-
message: "sessionMode cannot be changed after create",
|
|
1575
|
-
},
|
|
1576
|
-
});
|
|
1577
|
-
return;
|
|
1578
|
-
}
|
|
1579
1477
|
let record;
|
|
1580
1478
|
if (typeof body.title === "string")
|
|
1581
1479
|
record = await deps.store.rename(sessionId, body.title);
|
|
@@ -1634,7 +1532,13 @@ export async function handleReopenChatSession(req, res, deps, sessionId) {
|
|
|
1634
1532
|
});
|
|
1635
1533
|
return;
|
|
1636
1534
|
}
|
|
1637
|
-
const result = await deps.runtime.reopenSession(
|
|
1535
|
+
const result = await deps.runtime.reopenSession({
|
|
1536
|
+
sessionId,
|
|
1537
|
+
sessionFile: record.sessionFile,
|
|
1538
|
+
...(record.modelProvider && record.modelId
|
|
1539
|
+
? { model: { provider: record.modelProvider, modelId: record.modelId } }
|
|
1540
|
+
: {}),
|
|
1541
|
+
});
|
|
1638
1542
|
if (!result.ok) {
|
|
1639
1543
|
const mapped = await mapFailedReopen(deps, sessionId, result);
|
|
1640
1544
|
sendJson(res, mapped.status, {
|
|
@@ -1714,7 +1618,13 @@ export async function handleChatPrompt(req, res, deps, sessionId) {
|
|
|
1714
1618
|
});
|
|
1715
1619
|
return;
|
|
1716
1620
|
}
|
|
1717
|
-
const reopen = await deps.runtime.reopenSession(
|
|
1621
|
+
const reopen = await deps.runtime.reopenSession({
|
|
1622
|
+
sessionId,
|
|
1623
|
+
sessionFile: record.sessionFile,
|
|
1624
|
+
...(record.modelProvider && record.modelId
|
|
1625
|
+
? { model: { provider: record.modelProvider, modelId: record.modelId } }
|
|
1626
|
+
: {}),
|
|
1627
|
+
});
|
|
1718
1628
|
if (!reopen.ok) {
|
|
1719
1629
|
const mapped = await mapFailedReopen(deps, sessionId, reopen);
|
|
1720
1630
|
sendJson(res, mapped.status, {
|
|
@@ -1978,7 +1888,13 @@ export async function handleCreateChatTurn(req, res, deps, sessionId, trustedPay
|
|
|
1978
1888
|
});
|
|
1979
1889
|
return;
|
|
1980
1890
|
}
|
|
1981
|
-
const reopen = await deps.runtime.reopenSession(
|
|
1891
|
+
const reopen = await deps.runtime.reopenSession({
|
|
1892
|
+
sessionId,
|
|
1893
|
+
sessionFile: record.sessionFile,
|
|
1894
|
+
...(record.modelProvider && record.modelId
|
|
1895
|
+
? { model: { provider: record.modelProvider, modelId: record.modelId } }
|
|
1896
|
+
: {}),
|
|
1897
|
+
});
|
|
1982
1898
|
if (!reopen.ok) {
|
|
1983
1899
|
const mapped = await mapFailedReopen(deps, sessionId, reopen);
|
|
1984
1900
|
sendJson(res, mapped.status, {
|
|
@@ -2904,7 +2820,6 @@ export async function handleChatCommands(res, deps, sessionId) {
|
|
|
2904
2820
|
const warning = typeof listed.warning === "string" && listed.warning.trim()
|
|
2905
2821
|
? listed.warning.trim().slice(0, 160)
|
|
2906
2822
|
: undefined;
|
|
2907
|
-
const resolvedMode = await readChatSessionMode(deps, sessionId);
|
|
2908
2823
|
res.statusCode = 200;
|
|
2909
2824
|
res.setHeader("content-type", "application/json; charset=utf-8");
|
|
2910
2825
|
res.end(JSON.stringify({
|
|
@@ -2912,25 +2827,18 @@ export async function handleChatCommands(res, deps, sessionId) {
|
|
|
2912
2827
|
commands,
|
|
2913
2828
|
capabilities: {
|
|
2914
2829
|
sddBingo: Boolean(await deps.sddDataAlignment?.isEligible()),
|
|
2915
|
-
...(resolvedMode.ok ? { sessionMode: resolvedMode.sessionMode } : {}),
|
|
2916
2830
|
},
|
|
2917
2831
|
...(warning ? { warning } : {}),
|
|
2918
2832
|
}));
|
|
2919
2833
|
}
|
|
2920
2834
|
catch (error) {
|
|
2921
2835
|
// Whole-list / readiness failures stay fail-soft with empty commands + warning.
|
|
2922
|
-
// Keep the two capability shapes symmetric: the fallback mode mirrors the
|
|
2923
|
-
// client-side prop fallback in useComposer.
|
|
2924
|
-
const fallbackMode = await readChatSessionMode(deps, sessionId).catch(() => undefined);
|
|
2925
2836
|
res.statusCode = 200;
|
|
2926
2837
|
res.setHeader("content-type", "application/json; charset=utf-8");
|
|
2927
2838
|
res.end(JSON.stringify({
|
|
2928
2839
|
ok: true,
|
|
2929
2840
|
commands: [],
|
|
2930
|
-
capabilities: {
|
|
2931
|
-
sddBingo: false,
|
|
2932
|
-
...(fallbackMode?.ok ? { sessionMode: fallbackMode.sessionMode } : {}),
|
|
2933
|
-
},
|
|
2841
|
+
capabilities: { sddBingo: false },
|
|
2934
2842
|
warning: error instanceof Error ? error.message : "commands unavailable",
|
|
2935
2843
|
}));
|
|
2936
2844
|
}
|
|
@@ -3175,7 +3083,13 @@ export async function ensureActiveSession(deps, sessionId) {
|
|
|
3175
3083
|
message: `chat session not found: ${sessionId}`,
|
|
3176
3084
|
};
|
|
3177
3085
|
}
|
|
3178
|
-
const reopened = await deps.runtime.reopenSession(
|
|
3086
|
+
const reopened = await deps.runtime.reopenSession({
|
|
3087
|
+
sessionId,
|
|
3088
|
+
sessionFile: record.sessionFile,
|
|
3089
|
+
...(record.modelProvider && record.modelId
|
|
3090
|
+
? { model: { provider: record.modelProvider, modelId: record.modelId } }
|
|
3091
|
+
: {}),
|
|
3092
|
+
});
|
|
3179
3093
|
if (!reopened.ok) {
|
|
3180
3094
|
return { ok: false, ...(await mapFailedReopen(deps, sessionId, reopened)) };
|
|
3181
3095
|
}
|
|
@@ -3504,7 +3418,7 @@ async function handleStartInterview(req, res, deps, sessionId) {
|
|
|
3504
3418
|
});
|
|
3505
3419
|
return;
|
|
3506
3420
|
}
|
|
3507
|
-
if (!(await
|
|
3421
|
+
if (!(await requireChatSession(res, deps, sessionId)))
|
|
3508
3422
|
return;
|
|
3509
3423
|
try {
|
|
3510
3424
|
const body = await readJsonBody(req);
|
|
@@ -3546,7 +3460,7 @@ async function handleAnswerInterview(req, res, deps, sessionId, interviewSession
|
|
|
3546
3460
|
});
|
|
3547
3461
|
return;
|
|
3548
3462
|
}
|
|
3549
|
-
if (!(await
|
|
3463
|
+
if (!(await requireChatSession(res, deps, sessionId)))
|
|
3550
3464
|
return;
|
|
3551
3465
|
try {
|
|
3552
3466
|
const body = await readJsonBody(req);
|
|
@@ -3582,7 +3496,7 @@ async function handleAnswerInterview(req, res, deps, sessionId, interviewSession
|
|
|
3582
3496
|
}
|
|
3583
3497
|
}
|
|
3584
3498
|
async function handleGetInterviewFact(res, deps, sessionId, interviewSessionId, fact) {
|
|
3585
|
-
if (!(await
|
|
3499
|
+
if (!(await requireChatSession(res, deps, sessionId)))
|
|
3586
3500
|
return;
|
|
3587
3501
|
const state = await new ChatInterviewAdapter(deps.appData, deps.events).get(interviewSessionId);
|
|
3588
3502
|
if (!state || state.interview.operatorSessionId !== sessionId) {
|
|
@@ -3680,7 +3594,7 @@ async function handleContractApplyHumanGate(req, res, deps, sessionId, step) {
|
|
|
3680
3594
|
});
|
|
3681
3595
|
return;
|
|
3682
3596
|
}
|
|
3683
|
-
if (!(await
|
|
3597
|
+
if (!(await requireChatSession(res, deps, sessionId)))
|
|
3684
3598
|
return;
|
|
3685
3599
|
const ctx = deps.runtime.actionContext;
|
|
3686
3600
|
if (!ctx) {
|
|
@@ -3862,7 +3776,7 @@ async function handleDagHumanGate(req, res, deps, sessionId, step) {
|
|
|
3862
3776
|
});
|
|
3863
3777
|
return;
|
|
3864
3778
|
}
|
|
3865
|
-
if (!(await
|
|
3779
|
+
if (!(await requireChatSession(res, deps, sessionId)))
|
|
3866
3780
|
return;
|
|
3867
3781
|
const ctx = deps.runtime.actionContext;
|
|
3868
3782
|
if (!ctx) {
|
|
@@ -3971,7 +3885,7 @@ async function handleMutationHumanGate(req, res, deps, sessionId) {
|
|
|
3971
3885
|
});
|
|
3972
3886
|
return;
|
|
3973
3887
|
}
|
|
3974
|
-
if (!(await
|
|
3888
|
+
if (!(await requireChatSession(res, deps, sessionId)))
|
|
3975
3889
|
return;
|
|
3976
3890
|
const ctx = deps.runtime.actionContext;
|
|
3977
3891
|
if (!ctx) {
|
|
@@ -4060,7 +3974,7 @@ async function handleConfirmTaskKind(req, res, deps, sessionId, interviewSession
|
|
|
4060
3974
|
});
|
|
4061
3975
|
return;
|
|
4062
3976
|
}
|
|
4063
|
-
if (!(await
|
|
3977
|
+
if (!(await requireChatSession(res, deps, sessionId)))
|
|
4064
3978
|
return;
|
|
4065
3979
|
try {
|
|
4066
3980
|
const body = await readJsonBody(req);
|
|
@@ -4116,7 +4030,13 @@ export async function handleChatCompact(req, res, deps, sessionId) {
|
|
|
4116
4030
|
return;
|
|
4117
4031
|
}
|
|
4118
4032
|
if (!deps.runtime.hasSession(sessionId)) {
|
|
4119
|
-
const reopened = await deps.runtime.reopenSession(
|
|
4033
|
+
const reopened = await deps.runtime.reopenSession({
|
|
4034
|
+
sessionId,
|
|
4035
|
+
sessionFile: record.sessionFile,
|
|
4036
|
+
...(record.modelProvider && record.modelId
|
|
4037
|
+
? { model: { provider: record.modelProvider, modelId: record.modelId } }
|
|
4038
|
+
: {}),
|
|
4039
|
+
});
|
|
4120
4040
|
if (!reopened.ok) {
|
|
4121
4041
|
const mapped = await mapFailedReopen(deps, sessionId, reopened);
|
|
4122
4042
|
sendJson(res, mapped.status, {
|
|
@@ -4140,9 +4060,7 @@ export async function handleChatCompact(req, res, deps, sessionId) {
|
|
|
4140
4060
|
const rawInstructions = typeof body.instructions === "string" ? body.instructions : undefined;
|
|
4141
4061
|
const currentTodos = projectCurrentTodos(deps.events.snapshot(sessionId));
|
|
4142
4062
|
const todoInstructions = buildTodoCompactionInstructions(rawInstructions, currentTodos);
|
|
4143
|
-
const customInstructions =
|
|
4144
|
-
? buildGoalCompactionInstructions(todoInstructions, deps.goalRegistry?.get(sessionId) ?? null)
|
|
4145
|
-
: todoInstructions;
|
|
4063
|
+
const customInstructions = buildGoalCompactionInstructions(todoInstructions, deps.goalRegistry?.get(sessionId) ?? null);
|
|
4146
4064
|
const turnId = deps.events.latestTurnId(sessionId) ?? `${sessionId}:compact`;
|
|
4147
4065
|
const compactionId = `${sessionId}:compaction:${randomUUID()}`;
|
|
4148
4066
|
deps.events.append(sessionId, turnId, {
|
|
@@ -4157,42 +4075,27 @@ export async function handleChatCompact(req, res, deps, sessionId) {
|
|
|
4157
4075
|
});
|
|
4158
4076
|
try {
|
|
4159
4077
|
const snapshot = await deps.runtime.compact(sessionId, customInstructions);
|
|
4160
|
-
const completedAt = new Date().toISOString();
|
|
4161
|
-
const completedData = {
|
|
4162
|
-
schemaVersion: 1,
|
|
4163
|
-
compactionId,
|
|
4164
|
-
reason: "manual",
|
|
4165
|
-
status: "completed",
|
|
4166
|
-
summary: snapshot.summary,
|
|
4167
|
-
...(snapshot.firstKeptEntryId
|
|
4168
|
-
? { firstKeptEntryId: snapshot.firstKeptEntryId }
|
|
4169
|
-
: {}),
|
|
4170
|
-
...(snapshot.tokensBefore === undefined
|
|
4171
|
-
? {}
|
|
4172
|
-
: { tokensBefore: snapshot.tokensBefore }),
|
|
4173
|
-
...(snapshot.estimatedTokensAfter === undefined
|
|
4174
|
-
? {}
|
|
4175
|
-
: { estimatedTokensAfter: snapshot.estimatedTokensAfter }),
|
|
4176
|
-
willRetry: false,
|
|
4177
|
-
};
|
|
4178
4078
|
const event = deps.events.append(sessionId, turnId, {
|
|
4179
4079
|
kind: "compaction_end",
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4080
|
+
data: {
|
|
4081
|
+
schemaVersion: 1,
|
|
4082
|
+
compactionId,
|
|
4083
|
+
reason: "manual",
|
|
4084
|
+
status: "completed",
|
|
4085
|
+
summary: snapshot.summary,
|
|
4086
|
+
...(snapshot.firstKeptEntryId
|
|
4087
|
+
? { firstKeptEntryId: snapshot.firstKeptEntryId }
|
|
4088
|
+
: {}),
|
|
4089
|
+
...(snapshot.tokensBefore === undefined
|
|
4090
|
+
? {}
|
|
4091
|
+
: { tokensBefore: snapshot.tokensBefore }),
|
|
4092
|
+
...(snapshot.estimatedTokensAfter === undefined
|
|
4093
|
+
? {}
|
|
4094
|
+
: { estimatedTokensAfter: snapshot.estimatedTokensAfter }),
|
|
4095
|
+
willRetry: false,
|
|
4194
4096
|
},
|
|
4195
4097
|
});
|
|
4098
|
+
sendJson(res, 200, { ok: true, snapshot, eventId: event.eventId });
|
|
4196
4099
|
}
|
|
4197
4100
|
catch (error) {
|
|
4198
4101
|
const classified = classifyChatCompactionFailure(error);
|
|
@@ -4243,51 +4146,6 @@ export async function handleChatMessages(res, deps, sessionId, url) {
|
|
|
4243
4146
|
export async function handleChatRequest(req, res, deps, pathname, workspaceScope) {
|
|
4244
4147
|
if (!deps)
|
|
4245
4148
|
return false;
|
|
4246
|
-
try {
|
|
4247
|
-
return await dispatchChatRequest(req, res, deps, pathname, workspaceScope);
|
|
4248
|
-
}
|
|
4249
|
-
catch (error) {
|
|
4250
|
-
// Store-level fail-closed for corrupt sessionMode: bounded 409 instead of
|
|
4251
|
-
// a generic 500, for any handler that reads the record without its own
|
|
4252
|
-
// UnknownChatSessionModeError mapping (readChatSessionMode covers the rest).
|
|
4253
|
-
if (error instanceof UnknownChatSessionModeError) {
|
|
4254
|
-
sendJson(res, 409, {
|
|
4255
|
-
ok: false,
|
|
4256
|
-
error: { code: error.code, message: error.message },
|
|
4257
|
-
});
|
|
4258
|
-
return true;
|
|
4259
|
-
}
|
|
4260
|
-
throw error;
|
|
4261
|
-
}
|
|
4262
|
-
}
|
|
4263
|
-
async function dispatchChatRequest(req, res, deps, pathname, workspaceScope) {
|
|
4264
|
-
// Terminal management API (model + Console UI shared PTY registry).
|
|
4265
|
-
if (await handleTerminalRequest(req, res, {
|
|
4266
|
-
terminals: deps.terminals ?? new TerminalSessionRegistry(),
|
|
4267
|
-
gateMutation: (r) => gateMutation(r, deps),
|
|
4268
|
-
// Terminals open in the workspace repo root, not the Console process cwd.
|
|
4269
|
-
defaultCwd: deps.appData.repoRoot,
|
|
4270
|
-
}, pathname)) {
|
|
4271
|
-
return true;
|
|
4272
|
-
}
|
|
4273
|
-
// Source control API (model + Console UI shared workspace ScmService).
|
|
4274
|
-
if (deps.scm) {
|
|
4275
|
-
if (await handleScmRequest(req, res, {
|
|
4276
|
-
scm: deps.scm,
|
|
4277
|
-
gateMutation: (r) => gateMutation(r, deps),
|
|
4278
|
-
}, pathname)) {
|
|
4279
|
-
return true;
|
|
4280
|
-
}
|
|
4281
|
-
}
|
|
4282
|
-
// Browser probe API (read-only; explains iframe refusals to the panel).
|
|
4283
|
-
if (await handleBrowserRequest(req, res, {
|
|
4284
|
-
automation: deps.browserAutomation,
|
|
4285
|
-
requireWorkspace: () => workspaceScope
|
|
4286
|
-
? { ok: true, workspaceId: workspaceScope }
|
|
4287
|
-
: { ok: false },
|
|
4288
|
-
}, pathname)) {
|
|
4289
|
-
return true;
|
|
4290
|
-
}
|
|
4291
4149
|
if (!pathname.startsWith("/api/operator/v1/chat/") &&
|
|
4292
4150
|
!pathname.startsWith("/api/operator/v1/pi/"))
|
|
4293
4151
|
return false;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
2
|
import { readFile, stat } from "node:fs/promises";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
@@ -10,49 +10,8 @@ export const SDD_SKILL_NAMES = [
|
|
|
10
10
|
/** Backward-compatible name for callers that need a stable representative value. */
|
|
11
11
|
export const SDD_DEFAULT_SKILL_NAME = "SDD-implementation-test-review";
|
|
12
12
|
export const SDD_TELEMETRY_URL = "https://wizard-ai.paic.com.cn/code_pilot/api/skill-usage-log";
|
|
13
|
-
|
|
14
|
-
export const DEFAULT_AI_MA_PUB_SALT_KEY = "52aad0c09e6b46818a11ee702d6fe0ba";
|
|
15
|
-
export const SDD_TELEMETRY_SIGN = DEFAULT_AI_MA_PUB_SALT_KEY;
|
|
16
|
-
export const AIMAX_AUTH_TOKEN_ENV = "AIMAX_AUTH_TOKEN";
|
|
13
|
+
export const SDD_TELEMETRY_SIGN = "52aad0c09e6b46818a11ee702d6fe0ba";
|
|
17
14
|
export const WIZARD_LOCAL_DEFAULT_USER_AGENT = "Builder/OpenCode ai-sdk/provider-utils/4.0.21 runtime/bun/1.3.11";
|
|
18
|
-
const SM4_V1_PREFIX = "sm4:v1:";
|
|
19
|
-
/** Decode a plaintext ticket or `sm4:v1:` ciphertext. Unknown prefixes and crypto errors fail closed. */
|
|
20
|
-
export function decodeAimaxAuthToken(raw, keyHex = DEFAULT_AI_MA_PUB_SALT_KEY) {
|
|
21
|
-
const candidate = raw.trim();
|
|
22
|
-
if (!candidate)
|
|
23
|
-
return undefined;
|
|
24
|
-
if (!candidate.startsWith("sm4:"))
|
|
25
|
-
return candidate;
|
|
26
|
-
if (!candidate.startsWith(SM4_V1_PREFIX))
|
|
27
|
-
return undefined;
|
|
28
|
-
const hex = candidate.slice(SM4_V1_PREFIX.length);
|
|
29
|
-
if (!hex || hex.length % 2 !== 0 || /[^0-9a-fA-F]/.test(hex))
|
|
30
|
-
return undefined;
|
|
31
|
-
const key = Buffer.from(keyHex.trim(), "hex");
|
|
32
|
-
if (key.length !== 16)
|
|
33
|
-
return undefined;
|
|
34
|
-
try {
|
|
35
|
-
const encrypted = Buffer.from(hex, "hex");
|
|
36
|
-
if (encrypted.length === 0 || encrypted.length % 16 !== 0)
|
|
37
|
-
return undefined;
|
|
38
|
-
const decipher = createDecipheriv("sm4-ecb", key, null);
|
|
39
|
-
decipher.setAutoPadding(true);
|
|
40
|
-
const plain = Buffer.concat([decipher.update(encrypted), decipher.final()])
|
|
41
|
-
.toString("utf8")
|
|
42
|
-
.trim();
|
|
43
|
-
return plain || undefined;
|
|
44
|
-
}
|
|
45
|
-
catch {
|
|
46
|
-
return undefined;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
/** Set or delete `AIMAX_AUTH_TOKEN`. Empty string is treated as absent. */
|
|
50
|
-
export function syncAimaxAuthTokenEnv(env, token) {
|
|
51
|
-
if (token)
|
|
52
|
-
env[AIMAX_AUTH_TOKEN_ENV] = token;
|
|
53
|
-
else
|
|
54
|
-
delete env[AIMAX_AUTH_TOKEN_ENV];
|
|
55
|
-
}
|
|
56
15
|
function sameAuthFileVersion(left, right) {
|
|
57
16
|
if (!left.exists || !right.exists)
|
|
58
17
|
return left.exists === right.exists;
|
|
@@ -62,22 +21,9 @@ function sameAuthFileVersion(left, right) {
|
|
|
62
21
|
/** Reads ~/.aima-go/auth.json with metadata-based parse caching and fail-closed semantics. */
|
|
63
22
|
export class AimaxAuthReader {
|
|
64
23
|
authFile;
|
|
65
|
-
env;
|
|
66
24
|
cached;
|
|
67
|
-
constructor(authFile = path.join(os.homedir(), ".aima-go", "auth.json")
|
|
25
|
+
constructor(authFile = path.join(os.homedir(), ".aima-go", "auth.json")) {
|
|
68
26
|
this.authFile = authFile;
|
|
69
|
-
this.env = env;
|
|
70
|
-
}
|
|
71
|
-
resolveKeyHex() {
|
|
72
|
-
const injected = typeof this.env.AI_MA_PUB_SALT_KEY === "string" ? this.env.AI_MA_PUB_SALT_KEY.trim() : "";
|
|
73
|
-
if (injected)
|
|
74
|
-
return injected;
|
|
75
|
-
const host = process.env.AI_MA_PUB_SALT_KEY?.trim();
|
|
76
|
-
return host || DEFAULT_AI_MA_PUB_SALT_KEY;
|
|
77
|
-
}
|
|
78
|
-
finish(token) {
|
|
79
|
-
syncAimaxAuthTokenEnv(this.env, token);
|
|
80
|
-
return token;
|
|
81
27
|
}
|
|
82
28
|
async getToken() {
|
|
83
29
|
let version;
|
|
@@ -88,24 +34,22 @@ export class AimaxAuthReader {
|
|
|
88
34
|
}
|
|
89
35
|
catch {
|
|
90
36
|
this.cached = { version: { exists: false } };
|
|
91
|
-
return
|
|
92
|
-
}
|
|
93
|
-
if (this.cached && sameAuthFileVersion(this.cached.version, version)) {
|
|
94
|
-
return this.finish(this.cached.token);
|
|
37
|
+
return undefined;
|
|
95
38
|
}
|
|
39
|
+
if (this.cached && sameAuthFileVersion(this.cached.version, version))
|
|
40
|
+
return this.cached.token;
|
|
96
41
|
let token;
|
|
97
42
|
try {
|
|
98
43
|
const parsed = JSON.parse(await readFile(this.authFile, "utf8"));
|
|
99
44
|
const candidate = parsed["aimax-auth-token"];
|
|
100
|
-
if (typeof candidate === "string" && candidate.trim())
|
|
101
|
-
token =
|
|
102
|
-
}
|
|
45
|
+
if (typeof candidate === "string" && candidate.trim())
|
|
46
|
+
token = candidate;
|
|
103
47
|
}
|
|
104
48
|
catch {
|
|
105
49
|
// Malformed or unreadable files are intentionally ineligible.
|
|
106
50
|
}
|
|
107
51
|
this.cached = { version, ...(token ? { token } : {}) };
|
|
108
|
-
return
|
|
52
|
+
return token;
|
|
109
53
|
}
|
|
110
54
|
async isEligible() {
|
|
111
55
|
return Boolean(await this.getToken());
|
|
@@ -1,36 +1,5 @@
|
|
|
1
1
|
import { isBlankChatSession } from "./session-store.js";
|
|
2
2
|
import { projectDeferredTurnSummaries, projectDeferredTurnSummary, } from "./deferred-turn.js";
|
|
3
|
-
/** Sidebar / global GET /chat/sessions projection. Must include sessionMode. */
|
|
4
|
-
export function projectChatSessionCatalogListItem(entry, active) {
|
|
5
|
-
return {
|
|
6
|
-
sessionId: entry.sessionId,
|
|
7
|
-
...(entry.workspaceId ? { workspaceId: entry.workspaceId } : {}),
|
|
8
|
-
state: entry.state,
|
|
9
|
-
createdAt: entry.createdAt,
|
|
10
|
-
updatedAt: entry.updatedAt,
|
|
11
|
-
...(entry.title !== undefined ? { title: entry.title } : {}),
|
|
12
|
-
...(entry.displayTitle !== undefined
|
|
13
|
-
? { displayTitle: entry.displayTitle }
|
|
14
|
-
: {}),
|
|
15
|
-
...(entry.modelProvider !== undefined
|
|
16
|
-
? { modelProvider: entry.modelProvider }
|
|
17
|
-
: {}),
|
|
18
|
-
...(entry.modelId !== undefined ? { modelId: entry.modelId } : {}),
|
|
19
|
-
...(entry.thinkingLevel !== undefined
|
|
20
|
-
? { thinkingLevel: entry.thinkingLevel }
|
|
21
|
-
: {}),
|
|
22
|
-
sessionMode: entry.sessionMode,
|
|
23
|
-
activeTurnId: active?.turnId,
|
|
24
|
-
turnPhase: active?.abortRequestedAt
|
|
25
|
-
? "stopping"
|
|
26
|
-
: active
|
|
27
|
-
? "running"
|
|
28
|
-
: "idle",
|
|
29
|
-
deferredTurn: entry.deferredTurn,
|
|
30
|
-
deferredTurns: entry.deferredTurns,
|
|
31
|
-
isBlank: entry.isBlank && !active,
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
3
|
/**
|
|
35
4
|
* Process-wide Session baseline, mirroring DSH's independent session.list.
|
|
36
5
|
* Full records stay in their fingerprint-isolated stores; this catalog only
|
|
@@ -67,7 +36,6 @@ export class ChatSessionCatalog {
|
|
|
67
36
|
deferredTurns: projectDeferredTurnSummaries(record.deferredTurns ?? []),
|
|
68
37
|
isBlank: isBlankChatSession(record),
|
|
69
38
|
...(workspaceId ? { workspaceId } : {}),
|
|
70
|
-
sessionMode: record.sessionMode,
|
|
71
39
|
});
|
|
72
40
|
}
|
|
73
41
|
remove(sessionId) {
|