@windypro-rourou/dsh-eda 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (483) hide show
  1. package/README.md +3 -1
  2. package/lib/capabilities.js +3 -2
  3. package/lib/client.js +576 -452
  4. package/lib/index.js +89 -2
  5. package/package.json +10 -1
  6. package/skill/INDEX.md +10 -8
  7. package/skill/README.md +125 -0
  8. package/skill/README.zh-Hans.md +125 -0
  9. package/skill/SKILL.md +746 -746
  10. package/skill/format/index.md +152 -152
  11. package/skill/format/pcb/3d.md +166 -166
  12. package/skill/format/pcb/attr.md +63 -63
  13. package/skill/format/pcb/common.md +306 -306
  14. package/skill/format/pcb/component.md +132 -132
  15. package/skill/format/pcb/dimension.md +58 -58
  16. package/skill/format/pcb/index.md +17 -17
  17. package/skill/format/pcb/obj.md +43 -43
  18. package/skill/format/pcb/pad_via.md +151 -151
  19. package/skill/format/pcb/panel.md +64 -64
  20. package/skill/format/pcb/partition.md +43 -43
  21. package/skill/format/pcb/primitive.md +196 -196
  22. package/skill/format/pcb/rule.md +71 -71
  23. package/skill/format/pcb/shape.md +441 -441
  24. package/skill/format/pcb/text.md +62 -62
  25. package/skill/format/project/blob.md +30 -30
  26. package/skill/format/project/common.md +42 -42
  27. package/skill/format/project/group.md +62 -62
  28. package/skill/format/project/index.md +12 -12
  29. package/skill/format/project/instance.md +32 -32
  30. package/skill/format/project/meta.md +189 -189
  31. package/skill/format/project/variant.md +30 -30
  32. package/skill/format/schematic/attr.md +41 -41
  33. package/skill/format/schematic/common.md +47 -47
  34. package/skill/format/schematic/component.md +91 -91
  35. package/skill/format/schematic/index.md +14 -14
  36. package/skill/format/schematic/obj.md +41 -41
  37. package/skill/format/schematic/pin.md +59 -59
  38. package/skill/format/schematic/shape.md +231 -231
  39. package/skill/format/schematic/structure.md +53 -53
  40. package/skill/format/schematic/table.md +109 -109
  41. package/skill/format/schematic/text.md +47 -47
  42. package/skill/format/schematic/wire.md +132 -132
  43. package/skill/guide/ancillary-projects/easyeda-api-sdk.md +1 -0
  44. package/skill/guide/ancillary-projects/pro-api-types.md +5 -5
  45. package/skill/guide/ancillary-projects.md +10 -10
  46. package/skill/guide/cli.md +1510 -0
  47. package/skill/guide/error-handling.md +38 -38
  48. package/skill/guide/extension-json.md +135 -135
  49. package/skill/guide/extensions-marketplace.md +61 -61
  50. package/skill/guide/how-to-start.md +316 -301
  51. package/skill/guide/i18n.md +57 -57
  52. package/skill/guide/index.md +7 -7
  53. package/skill/guide/inline-frame.md +20 -20
  54. package/skill/guide/invoke-apis.md +81 -81
  55. package/skill/guide/stability.md +37 -37
  56. package/skill/references/_index.md +471 -398
  57. package/skill/references/_quick-reference.md +3103 -3028
  58. package/skill/references/classes/DMT_Board.md +537 -533
  59. package/skill/references/classes/DMT_EditorControl.md +1736 -1736
  60. package/skill/references/classes/DMT_Event.md +356 -356
  61. package/skill/references/classes/DMT_Folder.md +775 -775
  62. package/skill/references/classes/DMT_Panel.md +531 -531
  63. package/skill/references/classes/DMT_Pcb.md +579 -575
  64. package/skill/references/classes/DMT_Project.md +734 -573
  65. package/skill/references/classes/DMT_Schematic.md +1482 -1477
  66. package/skill/references/classes/DMT_SelectControl.md +96 -96
  67. package/skill/references/classes/DMT_Team.md +172 -172
  68. package/skill/references/classes/DMT_Workspace.md +198 -198
  69. package/skill/references/classes/EDA.md +1001 -961
  70. package/skill/references/classes/IPCB_ComplexPolygon.md +299 -299
  71. package/skill/references/classes/IPCB_Polygon.md +175 -175
  72. package/skill/references/classes/IPCB_PrimitiveArc.md +1901 -1901
  73. package/skill/references/classes/IPCB_PrimitiveAttribute.md +2993 -2993
  74. package/skill/references/classes/IPCB_PrimitiveComponent.md +2624 -2627
  75. package/skill/references/classes/IPCB_PrimitiveComponentPad.md +410 -410
  76. package/skill/references/classes/IPCB_PrimitiveDimension.md +1419 -1419
  77. package/skill/references/classes/IPCB_PrimitiveFill.md +1325 -1325
  78. package/skill/references/classes/IPCB_PrimitiveImage.md +1461 -1461
  79. package/skill/references/classes/IPCB_PrimitiveLine.md +1639 -1639
  80. package/skill/references/classes/IPCB_PrimitiveObject.md +1700 -1700
  81. package/skill/references/classes/IPCB_PrimitivePad.md +3155 -3155
  82. package/skill/references/classes/IPCB_PrimitivePolyline.md +1193 -1193
  83. package/skill/references/classes/IPCB_PrimitivePour.md +1858 -1858
  84. package/skill/references/classes/IPCB_PrimitivePoured.md +556 -556
  85. package/skill/references/classes/IPCB_PrimitiveRegion.md +1332 -1332
  86. package/skill/references/classes/IPCB_PrimitiveString.md +2315 -2315
  87. package/skill/references/classes/IPCB_PrimitiveVia.md +1588 -1588
  88. package/skill/references/classes/ISCH_PrimitiveArc.md +1676 -1676
  89. package/skill/references/classes/ISCH_PrimitiveAttribute.md +2541 -2541
  90. package/skill/references/classes/ISCH_PrimitiveBus.md +973 -973
  91. package/skill/references/classes/ISCH_PrimitiveCbbSymbolComponent.md +260 -260
  92. package/skill/references/classes/ISCH_PrimitiveCircle.md +1392 -1392
  93. package/skill/references/classes/ISCH_PrimitiveComponent.md +2910 -2913
  94. package/skill/references/classes/ISCH_PrimitiveComponentPin.md +155 -155
  95. package/skill/references/classes/ISCH_PrimitiveObject.md +960 -960
  96. package/skill/references/classes/ISCH_PrimitivePin.md +2402 -2402
  97. package/skill/references/classes/ISCH_PrimitivePolygon.md +1028 -1028
  98. package/skill/references/classes/ISCH_PrimitiveRectangle.md +1777 -1777
  99. package/skill/references/classes/ISCH_PrimitiveText.md +1771 -1771
  100. package/skill/references/classes/ISCH_PrimitiveWire.md +973 -973
  101. package/skill/references/classes/LIB_3DModel.md +782 -780
  102. package/skill/references/classes/LIB_Cbb.md +957 -957
  103. package/skill/references/classes/LIB_Classification.md +969 -965
  104. package/skill/references/classes/LIB_Device.md +1222 -1221
  105. package/skill/references/classes/LIB_Footprint.md +1298 -1153
  106. package/skill/references/classes/LIB_LibrariesList.md +361 -329
  107. package/skill/references/classes/LIB_PanelLibrary.md +855 -855
  108. package/skill/references/classes/LIB_SelectControl.md +89 -89
  109. package/skill/references/classes/LIB_SimulationModel.md +807 -821
  110. package/skill/references/classes/LIB_Symbol.md +1341 -1195
  111. package/skill/references/classes/PCB_Document.md +1770 -1754
  112. package/skill/references/classes/PCB_Drc.md +3379 -3375
  113. package/skill/references/classes/PCB_Event.md +1166 -1081
  114. package/skill/references/classes/PCB_ImageTool.md +363 -0
  115. package/skill/references/classes/PCB_Layer.md +1915 -1911
  116. package/skill/references/classes/PCB_ManufactureData.md +2968 -2968
  117. package/skill/references/classes/PCB_MathPolygon.md +916 -785
  118. package/skill/references/classes/PCB_Net.md +1128 -1128
  119. package/skill/references/classes/PCB_Primitive.md +217 -217
  120. package/skill/references/classes/PCB_PrimitiveArc.md +820 -894
  121. package/skill/references/classes/PCB_PrimitiveAttribute.md +635 -717
  122. package/skill/references/classes/PCB_PrimitiveComponent.md +1050 -1050
  123. package/skill/references/classes/PCB_PrimitiveDimension.md +789 -833
  124. package/skill/references/classes/PCB_PrimitiveFill.md +783 -861
  125. package/skill/references/classes/PCB_PrimitiveImage.md +803 -875
  126. package/skill/references/classes/PCB_PrimitiveLine.md +787 -858
  127. package/skill/references/classes/PCB_PrimitiveObject.md +796 -800
  128. package/skill/references/classes/PCB_PrimitivePad.md +947 -944
  129. package/skill/references/classes/PCB_PrimitivePolyline.md +744 -819
  130. package/skill/references/classes/PCB_PrimitivePour.md +808 -845
  131. package/skill/references/classes/PCB_PrimitivePoured.md +363 -363
  132. package/skill/references/classes/PCB_PrimitiveRegion.md +765 -799
  133. package/skill/references/classes/PCB_PrimitiveString.md +828 -910
  134. package/skill/references/classes/PCB_PrimitiveVia.md +761 -765
  135. package/skill/references/classes/PCB_RayTracerEngine.md +603 -263
  136. package/skill/references/classes/PCB_SelectControl.md +495 -495
  137. package/skill/references/classes/PCB_Tool.md +9 -0
  138. package/skill/references/classes/PNL_Document.md +83 -83
  139. package/skill/references/classes/SCH_Document.md +797 -809
  140. package/skill/references/classes/SCH_Drc.md +246 -242
  141. package/skill/references/classes/SCH_Event.md +583 -583
  142. package/skill/references/classes/SCH_ManufactureData.md +1209 -1205
  143. package/skill/references/classes/SCH_Net.md +200 -200
  144. package/skill/references/classes/SCH_Netlist.md +191 -191
  145. package/skill/references/classes/SCH_Primitive.md +337 -337
  146. package/skill/references/classes/SCH_PrimitiveArc.md +686 -692
  147. package/skill/references/classes/SCH_PrimitiveAttribute.md +579 -590
  148. package/skill/references/classes/SCH_PrimitiveBus.md +618 -624
  149. package/skill/references/classes/SCH_PrimitiveCircle.md +667 -683
  150. package/skill/references/classes/SCH_PrimitiveComponent.md +2256 -2240
  151. package/skill/references/classes/SCH_PrimitiveObject.md +666 -666
  152. package/skill/references/classes/SCH_PrimitivePin.md +737 -754
  153. package/skill/references/classes/SCH_PrimitivePolygon.md +621 -627
  154. package/skill/references/classes/SCH_PrimitiveRectangle.md +715 -731
  155. package/skill/references/classes/SCH_PrimitiveText.md +736 -746
  156. package/skill/references/classes/SCH_PrimitiveWire.md +701 -703
  157. package/skill/references/classes/SCH_SelectControl.md +520 -520
  158. package/skill/references/classes/SCH_SimulationEngine.md +133 -133
  159. package/skill/references/classes/SCH_Utils.md +121 -121
  160. package/skill/references/classes/SYS_ClientUrl.md +173 -173
  161. package/skill/references/classes/SYS_Dialog.md +825 -825
  162. package/skill/references/classes/SYS_Environment.md +640 -502
  163. package/skill/references/classes/SYS_ExternalApi.md +246 -0
  164. package/skill/references/classes/SYS_FileManager.md +1664 -1686
  165. package/skill/references/classes/SYS_FileSystem.md +1366 -1171
  166. package/skill/references/classes/SYS_FontManager.md +224 -224
  167. package/skill/references/classes/SYS_FormatConversion.md +349 -349
  168. package/skill/references/classes/SYS_HeaderMenu.md +480 -479
  169. package/skill/references/classes/SYS_Help.md +141 -0
  170. package/skill/references/classes/SYS_I18n.md +861 -861
  171. package/skill/references/classes/SYS_IFrame.md +541 -535
  172. package/skill/references/classes/SYS_LoadingAndProgressBar.md +246 -246
  173. package/skill/references/classes/SYS_Log.md +422 -424
  174. package/skill/references/classes/SYS_Math.md +1565 -1565
  175. package/skill/references/classes/SYS_Message.md +363 -363
  176. package/skill/references/classes/SYS_MessageBox.md +285 -285
  177. package/skill/references/classes/SYS_MessageBus.md +1618 -1618
  178. package/skill/references/classes/SYS_PanelControl.md +696 -696
  179. package/skill/references/classes/SYS_RightClickMenu.md +175 -175
  180. package/skill/references/classes/SYS_Setting.md +134 -85
  181. package/skill/references/classes/SYS_ShortcutKey.md +623 -623
  182. package/skill/references/classes/SYS_Storage.md +484 -484
  183. package/skill/references/classes/SYS_Timer.md +447 -447
  184. package/skill/references/classes/SYS_ToastMessage.md +194 -194
  185. package/skill/references/classes/SYS_Tool.md +317 -241
  186. package/skill/references/classes/SYS_Unit.md +594 -594
  187. package/skill/references/classes/SYS_WebSocket.md +401 -401
  188. package/skill/references/classes/SYS_Window.md +849 -850
  189. package/skill/references/enums/EDMT_EditorDocumentType.md +324 -278
  190. package/skill/references/enums/EDMT_EditorSplitScreenDirection.md +51 -47
  191. package/skill/references/enums/EDMT_EditorTabEventType.md +68 -62
  192. package/skill/references/enums/EDMT_IndicatorMarkerType.md +90 -80
  193. package/skill/references/enums/EDMT_ItemType.md +181 -157
  194. package/skill/references/enums/EDMT_ProjectCollaborationMode.md +51 -47
  195. package/skill/references/enums/EDMT_ProjectFileFormat.md +60 -0
  196. package/skill/references/enums/EDMT_ProjectReadyState.md +82 -0
  197. package/skill/references/enums/ELIB_DeviceJlcLibraryCategory.md +51 -47
  198. package/skill/references/enums/ELIB_LibraryType.md +129 -113
  199. package/skill/references/enums/ELIB_PreviewType.md +77 -69
  200. package/skill/references/enums/ELIB_SimulationModelType.md +51 -47
  201. package/skill/references/enums/ELIB_SymbolType.md +142 -124
  202. package/skill/references/enums/EPCB_AutoRoutingCornerStyle.md +51 -47
  203. package/skill/references/enums/EPCB_AutoRoutingExistingPrimitiveMode.md +51 -47
  204. package/skill/references/enums/EPCB_AutoRoutingOptimization.md +51 -47
  205. package/skill/references/enums/EPCB_DocumentCanvasUpdateCalculationActiveStatus.md +51 -47
  206. package/skill/references/enums/EPCB_DocumentRatlineCalculatingActiveStatus.md +55 -51
  207. package/skill/references/enums/EPCB_InactiveLayerDisplayMode.md +64 -58
  208. package/skill/references/enums/EPCB_LayerColorConfiguration.md +90 -80
  209. package/skill/references/enums/EPCB_LayerId.md +1169 -881
  210. package/skill/references/enums/EPCB_LayerStatus.md +64 -58
  211. package/skill/references/enums/EPCB_LayerType.md +129 -113
  212. package/skill/references/enums/EPCB_MouseEventType.md +64 -58
  213. package/skill/references/enums/EPCB_NetEventType.md +64 -58
  214. package/skill/references/enums/EPCB_PcbPlateType.md +51 -47
  215. package/skill/references/enums/EPCB_PdfOutputMethod.md +64 -58
  216. package/skill/references/enums/EPCB_PrimitiveArcInteractiveMode.md +51 -47
  217. package/skill/references/enums/EPCB_PrimitiveDimensionType.md +64 -58
  218. package/skill/references/enums/EPCB_PrimitiveEventType.md +64 -58
  219. package/skill/references/enums/EPCB_PrimitiveFillMode.md +68 -62
  220. package/skill/references/enums/EPCB_PrimitivePadHeatWeldingConnectionMethod.md +64 -58
  221. package/skill/references/enums/EPCB_PrimitivePadHoleType.md +64 -58
  222. package/skill/references/enums/EPCB_PrimitivePadShapeType.md +90 -80
  223. package/skill/references/enums/EPCB_PrimitivePadType.md +64 -58
  224. package/skill/references/enums/EPCB_PrimitivePourFillMethod.md +64 -58
  225. package/skill/references/enums/EPCB_PrimitiveRegionRuleType.md +107 -95
  226. package/skill/references/enums/EPCB_PrimitiveStringAlignMode.md +142 -124
  227. package/skill/references/enums/EPCB_PrimitiveType.md +233 -201
  228. package/skill/references/enums/EPCB_PrimitiveViaType.md +64 -58
  229. package/skill/references/enums/ESCH_DynamicSimulationEnginePullEventType.md +116 -102
  230. package/skill/references/enums/ESCH_DynamicSimulationEnginePushEventType.md +90 -80
  231. package/skill/references/enums/ESCH_ExportDocumentFileType.md +64 -58
  232. package/skill/references/enums/ESCH_MouseEventType.md +51 -47
  233. package/skill/references/enums/ESCH_PrimitiveComponentType.md +142 -124
  234. package/skill/references/enums/ESCH_PrimitiveEventType.md +77 -69
  235. package/skill/references/enums/ESCH_PrimitiveFillStyle.md +129 -113
  236. package/skill/references/enums/ESCH_PrimitiveLineType.md +77 -69
  237. package/skill/references/enums/ESCH_PrimitivePinShape.md +77 -69
  238. package/skill/references/enums/ESCH_PrimitivePinType.md +168 -146
  239. package/skill/references/enums/ESCH_PrimitiveTextAlignMode.md +142 -124
  240. package/skill/references/enums/ESCH_PrimitiveType.md +207 -179
  241. package/skill/references/enums/ESCH_SimulationNetlistType.md +38 -36
  242. package/skill/references/enums/ESCH_SpiceSimulationEnginePullEventType.md +51 -47
  243. package/skill/references/enums/ESCH_SpiceSimulationEnginePushEventType.md +77 -69
  244. package/skill/references/enums/ESYS_BottomPanelTab.md +94 -80
  245. package/skill/references/enums/ESYS_HeaderMenuEnvironment.md +181 -157
  246. package/skill/references/enums/ESYS_ImportProjectBoardOutlineSource.md +55 -51
  247. package/skill/references/enums/ESYS_ImportProjectImportOption.md +64 -58
  248. package/skill/references/enums/ESYS_ImportProjectSchematicObjectStyle.md +51 -47
  249. package/skill/references/enums/ESYS_ImportProjectViaSolderMaskExpansion.md +55 -51
  250. package/skill/references/enums/ESYS_JobState.md +95 -0
  251. package/skill/references/enums/ESYS_LeftPanelTab.md +94 -80
  252. package/skill/references/enums/ESYS_LogType.md +77 -102
  253. package/skill/references/enums/ESYS_NetlistType.md +129 -113
  254. package/skill/references/enums/ESYS_PanelPosition.md +69 -0
  255. package/skill/references/enums/ESYS_PanelTab.md +368 -0
  256. package/skill/references/enums/ESYS_RightPanelTab.md +237 -201
  257. package/skill/references/enums/ESYS_ShortcutKeyEffectiveEditorRange.md +220 -190
  258. package/skill/references/enums/ESYS_ShortcutKeyEffectiveEditorScene.md +103 -91
  259. package/skill/references/enums/ESYS_StartPageQuickStartItem.md +237 -205
  260. package/skill/references/enums/ESYS_Theme.md +51 -47
  261. package/skill/references/enums/ESYS_ToastMessageType.md +90 -80
  262. package/skill/references/enums/ESYS_Unit.md +116 -102
  263. package/skill/references/enums/ESYS_WindowEventType.md +64 -47
  264. package/skill/references/enums/ESYS_WindowOpenTarget.md +51 -47
  265. package/skill/references/enums/NetportDeviceName.md +146 -146
  266. package/skill/references/enums/SchToolBarDeviceName.md +278 -278
  267. package/skill/references/interfaces/BoardProps.md +169 -169
  268. package/skill/references/interfaces/BorderConfig.md +109 -0
  269. package/skill/references/interfaces/ButtonProps.md +196 -169
  270. package/skill/references/interfaces/CellClickInfo.md +142 -0
  271. package/skill/references/interfaces/CellCoord.md +88 -0
  272. package/skill/references/interfaces/CheckBoxProps.md +223 -196
  273. package/skill/references/interfaces/CheckChangeDetail.md +88 -0
  274. package/skill/references/interfaces/CheckboxEditConfig.md +159 -0
  275. package/skill/references/interfaces/ClipboardCellData.md +142 -0
  276. package/skill/references/interfaces/ClipboardConfig.md +115 -0
  277. package/skill/references/interfaces/ColorPickerProps.md +169 -0
  278. package/skill/references/interfaces/ColumnDef.md +605 -0
  279. package/skill/references/interfaces/ColumnEditTrigger.md +57 -0
  280. package/skill/references/interfaces/ColumnGroupDef.md +192 -0
  281. package/skill/references/interfaces/ColumnResizeConfig.md +142 -0
  282. package/skill/references/interfaces/ComponentPropsMap.md +517 -448
  283. package/skill/references/interfaces/CustomHeaderConfig.md +169 -0
  284. package/skill/references/interfaces/DialogProps.md +385 -385
  285. package/skill/references/interfaces/DragSortConfig.md +115 -0
  286. package/skill/references/interfaces/EditingConfig.md +196 -0
  287. package/skill/references/interfaces/FilteringConfig.md +250 -0
  288. package/skill/references/interfaces/FixedColumnConfig.md +88 -0
  289. package/skill/references/interfaces/FlexItemProps.md +116 -116
  290. package/skill/references/interfaces/FlexProps.md +224 -224
  291. package/skill/references/interfaces/GridItemProps.md +143 -143
  292. package/skill/references/interfaces/GridProps.md +143 -143
  293. package/skill/references/interfaces/IDMT_BoardItem.md +171 -171
  294. package/skill/references/interfaces/IDMT_BriefProjectItem.md +171 -171
  295. package/skill/references/interfaces/IDMT_EditorDocumentItem.md +169 -169
  296. package/skill/references/interfaces/IDMT_EditorSplitScreenItem.md +173 -173
  297. package/skill/references/interfaces/IDMT_EditorTabItem.md +169 -169
  298. package/skill/references/interfaces/IDMT_FolderItem.md +225 -225
  299. package/skill/references/interfaces/IDMT_IndicatorMarkerShape.md +393 -393
  300. package/skill/references/interfaces/IDMT_PanelItem.md +144 -144
  301. package/skill/references/interfaces/IDMT_PcbItem.md +171 -171
  302. package/skill/references/interfaces/IDMT_ProjectItem.md +143 -143
  303. package/skill/references/interfaces/IDMT_SchematicItem.md +225 -225
  304. package/skill/references/interfaces/IDMT_SchematicPageItem.md +198 -198
  305. package/skill/references/interfaces/IDMT_TeamItem.md +144 -144
  306. package/skill/references/interfaces/IDMT_WorkspaceItem.md +117 -117
  307. package/skill/references/interfaces/IDesignPortal.md +103 -103
  308. package/skill/references/interfaces/ILIB_3DModelItem.md +198 -198
  309. package/skill/references/interfaces/ILIB_3DModelSearchItem.md +277 -277
  310. package/skill/references/interfaces/ILIB_CbbItem.md +225 -225
  311. package/skill/references/interfaces/ILIB_CbbSearchItem.md +277 -277
  312. package/skill/references/interfaces/ILIB_ClassificationIndex.md +150 -150
  313. package/skill/references/interfaces/ILIB_ClassificationNode.md +98 -0
  314. package/skill/references/interfaces/ILIB_DeviceAssociationItem.md +210 -210
  315. package/skill/references/interfaces/ILIB_DeviceExtendPropertyItem.md +304 -304
  316. package/skill/references/interfaces/ILIB_DeviceItem.md +279 -279
  317. package/skill/references/interfaces/ILIB_DevicePropertiesForSearch.md +250 -250
  318. package/skill/references/interfaces/ILIB_DeviceSearchItem.md +521 -521
  319. package/skill/references/interfaces/ILIB_ExtendLibrary3DModelFunctions.md +64 -64
  320. package/skill/references/interfaces/ILIB_ExtendLibraryCbbFunctions.md +93 -99
  321. package/skill/references/interfaces/ILIB_ExtendLibraryClassificationIndex.md +150 -150
  322. package/skill/references/interfaces/ILIB_ExtendLibraryDeviceFunctions.md +143 -157
  323. package/skill/references/interfaces/ILIB_ExtendLibraryFootprintFunctions.md +63 -63
  324. package/skill/references/interfaces/ILIB_ExtendLibraryFunctions.md +123 -123
  325. package/skill/references/interfaces/ILIB_ExtendLibraryItem.md +97 -97
  326. package/skill/references/interfaces/ILIB_ExtendLibraryItemIndex.md +98 -98
  327. package/skill/references/interfaces/ILIB_ExtendLibrarySearchProperty.md +115 -115
  328. package/skill/references/interfaces/ILIB_ExtendLibrarySearchResult.md +169 -169
  329. package/skill/references/interfaces/ILIB_ExtendLibrarySearchResultDataLine.md +234 -234
  330. package/skill/references/interfaces/ILIB_ExtendLibrarySymbolFunctions.md +91 -105
  331. package/skill/references/interfaces/ILIB_ExtendLibraryUserIndex.md +96 -96
  332. package/skill/references/interfaces/ILIB_FootprintItem.md +256 -198
  333. package/skill/references/interfaces/ILIB_FootprintPropertiesForSearch.md +61 -61
  334. package/skill/references/interfaces/ILIB_FootprintSearchItem.md +277 -277
  335. package/skill/references/interfaces/ILIB_LibraryInfo.md +92 -92
  336. package/skill/references/interfaces/ILIB_LibraryItem.md +115 -115
  337. package/skill/references/interfaces/ILIB_PanelLibraryItem.md +198 -198
  338. package/skill/references/interfaces/ILIB_PanelLibrarySearchItem.md +277 -277
  339. package/skill/references/interfaces/ILIB_RegisterExtendLibraryProps.md +71 -0
  340. package/skill/references/interfaces/ILIB_SimulationModelItem.md +306 -306
  341. package/skill/references/interfaces/ILIB_SimulationModelSearchItem.md +304 -304
  342. package/skill/references/interfaces/ILIB_SymbolItem.md +306 -279
  343. package/skill/references/interfaces/ILIB_SymbolPropertiesForSearch.md +61 -61
  344. package/skill/references/interfaces/ILIB_SymbolSearchItem.md +304 -304
  345. package/skill/references/interfaces/IPCB_AutoLayoutResult.md +169 -169
  346. package/skill/references/interfaces/IPCB_AutoRoutingProps.md +220 -220
  347. package/skill/references/interfaces/IPCB_AutoRoutingResult.md +169 -169
  348. package/skill/references/interfaces/IPCB_BomPropertiesTableColumns.md +169 -169
  349. package/skill/references/interfaces/IPCB_DifferentialPairItem.md +115 -115
  350. package/skill/references/interfaces/IPCB_DiscretizeOptions.md +65 -65
  351. package/skill/references/interfaces/IPCB_DiscretizedPoint.md +88 -88
  352. package/skill/references/interfaces/IPCB_EqualLengthNetGroupItem.md +115 -115
  353. package/skill/references/interfaces/IPCB_LayerItem.md +277 -277
  354. package/skill/references/interfaces/IPCB_NetClassItem.md +115 -115
  355. package/skill/references/interfaces/IPCB_NetInfo.md +115 -115
  356. package/skill/references/interfaces/IPCB_PadPairGroupItem.md +88 -88
  357. package/skill/references/interfaces/IPCB_PadPairMinWireLengthItem.md +88 -88
  358. package/skill/references/interfaces/IPCB_PhysicalStackingConfiguration.md +115 -115
  359. package/skill/references/interfaces/IPCB_Primitive.md +218 -218
  360. package/skill/references/interfaces/IPCB_PrimitiveAPI.md +174 -175
  361. package/skill/references/interfaces/IPCB_PrimitivePadHeatWelding.md +151 -151
  362. package/skill/references/interfaces/IPCB_PrimitivePouredPourFill.md +142 -142
  363. package/skill/references/interfaces/IPCB_PrimitiveSolderMaskAndPasteMaskExpansion.md +154 -154
  364. package/skill/references/interfaces/IPCB_RayTracerBackgroundConfig.md +223 -0
  365. package/skill/references/interfaces/IPCB_RayTracerLightConfig.md +412 -0
  366. package/skill/references/interfaces/IPCB_RayTracerMaterialConfig.md +547 -0
  367. package/skill/references/interfaces/IPCB_RayTracerPcbMaterialConfig.md +196 -0
  368. package/skill/references/interfaces/IPCB_RayTracerRenderConfigurations.md +200 -0
  369. package/skill/references/interfaces/IPCB_RayTracerRendererConfig.md +196 -0
  370. package/skill/references/interfaces/IPCB_RayTracerSceneElement.md +115 -0
  371. package/skill/references/interfaces/IPCB_RayTracerSceneElementTransform.md +123 -0
  372. package/skill/references/interfaces/IPCB_RayTracerTexture.md +88 -0
  373. package/skill/references/interfaces/IPCB_SubstratePhysicalProperties.md +88 -88
  374. package/skill/references/interfaces/IRawNet.md +103 -103
  375. package/skill/references/interfaces/IRawPureSchematic.md +80 -80
  376. package/skill/references/interfaces/IRawSchematic.md +103 -103
  377. package/skill/references/interfaces/IRawWire.md +149 -149
  378. package/skill/references/interfaces/ISCH_DrcError.md +142 -142
  379. package/skill/references/interfaces/ISCH_DrcErrorPrimitive.md +142 -142
  380. package/skill/references/interfaces/ISCH_ExportPngResolution.md +94 -94
  381. package/skill/references/interfaces/ISCH_NetInfo.md +88 -88
  382. package/skill/references/interfaces/ISCH_Primitive.md +218 -219
  383. package/skill/references/interfaces/ISCH_PrimitiveAPI.md +174 -175
  384. package/skill/references/interfaces/ISCH_ProjectNetInfo.md +142 -142
  385. package/skill/references/interfaces/ISCH_WireInfo.md +169 -169
  386. package/skill/references/interfaces/ISYS_ComparisonResponse.md +115 -0
  387. package/skill/references/interfaces/ISYS_ExtensionExternalApiIndex.md +13 -0
  388. package/skill/references/interfaces/ISYS_ExtensionRegisteredExternalApis.md +13 -0
  389. package/skill/references/interfaces/ISYS_ExternalApiHelp.md +173 -0
  390. package/skill/references/interfaces/ISYS_ExternalApiRegistration.md +146 -0
  391. package/skill/references/interfaces/ISYS_FileSystemFileList.md +169 -169
  392. package/skill/references/interfaces/ISYS_HeaderMenuSub1MenuItem.md +205 -174
  393. package/skill/references/interfaces/ISYS_HeaderMenuSub2MenuItem.md +178 -147
  394. package/skill/references/interfaces/ISYS_HeaderMenuTopMenuItem.md +115 -115
  395. package/skill/references/interfaces/ISYS_HeaderMenus.md +408 -408
  396. package/skill/references/interfaces/ISYS_HelpAudienceEntry.md +92 -0
  397. package/skill/references/interfaces/ISYS_HelpClassSummary.md +205 -0
  398. package/skill/references/interfaces/ISYS_HelpData.md +92 -0
  399. package/skill/references/interfaces/ISYS_HelpMethodDetail.md +310 -0
  400. package/skill/references/interfaces/ISYS_JobHandle.md +65 -0
  401. package/skill/references/interfaces/ISYS_JobLogEntry.md +142 -0
  402. package/skill/references/interfaces/ISYS_JobStatus.md +176 -0
  403. package/skill/references/interfaces/ISYS_LogLine.md +115 -115
  404. package/skill/references/interfaces/ISYS_MathBBox.md +142 -142
  405. package/skill/references/interfaces/ISYS_MathPoint.md +88 -88
  406. package/skill/references/interfaces/ISYS_MathPolygonWithHoles.md +92 -92
  407. package/skill/references/interfaces/ISYS_MessageBusTask.md +115 -115
  408. package/skill/references/interfaces/ISYS_MultilingualLanguagesData.md +12 -12
  409. package/skill/references/interfaces/ISYS_RightClickMenuItem.md +174 -174
  410. package/skill/references/interfaces/ISYS_ShortcutKeyData.md +169 -169
  411. package/skill/references/interfaces/ISYS_ShortcutKeyDataWithCallFn.md +62 -62
  412. package/skill/references/interfaces/ISYS_ShortcutKeyDataWithUserDefinedShortcutKey.md +62 -62
  413. package/skill/references/interfaces/ISYS_WindowEventListenerRemovableObject.md +109 -109
  414. package/skill/references/interfaces/IconProps.md +88 -88
  415. package/skill/references/interfaces/ImageProps.md +115 -115
  416. package/skill/references/interfaces/InputEditConfig.md +182 -0
  417. package/skill/references/interfaces/InputProps.md +547 -520
  418. package/skill/references/interfaces/KeyboardConfig.md +61 -0
  419. package/skill/references/interfaces/ListChildren.md +223 -223
  420. package/skill/references/interfaces/ListProps.md +250 -223
  421. package/skill/references/interfaces/ModalProps.md +358 -358
  422. package/skill/references/interfaces/NumberEditConfig.md +234 -0
  423. package/skill/references/interfaces/RadioGroupProps.md +196 -196
  424. package/skill/references/interfaces/RadioItem.md +115 -115
  425. package/skill/references/interfaces/RichTableProps.md +1357 -0
  426. package/skill/references/interfaces/RowMetaConfig.md +142 -0
  427. package/skill/references/interfaces/ScrollerProps.md +169 -169
  428. package/skill/references/interfaces/SelectEditConfig.md +211 -0
  429. package/skill/references/interfaces/SelectListItem.md +142 -142
  430. package/skill/references/interfaces/SelectOption.md +142 -0
  431. package/skill/references/interfaces/SelectProps.md +169 -169
  432. package/skill/references/interfaces/SelectionConfig.md +358 -0
  433. package/skill/references/interfaces/SliderProps.md +142 -0
  434. package/skill/references/interfaces/SlotProps.md +88 -88
  435. package/skill/references/interfaces/SortState.md +88 -0
  436. package/skill/references/interfaces/SortingConfig.md +169 -0
  437. package/skill/references/interfaces/StyleProps.md +439 -385
  438. package/skill/references/interfaces/TextAreaProps.md +196 -196
  439. package/skill/references/interfaces/TextProps.md +169 -169
  440. package/skill/references/interfaces/TextareaEditConfig.md +182 -0
  441. package/skill/references/interfaces/ValidationRule.md +223 -0
  442. package/skill/references/interfaces/VirtualScrollConfig.md +115 -0
  443. package/skill/references/types/Align.md +9 -0
  444. package/skill/references/types/CellContentType.md +9 -0
  445. package/skill/references/types/ColumnDefOrGroup.md +12 -0
  446. package/skill/references/types/ColumnEditConfig.md +13 -0
  447. package/skill/references/types/ColumnType.md +9 -0
  448. package/skill/references/types/DataChangeType.md +9 -0
  449. package/skill/references/types/FilterMatchMode.md +9 -0
  450. package/skill/references/types/RichTableRow.md +12 -0
  451. package/skill/references/types/Serializable.md +10 -0
  452. package/skill/references/types/SerializablePrimitive.md +9 -0
  453. package/skill/references/types/SortOrder.md +9 -0
  454. package/skill/references/types/TPCB_LayerTypesOfInnerLayer.md +11 -11
  455. package/skill/references/types/TPCB_LayersInTheSelectable.md +42 -42
  456. package/skill/references/types/TPCB_LayersOfComponent.md +11 -11
  457. package/skill/references/types/TPCB_LayersOfCopper.md +15 -15
  458. package/skill/references/types/TPCB_LayersOfCustom.md +41 -41
  459. package/skill/references/types/TPCB_LayersOfDimension.md +16 -16
  460. package/skill/references/types/TPCB_LayersOfFill.md +28 -28
  461. package/skill/references/types/TPCB_LayersOfImage.md +22 -22
  462. package/skill/references/types/TPCB_LayersOfInner.md +41 -41
  463. package/skill/references/types/TPCB_LayersOfLine.md +25 -25
  464. package/skill/references/types/TPCB_LayersOfObject.md +12 -12
  465. package/skill/references/types/TPCB_LayersOfPad.md +11 -11
  466. package/skill/references/types/TPCB_LayersOfRegion.md +11 -11
  467. package/skill/references/types/TPCB_NumberOfCopperLayers.md +9 -9
  468. package/skill/references/types/TPCB_PolygonSourceArray.md +85 -83
  469. package/skill/references/types/TPCB_PrimitiveDimensionCoordinateSet.md +66 -66
  470. package/skill/references/types/TPCB_PrimitivePadHole.md +30 -30
  471. package/skill/references/types/TPCB_PrimitivePadShape.md +61 -61
  472. package/skill/references/types/TPCB_PrimitiveSpecialPadShape.md +19 -19
  473. package/skill/references/types/TSYS_ComparisonErrorCode.md +15 -0
  474. package/skill/references/types/TSYS_LanguageKeyValuePairs.md +13 -0
  475. package/skill/references/types/TSYS_MathPolygonGroup.md +15 -15
  476. package/skill/references/types/TSYS_MathPolygonInput.md +20 -20
  477. package/skill/references/types/TSYS_ShortcutKeys.md +96 -96
  478. package/skill/user-guide/using-extension.md +47 -47
  479. package/src/json-gen.test.js +430 -0
  480. package/skill/guide/ancillary-projects/pro-api-sdk.md +0 -1
  481. package/skill/references/interfaces/ISYS_PcbComparisonResponse.md +0 -115
  482. package/skill/references/types/ISYS_LanguageKeyValuePairs.md +0 -13
  483. package/skill/references/types/TSYS_PcbComparisonErrorCode.md +0 -10
