@tea-agent/loop-agent 0.40.0-next.4 → 0.40.0-next.6

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.
Files changed (134) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/build-stamp.json +3 -3
  3. package/dist/executors/shell-executor.js +4 -1
  4. package/dist/infrastructure/harness/atomic-write.js +23 -0
  5. package/dist/worker/console/chat/chat-event-store.js +62 -4
  6. package/dist/worker/console/chat/context-panel.js +7 -0
  7. package/dist/worker/console/chat/deferred-turn.js +12 -0
  8. package/dist/worker/console/chat/pi-runtime.js +264 -16
  9. package/dist/worker/console/chat/provider-error.js +98 -0
  10. package/dist/worker/console/chat/routes.js +292 -29
  11. package/dist/worker/console/chat/session-stats.js +179 -0
  12. package/dist/worker/console/chat/session-store.js +93 -63
  13. package/dist/worker/console/chat/todos.js +115 -0
  14. package/dist/worker/console/chat/tool-preview.js +42 -0
  15. package/dist/worker/console/chat/turn-process.js +20 -55
  16. package/dist/worker/console/chat/user-questions.js +266 -0
  17. package/dist/worker/console/chat/workspace-landing.js +14 -0
  18. package/dist/worker/console/native-directory-picker.js +13 -0
  19. package/dist/worker/console/routes.js +309 -1
  20. package/dist/worker/console/security.js +4 -4
  21. package/dist/worker/console/server.js +529 -186
  22. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-CTx1TrNa.js → abnfDiagram-N423BO3Z-DGt5TRsk.js} +1 -1
  23. package/dist/worker/console/static/assets/{arc-B4i9cVxX.js → arc-DKBSJsXm.js} +1 -1
  24. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-BAXE8_Rl.js → architectureDiagram-T3A2C74G-BnhooRBs.js} +1 -1
  25. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-C5Xh59at.js → blockDiagram-VBNYF7ZC-Bm9qkrJP.js} +1 -1
  26. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-B_asOzAu.js → c4Diagram-5PPSVZJV-B2cFh4bO.js} +1 -1
  27. package/dist/worker/console/static/assets/channel-DSgFX07x.js +1 -0
  28. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-wRO_iRNc.js → chunk-2GRJ4B5K-DhvWRI03.js} +1 -1
  29. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-ByOaSh_G.js → chunk-2Q5K7J3B-chzTP_2w.js} +1 -1
  30. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DjLzudan.js → chunk-5RXB4S5H-SdWIR12m.js} +1 -1
  31. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-JCNGkXYT.js → chunk-5VM5RSS4-C2-8Eo_A.js} +1 -1
  32. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-BhrPXXMZ.js → chunk-6Q2QTUOP-DvbE1yQW.js} +1 -1
  33. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-TJ5JuEBT.js → chunk-GF5L2VYU-CEenyPTz.js} +1 -1
  34. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-VVthn_mD.js → chunk-JWPE2WC7-CcaZrq0k.js} +1 -1
  35. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-D60-Mny4.js → chunk-KBJHAD2P-FGngOTto.js} +1 -1
  36. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-zXv7aVye.js → chunk-RYQCIY6F-jT_yX3sf.js} +1 -1
  37. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-By9VQoi1.js → chunk-XXDRQBXY-CjE9LQOM.js} +1 -1
  38. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-unJObRls.js +1 -0
  39. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-unJObRls.js +1 -0
  40. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-C4zQLe-M.js → cose-bilkent-JH36ORCC-GQWns1tb.js} +1 -1
  41. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-wh5N2ReN.js → cynefin-VYW2F7L2-CGRpxWNJ.js} +1 -1
  42. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-Dlu5wIqs.js → cynefinDiagram-MW4NZA55-Cd3uFGE4.js} +1 -1
  43. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-CrDgthc6.js → dagre-VZM6K2ZE-DmDHuUW0.js} +1 -1
  44. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-zN1clg27.js → diagram-7IWD3JNH-kAr--hF3.js} +1 -1
  45. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-BN-o7J7-.js → diagram-B4RE2ZJO-woahL2Oh.js} +1 -1
  46. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-C8SuPt0d.js → diagram-LBJQPF4R-7syNVaNf.js} +1 -1
  47. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-BoizuHbZ.js → diagram-Q27KOJAE-BELPXiaY.js} +1 -1
  48. package/dist/worker/console/static/assets/{diagram-UB23O5K3-BzUzXixG.js → diagram-UB23O5K3-CrPa4aXi.js} +1 -1
  49. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-Ev3lA4Cf.js → ebnfDiagram-BXEA7PRR-B48u2VVe.js} +1 -1
  50. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-GALUzRbs.js → erDiagram-JOGREHBK-DhBTfwTF.js} +1 -1
  51. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CZJN65Sb.js → flowDiagram-UKHOOZJN-CAeZ5nDU.js} +1 -1
  52. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-JLB9OESl.js → ganttDiagram-PKOTCBZU-CkIFeFLN.js} +1 -1
  53. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-CcvCr4GD.js → gitGraphDiagram-DS77QQ5N-t0HGYDel.js} +1 -1
  54. package/dist/worker/console/static/assets/index-B4l5ag79.js +407 -0
  55. package/dist/worker/console/static/assets/index-CwVHWB71.css +1 -0
  56. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-HG5z7aVg.js → infoDiagram-6WML65LV-WM0HZhe4.js} +1 -1
  57. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-BHEu9chR.js → ishikawaDiagram-WSZJBQD7-CV5byHe0.js} +1 -1
  58. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-Cp_Up8-a.js → journeyDiagram-NVQOT4AX-lIyWkgnw.js} +1 -1
  59. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-DvVeY-em.js → kanban-definition-27J2QSJJ-BIH4YNRY.js} +1 -1
  60. package/dist/worker/console/static/assets/{linear-aGmcjgTn.js → linear-lQ0ZGrWc.js} +1 -1
  61. package/dist/worker/console/static/assets/{mermaid.core-Biyo-tqA.js → mermaid.core-BYdXtke8.js} +5 -5
  62. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-DyxY2pIb.js → mindmap-definition-FAOFIHXS-k93vkIa4.js} +1 -1
  63. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-CkdGuc50.js → pegDiagram-VL7TDLO6-Bm6AqvSy.js} +1 -1
  64. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-NNQI9xVR.js → pieDiagram-7S7Q4E2Y-DnJW6Xpf.js} +1 -1
  65. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-PAJkuz_G.js → quadrantDiagram-CIZ2JOQS-CMzm4ObL.js} +1 -1
  66. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-ZwrQod0O.js → railroadDiagram-AXF67PYL-fwFF5dFQ.js} +1 -1
  67. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-D3ZfrzM2.js → requirementDiagram-LRYGKXZP-tzl9VDUc.js} +1 -1
  68. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-DDGFmWk5.js → sankeyDiagram-W5VNT64P-B26V09DD.js} +1 -1
  69. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DO6mmXTA.js → sequenceDiagram-SI44F4Z6-D2npyCeP.js} +1 -1
  70. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-DMbCQiJt.js → sizeCapture-X5ZJPWSS-CTJtkRU2.js} +1 -1
  71. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-Di_YUEfC.js → stateDiagram-OKZ733FA-B8lk4Lzu.js} +1 -1
  72. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BmOcMTJE.js +1 -0
  73. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-Bn2PphNJ.js → swimlanes-SLNWSIFB-C3yP53hH.js} +2 -2
  74. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Beah-dq0.js +8 -0
  75. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-DPh8pRsp.js → timeline-definition-Z64GVDOM-Bck7xjhe.js} +1 -1
  76. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-GMfl26pW.js → vennDiagram-T6HMQDX7-CCntr1w7.js} +1 -1
  77. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DTlmVrmF.js → wardleyDiagram-T6FBY63Y-DsCqCBZz.js} +1 -1
  78. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-YGBjKAS5.js → xychartDiagram-ELKLHX3M-Br2l90OM.js} +1 -1
  79. package/dist/worker/console/static/index.html +2 -2
  80. package/dist/worker/console/static-src/app/console-types.js +29 -4
  81. package/dist/worker/console/static-src/app/useConsoleShell.js +30 -12
  82. package/dist/worker/console/static-src/app/useOperatorActions.js +36 -6
  83. package/dist/worker/console/static-src/app/useRecoveryConsole.js +10 -11
  84. package/dist/worker/console/static-src/app/useRunProgress.js +2 -1
  85. package/dist/worker/console/static-src/app/useTaskWizard.js +2 -2
  86. package/dist/worker/console/static-src/night/useNightBoard.js +8 -5
  87. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +140 -8
  88. package/dist/worker/console/static-src/operator-chat/details-dag-actions.js +122 -0
  89. package/dist/worker/console/static-src/operator-chat/refs.js +3 -0
  90. package/dist/worker/console/static-src/operator-chat/runtime-selection-labels.js +27 -0
  91. package/dist/worker/console/static-src/operator-chat/turn-submission.js +3 -2
  92. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +168 -72
  93. package/dist/worker/console/static-src/operator-chat/useChatStream.js +78 -17
  94. package/dist/worker/console/static-src/operator-chat/useChatThread.js +184 -4
  95. package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +63 -9
  96. package/dist/worker/console/static-src/operator-chat/useWorkspaceBrowserGate.js +4 -0
  97. package/dist/worker/console/static-src/operator-chat/workspace-layout-mode.js +3 -3
  98. package/dist/worker/console/static-src/shell/useWorkspaces.js +299 -0
  99. package/dist/worker/console/static-src/shell/workspace-route.js +337 -0
  100. package/dist/worker/console/workspace-context.js +234 -0
  101. package/dist/worker/console/workspace-registry.js +214 -0
  102. package/dist/worker/observe/server.js +4 -0
  103. package/dist/worker/observe/static/api.js +26 -6
  104. package/dist/worker/observe/static/app.js +18 -70
  105. package/dist/worker/observe/static/index.html +1 -1
  106. package/dist/worker/observe/static/inspect-workspace.js +307 -0
  107. package/dist/worker/observe/static/operator-chrome.css +145 -20
  108. package/dist/worker/observe/static/operator-chrome.d.ts +20 -3
  109. package/dist/worker/observe/static/operator-chrome.js +330 -100
  110. package/dist/worker/observe/static/router.d.ts +46 -0
  111. package/dist/worker/observe/static/router.js +25 -1
  112. package/dist/worker/observe/static/state.d.ts +50 -0
  113. package/dist/worker/observe/static/state.js +172 -0
  114. package/dist/worker/observe/static/views/dag-inspector.js +3 -2
  115. package/dist/worker/observe/static/views/dag.js +2 -1
  116. package/dist/worker/observe/static/views/dashboard.js +6 -4
  117. package/dist/worker/observe/static/views/night.js +2 -2
  118. package/dist/worker/observe/static/views/pool.js +1 -0
  119. package/dist/worker/observe/static/views/run.js +3 -1
  120. package/dist/worker/observe/static/views/task.js +1 -1
  121. package/dist/workflows/dag/backend-test-pytest-collection.js +11 -10
  122. package/dist/workflows/dag/interrupt-request.js +3 -3
  123. package/dist/workflows/dag/lifecycle.js +3 -3
  124. package/docs/README.md +1 -0
  125. package/docs/operations/local-development-environment.md +21 -0
  126. package/harness.json +3 -3
  127. package/package.json +3 -1
  128. package/dist/worker/console/static/assets/channel-Dj_4Moei.js +0 -1
  129. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C0YYAyCa.js +0 -1
  130. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C0YYAyCa.js +0 -1
  131. package/dist/worker/console/static/assets/index-CW88Fjbw.js +0 -406
  132. package/dist/worker/console/static/assets/index-DP0ZJl39.css +0 -1
  133. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DrdDvela.js +0 -1
  134. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DPkEAULl.js +0 -8
