@tea-agent/loop-agent 0.44.0-next.3 → 0.44.0-next.5

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 (102) hide show
  1. package/CHANGELOG.md +8 -2
  2. package/dist/build-stamp.json +3 -3
  3. package/dist/executors/dag-pi-executor.js +2 -2
  4. package/dist/executors/shell-write-guard.js +26 -3
  5. package/dist/shared/file-identity.js +23 -0
  6. package/dist/shared/git-workspace-status.js +480 -0
  7. package/dist/shared/path-safety.js +2 -2
  8. package/dist/task/config-types.js +2 -1
  9. package/dist/task/contract/schema.js +1 -0
  10. package/dist/worker/console/chat/chat-event-store.js +32 -0
  11. package/dist/worker/console/chat/context-insights.js +723 -0
  12. package/dist/worker/console/chat/conversation-nodes.js +383 -0
  13. package/dist/worker/console/chat/pi-runtime.js +128 -12
  14. package/dist/worker/console/chat/provider-error.js +0 -12
  15. package/dist/worker/console/chat/repo-browser.js +3 -4
  16. package/dist/worker/console/chat/routes.js +209 -4
  17. package/dist/worker/console/chat/shortcuts.js +7 -0
  18. package/dist/worker/console/chat/turn-process.js +128 -7
  19. package/dist/worker/console/prd-intake-bridge.js +3 -0
  20. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-COQlLTI7.js → abnfDiagram-N423BO3Z-BHuhGM1e.js} +1 -1
  21. package/dist/worker/console/static/assets/{arc-zN3QkNaV.js → arc-CKh5E_sr.js} +1 -1
  22. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-Pyoyj5f2.js → architectureDiagram-T3A2C74G-DizhiBEv.js} +1 -1
  23. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-BNppA5WW.js → blockDiagram-VBNYF7ZC-3Neea-Z-.js} +1 -1
  24. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-lyxL8nTx.js → c4Diagram-5PPSVZJV-BCP_Qrgi.js} +1 -1
  25. package/dist/worker/console/static/assets/channel-DxgzA1GF.js +1 -0
  26. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-0hgjcdK4.js → chunk-2GRJ4B5K-C_wydftK.js} +1 -1
  27. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-D63N9d4i.js → chunk-2Q5K7J3B-jRPXZbzx.js} +1 -1
  28. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-CUw2AyB5.js → chunk-5RXB4S5H-BLQf2OYO.js} +1 -1
  29. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-Q_kwZT30.js → chunk-5VM5RSS4-0qRq64rI.js} +1 -1
  30. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-C7vMiKcw.js → chunk-6Q2QTUOP-ClMg8xmV.js} +1 -1
  31. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-T9GbV5Hz.js → chunk-GF5L2VYU-Coop2FlL.js} +1 -1
  32. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-D8nUSUJI.js → chunk-JWPE2WC7-CDdO-jPJ.js} +1 -1
  33. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BCH2ewdp.js → chunk-KBJHAD2P-D8Gkppjl.js} +1 -1
  34. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-BTdDuDBN.js → chunk-RYQCIY6F-DA9HIySf.js} +1 -1
  35. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-Cqm2RcKF.js → chunk-XXDRQBXY-DZNDRX1k.js} +1 -1
  36. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BZcm7fs6.js +1 -0
  37. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BZcm7fs6.js +1 -0
  38. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-pjwfpVu4.js → cose-bilkent-JH36ORCC-CZ1zGyjq.js} +1 -1
  39. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BvalptKA.js → cynefin-VYW2F7L2-B8u1_FtM.js} +1 -1
  40. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-BU4qJ6d7.js → cynefinDiagram-MW4NZA55-CPBB6lfo.js} +1 -1
  41. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-DVTpq8J9.js → dagre-VZM6K2ZE-CG3Eov3E.js} +1 -1
  42. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-B8s1W6Fc.js → diagram-7IWD3JNH-ycI-dOjh.js} +1 -1
  43. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-DPrFk9yH.js → diagram-B4RE2ZJO-Bx_GyQ7Y.js} +1 -1
  44. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-CnQIQsHC.js → diagram-LBJQPF4R-m0G6mP4d.js} +1 -1
  45. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-op0DEpCv.js → diagram-Q27KOJAE-DTDJkqcJ.js} +1 -1
  46. package/dist/worker/console/static/assets/{diagram-UB23O5K3-DXQamm4T.js → diagram-UB23O5K3-BCfFrG-p.js} +1 -1
  47. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-b1ad2C0r.js → ebnfDiagram-BXEA7PRR-BIkTNPpp.js} +1 -1
  48. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-B4cD-ZFJ.js → erDiagram-JOGREHBK-DTcMWrd2.js} +1 -1
  49. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CrgGjlQ1.js → flowDiagram-UKHOOZJN-BqzDaNQ7.js} +1 -1
  50. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DovmXQNV.js → ganttDiagram-PKOTCBZU-BSl_vGFe.js} +1 -1
  51. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-DpFyu2Jn.js → gitGraphDiagram-DS77QQ5N-DCA5HXM6.js} +1 -1
  52. package/dist/worker/console/static/assets/index-BAEDjTbD.css +1 -0
  53. package/dist/worker/console/static/assets/index-wKEJUaP5.js +482 -0
  54. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-D3MoQZIl.js → infoDiagram-6WML65LV-DvqT18ge.js} +1 -1
  55. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-Ci6C1yjS.js → ishikawaDiagram-WSZJBQD7-B6zGKrQ3.js} +1 -1
  56. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-BWMo2lIP.js → journeyDiagram-NVQOT4AX-BpLQPI9C.js} +1 -1
  57. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BdthIAg3.js → kanban-definition-27J2QSJJ-CzIz_-Lt.js} +1 -1
  58. package/dist/worker/console/static/assets/{linear-DuFAlSOj.js → linear-CMQ8Jpp-.js} +1 -1
  59. package/dist/worker/console/static/assets/{mermaid.core-Dqz3Slj9.js → mermaid.core-BdAMrTf7.js} +5 -5
  60. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-DNVTrD09.js → mindmap-definition-FAOFIHXS-hSwF6sOq.js} +1 -1
  61. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-CgfZPfBh.js → pegDiagram-VL7TDLO6-DZdv509B.js} +1 -1
  62. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-ClM9P7yo.js → pieDiagram-7S7Q4E2Y-CmD4-b0K.js} +1 -1
  63. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-DwnEak2J.js → quadrantDiagram-CIZ2JOQS-DtKxNxlS.js} +1 -1
  64. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-rK4hxt9P.js → railroadDiagram-AXF67PYL-D48iIoiS.js} +1 -1
  65. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-Cjqa6vo3.js → requirementDiagram-LRYGKXZP-C3N0K-2p.js} +1 -1
  66. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-D3Fa250Z.js → sankeyDiagram-W5VNT64P-CACWR-Xs.js} +1 -1
  67. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-2PdrNajj.js → sequenceDiagram-SI44F4Z6-g_QgugvZ.js} +1 -1
  68. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-BBcuGeZn.js → sizeCapture-X5ZJPWSS-DqLoRPGK.js} +1 -1
  69. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-CSJX9X6s.js → stateDiagram-OKZ733FA-ES59VgMG.js} +1 -1
  70. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DyCIq6jx.js +1 -0
  71. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-pOUU1bic.js → swimlanes-SLNWSIFB-fjyLVNWo.js} +2 -2
  72. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-CsKtO34q.js +8 -0
  73. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-CAeqfQn0.js → timeline-definition-Z64GVDOM-Cd5-biKv.js} +1 -1
  74. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-DYPLOMVO.js → vennDiagram-T6HMQDX7-CZTu6mPf.js} +1 -1
  75. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-Dy2V0Cha.js → wardleyDiagram-T6FBY63Y-DR01jjbe.js} +1 -1
  76. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-Dj9o7jrn.js → xychartDiagram-ELKLHX3M-iZcuGVGa.js} +1 -1
  77. package/dist/worker/console/static/index.html +2 -2
  78. package/dist/worker/console/static-src/operator-chat/animation-frame-batcher.js +38 -0
  79. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +97 -3
  80. package/dist/worker/console/static-src/operator-chat/context-insights-store.js +64 -0
  81. package/dist/worker/console/static-src/operator-chat/process-label.js +11 -2
  82. package/dist/worker/console/static-src/operator-chat/turn-group-equality.js +2 -1
  83. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +2 -0
  84. package/dist/worker/console/static-src/operator-chat/useChatThread.js +9 -0
  85. package/dist/worker/observe/node-context-insights.js +479 -0
  86. package/dist/workflows/dag/frontend-implementation-contract.js +3 -1
  87. package/dist/workflows/dag/frontend-plan-completeness.js +13 -3
  88. package/dist/workflows/dag/frontend-recovery-plan.js +10 -6
  89. package/dist/workflows/dag/frontend-typed-event-store.js +5 -0
  90. package/dist/workflows/dag/frontend-writer-admission.js +1 -0
  91. package/dist/workflows/dag/output-protocol.js +1 -0
  92. package/dist/workflows/dag/rerun-task.js +1 -0
  93. package/docs/README.md +1 -1
  94. package/docs/governance/harness-methodology-verification.md +11 -0
  95. package/package.json +1 -1
  96. package/dist/worker/console/static/assets/channel-CgLPkTw2.js +0 -1
  97. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-CuSD1Mhb.js +0 -1
  98. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-CuSD1Mhb.js +0 -1
  99. package/dist/worker/console/static/assets/index-DHBWEwz_.css +0 -1
  100. package/dist/worker/console/static/assets/index-JRfTUgP7.js +0 -478
  101. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Cqskj0zt.js +0 -1
  102. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-CM0ZIhNP.js +0 -8
