@max-null/dsh-node-appearance 0.3.6 → 0.5.0

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 (28) hide show
  1. package/README.md +27 -3
  2. package/docs/shots//344/272/244/344/273/230/350/241/214-/345/261/225/345/274/200.png +0 -0
  3. package/docs/shots//344/272/244/344/273/230/350/241/214-/346/212/230/345/217/240.png +0 -0
  4. package/docs/shots//344/274/232/350/257/235/351/235/242/346/235/277/346/210/252/345/233/276.png +0 -0
  5. package/docs/shots//346/217/220/351/227/256/345/215/241/347/211/207/346/210/252/345/233/276.png +0 -0
  6. package/docs/shots//347/233/256/346/240/207/350/257/246/346/203/205-/345/261/225/345/274/200.png +0 -0
  7. package/docs/shots//347/233/256/346/240/207/350/257/246/346/203/205-/346/212/230/345/217/240.png +0 -0
  8. package/docs/shots//350/256/276/347/275/256/345/215/241/347/211/207.png +0 -0
  9. package/lib/client.js +782 -26
  10. package/lib/client.js.map +1 -1
  11. package/lib/index.js +4 -0
  12. package/lib/types/client/ask-card.d.ts +19 -0
  13. package/lib/types/client/ask-card.d.ts.map +1 -0
  14. package/lib/types/client/ask-model.d.ts +92 -0
  15. package/lib/types/client/ask-model.d.ts.map +1 -0
  16. package/lib/types/client/deliverable-model.d.ts +69 -0
  17. package/lib/types/client/deliverable-model.d.ts.map +1 -0
  18. package/lib/types/client/deliverable-row.d.ts +19 -0
  19. package/lib/types/client/deliverable-row.d.ts.map +1 -0
  20. package/lib/types/client/goal-detail.d.ts +32 -0
  21. package/lib/types/client/goal-detail.d.ts.map +1 -0
  22. package/lib/types/client/index.d.ts.map +1 -1
  23. package/lib/types/client/palette.d.ts +1 -1
  24. package/lib/types/client/palette.d.ts.map +1 -1
  25. package/lib/types/client/settings-card.d.ts.map +1 -1
  26. package/lib/types/index.d.ts +2 -0
  27. package/lib/types/index.d.ts.map +1 -1
  28. package/package.json +3 -4
