cardbuddy 0.11.0 → 0.12.1

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 (313) hide show
  1. package/README.md +46 -5
  2. package/dist/cli.js +51 -1
  3. package/dist/config.js +51 -16
  4. package/dist/core.js +2 -2
  5. package/dist/init.js +425 -0
  6. package/dist/preview-editor/assets/index-CHuGGIR3.js +276 -0
  7. package/dist/preview-editor/assets/{index-B4VZgNSK.css → index-CQScMhyg.css} +1 -1
  8. package/dist/preview-editor/index.html +2 -2
  9. package/dist/standalone.js +8 -0
  10. package/dist/vendored/mcp/client.mjs +537 -0
  11. package/dist/vendored/mcp/tools.mjs +268 -0
  12. package/dist/vendored/preview/assets/default-image.png +0 -0
  13. package/dist/{server-core → vendored/server/core}/ai-chat.js +82 -38
  14. package/dist/{server-core → vendored/server/core}/browser.js +1 -1
  15. package/dist/{server-core → vendored/server/core}/cardSave.js +8 -3
  16. package/dist/{server-core → vendored/server/core}/cardSync.js +6 -14
  17. package/dist/{server-core → vendored/server/core}/cardValidate.js +11 -8
  18. package/dist/{server-core → vendored/server/core}/index.js +5 -3
  19. package/dist/vendored/server/core/skillPaths.js +124 -0
  20. package/dist/{server-core → vendored/server/core}/sliceUpload.js +5 -8
  21. package/dist/vendored/skills/README.md +93 -0
  22. package/dist/vendored/skills/card-doctor/SKILL.md +52 -0
  23. package/dist/vendored/skills/card-skill-trainer/SKILL.md +312 -0
  24. package/dist/vendored/skills/card-skill-trainer/baselines/v3-r038n.json +43 -0
  25. package/dist/vendored/skills/card-skill-trainer/baselines/v3-r039n.json +47 -0
  26. package/dist/vendored/skills/card-skill-trainer/baselines/v3-r050n.json +48 -0
  27. package/dist/vendored/skills/card-skill-trainer/scripts/build_dataset.py +472 -0
  28. package/dist/vendored/skills/card-skill-trainer/scripts/build_sample.mjs +162 -0
  29. package/dist/vendored/skills/card-skill-trainer/scripts/diagnose_case.mjs +241 -0
  30. package/dist/vendored/skills/card-skill-trainer/scripts/lib/scoring.mjs +525 -0
  31. package/dist/vendored/skills/card-skill-trainer/scripts/round_diff.mjs +133 -0
  32. package/dist/vendored/skills/card-skill-trainer/scripts/run_round.mjs +1043 -0
  33. package/dist/vendored/skills/card-skill-trainer/scripts/score_round.mjs +195 -0
  34. package/dist/vendored/skills/card-skill-trainer/scripts/test_missing_slice.py +122 -0
  35. package/dist/vendored/skills/dsl-card-ai/SKILL.md +191 -0
  36. package/dist/vendored/skills/dsl-card-generator/SKILL.md +480 -0
  37. package/dist/vendored/skills/dsl-card-generator/config/render-contract.json +11 -0
  38. package/dist/vendored/skills/dsl-card-generator/references/amount_formatting.md +138 -0
  39. package/dist/vendored/skills/dsl-card-generator/references/card_index.json +1597 -0
  40. package/dist/vendored/skills/dsl-card-generator/references/card_templates.json +384 -0
  41. package/dist/vendored/skills/dsl-card-generator/references/card_to_summary.md +56 -0
  42. package/dist/vendored/skills/dsl-card-generator/references/component_rules.md +76 -0
  43. package/dist/vendored/skills/dsl-card-generator/references/component_specs.md +393 -0
  44. package/dist/vendored/skills/dsl-card-generator/references/dsl_structure.md +208 -0
  45. package/dist/vendored/skills/dsl-card-generator/references/event_patterns.md +287 -0
  46. package/dist/vendored/skills/dsl-card-generator/references/expression_engine.md +121 -0
  47. package/dist/vendored/skills/dsl-card-generator/references/field_name_dict.json +34 -0
  48. package/dist/vendored/skills/dsl-card-generator/references/field_naming.md +101 -0
  49. package/dist/vendored/skills/dsl-card-generator/references/generation_pitfalls.md +928 -0
  50. package/dist/vendored/skills/dsl-card-generator/references/handcrafted/README.md +69 -0
  51. package/dist/vendored/skills/dsl-card-generator/references/handcrafted/examples_index.json +2967 -0
  52. package/dist/vendored/skills/dsl-card-generator/references/handcrafted/patterns.json +2835 -0
  53. package/dist/vendored/skills/dsl-card-generator/references/handcrafted/recipes_v2.json +648 -0
  54. package/dist/vendored/skills/dsl-card-generator/references/handcrafted/recipes_v2_schema.md +295 -0
  55. package/dist/vendored/skills/dsl-card-generator/references/image_diff.md +48 -0
  56. package/dist/vendored/skills/dsl-card-generator/references/image_to_card.md +129 -0
  57. package/dist/vendored/skills/dsl-card-generator/references/ir-format.md +212 -0
  58. package/dist/vendored/skills/dsl-card-generator/references/message-center-pattern.md +149 -0
  59. package/dist/vendored/skills/dsl-card-generator/references/platform_jsapi.md +196 -0
  60. package/dist/vendored/skills/dsl-card-generator/references/previewer_contract.md +54 -0
  61. package/dist/vendored/skills/dsl-card-generator/references/quickref.md +197 -0
  62. package/dist/vendored/skills/dsl-card-generator/references/recipe_snippets/absolute-badge.json +84 -0
  63. package/dist/vendored/skills/dsl-card-generator/references/recipe_snippets/accordion-group-toggle.json +18 -0
  64. package/dist/vendored/skills/dsl-card-generator/references/recipe_snippets/alertCard-pair.json +12 -0
  65. package/dist/vendored/skills/dsl-card-generator/references/recipe_snippets/alertDialog-call.json +12 -0
  66. package/dist/vendored/skills/dsl-card-generator/references/recipe_snippets/canvas-countdown.json +15 -0
  67. package/dist/vendored/skills/dsl-card-generator/references/recipe_snippets/canvas-donut.json +15 -0
  68. package/dist/vendored/skills/dsl-card-generator/references/recipe_snippets/canvas-gauge-score.json +11 -0
  69. package/dist/vendored/skills/dsl-card-generator/references/recipe_snippets/canvas-radar.json +10 -0
  70. package/dist/vendored/skills/dsl-card-generator/references/recipe_snippets/canvas-title-head.json +13 -0
  71. package/dist/vendored/skills/dsl-card-generator/references/recipe_snippets/globalSet.json +12 -0
  72. package/dist/vendored/skills/dsl-card-generator/references/recipe_snippets/label-col-modes.json +21 -0
  73. package/dist/vendored/skills/dsl-card-generator/references/recipe_snippets/list-expand-collapse.json +17 -0
  74. package/dist/vendored/skills/dsl-card-generator/references/recipe_snippets/money-format.json +11 -0
  75. package/dist/vendored/skills/dsl-card-generator/references/recipe_snippets/opacity-switch.json +130 -0
  76. package/dist/vendored/skills/dsl-card-generator/references/recipe_snippets/progress-bar.json +25 -0
  77. package/dist/vendored/skills/dsl-card-generator/references/recipe_snippets/tab-billMode.json +15 -0
  78. package/dist/vendored/skills/dsl-card-generator/references/recipe_snippets/title-underline-overlay.json +21 -0
  79. package/dist/vendored/skills/dsl-card-generator/references/recipes.md +797 -0
  80. package/dist/vendored/skills/dsl-card-generator/references/rules.md +235 -0
  81. package/dist/vendored/skills/dsl-card-generator/references/slices_convention.md +177 -0
  82. package/dist/vendored/skills/dsl-card-generator/references/spec_to_schema_patterns.md +609 -0
  83. package/dist/vendored/skills/dsl-card-generator/references/ui_fidelity_rules.md +131 -0
  84. package/dist/vendored/skills/dsl-card-generator/scripts/add_component.mjs +118 -0
  85. package/dist/vendored/skills/dsl-card-generator/scripts/analyze_component_usage.mjs +153 -0
  86. package/dist/vendored/skills/dsl-card-generator/scripts/apply_opacity_pattern.mjs +343 -0
  87. package/dist/vendored/skills/dsl-card-generator/scripts/build_card_index.mjs +108 -0
  88. package/dist/vendored/skills/dsl-card-generator/scripts/build_card_templates.mjs +190 -0
  89. package/dist/vendored/skills/dsl-card-generator/scripts/check_fidelity.mjs +257 -0
  90. package/dist/vendored/skills/dsl-card-generator/scripts/check_magic_values.mjs +79 -0
  91. package/dist/vendored/skills/dsl-card-generator/scripts/crop_slices.mjs +98 -0
  92. package/dist/vendored/skills/dsl-card-generator/scripts/describe_card.mjs +265 -0
  93. package/dist/vendored/skills/dsl-card-generator/scripts/diff_bands.mjs +257 -0
  94. package/dist/vendored/skills/dsl-card-generator/scripts/diff_card.mjs +316 -0
  95. package/dist/vendored/skills/dsl-card-generator/scripts/expand_ir.mjs +873 -0
  96. package/dist/vendored/skills/dsl-card-generator/scripts/extract_handcrafted.py +1199 -0
  97. package/dist/vendored/skills/dsl-card-generator/scripts/extract_subtree.mjs +191 -0
  98. package/dist/vendored/skills/dsl-card-generator/scripts/generate_cards.mjs +389 -0
  99. package/dist/vendored/skills/dsl-card-generator/scripts/inventory_schemas.py +160 -0
  100. package/dist/vendored/skills/dsl-card-generator/scripts/iterate.mjs +700 -0
  101. package/dist/vendored/skills/dsl-card-generator/scripts/lib/design_image.mjs +56 -0
  102. package/dist/vendored/skills/dsl-card-generator/scripts/lib/design_sample.mjs +328 -0
  103. package/dist/vendored/skills/dsl-card-generator/scripts/lib/layout-tokens.mjs +79 -0
  104. package/dist/vendored/skills/dsl-card-generator/scripts/lib/paths.mjs +103 -0
  105. package/dist/vendored/skills/dsl-card-generator/scripts/lib/scaffold.mjs +575 -0
  106. package/dist/vendored/skills/dsl-card-generator/scripts/lib/slicePath.mjs +81 -0
  107. package/dist/vendored/skills/dsl-card-generator/scripts/lib/slice_dedupe.mjs +147 -0
  108. package/dist/vendored/skills/dsl-card-generator/scripts/lint_autofix.mjs +363 -0
  109. package/dist/vendored/skills/dsl-card-generator/scripts/lint_card.mjs +1399 -0
  110. package/dist/vendored/skills/dsl-card-generator/scripts/preflight.mjs +249 -0
  111. package/dist/vendored/skills/dsl-card-generator/scripts/register_card_template.mjs +208 -0
  112. package/dist/vendored/skills/dsl-card-generator/scripts/render_baseline.mjs +231 -0
  113. package/dist/vendored/skills/dsl-card-generator/scripts/render_card.mjs +801 -0
  114. package/dist/vendored/skills/dsl-card-generator/scripts/render_diff.mjs +239 -0
  115. package/dist/vendored/skills/dsl-card-generator/scripts/resolve_card_template.mjs +73 -0
  116. package/dist/vendored/skills/dsl-card-generator/scripts/route_input.mjs +447 -0
  117. package/dist/vendored/skills/dsl-card-generator/scripts/scaffold_card.mjs +81 -0
  118. package/dist/vendored/skills/dsl-card-generator/scripts/slices_normalize.mjs +316 -0
  119. package/dist/vendored/skills/dsl-card-generator/scripts/spec_audit.mjs +462 -0
  120. package/dist/vendored/skills/dsl-card-generator/scripts/spec_to_schema_v3.mjs +7735 -0
  121. package/dist/vendored/skills/dsl-card-generator/scripts/spec_tree.mjs +355 -0
  122. package/dist/vendored/skills/dsl-card-generator/scripts/validate_all_schemas.py +71 -0
  123. package/dist/vendored/skills/dsl-card-generator/vendor/preview/assets/default-image-wzZYQ86K.png +0 -0
  124. package/dist/vendored/skills/dsl-card-generator/vendor/preview/assets/standalone-C9k-07y7.css +1 -0
  125. package/dist/vendored/skills/dsl-card-generator/vendor/preview/assets/standalone-oFRM4f4V.js +55 -0
  126. package/dist/vendored/skills/dsl-card-generator/vendor/preview/assets/svg-symbols-B2exBrAr.svg +118 -0
  127. package/dist/vendored/skills/dsl-card-generator/vendor/preview/meta/component-meta.json +2714 -0
  128. package/dist/vendored/skills/dsl-card-generator/vendor/preview/meta/directive-meta.json +40 -0
  129. package/dist/vendored/skills/dsl-card-generator/vendor/preview/meta/style-meta.json +1086 -0
  130. package/dist/vendored/{standalone.html → skills/dsl-card-generator/vendor/preview/standalone.html} +2 -1
  131. package/dist/vendored/skills/finmall-card-sync/SKILL.md +262 -0
  132. package/dist/vendored/skills/finmall-session-navigator/SKILL.md +169 -0
  133. package/dist/vendored/skills/finmall-session-navigator/scripts/finmall_login.mjs +882 -0
  134. package/dist/vendored/skills/finmall-session-navigator/scripts/package-lock.json +59 -0
  135. package/dist/vendored/skills/finmall-session-navigator/scripts/package.json +10 -0
  136. package/dist/vendored/skills/finmall-session-navigator/scripts/session-manager.mjs +96 -0
  137. package/dist/vendored/skills/shared/README.md +55 -0
  138. package/dist/vendored/skills/shared/auth-model.md +79 -0
  139. package/dist/vendored/skills/sketch-spec-to-card/SKILL.md +329 -0
  140. package/dist/vendored/skills/sketch-spec-to-card/references/boundary.json +14 -0
  141. package/dist/vendored/skills/sketch-spec-to-card/references/card_refs.json +13 -0
  142. package/dist/vendored/skills/sketch-spec-to-card/references/spec-schema.md +103 -0
  143. package/dist/vendored/skills/sketch-spec-to-card/scripts/build_prompt.py +797 -0
  144. package/dist/vendored/skills/sketch-spec-to-card/scripts/card_refs.py +94 -0
  145. package/dist/vendored/skills/sketch-spec-to-card/scripts/cluster_states.py +706 -0
  146. package/dist/vendored/skills/sketch-spec-to-card/scripts/parse_meaxure.py +1781 -0
  147. package/dist/vendored/skills/sketch-spec-to-card/scripts/png_utils.py +318 -0
  148. package/dist/vendored/skills/sketch-spec-to-card/scripts/vision.py +1118 -0
  149. package/dist/vendored/templates/helloCard/data.json +10 -0
  150. package/dist/vendored/templates/helloCard/schema.json +238 -0
  151. package/dist/vendored/tools/link-skills.mjs +485 -0
  152. package/package.json +2 -1
  153. package/dist/preview-editor/assets/index-jl4YJzKv.js +0 -180
  154. package/dist/vendored/App.vue +0 -2858
  155. package/dist/vendored/ansi.js +0 -185
  156. package/dist/vendored/assets/apple-touch-icon.png +0 -0
  157. package/dist/vendored/assets/default-image.png +0 -0
  158. package/dist/vendored/assets/favicon-16.png +0 -0
  159. package/dist/vendored/assets/favicon-32.png +0 -0
  160. package/dist/vendored/assets/site-icon.png +0 -0
  161. package/dist/vendored/assets/svgIcons/icons.svg +0 -87
  162. package/dist/vendored/assets/svgIcons/index.js +0 -39
  163. package/dist/vendored/components/AiSettings.vue +0 -392
  164. package/dist/vendored/components/AlertCardInstance.vue +0 -58
  165. package/dist/vendored/components/AlertCardLayer.vue +0 -59
  166. package/dist/vendored/components/ApiCallPanel.vue +0 -127
  167. package/dist/vendored/components/ApiPayloadTree.vue +0 -201
  168. package/dist/vendored/components/AppToast.vue +0 -37
  169. package/dist/vendored/components/CardGallery.vue +0 -291
  170. package/dist/vendored/components/CardPreview.vue +0 -72
  171. package/dist/vendored/components/CardSelect.vue +0 -206
  172. package/dist/vendored/components/ChatComposer.vue +0 -413
  173. package/dist/vendored/components/ChatMessage.vue +0 -383
  174. package/dist/vendored/components/ChatPanel.vue +0 -937
  175. package/dist/vendored/components/ComponentPalette.vue +0 -301
  176. package/dist/vendored/components/ConfirmDialog.vue +0 -54
  177. package/dist/vendored/components/DatePickerOverlay.vue +0 -345
  178. package/dist/vendored/components/DebugPanel.vue +0 -1734
  179. package/dist/vendored/components/DeviceOverlay.vue +0 -70
  180. package/dist/vendored/components/Dropdown.vue +0 -193
  181. package/dist/vendored/components/EventEditor.vue +0 -273
  182. package/dist/vendored/components/HoverGuides.vue +0 -122
  183. package/dist/vendored/components/JsonTree.vue +0 -547
  184. package/dist/vendored/components/LogValue.vue +0 -52
  185. package/dist/vendored/components/MarkdownBody.vue +0 -64
  186. package/dist/vendored/components/NewCardDialog.vue +0 -132
  187. package/dist/vendored/components/NodeInspector.vue +0 -295
  188. package/dist/vendored/components/NumberStepper.vue +0 -125
  189. package/dist/vendored/components/PickerOverlay.vue +0 -131
  190. package/dist/vendored/components/PropControl.vue +0 -245
  191. package/dist/vendored/components/PropTree.vue +0 -128
  192. package/dist/vendored/components/RemotePreview.vue +0 -173
  193. package/dist/vendored/components/SelectionOverlay.vue +0 -105
  194. package/dist/vendored/components/StructureTree.vue +0 -1002
  195. package/dist/vendored/components/Switch.vue +0 -38
  196. package/dist/vendored/components/setters/SetBgPosition.vue +0 -64
  197. package/dist/vendored/components/setters/SetBgSize.vue +0 -90
  198. package/dist/vendored/components/setters/SetCode.vue +0 -198
  199. package/dist/vendored/components/setters/SetColor.vue +0 -244
  200. package/dist/vendored/components/setters/SetCustomSelect.vue +0 -58
  201. package/dist/vendored/components/setters/SetExpr.vue +0 -107
  202. package/dist/vendored/components/setters/SetGradient.vue +0 -125
  203. package/dist/vendored/components/setters/SetGrid9.vue +0 -68
  204. package/dist/vendored/components/setters/SetIconSelect.vue +0 -67
  205. package/dist/vendored/components/setters/SetIfForm.vue +0 -61
  206. package/dist/vendored/components/setters/SetImage.vue +0 -43
  207. package/dist/vendored/components/setters/SetList.vue +0 -139
  208. package/dist/vendored/components/setters/SetNumber.vue +0 -118
  209. package/dist/vendored/components/setters/SetNumberStyle.vue +0 -113
  210. package/dist/vendored/components/setters/SetPadding.vue +0 -77
  211. package/dist/vendored/components/setters/SetSegment.vue +0 -160
  212. package/dist/vendored/components/setters/SetSelect.vue +0 -51
  213. package/dist/vendored/components/setters/SetSwitch.vue +0 -49
  214. package/dist/vendored/components/setters/SetText.vue +0 -52
  215. package/dist/vendored/components/setters/props.js +0 -23
  216. package/dist/vendored/fidelity/baseline-messageOverview.json +0 -87
  217. package/dist/vendored/fidelity/calibration.json +0 -29
  218. package/dist/vendored/fidelity/fidelity-messageOverview-after.html +0 -114
  219. package/dist/vendored/fidelity/fidelity-messageOverview-after.json +0 -272
  220. package/dist/vendored/fidelity/fidelity-messageOverview.html +0 -185
  221. package/dist/vendored/fidelity/fidelity-messageOverview.json +0 -336
  222. package/dist/vendored/fidelity/fidelity-messageOverview_v2.html +0 -262
  223. package/dist/vendored/fidelity/fidelity-messageOverview_v2.json +0 -502
  224. package/dist/vendored/fidelity/fidelity-messageOverview_v3.html +0 -201
  225. package/dist/vendored/fidelity/fidelity-messageOverview_v3.json +0 -417
  226. package/dist/vendored/fidelity/fidelity-messageOverview_visual.html +0 -125
  227. package/dist/vendored/fidelity/fidelity-messageOverview_visual.json +0 -338
  228. package/dist/vendored/index.html +0 -16
  229. package/dist/vendored/main.js +0 -37
  230. package/dist/vendored/runtime/ai-api.js +0 -165
  231. package/dist/vendored/runtime/alert-card.js +0 -125
  232. package/dist/vendored/runtime/app-toast.js +0 -33
  233. package/dist/vendored/runtime/clipboard-node.js +0 -78
  234. package/dist/vendored/runtime/clipboard.js +0 -29
  235. package/dist/vendored/runtime/event-model.js +0 -300
  236. package/dist/vendored/runtime/hoverGuide.js +0 -31
  237. package/dist/vendored/runtime/jsapi-mock.js +0 -256
  238. package/dist/vendored/runtime/markdown.js +0 -140
  239. package/dist/vendored/runtime/node-model.js +0 -217
  240. package/dist/vendored/skills/.manifest.json +0 -1101
  241. package/dist/vendored/standalone-main.js +0 -36
  242. package/dist/vendored/styles/ai-chat.css +0 -1850
  243. package/dist/vendored/styles/app.css +0 -3648
  244. package/dist/vendored/styles/card-gallery.css +0 -285
  245. package/dist/vendored/styles/card-select.css +0 -288
  246. package/dist/vendored/styles/components.css +0 -383
  247. package/dist/vendored/styles/dropdown.css +0 -324
  248. package/dist/vendored/styles/json-tree.css +0 -308
  249. package/dist/vendored/styles/node-inspector.css +0 -800
  250. package/dist/vendored/styles/setters.css +0 -1050
  251. package/dist/vendored/styles/standalone.css +0 -27
  252. package/dist/vendored/styles/structure-tree.css +0 -460
  253. /package/dist/vendored/{api.js → preview/api.js} +0 -0
  254. /package/dist/vendored/{assets → preview/assets}/svg-symbols.svg +0 -0
  255. /package/dist/vendored/{components → preview/components}/AbsoluteLayout.vue +0 -0
  256. /package/dist/vendored/{components → preview/components}/Button.vue +0 -0
  257. /package/dist/vendored/{components → preview/components}/Canvas.vue +0 -0
  258. /package/dist/vendored/{components → preview/components}/CheckGroup.vue +0 -0
  259. /package/dist/vendored/{components → preview/components}/Column.vue +0 -0
  260. /package/dist/vendored/{components → preview/components}/CustomPlaceholder.vue +0 -0
  261. /package/dist/vendored/{components → preview/components}/Divider.vue +0 -0
  262. /package/dist/vendored/{components → preview/components}/GridLayout.vue +0 -0
  263. /package/dist/vendored/{components → preview/components}/Icon.vue +0 -0
  264. /package/dist/vendored/{components → preview/components}/Image.vue +0 -0
  265. /package/dist/vendored/{components → preview/components}/Input.vue +0 -0
  266. /package/dist/vendored/{components → preview/components}/ListLayout.vue +0 -0
  267. /package/dist/vendored/{components → preview/components}/Map.vue +0 -0
  268. /package/dist/vendored/{components → preview/components}/MultiColumn.vue +0 -0
  269. /package/dist/vendored/{components → preview/components}/MultiText.vue +0 -0
  270. /package/dist/vendored/{components → preview/components}/ProgressSlider.vue +0 -0
  271. /package/dist/vendored/{components → preview/components}/RadioButton.vue +0 -0
  272. /package/dist/vendored/{components → preview/components}/RenderTree.vue +0 -0
  273. /package/dist/vendored/{components → preview/components}/Root.vue +0 -0
  274. /package/dist/vendored/{components → preview/components}/Row.vue +0 -0
  275. /package/dist/vendored/{components → preview/components}/SvgCode.vue +0 -0
  276. /package/dist/vendored/{components → preview/components}/SvgSymbols.vue +0 -0
  277. /package/dist/vendored/{components → preview/components}/Text.vue +0 -0
  278. /package/dist/vendored/{components → preview/components}/Video.vue +0 -0
  279. /package/dist/vendored/{components → preview/components}/ViewContainer.vue +0 -0
  280. /package/dist/vendored/{components → preview/components}/base.js +0 -0
  281. /package/dist/vendored/{components → preview/components}/icons.js +0 -0
  282. /package/dist/vendored/{components → preview/components}/index.js +0 -0
  283. /package/dist/vendored/{meta → preview/meta}/component-meta.json +0 -0
  284. /package/dist/vendored/{meta → preview/meta}/directive-meta.json +0 -0
  285. /package/dist/vendored/{meta → preview/meta}/style-meta.json +0 -0
  286. /package/dist/vendored/{runtime → preview/runtime}/StyleParser.js +0 -0
  287. /package/dist/vendored/{runtime → preview/runtime}/adapter.js +0 -0
  288. /package/dist/vendored/{runtime → preview/runtime}/assets.js +0 -0
  289. /package/dist/vendored/{runtime → preview/runtime}/canvas-context.js +0 -0
  290. /package/dist/vendored/{runtime → preview/runtime}/card-runtime.js +0 -0
  291. /package/dist/vendored/{runtime → preview/runtime}/evaluate.js +0 -0
  292. /package/dist/vendored/{runtime → preview/runtime}/property.js +0 -0
  293. /package/dist/vendored/{runtime → preview/runtime}/selectionOverlay.js +0 -0
  294. /package/dist/vendored/{runtime → preview/runtime}/toPreview.js +0 -0
  295. /package/dist/{server-core → vendored/server/core}/assetProxy.js +0 -0
  296. /package/dist/{server-core → vendored/server/core}/bbox.js +0 -0
  297. /package/dist/{server-core → vendored/server/core}/buildDataFromSchema.js +0 -0
  298. /package/dist/{server-core → vendored/server/core}/cardFiles.js +0 -0
  299. /package/dist/{server-core → vendored/server/core}/cardHistory.js +0 -0
  300. /package/dist/{server-core → vendored/server/core}/cardImage.js +0 -0
  301. /package/dist/{server-core → vendored/server/core}/cardImportMeta.js +0 -0
  302. /package/dist/{server-core → vendored/server/core}/cardListCache.js +0 -0
  303. /package/dist/{server-core → vendored/server/core}/cardOpenFolder.js +0 -0
  304. /package/dist/{server-core → vendored/server/core}/cardSidecar.js +0 -0
  305. /package/dist/{server-core → vendored/server/core}/codeBridge.js +0 -0
  306. /package/dist/{server-core → vendored/server/core}/logStream.js +0 -0
  307. /package/dist/{server-core → vendored/server/core}/logger.js +0 -0
  308. /package/dist/{server-core → vendored/server/core}/nodeModels.js +0 -0
  309. /package/dist/{server-core → vendored/server/core}/renderStatus.js +0 -0
  310. /package/dist/{server-core → vendored/server/core}/screenshot.js +0 -0
  311. /package/dist/{server-core → vendored/server/core}/sliceStatic.js +0 -0
  312. /package/dist/vendored/{meta → skills/dsl-card-generator/vendor/preview/meta}/action-meta.json +0 -0
  313. /package/dist/{server-core/_vendor → vendored/tools}/finmall-env.mjs +0 -0
