@cannbot-plugin/cannbot-harness 0.3.3 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -31,10 +31,15 @@ window.__ModuleLoader__.load({
31
31
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
32
32
  _deepseek_ai_dsh_client_ui_primitives = __toESM(_deepseek_ai_dsh_client_ui_primitives, 1);
33
33
  //#region src/client/locales.ts
34
- const PRODUCT = "CANNBot Harness";
34
+ const PRODUCT = "CANNBot";
35
35
  const NAMESPACE = "cannbotHarness";
36
36
  const PACKAGE = "@cannbot-plugin/cannbot-harness";
37
37
  const zh = {
38
+ tasksTitle: "任务列表",
39
+ tasksDone: "已完成",
40
+ tasksRecent: "仅显示最近完成",
41
+ tasksAll: "查看全部任务",
42
+ currentWorkflow: "工作流",
38
43
  contentCatalog: "工作流目录",
39
44
  contentCheck: "检查工作流更新",
40
45
  contentVersion: "当前版本",
@@ -83,27 +88,20 @@ window.__ModuleLoader__.load({
83
88
  commandHint: "发送时自动应用所选工作流,只需填写需求。",
84
89
  flash: "ops-direct-invoke-flash",
85
90
  registry: "ops-registry-invoke",
86
- model: "model-infer-optimize",
87
- hccl: "hccl-op-generator",
88
- triton: "triton-op-generator",
89
- catlass: "catlass-op-generator",
90
- performance: "ops-perf-optimize",
91
- pypto: "pypto-op-orchestrator",
92
91
  operatorDescription: "开发 Ascend C 算子,通过直调方式接入使用。",
93
92
  flashDescription: "快速生成并验证 Ascend C 算子。",
94
93
  registryDescription: "开发 Ascend C 注册算子,通过 ACLNN / GEIR 接入框架。",
95
- modelDescription: "将模型迁移到 NPU,完成精度对齐与推理性能优化。",
96
- hcclDescription: "开发 HCCL AICPU 通信算子,协同完成代码生成与验证。",
97
- tritonDescription: "生成并优化 Triton-Ascend 算子代码。",
98
- catlassDescription: "基于 CATLASS 模板开发矩阵计算、注意力等算子,验证精度与性能。",
99
- performanceDescription: "分析并优化 Ascend C 算子性能,验证精度并检查性能退化。",
100
- pyptoDescription: "开发并调优 PyPTO 算子,也支持对已有算子单独调优。",
101
94
  chooseWorkspace: "请先选择工作目录。",
102
95
  insertFailed: "工作流准备或设置未完成,请到插件详情查看准备日志后重试。",
103
96
  settingsRetry: "设置连接失败,重试",
104
97
  workflowRetry: "工作流未就绪,重试"
105
98
  };
106
99
  const en = {
100
+ tasksTitle: "Tasks",
101
+ tasksDone: "Completed",
102
+ tasksRecent: "Show recent completions",
103
+ tasksAll: "Show all tasks",
104
+ currentWorkflow: "Workflow",
107
105
  contentCatalog: "Workflow catalog",
108
106
  contentCheck: "Check workflow updates",
109
107
  contentVersion: "Installed",
@@ -152,21 +150,9 @@ window.__ModuleLoader__.load({
152
150
  commandHint: "The selected workflow is applied in the background when you send.",
153
151
  flash: "ops-direct-invoke-flash",
154
152
  registry: "ops-registry-invoke",
155
- model: "model-infer-optimize",
156
- hccl: "hccl-op-generator",
157
- triton: "triton-op-generator",
158
- catlass: "catlass-op-generator",
159
- performance: "ops-perf-optimize",
160
- pypto: "pypto-op-orchestrator",
161
153
  operatorDescription: "Develop Ascend C operators and integrate them through direct invocation.",
162
154
  flashDescription: "Quickly generate and validate Ascend C operators.",
163
155
  registryDescription: "Develop registered Ascend C operators for framework integration through ACLNN / GEIR.",
164
- modelDescription: "Migrate models to NPU, align accuracy and optimize inference performance.",
165
- hcclDescription: "Develop HCCL AICPU communication operators with coordinated code generation and validation.",
166
- tritonDescription: "Generate and optimize Triton-Ascend operator code.",
167
- catlassDescription: "Build matrix and attention operators using CATLASS templates; validate accuracy and performance.",
168
- performanceDescription: "Analyze and optimize Ascend C operator performance, checking accuracy and regressions.",
169
- pyptoDescription: "Develop and tune PyPTO operators, or tune existing operators independently.",
170
156
  chooseWorkspace: "Choose a working directory first.",
171
157
  insertFailed: "Workflow preparation or saving failed. Check preparation logs in the plugin details and retry.",
172
158
  settingsRetry: "Reconnect settings",
@@ -202,13 +188,13 @@ window.__ModuleLoader__.load({
202
188
  function SidebarName() {
203
189
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
204
190
  className: "cannbot-harness-name",
205
- children: PRODUCT
191
+ children: "CANNBot"
206
192
  });
207
193
  }
208
194
  function Hero({ size }) {
209
195
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
210
196
  "data-cannbot-harness-hero": "",
211
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Mark, { size }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: PRODUCT })]
197
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Mark, { size }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "CANNBot" })]
212
198
  });
213
199
  }
214
200
  //#endregion
@@ -228,36 +214,6 @@ window.__ModuleLoader__.load({
228
214
  id: "ops-registry-invoke",
229
215
  label: "registry",
230
216
  description: "registryDescription"
231
- },
232
- {
233
- id: "model-infer-optimize",
234
- label: "model",
235
- description: "modelDescription"
236
- },
237
- {
238
- id: "hccl-op-generator",
239
- label: "hccl",
240
- description: "hcclDescription"
241
- },
242
- {
243
- id: "triton-op-generator",
244
- label: "triton",
245
- description: "tritonDescription"
246
- },
247
- {
248
- id: "catlass-op-generator",
249
- label: "catlass",
250
- description: "catlassDescription"
251
- },
252
- {
253
- id: "ops-perf-optimize",
254
- label: "performance",
255
- description: "performanceDescription"
256
- },
257
- {
258
- id: "pypto-op-orchestrator",
259
- label: "pypto",
260
- description: "pyptoDescription"
261
217
  }
262
218
  ];
263
219
  //#endregion
@@ -320,7 +276,9 @@ window.__ModuleLoader__.load({
320
276
  }
321
277
  };
322
278
  const endpoint = () => new URL(CONTENT_PATH, document.baseURI);
279
+ let requestSequence = 0;
323
280
  const pull = async () => {
281
+ const sequence = ++requestSequence;
324
282
  try {
325
283
  const response = await fetch(endpoint(), {
326
284
  credentials: "same-origin",
@@ -329,11 +287,12 @@ window.__ModuleLoader__.load({
329
287
  });
330
288
  if (response.ok) {
331
289
  const status = await response.json();
332
- if (Array.isArray(status.plugins) && status.plugins.every((item) => /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(item.id) && typeof item.title === "string")) publish(status);
290
+ if (sequence === requestSequence && Array.isArray(status.plugins) && status.plugins.every((item) => /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(item.id) && typeof item.title === "string")) publish(status);
333
291
  }
334
292
  } catch {}
335
293
  };
336
294
  const post = async (body) => {
295
+ ++requestSequence;
337
296
  if (!(await fetch(endpoint(), {
338
297
  method: "POST",
339
298
  credentials: "same-origin",
@@ -505,6 +464,74 @@ window.__ModuleLoader__.load({
505
464
  const noSubscribe = () => () => {};
506
465
  const noSnapshot = () => void 0;
507
466
  //#endregion
467
+ //#region src/client/SessionWorkflow.tsx
468
+ /** Read the committed selection for this header's Session, including after reload. */
469
+ function SessionWorkflow({ sessionId, selection, t }) {
470
+ const workflow = (0, react.useSyncExternalStore)(selection.subscribe, selection.getSnapshot).values[sessionId];
471
+ if (!workflow) return null;
472
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
473
+ className: "cannbot-harness-session-workflow",
474
+ title: `${t("currentWorkflow")}: ${workflow}`,
475
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("currentWorkflow") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: workflow })]
476
+ });
477
+ }
478
+ //#endregion
479
+ //#region src/client/TaskList.tsx
480
+ /** One view of the native todos projection, including a compact completion history. */
481
+ function TaskList({ todos, t }) {
482
+ const [expanded, setExpanded] = (0, react.useState)(false);
483
+ const [showAll, setShowAll] = (0, react.useState)(false);
484
+ if (!todos.length) return null;
485
+ const done = todos.filter((task) => task.status === "completed");
486
+ const open = todos.filter((task) => task.status !== "completed");
487
+ const visible = [...(showAll ? done : done.slice(-2)).reverse(), ...open];
488
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
489
+ className: "cannbot-task-list",
490
+ "aria-label": t("tasksTitle"),
491
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
492
+ className: "cannbot-task-list-toggle",
493
+ type: "button",
494
+ "aria-expanded": expanded,
495
+ onClick: () => setExpanded((value) => !value),
496
+ children: [
497
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("tasksTitle") }),
498
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
499
+ role: "status",
500
+ children: [
501
+ t("tasksDone"),
502
+ " ",
503
+ done.length,
504
+ " / ",
505
+ todos.length
506
+ ]
507
+ }),
508
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
509
+ className: "cannbot-task-list-chevron",
510
+ "aria-hidden": true,
511
+ children: expanded ? "⌄" : "⌃"
512
+ })
513
+ ]
514
+ }), expanded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", { children: visible.map((task) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
515
+ "data-status": task.status,
516
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
517
+ className: "cannbot-task-list-icon",
518
+ "aria-hidden": true,
519
+ children: task.status === "in_progress" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "ongoing" }) : task.status === "completed" ? "✓" : "○"
520
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: task.content })]
521
+ }, task.content)) }), done.length > 2 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
522
+ type: "button",
523
+ onClick: () => setShowAll((value) => !value),
524
+ children: t(showAll ? "tasksRecent" : "tasksAll")
525
+ })] })]
526
+ });
527
+ }
528
+ function TaskDock({ useProjection, t }) {
529
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TaskList, {
530
+ todos: useProjection("todos") ?? [],
531
+ t
532
+ });
533
+ }
534
+ //#endregion
508
535
  //#region src/client/theme.ts
509
536
  /** Portal design-v2 palette, applied through the documented theme override layer. */
