@tea-agent/loop-agent 0.40.0-next.11 → 0.40.0-next.13
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 +45 -0
- package/README.md +1 -1
- 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/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/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 +485 -29
- package/dist/worker/console/chat/session-catalog.js +48 -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 +32 -3
- package/dist/worker/console/operator-actions.js +16 -2
- 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 +100 -0
- package/dist/worker/console/routes.js +221 -6
- package/dist/worker/console/server.js +172 -42
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-Bs-CDAXM.js → abnfDiagram-N423BO3Z-Wj-fsQlk.js} +1 -1
- package/dist/worker/console/static/assets/{arc-CAkA3We3.js → arc-CkXT-vzQ.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-DEmI_zqr.js → architectureDiagram-T3A2C74G-xlfnojWU.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-uDHANebE.js → blockDiagram-VBNYF7ZC-BilahvuB.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-Bv97b4_B.js → c4Diagram-5PPSVZJV-DqtAVhjz.js} +1 -1
- package/dist/worker/console/static/assets/channel-SnQ_u-Td.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-shmQKsFz.js → chunk-2GRJ4B5K-pAqQXZ5y.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-BAraNvcN.js → chunk-2Q5K7J3B-BEWxeq2r.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BirhxUop.js → chunk-5RXB4S5H-CvlbGDTp.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-C9LgUJpR.js → chunk-5VM5RSS4-D0uGd9-f.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DrU-s-t7.js → chunk-6Q2QTUOP-DSdWIteg.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-Tx-H_FA2.js → chunk-GF5L2VYU-Dweg7f0v.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BjLtNFrR.js → chunk-JWPE2WC7-BpZKI_k7.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-UNLVwSsy.js → chunk-KBJHAD2P-IPLknC4m.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-CBEUX8XD.js → chunk-RYQCIY6F-E93k9lVI.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-WTL7IZOq.js → chunk-XXDRQBXY-BrESwkPq.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-SGM51NVY.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-SGM51NVY.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CkHG6W3s.js → cose-bilkent-JH36ORCC-DmFHvJkB.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BRzFqTaL.js → cynefin-VYW2F7L2-CDigXiSL.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-2_CFp_i7.js → cynefinDiagram-MW4NZA55-B0zhrbaA.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BJtsmdkE.js → dagre-VZM6K2ZE-DrKybVxm.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-DNEFFo6w.js → diagram-7IWD3JNH-CeUrnbFk.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-B_IWV7eo.js → diagram-B4RE2ZJO-BJyunUMi.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-DvvRx2dz.js → diagram-LBJQPF4R-a5TBP73u.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-CsibsWLg.js → diagram-Q27KOJAE-ChRgBURJ.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-les_djBQ.js → diagram-UB23O5K3-CqCnPRSk.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BEm2n7qJ.js → ebnfDiagram-BXEA7PRR-BI-UD9_S.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-BI7vHHVm.js → erDiagram-JOGREHBK-CDLvvkYZ.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CUFCERrB.js → flowDiagram-UKHOOZJN-Heoo4afj.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-wxyLiGWt.js → ganttDiagram-PKOTCBZU-kFpOitHd.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Bt897K8Z.js → gitGraphDiagram-DS77QQ5N-FvyZ9WAY.js} +1 -1
- package/dist/worker/console/static/assets/index-C80SO8y0.js +437 -0
- package/dist/worker/console/static/assets/index-CmJCHmJP.css +1 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DYNx_IPv.js → infoDiagram-6WML65LV-HBzlwtgI.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-CzpLNEu6.js → ishikawaDiagram-WSZJBQD7-C9Iim5sm.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-97f9owNU.js → journeyDiagram-NVQOT4AX-CJwJTg0S.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BxM9hyBn.js → kanban-definition-27J2QSJJ-CZNJ7S4q.js} +1 -1
- package/dist/worker/console/static/assets/{linear-ByuxcHvp.js → linear-RZ0AnGi8.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-DwPGvpCv.js → mermaid.core-EYSdm-nd.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-DCoqG9RT.js → mindmap-definition-FAOFIHXS-D0OLECFN.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BLSBmBMx.js → pegDiagram-VL7TDLO6-CPTvGbh7.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-B0t_0oJW.js → pieDiagram-7S7Q4E2Y-Ddc1aDea.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-sTzDk7Nt.js → quadrantDiagram-CIZ2JOQS-CWCTCdAt.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-B3jRdATC.js → railroadDiagram-AXF67PYL-CfsaBL8E.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-D-cTtXEN.js → requirementDiagram-LRYGKXZP-BH2rqGf6.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-B25igJRE.js → sankeyDiagram-W5VNT64P-BZgJ1Til.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-jW_lM1_D.js → sequenceDiagram-SI44F4Z6-DmPr-o-y.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-CrzTgsHE.js → sizeCapture-X5ZJPWSS-CF6HzDh_.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-B01MvlqE.js → stateDiagram-OKZ733FA-DhS8N_B9.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-N56zxwsk.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-YcF12FiU.js → swimlanes-SLNWSIFB-CYNzoiaD.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-o47kGgVt.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-ClnRcg2s.js → timeline-definition-Z64GVDOM-QBICF5qH.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-B6gr_z-q.js → vennDiagram-T6HMQDX7-fquBvWcf.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-CvSgguGH.js → wardleyDiagram-T6FBY63Y-BYaJLlSd.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-23OtSZCb.js → xychartDiagram-ELKLHX3M--ePe_JCJ.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 +24 -19
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +0 -11
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +8 -1
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +34 -4
- 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/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 +6 -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/init-hybrid.js +3 -3
- package/docs/architecture/runtime-boundaries.md +2 -1
- package/docs/templates/backend-test-dag.json +3 -3
- package/package.json +3 -2
- package/skills/loop-agent/references/command-reference.md +14 -0
- 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
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { projectDeferredTurnSummaries, projectDeferredTurnSummary, } from "./deferred-turn.js";
|
|
2
|
+
/**
|
|
3
|
+
* Process-wide Session baseline, mirroring DSH's independent session.list.
|
|
4
|
+
* Full records stay in their fingerprint-isolated stores; this catalog only
|
|
5
|
+
* removes repeated filesystem discovery and resolves Session ownership.
|
|
6
|
+
*/
|
|
7
|
+
export class ChatSessionCatalog {
|
|
8
|
+
entries = new Map();
|
|
9
|
+
upsert(record, ownerWorkspaceId) {
|
|
10
|
+
const workspaceId = ownerWorkspaceId?.trim() || record.workspaceId?.trim();
|
|
11
|
+
const existing = this.entries.get(record.sessionId);
|
|
12
|
+
if (existing &&
|
|
13
|
+
existing.repoFingerprint !== record.repoFingerprint) {
|
|
14
|
+
throw new Error(`chat session catalog conflict: ${record.sessionId} belongs to multiple repositories`);
|
|
15
|
+
}
|
|
16
|
+
this.entries.set(record.sessionId, {
|
|
17
|
+
sessionId: record.sessionId,
|
|
18
|
+
repoFingerprint: record.repoFingerprint,
|
|
19
|
+
repoRootDisplay: record.repoRootDisplay,
|
|
20
|
+
state: record.state,
|
|
21
|
+
...(record.title !== undefined ? { title: record.title } : {}),
|
|
22
|
+
...(record.displayTitle !== undefined
|
|
23
|
+
? { displayTitle: record.displayTitle }
|
|
24
|
+
: {}),
|
|
25
|
+
createdAt: record.createdAt,
|
|
26
|
+
updatedAt: record.updatedAt,
|
|
27
|
+
...(record.modelProvider !== undefined
|
|
28
|
+
? { modelProvider: record.modelProvider }
|
|
29
|
+
: {}),
|
|
30
|
+
...(record.modelId !== undefined ? { modelId: record.modelId } : {}),
|
|
31
|
+
...(record.thinkingLevel !== undefined
|
|
32
|
+
? { thinkingLevel: record.thinkingLevel }
|
|
33
|
+
: {}),
|
|
34
|
+
deferredTurn: projectDeferredTurnSummary(record.deferredTurns?.[0]),
|
|
35
|
+
deferredTurns: projectDeferredTurnSummaries(record.deferredTurns ?? []),
|
|
36
|
+
...(workspaceId ? { workspaceId } : {}),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
remove(sessionId) {
|
|
40
|
+
this.entries.delete(sessionId);
|
|
41
|
+
}
|
|
42
|
+
get(sessionId) {
|
|
43
|
+
return this.entries.get(sessionId);
|
|
44
|
+
}
|
|
45
|
+
list() {
|
|
46
|
+
return [...this.entries.values()].sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -40,14 +40,20 @@ function recordPath(appData, sessionId) {
|
|
|
40
40
|
}
|
|
41
41
|
export class ChatSessionStore {
|
|
42
42
|
appData;
|
|
43
|
+
options;
|
|
43
44
|
/**
|
|
44
45
|
* Per-session write lock. Each mutating op chains onto the previous one so
|
|
45
46
|
* concurrent appendMessage / recordToolInvocation calls do not lose updates
|
|
46
47
|
* via last-write-wins on the same JSON record.
|
|
47
48
|
*/
|
|
48
49
|
writeChains = new Map();
|
|
49
|
-
constructor(appData) {
|
|
50
|
+
constructor(appData, options = {}) {
|
|
50
51
|
this.appData = appData;
|
|
52
|
+
this.options = options;
|
|
53
|
+
}
|
|
54
|
+
async persist(record) {
|
|
55
|
+
await writeSecureJson(recordPath(this.appData, record.sessionId), record);
|
|
56
|
+
this.options.onRecordChange?.(record.sessionId, record);
|
|
51
57
|
}
|
|
52
58
|
/** Read + migrate legacy V1 records into the V2 in-memory shape. */
|
|
53
59
|
async get(sessionId) {
|
|
@@ -147,7 +153,7 @@ export class ChatSessionStore {
|
|
|
147
153
|
messages: [],
|
|
148
154
|
toolInvocations: [],
|
|
149
155
|
};
|
|
150
|
-
await
|
|
156
|
+
await this.persist(record);
|
|
151
157
|
return record;
|
|
152
158
|
});
|
|
153
159
|
}
|
|
@@ -169,7 +175,7 @@ export class ChatSessionStore {
|
|
|
169
175
|
messages: structuredClone(source.messages),
|
|
170
176
|
toolInvocations: structuredClone(source.toolInvocations),
|
|
171
177
|
};
|
|
172
|
-
await
|
|
178
|
+
await this.persist(record);
|
|
173
179
|
return record;
|
|
174
180
|
});
|
|
175
181
|
}
|
|
@@ -180,7 +186,7 @@ export class ChatSessionStore {
|
|
|
180
186
|
throw new Error(`chat session not found: ${sessionId}`);
|
|
181
187
|
record.title = title.trim().slice(0, 160) || undefined;
|
|
182
188
|
record.updatedAt = new Date().toISOString();
|
|
183
|
-
await
|
|
189
|
+
await this.persist(record);
|
|
184
190
|
return record;
|
|
185
191
|
});
|
|
186
192
|
}
|
|
@@ -195,7 +201,7 @@ export class ChatSessionStore {
|
|
|
195
201
|
return undefined;
|
|
196
202
|
record.title = cleaned;
|
|
197
203
|
record.updatedAt = new Date().toISOString();
|
|
198
|
-
await
|
|
204
|
+
await this.persist(record);
|
|
199
205
|
return record;
|
|
200
206
|
});
|
|
201
207
|
}
|
|
@@ -211,7 +217,7 @@ export class ChatSessionStore {
|
|
|
211
217
|
if (selection.thinkingLevel !== undefined)
|
|
212
218
|
record.thinkingLevel = selection.thinkingLevel;
|
|
213
219
|
record.updatedAt = new Date().toISOString();
|
|
214
|
-
await
|
|
220
|
+
await this.persist(record);
|
|
215
221
|
return record;
|
|
216
222
|
});
|
|
217
223
|
}
|
|
@@ -222,7 +228,7 @@ export class ChatSessionStore {
|
|
|
222
228
|
throw new Error(`chat session not found: ${sessionId}`);
|
|
223
229
|
record.state = state;
|
|
224
230
|
record.updatedAt = new Date().toISOString();
|
|
225
|
-
await
|
|
231
|
+
await this.persist(record);
|
|
226
232
|
return record;
|
|
227
233
|
});
|
|
228
234
|
}
|
|
@@ -232,6 +238,7 @@ export class ChatSessionStore {
|
|
|
232
238
|
if (!record)
|
|
233
239
|
return false;
|
|
234
240
|
await rm(recordPath(this.appData, sessionId), { force: true });
|
|
241
|
+
this.options.onRecordChange?.(sessionId, undefined);
|
|
235
242
|
return true;
|
|
236
243
|
});
|
|
237
244
|
}
|
|
@@ -285,7 +292,7 @@ export class ChatSessionStore {
|
|
|
285
292
|
record.deferredTurn = queue[0];
|
|
286
293
|
record.deferredQueueRevision = (record.deferredQueueRevision ?? 0) + 1;
|
|
287
294
|
record.updatedAt = now;
|
|
288
|
-
await
|
|
295
|
+
await this.persist(record);
|
|
289
296
|
return { ok: true, deferredTurn, idempotent: false };
|
|
290
297
|
});
|
|
291
298
|
}
|
|
@@ -313,7 +320,7 @@ export class ChatSessionStore {
|
|
|
313
320
|
record.deferredTurn = queue[0];
|
|
314
321
|
record.deferredQueueRevision = (record.deferredQueueRevision ?? 0) + 1;
|
|
315
322
|
record.updatedAt = next.updatedAt;
|
|
316
|
-
await
|
|
323
|
+
await this.persist(record);
|
|
317
324
|
return { ok: true, deferredTurn: next };
|
|
318
325
|
});
|
|
319
326
|
}
|
|
@@ -335,7 +342,7 @@ export class ChatSessionStore {
|
|
|
335
342
|
record.deferredTurn = queue[0];
|
|
336
343
|
record.deferredQueueRevision = (record.deferredQueueRevision ?? 0) + 1;
|
|
337
344
|
record.updatedAt = next.updatedAt;
|
|
338
|
-
await
|
|
345
|
+
await this.persist(record);
|
|
339
346
|
return next;
|
|
340
347
|
});
|
|
341
348
|
}
|
|
@@ -356,7 +363,7 @@ export class ChatSessionStore {
|
|
|
356
363
|
record.deferredTurn = queue[0];
|
|
357
364
|
record.deferredQueueRevision = (record.deferredQueueRevision ?? 0) + 1;
|
|
358
365
|
record.updatedAt = new Date().toISOString();
|
|
359
|
-
await
|
|
366
|
+
await this.persist(record);
|
|
360
367
|
return { ok: true, deferredTurn: existing };
|
|
361
368
|
});
|
|
362
369
|
}
|
|
@@ -373,7 +380,7 @@ export class ChatSessionStore {
|
|
|
373
380
|
record.deferredTurn = queue[0];
|
|
374
381
|
record.deferredQueueRevision = (record.deferredQueueRevision ?? 0) + 1;
|
|
375
382
|
record.updatedAt = new Date().toISOString();
|
|
376
|
-
await
|
|
383
|
+
await this.persist(record);
|
|
377
384
|
return { deferredTurn: existing, clearedRevision: existing.revision + 1 };
|
|
378
385
|
});
|
|
379
386
|
}
|
|
@@ -392,7 +399,7 @@ export class ChatSessionStore {
|
|
|
392
399
|
record.displayTitle = cleanChatTitle(stored.text);
|
|
393
400
|
}
|
|
394
401
|
record.updatedAt = stored.at;
|
|
395
|
-
await
|
|
402
|
+
await this.persist(record);
|
|
396
403
|
return stored;
|
|
397
404
|
});
|
|
398
405
|
}
|
|
@@ -403,7 +410,7 @@ export class ChatSessionStore {
|
|
|
403
410
|
return;
|
|
404
411
|
record.toolInvocations.push({ ...entry, at: new Date().toISOString() });
|
|
405
412
|
record.updatedAt = new Date().toISOString();
|
|
406
|
-
await
|
|
413
|
+
await this.persist(record);
|
|
407
414
|
});
|
|
408
415
|
}
|
|
409
416
|
}
|
|
@@ -501,10 +508,12 @@ export async function runChatTurn(options) {
|
|
|
501
508
|
},
|
|
502
509
|
};
|
|
503
510
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
511
|
+
if (options.persistUserMessage !== false) {
|
|
512
|
+
const userMessage = await store.appendMessage(sessionId, { role: "user", text });
|
|
513
|
+
const afterUserMessage = await store.get(sessionId);
|
|
514
|
+
if (afterUserMessage)
|
|
515
|
+
await options.onUserMessagePersisted?.(afterUserMessage, userMessage);
|
|
516
|
+
}
|
|
508
517
|
let turnError;
|
|
509
518
|
// Collect persistence promises so runChatTurn does not resolve before the
|
|
510
519
|
// chat history / audit trail is durably written (also makes the outcome
|
|
@@ -44,6 +44,13 @@ export const SHORTCUTS = [
|
|
|
44
44
|
];
|
|
45
45
|
/** Pi Web commands with real browser-equivalent behavior (UI-11). */
|
|
46
46
|
export const WEB_SLASH_COMMANDS = [
|
|
47
|
+
{
|
|
48
|
+
command: "/goal",
|
|
49
|
+
label: "持续目标",
|
|
50
|
+
description: "创建或编辑一个跨多个回合持续推进的目标",
|
|
51
|
+
action: "goal",
|
|
52
|
+
source: "web",
|
|
53
|
+
},
|
|
47
54
|
{
|
|
48
55
|
command: "/compact",
|
|
49
56
|
label: "压缩上下文",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createSiftBridgeState, parseSiftBridgeConfig, compressProviderPayload, executeSiftRetrieve, housekeepSiftStash, createSiftRetrieveToolDefinition, SIFT_RETRIEVE_TOOL_NAME, SIFT_POLICY_VERSION, } from "../../../shared/pi-context-pressure/sift-bridge.js";
|
|
@@ -34,17 +34,21 @@ export function hydrateSessionThread(raw) {
|
|
|
34
34
|
for (const item of raw) {
|
|
35
35
|
const createdAt = Date.parse(item.at) || Date.now();
|
|
36
36
|
if (item.role === "user") {
|
|
37
|
-
turnId = `restored-${item.id}`;
|
|
37
|
+
turnId = item.turnId ?? `restored-${item.id}`;
|
|
38
38
|
pendingTools = [];
|
|
39
39
|
messages.push({
|
|
40
40
|
id: item.id,
|
|
41
41
|
role: "user",
|
|
42
42
|
text: item.text,
|
|
43
43
|
createdAt,
|
|
44
|
+
...(item.eventSeq === undefined ? {} : { eventSeq: item.eventSeq }),
|
|
45
|
+
...(item.turnId ? { turnId: item.turnId } : {}),
|
|
44
46
|
});
|
|
45
47
|
continue;
|
|
46
48
|
}
|
|
47
49
|
if (item.role === "assistant") {
|
|
50
|
+
if (item.turnId)
|
|
51
|
+
turnId = item.turnId;
|
|
48
52
|
if (!turnId)
|
|
49
53
|
turnId = `restored-${item.id}`;
|
|
50
54
|
const content = parseAssistantContent(item.content);
|
|
@@ -53,6 +57,8 @@ export function hydrateSessionThread(raw) {
|
|
|
53
57
|
role: "assistant",
|
|
54
58
|
text: item.text,
|
|
55
59
|
createdAt,
|
|
60
|
+
...(item.eventSeq === undefined ? {} : { eventSeq: item.eventSeq }),
|
|
61
|
+
...(item.turnId ? { turnId: item.turnId } : {}),
|
|
56
62
|
...(item.kind === "provider-error" && item.providerError
|
|
57
63
|
? { kind: item.kind, providerError: item.providerError }
|
|
58
64
|
: {}),
|
|
@@ -62,6 +68,8 @@ export function hydrateSessionThread(raw) {
|
|
|
62
68
|
continue;
|
|
63
69
|
}
|
|
64
70
|
if (item.role === "tool") {
|
|
71
|
+
if (item.turnId)
|
|
72
|
+
turnId = item.turnId;
|
|
65
73
|
if (!turnId)
|
|
66
74
|
turnId = `restored-tool-${item.id}`;
|
|
67
75
|
const entry = {
|
|
@@ -72,7 +80,11 @@ export function hydrateSessionThread(raw) {
|
|
|
72
80
|
result: item.text,
|
|
73
81
|
createdAt,
|
|
74
82
|
finishedAt: createdAt,
|
|
75
|
-
turnId,
|
|
83
|
+
turnId: item.turnId ?? turnId,
|
|
84
|
+
...(item.eventSeq === undefined ? {} : { eventSeq: item.eventSeq }),
|
|
85
|
+
...(item.finishedSeq === undefined
|
|
86
|
+
? {}
|
|
87
|
+
: { finishedSeq: item.finishedSeq }),
|
|
76
88
|
...(item.operationId ? { operationId: item.operationId } : {}),
|
|
77
89
|
};
|
|
78
90
|
toolCalls.push(entry);
|
|
@@ -196,6 +208,8 @@ function fillProcessDetails(group) {
|
|
|
196
208
|
group.answer = finalAssistant;
|
|
197
209
|
return;
|
|
198
210
|
}
|
|
211
|
+
if (split.answerBlocks.length === 0)
|
|
212
|
+
return;
|
|
199
213
|
const answerText = joinAssistantText(split.answerBlocks);
|
|
200
214
|
group.answer = {
|
|
201
215
|
...finalAssistant,
|
|
@@ -207,7 +221,22 @@ function fillProcessDetails(group) {
|
|
|
207
221
|
* Build user → process → answer groups for the message timeline.
|
|
208
222
|
*/
|
|
209
223
|
export function buildTurnProcessGroups(input) {
|
|
210
|
-
const visible = input.messages
|
|
224
|
+
const visible = input.messages
|
|
225
|
+
.filter((m) => m.role === "user" || m.role === "assistant")
|
|
226
|
+
.sort((a, b) => {
|
|
227
|
+
if (a.eventSeq !== undefined &&
|
|
228
|
+
b.eventSeq !== undefined &&
|
|
229
|
+
a.eventSeq !== b.eventSeq) {
|
|
230
|
+
return a.eventSeq - b.eventSeq;
|
|
231
|
+
}
|
|
232
|
+
if (a.createdAt !== b.createdAt)
|
|
233
|
+
return a.createdAt - b.createdAt;
|
|
234
|
+
if (a.eventSeq !== undefined && b.eventSeq === undefined)
|
|
235
|
+
return 1;
|
|
236
|
+
if (a.eventSeq === undefined && b.eventSeq !== undefined)
|
|
237
|
+
return -1;
|
|
238
|
+
return 0;
|
|
239
|
+
});
|
|
211
240
|
const groups = [];
|
|
212
241
|
let current = null;
|
|
213
242
|
const startGroup = (key) => {
|
|
@@ -1148,14 +1148,14 @@ export async function dispatchOperatorAction(ctx, req) {
|
|
|
1148
1148
|
if (usesUnifiedSurface) {
|
|
1149
1149
|
const inspectPath = target
|
|
1150
1150
|
? buildInspectDeepLink(consoleOrigin, target).slice(consoleOrigin.length)
|
|
1151
|
-
: "
|
|
1151
|
+
: "/#/inspect";
|
|
1152
1152
|
return {
|
|
1153
1153
|
kind: "sync",
|
|
1154
1154
|
status: 200,
|
|
1155
1155
|
body: operatorSucceeded("observeLink", {
|
|
1156
1156
|
url: target
|
|
1157
1157
|
? buildInspectDeepLink(consoleOrigin, target)
|
|
1158
|
-
: `${consoleOrigin.replace(/\/+$/, "")}
|
|
1158
|
+
: `${consoleOrigin.replace(/\/+$/, "")}/#/inspect`,
|
|
1159
1159
|
inspectPath,
|
|
1160
1160
|
status: "same-origin",
|
|
1161
1161
|
requiredCapability: requiredCapability ?? null,
|
|
@@ -1817,6 +1817,18 @@ export async function dispatchOperatorAction(ctx, req) {
|
|
|
1817
1817
|
const taskIdError = taskIdInputError(taskId);
|
|
1818
1818
|
if (taskIdError)
|
|
1819
1819
|
return invalid(action, taskIdError);
|
|
1820
|
+
// Optional write-set gate approval: the token is the server-issued
|
|
1821
|
+
// `<gate-id>:sha256:<hex>` that `task status` reports in
|
|
1822
|
+
// gate.approveCommand. Forwarded as --approve-gate so an operator can
|
|
1823
|
+
// complete the human approval through the Console operation path
|
|
1824
|
+
// instead of dropping to a raw terminal. This dispatch already sits
|
|
1825
|
+
// behind the Console mutation gate (boot cookie + confirmation
|
|
1826
|
+
// header), so it carries the same authority as typing the CLI flag.
|
|
1827
|
+
const approveGateRaw = str(p.approveGate);
|
|
1828
|
+
if (approveGateRaw &&
|
|
1829
|
+
!/^[A-Za-z0-9._-]+:sha256:[0-9a-f]{64}$/.test(approveGateRaw)) {
|
|
1830
|
+
return invalid(action, "approveGate must look like <gate-id>:sha256:<64-hex> (copy the token from task status gate.approveCommand)");
|
|
1831
|
+
}
|
|
1820
1832
|
const args = ["task", "advance", taskId];
|
|
1821
1833
|
const title = str(p.title);
|
|
1822
1834
|
if (title)
|
|
@@ -1830,6 +1842,8 @@ export async function dispatchOperatorAction(ctx, req) {
|
|
|
1830
1842
|
const profile = str(p.profile);
|
|
1831
1843
|
if (profile)
|
|
1832
1844
|
args.push("--profile", profile);
|
|
1845
|
+
if (approveGateRaw)
|
|
1846
|
+
args.push("--approve-gate", approveGateRaw);
|
|
1833
1847
|
appendEngineeringCliArgs(args, parseEngineeringBoundaryFromParams(p));
|
|
1834
1848
|
args.push("--json");
|
|
1835
1849
|
return acceptOperation(ctx, {
|
|
@@ -27,7 +27,11 @@ export function encodeInspectHash(selection) {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
export function buildInspectPath(selection) {
|
|
30
|
-
|
|
30
|
+
if (!selection)
|
|
31
|
+
return "/#/inspect";
|
|
32
|
+
const hash = encodeInspectHash(selection);
|
|
33
|
+
const internal = hash.startsWith("#") ? hash.slice(1) : hash;
|
|
34
|
+
return `/#/inspect${internal}`;
|
|
31
35
|
}
|
|
32
36
|
export function buildInspectUrl(origin, selection) {
|
|
33
37
|
const base = origin.trim().replace(/\/+$/, "");
|
|
@@ -99,7 +103,7 @@ export function selectionFromObserveLinkTarget(target) {
|
|
|
99
103
|
export function normalizeLegacyConsoleDagHash(pathnameAndHash) {
|
|
100
104
|
const [pathname, hash = ""] = pathnameAndHash.split("#", 2);
|
|
101
105
|
if ((pathname === "/" || pathname === "") && /^\/dag\/[^/]+$/.test(hash)) {
|
|
102
|
-
return
|
|
106
|
+
return `/#/inspect${hash}`;
|
|
103
107
|
}
|
|
104
108
|
return pathnameAndHash;
|
|
105
109
|
}
|