@linxin666/dsh-client-ui-task-board 0.1.16 → 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
@@ -2883,12 +3231,50 @@ window.__ModuleLoader__.load({
2883
3231
  exec: new ExecutionService({
2884
3232
  sessions: {
2885
3233
  list: sessions.list,
2886
- 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)
2887
3256
  },
2888
3257
  workspaces: {
2889
3258
  list: workspaces.list,
2890
3259
  connectWorkspace: (id) => workspaces.connectWorkspace(id)
2891
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
+ } },
2892
3278
  history: { loadTail: async (sessionId) => {
2893
3279
  const response = await connection.api.sessions.history({
2894
3280
  sessionId,
@@ -2916,6 +3302,34 @@ window.__ModuleLoader__.load({
2916
3302
  });
2917
3303
  scheduler.start();
2918
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
+ }));
2919
3333
  try {
2920
3334
  disposers.push(mountSidebarEntry(controller));
2921
3335
  disposers.push(mountBoard(controller));