510
537
  const cannTheme = Object.fromEntries(Object.entries({
@@ -552,11 +579,11 @@ window.__ModuleLoader__.load({
552
579
  dark: values[1]
553
580
  }]));
554
581
  //#endregion
555
- //#region \0dsh-inline-css:D:\code\cannbot-harness-dsh-plugin\src\client\interface.css.mjs
582
+ //#region \0dsh-inline-css:/home/t00607008/cannbot-dsh/cannbot/dsh/src/client/interface.css.mjs
556
583
  var interface_css_default = "span:has(>[data-slot=\"conversation.hero.brand.mark\"]>[data-cannbot-harness-hero]){width:auto;min-width:0;height:auto}span:has(>[data-slot=\"conversation.hero.brand.mark\"]>[data-cannbot-harness-hero])+span{display:none}[data-cannbot-harness-hero]{letter-spacing:-.6px;color:var(--dsw-alias-label-primary);justify-content:center;align-items:center;gap:12px;font-size:26px;font-weight:650;line-height:1.3;display:inline-flex}[data-cannbot-harness-hero] svg{flex-shrink:0}.cannbot-harness-name{letter-spacing:-.3px;font-weight:650}";
557
584
  //#endregion
558
- //#region \0dsh-global-css:D:\code\cannbot-harness-dsh-plugin\src\client\controls.css.mjs
559
- const css$1 = ".cannbot-harness-workflow{flex-direction:column;align-items:flex-start;gap:4px;min-width:120px;max-width:280px;display:inline-flex;position:relative}.cannbot-harness-workflow-anchor{flex:none;min-width:120px;max-width:100%}.cannbot-harness-workflow-trigger{border-radius:var(--dsw-radius-sm);min-width:0;max-width:100%;min-height:28px;color:var(--dsw-alias-label-primary);white-space:nowrap;cursor:pointer;background:0 0;border:0;align-items:center;gap:4px;padding:0 8px;font-family:inherit;font-size:13px;font-weight:500;line-height:20px;display:inline-flex}.cannbot-harness-workflow-trigger svg{flex:none}.cannbot-harness-workflow-trigger svg:last-child{color:var(--dsw-alias-label-caption)}.cannbot-harness-workflow-trigger[aria-expanded=true]{background:var(--dsw-alias-interactive-bg-hover)}.cannbot-harness-workflow-trigger:disabled{cursor:default;color:var(--dsw-alias-label-quaternary)}.cannbot-harness-workflow-trigger:focus-visible{outline:2px solid var(--dsw-focus-ring-color);outline-offset:2px}.cannbot-harness-workflow-label{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}@media (hover:hover){.cannbot-harness-workflow-trigger:not(:disabled):hover{background:var(--dsw-alias-interactive-bg-hover)}}.cannbot-harness-workflow-option{white-space:normal;flex-direction:column;gap:4px;max-width:320px;padding:5px 0;display:flex}.cannbot-harness-workflow-option small{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5}.cannbot-harness-error{color:var(--dsw-alias-label-secondary);max-width:100%;font-size:12px;line-height:18px}.cannbot-harness-error button{color:inherit;font:inherit;text-align:start;cursor:pointer;text-underline-offset:3px;background:0 0;border:0;padding:0 8px;text-decoration:underline}.cannbot-harness-toggle{box-sizing:border-box;justify-content:space-between;align-items:center;gap:8px;width:100%;padding:8px;display:flex}.cannbot-harness-toggle-name{min-width:0;color:var(--dsw-alias-label-primary);align-items:center;gap:8px;font-size:12px;line-height:20px;display:inline-flex}.cannbot-harness-toggle-name svg{flex-shrink:0}.cannbot-harness-toggle-compact{flex-direction:column;gap:6px}.cannbot-harness-switch{background:var(--dsw-alias-interactive-bg-hover,#d7dadd);cursor:pointer;border:0;border-radius:99px;flex-shrink:0;width:36px;height:20px;padding:2px}.cannbot-harness-switch[aria-checked=true]{background:#cf1740}.cannbot-harness-switch>span{background:#fff;border-radius:50%;width:16px;height:16px;display:block;transform:translate(0)}.cannbot-harness-switch[aria-checked=true]>span{transform:translate(16px)}.cannbot-harness-switch:focus-visible{outline:2px solid var(--dsw-focus-ring-color,#cf1740);outline-offset:2px}.cannbot-harness-update{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:var(--dsw-radius-md,12px);color:var(--dsw-alias-label-primary);padding:16px}.cannbot-harness-update-heading{flex-wrap:wrap;align-items:baseline;gap:12px;margin-bottom:14px;display:flex}.cannbot-harness-update h4{margin:0;font-size:14px;font-weight:600}.cannbot-harness-update-heading>span,.cannbot-harness-update p{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.6}.cannbot-harness-update-actions{flex-wrap:wrap;align-items:center;gap:12px;display:flex}.cannbot-harness-update-button{box-sizing:border-box;background:var(--dsw-alias-brand-primary,#cf1740);color:#fff;min-height:32px;font:inherit;cursor:pointer;border:0;border-radius:8px;align-items:center;padding:5px 14px;font-size:13px;text-decoration:none;display:inline-flex}.cannbot-harness-update-button:disabled{opacity:.6;cursor:default}.cannbot-harness-update-button:focus-visible,.cannbot-harness-update-recheck:focus-visible{outline:2px solid var(--dsw-focus-ring-color,#cf1740);outline-offset:3px}.cannbot-harness-update-recheck{font:inherit;color:var(--dsw-alias-brand-primary,#cf1740);cursor:pointer;background:0 0;border:0;padding:4px;font-size:12px}.cannbot-harness-update p{margin:10px 0 0}.cannbot-harness-content{margin-top:16px}.cannbot-harness-content details{margin-top:12px;font-size:12px}.cannbot-harness-content summary{cursor:pointer}.cannbot-harness-content pre{white-space:pre-wrap;overflow-wrap:anywhere;max-height:220px;font-size:11px;line-height:1.5;overflow:auto}.cannbot-harness-workflow-package{border-bottom:1px solid var(--dsw-alias-border-l2,#eee);justify-content:space-between;align-items:center;gap:12px;padding:14px 0;display:flex}.cannbot-harness-workflow-package>div:first-child{min-width:0}.cannbot-harness-workflow-package strong{font-size:13px;font-weight:500}.cannbot-harness-workflow-package small{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;font-size:11px;line-height:1.6;display:block}.cannbot-harness-workflow-package-actions{flex-wrap:wrap;flex-shrink:0;justify-content:flex-end;gap:8px;display:flex}@media (width<=480px){.cannbot-harness-workflow-package{flex-direction:column;align-items:flex-start}}";
585
+ //#region \0dsh-global-css:/home/t00607008/cannbot-dsh/cannbot/dsh/src/client/controls.css.mjs
586
+ const css$1 = ".cannbot-harness-workflow{flex-direction:column;align-items:flex-start;gap:4px;min-width:120px;max-width:280px;display:inline-flex;position:relative}.cannbot-harness-workflow-anchor{flex:none;min-width:120px;max-width:100%}.cannbot-harness-workflow-trigger{border-radius:var(--dsw-radius-sm);min-width:0;max-width:100%;min-height:28px;color:var(--dsw-alias-label-primary);white-space:nowrap;cursor:pointer;background:0 0;border:0;align-items:center;gap:4px;padding:0 8px;font-family:inherit;font-size:13px;font-weight:500;line-height:20px;display:inline-flex}.cannbot-harness-workflow-trigger svg{flex:none}.cannbot-harness-workflow-trigger svg:last-child{color:var(--dsw-alias-label-caption)}.cannbot-harness-workflow-trigger[aria-expanded=true]{background:var(--dsw-alias-interactive-bg-hover)}.cannbot-harness-workflow-trigger:disabled{cursor:default;color:var(--dsw-alias-label-quaternary)}.cannbot-harness-workflow-trigger:focus-visible{outline:2px solid var(--dsw-focus-ring-color);outline-offset:2px}.cannbot-harness-workflow-label{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}@media (hover:hover){.cannbot-harness-workflow-trigger:not(:disabled):hover{background:var(--dsw-alias-interactive-bg-hover)}}.cannbot-harness-workflow-option{white-space:normal;flex-direction:column;gap:4px;max-width:320px;padding:5px 0;display:flex}.cannbot-harness-workflow-option small{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5}.cannbot-harness-error{color:var(--dsw-alias-label-secondary);max-width:100%;font-size:12px;line-height:18px}.cannbot-harness-error button{color:inherit;font:inherit;text-align:start;cursor:pointer;text-underline-offset:3px;background:0 0;border:0;padding:0 8px;text-decoration:underline}.cannbot-harness-toggle{box-sizing:border-box;justify-content:space-between;align-items:center;gap:8px;width:100%;padding:8px;display:flex}.cannbot-harness-toggle-name{min-width:0;color:var(--dsw-alias-label-primary);align-items:center;gap:8px;font-size:12px;line-height:20px;display:inline-flex}.cannbot-harness-toggle-name svg{flex-shrink:0}.cannbot-harness-toggle-compact{flex-direction:column;gap:6px}.cannbot-harness-switch{background:var(--dsw-alias-interactive-bg-hover,#d7dadd);cursor:pointer;border:0;border-radius:99px;flex-shrink:0;width:36px;height:20px;padding:2px}.cannbot-harness-switch[aria-checked=true]{background:#cf1740}.cannbot-harness-switch>span{background:#fff;border-radius:50%;width:16px;height:16px;display:block;transform:translate(0)}.cannbot-harness-switch[aria-checked=true]>span{transform:translate(16px)}.cannbot-harness-switch:focus-visible{outline:2px solid var(--dsw-focus-ring-color,#cf1740);outline-offset:2px}.cannbot-harness-update{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:var(--dsw-radius-md,12px);color:var(--dsw-alias-label-primary);padding:16px}.cannbot-harness-update-heading{flex-wrap:wrap;align-items:baseline;gap:12px;margin-bottom:14px;display:flex}.cannbot-harness-update h4{margin:0;font-size:14px;font-weight:600}.cannbot-harness-update-heading>span,.cannbot-harness-update p{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.6}.cannbot-harness-update-actions{flex-wrap:wrap;align-items:center;gap:12px;display:flex}.cannbot-harness-update-button{box-sizing:border-box;background:var(--dsw-alias-brand-primary,#cf1740);color:#fff;min-height:32px;font:inherit;cursor:pointer;border:0;border-radius:8px;align-items:center;padding:5px 14px;font-size:13px;text-decoration:none;display:inline-flex}.cannbot-harness-update-button:disabled{opacity:.6;cursor:default}.cannbot-harness-update-button:focus-visible,.cannbot-harness-update-recheck:focus-visible{outline:2px solid var(--dsw-focus-ring-color,#cf1740);outline-offset:3px}.cannbot-harness-update-recheck{font:inherit;color:var(--dsw-alias-brand-primary,#cf1740);cursor:pointer;background:0 0;border:0;padding:4px;font-size:12px}.cannbot-harness-update p{margin:10px 0 0}.cannbot-harness-content{margin-top:16px}.cannbot-harness-content details{margin-top:12px;font-size:12px}.cannbot-harness-content summary{cursor:pointer}.cannbot-harness-content pre{white-space:pre-wrap;overflow-wrap:anywhere;max-height:220px;font-size:11px;line-height:1.5;overflow:auto}.cannbot-harness-workflow-package{border-bottom:1px solid var(--dsw-alias-border-l2,#eee);justify-content:space-between;align-items:center;gap:12px;padding:14px 0;display:flex}.cannbot-harness-workflow-package>div:first-child{min-width:0}.cannbot-harness-workflow-package strong{font-size:13px;font-weight:500}.cannbot-harness-workflow-package small{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;font-size:11px;line-height:1.6;display:block}.cannbot-harness-workflow-package-actions{flex-wrap:wrap;flex-shrink:0;justify-content:flex-end;gap:8px;display:flex}@media (width<=480px){.cannbot-harness-workflow-package{flex-direction:column;align-items:flex-start}}.cannbot-harness-session-workflow{border-radius:var(--dsw-radius-sm,6px);background:var(--dsw-alias-interactive-bg-hover);min-width:0;max-width:min(320px,40vw);color:var(--dsw-alias-label-secondary);align-items:center;gap:6px;padding:3px 8px;font-size:12px;line-height:20px;display:inline-flex}.cannbot-harness-session-workflow>span{flex-shrink:0}.cannbot-harness-session-workflow code{text-overflow:ellipsis;white-space:nowrap;font-size:inherit;color:var(--dsw-alias-label-primary);overflow:hidden}.cannbot-task-list{width:calc(100% - 48px);max-width:var(--dsh-composer-card-max-width,760px);box-sizing:border-box;border-radius:var(--dsw-radius-lg,12px);background:var(--dsw-specific-menu);color:var(--dsw-alias-label-primary);margin:0 auto;padding:8px 12px;font-size:13px}.cannbot-task-list .cannbot-task-list-toggle{text-align:left;flex-wrap:wrap;align-items:center;gap:12px;width:100%;padding:0;display:flex}.cannbot-task-list-toggle span{color:var(--dsw-alias-label-secondary)}.cannbot-task-list-chevron{margin-left:auto}.cannbot-task-list button{color:inherit;font:inherit;cursor:pointer;background:0 0;border:0;margin-left:auto}.cannbot-task-list ul{max-height:220px;margin:8px 0 0;padding:0;list-style:none;overflow-y:auto}.cannbot-task-list li{overflow-wrap:anywhere;gap:8px;padding:3px 0;display:flex}.cannbot-task-list li[data-status=completed]{color:var(--dsw-alias-label-secondary)}.cannbot-task-list-icon{flex:none;justify-content:center;align-items:center;width:14px;display:inline-flex}";
560
587
  const tagId$1 = "@cannbot-plugin/cannbot-harness/controls.css";
561
588
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
562
589
  const tag = document.createElement("style");
@@ -574,7 +601,7 @@ window.__ModuleLoader__.load({
574
601
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
575
602
  className: "cannbot-harness-toggle-name",
576
603
  title: PRODUCT,
577
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Mark, { size: 20 }), wide && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "CANNBot Harness" })]
604
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Mark, { size: 20 }), wide && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "CANNBot" })]
578
605
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
579
606
  type: "button",