@@ -1,206 +0,0 @@
1
- <template>
2
- <div ref="root" class="csel" :class="{ 'csel--open': open }">
3
- <button
4
- type="button"
5
- class="csel__trigger"
6
- :class="{ 'csel__trigger--active': open }"
7
- @click="toggle"
8
- >
9
- <span class="csel__current">
10
- <span class="csel__id">{{ current.id }}</span>
11
- <span class="csel__name">{{ current.name }}</span>
12
- </span>
13
- <svg class="csel__chev" viewBox="0 0 16 16" width="14" height="14" aria-hidden="true"><use href="#icon-chevron" /></svg>
14
- </button>
15
-
16
- <transition name="csel-fade">
17
- <div v-if="open" class="csel__pop">
18
- <div class="csel__search">
19
- <svg class="csel__search-icon" viewBox="0 0 16 16" width="13" height="13" aria-hidden="true"><use href="#icon-search" /></svg>
20
- <input
21
- ref="search"
22
- v-model="query"
23
- class="csel__input"
24
- type="text"
25
- placeholder="搜索卡片 ID / 名称…"
26
- @keydown.down.prevent="move(1)"
27
- @keydown.up.prevent="move(-1)"
28
- @keydown.enter.prevent="choose(filtered[highlighted])"
29
- @keydown.esc.prevent="close"
30
- />
31
- </div>
32
- <ul ref="list" class="csel__list">
33
- <li
34
- v-for="(opt, i) in filtered"
35
- :key="opt.id"
36
- :class="[
37
- 'csel__item',
38
- {
39
- 'csel__item--active': i === highlighted,
40
- 'csel__item--selected': opt.id === value,
41
- },
42
- ]"
43
- @mousemove="highlighted = i"
44
- @click="choose(opt)"
45
- >
46
- <span
47
- class="csel__dot"
48
- :class="{ 'csel__dot--imported': opt.imported }"
49
- :title="opt.imported ? '导入卡片(含 .import-meta.json 来源信息)' : '本地卡片(无导入来源信息)'"
50
- aria-hidden="true"
51
- ></span>
52
- <span class="csel__item-id">{{ opt.id }}</span>
53
- <span class="csel__item-name">{{ opt.name }}</span>
54
- <svg v-if="opt.id === value" class="csel__check" viewBox="0 0 16 16" width="14" height="14" aria-hidden="true"><use href="#icon-check" /></svg>
55
- </li>
56
- <li v-if="!filtered.length" class="csel__empty">无匹配卡片</li>
57
- </ul>
58
- <div class="csel__foot">
59
- <button
60
- class="csel__sort"
61
- :class="{ 'csel__sort--active': sortByTime }"
62
- type="button"
63
- :title="sortByTime ? '已按修改时间排序(新→旧),点击取消' : '按修改时间排序(新→旧)'"
64
- :aria-pressed="sortByTime"
65
- @click="toggleSort"
66
- >按修改时间排序</button>
67
- <span class="csel__count">{{ filtered.length }} / {{ options.length }} 张卡片</span>
68
- </div>
69
- </div>
70
- </transition>
71
- </div>
72
- </template>
73
-
74
- <script>
75
- export default {
76
- name: 'CardSelect',
77
- // 必须声明 emits:否则父组件的 @change 会作为 onChange 透传到根 div,
78
- // 内部搜索框 <input> 的原生 change 事件冒泡上来会再次触发父级 onSelect,
79
- // 把 selectedId 覆盖成 Event 对象(表现为搜索后选卡片不生效)。
80
- emits: ['input', 'change'],
81
- props: {
82
- value: { type: String, default: '' },
83
- options: { type: Array, default: () => [] },
84
- },
85
- data() {
86
- return {
87
- open: false,
88
- query: '',
89
- highlighted: 0,
90
- // 排序开关:false=按名称(默认),true=按修改时间新→旧
91
- // 初始值从 localStorage 读取,保证刷新后仍保持上次选择
92
- sortByTime: this.loadSortByTime(),
93
- }
94
- },
95
- created() {
96
- // 仅确保 data 阶段读取的持久化值已落盘(无记录时建立基线)
97
- this.saveSortByTime()
98
- },
99
- computed: {
100
- current() {
101
- return (
102
- this.options.find((o) => o.id === this.value) || {
103
- id: this.value,
104
- name: this.value,
105
- }
106
- )
107
- },
108
- filtered() {
109
- const q = this.query.trim().toLowerCase()
110
- let arr = this.options
111
- if (q) {
112
- arr = this.options.filter(
113
- (o) =>
114
- o.id.toLowerCase().includes(q) ||
115
- String(o.name || '').toLowerCase().includes(q)
116
- )
117
- }
118
- // 排序:时间模式按修改时间新→旧;否则按名称(默认)
119
- const sorted = this.sortByTime
120
- ? arr.slice().sort((a, b) => (b.mtime || 0) - (a.mtime || 0))
121
- : arr.slice().sort((a, b) =>
122
- String(a.name || '').localeCompare(String(b.name || ''))
123
- )
124
- return sorted
125
- },
126
- },
127
- watch: {
128
- open(v) {
129
- if (v) {
130
- this.query = ''
131
- this.highlighted = Math.max(0, this.filtered.findIndex((o) => o.id === this.value))
132
- this.$nextTick(() => {
133
- if (this.$refs.search) this.$refs.search.focus()
134
- this.scrollToActive()
135
- })
136
- document.addEventListener('click', this.onDocClick, true)
137
- } else {
138
- document.removeEventListener('click', this.onDocClick, true)
139
- }
140
- },
141
- // 切换排序方式时立即持久化,避免每次刷新都要手动再点一次
142
- sortByTime(v) {
143
- this.saveSortByTime()
144
- },
145
- },
146
- beforeUnmount() {
147
- document.removeEventListener('click', this.onDocClick, true)
148
- },
149
- methods: {
150
- toggle() {
151
- this.open = !this.open
152
- },
153
- /** 切换「按修改时间排序」:激活时列表新→旧;再次点击取消,回到按名称默认排序。
154
- * 切换后把高亮重新指回当前选中卡片,避免高亮错位到别的行。 */
155
- toggleSort() {
156
- this.sortByTime = !this.sortByTime
157
- this.highlighted = Math.max(0, this.filtered.findIndex((o) => o.id === this.value))
158
- },
159
- /** 读取持久化的排序方式(localStorage)。无记录或损坏时回退默认 false。 */
160
- loadSortByTime() {
161
- try {
162
- return localStorage.getItem('cardbuddy:cardselect-sort-by-time') === '1'
163
- } catch (e) {
164
- return false
165
- }
166
- },
167
- /** 持久化排序方式到 localStorage:'1'=按修改时间,'0'=按名称。 */
168
- saveSortByTime() {
169
- try {
170
- localStorage.setItem(
171
- 'cardbuddy:cardselect-sort-by-time',
172
- this.sortByTime ? '1' : '0'
173
- )
174
- } catch (e) {
175
- /* localStorage 不可用时忽略 */
176
- }
177
- },
178
- close() {
179
- this.open = false
180
- },
181
- onDocClick(e) {
182
- if (this.$refs.root && !this.$refs.root.contains(e.target)) this.close()
183
- },
184
- move(delta) {
185
- if (!this.filtered.length) return
186
- const n = this.filtered.length
187
- this.highlighted = (this.highlighted + delta + n) % n
188
- this.$nextTick(this.scrollToActive)
189
- },
190
- scrollToActive() {
191
- const list = this.$refs.list
192
- if (!list) return
193
- const el = list.children[this.highlighted]
194
- if (el && el.scrollIntoView) el.scrollIntoView({ block: 'nearest' })
195
- },
196
- choose(opt) {
197
- if (!opt) return
198
- this.close()
199
- if (opt.id !== this.value) {
200
- this.$emit('input', opt.id)
201
- this.$emit('change', opt.id)
202
- }
203
- },
204
- },
205
- }
206
- </script>
@@ -1,413 +0,0 @@
1
- <template>
2
- <div class="aicomp" :class="{ 'is-busy': busy, 'is-drag': dragOver, 'is-manual': heightPx > 0, 'is-resizing': resizing }" :style="compStyle">
3
- <!-- 上缘拖拽把手:调输入区高度(106px ~ 面板高度 50%,双击恢复自适应),与面板宽度把手同一套交互 -->
4
- <div
5
- class="aicomp__grip"
6
- :class="{ 'is-dragging': resizing }"
7
- title="拖拽调整输入区高度(双击恢复自适应)"
8
- @pointerdown.prevent="startResize"
9
- @dblclick.prevent="resetHeight"
10
- ></div>
11
-
12
- <!-- 已挂载的本地文件:只预览 + 传路径,不上传 -->
13
- <div v-if="attachments.length" class="aicomp__files">
14
- <div
15
- v-for="att in attachments"
16
- :key="att.path"
17
- class="aichip"
18
- :class="{ 'aichip--dir': att.isDir, 'aichip--pending': att.pending, 'aichip--missing': att.exists === false }"
19
- :title="att.path"
20
- >
21
- <img v-if="att.isImage && !att.pending" class="aichip__thumb" :src="fileUrl(att.path)" :alt="att.name" loading="lazy" />
22
- <svg v-else class="aichip__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
23
- <use :href="att.pending ? '#icon-loading' : att.isDir ? '#icon-folder-plus' : att.isImage ? '#icon-image' : '#icon-file-text'" />
24
- </svg>
25
- <span class="aichip__name">{{ att.pending ? '解析路径中…' : att.name }}</span>
26
- <span v-if="!att.pending" class="aichip__sub">{{ chipSub(att) }}</span>
27
- <button type="button" class="aichip__rm" title="移除" @click="$emit('remove-attachment', att.path)">
28
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><use href="#icon-x" /></svg>
29
- </button>
30
- </div>
31
- </div>
32
-
33
- <!-- 粘贴绝对路径(非 macOS / 拖拽反查失败时的兜底入口) -->
34
- <div v-if="pathInputOpen" class="aicomp__path">
35
- <input
36
- ref="pathEl"
37
- v-model="pathText"
38
- class="aicomp__path-input"
39
- type="text"
40
- placeholder="粘贴本地图片或文件夹的绝对路径,回车确认"
41
- spellcheck="false"
42
- @keydown.enter.prevent="confirmPath"
43
- @keydown.esc.stop.prevent="closePathInput"
44
- />
45
- <button type="button" class="aicomp__path-ok" :disabled="!pathText.trim()" @click="confirmPath">添加</button>
46
- <button type="button" class="aicomp__path-no" @click="closePathInput">取消</button>
47
- </div>
48
-
49
- <div
50
- class="aicomp__box"
51
- @dragenter.prevent="onDragEnter"
52
- @dragover.prevent="onDragOver"
53
- @dragleave.prevent="onDragLeave"
54
- @drop.prevent="onDrop"
55
- >
56
- <textarea
57
- ref="taEl"
58
- v-model="text"
59
- class="aicomp__ta"
60
- :placeholder="placeholder"
61
- rows="1"
62
- @input="autoGrow"
63
- @keydown="onKeydown"
64
- @paste="onPaste"
65
- ></textarea>
66
- <div class="aicomp__bar">
67
- <div class="aicomp__tools">
68
- <div class="aicomp__attach" ref="attachEl">
69
- <button type="button" class="aicomp__iconbtn" :class="{ 'is-open': attachOpen }" title="挂载本地图片 / 文件 / 文件夹" @click="toggleAttach">
70
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><use href="#icon-paperclip" /></svg>
71
- </button>
72
- <div v-if="attachOpen" class="aicomp__menu" role="menu">
73
- <button type="button" role="menuitem" @click="pick('image')">
74
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><use href="#icon-image" /></svg>
75
- 本地图片…
76
- </button>
77
- <button type="button" role="menuitem" @click="pick('file')">
78
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><use href="#icon-file-text" /></svg>
79
- 本地文件…
80
- </button>
81
- <button type="button" role="menuitem" @click="pick('folder')">
82
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><use href="#icon-folder-plus" /></svg>
83
- 本地文件夹…
84
- </button>
85
- <div class="aicomp__menu-sep"></div>
86
- <button type="button" role="menuitem" @click="openPathInput">
87
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><use href="#icon-link" /></svg>
88
- 粘贴路径…
89
- </button>
90
- </div>
91
- </div>
92
- <span class="aicomp__hint">拖拽文件 / 文件夹到此,或直接 ⌘V 粘贴截图</span>
93
- </div>
94
- <div class="aicomp__right">
95
- <span v-if="ctx" class="aicomp__ctx" :class="`is-${ctx.level}`" :title="ctxTitle">
96
- <svg class="aicomp__ctx-ring" viewBox="0 0 20 20" aria-hidden="true">
97
- <circle class="aicomp__ctx-track" cx="10" cy="10" r="8" />
98
- <circle
99
- class="aicomp__ctx-arc"
100
- cx="10"
101
- cy="10"
102
- r="8"
103
- :stroke-dasharray="`${ctx.arc} ${ctx.circ}`"
104
- transform="rotate(-90 10 10)"
105
- />
106
- </svg>
107
- <span class="aicomp__ctx-pct">{{ ctx.pctLabel }}</span>
108
- </span>
109
- <span v-if="model" class="aicomp__model" :title="`当前模型:${model}`">{{ model }}</span>
110
- <button
111
- v-if="busy"
112
- type="button"
113
- class="aicomp__send aicomp__send--stop"
114
- title="终止生成(Esc)"
115
- @click="$emit('stop')"
116
- >
117
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><use href="#icon-stop" /></svg>
118
- </button>
119
- <button
120
- v-else
121
- type="button"
122
- class="aicomp__send"
123
- :disabled="!canSend"
124
- :title="canSend ? '发送(Enter)' : '输入内容后发送'"
125
- @click="submit"
126
- >
127
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><use href="#icon-send" /></svg>
128
- </button>
129
- </div>
130
- </div>
131
- </div>
132
- </div>
133
- </template>
134
-
135
- <script>
136
- import { aiFileUrl } from '../runtime/ai-api.js'
137
-
138
- /** 输入区手动高度下限(px):两行正文 + 工具条的最小可用高度 */
139
- const MIN_HEIGHT = 106
140
- /** 输入区手动高度上限 = 对话面板高度的比例 */
141
- const MAX_RATIO = 0.5
142
- const HEIGHT_KEY = 'cardbuddy:ai-composer-height'
143
-
144
- export default {
145
- name: 'ChatComposer',
146
- props: {
147
- /** 生成中:发送键切成终止键,Enter 不再触发发送 */
148
- busy: { type: Boolean, default: false },
149
- /** 当前模型名(状态展示) */
150
- model: { type: String, default: '' },
151
- /** 已挂载的本地文件 / 文件夹 */
152
- attachments: { type: Array, default: () => [] },
153
- /** 未配置模型时的占位提示 */
154
- placeholder: { type: String, default: '描述你要改的卡片,Enter 发送 / Shift+Enter 换行' },
155
- /** 上下文占用(后端每轮 SSE context-usage 回传):{ used, total, window },null = 尚未跑过 */
156
- context: { type: Object, default: null },
157
- },
158
- emits: ['send', 'stop', 'pick', 'add-path', 'remove-attachment', 'drop-files', 'paste-image', 'escape'],
159
- data() {
160
- return {
161
- text: '',
162
- attachOpen: false,
163
- pathInputOpen: false,
164
- pathText: '',
165
- dragOver: false,
166
- /** 输入区手动高度(px,0 = 自适应):拖拽把手设定,localStorage 持久化 */
167
- heightPx: 0,
168
- resizing: false,
169
- _outside: null,
170
- _onWinResize: null,
171
- }
172
- },
173
- computed: {
174
- canSend() {
175
- return Boolean(this.text.trim() || this.attachments.some((a) => !a.pending && a.exists !== false))
176
- },
177
- /** 手动高度生效时才写内联高度:自适应态完全交给内容撑开 */
178
- compStyle() {
179
- return this.heightPx > 0 ? { height: `${this.heightPx}px` } : null
180
- },
181
- /** 上下文占比圆环的几何量:环周长固定,弧长 = 周长 × 占比 */
182
- ctx() {
183
- const c = this.context
184
- if (!c) return null
185
- const total = Number(c.window) > 0 ? Number(c.window) : Number(c.total) > 0 ? Number(c.total) : 0
186
- const used = Math.max(0, Number(c.used) || 0)
187
- if (!(total > 0)) return null
188
- const pct = Math.min(1, used / total)
189
- const circ = 2 * Math.PI * 8
190
- return {
191
- pct,
192
- arc: (circ * pct).toFixed(2),
193
- circ: circ.toFixed(2),
194
- pctLabel: `${Math.round(pct * 100)}%`,
195
- level: pct >= 0.85 ? 'danger' : pct >= 0.6 ? 'warn' : 'ok',
196
- used,
197
- total,
198
- }
199
- },
200
- ctxTitle() {
201
- const c = this.ctx
202
- if (!c) return ''
203
- const fmt = (n) => (n >= 1000 ? `${(n / 1000).toFixed(1)}k` : String(Math.round(n)))
204
- const win = Number(this.context?.window) > 0 ? ` · 网关窗口 ${fmt(Number(this.context.window))}` : ''
205
- return `上下文占用 ${fmt(c.used)} / ${fmt(c.total)} token(${c.pctLabel})${win};接近上限时后端会自动折叠早期工具结果`
206
- },
207
- },
208
- mounted() {
209
- this._outside = (ev) => {
210
- const host = this.$refs.attachEl
211
- if (host && !host.contains(ev.target)) this.attachOpen = false
212
- }
213
- document.addEventListener('mousedown', this._outside)
214
- this.loadHeight()
215
- // 面板 / 窗口变矮时手动高度可能超过 50% 上限:实时夹回,避免输入区吃掉半个对话面板
216
- this._onWinResize = () => this.clampHeight()
217
- window.addEventListener('resize', this._onWinResize)
218
- this.autoGrow()
219
- },
220
- beforeUnmount() {
221
- if (this._outside) document.removeEventListener('mousedown', this._outside)
222
- if (this._onWinResize) window.removeEventListener('resize', this._onWinResize)
223
- },
224
- methods: {
225
- focus() {
226
- this.$nextTick(() => this.$refs.taEl?.focus())
227
- },
228
- /** 供面板「建议问法」等外部填充输入框 */
229
- setText(value) {
230
- this.text = value
231
- this.focus()
232
- this.autoGrow()
233
- },
234
- fileUrl(p) {
235
- return aiFileUrl(p)
236
- },
237
- chipSub(att) {
238
- if (att.exists === false) return '不可读'
239
- if (att.isDir) return `${att.entryCount ?? att.entries?.length ?? 0} 项`
240
- const n = Number(att.size || 0)
241
- if (!n) return ''
242
- if (n < 1024) return `${n} B`
243
- if (n < 1024 * 1024) return `${(n / 1024).toFixed(0)} KB`
244
- return `${(n / 1024 / 1024).toFixed(1)} MB`
245
- },
246
- autoGrow() {
247
- const el = this.$refs.taEl
248
- if (!el) return
249
- // 手动高度态:高度由容器决定(textarea 撑满剩余空间),内容超出自己滚动
250
- if (this.heightPx > 0) {
251
- el.style.height = ''
252
- return
253
- }
254
- el.style.height = 'auto'
255
- el.style.height = `${Math.min(el.scrollHeight, 168)}px`
256
- },
257
- // ---------- 输入区高度(与面板宽度把手同一套:pointer 捕获 + body 光标 + localStorage)----------
258
- /** 上限 = 对话面板高度的 50%;下限 106px(够放两行正文 + 工具条) */
259
- heightLimits() {
260
- const panel = this.$el?.closest('.aichat')
261
- const panelH = panel?.clientHeight || window.innerHeight
262
- return { min: MIN_HEIGHT, max: Math.max(MIN_HEIGHT, Math.floor(panelH * MAX_RATIO)) }
263
- },
264
- clampHeight() {
265
- if (!this.heightPx) return
266
- const { min, max } = this.heightLimits()
267
- this.heightPx = Math.max(min, Math.min(max, this.heightPx))
268
- },
269
- loadHeight() {
270
- try {
271
- const v = localStorage.getItem(HEIGHT_KEY)
272
- const px = v == null ? 0 : parseInt(v, 10)
273
- if (!Number.isNaN(px) && px >= MIN_HEIGHT) this.heightPx = px
274
- } catch {
275
- /* localStorage 不可用时保持自适应 */
276
- }
277
- this.clampHeight()
278
- },
279
- saveHeight() {
280
- try {
281
- if (this.heightPx) localStorage.setItem(HEIGHT_KEY, String(Math.round(this.heightPx)))
282
- else localStorage.removeItem(HEIGHT_KEY)
283
- } catch {
284
- /* 忽略 */
285
- }
286
- },
287
- startResize(ev) {
288
- const el = ev && ev.currentTarget
289
- if (!el) return
290
- this.resizing = true
291
- document.body.style.cursor = 'row-resize'
292
- document.body.style.userSelect = 'none'
293
- const pointerId = ev.pointerId
294
- try {
295
- el.setPointerCapture(pointerId)
296
- } catch {
297
- /* 不支持捕获时退化为元素级监听 */
298
- }
299
- // 输入区贴面板底边:新高度 = 底边 - 指针 y(往上拖变高)
300
- const bottom = this.$el.getBoundingClientRect().bottom
301
- const move = (e) => {
302
- const { min, max } = this.heightLimits()
303
- this.heightPx = Math.max(min, Math.min(max, Math.round(bottom - e.clientY)))
304
- }
305
- const finish = () => {
306
- el.removeEventListener('pointermove', move)
307
- el.removeEventListener('pointerup', finish)
308
- el.removeEventListener('pointercancel', finish)
309
- window.removeEventListener('blur', finish)
310
- try {
311
- if (el.hasPointerCapture?.(pointerId)) el.releasePointerCapture(pointerId)
312
- } catch {
313
- /* 已释放 */
314
- }
315
- this.resizing = false
316
- document.body.style.cursor = ''
317
- document.body.style.userSelect = ''
318
- this.saveHeight()
319
- }
320
- el.addEventListener('pointermove', move)
321
- el.addEventListener('pointerup', finish)
322
- el.addEventListener('pointercancel', finish)
323
- window.addEventListener('blur', finish) // 失焦兜底,避免拖拽态卡死
324
- },
325
- /** 双击把手:回到内容自适应(清持久化) */
326
- resetHeight() {
327
- this.heightPx = 0
328
- this.saveHeight()
329
- this.$nextTick(this.autoGrow)
330
- },
331
- onKeydown(ev) {
332
- // Esc:生成中 → 交给面板终止;否则关面板(与 Codex 一致的中断手感)
333
- if (ev.key === 'Escape') {
334
- ev.preventDefault()
335
- this.$emit('escape')
336
- return
337
- }
338
- if (ev.key !== 'Enter') return
339
- // 输入法组词中的 Enter 是「选词」,不能当发送
340
- if (ev.isComposing || ev.keyCode === 229) return
341
- if (ev.shiftKey) return // Shift+Enter 换行
342
- ev.preventDefault()
343
- if (!this.busy) this.submit()
344
- },
345
- submit() {
346
- if (this.busy || !this.canSend) return
347
- const payload = { text: this.text.trim(), attachments: this.attachments.filter((a) => !a.pending && a.exists !== false) }
348
- this.text = ''
349
- this.attachOpen = false
350
- this.$nextTick(this.autoGrow)
351
- this.$emit('send', payload)
352
- },
353
- toggleAttach() {
354
- this.attachOpen = !this.attachOpen
355
- },
356
- pick(kind) {
357
- this.attachOpen = false
358
- this.$emit('pick', kind)
359
- },
360
- openPathInput() {
361
- this.attachOpen = false
362
- this.pathInputOpen = true
363
- this.pathText = ''
364
- this.$nextTick(() => this.$refs.pathEl?.focus())
365
- },
366
- closePathInput() {
367
- this.pathInputOpen = false
368
- this.pathText = ''
369
- },
370
- confirmPath() {
371
- const value = this.pathText.trim()
372
- if (!value) return
373
- this.$emit('add-path', value)
374
- this.closePathInput()
375
- },
376
- onDragEnter() {
377
- this.dragOver = true
378
- },
379
- onDragOver() {
380
- this.dragOver = true
381
- },
382
- onDragLeave() {
383
- this.dragOver = false
384
- },
385
- onDrop(ev) {
386
- this.dragOver = false
387
- const dt = ev.dataTransfer
388
- if (!dt) return
389
- this.$emit('drop-files', dt)
390
- },
391
- /** ⌘V 粘贴截图:交给面板落盘成本机文件(不上传远端) */
392
- async onPaste(ev) {
393
- const items = ev.clipboardData?.items
394
- if (!items) return
395
- for (const item of items) {
396
- if (item.type && item.type.indexOf('image/') === 0) {
397
- const file = item.getAsFile()
398
- if (!file) continue
399
- ev.preventDefault()
400
- const dataUrl = await new Promise((resolve) => {
401
- const fr = new FileReader()
402
- fr.onload = () => resolve(String(fr.result || ''))
403
- fr.onerror = () => resolve('')
404
- fr.readAsDataURL(file)
405
- })
406
- if (dataUrl) this.$emit('paste-image', dataUrl)
407
- return
408
- }
409
- }
410
- },
411
- },
412
- }
413
- </script>