@tea-agent/loop-agent 0.42.0-next.3 → 0.42.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 (82) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/build-stamp.json +3 -3
  3. package/dist/executors/dag-pi-executor.js +6 -2
  4. package/dist/worker/console/chat/pi-runtime.js +26 -0
  5. package/dist/worker/console/chat/routes.js +60 -5
  6. package/dist/worker/console/chat/sdd-data-alignment.js +219 -0
  7. package/dist/worker/console/chat/session-catalog.js +2 -0
  8. package/dist/worker/console/chat/session-store.js +26 -0
  9. package/dist/worker/console/chat/shortcuts.js +18 -2
  10. package/dist/worker/console/server.js +1 -0
  11. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-CeznJ4Iw.js → abnfDiagram-N423BO3Z-BJpsGgAv.js} +1 -1
  12. package/dist/worker/console/static/assets/{arc-B4u9u7SX.js → arc-DjMFPsEd.js} +1 -1
  13. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-oghpT81p.js → architectureDiagram-T3A2C74G-DqdZlr1O.js} +1 -1
  14. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-BPJ5Kvcj.js → blockDiagram-VBNYF7ZC-BmZnfFEO.js} +1 -1
  15. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-CoIu69pd.js → c4Diagram-5PPSVZJV-3cKberpL.js} +1 -1
  16. package/dist/worker/console/static/assets/channel-DWYwciiv.js +1 -0
  17. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-DtgiAsSc.js → chunk-2GRJ4B5K-q-0yjQ1h.js} +1 -1
  18. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-YSu_EVSD.js → chunk-2Q5K7J3B-DnONBaDW.js} +1 -1
  19. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DaRO-NB6.js → chunk-5RXB4S5H-v3a6PCOS.js} +1 -1
  20. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-Dh0ZKiGA.js → chunk-5VM5RSS4-D1kLrlU_.js} +1 -1
  21. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DOrvbR-H.js → chunk-6Q2QTUOP-BPelzihi.js} +1 -1
  22. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-C3b22LN2.js → chunk-GF5L2VYU-DauNE69H.js} +1 -1
  23. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-CXlqO8l6.js → chunk-JWPE2WC7-RIg5_bFJ.js} +1 -1
  24. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BblTBrDu.js → chunk-KBJHAD2P-BuILuoxs.js} +1 -1
  25. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-DswqPALe.js → chunk-RYQCIY6F-VHORV5oW.js} +1 -1
  26. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CfTwVOlc.js → chunk-XXDRQBXY-BJYr4xHC.js} +1 -1
  27. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-D6jOf_l4.js +1 -0
  28. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-D6jOf_l4.js +1 -0
  29. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-bLD8jVFo.js → cose-bilkent-JH36ORCC-BS6nuqQn.js} +1 -1
  30. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BvoG1fh5.js → cynefin-VYW2F7L2-BBhF0NAT.js} +1 -1
  31. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-DEPAdJu3.js → cynefinDiagram-MW4NZA55-D1135Ifg.js} +1 -1
  32. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-DmrNvBLy.js → dagre-VZM6K2ZE-vAOYPUWJ.js} +1 -1
  33. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-CdwzIwvs.js → diagram-7IWD3JNH-DuaSPkfa.js} +1 -1
  34. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-CJ3hj-md.js → diagram-B4RE2ZJO-mMvXvGU6.js} +1 -1
  35. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-C6YJT2a4.js → diagram-LBJQPF4R-CDIEJtlL.js} +1 -1
  36. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-C_LPfjhX.js → diagram-Q27KOJAE-Bi_6JvCW.js} +1 -1
  37. package/dist/worker/console/static/assets/{diagram-UB23O5K3-xvsSb5Ie.js → diagram-UB23O5K3-DAqj57yN.js} +1 -1
  38. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-Rxp2tKcD.js → ebnfDiagram-BXEA7PRR-DfWaxNEo.js} +1 -1
  39. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DRyLYmZh.js → erDiagram-JOGREHBK-Bt7QqkNG.js} +1 -1
  40. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-TLSU_D2B.js → flowDiagram-UKHOOZJN-CRRhQwT2.js} +1 -1
  41. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DGqeTvHC.js → ganttDiagram-PKOTCBZU-DAV1O5B6.js} +1 -1
  42. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-BZxyH2wh.js → gitGraphDiagram-DS77QQ5N-0X2Qo4Lp.js} +1 -1
  43. package/dist/worker/console/static/assets/index-CVdddQsA.js +451 -0
  44. package/dist/worker/console/static/assets/index-DDQc5a50.css +1 -0
  45. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-BsYtzx01.js → infoDiagram-6WML65LV-C5W5eILC.js} +1 -1
  46. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-Qr-ezGv-.js → ishikawaDiagram-WSZJBQD7-5SfqU-Tb.js} +1 -1
  47. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DYbB3ibo.js → journeyDiagram-NVQOT4AX-CKDRcaKf.js} +1 -1
  48. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BHJHewZO.js → kanban-definition-27J2QSJJ-Cc7_TuSb.js} +1 -1
  49. package/dist/worker/console/static/assets/{linear-CmPIPmCG.js → linear-BcQYYmeT.js} +1 -1
  50. package/dist/worker/console/static/assets/{mermaid.core-F--C1uV0.js → mermaid.core-CwLZPtQo.js} +5 -5
  51. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-YTXfL1st.js → mindmap-definition-FAOFIHXS-D29M025z.js} +1 -1
  52. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-DdDMYXP9.js → pegDiagram-VL7TDLO6-CV-ZAWYe.js} +1 -1
  53. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-C3nH4KVd.js → pieDiagram-7S7Q4E2Y-C6iPS_o5.js} +1 -1
  54. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-kXyxjG7Y.js → quadrantDiagram-CIZ2JOQS-BFCD1sTg.js} +1 -1
  55. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-KNzbl-7w.js → railroadDiagram-AXF67PYL-CztNj4O9.js} +1 -1
  56. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-CSwI6dG0.js → requirementDiagram-LRYGKXZP-BWIELSNd.js} +1 -1
  57. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-Bl1AyuXy.js → sankeyDiagram-W5VNT64P-CPtxrjJQ.js} +1 -1
  58. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-2y4EmXQa.js → sequenceDiagram-SI44F4Z6-BEWVSFsu.js} +1 -1
  59. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-E8v8YrMg.js → sizeCapture-X5ZJPWSS-DyhzoX_J.js} +1 -1
  60. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-eGGlR856.js → stateDiagram-OKZ733FA-xLox0nu7.js} +1 -1
  61. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DS5ZRvJG.js +1 -0
  62. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-B7g7xc07.js → swimlanes-SLNWSIFB-CLC_ow9A.js} +2 -2
  63. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Dvpxn-bf.js +8 -0
  64. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-DR3VCHBG.js → timeline-definition-Z64GVDOM-DmJZ4uyY.js} +1 -1
  65. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-LUvapZIy.js → vennDiagram-T6HMQDX7-DD7GGi9Z.js} +1 -1
  66. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-C7GDcaXq.js → wardleyDiagram-T6FBY63Y-Bi8PQoGt.js} +1 -1
  67. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CbNAqoGK.js → xychartDiagram-ELKLHX3M-uKdAY8Dp.js} +1 -1
  68. package/dist/worker/console/static/index.html +2 -2
  69. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +225 -21
  70. package/dist/worker/console/static-src/operator-chat/useComposer.js +5 -1
  71. package/dist/worker/console/workspace-context.js +4 -0
  72. package/dist/workflows/dag/backend-test-writer-completeness.js +10 -0
  73. package/dist/workflows/dag/init-hybrid.js +22 -15
  74. package/docs/templates/backend-test-dag.json +8 -5
  75. package/package.json +1 -1
  76. package/dist/worker/console/static/assets/channel-DmIXqJ6B.js +0 -1
  77. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-MFV5Qxb5.js +0 -1
  78. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-MFV5Qxb5.js +0 -1
  79. package/dist/worker/console/static/assets/index-C8V8K9b4.js +0 -451
  80. package/dist/worker/console/static/assets/index-Cnf_KxTQ.css +0 -1
  81. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-B8e4J3at.js +0 -1
  82. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Do88I1Nb.js +0 -8