@@ -19,7 +19,7 @@ import { OPERATOR_CHAT_ALLOWED_TOOLS, OPERATOR_CHAT_DENIED_TOOLS, OPERATOR_CHAT_
19
19
  import { InvalidChatSessionModeError, SESSION_MODE_ACTION_DENIED_CODE, SESSION_MODE_ACTION_DENIED_MESSAGE, SESSION_MODE_IMMUTABLE_CODE, UnknownChatSessionModeError, isWorkflowSessionMode, parseCreateSessionMode, readStoredSessionMode, shouldAcceptOperatorSnapshot, } from "./session-mode.js";
20
20
  import { buildModelCallableToolSchemas } from "./tool-adapter.js";
21
21
  import { cleanChatTitle, acceptedOperationIdFromResult, isBlankChatSession } from "./session-store.js";
22
- import { hashChatTurnPayload, projectChatToolEventPayload, projectCompactSnapshot, } from "./chat-event-store.js";
22
+ import { hashChatTurnPayload, projectChatToolEventPayload, projectUnknownChatEventPayload, projectCompactSnapshot, } from "./chat-event-store.js";
23
23
  import { projectDeferredTurnSummary, projectDeferredTurnSummaries, } from "./deferred-turn.js";
24
24
  import { THINKING_LEVELS, RuntimeSnapshotUnavailableError, } from "./pi-runtime.js";
25
25
  import { ResourcePreferencesError, setSkillAutoInvocationPreference, } from "./resource-preferences-store.js";
@@ -36,6 +36,7 @@ import { dispatchOperatorAction } from "../operator-actions.js";
36
36
  import { makeHumanGateCard, } from "./human-gate-card.js";
37
37
  import { ContractApplyReceiptStore } from "./contract-apply-receipt-store.js";
38
38
  import { projectTaskContext } from "./context-panel.js";
39
+ import { deriveContextInsights, estimateTokensFromText, } from "./context-insights.js";
39
40
  import { deriveChatSessionTelemetry, deriveChatTurnTelemetry } from "./session-stats.js";
40
41
  import { contractApplyPayloadHash, issueHumanGateToken, verifyHumanGateToken, } from "../human-gate-token.js";
41
42
  import { sendJson } from "../routes.js";
@@ -197,6 +198,16 @@ export function projectStoredMessagesWithEventOrder(messages, events) {
197
198
  ...(finish
198
199
  ? { finishedSeq: finish.seq, finishedAt: finish.at }
199
200
  : {}),
201
+ ...(start && typeof start.data.step === "number"
202
+ ? { step: start.data.step }
203
+ : {}),
204
+ ...(start &&
205
+ typeof start.data.parentToolCallId ===
206
+ "string"
207
+ ? {
208
+ parentToolCallId: start.data.parentToolCallId,
209
+ }
210
+ : {}),
200
211
  };
201
212
  });
