@tea-agent/loop-agent 0.40.0-next.9 → 0.40.0
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/AGENTS.md +1 -1
- package/CHANGELOG.md +21 -21
- package/README.md +2 -2
- package/dist/application/dag/generate-task-dag.js +6 -2
- package/dist/build-stamp.json +3 -3
- package/dist/cli/command-definitions.js +9 -5
- package/dist/cli/program.js +38 -3
- package/dist/commands/client-recovery.js +8 -36
- package/dist/commands/init-model-catalog.js +22 -0
- package/dist/commands/task-advance.js +23 -1
- package/dist/commands/task-source-prepare.js +5 -0
- package/dist/commands/task-status.js +1 -0
- package/dist/executors/pi-sdk-executor.js +33 -5
- package/dist/executors/shell-executor.js +94 -20
- package/dist/governance/checks.js +1 -0
- package/dist/shared/operator/capabilities.js +9 -1
- package/dist/shared/pi-context-pressure/checkpoint.js +116 -0
- package/dist/shared/pi-context-pressure/compaction-policy.js +151 -0
- package/dist/shared/pi-context-pressure/env.js +58 -0
- package/dist/shared/pi-context-pressure/extension.js +100 -0
- package/dist/shared/pi-context-pressure/index.js +7 -0
- package/dist/shared/pi-context-pressure/overflow.js +252 -0
- package/dist/shared/pi-context-pressure/sift-bridge.js +386 -0
- package/dist/shared/pi-context-pressure/telemetry.js +51 -0
- package/dist/worker/console/chat/assistant-content.js +7 -0
- package/dist/worker/console/chat/chat-event-store.js +82 -11
- package/dist/worker/console/chat/goal-round-driver.js +72 -0
- package/dist/worker/console/chat/goals.js +300 -0
- package/dist/worker/console/chat/pi-runtime.js +285 -8
- package/dist/worker/console/chat/provider-error.js +2 -1
- package/dist/worker/console/chat/repo-browser.js +94 -12
- package/dist/worker/console/chat/routes.js +495 -30
- package/dist/worker/console/chat/session-catalog.js +48 -0
- package/dist/worker/console/chat/session-stats.js +96 -0
- package/dist/worker/console/chat/session-store.js +27 -18
- package/dist/worker/console/chat/shortcuts.js +7 -0
- package/dist/worker/console/chat/sift-bridge.js +1 -0
- package/dist/worker/console/chat/turn-process.js +42 -5
- package/dist/worker/console/dag-execution-receipt.js +20 -2
- package/dist/worker/console/operator-actions.js +20 -5
- package/dist/worker/console/operator-selection.js +6 -2
- package/dist/worker/console/pi-plugins.catalog.json +73658 -0
- package/dist/worker/console/pi-plugins.js +179 -0
- package/dist/worker/console/routes.js +246 -6
- package/dist/worker/console/server.js +173 -42
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-Bs-CDAXM.js → abnfDiagram-N423BO3Z-Dy71QJp3.js} +1 -1
- package/dist/worker/console/static/assets/{arc-CAkA3We3.js → arc-M25fNMTE.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-DEmI_zqr.js → architectureDiagram-T3A2C74G-CUWlVl1a.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-uDHANebE.js → blockDiagram-VBNYF7ZC-Dd0Whpx2.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-Bv97b4_B.js → c4Diagram-5PPSVZJV-BdfeCkI5.js} +1 -1
- package/dist/worker/console/static/assets/channel-Ba0AKiEZ.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-shmQKsFz.js → chunk-2GRJ4B5K-D_1sUkyD.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-BAraNvcN.js → chunk-2Q5K7J3B-Cxnxf36E.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BirhxUop.js → chunk-5RXB4S5H-D9RG3G_x.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-C9LgUJpR.js → chunk-5VM5RSS4-Zz9jgjLX.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DrU-s-t7.js → chunk-6Q2QTUOP-BCggDRCH.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-Tx-H_FA2.js → chunk-GF5L2VYU-CFg-5iAS.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BjLtNFrR.js → chunk-JWPE2WC7-DRQTE8x_.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-UNLVwSsy.js → chunk-KBJHAD2P-C_Dw7uZ8.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-CBEUX8XD.js → chunk-RYQCIY6F-BjIiApsk.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-WTL7IZOq.js → chunk-XXDRQBXY-B5XQD4KG.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BU3IjVEe.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BU3IjVEe.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CkHG6W3s.js → cose-bilkent-JH36ORCC-huHqH6WQ.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BRzFqTaL.js → cynefin-VYW2F7L2-BSi6yZqP.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-2_CFp_i7.js → cynefinDiagram-MW4NZA55-Bs_Jp31y.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BJtsmdkE.js → dagre-VZM6K2ZE-CYxavikT.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-DNEFFo6w.js → diagram-7IWD3JNH-B6TErl71.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-B_IWV7eo.js → diagram-B4RE2ZJO-CvH4J2ii.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-DvvRx2dz.js → diagram-LBJQPF4R-v1NBAqXS.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-CsibsWLg.js → diagram-Q27KOJAE-CUNHVAn2.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-les_djBQ.js → diagram-UB23O5K3-Dzz1gUu-.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BEm2n7qJ.js → ebnfDiagram-BXEA7PRR-CCF8_LjK.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-BI7vHHVm.js → erDiagram-JOGREHBK-DObdPVLa.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CUFCERrB.js → flowDiagram-UKHOOZJN-DlN8Pxrj.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-wxyLiGWt.js → ganttDiagram-PKOTCBZU-BJKIPTGX.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Bt897K8Z.js → gitGraphDiagram-DS77QQ5N-XcSSnObi.js} +1 -1
- package/dist/worker/console/static/assets/index-CIYzS16i.css +1 -0
- package/dist/worker/console/static/assets/index-CS3QOTfl.js +451 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DYNx_IPv.js → infoDiagram-6WML65LV-BKrRKMww.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-CzpLNEu6.js → ishikawaDiagram-WSZJBQD7-CN5dk-yb.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-97f9owNU.js → journeyDiagram-NVQOT4AX-B4P4KZ-Y.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BxM9hyBn.js → kanban-definition-27J2QSJJ-BRlteP32.js} +1 -1
- package/dist/worker/console/static/assets/{linear-ByuxcHvp.js → linear-CG8D9fuL.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-DwPGvpCv.js → mermaid.core-BuB6P2rX.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-DCoqG9RT.js → mindmap-definition-FAOFIHXS-DYXGl_DR.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BLSBmBMx.js → pegDiagram-VL7TDLO6-BM48yEVG.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-B0t_0oJW.js → pieDiagram-7S7Q4E2Y-mT8NL-Ow.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-sTzDk7Nt.js → quadrantDiagram-CIZ2JOQS-C4pZ6DH_.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-B3jRdATC.js → railroadDiagram-AXF67PYL-BKAcr70m.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-D-cTtXEN.js → requirementDiagram-LRYGKXZP-CRxcKpoO.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-B25igJRE.js → sankeyDiagram-W5VNT64P-Ds4LxQDI.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-jW_lM1_D.js → sequenceDiagram-SI44F4Z6-CPLwPf_p.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-CrzTgsHE.js → sizeCapture-X5ZJPWSS-CL65uij0.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-B01MvlqE.js → stateDiagram-OKZ733FA-CO0Mgd1W.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BUewAVYS.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-YcF12FiU.js → swimlanes-SLNWSIFB-Cxv3TSNw.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Bhe67Wjl.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-ClnRcg2s.js → timeline-definition-Z64GVDOM-Dw85f9L2.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-B6gr_z-q.js → vennDiagram-T6HMQDX7-B4QLCqCy.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-CvSgguGH.js → wardleyDiagram-T6FBY63Y-B_yKCWwn.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-23OtSZCb.js → xychartDiagram-ELKLHX3M-nniBEGv2.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +95 -25
- package/dist/worker/console/static-src/operator-chat/compaction-message.js +35 -1
- package/dist/worker/console/static-src/operator-chat/open-preview-in-browser.js +3 -1
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +26 -19
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +0 -11
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +14 -1
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +34 -4
- package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +28 -3
- package/dist/worker/console/static-src/operator-chat/workspace-reorder.js +18 -0
- package/dist/worker/console/static-src/shell/useWorkspaces.js +150 -34
- package/dist/worker/console/static-src/shell/workspace-route.js +3 -1
- package/dist/worker/console/workspace-context.js +28 -3
- package/dist/worker/console/workspace-registry.js +333 -60
- package/dist/worker/observe/static/inspect-bootstrap.d.ts +8 -0
- package/dist/worker/observe/static/inspect-bootstrap.js +57 -0
- package/dist/worker/observe/static/inspect-workspace.js +54 -10
- package/dist/worker/observe/static/operator-chrome.css +23 -4
- package/dist/worker/observe/static/operator-chrome.js +7 -2
- package/dist/worker/observe/static/styles.css +87 -25
- package/dist/worker/observe/static/views/dag-inspector.js +42 -1
- package/dist/worker/observe/static/views/dags.js +7 -5
- package/dist/worker/observe/static/views/session-timeline.js +135 -0
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +162 -8
- package/dist/workflows/dag/backend-test-pytest-collection.js +70 -2
- package/dist/workflows/dag/backend-test-result-contract.js +5 -1
- package/dist/workflows/dag/backend-test-scenario-param.js +339 -53
- package/dist/workflows/dag/backend-test-writer-completeness.js +11 -0
- package/dist/workflows/dag/init-hybrid.js +5 -4
- package/docs/architecture/runtime-boundaries.md +2 -1
- package/docs/templates/backend-test-dag.json +6 -5
- package/docs/templates/init-managed-agents.md +1 -1
- package/package.json +3 -2
- package/skills/loop-agent/references/command-reference.md +15 -1
- package/dist/worker/console/static/assets/channel-amxUpk7o.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-bejwBVIz.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-bejwBVIz.js +0 -1
- package/dist/worker/console/static/assets/index-BHhUOTri.css +0 -1
- package/dist/worker/console/static/assets/index-DqJbO3-p.js +0 -407
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BvFKEtm2.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DIB2eVg-.js +0 -8
|
@@ -8,6 +8,9 @@ import { readPackageVersion } from "../../shared/package-metadata.js";
|
|
|
8
8
|
import { DAG_ABSOLUTE_MAX_WALL_CLOCK_MS } from "../../shared/timeout-policy.js";
|
|
9
9
|
import { openConsoleAppData } from "./app-data.js";
|
|
10
10
|
import { isLoopbackHost } from "./loopback.js";
|
|
11
|
+
import { ChatSessionStore } from "./chat/session-store.js";
|
|
12
|
+
import { ChatSessionCatalog } from "./chat/session-catalog.js";
|
|
13
|
+
import { matchRepoHtmlPreviewRoute } from "./chat/repo-browser.js";
|
|
11
14
|
import { handleConsoleHealthRequest, handleWorkspaceRoutes, sendJson, serveConsoleStatic, } from "./routes.js";
|
|
12
15
|
import { issueBootCapabilityToken, injectConfirmationTokenScript, } from "./security.js";
|
|
13
16
|
import { resolvePackageRootFromConsole } from "./sibling-controller.js";
|
|
@@ -74,6 +77,35 @@ export async function createConsoleServer(options) {
|
|
|
74
77
|
});
|
|
75
78
|
const registry = new WorkspaceRegistry(bootstrapAppData);
|
|
76
79
|
const startupRecord = await registry.ensureStartupWorkspace(repoRoot);
|
|
80
|
+
const chatSessionCatalog = new ChatSessionCatalog();
|
|
81
|
+
// DSH-style dual baseline: Workspace records own grouping/order, while the
|
|
82
|
+
// Session catalog is rebuilt once at Host startup from durable Session
|
|
83
|
+
// persistence. Requests never rediscover every Workspace store.
|
|
84
|
+
for (const record of await registry.listAll()) {
|
|
85
|
+
try {
|
|
86
|
+
const store = new ChatSessionStore(openConsoleAppData({
|
|
87
|
+
repoRoot: record.repoRoot,
|
|
88
|
+
...(options.appDataRoot
|
|
89
|
+
? { appDataRoot: options.appDataRoot }
|
|
90
|
+
: {}),
|
|
91
|
+
}));
|
|
92
|
+
const sessions = await store.list({ includeArchived: true });
|
|
93
|
+
for (const session of sessions) {
|
|
94
|
+
if (session.repoFingerprint !== record.repoFingerprint)
|
|
95
|
+
continue;
|
|
96
|
+
chatSessionCatalog.upsert(session, record.workspaceId);
|
|
97
|
+
}
|
|
98
|
+
if (!record.hidden) {
|
|
99
|
+
await registry.reconcileSessions(record.workspaceId, sessions
|
|
100
|
+
.filter((session) => session.repoFingerprint === record.repoFingerprint)
|
|
101
|
+
.map((session) => session.sessionId));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// A removed or externally unavailable Workspace is not an empty Session
|
|
106
|
+
// baseline. Its prior durable membership remains untouched.
|
|
107
|
+
}
|
|
108
|
+
}
|
|
77
109
|
const instanceNonce = configuredPort === 0 ? randomBytes(16).toString("hex") : undefined;
|
|
78
110
|
const bootToken = issueBootCapabilityToken({
|
|
79
111
|
repoFingerprint: startupRecord.repoFingerprint,
|
|
@@ -96,28 +128,10 @@ export async function createConsoleServer(options) {
|
|
|
96
128
|
// ---- Per-workspace lazily-created contexts -------------------------------
|
|
97
129
|
const workspaceContexts = new Map();
|
|
98
130
|
let sharedConsoleUpdateExecutor = options.consoleUpdateExecutor;
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
if (!id) {
|
|
102
|
-
return {
|
|
103
|
-
ok: false,
|
|
104
|
-
status: 400,
|
|
105
|
-
code: "WORKSPACE_REQUIRED",
|
|
106
|
-
message: "workspaceId is required",
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
const existing = workspaceContexts.get(id);
|
|
131
|
+
const materializeContext = async (record) => {
|
|
132
|
+
const existing = workspaceContexts.get(record.workspaceId);
|
|
110
133
|
if (existing)
|
|
111
|
-
return
|
|
112
|
-
const record = await registry.getVisible(id);
|
|
113
|
-
if (!record) {
|
|
114
|
-
return {
|
|
115
|
-
ok: false,
|
|
116
|
-
status: 404,
|
|
117
|
-
code: "WORKSPACE_NOT_FOUND",
|
|
118
|
-
message: `unknown workspace: ${id}`,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
134
|
+
return existing;
|
|
121
135
|
const context = await createWorkspaceContext(record, {
|
|
122
136
|
appDataRoot: options.appDataRoot,
|
|
123
137
|
staticDir,
|
|
@@ -132,12 +146,35 @@ export async function createConsoleServer(options) {
|
|
|
132
146
|
createClient: options.createClient,
|
|
133
147
|
defaultTimeoutMs: options.defaultTimeoutMs,
|
|
134
148
|
skipReconcile: options.skipReconcile,
|
|
149
|
+
chatSessionCatalog,
|
|
135
150
|
});
|
|
136
151
|
if (sharedConsoleUpdateExecutor) {
|
|
137
152
|
context.actionContext.consoleUpdateExecutor = sharedConsoleUpdateExecutor;
|
|
138
153
|
}
|
|
139
|
-
workspaceContexts.set(
|
|
154
|
+
workspaceContexts.set(record.workspaceId, context);
|
|
140
155
|
void context.recoverDeferredTurns().catch(() => undefined);
|
|
156
|
+
return context;
|
|
157
|
+
};
|
|
158
|
+
const resolveContext = async (workspaceId) => {
|
|
159
|
+
const id = workspaceId?.trim();
|
|
160
|
+
if (!id) {
|
|
161
|
+
return {
|
|
162
|
+
ok: false,
|
|
163
|
+
status: 400,
|
|
164
|
+
code: "WORKSPACE_REQUIRED",
|
|
165
|
+
message: "workspaceId is required",
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
const record = await registry.getVisible(id);
|
|
169
|
+
if (!record) {
|
|
170
|
+
return {
|
|
171
|
+
ok: false,
|
|
172
|
+
status: 404,
|
|
173
|
+
code: "WORKSPACE_NOT_FOUND",
|
|
174
|
+
message: `unknown workspace: ${id}`,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
const context = await materializeContext(record);
|
|
141
178
|
return { ok: true, context };
|
|
142
179
|
};
|
|
143
180
|
const startupResolution = await resolveContext(startupRecord.workspaceId);
|
|
@@ -383,6 +420,52 @@ export async function createConsoleServer(options) {
|
|
|
383
420
|
// the JSON body; all other chat routes resolve via Session ownership
|
|
384
421
|
// (durable) with optional query workspaceId conflict check.
|
|
385
422
|
const { handleChatRequest: dispatchChat } = await import("./chat/routes.js");
|
|
423
|
+
const htmlPreviewRoute = matchRepoHtmlPreviewRoute(pathname);
|
|
424
|
+
if (method === "GET" &&
|
|
425
|
+
pathname === "/api/operator/v1/chat/sessions" &&
|
|
426
|
+
!url.searchParams.has("workspaceId")) {
|
|
427
|
+
const sessions = chatSessionCatalog.list().map((entry) => {
|
|
428
|
+
const active = entry.workspaceId
|
|
429
|
+
? workspaceContexts
|
|
430
|
+
.get(entry.workspaceId)
|
|
431
|
+
?.chatRouteDeps.events.getActiveTurn(entry.sessionId)
|
|
432
|
+
: undefined;
|
|
433
|
+
return {
|
|
434
|
+
sessionId: entry.sessionId,
|
|
435
|
+
...(entry.workspaceId ? { workspaceId: entry.workspaceId } : {}),
|
|
436
|
+
state: entry.state,
|
|
437
|
+
createdAt: entry.createdAt,
|
|
438
|
+
updatedAt: entry.updatedAt,
|
|
439
|
+
...(entry.title !== undefined ? { title: entry.title } : {}),
|
|
440
|
+
...(entry.displayTitle !== undefined
|
|
441
|
+
? { displayTitle: entry.displayTitle }
|
|
442
|
+
: {}),
|
|
443
|
+
...(entry.modelProvider !== undefined
|
|
444
|
+
? { modelProvider: entry.modelProvider }
|
|
445
|
+
: {}),
|
|
446
|
+
...(entry.modelId !== undefined ? { modelId: entry.modelId } : {}),
|
|
447
|
+
...(entry.thinkingLevel !== undefined
|
|
448
|
+
? { thinkingLevel: entry.thinkingLevel }
|
|
449
|
+
: {}),
|
|
450
|
+
activeTurnId: active?.turnId,
|
|
451
|
+
turnPhase: active?.abortRequestedAt
|
|
452
|
+
? "stopping"
|
|
453
|
+
: active
|
|
454
|
+
? "running"
|
|
455
|
+
: "idle",
|
|
456
|
+
deferredTurn: entry.deferredTurn,
|
|
457
|
+
deferredTurns: entry.deferredTurns,
|
|
458
|
+
};
|
|
459
|
+
});
|
|
460
|
+
sendJson(res, 200, {
|
|
461
|
+
ok: true,
|
|
462
|
+
schemaVersion: 2,
|
|
463
|
+
sessions,
|
|
464
|
+
hasBash: true,
|
|
465
|
+
workspaceErrors: [],
|
|
466
|
+
});
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
386
469
|
if (method === "POST" && pathname === "/api/operator/v1/chat/sessions") {
|
|
387
470
|
// AC-R5-006: the mutation gate fires BEFORE body pre-read/workspace
|
|
388
471
|
// resolution — an unauthenticated mutation gets exactly 403, never a
|
|
@@ -445,30 +528,44 @@ export async function createConsoleServer(options) {
|
|
|
445
528
|
}
|
|
446
529
|
}
|
|
447
530
|
const requestedId = url.searchParams.get("workspaceId")?.trim();
|
|
531
|
+
const catalogEntry = chatSessionCatalog.get(sessionId);
|
|
448
532
|
let owner;
|
|
449
533
|
if (requestedId) {
|
|
534
|
+
if (catalogEntry?.workspaceId &&
|
|
535
|
+
catalogEntry.workspaceId !== requestedId) {
|
|
536
|
+
sendJson(res, 403, {
|
|
537
|
+
ok: false,
|
|
538
|
+
error: {
|
|
539
|
+
code: "WORKSPACE_CONFLICT",
|
|
540
|
+
message: "workspaceId does not match the session's owning workspace",
|
|
541
|
+
},
|
|
542
|
+
});
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
450
545
|
// The current UI always sends its selected workspace. Resolve that one
|
|
451
546
|
// context directly: scanning every historical registry entry first can
|
|
452
547
|
// fail on an old, deleted temp directory before reaching the real owner.
|
|
453
|
-
const
|
|
454
|
-
|
|
548
|
+
const ownerRecord = catalogEntry
|
|
549
|
+
? await registry.get(requestedId)
|
|
550
|
+
: await registry.getVisible(requestedId);
|
|
551
|
+
if (!ownerRecord ||
|
|
552
|
+
(catalogEntry &&
|
|
553
|
+
ownerRecord.repoFingerprint !== catalogEntry.repoFingerprint)) {
|
|
455
554
|
// A session-scoped workspace hint is a conflict boundary. Unknown
|
|
456
555
|
// workspace ids must not reveal whether the session exists elsewhere.
|
|
457
|
-
|
|
458
|
-
sendJson(res, workspaceConflict ? 403 : resolution.status, {
|
|
556
|
+
sendJson(res, 403, {
|
|
459
557
|
ok: false,
|
|
460
|
-
error:
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
}
|
|
465
|
-
: { code: resolution.code, message: resolution.message },
|
|
558
|
+
error: {
|
|
559
|
+
code: "WORKSPACE_CONFLICT",
|
|
560
|
+
message: "workspaceId does not match the session's owning workspace",
|
|
561
|
+
},
|
|
466
562
|
});
|
|
467
563
|
return;
|
|
468
564
|
}
|
|
469
|
-
const
|
|
565
|
+
const context = await materializeContext(ownerRecord);
|
|
566
|
+
const stored = await context.chatRouteDeps.store.get(sessionId);
|
|
470
567
|
if (stored)
|
|
471
|
-
owner =
|
|
568
|
+
owner = context;
|
|
472
569
|
else {
|
|
473
570
|
// Do not scan another workspace and disclose whether the id exists there.
|
|
474
571
|
sendJson(res, 403, {
|
|
@@ -481,12 +578,18 @@ export async function createConsoleServer(options) {
|
|
|
481
578
|
return;
|
|
482
579
|
}
|
|
483
580
|
}
|
|
581
|
+
else if (catalogEntry?.workspaceId) {
|
|
582
|
+
const ownerRecord = await registry.get(catalogEntry.workspaceId);
|
|
583
|
+
if (ownerRecord &&
|
|
584
|
+
ownerRecord.repoFingerprint === catalogEntry.repoFingerprint) {
|
|
585
|
+
owner = await materializeContext(ownerRecord);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
484
588
|
else {
|
|
485
|
-
//
|
|
486
|
-
//
|
|
487
|
-
//
|
|
488
|
-
const
|
|
489
|
-
for (const record of visible) {
|
|
589
|
+
// Catalog misses are limited to out-of-process/legacy writes after Host
|
|
590
|
+
// startup. Recover once, then publish the discovered Session into the
|
|
591
|
+
// independent baseline for subsequent requests.
|
|
592
|
+
for (const record of await registry.listVisible()) {
|
|
490
593
|
try {
|
|
491
594
|
const resolution = await resolveContext(record.workspaceId);
|
|
492
595
|
if (!resolution.ok)
|
|
@@ -494,6 +597,7 @@ export async function createConsoleServer(options) {
|
|
|
494
597
|
const stored = await resolution.context.chatRouteDeps.store.get(sessionId);
|
|
495
598
|
if (stored) {
|
|
496
599
|
owner = resolution.context;
|
|
600
|
+
chatSessionCatalog.upsert(stored, record.workspaceId);
|
|
497
601
|
break;
|
|
498
602
|
}
|
|
499
603
|
}
|
|
@@ -519,9 +623,24 @@ export async function createConsoleServer(options) {
|
|
|
519
623
|
await dispatchChat(req, res, owner.chatRouteDeps, pathname, undefined);
|
|
520
624
|
return;
|
|
521
625
|
}
|
|
522
|
-
// Non-session chat
|
|
523
|
-
//
|
|
524
|
-
|
|
626
|
+
// Non-session chat surfaces normally resolve from ?workspaceId=. The
|
|
627
|
+
// HTML preview route carries it in the URL path so browser-relative
|
|
628
|
+
// CSS/image requests retain the same workspace scope after dropping a
|
|
629
|
+
// document query string.
|
|
630
|
+
const queryWorkspaceId = url.searchParams.get("workspaceId")?.trim() || undefined;
|
|
631
|
+
if (htmlPreviewRoute &&
|
|
632
|
+
queryWorkspaceId &&
|
|
633
|
+
queryWorkspaceId !== htmlPreviewRoute.workspaceId) {
|
|
634
|
+
sendJson(res, 403, {
|
|
635
|
+
ok: false,
|
|
636
|
+
error: {
|
|
637
|
+
code: "WORKSPACE_CONFLICT",
|
|
638
|
+
message: "workspaceId does not match the HTML preview route",
|
|
639
|
+
},
|
|
640
|
+
});
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
const workspaceId = htmlPreviewRoute?.workspaceId || queryWorkspaceId;
|
|
525
644
|
const resolution = await resolveContext(workspaceId);
|
|
526
645
|
if (!resolution.ok) {
|
|
527
646
|
sendJson(res, resolution.status, {
|
|
@@ -595,6 +714,14 @@ export async function createConsoleServer(options) {
|
|
|
595
714
|
await handleConsoleOperatorRequest(req, res, operatorRouteContext(startup));
|
|
596
715
|
return;
|
|
597
716
|
}
|
|
717
|
+
// Pi 插件目录 / 版本 / 安装 / 卸载:全局用户级(~/.pi/agent),非工作区作用域,用 startup context。
|
|
718
|
+
if (pathname === "/api/operator/v1/pi-plugins" ||
|
|
719
|
+
pathname === "/api/operator/v1/pi-plugins/versions" ||
|
|
720
|
+
pathname === "/api/operator/v1/pi-plugins/install" ||
|
|
721
|
+
pathname === "/api/operator/v1/pi-plugins/uninstall") {
|
|
722
|
+
await handleConsoleOperatorRequest(req, res, operatorRouteContext(startup));
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
598
725
|
// Unknown operator route: fail closed (never a startup-workspace proxy).
|
|
599
726
|
sendJson(res, 404, {
|
|
600
727
|
ok: false,
|
|
@@ -670,7 +797,11 @@ export async function createConsoleServer(options) {
|
|
|
670
797
|
}
|
|
671
798
|
}
|
|
672
799
|
workspaceContexts.clear();
|
|
800
|
+
registry.close();
|
|
673
801
|
server.close((err) => (err ? closeReject(err) : closeResolve()));
|
|
802
|
+
// Workspace/event SSE responses are intentionally long-lived. Force them
|
|
803
|
+
// closed after initiating shutdown so Console close never hangs on a tab.
|
|
804
|
+
server.closeAllConnections();
|
|
674
805
|
}),
|
|
675
806
|
});
|
|
676
807
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-
|
|
1
|
+
import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-BCggDRCH.js";import{p as f}from"./chunk-JWPE2WC7-DRQTE8x_.js";import{_ as n,l as o}from"./mermaid.core-BuB6P2rX.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-BSi6yZqP.js";import"./index-CS3QOTfl.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-
|
|
1
|
+
import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-BuB6P2rX.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
|