package/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ - 修复 backend-test Manifest 把模型生成的 Module Stem 展示单元格当成模块身份真源、导致 low-tier 输出(缺 `test_` 前缀或整段 Markdown 链接)在 N3 `module-markdown-path-mismatch` 反复失败的问题:N3 现在先解析唯一合法 Markdown Path 与 `<stem>.md` 相对链接作为 canonical 身份,再校验业务 ownership/split 与路径安全;Stem 单元格只作冗余展示并能确定性重写为 canonical 文件名 stem。strict `backendTest.moduleLayout` 改为先按唯一 required Markdown Path 定位模块,再恢复冻结 Markdown/Pytest path pair,避免错误 stem 提前丢弃整行,同时保留 Plan-only pytest path 修复。Markdown Path 缺失/多候选/越界或与 strict path pair 冲突、以及多行 canonicalize 后同 identity(`duplicate-canonical-module-stem`)继续 fail-closed,不再静默去重。同步加强 N2 prompt(Stem 单元格仅允许纯文件名 stem)。
6
+ - 修复 Next Release 的 io-heavy 测试并发不稳定:发布 workflow 将该池固定为单 worker,避免全部测试已通过后触发 Vitest `onTaskUpdate` RPC settlement timeout,并消除 controller identity/package fingerprint 测试之间的共享状态竞态;不跳过或删除任何测试。
7
+ - 修复 backend-test 唯一 pytest collection repair 已产生受控非空修改、却因模型遗漏 `IMPLEMENTATION_OUTCOME` 而阻断整条执行链的问题:仅 N11 exact repair writer 可把完全缺失的 outcome 确定性恢复为候选 changed,随后仍必须由 N12 重新通过 scenario、correspondence、payload、collection、fixture 和 readiness 门禁;unknown/conflicting/blocked、空 diff、越界写入及 provider/context failure 继续 fail-closed。
8
+ - 新建和删除对话现在会立即在侧栏中反馈:新建时先显示“正在创建”,删除时平滑淡出;网络失败会自动恢复原会话,不再需要等待整张会话列表刷新后才看到变化。
9
+ - 新建对话会优先复用当前工作区中真正的空白会话,避免重复创建;有历史消息、工具调用、待发送内容或正在运行的会话不会被复用。
10
+ - 会话列表刷新现在会复用未变化的行和列表引用,标题、运行状态或队列变化时只更新对应会话,侧栏切换和刷新更平滑。
11
+ - Operator Chat 新增仅对具备 Aimax 凭证的用户可见的 `/sdd-bingo` 数据对齐命令;`wizard-local` 模型请求会自动携带与上报一致的 OpenCode 风格会话身份、当前模型和最新 API key,请求头与资格文件变更均在下一次操作自动生效。
5
12
  - 修复前端任务产物派生续跑无法识别当前节点链的问题;从实现节点继续时,设计约束、写入准入、验证和收尾步骤会按现行流程安全重放。
