@xiaobuyu/nodesign 0.0.5 → 0.0.7

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 (137) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/package.json +1 -1
  4. package/server/api/assets/helpers.js +18 -0
  5. package/server/api/assets/notes.js +50 -0
  6. package/server/api/assets.js +11 -6
  7. package/server/api/instruction.js +3 -3
  8. package/server/engine/agent/events.js +11 -1
  9. package/server/engine/agent/hooks/failure.js +11 -1
  10. package/server/engine/agent/hooks/lifecycle.js +10 -39
  11. package/server/engine/agent/hooks/post-guidance.js +4 -38
  12. package/server/engine/agent/hooks/user-prompt-submit.js +11 -40
  13. package/server/engine/agent/hooks.js +4 -8
  14. package/server/engine/agent/memory-config.js +61 -0
  15. package/server/engine/agent/prompts/nodesign-prelude.md +14 -12
  16. package/server/engine/agent/prompts/tools/generate-image-cookbook.md +24 -7
  17. package/server/engine/agent/prompts/tools/site-reference.md +13 -3
  18. package/server/engine/agent/session-loop.js +29 -18
  19. package/server/engine/agents/explorer.md +1 -1
  20. package/server/engine/agents/index.js +1 -1
  21. package/server/engine/mcp/index.js +4 -11
  22. package/server/engine/mcp/tools/arrange-on-board.js +3 -1
  23. package/server/engine/mcp/tools/browse-computer.js +2 -1
  24. package/server/engine/mcp/tools/browse-find-batch.js +20 -3
  25. package/server/engine/mcp/tools/browse.js +24 -2
  26. package/server/engine/mcp/tools/crystallize-skill.js +1 -1
  27. package/server/engine/mcp/tools/generate-image.js +50 -70
  28. package/server/engine/mcp/tools/helpers/codex-imagegen.js +139 -0
  29. package/server/engine/mcp/tools/helpers/rembg.js +7 -2
  30. package/server/engine/mcp/tools/helpers/shot-pipeline.js +109 -0
  31. package/server/engine/mcp/tools/list-pages.js +11 -5
  32. package/server/engine/mcp/tools/organize-board.js +26 -1
  33. package/server/engine/mcp/tools/pin-to-board.js +26 -17
  34. package/server/engine/mcp/tools/read-board.js +19 -5
  35. package/server/engine/mcp/tools/relate-on-board.js +42 -4
  36. package/server/engine/mcp/tools/report-issue.js +14 -7
  37. package/server/engine/mcp/tools/screenshot.js +17 -7
  38. package/server/engine/mcp/tools/sketch-on-board.js +13 -5
  39. package/server/engine/mcp/tools/web-search.js +11 -15
  40. package/server/engine/mcp/tools/write-on-board.js +15 -6
  41. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/SKILL.md +3 -4
  42. package/server/engine/plugins/nodesign/skills/docx-craft/SKILL.md +10 -1
  43. package/server/engine/plugins/nodesign/skills/docx-craft/references/token-schema.md +16 -0
  44. package/server/engine/plugins/nodesign/skills/site-craft/SKILL.md +4 -4
  45. package/server/index.js +0 -2
  46. package/server/lib/artifact-target.js +31 -14
  47. package/server/lib/board-kind-sizes.js +2 -3
  48. package/server/lib/canvas-id.js +29 -4
  49. package/server/lib/export-collect.js +3 -1
  50. package/server/lib/issues-store.js +3 -1
  51. package/server/lib/kinds/docx.js +11 -4
  52. package/server/lib/kinds/index.js +6 -16
  53. package/server/lib/kinds/site.js +40 -7
  54. package/server/lib/rewrite-refs.js +110 -0
  55. package/server/lib/ssrf-guard.js +9 -0
  56. package/server/lib/task-scan.js +18 -0
  57. package/server/projects/board-store.js +42 -1
  58. package/server/projects/memory-migration.js +85 -0
  59. package/server/projects/move-entry.js +11 -1
  60. package/server/projects/ui-config.js +2 -1
  61. package/server/projects/workspace-templates.js +13 -10
  62. package/server/projects/workspace.js +15 -15
  63. package/server/services/rembg-launcher.js +5 -2
  64. package/web/dist/assets/{BrowserWindow-P_vIdh-G.js → BrowserWindow-BoOBaIyz.js} +1 -1
  65. package/web/dist/assets/DeckWindow-Bg3rgkvi.js +11 -0
  66. package/web/dist/assets/{DocxWindow-DSAU1-tD.js → DocxWindow-B_u6aX9o.js} +1 -1
  67. package/web/dist/assets/{MermaidBlock-DR1GikCv.js → MermaidBlock-BO-46Du5.js} +6 -6
  68. package/web/dist/assets/{SiteWindow-92uBuRRR.js → SiteWindow-ConPmzdM.js} +1 -1
  69. package/web/dist/assets/{abnfDiagram-VCTEODGH-uA8Esix4.js → abnfDiagram-VCTEODGH-FCO9yf-n.js} +1 -1
  70. package/web/dist/assets/{arc-D_khH_xN.js → arc-BLcEOSRX.js} +1 -1
  71. package/web/dist/assets/{architectureDiagram-5GKGNRK7-DydJHqOt.js → architectureDiagram-5GKGNRK7-kxiX4TeN.js} +1 -1
  72. package/web/dist/assets/{blockDiagram-NRAW4CY4-B7wBbKiW.js → blockDiagram-NRAW4CY4-CptFksix.js} +1 -1
  73. package/web/dist/assets/{c4Diagram-UCG6FXSJ-6mrH0x7Y.js → c4Diagram-UCG6FXSJ-Dxmxj34F.js} +1 -1
  74. package/web/dist/assets/channel-DFyiuGL0.js +1 -0
  75. package/web/dist/assets/{chunk-2Q5K7J3B-Cuikho5Q.js → chunk-2Q5K7J3B-D9inx5oo.js} +1 -1
  76. package/web/dist/assets/{chunk-5VM5RSS4-3-KZ5AUz.js → chunk-5VM5RSS4-DydfHlEc.js} +1 -1
  77. package/web/dist/assets/{chunk-F27PBJKO-Bkwq2gGU.js → chunk-F27PBJKO-BO7GxhSv.js} +1 -1
  78. package/web/dist/assets/{chunk-G27WJ6UU-BLyQzdGE.js → chunk-G27WJ6UU-BzP6YiQ_.js} +1 -1
  79. package/web/dist/assets/{chunk-JWPE2WC7-B7HxxQds.js → chunk-JWPE2WC7-CHcgcd0s.js} +1 -1
  80. package/web/dist/assets/{chunk-LCL6LL3I-CtXrnUwF.js → chunk-LCL6LL3I-D2Wg5JtX.js} +1 -1
  81. package/web/dist/assets/{chunk-POPQ4Y6H-dxddZlXt.js → chunk-POPQ4Y6H-B2fCRfpM.js} +1 -1
  82. package/web/dist/assets/{chunk-SVP7TREG-DpkmrgHn.js → chunk-SVP7TREG-JSLcsRlZ.js} +1 -1
  83. package/web/dist/assets/{chunk-XXDRQBXY-BwZ7RbpQ.js → chunk-XXDRQBXY-BCjvaeHm.js} +1 -1
  84. package/web/dist/assets/classDiagram-DTDB5LWJ-Aw1f8z-b.js +1 -0
  85. package/web/dist/assets/classDiagram-v2-JRS7N3AN-Aw1f8z-b.js +1 -0
  86. package/web/dist/assets/{cose-bilkent-JH36ORCC-DGFOsMUt.js → cose-bilkent-JH36ORCC-0uKv6oJ7.js} +1 -1
  87. package/web/dist/assets/{cynefin-OW5HDTMX-DUwn3ehS.js → cynefin-OW5HDTMX-Bvt-gEmA.js} +1 -1
  88. package/web/dist/assets/{cynefinDiagram-5FMLGOSQ-DlLAOZ9x.js → cynefinDiagram-5FMLGOSQ-C9Ht02qC.js} +1 -1
  89. package/web/dist/assets/{dagre-3AP2YEHR-CyourLfz.js → dagre-3AP2YEHR-BfxZny4s.js} +1 -1
  90. package/web/dist/assets/{diagram-S7CK7UJ4-BTMbx2np.js → diagram-S7CK7UJ4-CrE0ZETE.js} +1 -1
  91. package/web/dist/assets/{diagram-UQ7AKVKN-UK94_1-P.js → diagram-UQ7AKVKN-BO8VQ4Fx.js} +1 -1
  92. package/web/dist/assets/{diagram-VSXAHHWV-C7zS-v9v.js → diagram-VSXAHHWV-CHUZnR9F.js} +1 -1
  93. package/web/dist/assets/{diagram-VX7I27RA-DKJRa6CK.js → diagram-VX7I27RA-DYQAz1Vu.js} +1 -1
  94. package/web/dist/assets/{diagram-Z3DM3KII-kUbAfGAp.js → diagram-Z3DM3KII-BDjivgLr.js} +1 -1
  95. package/web/dist/assets/{ebnfDiagram-PWID7BFC-CVW16_vb.js → ebnfDiagram-PWID7BFC-Bpe_QVbH.js} +1 -1
  96. package/web/dist/assets/{erDiagram-SSCWMZ5O-BRQMFQ5y.js → erDiagram-SSCWMZ5O-BxhwuAu1.js} +1 -1
  97. package/web/dist/assets/{flowDiagram-A5DVABFB-S34LpLtK.js → flowDiagram-A5DVABFB-CCw2H08-.js} +1 -1
  98. package/web/dist/assets/{ganttDiagram-EL5Y4UJY-BFiqk1-G.js → ganttDiagram-EL5Y4UJY-DtTc7MyI.js} +1 -1
  99. package/web/dist/assets/{gitGraphDiagram-WWUBYQGX-LZsrdyyv.js → gitGraphDiagram-WWUBYQGX-BvORxMd2.js} +1 -1
  100. package/web/dist/assets/index-DGG5wIZs.js +2118 -0
  101. package/web/dist/assets/{infoDiagram-RXCK75RN-0DvN6KIp.js → infoDiagram-RXCK75RN-DMcrkypD.js} +1 -1
  102. package/web/dist/assets/{ishikawaDiagram-5VMMS53U-CaY3A-Bx.js → ishikawaDiagram-5VMMS53U-CZkTIbe-.js} +1 -1
  103. package/web/dist/assets/{journeyDiagram-EYS64GPL-BBeiaCrj.js → journeyDiagram-EYS64GPL-DR0XazdE.js} +1 -1
  104. package/web/dist/assets/{kanban-definition-3QL26DDD-ux42DRXQ.js → kanban-definition-3QL26DDD-DN8VbwVu.js} +1 -1
  105. package/web/dist/assets/{layout-CnXiF_NB.js → layout-9_paCbyt.js} +1 -1
  106. package/web/dist/assets/{linear-BMW0u6G6.js → linear-g6Ct012e.js} +1 -1
  107. package/web/dist/assets/{mindmap-definition-FBJOCRG2-hUxSpdKn.js → mindmap-definition-FBJOCRG2-BGt4omYC.js} +1 -1
  108. package/web/dist/assets/{pegDiagram-XKGWAZYB-aCaQPH0w.js → pegDiagram-XKGWAZYB-uSfS-PBE.js} +1 -1
  109. package/web/dist/assets/{pending-edit-apply-AcdOQ9Ij.js → pending-edit-apply-uP4uvrOD.js} +1 -1
  110. package/web/dist/assets/{pieDiagram-E7YTZNPT-CmOEZ8zg.js → pieDiagram-E7YTZNPT-DpeI935H.js} +1 -1
  111. package/web/dist/assets/{quadrantDiagram-AXDQQJYC-VW6fAhsV.js → quadrantDiagram-AXDQQJYC-B7IuNvWa.js} +1 -1
  112. package/web/dist/assets/{railroadDiagram-O6MQD6OU-CKJ7Ba5K.js → railroadDiagram-O6MQD6OU-ARzYpPQI.js} +1 -1
  113. package/web/dist/assets/{requirementDiagram-EFPCY7ZU-pNGkq9Vw.js → requirementDiagram-EFPCY7ZU-Cj4upkAo.js} +1 -1
  114. package/web/dist/assets/{rotate-cw-KAfChbGV.js → rotate-cw-CXJcyHWk.js} +1 -1
  115. package/web/dist/assets/{sankeyDiagram-P5KCCOFB-BIMmDTfZ.js → sankeyDiagram-P5KCCOFB-OaVwSnLP.js} +1 -1
  116. package/web/dist/assets/{sequenceDiagram-WJ2MYXX4-BBW7wzKY.js → sequenceDiagram-WJ2MYXX4-1yrUbq4t.js} +1 -1
  117. package/web/dist/assets/{sizeCapture-X5ZJPWSS-DdkXmLYR.js → sizeCapture-X5ZJPWSS-nYH5p9D6.js} +1 -1
  118. package/web/dist/assets/{square-dashed-mouse-pointer-CDUlhUP7.js → square-dashed-mouse-pointer-CTtTVKoH.js} +1 -1
  119. package/web/dist/assets/{stateDiagram-HBIQ2CUA-W313Uz16.js → stateDiagram-HBIQ2CUA-Dj5HvyNq.js} +1 -1
  120. package/web/dist/assets/stateDiagram-v2-4QOOHH4V-kJ1m_zJT.js +1 -0
  121. package/web/dist/assets/{swimlanes-XN3QIQJK-C29TL26K.js → swimlanes-XN3QIQJK-umeT0HpB.js} +1 -1
  122. package/web/dist/assets/swimlanesDiagram-VK2B7HYN-DPSkMbbl.js +8 -0
  123. package/web/dist/assets/{timeline-definition-24CTP7MA-CF0JMObX.js → timeline-definition-24CTP7MA-MqnQfHKB.js} +1 -1
  124. package/web/dist/assets/{vennDiagram-4TSXK5OY-DrDFsaH3.js → vennDiagram-4TSXK5OY-b2liyZra.js} +1 -1
  125. package/web/dist/assets/{wardleyDiagram-VM6X3IG4-CVrnRIS_.js → wardleyDiagram-VM6X3IG4-QMK-zNh1.js} +1 -1
  126. package/web/dist/assets/{xychartDiagram-S5SC5T6Z-BvkN1zsT.js → xychartDiagram-S5SC5T6Z-D5Mc6tfA.js} +1 -1
  127. package/web/dist/index.html +1 -1
  128. package/server/api/memory.js +0 -185
  129. package/server/engine/agent/prompts/tools/generate-image-cookbook.gemini-gateway.md +0 -583
  130. package/server/engine/mcp/tools/record-decision.js +0 -140
  131. package/web/dist/assets/DeckWindow-BpLv5082.js +0 -16
  132. package/web/dist/assets/channel-DGkccMO1.js +0 -1
  133. package/web/dist/assets/classDiagram-DTDB5LWJ-BGscw3OD.js +0 -1
  134. package/web/dist/assets/classDiagram-v2-JRS7N3AN-BGscw3OD.js +0 -1
  135. package/web/dist/assets/index-GAamh1p4.js +0 -2152
  136. package/web/dist/assets/stateDiagram-v2-4QOOHH4V-DDhJBZzf.js +0 -1
  137. package/web/dist/assets/swimlanesDiagram-VK2B7HYN-BfN-Xdmu.js +0 -8