@@ -0,0 +1,50 @@
1
+ /** 与 state.js 对应的类型声明(供 vitest/TS 侧导入契约测试)。 */
2
+
3
+ export type ViewStateKind = "loading" | "empty" | "degraded" | "error";
4
+
5
+ export type ViewStateDescriptor = {
6
+ kind: ViewStateKind;
7
+ className: string;
8
+ role: string | null;
9
+ ariaLive: string | null;
10
+ message: string;
11
+ detail: string | null;
12
+ messageClass: string | null;
13
+ };
14
+
15
+ export const uiState: {
16
+ lastSnapshot: unknown;
17
+ specEvidenceDetail: {
18
+ source: string;
19
+ path: string;
20
+ loading: boolean;
21
+ error: string | null;
22
+ data: unknown;
23
+ triggerId: string | null;
24
+ } | null;
25
+ dagNodeExecutionOutputCache: Map<string, unknown> | null;
26
+ [key: string]: unknown;
27
+ };
28
+
29
+ export function setWorkspaceScope(workspaceId: string | null): void;
30
+ export function workspaceScope(): string | null;
31
+ export function scopedApiUrl(url: string): string;
32
+ export function workspaceRequestSignal(): AbortSignal | undefined;
33
+ export function fetchWithWorkspaceScope(
34
+ url: string,
35
+ init?: RequestInit,
36
+ ): Promise<Response>;
37
+ export function abortWorkspaceRequests(): void;
38
+ export function setWorkspaceActive(active: boolean): void;
39
+ export function stopTimers(): void;
40
+ export function pauseForegroundTimers(): void;
41
+
42
+ /** Multi-workspace atomic scope switch (2026-08-26, AC-006). */
43
+ export function applyWorkspaceScopeSwitch(
44
+ nextWorkspaceId: string | null,
45
+ routeValue?: (() => void) | string,
46
+ options?: {
47
+ route?: (hashValue: string) => void;
48
+ onTrace?: (trace: string[]) => void;
49
+ },
50
+ ): string[];
@@ -116,6 +116,8 @@ export const uiState = {
116
116
  /** Last-rendered spec-evidence list, used to restore the list synchronously. */
117
117
  specEvidenceListEvidence: null,
118
118
  pollingGeneration: 0,
119
+ /** Hosted Inspect workspace is foreground. Standalone defaults to active. */
120
+ workspaceActive: true,
119
121
  };