6
13
  - 统一工作区、Todo 和其他滚动区域的滚动条样式,默认更轻巧,鼠标悬浮时也更容易辨认。
7
14
  - HTML 文件预览现在支持页面内的标签切换等交互;较大的自包含 HTML 可以在新窗口中直接完整加载,不再受源码摘要长度影响。
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "version": "0.42.0-next.3",
4
- "gitSha": "fe1e2b416961d2f3782e2a35056441ba584c9048",
5
- "builtAt": "2026-09-01T01:43:24.005Z"
3
+ "version": "0.42.0-next.5",
4
+ "gitSha": "260dc2585e355412fa689ac856badc73b2f609f9",
5
+ "builtAt": "2026-09-01T18:19:10.922Z"
6
6
  }
@@ -17,7 +17,7 @@ import { GitStatusUnavailableError, pathsChangedDuringRun, readGitStatusPorcelai
17
17
  import { captureWorkspaceWriteSnapshot, diffWorkspaceWriteSnapshots, } from "./workspace-write-snapshot.js";
18
18
  import { pathMatchesPattern } from "../shared/git-progress.js";
19
19
  import { isTargetTemplateTransientRetryNode, isWriterEmptyDiffRetryCandidate, isWriterTransportRetryCandidate, INCOMPLETE_WRITE_SET_RETRY_CATEGORY, WRITER_CLEAN_TIMEOUT_RETRY_CATEGORY, WRITER_EMPTY_DIFF_RETRY_CATEGORY, } from "../workflows/dag/retry-policy.js";
20
- import { assessBackendTestMdPlanCompleteness, assessBackendTestMdWriterCompleteness, assessBackendTestPytestPlanCompleteness, assessBackendTestPytestWriterCompleteness, assessBackendTestShardChildCompleteness, backendTestWriterProgressRoleForTask, classifyBackendTestWriterCompletenessFailure, isBackendTestCompletenessRetryCandidate, isBackendTestMdPlanTask, isBackendTestPytestPlanTask, isBackendTestShardChildTask, writeBackendTestWriterProgressArtifacts, } from "../workflows/dag/backend-test-writer-completeness.js";
20
+ import { assessBackendTestMdPlanCompleteness, assessBackendTestMdWriterCompleteness, assessBackendTestPytestPlanCompleteness, assessBackendTestPytestWriterCompleteness, assessBackendTestShardChildCompleteness, backendTestWriterProgressRoleForTask, classifyBackendTestWriterCompletenessFailure, isBackendTestCompletenessRetryCandidate, isBackendTestMdPlanTask, isBackendTestPytestCollectionRepairOutcomeRecoveryCandidate, isBackendTestPytestPlanTask, isBackendTestShardChildTask, writeBackendTestWriterProgressArtifacts, } from "../workflows/dag/backend-test-writer-completeness.js";
21
21
  import { resolveBackendTestLayout } from "../workflows/dag/backend-test-layout.js";
22
22
  import { frontendTestLayoutFromSpec } from "../workflows/dag/frontend-test-layout.js";
23
23
  import { redactSecrets, truncateUtf8Preview } from "../shared/preview.js";
@@ -40,6 +40,10 @@ export const WRITER_THINKING_EXHAUSTED_CATEGORY = "writer-thinking-exhausted";
40
40
  export const WRITER_BUDGET_EXHAUSTED_CATEGORY = "writer-budget-exhausted";
41
41
  /** Token ceiling for a single writer node before it is judged budget-exhausted. */
42
42
  export const WRITER_TOKEN_BUDGET = 2_000_000;
43
+ export function allowsMissingChangedWriterOutcomeRecovery(task) {
44
+ return (isBackendTestCompletenessRetryCandidate(task) ||
45
+ isBackendTestPytestCollectionRepairOutcomeRecoveryCandidate(task));
46
+ }
43
47
  function readWriterThinkingExhaustionEvidence(result) {
44
48
  const wider = result;
45
49
  return {
@@ -4456,7 +4460,7 @@ export async function executeDagPiNode(input, meta, piStepFn = executePiStep, wr
4456
4460
  else {
4457
4461
  const outcomeValidation = validateWriterImplementationOutcome(mapped.assistantText || mapped.stdout, changeManifestChangedFiles, {
4458
4462
  requireChangedFiles: input.task.writerOutcomePolicy.requireChangedFiles === true,
4459
- allowMissingChangedOutcomeWhenDiffPresent: isBackendTestCompletenessRetryCandidate(input.task),
4463
+ allowMissingChangedOutcomeWhenDiffPresent: allowsMissingChangedWriterOutcomeRecovery(input.task),
4460
4464
  });
4461
4465
  if (!outcomeValidation.ok) {
4462
4466
  writerOutcomeViolation = outcomeValidation.reason;
@@ -43,6 +43,7 @@ import { filterActiveInterviewTools } from "../interview/tools.js";
43
43
  import { RUNTIME_CONTEXT_TEXT_MAX, redactRuntimeText, } from "./runtime-context.js";
44
44
  import { buildTodoContinuationContext, } from "./todos.js";
45
45
  import { buildGoalContinuationContext, } from "./goals.js";
46
+ import { injectWizardLocalHeaders, } from "./sdd-data-alignment.js";
46
47
  /**
47
48
  * Base system prompt fragment every General Operator Chat session receives.
48
49
  *
@@ -298,6 +299,24 @@ export function createGoalCompactionContextExtension(options) {
298
299
  },
299
300
  };
300
301
  }
302
+ export function createWizardLocalHeadersExtension(options) {
303
+ return {
304
+ name: "operator-chat-wizard-local-headers",
305
+ hidden: true,
306
+ factory: (api) => {
307
+ api.on("before_provider_headers", async (rawEvent, context) => {
308
+ if (!context || !rawEvent.headers || typeof rawEvent.headers !== "object")
309
+ return;
310
+ await injectWizardLocalHeaders({
311
+ headers: rawEvent.headers,
312
+ context,
313
+ sessionId: options.sessionId,
314
+ service: options.service,
315
+ });
316
+ });
317
+ },
318
+ };
319
+ }
301
320
  /**
302
321
  * Build Pi custom ToolDefinition objects for every whitelisted operator action.
303
322
  * Each tool's execute() routes into the operator action dispatcher (Gate 3).
@@ -1061,10 +1080,17 @@ export class ConsolePiRuntime {
1061
1080
  registry: this.options.goalRegistry,
1062
1081
  })
1063
1082
  : undefined;
1083
+ const wizardLocalHeadersExtension = sessionId && this.options.sddDataAlignment
1084
+ ? createWizardLocalHeadersExtension({
1085
+ sessionId,
1086
+ service: this.options.sddDataAlignment,
1087
+ })
1088
+ : undefined;
1064
1089
  const extraFactories = [
1065
1090
  todoContextExtension,
1066
1091
  goalContextExtension,
1067
1092
  pressureExtension,
1093
+ wizardLocalHeadersExtension,
1068
1094
  ].filter((item) => Boolean(item));
1069
1095
  return {
1070
1096
  ...base,
@@ -16,7 +16,7 @@ import { randomUUID } from "node:crypto";
16
16
  import { parseAssistantContent } from "./assistant-content.js";
17
17
  import { OPERATOR_CHAT_ALLOWED_TOOLS, OPERATOR_CHAT_DENIED_TOOLS, OPERATOR_CHAT_DENIED_OPERATOR_ACTIONS, } from "./tools.js";
18
18
  import { buildModelCallableToolSchemas } from "./tool-adapter.js";
19
- import { cleanChatTitle, acceptedOperationIdFromResult } from "./session-store.js";
19
+ import { cleanChatTitle, acceptedOperationIdFromResult, isBlankChatSession } from "./session-store.js";
20
20
  import { hashChatTurnPayload, projectChatToolEventPayload, projectCompactSnapshot, } from "./chat-event-store.js";
21
21
  import { projectDeferredTurnSummary, projectDeferredTurnSummaries, } from "./deferred-turn.js";
22
22
  import { THINKING_LEVELS, RuntimeSnapshotUnavailableError, } from "./pi-runtime.js";
@@ -42,6 +42,12 @@ import { buildTodoCompactionInstructions, projectCurrentTodos } from "./todos.js
42
42
  import { buildGoalCompactionInstructions, buildGoalContinuationContext, } from "./goals.js";
43
43
  import { classifyGoalRoundAdmission, } from "./goal-round-driver.js";
44
44
  import { isTerminalOperationState } from "../../../infrastructure/console/operation-store.js";
45
+ import { SddDataAlignmentError, } from "./sdd-data-alignment.js";
46
+ function projectBrowserChatSession(record) {
47
+ const { telemetrySessionId, ...projected } = record;
48
+ void telemetrySessionId;
49
+ return projected;
50
+ }
45
51
  /**
46
52
  * Reattach the durable event-ring order to session-store rows. The session
47
53
  * store remains the content authority; the ring only supplies chronology.
@@ -616,7 +622,7 @@ workspaceId) {
616
622
  sessionId: handle.sessionId,
617
623
  sessionFile: handle.sessionFile,
618
624
  model: handle.model,
619
- session,
625
+ session: { ...session, isBlank: isBlankChatSession(session) },
620
626
  activeTools: handle.activeTools,
621
627
  hasBash: true,
622
628
  ...(handle.initializing ? { initializing: true } : {}),
@@ -820,7 +826,7 @@ export async function handleGetChatSession(_req, res, deps, sessionId) {
820
826
  ok: true,
821
827
  eventEpoch: deps.events.epoch(sessionId),
822
828
  session: {
823
- ...record,
829
+ ...projectBrowserChatSession(record),
824
830
  messages: projectStoredMessagesWithEventOrder(record.messages, snapshot),
825
831
  composerDraft,
826
832
  activeTurnId: activeTurn?.turnId,
@@ -1406,6 +1412,7 @@ export async function listChatSessionSummaries(deps, ownerWorkspaceId) {
1406
1412
  : "idle",
1407
1413
  deferredTurn: projectDeferredTurnSummary(session.deferredTurns?.[0]),
1408
1414
  deferredTurns: projectDeferredTurnSummaries(session.deferredTurns ?? []),
1415
+ isBlank: isBlankChatSession(session) && !active,
1409
1416
  };
1410
1417
  });
1411
1418
  }
@@ -1436,7 +1443,7 @@ export async function handlePatchChatSession(req, res, deps, sessionId) {
1436
1443
  });
1437
1444
  return;
1438
1445
  }
1439
- sendJson(res, 200, { ok: true, session: record });
1446
+ sendJson(res, 200, { ok: true, session: projectBrowserChatSession(record) });
1440
1447
  }
1441
1448
  catch (error) {
1442
1449
  sendJson(res, 404, {
@@ -2776,6 +2783,9 @@ export async function handleChatCommands(res, deps, sessionId) {
2776
2783
  res.end(JSON.stringify({
2777
2784
  ok: true,
2778
2785
  commands,
2786
+ capabilities: {
2787
+ sddBingo: Boolean(await deps.sddDataAlignment?.isEligible()),
2788
+ },
2779
2789
  ...(warning ? { warning } : {}),
2780
2790
  }));
2781
2791
  }
@@ -2786,10 +2796,46 @@ export async function handleChatCommands(res, deps, sessionId) {
2786
2796
  res.end(JSON.stringify({
2787
2797
  ok: true,
2788
2798
  commands: [],
2799
+ capabilities: { sddBingo: false },
2789
2800
  warning: error instanceof Error ? error.message : "commands unavailable",
2790
2801
  }));
2791
2802
  }
2792
2803
  }
2804
+ async function handleSddBingo(req, res, deps, sessionId) {
2805
+ const gate = gateMutation(req, deps);
2806
+ if (!gate.ok) {
2807
+ sendJson(res, gate.status, { ok: false, error: { code: gate.code, message: gate.message } });
2808
+ return;
2809
+ }
2810
+ if (!deps.sddDataAlignment) {
2811
+ sendJson(res, 403, {
2812
+ ok: false,
2813
+ error: { code: "SDD_NOT_ELIGIBLE", message: "当前用户不可使用 SDD 数据对齐" },
2814
+ });
2815
+ return;
2816
+ }
2817
+ try {
2818
+ const body = await readJsonBody(req);
2819
+ if (Object.keys(body).some((key) => key !== "skillName")) {
2820
+ throw new SddDataAlignmentError("SDD_INVALID_SKILL_NAME", "请求体只允许 skillName 字段", 400);
2821
+ }
2822
+ await deps.sddDataAlignment.report(sessionId, body.skillName);
2823
+ sendJson(res, 200, { ok: true });
2824
+ }
2825
+ catch (error) {
2826
+ if (error instanceof SddDataAlignmentError) {
2827
+ sendJson(res, error.status, {
2828
+ ok: false,
2829
+ error: { code: error.code, message: error.message },
2830
+ });
2831
+ return;
2832
+ }
2833
+ sendJson(res, 502, {
2834
+ ok: false,
2835
+ error: { code: "SDD_UPSTREAM_FAILED", message: "SDD 数据对齐上报失败" },
2836
+ });
2837
+ }
2838
+ }
2793
2839
  export async function handleRuntimeContext(res, deps, sessionId) {
2794
2840
  const ensured = await ensureActiveSession(deps, sessionId);
2795
2841
  if (!ensured.ok) {
@@ -2921,7 +2967,11 @@ export async function handleModels(req, res, deps, sessionId) {
2921
2967
  // folded into a 409 MODEL_SWITCH_FAILED (the frontend refresh path
2922
2968
  // re-reads the snapshot to converge on the applied selection).
2923
2969
  const snapshot = await deps.runtime.getRuntimeSnapshot(sessionId);
2924
- sendJson(res, 200, { ok: true, session: updated, snapshot });
2970
+ sendJson(res, 200, {
2971
+ ok: true,
2972
+ session: projectBrowserChatSession(updated),
2973
+ snapshot,
2974
+ });
2925
2975
  }
2926
2976
  catch (error) {
2927
2977
  if (error instanceof RuntimeSnapshotUnavailableError) {
@@ -4188,6 +4238,11 @@ export async function handleChatRequest(req, res, deps, pathname, workspaceScope
4188
4238
  await handleSkillAutoInvocation(req, res, deps, decodeURIComponent(skillAutoInvocation[1]), decodeURIComponent(skillAutoInvocation[2]));
4189
4239
  return true;
4190
4240
  }
4241
+ const sddBingo = pathname.match(/^\/api\/operator\/v1\/chat\/sessions\/([^/]+)\/sdd-bingo$/);
4242
+ if (method === "POST" && sddBingo) {
4243
+ await handleSddBingo(req, res, deps, decodeURIComponent(sddBingo[1]));
4244
+ return true;
4245
+ }
4191
4246
  const m4Route = pathname.match(/^\/api\/operator\/v1\/chat\/sessions\/([^/]+)\/(draft|files|runtime-context|runtime-snapshot|models|model|reload|commands)$/);
4192
4247
  if (m4Route) {
4193
4248
  const id = decodeURIComponent(m4Route[1]);
@@ -0,0 +1,219 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { readFile, stat } from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ export const SDD_DEFAULT_SKILL_NAME = "SDD-implementation-test-review";
6
+ export const SDD_TELEMETRY_URL = "https://wizard-ai.paic.com.cn/code_pilot/api/skill-usage-log";
7
+ export const SDD_TELEMETRY_SIGN = "52aad0c09e6b46818a11ee702d6fe0ba";
8
+ export const WIZARD_LOCAL_DEFAULT_USER_AGENT = "Builder/OpenCode ai-sdk/provider-utils/4.0.21 runtime/bun/1.3.11";
9
+ function sameAuthFileVersion(left, right) {
10
+ if (!left.exists || !right.exists)
11
+ return left.exists === right.exists;
12
+ return left.dev === right.dev && left.ino === right.ino && left.size === right.size &&
13
+ left.mtimeNs === right.mtimeNs && left.ctimeNs === right.ctimeNs;
14
+ }
15
+ /** Reads ~/.aima-go/auth.json with metadata-based parse caching and fail-closed semantics. */
16
+ export class AimaxAuthReader {
17
+ authFile;
18
+ cached;
19
+ constructor(authFile = path.join(os.homedir(), ".aima-go", "auth.json")) {
20
+ this.authFile = authFile;
21
+ }
22
+ async getToken() {
23
+ let version;
24
+ try {
25
+ const info = await stat(this.authFile, { bigint: true });
26
+ version = { exists: true, dev: info.dev, ino: info.ino, size: info.size,
27
+ mtimeNs: info.mtimeNs, ctimeNs: info.ctimeNs };
28
+ }
29
+ catch {
30
+ this.cached = { version: { exists: false } };
31
+ return undefined;
32
+ }
33
+ if (this.cached && sameAuthFileVersion(this.cached.version, version))
34
+ return this.cached.token;
35
+ let token;
36
+ try {
37
+ const parsed = JSON.parse(await readFile(this.authFile, "utf8"));
38
+ const candidate = parsed["aimax-auth-token"];
39
+ if (typeof candidate === "string" && candidate.trim())
40
+ token = candidate;
41
+ }
42
+ catch {
43
+ // Malformed or unreadable files are intentionally ineligible.
44
+ }
45
+ this.cached = { version, ...(token ? { token } : {}) };
46
+ return token;
47
+ }
48
+ async isEligible() {
49
+ return Boolean(await this.getToken());
50
+ }
51
+ }
52
+ const OPENCODE_RANDOM_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
53
+ const OPENCODE_TIME_MASK = (1n << 48n) - 1n;
54
+ let lastOpenCodeMillisecond = -1;
55
+ let openCodeMillisecondCounter = 0;
56
+ /** Generate the OpenCode-compatible `ses_` identifier without an OpenCode dependency. */
57
+ export function createOpenCodeSessionId(options = {}) {
58
+ const now = Math.floor((options.now ?? Date.now)());
59
+ if (now === lastOpenCodeMillisecond)
60
+ openCodeMillisecondCounter = (openCodeMillisecondCounter + 1) & 0xfff;
61
+ else {
62
+ lastOpenCodeMillisecond = now;
63
+ openCodeMillisecondCounter = 0;
64
+ }
65
+ const ordered = BigInt(now) * 0x1000n + BigInt(openCodeMillisecondCounter);
66
+ const timePart = ((~ordered) & OPENCODE_TIME_MASK).toString(16).padStart(12, "0");
67
+ const bytes = (options.random ?? randomBytes)(14);
68
+ let randomPart = "";
69
+ for (const byte of bytes)
70
+ randomPart += OPENCODE_RANDOM_ALPHABET[byte % OPENCODE_RANDOM_ALPHABET.length];
71
+ return `ses_${timePart}${randomPart}`;
72
+ }
73
+ export class SddDataAlignmentError extends Error {
74
+ code;
75
+ status;
76
+ constructor(code, message, status) {
77
+ super(message);
78
+ this.code = code;
79
+ this.status = status;
80
+ this.name = "SddDataAlignmentError";
81
+ }
82
+ }
83
+ export function normalizeSddSkillName(value) {
84
+ if (value !== undefined && typeof value !== "string") {
85
+ throw new SddDataAlignmentError("SDD_INVALID_SKILL_NAME", "skillName 必须是字符串", 400);
86
+ }
87
+ const raw = value ?? "";
88
+ const normalized = raw.trim() || SDD_DEFAULT_SKILL_NAME;
89
+ if ([...normalized].length > 256 || /[\u0000-\u001f\u007f]/u.test(raw)) {
90
+ throw new SddDataAlignmentError("SDD_INVALID_SKILL_NAME", "skillName 不能超过 256 个字符或包含控制字符", 400);
91
+ }
92
+ return normalized;
93
+ }
94
+ export class SddDataAlignmentService {
95
+ store;
96
+ auth;
97
+ fetchImpl;
98
+ constructor(store, auth = new AimaxAuthReader(), fetchImpl = fetch) {
99
+ this.store = store;
100
+ this.auth = auth;
101
+ this.fetchImpl = fetchImpl;
102
+ }
103
+ async isEligible() {
104
+ return this.auth.isEligible();
105
+ }
106
+ async ensureTelemetrySessionId(sessionId) {
107
+ const value = await this.store.ensureTelemetrySessionId(sessionId, createOpenCodeSessionId);
108
+ if (!value)
109
+ throw new SddDataAlignmentError("SDD_SESSION_NOT_FOUND", "当前对话不存在", 404);
110
+ return value;
111
+ }
112
+ async report(sessionId, rawSkillName) {
113
+ const token = await this.auth.getToken();
114
+ if (!token) {
115
+ throw new SddDataAlignmentError("SDD_NOT_ELIGIBLE", "当前用户不可使用 SDD 数据对齐", 403);
116
+ }
117
+ const skillName = normalizeSddSkillName(rawSkillName);
118
+ const telemetrySessionId = await this.ensureTelemetrySessionId(sessionId);
119
+ const controller = new AbortController();
120
+ const timeout = setTimeout(() => controller.abort(), 30_000);
121
+ let response;
122
+ try {
123
+ response = await this.fetchImpl(SDD_TELEMETRY_URL, {
124
+ method: "POST",
125
+ headers: {
126
+ "Content-Type": "application/json",
127
+ "ws-auth": token,
128
+ "ws-sign": SDD_TELEMETRY_SIGN,
129
+ Connection: "keep-alive",
130
+ "User-Agent": "opencode/1.3.6",
131
+ Accept: "*/*",
132
+ Host: "wizard-ai.paic.com.cn",
133
+ "Accept-Encoding": "gzip, deflate, br, zstd",
134
+ },
135
+ body: JSON.stringify({ sessionId: telemetrySessionId, builderId: "opencode", skillName }),
136
+ signal: controller.signal,
137
+ });
138
+ }
139
+ catch {
140
+ if (controller.signal.aborted) {
141
+ throw new SddDataAlignmentError("SDD_UPSTREAM_TIMEOUT", "SDD 数据对齐上报超时", 504);
142
+ }
143
+ throw new SddDataAlignmentError("SDD_UPSTREAM_FAILED", "SDD 数据对齐上报失败", 502);
144
+ }
145
+ finally {
146
+ clearTimeout(timeout);
147
+ }
148
+ const body = await readBoundedTelemetryJson(response);
149
+ if (!response.ok || body?.ret !== 0 || body.succ !== true) {
150
+ throw new SddDataAlignmentError("SDD_UPSTREAM_FAILED", "SDD 数据对齐上报失败", 502);
151
+ }
152
+ }
153
+ }
154
+ async function readBoundedTelemetryJson(response) {
155
+ const reader = response.body?.getReader();
156
+ if (!reader)
157
+ return undefined;
158
+ const chunks = [];
159
+ let total = 0;
160
+ try {
161
+ for (;;) {
162
+ const item = await reader.read();
163
+ if (item.done)
164
+ break;
165
+ total += item.value.byteLength;
166
+ if (total > 64 * 1024) {
167
+ await reader.cancel();
168
+ return undefined;
169
+ }
170
+ chunks.push(item.value);
171
+ }
172
+ const merged = new Uint8Array(total);
173
+ let offset = 0;
174
+ for (const chunk of chunks) {
175
+ merged.set(chunk, offset);
176
+ offset += chunk.byteLength;
177
+ }
178
+ return JSON.parse(new TextDecoder().decode(merged));
179
+ }
180
+ catch {
181
+ return undefined;
182
+ }
183
+ finally {
184
+ reader.releaseLock();
185
+ }
186
+ }
187
+ function deleteHeaderCaseInsensitive(headers, name) {
188
+ for (const key of Object.keys(headers))
189
+ if (key.toLowerCase() === name.toLowerCase())
190
+ delete headers[key];
191
+ }
192
+ function configuredHeader(headers, name) {
193
+ const key = Object.keys(headers ?? {}).find((entry) => entry.toLowerCase() === name.toLowerCase());
194
+ return key ? headers?.[key] : undefined;
195
+ }
196
+ function setStaticHeader(headers, configured, name, defaultValue) {
197
+ deleteHeaderCaseInsensitive(headers, name);
198
+ headers[name] = configuredHeader(configured, name) ?? defaultValue;
199
+ }
200
+ export async function injectWizardLocalHeaders(options) {
201
+ const model = options.context.model;
202
+ if (model?.provider !== "wizard-local" || !model.id)
203
+ return;
204
+ if (!(await options.service.isEligible()))
205
+ return;
206
+ const getAuth = options.context.modelRegistry?.getApiKeyAndHeaders;
207
+ if (!getAuth)
208
+ return;
209
+ const auth = await getAuth(model);
210
+ if (!auth.ok || typeof auth.apiKey !== "string" || !auth.apiKey)
211
+ return;
212
+ setStaticHeader(options.headers, auth.headers, "client-code", "OpenCode");
213
+ setStaticHeader(options.headers, auth.headers, "User-Agent", WIZARD_LOCAL_DEFAULT_USER_AGENT);
214
+ for (const name of ["x-api-key", "X-Session-Id", "X-Model-Id"])
215
+ deleteHeaderCaseInsensitive(options.headers, name);
216
+ options.headers["x-api-key"] = auth.apiKey;
217
+ options.headers["X-Session-Id"] = await options.service.ensureTelemetrySessionId(options.sessionId);
218
+ options.headers["X-Model-Id"] = model.id;
219
+ }
@@ -1,3 +1,4 @@
1
+ import { isBlankChatSession } from "./session-store.js";
1
2
  import { projectDeferredTurnSummaries, projectDeferredTurnSummary, } from "./deferred-turn.js";
2
3
  /**
3
4
  * Process-wide Session baseline, mirroring DSH's independent session.list.
@@ -33,6 +34,7 @@ export class ChatSessionCatalog {
33
34
  : {}),
34
35
  deferredTurn: projectDeferredTurnSummary(record.deferredTurns?.[0]),
35
36
  deferredTurns: projectDeferredTurnSummaries(record.deferredTurns ?? []),
37
+ isBlank: isBlankChatSession(record),
36
38
  ...(workspaceId ? { workspaceId } : {}),
37
39
  });
38
40
  }
@@ -18,6 +18,15 @@ import { authorizeOperatorChatTool } from "./tools.js";
18
18
  import { projectOperationForChat } from "./chat-event-store.js";
19
19
  import { scrubSecrets } from "./explore-tools.js";
20
20
  import { hashDeferredTurnPayload, parseDeferredTurns, } from "./deferred-turn.js";
21
+ /** True only for a durable session that has never received user work. */
22
+ export function isBlankChatSession(record) {
23
+ return (record.state === "active" &&
24
+ !record.title &&
25
+ !record.displayTitle &&
26
+ record.messages.length === 0 &&
27
+ record.toolInvocations.length === 0 &&
28
+ (record.deferredTurns?.length ?? 0) === 0);
29
+ }
21
30
  const CHAT_TITLE_MAX_CHARS = 80;
22
31
  /** Safe, one-line bounded title used for placeholders and model output. */
23
32
  export function cleanChatTitle(value) {
@@ -81,6 +90,9 @@ export class ChatSessionStore {
81
90
  ...(typeof raw.modelProvider === "string" ? { modelProvider: raw.modelProvider } : {}),
82
91
  ...(typeof raw.modelId === "string" ? { modelId: raw.modelId } : {}),
83
92
  ...(typeof raw.thinkingLevel === "string" ? { thinkingLevel: raw.thinkingLevel } : {}),
93
+ ...(typeof raw.telemetrySessionId === "string" && raw.telemetrySessionId
94
+ ? { telemetrySessionId: raw.telemetrySessionId }
95
+ : {}),
84
96
  ...(typeof raw.workspaceId === "string" && raw.workspaceId
85
97
  ? { workspaceId: raw.workspaceId }
86
98
  : {}),
@@ -165,6 +177,7 @@ export class ChatSessionStore {
165
177
  const now = new Date().toISOString();
166
178
  const record = {
167
179
  ...source,
180
+ telemetrySessionId: undefined,
168
181
  sessionId: input.targetSessionId,
169
182
  state: "active",
170
183
  ...(input.targetSessionFile ? { sessionFile: input.targetSessionFile } : { sessionFile: undefined }),
@@ -179,6 +192,19 @@ export class ChatSessionStore {
179
192
  return record;
180
193
  });
181
194
  }
195
+ /** Atomically backfill the per-conversation simulated identity on first use. */
196
+ async ensureTelemetrySessionId(sessionId, createId) {
197
+ return this.serialize(sessionId, async () => {
198
+ const record = await this.get(sessionId);
199
+ if (!record)
200
+ return undefined;
201
+ if (record.telemetrySessionId)
202
+ return record.telemetrySessionId;
203
+ record.telemetrySessionId = createId();
204
+ await this.persist(record);
205
+ return record.telemetrySessionId;
206
+ });
207
+ }
182
208
  async rename(sessionId, title) {
183
209
  return this.serialize(sessionId, async () => {
184
210
  const record = await this.get(sessionId);
@@ -42,6 +42,13 @@ export const SHORTCUTS = [
42
42
  source: "operator",
43
43
  },
44
44
  ];
45
+ export const SDD_BINGO_SHORTCUT = {
46
+ command: "/sdd-bingo",
47
+ label: "sdd-bingo",
48
+ description: "SDD数据对齐",
49
+ action: "sdd-bingo",
50
+ source: "operator",
51
+ };
45
52
  /** Pi Web commands with real browser-equivalent behavior (UI-11). */
46
53
  export const WEB_SLASH_COMMANDS = [
47
54
  {
@@ -98,7 +105,7 @@ export function resolveShortcut(input) {
98
105
  const token = input.trim().split(/\s+/, 1)[0]?.toLowerCase();
99
106
  if (!token?.startsWith("/"))
100
107
  return undefined;
101
- const local = [...SHORTCUTS, ...WEB_SLASH_COMMANDS].find((shortcut) => shortcut.command === token);
108
+ const local = [...SHORTCUTS, ...WEB_SLASH_COMMANDS, SDD_BINGO_SHORTCUT].find((shortcut) => shortcut.command === token);
102
109
  if (local)
103
110
  return { command: local.command, action: local.action };
104
111
  return { command: token, action: "unknown" };
@@ -116,7 +123,7 @@ export function workspaceForShortcut(action) {
116
123
  * Merge Operator, Web, and dynamic Session commands with conflict dedupe.
117
124
  * Priority: operator/web > extension > skill > prompt. /reload is single-card.
118
125
  */
119
- export function mergeSlashCommands(dynamic = []) {
126
+ export function mergeSlashCommands(dynamic = [], capabilities = {}) {
120
127
  const byName = new Map();
121
128
  const upsert = (item) => {
122
129
  const key = normalizeCommandName(item.command);
@@ -149,6 +156,15 @@ export function mergeSlashCommands(dynamic = []) {
149
156
  action: item.action,
150
157
  });
151
158
  }
159
+ if (capabilities.sddBingo) {
160
+ upsert({
161
+ command: SDD_BINGO_SHORTCUT.command,
162
+ label: SDD_BINGO_SHORTCUT.label,
163
+ description: SDD_BINGO_SHORTCUT.description,
164
+ source: SDD_BINGO_SHORTCUT.source,
165
+ action: SDD_BINGO_SHORTCUT.action,
166
+ });
167
+ }
152
168
  for (const item of dynamic) {
153
169
  const command = normalizeCommandName(item.command);
154
170
  if (!command)
@@ -455,6 +455,7 @@ export async function createConsoleServer(options) {
455
455
  : "idle",
456
456
  deferredTurn: entry.deferredTurn,
457
457
  deferredTurns: entry.deferredTurns,
458
+ isBlank: entry.isBlank && !active,
458
459
  };
459
460
  });
460
461
  sendJson(res, 200, {
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-DOrvbR-H.js";import{p as f}from"./chunk-JWPE2WC7-CXlqO8l6.js";import{_ as n,l as o}from"./mermaid.core-F--C1uV0.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-BvoG1fh5.js";import"./index-C8V8K9b4.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-BPelzihi.js";import{p as f}from"./chunk-JWPE2WC7-RIg5_bFJ.js";import{_ as n,l as o}from"./mermaid.core-CwLZPtQo.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-BBhF0NAT.js";import"./index-CVdddQsA.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-F--C1uV0.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-CwLZPtQo.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};