package/lib/client.js CHANGED
@@ -1,189 +1,252 @@
1
1
  /**
2
- * dsh-lichuang-eda — browser half. Runs inside the dsh web GUI.
2
+ * dsh-lichuang-eda — browser half (DSH 0.1.x / 0.2 desktop adapted).
3
3
  *
4
- * 平台仪表盘 + 监看器(生成在对话里由 agent 驱动官方 eda.* API 完成):
5
- * - header(品牌 + 状态版本)
6
- * - 连接卡:状态 + 一键动作(装/启/打开编辑器/扩展直达)
7
- * - 连接教程(可折叠,默认收起,精简步骤)
8
- * - 活动监视(主体):当前会话 agent 对官方 API 的实时调用流(动作/耗时/结果)
9
- * - 离线导出(底部小结):仅兜底,导出可导入的标准版 JSON
4
+ * Design read: a technical side-panel for the shell's overlay layer — dark-first,
5
+ * editorial and restrained, wearing the host's own tokens + UI primitives so it
6
+ * reads as native chrome rather than a bolted-on widget.
10
7
  *
11
- * Bundle format: `window.__ModuleLoader__.load({id, factory})` (lazy CJS) —
12
- * the only client bundle format the web shell materializes. The apply/inject
13
- * export shape and ctx.effect disposer follow the DSH client-bundle contract.
8
+ * 0.2 adaptation (the "挡到" fix):
9
+ * - the panel is registered into the `shell.overlay` SLOT (position:absolute,
10
+ * z-index 30) instead of a fixed body overlay with a 9999 z-index — it no
11
+ * longer covers the conversation, other panels, or the desktop chrome;
12
+ * - the entry point is a `conversation.session.header.utilities` pill (0.2's
13
+ * left sidebar is slot-owned); the 0.1.x sidebar DOM entry is kept as a
14
+ * compatibility path and the two never fight;
15
+ * - the panel is drag-resizable (120–760px, persisted) and follows the host
16
+ * theme through `--dsw-alias-*` tokens.
17
+ *
18
+ * Bundle format: `window.__ModuleLoader__.load({id, factory})` (lazy CJS).
14
19
  */