@@ -1,140 +0,0 @@
1
- /**
2
- * mcp/tools/record-decision.js — record_decision MCP tool
3
- *
4
- * agent 在做关键设计决策时调,把"做了什么 + 为什么"写成共享便利贴
5
- * `notes/决策.md` 的一面(`---` 分面)。2026-07-30 起决策
6
- * 不再进 spec.json.decisions[]:便利贴是 agent 和用户的**共享层**——
7
- * 用户在画布上直接看到、能翻、能改;spec.json 只是 agent 自己的暗档案,
8
- * 用户看不见,头脑风暴根本进不来。旧会话已有的 spec.json decisions[]
9
- * 仍被 hooks 注入(只读遗产),新决策一律走这里。
10
- *
11
- * 便利贴格式约定(前端 NoteSticker 按此渲染):
12
- * - 一个 .md = 一张贴;`\n---\n` 分面,翻页看
13
- * - 每面第一行 `# 标题`
14
- *
15
- * 落点:工作区 `notes/`(扁平模型,2026-08-08 起)—— 没有"任务归属"了,
16
- * 便利贴直接住项目桌面。
17
- */
18
-
19
- import { tool } from '@anthropic-ai/claude-agent-sdk';
20
- import { z } from 'zod';
21
- import { promises as fs } from 'node:fs';
22
- import path from 'node:path';
23
- import { Events } from '../../agent/events.js';
24
-
25
- const NOTE_FILE = '决策.md';
26
-
27
- /**
28
- * @param {object} deps
29
- * @param {string} deps.workspaceRoot
30
- * @param {string} [deps.sessionId]
31
- * @param {import('../../agent/context.js').AgentContext} [deps.ctx]
32
- */
33
- export function makeRecordDecisionTool({ workspaceRoot, sessionId, ctx }) {
34
- return tool(
35
- 'record_decision',
36
- `Record a key design decision as a face of the project's decision sticky note
37
- (notes/决策.md). The note is SHARED with the user — it renders as
38
- a flippable sticky on their canvas, they can read and edit it. Use this to
39
- capture WHY you made a particular choice — color, type scale, layout metaphor,
40
- copy strategy — so the intent survives across sessions and the user can push
41
- back on it.
42
-
43
- Use this tool when:
44
- - You make a non-trivial choice that has multiple defensible alternatives
45
- (e.g., picking a primary color, deciding deck length, choosing a layout)
46
- - The user gives feedback that changes a previous decision (record both)
47
- - You want to document a constraint discovered mid-work
48
-
49
- Do NOT use this tool for:
50
- - Trivial implementation details (CSS class names, file structure)
51
- - Things obvious from the canvas itself (the visible design speaks for itself)
52
- - Every change — over-recording bloats the note and dilutes signal
53
-
54
- For free-form shared notes (brainstorm material, reference digests, handoff
55
- context), just Write notes/<slug>.md directly — same sticky-note
56
- rendering, no tool needed.`,
57
- {
58
- title: z
59
- .string()
60
- .min(2)
61
- .max(200)
62
- .describe('Short decision title (e.g., "Primary color = #3366FF")'),
63
- rationale: z
64
- .string()
65
- .min(2)
66
- .max(2000)
67
- .describe('Why this choice — connect to brief / user feedback / design principle'),
68
- scope: z
69
- .string()
70
- .optional()
71
- .describe('Where it applies (e.g., "Global", "Cover page", "All H1 headings")'),
72
- alternatives: z
73
- .array(z.string())
74
- .optional()
75
- .describe('Alternatives considered, briefly noting why rejected'),
76
- },
77
- async ({ title, rationale, scope, alternatives }) => {
78
- try {
79
- if (!workspaceRoot) {
80
- return {
81
- content: [{ type: 'text', text: 'No workspace bound; cannot record decision.' }],
82
- isError: true,
83
- };
84
- }
85
- const alts = Array.isArray(alternatives)
86
- ? alternatives.map(s => String(s).trim()).filter(Boolean) : [];
87
- const face = [
88
- `# ${title.trim()}`,
89
- '',
90
- rationale.trim(),
91
- ...(scope ? ['', `- 范围:${scope.trim()}`] : []),
92
- ...(alts.length ? [`- 备选:${alts.join(' / ')}`] : []),
93
- `- ${new Date().toISOString().slice(0, 10)}`,
94
- ].join('\n');
95
-
96
- const notesDir = path.join(workspaceRoot, 'notes');
97
- await fs.mkdir(notesDir, { recursive: true });
98
- const noteFile = path.join(notesDir, NOTE_FILE);
99
- let prev = '';
100
- try { prev = await fs.readFile(noteFile, 'utf8'); } catch { /* 首条 */ }
101
- const next = prev.trim() ? `${prev.replace(/\s+$/, '')}\n\n---\n\n${face}\n` : `${face}\n`;
102
- await fs.writeFile(noteFile, next, 'utf8');
103
-
104
- const faceCount = next.split(/\n---\n/).length;
105
- try {
106
- // MCP 工具写盘不走 PostToolUse(Write/Edit) 那条 file_changed 直发,
107
- // 自己补一发,前端便利贴才会当场刷新
108
- // 工作区相对路径(fileChanged 正字法;曾发绝对路径=前端只吃到清单重拉,
109
- // 寻址和版本 key 全失配。2026-08-14 普查改)
110
- ctx?.emit?.(Events.fileChanged(`notes/${NOTE_FILE}`, 'change'));
111
- ctx?.emit?.({
112
- type: 'run.decision_recorded',
113
- title: title.trim(),
114
- scope: scope?.trim() || null,
115
- decisionsCount: faceCount,
116
- });
117
- } catch { /* emit fail-safe */ }
118
-
119
- return {
120
- content: [{
121
- type: 'text',
122
- // ⚠️ 这里曾写 `tasks/${task}/...` —— 扁平化删掉 task 变量时漏了这行,
123
- // `task` 成悬空引用:决策照写、事件照发,**返回时 ReferenceError 被
124
- // 外层 catch 接住**,agent 每次调用都收到报错以为失败(还可能重试出
125
- // 重复面)。悬空引用潜伏族第二案(第一案 reloadToken,2026-08-08)。
126
- text: `Decision recorded as face ${faceCount} of notes/${NOTE_FILE}: "${title.trim()}"`,
127
- }],
128
- };
129
- } catch (err) {
130
- return {
131
- content: [{
132
- type: 'text',
133
- text: `Record decision failed: ${err?.message || String(err)}`,
134
- }],
135
- isError: true,
136
- };
137
- }
138
- },
139
- );
140
- }
@@ -1,16 +0,0 @@
1
- import{c as et,r as o,j as e,d as r,G as t,_ as Ht,R as $,F as p,a as E,$ as tt,u as q,X as ue,w as nt,e as z,a0 as st,a1 as _t,a2 as Dt,a3 as ke,a4 as It,a5 as rt,P as ze,a6 as qt,a7 as it,a8 as Nt,a9 as Ut,aa as Gt,ab as lt,ac as Xt,ad as Kt,ae as Vt,m as ot,af as at,o as dt,ag as Yt,k as Zt,ah as ct,ai as Ct,S as Qt,aj as ut,ak as Jt,al as en,am as Xe,an as tn,Q as nn,ao as sn,ap as rn,aq as ln,M as on,ar as an,as as dn,n as cn,A as un}from"./index-GAamh1p4.js";import{d as Ke,c as Ve,M as xn,o as pn,t as gn,E as fn,C as hn,G as mn,p as yn,D as bn,b as wn,a as vn,P as kn,I as jn,R as Sn,e as zn}from"./pending-edit-apply-AcdOQ9Ij.js";import{E as $n,S as En}from"./square-dashed-mouse-pointer-CDUlhUP7.js";/**
2
- * @license lucide-react v0.468.0 - ISC
3
- *
4
- * This source code is licensed under the ISC license.
5
- * See the LICENSE file in the root directory of this source tree.
6
- */const xt=et("MessageSquare",[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z",key:"1lielz"}]]);/**
7
- * @license lucide-react v0.468.0 - ISC
8
- *
9
- * This source code is licensed under the ISC license.
10
- * See the LICENSE file in the root directory of this source tree.
11
- */const Fn=et("ShieldCheck",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]]),Ln=1920,An=1080;function Tn({src:n,srcDoc:s,mode:i="edit",onSelect:l,onTextEdit:d,onIframeReady:f,zoom:m=1,deckW:c=Ln,deckH:y=An}){const u=o.useRef(null),a=o.useRef(!1),w=o.useRef(0),[x,v]=o.useState(!1);o.useEffect(()=>{v(!0)},[n,s]),o.useEffect(()=>{const b=u.current;if(!(!b||!a.current))return Ke(b),i==="edit"&&Ve(b,{onSelect:l,onTextEdit:d}),()=>Ke(b)},[i,l,d]),o.useEffect(()=>()=>{var b;try{const L=(b=u.current)==null?void 0:b.contentWindow;L&&typeof L.scrollY=="number"&&(w.current=L.scrollY)}catch{}},[n,s]);const k=()=>{a.current=!0;const b=u.current;if(b){if(f==null||f(b),i==="edit"&&Ve(b,{onSelect:l,onTextEdit:d}),w.current>0)try{requestAnimationFrame(()=>{var L;try{(L=b.contentWindow)==null||L.scrollTo(0,w.current)}catch{}})}catch{}requestAnimationFrame(()=>{requestAnimationFrame(()=>v(!1))})}};return e.jsx("div",{style:{flex:1,minHeight:0,overflow:"hidden",background:r.bgWhite,position:"relative",display:"flex",alignItems:"center",justifyContent:"center"},children:e.jsx("iframe",{ref:u,src:n,srcDoc:s,onLoad:k,sandbox:"allow-scripts allow-same-origin",style:{width:`${c}px`,height:`${y}px`,flexShrink:0,border:0,background:r.bgWhite,transform:m===1?"none":`scale(${m})`,transformOrigin:"center center",opacity:x?.5:1,transition:"opacity 180ms ease-out"}})})}function Pn({candidates:n,activeId:s,onSelect:i,onAdd:l,onRemove:d,onRename:f}){if(!n||n.length===0)return null;const m=n.length===1;return e.jsxs("div",{style:{flexShrink:0,height:36,borderBottom:`1px solid ${r.border}`,background:r.bgWhite,padding:`0 ${t.lg}px`,display:"flex",alignItems:"center",gap:t.xs,overflowX:"auto",overflowY:"hidden"},children:[e.jsx(Ht,{size:11,color:r.sub,style:{flexShrink:0,marginRight:t.xs}}),n.map(c=>{const y=c.id===s;return e.jsx(Wn,{candidate:c,active:y,onSelect:()=>i==null?void 0:i(c.id),onRemove:m?null:()=>d==null?void 0:d(c.id),onRename:f},c.id)}),e.jsxs("button",{onClick:l,title:"新建候选(mock 复制当前)",style:{flexShrink:0,padding:`${t.xs}px ${t.md}px`,display:"inline-flex",alignItems:"center",gap:t.xs,fontFamily:E,fontSize:p.xs,color:r.sub,background:"transparent",border:`1px dashed ${r.borderMd}`,borderRadius:$.sm,cursor:"pointer"},onMouseEnter:c=>{c.currentTarget.style.color=r.text2,c.currentTarget.style.background="rgba(0,0,0,0.03)"},onMouseLeave:c=>{c.currentTarget.style.color=r.sub,c.currentTarget.style.background="transparent"},children:[e.jsx(tt,{size:11})," 新候选"]}),e.jsx("div",{style:{flex:1}}),e.jsxs("span",{style:{fontFamily:E,fontSize:p.xs,color:r.sub,opacity:m?0:.7,flexShrink:0},children:[n.length," 个候选"]})]})}function Wn({candidate:n,active:s,onSelect:i,onRemove:l,onRename:d}){const[f,m]=o.useState(!1),c=q(w=>w.prompt),y=q(w=>w.confirm),u=async w=>{if(w.stopPropagation(),!d)return;const x=await c({title:"重命名候选",initialValue:n.label,placeholder:"候选名"});x&&x.trim()&&x!==n.label&&d(n.id,x.trim())},a=async w=>{w.stopPropagation(),await y({title:"删除候选",message:`删除候选「${n.label}」?`,confirmLabel:"删除",danger:!0})&&l()};return e.jsxs("div",{onMouseEnter:()=>m(!0),onMouseLeave:()=>m(!1),style:{flexShrink:0,position:"relative",display:"inline-flex",alignItems:"center",background:s?"rgba(45,36,24,0.06)":"transparent",borderRadius:$.sm,transition:"background 0.15s"},children:[e.jsx("button",{onClick:i,onDoubleClick:u,title:"双击重命名",style:{padding:`${t.xs}px ${l&&f?t.lg:t.md}px ${t.xs}px ${t.md}px`,fontFamily:E,fontSize:p.xs,fontWeight:s?500:400,color:s?r.text:r.text4,background:"transparent",borderRadius:$.sm,cursor:"pointer",transition:"all 0.15s"},children:n.label}),l&&f&&e.jsx("button",{onClick:a,style:{position:"absolute",right:2,top:"50%",transform:"translateY(-50%)",width:14,height:14,borderRadius:$.xs,background:"rgba(0,0,0,0.06)",color:r.sub,display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer"},onMouseEnter:w=>{w.currentTarget.style.background="rgba(184,58,42,0.15)",w.currentTarget.style.color=r.error},onMouseLeave:w=>{w.currentTarget.style.background="rgba(0,0,0,0.06)",w.currentTarget.style.color=r.sub},title:"删除候选",children:e.jsx(ue,{size:9})})]})}const de=12,Bn=8;function $e(n,s){const[i,l]=o.useState(null);return o.useLayoutEffect(()=>{const d=n==null?void 0:n.current;if(!d){l(null);return}const f=()=>{const m=d.getBoundingClientRect();if(!m.width&&!m.height){l(null);return}const c=window.innerWidth,y=window.innerHeight,u=Math.max(de,Math.min(m.left,c-s-de)),a=Math.min(m.bottom+Bn,y-de-120);l({position:"fixed",left:u,top:a,maxHeight:y-a-de})};return f(),window.addEventListener("resize",f),()=>window.removeEventListener("resize",f)},[n,s]),i||{position:"absolute",top:78,right:16}}function Mn({anchorRef:n,onClose:s,iframeDoc:i}){const l=o.useRef(null),d=$e(n,320),[f,m]=o.useState(!1),[c,y]=o.useState(null);o.useEffect(()=>{i&&u()},[i]),o.useEffect(()=>{const a=w=>{var x;l.current&&!l.current.contains(w.target)&&!((x=n==null?void 0:n.current)!=null&&x.contains(w.target))&&(s==null||s())};return window.addEventListener("mousedown",a),()=>window.removeEventListener("mousedown",a)},[s,n]);const u=()=>{i&&(m(!0),setTimeout(()=>{y(On(i)),m(!1)},400))};return e.jsxs("div",{ref:l,style:{...d,width:320,background:r.bgWhite,borderRadius:2,boxShadow:"0 2px 4px rgba(0,0,0,0.04), 0 8px 20px rgba(0,0,0,0.08), 0 24px 48px rgba(0,0,0,0.10), inset 0 1px 0 rgba(255,255,255,0.8)",zIndex:60,overflow:"hidden"},children:[e.jsxs("div",{style:{padding:`${t.md}px ${t.lg}px`,display:"flex",alignItems:"center",justifyContent:"space-between",borderBottom:`1px solid ${r.borderLt}`},children:[e.jsx("span",{style:{fontFamily:E,fontSize:p.sm,fontWeight:500,color:r.text},children:"Accessibility Review"}),e.jsx("button",{onClick:u,disabled:f,style:{padding:t.xs,color:r.sub,borderRadius:$.xs,opacity:f?.5:1},title:"重新扫描",children:e.jsx(nt,{size:11,className:f?"spin":""})})]}),e.jsxs("div",{style:{padding:t.lg,maxHeight:360,overflowY:"auto"},children:[f&&e.jsx("div",{style:{fontFamily:z,fontSize:p.sm,color:r.sub,textAlign:"center",padding:t.lg},children:"扫描中…"}),!f&&c&&e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:t.sm},children:c.map((a,w)=>e.jsx(Rn,{...a},w))})]}),e.jsx("div",{style:{padding:`${t.sm}px ${t.lg}px`,background:r.bgCard,borderTop:`1px solid ${r.borderLt}`,fontFamily:z,fontSize:p.xs,color:r.sub,lineHeight:1.5},children:"P5 接 LLM 真做 contrast / hierarchy / usability 审查;当前是启发式扫描。"})]})}function Rn({kind:n,label:s,hint:i,count:l}){const d=n==="ok",f=n==="warn",m=d?st:f?_t:ue,c=d?r.success:f?r.warn:r.error;return e.jsxs("div",{style:{display:"flex",alignItems:"flex-start",gap:t.sm,padding:`${t.xs}px ${t.sm}px`,background:d?"transparent":"rgba(0,0,0,0.02)",borderRadius:$.sm},children:[e.jsx(m,{size:12,color:c,style:{marginTop:t.xxs,flexShrink:0}}),e.jsxs("div",{style:{flex:1},children:[e.jsxs("div",{style:{fontFamily:z,fontSize:p.sm,color:r.text2,lineHeight:1.4},children:[s," ",l!=null&&e.jsxs("span",{style:{color:r.sub,fontSize:p.xs},children:["(",l,")"]})]}),i&&e.jsx("div",{style:{fontFamily:z,fontSize:p.xs,color:r.sub,marginTop:1,lineHeight:1.4},children:i})]})]})}function On(n){const s=[],i=Array.from(n.querySelectorAll("img")),l=i.filter(u=>!u.hasAttribute("alt"));i.length===0?s.push({kind:"ok",label:"无图片元素需要 alt",hint:"没有 <img> 标签"}):l.length===0?s.push({kind:"ok",label:"图片 alt 完整",count:i.length}):s.push({kind:"warn",label:"部分图片缺 alt",count:l.length,hint:"加 alt 才能让屏幕阅读器识别"});const d=n.querySelectorAll("h1").length,f=n.querySelectorAll("h2").length;d===0&&f===0?s.push({kind:"warn",label:"没有 h1/h2 标题",hint:"层级缺失,screen reader 难导航"}):d>5?s.push({kind:"warn",label:"h1 过多",count:d,hint:"一般每页只 1 个 h1(每 section 1 个也可)"}):s.push({kind:"ok",label:"标题层级合理",hint:`h1 × ${d}, h2 × ${f}`});const m=Array.from(n.querySelectorAll("button")),c=m.filter(u=>!(u.textContent||"").trim()&&!u.getAttribute("aria-label"));m.length===0?s.push({kind:"ok",label:"无 button 需要文本",hint:"页面没有 <button>"}):c.length===0?s.push({kind:"ok",label:"按钮文本完整",count:m.length}):s.push({kind:"warn",label:"部分按钮缺文本/aria-label",count:c.length});const y=n.documentElement;return y.hasAttribute("lang")?s.push({kind:"ok",label:`<html> 标记了 lang="${y.getAttribute("lang")}"`}):s.push({kind:"warn",label:"<html> 缺 lang 属性",hint:"影响 screen reader 发音"}),s.push({kind:"ok",label:"色彩对比度(抽样)",hint:"主色块 WCAG AA pass(mock)"}),s.push({kind:"ok",label:"焦点顺序(mock)",hint:"Tab 键 traversal — P5 真模拟"}),s}function Hn({project:n,deckSpec:s,projectId:i}){var j,T,H;const l=Dt(h=>{var P;return((P=h.contextByProject[i])==null?void 0:P.systemInfo)||null}),d=q(h=>h.showToast),f=q(h=>h.confirm),[m,c]=o.useState([]),[y,u]=o.useState(!1),[a,w]=o.useState(!1),x=o.useRef(null),v=o.useCallback(async()=>{if(i){u(!0);try{const{plugins:h}=await ke.listProject(i);c(h||[])}catch(h){console.error("[SystemTab] listProject plugins failed:",h)}finally{u(!1)}}},[i]);o.useEffect(()=>{v()},[v]);const k=o.useCallback(async(h,P=!1)=>{var _,D,ee,X,K;if(!(!h||!i)){w(!0);try{const F=await ke.installProject(i,h,{force:P}),N=(_=F==null?void 0:F.installed)==null?void 0:_.name;d(`已装 plugin \`${N}\`(新会话生效)`,"success"),(D=F==null?void 0:F.warnings)!=null&&D.length&&d(`警告:${F.warnings.join(";")}`,"warn"),await v()}catch(F){if(F.status===409&&((ee=F.body)!=null&&ee.existing)){await f({title:"覆盖已装 plugin?",message:`已装 \`${F.body.existing.name}@${F.body.existing.version}\`,将覆盖为 \`${F.body.incoming.name}@${F.body.incoming.version}\`。`,confirmLabel:"覆盖",cancelLabel:"取消",danger:!0})&&await k(h,!0);return}const N=(K=(X=F.body)==null?void 0:X.errors)!=null&&K.length?`:${F.body.errors.join(";")}`:"";d(`安装失败${N||`:${F.message}`}`,"error")}finally{w(!1),x.current&&(x.current.value="")}}},[i,v,d,f]),b=o.useCallback(async h=>{if(await f({title:"卸载 plugin?",message:`从 project 移除 \`${h}\`(新会话生效)。文件会被删除。`,confirmLabel:"卸载",cancelLabel:"取消",danger:!0}))try{await ke.removeProject(i,h),d(`已卸载 \`${h}\``,"success"),await v()}catch(_){d(`卸载失败:${_.message}`,"error")}},[i,v,d,f]),L=Array.isArray(l==null?void 0:l.skills)?l.skills.map(h=>typeof h=="string"?h:h.name||h.id).filter(Boolean):[],W=Array.isArray(l==null?void 0:l.plugins)?l.plugins.map(h=>typeof h=="string"?h:h.name||h.id).filter(Boolean):[];return e.jsxs("div",{style:{padding:t.lg,display:"flex",flexDirection:"column",gap:t.xl},children:[e.jsx(J,{label:"本会话的 Skills",children:L.length===0?e.jsx("span",{style:{fontFamily:z,fontSize:p.sm,color:r.sub},children:"(等会话起动后从 SDK system_init 拉取)"}):e.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:t.xs},children:L.map(h=>e.jsx(Ye,{icon:It,label:h},h))})}),e.jsx(J,{label:"本会话的 Plugins",children:W.length===0?e.jsx("span",{style:{fontFamily:z,fontSize:p.sm,color:r.sub},children:"—"}):e.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:t.xs},children:W.map(h=>e.jsx(Ye,{icon:rt,label:h},h))})}),e.jsxs(J,{label:"Project 级 Plugins",children:[e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:t.xs,marginBottom:t.sm},children:y&&m.length===0?e.jsx("span",{style:{fontFamily:z,fontSize:p.sm,color:r.sub},children:"加载中…"}):m.length===0?e.jsx("span",{style:{fontFamily:z,fontSize:p.sm,color:r.sub},children:"暂无(上传 zip 安装到本 project)"}):m.map(h=>e.jsx(_n,{plugin:h,onUninstall:()=>b(h.name)},h.name))}),e.jsx("input",{ref:x,type:"file",accept:".md,.zip,application/zip,text/markdown,text/plain",style:{display:"none"},onChange:h=>{var _;const P=(_=h.target.files)==null?void 0:_[0];P&&k(P)}}),e.jsxs("button",{onClick:()=>{var h;return(h=x.current)==null?void 0:h.click()},disabled:a,style:{display:"inline-flex",alignItems:"center",gap:t.xs,padding:`${t.xs+1}px ${t.md}px`,fontFamily:z,fontSize:p.xs,color:r.text2,background:r.bgWhite,boxShadow:ze.far,borderRadius:$.md,cursor:a?"not-allowed":"pointer",opacity:a?.6:1},children:[e.jsx(qt,{size:11})," ",a?"安装中…":"上传 skill / plugin"]}),e.jsx("div",{style:{marginTop:t.xs,fontFamily:z,fontSize:p.xs,color:r.sub,lineHeight:1.5},children:"支持单 .md / skill zip / 完整 plugin zip。仅装到本 project;全局可见的走右上角 Skill 页面。新会话生效。"})]}),e.jsxs(J,{label:"模型",children:[e.jsx(ce,{k:"LLM",v:(l==null?void 0:l.model)||"—"}),(l==null?void 0:l.cwd)&&e.jsx(ce,{k:"cwd",v:l.cwd})]}),s&&e.jsxs(J,{label:"设计意图(spec)",children:[e.jsx(ce,{k:"metaphor",v:((j=s.meta)==null?void 0:j.metaphor)||"—"}),e.jsx(ce,{k:"audience",v:((T=s.meta)==null?void 0:T.audience)||"—"}),((H=s.meta)==null?void 0:H.intent)&&e.jsx("div",{style:{marginTop:t.sm,padding:t.md,background:r.bgCard,border:`1px solid ${r.borderLt}`,borderRadius:$.md,fontFamily:z,fontSize:p.xs,color:r.text2,lineHeight:1.6},children:s.meta.intent}),s.outline&&s.outline.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{marginTop:t.lg,fontFamily:E,fontSize:p.xs,color:r.sub,textTransform:"uppercase",letterSpacing:"0.05em",marginBottom:t.sm},children:["页面 outline (",s.outline.length,")"]}),e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:t.xs},children:s.outline.map(h=>e.jsxs("div",{style:{padding:`${t.xs+1}px ${t.md}px`,fontFamily:z,fontSize:p.xs,background:"rgba(43,33,23,0.025)",borderRadius:$.sm,display:"flex",gap:t.sm,alignItems:"baseline"},children:[e.jsx("span",{style:{fontFamily:E,color:r.sub,minWidth:24},children:String(h.index).padStart(2,"0")}),e.jsx("span",{style:{color:r.text3,minWidth:64,fontFamily:E,fontSize:p.xs,textTransform:"uppercase"},children:h.layout}),e.jsx("span",{style:{color:r.text2,flex:1,lineHeight:1.4},children:h.intent})]},h.id))})]})]})]})}function _n({plugin:n,onUninstall:s}){var i;return e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:t.sm,padding:`${t.xs+1}px ${t.sm}px`,background:"rgba(43,33,23,0.025)",borderRadius:$.sm},children:[e.jsx(rt,{size:11,color:r.text4}),e.jsxs("div",{style:{flex:1,minWidth:0},children:[e.jsxs("div",{style:{display:"flex",alignItems:"baseline",gap:t.xs},children:[e.jsx("span",{style:{fontFamily:E,fontSize:p.sm,color:r.text2},children:n.name}),e.jsx("span",{style:{fontFamily:E,fontSize:p.xs,color:r.sub},children:n.version}),e.jsxs("span",{style:{fontFamily:z,fontSize:p.xs,color:r.sub},children:["· ",((i=n.skills)==null?void 0:i.length)||0," skill"]})]}),n.description&&e.jsx("div",{style:{fontFamily:z,fontSize:p.xs,color:r.sub,lineHeight:1.4,marginTop:t.xxs,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},title:n.description,children:n.description})]}),e.jsx("button",{onClick:s,title:"卸载",style:{background:"transparent",border:"none",color:r.sub,cursor:"pointer",padding:t.xxs},children:e.jsx(it,{size:11})})]})}function Ye({icon:n,label:s}){return e.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:t.xs,padding:`${t.xxs}px ${t.sm}px`,fontFamily:E,fontSize:p.xs,color:r.text2,background:"rgba(43,33,23,0.04)",borderRadius:$.pill},children:[e.jsx(n,{size:10,color:r.text4}),s]})}function J({label:n,children:s}){return e.jsxs("div",{children:[e.jsx("div",{style:{fontFamily:E,fontSize:p.xs,color:r.sub,textTransform:"uppercase",letterSpacing:"0.05em",marginBottom:t.sm},children:n}),e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:t.xs},children:s})]})}function ce({k:n,v:s}){return e.jsxs("div",{style:{display:"flex",gap:t.md,fontFamily:z,fontSize:p.sm},children:[e.jsx("span",{style:{color:r.sub,minWidth:70},children:n}),e.jsx("span",{style:{color:r.text2,flex:1,wordBreak:"break-word"},children:s})]})}function Dn({projectId:n,sessionId:s,reloadKey:i=0}){const[l,d]=o.useState(null),[f,m]=o.useState(!1),[c,y]=o.useState(null),u=o.useCallback(async()=>{if(!n||!s){d({});return}m(!0),y(null);try{const x=await Nt.read(n);d((x==null?void 0:x.spec)||{})}catch(x){y(x)}finally{m(!1)}},[n,s]);o.useEffect(()=>{u()},[u,i]);const a=Array.isArray(l==null?void 0:l.decisions)?l.decisions:[],w=Array.isArray(l==null?void 0:l.history)?l.history:[];return e.jsxs("div",{style:{padding:t.lg},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:t.md},children:[e.jsxs("div",{style:{fontFamily:E,fontSize:p.sm,fontWeight:500,color:r.text},children:["DECISIONS",e.jsxs("span",{style:{color:r.sub,fontWeight:400,marginLeft:t.sm},children:["(",a.length,")"]})]}),e.jsxs("button",{onClick:u,disabled:f,title:"刷新(agent 调用 record_decision 后会自动刷新;手动按这个也行)",style:{display:"inline-flex",alignItems:"center",gap:t.xs,padding:`${t.xs}px ${t.sm}px`,background:"rgba(43,33,23,0.04)",border:"none",borderRadius:$.sm,cursor:f?"wait":"pointer",fontFamily:z,fontSize:p.sm,color:r.sub},children:[e.jsx(nt,{size:11,style:{animation:f?"rcw-spin 1s linear infinite":"none"}}),f?"...":"刷新"]})]}),c&&e.jsxs("div",{style:{padding:t.md,background:"rgba(220, 53, 69, 0.06)",border:`1px solid ${r.error}33`,borderRadius:$.md,fontFamily:z,fontSize:p.xs,color:r.error,marginBottom:t.md},children:["读取失败:",c.message]}),a.length===0&&!f&&e.jsxs("div",{style:{padding:t.lg,textAlign:"center",fontFamily:z,fontSize:p.sm,color:r.sub,lineHeight:1.6},children:["设计决策现在记在画布的任务便利贴上",e.jsx("br",{}),"(",e.jsx("code",{style:{background:"rgba(43,33,23,0.06)",padding:`1px ${t.xs}px`,borderRadius:$.xs},children:"notes/决策.md"}),", 任务区里那张黄贴纸)。",e.jsx("br",{}),"这里只显示旧会话的存量决策和压缩历史。"]}),a.map((x,v)=>e.jsx(In,{decision:x,index:a.length-v},v)).reverse(),w.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{marginTop:t.xl,marginBottom:t.sm,fontFamily:E,fontSize:p.xs,fontWeight:500,color:r.sub,display:"flex",alignItems:"center",gap:t.xs,letterSpacing:"0.04em"},children:[e.jsx(Ut,{size:11})," COMPACT HISTORY (",w.length,")"]}),w.map((x,v)=>e.jsx(qn,{entry:x},v)).reverse()]}),e.jsx("style",{children:`
12
- @keyframes rcw-spin {
13
- from { transform: rotate(0deg); }
14
- to { transform: rotate(360deg); }
15
- }
16
- `})]})}function In({decision:n}){return e.jsxs("div",{style:{padding:t.md,marginBottom:t.sm,borderRadius:2,background:r.bgWhite,boxShadow:ze.far},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:t.xs,marginBottom:t.xs},children:[e.jsx(Gt,{size:11,color:r.text4}),e.jsx("div",{style:{flex:1,fontFamily:z,fontSize:p.sm,fontWeight:500,color:r.text,lineHeight:1.4},children:n.title||"(no title)"})]}),e.jsx("div",{style:{fontFamily:z,fontSize:p.xs,color:r.text4,lineHeight:1.5,marginBottom:t.xs,whiteSpace:"pre-wrap",wordBreak:"break-word"},children:n.rationale}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:t.sm,fontFamily:E,fontSize:p.xs,color:r.sub},children:[n.scope&&e.jsxs("span",{children:["scope: ",n.scope]}),e.jsx("span",{children:pt(n.ts)})]}),Array.isArray(n.alternatives)&&n.alternatives.length>0&&e.jsxs("details",{style:{marginTop:t.xs},children:[e.jsxs("summary",{style:{fontFamily:E,fontSize:p.xs,color:r.sub,cursor:"pointer"},children:["考虑过的替代 (",n.alternatives.length,")"]}),e.jsx("ul",{style:{margin:`${t.xs}px 0 0 0`,paddingLeft:t.xl,fontFamily:z,fontSize:p.xs,color:r.text4,lineHeight:1.5},children:n.alternatives.map((s,i)=>e.jsx("li",{children:s},i))})]})]})}function qn({entry:n}){var s;return e.jsxs("div",{style:{padding:t.md,marginBottom:t.sm,borderLeft:`2px solid ${r.borderMd}`,paddingLeft:t.md},children:[e.jsxs("div",{style:{fontFamily:E,fontSize:p.xs,color:r.sub,marginBottom:t.xs,letterSpacing:"0.04em"},children:[((s=n.source)==null?void 0:s.toUpperCase())||"COMPACT"," · ",pt(n.ts),n.trigger&&n.trigger!=="auto"&&` · ${n.trigger}`]}),e.jsx("div",{style:{fontFamily:z,fontSize:p.xs,color:r.text4,lineHeight:1.5,whiteSpace:"pre-wrap"},children:n.summary})]})}function pt(n){if(!n)return"";try{return new Date(n).toLocaleString("zh-CN",{month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"})}catch{return n}}function Nn({anchorRef:n,onClose:s,project:i,deckSpec:l,projectId:d,sessionId:f,decisionsReloadKey:m=0,onA11yClick:c,tweaksEnabled:y=null,onTweaksEnabledChange:u=null}){const a=q(j=>j.canvasFont),w=q(j=>j.followAgent),x=q(j=>j.setFollowAgent),v=q(j=>j.setCanvasFont),k=o.useRef(null),[b,L]=o.useState(!1),W=$e(n,360);return o.useEffect(()=>{const j=T=>{var H;k.current&&!k.current.contains(T.target)&&!((H=n==null?void 0:n.current)!=null&&H.contains(T.target))&&(s==null||s())};return window.addEventListener("mousedown",j),()=>window.removeEventListener("mousedown",j)},[s,n]),o.useEffect(()=>{const j=T=>{T.key==="Escape"&&(s==null||s())};return window.addEventListener("keydown",j),()=>window.removeEventListener("keydown",j)},[s]),e.jsxs("div",{ref:k,style:{...W,width:360,background:r.bgWhite,borderRadius:2,boxShadow:"0 2px 4px rgba(0,0,0,0.04), 0 8px 20px rgba(0,0,0,0.08), 0 24px 48px rgba(0,0,0,0.10), inset 0 1px 0 rgba(255,255,255,0.8)",zIndex:60,display:"flex",flexDirection:"column",overflow:"hidden"},children:[e.jsxs("div",{style:{padding:`${t.md}px ${t.lg}px`,display:"flex",alignItems:"center",gap:t.sm,borderBottom:`1px solid ${r.borderLt}`,flexShrink:0},children:[e.jsx(lt,{size:12,color:r.text4}),e.jsx("span",{style:{fontFamily:E,fontSize:p.sm,fontWeight:500,color:r.text},children:"System"})]}),e.jsxs("div",{style:{flex:1,minHeight:0,overflowY:"auto"},children:[c&&e.jsxs("div",{style:{padding:`${t.md}px ${t.lg}px`,borderBottom:`1px solid ${r.borderLt}`,display:"flex",flexDirection:"column",gap:t.sm},children:[e.jsx("div",{style:{fontFamily:E,fontSize:p.xs,color:r.sub,textTransform:"uppercase",letterSpacing:"0.05em"},children:"Canvas 工具"}),e.jsx("div",{style:{display:"flex",gap:t.sm},children:e.jsxs("button",{onClick:()=>{c(),s==null||s()},style:Un,title:"无障碍审查(mock)",children:[e.jsx(Fn,{size:11})," A11y"]})})]}),u&&e.jsxs("div",{style:{padding:`${t.md}px ${t.lg}px`,borderBottom:`1px solid ${r.borderLt}`,display:"flex",alignItems:"center",gap:t.sm},children:[e.jsxs("div",{style:{flex:1,minWidth:0},children:[e.jsx("div",{style:{fontFamily:z,fontSize:p.sm,color:r.text},children:"Tweaks 模式"}),e.jsx("div",{style:{fontFamily:z,fontSize:p.xs,color:r.sub,marginTop:2,lineHeight:1.5},children:y?"开:agent 会主动把核心参数做成控件让你拖":"关:不暴露控件,改样式走对话"})]}),e.jsx(Ze,{checked:!!y,onChange:u})]}),e.jsxs("div",{style:{padding:`${t.md}px ${t.lg}px`,borderBottom:`1px solid ${r.borderLt}`,display:"flex",alignItems:"center",gap:t.sm},children:[e.jsxs("div",{style:{flex:1,minWidth:0},children:[e.jsx("div",{style:{fontFamily:z,fontSize:p.sm,color:r.text},children:"镜头跟随 agent"}),e.jsx("div",{style:{fontFamily:z,fontSize:p.xs,color:r.sub,marginTop:2,lineHeight:1.5},children:w?"开:agent 换到哪个产物,镜头就飞过去(你操作后 8 秒内不抢)":"关:镜头只听你的;agent 在动什么看光圈"})]}),e.jsx(Ze,{checked:w,onChange:x})]}),e.jsxs("div",{style:{padding:`${t.md}px ${t.lg}px`,borderBottom:`1px solid ${r.borderLt}`},children:[e.jsx("div",{style:{fontFamily:z,fontSize:p.sm,color:r.text},children:"画布手写字体"}),e.jsx("div",{style:{fontFamily:z,fontSize:p.xs,color:r.sub,marginTop:2,marginBottom:t.sm},children:"用「文字」工具(T)在画布上写字时用这个"}),e.jsx("div",{style:{display:"flex",gap:t.xs,flexWrap:"wrap"},children:Object.entries(Xt).map(([j,T])=>e.jsx("button",{onClick:()=>v({...a,font:j}),style:{padding:`${t.xs}px ${t.sm}px`,borderRadius:$.md,cursor:"pointer",fontFamily:Kt[j],fontSize:p.sm,border:`1px solid ${a.font===j?r.text:r.borderLt}`,background:a.font===j?r.text:"transparent",color:a.font===j?r.bg:r.text2},children:T},j))}),e.jsx("div",{style:{display:"flex",gap:t.xs,marginTop:t.sm},children:Object.entries(Vt).map(([j,T])=>e.jsx("button",{onClick:()=>v({...a,size:j}),style:{padding:`${t.xs}px ${t.sm}px`,borderRadius:$.md,cursor:"pointer",fontFamily:z,fontSize:p.xs,border:`1px solid ${a.size===j?r.text:r.borderLt}`,background:a.size===j?r.text:"transparent",color:a.size===j?r.bg:r.text2},children:T},j))})]}),e.jsx(Hn,{project:i,deckSpec:l,projectId:d}),e.jsxs("div",{style:{borderTop:`1px solid ${r.borderLt}`,padding:`${t.md}px ${t.lg}px 0`},children:[e.jsxs("button",{onClick:()=>L(j=>!j),style:{display:"flex",alignItems:"center",gap:t.xs,width:"100%",padding:`${t.xs}px 0`,background:"transparent",border:"none",fontFamily:E,fontSize:p.xs,color:r.sub,textTransform:"uppercase",letterSpacing:"0.05em",cursor:"pointer"},children:[e.jsx(ot,{size:11,style:{transform:b?"rotate(90deg)":"rotate(0deg)",transition:"transform 0.12s ease"}}),"项目档案 — Decisions / History"]}),!b&&e.jsx("div",{style:{fontFamily:z,fontSize:p.xs,color:r.sub,padding:`${t.xs}px 0 ${t.md}px ${t.lg}px`,lineHeight:1.5},children:"展开看 agent 记录的设计决策 + compact 摘要历史。"})]}),b&&e.jsx("div",{style:{background:"rgba(0,0,0,0.015)",margin:`0 ${t.lg}px ${t.md}px`,border:`1px solid ${r.borderLt}`,borderRadius:$.md},children:e.jsx(Dn,{projectId:d,sessionId:f,reloadKey:m})})]}),e.jsx("div",{style:{padding:`${t.sm}px ${t.lg}px`,background:r.bgCard,borderTop:`1px solid ${r.borderLt}`,fontFamily:z,fontSize:p.xs,color:r.sub,lineHeight:1.5,flexShrink:0},children:"spec 不可在此编辑 — 改 spec 跟 agent 说,触发新 run。"})]})}function Ze({checked:n,onChange:s,title:i}){return e.jsx("button",{onClick:()=>s==null?void 0:s(!n),title:i,style:{width:28,height:16,padding:0,border:"none",borderRadius:$.lg,background:n?r.text:"rgba(0,0,0,0.18)",position:"relative",cursor:"pointer",transition:"background 0.15s",flexShrink:0},children:e.jsx("span",{style:{position:"absolute",top:2,left:n?14:2,width:12,height:12,borderRadius:$.round,background:r.bgWhite,boxShadow:at.crispSm,transition:"left 0.15s"}})})}const Un={padding:`${t.xs+1}px ${t.md}px`,fontFamily:E,fontSize:p.xs,color:r.text4,background:"rgba(0,0,0,0.04)",border:"none",borderRadius:$.sm,display:"inline-flex",alignItems:"center",gap:t.xs,cursor:"pointer"};function Gn({comments:n=[],iframeDoc:s,iframeRef:i,anchorRef:l,onClose:d,onResolveComment:f,onDeleteComment:m,onSelectAnchor:c}){const y=o.useRef(null),u=$e(l,380);o.useEffect(()=>{const x=v=>{var k;y.current&&!y.current.contains(v.target)&&!((k=l==null?void 0:l.current)!=null&&k.contains(v.target))&&(d==null||d())};return window.addEventListener("mousedown",x),()=>window.removeEventListener("mousedown",x)},[d,l]),o.useEffect(()=>{const x=v=>{v.key==="Escape"&&(d==null||d())};return window.addEventListener("keydown",x),()=>window.removeEventListener("keydown",x)},[d]);const a=o.useMemo(()=>{const x=new Map;for(const k of n){const b=s&&k.anchor?dt(k.anchor,s.body):null,L=b?Yt(b):null,W=(L==null?void 0:L.index)??null;x.has(W)||x.set(W,[]),x.get(W).push({comment:k,el:b})}return[...x.entries()].sort((k,b)=>k[0]===null?1:b[0]===null?-1:k[0]-b[0])},[n,s]),w=x=>{if(x.el)try{x.el.scrollIntoView({behavior:"smooth",block:"center"})}catch{}c&&c(x.comment.anchor)};return e.jsxs("div",{ref:y,style:{...u,width:380,background:r.bgWhite,borderRadius:2,boxShadow:"0 2px 4px rgba(0,0,0,0.04), 0 8px 20px rgba(0,0,0,0.08), 0 24px 48px rgba(0,0,0,0.10), inset 0 1px 0 rgba(255,255,255,0.8)",zIndex:60,display:"flex",flexDirection:"column",overflow:"hidden"},children:[e.jsxs("div",{style:{padding:`${t.md}px ${t.lg}px`,display:"flex",alignItems:"center",gap:t.sm,borderBottom:`1px solid ${r.borderLt}`,flexShrink:0},children:[e.jsx(xt,{size:12,color:r.text4}),e.jsxs("span",{style:{fontFamily:E,fontSize:p.sm,fontWeight:500,color:r.text,flex:1},children:["全部评论 ",n.length>0&&`(${n.length})`]}),e.jsx("button",{onClick:d,title:"关闭",style:{padding:t.xs,color:r.text5,borderRadius:$.xs,background:"transparent",border:"none",cursor:"pointer"},children:e.jsx(ue,{size:12})})]}),e.jsx("div",{style:{flex:1,minHeight:0,overflowY:"auto"},children:n.length===0?e.jsxs("div",{style:{padding:`${t.lg+t.md}px ${t.lg}px`,fontFamily:z,fontSize:p.sm,color:r.sub,textAlign:"center",lineHeight:1.6},children:["还没有评论。",e.jsx("br",{}),"点击画布上任意元素 → 在弹出的浮卡里写评论。"]}):a.map(([x,v])=>e.jsxs("div",{style:{padding:`${t.md}px ${t.lg}px`,borderBottom:`1px solid ${r.borderLt}`},children:[e.jsxs("div",{style:{fontFamily:E,fontSize:p.xs,color:r.sub,textTransform:"uppercase",letterSpacing:"0.05em",marginBottom:t.sm},children:[x===null?"未定位":`第 ${x+1} 页`," · ",v.length," 条"]}),e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:t.xs},children:v.map(({comment:k,el:b})=>e.jsx(Xn,{comment:k,available:!!b,onClick:()=>w({comment:k,el:b}),onResolve:()=>f==null?void 0:f(k.id),onDelete:()=>m==null?void 0:m(k.id)},k.id))})]},x??"orphan"))}),e.jsx("div",{style:{padding:`${t.sm}px ${t.lg}px`,background:r.bgCard,borderTop:`1px solid ${r.borderLt}`,fontFamily:z,fontSize:p.xs,color:r.sub,lineHeight:1.5,flexShrink:0},children:"点击评论 → 跳到对应元素;evaluator 切到 edit 模式后可在浮卡续写。"})]})}function Xn({comment:n,available:s,onClick:i,onResolve:l,onDelete:d}){var m,c,y;const f=n.status==="resolved";return e.jsxs("div",{style:{padding:`${t.sm}px ${t.md}px`,background:r.bgWhite,boxShadow:ze.far,borderRadius:$.md,display:"flex",flexDirection:"column",gap:t.xs,opacity:f?.5:1,cursor:s?"pointer":"default",transition:"background 0.1s"},onClick:s?i:void 0,onMouseEnter:u=>{s&&(u.currentTarget.style.background="rgba(0,0,0,0.02)")},onMouseLeave:u=>{u.currentTarget.style.background=r.bgWhite},children:[e.jsx("div",{style:{fontFamily:z,fontSize:p.sm,color:r.text2,lineHeight:1.5,textDecoration:f?"line-through":"none",whiteSpace:"pre-wrap",wordBreak:"break-word"},children:n.text}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:t.xs,fontFamily:E,fontSize:p.xs,color:r.sub},children:[s?e.jsxs(e.Fragment,{children:[e.jsx(xn,{size:9}),e.jsx("span",{children:((m=n.anchor)==null?void 0:m.dataId)||((y=(c=n.anchor)==null?void 0:c.path)==null?void 0:y.split(">").pop())||"元素"})]}):e.jsx("span",{style:{fontStyle:"italic"},children:"元素已不在"}),e.jsx("span",{style:{flex:1}}),e.jsx("button",{onClick:u=>{u.stopPropagation(),l()},title:f?"取消解决":"标记解决",style:{padding:t.xxs,color:r.sub,borderRadius:$.xs,background:"transparent",border:"none",cursor:"pointer"},children:e.jsx(st,{size:11})}),e.jsx("button",{onClick:u=>{u.stopPropagation(),d()},title:"删除",style:{padding:t.xxs,color:r.sub,borderRadius:$.xs,background:"transparent",border:"none",cursor:"pointer"},children:e.jsx(it,{size:11})})]})]})}function Kn({iframeDoc:n,active:s}){const[i,l]=o.useState([]),[d,f]=o.useState(0);o.useEffect(()=>{if(!s||!n){l([]);return}let c=null;const y=()=>{const a=Array.from(n.querySelectorAll("section[data-page]"));if(l(a),c&&c.disconnect(),!!a.length)try{c=new(n.defaultView||window).IntersectionObserver(w=>{const x=w.filter(k=>k.isIntersecting).sort((k,b)=>b.intersectionRatio-k.intersectionRatio)[0];if(!x)return;const v=a.indexOf(x.target);v>=0&&f(v)},{threshold:[.35,.6]}),a.forEach(w=>c.observe(w))}catch{}};y();let u=null;try{u=new(n.defaultView||window).MutationObserver(()=>y()),n.body&&u.observe(n.body,{childList:!0,subtree:!0})}catch{}return()=>{c==null||c.disconnect(),u==null||u.disconnect()}},[n,s]);const m=o.useCallback(c=>{f(y=>{const u=Math.max(0,Math.min(i.length-1,y+c)),a=i[u];if(a)try{a.scrollIntoView({behavior:"smooth",block:"start"})}catch{}return u})},[i]);return o.useEffect(()=>{if(!s||i.length<2)return;const c=u=>{if(u.key!=="ArrowLeft"&&u.key!=="ArrowRight")return;const a=u.target;a&&(a.tagName==="INPUT"||a.tagName==="TEXTAREA"||a.isContentEditable)||(u.preventDefault(),m(u.key==="ArrowRight"?1:-1))};window.addEventListener("keydown",c);let y=null;try{y=n,y==null||y.addEventListener("keydown",c)}catch{}return()=>{window.removeEventListener("keydown",c);try{y==null||y.removeEventListener("keydown",c)}catch{}}},[s,i.length,m,n]),!s||i.length<2?null:e.jsxs("div",{style:{position:"absolute",bottom:16,left:"50%",transform:"translateX(-50%)",display:"flex",alignItems:"center",gap:t.xxs,background:"rgba(28,24,18,0.86)",borderRadius:$.pill,padding:t.xs,boxShadow:"0 6px 22px rgba(0,0,0,0.22)",zIndex:30,backdropFilter:"blur(6px)"},children:[e.jsx(Ce,{onClick:()=>m(-1),disabled:d===0,icon:Zt,title:"上一页(←)"}),e.jsxs("span",{style:{fontFamily:E,fontSize:p.sm,color:ct.ink,padding:`0 ${t.md}px`,minWidth:52,textAlign:"center",userSelect:"none"},children:[d+1," / ",i.length]}),e.jsx(Ce,{onClick:()=>m(1),disabled:d===i.length-1,icon:ot,title:"下一页(→)"})]})}function Ce({onClick:n,disabled:s,icon:i,title:l}){return e.jsx("button",{onClick:n,disabled:s,title:l,style:{display:"flex",alignItems:"center",justifyContent:"center",width:26,height:26,borderRadius:$.round,border:"none",background:"transparent",color:s?"rgba(232,226,210,0.3)":ct.ink,cursor:s?"default":"pointer",transition:"background 0.15s"},onMouseEnter:d=>{s||(d.currentTarget.style.background="rgba(255,255,255,0.12)")},onMouseLeave:d=>{d.currentTarget.style.background="transparent"},children:e.jsx(i,{size:15})})}function Vn({edits:n=[],onApply:s,onUndo:i,onClearAll:l,canUndo:d=!1,isRunning:f=!1}){const m=n.length;if(m===0)return null;const c=Yn(n);return e.jsxs("div",{style:{position:"absolute",bottom:16,left:"50%",transform:"translateX(-50%)",background:"rgba(45, 36, 24, 0.94)",color:r.btnText,borderRadius:$.lg,padding:`${t.sm}px ${t.lg}px`,display:"flex",alignItems:"center",gap:t.md,fontFamily:E,fontSize:p.xs,boxShadow:"0 8px 32px rgba(0,0,0,0.25), 0 2px 8px rgba(0,0,0,0.18)",zIndex:50,backdropFilter:"blur(8px)",WebkitBackdropFilter:"blur(8px)"},children:[e.jsx("span",{style:{padding:`${t.xxs}px ${t.md}px`,background:"rgba(245, 240, 232, 0.15)",borderRadius:$.xl,fontWeight:600,minWidth:22,textAlign:"center"},children:m}),e.jsxs("span",{style:{color:"#dfd6c6"},children:[c," 待应用"]}),e.jsx("div",{style:{width:1,height:18,background:"rgba(245,240,232,0.2)"}}),e.jsxs("button",{onClick:i,disabled:!d,title:d?"撤销最近一次 (Cmd+Z)":"无可撤销操作",style:{...Qe,opacity:d?1:.4,cursor:d?"pointer":"not-allowed"},children:[e.jsx(Ct,{size:11})," 撤销"]}),e.jsxs("button",{onClick:l,title:"全部撤销 — 把所有 pending 编辑清掉",style:Qe,children:[e.jsx(ue,{size:11})," 全部撤销"]}),e.jsxs("button",{onClick:s,disabled:f,title:f?"agent 正在跑,等当前 run 结束":"让 agent 把这些调整落到源代码",style:{...Zn,opacity:f?.6:1,cursor:f?"wait":"pointer"},children:[e.jsx(Qt,{size:11})," 应用"]})]})}function Yn(n){const s={move:0,style:0,dup:0,del:0};for(const l of n)l.kind==="pending-move"?s.move++:l.kind==="pending-style"?s.style++:l.kind==="pending-duplicate"?s.dup++:l.kind==="pending-delete"&&s.del++;const i=[];return s.move&&i.push(`${s.move} 拖动`),s.dup&&i.push(`${s.dup} 复制`),s.style&&i.push(`${s.style} 样式`),s.del&&i.push(`${s.del} 删除`),i.join(" · ")||"调整"}const Qe={display:"inline-flex",alignItems:"center",gap:t.xs,padding:`${t.xs}px ${t.base}px`,fontFamily:"inherit",fontSize:p.xs,color:r.btnText,background:"transparent",border:"1px solid rgba(245,240,232,0.25)",borderRadius:$.sm},Zn={display:"inline-flex",alignItems:"center",gap:t.xs,padding:"5px 14px",fontFamily:"inherit",fontSize:p.xs,fontWeight:600,color:r.btn,background:r.btnText,border:"none",borderRadius:$.sm,boxShadow:"0 1px 2px rgba(0,0,0,0.15)"},Je=ut.purple,Cn=Jt(ut.purple,.18);function Qn({edits:n=[],iframeRef:s,zoom:i=1}){const[,l]=o.useState(0);o.useEffect(()=>{if(n.length===0)return;const x=s==null?void 0:s.current;if(!x)return;const v=x.contentWindow;if(!v)return;let k=null;const b=()=>{k||(k=requestAnimationFrame(()=>{k=null,l(L=>L+1)}))};try{v.addEventListener("scroll",b,{passive:!0,capture:!0}),v.addEventListener("resize",b),window.addEventListener("resize",b)}catch{}return()=>{try{v.removeEventListener("scroll",b,{capture:!0}),v.removeEventListener("resize",b),window.removeEventListener("resize",b)}catch{}k&&cancelAnimationFrame(k)}},[n.length,s]);const d=o.useMemo(()=>n.filter(x=>(x.kind==="pending-move"||x.kind==="pending-duplicate")&&x.reactMount===!0),[n]);if(d.length===0||!(s!=null&&s.current))return null;const f=s.current,m=f.contentDocument;if(!m)return null;const c=f.getBoundingClientRect(),y=pn(f);if(!y)return null;const u=f.contentWindow,a=(u==null?void 0:u.innerWidth)??c.width/i,w=(u==null?void 0:u.innerHeight)??c.height/i;return e.jsx(e.Fragment,{children:d.map((x,v)=>{var h;const k=dt(x.anchor,m.body);if(!k)return null;const b=k.getBoundingClientRect();if(b.bottom<=0||b.top>=w||b.right<=0||b.left>=a)return null;const{top:L,left:W}=gn(y,b.left,b.top,i),j=b.width*i,T=b.height*i,H=(h=x.aiContext)!=null&&h.targetContainerTag?`${x.aiContext.targetContainerTag}`:"目标容器";return e.jsxs("div",{style:{position:"absolute",top:0,left:0,pointerEvents:"none"},children:[e.jsx("div",{style:{position:"absolute",pointerEvents:"none",top:L-3,left:W-3,width:j+6,height:T+6,border:`2px dashed ${Je}`,borderRadius:$.sm,boxShadow:`0 0 0 3px ${Cn}`,zIndex:9}}),e.jsxs("div",{style:{position:"absolute",pointerEvents:"none",top:L-12,left:W+j-8,transform:"translateX(-100%)",padding:`${t.xxs}px ${t.sm}px`,fontFamily:E,fontSize:p.xs,lineHeight:"14px",fontWeight:500,color:r.bgWhite,background:Je,borderRadius:$.xs,whiteSpace:"nowrap",boxShadow:at.crisp,zIndex:11,maxWidth:Math.max(120,j),overflow:"hidden",textOverflow:"ellipsis"},children:[x.kind==="pending-duplicate"?"复制到":"移到"," <",H,">"]})]},v)})})}const je={"16:9":{w:1920,h:1080},"16:10":{w:1920,h:1200},"9:16":{w:1080,h:1920},"4:3":{w:1440,h:1080}},Se="16:9";function Jn(n){if(!n||typeof n!="string")return Se;const s=n.match(/<div\b[^>]*class\s*=\s*['"][^'"]*__nd-deck-wrap[^'"]*['"][^>]*data-deck-aspect\s*=\s*['"]([^'"]+)['"]/i)||n.match(/<div\b[^>]*data-deck-aspect\s*=\s*['"]([^'"]+)['"][^>]*class\s*=\s*['"][^'"]*__nd-deck-wrap[^'"]*['"]/i);return s&&je[s[1]]?s[1]:Se}function ss({tab:n,onTabChange:s,onClose:i,artifactExports:l=null,onExport:d=null,onToolbarGroups:f=null,title:m="幻灯",htmlSrc:c,htmlContent:y,selectedAnchor:u,onSelectChange:a,onTextEdit:w,onIframeReady:x,candidates:v,activeCandidateId:k,onSelectCandidate:b,onAddCandidate:L,onRemoveCandidate:W,onRenameCandidate:j,project:T,deckSpec:H,projectId:h,sessionId:P,decisionsReloadKey:_,comments:D=[],onAddComment:ee,onResolveComment:X,onDeleteComment:K,onRegionComment:F=null,tweaksAvailable:N=!1,pendingEdits:xe=[],onCommitMove:U,onCommitFreePosition:pe,onSubmitDragNote:gt,lastPendingEditId:ft=null,onApplyPendingEdits:ht,onUndoPending:mt,onClearAllPending:yt,canUndoPending:bt=!1,isStreaming:G=!1}){var Me,Re,Oe,He,_e,De,Ie,qe,Ne,Ue;const{panels:ge,setPanelVisible:wt}=en(),fe=!!((Me=ge==null?void 0:ge.tweaks)!=null&&Me.visible),vt=()=>wt("tweaks",!fe),[V,Ee]=o.useState(!1);o.useEffect(()=>{G&&n==="drag"&&(s==null||s("edit"))},[G,n,s]);const kt=o.useRef(null),[he,jt]=o.useState(!1),[Fe,St]=o.useState(null),[zt,Le]=o.useState(!1),[Y,te]=o.useState("fit"),[Z,$t]=o.useState({width:0,height:0}),[Ae,Et]=o.useState(0),[me,ne]=o.useState(""),[ye,se]=o.useState(!1),[I,Te]=o.useState(null),[be,re]=o.useState(!1),[C,ie]=o.useState(!1),[Q,le]=o.useState(!1),[oe,Pe]=o.useState(!0),O=o.useRef(null),we=o.useRef(null),We=o.useRef(null);o.useEffect(()=>{if(!h||!P)return;let g=!1;return Xe.read(h).then(({config:S})=>{g||S&&typeof S.tweaks_mode_enabled=="boolean"&&Pe(S.tweaks_mode_enabled)}).catch(()=>{}),()=>{g=!0}},[h,P]);const Ft=o.useCallback(g=>{Pe(g),!(!h||!P)&&Xe.patch(h,{tweaks_mode_enabled:g}).catch(()=>{})},[h,P]);o.useEffect(()=>{const g=O.current;if(!g)return;const S=()=>{const M=g.getBoundingClientRect();$t(R=>R.width===M.width&&R.height===M.height?R:{width:M.width,height:M.height})};S();let A=null;try{A=new ResizeObserver(S),A.observe(g)}catch{}return window.addEventListener("resize",S),()=>{A&&A.disconnect(),window.removeEventListener("resize",S)}},[n]);const Be=Jn(me),ae=je[Be]||je[Se],B=Y==="fit"?Z.width>0&&Z.height>0?Math.min(Z.width/ae.w,Z.height/ae.h):1:Y,Lt=v&&v.length>=1;o.useEffect(()=>{se(!1),Te(null)},[k]),o.useEffect(()=>{const g=A=>{var R;if(A.key!=="Escape")return;const M=A.target;((R=M==null?void 0:M.getAttribute)==null?void 0:R.call(M,"contenteditable"))!=="true"&&(C||be||Q||(u?a==null||a(null):i==null||i()))};window.addEventListener("keydown",g);let S=null;try{S=I,S==null||S.addEventListener("keydown",g)}catch{}return()=>{window.removeEventListener("keydown",g);try{S==null||S.removeEventListener("keydown",g)}catch{}}},[u,I,a,i,C,be,Q]),o.useEffect(()=>{const g=S=>{const A=S==null?void 0:S.data;if(!(!A||typeof A!="object")&&A.type==="canvas-page-change"&&Number.isFinite(A.page))try{window.dispatchEvent(new CustomEvent("nd-canvas-page-change",{detail:{page:A.page}}))}catch{}};return window.addEventListener("message",g),()=>window.removeEventListener("message",g)},[]),o.useEffect(()=>{if(!c){ne(y||""),se(!1);return}fetch(c).then(g=>g.text()).then(g=>{ne(g),se(!1)}).catch(()=>ne("<!-- 无法加载源码 -->"))},[c,y,Ae]);const At=g=>{a==null||a((g==null?void 0:g.anchor)||null)},Tt=g=>{w==null||w(g),console.log("[direct edit]",g)},Pt=o.useCallback(g=>{ne(g),se(!0)},[]),Wt=o.useCallback(g=>{try{Te(g.contentDocument)}catch{}x==null||x(g)},[x]),Bt=()=>{Et(g=>g+1),a==null||a(null)},Mt=()=>{re(!1),ie(!1),le(g=>!g)},Rt=()=>{re(!1),le(!1),ie(g=>!g)},ve=Array.isArray(D)?D.filter(g=>g.status!=="resolved").length:0,Ot=o.useMemo(()=>[cn({kind:"deck",exports:l,onExport:d}),{id:"mode",type:"mode",value:n,onChange:g=>{s==null||s(g),a==null||a(null)},items:[{id:"preview",icon:$n,label:"预览",title:"看成品(左右键翻页)"},{id:"edit",icon:tn,label:"编辑",title:"双击文字直接改 · 单击元素弹评论卡"},{id:"drag",icon:nn,label:"拖拽",disabled:G,title:G?"agent 正在跑,拖拽暂停以免和它抢同一份源码":"拖动元素调布局"},{id:"region",icon:En,label:"圈选",disabled:!F,title:F?"框一块地方说事 —— 框住谁、当时长什么样、你想说什么,一起交给 agent":"要先开一个会话才能把圈选交给 agent"},{id:"code",icon:sn,label:"源码",title:"看/改这一份 HTML"}]},n==="drag"&&{id:"dragmode",items:[{id:"free",icon:rn,label:V?"自由":"嵌入",active:V,title:V?"自由摆放 · 松手落到像素位置(P 切回嵌入)":"嵌入 · 松手按 DOM 树插进容器(P 切自由摆放)",onClick:()=>Ee(g=>!g)}]},n!=="code"&&{id:"zoom",items:[{id:"zoomOut",icon:ln,title:"缩小",onClick:()=>te(Math.max(.25,B-.1))},{id:"zoomLevel",label:`${Math.round(B*100)}%`,active:Y==="fit",title:Y==="fit"?"当前自适应窗口":"点一下自适应窗口",onClick:()=>te("fit")},{id:"zoomIn",icon:tt,title:"放大",onClick:()=>te(Math.min(3,B+.1))},{id:"fit",icon:on,title:"自适应窗口",onClick:()=>te("fit")}]},{id:"actions",items:[{id:"tweaks",icon:an,active:fe,disabled:!oe,title:oe?N?"Tweaks:拖控件实时改样式":"Tweaks(agent 还没暴露参数 — 跟它说一句让它 expose_tweaks)":"Tweaks 模式已关(在 System 里开)",onClick:vt},{id:"comment",icon:xt,label:ve>0?String(ve):void 0,active:Q,btnRef:We,title:"这一份上已有的评论",onClick:Mt},{id:"reload",icon:dn,title:"重载(agent 改完没刷新时用)",onClick:Bt},{id:"system",icon:lt,active:C,btnRef:we,title:"System:项目档案 / Tweaks 模式 / A11y",onClick:Rt}]}].filter(Boolean),[n,G,V,Y,B,fe,oe,N,Q,C,ve,F,l,d]);return e.jsxs(un,{kind:"deck",title:m,subtitle:Be,onClose:i,escToClose:!1,groups:Ot,onToolbarGroups:f,headerExtra:Lt?e.jsx(Pn,{candidates:v,activeId:k,onSelect:b,onAdd:L,onRemove:W,onRename:j}):null,children:[(n==="edit"||n==="preview"||n==="drag"||n==="region")&&e.jsxs("div",{ref:O,style:{flex:1,minHeight:0,position:"relative",display:"flex",flexDirection:"column"},children:[e.jsx(Tn,{src:ye?void 0:c,srcDoc:ye?me:c?void 0:y,mode:n==="drag"||n==="region"?"preview":n,onSelect:At,onTextEdit:Tt,onIframeReady:Wt,zoom:B,deckW:ae.w,deckH:ae.h},`${k||"default"}-${Ae}-${ye?"doc":"src"}`),n==="edit"&&u&&e.jsx(fn,{selectedAnchor:u,iframeRef:{current:(Re=O.current)==null?void 0:Re.querySelector("iframe")},zoom:B}),e.jsx(hn,{comments:D,iframeRef:{current:(Oe=O.current)==null?void 0:Oe.querySelector("iframe")},zoom:B,onSelectAnchor:g=>{n!=="edit"&&(s==null||s("edit")),a==null||a(g)}}),e.jsx(Qn,{edits:xe,iframeRef:{current:(He=O.current)==null?void 0:He.querySelector("iframe")},zoom:B}),e.jsx(Kn,{iframeDoc:I,active:n==="preview"}),e.jsx(mn,{active:n==="drag"&&!he,iframeRef:{current:(_e=O.current)==null?void 0:_e.querySelector("iframe")},zoom:B,pickDragSource:yn,isDragging:he}),e.jsx(bn,{active:n==="drag",iframeRef:{current:(De=O.current)==null?void 0:De.querySelector("iframe")},zoom:B,freeMode:V,onFreeModeChange:Ee,apiRef:kt,onDraggingChange:jt,onSelectionChange:g=>{St(g),g&&Le(!0)},onCommitMove:(g,S)=>{var M;if(S.duplicate){const R=(M=S.sourceEl)==null?void 0:M.cloneNode(!0);let Ge=()=>{};if(R&&S.targetContainer){try{R.removeAttribute("data-anchor")}catch{}S.beforeEl&&S.beforeEl.parentNode===S.targetContainer?S.targetContainer.insertBefore(R,S.beforeEl):S.targetContainer.appendChild(R),Ge=()=>{try{R.remove()}catch{}}}U==null||U(g,Ge);return}const A=vn({iframeDoc:I,sourceEl:S.sourceEl,targetContainer:S.targetContainer,beforeEl:S.beforeEl});U==null||U(g,A==null?void 0:A.revert)},onCommitFreePosition:(g,S)=>{const A=wn({sourceEl:S.sourceEl,parentEl:S.parentEl,styleDelta:g.styleDelta,runtimeLocks:g.runtimeLocks,parentNeedsRelative:g.parentNeedsRelative});pe==null||pe(g,A==null?void 0:A.revert)}}),e.jsx(kn,{active:n==="drag"&&zt&&!he&&!!Fe,iframeRef:{current:(Ie=O.current)==null?void 0:Ie.querySelector("iframe")},zoom:B,sourceEl:Fe,hasPendingEditId:!!ft,onSubmit:gt,onDismiss:()=>Le(!1)}),n==="edit"&&u&&I&&e.jsx(jn,{selectedAnchor:u,iframeDoc:I,iframeRef:{current:(qe=O.current)==null?void 0:qe.querySelector("iframe")},iframeRect:Z,zoom:B,comments:D,onClose:()=>a==null?void 0:a(null),onAddComment:ee,onResolveComment:X,onDeleteComment:K}),e.jsx(Sn,{active:n==="region"&&!!F,iframeRef:{current:(Ne=O.current)==null?void 0:Ne.querySelector("iframe")},zoom:B,onSubmit:g=>F==null?void 0:F(g),onExit:()=>s==null?void 0:s("preview")}),e.jsx(Vn,{edits:xe,onApply:ht,onUndo:mt,onClearAll:yt,canUndo:bt,isRunning:G})]}),n==="code"&&e.jsx(zn,{value:me,onChange:Pt,readOnly:!1}),be&&e.jsx(Mn,{anchorRef:we,onClose:()=>re(!1),iframeDoc:I}),C&&e.jsx(Nn,{anchorRef:we,onClose:()=>ie(!1),project:T,deckSpec:H,projectId:h,sessionId:P,decisionsReloadKey:_,onA11yClick:()=>{ie(!1),re(!0)},tweaksEnabled:oe,onTweaksEnabledChange:Ft}),Q&&e.jsx(Gn,{comments:D,iframeDoc:I,iframeRef:{current:(Ue=O.current)==null?void 0:Ue.querySelector("iframe")},anchorRef:We,onClose:()=>le(!1),onResolveComment:X,onDeleteComment:K,onSelectAnchor:g=>{le(!1),n!=="edit"&&(s==null||s("edit")),a==null||a(g)}})]})}export{ss as default};
@@ -1 +0,0 @@
1
- import{ai as o,aj as n}from"./MermaidBlock-DR1GikCv.js";const t=(a,r)=>o.lang.round(n.parse(a)[r]);export{t as c};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-LCL6LL3I-CtXrnUwF.js";import{_ as i}from"./MermaidBlock-DR1GikCv.js";import"./chunk-5VM5RSS4-3-KZ5AUz.js";import"./chunk-XXDRQBXY-BwZ7RbpQ.js";import"./chunk-POPQ4Y6H-dxddZlXt.js";import"./chunk-F27PBJKO-Bkwq2gGU.js";import"./index-GAamh1p4.js";var n={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{n as diagram};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-LCL6LL3I-CtXrnUwF.js";import{_ as i}from"./MermaidBlock-DR1GikCv.js";import"./chunk-5VM5RSS4-3-KZ5AUz.js";import"./chunk-XXDRQBXY-BwZ7RbpQ.js";import"./chunk-POPQ4Y6H-dxddZlXt.js";import"./chunk-F27PBJKO-Bkwq2gGU.js";import"./index-GAamh1p4.js";var n={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{n as diagram};