120
122
 
121
123
  /** Per-dagRunId graph viewport restore map (stable Map instance). */
@@ -279,16 +281,186 @@ export function isPageVisible() {
279
281
  );
280
282
  }
281
283
 
284
+ export function isWorkspaceActive() {
285
+ return uiState.workspaceActive !== false;
286
+ }
287
+
288
+ export function setWorkspaceActive(active) {
289
+ uiState.workspaceActive = Boolean(active);
290
+ }
291
+
292
+ /**
293
+ * Multi-workspace scope (2026-08-23): every Observe GET must carry the
294
+ * current workspaceId (AC-002/AC-003). The scope is synced from the parent
295
+ * Console shell hash (`?workspaceId=`) or via postMessage for hosted mode;
296
+ * standalone pages default to null and all workspace-scoped routes fail closed
297
+ * until the host or hash publishes an explicit workspace id.
298
+ */
299
+ let currentWorkspaceScope = null;
300
+ let currentWorkspaceRequestController =
301
+ typeof AbortController === "undefined" ? null : new AbortController();
302
+
303
+ export function setWorkspaceScope(workspaceId) {
304
+ currentWorkspaceScope =
305
+ typeof workspaceId === "string" && workspaceId.trim()
306
+ ? workspaceId.trim()
307
+ : null;
308
+ }
309
+
310
+ export function workspaceScope() {
311
+ return currentWorkspaceScope;
312
+ }
313
+
314
+ /** Signal shared by every workspace-scoped Observe request in the active scope. */
315
+ export function workspaceRequestSignal() {
316
+ if (
317
+ typeof AbortController !== "undefined" &&
318
+ (!currentWorkspaceRequestController ||
319
+ currentWorkspaceRequestController.signal.aborted)
320
+ ) {
321
+ currentWorkspaceRequestController = new AbortController();
322
+ }
323
+ return currentWorkspaceRequestController?.signal;
324
+ }
325
+
326
+ function combinedRequestSignal(scopeSignal, requestSignal) {
327
+ const signals = [scopeSignal, requestSignal].filter(Boolean);
328
+ if (signals.length <= 1) return { signal: signals[0], cleanup: () => {} };
329
+ const controller = new AbortController();
330
+ const abort = () => controller.abort();
331
+ for (const signal of signals) {
332
+ if (signal.aborted) abort();
333
+ else signal.addEventListener("abort", abort, { once: true });
334
+ }
335
+ return {
336
+ signal: controller.signal,
337
+ cleanup: () => {
338
+ for (const signal of signals) signal.removeEventListener("abort", abort);
339
+ },
340
+ };
341
+ }
342
+
343
+ /** Fetch through the current workspace boundary and abort on any scope swap. */
344
+ export async function fetchWithWorkspaceScope(url, init = {}) {
345
+ const { signal: requestSignal, ...rest } = init;
346
+ const combined = combinedRequestSignal(
347
+ workspaceRequestSignal(),
348
+ requestSignal,
349
+ );
350
+ try {
351
+ return await fetch(scopedApiUrl(url), {
352
+ ...rest,
353
+ ...(combined.signal ? { signal: combined.signal } : {}),
354
+ });
355
+ } finally {
356
+ combined.cleanup();
357
+ }
358
+ }
359
+
360
+ /** Abort every old-scope request and invalidate request identity guards. */
361
+ export function abortWorkspaceRequests() {
362
+ currentWorkspaceRequestController?.abort();
363
+ currentWorkspaceRequestController =
364
+ typeof AbortController === "undefined" ? null : new AbortController();
365
+ uiState.dagHistoryAbortController?.abort?.();
366
+ uiState.dagHistoryAbortController = null;
367
+ uiState.dagHistoryRequestSeq += 1;
368
+ uiState.dagHistoryPrefetchGeneration += 1;
369
+ uiState.dagNodeInputRequestSeq += 1;
370
+ uiState.dagNodeProcessRequestSeq += 1;
371
+ uiState.dagNodeExecutionOutputRequestSeq += 1;
372
+ }
373
+
374
+ /** Multi-workspace atomic scope switch (2026-08-26, AC-006).
375
+ *
376
+ * Contract order — strictly sequential, no interleaving:
377
+ * 1. abort old — stop every poll/SSE so no late request can race the swap;
378
+ * 2. clear old — drop cached run/task/selection state of the old scope;
379
+ * 3. set scope — publish the new workspaceId for scopedApiUrl;
380
+ * 4. reload new — re-route/re-render with the new scope active.
381
+ *
382
+ * Observability: each stage appends to the returned trace so tests (and
383
+ * diagnostics) can assert the exact ordering; there is no window in which a
384
+ * new route is requested with the old scope or vice versa.
385
+ */
386
+ export function applyWorkspaceScopeSwitch(
387
+ nextWorkspaceId,
388
+ routeValue,
389
+ options = {},
390
+ ) {
391
+ const trace = [];
392
+ // 1. abort old
393
+ abortWorkspaceRequests();
394
+ stopTimers();
395
+ pauseForegroundTimers();
396
+ trace.push("abort-old");
397
+ // 2. clear old
398
+ uiState.lastSnapshot = null;
399
+ uiState.specEvidenceDetail = null;
400
+ uiState.specEvidenceListEvidence = null;
401
+ clearDagNodeExecutionOutputCache();
402
+ trace.push("clear-old");
403
+ // 3. set scope
404
+ setWorkspaceScope(nextWorkspaceId);
405
+ trace.push(`set-scope:${workspaceScope() ?? ""}`);
406
+ // 4. route/reload new
407
+ if (typeof routeValue === "function") routeValue();
408
+ else if (typeof routeValue === "string") options.route?.(routeValue);
409
+ trace.push("route-new");
410
+ if (options.onTrace) options.onTrace(trace);
411
+ return trace;
412
+ }
413
+
414
+ /** Append ?workspaceId= to an observe API URL (real request path kept). */
415
+ export function scopedApiUrl(url) {
416
+ const raw = String(url ?? "");
417
+ if (!currentWorkspaceScope || !raw.startsWith("/api/")) return raw;
418
+ const qIndex = raw.indexOf("?");
419
+ if (qIndex >= 0) {
420
+ const params = new URLSearchParams(raw.slice(qIndex + 1));
421
+ if (params.has("workspaceId")) return raw;
422
+ params.set("workspaceId", currentWorkspaceScope);
423
+ return `${raw.slice(0, qIndex)}?${params.toString()}`;
424
+ }
425
+ return `${raw}?workspaceId=${encodeURIComponent(currentWorkspaceScope)}`;
426
+ }
427
+
282
428
  export function detailPollDelay(status, isVisible) {
283
429
  const normalizedStatus = (status ?? "").toLowerCase().replace(/-/g, "_");
284
430
  if (TERMINAL_RUN_STATUSES.has(normalizedStatus)) return null;
431
+ if (!isWorkspaceActive()) return null;
285
432
  return isVisible ? ACTIVE_DETAIL_POLL_MS : HIDDEN_POLL_MS;
286
433
  }