202
213
  }
@@ -243,10 +254,99 @@ function writeChatSse(res, event) {
243
254
  /** Map a runtime ChatTurnEvent to the persisted event-store partial.
244
255
  *
245
256
  * Returns undefined for heartbeat (not persisted — keep-alive only). */
246
- function turnEventToStorePartial(event) {
257
+ export function turnEventToStorePartial(event) {
247
258
  switch (event.type) {
248
259
  case "agent_start":
249
260
  return { kind: "agent_start", data: {} };
261
+ case "step_start":
262
+ case "step_end":
263
+ return {
264
+ kind: event.type,
265
+ data: {
266
+ step: Number(event.step ?? 1),
267
+ ...(event.type === "step_end"
268
+ ? { outcome: String(event.outcome ?? "completed") }
269
+ : {}),
270
+ },
271
+ };
272
+ case "model_retry":
273
+ {
274
+ const retryState = event.state === "completed" || event.state === "failed"
275
+ ? event.state
276
+ : "scheduled";
277
+ return {
278
+ kind: "model_retry",
279
+ data: {
280
+ step: Number(event.step ?? 1),
281
+ attempt: Number(event.attempt ?? 1),
282
+ ...(typeof event.maxAttempts === "number"
283
+ ? { maxAttempts: event.maxAttempts }
284
+ : {}),
285
+ ...(typeof event.delayMs === "number" ? { delayMs: event.delayMs } : {}),
286
+ ...(typeof event.errorMessage === "string"
287
+ ? { errorMessage: event.errorMessage }
288
+ : {}),
289
+ state: retryState,
290
+ ...(typeof event.success === "boolean" ? { success: event.success } : {}),
291
+ },
292
+ };
293
+ }
294
+ case "turn_max_tokens":
295
+ return {
296
+ kind: "turn_max_tokens",
297
+ data: { step: Number(event.step ?? 1) },
298
+ };
299
+ case "turn_error":
300
+ return {
301
+ kind: "turn_error",
302
+ data: {
303
+ ...(typeof event.step === "number" ? { step: event.step } : {}),
304
+ ...(typeof event.code === "string" ? { code: event.code } : {}),
305
+ message: String(event.message ?? "模型请求失败"),
306
+ },
307
+ };
308
+ case "request_context":
309
+ return {
310
+ kind: "request_context",
311
+ data: {
312
+ requestId: String(event.requestId ?? ""),
313
+ step: Number(event.step ?? 1),
314
+ ...(event.model && typeof event.model === "object"
315
+ ? { model: event.model }
316
+ : {}),
317
+ ...(typeof event.thinkingLevel === "string"
318
+ ? { thinkingLevel: event.thinkingLevel }
319
+ : {}),
320
+ systemPromptHash: String(event.systemPromptHash ?? ""),
321
+ systemPromptChars: Number(event.systemPromptChars ?? 0),
322
+ activeTools: Array.isArray(event.activeTools) ? event.activeTools : [],
323
+ inputChars: Number(event.inputChars ?? 0),
324
+ imageCount: Number(event.imageCount ?? 0),
325
+ sources: Array.isArray(event.sources) ? event.sources : [],
326
+ },
327
+ };
328
+ case "command":
329
+ return {
330
+ kind: "command",
331
+ data: {
332
+ commandId: String(event.commandId ?? ""),
333
+ name: String(event.name ?? "unknown"),
334
+ ...(typeof event.argsPreview === "string"
335
+ ? { argsPreview: event.argsPreview }
336
+ : {}),
337
+ ...(typeof event.action === "string" ? { action: event.action } : {}),
338
+ outcome: event.outcome === "failed" ? "failed" : "completed",
339
+ ...(typeof event.message === "string" ? { message: event.message } : {}),
340
+ },
341
+ };
342
+ case "unknown":
343
+ return {
344
+ kind: "unknown",
345
+ data: projectUnknownChatEventPayload({
346
+ eventType: String(event.eventType ?? "unknown"),
347
+ value: event.value,
348
+ }),
349
+ };
250
350
  case "message_update":
251
351
  case "message_end": {
252
352
  const content = parseAssistantContent(event.content);
@@ -291,6 +391,10 @@ function turnEventToStorePartial(event) {
291
391
  event.messageId
292
392
  ? { messageId: event.messageId }
293
393
  : {}),
394
+ ...(typeof event.step === "number" ? { step: event.step } : {}),
395
+ ...(typeof event.stopReason === "string"
396
+ ? { stopReason: event.stopReason }
397
+ : {}),
294
398
  },
295
399
  };
296
400
  }
@@ -304,6 +408,10 @@ function turnEventToStorePartial(event) {
304
408
  toolCallId: String(event.toolCallId ?? ""),
305
409
  toolName: String(event.toolName ?? ""),
306
410
  value: event.args,
411
+ ...(typeof event.step === "number" ? { step: event.step } : {}),
412
+ ...(typeof event.parentToolCallId === "string"
413
+ ? { parentToolCallId: event.parentToolCallId }
414
+ : {}),
307
415
  }),
308
416
  };