580
607
  role: "switch",
@@ -818,12 +845,7 @@ window.__ModuleLoader__.load({
818
845
  }
819
846
  //#endregion
820
847
  //#region src/client/plugin-update.ts
821
- const UPDATE_PACKAGES = [
822
- "cannbot-harness",
823
- "cannbot-dsh",
824
- "dsh-cannbot",
825
- "@cannbot-plugin/cannbot-harness"
826
- ];
848
+ const UPDATE_PACKAGES = ["cannbot-harness", "@cannbot-plugin/cannbot-harness"];
827
849
  /** Only stable npm releases of our two installation entries may be selected. */
828
850
  function newerVersion(candidate, current) {
829
851
  const next = /^(\d+)\.(\d+)\.(\d+)$/.exec(candidate);
@@ -833,7 +855,7 @@ window.__ModuleLoader__.load({
833
855
  const difference = Number(next[index]) - Number(old[index]);
834
856
  if (difference) return difference > 0;
835
857
  }
836
- return current.includes("-");
858
+ return /^\d+\.\d+\.\d+-/.test(current);
837
859
  }
838
860
  async function latestRelease(name, signal) {
839
861
  if (!UPDATE_PACKAGES.includes(name)) throw new Error("Unsupported update target");
@@ -1253,13 +1275,7 @@ window.__ModuleLoader__.load({
1253
1275
  //#endregion
1254
1276
  //#region src/client/workbench-data.ts
1255
1277
  /** Presentation copy only. Execution and initialization remain owned by the workflow packages. */
1256
- const categories = [
1257
- "全部",
1258
- "Ascend C",
1259
- "其他算子",
1260
- "通信",
1261
- "性能优化"
1262
- ];
1278
+ const categories = ["全部", "Ascend C"];
1263
1279
  const guides = {
1264
1280
  "ops-direct-invoke": {
1265
1281
  category: "Ascend C",
@@ -1284,58 +1300,10 @@ window.__ModuleLoader__.load({
1284
1300
  inputs: ["必需:算子定义、输入输出及接入方式", "可选:现有工程、参考实现及目标环境"],
1285
1301
  outputs: ["注册算子相关代码及接入示例", "按实际环境完成的验证与使用说明"],
1286
1302
  example: "开发一个 Ascend C 的自定义算子,并通过 ACLNN 接入。请先检查当前工程及输入输出定义。"
1287
- },
1288
- "triton-op-generator": {
1289
- category: "其他算子",
1290
- icon: "code",
1291
- scenes: ["使用 Triton-Ascend 开发算子", "优化已有 Triton 算子实现"],
1292
- inputs: ["必需:功能需求或已有 Triton 代码", "可选:张量规格、目标硬件与性能目标"],
1293
- outputs: ["Triton-Ascend 算子代码", "实际执行的验证与调优记录"],
1294
- example: "使用 Triton-Ascend 实现一个逐元素 Add 算子,并为不同输入形状添加验证。"
1295
- },
1296
- "catlass-op-generator": {
1297
- category: "其他算子",
1298
- icon: "layers",
1299
- scenes: ["基于 CATLASS 模板开发矩阵计算算子", "开发注意力相关算子并验证精度与性能"],
1300
- inputs: ["必需:计算需求及张量规格", "可选:CATLASS 工程、参考实现与性能目标"],
1301
- outputs: ["基于 CATLASS 的实现及调用示例", "可用环境中的精度与性能验证结果"],
1302
- example: "基于 CATLASS 模板开发一个矩阵乘算子,请先检查工程环境,再验证精度与性能。"
1303
- },
1304
- "pypto-op-orchestrator": {
1305
- category: "其他算子",
1306
- icon: "nodes",
1307
- scenes: ["使用 PyPTO 开发并调优算子", "单独调优已有的 PyPTO 算子"],
1308
- inputs: ["必需:算子需求或已有 PyPTO 代码", "可选:测试用例、目标硬件与性能目标"],
1309
- outputs: ["PyPTO 算子实现或调优修改", "按实际执行情况整理的验证与优化结果"],
1310
- example: "请分析当前 PyPTO 算子,保持计算结果一致,尝试优化性能并记录验证结果。"
1311
- },
1312
- "hccl-op-generator": {
1313
- category: "通信",
1314
- icon: "arrows",
1315
- scenes: ["开发 HCCL AICPU 通信算子", "生成通信代码并准备验证"],
1316
- inputs: ["必需:通信操作、参与设备及数据规格", "可选:现有通信工程及运行环境"],
1317
- outputs: ["通信算子相关代码", "在可用设备环境中的验证结果及运行说明"],
1318
- example: "帮我开发一个 HCCL AICPU 通信算子,请先确认通信操作、设备数量和测试环境。"
1319
- },
1320
- "ops-perf-optimize": {
1321
- category: "性能优化",
1322
- icon: "chart",
1323
- scenes: ["分析已有 Ascend C 算子的性能瓶颈", "在保持精度的前提下迭代调优"],
1324
- inputs: ["必需:已有算子代码及复现方法", "可选:基准数据、性能分析结果与目标"],
1325
- outputs: ["性能分析及代码修改", "精度检查、性能对比及退化检查记录"],
1326
- example: "请分析当前 Ascend C 算子的性能瓶颈,在保持精度的前提下优化,并对比修改前后的表现。"
1327
- },
1328
- "model-infer-optimize": {
1329
- category: "性能优化",
1330
- icon: "gear",
1331
- scenes: ["将模型迁移到 NPU", "对齐精度并优化推理性能"],
1332
- inputs: ["必需:模型代码、依赖及运行方法", "可选:模型权重路径、测试数据和基准结果"],
1333
- outputs: ["模型迁移或推理优化修改", "实际完成的精度对齐与性能验证记录"],
1334
- example: "请将当前模型迁移到 NPU,先检查依赖与运行方式,再进行精度对齐和推理性能优化。"
1335
1303
  }
1336
1304
  };
1337
1305
  const guideFor = (id) => guides[id] ?? {
1338
- category: "其他算子",
1306
+ category: "Ascend C",
1339
1307
  icon: "nodes",
1340
1308
  scenes: ["使用此工作流完成开发需求"],
1341
1309
  inputs: ["请描述目标,并提供相关工程或代码"],
@@ -1381,6 +1349,144 @@ window.__ModuleLoader__.load({
1381
1349
  });
1382
1350
  }
1383
1351
  //#endregion
1352
+ //#region src/client/WorkspaceDirectory.tsx
1353
+ /** Browse Host directories through the capability shared by Web and desktop pickers. */
1354
+ function WorkspaceDirectory({ ctx, initialPath, onSelect, onClose }) {
1355
+ const dialog = (0, react.useRef)(null);
1356
+ const lifetime = (0, react.useRef)(null);
1357
+ const request = (0, react.useRef)(null);
1358
+ const [listing, setListing] = (0, react.useState)();
1359
+ const [path, setPath] = (0, react.useState)(initialPath ?? "");
1360
+ const [loading, setLoading] = (0, react.useState)(true);
1361
+ const [saving, setSaving] = (0, react.useState)(false);
1362
+ const [error, setError] = (0, react.useState)("");
1363
+ const browse = async (target) => {
1364
+ request.current?.abort();
1365
+ const controller = new AbortController();
1366
+ request.current = controller;
1367
+ setLoading(true);
1368
+ setError("");
1369
+ setListing(void 0);
1370
+ try {
1371
+ const next = await ctx.uiWorkspace.listDirectory(target || void 0, controller.signal);
1372
+ if (!controller.signal.aborted) {
1373
+ setListing(next);
1374
+ setPath(next.path);
1375
+ }
1376
+ } catch (reason) {
1377
+ if (!controller.signal.aborted) setError(reason instanceof Error ? reason.message : "无法读取目录,请重试。");
1378
+ } finally {
1379
+ if (!controller.signal.aborted) setLoading(false);
1380
+ }
1381
+ };
1382
+ (0, react.useEffect)(() => {
1383
+ lifetime.current = new AbortController();
1384
+ dialog.current?.showModal();
1385
+ browse(initialPath);
1386
+ return () => {
1387
+ lifetime.current?.abort();
1388
+ request.current?.abort();
1389
+ };
1390
+ }, []);
1391
+ const choose = async () => {
1392
+ if (!listing || loading || saving) return;
1393
+ setSaving(true);
1394
+ setError("");
1395
+ try {
1396
+ const selected = ctx.workspaces.list.getSnapshot().items.find((item) => item.path === listing.path) ?? await ctx.workspaces.create({ path: listing.path });
1397
+ if (!lifetime.current?.signal.aborted) {
1398
+ onSelect(selected.workspaceId);
1399
+ onClose();
1400
+ }
1401
+ } catch (reason) {
1402
+ if (!lifetime.current?.signal.aborted) setError(reason instanceof Error ? reason.message : "无法选择工作区,请重试。");
1403
+ } finally {
1404
+ if (!lifetime.current?.signal.aborted) setSaving(false);
1405
+ }
1406
+ };
1407
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dialog", {
1408
+ ref: dialog,
1409
+ className: "cwb-directory",
1410
+ "aria-label": "选择工作区目录",
1411
+ onCancel: (event) => {
1412
+ event.preventDefault();
1413
+ if (!saving) onClose();
1414
+ },
1415
+ children: [
1416
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: "选择工作区" }),
1417
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "选择 DSH 所在机器上的项目目录。" }),
1418
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
1419
+ onSubmit: (event) => {
1420
+ event.preventDefault();
1421
+ if (!saving) browse(path);
1422
+ },
1423
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1424
+ "aria-label": "目录路径",
1425
+ value: path,
1426
+ disabled: saving,
1427
+ onChange: (event) => setPath(event.target.value)
1428
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1429
+ className: "cwb-text-button",
1430
+ disabled: saving,
1431
+ type: "submit",
1432
+ children: "打开目录"
1433
+ })]
1434
+ }),
1435
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("nav", {
1436
+ "aria-label": "目录层级",
1437
+ children: listing?.crumbs.map((crumb) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1438
+ type: "button",
1439
+ className: "cwb-text-button",
1440
+ disabled: saving,
1441
+ onClick: () => void browse(crumb.path),
1442
+ children: crumb.name || crumb.path
1443
+ }, crumb.path))
1444
+ }),
1445
+ loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1446
+ role: "status",
1447
+ children: "正在读取目录…"
1448
+ }) : listing && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
1449
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
1450
+ className: "cwb-directory-list",
1451
+ children: listing.entries.map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1452
+ type: "button",
1453
+ disabled: saving,
1454
+ onClick: () => void browse(entry.path),
1455
+ children: [
1456
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchIcon, {
1457
+ name: "folder",
1458
+ size: 16
1459
+ }),
1460
+ " ",
1461
+ entry.name
1462
+ ]
1463
+ }) }, entry.path))
1464
+ }),
1465
+ !listing.entries.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "此目录下没有子目录,可以直接选择当前目录。" }),
1466
+ listing.truncated && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "目录较多,仅显示部分结果;可输入完整路径打开。" })
1467
+ ] }),
1468
+ error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1469
+ role: "alert",
1470
+ className: "cwb-error",
1471
+ children: error
1472
+ }),
1473
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("footer", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1474
+ type: "button",
1475
+ className: "cwb-text-button",
1476
+ disabled: saving,
1477
+ onClick: onClose,
1478
+ children: "取消"
1479
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1480
+ type: "button",
1481
+ className: "cwb-primary",
1482
+ disabled: loading || saving || !listing || path !== listing.path,
1483
+ onClick: () => void choose(),
1484
+ children: saving ? "正在选择…" : "选择此目录"
1485
+ })] })
1486
+ ]
1487
+ });
1488
+ }
1489
+ //#endregion
1384
1490
  //#region src/client/workbench-launch.ts
