@tea-agent/loop-agent 0.42.0-next.4 → 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.
- package/CHANGELOG.md +5 -0
- package/dist/build-stamp.json +3 -3
- package/dist/worker/console/chat/pi-runtime.js +26 -0
- package/dist/worker/console/chat/routes.js +60 -5
- package/dist/worker/console/chat/sdd-data-alignment.js +219 -0
- package/dist/worker/console/chat/session-catalog.js +2 -0
- package/dist/worker/console/chat/session-store.js +26 -0
- package/dist/worker/console/chat/shortcuts.js +18 -2
- package/dist/worker/console/server.js +1 -0
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-CeznJ4Iw.js → abnfDiagram-N423BO3Z-BJpsGgAv.js} +1 -1
- package/dist/worker/console/static/assets/{arc-B4u9u7SX.js → arc-DjMFPsEd.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-oghpT81p.js → architectureDiagram-T3A2C74G-DqdZlr1O.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-BPJ5Kvcj.js → blockDiagram-VBNYF7ZC-BmZnfFEO.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-CoIu69pd.js → c4Diagram-5PPSVZJV-3cKberpL.js} +1 -1
- package/dist/worker/console/static/assets/channel-DWYwciiv.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-DtgiAsSc.js → chunk-2GRJ4B5K-q-0yjQ1h.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-YSu_EVSD.js → chunk-2Q5K7J3B-DnONBaDW.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DaRO-NB6.js → chunk-5RXB4S5H-v3a6PCOS.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-Dh0ZKiGA.js → chunk-5VM5RSS4-D1kLrlU_.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DOrvbR-H.js → chunk-6Q2QTUOP-BPelzihi.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-C3b22LN2.js → chunk-GF5L2VYU-DauNE69H.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-CXlqO8l6.js → chunk-JWPE2WC7-RIg5_bFJ.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BblTBrDu.js → chunk-KBJHAD2P-BuILuoxs.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-DswqPALe.js → chunk-RYQCIY6F-VHORV5oW.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CfTwVOlc.js → chunk-XXDRQBXY-BJYr4xHC.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-D6jOf_l4.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-D6jOf_l4.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-bLD8jVFo.js → cose-bilkent-JH36ORCC-BS6nuqQn.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BvoG1fh5.js → cynefin-VYW2F7L2-BBhF0NAT.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-DEPAdJu3.js → cynefinDiagram-MW4NZA55-D1135Ifg.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-DmrNvBLy.js → dagre-VZM6K2ZE-vAOYPUWJ.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-CdwzIwvs.js → diagram-7IWD3JNH-DuaSPkfa.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-CJ3hj-md.js → diagram-B4RE2ZJO-mMvXvGU6.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-C6YJT2a4.js → diagram-LBJQPF4R-CDIEJtlL.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-C_LPfjhX.js → diagram-Q27KOJAE-Bi_6JvCW.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-xvsSb5Ie.js → diagram-UB23O5K3-DAqj57yN.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-Rxp2tKcD.js → ebnfDiagram-BXEA7PRR-DfWaxNEo.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DRyLYmZh.js → erDiagram-JOGREHBK-Bt7QqkNG.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-TLSU_D2B.js → flowDiagram-UKHOOZJN-CRRhQwT2.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DGqeTvHC.js → ganttDiagram-PKOTCBZU-DAV1O5B6.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-BZxyH2wh.js → gitGraphDiagram-DS77QQ5N-0X2Qo4Lp.js} +1 -1
- package/dist/worker/console/static/assets/index-CVdddQsA.js +451 -0
- package/dist/worker/console/static/assets/index-DDQc5a50.css +1 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-BsYtzx01.js → infoDiagram-6WML65LV-C5W5eILC.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-Qr-ezGv-.js → ishikawaDiagram-WSZJBQD7-5SfqU-Tb.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DYbB3ibo.js → journeyDiagram-NVQOT4AX-CKDRcaKf.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BHJHewZO.js → kanban-definition-27J2QSJJ-Cc7_TuSb.js} +1 -1
- package/dist/worker/console/static/assets/{linear-CmPIPmCG.js → linear-BcQYYmeT.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-F--C1uV0.js → mermaid.core-CwLZPtQo.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-YTXfL1st.js → mindmap-definition-FAOFIHXS-D29M025z.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-DdDMYXP9.js → pegDiagram-VL7TDLO6-CV-ZAWYe.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-C3nH4KVd.js → pieDiagram-7S7Q4E2Y-C6iPS_o5.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-kXyxjG7Y.js → quadrantDiagram-CIZ2JOQS-BFCD1sTg.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-KNzbl-7w.js → railroadDiagram-AXF67PYL-CztNj4O9.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-CSwI6dG0.js → requirementDiagram-LRYGKXZP-BWIELSNd.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-Bl1AyuXy.js → sankeyDiagram-W5VNT64P-CPtxrjJQ.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-2y4EmXQa.js → sequenceDiagram-SI44F4Z6-BEWVSFsu.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-E8v8YrMg.js → sizeCapture-X5ZJPWSS-DyhzoX_J.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-eGGlR856.js → stateDiagram-OKZ733FA-xLox0nu7.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DS5ZRvJG.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-B7g7xc07.js → swimlanes-SLNWSIFB-CLC_ow9A.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Dvpxn-bf.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-DR3VCHBG.js → timeline-definition-Z64GVDOM-DmJZ4uyY.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-LUvapZIy.js → vennDiagram-T6HMQDX7-DD7GGi9Z.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-C7GDcaXq.js → wardleyDiagram-T6FBY63Y-Bi8PQoGt.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CbNAqoGK.js → xychartDiagram-ELKLHX3M-uKdAY8Dp.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +225 -21
- package/dist/worker/console/static-src/operator-chat/useComposer.js +5 -1
- package/dist/worker/console/workspace-context.js +4 -0
- package/dist/workflows/dag/init-hybrid.js +22 -15
- package/docs/templates/backend-test-dag.json +3 -3
- package/package.json +1 -1
- package/dist/worker/console/static/assets/channel-DmIXqJ6B.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-MFV5Qxb5.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-MFV5Qxb5.js +0 -1
- package/dist/worker/console/static/assets/index-C8V8K9b4.js +0 -451
- package/dist/worker/console/static/assets/index-Cnf_KxTQ.css +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-B8e4J3at.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Do88I1Nb.js +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -2,8 +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)。
|
|
5
6
|
- 修复 Next Release 的 io-heavy 测试并发不稳定:发布 workflow 将该池固定为单 worker,避免全部测试已通过后触发 Vitest `onTaskUpdate` RPC settlement timeout,并消除 controller identity/package fingerprint 测试之间的共享状态竞态;不跳过或删除任何测试。
|
|
6
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,请求头与资格文件变更均在下一次操作自动生效。
|
|
7
12
|
- 修复前端任务产物派生续跑无法识别当前节点链的问题;从实现节点继续时,设计约束、写入准入、验证和收尾步骤会按现行流程安全重放。
|
|
8
13
|
- 统一工作区、Todo 和其他滚动区域的滚动条样式,默认更轻巧,鼠标悬浮时也更容易辨认。
|
|
9
14
|
- HTML 文件预览现在支持页面内的标签切换等交互;较大的自包含 HTML 可以在新窗口中直接完整加载,不再受源码摘要长度影响。
|
package/dist/build-stamp.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"version": "0.42.0-next.
|
|
4
|
-
"gitSha": "
|
|
5
|
-
"builtAt": "2026-09-
|
|
3
|
+
"version": "0.42.0-next.5",
|
|
4
|
+
"gitSha": "260dc2585e355412fa689ac856badc73b2f609f9",
|
|
5
|
+
"builtAt": "2026-09-01T18:19:10.922Z"
|
|
6
6
|
}
|
|
@@ -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, {
|
|
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)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as p,r as u,d as a}from"./chunk-6Q2QTUOP-
|
|
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-
|
|
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};
|