@tea-agent/loop-agent 0.44.0-next.5 → 0.44.0-next.7
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 +299 -445
- package/dist/build-stamp.json +3 -3
- package/dist/executors/pi-sdk-executor.js +7 -7
- package/dist/infrastructure/console/operation-store.js +46 -14
- package/dist/shared/git-workspace-status.js +2 -0
- package/dist/shared/wizard-local-telemetry.js +2 -1
- package/dist/worker/console/chat/assistant-content.js +5 -34
- package/dist/worker/console/chat/chat-event-store.js +27 -10
- package/dist/worker/console/chat/db-connections.js +72 -8
- package/dist/worker/console/chat/pi-runtime/custom-tools/sql-tools.js +52 -24
- package/dist/worker/console/chat/pi-runtime.js +251 -18
- package/dist/worker/console/chat/repo-browser.js +49 -0
- package/dist/worker/console/chat/routes.js +215 -66
- package/dist/worker/console/chat/session-store.js +147 -19
- package/dist/worker/console/chat/turn-process.js +69 -23
- package/dist/worker/console/chat/user-turn-outline.js +19 -0
- package/dist/worker/console/console-update-runtime.js +2 -2
- package/dist/worker/console/operator-user-error.js +28 -1
- package/dist/worker/console/pi-readiness.js +4 -4
- package/dist/worker/console/recovery-cta.js +14 -14
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-BHuhGM1e.js → abnfDiagram-N423BO3Z-DTuku_-7.js} +1 -1
- package/dist/worker/console/static/assets/{arc-CKh5E_sr.js → arc-CQbCsSqb.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-DizhiBEv.js → architectureDiagram-T3A2C74G-C-xUntTR.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-3Neea-Z-.js → blockDiagram-VBNYF7ZC-DhNlwGAl.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-BCP_Qrgi.js → c4Diagram-5PPSVZJV-B7j3nx8o.js} +1 -1
- package/dist/worker/console/static/assets/channel-5_os7t_x.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-C_wydftK.js → chunk-2GRJ4B5K-BCrcxEh2.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-jRPXZbzx.js → chunk-2Q5K7J3B-CsaePDb3.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BLQf2OYO.js → chunk-5RXB4S5H--SRQc1rN.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-0qRq64rI.js → chunk-5VM5RSS4-C5BFY2Po.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-ClMg8xmV.js → chunk-6Q2QTUOP-Caso6uN7.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-Coop2FlL.js → chunk-GF5L2VYU-AY2ZSAx2.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-CDdO-jPJ.js → chunk-JWPE2WC7-DiMqZQ_8.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-D8Gkppjl.js → chunk-KBJHAD2P-gpvvriOp.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-DA9HIySf.js → chunk-RYQCIY6F-CUdyoJhI.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-DZNDRX1k.js → chunk-XXDRQBXY-Bp1xW3T4.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-loz0n18W.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-loz0n18W.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CZ1zGyjq.js → cose-bilkent-JH36ORCC-D-JIcOIT.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-B8u1_FtM.js → cynefin-VYW2F7L2-C-NKFflx.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-CPBB6lfo.js → cynefinDiagram-MW4NZA55-CSOcvOAA.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-CG3Eov3E.js → dagre-VZM6K2ZE-BQSBltMy.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-ycI-dOjh.js → diagram-7IWD3JNH-B0LVC45G.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-Bx_GyQ7Y.js → diagram-B4RE2ZJO-Cypg3nqy.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-m0G6mP4d.js → diagram-LBJQPF4R-BBDU88XJ.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-DTDJkqcJ.js → diagram-Q27KOJAE-BZusLqSb.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-BCfFrG-p.js → diagram-UB23O5K3-Cfolotcr.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BIkTNPpp.js → ebnfDiagram-BXEA7PRR-CjfyUy0m.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DTcMWrd2.js → erDiagram-JOGREHBK-DJdz7txE.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-BqzDaNQ7.js → flowDiagram-UKHOOZJN-CQqgPO6y.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-BSl_vGFe.js → ganttDiagram-PKOTCBZU-BOpGfS2m.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-DCA5HXM6.js → gitGraphDiagram-DS77QQ5N-C6UCu0qx.js} +1 -1
- package/dist/worker/console/static/assets/index-CUT440A8.css +1 -0
- package/dist/worker/console/static/assets/index-DWKejNVJ.js +486 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DvqT18ge.js → infoDiagram-6WML65LV-BWeaVEUB.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-B6zGKrQ3.js → ishikawaDiagram-WSZJBQD7-C8gmlBbk.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-BpLQPI9C.js → journeyDiagram-NVQOT4AX-DF3bm8Bp.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-CzIz_-Lt.js → kanban-definition-27J2QSJJ-D2fG2Vxi.js} +1 -1
- package/dist/worker/console/static/assets/{linear-CMQ8Jpp-.js → linear-BGKgMc2T.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-BdAMrTf7.js → mermaid.core-DF6mMPJ9.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-hSwF6sOq.js → mindmap-definition-FAOFIHXS-AMhePheC.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-DZdv509B.js → pegDiagram-VL7TDLO6-DN1Cl0W0.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-CmD4-b0K.js → pieDiagram-7S7Q4E2Y-Cx9ngUeN.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-DtKxNxlS.js → quadrantDiagram-CIZ2JOQS-BcYPTQJb.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-D48iIoiS.js → railroadDiagram-AXF67PYL-BqHUZWnH.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-C3N0K-2p.js → requirementDiagram-LRYGKXZP-CmqWZ0-B.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-CACWR-Xs.js → sankeyDiagram-W5VNT64P--4YetH1y.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-g_QgugvZ.js → sequenceDiagram-SI44F4Z6-DGD4VMfD.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-DqLoRPGK.js → sizeCapture-X5ZJPWSS-QVw9q7rh.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-ES59VgMG.js → stateDiagram-OKZ733FA-CuemV9pe.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BdlGdIJw.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-fjyLVNWo.js → swimlanes-SLNWSIFB-C7oKzZKs.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DjjbHbde.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-Cd5-biKv.js → timeline-definition-Z64GVDOM-C2Of60nT.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-CZTu6mPf.js → vennDiagram-T6HMQDX7-DHtpQHyL.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DR01jjbe.js → wardleyDiagram-T6FBY63Y-COi9OhSy.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-iZcuGVGa.js → xychartDiagram-ELKLHX3M-DPHQfRrt.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/app/console-types.js +9 -1
- package/dist/worker/console/static-src/operator-chat/chat-link.js +20 -0
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +58 -3
- package/dist/worker/console/static-src/operator-chat/details-rail-surfaces.js +98 -0
- package/dist/worker/console/static-src/operator-chat/file-palette-nav.js +81 -0
- package/dist/worker/console/static-src/operator-chat/process-label.js +19 -6
- package/dist/worker/console/static-src/operator-chat/transcript-mode.js +21 -0
- package/dist/worker/console/static-src/operator-chat/turn-group-equality.js +2 -0
- package/dist/worker/console/static-src/operator-chat/turn-process-disclosure.js +13 -5
- package/dist/worker/console/static-src/operator-chat/turn-state-projection.js +166 -0
- package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +56 -2
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +202 -41
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +78 -23
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +55 -18
- package/dist/worker/console/static-src/operator-chat/useComposer.js +80 -6
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +13 -3
- package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +36 -17
- package/dist/worker/console/static-src/operator-chat/useRuntimeSnapshot.js +18 -0
- package/dist/worker/console/static-src/operator-chat/useWorkspaceBrowserGate.js +4 -0
- package/dist/worker/console/static-src/shell/console-update-reload.js +1 -1
- package/dist/worker/console/workspace-initialization.js +3 -3
- package/dist/worker/observability/read-model.js +23 -2
- package/dist/worker/scheduler/scheduled-goal-dispatch.js +3 -2
- package/dist/worker/scheduler/scheduled-goal-evidence.js +6 -1
- package/docs/templates/backend-test-dag.json +1 -0
- package/package.json +4 -4
- package/dist/worker/console/static/assets/channel-DxgzA1GF.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BZcm7fs6.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BZcm7fs6.js +0 -1
- package/dist/worker/console/static/assets/index-BAEDjTbD.css +0 -1
- package/dist/worker/console/static/assets/index-wKEJUaP5.js +0 -482
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DyCIq6jx.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-CsKtO34q.js +0 -8
|
@@ -191,6 +191,25 @@ async function bindSessionExtensions(session) {
|
|
|
191
191
|
return;
|
|
192
192
|
await session.bindExtensions(createConsoleExtensionBindings());
|
|
193
193
|
}
|
|
194
|
+
export function branchForkedSessionManager(sessionManager, throughUserMessageIndex) {
|
|
195
|
+
const userEntries = (sessionManager.getBranch?.() ?? []).filter((entry) => {
|
|
196
|
+
if (!entry || typeof entry !== "object")
|
|
197
|
+
return false;
|
|
198
|
+
const candidate = entry;
|
|
199
|
+
return candidate.type === "message" && candidate.message?.role === "user";
|
|
200
|
+
});
|
|
201
|
+
const target = userEntries[throughUserMessageIndex];
|
|
202
|
+
if (!target || typeof target.id !== "string") {
|
|
203
|
+
throw new Error("FORK_MESSAGE_ENTRY_NOT_FOUND");
|
|
204
|
+
}
|
|
205
|
+
sessionManager.branch(target.id);
|
|
206
|
+
if (typeof sessionManager.appendCustomEntry !== "function") {
|
|
207
|
+
throw new Error("FORK_MESSAGE_ENTRY_PERSIST_UNSUPPORTED");
|
|
208
|
+
}
|
|
209
|
+
sessionManager.appendCustomEntry("loop-agent-fork-point", {
|
|
210
|
+
throughUserMessageIndex,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
194
213
|
function pinOperatorChatTools(session, sessionMode = DEFAULT_CONSOLE_CHAT_SESSION_MODE) {
|
|
195
214
|
session.setActiveToolsByName(computeChatActiveToolNames(session, sessionMode));
|
|
196
215
|
}
|
|
@@ -296,6 +315,14 @@ export function createWizardLocalHeadersExtension(options) {
|
|
|
296
315
|
}
|
|
297
316
|
export { THINKING_LEVELS, RuntimeSnapshotUnavailableError, projectRuntimeSnapshot, };
|
|
298
317
|
export { createDefaultPiSdkBindings } from "./pi-runtime/sdk-bindings.js";
|
|
318
|
+
/** Catalog listing must not load skills/extensions/context — those belong to reopen. */
|
|
319
|
+
const CATALOG_RESOURCE_LOADER_OPTIONS = Object.freeze({
|
|
320
|
+
noContextFiles: true,
|
|
321
|
+
noSkills: true,
|
|
322
|
+
noExtensions: true,
|
|
323
|
+
noPromptTemplates: true,
|
|
324
|
+
noThemes: true,
|
|
325
|
+
});
|
|
299
326
|
export { extractAssistantContentBlocks, extractAssistantText, isAssistantSdkMessage };
|
|
300
327
|
export function buildRequestContextEvent(input) {
|
|
301
328
|
const systemPrompt = input.session.state?.systemPrompt ?? input.session.systemPrompt ?? "";
|
|
@@ -440,6 +467,8 @@ export class ConsolePiRuntime {
|
|
|
440
467
|
mainlineLeaves = new Map();
|
|
441
468
|
/** Per-sessionId single-flight materialization (create fast-path / readiness fence). */
|
|
442
469
|
sessionInit = new Map();
|
|
470
|
+
/** Concurrent reopen of the same historical JSONL shares one in-flight promise. */
|
|
471
|
+
reopenInFlight = new Map();
|
|
443
472
|
/** Resolved model binding after materialization (create may return before this is known). */
|
|
444
473
|
sessionModels = new Map();
|
|
445
474
|
/** Durable session mode; record is the source of truth, this is the live handle cache. */
|
|
@@ -1188,6 +1217,9 @@ export class ConsolePiRuntime {
|
|
|
1188
1217
|
targetSessionDir: this.options.sessionDir,
|
|
1189
1218
|
targetSessionId: sessionId,
|
|
1190
1219
|
});
|
|
1220
|
+
if (init.throughUserMessageIndex !== undefined) {
|
|
1221
|
+
branchForkedSessionManager(sessionManager, init.throughUserMessageIndex);
|
|
1222
|
+
}
|
|
1191
1223
|
const built = await this.buildSessionWithServices({
|
|
1192
1224
|
sessionId,
|
|
1193
1225
|
sessionManager,
|
|
@@ -1251,11 +1283,68 @@ export class ConsolePiRuntime {
|
|
|
1251
1283
|
entries: manager.getBranch?.() ?? [],
|
|
1252
1284
|
};
|
|
1253
1285
|
}
|
|
1286
|
+
/**
|
|
1287
|
+
* Workspace-scoped model catalog. A live session's ModelRuntime is reused
|
|
1288
|
+
* when present; otherwise services are created without opening the Pi
|
|
1289
|
+
* conversation JSONL so the picker is not blocked on cold reopen.
|
|
1290
|
+
*/
|
|
1291
|
+
workspaceModelRuntime;
|
|
1292
|
+
workspaceInspection;
|
|
1293
|
+
async getWorkspaceModelRuntime() {
|
|
1294
|
+
if (!this.workspaceModelRuntime) {
|
|
1295
|
+
this.workspaceModelRuntime = (async () => {
|
|
1296
|
+
const agentDir = await safeGetAgentDir(this.bindings);
|
|
1297
|
+
const { services } = await this.bindings.createServices({
|
|
1298
|
+
cwd: this.options.cwd,
|
|
1299
|
+
agentDir,
|
|
1300
|
+
resourceLoaderOptions: { ...CATALOG_RESOURCE_LOADER_OPTIONS },
|
|
1301
|
+
});
|
|
1302
|
+
return services.modelRuntime;
|
|
1303
|
+
})().catch((error) => {
|
|
1304
|
+
this.workspaceModelRuntime = undefined;
|
|
1305
|
+
throw error;
|
|
1306
|
+
});
|
|
1307
|
+
}
|
|
1308
|
+
return this.workspaceModelRuntime;
|
|
1309
|
+
}
|
|
1310
|
+
/**
|
|
1311
|
+
* Full OPEN-surface services for inspect UIs. No SessionManager / JSONL.
|
|
1312
|
+
* Cached without sessionId so todo/goal extensions stay off the shared scope.
|
|
1313
|
+
*/
|
|
1314
|
+
async getWorkspaceInspectionServices() {
|
|
1315
|
+
if (!this.workspaceInspection) {
|
|
1316
|
+
this.workspaceInspection = (async () => {
|
|
1317
|
+
const agentDir = await safeGetAgentDir(this.bindings);
|
|
1318
|
+
const appendSystemPrompt = composeChatSystemPromptParts({
|
|
1319
|
+
sessionMode: DEFAULT_CONSOLE_CHAT_SESSION_MODE,
|
|
1320
|
+
workflowPrompt: OPERATOR_CHAT_SYSTEM_PROMPT_BASE,
|
|
1321
|
+
});
|
|
1322
|
+
const { services } = await this.bindings.createServices({
|
|
1323
|
+
cwd: this.options.cwd,
|
|
1324
|
+
agentDir,
|
|
1325
|
+
resourceLoaderOptions: await this.buildResourceLoaderOptions({
|
|
1326
|
+
appendSystemPrompt,
|
|
1327
|
+
}),
|
|
1328
|
+
});
|
|
1329
|
+
return {
|
|
1330
|
+
modelRuntime: services.modelRuntime,
|
|
1331
|
+
resourceLoader: services
|
|
1332
|
+
.resourceLoader,
|
|
1333
|
+
settingsManager: services.settingsManager,
|
|
1334
|
+
};
|
|
1335
|
+
})().catch((error) => {
|
|
1336
|
+
this.workspaceInspection = undefined;
|
|
1337
|
+
throw error;
|
|
1338
|
+
});
|
|
1339
|
+
}
|
|
1340
|
+
return this.workspaceInspection;
|
|
1341
|
+
}
|
|
1254
1342
|
async listModels(sessionId) {
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1343
|
+
const live = this.modelRuntimes.get(sessionId);
|
|
1344
|
+
if (live && this.sessions.has(sessionId)) {
|
|
1345
|
+
return this.bindings.listAvailableModels({ modelRuntime: live });
|
|
1346
|
+
}
|
|
1347
|
+
const modelRuntime = await this.getWorkspaceModelRuntime();
|
|
1259
1348
|
return this.bindings.listAvailableModels({ modelRuntime });
|
|
1260
1349
|
}
|
|
1261
1350
|
async applyModel(sessionId, model) {
|
|
@@ -1518,11 +1607,11 @@ export class ConsolePiRuntime {
|
|
|
1518
1607
|
return { ok: true, revision: this.revisions.get(sessionId) ?? 0 };
|
|
1519
1608
|
}
|
|
1520
1609
|
/**
|
|
1521
|
-
* Project the unified
|
|
1522
|
-
*
|
|
1523
|
-
*
|
|
1524
|
-
*
|
|
1525
|
-
*
|
|
1610
|
+
* Project the unified runtime snapshot (design §2.2). A live Pi session is
|
|
1611
|
+
* the source of truth when present. Inspect GETs may pass
|
|
1612
|
+
* `workspaceProjection` to render ResourceLoader inventories without
|
|
1613
|
+
* opening the conversation JSONL. Unknown ids without that hint stay
|
|
1614
|
+
* undefined so callers fail closed.
|
|
1526
1615
|
*/
|
|
1527
1616
|
/**
|
|
1528
1617
|
* ConsolePiRuntime.listSlashCommands
|
|
@@ -1541,18 +1630,27 @@ export class ConsolePiRuntime {
|
|
|
1541
1630
|
return collectSlashCommands({ session, resourceLoader });
|
|
1542
1631
|
}
|
|
1543
1632
|
async getRuntimeSnapshot(sessionId, options) {
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1633
|
+
const initializing = this.sessionInit.get(sessionId)?.status === "initializing";
|
|
1634
|
+
if (this.sessions.has(sessionId) || initializing) {
|
|
1635
|
+
try {
|
|
1636
|
+
await this.ensureSessionReady(sessionId);
|
|
1637
|
+
}
|
|
1638
|
+
catch (error) {
|
|
1639
|
+
if (error instanceof PiSessionInitFailedError)
|
|
1640
|
+
throw error;
|
|
1641
|
+
if (options?.workspaceProjection) {
|
|
1642
|
+
return this.projectWorkspaceRuntimeSnapshot(sessionId, options);
|
|
1643
|
+
}
|
|
1644
|
+
return undefined;
|
|
1645
|
+
}
|
|
1552
1646
|
}
|
|
1553
1647
|
const session = this.sessions.get(sessionId);
|
|
1554
|
-
if (!session)
|
|
1648
|
+
if (!session) {
|
|
1649
|
+
if (options?.workspaceProjection) {
|
|
1650
|
+
return this.projectWorkspaceRuntimeSnapshot(sessionId, options);
|
|
1651
|
+
}
|
|
1555
1652
|
return undefined;
|
|
1653
|
+
}
|
|
1556
1654
|
const services = this.serviceScopes.get(sessionId);
|
|
1557
1655
|
const modelRuntime = this.modelRuntimes.get(sessionId);
|
|
1558
1656
|
const resourceLoader = services?.resourceLoader;
|
|
@@ -1653,6 +1751,116 @@ export class ConsolePiRuntime {
|
|
|
1653
1751
|
hasBash: true,
|
|
1654
1752
|
});
|
|
1655
1753
|
}
|
|
1754
|
+
resolveWorkspaceThinkingSelection(sessionId, stored) {
|
|
1755
|
+
const live = this.thinkingSelections.get(sessionId);
|
|
1756
|
+
if (live)
|
|
1757
|
+
return live;
|
|
1758
|
+
if (!stored || stored === "auto")
|
|
1759
|
+
return "auto";
|
|
1760
|
+
if (THINKING_LEVELS.includes(stored)) {
|
|
1761
|
+
return stored;
|
|
1762
|
+
}
|
|
1763
|
+
return "auto";
|
|
1764
|
+
}
|
|
1765
|
+
/**
|
|
1766
|
+
* Inspect projection without SessionManager.open. Used only when the Agent
|
|
1767
|
+
* is not live and the caller confirmed a durable session record.
|
|
1768
|
+
*/
|
|
1769
|
+
async projectWorkspaceRuntimeSnapshot(sessionId, options) {
|
|
1770
|
+
const hint = options.workspaceProjection ?? {};
|
|
1771
|
+
const sessionMode = hint.sessionMode ?? this.sessionModeOf(sessionId);
|
|
1772
|
+
let inspection;
|
|
1773
|
+
try {
|
|
1774
|
+
inspection = await this.getWorkspaceInspectionServices();
|
|
1775
|
+
}
|
|
1776
|
+
catch (error) {
|
|
1777
|
+
throw new RuntimeSnapshotUnavailableError(`workspace runtime projection failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1778
|
+
}
|
|
1779
|
+
const resourceLoader = inspection.resourceLoader;
|
|
1780
|
+
const settingsManager = inspection.settingsManager;
|
|
1781
|
+
const thinkingSelection = this.resolveWorkspaceThinkingSelection(sessionId, hint.thinkingLevel);
|
|
1782
|
+
const effectiveThinkingLevel = settingsManager?.getDefaultThinkingLevel?.() ??
|
|
1783
|
+
(thinkingSelection === "auto" ? undefined : thinkingSelection);
|
|
1784
|
+
const rawSystemPrompt = resourceLoader?.getSystemPrompt?.() ||
|
|
1785
|
+
composeChatSystemPrompt({
|
|
1786
|
+
sessionMode,
|
|
1787
|
+
workflowPrompt: OPERATOR_CHAT_SYSTEM_PROMPT_BASE,
|
|
1788
|
+
});
|
|
1789
|
+
if (!rawSystemPrompt) {
|
|
1790
|
+
throw new RuntimeSnapshotUnavailableError("system prompt projection failed: workspace prompt was empty");
|
|
1791
|
+
}
|
|
1792
|
+
let models = [];
|
|
1793
|
+
try {
|
|
1794
|
+
models = this.bindings
|
|
1795
|
+
.listAvailableModels({ modelRuntime: inspection.modelRuntime })
|
|
1796
|
+
.map((entry) => ({
|
|
1797
|
+
provider: entry.provider,
|
|
1798
|
+
id: entry.id,
|
|
1799
|
+
...(entry.name ? { name: entry.name } : {}),
|
|
1800
|
+
hasCredentials: entry.hasCredentials,
|
|
1801
|
+
}));
|
|
1802
|
+
}
|
|
1803
|
+
catch (error) {
|
|
1804
|
+
throw new RuntimeSnapshotUnavailableError(`model enumeration failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1805
|
+
}
|
|
1806
|
+
const thinkingLevels = [
|
|
1807
|
+
{ value: "auto" },
|
|
1808
|
+
...THINKING_LEVELS.map((value) => ({ value })),
|
|
1809
|
+
];
|
|
1810
|
+
let skillPrefs = { schemaVersion: 1, skills: {} };
|
|
1811
|
+
let skillPrefsError;
|
|
1812
|
+
if (resourceLoader) {
|
|
1813
|
+
try {
|
|
1814
|
+
skillPrefs = await this.loadSkillAutoInvocationPreferences();
|
|
1815
|
+
}
|
|
1816
|
+
catch (error) {
|
|
1817
|
+
skillPrefsError = error;
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
const activeTools = chatActiveToolBaseline(sessionMode);
|
|
1821
|
+
const inventories = await collectRuntimeInventories({
|
|
1822
|
+
resourceLoader,
|
|
1823
|
+
skillPrefs,
|
|
1824
|
+
skillPrefsError,
|
|
1825
|
+
agentDir: await safeGetAgentDir(this.bindings),
|
|
1826
|
+
cwd: this.options.cwd,
|
|
1827
|
+
tools: [],
|
|
1828
|
+
activeToolNames: activeTools,
|
|
1829
|
+
});
|
|
1830
|
+
const storedModel = this.sessionModels.get(sessionId);
|
|
1831
|
+
const provider = storedModel?.provider ?? hint.modelProvider;
|
|
1832
|
+
const modelId = storedModel?.modelId ?? hint.modelId;
|
|
1833
|
+
return projectRuntimeSnapshot({
|
|
1834
|
+
sessionId,
|
|
1835
|
+
revision: this.revisions.get(sessionId) ?? 0,
|
|
1836
|
+
loadedAt: new Date().toISOString(),
|
|
1837
|
+
selection: {
|
|
1838
|
+
...(provider && modelId
|
|
1839
|
+
? { model: { provider, id: modelId } }
|
|
1840
|
+
: {}),
|
|
1841
|
+
thinkingSelection,
|
|
1842
|
+
...(effectiveThinkingLevel
|
|
1843
|
+
? { effectiveThinkingLevel: effectiveThinkingLevel }
|
|
1844
|
+
: {}),
|
|
1845
|
+
},
|
|
1846
|
+
models,
|
|
1847
|
+
thinkingLevels,
|
|
1848
|
+
systemPrompt: {
|
|
1849
|
+
...(options.includeRaw ? { raw: rawSystemPrompt } : {}),
|
|
1850
|
+
text: rawSystemPrompt,
|
|
1851
|
+
sha256: createHash("sha256").update(rawSystemPrompt).digest("hex"),
|
|
1852
|
+
characters: rawSystemPrompt.length,
|
|
1853
|
+
},
|
|
1854
|
+
activeTools,
|
|
1855
|
+
contextFiles: inventories.contextFiles,
|
|
1856
|
+
skills: inventories.skills,
|
|
1857
|
+
extensions: inventories.extensions,
|
|
1858
|
+
packages: inventories.packages,
|
|
1859
|
+
mcp: inventories.mcp,
|
|
1860
|
+
diagnostics: inventories.diagnostics,
|
|
1861
|
+
hasBash: true,
|
|
1862
|
+
});
|
|
1863
|
+
}
|
|
1656
1864
|
/**
|
|
1657
1865
|
* Re-open a previously persisted Chat session after Console restart or
|
|
1658
1866
|
* browser refresh (roadmap M1-S04 / S05).
|
|
@@ -1667,6 +1875,19 @@ export class ConsolePiRuntime {
|
|
|
1667
1875
|
* than silently creating a fresh empty session and losing prior context.
|
|
1668
1876
|
*/
|
|
1669
1877
|
async reopenSession(init) {
|
|
1878
|
+
const sessionId = init.sessionId;
|
|
1879
|
+
const existing = this.reopenInFlight.get(sessionId);
|
|
1880
|
+
if (existing)
|
|
1881
|
+
return existing;
|
|
1882
|
+
const pending = this.reopenSessionExclusive(init).finally(() => {
|
|
1883
|
+
if (this.reopenInFlight.get(sessionId) === pending) {
|
|
1884
|
+
this.reopenInFlight.delete(sessionId);
|
|
1885
|
+
}
|
|
1886
|
+
});
|
|
1887
|
+
this.reopenInFlight.set(sessionId, pending);
|
|
1888
|
+
return pending;
|
|
1889
|
+
}
|
|
1890
|
+
async reopenSessionExclusive(init) {
|
|
1670
1891
|
await this.syncAimaxAuthToken();
|
|
1671
1892
|
const sessionId = init.sessionId;
|
|
1672
1893
|
const sessionMode = this.rememberSessionMode(sessionId, init.sessionMode ?? this.sessionModeOf(sessionId));
|
|
@@ -2493,6 +2714,18 @@ export function mapSdkEvent(sessionId, event, compactionId, step = 1) {
|
|
|
2493
2714
|
? { parentToolCallId: event.parentToolCallId }
|
|
2494
2715
|
: {}),
|
|
2495
2716
|
};
|
|
2717
|
+
case "tool_execution_update":
|
|
2718
|
+
return {
|
|
2719
|
+
type: "tool_update",
|
|
2720
|
+
sessionId,
|
|
2721
|
+
toolCallId: event.toolCallId,
|
|
2722
|
+
toolName: event.toolName,
|
|
2723
|
+
partialResult: event.partialResult,
|
|
2724
|
+
step,
|
|
2725
|
+
...(event.parentToolCallId
|
|
2726
|
+
? { parentToolCallId: event.parentToolCallId }
|
|
2727
|
+
: {}),
|
|
2728
|
+
};
|
|
2496
2729
|
case "tool_execution_end":
|
|
2497
2730
|
return {
|
|
2498
2731
|
type: "tool_result",
|
|
@@ -127,6 +127,55 @@ export async function listRepoDirectory(repoRoot, rawPath) {
|
|
|
127
127
|
throw error;
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
|
+
/** Composer `@` palette keeps the first page of a directory listing scannable. */
|
|
131
|
+
export const FILE_PALETTE_LIMIT = 50;
|
|
132
|
+
/**
|
|
133
|
+
* Split an `@` token query into a directory listing target and basename filter.
|
|
134
|
+
* Empty or slash-free queries stay on the workspace root (M3 fuzzy is out of
|
|
135
|
+
* scope). A trailing slash lists that directory with an empty fragment.
|
|
136
|
+
*/
|
|
137
|
+
export function parseFilePaletteQuery(rawQuery) {
|
|
138
|
+
const query = rawQuery.replaceAll("\\", "/").replace(/^\/+/u, "");
|
|
139
|
+
const slash = query.lastIndexOf("/");
|
|
140
|
+
if (slash < 0)
|
|
141
|
+
return { directory: "", fragment: query };
|
|
142
|
+
return {
|
|
143
|
+
directory: query.slice(0, slash),
|
|
144
|
+
fragment: query.slice(slash + 1),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
export function projectFilePaletteEntries(entries, fragment) {
|
|
148
|
+
const showDots = fragment.startsWith(".");
|
|
149
|
+
const needle = fragment.toLowerCase();
|
|
150
|
+
const projected = [];
|
|
151
|
+
for (const entry of entries) {
|
|
152
|
+
if (!showDots && entry.name.startsWith("."))
|
|
153
|
+
continue;
|
|
154
|
+
if (needle !== "" && !entry.name.toLowerCase().includes(needle))
|
|
155
|
+
continue;
|
|
156
|
+
const isDir = entry.kind === "directory";
|
|
157
|
+
projected.push({
|
|
158
|
+
path: isDir ? `${entry.path}/` : entry.path,
|
|
159
|
+
isDir,
|
|
160
|
+
});
|
|
161
|
+
if (projected.length >= FILE_PALETTE_LIMIT)
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
return projected;
|
|
165
|
+
}
|
|
166
|
+
/** One-level `@` file palette listing. Unreadable or out-of-repo queries are empty. */
|
|
167
|
+
export async function listChatFilePalette(repoRoot, rawQuery) {
|
|
168
|
+
const { directory, fragment } = parseFilePaletteQuery(rawQuery);
|
|
169
|
+
try {
|
|
170
|
+
const listed = await listRepoDirectory(repoRoot, directory);
|
|
171
|
+
return projectFilePaletteEntries(listed.entries, fragment);
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
if (error instanceof RepoBrowserError)
|
|
175
|
+
return [];
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
130
179
|
export async function readRepoPreview(repoRoot, rawPath) {
|
|
131
180
|
const guard = await guardReadPath(repoRoot, rawPath);
|
|
132
181
|
if (!guard.ok)
|