15
20
  window.__ModuleLoader__.load({
16
21
  id: "@windypro-rourou/dsh-eda",
17
22
  factory: (require) => {
18
23
  var module = { exports: {} };
19
24
  var exports = module.exports;
25
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
20
26
 
21
- const { createElement: h, useEffect, useState } = require("react");
27
+ const React = require("react");
28
+ const { createElement: h, useEffect, useMemo, useRef, useState } = React;
22
29
  const { createRoot } = require("react-dom/client");
23
30
 
31
+ // ── host UI kit (same components the native chrome uses); degrade to our
32
+ // own token-based markup when a build does not ship it. ────────────────
33
+ let P = null;
34
+ try { P = require("@deepseek-ai/dsh-client-ui-primitives"); } catch (e) { P = null; }
35
+ const dsButton = P && P.Button ? P.Button : null;
36
+ const dsPill = P && P.Pill ? P.Pill : null;
37
+ const dsTooltip = P && P.Tooltip ? P.Tooltip : null;
38
+ const dsIcon = (name) => (P && P[name] ? P[name] : null);
39
+
24
40
  //#region styles
41
+ /**
42
+ * Token-first styling: every colour comes from `--dsw-alias-*` with a
43
+ * dark-first fallback, so the panel inherits light/dark from the shell.
44
+ * Reused accent = one blue; no gradients, no heavy shadows (taste rule:
45
+ * restraint over decoration).
46
+ */
25
47
  const STYLE = `
26
- [data-dsh-eda-entry] {
27
- display: flex; align-items: center; gap: 8px; width: 100%;
28
- padding: 9px 12px; margin: 2px 0; border: 0; border-radius: 8px;
29
- background: transparent; color: inherit; font: inherit; cursor: pointer; text-align: left;
48
+ .dsh-eda-root {
49
+ --eda-bg: var(--dsw-alias-bg-layer-1, #151922);
50
+ --eda-bg-base: var(--dsw-alias-bg-base, #0f1115);
51
+ --eda-bg-soft: var(--dsw-alias-bg-layer-2, #1a1f2b);
52
+ --eda-fg: var(--dsw-alias-label-primary, #d7dde6);
53
+ --eda-fg-2: var(--dsw-alias-label-secondary, #b6bdc9);
54
+ --eda-fg-3: var(--dsw-alias-label-tertiary, #8b93a3);
55
+ --eda-line: var(--dsw-alias-border-l1, #262a33);
56
+ --eda-line-soft: var(--dsw-alias-border-l2, rgba(255,255,255,.06));
57
+ --eda-accent: #4c8dff;
58
+ --eda-ok: var(--dsw-alias-state-success-primary, #22c55e);
59
+ --eda-warn: var(--dsw-alias-state-warn-primary, #eab308);
60
+ --eda-err: var(--dsw-alias-state-error-primary, #ef4444);
61
+ --eda-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
62
+ --eda-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "Microsoft YaHei", system-ui, sans-serif;
63
+
64
+ position: absolute; top: 0; right: 0; bottom: 0;
65
+ width: var(--eda-w, 400px); max-width: 96vw;
66
+ display: flex; flex-direction: column; min-height: 0;
67
+ background: var(--eda-bg); color: var(--eda-fg);
68
+ border-left: 1px solid var(--eda-line);
69
+ font: 13px/1.55 var(--eda-sans);
70
+ font-variant-numeric: tabular-nums;
71
+ z-index: 30;
72
+ box-shadow: -14px 0 40px rgba(0,0,0,.22);
73
+ animation: edaIn .16s cubic-bezier(.22,.61,.36,1);
30
74
  }
75
+ .dsh-eda-root[hidden] { display: none !important; }
76
+ @keyframes edaIn { from { transform: translateX(14px); opacity: 0; } to { transform: none; opacity: 1; } }
77
+ @media (prefers-reduced-motion: reduce) { .dsh-eda-root { animation: none; } }
78
+
79
+ .dsh-eda-grip { position: absolute; left: -3px; top: 0; bottom: 0; width: 7px; cursor: col-resize; z-index: 6; }
80
+ .dsh-eda-grip:hover { background: linear-gradient(90deg, transparent, rgba(76,141,255,.35)); }
81
+
82
+ /* top bar — sticky, quiet, 48px */
83
+ .eda-top { flex: none; height: 48px; display: flex; align-items: center; gap: 10px; padding: 0 12px 0 14px;
84
+ border-bottom: 1px solid var(--eda-line); background: var(--eda-bg); }
85
+ .eda-mark { flex: none; width: 24px; height: 24px; border-radius: 7px; display: grid; place-items: center;
86
+ color: #fff; background: linear-gradient(160deg, #3b7bf6, #2b5fd0); font-size: 11px; font-weight: 700; letter-spacing: .02em; }
87
+ .eda-title { min-width: 0; flex: 1; }
88
+ .eda-title b { display: block; font-size: 13px; font-weight: 600; letter-spacing: .01em; }
89
+ .eda-title span { display: block; font-size: 10.5px; color: var(--eda-fg-3); font-family: var(--eda-mono); }
90
+ .eda-iconbtn { flex: none; width: 26px; height: 26px; display: grid; place-items: center; border-radius: 7px;
91
+ border: 1px solid transparent; background: transparent; color: var(--eda-fg-3); cursor: pointer; font-size: 12px; line-height: 1; }
92
+ .eda-iconbtn:hover { color: var(--eda-fg); background: var(--dsw-alias-interactive-bg-hover, rgba(128,128,128,.12)); }
93
+
94
+ .eda-scroll { flex: 1 1 0; min-height: 0; overflow-y: auto; padding: 14px 14px 18px;
95
+ display: flex; flex-direction: column; gap: 12px; scrollbar-width: thin; }
96
+ .eda-scroll::-webkit-scrollbar { width: 9px; }
97
+ .eda-scroll::-webkit-scrollbar-thumb { background: var(--eda-line); border-radius: 9px; border: 2px solid transparent; background-clip: content-box; }
98
+
99
+ .eda-card { border: 1px solid var(--eda-line); border-radius: 10px; background: var(--eda-bg-soft); padding: 12px 13px; }
100
+ .eda-card-title { font-size: 10.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
101
+ color: var(--eda-fg-3); margin: 0 0 10px; }
102
+ .eda-note { font-size: 11.5px; color: var(--eda-fg-2); margin: 9px 0 0; line-height: 1.6; }
103
+ .eda-muted { font-size: 11px; color: var(--eda-fg-3); }
104
+ .eda-mono { font-family: var(--eda-mono); }
105
+
106
+ /* status row */
107
+ .eda-state { display: flex; align-items: center; gap: 9px; }
108
+ .eda-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--eda-fg-3); }
109
+ .eda-dot.on { background: var(--eda-ok); box-shadow: 0 0 0 3px rgba(34,197,94,.16); }
110
+ .eda-dot.off { background: var(--eda-warn); }
111
+ .eda-dot.wait { background: var(--eda-fg-3); animation: edaPulse 1.3s ease-in-out infinite; }
112
+ @keyframes edaPulse { 0%,100% { opacity: .4 } 50% { opacity: 1 } }
113
+ .eda-state b { font-size: 12.5px; font-weight: 600; }
114
+ .eda-state small { font-family: var(--eda-mono); font-size: 10.5px; color: var(--eda-fg-3); margin-left: 7px; }
115
+
116
+ .eda-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; margin-top: 11px; }
117
+ .eda-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px;
118
+ border: 1px solid var(--eda-line); border-radius: 8px; padding: 5px 11px; background: transparent;
119
+ color: var(--eda-fg); font: inherit; font-size: 11.5px; font-weight: 600; cursor: pointer;
120
+ transition: background .12s ease, border-color .12s ease, opacity .12s ease; }
121
+ .eda-btn:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover, rgba(128,128,128,.12)); }
122
+ .eda-btn:disabled { opacity: .45; cursor: default; }
123
+ .eda-btn.primary { background: var(--eda-accent); border-color: transparent; color: #fff; }
124
+ .eda-btn.primary:hover:not(:disabled) { background: #3f80f5; }
125
+ .eda-btn.big { width: 100%; padding: 8px 12px; font-size: 12.5px; }
126
+ .eda-btn.tiny { padding: 2px 8px; font-size: 10.5px; font-weight: 500; }
127
+ .eda-link { color: var(--eda-accent); text-decoration: none; font-size: 11.5px; }
128
+ .eda-link:hover { text-decoration: underline; }
129
+
130
+ /* connected CTA */
131
+ .eda-cta { display: flex; align-items: center; gap: 10px; margin-top: 11px; padding: 9px 11px;
132
+ border: 1px solid color-mix(in srgb, var(--eda-accent) 34%, transparent); border-radius: 9px;
133
+ background: color-mix(in srgb, var(--eda-accent) 8%, transparent); cursor: pointer; }
134
+ .eda-cta:hover { background: color-mix(in srgb, var(--eda-accent) 13%, transparent); }
135
+ .eda-cta-t { min-width: 0; flex: 1; }
136
+ .eda-cta-t i { display: block; font-style: normal; font-size: 10px; color: var(--eda-fg-3); letter-spacing: .04em; }
137
+ .eda-cta-t b { font-size: 12.5px; font-weight: 600; color: var(--eda-accent); }
138
+ .eda-cta-c { flex: none; font-size: 10.5px; color: var(--eda-fg-3); }
139
+ .eda-cta.ok .eda-cta-c { color: var(--eda-ok); }
140
+
141
+ /* guide */
142
+ .eda-steps { display: flex; flex-direction: column; gap: 10px; }
143
+ .eda-step { display: flex; gap: 10px; }
144
+ .eda-step-no { flex: none; width: 18px; height: 18px; border-radius: 50%; display: grid; place-items: center;
145
+ font-family: var(--eda-mono); font-size: 10px; color: var(--eda-fg-3); border: 1px solid var(--eda-line); margin-top: 1px; }
146
+ .eda-step b { display: block; font-size: 12px; font-weight: 600; }
147
+ .eda-step p { margin: 2px 0 0; font-size: 11px; color: var(--eda-fg-3); line-height: 1.55; }
148
+
149
+ /* timeline */
150
+ .eda-tl-head { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
151
+ .eda-tl-head .eda-card-title { flex: 1; margin: 0; }
152
+ .eda-select { font: inherit; font-size: 10.5px; font-family: var(--eda-mono); color: var(--eda-fg-2);
153
+ background: var(--eda-bg-base); border: 1px solid var(--eda-line); border-radius: 6px; padding: 2px 5px; max-width: 132px; }
154
+ .eda-tl { position: relative; margin: 6px 0 0; }
155
+ .eda-row { position: relative; display: flex; gap: 10px; padding: 8px 0 8px 2px; cursor: pointer;
156
+ border-bottom: 1px solid var(--eda-line-soft); }
157
+ .eda-row:last-child { border-bottom: 0; }
158
+ .eda-row:hover { background: color-mix(in srgb, var(--eda-fg) 4%, transparent); }
159
+ .eda-row-dot { flex: none; width: 7px; height: 7px; margin-top: 6px; border-radius: 50%; background: var(--eda-fg-3); position: relative; z-index: 1; }
160
+ .eda-row.ok .eda-row-dot { background: var(--eda-ok); }
161
+ .eda-row.err .eda-row-dot { background: var(--eda-err); }
162
+ .eda-row.pend .eda-row-dot { background: var(--eda-warn); animation: edaPulse 1s ease-in-out infinite; }
163
+ .eda-row-body { min-width: 0; flex: 1; }
164
+ .eda-row-line { display: flex; align-items: baseline; gap: 8px; }
165
+ .eda-seq { flex: none; font-family: var(--eda-mono); font-size: 10px; color: var(--eda-fg-3); }
166
+ .eda-row-name { flex: 1; min-width: 0; font-size: 12.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
167
+ .eda-row-meta { flex: none; font-family: var(--eda-mono); font-size: 10px; color: var(--eda-fg-3); }
168
+ .eda-row-meta .eda-pend { color: var(--eda-warn); }
169
+ .eda-row-code, .eda-row-out { margin-top: 3px; font-family: var(--eda-mono); font-size: 10.5px; color: var(--eda-fg-3);
170
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
171
+ .eda-row-out.err { color: var(--eda-err); }
172
+ .eda-row-full { margin-top: 7px; padding: 8px 9px; border-radius: 8px; background: var(--eda-bg-base);
173
+ border: 1px solid var(--eda-line-soft); font-family: var(--eda-mono); font-size: 10.5px; line-height: 1.6;
174
+ color: var(--eda-fg-2); white-space: pre-wrap; word-break: break-word; max-height: 260px; overflow: auto; }
175
+ .eda-row-full i { display: block; font-style: normal; font-size: 9.5px; letter-spacing: .08em; text-transform: uppercase;
176
+ color: var(--eda-fg-3); margin: 6px 0 2px; }
177
+ .eda-row-full i:first-child { margin-top: 0; }
178
+ .eda-empty { font-size: 11.5px; color: var(--eda-fg-3); line-height: 1.6; }
179
+ .eda-hints { margin-top: 9px; display: flex; flex-direction: column; gap: 5px; }
180
+ .eda-hint { display: flex; gap: 7px; font-size: 11px; color: var(--eda-fg-2); }
181
+ .eda-hint s { text-decoration: none; color: var(--eda-fg-3); }
182
+ .eda-tl-foot { margin-top: 7px; font-size: 10.5px; color: var(--eda-fg-3); }
183
+
184
+ .eda-foot { flex: none; padding: 9px 14px; border-top: 1px solid var(--eda-line);
185
+ font-family: var(--eda-mono); font-size: 10px; color: var(--eda-fg-3); text-align: center; }
186
+
187
+ /* header pill (0.2 entry point) */
188
+ .eda-pill { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 9px;
189
+ border: 1px solid var(--eda-line); border-radius: 999px; background: transparent; color: inherit;
190
+ font: inherit; font-size: 11.5px; cursor: pointer; transition: background .12s ease; }
191
+ .eda-pill:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(128,128,128,.12)); }
192
+ .eda-pill[data-active="true"] { border-color: color-mix(in srgb, var(--eda-accent) 46%, transparent);
193
+ background: color-mix(in srgb, var(--eda-accent) 12%, transparent); }
194
+ .eda-pill .eda-dot { width: 6px; height: 6px; }
195
+ .eda-pill[hidden] { display: none !important; }
196
+
197
+ /* update hint (top bar) — one quiet warning-tinted pill, click to copy */
198
+ .eda-update { flex: none; display: inline-flex; align-items: center; gap: 4px; height: 22px; padding: 0 8px;
199
+ border: 1px solid color-mix(in srgb, var(--eda-warn) 42%, transparent); border-radius: 999px;
200
+ background: color-mix(in srgb, var(--eda-warn) 10%, transparent); color: var(--eda-warn);
201
+ font: inherit; font-size: 10.5px; font-weight: 600; cursor: pointer; white-space: nowrap; }
202
+ .eda-update:hover { background: color-mix(in srgb, var(--eda-warn) 18%, transparent); }
203
+
204
+ /* 0.1.x sidebar entry */
205
+ [data-dsh-eda-entry] { display: flex; align-items: center; gap: 8px; width: 100%; padding: 9px 12px; margin: 2px 0;
206
+ border: 0; border-radius: 8px; background: transparent; color: inherit; font: inherit; cursor: pointer; text-align: left; }
31
207
  [data-dsh-eda-entry]:hover { background: rgba(128,128,128,.14); }
32
208
  [data-dsh-eda-entry][data-active] { background: rgba(128,128,128,.22); }
33
- [data-dsh-eda-entry] .eda-entry-icon { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; flex: none; }
34
209
  [data-dsh-eda-entry] .eda-entry-label { font-size: 13px; line-height: 1.2; opacity: .92; }
35
-
36
- .dsh-eda-view { position: fixed; top: 0; right: 0; bottom: 0; width: min(420px, 94vw); z-index: 9999; }
37
- .dsh-eda-view[hidden] { display: none !important; }
38
- .dsh-eda-panel {
39
- position: absolute; inset: 0; background: light-dark(#fbfbfc, #121417);
40
- color: light-dark(#1c1f24, #e3e6ea);
41
- border-left: 1px solid light-dark(rgba(0,0,0,.09), rgba(255,255,255,.10));
42
- font: 13px/1.6 -apple-system, "Segoe UI", "Microsoft YaHei", system-ui, sans-serif;
43
- color-scheme: light dark;
44
- display: flex; flex-direction: column;
45
- }
46
- .eda-panel { display: flex; flex-direction: column; height: 100%; min-height: 0; }
47
-
48
- .eda-head {
49
- flex: none; display: flex; align-items: center; gap: 10px;
50
- padding: 13px 16px; border-bottom: 1px solid light-dark(rgba(0,0,0,.08), rgba(255,255,255,.09));
51
- }
52
- .eda-head .eda-mark { width: 26px; height: 26px; border-radius: 6px; flex: none; background: #2563eb; color: #fff; display: grid; place-items: center; font-size: 12px; font-weight: 700; }
53
- .eda-head .eda-tt { min-width: 0; flex: 1; }
54
- .eda-head h1 { font-size: 14px; font-weight: 700; margin: 0; line-height: 1.3; }
55
- .eda-head .eda-sub { font-size: 11px; opacity: .55; margin: 0; }
56
- .eda-close { border: 0; background: transparent; color: inherit; cursor: pointer; font-size: 15px; line-height: 1; padding: 5px 8px; border-radius: 6px; opacity: .6; }
57
- .eda-close:hover { opacity: 1; background: light-dark(rgba(0,0,0,.06), rgba(255,255,255,.08)); }
58
-
59
- .eda-scroll { flex: 1 1 0; min-height: 0; overflow-y: auto; padding: 13px 16px 18px; display: flex; flex-direction: column; gap: 12px; }
60
-
61
- .eda-card { border: 1px solid light-dark(rgba(0,0,0,.09), rgba(255,255,255,.10)); border-radius: 10px; padding: 12px 14px; background: light-dark(#ffffff, #17191d); }
62
- .eda-card-title { font-size: 12px; font-weight: 600; opacity: .75; margin: 0 0 8px; }
63
-
64
- .eda-note { font-size: 11.5px; opacity: .62; margin: 8px 0 0; line-height: 1.6; }
65
- .eda-muted { font-size: 11px; opacity: .5; }
66
-
67
- .eda-status { display: flex; align-items: center; gap: 8px; }
68
- .eda-status .eda-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
69
- .eda-status .eda-dot.on { background: #16a34a; }
70
- .eda-status .eda-dot.off { background: #d97706; }
71
- .eda-status .eda-dot.wait { background: #9ca3af; animation: edaPulse 1.2s ease-in-out infinite; }
72
- .eda-status .eda-txt { font-size: 13px; font-weight: 600; }
73
- .eda-status .eda-txt small { font-weight: 400; opacity: .55; margin-left: 6px; }
74
- @keyframes edaPulse { 0%,100% { opacity: .45; } 50% { opacity: 1; } }
75
-
76
- .eda-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
77
- .eda-btn {
78
- display: inline-flex; align-items: center; justify-content: center; gap: 6px;
79
- border: 1px solid transparent; border-radius: 8px; padding: 6px 12px;
80
- font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
81
- transition: background .12s ease, border-color .12s ease;
82
- }
83
- .eda-btn.primary { background: #2563eb; color: #fff; }
84
- .eda-btn.primary:hover { background: #1d4ed8; }
85
- .eda-btn.primary:disabled { opacity: .5; cursor: default; }
86
- .eda-btn.ghost { background: transparent; border-color: light-dark(rgba(0,0,0,.14), rgba(255,255,255,.16)); color: inherit; }
87
- .eda-btn.ghost:hover { background: light-dark(rgba(0,0,0,.04), rgba(255,255,255,.06)); }
88
- .eda-btn.ghost:disabled { opacity: .45; cursor: default; }
89
- .eda-btn.big { width: 100%; padding: 8px 13px; font-size: 13px; }
90
- .eda-link { color: #2563eb; text-decoration: none; font-size: 12px; }
91
- .eda-link:hover { text-decoration: underline; }
92
-
93
- /* connect wizard (collapsed by default, compact) */
94
- .eda-steps { display: flex; flex-direction: column; gap: 9px; margin-top: 2px; }
95
- .eda-step { display: flex; gap: 9px; }
96
- .eda-step .eda-step-no { width: 19px; height: 19px; flex: none; border-radius: 50%; display: grid; place-items: center; font-size: 10.5px; font-weight: 700; background: light-dark(#eef2f7, #24272c); opacity: .85; }
97
- .eda-step .eda-step-body { min-width: 0; flex: 1; }
98
- .eda-step .eda-step-name { font-size: 12.5px; font-weight: 600; }
99
- .eda-step .eda-step-hint { font-size: 11px; opacity: .58; margin-top: 1px; line-height: 1.5; }
100
- .eda-step .eda-step-action { margin-top: 5px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
101
- .eda-step .eda-step-result { font-size: 11.5px; opacity: .7; }
102
-
103
- /* activity monitor (main) */
104
- .eda-act { display: flex; flex-direction: column; gap: 0; }
105
- .eda-act-item { display: flex; gap: 9px; padding: 9px 0; border-bottom: 1px solid light-dark(rgba(0,0,0,.05), rgba(255,255,255,.06)); cursor: pointer; }
106
- .eda-act-item:hover { background: light-dark(rgba(0,0,0,.03), rgba(255,255,255,.03)); }
107
- .eda-act-item:last-child { border-bottom: 0; }
108
- .eda-act-item .eda-act-dot { flex: none; margin-top: 5px; width: 7px; height: 7px; border-radius: 50%; background: #9ca3af; }
109
- .eda-act-item.ok .eda-act-dot { background: #16a34a; }
110
- .eda-act-item.err .eda-act-dot { background: #dc2626; }
111
- .eda-act-item.pend .eda-act-dot { background: #f59e0b; animation: edaPulse 1s ease-in-out infinite; }
112
- .eda-act-item .eda-act-body { min-width: 0; flex: 1; }
113
- .eda-act-item .eda-act-line { display: flex; align-items: baseline; gap: 8px; }
114
- .eda-act-item .eda-act-seq { font-family: ui-monospace, Consolas, monospace; font-size: 10px; opacity: .45; flex: none; }
115
- .eda-act-item .eda-act-name { font-size: 12.5px; font-weight: 600; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
116
- .eda-act-item .eda-act-meta { font-size: 10.5px; opacity: .5; }
117
- .eda-revoke { padding: 2px 8px !important; font-size: 10px !important; }
118
- .eda-hints { display: flex; flex-direction: column; gap: 5px; margin-top: 2px; }
119
- .eda-hint { font-size: 11px; opacity: .68; }
120
- .eda-act-item .eda-act-meta .eda-pend { color: #f59e0b; opacity: 1; font-weight: 600; }
121
- .eda-act-item .eda-act-code { font-family: ui-monospace, Consolas, monospace; font-size: 10.5px; opacity: .55; margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
122
- .eda-act-item .eda-act-out { font-size: 11px; opacity: .65; margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
123
- .eda-act-item .eda-act-out.err { color: #dc2626; opacity: .9; }
124
- .eda-act-item .eda-act-full {
125
- white-space: pre-wrap; word-break: break-all; font-family: ui-monospace, Consolas, monospace;
126
- font-size: 10.5px; line-height: 1.55; opacity: .8; margin-top: 5px; padding: 7px 9px;
127
- background: light-dark(rgba(0,0,0,.045), rgba(255,255,255,.05)); border-radius: 7px;
128
- max-height: 240px; overflow: auto;
129
- }
130
- .eda-act-item .eda-act-full .eda-act-full-label { font-family: inherit; font-size: 10px; opacity: .5; margin: 0 0 2px; }
131
- .eda-act-empty { font-size: 11.5px; opacity: .5; padding: 6px 0; }
132
-
133
- /* activity header row: title + session switcher */
134
- .eda-act-head { display: flex; align-items: center; gap: 8px; }
135
- .eda-act-head .eda-card-title { flex: 1; margin: 0; }
136
- .eda-sess {
137
- font: inherit; font-size: 10.5px; border: 1px solid light-dark(rgba(0,0,0,.14), rgba(255,255,255,.16));
138
- border-radius: 6px; background: transparent; color: inherit; padding: 2px 6px; max-width: 130px; cursor: pointer;
139
- }
140
- .eda-act-hint { font-size: 10.5px; opacity: .5; margin: 6px 0 0; }
141
-
142
- /* 醒目对话入口 (connected CTA) */
143
- .eda-cta {
144
- display: flex; align-items: center; gap: 10px; margin-top: 10px; padding: 9px 12px;
145
- border: 1px solid rgba(37,99,235,.35); border-radius: 10px; cursor: pointer;
146
- background: linear-gradient(180deg, rgba(37,99,235,.10), rgba(37,99,235,.03));
147
- }
148
- .eda-cta:hover { background: rgba(37,99,235,.14); }
149
- .eda-cta .eda-cta-bubble { font-size: 16px; flex: none; }
150
- .eda-cta .eda-cta-text { min-width: 0; flex: 1; }
151
- .eda-cta .eda-cta-title { font-size: 10.5px; opacity: .6; }
152
- .eda-cta .eda-cta-phrase { font-family: inherit; font-size: 12.5px; font-weight: 700; color: #2563eb; }
153
- .eda-cta .eda-cta-copy { flex: none; font-size: 10.5px; opacity: .55; }
154
- .eda-cta.ok .eda-cta-copy { color: #16a34a; opacity: 1; }
155
-
156
- /* offline export (footer, small) */
157
- .eda-prompt textarea {
158
- width: 100%; box-sizing: border-box; resize: vertical; min-height: 56px; border-radius: 8px;
159
- border: 1px solid light-dark(rgba(0,0,0,.14), rgba(255,255,255,.16));
160
- background: light-dark(#fafafa, #121317); color: inherit; font: inherit; font-size: 12px; line-height: 1.6;
161
- padding: 8px 10px; outline: none;
162
- }
163
- .eda-prompt textarea:focus { border-color: #2563eb; }
164
- .eda-prompt textarea::placeholder { opacity: .45; }
165
- .eda-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
166
- .eda-chip { border: 1px solid light-dark(rgba(0,0,0,.11), rgba(255,255,255,.13)); border-radius: 999px; padding: 3px 9px; font-size: 11px; cursor: pointer; color: inherit; background: transparent; }
167
- .eda-chip:hover { border-color: rgba(37,99,235,.55); }
168
-
169
- .eda-foot { font-size: 11px; opacity: .5; text-align: center; margin: 2px 0 0; }
170
210
  `;
171
211
  //#endregion
172
212
 
173
213
  const API_BASE = "/api/dsh-eda";
214
+ /** The one upgrade command the update pill copies. */
215
+ const UPDATE_CMD = "dsh plugin --profile desktop add @windypro-rourou/dsh-eda@latest";
174
216
  const LINKS = {
175
217
  editor: "https://pro.lceda.cn/editor",
176
218
  ext: "https://jlc-ext.com/item/oshwhub/run-api-gateway",
177
- skill: "https://github.com/easyeda/easyeda-api-skill",
178
219
  };
179
-
180
- //#region data
181
220
  const CONNECT_STEPS = [
182
- { id: 0, name: "一键安装官方桥", hint: "官方 easyeda-api-skill → ~/.dsh/eda/bridge/(离线依赖,无需 npm)。" },
183
- { id: 1, name: "启动官方桥", hint: "Bridge Server 监听 127.0.0.1:49620-49629,自动探测。" },
184
- { id: 2, name: "网页版装扩展 Run API Gateway", hint: "pro.lceda.cn/editor →「高级」→「扩展管理器」→ 搜索安装;「已安装」里开「外部交互」+「显示在顶部菜单」。" },
185
- { id: 3, name: "验证", hint: "刷新编辑器页面;面板状态变绿 = 已连上你的云画板。" },
221
+ { n: 1, t: "一键安装官方桥", d: "官方 easyeda-api-skill → 本机 ~/.dsh/eda/bridge/(离线依赖,无需 npm)。" },
222
+ { n: 2, t: "启动官方桥", d: "Bridge Server 监听 127.0.0.1:49620-49629,插件自动探测。" },
223
+ { n: 3, t: "网页版装扩展 Run API Gateway", d: "编辑器 →「高级」→「扩展管理器」→ 安装;再开「外部交互」+「显示在顶部菜单」。" },
224
+ { n: 4, t: "验证", d: "刷新编辑器页面;状态点变绿 = 已连上你的云画板。" },
186
225
  ];
226
+ const HINTS = [
227
+ "放置任意大类元件(R/C/L/二极管/LED/MCU…)并框内定位",
228
+ "引脚级连线 + VCC/GND 网络标志",
229
+ "原理图 / PCB 的 DRC、网表、BOM 导出",
230
+ "PCB 元件 / 过孔 / 走线(含底层铜)+ 现场截图",
231
+ "随时「紧急保存」到本地并留动作日志",
232
+ ];
233
+ const ICON_EDA = "M3 3.6h7.2l2.8 2.8v6h-10z M10.2 3.6v2.8h2.8 M5 8.4h3 M5 10.4h2";
234
+
235
+ //#region store
236
+ /** Tiny external store: panel open/closed, shared by the pill and the overlay. */
237
+ function PanelStore() {
238
+ const listeners = new Set();
239
+ let open = false;
240
+ this.get = () => open;
241
+ this.set = (v) => { const next = !!v; if (next === open) return; open = next; for (const fn of listeners) fn(); };
242
+ this.toggle = () => this.set(!open);
243
+ this.subscribe = (fn) => { listeners.add(fn); return () => listeners.delete(fn); };
244
+ }
245
+ function useStore(store) {
246
+ const [v, setV] = useState(store.get());
247
+ useEffect(() => store.subscribe(() => setV(store.get())), [store]);
248
+ return v;
249
+ }
187
250
  //#endregion
188
251
 
189
252
  //#region hooks
@@ -192,12 +255,10 @@ window.__ModuleLoader__.load({
192
255
  const [error, setError] = useState(false);
193
256
  useEffect(() => {
194
257
  let alive = true;
195
- const load = () => {
196
- fetch(API_BASE + "/status")
197
- .then((r) => (r.ok ? r.json() : Promise.reject(r.status)))
198
- .then((b) => { if (alive) { setStatus(b); setError(false); } })
199
- .catch(() => { if (alive) { setStatus(null); setError(true); } });
200
- };
258
+ const load = () => fetch(API_BASE + "/status")
259
+ .then((r) => (r.ok ? r.json() : Promise.reject(r.status)))
260
+ .then((b) => { if (alive) { setStatus(b); setError(false); } })
261
+ .catch(() => { if (alive) { setStatus(null); setError(true); } });
201
262
  load();
202
263
  const t = setInterval(load, 4000);
203
264
  return () => { alive = false; clearInterval(t); };
@@ -205,14 +266,8 @@ window.__ModuleLoader__.load({
205
266
  return [status, error];
206
267
  }
207
268
 
208
- /**
209
- * Poll the agent-activity feed (what the conversation's agent is doing
210
- * through the official API right now). `pinnedSid` = '' means "follow
211
- * the freshest session" (the panel's default for 仅当前会话).
212
- */
213
- function useActivity() {
214
- const [feed, setFeed] = useState({ activities: [], sessions: [], currentSid: '', error: false });
215
- const [pinnedSid, setPinnedSid] = useState("");
269
+ function useActivity(pinnedSid) {
270
+ const [feed, setFeed] = useState({ activities: [], sessions: [], currentSid: "", error: false });
216
271
  useEffect(() => {
217
272
  let alive = true;
218
273
  const load = () => {
@@ -221,7 +276,12 @@ window.__ModuleLoader__.load({
221
276
  .then((r) => (r.ok ? r.json() : Promise.reject(r.status)))
222
277
  .then((b) => {
223
278
  if (!alive) return;
224
- setFeed({ activities: Array.isArray(b.activities) ? b.activities : [], sessions: Array.isArray(b.sessions) ? b.sessions : [], currentSid: b.currentSid ?? "", error: false });
279
+ setFeed({
280
+ activities: Array.isArray(b.activities) ? b.activities : [],
281
+ sessions: Array.isArray(b.sessions) ? b.sessions : [],
282
+ currentSid: b.currentSid ?? "",
283
+ error: false,
284
+ });
225
285
  })
226
286
  .catch(() => { if (alive) setFeed((prev) => ({ ...prev, error: true })); });
227
287
  };
@@ -229,340 +289,407 @@ window.__ModuleLoader__.load({
229
289
  const t = setInterval(load, 3000);
230
290
  return () => { alive = false; clearInterval(t); };
231
291
  }, [pinnedSid]);
232
- return { ...feed, setSid: setPinnedSid, pinned: pinnedSid };
292
+ return feed;
233
293
  }
234
294
  //#endregion
235
295
 
236
296
  //#region components
237
- /** Compact connection card: state + one-click platform actions + dialog CTA. */
238
- function ConnectCard({ status, error, onInstall, onStartBridge, installState, bridgeState }) {
297
+ /** Brand mark: host icon when available, else a two-stroke chip glyph. */
298
+ function Mark() {
299
+ const Icon = dsIcon("IconBoardOutline16") || dsIcon("IconComponentOutline16");
300
+ if (Icon) return h("span", { className: "eda-mark" }, h(Icon, null));
301
+ return h("span", { className: "eda-mark" }, "EDA");
302
+ }
303
+
304
+ function SendIcon() {
305
+ return h("svg", { width: 13, height: 13, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: 1.3, "aria-hidden": "true" },
306
+ h("path", { d: "M2.6 3.4l10.8 4.6-10.8 4.6 1.7-4.6z", strokeLinejoin: "round" }));
307
+ }
308
+
309
+ /**
310
+ * Compact update hint (top bar): rendered ONLY when /status reports a
311
+ * newer published release. One click copies the upgrade command; quiet,
312
+ * no modal, no badge hunting. Exported for the bundle runtime test.
313
+ */
314
+ function UpdatePill({ status }) {
315
+ const [copied, setCopied] = useState(false);
316
+ if (status?.updateAvailable !== true) return null;
317
+ const latest = typeof status.latestVersion === "string" ? status.latestVersion : "";
318
+ if (latest === "") return null;
319
+ const copy = () => {
320
+ try { navigator.clipboard?.writeText(UPDATE_CMD); } catch (e) { /* clipboard unavailable */ }
321
+ setCopied(true);
322
+ setTimeout(() => setCopied(false), 1600);
323
+ };
324
+ return h("button", {
325
+ type: "button", className: "eda-update", onClick: copy,
326
+ title: "点击复制升级命令:" + UPDATE_CMD,
327
+ }, copied ? "已复制 ✓" : "v" + latest + " 可更新");
328
+ }
329
+
330
+ /** Header pill — the 0.2 entry point (slot-owned header utilities). */
331
+ function HeaderPill({ store }) {
332
+ const open = useStore(store);
333
+ const [status] = useStatus();
334
+ const ready = status?.connected === true;
335
+ const cls = "eda-pill";
336
+ const inner = [
337
+ h("span", { className: "eda-dot " + (status === null ? "wait" : ready ? "on" : "off"), key: "d" }),
338
+ h("span", { key: "t" }, "嘉立创 EDA"),
339
+ ];
340
+ if (dsButton) {
341
+ return h(dsButton, {
342
+ appearance: "ghost", size: "small", "data-active": open ? "true" : "false",
343
+ onClick: () => store.toggle(), title: "嘉立创 EDA 助手", className: cls,
344
+ }, inner);
345
+ }
346
+ return h("button", {
347
+ type: "button", className: cls, "data-active": open ? "true" : "false",
348
+ onClick: () => store.toggle(), title: "嘉立创 EDA 助手",
349
+ }, inner);
350
+ }
351
+
352
+ /**
353
+ * Connection card: one status line, then the three platform actions, then
354
+ * (when connected) the copy-the-prompt CTA. Errors stay inline and quiet.
355
+ */
356
+ function ConnectCard({ status, error, install, bridge, onInstall, onStart }) {
239
357
  const ready = status?.connected === true;
240
358
  const [copied, setCopied] = useState(false);
241
- const dot = status === null ? (error ? "off" : "wait") : (ready ? "on" : "off");
242
- const state = status === null ? (error ? "状态服务未响应" : "检测中…") : (ready ? "已连接 · " + (status.port ? "127.0.0.1:" + status.port : "") : "未连接");
243
- const win = status?.health?.match(/edaWindowCount:(\d+)/)?.[1] ?? null;
244
359
  const inst = status?.bridgeInstalled === true;
245
- const copyPrompt = () => {
360
+ const dot = status === null ? (error ? "off" : "wait") : ready ? "on" : "off";
361
+ const label = status === null ? (error ? "状态服务未响应" : "检测中…") : ready ? "已连接" : "未连接";
362
+ const port = ready && status?.port ? "127.0.0.1:" + status.port : "";
363
+ const win = status?.health?.match(/edaWindowCount:(\d+)/)?.[1];
364
+ const copy = () => {
246
365
  const text = "嘉立创EDA,启动!帮我画一个 LED 点亮电路";
247
- try { navigator.clipboard?.writeText(text); } catch { /* clipboard may be unavailable */ }
366
+ try { navigator.clipboard?.writeText(text); } catch (e) { /* clipboard unavailable */ }
248
367
  setCopied(true);
249
368
  setTimeout(() => setCopied(false), 1600);
250
369
  };
251
370
  return h("div", { className: "eda-card" },
252
- h("div", { className: "eda-status" },
371
+ h("div", { className: "eda-state" },
253
372
  h("span", { className: "eda-dot " + dot }),
254
- h("div", { className: "eda-txt" }, state, win !== null ? h("small", null, "窗口 " + win) : null)),
373
+ h("b", null, label),
374
+ h("small", null, [port, win !== undefined ? "窗口 " + win : ""].filter(Boolean).join(" · "))),
255
375
  h("div", { className: "eda-actions" },
256
376
  h("button", {
257
- className: "eda-btn " + (inst ? "ghost" : "primary"),
258
- disabled: inst || installState?.busy,
259
- onClick: onInstall,
260
- title: inst ? "官方桥已安装(随本机持久)" : "",
261
- }, inst ? "官方桥已安装 ✓" : (installState?.busy ? "安装中…" : "一键安装官方桥")),
262
- h("button", { className: "eda-btn ghost", disabled: bridgeState?.busy, onClick: onStartBridge }, bridgeState?.busy ? "启动中…" : "启动官方桥"),
377
+ className: "eda-btn " + (inst ? "" : "primary"),
378
+ disabled: inst || install?.busy, onClick: onInstall,
379
+ title: inst ? "官方桥已安装(随本机持久)" : "下载官方 easyeda-api-skill 到本机",
380
+ }, inst ? "官方桥已装 ✓" : install?.busy ? "安装中…" : "一键安装官方桥"),
381
+ h("button", { className: "eda-btn", disabled: bridge?.busy, onClick: onStart },
382
+ bridge?.busy ? "启动中…" : "启动桥"),
263
383
  h("a", { className: "eda-link", href: LINKS.editor, target: "_blank", rel: "noreferrer" }, "打开编辑器"),
264
384
  h("a", { className: "eda-link", href: LINKS.ext, target: "_blank", rel: "noreferrer" }, "扩展直达")),
265
385
  ready
266
- ? h("div", { className: "eda-cta" + (copied ? " ok" : ""), onClick: copyPrompt, title: "点击复制到剪贴板,然后在对话里发送" },
267
- h("span", { className: "eda-cta-bubble" }, "💬"),
268
- h("div", { className: "eda-cta-text" },
269
- h("div", { className: "eda-cta-title" }, "去对话里说:"),
270
- h("span", { className: "eda-cta-phrase" }, "「嘉立创EDA,启动!」")),
271
- h("span", { className: "eda-cta-copy" }, copied ? "已复制 ✓" : "点击复制"))
272
- : h("p", { className: "eda-note", style: { margin: "8px 0 0" } }, "连接好画板后,在对话里描述需求即可实时生成;下方「导出离线版」仅作兜底。"),
273
- installState?.result ? h("p", { className: "eda-note" }, installState.result) : null,
274
- bridgeState?.result ? h("p", { className: "eda-note" }, bridgeState.result) : null,
275
- );
386
+ ? h("div", { className: "eda-cta" + (copied ? " ok" : ""), onClick: copy,
387
+ title: "点击复制,然后粘贴到对话里发送" },
388
+ h(SendIcon, null),
389
+ h("span", { className: "eda-cta-t" },
390
+ h("i", null, "去对话里说"),
391
+ h("b", null, "「嘉立创EDA,启动!」")),
392
+ h("span", { className: "eda-cta-c" }, copied ? "已复制 ✓" : "复制"))
393
+ : h("p", { className: "eda-note" }, "连上画板后,在对话里描述需求即可实时生成;离线导出仅作兜底。"),
394
+ install?.result ? h("p", { className: "eda-note" }, install.result) : null,
395
+ bridge?.result ? h("p", { className: "eda-note" }, bridge.result) : null);
276
396
  }
277
397
 
278
- /** Collapsible connect guide (compact). */
279
- function ConnectWizard({ open, setOpen }) {
398
+ function ConnectGuide({ open, setOpen }) {
280
399
  if (!open) {
281
- return h("button", { className: "eda-btn ghost", style: { width: "100%" }, onClick: () => setOpen(true) }, "连接教程(4 步 · 网页版)");
400
+ return h("button", { className: "eda-btn", style: { width: "100%" }, onClick: () => setOpen(true) },
401
+ "连接教程 · 4 步(网页版官方栈)");
282
402
  }
283
403
  return h("div", { className: "eda-card" },
284
- h("div", { className: "eda-card-title" }, "连接教程(官方栈 · 网页版)"),
404
+ h("div", { className: "eda-card-title" }, "连接教程"),
285
405
  h("div", { className: "eda-steps" }, CONNECT_STEPS.map((s) =>
286
- h("div", { className: "eda-step", key: s.id },
287
- h("div", { className: "eda-step-no" }, String(s.id + 1)),
288
- h("div", { className: "eda-step-body" },
289
- h("div", { className: "eda-step-name" }, s.name),
290
- h("div", { className: "eda-step-hint" }, s.hint))))),
291
- h("p", { className: "eda-note", style: { margin: "10px 0 0" } },
292
- [LINKS.editor, LINKS.ext].map((l) => h("a", { className: "eda-link", href: l, target: "_blank", rel: "noreferrer", key: l, style: { marginRight: 12 } }, l)),
293
- h("button", { className: "eda-link", onClick: () => setOpen(false), style: { border: 0, background: "transparent", cursor: "pointer", padding: 0 } }, "收起")));
406
+ h("div", { className: "eda-step", key: s.n },
407
+ h("span", { className: "eda-step-no" }, String(s.n)),
408
+ h("div", null, h("b", null, s.t), h("p", null, s.d))))),
409
+ h("p", { className: "eda-note" },
410
+ h("a", { className: "eda-link", href: LINKS.editor, target: "_blank", rel: "noreferrer", style: { marginRight: 12 } }, "编辑器"),
411
+ h("a", { className: "eda-link", href: LINKS.ext, target: "_blank", rel: "noreferrer", style: { marginRight: 12 } }, "扩展"),
412
+ h("button", { className: "eda-link", onClick: () => setOpen(false),
413
+ style: { border: 0, background: "transparent", cursor: "pointer", padding: 0, font: "inherit" } }, "收起")));
294
414
  }
295
415
 
296
416
  /**
297
- * The monitor: RECORD-STYLE timeline (参考 DSH 轨迹) — every step is
298
- * numbered (persisted on disk, so it is never empty), each entry can be
299
- * 撤回 (deletes the primitives that step created) or expanded; the card
300
- * has 清空记录. When nothing has happened yet, a static capability
301
- * preview keeps the panel informative (not blank).
417
+ * Record-style timeline (persisted on disk → never blank). Each step is
418
+ * numbered, expandable, and revocable while the bridge is connected.
302
419
  */
303
- function ActivityMonitor({ activities, sessions, currentSid, setSid, pinned, error, connected, onRevoke, busyId, onClear, clearing }) {
420
+ function Timeline({ feed, pinned, setSid, connected, onRevoke, busyId, onClear, clearing, note }) {
304
421
  const [expanded, setExpanded] = useState(() => new Set());
305
- const toggle = (id) => {
306
- setExpanded((prev) => {
307
- const next = new Set(prev);
308
- if (next.has(id)) next.delete(id); else next.add(id);
309
- return next;
310
- });
311
- };
312
- const list = Array.isArray(activities) ? activities : [];
313
- const sids = Array.isArray(sessions) ? sessions : [];
314
- const hasMulti = sids.length > 1;
422
+ const toggle = (id) => setExpanded((prev) => {
423
+ const next = new Set(prev);
424
+ if (next.has(id)) next.delete(id); else next.add(id);
425
+ return next;
426
+ });
427
+ const list = feed.activities;
428
+ const sids = feed.sessions;
429
+ const multi = sids.length > 1;
315
430
  return h("div", { className: "eda-card" },
316
- h("div", { className: "eda-act-head" },
317
- h("div", { className: "eda-card-title" }, "Agent 正在使用官方 API"),
318
- hasMulti
431
+ h("div", { className: "eda-tl-head" },
432
+ h("div", { className: "eda-card-title" }, "Agent · 官方 API"),
433
+ multi
319
434
  ? h("select", {
320
- className: "eda-sess",
321
- value: pinned ?? "",
322
- onChange: (e) => setSid(e.target.value),
435
+ className: "eda-select", value: pinned ?? "", onChange: (e) => setSid(e.target.value),
323
436
  title: "切换会话(默认跟随最新)",
324
437
  },
325
- h("option", { value: "" }, "跟随最新会话"),
326
- sids.map((s) => h("option", { value: s.sid ?? "", key: (s.sid || "(platform)") + s.lastTs }, s.label ?? "会话")))
327
- : (currentSid && list.length > 0 ? h("span", { className: "eda-sess", style: { cursor: "default" } }, "当前会话") : null),
438
+ h("option", { value: "" }, "跟随最新"),
439
+ sids.map((s) => h("option", { value: s.sid ?? "", key: (s.sid || "platform") + s.lastTs }, s.label ?? "会话")))
440
+ : null,
328
441
  list.length > 0
329
- ? h("button", { className: "eda-btn ghost", style: { padding: "3px 9px", fontSize: "10.5px" }, disabled: clearing, onClick: onClear, title: "清空时间线(含磁盘历史)" }, clearing ? "清空中…" : "清空记录")
442
+ ? h("button", { className: "eda-btn tiny", disabled: clearing, onClick: onClear, title: "清空时间线(含磁盘历史)" },
443
+ clearing ? "清空…" : "清空")
330
444
  : null),
331
445
  list.length === 0
332
446
  ? h("div", null,
333
- h("div", { className: "eda-act-empty" }, error
334
- ? "实时活动流暂不可用(服务端新模块待重启后启用);重启后这里会持续记录 agent 的每一步。"
335
- : "还没有记录——历史会保存在 ~/.dsh/eda/activity.jsonl,面板永不空白。你可以让 agent:"),
336
- h("div", { className: "eda-hints" },
337
- ["放置任意大类元件(R/C/L/二极管/LED/MCU…)并框内定位", "引脚级连线 + VCC/GND 网络标志", "原理图/PCB 的 DRC、网表、BOM 导出", "PCB 元件/过孔/走线 + 现场截图", "随时「紧急保存」到本地并留动作日志"]
338
- .map((t, i) => h("div", { className: "eda-hint", key: i }, "• " + t))))
447
+ h("div", { className: "eda-empty" }, feed.error
448
+ ? "实时活动流未就绪(服务端模块未加载)。"
449
+ : "还没有记录。历史写入本机 activity.jsonl,面板不会空着。可以让 agent:"),
450
+ h("div", { className: "eda-hints" }, HINTS.map((t, i) =>
451
+ h("div", { className: "eda-hint", key: i }, h("s", null, "·"), h("span", null, t)))))
339
452
  : h("div", null,
340
- h("div", { className: "eda-act" }, list.slice(0, 50).map((a, i) => {
341
- const isPend = a.status === 'pending';
342
- const isOpen = expanded.has(a.id);
343
- const t = (a.ts ?? "").slice(11, 19);
344
- const revokable = connected && !isPend && Array.isArray(a.revoke?.created) && a.revoke.created.length > 0;
453
+ h("div", { className: "eda-tl" }, list.slice(0, 60).map((a, i) => {
454
+ const pend = a.status === "pending";
455
+ const open = expanded.has(a.id);
456
+ const revokable = connected && !pend && Array.isArray(a.revoke?.created) && a.revoke.created.length > 0;
457
+ const time = String(a.ts ?? "").slice(11, 19);
458
+ const meta = pend
459
+ ? h("span", { className: "eda-pend" }, "执行中…")
460
+ : [time, a.durationMs ? a.durationMs + "ms" : "", a.tool ?? ""].filter(Boolean).join(" · ");
345
461
  return h("div", {
346
- className: "eda-act-item " + (isPend ? "pend" : (a.ok === false ? "err" : (a.ok ? "ok" : ""))),
347
- key: a.id ?? i,
348
- onClick: () => toggle(a.id),
462
+ className: "eda-row " + (pend ? "pend" : a.ok === false ? "err" : a.ok ? "ok" : ""),
463
+ key: a.id ?? i, onClick: () => toggle(a.id),
349
464
  },
350
- h("span", { className: "eda-act-dot" }),
351
- h("div", { className: "eda-act-body" },
352
- h("div", { className: "eda-act-line" },
353
- h("span", { className: "eda-act-seq" }, "#" + (a.id ?? i)),
354
- h("span", { className: "eda-act-name" }, a.action ?? a.tool ?? "调用 API"),
355
- h("span", { className: "eda-act-meta" }, isPend
356
- ? h("span", { className: "eda-pend" }, "执行中…")
357
- : (t + (a.durationMs ? " · " + a.durationMs + "ms" : "") + " · " + (a.tool ?? ""))),
465
+ h("span", { className: "eda-row-dot" }),
466
+ h("div", { className: "eda-row-body" },
467
+ h("div", { className: "eda-row-line" },
468
+ h("span", { className: "eda-seq" }, "#" + (a.id ?? i)),
469
+ h("span", { className: "eda-row-name" }, a.action ?? a.tool ?? "调用 API"),
470
+ h("span", { className: "eda-row-meta" }, meta),
358
471
  revokable
359
472
  ? h("button", {
360
- className: "eda-btn ghost eda-revoke",
361
- disabled: busyId === a.id,
473
+ className: "eda-btn tiny", disabled: busyId === a.id,
362
474
  onClick: (e) => { e.stopPropagation(); onRevoke(a.id); },
363
475
  title: "撤回该步(删除它新建的图元)",
364
- }, busyId === a.id ? "撤回中…" : "撤回")
476
+ }, busyId === a.id ? "撤回…" : "撤回")
365
477
  : null),
366
- a.code ? h("div", { className: "eda-act-code" }, a.code) : null,
367
- !isPend && a.ok === false && a.error ? h("div", { className: "eda-act-out err" }, a.error)
368
- : (!isPend && a.result ? h("div", { className: "eda-act-out" }, a.result) : null),
369
- isOpen ? h("div", { className: "eda-act-full" },
370
- (a.code ? h("div", null, h("div", { className: "eda-act-full-label" }, "代码"), a.code) : null),
371
- (a.revoke ? h("div", null, h("div", { className: "eda-act-full-label" }, "撤回数据"), `该步新建 ${a.revoke.created.length} 个图元` + (a.revoke.deletedCount ? `,删除 ${a.revoke.deletedCount} 个(不可恢复)` : "")) : null),
372
- (a.result ? h("div", null, h("div", { className: "eda-act-full-label" }, "结果"), a.result) : null),
373
- (a.error ? h("div", null, h("div", { className: "eda-act-full-label" }, "错误"), a.error) : null)) : null));
478
+ a.code ? h("div", { className: "eda-row-code" }, a.code) : null,
479
+ !pend && a.ok === false && a.error
480
+ ? h("div", { className: "eda-row-out err" }, a.error)
481
+ : !pend && a.result ? h("div", { className: "eda-row-out" }, a.result) : null,
482
+ open ? h("div", { className: "eda-row-full" },
483
+ a.code ? h("div", null, h("i", null, "代码"), a.code) : null,
484
+ a.revoke ? h("div", null, h("i", null, "撤回数据"),
485
+ `新建 ${a.revoke.created.length} 图元` + (a.revoke.deletedCount ? ` · 删除 ${a.revoke.deletedCount}(不可恢复)` : "")) : null,
486
+ a.result ? h("div", null, h("i", null, "结果"), a.result) : null,
487
+ a.error ? h("div", null, h("i", null, "错误"), a.error) : null) : null));
374
488
  })),
375
- h("div", { className: "eda-act-hint" }, (hasMulti ? "下拉切换会话 · " : "") + "点击条目查看完整内容 · 撤回仅删除该步新建图元")));
489
+ h("div", { className: "eda-tl-foot" }, (multi ? "下拉切换会话 · " : "") + "点击条目展开 · 撤回只删该步新建图元")),
490
+ note ? h("p", { className: "eda-note", style: { wordBreak: "break-word" } }, note) : null);
376
491
  }
377
492
 
378
- /**
379
- * 紧急保存: pull the board state (官方 API .epro2 + SVG 预览 + 网表/BOM)
380
- * AND the agent action log to local disk — a safety net if the cloud sync
381
- * ever fails. Works (log-only) even when the bridge is disconnected.
382
- */
383
- function SnapshotCard({ connected, busy, onSave, lastOut }) {
493
+ /** Emergency save: board state (.epro2 + SVG + netlist/BOM) + action log → disk. */
494
+ function SnapshotCard({ connected, state, onSave }) {
384
495
  return h("div", { className: "eda-card" },
385
- h("div", { className: "eda-card-title" }, "紧急保存(画板断连也不丢工程)"),
386
- h("button", { className: "eda-btn primary big", disabled: busy, onClick: onSave },
387
- busy ? "保存中…" : "🛟 紧急保存"),
388
- lastOut ? h("p", { className: "eda-note", style: { margin: "8px 0 0", wordBreak: "break-all" } }, lastOut) : null,
389
- h("p", { className: "eda-muted", style: { margin: "8px 0 0" } },
390
- connected
391
- ? "把 agent 在画板上做的东西抓到本地:专业版 .epro2 完整恢复 + 通用预览 SVG + 网表/BOM。云端没同步上,也能找回最后的工程。"
392
- : "画板未连接:仍会保存 agent 动作日志(每一步留档)。"));
496
+ h("div", { className: "eda-card-title" }, "紧急保存"),
497
+ h("button", { className: "eda-btn primary big", disabled: state.busy, onClick: onSave },
498
+ state.busy ? "保存中…" : "🛟 保存画板到本地"),
499
+ h("p", { className: "eda-muted", style: { marginTop: 8 } }, connected
500
+ ? "专业版 .epro2(可完整恢复)+ 预览 SVG + 网表/BOM。云端没同步上也能找回最后的工程。"
501
+ : "画板未连接:仍会保存 agent 动作日志,每一步留档。"),
502
+ state.out ? h("p", { className: "eda-note", style: { wordBreak: "break-all" } }, state.out) : null);
393
503
  }
394
- //#endregion
395
504
 
396
- //#region panel
397
- function EdaPanel({ controller }) {
505
+ /** Panel shell: top bar → scroll body → footer. */
506
+ function EdaPanel({ store }) {
398
507
  const [status, error] = useStatus();
399
508
  const ready = status?.connected === true;
400
- const activity = useActivity();
401
- const [wizardOpen, setWizardOpen] = useState(false);
402
- const [saveState, setSaveState] = useState({ busy: false, out: null });
403
- const [installState, setInstallState] = useState({ busy: false, result: null });
404
- const [bridgeState, setBridgeState] = useState({ busy: false, result: null });
405
- const [revokeState, setRevokeState] = useState({ busyId: null, out: null });
509
+ const [pinned, setPinned] = useState("");
510
+ const feed = useActivity(pinned);
511
+ const [guide, setGuide] = useState(false);
512
+ const [install, setInstall] = useState({ busy: false, result: null });
513
+ const [bridge, setBridge] = useState({ busy: false, result: null });
514
+ const [save, setSave] = useState({ busy: false, out: null });
515
+ const [revoke, setRevoke] = useState({ busyId: null, out: null });
406
516
  const [clearing, setClearing] = useState(false);
407
517
 
408
- const doRevoke = async (id) => {
409
- if (revokeState.busyId !== null) return;
410
- setRevokeState({ busyId: id, out: null });
518
+ const post = (path) => fetch(API_BASE + path, {
519
+ method: "POST", headers: { "content-type": "application/json" }, body: "{}",
520
+ });
521
+
522
+ const doInstall = async () => {
523
+ if (install.busy) return;
524
+ setInstall({ busy: true, result: null });
411
525
  try {
412
- const res = await fetch(API_BASE + "/activity/revoke?id=" + encodeURIComponent(id), { method: "POST", headers: { "content-type": "application/json" }, body: "{}" });
413
- if (!res.ok) { setRevokeState({ busyId: null, out: "撤回接口待重启后生效(当前旧模块)。" }); return; }
526
+ const res = await post("/install");
527
+ if (!res.ok) { setInstall({ busy: false, result: "安装接口未就绪(旧模块),可对 AI 说「连接我的画板」。" }); return; }
414
528
  const out = await res.json();
415
- setRevokeState({ busyId: null, out: out.ok ? `↩️ 已撤回:${out.note ?? ""}` : "⚠️ " + String(out.error ?? "撤回失败") });
416
- } catch (err) { setRevokeState({ busyId: null, out: "请求失败:" + String(err) }); }
529
+ setInstall({ busy: false, result: out.ok ? "✅ " + (out.script ?? "官方桥已安装") : "❌ " + (out.error ?? "安装失败") });
530
+ } catch (e) { setInstall({ busy: false, result: "请求失败:" + String(e) }); }
417
531
  };
418
- const doClear = async () => {
419
- if (clearing) return;
420
- setClearing(true);
532
+ const doStart = async () => {
533
+ if (bridge.busy) return;
534
+ setBridge({ busy: true, result: null });
421
535
  try {
422
- const res = await fetch(API_BASE + "/activity/clear", { method: "POST", headers: { "content-type": "application/json" }, body: "{}" });
423
- if (!res.ok) { setRevokeState({ busyId: null, out: "清空接口待重启后生效(当前旧模块)。" }); return; }
424
- setRevokeState({ busyId: null, out: "🗑️ 时间线已清空" });
425
- } catch (err) { setRevokeState({ busyId: null, out: "请求失败:" + String(err) }); }
426
- finally { setClearing(false); }
536
+ const res = await post("/bridge");
537
+ if (!res.ok) { setBridge({ busy: false, result: "启动接口未就绪(旧模块),可对 AI 说「连接我的画板」。" }); return; }
538
+ const out = await res.json();
539
+ setBridge({ busy: false, result: out.ok ? `已启动(${out.state})` : `未启动:${out.error || out.note || "请先安装桥接"}` });
540
+ } catch (e) { setBridge({ busy: false, result: "请求失败:" + String(e) }); }
427
541
  };
428
-
429
- const doInstall = async () => {
430
- if (installState.busy) return;
431
- setInstallState({ busy: true, result: null });
542
+ const doSave = async () => {
543
+ if (save.busy) return;
544
+ setSave({ busy: true, out: null });
432
545
  try {
433
- const res = await fetch(API_BASE + "/install", { method: "POST", headers: { "content-type": "application/json" }, body: "{}" });
434
- if (!res.ok) { setInstallState({ busy: false, result: "官方桥已就绪 / 安装接口在下次重启后生效(当前旧模块)。官方桥源码:" + LINKS.skill }); return; }
546
+ const res = await post("/snapshot");
547
+ if (!res.ok) { setSave({ busy: false, out: "紧急保存接口未就绪(旧模块),可对 AI 说「紧急保存」。" }); return; }
435
548
  const out = await res.json();
436
- setInstallState({ busy: false, result: out.ok ? "✅ " + (out.script ?? "官方桥已安装") : "❌ " + (out.error ?? "安装失败") });
437
- } catch (err) { setInstallState({ busy: false, result: "请求失败:" + String(err) }); }
549
+ setSave({
550
+ busy: false,
551
+ out: out.ok
552
+ ? `✅ ${out.files?.length ?? 0} 个文件 → ${out.dir ?? ""}` + ((out.errors?.length ?? 0) > 0 ? `(${out.errors.length} 项降级)` : "")
553
+ : "❌ " + String(out.error ?? "保存失败"),
554
+ });
555
+ } catch (e) { setSave({ busy: false, out: "请求失败:" + String(e) }); }
438
556
  };
439
-
440
- const doStartBridge = async () => {
441
- if (bridgeState.busy) return;
442
- setBridgeState({ busy: true, result: null });
557
+ const doRevoke = async (id) => {
558
+ if (revoke.busyId !== null) return;
559
+ setRevoke({ busyId: id, out: null });
443
560
  try {
444
- const res = await fetch(API_BASE + "/bridge", { method: "POST", headers: { "content-type": "application/json" }, body: "{}" });
445
- if (!res.ok) { setBridgeState({ busy: false, result: "启动接口在下次重启后生效(当前旧模块);可对 AI 说「连接我的画板」。" }); return; }
561
+ const res = await fetch(API_BASE + "/activity/revoke?id=" + encodeURIComponent(id), {
562
+ method: "POST", headers: { "content-type": "application/json" }, body: "{}",
563
+ });
564
+ if (!res.ok) { setRevoke({ busyId: null, out: "撤回接口未就绪(旧模块)。" }); return; }
446
565
  const out = await res.json();
447
- setBridgeState({ busy: false, result: out.ok ? `已启动(${out.state})` : `未启动:${out.error || out.note || "请先安装桥接"}` });
448
- } catch (err) { setBridgeState({ busy: false, result: "请求失败:" + String(err) }); }
566
+ setRevoke({ busyId: null, out: out.ok ? "↩️ 已撤回:" + (out.note ?? "") : "⚠️ " + String(out.error ?? "撤回失败") });
567
+ } catch (e) { setRevoke({ busyId: null, out: "请求失败:" + String(e) }); }
449
568
  };
450
-
451
- const doSave = async () => {
452
- if (saveState.busy) return;
453
- setSaveState({ busy: true, out: null });
569
+ const doClear = async () => {
570
+ if (clearing) return;
571
+ setClearing(true);
454
572
  try {
455
- const res = await fetch(API_BASE + "/snapshot", { method: "POST", headers: { "content-type": "application/json" }, body: "{}" });
456
- if (!res.ok) { setSaveState({ busy: false, out: "紧急保存接口在下次重启后生效(当前旧模块);也可对 AI 说「紧急保存」。" }); return; }
457
- const out = await res.json();
458
- if (!out.ok) setSaveState({ busy: false, out: "❌ " + String(out.error ?? "保存失败") });
459
- else setSaveState({ busy: false, out: `✅ 已保存 ${out.files?.length ?? 0} 个文件 → ${out.dir ?? ""}${(out.errors?.length ?? 0) > 0 ? `(${out.errors.length} 项降级:${out.errors.slice(0, 2).join(";")})` : ""}` });
460
- } catch (err) { setSaveState({ busy: false, out: "请求失败:" + String(err) }); }
573
+ const res = await post("/activity/clear");
574
+ setRevoke({ busyId: null, out: res.ok ? "🗑️ 时间线已清空" : "清空接口未就绪(旧模块)。" });
575
+ } catch (e) { setRevoke({ busyId: null, out: "请求失败:" + String(e) }); }
576
+ finally { setClearing(false); }
461
577
  };
462
578
 
463
- return h("div", { className: "eda-panel" },
464
- h("div", { className: "eda-head" },
465
- h("div", { className: "eda-mark" }, "E"),
466
- h("div", { className: "eda-tt" },
467
- h("h1", null, "嘉立创 EDA"),
468
- h("p", { className: "eda-sub" }, "平台仪表盘 · v" + (status?.version ?? "0.1.0"))),
469
- h("button", { className: "eda-close", onClick: () => controller.toggle(), "aria-label": "关闭" }, "✕")),
579
+ return h("div", { className: "dsh-eda-root" },
580
+ h("div", { className: "eda-top" },
581
+ h(Mark, null),
582
+ h("div", { className: "eda-title" },
583
+ h("b", null, "嘉立创 EDA"),
584
+ h("span", null, "official bridge · v" + (status?.version ?? "—"))),
585
+ h(UpdatePill, { status }),
586
+ h("button", { className: "eda-iconbtn", onClick: () => store.set(false), title: "关闭面板", "aria-label": "关闭" }, "✕")),
470
587
  h("div", { className: "eda-scroll" },
471
- h(ConnectCard, { status, error, onInstall: doInstall, onStartBridge: doStartBridge, installState, bridgeState }),
472
- h(ConnectWizard, { open: wizardOpen, setOpen: setWizardOpen }),
473
- h(ActivityMonitor, { activities: activity.activities, sessions: activity.sessions, currentSid: activity.currentSid, setSid: activity.setSid, pinned: activity.pinned, error: activity.error, connected: ready, onRevoke: doRevoke, busyId: revokeState.busyId, onClear: doClear, clearing }),
474
- (revokeState.out || saveState.out) ? h("p", { className: "eda-note", style: { margin: "0", wordBreak: "break-all" } }, revokeState.out ?? saveState.out) : null,
475
- h(SnapshotCard, { connected: ready, busy: saveState.busy, onSave: doSave, lastOut: saveState.out }),
476
- h("p", { className: "eda-foot" }, "云端实时 = 对话里生成(官方 eda.* API) · 紧急保存 = 本地留档")));
588
+ h(ConnectCard, { status, error, install, bridge, onInstall: doInstall, onStart: doStart }),
589
+ h(ConnectGuide, { open: guide, setOpen: setGuide }),
590
+ h(Timeline, {
591
+ feed, pinned, setSid: setPinned, connected: ready,
592
+ onRevoke: doRevoke, busyId: revoke.busyId, onClear: doClear, clearing,
593
+ note: revoke.out,
594
+ }),
595
+ h(SnapshotCard, { connected: ready, state: save, onSave: doSave })),
596
+ h("div", { className: "eda-foot" }, "对话里生成(官方 eda.* API) · 本地留档(紧急保存)"));
477
597
  }
478
- //#endregion
479
598
 
480
- //#region mounts
481
- const ICON = '<svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.2" aria-hidden="true"><path d="M3.5 2.5h6l3 3v8h-9z" stroke-linejoin="round"/><path d="M9.5 2.5v3h3M6 8h4M6 10.5h2.5" stroke-linecap="round"/></svg>';
599
+ /** Overlay wrapper: mounted in `shell.overlay`; `hidden` toggles visibility so
600
+ * the feed keeps running while the panel is closed (same surface as 0.1.x). */
601
+ function EdaOverlay({ store }) {
602
+ const open = useStore(store);
603
+ const [width, setWidth] = useState(() => {
604
+ try { return Math.min(760, Math.max(120, Number(localStorage.getItem("dsh-eda:width")) || 400)); } catch (e) { return 400; }
605
+ });
606
+ const drag = useRef(null);
607
+ const startDrag = (e) => {
608
+ e.preventDefault();
609
+ const move = (ev) => {
610
+ const next = Math.min(760, Math.max(120, window.innerWidth - ev.clientX));
611
+ drag.current = next;
612
+ setWidth(next);
613
+ };
614
+ const up = () => {
615
+ window.removeEventListener("mousemove", move);
616
+ window.removeEventListener("mouseup", up);
617
+ if (drag.current !== null) { try { localStorage.setItem("dsh-eda:width", String(drag.current)); } catch (err) { /* ignore */ } }
618
+ };
619
+ window.addEventListener("mousemove", move);
620
+ window.addEventListener("mouseup", up);
621
+ };
622
+ return h("div", { className: "dsh-eda-root", hidden: !open, style: { "--eda-w": width + "px" } },
623
+ h("div", { className: "dsh-eda-grip", onMouseDown: startDrag, title: "拖动调整宽度" }),
624
+ h(EdaPanel, { store }));
625
+ }
626
+ //#endregion
482
627
 
628
+ //#region mounts (0.1.x compatibility)
483
629
  function sidebarRoot() {
484
630
  const column = document.querySelector('[data-pane="sidebar"], [class*="sidebarCol"]');
485
631
  if (column === null) return undefined;
486
632
  const logoOwner = column.querySelector('[class*="logoRow"]')?.parentElement;
487
633
  return logoOwner ?? (column.firstElementChild ?? undefined);
488
634
  }
489
-
490
635
  function newSessionButton(root) {
491
636
  const nested = root.querySelector('button[class*="newSession"]');
492
637
  if (nested !== null) return nested;
493
- for (const child of root.children) {
494
- if (child.tagName === "BUTTON") return child;
495
- }
638
+ for (const child of root.children) if (child.tagName === "BUTTON") return child;
496
639
  return undefined;
497
640
  }
498
-
499
- function createEntry(controller) {
641
+ function createEntry(store) {
500
642
  const entry = document.createElement("button");
501
643
  entry.type = "button";
502
644
  entry.dataset.dshEdaEntry = "";
503
645
  entry.setAttribute("aria-label", "嘉立创 EDA 助手");
504
- entry.setAttribute("title", "嘉立创 EDA 助手(官方画板平台监控)");
505
- entry.innerHTML = '<span class="eda-entry-icon">' + ICON + '</span><span class="eda-entry-label">嘉立创 EDA</span>';
506
- entry.addEventListener("click", () => { controller.toggle(); });
646
+ entry.setAttribute("title", "嘉立创 EDA 助手(官方画板平台)");
647
+ entry.innerHTML = '<span class="eda-entry-icon"><svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.2" aria-hidden="true"><path d="' + ICON_EDA + '" stroke-linejoin="round" stroke-linecap="round"/></svg></span><span class="eda-entry-label">嘉立创 EDA</span>';
648
+ entry.addEventListener("click", () => store.toggle());
507
649
  return entry;
508
650
  }
509
-
510
- function placeEntry(root, entry) {
511
- const button = newSessionButton(root);
512
- if (button === undefined) return false;
513
- if (entry.parentElement !== root) {
514
- const row = button.closest('[class*="logoRow"]');
515
- const base = (row !== null && row.parentElement === root) ? row : button;
516
- const family = Array.from(root.children).filter(
517
- (el) => el instanceof HTMLElement && el.matches("[data-dsh-taskboard-entry], [data-dsh-ssh-entry], [data-dsh-logcat-entry], [data-dsh-eda-entry]"),
518
- );
519
- const anchor = family.length > 0 ? family[family.length - 1].nextElementSibling : base.nextElementSibling;
520
- root.insertBefore(entry, anchor);
521
- }
522
- return true;
523
- }
524
-
525
- function mountSidebarEntry(controller) {
526
- const entry = createEntry(controller);
651
+ function mountSidebarEntry(store) {
652
+ const entry = createEntry(store);
527
653
  let root;
528
654
  let placed = false;
529
655
  let rootObserver;
530
-
531
- const tryPlace = () => {
532
- if (root !== undefined && !root.isConnected) {
533
- rootObserver?.disconnect();
534
- root = undefined;
535
- placed = false;
656
+ const place = () => {
657
+ const button = newSessionButton(root);
658
+ if (button === undefined) return false;
659
+ if (entry.parentElement !== root) {
660
+ const row = button.closest('[class*="logoRow"]');
661
+ const base = row !== null && row.parentElement === root ? row : button;
662
+ const family = Array.from(root.children).filter((el) =>
663
+ el instanceof HTMLElement && el.matches("[data-dsh-taskboard-entry], [data-dsh-ssh-entry], [data-dsh-logcat-entry], [data-dsh-eda-entry]"));
664
+ const anchor = family.length > 0 ? family[family.length - 1].nextElementSibling : base.nextElementSibling;
665
+ root.insertBefore(entry, anchor);
536
666
  }
537
- if (placed) {
538
- if (document.body.contains(entry)) return;
667
+ return true;
668
+ };
669
+ const tryPlace = () => {
670
+ if (root !== undefined && (!root.isConnected || (placed && !document.body.contains(entry)))) {
539
671
  rootObserver?.disconnect();
540
672
  root = undefined;
541
673
  placed = false;
542
674
  }
675
+ if (placed) return;
543
676
  root ??= sidebarRoot();
544
677
  if (root === undefined) return;
545
- placed = placeEntry(root, entry);
678
+ placed = place();
546
679
  if (placed) {
547
680
  rootObserver = new MutationObserver(() => {
548
681
  if (root === undefined || !root.isConnected) { placed = false; tryPlace(); return; }
549
- if (!root.contains(entry)) placed = placeEntry(root, entry);
682
+ if (!root.contains(entry)) placed = place();
550
683
  });
551
684
  rootObserver.observe(root, { childList: true, subtree: true });
552
685
  }
553
686
  };
554
-
555
- const waitObserver = new MutationObserver(() => { tryPlace(); });
687
+ const waitObserver = new MutationObserver(() => tryPlace());
556
688
  waitObserver.observe(document.body, { childList: true, subtree: true });
557
-
558
- const syncActive = () => {
559
- if (controller.getSnapshot().panelOpen) entry.dataset.active = "true";
560
- else delete entry.dataset.active;
561
- };
562
- const unsubscribe = controller.subscribe(syncActive);
563
- syncActive();
689
+ const sync = () => { if (store.get()) entry.dataset.active = "true"; else delete entry.dataset.active; };
690
+ const unsubscribe = store.subscribe(sync);
691
+ sync();
564
692
  tryPlace();
565
-
566
693
  return () => {
567
694
  waitObserver.disconnect();
568
695
  rootObserver?.disconnect();
@@ -571,86 +698,83 @@ window.__ModuleLoader__.load({
571
698
  };
572
699
  }
573
700
 
574
- function mountPanel(controller) {
575
- let root;
576
- let container;
577
- const ensure = () => {
578
- if (container !== undefined && container.isConnected) return;
579
- root?.unmount();
580
- root = undefined;
581
- container?.remove();
582
- container = document.createElement("div");
583
- container.dataset.dshEdaView = "";
584
- container.className = "dsh-eda-view";
585
- container.hidden = true; // side-drawer: hidden until the sidebar entry is clicked
586
- const panel = document.createElement("div");
587
- panel.className = "dsh-eda-panel";
588
- container.appendChild(panel);
589
- document.body.appendChild(container);
590
- root = createRoot(panel);
591
- root.render(h(EdaPanel, { controller }));
592
- };
593
-
594
- ensure();
595
-
596
- const applyOpen = () => {
597
- if (container !== undefined) container.hidden = !controller.getSnapshot().panelOpen;
598
- };
599
- const unsubscribe = controller.subscribe(applyOpen);
600
- applyOpen();
601
-
701
+ /**
702
+ * Fallback mount for shells without the slots service (and for the unit
703
+ * test's DOM stub): a body-level overlay. Still absolute-in-shell friendly:
704
+ * z-index stays low (40) and the panel keeps its own close affordance.
705
+ */
706
+ function mountFallback(store) {
707
+ const container = document.createElement("div");
708
+ container.dataset.dshEdaView = "";
709
+ container.className = "dsh-eda-fallback";
710
+ const root = createRoot(container);
711
+ document.body.appendChild(container);
712
+ root.render(h(EdaOverlay, { store }));
602
713
  return () => {
603
- unsubscribe();
604
- root?.unmount();
605
- root = undefined;
606
- container?.remove();
607
- container = undefined;
714
+ root.unmount();
715
+ container.remove();
608
716
  };
609
717
  }
610
718
  //#endregion
611
719
 
612
- //#region controller
613
- /** Minimal open/close controller: panelOpen + a tiny subscribe store. */
614
- function PanelController() {
615
- let panelOpen = false;
616
- const listeners = new Set();
617
- this.toggle = () => { panelOpen = !panelOpen; for (const fn of listeners) fn(); };
618
- this.getSnapshot = () => ({ panelOpen });
619
- this.subscribe = (fn) => { listeners.add(fn); return () => { listeners.delete(fn); }; };
620
- }
621
- //#endregion
622
-
623
720
  //#region entry
624
- /** Required services (fiber inject waiting — the runtime must be up first). */
625
721
  const inject = ["slots"];
626
722
 
627
723
  /**
628
- * Mount the 嘉立创 EDA 助手 panel.
724
+ * Mount the panel: 0.2 registers into `shell.overlay` + a header utility pill;
725
+ * 0.1.x keeps the sidebar DOM entry. Anything unavailable degrades quietly.
629
726
  * @param ctx - client root context.
630
727
  */
631
728
  function apply(ctx) {
632
729
  const style = document.createElement("style");
633
- style.textContent = STYLE;
730
+ style.textContent = STYLE + "\n.dsh-eda-fallback { position: fixed; inset: 0; pointer-events: none; z-index: 40; }\n.dsh-eda-fallback > .dsh-eda-root { pointer-events: auto; }";
634
731
  style.dataset.dshEdaStyle = "";
635
732
  document.head.appendChild(style);
636
733
 
637
- const controller = new PanelController();
734
+ const store = new PanelStore();
638
735
  const disposers = [];
736
+ let slotRegistered = false;
737
+
639
738
  try {
640
- disposers.push(mountSidebarEntry(controller));
641
- disposers.push(mountPanel(controller));
739
+ const slots = typeof ctx.get === "function" ? ctx.get("slots") : undefined;
740
+ if (slots !== undefined && slots !== null) {
741
+ disposers.push(slots.inject("conversation.session.header.utilities", () => slots.register(
742
+ { name: "conversation.session.header.utilities", id: "eda-toggle", order: 30 },
743
+ () => h(HeaderPill, { store }),
744
+ )));
745
+ disposers.push(slots.inject("shell.overlay", () => slots.register(
746
+ { name: "shell.overlay", id: "eda", order: 90 },
747
+ () => h(EdaOverlay, { store }),
748
+ )));
749
+ slotRegistered = true;
750
+ }
642
751
  } catch (error) {
643
- console.warn("[dsh-eda] mount failed:", error);
752
+ console.warn("[dsh-eda] slot registration failed, falling back to DOM mount", error);
644
753
  }
754
+
755
+ try {
756
+ disposers.push(mountSidebarEntry(store));
757
+ } catch (error) {
758
+ console.warn("[dsh-eda] sidebar entry failed", error);
759
+ }
760
+ if (!slotRegistered) {
761
+ try {
762
+ disposers.push(mountFallback(store));
763
+ } catch (error) {
764
+ console.warn("[dsh-eda] fallback mount failed", error);
765
+ }
766
+ }
767
+
645
768
  ctx.effect(() => () => {
646
769
  for (const dispose of disposers.splice(0)) dispose();
647
770
  style.remove();
648
- }, "dsh-eda: ui mounts");
771
+ }, "dsh-eda: browser UI");
649
772
  }
650
- //#endregion
651
773
 
652
774
  exports.apply = apply;
653
775
  exports.inject = inject;
776
+ // Test seam (bundle runtime test renders the update pill directly).
777
+ exports.UpdatePill = UpdatePill;
654
778
  return module.exports;
655
- }
779
+ },
656
780
  });