309
417
  case "tool_result": {
@@ -318,6 +426,10 @@ function turnEventToStorePartial(event) {
318
426
  toolName: String(event.toolName ?? ""),
319
427
  value: event.result,
320
428
  isError: Boolean(event.isError),
429
+ ...(typeof event.step === "number" ? { step: event.step } : {}),
430
+ ...(typeof event.parentToolCallId === "string"
431
+ ? { parentToolCallId: event.parentToolCallId }
432
+ : {}),
321
433
  ...(resultOperationId ? { operationId: resultOperationId } : {}),
322
434
  }),
323
435
  };
@@ -1029,6 +1141,16 @@ export async function handleGetChatSession(_req, res, deps, sessionId) {
1029
1141
  turnId: event.turnId,
1030
1142
  data: event.data,
1031
1143
  })),
1144
+ conversationEvents: snapshot.filter((event) => [
1145
+ "step_start",
1146
+ "step_end",
1147
+ "model_retry",
1148
+ "turn_error",
1149
+ "turn_max_tokens",
1150
+ "request_context",
1151
+ "command",
1152
+ "unknown",
1153
+ ].includes(event.kind)),
1032
1154
  lastEventId: lastEvent?.eventId ?? null,
1033
1155
  lastEventSeq: lastEvent?.seq ?? 0,