package/lib/client.js CHANGED
@@ -25,7 +25,9 @@ window.__ModuleLoader__.load({
25
25
  agent: "#a855f7",
26
26
  execute: "#f59e0b",
27
27
  file: "#22c55e",
28
+ deliver: "#06b6d4",
28
29
  task: "#ec4899",
30
+ ask: "#65a30d",
29
31
  command: "#f97316",
30
32
  thinking: "#c4b5fd",
31
33
  context: "#8a9bb5",
@@ -65,6 +67,7 @@ window.__ModuleLoader__.load({
65
67
  "glob",
66
68
  "grep"
67
69
  ],
70
+ deliver: ["present"],
68
71
  task: [
69
72
  "todo_write",
70
73
  "create_goal",
@@ -78,6 +81,7 @@ window.__ModuleLoader__.load({
78
81
  "schedule_list",
79
82
  "exit_plan_mode"
80
83
  ],
84
+ ask: ["ask_user_question"],
81
85
  other: []
82
86
  };
83
87
  /** Selector matching every tool row inside a tool-call node. */
@@ -192,45 +196,45 @@ window.__ModuleLoader__.load({
192
196
  }
193
197
  //#endregion
194
198
  //#region \0dsh-css:H:\MaxNull\WorkStation\max-null-plugins\dsh-node-appearance\src\client\card.module.css.mjs
195
- const css = ".CDqThG_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.CDqThG_card:hover{border-color:var(--dsw-alias-label-dimmed)}.CDqThG_cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.CDqThG_header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.CDqThG_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.CDqThG_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.CDqThG_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.CDqThG_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.CDqThG_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.CDqThG_chevronOpen{transform:rotate(180deg)}.CDqThG_body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.CDqThG_readOnly,.CDqThG_statusLine{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}.CDqThG_disabled{opacity:.55;pointer-events:none}.CDqThG_footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:16px 0 4px;display:flex}.CDqThG_reset{appearance:none;border:1px solid var(--dsw-alias-border-l2);font:inherit;cursor:pointer;color:var(--dsw-alias-label-secondary);background:0 0;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.CDqThG_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.CDqThG_resetConfirm{border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.CDqThG_reset:disabled{opacity:.4;cursor:default}.CDqThG_reset:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.CDqThG_row{border-top:1px solid var(--dsw-alias-border-l2);align-items:center;gap:10px;margin-top:10px;padding:10px 0 4px;display:flex;position:relative}.CDqThG_row:first-child{border-top:none;margin-top:4px}.CDqThG_rowLabel{min-width:0;color:var(--dsw-alias-label-primary);flex-direction:column;flex:1;gap:2px;font-size:13px;font-weight:500;line-height:1.5;display:flex}.CDqThG_rowHint{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:1.5}.CDqThG_colorInput{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);cursor:pointer;border-radius:8px;flex:none;width:34px;height:28px;padding:2px}.CDqThG_colorValue{width:64px;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;font-size:12px;line-height:1.5}.CDqThG_sectionTitle{color:var(--dsw-alias-label-primary);margin:14px 0 0;font-size:13px;font-weight:600;line-height:1.5}.CDqThG_toolName{min-width:0;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;flex:1;font-size:13px;line-height:1.5;overflow:hidden}.CDqThG_removeButton{appearance:none;border:1px solid var(--dsw-alias-border-l2);font:inherit;cursor:pointer;color:var(--dsw-alias-label-secondary);background:0 0;border-radius:8px;flex:none;padding:3px 10px;font-size:12px;line-height:1.5}.CDqThG_removeButton:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.CDqThG_addRow{align-items:center;gap:8px;margin-top:10px;margin-bottom:12px;display:flex}.CDqThG_toolInput{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);min-width:0;height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;flex:1;padding:0 12px;font-size:13px;line-height:1.5}.CDqThG_toolInput:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.CDqThG_toolInput::placeholder{color:var(--dsw-alias-label-tertiary)}.CDqThG_addButton{appearance:none;font:inherit;cursor:pointer;background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3);border:1px solid #0000;border-radius:8px;flex:none;padding:5px 14px;font-size:13px;line-height:1.5}.CDqThG_addButton:disabled{opacity:.4;cursor:default}.CDqThG_switch{cursor:pointer;background:var(--dsw-alias-border-l4,#00000029);border:none;border-radius:11px;flex:none;width:40px;height:22px;padding:0;transition:background .15s}.CDqThG_switch.CDqThG_on{background:var(--dsw-alias-state-business-primary,#4fc3f7)}.CDqThG_knob{pointer-events:none;background:#fff;border-radius:8px;width:16px;height:16px;margin-left:2px;transition:margin-left .15s;display:block}.CDqThG_switch.CDqThG_on .CDqThG_knob{margin-left:22px}";
196
- const tagId = "@max-null/dsh-node-appearance/card.module.css";
197
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
199
+ const css$3 = ".CDqThG_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.CDqThG_card:hover{border-color:var(--dsw-alias-label-dimmed)}.CDqThG_cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.CDqThG_header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.CDqThG_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.CDqThG_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.CDqThG_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.CDqThG_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.CDqThG_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.CDqThG_chevronOpen{transform:rotate(180deg)}.CDqThG_body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.CDqThG_readOnly,.CDqThG_statusLine{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}.CDqThG_disabled{opacity:.55;pointer-events:none}.CDqThG_footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:16px 0 4px;display:flex}.CDqThG_reset{appearance:none;border:1px solid var(--dsw-alias-border-l2);font:inherit;cursor:pointer;color:var(--dsw-alias-label-secondary);background:0 0;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.CDqThG_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.CDqThG_resetConfirm{border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.CDqThG_reset:disabled{opacity:.4;cursor:default}.CDqThG_reset:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.CDqThG_row{border-top:1px solid var(--dsw-alias-border-l2);align-items:center;gap:10px;margin-top:10px;padding:10px 0 4px;display:flex;position:relative}.CDqThG_row:first-child{border-top:none;margin-top:4px}.CDqThG_rowLabel{min-width:0;color:var(--dsw-alias-label-primary);flex-direction:column;flex:1;gap:2px;font-size:13px;font-weight:500;line-height:1.5;display:flex}.CDqThG_rowHint{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:1.5}.CDqThG_colorInput{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);cursor:pointer;border-radius:8px;flex:none;width:34px;height:28px;padding:2px}.CDqThG_colorValue{width:64px;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;font-size:12px;line-height:1.5}.CDqThG_sectionTitle{color:var(--dsw-alias-label-primary);margin:14px 0 0;font-size:13px;font-weight:600;line-height:1.5}.CDqThG_toolName{min-width:0;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;flex:1;font-size:13px;line-height:1.5;overflow:hidden}.CDqThG_removeButton{appearance:none;border:1px solid var(--dsw-alias-border-l2);font:inherit;cursor:pointer;color:var(--dsw-alias-label-secondary);background:0 0;border-radius:8px;flex:none;padding:3px 10px;font-size:12px;line-height:1.5}.CDqThG_removeButton:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.CDqThG_addRow{align-items:center;gap:8px;margin-top:10px;margin-bottom:12px;display:flex}.CDqThG_toolInput{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);min-width:0;height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;flex:1;padding:0 12px;font-size:13px;line-height:1.5}.CDqThG_toolInput:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.CDqThG_toolInput::placeholder{color:var(--dsw-alias-label-tertiary)}.CDqThG_addButton{appearance:none;font:inherit;cursor:pointer;background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3);border:1px solid #0000;border-radius:8px;flex:none;padding:5px 14px;font-size:13px;line-height:1.5}.CDqThG_addButton:disabled{opacity:.4;cursor:default}.CDqThG_switch{cursor:pointer;background:var(--dsw-alias-border-l4,#00000029);border:none;border-radius:11px;flex:none;width:40px;height:22px;padding:0;transition:background .15s}.CDqThG_switch.CDqThG_on{background:var(--dsw-alias-state-business-primary,#4fc3f7)}.CDqThG_knob{pointer-events:none;background:#fff;border-radius:8px;width:16px;height:16px;margin-left:2px;transition:margin-left .15s;display:block}.CDqThG_switch.CDqThG_on .CDqThG_knob{margin-left:22px}";
200
+ const tagId$3 = "@max-null/dsh-node-appearance/card.module.css";
201
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
198
202
  const tag = document.createElement("style");
199
203
  tag.dataset.plugin = "@max-null/dsh-node-appearance";
200
- tag.dataset.pluginCss = tagId;
201
- tag.textContent = css;
204
+ tag.dataset.pluginCss = tagId$3;
205
+ tag.textContent = css$3;
202
206
  document.head.appendChild(tag);
203
207
  }
204
208
  var card_module_css_default = {
205
- "reset": "CDqThG_reset",
206
- "header": "CDqThG_header",
207
- "disabled": "CDqThG_disabled",
208
209
  "toolInput": "CDqThG_toolInput",
209
- "chevron": "CDqThG_chevron",
210
+ "knob": "CDqThG_knob",
211
+ "disabled": "CDqThG_disabled",
212
+ "header": "CDqThG_header",
213
+ "headText": "CDqThG_headText",
214
+ "colorValue": "CDqThG_colorValue",
210
215
  "rowHint": "CDqThG_rowHint",
211
- "statusLine": "CDqThG_statusLine",
212
- "addButton": "CDqThG_addButton",
213
216
  "sectionTitle": "CDqThG_sectionTitle",
214
- "headText": "CDqThG_headText",
215
- "colorInput": "CDqThG_colorInput",
216
- "removeButton": "CDqThG_removeButton",
217
- "readOnly": "CDqThG_readOnly",
218
- "resetConfirm": "CDqThG_resetConfirm",
219
- "on": "CDqThG_on",
220
- "description": "CDqThG_description",
221
- "row": "CDqThG_row",
222
- "addRow": "CDqThG_addRow",
223
- "footer": "CDqThG_footer",
224
- "body": "CDqThG_body",
225
- "knob": "CDqThG_knob",
226
- "chevronOpen": "CDqThG_chevronOpen",
227
217
  "rowLabel": "CDqThG_rowLabel",
228
218
  "switch": "CDqThG_switch",
229
- "name": "CDqThG_name",
219
+ "chevron": "CDqThG_chevron",
220
+ "readOnly": "CDqThG_readOnly",
221
+ "description": "CDqThG_description",
222
+ "on": "CDqThG_on",
230
223
  "toolName": "CDqThG_toolName",
224
+ "reset": "CDqThG_reset",
225
+ "resetConfirm": "CDqThG_resetConfirm",
226
+ "body": "CDqThG_body",
227
+ "addRow": "CDqThG_addRow",
228
+ "addButton": "CDqThG_addButton",
231
229
  "cardOpen": "CDqThG_cardOpen",
230
+ "statusLine": "CDqThG_statusLine",
231
+ "colorInput": "CDqThG_colorInput",
232
232
  "card": "CDqThG_card",
233
- "colorValue": "CDqThG_colorValue"
233
+ "removeButton": "CDqThG_removeButton",
234
+ "name": "CDqThG_name",
235
+ "row": "CDqThG_row",
236
+ "chevronOpen": "CDqThG_chevronOpen",
237
+ "footer": "CDqThG_footer"
234
238
  };
235
239
  //#endregion
236
240
  //#region src/client/settings-card.tsx
@@ -253,7 +257,9 @@ window.__ModuleLoader__.load({
253
257
  agent: "智能体调用",
254
258
  execute: "代码 / 指令执行",
255
259
  file: "文件操作",
260
+ deliver: "交付文件",
256
261
  task: "任务 / 目标",
262
+ ask: "提问卡片",
257
263
  command: "指令节点",
258
264
  thinking: "思考过程",
259
265
  context: "上下文注入",
@@ -480,6 +486,739 @@ window.__ModuleLoader__.load({
480
486
  });
481
487
  }
482
488
  //#endregion
489
+ //#region src/client/ask-model.ts
490
+ function isRecord(value) {
491
+ return typeof value === "object" && value !== null && !Array.isArray(value);
492
+ }
493
+ /** 读一个字符串字段,非字符串一律当空串。 */
494
+ function text(value) {
495
+ return typeof value === "string" ? value : "";
496
+ }
497
+ function parseJson(source) {
498
+ try {
499
+ return JSON.parse(source);
500
+ } catch {
501
+ return;
502
+ }
503
+ }
504
+ /** 从结果内容块拼出展示文本(文本块原样、其余块转 JSON)。 */
505
+ function resultTextOf(block) {
506
+ const content = block.content;
507
+ if (!Array.isArray(content) || content.length === 0) return null;
508
+ const parts = [];
509
+ for (const part of content) if (isRecord(part) && part.type === "text" && typeof part.text === "string") parts.push(part.text);
510
+ else parts.push(JSON.stringify(part, null, 2));
511
+ return parts.length === 0 ? null : parts.join("\n");
512
+ }
513
+ function readOptions(value) {
514
+ if (!Array.isArray(value)) return [];
515
+ const options = [];
516
+ for (const item of value) {
517
+ if (typeof item === "string") {
518
+ if (item !== "") options.push({
519
+ label: item,
520
+ description: ""
521
+ });
522
+ continue;
523
+ }
524
+ if (!isRecord(item)) continue;
525
+ const label = text(item.label);
526
+ if (label === "") continue;
527
+ options.push({
528
+ label,
529
+ description: text(item.description)
530
+ });
531
+ }
532
+ return options;
533
+ }
534
+ /** 读调用参数里的问题列表;拿不到合法问题时返回 null(由调用方兜底)。 */
535
+ function readQuestions(argsRaw) {
536
+ const parsed = parseJson(argsRaw);
537
+ if (!isRecord(parsed) || !Array.isArray(parsed.questions)) return null;
538
+ const questions = [];
539
+ for (const item of parsed.questions) {
540
+ if (!isRecord(item)) continue;
541
+ const question = text(item.question);
542
+ if (question === "") continue;
543
+ questions.push({
544
+ id: text(item.id),
545
+ question,
546
+ header: text(item.header),
547
+ detail: text(item.detail),
548
+ multiSelect: item.multiSelect === true,
549
+ options: readOptions(item.options)
550
+ });
551
+ }
552
+ return questions.length === 0 ? null : questions;
553
+ }
554
+ function readAnswers(resultText) {
555
+ if (resultText === null) return null;
556
+ const parsed = parseJson(resultText);
557
+ if (!isRecord(parsed) || !Array.isArray(parsed.answers)) return null;
558
+ const answers = [];
559
+ for (const item of parsed.answers) {
560
+ if (!isRecord(item)) continue;
561
+ const selected = Array.isArray(item.selected) ? item.selected.filter((v) => typeof v === "string") : [];
562
+ answers.push({
563
+ id: text(item.id),
564
+ selected,
565
+ custom: text(item.custom)
566
+ });
567
+ }
568
+ return answers;
569
+ }
570
+ /** 调用参数:运行中取 block 自身,结算后取结算节点的调用头。 */
571
+ function argsRawOf(block) {
572
+ return "kind" in block ? block.call?.argsRaw ?? "" : block.argsRaw ?? "";
573
+ }
574
+ /**
575
+ * 从一次提问调用的冻结切片派生卡片模型。
576
+ * @param block - 运行中的调用或已结算的结果节点。
577
+ * @returns 卡片模型;参数或结果畸形时 `questions` 为空并带兜底文本。
578
+ */
579
+ function askCardModel(block) {
580
+ const settled = "kind" in block;
581
+ const code = settled ? block.error?.code : void 0;
582
+ const state = !settled ? "running" : code === "ASK_ABORTED" || code === "interrupted" ? "stopped" : code === "ASK_CANCELLED" ? "ok" : block.isError === true ? "error" : "ok";
583
+ const argsRaw = argsRawOf(block);
584
+ const resultText = settled ? resultTextOf(block) : null;
585
+ let verdict;
586
+ let phase;
587
+ if (code === "ASK_CANCELLED") {
588
+ verdict = "cancelled";
589
+ phase = "unanswered";
590
+ } else if (code === "ASK_ABORTED") {
591
+ verdict = "aborted";
592
+ phase = "unanswered";
593
+ } else if (!settled) phase = "pending";
594
+ else phase = resultText === null ? "unanswered" : "answered";
595
+ const raw = readQuestions(argsRaw);
596
+ if (raw === null) return {
597
+ state,
598
+ phase,
599
+ verdict,
600
+ questions: [],
601
+ answeredCount: 0,
602
+ fallbackText: resultText ?? (argsRaw === "" ? null : argsRaw)
603
+ };
604
+ const byId = /* @__PURE__ */ new Map();
605
+ for (const answer of readAnswers(resultText) ?? []) if (!byId.has(answer.id)) byId.set(answer.id, answer);
606
+ const questions = raw.map((question) => {
607
+ const answer = byId.get(question.id);
608
+ return {
609
+ ...question,
610
+ selected: answer?.selected ?? [],
611
+ custom: answer?.custom ?? ""
612
+ };
613
+ });
614
+ const answeredCount = questions.filter((question) => question.selected.length > 0 || question.custom !== "").length;
615
+ return {
616
+ state,
617
+ phase,
618
+ verdict,
619
+ questions,
620
+ answeredCount,
621
+ fallbackText: resultText
622
+ };
623
+ }
624
+ /** 折叠行右侧的进度计数(文案由组件用 locale 组装)。 */
625
+ function askProgress(model) {
626
+ return {
627
+ answered: model.answeredCount,
628
+ total: model.questions.length
629
+ };
630
+ }
631
+ //#endregion
632
+ //#region \0dsh-css:H:\MaxNull\WorkStation\max-null-plugins\dsh-node-appearance\src\client\ask-card.module.css.mjs
633
+ const css$2 = ".ylzLDa_root{--ask-accent:var(--ncolor-accent,#65a30d);flex-direction:column;display:flex}.ylzLDa_row{position:relative;overflow:hidden}.ylzLDa_root[data-state=running] .ylzLDa_row:after{content:\"\";background:linear-gradient(90deg, transparent 0%, color-mix(in srgb, var(--dsw-alias-bg-base) 60%, transparent) 55%, transparent 100%);pointer-events:none;width:300px;animation:2.6s ease-out infinite ylzLDa_ask-row-sweep;position:absolute;top:0;bottom:0;left:0}@keyframes ylzLDa_ask-row-sweep{0%{left:-300px}90%,to{left:100%}}.ylzLDa_leading{flex-shrink:0}.ylzLDa_chevron{color:var(--dsw-alias-label-secondary)}.ylzLDa_title{font-weight:400}.ylzLDa_sep{background:var(--dsw-alias-label-caption);border-radius:1px;flex:none;width:2px;height:2px;margin:0 8px}.ylzLDa_summary{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-tertiary);flex:auto;overflow:hidden}.ylzLDa_bodyWrap{flex-direction:column;display:flex}.ylzLDa_card{border:1px solid color-mix(in srgb, var(--ask-accent) 34%, transparent);background:color-mix(in srgb, var(--ask-accent) 6%, var(--dsw-alias-bg-base));border-radius:12px;flex-direction:column;gap:14px;margin:4px 0 4px 4px;padding:14px 16px;display:flex}.ylzLDa_item{flex-direction:column;gap:8px;min-width:0;display:flex}.ylzLDa_header{color:var(--ask-accent);font-size:var(--dsh-content-font-size-secondary,13px);font-weight:500;line-height:calc(20px + var(--dsh-content-font-delta,0px))}.ylzLDa_question{color:var(--dsw-alias-label-primary);font-size:var(--dsh-content-font-size,14px);line-height:calc(22px + var(--dsh-content-font-delta,0px));white-space:pre-wrap;overflow-wrap:anywhere}.ylzLDa_detail{color:var(--dsw-alias-label-tertiary);font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(20px + var(--dsh-content-font-delta,0px));white-space:pre-wrap;overflow-wrap:anywhere}.ylzLDa_verdict{color:var(--dsw-alias-label-tertiary);font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(20px + var(--dsh-content-font-delta,0px));margin:0}.ylzLDa_options{flex-direction:column;gap:6px;display:flex}.ylzLDa_option{border:1px solid var(--dsw-alias-border-l3);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);font-size:var(--dsh-content-font-size,14px);line-height:calc(22px + var(--dsh-content-font-delta,0px));border-radius:8px;align-items:flex-start;gap:8px;padding:9px 12px;display:flex}.ylzLDa_option[data-chosen]{border-color:var(--ask-accent);background:color-mix(in srgb, var(--ask-accent) 14%, transparent);color:var(--ask-accent);font-weight:500}.ylzLDa_marker{width:16px;height:calc(22px + var(--dsh-content-font-delta,0px));flex:none;justify-content:center;align-items:center;display:inline-flex}.ylzLDa_optionText{flex-direction:column;gap:2px;min-width:0;display:flex}.ylzLDa_label{overflow-wrap:anywhere}.ylzLDa_desc{color:inherit;opacity:.72;font-size:var(--dsh-content-font-size-secondary,13px);font-weight:400;line-height:calc(20px + var(--dsh-content-font-delta,0px));overflow-wrap:anywhere}.ylzLDa_answers{flex-direction:column;gap:2px;display:flex}.ylzLDa_answerLine{color:var(--dsw-alias-label-primary);font-size:var(--dsh-content-font-size,14px);line-height:calc(22px + var(--dsh-content-font-delta,0px));white-space:pre-wrap;overflow-wrap:anywhere}.ylzLDa_answersEmpty{color:var(--dsw-alias-label-tertiary);font-size:var(--dsh-content-font-size,14px);line-height:calc(22px + var(--dsh-content-font-delta,0px))}.ylzLDa_fallback{white-space:pre-wrap;overflow-wrap:anywhere;font:var(--dsw-font-xs-13);color:var(--dsw-alias-label-tertiary);margin:4px 0 4px 4px}.ylzLDa_inspectButton{border:.5px solid var(--dsw-alias-border-l3);corner-shape:round;background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-secondary);cursor:pointer;opacity:0;border-radius:999px;align-self:flex-start;align-items:center;gap:4px;margin:4px 0 2px 4px;padding:2px 8px;font-size:11px;line-height:16px;transition:opacity .1s;display:inline-flex}.ylzLDa_root:hover .ylzLDa_inspectButton,.ylzLDa_inspectButton:focus-visible{opacity:1}.ylzLDa_inspectButton:hover{background:var(--dsw-alias-interactive-bg-hover-solid);color:var(--dsw-alias-label-primary)}";
634
+ const tagId$2 = "@max-null/dsh-node-appearance/ask-card.module.css";
635
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
636
+ const tag = document.createElement("style");
637
+ tag.dataset.plugin = "@max-null/dsh-node-appearance";
638
+ tag.dataset.pluginCss = tagId$2;
639
+ tag.textContent = css$2;
640
+ document.head.appendChild(tag);
641
+ }
642
+ var ask_card_module_css_default = {
643
+ "ask-row-sweep": "ylzLDa_ask-row-sweep",
644
+ "answers": "ylzLDa_answers",
645
+ "option": "ylzLDa_option",
646
+ "root": "ylzLDa_root",
647
+ "bodyWrap": "ylzLDa_bodyWrap",
648
+ "answersEmpty": "ylzLDa_answersEmpty",
649
+ "label": "ylzLDa_label",
650
+ "header": "ylzLDa_header",
651
+ "question": "ylzLDa_question",
652
+ "row": "ylzLDa_row",
653
+ "detail": "ylzLDa_detail",
654
+ "verdict": "ylzLDa_verdict",
655
+ "chevron": "ylzLDa_chevron",
656
+ "options": "ylzLDa_options",
657
+ "desc": "ylzLDa_desc",
658
+ "fallback": "ylzLDa_fallback",
659
+ "inspectButton": "ylzLDa_inspectButton",
660
+ "card": "ylzLDa_card",
661
+ "leading": "ylzLDa_leading",
662
+ "marker": "ylzLDa_marker",
663
+ "summary": "ylzLDa_summary",
664
+ "title": "ylzLDa_title",
665
+ "answerLine": "ylzLDa_answerLine",
666
+ "sep": "ylzLDa_sep",
667
+ "item": "ylzLDa_item",
668
+ "optionText": "ylzLDa_optionText"
669
+ };
670
+ //#endregion
671
+ //#region src/client/ask-card.tsx
672
+ /**
673
+ * 提问卡:接管 `ask_user_question` 的工具行。
674
+ *
675
+ * 官方转录卡只列**已选答案**,结算后就再也看不到当时还有哪些选项。本卡片
676
+ * 用调用参数里的 `options` 把每个选项都渲染成一块,被选中的那块用插件色板
677
+ * 里 ask 类别的强调色(默认蓝)反显并打勾。
678
+ *
679
+ * 接管是 DSH 支持的机制(keyed slot 用不同 priority 遮蔽既有占用者,
680
+ * 见 ui-slots 的 `register()`),代价是本文件要自己承担官方 ToolRow 的
681
+ * 折叠行外观 —— 因此行外壳逐项对齐 ToolRow.module.css 的既有视觉
682
+ * (24px 行高、2px 分隔点、13px 次级摘要、running 扫光、hover 才现的
683
+ * Inspect 胶囊),组件则全部来自共享的 ui-primitives。
684
+ */
685
+ /** 折叠行右侧的摘要:等待 / 已取消 / 已中断 / 未回答 / N-M 已回答。 */
686
+ function summaryText(model, t) {
687
+ if (model.phase === "pending") return t("ask.waiting");
688
+ if (model.phase === "unanswered") {
689
+ if (model.verdict === "cancelled") return t("ask.cancelled");
690
+ if (model.verdict === "aborted") return t("ask.interrupted");
691
+ return t("ask.skipped");
692
+ }
693
+ const { answered, total } = askProgress(model);
694
+ return t("ask.answered", {
695
+ answered,
696
+ total
697
+ });
698
+ }
699
+ /** 一行「未选/已选」选项块。 */
700
+ function OptionRow({ label, description, chosen }) {
701
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
702
+ className: ask_card_module_css_default.option,
703
+ "data-chosen": chosen ? "" : void 0,
704
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
705
+ className: ask_card_module_css_default.marker,
706
+ "aria-hidden": "true",
707
+ children: chosen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCheckOutline14, {})
708
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
709
+ className: ask_card_module_css_default.optionText,
710
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
711
+ className: ask_card_module_css_default.label,
712
+ children: label
713
+ }), description !== void 0 && description !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
714
+ className: ask_card_module_css_default.desc,
715
+ children: description
716
+ })]
717
+ })]
718
+ });
719
+ }
720
+ /** 展开后的卡片体:逐问题列出全部选项并标出选中项。 */
721
+ function QuestionList({ model, t }) {
722
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
723
+ className: ask_card_module_css_default.card,
724
+ children: [model.verdict !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
725
+ className: ask_card_module_css_default.verdict,
726
+ children: model.verdict === "cancelled" ? t("ask.cancelledDetail") : t("ask.interruptedDetail")
727
+ }), model.questions.map((question, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
728
+ className: ask_card_module_css_default.item,
729
+ children: [
730
+ question.header !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
731
+ className: ask_card_module_css_default.header,
732
+ children: question.header
733
+ }),
734
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
735
+ className: ask_card_module_css_default.question,
736
+ children: question.question
737
+ }),
738
+ question.detail !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
739
+ className: ask_card_module_css_default.detail,
740
+ children: question.detail
741
+ }),
742
+ question.options.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
743
+ className: ask_card_module_css_default.options,
744
+ children: [question.options.map((option, optionIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OptionRow, {
745
+ label: option.label,
746
+ description: option.description,
747
+ chosen: question.selected.includes(option.label)
748
+ }, `${String(optionIndex)}-${option.label}`)), question.custom !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OptionRow, {
749
+ label: question.custom,
750
+ chosen: true
751
+ })]
752
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
753
+ className: ask_card_module_css_default.answers,
754
+ children: [
755
+ question.selected.map((answer, answerIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
756
+ className: ask_card_module_css_default.answerLine,
757
+ children: answer
758
+ }, `${String(answerIndex)}-${answer}`)),
759
+ question.custom !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
760
+ className: ask_card_module_css_default.answerLine,
761
+ children: question.custom
762
+ }),
763
+ question.selected.length === 0 && question.custom === "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
764
+ className: ask_card_module_css_default.answersEmpty,
765
+ children: t("ask.skipped")
766
+ })
767
+ ]
768
+ })
769
+ ]
770
+ }, question.id !== "" ? question.id : `q${String(index)}`))]
771
+ });
772
+ }
773
+ /**
774
+ * 渲染一次提问的完整记录。
775
+ * @param props - locale 翻译函数、冻结的调用切片与可选的轨迹入口。
776
+ * @returns 折叠行 + 展开后的选项卡片。
777
+ */
778
+ function AskQuestionRow({ t, block, inspect }) {
779
+ const model = (0, react.useMemo)(() => askCardModel(block), [block]);
780
+ const [expanded, setExpanded] = (0, react.useState)(false);
781
+ const hasBody = model.questions.length > 0 || model.fallbackText !== null;
782
+ const open = expanded && hasBody;
783
+ const leading = model.state === "error" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "error" }) : model.state === "stopped" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "warning" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconQuestionOutline14, {});
784
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
785
+ className: ask_card_module_css_default.root,
786
+ "data-variant": "others",
787
+ "data-tool": "ask_user_question",
788
+ "data-state": model.state,
789
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DisclosureRow, {
790
+ rowClassName: ask_card_module_css_default.row,
791
+ leadingClassName: ask_card_module_css_default.leading,
792
+ titleClassName: ask_card_module_css_default.title,
793
+ chevronClassName: ask_card_module_css_default.chevron,
794
+ icon: leading,
795
+ title: t("ask.rowTitle"),
796
+ open,
797
+ expandable: hasBody,
798
+ expandOnRowClick: true,
799
+ keepContentWhenOpen: true,
800
+ onToggle: () => {
801
+ setExpanded((value) => !value);
802
+ },
803
+ collapsedContent: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
804
+ className: ask_card_module_css_default.sep,
805
+ "aria-hidden": true
806
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
807
+ className: ask_card_module_css_default.summary,
808
+ children: summaryText(model, t)
809
+ })] }),
810
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
811
+ className: ask_card_module_css_default.bodyWrap,
812
+ children: [model.questions.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QuestionList, {
813
+ model,
814
+ t
815
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
816
+ className: ask_card_module_css_default.fallback,
817
+ children: model.fallbackText
818
+ }), inspect !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
819
+ type: "button",
820
+ className: ask_card_module_css_default.inspectButton,
821
+ onClick: inspect,
822
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconInspectOutline12, {}), t("row.inspect")]
823
+ })]
824
+ })
825
+ })
826
+ });
827
+ }
828
+ //#endregion
829
+ //#region src/client/deliverable-model.ts
830
+ /**
831
+ * 从参数 JSON 里取文件路径。
832
+ * 截断的 JSON(调用仍在流式输出)返回 null —— 与官方一致:那时原样显示参数
833
+ * 文本,而不是当成「零个文件」。
834
+ * @param raw - 参数 JSON 原文。
835
+ * @returns 路径数组;JSON 未成形时为 null。
836
+ */
837
+ function parsePaths(raw) {
838
+ let args;
839
+ try {
840
+ args = JSON.parse(raw);
841
+ } catch {
842
+ return null;
843
+ }
844
+ if (typeof args !== "object" || args === null || !("files" in args)) return null;
845
+ const files = args.files;
846
+ if (!Array.isArray(files)) return null;
847
+ return files.flatMap((file) => {
848
+ if (typeof file !== "object" || file === null || !("path" in file)) return [];
849
+ const path = file.path;
850
+ return typeof path === "string" ? [path] : [];
851
+ });
852
+ }
853
+ /** 最后一个路径分隔符的下标;没有分隔符时为 -1。 */
854
+ function separatorAt(path) {
855
+ return Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
856
+ }
857
+ /** 扩展名徽标:最后一个点之后的部分,过长截断;无扩展名返回 null。 */
858
+ function extensionBadge(name) {
859
+ const dot = name.lastIndexOf(".");
860
+ if (dot <= 0 || dot === name.length - 1) return null;
861
+ const ext = name.slice(dot + 1);
862
+ return (ext.length <= 4 ? ext : ext.slice(0, 4)).toUpperCase();
863
+ }
864
+ /** 拆一行:路径 → 文件名 + 所在目录 + 扩展名徽标。 */
865
+ function fileOf(path) {
866
+ const cut = separatorAt(path);
867
+ const name = cut === -1 ? path : path.slice(cut + 1);
868
+ return {
869
+ path,
870
+ name,
871
+ dir: cut === -1 ? "" : path.slice(0, cut),
872
+ badge: extensionBadge(name)
873
+ };
874
+ }
875
+ /**
876
+ * 折叠态摘要。
877
+ * `paths === null` 表示参数 JSON 未成形,此时按官方做法原样显示参数文本;解析
878
+ * 成功但一个路径都没取到时返回空串,不把 `{"files":[]}` 这种原文当摘要抛出去。
879
+ */
880
+ function summaryOf(paths, fallback) {
881
+ if (paths === null) return fallback;
882
+ const first = paths[0];
883
+ if (first === void 0) return "";
884
+ const name = fileOf(first).name;
885
+ return paths.length === 1 ? name : `${name} 等 ${String(paths.length)} 个文件`;
886
+ }
887
+ /** 结果文本:把结果节点拼成一段;未结算时没有结果。 */
888
+ function outputOf(settled, block) {
889
+ if (!settled) return "";
890
+ return (block.content ?? []).map((item) => item.type === "text" ? item.text ?? "" : JSON.stringify(item)).join("\n");
891
+ }
892
+ /** 错误描述:没有结果文本时的兜底,比整行空白有用。 */
893
+ function errorTextOf(error) {
894
+ if (error === void 0) return "";
895
+ const name = error.name ?? "error";
896
+ return error.code === void 0 ? name : `${name}: ${error.code}`;
897
+ }
898
+ /**
899
+ * 派生一次交付的全部渲染数据。
900
+ * @param block - 工具调用/结果块。
901
+ * @returns 状态、折叠摘要、逐文件数据与结果文本。
902
+ */
903
+ function deliverableModel(block) {
904
+ const settled = "kind" in block;
905
+ const state = !settled ? "running" : block.error?.code === "interrupted" ? "stopped" : block.isError === true ? "error" : "ok";
906
+ const args = (settled ? block.call?.argsRaw : block.argsRaw) ?? "";
907
+ const output = outputOf(settled, block);
908
+ const details = output !== "" ? output : settled ? errorTextOf(block.error) : "";
909
+ const paths = parsePaths(args);
910
+ const files = paths?.map(fileOf) ?? [];
911
+ return {
912
+ state,
913
+ summary: summaryOf(paths, args),
914
+ files,
915
+ details,
916
+ lineCount: details === "" ? 0 : details.split("\n").length,
917
+ expandable: files.length > 0 || details !== ""
918
+ };
919
+ }
920
+ //#endregion
921
+ //#region \0dsh-css:H:\MaxNull\WorkStation\max-null-plugins\dsh-node-appearance\src\client\deliverable-row.module.css.mjs
922
+ const css$1 = "._8xFzxq_root{--deliverable-accent:var(--ncolor-accent,#06b6d4);flex-direction:column;display:flex}._8xFzxq_row{position:relative;overflow:hidden}._8xFzxq_root[data-state=running] ._8xFzxq_row:after{content:\"\";background:linear-gradient(90deg, transparent 0%, color-mix(in srgb, var(--dsw-alias-bg-base) 60%, transparent) 55%, transparent 100%);pointer-events:none;width:300px;animation:2.6s ease-out infinite _8xFzxq_deliverable-row-sweep;position:absolute;top:0;bottom:0;left:0}@keyframes _8xFzxq_deliverable-row-sweep{0%{left:-300px}90%,to{left:100%}}._8xFzxq_leading{flex-shrink:0}._8xFzxq_chevron{color:var(--dsw-alias-label-secondary)}._8xFzxq_title{font-weight:400}._8xFzxq_sep{background:var(--dsw-alias-label-caption);border-radius:1px;flex:none;width:2px;height:2px;margin:0 8px}._8xFzxq_summary{min-width:0;font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-tertiary);flex:auto;align-items:center;gap:8px;display:flex;overflow:hidden}._8xFzxq_state{color:var(--dsw-alias-label-secondary);flex:none}._8xFzxq_paths{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}._8xFzxq_bodyWrap{flex-direction:column;padding:2px 0 2px 4px;display:flex}._8xFzxq_files{flex-direction:column;gap:4px;margin:4px 0 0;padding:0;list-style:none;display:flex}._8xFzxq_file{align-items:center;gap:8px;min-width:0;display:flex}._8xFzxq_ext{box-sizing:border-box;background:color-mix(in srgb, var(--deliverable-accent) 14%, transparent);width:38px;color:var(--deliverable-accent);letter-spacing:.04em;text-align:center;border-radius:4px;flex:none;padding:1px 4px;font-size:10px;font-weight:600;line-height:16px}._8xFzxq_name{color:var(--dsw-alias-label-primary);font-size:var(--dsh-content-font-size,14px);line-height:calc(20px + var(--dsh-content-font-delta,0px));overflow-wrap:anywhere;flex:none}._8xFzxq_path{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-tertiary);font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(20px + var(--dsh-content-font-delta,0px));flex:auto;overflow:hidden}._8xFzxq_meta{color:var(--dsw-alias-label-tertiary);font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(20px + var(--dsh-content-font-delta,0px));margin-top:10px}._8xFzxq_output{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);white-space:pre-wrap;overflow-wrap:anywhere;border-radius:8px;margin:8px 0 0;padding:12px;font-size:12px}._8xFzxq_inspectButton{border:.5px solid var(--dsw-alias-border-l3);corner-shape:round;background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-secondary);cursor:pointer;opacity:0;border-radius:999px;align-self:flex-start;align-items:center;gap:4px;margin:8px 0 2px;padding:2px 8px;font-size:11px;line-height:16px;transition:opacity .1s;display:inline-flex}._8xFzxq_root:hover ._8xFzxq_inspectButton,._8xFzxq_inspectButton:focus-visible{opacity:1}._8xFzxq_inspectButton:hover{background:var(--dsw-alias-interactive-bg-hover-solid);color:var(--dsw-alias-label-primary)}";
923
+ const tagId$1 = "@max-null/dsh-node-appearance/deliverable-row.module.css";
924
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
925
+ const tag = document.createElement("style");
926
+ tag.dataset.plugin = "@max-null/dsh-node-appearance";
927
+ tag.dataset.pluginCss = tagId$1;
928
+ tag.textContent = css$1;
929
+ document.head.appendChild(tag);
930
+ }
931
+ var deliverable_row_module_css_default = {
932
+ "name": "_8xFzxq_name",
933
+ "title": "_8xFzxq_title",
934
+ "state": "_8xFzxq_state",
935
+ "row": "_8xFzxq_row",
936
+ "chevron": "_8xFzxq_chevron",
937
+ "output": "_8xFzxq_output",
938
+ "deliverable-row-sweep": "_8xFzxq_deliverable-row-sweep",
939
+ "leading": "_8xFzxq_leading",
940
+ "path": "_8xFzxq_path",
941
+ "meta": "_8xFzxq_meta",
942
+ "paths": "_8xFzxq_paths",
943
+ "summary": "_8xFzxq_summary",
944
+ "bodyWrap": "_8xFzxq_bodyWrap",
945
+ "root": "_8xFzxq_root",
946
+ "files": "_8xFzxq_files",
947
+ "file": "_8xFzxq_file",
948
+ "ext": "_8xFzxq_ext",
949
+ "sep": "_8xFzxq_sep",
950
+ "inspectButton": "_8xFzxq_inspectButton"
951
+ };
952
+ //#endregion
953
+ //#region src/client/deliverable-row.tsx
954
+ /**
955
+ * 交付行:接管 `present` 的工具行。
956
+ *
957
+ * 官方 PresentRow 是一个 45 行的折叠行:状态点 + 「交付文件」标题 + **逗号拼接
958
+ * 的文件名** + 可展开的结果文本 + inspect 入口。多文件时那串文件名会挤成一行
959
+ * 读不完,也看不出这一轮交付了几个。
960
+ *
961
+ * 本组件保留官方全部信息与交互(四态、状态词、文件名、结果文本、inspect,以及
962
+ * `data-tool="present"` / `data-state` 这两个样式与快照测试的锚点),另加三件:
963
+ * ① 折叠态文件名只报「首个 + 数量」,多文件不再挤成一行;
964
+ * ② 展开态逐文件成行,带扩展名徽标与所在目录;
965
+ * ③ 结果文本标注行数。
966
+ *
967
+ * 全部派生在 deliverable-model.ts 里,本文件只做 JSX。
968
+ *
969
+ * 接管是 DSH 支持的机制(keyed slot 用不同 priority 遮蔽既有占用者,见
970
+ * ui-slots 的 `register()`;官方插件开发 skill:registering an existing key
971
+ * may replace the product's default card)。代价是本文件要自己承担官方行的
972
+ * 折叠外观 —— 因此行外壳逐项对齐 ToolRow.module.css 与同插件的提问卡
973
+ * (24px 行高、2px 分隔点、13px 次级摘要、running 扫光、hover 才现的
974
+ * Inspect 胶囊),组件全部来自共享 ui-primitives。
975
+ *
976
+ * 下载卡片与「打开」菜单不在这里:它们属于 `conversation.chat.turnTail` 槽的
977
+ * Deliverables 网格,与本 toolview 是两个不同的槽,接管互不影响。
978
+ */
979
+ /** 状态点的外观名,四态映射与官方 PresentRow 一致。 */
980
+ const DOT = {
981
+ running: "ongoing",
982
+ ok: "done",
983
+ stopped: "warning",
984
+ error: "error"
985
+ };
986
+ /** 逐文件一行:扩展名徽标 + 文件名 + 所在目录(完整路径挂在 title 上)。 */
987
+ function FileLine({ file }) {
988
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
989
+ className: deliverable_row_module_css_default.file,
990
+ children: [
991
+ file.badge !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
992
+ className: deliverable_row_module_css_default.ext,
993
+ "aria-hidden": true,
994
+ children: file.badge
995
+ }),
996
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
997
+ className: deliverable_row_module_css_default.name,
998
+ children: file.name
999
+ }),
1000
+ file.dir !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1001
+ className: deliverable_row_module_css_default.path,
1002
+ title: file.path,
1003
+ children: file.dir
1004
+ })
1005
+ ]
1006
+ });
1007
+ }
1008
+ /**
1009
+ * 渲染一次交付的完整记录。
1010
+ * @param props - locale 翻译函数、调用/结果切片与可选的轨迹入口。
1011
+ * @returns 折叠行 + 展开后的文件清单与结果文本。
1012
+ */
1013
+ function DeliverableRow({ t, block, inspect }) {
1014
+ const model = deliverableModel(block);
1015
+ const [expanded, setExpanded] = (0, react.useState)(false);
1016
+ const open = expanded && model.expandable;
1017
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1018
+ className: deliverable_row_module_css_default.root,
1019
+ "data-variant": "others",
1020
+ "data-tool": "present",
1021
+ "data-state": model.state,
1022
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DisclosureRow, {
1023
+ rowClassName: deliverable_row_module_css_default.row,
1024
+ leadingClassName: deliverable_row_module_css_default.leading,
1025
+ titleClassName: deliverable_row_module_css_default.title,
1026
+ chevronClassName: deliverable_row_module_css_default.chevron,
1027
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: DOT[model.state] }),
1028
+ title: t("row.title"),
1029
+ open,
1030
+ expandable: model.expandable,
1031
+ expandOnRowClick: true,
1032
+ keepContentWhenOpen: true,
1033
+ onToggle: () => {
1034
+ setExpanded((value) => !value);
1035
+ },
1036
+ collapsedContent: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1037
+ className: deliverable_row_module_css_default.sep,
1038
+ "aria-hidden": true
1039
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1040
+ className: deliverable_row_module_css_default.summary,
1041
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1042
+ className: deliverable_row_module_css_default.state,
1043
+ children: t(`row.${model.state}`)
1044
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1045
+ className: deliverable_row_module_css_default.paths,
1046
+ children: model.summary
1047
+ })]
1048
+ })] }),
1049
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1050
+ className: deliverable_row_module_css_default.bodyWrap,
1051
+ children: [
1052
+ model.files.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
1053
+ className: deliverable_row_module_css_default.files,
1054
+ "aria-label": t("presented.all", { count: model.files.length }),
1055
+ children: model.files.map((file, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FileLine, { file }, `${String(index)}-${file.path}`))
1056
+ }),
1057
+ model.details !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [model.files.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1058
+ className: deliverable_row_module_css_default.meta,
1059
+ children: `输出 ${String(model.lineCount)} 行`
1060
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
1061
+ className: deliverable_row_module_css_default.output,
1062
+ children: model.details
1063
+ })] }),
1064
+ inspect !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1065
+ type: "button",
1066
+ className: deliverable_row_module_css_default.inspectButton,
1067
+ onClick: inspect,
1068
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconInspectOutline12, {}), t("row.inspect")]
1069
+ })
1070
+ ]
1071
+ })
1072
+ })
1073
+ });
1074
+ }
1075
+ //#endregion
1076
+ //#region \0dsh-css:H:\MaxNull\WorkStation\max-null-plugins\dsh-node-appearance\src\client\goal-detail.module.css.mjs
1077
+ const css = ".WyWU3a_root{box-sizing:border-box;width:calc(100% - var(--dsh-composer-side-clearance) - var(--dsh-composer-side-clearance) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset));max-width:calc(var(--dsh-composer-card-max-width) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset));border:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-specific-tip);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-top-color:#0000;border-radius:0 0 12px 12px;flex:none;margin:-6px auto 0;overflow:hidden}[data-goal-bar]>div:first-child{border-bottom-color:#0000;border-bottom-right-radius:0;border-bottom-left-radius:0}.WyWU3a_body{flex-direction:column;gap:8px;padding:6px 12px;display:flex}.WyWU3a_header{text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:10px;width:100%;padding:0;display:flex}.WyWU3a_lead{color:var(--dsw-alias-label-tertiary);flex:none;place-items:center;display:grid}.WyWU3a_title{color:var(--dsw-alias-label-primary);flex:none;font-size:13px;font-weight:500;line-height:24px}.WyWU3a_summary{min-width:0;color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;flex:auto;font-size:13px;line-height:20px;overflow:hidden}.WyWU3a_chevron{color:var(--dsw-alias-label-tertiary);flex:none;place-items:center;display:grid}.WyWU3a_detail{flex-direction:column;gap:6px;max-height:180px;margin:0;display:flex;overflow-y:auto}.WyWU3a_row{grid-template-columns:max-content 1fr;align-items:baseline;column-gap:10px;margin:0;display:grid}.WyWU3a_key{color:var(--dsw-alias-label-caption);font-size:13px;line-height:20px}.WyWU3a_value{min-width:0;color:var(--dsw-alias-label-secondary);white-space:pre-wrap;overflow-wrap:anywhere;margin:0;font-size:13px;line-height:20px}.WyWU3a_code{font-family:var(--ds-font-family-code);color:var(--dsw-alias-label-caption);font-size:11px}.WyWU3a_value>.WyWU3a_code:not(:first-child){margin-left:8px}";
1078
+ const tagId = "@max-null/dsh-node-appearance/goal-detail.module.css";
1079
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
1080
+ const tag = document.createElement("style");
1081
+ tag.dataset.plugin = "@max-null/dsh-node-appearance";
1082
+ tag.dataset.pluginCss = tagId;
1083
+ tag.textContent = css;
1084
+ document.head.appendChild(tag);
1085
+ }
1086
+ var goal_detail_module_css_default = {
1087
+ "root": "WyWU3a_root",
1088
+ "lead": "WyWU3a_lead",
1089
+ "chevron": "WyWU3a_chevron",
1090
+ "key": "WyWU3a_key",
1091
+ "body": "WyWU3a_body",
1092
+ "title": "WyWU3a_title",
1093
+ "header": "WyWU3a_header",
1094
+ "summary": "WyWU3a_summary",
1095
+ "value": "WyWU3a_value",
1096
+ "row": "WyWU3a_row",
1097
+ "code": "WyWU3a_code",
1098
+ "detail": "WyWU3a_detail"
1099
+ };
1100
+ //#endregion
1101
+ //#region src/client/goal-detail.tsx
1102
+ /**
1103
+ * 目标详情折叠条:接在官方 GoalBar 下面(`conversation.input.dock` 里
1104
+ * `order: 11`,官方那条是 10),把官方条上被 ellipsis 截断的目标展开成可读
1105
+ * 详情。
1106
+ *
1107
+ * 卡片形态照同槽的待办面板(ui-conversation 的 TodoPanel):同一套 dock 宽度
1108
+ * 公式、同一张 `--dsw-specific-tip` 卡片、同一个「标题 + 右侧摘要 + chevron」
1109
+ * 折叠头,默认收起。折叠头只放官方条**没有**的元信息(版本号、自主轮次),
1110
+ * 目标原文放在展开区 —— 这样两块不会互相重复。
1111
+ *
1112
+ * 为什么是「另加一条」而不是接管官方条:`conversation.input.dock` 是 list
1113
+ * 槽,不同 id 各自成格并列渲染;而官方 ui-goal 的注入面(edit/pause/resume/
1114
+ * clear 四个 Remote 动词 + 一个带竞态防护的 activation 订阅源)是**注册者
1115
+ * 私有**的,接管就得整套复刻 —— 那会把这个「只读地多看一行」的需求变成
1116
+ * 插件里多一处会写会话数据的 RPC 客户端。这里只读 `useProjection('goal')`。
1117
+ */
1118
+ /** 阶段文案:与官方 goal 字典同义,按本插件既有做法直写中文。 */
1119
+ const PHASE_LABEL = {
1120
+ active: "进行中",
1121
+ paused: "已暂停",
1122
+ blocked: "已阻塞",
1123
+ complete: "已完成"
1124
+ };
1125
+ /** 折叠头右侧摘要:只放官方条没有的元信息。 */
1126
+ function summaryLabel(goal) {
1127
+ const parts = [`rev ${String(goal.revision)}`];
1128
+ if (goal.roundsStarted !== void 0) parts.push(goal.maxGoalRounds === void 0 ? `${String(goal.roundsStarted)} 轮` : `${String(goal.roundsStarted)} / ${String(goal.maxGoalRounds)} 轮`);
1129
+ return parts.join(" · ");
1130
+ }
1131
+ /** 展开区里的一组「键 / 值」。 */
1132
+ function Row({ label, children }) {
1133
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1134
+ className: goal_detail_module_css_default.row,
1135
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", {
1136
+ className: goal_detail_module_css_default.key,
1137
+ children: label
1138
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
1139
+ className: goal_detail_module_css_default.value,
1140
+ children
1141
+ })]
1142
+ });
1143
+ }
1144
+ /**
1145
+ * 渲染目标详情折叠条。
1146
+ * @param props - 框架标准投影席位。
1147
+ * @returns 折叠条;加载中、无目标、或目标已完成时不渲染(与官方条一致)。
1148
+ */
1149
+ function GoalDetail({ useProjection }) {
1150
+ const projection = useProjection("goal");
1151
+ const [collapsed, setCollapsed] = (0, react.useState)(true);
1152
+ const goalId = projection?.goal.id;
1153
+ (0, react.useEffect)(() => {
1154
+ setCollapsed(true);
1155
+ }, [goalId]);
1156
+ const goal = projection?.goal;
1157
+ if (goal === void 0 || goal === null || goal.phase === "complete") return null;
1158
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
1159
+ className: goal_detail_module_css_default.root,
1160
+ "data-goal-detail": true,
1161
+ "aria-label": "目标详情",
1162
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1163
+ className: goal_detail_module_css_default.body,
1164
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1165
+ type: "button",
1166
+ className: goal_detail_module_css_default.header,
1167
+ "aria-expanded": !collapsed,
1168
+ onClick: () => {
1169
+ setCollapsed((value) => !value);
1170
+ },
1171
+ children: [
1172
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1173
+ className: goal_detail_module_css_default.lead,
1174
+ "aria-hidden": true,
1175
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconGoalOutline16, { size: 14 })
1176
+ }),
1177
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1178
+ className: goal_detail_module_css_default.title,
1179
+ children: "目标详情"
1180
+ }),
1181
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1182
+ className: goal_detail_module_css_default.summary,
1183
+ children: summaryLabel(goal)
1184
+ }),
1185
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1186
+ className: goal_detail_module_css_default.chevron,
1187
+ "aria-hidden": true,
1188
+ children: collapsed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutline14, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, {})
1189
+ })
1190
+ ]
1191
+ }), !collapsed && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", {
1192
+ className: goal_detail_module_css_default.detail,
1193
+ children: [
1194
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
1195
+ label: "目标",
1196
+ children: goal.objective
1197
+ }),
1198
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
1199
+ label: "阶段",
1200
+ children: PHASE_LABEL[goal.phase]
1201
+ }),
1202
+ goal.blockedReason !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Row, {
1203
+ label: "阻塞",
1204
+ children: [goal.blockedReason.message, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1205
+ className: goal_detail_module_css_default.code,
1206
+ children: goal.blockedReason.code
1207
+ })]
1208
+ }),
1209
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
1210
+ label: "标识",
1211
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1212
+ className: goal_detail_module_css_default.code,
1213
+ children: goal.id
1214
+ })
1215
+ })
1216
+ ]
1217
+ })]
1218
+ })
1219
+ });
1220
+ }
1221
+ //#endregion
483
1222
  //#region src/client/index.ts
484
1223
  const inject = [
485
1224
  "slots",
@@ -543,6 +1282,23 @@ window.__ModuleLoader__.load({
543
1282
  key: NODE_APPEARANCE_NS,
544
1283
  inject: () => face
545
1284
  }, NodeAppearanceRow));
1285
+ ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
1286
+ name: "tool.call.toolview",
1287
+ key: "ask_user_question",
1288
+ priority: -1,
1289
+ locale: "conversation"
1290
+ }, AskQuestionRow));
1291
+ ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
1292
+ name: "tool.call.toolview",
1293
+ key: "present",
1294
+ priority: -1,
1295
+ locale: "deliverables"
1296
+ }, DeliverableRow));
1297
+ ctx.slots.inject("conversation.input.dock", () => ctx.slots.register({
1298
+ name: "conversation.input.dock",
1299
+ id: "max-null/goal-detail",
1300
+ order: 11
1301
+ }, GoalDetail));
546
1302
  }
547
1303
  //#endregion
548
1304
  exports.apply = apply;