1385
1491
  /** Transfer to the resident DSH composer; its own submit policy remains authoritative. */
1386
1492
  async function launchWorkbench(ctx, selection, request, signal, onStage = () => {}) {
@@ -1415,8 +1521,8 @@ window.__ModuleLoader__.load({
1415
1521
  if (request.files.length) {
1416
1522
  onStage("upload");
1417
1523
  if (typeof conversation.createDrafts !== "function") throw new Error("此 DSH 版本请进入对话后添加文件。");
1418
- attachments = conversation.createDrafts(id, request.files, true);
1419
- await waitForUploads(conversation, attachments.map((item) => item.id), signal);
1524
+ attachments = conversation.createDrafts(id, request.files);
1525
+ await waitForUploads(conversation, attachments.filter((item) => item.kind === "file").map((item) => item.id), signal);
1420
1526
  if (!input.addAttachments(attachments.map((item) => item.id))) throw new Error("文件暂时无法加入对话,请重试。");
1421
1527
  }
1422
1528
  signal.throwIfAborted();
@@ -1476,6 +1582,7 @@ window.__ModuleLoader__.load({
1476
1582
  const saved = (0, react.useSyncExternalStore)(selection.subscribe, selection.getSnapshot);
1477
1583
  const [category, setCategory] = (0, react.useState)("全部");
1478
1584
  const [query, setQuery] = (0, react.useState)("");
1585
+ const [pickingWorkspace, setPickingWorkspace] = (0, react.useState)(false);
1479
1586
  const input = (0, react.useRef)(null);
1480
1587
  const files = (0, react.useRef)(null);
1481
1588
  const visible = [...workflows].sort((a, b) => (cardOrder.indexOf(a.id) < 0 ? 999 : cardOrder.indexOf(a.id)) - (cardOrder.indexOf(b.id) < 0 ? 999 : cardOrder.indexOf(b.id))).filter((workflow) => (category === "全部" || guideFor(workflow.id).category === category) && `${workflow.id} ${copy(workflow).description}`.toLowerCase().includes(query.toLowerCase().trim()));
@@ -1487,28 +1594,6 @@ window.__ModuleLoader__.load({
1487
1594
  const navigate = (panel) => ctx.layout.selectPanel(panel);
1488
1595
  const settings = () => ctx.get("pluginNavigation")?.openBundle(PACKAGE);
1489
1596
  const fail = (error) => store.set({ error: error instanceof Error ? error.message : "暂时无法完成,请重试。" });
1490
- const addWorkspace = async () => {
1491
- if (store.getSnapshot().busy) return;
1492
- store.set({
1493
- error: "",
1494
- busy: true,
1495
- stage: "workspace"
1496
- });
1497
- try {
1498
- const path = await ctx.uiWorkspace.pickDirectory();
1499
- if (path && !store.signal.aborted) {
1500
- const created = await ctx.workspaces.create({ path });
1501
- store.set({ workspaceId: created.workspaceId });
1502
- }
1503
- } catch (error) {
1504
- fail(error);
1505
- } finally {
1506
- store.set({
1507
- busy: false,
1508
- stage: "idle"
1509
- });
1510
- }
1511
- };
1512
1597
  const start = async (event) => {
1513
1598
  event?.preventDefault();
1514
1599
  if (store.getSnapshot().busy) return;
@@ -1556,307 +1641,321 @@ window.__ModuleLoader__.load({
1556
1641
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("main", {
1557
1642
  className: "cannbot-workbench",
1558
1643
  "aria-label": library ? "CANNBot 工作流" : "CANNBot工作台",
1559
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
1560
- className: "cwb-header",
1561
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1562
- className: "cwb-workspace",
1644
+ children: [
1645
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
1646
+ className: "cwb-header",
1647
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1648
+ className: "cwb-workspace",
1649
+ children: [
1650
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchIcon, { name: "folder" }),
1651
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1652
+ className: "cwb-workspace-info",
1653
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1654
+ className: "cwb-workspace-choice",
1655
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
1656
+ "aria-label": "当前工作区",
1657
+ value: workspace?.workspaceId ?? "",
1658
+ disabled: state.busy || workspaceState.phase !== "ready",
1659
+ onChange: (event) => store.set({
1660
+ workspaceId: event.target.value,
1661
+ error: ""
1662
+ }),
1663
+ children: [!workspace && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1664
+ value: "",
1665
+ children: "选择工作区"
1666
+ }), workspaceState.items.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1667
+ value: item.workspaceId,
1668
+ children: item.title === "default-workspace" ? "默认工作区" : item.title
1669
+ }, item.workspaceId))]
1670
+ }), inherited && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1671
+ className: "cwb-inherited",
1672
+ children: "沿用当前对话"
1673
+ })]
1674
+ }), workspace && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1675
+ className: "cwb-workspace-path",
1676
+ title: workspace.path,
1677
+ children: workspace.path
1678
+ })]
1679
+ }),
1680
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1681
+ className: "cwb-text-button",
1682
+ disabled: state.busy,
1683
+ onClick: () => setPickingWorkspace(true),
1684
+ children: "选择工作区"
1685
+ })
1686
+ ]
1687
+ }), library && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1688
+ className: "cwb-text-button",
1689
+ onClick: settings,
1690
+ children: "插件设置"
1691
+ })]
1692
+ }),
1693
+ pickingWorkspace && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkspaceDirectory, {
1694
+ ctx,
1695
+ initialPath: workspace?.path,
1696
+ onSelect: (workspaceId) => {
1697
+ if (!store.signal.aborted) store.set({
1698
+ workspaceId,
1699
+ error: ""
1700
+ });
1701
+ },
1702
+ onClose: () => setPickingWorkspace(false)
1703
+ }),
1704
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1705
+ className: "cwb-content",
1563
1706
  children: [
1564
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchIcon, { name: "folder" }),
1565
1707
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1566
- className: "cwb-workspace-info",
1567
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1568
- className: "cwb-workspace-choice",
1569
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
1570
- "aria-label": "当前工作区",
1571
- value: workspace?.workspaceId ?? "",
1572
- disabled: state.busy || workspaceState.phase !== "ready",
1573
- onChange: (event) => store.set({
1574
- workspaceId: event.target.value,
1575
- error: ""
1708
+ className: "cwb-heading",
1709
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", { children: library ? "找到适合你的工作流" : "开始你的 Ascend 开发" }), library && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "了解适用场景,准备好输入,再开始。" })]
1710
+ }),
1711
+ !library && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
1712
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
1713
+ className: "cwb-composer",
1714
+ onSubmit: (event) => void start(event),
1715
+ onDragOver: (event) => event.preventDefault(),
1716
+ onDrop: (event) => {
1717
+ event.preventDefault();
1718
+ if (!state.busy) store.set({ files: [...state.files, ...Array.from(event.dataTransfer.files)] });
1719
+ },
1720
+ children: [
1721
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
1722
+ ref: input,
1723
+ "aria-label": "开发需求",
1724
+ placeholder: selected ? `例如:${guideFor(selected.id).example}` : "描述算子需求,或添加需要优化的代码。",
1725
+ value: state.prompt,
1726
+ disabled: state.busy,
1727
+ onChange: (event) => store.set({ prompt: event.target.value })
1728
+ }),
1729
+ state.files.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
1730
+ className: "cwb-files",
1731
+ children: state.files.map((file, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [
1732
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchIcon, {
1733
+ name: "document",
1734
+ size: 14
1735
+ }),
1736
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: file.name }),
1737
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1738
+ type: "button",
1739
+ disabled: state.busy,
1740
+ "aria-label": `移除 ${file.name}`,
1741
+ onClick: () => store.set({ files: state.files.filter((_, i) => i !== index) }),
1742
+ children: "×"
1743
+ })
1744
+ ] }, `${file.name}-${index}`))
1576
1745
  }),
