@tea-agent/loop-agent 0.43.0-next.11 → 0.43.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 +3 -0
- package/dist/build-stamp.json +3 -3
- package/dist/commands/client-recovery.js +20 -55
- package/dist/executors/shell-write-guard.js +27 -32
- package/dist/shared/pi-context-pressure/extension.js +26 -16
- package/dist/shared/pi-provider-recovery.js +182 -0
- package/dist/shared/pi-retry-settings.js +40 -0
- package/dist/worker/console/chat/pi-runtime.js +7 -5
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-CTSK0xbU.js → abnfDiagram-N423BO3Z-BEg5712w.js} +1 -1
- package/dist/worker/console/static/assets/{arc-_2MfctFP.js → arc-CkQvaBGZ.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-DsDe2wTg.js → architectureDiagram-T3A2C74G-BrdwFNJ7.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-Dtz_779U.js → blockDiagram-VBNYF7ZC-M_LjP2kx.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-LaULi-gw.js → c4Diagram-5PPSVZJV-Bwr5Dtjc.js} +1 -1
- package/dist/worker/console/static/assets/channel-CKmyKgY-.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-DuHBqqX8.js → chunk-2GRJ4B5K-CDc44stW.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-BZgZs1dn.js → chunk-2Q5K7J3B-DZELwsTt.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-tzwmlIO_.js → chunk-5RXB4S5H-D7YI6SWX.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-CeYrLkSn.js → chunk-5VM5RSS4-Bc46bEyj.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-C92cgilm.js → chunk-6Q2QTUOP-Bj4vc-Dp.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-XOXpGC0F.js → chunk-GF5L2VYU-DRi-0nDX.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-CGHbJyCH.js → chunk-JWPE2WC7-Dr-wFY60.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-Bs2-LTzf.js → chunk-KBJHAD2P-CqIHE_D7.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-rN7up7E4.js → chunk-RYQCIY6F-C-Dl8wzk.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-B_fWjKpR.js → chunk-XXDRQBXY-CV4Mydz3.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-D8Wc3jJP.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-D8Wc3jJP.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-DE3SdJvB.js → cose-bilkent-JH36ORCC-C3MamSMJ.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-B-4yuRAX.js → cynefin-VYW2F7L2-zo_Jy2sf.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-TiCPFuO8.js → cynefinDiagram-MW4NZA55-BB2PN1AG.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-7crzLMzA.js → dagre-VZM6K2ZE-BimYueoi.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-Cvr-x6Fd.js → diagram-7IWD3JNH-Di1ObJRS.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-BzcRHUjH.js → diagram-B4RE2ZJO-C83l-IJx.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-BjkAXilh.js → diagram-LBJQPF4R-B3S3fOpm.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-BkzyATK7.js → diagram-Q27KOJAE-urW_Zhe7.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-rZuTarYP.js → diagram-UB23O5K3-nvIbCwF6.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-CAYENaN1.js → ebnfDiagram-BXEA7PRR-DG6O3KpP.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DCEam0Uq.js → erDiagram-JOGREHBK-DpXdtdsj.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-e_dH4wVO.js → flowDiagram-UKHOOZJN-DvXWHrND.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-CvZa2zOK.js → ganttDiagram-PKOTCBZU-6F7SbvUS.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-CbT5TuKp.js → gitGraphDiagram-DS77QQ5N-D1tZnFec.js} +1 -1
- package/dist/worker/console/static/assets/{index-CUPeoE8W.js → index-CWarwRqc.js} +94 -94
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-BWzHQa_Z.js → infoDiagram-6WML65LV-HN4qwJ2M.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-BTjlovtU.js → ishikawaDiagram-WSZJBQD7-OJ4qwDRo.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DkvQoCc1.js → journeyDiagram-NVQOT4AX-CJZ6giQk.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-CHSzGi3W.js → kanban-definition-27J2QSJJ-co60m19S.js} +1 -1
- package/dist/worker/console/static/assets/{linear-DZMkTCWH.js → linear-D1KeFqZY.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-BIMhty7A.js → mermaid.core-i7dDGqov.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-Dx-tyMl3.js → mindmap-definition-FAOFIHXS-1SkQxBh1.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-C6G34rbY.js → pegDiagram-VL7TDLO6-B10dhI-Y.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-CHK9XOfm.js → pieDiagram-7S7Q4E2Y-CiUKUo6j.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-CDARkI0w.js → quadrantDiagram-CIZ2JOQS-C5vH4LXZ.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-DiuUe0ZQ.js → railroadDiagram-AXF67PYL-5nlWOCEj.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-RE61UR56.js → requirementDiagram-LRYGKXZP-CILd6QS3.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-KDNLHMEG.js → sankeyDiagram-W5VNT64P-Dfp18ZO2.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-CeVgXnD9.js → sequenceDiagram-SI44F4Z6-B9pkswBi.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-CXwGyjjG.js → sizeCapture-X5ZJPWSS-C1-eSgx4.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-BjTfozab.js → stateDiagram-OKZ733FA-COJsOoAF.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Bpfb0q5s.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-BaXOB8GT.js → swimlanes-SLNWSIFB-Dv5NXJUM.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BEwGGabW.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-C3r2hqUU.js → timeline-definition-Z64GVDOM-DRdrZ7eR.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-MWKgl1S9.js → vennDiagram-T6HMQDX7-0-2TlwCj.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-C9iFcZPk.js → wardleyDiagram-T6FBY63Y-3-o3q92P.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-DqnM24Jp.js → xychartDiagram-ELKLHX3M-DSgOgdUi.js} +1 -1
- package/dist/worker/console/static/index.html +1 -1
- package/dist/worker/console/static-src/operator-chat/composer-session-ledger.js +192 -0
- package/dist/worker/console/static-src/operator-chat/pending-user-message.js +9 -1
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +78 -35
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +145 -70
- package/dist/worker/console/static-src/operator-chat/useComposer.js +182 -69
- package/dist/workflows/dag/frontend-repair.js +55 -76
- package/docs/architecture/runtime-boundaries.md +3 -3
- package/package.json +4 -1
- package/dist/worker/console/static/assets/channel-CqS4yBWT.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DVOxNOq0.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DVOxNOq0.js +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BXoYsyr2.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DfKliS4e.js +0 -8
|
@@ -1,31 +1,70 @@
|
|
|
1
|
-
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from "react";
|
|
1
|
+
import { useCallback, useEffect, useLayoutEffect, useMemo, useReducer, useRef, useState, } from "react";
|
|
2
2
|
import { filterSlashCommands, mergeSlashCommands, } from "../../chat/shortcuts.js";
|
|
3
|
-
import {
|
|
3
|
+
import { ComposerSessionLedger, composerSessionKey, } from "./composer-session-ledger.js";
|
|
4
|
+
import { confirmationToken, requestId } from "./format.js";
|
|
4
5
|
import { clampShortcutIndex } from "./slash-palette-nav.js";
|
|
5
|
-
import { createInputHistoryState, navigateInputHistory, recordInputHistoryEntry, resetInputHistoryBrowsing, } from "./input-history.js";
|
|
6
6
|
import { attachRuntimeSnapshotController } from "./useRuntimeSnapshot.js";
|
|
7
|
+
function sameComposerSession(left, right) {
|
|
8
|
+
if (!left || !right)
|
|
9
|
+
return left === right;
|
|
10
|
+
return composerSessionKey(left) === composerSessionKey(right);
|
|
11
|
+
}
|
|
12
|
+
function readPendingImage(file) {
|
|
13
|
+
return new Promise((resolve, reject) => {
|
|
14
|
+
const reader = new FileReader();
|
|
15
|
+
reader.onerror = () => reject(reader.error ?? new Error("图片读取失败"));
|
|
16
|
+
reader.onload = () => {
|
|
17
|
+
const value = String(reader.result ?? "");
|
|
18
|
+
resolve({
|
|
19
|
+
name: file.name,
|
|
20
|
+
type: "image",
|
|
21
|
+
mimeType: file.type,
|
|
22
|
+
data: value.slice(value.indexOf(",") + 1),
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
reader.readAsDataURL(file);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
7
28
|
/** Composer state: input text, @file palette, image attachments, /shortcuts,
|
|
8
29
|
* IME composition guards, auto-grow and server-side draft sync. */
|
|
9
30
|
export function useComposer(params) {
|
|
10
|
-
const { origin,
|
|
11
|
-
const
|
|
31
|
+
const { origin, sessionIdentity, sessionMode, sessionReady = true, refs, setError, onUnrecoverableSession, } = params;
|
|
32
|
+
const sessionId = sessionIdentity?.sessionId;
|
|
33
|
+
const ledgerRef = useRef(null);
|
|
34
|
+
if (!ledgerRef.current)
|
|
35
|
+
ledgerRef.current = new ComposerSessionLedger();
|
|
36
|
+
const ledger = ledgerRef.current;
|
|
37
|
+
const activeIdentityRef = useRef(sessionIdentity);
|
|
38
|
+
activeIdentityRef.current = sessionIdentity;
|
|
39
|
+
const [, forceRender] = useReducer((version) => version + 1, 0);
|
|
40
|
+
const activeSnapshot = sessionIdentity
|
|
41
|
+
? ledger.snapshot(sessionIdentity)
|
|
42
|
+
: { draft: "", images: [] };
|
|
43
|
+
const input = activeSnapshot.draft;
|
|
44
|
+
const pendingImages = activeSnapshot.images;
|
|
12
45
|
const [fileOptions, setFileOptions] = useState([]);
|
|
13
|
-
const [pendingImages, setPendingImages] = useState([]);
|
|
14
46
|
const [shortcutOpen, setShortcutOpen] = useState(false);
|
|
15
47
|
/** Any composer text that starts with `/` should reveal the palette,
|
|
16
48
|
* including draft restore. Escape can still close it without clearing. */
|
|
17
49
|
const setInput = useCallback((value) => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const next = value(prev);
|
|
21
|
-
setShortcutOpen(next.startsWith("/"));
|
|
22
|
-
return next;
|
|
23
|
-
});
|
|
50
|
+
const identity = activeIdentityRef.current;
|
|
51
|
+
if (!identity)
|
|
24
52
|
return;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
53
|
+
const previous = ledger.snapshot(identity).draft;
|
|
54
|
+
const next = typeof value === "function" ? value(previous) : value;
|
|
55
|
+
if (ledger.setDraft(identity, next))
|
|
56
|
+
forceRender();
|
|
57
|
+
setShortcutOpen(next.startsWith("/"));
|
|
58
|
+
}, [ledger]);
|
|
59
|
+
const setPendingImages = useCallback((value) => {
|
|
60
|
+
const identity = activeIdentityRef.current;
|
|
61
|
+
if (!identity)
|
|
62
|
+
return;
|
|
63
|
+
const previous = ledger.snapshot(identity).images;
|
|
64
|
+
const next = typeof value === "function" ? value(previous) : value;
|
|
65
|
+
ledger.setImages(identity, next);
|
|
66
|
+
forceRender();
|
|
67
|
+
}, [ledger]);
|
|
29
68
|
const [shortcutIndex, setShortcutIndex] = useState(0);
|
|
30
69
|
const [dynamicCommands, setDynamicCommands] = useState([]);
|
|
31
70
|
const [commandCapabilities, setCommandCapabilities] = useState({
|
|
@@ -36,30 +75,29 @@ export function useComposer(params) {
|
|
|
36
75
|
const [dynamicCommandsError, setDynamicCommandsError] = useState(null);
|
|
37
76
|
const [commandsEpoch, setCommandsEpoch] = useState(0);
|
|
38
77
|
const textareaRef = useRef(null);
|
|
39
|
-
/** Arrow-key input history; unsent drafts survive history browsing. */
|
|
40
|
-
const historyRef = useRef(createInputHistoryState());
|
|
41
78
|
/** Active session generation for /commands; bumped immediately on switch (AC-2). */
|
|
42
79
|
const commandsSessionRef = useRef(sessionId);
|
|
43
80
|
const commandsGenerationRef = useRef(0);
|
|
44
81
|
const handleInputChange = useCallback((value) => {
|
|
45
82
|
setInput(value);
|
|
46
|
-
setShortcutOpen(value.startsWith("/"));
|
|
47
83
|
setShortcutIndex(0);
|
|
48
|
-
|
|
49
|
-
historyRef.current = resetInputHistoryBrowsing(historyRef.current);
|
|
50
|
-
}, []);
|
|
84
|
+
}, [setInput]);
|
|
51
85
|
/** Recall an earlier input via ↑/↓; returns true when the key was consumed. */
|
|
52
86
|
const navigateHistory = useCallback((direction) => {
|
|
87
|
+
const identity = activeIdentityRef.current;
|
|
88
|
+
if (!identity)
|
|
89
|
+
return false;
|
|
90
|
+
const current = ledger.snapshot(identity).draft;
|
|
53
91
|
const textarea = textareaRef.current;
|
|
54
|
-
const decision =
|
|
55
|
-
text:
|
|
56
|
-
caretStart: textarea?.selectionStart ??
|
|
57
|
-
caretEnd: textarea?.selectionEnd ??
|
|
92
|
+
const decision = ledger.navigateHistory(identity, direction, {
|
|
93
|
+
text: current,
|
|
94
|
+
caretStart: textarea?.selectionStart ?? current.length,
|
|
95
|
+
caretEnd: textarea?.selectionEnd ?? current.length,
|
|
58
96
|
});
|
|
59
97
|
if (!decision.handled)
|
|
60
98
|
return false;
|
|
61
|
-
|
|
62
|
-
|
|
99
|
+
forceRender();
|
|
100
|
+
setShortcutOpen(decision.text.startsWith("/"));
|
|
63
101
|
const caret = decision.text.length;
|
|
64
102
|
queueMicrotask(() => {
|
|
65
103
|
const el = textareaRef.current;
|
|
@@ -68,22 +106,76 @@ export function useComposer(params) {
|
|
|
68
106
|
}
|
|
69
107
|
});
|
|
70
108
|
return true;
|
|
71
|
-
}, [
|
|
72
|
-
/** Record a submitted text into
|
|
109
|
+
}, [ledger]);
|
|
110
|
+
/** Record a submitted text into the selected session's history. */
|
|
73
111
|
const recordHistory = useCallback((text) => {
|
|
74
|
-
|
|
75
|
-
|
|
112
|
+
const identity = activeIdentityRef.current;
|
|
113
|
+
if (identity)
|
|
114
|
+
ledger.recordHistory(identity, text);
|
|
115
|
+
}, [ledger]);
|
|
116
|
+
const claimSubmission = useCallback(() => {
|
|
117
|
+
const identity = activeIdentityRef.current;
|
|
118
|
+
if (!identity)
|
|
119
|
+
return null;
|
|
120
|
+
const attempt = ledger.beginSubmission(identity, refs.sessionGenerationRef.current, requestId("chat-submit"));
|
|
121
|
+
if (!attempt)
|
|
122
|
+
return null;
|
|
123
|
+
forceRender();
|
|
124
|
+
setShortcutOpen(false);
|
|
125
|
+
setShortcutIndex(0);
|
|
126
|
+
return attempt;
|
|
127
|
+
}, [ledger, refs]);
|
|
128
|
+
const claimSessionSubmission = useCallback((identity, text, images = []) => {
|
|
129
|
+
ledger.setDraft(identity, text);
|
|
130
|
+
ledger.setImages(identity, images);
|
|
131
|
+
const attempt = ledger.beginSubmission(identity, refs.sessionGenerationRef.current, requestId("chat-submit"));
|
|
132
|
+
if (sameComposerSession(activeIdentityRef.current, identity))
|
|
133
|
+
forceRender();
|
|
134
|
+
return attempt;
|
|
135
|
+
}, [ledger, refs]);
|
|
136
|
+
const settleSubmission = useCallback((attempt, outcome) => {
|
|
137
|
+
const result = ledger.settle(attempt, outcome);
|
|
138
|
+
if (sameComposerSession(activeIdentityRef.current, attempt.identity))
|
|
139
|
+
forceRender();
|
|
140
|
+
return result;
|
|
141
|
+
}, [ledger]);
|
|
142
|
+
const settleSubmissionByRequest = useCallback((identity, clientRequestId, outcome) => {
|
|
143
|
+
const result = ledger.settleByRequest(identity, clientRequestId, outcome);
|
|
144
|
+
if (sameComposerSession(activeIdentityRef.current, identity))
|
|
145
|
+
forceRender();
|
|
146
|
+
return result;
|
|
147
|
+
}, [ledger]);
|
|
148
|
+
const seedSession = useCallback((identity, draft) => {
|
|
149
|
+
const seeded = ledger.seedDraft(identity, draft);
|
|
150
|
+
if (seeded && sameComposerSession(activeIdentityRef.current, identity))
|
|
151
|
+
forceRender();
|
|
152
|
+
return seeded;
|
|
153
|
+
}, [ledger]);
|
|
154
|
+
const replaceSessionDraft = useCallback((identity, draft, images) => {
|
|
155
|
+
ledger.setDraft(identity, draft);
|
|
156
|
+
ledger.setImages(identity, images);
|
|
157
|
+
if (sameComposerSession(activeIdentityRef.current, identity))
|
|
158
|
+
forceRender();
|
|
159
|
+
}, [ledger]);
|
|
160
|
+
const releaseSession = useCallback((identity) => {
|
|
161
|
+
ledger.release(identity);
|
|
162
|
+
if (sameComposerSession(activeIdentityRef.current, identity))
|
|
163
|
+
forceRender();
|
|
164
|
+
}, [ledger]);
|
|
76
165
|
// Immediate invalidation on A→B even when B palette never opens (AC-2).
|
|
77
166
|
useLayoutEffect(() => {
|
|
78
167
|
commandsSessionRef.current = sessionId;
|
|
79
168
|
commandsGenerationRef.current += 1;
|
|
169
|
+
refs.isComposingRef.current = false;
|
|
170
|
+
setFileOptions([]);
|
|
171
|
+
setShortcutOpen(input.startsWith("/"));
|
|
80
172
|
setDynamicCommands([]);
|
|
81
173
|
setCommandCapabilities({ sddBingo: false, sessionMode });
|
|
82
174
|
setDynamicCommandsError(null);
|
|
83
175
|
setDynamicCommandsLoading(false);
|
|
84
176
|
}, [sessionId, sessionMode]);
|
|
85
177
|
const loadDynamicCommands = useCallback(async () => {
|
|
86
|
-
if (!sessionId) {
|
|
178
|
+
if (!sessionId || !sessionReady) {
|
|
87
179
|
setDynamicCommands([]);
|
|
88
180
|
setDynamicCommandsError(null);
|
|
89
181
|
setDynamicCommandsLoading(false);
|
|
@@ -147,21 +239,21 @@ export function useComposer(params) {
|
|
|
147
239
|
setDynamicCommandsLoading(false);
|
|
148
240
|
}
|
|
149
241
|
}
|
|
150
|
-
}, [origin, sessionId, sessionMode]);
|
|
242
|
+
}, [origin, sessionId, sessionMode, sessionReady]);
|
|
151
243
|
// Lazy-load dynamic commands when slash palette opens or session changes.
|
|
152
244
|
useEffect(() => {
|
|
153
|
-
if (!sessionId)
|
|
245
|
+
if (!sessionId || !sessionReady)
|
|
154
246
|
return;
|
|
155
247
|
if (!shortcutOpen && commandsEpoch === 0)
|
|
156
248
|
return;
|
|
157
249
|
void loadDynamicCommands();
|
|
158
|
-
}, [sessionId, shortcutOpen, commandsEpoch, loadDynamicCommands]);
|
|
250
|
+
}, [sessionId, sessionReady, shortcutOpen, commandsEpoch, loadDynamicCommands]);
|
|
159
251
|
const retryDynamicCommands = useCallback(() => {
|
|
160
252
|
setCommandsEpoch((n) => n + 1);
|
|
161
253
|
void loadDynamicCommands();
|
|
162
254
|
}, [loadDynamicCommands]);
|
|
163
255
|
useEffect(() => {
|
|
164
|
-
if (!sessionId)
|
|
256
|
+
if (!sessionId || !sessionIdentity || !sessionReady)
|
|
165
257
|
return;
|
|
166
258
|
const match = input
|
|
167
259
|
.slice(0, textareaRef.current?.selectionStart ?? input.length)
|
|
@@ -170,13 +262,29 @@ export function useComposer(params) {
|
|
|
170
262
|
setFileOptions([]);
|
|
171
263
|
return;
|
|
172
264
|
}
|
|
265
|
+
const owner = { ...sessionIdentity };
|
|
266
|
+
const ownerKey = composerSessionKey(owner);
|
|
267
|
+
const generation = refs.sessionGenerationRef.current;
|
|
268
|
+
const controller = new AbortController();
|
|
173
269
|
const timer = window.setTimeout(() => {
|
|
174
|
-
void fetch(`${origin}/api/operator/v1/chat/sessions/${encodeURIComponent(sessionId)}/files?q=${encodeURIComponent(match[1] ?? "")}
|
|
270
|
+
void fetch(`${origin}/api/operator/v1/chat/sessions/${encodeURIComponent(sessionId)}/files?q=${encodeURIComponent(match[1] ?? "")}`, { signal: controller.signal })
|
|
175
271
|
.then((r) => (r.ok ? r.json() : null))
|
|
176
|
-
.then((body) =>
|
|
272
|
+
.then((body) => {
|
|
273
|
+
const active = activeIdentityRef.current;
|
|
274
|
+
if (controller.signal.aborted ||
|
|
275
|
+
!active ||
|
|
276
|
+
composerSessionKey(active) !== ownerKey ||
|
|
277
|
+
refs.sessionGenerationRef.current !== generation)
|
|
278
|
+
return;
|
|
279
|
+
setFileOptions((body?.files ?? []).map((item) => item.path));
|
|
280
|
+
})
|
|
281
|
+
.catch(() => undefined);
|
|
177
282
|
}, 150);
|
|
178
|
-
return () =>
|
|
179
|
-
|
|
283
|
+
return () => {
|
|
284
|
+
window.clearTimeout(timer);
|
|
285
|
+
controller.abort();
|
|
286
|
+
};
|
|
287
|
+
}, [origin, sessionId, sessionIdentity, sessionReady, input, refs]);
|
|
180
288
|
const insertFileReference = useCallback((file) => {
|
|
181
289
|
const caret = textareaRef.current?.selectionStart ?? input.length;
|
|
182
290
|
const before = input.slice(0, caret);
|
|
@@ -185,33 +293,31 @@ export function useComposer(params) {
|
|
|
185
293
|
return;
|
|
186
294
|
setInput(`${input.slice(0, start)}@${file} ${input.slice(caret)}`);
|
|
187
295
|
setFileOptions([]);
|
|
188
|
-
}, [input]);
|
|
296
|
+
}, [input, setInput]);
|
|
189
297
|
const addImagesFromFiles = useCallback((files) => {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
}, [setError]);
|
|
298
|
+
const owner = activeIdentityRef.current;
|
|
299
|
+
if (!owner)
|
|
300
|
+
return;
|
|
301
|
+
const ownerIdentity = { ...owner };
|
|
302
|
+
const selected = Array.from(files).slice(0, 4);
|
|
303
|
+
const valid = selected.filter((file) => file.type.startsWith("image/") && file.size <= 5 * 1024 * 1024);
|
|
304
|
+
if (valid.length !== selected.length)
|
|
305
|
+
setError("图片仅支持 PNG/JPEG/GIF/WebP,单张不超过 5 MiB");
|
|
306
|
+
void Promise.all(valid.map(readPendingImage)).then((loaded) => {
|
|
307
|
+
if (!ledger.has(ownerIdentity) || loaded.length === 0)
|
|
308
|
+
return;
|
|
309
|
+
const current = ledger.snapshot(ownerIdentity).images;
|
|
310
|
+
ledger.setImages(ownerIdentity, [...current, ...loaded].slice(0, 4));
|
|
311
|
+
if (sameComposerSession(activeIdentityRef.current, ownerIdentity))
|
|
312
|
+
forceRender();
|
|
313
|
+
}, (error) => {
|
|
314
|
+
if (sameComposerSession(activeIdentityRef.current, ownerIdentity))
|
|
315
|
+
setError(error instanceof Error ? error.message : "图片读取失败");
|
|
316
|
+
});
|
|
317
|
+
}, [ledger, setError]);
|
|
212
318
|
const removeImage = useCallback((image) => {
|
|
213
319
|
setPendingImages((items) => items.filter((item) => item !== image));
|
|
214
|
-
}, []);
|
|
320
|
+
}, [setPendingImages]);
|
|
215
321
|
// Chromium handles growth in CSS without forcing a layout read on every key.
|
|
216
322
|
// Keep a deferred fallback for browsers that do not support field-sizing.
|
|
217
323
|
useEffect(() => {
|
|
@@ -231,7 +337,7 @@ export function useComposer(params) {
|
|
|
231
337
|
}, [input]);
|
|
232
338
|
// Debounced server-side composer draft sync.
|
|
233
339
|
useEffect(() => {
|
|
234
|
-
if (!sessionId)
|
|
340
|
+
if (!sessionId || !sessionReady)
|
|
235
341
|
return;
|
|
236
342
|
const timer = window.setTimeout(() => {
|
|
237
343
|
void fetch(`${origin}/api/operator/v1/chat/sessions/${encodeURIComponent(sessionId)}/draft`, {
|
|
@@ -245,7 +351,7 @@ export function useComposer(params) {
|
|
|
245
351
|
});
|
|
246
352
|
}, 400);
|
|
247
353
|
return () => window.clearTimeout(timer);
|
|
248
|
-
}, [origin, sessionId, input]);
|
|
354
|
+
}, [origin, sessionId, sessionReady, input]);
|
|
249
355
|
const mergedCommands = useMemo(() => mergeSlashCommands(dynamicCommands, commandCapabilities), [dynamicCommands, commandCapabilities]);
|
|
250
356
|
const filteredShortcuts = useMemo(() => input.startsWith("/")
|
|
251
357
|
? filterSlashCommands(mergedCommands, input)
|
|
@@ -279,17 +385,24 @@ export function useComposer(params) {
|
|
|
279
385
|
useEffect(() => {
|
|
280
386
|
attachRuntimeSnapshotController({
|
|
281
387
|
origin,
|
|
282
|
-
sessionId,
|
|
388
|
+
sessionId: sessionReady ? sessionId : undefined,
|
|
283
389
|
refs,
|
|
284
390
|
onUnrecoverableSession,
|
|
285
391
|
});
|
|
286
|
-
}, [origin, sessionId, refs, onUnrecoverableSession]);
|
|
392
|
+
}, [origin, sessionId, sessionReady, refs, onUnrecoverableSession]);
|
|
287
393
|
return {
|
|
288
394
|
input,
|
|
289
395
|
setInput,
|
|
290
396
|
handleInputChange,
|
|
291
397
|
navigateHistory,
|
|
292
398
|
recordHistory,
|
|
399
|
+
claimSubmission,
|
|
400
|
+
claimSessionSubmission,
|
|
401
|
+
settleSubmission,
|
|
402
|
+
settleSubmissionByRequest,
|
|
403
|
+
seedSession,
|
|
404
|
+
replaceSessionDraft,
|
|
405
|
+
releaseSession,
|
|
293
406
|
fileOptions,
|
|
294
407
|
pendingImages,
|
|
295
408
|
setPendingImages,
|
|
@@ -24,6 +24,50 @@ export const frontendCommandCategorySchema = z.enum([
|
|
|
24
24
|
"unit-test",
|
|
25
25
|
"trace",
|
|
26
26
|
]);
|
|
27
|
+
/**
|
|
28
|
+
* Ordered string-blob rules. Order is the contract: the first matching rule wins,
|
|
29
|
+
* so rules that share keywords keep their original precedence. `nodeIdIncludes`
|
|
30
|
+
* and `blobIncludes` are alternatives within one rule (logical OR).
|
|
31
|
+
*/
|
|
32
|
+
const BLOB_RULES = [
|
|
33
|
+
{
|
|
34
|
+
result: "contract",
|
|
35
|
+
nodeIdIncludes: ["contract"],
|
|
36
|
+
blobIncludes: ["contract mismatch", "source binding"],
|
|
37
|
+
},
|
|
38
|
+
{ result: "trace", nodeIdIncludes: ["trace"], blobIncludes: ["trace:"] },
|
|
39
|
+
{ result: "review", nodeIdIncludes: ["review"] },
|
|
40
|
+
{
|
|
41
|
+
result: "unit-test",
|
|
42
|
+
nodeIdIncludes: ["behavior"],
|
|
43
|
+
blobIncludes: ["vitest", "jest", "npm test"],
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
result: "typecheck",
|
|
47
|
+
blobIncludes: ["typecheck", "tsc"],
|
|
48
|
+
blobPatterns: [/error ts\d+/i],
|
|
49
|
+
},
|
|
50
|
+
{ result: "lint", blobIncludes: ["eslint", "lint"] },
|
|
51
|
+
// "vite build"/"next build" are subsumed by "build".
|
|
52
|
+
{ result: "build", blobIncludes: ["build"] },
|
|
53
|
+
{
|
|
54
|
+
result: "component-test",
|
|
55
|
+
blobIncludes: ["testing-library", "component", "render("],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
result: "dependency",
|
|
59
|
+
blobIncludes: ["package.json", "unapproved dependency", "npm install"],
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
result: "credential",
|
|
63
|
+
blobIncludes: ["credential", "api key", "secret"],
|
|
64
|
+
},
|
|
65
|
+
{ result: "deploy", blobIncludes: ["deploy", "production release"] },
|
|
66
|
+
{
|
|
67
|
+
result: "spec-unclear",
|
|
68
|
+
blobIncludes: ["spec unclear", "requirement ambiguous", "needs human"],
|
|
69
|
+
},
|
|
70
|
+
];
|
|
27
71
|
export function classifyFrontendFailure(input) {
|
|
28
72
|
// AC-2: structured evidence takes priority over string-blob heuristics.
|
|
29
73
|
if (input.failureCategory === "write-guard") {
|
|
@@ -39,86 +83,21 @@ export function classifyFrontendFailure(input) {
|
|
|
39
83
|
return "trace";
|
|
40
84
|
}
|
|
41
85
|
if (input.commandCategory) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return "typecheck";
|
|
45
|
-
case "build":
|
|
46
|
-
return "build";
|
|
47
|
-
case "lint":
|
|
48
|
-
return "lint";
|
|
49
|
-
case "component-test":
|
|
50
|
-
return "component-test";
|
|
51
|
-
case "unit-test":
|
|
52
|
-
return "unit-test";
|
|
53
|
-
}
|
|
86
|
+
// "trace" already returned above, so the remaining categories map 1:1.
|
|
87
|
+
return input.commandCategory;
|
|
54
88
|
}
|
|
55
|
-
// Fallback: string-blob
|
|
56
|
-
//
|
|
89
|
+
// Fallback: ordered string-blob heuristics. Only the shell executor's
|
|
90
|
+
// structured category proves a write-boundary failure, so blob text never
|
|
91
|
+
// overrides the structured checks above.
|
|
57
92
|
const blob = `${input.nodeId}\n${input.failureCategory ?? ""}\n${input.stdout ?? ""}\n${input.stderr ?? ""}`.toLowerCase();
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
// the shell executor's structured category proves a write-boundary failure.
|
|
65
|
-
if (input.failureCategory === "write-guard") {
|
|
66
|
-
return "path";
|
|
67
|
-
}
|
|
68
|
-
if (input.nodeId.includes("trace") || blob.includes("trace:")) {
|
|
69
|
-
return "trace";
|
|
70
|
-
}
|
|
71
|
-
if (input.nodeId.includes("review")) {
|
|
72
|
-
return "review";
|
|
73
|
-
}
|
|
74
|
-
// Classify the failed verification command before inspecting its output.
|
|
75
|
-
// Full test output includes unrelated passing-test titles such as
|
|
76
|
-
// "secret-shaped" and "write-guard failure".
|
|
77
|
-
if (blob.includes("vitest") ||
|
|
78
|
-
blob.includes("jest") ||
|
|
79
|
-
blob.includes("npm test") ||
|
|
80
|
-
input.nodeId.includes("behavior")) {
|
|
81
|
-
return "unit-test";
|
|
82
|
-
}
|
|
83
|
-
if (blob.includes("typecheck") ||
|
|
84
|
-
blob.includes("tsc") ||
|
|
85
|
-
/error ts\d+/i.test(blob)) {
|
|
86
|
-
return "typecheck";
|
|
87
|
-
}
|
|
88
|
-
if (blob.includes("eslint") || blob.includes("lint")) {
|
|
89
|
-
return "lint";
|
|
90
|
-
}
|
|
91
|
-
if (blob.includes("build") ||
|
|
92
|
-
blob.includes("vite build") ||
|
|
93
|
-
blob.includes("next build")) {
|
|
94
|
-
return "build";
|
|
95
|
-
}
|
|
96
|
-
if (blob.includes("testing-library") ||
|
|
97
|
-
blob.includes("component") ||
|
|
98
|
-
blob.includes("render(")) {
|
|
99
|
-
return "component-test";
|
|
100
|
-
}
|
|
101
|
-
if (blob.includes("package.json") ||
|
|
102
|
-
blob.includes("unapproved dependency") ||
|
|
103
|
-
blob.includes("npm install")) {
|
|
104
|
-
return "dependency";
|
|
105
|
-
}
|
|
106
|
-
if (blob.includes("credential") ||
|
|
107
|
-
blob.includes("api key") ||
|
|
108
|
-
blob.includes("secret")) {
|
|
109
|
-
return "credential";
|
|
110
|
-
}
|
|
111
|
-
if (blob.includes("deploy") || blob.includes("production release")) {
|
|
112
|
-
return "deploy";
|
|
113
|
-
}
|
|
114
|
-
if (blob.includes("spec unclear") ||
|
|
115
|
-
blob.includes("requirement ambiguous") ||
|
|
116
|
-
blob.includes("needs human")) {
|
|
117
|
-
return "spec-unclear";
|
|
93
|
+
for (const rule of BLOB_RULES) {
|
|
94
|
+
if (rule.nodeIdIncludes?.some((keyword) => input.nodeId.includes(keyword)) ||
|
|
95
|
+
rule.blobIncludes?.some((keyword) => blob.includes(keyword)) ||
|
|
96
|
+
rule.blobPatterns?.some((pattern) => pattern.test(blob))) {
|
|
97
|
+
return rule.result;
|
|
98
|
+
}
|
|
118
99
|
}
|
|
119
100
|
if (input.failureCategory === "invalid-output")
|
|
120
101
|
return "contract";
|
|
121
|
-
if (input.failureCategory === "write-guard")
|
|
122
|
-
return "path";
|
|
123
102
|
return "unknown";
|
|
124
103
|
}
|
|
@@ -205,15 +205,15 @@ Runtime 变更另需 `npm run typecheck` 及对应 targeted Vitest(见 exec pl
|
|
|
205
205
|
|
|
206
206
|
| 面 | 路径 / 入口 | 边界 |
|
|
207
207
|
| --- | --- | --- |
|
|
208
|
-
| OpenCode transient-retry | `.opencode/plugins/loop-agent-transient-retry.js`(init surface `generated`) |
|
|
208
|
+
| OpenCode transient-retry | `.opencode/plugins/loop-agent-transient-retry.js`(init surface `generated`) | 瞬态 UnknownError / TypeValidation wrapper 及已知被裁剪的内部 provider 波动文案 resume;busy/retry 门控 + backoff;overflow/401/配额/取消/业务标 permanent(`plugin-ignore-permanent-error`),**不** compact |
|
|
209
209
|
| OpenCode overflow-compact | `.opencode/plugins/loop-agent-context-overflow-compact.js`(init surface `generated`) | 仅 context overflow → `session.compact`(无则 `summarize`)+ 有限 `promptAsync` 续接;`MAX_OVERFLOW_RECOVERIES ≤ 2`;session 锁;非 overflow 不动作 |
|
|
210
210
|
| Pi project extension | `.pi/extensions/loop-agent-context-overflow.js`(init surface `generated`) | `message_end` 上将 overflow `errorMessage` 幂等改写为 `context_length_exceeded:` 前缀,触发 Pi 原生 compact/retry;分类器与控制器共享 P1–P10 / N1–N5 语料(含嵌套 JSON);**不**写 `~/.pi` settings / compaction / 模型窗口,**不**投影 sift native |
|
|
211
|
-
| Console / DAG 运行时 | npm 内置 inline extension + 可选 `@agent-context/sift` |
|
|
211
|
+
| Console / DAG 运行时 | npm 内置 inline extension + 可选 `@agent-context/sift` | Console 无需 init 即启用内部 provider transient 规范化、字段级 retry process defaults 与 L0/L1/L2;项目显式 retry 字段优先于用户全局字段,再优先于推荐默认值。DAG 使用独立 in-memory retry/compaction,且不做 streaming 主动 compact。`HARNESS_CONTEXT_PRESSURE_MODE=off` 只关 L0/L2,不关闭 Console transient 恢复;`HARNESS_CONSOLE_SIFT` / `HARNESS_DAG_SIFT` 的 `0\|false\|off` 关 L1。不进入目标项目 init 文件 |
|
|
212
212
|
| Pi 用户配置 | `~/.pi/agent/settings.json` | **不**进入项目 `.harness/init-surface.json` hash;仅 `--client-recovery=user` 可字段级补缺并原子写;`auto`/`project`/`off` 与 `check-update` 默认零写 home;读取时只有 `ENOENT` 视为缺文件,其他 I/O 错误 fail closed |
|
|
213
213
|
| CLI mode | `--client-recovery=auto\|project\|user\|off`(默认 `auto`) | `auto`/`project` 安装上述三份项目产物;`user` = 三产物 + 显式 Pi retry 合并;`off` 全跳过 |
|
|
214
214
|
| Ownership | recorded sha256 + apply-safe | 三份 generated 缺失可补、与 recorded hash 一致可升级;用户改过 → model merge / human decision,禁止静默覆盖 |
|
|
215
215
|
|
|
216
|
-
实现落点:`src/
|
|
216
|
+
实现落点:`src/shared/pi-provider-recovery.ts`(内置规则、纯 `additionalRules` 扩展接口与 generated predicate)、`src/shared/pi-retry-settings.ts`(字段级 process defaults)、`src/shared/pi-context-pressure/` 与 `src/worker/console/chat/pi-runtime.ts`(Console inline normalization),以及 `src/commands/client-recovery.ts` / `src/commands/init.ts`(项目投影与 surface 编排)。
|
|
217
217
|
|
|
218
218
|
## 演进里程碑
|
|
219
219
|
|
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.13",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"loop-agent": "bin/loop-agent.js",
|
|
@@ -98,10 +98,13 @@
|
|
|
98
98
|
},
|
|
99
99
|
"devDependencies": {
|
|
100
100
|
"@remixicon/react": "^4.9.0",
|
|
101
|
+
"@stryker-mutator/core": "^10.0.0",
|
|
102
|
+
"@stryker-mutator/vitest-runner": "^10.0.0",
|
|
101
103
|
"@types/node": "^24.6.0",
|
|
102
104
|
"@types/react": "^19.1.8",
|
|
103
105
|
"@types/react-dom": "^19.1.6",
|
|
104
106
|
"@types/semver": "^7.7.1",
|
|
107
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
105
108
|
"react": "^19.1.0",
|
|
106
109
|
"react-dom": "^19.1.0",
|
|
107
110
|
"react-markdown": "^10.1.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{ag as o,ah as n}from"./mermaid.core-BIMhty7A.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-XOXpGC0F.js";import{_ as i}from"./mermaid.core-BIMhty7A.js";import"./chunk-5VM5RSS4-CeYrLkSn.js";import"./chunk-XXDRQBXY-B_fWjKpR.js";import"./chunk-KBJHAD2P-Bs2-LTzf.js";import"./chunk-2GRJ4B5K-DuHBqqX8.js";import"./index-CUPeoE8W.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-XOXpGC0F.js";import{_ as i}from"./mermaid.core-BIMhty7A.js";import"./chunk-5VM5RSS4-CeYrLkSn.js";import"./chunk-XXDRQBXY-B_fWjKpR.js";import"./chunk-KBJHAD2P-Bs2-LTzf.js";import"./chunk-2GRJ4B5K-DuHBqqX8.js";import"./index-CUPeoE8W.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 r,b as e,a,S as s}from"./chunk-5RXB4S5H-tzwmlIO_.js";import{_ as i}from"./mermaid.core-BIMhty7A.js";import"./chunk-XXDRQBXY-B_fWjKpR.js";import"./chunk-KBJHAD2P-Bs2-LTzf.js";import"./chunk-2GRJ4B5K-DuHBqqX8.js";import"./index-CUPeoE8W.js";var u={parser:a,get db(){return new s(2)},renderer:e,styles:r,init:i(t=>{t.state||(t.state={}),t.state.arrowMarkerAbsolute=t.arrowMarkerAbsolute},"init")};export{u as diagram};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import{c as r,s as e}from"./flowDiagram-UKHOOZJN-e_dH4wVO.js";import{_ as a}from"./mermaid.core-BIMhty7A.js";import"./chunk-5VM5RSS4-CeYrLkSn.js";import"./chunk-XXDRQBXY-B_fWjKpR.js";import"./chunk-KBJHAD2P-Bs2-LTzf.js";import"./chunk-2GRJ4B5K-DuHBqqX8.js";import"./channel-CqS4yBWT.js";import"./index-CUPeoE8W.js";var o=a(t=>`${e(t)}
|
|
2
|
-
.swimlane.cluster rect {
|
|
3
|
-
stroke: ${t.clusterBorder} !important;
|
|
4
|
-
}
|
|
5
|
-
[data-look="neo"].cluster rect {
|
|
6
|
-
filter: none;
|
|
7
|
-
}
|
|
8
|
-
`,"getStyles"),s=o,n=r({defaultLayout:"swimlane",styles:s});export{n as diagram};
|