1034
1156
  });
@@ -2982,7 +3104,8 @@ async function handleSddBingo(req, res, deps, sessionId) {
2982
3104
  throw new SddDataAlignmentError("SDD_INVALID_SKILL_NAME", "请求体只允许 skillName 字段", 400);
2983
3105
  }
2984
3106
  const result = await deps.sddDataAlignment.report(sessionId, body.skillName);
2985
- deps.events.append(sessionId, deps.events.latestTurnId(sessionId) ?? `${sessionId}:operator-action`, {
3107
+ const turnId = deps.events.latestTurnId(sessionId) ?? `${sessionId}:operator-action`;
3108
+ deps.events.append(sessionId, turnId, {
2986
3109
  kind: "operator-action",
2987
3110
  data: {
2988
3111
  schemaVersion: 1,
@@ -2991,6 +3114,17 @@ async function handleSddBingo(req, res, deps, sessionId) {
2991
3114
  telemetrySessionId: result.telemetrySessionId,
2992
3115
  },
2993
3116
  });
3117
+ deps.events.append(sessionId, `${sessionId}:command:${result.telemetrySessionId}`, {
3118
+ kind: "command",
3119
+ data: {
3120
+ commandId: `sdd-bingo:${result.telemetrySessionId}`,
3121
+ name: "sdd-bingo",
3122
+ ...(result.skillName ? { argsPreview: result.skillName } : {}),
3123
+ action: "sdd-bingo",
3124
+ outcome: "completed",
3125
+ message: `Session: ${result.telemetrySessionId}`,
3126
+ },
3127
+ });
2994
3128
  sendJson(res, 200, {
2995
3129
  ok: true,
2996
3130
  skillName: result.skillName,
@@ -3075,6 +3209,73 @@ export async function handleRuntimeContext(res, deps, sessionId) {
3075
3209
  }),
3076
3210
  });
3077
3211
  }
3212
+ /**
3213
+ * GET /sessions/:id/context-insights: dsh-context parity dashboard projection.
3214
+ * Folds the persisted event ring (works for idle/restored sessions) and, when
3215
+ * the Pi session is live, anchors the estimate with the runtime snapshot's
3216
+ * system-prompt size + active tool count. Read-only; never fabricates payload
3217
+ * text beyond the bounded previews already stored on the ring.
3218
+ */
3219
+ export async function handleContextInsights(res, deps, sessionId) {
3220
+ const record = await deps.store.get(sessionId);
3221
+ if (!record) {
3222
+ sendJson(res, 404, {
3223
+ ok: false,
3224
+ error: { code: "NOT_FOUND", message: `chat session not found: ${sessionId}` },
3225
+ });
3226
+ return;
3227
+ }
3228
+ await deps.operationLinker.recoverSession(sessionId);
3229
+ const snapshot = deps.events.snapshot(sessionId);
3230
+ let systemPromptChars;
3231
+ let systemPromptPreview;
3232
+ let activeTools;
3233
+ let skillInjections;
3234
+ try {
3235
+ const runtimeSnapshot = await deps.runtime.getRuntimeSnapshot(sessionId, {
3236
+ includeRaw: true,
3237
+ });
3238
+ if (runtimeSnapshot) {
3239
+ systemPromptChars = runtimeSnapshot.systemPrompt.characters;
3240
+ const raw = runtimeSnapshot.systemPrompt.raw ??
3241
+ runtimeSnapshot.systemPrompt.text;
3242
+ if (typeof raw === "string" && raw) {
3243
+ systemPromptPreview = raw.slice(0, 120_000);
3244
+ }
3245
+ activeTools = runtimeSnapshot.activeTools;
3246
+ skillInjections = runtimeSnapshot.skills
3247
+ .slice(0, 50)
3248
+ .map((skill) => ({
3249
+ name: skill.name,
3250
+ tokens: estimateTokensFromText(skill.description ?? skill.name),
3251
+ }));
3252
+ }
3253
+ }
3254
+ catch {
3255
+ // Insights are derived from the durable ring; a live-snapshot miss only
3256
+ // drops the anchor figures / browser static categories, never the dashboard.
3257
+ }
3258
+ // Tool schemas: capabilities registry projection for whitelisted operator
3259
+ // actions, plus Pi builtins active on this session.
3260
+ const schemaTools = buildModelCallableToolSchemas().map((tool) => ({
3261
+ id: tool.toolId,
3262
+ description: tool.description,
3263
+ }));
3264
+ const activeSet = new Set((activeTools ?? []).map((t) => t.toLowerCase()));
3265
+ const builtinTools = (activeTools ?? [])
3266
+ .filter((name) => !schemaTools.some((t) => t.id === name))
3267
+ .map((name) => ({ id: name, description: "" }));
3268
+ const insights = deriveContextInsights(snapshot, {
3269
+ sessionId,
3270
+ ...(systemPromptChars !== undefined ? { systemPromptChars } : {}),
3271
+ ...(systemPromptPreview !== undefined
3272
+ ? { systemPromptPreview }
3273
+ : {}),
3274
+ tools: [...schemaTools, ...builtinTools],
3275
+ ...(skillInjections ? { skillInjections } : {}),
3276
+ });
3277
+ sendJson(res, 200, { ok: true, insights });
3278
+ }
3078
3279
  // Exported for the direct handler-boundary tests (trace binding for
3079
3280
  // vt-route-model-errors); router dispatch behavior is unchanged.
3080
3281
  export async function handleModels(req, res, deps, sessionId) {
@@ -4594,7 +4795,7 @@ async function dispatchChatRequest(req, res, deps, pathname, workspaceScope) {
4594
4795
  await handleSddBingo(req, res, deps, decodeURIComponent(sddBingo[1]));
4595
4796
  return true;
4596
4797
  }
4597
- const m4Route = pathname.match(/^\/api\/operator\/v1\/chat\/sessions\/([^/]+)\/(draft|files|runtime-context|runtime-snapshot|models|model|reload|commands)$/);
4798
+ const m4Route = pathname.match(/^\/api\/operator\/v1\/chat\/sessions\/([^/]+)\/(draft|files|runtime-context|runtime-snapshot|context-insights|models|model|reload|commands)$/);
4598
4799
  if (m4Route) {
4599
4800
  const id = decodeURIComponent(m4Route[1]);
4600
4801
  const route = m4Route[2];
@@ -4614,6 +4815,10 @@ async function dispatchChatRequest(req, res, deps, pathname, workspaceScope) {
4614
4815
  await handleRuntimeSnapshot(req, res, deps, id);
4615
4816
  return true;
4616
4817
  }
4818
+ if (route === "context-insights" && method === "GET") {
4819
+ await handleContextInsights(res, deps, id);
4820
+ return true;
4821
+ }
4617
4822
  if (route === "models" && method === "GET") {
4618
4823
  await handleModels(req, res, deps, id);
4619
4824
  return true;
@@ -42,6 +42,13 @@ export const SHORTCUTS = [
42
42
  action: "reload",
43
43
  source: "operator",
44
44
  },
45
+ {
46
+ command: "/context",
47
+ label: "Context insights",
48
+ description: "打开上下文洞察仪表盘:构成、趋势、事件与文件活动",
49
+ action: "focus:context-insights",
50
+ source: "operator",
51
+ },
45
52
  ];
46
53
  export const SDD_BINGO_SHORTCUT = {
47
54
  command: "/sdd-bingo",
@@ -3,7 +3,89 @@
3
3
  */
4
4
  import { getDisplayableAssistantBlocks, joinAssistantText, parseAssistantContent, splitFinalAssistantBlocks, } from "./assistant-content.js";
5
5
  import { dagProgressActivityForTool, semanticActivityForTool, } from "./semantic-activity.js";
6
+ import { compareChatOrder } from "./turn-order.js";
6
7
  import { ensureLinkedSubmissionOrder } from "./timeline-message-order.js";
8
+ function conversationNodeOrder(node) {
9
+ return { eventSeq: node.anchorSeq, createdAt: node.at };
10
+ }
11
+ function processItemOrder(item, group) {
12
+ const createdAt = item.createdAt ??
13
+ (item.kind === "tool" ? item.tool.createdAt : undefined) ??
14
+ group.assistants[0]?.createdAt ??
15
+ 0;
16
+ const eventSeq = item.eventSeq ?? (item.kind === "tool" ? item.tool.eventSeq : undefined);
17
+ return eventSeq === undefined ? { createdAt } : { eventSeq, createdAt };
18
+ }
19
+ function compareFlowEntries(a, b) {
20
+ return compareChatOrder(a.order, b.order);
21
+ }
22
+ /** Base identity for a rendered process row. Content is deliberately excluded
23
+ * so streaming text updates keep the same React instance. */
24
+ function processItemKey(item, order) {
25
+ if (item.kind === "tool")
26
+ return `tool:${item.tool.id}`;
27
+ if (item.kind === "activity")
28
+ return `activity:${item.activity.id}`;
29
+ if (item.kind === "dag-progress")
30
+ return `dag-progress:${item.progress.id}`;
31
+ const anchor = order.eventSeq ?? order.createdAt;
32
+ return `${item.kind}:${anchor}`;
33
+ }
34
+ export function turnProcessItemKey(item, occurrence = 0) {
35
+ const order = {
36
+ ...(item.eventSeq === undefined ? {} : { eventSeq: item.eventSeq }),
37
+ createdAt: item.createdAt ?? (item.kind === "tool" ? item.tool.createdAt : 0),
38
+ };
39
+ const base = processItemKey(item, order);
40
+ return occurrence === 0 ? base : `${base}:${occurrence}`;
41
+ }
42
+ /**
43
+ * Project one turn into the same ordered buckets used by the main timeline and
44
+ * the trajectory view. Only existing request/running-step nodes are prelude;
45
+ * retry and other lifecycle nodes stay in the collapsible process window.
46
+ */
47
+ export function projectTurnFlow(group) {
48
+ const conversationItems = group.conversationItems ?? [];
49
+ const prelude = conversationItems
50
+ .filter((item) => item.kind === "request" ||
51
+ (item.kind === "step" && item.node.status === "running"))
52
+ .sort((a, b) => compareChatOrder(conversationNodeOrder(a.node), conversationNodeOrder(b.node)));
53
+ const postAnswer = conversationItems
54
+ .filter((item) => item.kind === "max-tokens")
55
+ .sort((a, b) => compareChatOrder(conversationNodeOrder(a.node), conversationNodeOrder(b.node)));
56
+ const preludeKeys = new Set(prelude.map((item) => item.node.key));
57
+ const postAnswerKeys = new Set(postAnswer.map((item) => item.node.key));
58
+ const process = [];
59
+ for (const item of group.processItems) {
60
+ process.push({
61
+ source: "process",
62
+ key: "",
63
+ item,
64
+ order: processItemOrder(item, group),
65
+ });
66
+ }
67
+ for (const item of conversationItems) {
68
+ if (preludeKeys.has(item.node.key) || postAnswerKeys.has(item.node.key))
69
+ continue;
70
+ process.push({
71
+ source: "conversation",
72
+ key: `conversation:${item.node.key}`,
73
+ item,
74
+ order: conversationNodeOrder(item.node),
75
+ });
76
+ }
77
+ process.sort(compareFlowEntries);
78
+ const occurrences = new Map();
79
+ for (const entry of process) {
80
+ const base = entry.source === "conversation"
81
+ ? entry.key
82
+ : processItemKey(entry.item, entry.order);
83
+ const occurrence = occurrences.get(base) ?? 0;
84
+ occurrences.set(base, occurrence + 1);
85
+ entry.key = occurrence === 0 ? base : `${base}:${occurrence}`;
86
+ }
87
+ return { prelude, process, postAnswer };
88
+ }
7
89
  function emptyGroup(key, turnId) {
8
90
  return {
9
91
  key,
@@ -11,6 +93,7 @@ function emptyGroup(key, turnId) {
11
93
  assistants: [],
12
94
  tools: [],
13
95
  processItems: [],
96
+ conversationItems: [],
14
97
  live: false,
15
98
  };
16
99
  }
@@ -92,6 +175,10 @@ export function hydrateSessionThread(raw) {
92
175
  ? finishedAtMs
93
176
  : createdAt,
94
177
  turnId: item.turnId ?? turnId,
178
+ ...(item.step === undefined ? {} : { step: item.step }),
179
+ ...(item.parentToolCallId
180
+ ? { parentToolCallId: item.parentToolCallId }
181
+ : {}),
95
182
  ...(item.eventSeq === undefined ? {} : { eventSeq: item.eventSeq }),
96
183
  ...(item.finishedSeq === undefined
97
184
  ? {}
@@ -132,17 +219,21 @@ function flushToolBuffer(processItems, buffer) {
132
219
  return;
133
220
  const sorted = sortToolsStable(buffer);
134
221
  for (const tool of sorted) {
222
+ const order = {
223
+ ...(tool.eventSeq === undefined ? {} : { eventSeq: tool.eventSeq }),
224
+ createdAt: tool.createdAt,
225
+ };
135
226
  const dagProgress = dagProgressActivityForTool(tool);
136
227
  if (dagProgress) {
137
- processItems.push({ kind: "dag-progress", progress: dagProgress });
228
+ processItems.push({ kind: "dag-progress", progress: dagProgress, ...order });
138
229
  continue;
139
230
  }
140
231
  const activity = semanticActivityForTool(tool);
141
232
  if (activity) {
142
- processItems.push({ kind: "activity", activity });
233
+ processItems.push({ kind: "activity", activity, ...order });
143
234
  }
144
235
  else {
145
- processItems.push({ kind: "tool", tool });
236
+ processItems.push({ kind: "tool", tool, ...order });
146
237
  }
147
238
  }
148
239
  }
@@ -185,12 +276,23 @@ function fillProcessDetails(group) {
185
276
  };
186
277
  for (const block of blocks) {
187
278
  if (block.type === "thinking") {
188
- items.push({ kind: "thinking", thinking: block.thinking });
279
+ items.push({
280
+ kind: "thinking",
281
+ thinking: block.thinking,
282
+ ...(anchorSeq === undefined ? {} : { eventSeq: anchorSeq }),
283
+ createdAt: anchorAt,
284
+ });
189
285
  continue;
190
286
  }
191
287
  if (block.type === "text") {
192
- if (block.text.trim())
193
- items.push({ kind: "text", text: block.text });
288
+ if (block.text.trim()) {
289
+ items.push({
290
+ kind: "text",
291
+ text: block.text,
292
+ ...(anchorSeq === undefined ? {} : { eventSeq: anchorSeq }),
293
+ createdAt: anchorAt,
294
+ });
295
+ }
194
296
  continue;
195
297
  }
196
298
  const tool = group.tools.find((entry) => entry.id === block.toolCallId);
@@ -213,7 +315,12 @@ function fillProcessDetails(group) {
213
315
  anchorAt = tool.createdAt;
214
316
  }
215
317
  if (includeProviderError && assistant.providerError) {
216
- items.push({ kind: "provider-error", error: assistant.providerError });
318
+ items.push({
319
+ kind: "provider-error",
320
+ error: assistant.providerError,
321
+ ...(anchorSeq === undefined ? {} : { eventSeq: anchorSeq }),
322
+ createdAt: anchorAt,
323
+ });
217
324
  }
218
325
  flushItems();
219
326
  // Preserve the old-data fallback after this stage. Sequenced unmatched
@@ -401,6 +508,14 @@ export function buildTurnProcessGroups(input) {
401
508
  assigned.add(tool.id);
402
509
  }
403
510
  }
511
+ for (const node of input.conversationNodes ?? []) {
512
+ if (node.location.kind === "session")
513
+ continue;
514
+ const turnId = node.location.turnId;
515
+ if (!groups.some((group) => group.turnId === turnId)) {
516
+ startGroup(`turn-${turnId}`, turnId);
517
+ }
518
+ }
404
519
  for (const group of groups) {
405
520
  group.tools.sort((a, b) => {
406
521
  if (a.eventSeq !== undefined && b.eventSeq !== undefined) {
@@ -413,6 +528,12 @@ export function buildTurnProcessGroups(input) {
413
528
  input.activeAssistantId !== null &&
414
529
  group.assistants.some((a) => a.id === input.activeAssistantId);
415
530
  fillProcessDetails(group);
531
+ group.conversationItems = (input.conversationNodes ?? [])
532
+ .filter((node) => node.location.kind !== "session" && node.location.turnId === group.turnId)
533
+ .map((node) => ({ kind: node.kind, node }));
534
+ if (group.conversationItems.some((item) => item.kind === "turn-error")) {
535
+ group.processItems = group.processItems.filter((item) => item.kind !== "provider-error");
536
+ }
416
537
  }
417
538
  return groups;
418
539
  }
@@ -128,6 +128,9 @@ export function parseEngineeringBoundaryFromParams(p) {
128
128
  forbidden: Array.isArray(capabilityBoundaryRaw.forbidden)
129
129
  ? capabilityBoundaryRaw.forbidden.filter((x) => typeof x === "string" && x.trim().length > 0)
130
130
  : undefined,
131
+ requiredClauses: Array.isArray(capabilityBoundaryRaw.requiredClauses)
132
+ ? capabilityBoundaryRaw.requiredClauses.filter((x) => typeof x === "string" && x.trim().length > 0)
133
+ : undefined,
131
134
  }
132
135
  : undefined;
133
136
  const interactionIds = asList(p.interactionIds ?? p.interactionId);
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-C7vMiKcw.js";import{p as f}from"./chunk-JWPE2WC7-D8nUSUJI.js";import{_ as n,l as o}from"./mermaid.core-Dqz3Slj9.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-BvalptKA.js";import"./index-JRfTUgP7.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
1
+ import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-ClMg8xmV.js";import{p as f}from"./chunk-JWPE2WC7-CDdO-jPJ.js";import{_ as n,l as o}from"./mermaid.core-BdAMrTf7.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-B8u1_FtM.js";import"./index-wKEJUaP5.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
@@ -1 +1 @@
1
- import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-Dqz3Slj9.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
1
+ import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-BdAMrTf7.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};