287
434
 
288
435
  export function dashboardPollDelay() {
436
+ if (!isWorkspaceActive()) return null;
289
437
  return isPageVisible() ? DASHBOARD_POLL_MS : HIDDEN_POLL_MS;
290
438
  }
291
439
 
440
+ /** Stop pausable timers without destroying route/selection/scroll. */
441
+ export function pauseForegroundTimers() {
442
+ if (uiState.dashboardTimer) {
443
+ clearTimeout(uiState.dashboardTimer);
444
+ uiState.dashboardTimer = null;
445
+ }
446
+ if (uiState.runPollTimer) {
447
+ clearTimeout(uiState.runPollTimer);
448
+ uiState.runPollTimer = null;
449
+ }
450
+ if (uiState.dagPollTimer) {
451
+ clearTimeout(uiState.dagPollTimer);
452
+ uiState.dagPollTimer = null;
453
+ }
454
+ if (uiState.poolTimer) {
455
+ clearTimeout(uiState.poolTimer);
456
+ uiState.poolTimer = null;
457
+ }
458
+ if (uiState.taskPollTimer) {
459
+ clearTimeout(uiState.taskPollTimer);
460
+ uiState.taskPollTimer = null;
461
+ }
462
+ }
463
+
292
464
  export function updateDagGraphViewportState(
293
465
  _previous,
294
466
  dagRunId,
@@ -25,6 +25,7 @@ import { describeDagNodePurpose } from "../dag-node-purpose.js";
25
25
  import { buildPromptRestartCandidateOptions } from "../prompt-restart-candidates.js";
26
26
  import { copyText } from "../copy.js";
27
27
  import {
28
+ fetchWithWorkspaceScope,
28
29
  uiState,
29
30
  makeSessionEventIdentity,
30
31
  makeDagNodeInputIdentity,
@@ -1286,7 +1287,7 @@ export function frontendGateLedgerLines(input) {
1286
1287
  /** DAG run 专属 prewrite-result 只读拉取(内联 fetch,不新增 api.js 依赖)。 */
1287
1288
  async function fetchPrewriteResultJson(dagRunId) {
1288
1289
  try {
1289
- const res = await fetch(
1290
+ const res = await fetchWithWorkspaceScope(
1290
1291
  `/api/dag-runs/${encodeURIComponent(dagRunId)}/prewrite-result`,
1291
1292
  { credentials: "same-origin" },
1292
1293
  );
@@ -2012,7 +2013,7 @@ function effectiveExecutionKey(dagRunId, node) {
2012
2013
  async function fetchExecutionOutput(dagRunId, nodeId, key) {
2013
2014
  const url = `/api/dag-runs/${encodeURIComponent(dagRunId)}/nodes/${encodeURIComponent(nodeId)}/execution-output?key=${encodeURIComponent(key)}`;
2014
2015
  try {
2015
- const res = await fetch(url);
2016
+ const res = await fetchWithWorkspaceScope(url);
2016
2017
  let body = null;
2017
2018
  try {
2018
2019
  body = await res.json();
@@ -364,7 +364,7 @@ export async function renderDagDetail(dagRunId, initial = true) {
364
364
  "page-action-btn",
365
365
  "在操作台中止此运行 →",
366
366
  );
367
- interruptLink.href = `/#/recovery?dagRunId=${encodeURIComponent(dag.dagRunId)}&intent=interrupt`;
367
+ interruptLink.href = `/#/operate/recovery?dagRunId=${encodeURIComponent(dag.dagRunId)}&intent=interrupt`;
368
368
  interruptLink.setAttribute("data-testid", "inspect-dag-interrupt-link");
369
369
  interruptLink.title = "只跳转到操作台 Recovery,不会在观测页执行中止";
370
370
  primaryEntries.push(["协作中止", interruptLink]);
@@ -482,6 +482,7 @@ export function startDagPolling(dagRunId, initial = true) {
482
482
  const active = await renderDagDetail(dagRunId, isInitial);
483
483
  if (generation !== uiState.pollingGeneration || !active) return;
484
484
  const delay = detailPollDelay("running", isPageVisible());
485
+ if (delay == null) return;
485
486
  uiState.dagPollTimer = setTimeout(() => {
486
487
  uiState.dagPollTimer = null;
487
488
  void poll(false);
@@ -84,7 +84,7 @@ let dashboardLoadingNode = null;
84
84
 
85
85
  /**
86
86
  * 「昨夜班次」条带:夜间结果在观测侧的唯一一级呈现(替代旧「夜间任务」tab)。
87
- * 管理动作(晨审处置)始终落在操作侧 /#/night,保持 Inspect 只读不变式。
87
+ * 管理动作(晨审处置)始终落在操作侧 /#/operate/night,保持 Inspect 只读不变式。
88
88
  */
89
89
  async function renderNightStrip() {
90
90
  const strip = document.getElementById("dashboard-night");
@@ -118,14 +118,14 @@ async function renderNightStrip() {
118
118
 
119
119
  const actions = el("div", "night-strip-actions");
120
120
  const detail = el("a", "page-action-btn", "夜间详情");
121
- detail.href = "#/night";
121
+ detail.href = "/#/inspect/night";
122
122
  detail.addEventListener("click", (e) => {
123
123
  e.preventDefault();
124
124
  navigate("/night");
125
125
  });
126
126
  actions.appendChild(detail);
127
127
  const manage = el("a", "page-action-btn night-strip-manage", "晨审处置 →");
128
- manage.href = "/#/night";
128
+ manage.href = "/#/operate/night";
129
129
  manage.title = "夜间计划的管理与晨审处置在操作台完成(Inspect 保持只读)";
130
130
  actions.appendChild(manage);
131
131
  strip.appendChild(actions);
@@ -738,10 +738,12 @@ export function startDashboardPolling(scrollTo) {
738
738
  const poll = async (initialScrollTo) => {
739
739
  await renderDashboard(initialScrollTo);
740
740
  if (generation !== uiState.pollingGeneration) return;
741
+ const delay = dashboardPollDelay();
742
+ if (delay == null) return;
741
743
  uiState.dashboardTimer = setTimeout(() => {
742
744
  uiState.dashboardTimer = null;
743
745
  void poll();
744
- }, dashboardPollDelay());
746
+ }, delay);
745
747
  };
746
748
  void poll(scrollTo);
747
749
  }
@@ -46,8 +46,8 @@ export async function renderNightJobs(scheduleId) {
46
46
  showView("night");
47
47
  bindNightToolbar();
48
48
  const crumbs = [
49
- { label: UI_TEXT.dashboard, href: "#/" },
50
- { label: UI_TEXT.nightJobs, href: "#/night" },
49
+ { label: UI_TEXT.dashboard, href: "/#/inspect" },
50
+ { label: UI_TEXT.nightJobs, href: "/#/inspect/night" },
51
51
  ];
52
52
  if (scheduleId) crumbs.push({ label: scheduleId });
53
53
  setBreadcrumb(crumbs);
@@ -93,6 +93,7 @@ function startPoolAutoPolling() {
93
93
  if (generation !== uiState.pollingGeneration) return;
94
94
  if (!poolAutoRefreshEnabled()) return;
95
95
  const delay = isPageVisible() ? POOL_POLL_MS : dashboardPollDelay();
96
+ if (delay == null) return;
96
97
  uiState.poolTimer = setTimeout(() => {
97
98
  uiState.poolTimer = null;
98
99
  void poll();
@@ -50,6 +50,7 @@ import {
50
50
  } from "../relations.js";
51
51
  import { copyText, renderRecommendedCommand } from "../copy.js";
52
52
  import {
53
+ fetchWithWorkspaceScope,
53
54
  isPageVisible,
54
55
  detailPollDelay,
55
56
  dashboardPollDelay,
@@ -126,7 +127,7 @@ export function renderInlineArtifactList(container, artifacts) {
126
127
  list.appendChild(li);
127
128
  void (async () => {
128
129
  try {
129
- const res = await fetch(artifactUrl(artifactPath));
130
+ const res = await fetchWithWorkspaceScope(artifactUrl(artifactPath));
130
131
  const text = await res.text();
131
132
  if (!res.ok) {
132
133
  let message = text;
@@ -444,6 +445,7 @@ export function startRunPolling(workerRunId, initial = true) {
444
445
  const active = await renderRun(workerRunId, isInitial);
445
446
  if (generation !== uiState.pollingGeneration || !active) return;
446
447
  const delay = detailPollDelay("running", isPageVisible());
448
+ if (delay == null) return;
447
449
  uiState.runPollTimer = setTimeout(() => {
448
450
  uiState.runPollTimer = null;
449
451
  void poll(false);
@@ -86,7 +86,7 @@ export async function renderTaskDetail(featureId, taskId) {
86
86
  showView("task");
87
87
  setBreadcrumb([
88
88
  { label: UI_TEXT.dashboard, href: "#/" },
89
- { label: "资源池", href: "#/pool" },
89
+ { label: "资源池", href: "/#/inspect/pool" },
90
90
  { label: displayLabel },
91
91
  ]);
92
92
 
@@ -258,13 +258,14 @@ function bounded(value) {
258
258
  ? normalized
259
259
  : `${normalized.slice(0, MAX_DIAGNOSTIC_CHARS)}\n...[truncated]`;
260
260
  }
261
- function collectionItems(stdout) {
261
+ function collectionItems(stdout, layout) {
262
+ const rootPrefix = `${(layout ?? resolveBackendTestLayout(undefined)).testRoot}/`;
262
263
  return [...new Set(stdout.split(/\r?\n/).map((line) => line.trim()).filter((line) => {
263
264
  if (!line.includes("::"))
264
265
  return false;
265
266
  if (/^(ERROR|FAILED|E\s+)/.test(line))
266
267
  return false;
267
- return /^testcase\//.test(line.replaceAll("\\", "/"));
268
+ return line.replaceAll("\\", "/").startsWith(rootPrefix);
268
269
  }).map((line) => line.replaceAll("\\", "/")))];
269
270
  }
270
271
  function escapeRegExp(value) {
@@ -416,7 +417,7 @@ function classifyCollectionFailure(output, evidence) {
416
417
  return { status: "BLOCKED", kind: "unclassified-collection-error", detail: "collection failure cannot be safely attributed to generated testcase assets" };
417
418
  }
418
419
  export function assessBackendPytestCollection(input) {
419
- const items = collectionItems(input.stdout);
420
+ const items = collectionItems(input.stdout, input.layout);
420
421
  const fixtureResolution = input.fixtureResolution ?? { exitCode: 0, stdout: "fixture resolution assumed by direct assessor", stderr: "" };
421
422
  if (input.exitCode === 0 && fixtureResolution.exitCode === 0) {
422
423
  return backendPytestCollectionFactsSchema.parse({
@@ -740,7 +741,7 @@ export async function materializeBackendTestExecutionReadiness(input) {
740
741
  if (input.effective.phase !== "effective" || input.effective.status !== "PASS" || input.effective.fixtureResolutionStatus !== "PASS") {
741
742
  throw new Error("backend-test execution readiness requires effective collection and fixture-resolution PASS");
742
743
  }
743
- const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.effective.mappedScripts);
744
+ const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.effective.mappedScripts, { layout: input.layout });
744
745
  assertSameInventory(input.effective, current);
745
746
  const eligibility = input.eligibility ?? { eligibleItemIds: input.effective.collectedItemIds, excludedItems: [] };
746
747
  const status = eligibility.eligibleItemIds.length === 0
@@ -839,7 +840,7 @@ async function firstUnreadableAssetPath(workspaceRoot, readiness) {
839
840
  }
840
841
  return undefined;
841
842
  }
842
- export async function assertBackendTestExecutionReadinessFresh(workspaceRoot, readiness) {
843
+ export async function assertBackendTestExecutionReadinessFresh(workspaceRoot, readiness, layout) {
843
844
  if (!["PASS", "PARTIAL"].includes(readiness.status)) {
844
845
  const counts = formatReadinessCounts(readiness);
845
846
  const reasonTally = readiness.eligibleItemIds.length === 0 && readiness.excludedItems.length > 0
@@ -862,7 +863,7 @@ export async function assertBackendTestExecutionReadinessFresh(workspaceRoot, re
862
863
  }
863
864
  let current;
864
865
  try {
865
- current = await buildBackendPytestAssetInventory(workspaceRoot, readiness.mappedScripts);
866
+ current = await buildBackendPytestAssetInventory(workspaceRoot, readiness.mappedScripts, { layout });
866
867
  }
867
868
  catch {
868
869
  const fallbackPath = [...readiness.mappedScripts].sort()[0] ?? Object.keys(readiness.assetHashes).sort()[0] ?? "unknown";
@@ -897,11 +898,11 @@ export async function assertBackendTestExecutionReadinessFresh(workspaceRoot, re
897
898
  }
898
899
  }
899
900
  }
900
- export async function assertBackendPytestCollectionFresh(workspaceRoot, effective) {
901
+ export async function assertBackendPytestCollectionFresh(workspaceRoot, effective, layout) {
901
902
  if (effective.phase !== "effective" || effective.status !== "PASS") {
902
903
  throw new Error("backend pytest execution requires effective collection PASS facts");
903
904
  }
904
- const current = await buildBackendPytestAssetInventory(workspaceRoot, effective.mappedScripts);
905
+ const current = await buildBackendPytestAssetInventory(workspaceRoot, effective.mappedScripts, { layout });
905
906
  const priorityOnly = priorityOnlyBackendPytestScripts(current.assetFiles);
906
907
  if (priorityOnly.length > 0)
907
908
  throw new Error(`priority-only-pytest-module: ${priorityOnly.join(", ")}`);
@@ -909,7 +910,7 @@ export async function assertBackendPytestCollectionFresh(workspaceRoot, effectiv
909
910
  }
910
911
  export async function materializeEffectiveBackendPytestCollection(input) {
911
912
  if (input.initial.status === "PASS") {
912
- const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.initial.mappedScripts);
913
+ const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.initial.mappedScripts, { layout: input.layout });
913
914
  const priorityOnly = priorityOnlyBackendPytestScripts(current.assetFiles);
914
915
  if (priorityOnly.length > 0)
915
916
  throw new Error(`priority-only-pytest-module: ${priorityOnly.join(", ")}`);
@@ -927,7 +928,7 @@ export async function materializeEffectiveBackendPytestCollection(input) {
927
928
  if (input.final.status !== "PASS")
928
929
  throw new Error("backend pytest collection still fails after bounded repair");
929
930
  await assertBackendPytestRepairSafety(input.workspaceRoot, input.initial, input.final);
930
- const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.final.mappedScripts);
931
+ const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.final.mappedScripts, { layout: input.layout });
931
932
  const priorityOnly = priorityOnlyBackendPytestScripts(current.assetFiles);
932
933
  if (priorityOnly.length > 0)
933
934
  throw new Error(`priority-only-pytest-module: ${priorityOnly.join(", ")}`);
@@ -1,8 +1,8 @@
1
1
  import { watch } from "node:fs";
2
- import { mkdir, readFile } from "node:fs/promises";
2
+ import { mkdir } from "node:fs/promises";
3
3
  import { hostname as localHostname } from "node:os";
4
4
  import path from "node:path";
5
- import { writeJsonAtomic } from "../../infrastructure/harness/atomic-write.js";
5
+ import { readJsonWithTransientRetry, writeJsonAtomic, } from "../../infrastructure/harness/atomic-write.js";
6
6
  import { assessDagRunLiveness, getDagRunDir, locateDagRun, readDagRunState, } from "./lifecycle.js";
7
7
  export const INTERRUPT_ARTIFACT_REL = path.posix.join(".runtime", "interrupt.json");
8
8
  export const INTERRUPT_REASON_CODES = [
@@ -140,7 +140,7 @@ export function parseInterruptRequest(raw) {
140
140
  }
141
141
  export async function readInterruptRequest(runDir) {
142
142
  try {
143
- const raw = JSON.parse(await readFile(interruptArtifactPath(runDir), "utf-8"));
143
+ const raw = await readJsonWithTransientRetry(interruptArtifactPath(runDir));
144
144
  return parseInterruptRequest(raw);
145
145
  }
146
146
  catch (error) {
@@ -1,7 +1,7 @@
1
1
  import { access, mkdir, readFile, readdir, rename } from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { hostname as localHostname } from "node:os";
4
- import { writeJsonAtomic, } from "../../infrastructure/harness/atomic-write.js";
4
+ import { readJsonWithTransientRetry, writeJsonAtomic, } from "../../infrastructure/harness/atomic-write.js";
5
5
  import { parseDagSpec } from "./types.js";
6
6
  import { normalizeDagFailureCategory, } from "./failure-category.js";
7
7
  import { dagProductLineFailureCategoryValues, routeDagFailure, } from "./failure-routing.js";
@@ -43,14 +43,14 @@ export async function dagRunDirExists(runDir) {
43
43
  }
44
44
  }
45
45
  export async function readDagRunState(runDir) {
46
- const raw = JSON.parse(await readFile(path.join(runDir, "state.json"), "utf-8"));
46
+ const raw = await readJsonWithTransientRetry(path.join(runDir, "state.json"));
47
47
  return raw;
48
48
  }
49
49
  export async function writeDagRunState(runDir, state, options) {
50
50
  await writeJsonAtomic(path.join(runDir, "state.json"), state, options);
51
51
  }
52
52
  export async function readDagRunSpec(runDir) {
53
- const raw = JSON.parse(await readFile(path.join(runDir, "run.json"), "utf-8"));
53
+ const raw = await readJsonWithTransientRetry(path.join(runDir, "run.json"));
54
54
  return parseDagSpec(raw);
55
55
  }
56
56
  export async function locateDagRun(cwd, runId) {
package/docs/README.md CHANGED
@@ -73,6 +73,7 @@
73
73
  | `design/active/` | 仍会影响后续决策的设计输入、路线与契约 |
74
74
  | `design/visual-references/` | 长期视觉参考,不表达实现状态 |
75
75
  | `design/archive/` | 历史设计和已被实现/替代的阶段性设计 |
76
+ | `superpowers/specs/` | Superpowers 工作流产出的阶段性实现设计输入 |
76
77
  | `exec-plans/active/` | 仍需推进或明确保持 open 的任务合同 |
77
78
  | `exec-plans/completed/` | 已完成任务合同归档 |
78
79
  | `progress/` | 仍需下一次会话接手的当前 handoff 入口 |
@@ -2,6 +2,27 @@
2
2
 
3
3
  本文记录仅与特定开发环境有关、但可能反复影响验证结果的问题。它不是通用工程规则;标准验证命令仍以 [`verification-matrix.md`](../governance/verification-matrix.md) 为准。
4
4
 
5
+ ## Operator Console 前端快速迭代
6
+
7
+ 对 `src/worker/console/static-src/` 内的对话样式和前端交互做高频调整时,使用固定 8790 的开发入口:
8
+
9
+ ```bash
10
+ npm run console:dev
11
+ ```
12
+
13
+ 它从当前源码启动真实 Console 后端,并在内部 `8791` 常驻 Vite dev server。浏览器始终访问 `http://127.0.0.1:8790/`:API、HttpOnly Cookie、确认令牌和 Origin 校验仍由真实 Console 处理,前端 HTML/模块请求才由 8790 转发给 Vite。CSS 保存后原地热替换,TSX 保存后自动整页刷新;不生成 `static-dev` bundle,也不重复运行生产 build。
14
+
15
+ 常用参数:
16
+
17
+ ```bash
18
+ npm run console:dev -- --no-open
19
+ npm run console:dev -- --port 8792 --reload-port 8793 --no-open
20
+ ```
21
+
22
+ 默认端口是 Console `8790`、内部 Vite/HMR `8791`;两者都只允许 loopback。端口已占用时命令会失败并报告端口,不会停止或接管已有进程。前端类型检查在后台持续输出诊断,但不阻塞 HMR;后端源码变化时只重启 Console 子进程,Vite 保持常驻。
23
+
24
+ 该命令只优化编辑反馈,不构成验收。独立交互修复完成后仍需运行定向 Vitest;交付前按验证矩阵运行 typecheck、正式 `npm run console:build` / `npm run build`。正式构建继续写入 `dist/worker/console/static/`,不会包含 `/@vite/client`、8791 或开发代理代码。
25
+
5
26
  ## Git hooks(本仓库)
6
27
 
7
28
  每个 clone 安装一次:
package/harness.json CHANGED
@@ -82,9 +82,9 @@
82
82
  "executors": {
83
83
  "pi": {
84
84
  "description": "Pi 负责规划、评审、诊断;当 DAG toolProfile=write 时也可做有界写入。模型按复杂度三档配置,支持 provider/model 字符串或带 thinking 的对象;斜杠前为 Pi provider,后为 modelId,勿只写裸 modelId。",
85
- "LOW": "deepseek/deepseek-v4-flash",
86
- "MED": "deepseek/deepseek-v4-flash",
87
- "HIGH": "deepseek/deepseek-v4-flash"
85
+ "LOW": "wizard-local/minimax-m3",
86
+ "MED": "wizard-local/glm-5.3",
87
+ "HIGH": "wizard-local/gpt-5.6-sol"
88
88
  }
89
89
  }
90
90
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tea-agent/loop-agent",
3
- "version": "0.40.0-next.4",
3
+ "version": "0.40.0-next.6",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "loop-agent": "bin/loop-agent.js",
@@ -54,6 +54,7 @@
54
54
  "build": "npm run brand:sync && npm run clean && tsc -p tsconfig.build.json && node -e \"const fs=require('node:fs');const p='dist/worker/observe/static';fs.mkdirSync(p,{recursive:true});fs.cpSync('src/worker/observe/static',p,{recursive:true});\" && npm run console:build && node scripts/write-build-stamp.mjs",
55
55
  "console:typecheck": "tsc -p src/worker/console/tsconfig.json",
56
56
  "console:build": "npm run console:typecheck && vite build --config src/worker/console/vite.config.ts",
57
+ "console:dev": "node --import tsx/esm scripts/console-dev.mjs",
57
58
  "prepack": "npm run build",
58
59
  "prepublishOnly": "node scripts/check-npm-publish-policy.mjs && npm run typecheck && npm test && npm run build",
59
60
  "lint": "npm run typecheck",
@@ -71,6 +72,7 @@
71
72
  "verify:tree": "node scripts/pre-push-verify.mjs --verify-current-tree"
72
73
  },
73
74
  "dependencies": {
75
+ "@deepseek-ai/dsh-host-directory-picker-native": "0.1.1-rc.2",
74
76
  "@earendil-works/pi-ai": "0.83.0",
75
77
  "@earendil-works/pi-coding-agent": "0.83.0",
76
78
  "commander": "^12.1.0",
@@ -1 +0,0 @@
1
- import{ag as o,ah as n}from"./mermaid.core-Biyo-tqA.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-TJ5JuEBT.js";import{_ as i}from"./mermaid.core-Biyo-tqA.js";import"./chunk-5VM5RSS4-JCNGkXYT.js";import"./chunk-XXDRQBXY-By9VQoi1.js";import"./chunk-KBJHAD2P-D60-Mny4.js";import"./chunk-2GRJ4B5K-wRO_iRNc.js";import"./index-CW88Fjbw.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-TJ5JuEBT.js";import{_ as i}from"./mermaid.core-Biyo-tqA.js";import"./chunk-5VM5RSS4-JCNGkXYT.js";import"./chunk-XXDRQBXY-By9VQoi1.js";import"./chunk-KBJHAD2P-D60-Mny4.js";import"./chunk-2GRJ4B5K-wRO_iRNc.js";import"./index-CW88Fjbw.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};