@linxin666/dsh-client-ui-task-board 0.1.15 → 0.1.17

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
@@ -9,6 +9,16 @@ window.__ModuleLoader__.load({
9
9
  let react_jsx_runtime = require("react/jsx-runtime");
10
10
  let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
11
11
  //#region src/core/tasks.ts
12
+ /** Permission presets a task may pin on its execution session (the `/permission <id>` ids). */
13
+ const TASK_PERMISSIONS = [
14
+ "read-only",
15
+ "workspace-write",
16
+ "danger-full-access"
17
+ ];
18
+ /** Whether an unknown value is a known permission preset id. */
19
+ function isTaskPermission(value) {
20
+ return typeof value === "string" && TASK_PERMISSIONS.includes(value);
21
+ }
12
22
  /** The five kanban columns, in display order. */
13
23
  const COLUMNS = [
14
24
  {
@@ -46,6 +56,11 @@ window.__ModuleLoader__.load({
46
56
  function isTaskStatus(value) {
47
57
  return typeof value === "string" && ALL_STATUSES.includes(value);
48
58
  }
59
+ /** Normalize one optional execution-target string: trim; blank collapses to undefined. */
60
+ function normalizeTargetId$2(value) {
61
+ const trimmed = value?.trim();
62
+ return trimmed === void 0 || trimmed === "" ? void 0 : trimmed;
63
+ }
49
64
  /** Create a task from user input. */
50
65
  function createTask(input, now, id) {
51
66
  return {
@@ -56,7 +71,10 @@ window.__ModuleLoader__.load({
56
71
  status: "todo",
57
72
  createdAt: now,
58
73
  updatedAt: now,
59
- executions: []
74
+ executions: [],
75
+ workspaceId: normalizeTargetId$2(input.workspaceId),
76
+ mode: normalizeTargetId$2(input.mode),
77
+ permission: isTaskPermission(input.permission) ? input.permission : void 0
60
78
  };
61
79
  }
62
80
  /** Clone a task with an updated status and a fresh updatedAt. */
@@ -348,6 +366,25 @@ window.__ModuleLoader__.load({
348
366
  //#endregion
349
367
  //#region src/core/use-cases/task-update.ts
350
368
  /**
369
+ * Update-task use case: apply an editable-field patch (title/description/
370
+ * prompt plus the execution targets workspaceId/mode/permission) with a
371
+ * fresh updatedAt. Pure ledger transition (no persistence or notify — the
372
+ * controller orchestrates those).
373
+ *
374
+ * An explicit `undefined` in the patch clears the field (the task falls
375
+ * back to the runtime default); an unknown permission string is ignored so
376
+ * stale UI can never persist a value the execution service rejects.
377
+ */
378
+ /** Collapse a blank target string to undefined (clears the pin). */
379
+ function normalizeTargetId$1(value) {
380
+ return value !== void 0 && value.trim() === "" ? void 0 : value;
381
+ }
382
+ /** Keep an unknown permission string from entering the ledger. */
383
+ function normalizePermission(current, value) {
384
+ if (value === void 0) return void 0;
385
+ return isTaskPermission(value) ? value : current;
386
+ }
387
+ /**
351
388
  * Apply an update across the ledger. Tasks that do not match the id are left
352
389
  * untouched; the matched task receives the patch plus a fresh updatedAt.
353
390
  * @param tasks - current ledger.
@@ -356,11 +393,21 @@ window.__ModuleLoader__.load({
356
393
  * @param now - clock instant (ms epoch).
357
394
  */
358
395
  function applyUpdateTask(tasks, id, patch, now) {
359
- return tasks.map((task) => task.id === id ? {
360
- ...task,
361
- ...patch,
362
- updatedAt: now
363
- } : task);
396
+ return tasks.map((task) => {
397
+ if (task.id !== id) return task;
398
+ const workspaceId = "workspaceId" in patch ? normalizeTargetId$1(patch.workspaceId) : void 0;
399
+ const mode = "mode" in patch ? normalizeTargetId$1(patch.mode) : void 0;
400
+ const permission = "permission" in patch ? normalizePermission(task.permission, patch.permission) : void 0;
401
+ const next = {
402
+ ...task,
403
+ ...patch,
404
+ updatedAt: now
405
+ };
406
+ if (workspaceId !== void 0 || "workspaceId" in patch) next.workspaceId = workspaceId;
407
+ if (mode !== void 0 || "mode" in patch) next.mode = mode;
408
+ if (permission !== void 0 || "permission" in patch) next.permission = permission;
409
+ return next;
410
+ });
364
411
  }
365
412
  //#endregion
366
413
  //#region src/core/controller.ts
@@ -390,6 +437,10 @@ window.__ModuleLoader__.load({
390
437
  tasks = [];
391
438
  boardOpen = false;
392
439
  selectedTaskId;
440
+ executionOptions = {
441
+ workspaces: [],
442
+ presets: []
443
+ };
393
444
  listeners = /* @__PURE__ */ new Set();
394
445
  disposers = [];
395
446
  now;
@@ -425,7 +476,8 @@ window.__ModuleLoader__.load({
425
476
  return {
426
477
  tasks: this.tasks,
427
478
  boardOpen: this.boardOpen,
428
- selectedTaskId: this.selectedTaskId
479
+ selectedTaskId: this.selectedTaskId,
480
+ executionOptions: this.executionOptions
429
481
  };
430
482
  }
431
483
  subscribe(fn) {
@@ -471,6 +523,17 @@ window.__ModuleLoader__.load({
471
523
  this.tasks = [...applyUpdateTask(this.tasks, id, patch, this.now())];
472
524
  this.persistAndNotify();
473
525
  }
526
+ /**
527
+ * Replace (a part of) the picker option sets the UI feeds (workspace list
528
+ * and agent-preset roster come from the runtime, not the ledger).
529
+ */
530
+ setExecutionOptions(patch) {
531
+ this.executionOptions = {
532
+ ...this.executionOptions,
533
+ ...patch
534
+ };
535
+ this.notify();
536
+ }
474
537
  moveTask(id, status) {
475
538
  this.tasks = this.tasks.map((task) => task.id === id ? withStatus(task, status, this.now()) : task);
476
539
  this.persistAndNotify();
@@ -637,6 +700,18 @@ window.__ModuleLoader__.load({
637
700
  if (error instanceof Error) return error.message;
638
701
  return String(error);
639
702
  }
703
+ /**
704
+ * Whether a rejected preset switch actually means "the session already runs
705
+ * this preset" (the host's agent-preset-conflict with a matching
706
+ * existingPreset). A blank-session reuse race can produce this even though
707
+ * the requested composition is in place.
708
+ */
709
+ function presetAlreadyRuns(error, mode) {
710
+ if (typeof error !== "object" || error === null) return false;
711
+ const details = error.details;
712
+ if (typeof details !== "object" || details === null) return false;
713
+ return details.existingPreset === mode;
714
+ }
640
715
  /** Whether a `turn/end` payload closed the turn with an error reason. */
641
716
  function isErrorTurnEnd(data) {
642
717
  if (typeof data !== "object" || data === null) return false;
@@ -659,8 +734,17 @@ window.__ModuleLoader__.load({
659
734
  this.env = env;
660
735
  }
661
736
  async run(task, execution, onEvent) {
737
+ const settleFailed = (error) => {
738
+ onEvent({
739
+ kind: "settled",
740
+ taskId: task.id,
741
+ executionId: execution.id,
742
+ outcome: "failed",
743
+ error
744
+ });
745
+ };
662
746
  try {
663
- const sessionId = await this.connectSession();
747
+ const sessionId = await this.connectSession(task.workspaceId);
664
748
  onEvent({
665
749
  kind: "started",
666
750
  taskId: task.id,
@@ -669,38 +753,83 @@ window.__ModuleLoader__.load({
669
753
  });
670
754
  const driver = this.driverOf(sessionId);
671
755
  if (driver === void 0) {
672
- onEvent({
673
- kind: "settled",
674
- taskId: task.id,
675
- executionId: execution.id,
676
- outcome: "failed",
677
- error: "execution session is not ready"
678
- });
756
+ settleFailed("execution session is not ready");
679
757
  return;
680
758
  }
759
+ if (!await this.applyMode(driver, task, sessionId, settleFailed)) return;
760
+ if (!await this.applyPermission(driver, task, settleFailed)) return;
681
761
  await driver.rename(task.title).catch(() => {});
682
762
  const baseline = driver.getSnapshot().turnEnds.size;
683
763
  const accepted = await this.sendPrompt(driver, task);
684
764
  if (!accepted.ok) {
685
- onEvent({
686
- kind: "settled",
687
- taskId: task.id,
688
- executionId: execution.id,
689
- outcome: "failed",
690
- error: messageOf(accepted.error)
691
- });
765
+ settleFailed(messageOf(accepted.error));
692
766
  return;
693
767
  }
694
768
  this.watchForSettlement(driver, task.id, execution.id, onEvent, baseline);
695
769
  } catch (error) {
696
- onEvent({
697
- kind: "settled",
698
- taskId: task.id,
699
- executionId: execution.id,
700
- outcome: "failed",
701
- error: messageOf(error)
702
- });
770
+ settleFailed(messageOf(error));
771
+ }
772
+ }
773
+ /**
774
+ * Recompose the execution session's agent from the task-pinned preset.
775
+ * No-op when the task pins none or the session already runs it; fails the
776
+ * run when the session is no longer blank, the preset face is missing, or
777
+ * the wire refuses.
778
+ */
779
+ async applyMode(driver, task, sessionId, settleFailed) {
780
+ const mode = task.mode;
781
+ if (mode === void 0 || mode === "") return true;
782
+ const summary = this.env.sessions.list.getSnapshot().byId[sessionId];
783
+ if (summary?.blank === false) {
784
+ settleFailed(`cannot switch agent preset to ${mode}: the execution session is not blank`);
785
+ return false;
786
+ }
787
+ if (summary?.agentPreset === mode) return true;
788
+ if (this.env.presets === void 0) {
789
+ settleFailed(`this deployment does not support agent presets (task asks for ${mode})`);
790
+ return false;
791
+ }
792
+ try {
793
+ const result = await this.env.presets.select(sessionId, mode);
794
+ if (!result.ok) {
795
+ if (presetAlreadyRuns(result.error, mode)) {
796
+ this.env.sessions.noteAgentPreset?.(sessionId, mode);
797
+ return true;
798
+ }
799
+ settleFailed(`agent preset switch to ${mode} rejected: ${messageOf(result.error)}`);
800
+ return false;
801
+ }
802
+ } catch (error) {
803
+ settleFailed(`agent preset switch to ${mode} failed: ${messageOf(error)}`);
804
+ return false;
805
+ }
806
+ this.env.sessions.noteAgentPreset?.(sessionId, mode);
807
+ return true;
808
+ }
809
+ /**
810
+ * Apply the task-pinned permission preset through the `/permission <id>`
811
+ * slash command. No-op when the task pins none; fails the run when the
812
+ * admission is rejected or no command claimed the line.
813
+ */
814
+ async applyPermission(driver, task, settleFailed) {
815
+ const permission = task.permission;
816
+ if (permission === void 0) return true;
817
+ const line = `/permission ${permission}`;
818
+ try {
819
+ const result = await driver.command(line);
820
+ if (!result.ok) {
821
+ settleFailed(`permission command rejected: ${messageOf(result.error)}`);
822
+ return false;
823
+ }
824
+ if (!result.matched) {
825
+ settleFailed(`permission command not recognized: ${line}`);
826
+ return false;
827
+ }
828
+ } catch (error) {
829
+ settleFailed(`permission command failed: ${messageOf(error)}`);
830
+ return false;
703
831
  }
832
+ return true;
704
833
  }
705
834
  /**
706
835
  * Inspect a reloaded/background task that was left 'running' and emit a
@@ -773,8 +902,12 @@ window.__ModuleLoader__.load({
773
902
  return false;
774
903
  }
775
904
  }
776
- async connectSession() {
905
+ async connectSession(taskWorkspaceId) {
777
906
  const workspace = this.env.workspaces.list.getSnapshot();
907
+ if (taskWorkspaceId !== void 0 && taskWorkspaceId !== "") {
908
+ if (!workspace.items.some((item) => item.workspaceId === taskWorkspaceId)) throw new Error(`task workspace is not available: ${taskWorkspaceId}`);
909
+ return this.env.workspaces.connectWorkspace(taskWorkspaceId);
910
+ }
778
911
  const workspaceId = workspace.recentWorkspaceId ?? workspace.items[0]?.workspaceId;
779
912
  if (workspaceId === void 0) throw new Error("no workspace available to run the task in");
780
913
  return this.env.workspaces.connectWorkspace(workspaceId);
@@ -960,6 +1093,9 @@ window.__ModuleLoader__.load({
960
1093
  if (typeof record.prompt !== "string") return false;
961
1094
  if (typeof record.createdAt !== "number") return false;
962
1095
  if (typeof record.updatedAt !== "number") return false;
1096
+ if (record.workspaceId !== void 0 && typeof record.workspaceId !== "string") return false;
1097
+ if (record.mode !== void 0 && typeof record.mode !== "string") return false;
1098
+ if (record.permission !== void 0 && typeof record.permission !== "string") return false;
963
1099
  if (!Array.isArray(record.executions)) return false;
964
1100
  for (const execution of record.executions) {
965
1101
  if (typeof execution !== "object" || execution === null) return false;
@@ -973,6 +1109,10 @@ window.__ModuleLoader__.load({
973
1109
  }
974
1110
  return true;
975
1111
  }
1112
+ /** Collapse a blank persisted target string to undefined (clears the pin). */
1113
+ function normalizeTargetId(value) {
1114
+ return value !== void 0 && value.trim() === "" ? void 0 : value;
1115
+ }
976
1116
  /** Normalize an unknown persisted status back into the closed status union. */
977
1117
  function normalizeStatus(status) {
978
1118
  return isTaskStatus(status) ? status : "todo";
@@ -1019,6 +1159,9 @@ window.__ModuleLoader__.load({
1019
1159
  status: normalizeStatus(row.status)
1020
1160
  };
1021
1161
  task.schedule = normalizeSchedule(row.schedule);
1162
+ task.workspaceId = normalizeTargetId(row.workspaceId);
1163
+ task.mode = normalizeTargetId(row.mode);
1164
+ task.permission = isTaskPermission(row.permission) ? row.permission : void 0;
1022
1165
  tasks.push(task);
1023
1166
  }
1024
1167
  return tasks;
@@ -1176,6 +1319,20 @@ window.__ModuleLoader__.load({
1176
1319
  "detail.schedule.notScheduled": "尚未排程",
1177
1320
  "detail.schedule.dueSoon": "即将运行",
1178
1321
  "card.scheduled": "定时",
1322
+ "new.workspace": "工作区",
1323
+ "new.mode": "模式",
1324
+ "new.permission": "权限",
1325
+ "exec.workspace.recent": "最近使用(默认)",
1326
+ "exec.mode.default": "部署默认",
1327
+ "exec.mode.defaultSuffix": "(默认)",
1328
+ "exec.mode.brokenSuffix": "(不可用)",
1329
+ "exec.mode.removed": "(已移除)",
1330
+ "exec.permission.default": "会话默认",
1331
+ "exec.permission.read-only": "只读",
1332
+ "exec.permission.workspace-write": "工作区可写",
1333
+ "exec.permission.danger-full-access": "完全访问",
1334
+ "detail.executionSettings": "执行设置",
1335
+ "exec.hint": "执行时生效:工作区决定执行会话落在哪个工作区;模式决定会话的 agent 预设;权限经 /permission 命令应用到会话。留空则使用运行时默认。",
1179
1336
  "settings.title": "任务看板",
1180
1337
  "settings.description": "控制看板在 agent 系统提示中的播报行为。",
1181
1338
  "settings.enabled": "启用任务看板",
@@ -1266,6 +1423,20 @@ window.__ModuleLoader__.load({
1266
1423
  "detail.schedule.notScheduled": "Not scheduled yet",
1267
1424
  "detail.schedule.dueSoon": "Due soon",
1268
1425
  "card.scheduled": "scheduled",
1426
+ "new.workspace": "Workspace",
1427
+ "new.mode": "Mode",
1428
+ "new.permission": "Permission",
1429
+ "exec.workspace.recent": "Most recent (default)",
1430
+ "exec.mode.default": "Deployment default",
1431
+ "exec.mode.defaultSuffix": " (default)",
1432
+ "exec.mode.brokenSuffix": " (unavailable)",
1433
+ "exec.mode.removed": " (removed)",
1434
+ "exec.permission.default": "Session default",
1435
+ "exec.permission.read-only": "Read-only",
1436
+ "exec.permission.workspace-write": "Workspace Write",
1437
+ "exec.permission.danger-full-access": "Full Access",
1438
+ "detail.executionSettings": "Execution Settings",
1439
+ "exec.hint": "Applied when the task runs: the workspace decides where the execution session lands; the mode composes the session's agent preset; the permission is applied through the /permission command. Blank = runtime default.",
1269
1440
  "settings.title": "Task Board",
1270
1441
  "settings.description": "How the board announces itself in each agent system prompt.",
1271
1442
  "settings.enabled": "Enable the task board",
@@ -1300,7 +1471,7 @@ window.__ModuleLoader__.load({
1300
1471
  }
1301
1472
  //#endregion
1302
1473
  //#region \0dsh-css:packages/dsh-task-board/src/client/board.module.css.mjs
1303
- const css$1 = "[data-pane=conversation],[class*=centerCol]{position:relative}[data-dsh-taskboard-view]{z-index:60;background:var(--dsw-alias-bg-base);display:none;position:absolute;inset:0}html[data-dsh-taskboard-active]:not([data-dsh-ssh-active]) [data-dsh-taskboard-view]{display:block}html[data-dsh-taskboard-active]:not([data-dsh-ssh-active]) [data-pane=conversation]>:not([data-dsh-taskboard-view]),html[data-dsh-taskboard-active]:not([data-dsh-ssh-active]) [class*=centerCol]>:not([data-dsh-taskboard-view]){display:none!important}._7D6uKa_entry{width:100%;height:32px;color:var(--dsw-alias-label-secondary);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-radius:8px;align-items:center;gap:8px;padding:0 12px;font-size:13px;display:flex}._7D6uKa_entry:hover{background:var(--dsw-specific-sidebar-nav-item-hover);color:var(--dsw-alias-label-primary)}._7D6uKa_entry[data-active]{background:var(--dsw-specific-sidebar-nav-item-active);color:var(--dsw-alias-label-primary);font-weight:600}._7D6uKa_entryIcon{flex:none;justify-content:center;align-items:center;display:inline-flex}._7D6uKa_entryLabel{text-overflow:ellipsis;overflow:hidden}[data-dsh-frame][data-sidebar-collapsed] ._7D6uKa_entry{justify-content:center;width:100%;padding:0}[data-dsh-frame][data-sidebar-collapsed] ._7D6uKa_entryLabel{display:none}._7D6uKa_board{background:var(--dsw-alias-bg-base);min-width:0;height:100%;min-height:0;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-family);flex-direction:column;gap:12px;padding:14px 16px 16px;display:flex}._7D6uKa_boardHeader{flex:none;align-items:center;gap:10px;display:flex}._7D6uKa_boardTitle{color:var(--dsw-alias-label-primary);white-space:nowrap;margin:0;font-size:16px;font-weight:700}._7D6uKa_search{min-width:120px;color:var(--dsw-alias-label-primary);background:var(--dsw-specific-input-major);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;outline:none;flex:0 260px;padding:6px 10px;font-size:13px}._7D6uKa_search::placeholder{color:var(--dsw-alias-label-tertiary)}._7D6uKa_columns{flex:1;grid-template-columns:repeat(5,minmax(0,1fr));gap:12px;min-height:0;display:grid}._7D6uKa_column{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:12px;flex-direction:column;min-height:0;display:flex;overflow:hidden}._7D6uKa_columnHeader{flex:none;align-items:center;gap:6px;padding:10px 12px;display:flex}._7D6uKa_columnTitle{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;flex:1;margin:0;font-size:13px;font-weight:700;overflow:hidden}._7D6uKa_columnCount{min-width:0;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-interactive-bg-hover);border-radius:999px;flex:none;padding:1px 8px;font-size:12px}._7D6uKa_statusDot{border-radius:50%;flex:none;width:8px;height:8px}._7D6uKa_statusDot[data-status=backlog]{background:var(--dsw-alias-label-tertiary)}._7D6uKa_statusDot[data-status=todo]{background:var(--dsw-alias-state-business-primary)}._7D6uKa_statusDot[data-status=running]{background:var(--dsw-alias-state-warn-primary)}._7D6uKa_statusDot[data-status=done]{background:var(--dsw-alias-state-success-primary)}._7D6uKa_statusDot[data-status=failed]{background:var(--dsw-alias-state-error-primary)}._7D6uKa_cards{flex-direction:column;flex:1;gap:8px;min-height:0;padding:2px 8px 10px;display:flex;overflow-y:auto}._7D6uKa_columnEmpty{text-align:center;color:var(--dsw-alias-label-tertiary);padding:24px 8px;font-size:12px}._7D6uKa_card{text-align:left;background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);cursor:pointer;color:var(--dsw-alias-label-primary);border-radius:10px;flex-direction:column;gap:6px;padding:10px 12px;font-family:inherit;transition:box-shadow .12s,border-color .12s,transform .12s;display:flex}._7D6uKa_card:hover{box-shadow:var(--dsw-shadow-lv2);border-color:var(--dsw-alias-border-l3);transform:translateY(-1px)}._7D6uKa_card[data-status=running]{border-color:var(--dsw-alias-state-warn-primary)}._7D6uKa_cardTitle{-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:13px;font-weight:600;line-height:1.35;display:-webkit-box;overflow:hidden}._7D6uKa_cardExcerpt{color:var(--dsw-alias-label-secondary);-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:12px;line-height:1.4;display:-webkit-box;overflow:hidden}._7D6uKa_cardMeta{color:var(--dsw-alias-label-tertiary);align-items:center;gap:8px;font-size:11px;display:flex}._7D6uKa_cardTime{text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}._7D6uKa_cardSchedule{white-space:nowrap;min-width:0;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-interactive-bg-hover);border-radius:999px;flex:none;padding:2px 6px;font-size:12px;line-height:1}._7D6uKa_cardRun{flex:none}._7D6uKa_cardRun[data-result=failed]{color:var(--dsw-alias-state-error-primary)}._7D6uKa_cardRun[data-result=succeeded]{color:var(--dsw-alias-state-success-primary)}._7D6uKa_cardSession{color:var(--dsw-alias-state-business-primary);flex:none}._7D6uKa_cardRunningLabel{color:var(--dsw-alias-state-warn-primary);font-size:11px}._7D6uKa_cardSpinner{border:2px solid var(--dsw-alias-state-warn-primary);border-top-color:#0000;border-radius:50%;flex:none;width:10px;height:10px;animation:.8s linear infinite _7D6uKa_dshTbSpin}@keyframes _7D6uKa_dshTbSpin{to{transform:rotate(360deg)}}._7D6uKa_primaryButton{color:var(--dsw-alias-label-primary-foreground);background:var(--dsw-alias-button-info-fill);cursor:pointer;white-space:nowrap;border:none;border-radius:8px;padding:6px 14px;font-size:13px;font-weight:600}._7D6uKa_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-info-hover)}._7D6uKa_primaryButton:disabled{opacity:.5;cursor:default}._7D6uKa_ghostButton{color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l2);cursor:pointer;white-space:nowrap;background:0 0;border-radius:8px;padding:5px 12px;font-size:12px}._7D6uKa_ghostButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}._7D6uKa_ghostButton:disabled{opacity:.45;cursor:default}._7D6uKa_dangerButton{color:#fff;background:var(--dsw-alias-state-error-primary);cursor:pointer;white-space:nowrap;border:none;border-radius:8px;padding:6px 14px;font-size:13px;font-weight:600}._7D6uKa_dangerButton:hover:not(:disabled){filter:brightness(1.08)}._7D6uKa_dangerButton:active:not(:disabled){filter:brightness(.94)}._7D6uKa_dangerButton:disabled{opacity:.5;cursor:default}._7D6uKa_iconButton{width:26px;height:26px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;padding:0;font-size:13px;display:inline-flex}._7D6uKa_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._7D6uKa_linkButton{color:var(--dsw-alias-state-business-primary);cursor:pointer;white-space:nowrap;background:0 0;border:none;padding:0;font-size:12px}._7D6uKa_linkButton:hover{text-decoration:underline}._7D6uKa_modalBackdrop{z-index:1300;background:var(--dsw-alias-bg-mask-1);justify-content:center;align-items:center;display:flex;position:fixed;inset:0}._7D6uKa_modal{background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);width:min(520px,100vw - 48px);max-height:calc(100vh - 96px);box-shadow:var(--dsw-shadow-lv3);color:var(--dsw-alias-label-primary);border-radius:14px;flex-direction:column;gap:12px;padding:18px;display:flex;overflow-y:auto}._7D6uKa_modalTitle{margin:0;font-size:15px;font-weight:700}._7D6uKa_confirmMessage{color:var(--dsw-alias-label-secondary);white-space:pre-wrap;overflow-wrap:anywhere;margin:0;font-size:13px;line-height:1.5}._7D6uKa_modalFooter{justify-content:flex-end;gap:10px;margin-top:4px;display:flex}._7D6uKa_field{flex-direction:column;gap:5px;display:flex}._7D6uKa_fieldLabel{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:600}._7D6uKa_input{color:var(--dsw-alias-label-primary);background:var(--dsw-specific-input-major);border:1px solid var(--dsw-alias-border-l2);resize:vertical;border-radius:8px;outline:none;padding:7px 10px;font-family:inherit;font-size:13px}._7D6uKa_input:focus{border-color:var(--dsw-alias-state-business-primary)}._7D6uKa_input::placeholder{color:var(--dsw-alias-label-tertiary)}._7D6uKa_formError{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px}._7D6uKa_detail{background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);width:min(640px,100vw - 48px);max-height:calc(100vh - 80px);box-shadow:var(--dsw-shadow-lv3);color:var(--dsw-alias-label-primary);border-radius:14px;flex-direction:column;display:flex;overflow:hidden}._7D6uKa_detailHeader{border-bottom:1px solid var(--dsw-alias-separator-primary);flex:none;align-items:center;gap:10px;padding:14px 18px;display:flex}._7D6uKa_detailTitle{overflow-wrap:anywhere;flex:1;margin:0;font-size:15px;font-weight:700}._7D6uKa_statusBadge{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:2px 10px;font-size:12px}._7D6uKa_statusBadge[data-status=running]{color:var(--dsw-alias-state-warn-primary);border-color:var(--dsw-alias-state-warn-primary)}._7D6uKa_statusBadge[data-status=done]{color:var(--dsw-alias-state-success-primary);border-color:var(--dsw-alias-state-success-primary)}._7D6uKa_statusBadge[data-status=failed]{color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary)}._7D6uKa_detailBody{flex-direction:column;flex:1;gap:16px;padding:14px 18px;display:flex;overflow-y:auto}._7D6uKa_detailSection{flex-direction:column;gap:6px;display:flex}._7D6uKa_detailSection h4{color:var(--dsw-alias-label-tertiary);text-transform:none;margin:0;font-size:12px;font-weight:700}._7D6uKa_detailText{color:var(--dsw-alias-label-primary);white-space:pre-wrap;overflow-wrap:anywhere;margin:0;font-size:13px;line-height:1.55}._7D6uKa_scheduleToggle{color:var(--dsw-alias-label-primary);cursor:pointer;user-select:none;align-items:center;gap:8px;font-size:13px;display:flex}._7D6uKa_scheduleToggle input{accent-color:var(--dsw-alias-state-business-primary)}._7D6uKa_scheduleRow{align-items:center;gap:8px;display:flex}._7D6uKa_scheduleInput{min-width:0;font-family:var(--dsw-font-markdown-code-block-small);flex:1;font-size:12.5px}._7D6uKa_scheduleInputInvalid,._7D6uKa_scheduleInputInvalid:focus{border-color:var(--dsw-alias-state-error-primary)}._7D6uKa_schedulePreset{color:var(--dsw-alias-label-primary);background:var(--dsw-specific-input-major);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;outline:none;flex:none;padding:7px 8px;font-size:12.5px}._7D6uKa_scheduleMeta{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;margin:0;font-size:12px}._7D6uKa_promptBlock{font-size:12.5px;line-height:1.5;font-family:var(--dsw-font-markdown-code-block-small);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-markdown-code-block);border:1px solid var(--dsw-alias-border-l1);white-space:pre-wrap;overflow-wrap:anywhere;border-radius:8px;max-height:240px;margin:0;padding:10px 12px;overflow-y:auto}._7D6uKa_executionList{flex-direction:column;gap:8px;margin:0;padding:0;list-style:none;display:flex}._7D6uKa_executionRow{border:1px solid var(--dsw-alias-border-l1);border-radius:8px;flex-wrap:wrap;align-items:center;gap:10px;padding:8px 10px;display:flex}._7D6uKa_executionBadge{color:var(--dsw-alias-state-warn-primary);background:var(--dsw-alias-state-warn-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:600}._7D6uKa_executionBadge[data-result=succeeded]{color:var(--dsw-alias-state-success-primary);background:0 0}._7D6uKa_executionBadge[data-result=failed]{color:var(--dsw-alias-state-error-primary);background:0 0}._7D6uKa_executionBadge[data-result=cancelled]{color:var(--dsw-alias-label-tertiary);background:0 0}._7D6uKa_executionTimes{color:var(--dsw-alias-label-secondary);font-size:12px}._7D6uKa_executionError{width:100%;color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere;font-size:12px}._7D6uKa_moveRow{flex-wrap:wrap;gap:8px;display:flex}._7D6uKa_detailFooter{border-top:1px solid var(--dsw-alias-separator-primary);flex:none;align-items:center;gap:10px;padding:12px 18px;display:flex}._7D6uKa_detailMeta{color:var(--dsw-alias-label-tertiary);margin-left:auto;font-size:11px}._7D6uKa_entry:focus-visible,._7D6uKa_card:focus-visible,._7D6uKa_primaryButton:focus-visible,._7D6uKa_ghostButton:focus-visible,._7D6uKa_dangerButton:focus-visible,._7D6uKa_iconButton:focus-visible,._7D6uKa_linkButton:focus-visible,._7D6uKa_search:focus-visible,._7D6uKa_input:focus-visible,._7D6uKa_schedulePreset:focus-visible,._7D6uKa_scheduleToggle input:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}._7D6uKa_entry,._7D6uKa_primaryButton,._7D6uKa_ghostButton,._7D6uKa_dangerButton,._7D6uKa_iconButton,._7D6uKa_linkButton,._7D6uKa_search,._7D6uKa_input,._7D6uKa_schedulePreset,._7D6uKa_scheduleToggle input{transition:background-color .12s,color .12s,border-color .12s,outline-color .12s,box-shadow .12s,transform .12s}._7D6uKa_card:active{box-shadow:var(--dsw-shadow-lv1);transform:translateY(0)}._7D6uKa_entry:active,._7D6uKa_primaryButton:active:not(:disabled),._7D6uKa_ghostButton:active:not(:disabled),._7D6uKa_dangerButton:active:not(:disabled),._7D6uKa_iconButton:active:not(:disabled),._7D6uKa_linkButton:active:not(:disabled){transform:translateY(1px)}._7D6uKa_entry[data-active]:hover{background:var(--dsw-specific-sidebar-nav-item-active)}._7D6uKa_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._7D6uKa_linkButton:hover:not(:disabled){text-decoration:underline}._7D6uKa_iconButton:disabled,._7D6uKa_linkButton:disabled{opacity:.45;cursor:default}._7D6uKa_search:focus,._7D6uKa_schedulePreset:focus{border-color:var(--dsw-alias-state-business-primary)}._7D6uKa_scheduleToggle input{margin:0}@media (prefers-reduced-motion:reduce){._7D6uKa_entry,._7D6uKa_card,._7D6uKa_primaryButton,._7D6uKa_ghostButton,._7D6uKa_dangerButton,._7D6uKa_iconButton,._7D6uKa_linkButton,._7D6uKa_search,._7D6uKa_input,._7D6uKa_schedulePreset,._7D6uKa_scheduleToggle input{transition:none}._7D6uKa_cardSpinner{animation:none}}";
1474
+ const css$1 = "[data-pane=conversation],[class*=centerCol]{position:relative}[data-dsh-taskboard-view]{z-index:60;background:var(--dsw-alias-bg-base);display:none;position:absolute;inset:0}html[data-dsh-taskboard-active]:not([data-dsh-ssh-active]) [data-dsh-taskboard-view]{display:block}html[data-dsh-taskboard-active]:not([data-dsh-ssh-active]) [data-pane=conversation]>:not([data-dsh-taskboard-view]),html[data-dsh-taskboard-active]:not([data-dsh-ssh-active]) [class*=centerCol]>:not([data-dsh-taskboard-view]){display:none!important}._7D6uKa_entry{width:100%;height:32px;color:var(--dsw-alias-label-secondary);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-radius:8px;align-items:center;gap:8px;padding:0 12px;font-size:13px;display:flex}._7D6uKa_entry:hover{background:var(--dsw-specific-sidebar-nav-item-hover);color:var(--dsw-alias-label-primary)}._7D6uKa_entry[data-active]{background:var(--dsw-specific-sidebar-nav-item-active);color:var(--dsw-alias-label-primary);font-weight:600}._7D6uKa_entryIcon{flex:none;justify-content:center;align-items:center;display:inline-flex}._7D6uKa_entryLabel{text-overflow:ellipsis;overflow:hidden}[data-dsh-frame][data-sidebar-collapsed] ._7D6uKa_entry{justify-content:center;width:100%;padding:0}[data-dsh-frame][data-sidebar-collapsed] ._7D6uKa_entryLabel{display:none}._7D6uKa_board{background:var(--dsw-alias-bg-base);min-width:0;height:100%;min-height:0;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-family);flex-direction:column;gap:12px;padding:14px 16px 16px;display:flex}._7D6uKa_boardHeader{flex:none;align-items:center;gap:10px;display:flex}._7D6uKa_boardTitle{color:var(--dsw-alias-label-primary);white-space:nowrap;margin:0;font-size:16px;font-weight:700}._7D6uKa_search{min-width:120px;color:var(--dsw-alias-label-primary);background:var(--dsw-specific-input-major);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;outline:none;flex:0 260px;padding:6px 10px;font-size:13px}._7D6uKa_search::placeholder{color:var(--dsw-alias-label-tertiary)}._7D6uKa_columns{flex:1;grid-template-columns:repeat(5,minmax(0,1fr));gap:12px;min-height:0;display:grid}._7D6uKa_column{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:12px;flex-direction:column;min-height:0;display:flex;overflow:hidden}._7D6uKa_columnHeader{flex:none;align-items:center;gap:6px;padding:10px 12px;display:flex}._7D6uKa_columnTitle{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;flex:1;margin:0;font-size:13px;font-weight:700;overflow:hidden}._7D6uKa_columnCount{min-width:0;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-interactive-bg-hover);border-radius:999px;flex:none;padding:1px 8px;font-size:12px}._7D6uKa_statusDot{border-radius:50%;flex:none;width:8px;height:8px}._7D6uKa_statusDot[data-status=backlog]{background:var(--dsw-alias-label-tertiary)}._7D6uKa_statusDot[data-status=todo]{background:var(--dsw-alias-state-business-primary)}._7D6uKa_statusDot[data-status=running]{background:var(--dsw-alias-state-warn-primary)}._7D6uKa_statusDot[data-status=done]{background:var(--dsw-alias-state-success-primary)}._7D6uKa_statusDot[data-status=failed]{background:var(--dsw-alias-state-error-primary)}._7D6uKa_cards{flex-direction:column;flex:1;gap:8px;min-height:0;padding:2px 8px 10px;display:flex;overflow-y:auto}._7D6uKa_columnEmpty{text-align:center;color:var(--dsw-alias-label-tertiary);padding:24px 8px;font-size:12px}._7D6uKa_card{text-align:left;background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);cursor:pointer;color:var(--dsw-alias-label-primary);border-radius:10px;flex-direction:column;gap:6px;padding:10px 12px;font-family:inherit;transition:box-shadow .12s,border-color .12s,transform .12s;display:flex}._7D6uKa_card:hover{box-shadow:var(--dsw-shadow-lv2);border-color:var(--dsw-alias-border-l3);transform:translateY(-1px)}._7D6uKa_card[data-status=running]{border-color:var(--dsw-alias-state-warn-primary)}._7D6uKa_cardTitle{-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:13px;font-weight:600;line-height:1.35;display:-webkit-box;overflow:hidden}._7D6uKa_cardExcerpt{color:var(--dsw-alias-label-secondary);-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:12px;line-height:1.4;display:-webkit-box;overflow:hidden}._7D6uKa_cardMeta{color:var(--dsw-alias-label-tertiary);align-items:center;gap:8px;font-size:11px;display:flex}._7D6uKa_cardTime{text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}._7D6uKa_cardSchedule{white-space:nowrap;min-width:0;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-interactive-bg-hover);border-radius:999px;flex:none;padding:2px 6px;font-size:12px;line-height:1}._7D6uKa_cardRun{flex:none}._7D6uKa_cardRun[data-result=failed]{color:var(--dsw-alias-state-error-primary)}._7D6uKa_cardRun[data-result=succeeded]{color:var(--dsw-alias-state-success-primary)}._7D6uKa_cardSession{color:var(--dsw-alias-state-business-primary);flex:none}._7D6uKa_cardRunningLabel{color:var(--dsw-alias-state-warn-primary);font-size:11px}._7D6uKa_cardSpinner{border:2px solid var(--dsw-alias-state-warn-primary);border-top-color:#0000;border-radius:50%;flex:none;width:10px;height:10px;animation:.8s linear infinite _7D6uKa_dshTbSpin}@keyframes _7D6uKa_dshTbSpin{to{transform:rotate(360deg)}}._7D6uKa_primaryButton{color:var(--dsw-alias-label-primary-foreground);background:var(--dsw-alias-button-info-fill);cursor:pointer;white-space:nowrap;border:none;border-radius:8px;padding:6px 14px;font-size:13px;font-weight:600}._7D6uKa_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-info-hover)}._7D6uKa_primaryButton:disabled{opacity:.5;cursor:default}._7D6uKa_ghostButton{color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l2);cursor:pointer;white-space:nowrap;background:0 0;border-radius:8px;padding:5px 12px;font-size:12px}._7D6uKa_ghostButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}._7D6uKa_ghostButton:disabled{opacity:.45;cursor:default}._7D6uKa_dangerButton{color:#fff;background:var(--dsw-alias-state-error-primary);cursor:pointer;white-space:nowrap;border:none;border-radius:8px;padding:6px 14px;font-size:13px;font-weight:600}._7D6uKa_dangerButton:hover:not(:disabled){filter:brightness(1.08)}._7D6uKa_dangerButton:active:not(:disabled){filter:brightness(.94)}._7D6uKa_dangerButton:disabled{opacity:.5;cursor:default}._7D6uKa_iconButton{width:26px;height:26px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;padding:0;font-size:13px;display:inline-flex}._7D6uKa_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._7D6uKa_linkButton{color:var(--dsw-alias-state-business-primary);cursor:pointer;white-space:nowrap;background:0 0;border:none;padding:0;font-size:12px}._7D6uKa_linkButton:hover{text-decoration:underline}._7D6uKa_modalBackdrop{z-index:1300;background:var(--dsw-alias-bg-mask-1);justify-content:center;align-items:center;display:flex;position:fixed;inset:0}._7D6uKa_modal{background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);width:min(520px,100vw - 48px);max-height:calc(100vh - 96px);box-shadow:var(--dsw-shadow-lv3);color:var(--dsw-alias-label-primary);border-radius:14px;flex-direction:column;gap:12px;padding:18px;display:flex;overflow-y:auto}._7D6uKa_modalTitle{margin:0;font-size:15px;font-weight:700}._7D6uKa_confirmMessage{color:var(--dsw-alias-label-secondary);white-space:pre-wrap;overflow-wrap:anywhere;margin:0;font-size:13px;line-height:1.5}._7D6uKa_modalFooter{justify-content:flex-end;gap:10px;margin-top:4px;display:flex}._7D6uKa_field{flex-direction:column;gap:5px;display:flex}._7D6uKa_fieldLabel{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:600}._7D6uKa_input{color:var(--dsw-alias-label-primary);background:var(--dsw-specific-input-major);border:1px solid var(--dsw-alias-border-l2);resize:vertical;border-radius:8px;outline:none;padding:7px 10px;font-family:inherit;font-size:13px}._7D6uKa_input:focus{border-color:var(--dsw-alias-state-business-primary)}._7D6uKa_select{color:var(--dsw-alias-label-primary);background:var(--dsw-specific-input-major);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;outline:none;max-width:100%;padding:7px 10px;font-family:inherit;font-size:13px}._7D6uKa_input::placeholder{color:var(--dsw-alias-label-tertiary)}._7D6uKa_formError{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px}._7D6uKa_detail{background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);width:min(640px,100vw - 48px);max-height:calc(100vh - 80px);box-shadow:var(--dsw-shadow-lv3);color:var(--dsw-alias-label-primary);border-radius:14px;flex-direction:column;display:flex;overflow:hidden}._7D6uKa_detailHeader{border-bottom:1px solid var(--dsw-alias-separator-primary);flex:none;align-items:center;gap:10px;padding:14px 18px;display:flex}._7D6uKa_detailTitle{overflow-wrap:anywhere;flex:1;margin:0;font-size:15px;font-weight:700}._7D6uKa_statusBadge{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:2px 10px;font-size:12px}._7D6uKa_statusBadge[data-status=running]{color:var(--dsw-alias-state-warn-primary);border-color:var(--dsw-alias-state-warn-primary)}._7D6uKa_statusBadge[data-status=done]{color:var(--dsw-alias-state-success-primary);border-color:var(--dsw-alias-state-success-primary)}._7D6uKa_statusBadge[data-status=failed]{color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary)}._7D6uKa_detailBody{flex-direction:column;flex:1;gap:16px;padding:14px 18px;display:flex;overflow-y:auto}._7D6uKa_detailSection{flex-direction:column;gap:6px;display:flex}._7D6uKa_detailSection h4{color:var(--dsw-alias-label-tertiary);text-transform:none;margin:0;font-size:12px;font-weight:700}._7D6uKa_detailText{color:var(--dsw-alias-label-primary);white-space:pre-wrap;overflow-wrap:anywhere;margin:0;font-size:13px;line-height:1.55}._7D6uKa_scheduleToggle{color:var(--dsw-alias-label-primary);cursor:pointer;user-select:none;align-items:center;gap:8px;font-size:13px;display:flex}._7D6uKa_scheduleToggle input{accent-color:var(--dsw-alias-state-business-primary)}._7D6uKa_scheduleRow{align-items:center;gap:8px;display:flex}._7D6uKa_scheduleInput{min-width:0;font-family:var(--dsw-font-markdown-code-block-small);flex:1;font-size:12.5px}._7D6uKa_scheduleInputInvalid,._7D6uKa_scheduleInputInvalid:focus{border-color:var(--dsw-alias-state-error-primary)}._7D6uKa_schedulePreset{color:var(--dsw-alias-label-primary);background:var(--dsw-specific-input-major);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;outline:none;flex:none;padding:7px 8px;font-size:12.5px}._7D6uKa_scheduleMeta{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;margin:0;font-size:12px}._7D6uKa_promptBlock{font-size:12.5px;line-height:1.5;font-family:var(--dsw-font-markdown-code-block-small);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-markdown-code-block);border:1px solid var(--dsw-alias-border-l1);white-space:pre-wrap;overflow-wrap:anywhere;border-radius:8px;max-height:240px;margin:0;padding:10px 12px;overflow-y:auto}._7D6uKa_executionList{flex-direction:column;gap:8px;margin:0;padding:0;list-style:none;display:flex}._7D6uKa_executionRow{border:1px solid var(--dsw-alias-border-l1);border-radius:8px;flex-wrap:wrap;align-items:center;gap:10px;padding:8px 10px;display:flex}._7D6uKa_executionBadge{color:var(--dsw-alias-state-warn-primary);background:var(--dsw-alias-state-warn-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:600}._7D6uKa_executionBadge[data-result=succeeded]{color:var(--dsw-alias-state-success-primary);background:0 0}._7D6uKa_executionBadge[data-result=failed]{color:var(--dsw-alias-state-error-primary);background:0 0}._7D6uKa_executionBadge[data-result=cancelled]{color:var(--dsw-alias-label-tertiary);background:0 0}._7D6uKa_executionTimes{color:var(--dsw-alias-label-secondary);font-size:12px}._7D6uKa_executionError{width:100%;color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere;font-size:12px}._7D6uKa_moveRow{flex-wrap:wrap;gap:8px;display:flex}._7D6uKa_detailFooter{border-top:1px solid var(--dsw-alias-separator-primary);flex:none;align-items:center;gap:10px;padding:12px 18px;display:flex}._7D6uKa_detailMeta{color:var(--dsw-alias-label-tertiary);margin-left:auto;font-size:11px}._7D6uKa_entry:focus-visible,._7D6uKa_card:focus-visible,._7D6uKa_primaryButton:focus-visible,._7D6uKa_ghostButton:focus-visible,._7D6uKa_dangerButton:focus-visible,._7D6uKa_iconButton:focus-visible,._7D6uKa_linkButton:focus-visible,._7D6uKa_search:focus-visible,._7D6uKa_input:focus-visible,._7D6uKa_select:focus-visible,._7D6uKa_schedulePreset:focus-visible,._7D6uKa_scheduleToggle input:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}._7D6uKa_entry,._7D6uKa_primaryButton,._7D6uKa_ghostButton,._7D6uKa_dangerButton,._7D6uKa_iconButton,._7D6uKa_linkButton,._7D6uKa_search,._7D6uKa_input,._7D6uKa_select,._7D6uKa_schedulePreset,._7D6uKa_scheduleToggle input{transition:background-color .12s,color .12s,border-color .12s,outline-color .12s,box-shadow .12s,transform .12s}._7D6uKa_card:active{box-shadow:var(--dsw-shadow-lv1);transform:translateY(0)}._7D6uKa_entry:active,._7D6uKa_primaryButton:active:not(:disabled),._7D6uKa_ghostButton:active:not(:disabled),._7D6uKa_dangerButton:active:not(:disabled),._7D6uKa_iconButton:active:not(:disabled),._7D6uKa_linkButton:active:not(:disabled){transform:translateY(1px)}._7D6uKa_entry[data-active]:hover{background:var(--dsw-specific-sidebar-nav-item-active)}._7D6uKa_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._7D6uKa_linkButton:hover:not(:disabled){text-decoration:underline}._7D6uKa_iconButton:disabled,._7D6uKa_linkButton:disabled{opacity:.45;cursor:default}._7D6uKa_search:focus,._7D6uKa_select:focus,._7D6uKa_schedulePreset:focus{border-color:var(--dsw-alias-state-business-primary)}._7D6uKa_scheduleToggle input{margin:0}@media (prefers-reduced-motion:reduce){._7D6uKa_entry,._7D6uKa_card,._7D6uKa_primaryButton,._7D6uKa_ghostButton,._7D6uKa_dangerButton,._7D6uKa_iconButton,._7D6uKa_linkButton,._7D6uKa_search,._7D6uKa_input,._7D6uKa_select,._7D6uKa_schedulePreset,._7D6uKa_scheduleToggle input{transition:none}._7D6uKa_cardSpinner{animation:none}}";
1304
1475
  const tagId$1 = "@linxin666/dsh-client-ui-task-board/board.module.css";
1305
1476
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
1306
1477
  const tag = document.createElement("style");
@@ -1370,6 +1541,7 @@ window.__ModuleLoader__.load({
1370
1541
  "scheduleRow": "_7D6uKa_scheduleRow",
1371
1542
  "scheduleToggle": "_7D6uKa_scheduleToggle",
1372
1543
  "search": "_7D6uKa_search",
1544
+ "select": "_7D6uKa_select",
1373
1545
  "statusBadge": "_7D6uKa_statusBadge",
1374
1546
  "statusDot": "_7D6uKa_statusDot"
1375
1547
  };
@@ -1384,12 +1556,20 @@ window.__ModuleLoader__.load({
1384
1556
  const [title, setTitle] = (0, react.useState)("");
1385
1557
  const [description, setDescription] = (0, react.useState)("");
1386
1558
  const [prompt, setPrompt] = (0, react.useState)("");
1559
+ const [workspaceId, setWorkspaceId] = (0, react.useState)("");
1560
+ const [mode, setMode] = (0, react.useState)("");
1561
+ const [permission, setPermission] = (0, react.useState)("");
1387
1562
  const [error, setError] = (0, react.useState)(void 0);
1563
+ const [options, setOptions] = (0, react.useState)(controller.getSnapshot().executionOptions);
1564
+ (0, react.useEffect)(() => controller.subscribe(() => setOptions(controller.getSnapshot().executionOptions)), [controller]);
1388
1565
  const submit = () => {
1389
1566
  if (controller.createTask({
1390
1567
  title,
1391
1568
  description,
1392
- prompt
1569
+ prompt,
1570
+ workspaceId: workspaceId === "" ? void 0 : workspaceId,
1571
+ mode: mode === "" ? void 0 : mode,
1572
+ permission: permission === "" ? void 0 : permission
1393
1573
  }) === void 0) {
1394
1574
  setError(t("new.required"));
1395
1575
  return;
@@ -1460,6 +1640,71 @@ window.__ModuleLoader__.load({
1460
1640
  }
1461
1641
  })]
1462
1642
  }),
1643
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1644
+ className: board_module_css_default.field,
1645
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1646
+ className: board_module_css_default.fieldLabel,
1647
+ children: t("new.workspace")
1648
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
1649
+ className: board_module_css_default.select,
1650
+ value: workspaceId,
1651
+ onChange: (event) => {
1652
+ setWorkspaceId(event.target.value);
1653
+ },
1654
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1655
+ value: "",
1656
+ children: t("exec.workspace.recent")
1657
+ }), options.workspaces.map((workspace) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1658
+ value: workspace.workspaceId,
1659
+ children: workspace.title
1660
+ }, workspace.workspaceId))]
1661
+ })]
1662
+ }),
1663
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1664
+ className: board_module_css_default.field,
1665
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1666
+ className: board_module_css_default.fieldLabel,
1667
+ children: t("new.mode")
1668
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
1669
+ className: board_module_css_default.select,
1670
+ value: mode,
1671
+ onChange: (event) => {
1672
+ setMode(event.target.value);
1673
+ },
1674
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1675
+ value: "",
1676
+ children: t("exec.mode.default")
1677
+ }), options.presets.map((preset) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
1678
+ value: preset.id,
1679
+ disabled: preset.broken !== void 0,
1680
+ children: [
1681
+ preset.name ?? preset.id,
1682
+ preset.isDefault ? t("exec.mode.defaultSuffix") : "",
1683
+ preset.broken !== void 0 ? t("exec.mode.brokenSuffix") : ""
1684
+ ]
1685
+ }, preset.id))]
1686
+ })]
1687
+ }),
1688
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1689
+ className: board_module_css_default.field,
1690
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1691
+ className: board_module_css_default.fieldLabel,
1692
+ children: t("new.permission")
1693
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
1694
+ className: board_module_css_default.select,
1695
+ value: permission,
1696
+ onChange: (event) => {
1697
+ setPermission(event.target.value);
1698
+ },
1699
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1700
+ value: "",
1701
+ children: t("exec.permission.default")
1702
+ }), TASK_PERMISSIONS.map((id) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1703
+ value: id,
1704
+ children: t(`exec.permission.${id}`)
1705
+ }, id))]
1706
+ })]
1707
+ }),
1463
1708
  error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1464
