@tea-agent/loop-agent 0.43.0-next.2 → 0.43.0-next.4
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 +15 -12
- package/dist/application/dag/run-dag.js +5 -0
- package/dist/build-stamp.json +3 -3
- package/dist/executors/dag-pi-executor.js +274 -172
- package/dist/shared/frontend-execution-policy.js +1 -0
- package/dist/worker/console/chat/assistant-content.js +23 -2
- package/dist/worker/console/chat/explore-tools.js +13 -0
- package/dist/worker/console/chat/pi-runtime.js +18 -0
- package/dist/worker/console/chat/routes.js +11 -0
- package/dist/worker/console/chat/sdd-data-alignment.js +65 -9
- package/dist/worker/console/chat/terminal-routes.js +216 -0
- package/dist/worker/console/chat/terminal-sessions.js +284 -0
- package/dist/worker/console/chat/terminal-tools.js +199 -0
- package/dist/worker/console/chat/tool-preview.js +11 -0
- package/dist/worker/console/chat/tools.js +1 -0
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-B0Q0nClf.js → abnfDiagram-N423BO3Z-CCj36aaC.js} +1 -1
- package/dist/worker/console/static/assets/{arc-DCPjC19G.js → arc-Cl3MIVFh.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-CP5n9jmG.js → architectureDiagram-T3A2C74G-C_n4kMJS.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-CmaWi_Wg.js → blockDiagram-VBNYF7ZC-DlWYJ7cK.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-Ct5tcMfZ.js → c4Diagram-5PPSVZJV-Ud5pS7vS.js} +1 -1
- package/dist/worker/console/static/assets/channel-CEMRpNm-.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-C0osm1Zf.js → chunk-2GRJ4B5K-CQPwOv_j.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-CDWviED7.js → chunk-2Q5K7J3B-CMzjxrWI.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-mtSk1-j7.js → chunk-5RXB4S5H-pcnXnD6t.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-D5J9PHC7.js → chunk-5VM5RSS4-CEB3AvU2.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-Begg4WAa.js → chunk-6Q2QTUOP-DSKnbXbp.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-sF1AEy7T.js → chunk-GF5L2VYU-CS6-PjCZ.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BqbsWXZb.js → chunk-JWPE2WC7-f6q8Tnzz.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BKJrPcJ6.js → chunk-KBJHAD2P-DkB0QX3q.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-CcwNMRho.js → chunk-RYQCIY6F-BdB4jAv6.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-BEJi3iIs.js → chunk-XXDRQBXY-BVm1bnX6.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C9lhaZkR.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C9lhaZkR.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-DRLgTvVu.js → cose-bilkent-JH36ORCC-FV_P-IEp.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BoAVG3cs.js → cynefin-VYW2F7L2-BM7RtkA2.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-Bzol06hR.js → cynefinDiagram-MW4NZA55-C1BZwTG5.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-UmliJM77.js → dagre-VZM6K2ZE-C6McNKmY.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-BWLcJkFo.js → diagram-7IWD3JNH-C0aWRUaE.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-CgApOm-O.js → diagram-B4RE2ZJO-Bfk_SKE8.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-Bh3RgTLs.js → diagram-LBJQPF4R-prx1T4qf.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-Dsh-D5nE.js → diagram-Q27KOJAE-DBvty0eU.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-Dkbbpcpb.js → diagram-UB23O5K3-CF0em8e9.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-3EBaA3t3.js → ebnfDiagram-BXEA7PRR-CF90b4Ws.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-Bq2Dc5ok.js → erDiagram-JOGREHBK-hfunxzof.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-De7y55ha.js → flowDiagram-UKHOOZJN-D-QSy4Nl.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-fLiDbQRh.js → ganttDiagram-PKOTCBZU-DaBGNcvT.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Du617mp1.js → gitGraphDiagram-DS77QQ5N-BChcubGL.js} +1 -1
- package/dist/worker/console/static/assets/index-CJkCY1XR.js +464 -0
- package/dist/worker/console/static/assets/index-DUBCbiqv.css +1 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-BwmlF-XP.js → infoDiagram-6WML65LV-BkC67fIa.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-zsGtS59u.js → ishikawaDiagram-WSZJBQD7-ibhLczCD.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DTTPTe3f.js → journeyDiagram-NVQOT4AX-DCRMitay.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BkXg9aP-.js → kanban-definition-27J2QSJJ-DJ_hKaYI.js} +1 -1
- package/dist/worker/console/static/assets/{linear-7U2ue5IE.js → linear-CIlLsYsA.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-BUuGHmWO.js → mermaid.core-C-5IQMP_.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-7q6fX0Sv.js → mindmap-definition-FAOFIHXS-TCzV5TQT.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-CkQPJN55.js → pegDiagram-VL7TDLO6-bfhd2BQH.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-CCal_tfX.js → pieDiagram-7S7Q4E2Y-BxFRAm5N.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-B7bpxyAZ.js → quadrantDiagram-CIZ2JOQS-C-m12lxv.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-CJmww7D-.js → railroadDiagram-AXF67PYL-CwmLiGgx.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-D6ldWJEv.js → requirementDiagram-LRYGKXZP-oc0Q1jiD.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-VGh33I9e.js → sankeyDiagram-W5VNT64P-9Ght6Yur.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-CCkDrIjU.js → sequenceDiagram-SI44F4Z6-ndm3lyz9.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-NC8f5Otb.js → sizeCapture-X5ZJPWSS-7sPlKVcw.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-_92ezZdF.js → stateDiagram-OKZ733FA-Izl21-oS.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-CmElLFpP.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-BdUCGtbP.js → swimlanes-SLNWSIFB-CtO3D65o.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DKRbGG8V.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-CdD1H8ia.js → timeline-definition-Z64GVDOM-Cyg5cY7z.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-Dkdk3oFo.js → vennDiagram-T6HMQDX7-CwtE_TFK.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-CKu2uPPY.js → wardleyDiagram-T6FBY63Y-Dtt9v8OO.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-ClqAnuG8.js → xychartDiagram-ELKLHX3M-B2Y3ryb6.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +122 -10
- package/dist/worker/console/static-src/operator-chat/pending-user-message.js +27 -15
- package/dist/worker/console/static-src/operator-chat/process-label.js +41 -0
- package/dist/worker/console/static-src/operator-chat/turn-group-equality.js +13 -0
- package/dist/worker/console/static-src/operator-chat/use-searchable-hidden.js +51 -0
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +18 -2
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +39 -4
- package/dist/worker/console/static-src/operator-chat/user-turn-anchor-equality.js +21 -0
- package/dist/worker/console/workspace-context.js +9 -1
- package/dist/workflows/dag/frontend-shape.js +30 -1
- package/dist/workflows/dag/node-execution.js +6 -0
- package/package.json +6 -3
- package/dist/worker/console/static/assets/channel-DAS07MdS.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-Cwk-5jiW.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-Cwk-5jiW.js +0 -1
- package/dist/worker/console/static/assets/index-C0O48S_P.js +0 -449
- package/dist/worker/console/static/assets/index-CzKf4U8P.css +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DyJg5gzW.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-B1cw_0Uy.js +0 -8
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { useEffect, useLayoutEffect, useRef } from "react";
|
|
2
|
+
/** Whether this browser can reveal `hidden="until-found"` content through
|
|
3
|
+
* `beforematch` (Chrome 102+, Firefox 148+, Safari: not supported at all).
|
|
4
|
+
* `content-visibility` support does NOT imply this — Safari 18+ and
|
|
5
|
+
* Firefox 125–147 have the former without the latter. */
|
|
6
|
+
function supportsUntilFound() {
|
|
7
|
+
return typeof document !== "undefined" && "onbeforematch" in document.body;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Collapse content without removing it from the document: the element gets
|
|
11
|
+
* `hidden="until-found"` so browser find-in-page can still reach the text, and
|
|
12
|
+
* a match fires `beforematch`, which reveals (expands) the disclosure again.
|
|
13
|
+
*
|
|
14
|
+
* Mirrors DSH `useSearchableHidden` (2026-09-08 alignment). Browsers without
|
|
15
|
+
* `until-found` support get a plain `hidden=""` element, which keeps the
|
|
16
|
+
* pre-alignment behavior (collapsed and not searchable).
|
|
17
|
+
*
|
|
18
|
+
* @param hidden - whether the content is collapsed.
|
|
19
|
+
* @param reveal - expand callback invoked on `beforematch` and when the
|
|
20
|
+
* collapsed subtree already owns focus.
|
|
21
|
+
* @returns ref for the collapsible container.
|
|
22
|
+
*/
|
|
23
|
+
export function useSearchableHidden(hidden, reveal) {
|
|
24
|
+
const ref = useRef(null);
|
|
25
|
+
useLayoutEffect(() => {
|
|
26
|
+
const element = ref.current;
|
|
27
|
+
if (element === null)
|
|
28
|
+
return;
|
|
29
|
+
// Focus would otherwise be lost inside a hidden subtree.
|
|
30
|
+
if (hidden && element.contains(element.ownerDocument.activeElement)) {
|
|
31
|
+
reveal();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (hidden) {
|
|
35
|
+
element.setAttribute("hidden", supportsUntilFound() ? "until-found" : "");
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
element.removeAttribute("hidden");
|
|
39
|
+
}
|
|
40
|
+
}, [hidden, reveal]);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
const element = ref.current;
|
|
43
|
+
if (element === null)
|
|
44
|
+
return;
|
|
45
|
+
element.addEventListener("beforematch", reveal);
|
|
46
|
+
return () => {
|
|
47
|
+
element.removeEventListener("beforematch", reveal);
|
|
48
|
+
};
|
|
49
|
+
}, [reveal]);
|
|
50
|
+
return ref;
|
|
51
|
+
}
|
|
@@ -53,7 +53,11 @@ function clearEmptyAssistant(setMessages, assistantId) {
|
|
|
53
53
|
return;
|
|
54
54
|
setMessages((messages) => messages.filter((message) => !(message.id === assistantId &&
|
|
55
55
|
message.role === "assistant" &&
|
|
56
|
-
!message.text.trim()
|
|
56
|
+
!message.text.trim() &&
|
|
57
|
+
// A row carrying only thinking/tool blocks is real content. Deleting
|
|
58
|
+
// it here dropped the turn's process nodes while the settled path in
|
|
59
|
+
// chat-sse-events deliberately keeps them (2026-09-08).
|
|
60
|
+
!(message.content && message.content.length > 0))));
|
|
57
61
|
}
|
|
58
62
|
/** One GET /events stream owns all Chat events. Sending a prompt creates a
|
|
59
63
|
* detached Turn resource only; it never opens a second inline SSE consumer. */
|
|
@@ -140,7 +144,10 @@ export function useChatStream(params) {
|
|
|
140
144
|
current.generation === generation)
|
|
141
145
|
current.ready = true;
|
|
142
146
|
replay = false;
|
|
143
|
-
|
|
147
|
+
// Fall through: the applier owns the buffered-replay flush and
|
|
148
|
+
// returns immediately for this event. `continue` here silently
|
|
149
|
+
// dropped that flush, so a reconnect that landed after the
|
|
150
|
+
// turn settled never restored the answer (2026-09-08).
|
|
144
151
|
}
|
|
145
152
|
const assistantId = refs.assistantIdRef.current ?? fallbackAssistantId;
|
|
146
153
|
const eventId = applySseBlock(block, assistantId, {
|
|
@@ -713,6 +720,15 @@ export function useChatStream(params) {
|
|
|
713
720
|
if (refs.sessionRef.current?.sessionId !== activeSession.sessionId ||
|
|
714
721
|
refs.sessionGenerationRef.current !== generation) {
|
|
715
722
|
releaseSubmitOwnership(clientRequestId);
|
|
723
|
+
if (refs.sessionRef.current?.sessionId === activeSession.sessionId) {
|
|
724
|
+
// Same session, newer generation: the activation snapshot replaced
|
|
725
|
+
// the thread, so the optimistic row is gone. Restore the draft
|
|
726
|
+
// instead of losing the user's text silently (2026-09-08).
|
|
727
|
+
setMessages((messages) => removePendingSubmission(messages, clientRequestId));
|
|
728
|
+
clearEmptyAssistant(setMessages, assistantId);
|
|
729
|
+
setInput(draftText);
|
|
730
|
+
setPendingImages(draftImages);
|
|
731
|
+
}
|
|
716
732
|
return;
|
|
717
733
|
}
|
|
718
734
|
// Attachments stay until accepted (AC/UIS-accepted).
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
1
|
+
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from "react";
|
|
2
2
|
import { buildTurnProcessGroups, hydrateSessionThread, selectRecentTurnGroups, } from "../../chat/turn-process.js";
|
|
3
|
+
import { isToolFailure } from "../../chat/tool-preview.js";
|
|
3
4
|
import { mergeOperationCardState, } from "../../chat/operation-card.js";
|
|
4
5
|
import { createChatSseEventApplier, } from "./chat-sse-events.js";
|
|
5
6
|
import { mergePendingSubmissionOnHydration } from "./pending-user-message.js";
|
|
6
7
|
import { taskContextUnchanged } from "./format.js";
|
|
7
8
|
import { upsertCompactionMessage } from "./compaction-message.js";
|
|
9
|
+
import { sameTurnGroupInputs } from "./turn-group-equality.js";
|
|
8
10
|
const EMPTY_USAGE = {
|
|
9
11
|
inputTokens: 0,
|
|
10
12
|
outputTokens: 0,
|
|
@@ -115,6 +117,12 @@ export function useChatThread(params) {
|
|
|
115
117
|
// (UI-08); the SSE applier must not open the process panel.
|
|
116
118
|
void params.setProcessOpen;
|
|
117
119
|
const [messages, setMessages] = useState([]);
|
|
120
|
+
/** Rendered-messages mirror for the replay flush: it must resolve its target
|
|
121
|
+
* row synchronously, before React commits the queued updater (2026-09-08). */
|
|
122
|
+
const messagesRef = useRef([]);
|
|
123
|
+
useLayoutEffect(() => {
|
|
124
|
+
messagesRef.current = messages;
|
|
125
|
+
}, [messages]);
|
|
118
126
|
const [toolCalls, setToolCalls] = useState([]);
|
|
119
127
|
const [operationCards, setOperationCards] = useState([]);
|
|
120
128
|
const [artifactCards, setArtifactCards] = useState([]);
|
|
@@ -187,6 +195,7 @@ export function useChatThread(params) {
|
|
|
187
195
|
onTelemetryRefresh: () => void refreshSessionTelemetry(),
|
|
188
196
|
setMessages,
|
|
189
197
|
setToolCalls,
|
|
198
|
+
getMessages: () => messagesRef.current,
|
|
190
199
|
}), [refs, onReconcile, setError, refreshSessionTelemetry]);
|
|
191
200
|
/** Parse + apply one raw SSE block (frames separated by \n\n). Returns the
|
|
192
201
|
* eventId if the block carried an `id:` line (for Last-Event-ID tracking). */
|
|
@@ -285,7 +294,7 @@ export function useChatThread(params) {
|
|
|
285
294
|
if (toolCalls.length === 0)
|
|
286
295
|
return null;
|
|
287
296
|
const running = toolCalls.filter((t) => t.status === "running");
|
|
288
|
-
const errored = toolCalls.filter((t) => t
|
|
297
|
+
const errored = toolCalls.filter((t) => isToolFailure(t));
|
|
289
298
|
const current = running[running.length - 1];
|
|
290
299
|
let statusLabel = "完成";
|
|
291
300
|
let statusKind = "ok";
|
|
@@ -348,7 +357,9 @@ export function useChatThread(params) {
|
|
|
348
357
|
const previous = new Map(completedGroupsRef.current.map((group) => [group.key, group]));
|
|
349
358
|
const all = built.map((group) => {
|
|
350
359
|
const cached = previous.get(group.key);
|
|
351
|
-
return cached && !group.live
|
|
360
|
+
return cached && !group.live && sameTurnGroupInputs(cached, group)
|
|
361
|
+
? cached
|
|
362
|
+
: group;
|
|
352
363
|
});
|
|
353
364
|
completedGroupsRef.current = all.filter((group) => !group.live);
|
|
354
365
|
previousTimelineRef.current = {
|
|
@@ -450,7 +461,31 @@ export function useChatThread(params) {
|
|
|
450
461
|
/** Adopt a freshly activated session's hydrated thread + streaming flags. */
|
|
451
462
|
const applyActivatedSession = useCallback((next) => {
|
|
452
463
|
const visuallyStopped = next.turnPhase === "stopping";
|
|
453
|
-
|
|
464
|
+
// A submission still owned for THIS session keeps its optimistic bubble
|
|
465
|
+
// across an activation snapshot (refresh / reopen); a lease owned by
|
|
466
|
+
// another session must never leak into this thread (2026-09-08).
|
|
467
|
+
const ownedPending = refs.pendingSubmissionRef.current?.sessionId ===
|
|
468
|
+
refs.sessionRef.current?.sessionId
|
|
469
|
+
? refs.pendingSubmissionRef.current
|
|
470
|
+
: undefined;
|
|
471
|
+
setMessages(mergePendingSubmissionOnHydration(next.messages, ownedPending
|
|
472
|
+
? {
|
|
473
|
+
clientRequestId: ownedPending.clientRequestId,
|
|
474
|
+
user: {
|
|
475
|
+
id: ownedPending.userMessageId,
|
|
476
|
+
role: "user",
|
|
477
|
+
text: ownedPending.text,
|
|
478
|
+
createdAt: Date.now(),
|
|
479
|
+
clientRequestId: ownedPending.clientRequestId,
|
|
480
|
+
},
|
|
481
|
+
assistant: {
|
|
482
|
+
id: ownedPending.assistantId,
|
|
483
|
+
role: "assistant",
|
|
484
|
+
text: "",
|
|
485
|
+
createdAt: Date.now(),
|
|
486
|
+
},
|
|
487
|
+
}
|
|
488
|
+
: undefined));
|
|
454
489
|
setToolCalls(next.toolCalls);
|
|
455
490
|
setOperationCards([]);
|
|
456
491
|
setHumanGateCards([]);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** User anchors only depend on the ordered user-message objects, not on
|
|
2
|
+
* assistant/process updates that rebuild their containing turn groups. */
|
|
3
|
+
export function sameUserMessages(previous, next) {
|
|
4
|
+
let previousIndex = 0;
|
|
5
|
+
let nextIndex = 0;
|
|
6
|
+
for (;;) {
|
|
7
|
+
while (previousIndex < previous.length && !previous[previousIndex].user) {
|
|
8
|
+
previousIndex += 1;
|
|
9
|
+
}
|
|
10
|
+
while (nextIndex < next.length && !next[nextIndex].user) {
|
|
11
|
+
nextIndex += 1;
|
|
12
|
+
}
|
|
13
|
+
if (previousIndex === previous.length || nextIndex === next.length) {
|
|
14
|
+
return previousIndex === previous.length && nextIndex === next.length;
|
|
15
|
+
}
|
|
16
|
+
if (previous[previousIndex].user !== next[nextIndex].user)
|
|
17
|
+
return false;
|
|
18
|
+
previousIndex += 1;
|
|
19
|
+
nextIndex += 1;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -37,6 +37,7 @@ import { UserQuestionRegistry } from "./chat/user-questions.js";
|
|
|
37
37
|
import { TodoListRegistry } from "./chat/todos.js";
|
|
38
38
|
import { GoalRegistry } from "./chat/goals.js";
|
|
39
39
|
import { GoalRoundDriver } from "./chat/goal-round-driver.js";
|
|
40
|
+
import { TerminalSessionRegistry } from "./chat/terminal-sessions.js";
|
|
40
41
|
import { driveGoalRound, recoverDeferredTurns } from "./chat/routes.js";
|
|
41
42
|
import { createOperationEventStore, } from "./operation-sse.js";
|
|
42
43
|
import { OperationStore } from "../../infrastructure/console/operation-store.js";
|
|
@@ -254,7 +255,9 @@ export async function createWorkspaceContext(record, deps) {
|
|
|
254
255
|
}
|
|
255
256
|
},
|
|
256
257
|
});
|
|
257
|
-
const
|
|
258
|
+
const aimaxAuth = new AimaxAuthReader();
|
|
259
|
+
await aimaxAuth.getToken();
|
|
260
|
+
const sddDataAlignment = new SddDataAlignmentService(chatStore, aimaxAuth, deps.fetchImpl);
|
|
258
261
|
const chatEventEpoch = randomBytes(12).toString("hex");
|
|
259
262
|
const chatEvents = createChatEventStore({
|
|
260
263
|
appData,
|
|
@@ -285,6 +288,9 @@ export async function createWorkspaceContext(record, deps) {
|
|
|
285
288
|
operations,
|
|
286
289
|
operationEvents: events,
|
|
287
290
|
});
|
|
291
|
+
// Persistent PTY terminal sessions shared by the model tool (terminal) and
|
|
292
|
+
// the Console UI terminal panel (HTTP API), keyed per chat session owner.
|
|
293
|
+
const terminalRegistry = new TerminalSessionRegistry();
|
|
288
294
|
const chatRuntime = new ConsolePiRuntime({
|
|
289
295
|
cwd: repoRoot,
|
|
290
296
|
sessionDir: appData.chatSessions,
|
|
@@ -294,6 +300,7 @@ export async function createWorkspaceContext(record, deps) {
|
|
|
294
300
|
todoRegistry,
|
|
295
301
|
goalRegistry,
|
|
296
302
|
sddDataAlignment,
|
|
303
|
+
terminalRegistry,
|
|
297
304
|
});
|
|
298
305
|
let chatRouteDeps;
|
|
299
306
|
const goalRoundDriver = new GoalRoundDriver((sessionId) => driveGoalRound(chatRouteDeps, sessionId));
|
|
@@ -308,6 +315,7 @@ export async function createWorkspaceContext(record, deps) {
|
|
|
308
315
|
sddDataAlignment,
|
|
309
316
|
goalRoundDriver,
|
|
310
317
|
operationLinker: chatOperationLinker,
|
|
318
|
+
terminals: terminalRegistry,
|
|
311
319
|
appData,
|
|
312
320
|
bootToken: deps.bootToken,
|
|
313
321
|
getConsoleOrigin: deps.getConsoleOrigin,
|
|
@@ -61,7 +61,7 @@ function pathSpreadScore(paths) {
|
|
|
61
61
|
function collectEscalationSignals(blob, supervised) {
|
|
62
62
|
const signals = [];
|
|
63
63
|
for (const pattern of SHAPE_ESCALATION_PATTERNS) {
|
|
64
|
-
if (
|
|
64
|
+
if (hasAffirmativeShapeSignal(blob, pattern))
|
|
65
65
|
signals.push(pattern.id);
|
|
66
66
|
}
|
|
67
67
|
if (supervised)
|
|
@@ -72,6 +72,35 @@ function collectEscalationSignals(blob, supervised) {
|
|
|
72
72
|
}
|
|
73
73
|
return [...new Set(signals)];
|
|
74
74
|
}
|
|
75
|
+
function isExplicitShapeExclusion(clause, pattern) {
|
|
76
|
+
const match = new RegExp(pattern.re.source, "i").exec(clause);
|
|
77
|
+
if (!match)
|
|
78
|
+
return false;
|
|
79
|
+
const prefix = clause.slice(0, match.index).trim();
|
|
80
|
+
const suffix = clause.slice(match.index + match[0].length).trim();
|
|
81
|
+
const actionInSignal = ["new-route", "new-dependency"].includes(pattern.id);
|
|
82
|
+
if (suffix && !(actionInSignal && /^no$/i.test(prefix) && /^is\s+(?:required|needed)$/i.test(suffix)))
|
|
83
|
+
return false;
|
|
84
|
+
if (/^(?:不涉及|不(?:修改|变更|调整|改变|新增|添加)|无需(?:修改|变更|调整|改变|新增|添加)|no\s+changes?\s+to|(?:do\s+not|don't)\s+(?:change|modify))$/i.test(prefix))
|
|
85
|
+
return true;
|
|
86
|
+
return actionInSignal && /^(?:不|禁止|无需|无须|不需要|no|without|do\s+not|don't)$/i.test(prefix);
|
|
87
|
+
}
|
|
88
|
+
/** Only a complete, independent scope exclusion can suppress a risk signal.
|
|
89
|
+
* Nested negation, conditions and trailing consequences remain risk evidence;
|
|
90
|
+
* an excluded occurrence never cancels another occurrence elsewhere. */
|
|
91
|
+
function hasAffirmativeShapeSignal(blob, pattern) {
|
|
92
|
+
for (const sentence of blob.split(/[\n。.;;!?!?]/)) {
|
|
93
|
+
if (!pattern.re.test(sentence))
|
|
94
|
+
continue;
|
|
95
|
+
// Commas can attach a condition to an exclusion. A comma-separated list
|
|
96
|
+
// is independent only when every item is itself an explicit exclusion.
|
|
97
|
+
const clauses = sentence.split(/[,,、]/).map(part => part.trim().replace(/^(?:[-*+]|\d+\))\s+/, ""));
|
|
98
|
+
if (clauses.every(clause => SHAPE_ESCALATION_PATTERNS.some(candidate => isExplicitShapeExclusion(clause, candidate))))
|
|
99
|
+
continue;
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
75
104
|
/** Negation applies to the API mention itself, never to unrelated Mock policy. */
|
|
76
105
|
function hasFrontendRemoteSignal(blob) {
|
|
77
106
|
const remaining = blob
|
|
@@ -299,6 +299,12 @@ export function buildContextOverflowRetryPrompt(task, basePrompt) {
|
|
|
299
299
|
compactRetrySection(basePrompt, "task", COMPACT_RETRY_TASK_MAX_CHARS),
|
|
300
300
|
"</task>",
|
|
301
301
|
].join("\n"),
|
|
302
|
+
// Plan still needs the complete frozen obligations for ledger ownership
|
|
303
|
+
// and scoped projection. Its executor packs this block before dispatch;
|
|
304
|
+
// dropping or character-truncating it prevents safe progress recovery.
|
|
305
|
+
...(isFrontendPlanLadderTask(task)
|
|
306
|
+
? [basePrompt.match(/<frontend_plan_input>[\s\S]*?<\/frontend_plan_input>/)?.[0] ?? ""]
|
|
307
|
+
: []),
|
|
302
308
|
].join("\n\n");
|
|
303
309
|
}
|
|
304
310
|
function isFrontendPlanLadderTask(task) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tea-agent/loop-agent",
|
|
3
|
-
"version": "0.43.0-next.
|
|
3
|
+
"version": "0.43.0-next.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"loop-agent": "bin/loop-agent.js",
|
|
@@ -78,9 +78,12 @@
|
|
|
78
78
|
"@deepseek-ai/dsh-invariants": "0.1.1-rc.2",
|
|
79
79
|
"@earendil-works/pi-ai": "0.83.0",
|
|
80
80
|
"@earendil-works/pi-coding-agent": "0.83.0",
|
|
81
|
+
"@xterm/addon-fit": "^0.11.0",
|
|
82
|
+
"@xterm/xterm": "^6.0.0",
|
|
81
83
|
"commander": "^12.1.0",
|
|
82
84
|
"katex": "^0.16.47",
|
|
83
85
|
"mermaid": "^11.16.1",
|
|
86
|
+
"node-pty": "^1.2.0-beta.15",
|
|
84
87
|
"rehype-highlight": "^7.0.2",
|
|
85
88
|
"rehype-katex": "^7.0.1",
|
|
86
89
|
"remark-math": "^6.0.0",
|
|
@@ -90,8 +93,8 @@
|
|
|
90
93
|
"zod": "^3.25.76"
|
|
91
94
|
},
|
|
92
95
|
"optionalDependencies": {
|
|
93
|
-
"@
|
|
94
|
-
"@
|
|
96
|
+
"@agent-context/sift": "0.0.1-alpha.7",
|
|
97
|
+
"@cursor/sdk": "^1.0.7"
|
|
95
98
|
},
|
|
96
99
|
"devDependencies": {
|
|
97
100
|
"@remixicon/react": "^4.9.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{ag as o,ah as n}from"./mermaid.core-BUuGHmWO.js";const t=(a,r)=>o.lang.round(n.parse(a)[r]);export{t as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as a,c as s,a as e,C as t}from"./chunk-GF5L2VYU-sF1AEy7T.js";import{_ as i}from"./mermaid.core-BUuGHmWO.js";import"./chunk-5VM5RSS4-D5J9PHC7.js";import"./chunk-XXDRQBXY-BEJi3iIs.js";import"./chunk-KBJHAD2P-BKJrPcJ6.js";import"./chunk-2GRJ4B5K-C0osm1Zf.js";import"./index-C0O48S_P.js";var n={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{n as diagram};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as a,c as s,a as e,C as t}from"./chunk-GF5L2VYU-sF1AEy7T.js";import{_ as i}from"./mermaid.core-BUuGHmWO.js";import"./chunk-5VM5RSS4-D5J9PHC7.js";import"./chunk-XXDRQBXY-BEJi3iIs.js";import"./chunk-KBJHAD2P-BKJrPcJ6.js";import"./chunk-2GRJ4B5K-C0osm1Zf.js";import"./index-C0O48S_P.js";var n={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{n as diagram};
|