1577
- children: [!workspace && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1578
- value: "",
1579
- children: "选择工作区"
1580
- }), workspaceState.items.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1581
- value: item.workspaceId,
1582
- children: item.title === "default-workspace" ? "默认工作区" : item.title
1583
- }, item.workspaceId))]
1584
- }), inherited && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1585
- className: "cwb-inherited",
1586
- children: "沿用当前对话"
1746
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1747
+ className: "cwb-composer-actions",
1748
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1749
+ className: "cwb-composer-tools",
1750
+ children: [
1751
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1752
+ type: "file",
1753
+ multiple: true,
1754
+ hidden: true,
1755
+ ref: files,
1756
+ onChange: (event) => {
1757
+ store.set({ files: [...state.files, ...Array.from(event.target.files ?? [])] });
1758
+ event.target.value = "";
1759
+ }
1760
+ }),
1761
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1762
+ type: "button",
1763
+ className: "cwb-text-button",
1764
+ disabled: state.busy,
1765
+ onClick: () => files.current?.click(),
1766
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchIcon, {
1767
+ name: "clip",
1768
+ size: 18
1769
+ }), "添加文件"]
1770
+ }),
1771
+ state.workflow && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1772
+ className: "cwb-selection",
1773
+ children: [
1774
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchIcon, {
1775
+ name: guideFor(state.workflow).icon,
1776
+ size: 16
1777
+ }),
1778
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: state.workflow }),
1779
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1780
+ type: "button",
1781
+ disabled: state.busy,
1782
+ "aria-label": "取消工作流选择",
1783
+ onClick: () => store.set({ workflow: "" }),
1784
+ children: "×"
1785
+ })
1786
+ ]
1787
+ })
1788
+ ]
1789
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1790
+ className: "cwb-primary",
1791
+ type: "submit",
1792
+ disabled: state.busy || !saved.ready || saved.pending || !state.prompt.trim() && !state.files.length,
1793
+ children: [state.busy ? "处理中…" : "开始", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1794
+ "aria-hidden": "true",
1795
+ children: "→"
1796
+ })]
1797
+ })]
1798
+ })
1799
+ ]
1800
+ }),
1801
+ (state.busy || !saved.ready || !workspace) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1802
+ className: "cwb-hint",
1803
+ role: "status",
1804
+ "aria-live": "polite",
1805
+ children: state.busy ? preparationLabels[state.stage] : !saved.ready ? "正在连接工作流设置…" : "请先选择或添加工作区。"
1806
+ }),
1807
+ saved.errorKind === "settings" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1808
+ className: "cwb-text-button",
1809
+ onClick: () => selection.retry(),
1810
+ children: "重试连接工作流设置"
1811
+ })
1812
+ ] }),
1813
+ state.error && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1814
+ className: "cwb-error",
1815
+ role: "alert",
1816
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1817
+ className: "cwb-error-heading",
1818
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "暂时无法开始,需求和文件已保留。" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1819
+ type: "button",
1820
+ className: "cwb-text-button",
1821
+ disabled: state.busy || !saved.ready || saved.pending,
1822
+ onClick: () => void start(),
1823
+ children: "重试"
1587
1824
  })]
1588
- }), workspace && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1589
- className: "cwb-workspace-path",
1590
- title: workspace.path,
1591
- children: workspace.path
1592
- })]
1825
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", { children: [
1826
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: "查看原因" }),
1827
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: state.error }),
1828
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1829
+ className: "cwb-text-button",
1830
+ onClick: settings,
1831
+ children: "打开插件设置"
1832
+ })
1833
+ ] })]
1593
1834
  }),
1594
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1595
- className: "cwb-text-button",
1596
- disabled: state.busy,
1597
- onClick: () => void addWorkspace(),
1598
- children: "+ 添加工作区"
1599
- })
1600
- ]
1601
- }), library && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1602
- className: "cwb-text-button",
1603
- onClick: settings,
1604
- children: "插件设置"
1605
- })]
1606
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1607
- className: "cwb-content",
1608
- children: [
1609
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1610
- className: "cwb-heading",
1611
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", { children: library ? "找到适合你的工作流" : "开始你的 Ascend 开发" }), library && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "了解适用场景,准备好输入,再开始。" })]
1612
- }),
1613
- !library && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
1614
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
1615
- className: "cwb-composer",
1616
- onSubmit: (event) => void start(event),
1617
- onDragOver: (event) => event.preventDefault(),
1618
- onDrop: (event) => {
1619
- event.preventDefault();
1620
- if (!state.busy) store.set({ files: [...state.files, ...Array.from(event.dataTransfer.files)] });
1621
- },
1835
+ workspaceState.state === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1836
+ role: "alert",
1837
+ className: "cwb-error",
1838
+ children: "工作区加载失败,请检查 DSH 连接。"
1839
+ }),
1840
+ !library && state.workflow && !selected && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1841
+ role: "alert",
1842
+ className: "cwb-error",
1843
+ children: "所选工作流已不在当前目录中,请重新选择。"
1844
+ }),
1845
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1846
+ className: "cwb-catalog",
1847
+ "aria-label": "工作流目录",
1622
1848
  children: [
1623
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
1624
- ref: input,
1625
- "aria-label": "开发需求",
1626
- placeholder: selected ? `例如:${guideFor(selected.id).example}` : "描述算子需求,或添加需要优化的代码。",
1627
- value: state.prompt,
1628
- disabled: state.busy,
1629
- onChange: (event) => store.set({ prompt: event.target.value })
1849
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1850
+ className: "cwb-catalog-heading",
1851
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: library ? "全部工作流" : "工作流" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1852
+ className: "cwb-search",
1853
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchIcon, {
1854
+ name: "search",
1855
+ size: 17
1856
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1857
+ "aria-label": "搜索工作流",
1858
+ placeholder: "搜索工作流",
1859
+ value: query,
1860
+ onChange: (event) => setQuery(event.target.value)
1861
+ })]
1862
+ })]
1630
1863
  }),
1631
- state.files.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
1632
- className: "cwb-files",
1633
- children: state.files.map((file, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [
1634
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchIcon, {
1635
- name: "document",
1636
- size: 14
1637
- }),
1638
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: file.name }),
1639
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1640
- type: "button",
1641
- disabled: state.busy,
1642
- "aria-label": `移除 ${file.name}`,
1643
- onClick: () => store.set({ files: state.files.filter((_, i) => i !== index) }),
1644
- children: "×"
1645
- })
1646
- ] }, `${file.name}-${index}`))
1864
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1865
+ className: "cwb-categories",
1866
+ role: "group",
1867
+ "aria-label": "工作流分类",
1868
+ children: categories.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1869
+ "aria-pressed": category === item,
1870
+ onClick: () => setCategory(item),
1871
+ children: item
1872
+ }, item))
1647
1873
  }),
1648
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1649
- className: "cwb-composer-actions",
1650
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1651
- className: "cwb-composer-tools",
1874
+ library ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1875
+ className: "cwb-library",
1876
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("nav", {
1877
+ "aria-label": "选择工作流详情",
1878
+ className: "cwb-library-list",
1879
+ children: [visible.map((workflow) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1880
+ "aria-current": detail?.id === workflow.id ? "true" : void 0,
1881
+ onClick: () => store.set({ detail: workflow.id }),
1882
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchIcon, { name: guideFor(workflow.id).icon }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: workflow.id }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: copy(workflow).description })] })]
1883
+ }, workflow.id)), !visible.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1884
+ className: "cwb-empty",
1885
+ children: "没有匹配的工作流"
1886
+ })]
1887
+ }), detail ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkflowDetail, {
1888
+ workflow: detail,
1889
+ content,
1890
+ onUse: () => useWorkflow(detail.id),
1891
+ onExample: () => useWorkflow(detail.id, guideFor(detail.id).example),
1892
+ onSettings: settings
1893
+ }, detail.id) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1894
+ className: "cwb-empty",
1895
+ children: "工作流目录尚未准备完成,请到插件设置查看准备状态。"
1896
+ })]
1897
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1898
+ className: "cwb-grid",
1899
+ children: [visible.map((workflow) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1900
+ type: "button",
1901
+ className: "cwb-card",
1902
+ "aria-pressed": state.workflow === workflow.id,
1903
+ disabled: state.busy,
1904
+ onClick: () => {
1905
+ const next = state.workflow === workflow.id ? "" : workflow.id;
1906
+ store.set({
1907
+ workflow: next,
1908
+ error: ""
1909
+ });
1910
+ if (next) input.current?.focus();
1911
+ },
1652
1912
  children: [
1653
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1654
- type: "file",
1655
- multiple: true,
1656
- hidden: true,
1657
- ref: files,
1658
- onChange: (event) => {
1659
- store.set({ files: [...state.files, ...Array.from(event.target.files ?? [])] });
1660
- event.target.value = "";
1661
- }
1913
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1914
+ className: "cwb-card-icon",
1915
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchIcon, {
1916
+ name: guideFor(workflow.id).icon,
1917
+ size: 23
1918
+ })
1662
1919
  }),
1663
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1664
- type: "button",
1665
- className: "cwb-text-button",
1666
- disabled: state.busy,
1667
- onClick: () => files.current?.click(),
1668
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchIcon, {
1669
- name: "clip",
1670
- size: 18
1671
- }), "添加文件"]
1920
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1921
+ className: "cwb-card-copy",
1922
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: workflow.id }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: copy(workflow).description })]
1672
1923
  }),