1709
  className: board_module_css_default.formError,
1465
1710
  children: error
@@ -1686,6 +1931,105 @@ window.__ModuleLoader__.load({
1686
1931
  label: "detail.schedule.preset.weeklyMon9"
1687
1932
  }
1688
1933
  ];
1934
+ /** The execution-target editor: workspace / mode / permission pickers. */
1935
+ function ExecutionSettingsSection({ controller, task }) {
1936
+ const [options, setOptions] = (0, react.useState)(controller.getSnapshot().executionOptions);
1937
+ (0, react.useEffect)(() => controller.subscribe(() => setOptions(controller.getSnapshot().executionOptions)), [controller]);
1938
+ const workspaceId = task.workspaceId ?? "";
1939
+ const mode = task.mode ?? "";
1940
+ const permission = task.permission ?? "";
1941
+ const workspaceKnown = workspaceId === "" || options.workspaces.some((item) => item.workspaceId === workspaceId);
1942
+ const modeKnown = mode === "" || options.presets.some((item) => item.id === mode);
1943
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1944
+ className: board_module_css_default.detailSection,
1945
+ children: [
1946
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", { children: t("detail.executionSettings") }),
1947
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1948
+ className: board_module_css_default.detailText,
1949
+ children: t("exec.hint")
1950
+ }),
1951
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1952
+ className: board_module_css_default.field,
1953
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1954
+ className: board_module_css_default.fieldLabel,
1955
+ children: t("new.workspace")
1956
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
1957
+ className: board_module_css_default.select,
1958
+ value: workspaceId,
1959
+ onChange: (event) => {
1960
+ controller.updateTask(task.id, { workspaceId: event.target.value });
1961
+ },
1962
+ children: [
1963
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1964
+ value: "",
1965
+ children: t("exec.workspace.recent")
1966
+ }),
1967
+ !workspaceKnown && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
1968
+ value: workspaceId,
1969
+ children: [workspaceId, t("exec.mode.removed")]
1970
+ }),
1971
+ options.workspaces.map((workspace) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1972
+ value: workspace.workspaceId,
1973
+ children: workspace.title
1974
+ }, workspace.workspaceId))
1975
+ ]
1976
+ })]
1977
+ }),
1978
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1979
+ className: board_module_css_default.field,
1980
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1981
+ className: board_module_css_default.fieldLabel,
1982
+ children: t("new.mode")
1983
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
1984
+ className: board_module_css_default.select,
1985
+ value: mode,
1986
+ onChange: (event) => {
1987
+ controller.updateTask(task.id, { mode: event.target.value });
1988
+ },
1989
+ children: [
1990
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1991
+ value: "",
1992
+ children: t("exec.mode.default")
1993
+ }),
1994
+ !modeKnown && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
1995
+ value: mode,
1996
+ children: [mode, t("exec.mode.removed")]
1997
+ }),
1998
+ options.presets.map((preset) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
1999
+ value: preset.id,
2000
+ disabled: preset.broken !== void 0,
2001
+ children: [
2002
+ preset.name ?? preset.id,
2003
+ preset.isDefault ? t("exec.mode.defaultSuffix") : "",
2004
+ preset.broken !== void 0 ? t("exec.mode.brokenSuffix") : ""
2005
+ ]
2006
+ }, preset.id))
2007
+ ]
2008
+ })]
2009
+ }),
2010
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
2011
+ className: board_module_css_default.field,
2012
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2013
+ className: board_module_css_default.fieldLabel,
2014
+ children: t("new.permission")
2015
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
2016
+ className: board_module_css_default.select,
2017
+ value: permission,
2018
+ onChange: (event) => {
2019
+ controller.updateTask(task.id, { permission: event.target.value === "" ? void 0 : event.target.value });
2020
+ },
2021
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2022
+ value: "",
2023
+ children: t("exec.permission.default")
2024
+ }), TASK_PERMISSIONS.map((id) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2025
+ value: id,
2026
+ children: t(`exec.permission.${id}`)
2027
+ }, id))]
2028
+ })]
2029
+ })
2030
+ ]
2031
+ });
2032
+ }
1689
2033
  /** The scheduled-runs editor: enable toggle, cron input + presets, next-run info. */