1673
- state.workflow && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1674
- className: "cwb-selection",
1675
- children: [
1676
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchIcon, {
1677
- name: guideFor(state.workflow).icon,
1678
- size: 16
1679
- }),
1680
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: state.workflow }),
1681
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1682
- type: "button",
1683
- disabled: state.busy,
1684
- "aria-label": "取消工作流选择",
1685
- onClick: () => store.set({ workflow: "" }),
1686
- children: "×"
1687
- })
1688
- ]
1924
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1925
+ className: "cwb-card-corner",
1926
+ "aria-hidden": "true",
1927
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
1928
+ width: "18",
1929
+ height: "18",
1930
+ viewBox: "0 0 20 20",
1931
+ fill: "none",
1932
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
1933
+ cx: "10",
1934
+ cy: "10",
1935
+ r: "8",
1936
+ fill: state.workflow === workflow.id ? "#da203e" : "none",
1937
+ stroke: state.workflow === workflow.id ? "#da203e" : "currentColor",
1938
+ strokeWidth: "1.2"
1939
+ }), state.workflow === workflow.id && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1940
+ d: "m6 10 2.6 2.6L14 7.2",
1941
+ stroke: "white",
1942
+ strokeWidth: "1.6",
1943
+ strokeLinecap: "round",
1944
+ strokeLinejoin: "round"
1945
+ })]
1946
+ })
1689
1947
  })
1690
1948
  ]
1691
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1692
- className: "cwb-primary",
1693
- type: "submit",
1694
- disabled: state.busy || !saved.ready || saved.pending || !state.prompt.trim() && !state.files.length,
1695
- children: [state.busy ? "处理中…" : "开始", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1696
- "aria-hidden": "true",
1697
- children: "→"
1698
- })]
1949
+ }, workflow.id)), !visible.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1950
+ className: "cwb-empty",
1951
+ children: "没有匹配的工作流,请换一个关键词或分类。"
1699
1952
  })]
1700
1953
  })
1701
1954
  ]
1702
- }),
1703
- (state.busy || !saved.ready || !workspace) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1704
- className: "cwb-hint",
1705
- role: "status",
1706
- "aria-live": "polite",
1707
- children: state.busy ? preparationLabels[state.stage] : !saved.ready ? "正在连接工作流设置…" : "请先选择或添加工作区。"
1708
- }),
1709
- saved.errorKind === "settings" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1710
- className: "cwb-text-button",
1711
- onClick: () => selection.retry(),
1712
- children: "重试连接工作流设置"
1713
1955
  })
1714
- ] }),
1715
- state.error && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1716
- className: "cwb-error",
1717
- role: "alert",
1718
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1719
- className: "cwb-error-heading",
1720
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "暂时无法开始,需求和文件已保留。" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1721
- type: "button",
1722
- className: "cwb-text-button",
1723
- disabled: state.busy || !saved.ready || saved.pending,
1724
- onClick: () => void start(),
1725
- children: "重试"
1726
- })]
1727
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", { children: [
1728
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: "查看原因" }),
1729
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: state.error }),
1730
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1731
- className: "cwb-text-button",
1732
- onClick: settings,
1733
- children: "打开插件设置"
1734
- })
1735
- ] })]
1736
- }),
1737
- workspaceState.state === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1738
- role: "alert",
1739
- className: "cwb-error",
1740
- children: "工作区加载失败,请检查 DSH 连接。"
1741
- }),
1742
- !library && state.workflow && !selected && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1743
- role: "alert",
1744
- className: "cwb-error",
1745
- children: "所选工作流已不在当前目录中,请重新选择。"
1746
- }),
1747
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1748
- className: "cwb-catalog",
1749
- "aria-label": "工作流目录",
1750
- children: [
1751
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1752
- className: "cwb-catalog-heading",
1753
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: library ? "全部工作流" : "工作流" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1754
- className: "cwb-search",
1755
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchIcon, {
1756
- name: "search",
1757
- size: 17
1758
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1759
- "aria-label": "搜索工作流",
1760
- placeholder: "搜索工作流",
1761
- value: query,
1762
- onChange: (event) => setQuery(event.target.value)
1763
- })]
1764
- })]
1765
- }),
1766
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1767
- className: "cwb-categories",
1768
- role: "group",
1769
- "aria-label": "工作流分类",
1770
- children: categories.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1771
- "aria-pressed": category === item,
1772
- onClick: () => setCategory(item),
1773
- children: item
1774
- }, item))
1775
- }),
1776
- library ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1777
- className: "cwb-library",
1778
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("nav", {
1779
- "aria-label": "选择工作流详情",
1780
- className: "cwb-library-list",
1781
- children: [visible.map((workflow) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1782
- "aria-current": detail?.id === workflow.id ? "true" : void 0,
1783
- onClick: () => store.set({ detail: workflow.id }),
1784
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchIcon, { name: guideFor(workflow.id).icon }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: workflow.id }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: copy(workflow).description })] })]
1785
- }, workflow.id)), !visible.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1786
- className: "cwb-empty",
1787
- children: "没有匹配的工作流"
1788
- })]
1789
- }), detail ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkflowDetail, {
1790
- workflow: detail,
1791
- content,
1792
- onUse: () => useWorkflow(detail.id),
1793
- onExample: () => useWorkflow(detail.id, guideFor(detail.id).example),
1794
- onSettings: settings
1795
- }, detail.id) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1796
- className: "cwb-empty",
1797
- children: "工作流目录尚未准备完成,请到插件设置查看准备状态。"
1798
- })]
1799
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1800
- className: "cwb-grid",
1801
- children: [visible.map((workflow) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1802
- type: "button",
1803
- className: "cwb-card",
1804
- "aria-pressed": state.workflow === workflow.id,
1805
- disabled: state.busy,
1806
- onClick: () => {
1807
- const next = state.workflow === workflow.id ? "" : workflow.id;
1808
- store.set({
1809
- workflow: next,
1810
- error: ""
1811
- });
1812
- if (next) input.current?.focus();
1813
- },
1814
- children: [
1815
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1816
- className: "cwb-card-icon",
1817
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchIcon, {
1818
- name: guideFor(workflow.id).icon,
1819
- size: 23
1820
- })
1821
- }),
1822
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1823
- className: "cwb-card-copy",
1824
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: workflow.id }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: copy(workflow).description })]
1825
- }),
1826
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1827
- className: "cwb-card-corner",
1828
- "aria-hidden": "true",
1829
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
1830
- width: "18",
1831
- height: "18",
1832
- viewBox: "0 0 20 20",
1833
- fill: "none",
1834
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
1835
- cx: "10",
1836
- cy: "10",
1837
- r: "8",
1838
- fill: state.workflow === workflow.id ? "#da203e" : "none",
1839
- stroke: state.workflow === workflow.id ? "#da203e" : "currentColor",
1840
- strokeWidth: "1.2"
1841
- }), state.workflow === workflow.id && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1842
- d: "m6 10 2.6 2.6L14 7.2",
1843
- stroke: "white",
1844
- strokeWidth: "1.6",
1845
- strokeLinecap: "round",
1846
- strokeLinejoin: "round"
1847
- })]
1848
- })
1849
- })
1850
- ]
1851
- }, workflow.id)), !visible.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1852
- className: "cwb-empty",
1853
- children: "没有匹配的工作流,请换一个关键词或分类。"
1854
- })]
1855
- })
1856
- ]
1857
- })
1858
- ]
1859
- })]
1956
+ ]
1957
+ })
1958
+ ]
1860
1959
  });
1861
1960
  }
1862
1961
  function WorkflowDetail({ workflow, content, onUse, onExample, onSettings }) {
@@ -1965,8 +2064,8 @@ window.__ModuleLoader__.load({
1965
2064
  }, workflow.id);
1966
2065
  }
1967
2066
  //#endregion
1968
- //#region \0dsh-global-css:D:\code\cannbot-harness-dsh-plugin\src\client\workbench.css.mjs
1969
- const css = ".cannbot-workbench{--cwb-ink:var(--dsw-alias-label-primary,#17181d);--cwb-muted:var(--dsw-alias-label-secondary,#677185);--cwb-surface:var(--dsw-alias-bg-layer-1,#fff);--cwb-border:var(--dsw-alias-border-l2,#e2e5eb);--cwb-soft:var(--dsw-alias-bg-layer-3,#f6f8fa);--cwb-accent:var(--dsw-alias-state-business-primary,#da203e);--cwb-selected:var(--dsw-alias-state-business-tertiary,#fdeef0);color:var(--cwb-ink);background:var(--cwb-surface);height:100%;font-family:inherit;font-size:14px;overflow:auto}.cannbot-workbench *,.cannbot-workbench :before,.cannbot-workbench :after{box-sizing:border-box}.cannbot-workbench button,.cannbot-workbench input,.cannbot-workbench select,.cannbot-workbench textarea{font:inherit}.cannbot-workbench button{cursor:pointer}.cannbot-workbench button:disabled{opacity:.5;cursor:default}.cannbot-workbench :is(button,input,select,textarea):focus-visible{outline:2px solid var(--cwb-accent);outline-offset:3px}.cwb-header{border-bottom:1px solid var(--cwb-border);flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;min-height:62px;padding:12px 30px;display:flex}.cwb-workspace{flex-wrap:wrap;align-items:center;gap:12px;min-width:0;display:flex}.cwb-workspace-info{min-width:0}.cwb-workspace-choice{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.cwb-inherited{color:var(--cwb-muted);background:var(--cwb-soft);border-radius:5px;padding:3px 7px;font-size:11px}.cwb-workspace-path{text-overflow:ellipsis;white-space:nowrap;max-width:min(52vw,560px);color:var(--cwb-muted);padding-left:6px;font-size:12px;line-height:1.5;display:block;overflow:hidden}.cwb-workspace select{background:var(--cwb-surface);max-width:300px;color:var(--cwb-ink);border:0;padding:6px}.cwb-content{max-width:1260px;margin:0 auto;padding:26px 32px 22px}.cwb-heading{margin-bottom:20px}.cwb-heading h1{letter-spacing:-.5px;margin:0 0 8px;font-size:28px;font-weight:650;line-height:1.3}.cwb-heading p{color:var(--cwb-muted);margin:0;font-size:15px;line-height:1.6}.cwb-text-button{color:var(--cwb-muted);text-align:start;background:0 0;border:0;align-items:center;gap:7px;padding:5px 2px;display:inline-flex}.cwb-text-button:hover:not(:disabled){color:var(--cwb-accent)}.cwb-composer{background:var(--cwb-surface);border:1px solid var(--cwb-border);border-radius:14px;padding:18px 20px 14px;box-shadow:0 5px 20px #17213b05}.cwb-composer:focus-within{border-color:var(--cwb-accent)}.cwb-composer textarea{resize:vertical;width:100%;min-height:72px;max-height:340px;color:var(--cwb-ink);background:0 0;border:0;outline:0;padding:0;font-size:15px;line-height:1.65;display:block}.cwb-composer textarea:focus-visible{outline:0}.cwb-composer textarea::placeholder{color:var(--cwb-muted)}.cwb-composer-actions,.cwb-composer-tools{flex-wrap:wrap;align-items:center;gap:16px;min-width:0;display:flex}.cwb-composer-actions{justify-content:space-between;margin-top:12px}.cwb-primary{color:#fff;white-space:nowrap;background:#da203e;border:1px solid #d91d3e;border-radius:9px;justify-content:center;align-items:center;gap:22px;min-height:42px;padding:10px 22px;font-weight:550;display:inline-flex}.cwb-primary:hover:not(:disabled){background:#b11430}.cwb-selection{color:var(--cwb-accent);background:var(--cwb-selected);border-radius:7px;align-items:center;gap:8px;min-width:0;max-width:100%;padding:6px 9px;font-size:12px;display:inline-flex}.cwb-selection>span{overflow-wrap:anywhere}.cwb-selection button,.cwb-files button{color:inherit;background:0 0;border:0;padding:0 4px;font-size:18px}.cwb-files{flex-wrap:wrap;gap:8px;margin:0;padding:10px 0;list-style:none;display:flex}.cwb-files li{border:1px solid var(--cwb-border);border-radius:6px;align-items:center;gap:6px;max-width:250px;padding:3px 6px;display:inline-flex}.cwb-files li span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.cwb-hint{color:var(--cwb-muted);margin:10px 0 0;font-size:12px;line-height:1.6}.cwb-error{border-left:3px solid var(--cwb-accent);background:var(--cwb-selected);color:var(--cwb-ink);padding:12px 14px;line-height:1.6}.cwb-error-heading{justify-content:space-between;align-items:center;gap:12px;display:flex}.cwb-error .cwb-text-button{color:var(--cwb-accent)}.cwb-error summary{cursor:pointer;color:var(--cwb-muted);font-size:12px}.cwb-error details p{white-space:pre-wrap;overflow-wrap:anywhere;margin:8px 0}.cwb-catalog-heading{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;margin:26px 0 6px;display:flex}.cwb-catalog-heading h2{margin:0;font-size:20px;font-weight:600}.cwb-search{border:1px solid var(--cwb-border);color:var(--cwb-muted);border-radius:8px;align-items:center;gap:9px;padding:8px 11px;display:flex}.cwb-search input{width:170px;color:var(--cwb-ink);background:0 0;border:0;outline:0;font-size:13px}.cwb-categories{border-bottom:1px solid var(--cwb-border);gap:22px;margin-bottom:18px;display:flex;overflow-x:auto}.cwb-categories button{color:var(--cwb-muted);white-space:nowrap;background:0 0;border:0;border-bottom:2px solid #0000;padding:12px 3px}.cwb-categories button[aria-pressed=true]{border-bottom-color:var(--cwb-accent);color:var(--cwb-accent);font-weight:550}.cwb-grid{grid-template-columns:repeat(3,minmax(0,1fr));align-items:start;gap:10px;display:grid}.cwb-card{text-align:start;border:1px solid var(--cwb-border);width:100%;min-height:96px;color:var(--cwb-ink);background:var(--cwb-surface);border-radius:9px;grid-template-columns:28px minmax(0,1fr) 18px;align-items:start;gap:10px;padding:14px;transition:border-color .15s,background .15s;display:grid}.cwb-card:hover:not(:disabled){border-color:var(--cwb-accent)}.cwb-card[aria-pressed=true]{border-color:var(--cwb-accent);background:var(--cwb-selected)}.cwb-card-icon{background:var(--cwb-selected);width:40px;height:40px;color:var(--cwb-accent);border-radius:9px;flex:none;justify-content:center;align-items:center;display:inline-flex}.cwb-card .cwb-card-icon{border-radius:6px;width:28px;height:28px}.cwb-card .cwb-card-icon svg{width:19px;height:19px}.cwb-card-copy{flex-direction:column;gap:5px;min-width:0;padding-top:3px;display:flex}.cwb-card-copy strong{overflow-wrap:anywhere;font-size:14px;font-weight:600;line-height:1.4}.cwb-card-copy>span{color:var(--cwb-muted);font-size:12px;line-height:1.55}.cwb-card-corner{width:18px;height:18px;color:var(--cwb-muted);background:0 0;border:0;justify-content:center;align-items:center;margin-top:3px;display:inline-flex}.cwb-card-corner svg{flex:none;display:block}.cwb-empty{color:var(--cwb-muted);padding:20px 0;line-height:1.7}.cwb-library{border:1px solid var(--cwb-border);border-radius:12px;grid-template-columns:minmax(220px,.85fr) minmax(0,2fr);display:grid;overflow:hidden}.cwb-library-list{background:var(--cwb-soft);border-right:1px solid var(--cwb-border);padding:10px}.cwb-library-list button{text-align:start;width:100%;color:var(--cwb-ink);background:0 0;border:1px solid #0000;border-radius:8px;gap:12px;padding:14px 12px;display:flex}.cwb-library-list button[aria-current=true]{border-color:var(--cwb-border);background:var(--cwb-surface)}.cwb-library-list button[aria-current=true]>svg{color:var(--cwb-accent)}.cwb-library-list button>svg{flex:none;margin-top:2px}.cwb-library-list button span{min-width:0}.cwb-library-list strong{overflow-wrap:anywhere;font-size:13px;font-weight:550;line-height:1.5;display:block}.cwb-library-list small{color:var(--cwb-muted);margin-top:5px;font-size:12px;line-height:1.6;display:block}.cwb-detail{min-width:0;padding:28px 30px}.cwb-detail-title{align-items:center;gap:14px;display:flex}.cwb-detail-title small{color:var(--cwb-muted);font-size:12px}.cwb-detail-title h2{overflow-wrap:anywhere;margin:5px 0 0;font-size:21px;line-height:1.4}.cwb-detail-summary{color:var(--cwb-muted);margin:17px 0 20px;line-height:1.7}.cwb-guide-sections{grid-template-columns:1fr;gap:18px;margin-top:28px;display:grid}.cwb-detail h3{margin:0 0 9px;font-size:14px;font-weight:600}.cwb-guide-sections ul{color:var(--cwb-muted);margin:0;padding-left:18px;font-size:13px;line-height:1.9}.cwb-example{border:1px solid var(--cwb-border);background:var(--cwb-soft);border-radius:9px;margin-top:24px;padding:18px}.cwb-example p{color:var(--cwb-muted);margin:8px 0;font-size:13px;line-height:1.8}.cwb-example .cwb-text-button{color:var(--cwb-accent)}.cwb-example small{color:var(--cwb-muted);margin-top:6px;font-size:11px;display:block}.cwb-version{border-top:1px solid var(--cwb-border);color:var(--cwb-muted);margin-top:24px;padding-top:18px;font-size:12px;line-height:1.8}.cwb-version summary{cursor:pointer}.cwb-version-actions{flex-wrap:wrap;gap:15px;display:flex}.cannbot-workbench{container:cwb/inline-size}@container cwb (width<=900px){.cwb-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@container cwb (width<=590px){.cwb-grid{grid-template-columns:1fr}}@media (width<=1120px){.cwb-content{padding:24px}.cwb-library{grid-template-columns:minmax(190px,.9fr) minmax(0,1.6fr)}.cwb-detail{padding:22px}}@media (width<=700px){.cwb-header{padding:12px 16px}.cwb-content{padding:22px 16px}.cwb-heading h1{font-size:25px}.cwb-grid,.cwb-library{grid-template-columns:1fr}.cwb-library-list{border-right:0;border-bottom:1px solid var(--cwb-border);max-height:220px;overflow:auto}.cwb-composer{padding:15px}.cwb-workspace select{max-width:190px}.cwb-composer-tools{gap:8px}.cwb-composer-actions{align-items:end}.cwb-primary{padding:9px 17px}.cwb-search,.cwb-search input{width:100%}}@media (prefers-reduced-motion:reduce){.cwb-card{transition:none}}";
2067
+ //#region \0dsh-global-css:/home/t00607008/cannbot-dsh/cannbot/dsh/src/client/workbench.css.mjs
2068
+ const css = ".cannbot-workbench{--cwb-ink:var(--dsw-alias-label-primary,#17181d);--cwb-muted:var(--dsw-alias-label-secondary,#677185);--cwb-surface:var(--dsw-alias-bg-layer-1,#fff);--cwb-border:var(--dsw-alias-border-l2,#e2e5eb);--cwb-soft:var(--dsw-alias-bg-layer-3,#f6f8fa);--cwb-accent:var(--dsw-alias-state-business-primary,#da203e);--cwb-selected:var(--dsw-alias-state-business-tertiary,#fdeef0);color:var(--cwb-ink);background:var(--cwb-surface);height:100%;font-family:inherit;font-size:14px;overflow:auto}.cannbot-workbench *,.cannbot-workbench :before,.cannbot-workbench :after{box-sizing:border-box}.cannbot-workbench button,.cannbot-workbench input,.cannbot-workbench select,.cannbot-workbench textarea{font:inherit}.cannbot-workbench button{cursor:pointer}.cannbot-workbench button:disabled{opacity:.5;cursor:default}.cannbot-workbench :is(button,input,select,textarea):focus-visible{outline:2px solid var(--cwb-accent);outline-offset:3px}.cwb-header{border-bottom:1px solid var(--cwb-border);flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;min-height:62px;padding:12px 30px;display:flex}.cwb-workspace{flex-wrap:wrap;align-items:center;gap:12px;min-width:0;display:flex}.cwb-workspace-info{min-width:0}.cwb-workspace-choice{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.cwb-inherited{color:var(--cwb-muted);background:var(--cwb-soft);border-radius:5px;padding:3px 7px;font-size:11px}.cwb-workspace-path{text-overflow:ellipsis;white-space:nowrap;max-width:min(52vw,560px);color:var(--cwb-muted);padding-left:6px;font-size:12px;line-height:1.5;display:block;overflow:hidden}.cwb-workspace select{background:var(--cwb-surface);max-width:300px;color:var(--cwb-ink);border:0;padding:6px}.cwb-content{max-width:1260px;margin:0 auto;padding:26px 32px 22px}.cwb-heading{margin-bottom:20px}.cwb-heading h1{letter-spacing:-.5px;margin:0 0 8px;font-size:28px;font-weight:650;line-height:1.3}.cwb-heading p{color:var(--cwb-muted);margin:0;font-size:15px;line-height:1.6}.cwb-text-button{color:var(--cwb-muted);text-align:start;background:0 0;border:0;align-items:center;gap:7px;padding:5px 2px;display:inline-flex}.cwb-text-button:hover:not(:disabled){color:var(--cwb-accent)}.cwb-composer{background:var(--cwb-surface);border:1px solid var(--cwb-border);border-radius:14px;padding:18px 20px 14px;box-shadow:0 5px 20px #17213b05}.cwb-composer:focus-within{border-color:var(--cwb-accent)}.cwb-composer textarea{resize:vertical;width:100%;min-height:72px;max-height:340px;color:var(--cwb-ink);background:0 0;border:0;outline:0;padding:0;font-size:15px;line-height:1.65;display:block}.cwb-composer textarea:focus-visible{outline:0}.cwb-composer textarea::placeholder{color:var(--cwb-muted)}.cwb-composer-actions,.cwb-composer-tools{flex-wrap:wrap;align-items:center;gap:16px;min-width:0;display:flex}.cwb-composer-actions{justify-content:space-between;margin-top:12px}.cwb-primary{color:#fff;white-space:nowrap;background:#da203e;border:1px solid #d91d3e;border-radius:9px;justify-content:center;align-items:center;gap:22px;min-height:42px;padding:10px 22px;font-weight:550;display:inline-flex}.cwb-primary:hover:not(:disabled){background:#b11430}.cwb-selection{color:var(--cwb-accent);background:var(--cwb-selected);border-radius:7px;align-items:center;gap:8px;min-width:0;max-width:100%;padding:6px 9px;font-size:12px;display:inline-flex}.cwb-selection>span{overflow-wrap:anywhere}.cwb-selection button,.cwb-files button{color:inherit;background:0 0;border:0;padding:0 4px;font-size:18px}.cwb-files{flex-wrap:wrap;gap:8px;margin:0;padding:10px 0;list-style:none;display:flex}.cwb-files li{border:1px solid var(--cwb-border);border-radius:6px;align-items:center;gap:6px;max-width:250px;padding:3px 6px;display:inline-flex}.cwb-files li span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.cwb-hint{color:var(--cwb-muted);margin:10px 0 0;font-size:12px;line-height:1.6}.cwb-error{border-left:3px solid var(--cwb-accent);background:var(--cwb-selected);color:var(--cwb-ink);padding:12px 14px;line-height:1.6}.cwb-error-heading{justify-content:space-between;align-items:center;gap:12px;display:flex}.cwb-error .cwb-text-button{color:var(--cwb-accent)}.cwb-error summary{cursor:pointer;color:var(--cwb-muted);font-size:12px}.cwb-error details p{white-space:pre-wrap;overflow-wrap:anywhere;margin:8px 0}.cwb-catalog-heading{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;margin:26px 0 6px;display:flex}.cwb-catalog-heading h2{margin:0;font-size:20px;font-weight:600}.cwb-search{border:1px solid var(--cwb-border);color:var(--cwb-muted);border-radius:8px;align-items:center;gap:9px;padding:8px 11px;display:flex}.cwb-search input{width:170px;color:var(--cwb-ink);background:0 0;border:0;outline:0;font-size:13px}.cwb-categories{border-bottom:1px solid var(--cwb-border);gap:22px;margin-bottom:18px;display:flex;overflow-x:auto}.cwb-categories button{color:var(--cwb-muted);white-space:nowrap;background:0 0;border:0;border-bottom:2px solid #0000;padding:12px 3px}.cwb-categories button[aria-pressed=true]{border-bottom-color:var(--cwb-accent);color:var(--cwb-accent);font-weight:550}.cwb-grid{grid-template-columns:repeat(3,minmax(0,1fr));align-items:start;gap:10px;display:grid}.cwb-card{text-align:start;border:1px solid var(--cwb-border);width:100%;min-height:96px;color:var(--cwb-ink);background:var(--cwb-surface);border-radius:9px;grid-template-columns:28px minmax(0,1fr) 18px;align-items:start;gap:10px;padding:14px;transition:border-color .15s,background .15s;display:grid}.cwb-card:hover:not(:disabled){border-color:var(--cwb-accent)}.cwb-card[aria-pressed=true]{border-color:var(--cwb-accent);background:var(--cwb-selected)}.cwb-card-icon{background:var(--cwb-selected);width:40px;height:40px;color:var(--cwb-accent);border-radius:9px;flex:none;justify-content:center;align-items:center;display:inline-flex}.cwb-card .cwb-card-icon{border-radius:6px;width:28px;height:28px}.cwb-card .cwb-card-icon svg{width:19px;height:19px}.cwb-card-copy{flex-direction:column;gap:5px;min-width:0;padding-top:3px;display:flex}.cwb-card-copy strong{overflow-wrap:anywhere;font-size:14px;font-weight:600;line-height:1.4}.cwb-card-copy>span{color:var(--cwb-muted);font-size:12px;line-height:1.55}.cwb-card-corner{width:18px;height:18px;color:var(--cwb-muted);background:0 0;border:0;justify-content:center;align-items:center;margin-top:3px;display:inline-flex}.cwb-card-corner svg{flex:none;display:block}.cwb-empty{color:var(--cwb-muted);padding:20px 0;line-height:1.7}.cwb-library{border:1px solid var(--cwb-border);border-radius:12px;grid-template-columns:minmax(220px,.85fr) minmax(0,2fr);display:grid;overflow:hidden}.cwb-library-list{background:var(--cwb-soft);border-right:1px solid var(--cwb-border);padding:10px}.cwb-library-list button{text-align:start;width:100%;color:var(--cwb-ink);background:0 0;border:1px solid #0000;border-radius:8px;gap:12px;padding:14px 12px;display:flex}.cwb-library-list button[aria-current=true]{border-color:var(--cwb-border);background:var(--cwb-surface)}.cwb-library-list button[aria-current=true]>svg{color:var(--cwb-accent)}.cwb-library-list button>svg{flex:none;margin-top:2px}.cwb-library-list button span{min-width:0}.cwb-library-list strong{overflow-wrap:anywhere;font-size:13px;font-weight:550;line-height:1.5;display:block}.cwb-library-list small{color:var(--cwb-muted);margin-top:5px;font-size:12px;line-height:1.6;display:block}.cwb-detail{min-width:0;padding:28px 30px}.cwb-detail-title{align-items:center;gap:14px;display:flex}.cwb-detail-title small{color:var(--cwb-muted);font-size:12px}.cwb-detail-title h2{overflow-wrap:anywhere;margin:5px 0 0;font-size:21px;line-height:1.4}.cwb-detail-summary{color:var(--cwb-muted);margin:17px 0 20px;line-height:1.7}.cwb-guide-sections{grid-template-columns:1fr;gap:18px;margin-top:28px;display:grid}.cwb-detail h3{margin:0 0 9px;font-size:14px;font-weight:600}.cwb-guide-sections ul{color:var(--cwb-muted);margin:0;padding-left:18px;font-size:13px;line-height:1.9}.cwb-example{border:1px solid var(--cwb-border);background:var(--cwb-soft);border-radius:9px;margin-top:24px;padding:18px}.cwb-example p{color:var(--cwb-muted);margin:8px 0;font-size:13px;line-height:1.8}.cwb-example .cwb-text-button{color:var(--cwb-accent)}.cwb-example small{color:var(--cwb-muted);margin-top:6px;font-size:11px;display:block}.cwb-version{border-top:1px solid var(--cwb-border);color:var(--cwb-muted);margin-top:24px;padding-top:18px;font-size:12px;line-height:1.8}.cwb-version summary{cursor:pointer}.cwb-version-actions{flex-wrap:wrap;gap:15px;display:flex}.cannbot-workbench{container:cwb/inline-size}@container cwb (width<=900px){.cwb-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@container cwb (width<=590px){.cwb-grid{grid-template-columns:1fr}}@media (width<=1120px){.cwb-content{padding:24px}.cwb-library{grid-template-columns:minmax(190px,.9fr) minmax(0,1.6fr)}.cwb-detail{padding:22px}}@media (width<=700px){.cwb-header{padding:12px 16px}.cwb-content{padding:22px 16px}.cwb-heading h1{font-size:25px}.cwb-grid,.cwb-library{grid-template-columns:1fr}.cwb-library-list{border-right:0;border-bottom:1px solid var(--cwb-border);max-height:220px;overflow:auto}.cwb-composer{padding:15px}.cwb-workspace select{max-width:190px}.cwb-composer-tools{gap:8px}.cwb-composer-actions{align-items:end}.cwb-primary{padding:9px 17px}.cwb-search,.cwb-search input{width:100%}}@media (prefers-reduced-motion:reduce){.cwb-card{transition:none}}.cwb-directory{border:1px solid var(--cwb-border);width:min(600px,100vw - 40px);max-height:80vh;color:var(--cwb-ink);background:var(--cwb-surface);border-radius:12px;padding:24px;overflow:auto}.cwb-directory::backdrop{background:#00000059}.cwb-directory h2{margin:0 0 12px;font-size:20px}.cwb-directory p{color:var(--cwb-muted);font-size:13px}.cwb-directory form{gap:8px;display:flex}.cwb-directory input{border:1px solid var(--cwb-border);background:var(--cwb-surface);min-width:0;color:inherit;border-radius:6px;flex:1;padding:8px}.cwb-directory nav{flex-wrap:wrap;gap:8px;margin:12px 0;display:flex}.cwb-directory-list{max-height:35vh;padding:0;list-style:none;overflow:auto}.cwb-directory-list button{text-align:start;width:100%;color:inherit;cursor:pointer;background:0 0;border:0;border-radius:6px;padding:10px}.cwb-directory-list button:hover{background:var(--cwb-soft)}.cwb-directory footer{justify-content:flex-end;gap:16px;margin-top:20px;display:flex}";
1970
2069
  const tagId = "@cannbot-plugin/cannbot-harness/workbench.css";
1971
2070
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
1972
2071
  const tag = document.createElement("style");
@@ -2093,6 +2192,22 @@ window.__ModuleLoader__.load({
2093
2192
  ru: en,
2094
2193
  pt: en
2095
2194
  }));
2195
+ ctx.effect(() => injectSlot(ctx, "conversation.input.dock", () => ctx.slots.register({
2196
+ name: "conversation.input.dock",
2197
+ id: "todo",
2198
+ priority: -100,
2199
+ order: 0,
2200
+ locale: NAMESPACE
2201
+ }, TaskDock)));
2202
+ ctx.effect(() => injectSlot(ctx, "conversation.session.header.actions", () => ctx.slots.register({
2203
+ name: "conversation.session.header.actions",
2204
+ id: "cannbot-session-workflow",
2205
+ order: -100,
2206
+ locale: NAMESPACE
2207
+ }, (props) => (0, react.createElement)(SessionWorkflow, {
2208
+ ...props,
2209
+ selection
2210
+ }))));
2096
2211
  ctx.effect(() => {
2097
2212
  const controller = createPresentationController(() => mountInterface(ctx, selection, content));
2098
2213
  const releaseToggle = injectSlot(ctx, "sidebar.footer.action", () => ctx.slots.register({