1690
2034
  function ScheduleSection({ controller, task }) {
1691
2035
  const schedule = task.schedule;
@@ -1863,6 +2207,10 @@ window.__ModuleLoader__.load({
1863
2207
  children: current.prompt !== "" ? current.prompt : current.title
1864
2208
  })]
1865
2209
  }),
2210
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExecutionSettingsSection, {
2211
+ controller,
2212
+ task: current
2213
+ }),
1866
2214
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScheduleSection, {
1867
2215
  controller,
1868
2216
  task: current
@@ -2274,7 +2622,7 @@ window.__ModuleLoader__.load({
2274
2622
  }
2275
2623
  //#endregion
2276
2624
  //#region \0dsh-css:packages/dsh-task-board/src/client/settings-card.module.css.mjs
2277
- const css = ".Jh0q7G_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}.Jh0q7G_card:hover{border-color:var(--dsw-alias-label-dimmed)}.Jh0q7G_cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.Jh0q7G_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}.Jh0q7G_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.Jh0q7G_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.Jh0q7G_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.Jh0q7G_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.Jh0q7G_pending{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.Jh0q7G_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.Jh0q7G_chevronOpen{transform:rotate(180deg)}.Jh0q7G_body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.Jh0q7G_readOnly{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}.Jh0q7G_notExposed{color:var(--dsw-alias-state-warn-primary);margin:12px 0 0;font-size:12px;line-height:1.5}.Jh0q7G_footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}.Jh0q7G_failed{min-width:0;color:var(--dsw-alias-label-error);flex:1;margin:0;font-size:12px;line-height:1.5}.Jh0q7G_discard,.Jh0q7G_save{appearance:none;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.Jh0q7G_discard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.Jh0q7G_discard:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.Jh0q7G_save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}.Jh0q7G_discard:disabled,.Jh0q7G_save:disabled{opacity:.4;cursor:default}.Jh0q7G_discard:focus-visible,.Jh0q7G_save:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.Jh0q7G_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.Jh0q7G_field+.Jh0q7G_field{border-top:1px solid var(--dsw-alias-border-l2)}.Jh0q7G_head{align-items:center;gap:8px;display:flex}.Jh0q7G_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.Jh0q7G_badges{align-items:center;gap:8px;display:inline-flex}.Jh0q7G_badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.Jh0q7G_reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}.Jh0q7G_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.Jh0q7G_reset:disabled{cursor:default}.Jh0q7G_reset:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px;outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.Jh0q7G_input,.Jh0q7G_select{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.Jh0q7G_input:focus-visible,.Jh0q7G_select:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.Jh0q7G_input:disabled,.Jh0q7G_select:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.Jh0q7G_inputInvalid{border:1px solid var(--dsw-alias-label-error);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.Jh0q7G_inputInvalid:focus-visible{outline:2px solid var(--dsw-alias-label-error);outline-offset:1px;border-color:var(--dsw-alias-label-error)}.Jh0q7G_invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.Jh0q7G_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}@media (prefers-reduced-motion:reduce){.Jh0q7G_card,.Jh0q7G_header,.Jh0q7G_chevron,.Jh0q7G_chevronOpen,.Jh0q7G_discard,.Jh0q7G_save{transition:none}}";
2625
+ const css = ".Jh0q7G_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}.Jh0q7G_card:hover{border-color:var(--dsw-alias-label-dimmed)}.Jh0q7G_cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.Jh0q7G_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}.Jh0q7G_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.Jh0q7G_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.Jh0q7G_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.Jh0q7G_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.Jh0q7G_pending{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.Jh0q7G_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.Jh0q7G_chevronOpen{transform:rotate(180deg)}.Jh0q7G_body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.Jh0q7G_readOnly{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}.Jh0q7G_notExposed{color:var(--dsw-alias-state-warn-primary);margin:12px 0 0;font-size:12px;line-height:1.5}.Jh0q7G_footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}.Jh0q7G_failed{min-width:0;color:var(--dsw-alias-label-error);text-overflow:ellipsis;white-space:nowrap;flex:1;margin:0;font-size:12px;line-height:1.5;overflow:hidden}.Jh0q7G_discard,.Jh0q7G_save{appearance:none;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.Jh0q7G_discard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.Jh0q7G_discard:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.Jh0q7G_save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}.Jh0q7G_discard:disabled,.Jh0q7G_save:disabled{opacity:.4;cursor:default}.Jh0q7G_discard:focus-visible,.Jh0q7G_save:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.Jh0q7G_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.Jh0q7G_field+.Jh0q7G_field{border-top:1px solid var(--dsw-alias-border-l2)}.Jh0q7G_head{align-items:center;gap:8px;display:flex}.Jh0q7G_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.Jh0q7G_badges{align-items:center;gap:8px;display:inline-flex}.Jh0q7G_badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.Jh0q7G_reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}.Jh0q7G_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.Jh0q7G_reset:disabled{cursor:default}.Jh0q7G_reset:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px;outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.Jh0q7G_input,.Jh0q7G_select{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.Jh0q7G_input:focus-visible,.Jh0q7G_select:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.Jh0q7G_input:disabled,.Jh0q7G_select:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.Jh0q7G_inputInvalid{border:1px solid var(--dsw-alias-label-error);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.Jh0q7G_inputInvalid:focus-visible{outline:2px solid var(--dsw-alias-label-error);outline-offset:1px;border-color:var(--dsw-alias-label-error)}.Jh0q7G_invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.Jh0q7G_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}@media (prefers-reduced-motion:reduce){.Jh0q7G_card,.Jh0q7G_header,.Jh0q7G_chevron,.Jh0q7G_chevronOpen,.Jh0q7G_discard,.Jh0q7G_save{transition:none}}";
2278
2626
  const tagId = "@linxin666/dsh-client-ui-task-board/settings-card.module.css";
2279
2627
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
2280
2628
  const tag = document.createElement("style");
@@ -2430,10 +2778,10 @@ window.__ModuleLoader__.load({
2430
2778
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2431
2779
  className: settings_card_module_css_default.footer,
2432
2780
  children: [
2433
- state.failed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2781
+ state.failed ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
2434
2782
  className: settings_card_module_css_default.failed,
2435
2783
  role: "status",
2436
- children: props.t("settings.saveFailed")
2784
+ children: [props.t("settings.saveFailed"), state.failedReason ? " - " + state.failedReason : ""]
2437
2785
  }) : null,
2438
2786
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2439
2787
  type: "button",
@@ -2546,6 +2894,7 @@ window.__ModuleLoader__.load({
2546
2894
  listeners = /* @__PURE__ */ new Set();
2547
2895
  saving = false;
2548
2896
  failed = false;
2897
+ failedReason;
2549
2898
  /** @param scope - the bound settings scope for this card's namespace. */
2550
2899
  constructor(scope, specs) {
2551
2900
  this.scope = scope;
@@ -2573,7 +2922,8 @@ window.__ModuleLoader__.load({
2573
2922
  dirty: plan.length > 0,
2574
2923
  invalid: plan.some((item) => item.run === void 0),
2575
2924
  saving: this.saving,
2576
- failed: this.failed
2925
+ failed: this.failed,
2926
+ ...this.failedReason === void 0 ? {} : { failedReason: this.failedReason }
2577
2927
  };
2578
2928
  }
2579
2929
  /** Read one field's state from the effective section and its staged draft. */
@@ -2614,29 +2964,50 @@ window.__ModuleLoader__.load({
2614
2964
  if (this.staged.size === 0 && !this.failed) return;
2615
2965
  this.staged.clear();
2616
2966
  this.failed = false;
2967
+ this.failedReason = void 0;
2617
2968
  this.publish();
2618
2969
  }
2619
2970
  };
2620
2971
  }
2621
2972
  /**
2622
2973
  * Write every staged edit, then re-seed from what the Host accepted.
2974
+ *
2975
+ * When the scope carries the optional batch surface (the dsh-web-ui
2976
+ * bridge scope), every planned write rides one mutation so cross-field
2977
+ * validate hooks (baseURL+model) judge the batch as a unit instead of
2978
+ * deadlocking on per-field writes. Otherwise the per-field loop runs.
2979
+ * A field lands only when the Host reports it held the staged value; a
2980
+ * landed field's draft is dropped, a failed one stays staged for the user.
2623
2981
  * @returns settlement after every write and the read-back.
2624
2982
  */
2625
2983
  async save() {
2626
2984
  const plan = this.plan();
2627
- const writes = plan.flatMap((item) => item.run === void 0 ? [] : [item.run]);
2628
- if (plan.length === 0 || this.saving || writes.length !== plan.length) return;
2985
+ const valid = plan.filter((item) => item.run !== void 0);
2986
+ if (plan.length === 0 || this.saving || valid.length !== plan.length) return;
2987
+ const plannedWrites = valid.map((item) => item.op);
2629
2988
  const fields = new Set(plan.map((item) => item.field));
2630
2989
  this.saving = true;
2631
2990
  this.failed = false;
2991
+ this.failedReason = void 0;
2632
2992
  this.publish();
2633
- let landed = true;
2634
- for (const write of writes) landed = await write() && landed;
2635
- if (landed) for (const field of fields) this.staged.delete(field);
2993
+ const landed = /* @__PURE__ */ new Set();
2994
+ const batch = this.batchedScope();
2995
+ if (batch !== void 0) {
2996
+ const result = await batch.mutate(plannedWrites);
2997
+ if (result.ok) {
2998
+ for (const field of result.fields) if (field.landed) landed.add(field.field);
2999
+ } else this.failedReason = result.message;
3000
+ } else for (const item of valid) if (await item.run()) landed.add(item.field);
3001
+ for (const field of fields) if (landed.has(field)) this.staged.delete(field);
2636
3002
  this.saving = false;
2637
- this.failed = !landed;
3003
+ this.failed = landed.size !== fields.size;
2638
3004
  this.publish();
2639
3005
  }
3006
+ /** The scope's batch surface when it supports one; undefined conservatively otherwise. */
3007
+ batchedScope() {
3008
+ const candidate = this.scope;
3009
+ return typeof candidate?.mutate === "function" ? candidate : void 0;
3010
+ }
2640
3011
  /**
2641
3012
  * Every staged edit a save would write. An entry whose draft is not a value
2642
3013
  * its field accepts carries no write: the form is still dirty, and the save
@@ -2651,6 +3022,10 @@ window.__ModuleLoader__.load({
2651
3022
  if (staged.clear) {
2652
3023
  if (this.stored(field)) plan.push({
2653
3024
  field,
3025
+ op: {
3026
+ field,
3027
+ op: "unset"
3028
+ },
2654
3029
  run: () => this.clear(field)
2655
3030
  });
2656
3031
  continue;
@@ -2659,14 +3034,27 @@ window.__ModuleLoader__.load({
2659
3034
  const write = spec.parse(staged.text);
2660
3035
  if (write === void 0) plan.push({
2661
3036
  field,
3037
+ op: {
3038
+ field,
3039
+ op: "unset"
3040
+ },
2662
3041
  run: void 0
2663
3042
  });
2664
3043
  else if (write.kind === "clear") plan.push({
2665
3044
  field,
3045
+ op: {
3046
+ field,
3047
+ op: "unset"
3048
+ },
2666
3049
  run: () => this.clear(field)
2667
3050
  });
2668
3051
  else plan.push({
2669
3052
  field,
3053
+ op: {
3054
+ field,
3055
+ op: "set",
3056
+ value: write.value
3057
+ },
2670
3058
  run: () => this.store(field, write.value)
2671
3059
  });
2672
3060
  }
@@ -2678,11 +3066,13 @@ window.__ModuleLoader__.load({
2678
3066
  }
2679
3067
  async store(field, value) {
2680
3068
  await this.scope.set(field, value);
3069
+ if (this.specOf(field).secret) return true;
2681
3070
  return this.userLayer()?.[field] === value;
2682
3071
  }
2683
3072
  stage(field, edit) {
2684
3073
  this.staged.set(field, edit);
2685
3074
  this.failed = false;
3075
+ this.failedReason = void 0;
2686
3076
  this.publish();
2687
3077
  }
2688
3078
  specOf(field) {
@@ -2841,12 +3231,50 @@ window.__ModuleLoader__.load({
2841
3231
  exec: new ExecutionService({
2842
3232
  sessions: {
2843
3233
  list: sessions.list,
2844
- binding: (id) => sessions.binding(id)
3234
+ binding: (id) => {
3235
+ const binding = sessions.binding(id);
3236
+ if (binding === void 0) return void 0;
3237
+ const { session } = binding;
3238
+ return { session: {
3239
+ rename: (title) => session.rename(title),
3240
+ prompt: (content, mode) => session.prompt(content, mode).then((result) => result.ok ? { ok: true } : {
3241
+ ok: false,
3242
+ error: result.error
3243
+ }),
3244
+ command: (line) => session.command(line).then((result) => result.ok ? {
3245
+ ok: true,
3246
+ matched: result.value.matched
3247
+ } : {
3248
+ ok: false,
3249
+ error: result.error
3250
+ }),
3251
+ getSnapshot: () => session.getSnapshot(),
3252
+ subscribe: (fn) => session.subscribe(fn)
3253
+ } };
3254
+ },
3255
+ noteAgentPreset: (sessionId, agentPreset) => sessions.noteAgentPreset(sessionId, agentPreset)
2845
3256
  },
2846
3257
  workspaces: {
2847
3258
  list: workspaces.list,
2848
3259
  connectWorkspace: (id) => workspaces.connectWorkspace(id)
2849
3260
  },
3261
+ presets: { select: async (sessionId, agentPreset) => {
3262
+ try {
3263
+ const response = await connection.api.agentPresets.select({
3264
+ sessionId,
3265
+ agentPreset
3266
+ });
3267
+ return response.result.ok ? { ok: true } : {
3268
+ ok: false,
3269
+ error: response.result.error
3270
+ };
3271
+ } catch (error) {
3272
+ return {
3273
+ ok: false,
3274
+ error
3275
+ };
3276
+ }
3277
+ } },
2850
3278
  history: { loadTail: async (sessionId) => {
2851
3279
  const response = await connection.api.sessions.history({
2852
3280
  sessionId,
@@ -2874,6 +3302,34 @@ window.__ModuleLoader__.load({
2874
3302
  });
2875
3303
  scheduler.start();
2876
3304
  const disposers = [];
3305
+ const pushWorkspaceOptions = () => {
3306
+ const snapshot = workspaces.list.getSnapshot();
3307
+ controller.setExecutionOptions({ workspaces: snapshot.items.map((item) => ({
3308
+ workspaceId: item.workspaceId,
3309
+ title: item.title !== "" ? item.title : item.path
3310
+ })) });
3311
+ };
3312
+ pushWorkspaceOptions();
3313
+ disposers.push(workspaces.list.subscribe(pushWorkspaceOptions));
3314
+ const pushPresetOptions = async () => {
3315
+ try {
3316
+ const response = await connection.api.agentPresets.list({});
3317
+ if (!response.result.ok) return;
3318
+ controller.setExecutionOptions({ presets: response.result.value.presets.map((preset) => ({
3319
+ id: preset.id,
3320
+ name: preset.name,
3321
+ description: preset.description,
3322
+ broken: preset.broken,
3323
+ isDefault: preset.isDefault
3324
+ })) });
3325
+ } catch (error) {
3326
+ console.error("[dsh-task-board] agent preset roster read failed", error);
3327
+ }
3328
+ };
3329
+ pushPresetOptions();
3330
+ disposers.push(ctx.on("connection/reset", () => {
3331
+ pushPresetOptions();
3332
+ }));
2877
3333
  try {
2878
3334
  disposers.push(mountSidebarEntry(controller));
2879
3335
  disposers.push(mountBoard(controller));