@linxin666/dsh-client-ui-task-board 0.3.20 → 0.3.22
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/README.i18n.yaml +2 -2
- package/README.md +5 -0
- package/README.zh.md +5 -0
- package/lib/client.js +467 -67
- package/lib/client.js.map +1 -1
- package/lib/index.js +97 -13
- package/lib/types/client/board/EditTaskModal.d.ts +1 -1
- package/lib/types/client/board/TaskBoard.d.ts +8 -1
- package/lib/types/client/board/TaskForm.d.ts +18 -0
- package/lib/types/client/body-mutations.d.ts +45 -0
- package/lib/types/client/locales.d.ts +11 -0
- package/lib/types/client/panel-mount-core.d.ts +1 -1
- package/lib/types/client/sidebar-entry-core.d.ts +0 -15
- package/lib/types/core/controller.d.ts +2 -3
- package/lib/types/core/tasks.d.ts +66 -1
- package/lib/types/core/use-cases/task-archive.d.ts +6 -6
- package/lib/types/core/use-cases/task-update.d.ts +8 -1
- package/package.json +1 -1
- package/src/client/board/EditTaskModal.tsx +16 -3
- package/src/client/board/NewTaskModal.tsx +9 -2
- package/src/client/board/TaskBoard.tsx +61 -6
- package/src/client/board/TaskCard.tsx +17 -1
- package/src/client/board/TaskDetail.tsx +4 -2
- package/src/client/board/TaskForm.tsx +92 -0
- package/src/client/board.module.css +119 -0
- package/src/client/body-mutations.ts +133 -0
- package/src/client/index.ts +52 -20
- package/src/client/locales.ts +22 -0
- package/src/client/panel-mount-core.ts +21 -13
- package/src/client/sidebar-entry-core.ts +10 -7
- package/src/core/controller.ts +2 -3
- package/src/core/schedule.ts +4 -1
- package/src/core/store.ts +5 -1
- package/src/core/tasks.ts +119 -2
- package/src/core/use-cases/task-archive.ts +6 -6
- package/src/core/use-cases/task-update.ts +12 -2
- package/src/host-runner.ts +24 -1
- package/src/protocol.ts +11 -3
package/lib/client.js
CHANGED
|
@@ -7,9 +7,70 @@ window.__ModuleLoader__.load({
|
|
|
7
7
|
let react = require("react");
|
|
8
8
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
9
|
let react_dom_client = require("react-dom/client");
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Repair a persisted tag list: keep the well-formed entries, trim, drop
|
|
12
|
+
* blanks and repeats, cap the count, and collapse a blank prompt line to
|
|
13
|
+
* "display-only". Returns undefined when nothing usable remains, so the caller
|
|
14
|
+
* clears the field instead of storing an empty array.
|
|
15
|
+
*/
|
|
16
|
+
function normalizeTags(value) {
|
|
17
|
+
if (!Array.isArray(value)) return void 0;
|
|
18
|
+
const tags = [];
|
|
19
|
+
const seen = /* @__PURE__ */ new Set();
|
|
20
|
+
for (const entry of value) {
|
|
21
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) continue;
|
|
22
|
+
const row = entry;
|
|
23
|
+
if (typeof row.name !== "string") continue;
|
|
24
|
+
const name = row.name.trim();
|
|
25
|
+
if (name === "" || name.length > 32 || seen.has(name)) continue;
|
|
26
|
+
const raw = typeof row.promptPrefix === "string" ? row.promptPrefix.trim() : "";
|
|
27
|
+
const promptPrefix = raw === "" ? void 0 : raw.slice(0, 200);
|
|
28
|
+
seen.add(name);
|
|
29
|
+
tags.push(promptPrefix === void 0 ? { name } : {
|
|
30
|
+
name,
|
|
31
|
+
promptPrefix
|
|
32
|
+
});
|
|
33
|
+
if (tags.length >= 8) break;
|
|
34
|
+
}
|
|
35
|
+
return tags.length === 0 ? void 0 : tags;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Stable palette slot (0..5) for a tag name. The same label always lands on the
|
|
39
|
+
* same tone, so a badge needs no stored colour and two tasks sharing a label
|
|
40
|
+
* cannot disagree about it.
|
|
41
|
+
*/
|
|
42
|
+
function tagTone(name) {
|
|
43
|
+
let hash = 0;
|
|
44
|
+
for (const char of name) hash = hash * 31 + (char.codePointAt(0) ?? 0) >>> 0;
|
|
45
|
+
return hash % 6;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Union of the labels already carried by `tasks`, first occurrence wins (the
|
|
49
|
+
* oldest task's hint is the one offered). Feeds the editor's name datalist and
|
|
50
|
+
* the board's tag filter, so a label defined once can be reused everywhere.
|
|
51
|
+
*/
|
|
52
|
+
function collectKnownTags(tasks) {
|
|
53
|
+
const known = [];
|
|
54
|
+
const seen = /* @__PURE__ */ new Set();
|
|
55
|
+
for (const task of tasks) for (const tag of task.tags ?? []) {
|
|
56
|
+
if (seen.has(tag.name)) continue;
|
|
57
|
+
seen.add(tag.name);
|
|
58
|
+
known.push(tag);
|
|
59
|
+
}
|
|
60
|
+
return known;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Statuses a task may be archived from: every status but `running`, whose
|
|
64
|
+
* execution the runner still owns until it settles. A settled-only gate made
|
|
65
|
+
* the duplicate-and-archive flow a silent no-op for scheduled tasks, which
|
|
66
|
+
* return to `todo` after every successful run (issue #1447).
|
|
67
|
+
*/
|
|
68
|
+
const ARCHIVABLE_STATUSES = [
|
|
69
|
+
"backlog",
|
|
70
|
+
"todo",
|
|
71
|
+
"done",
|
|
72
|
+
"failed"
|
|
73
|
+
];
|
|
13
74
|
/** Permission presets a task may pin on its execution session (the `/permission <id>` ids). */
|
|
14
75
|
const TASK_PERMISSIONS = [
|
|
15
76
|
"read-only",
|
|
@@ -82,6 +143,7 @@ window.__ModuleLoader__.load({
|
|
|
82
143
|
}
|
|
83
144
|
/** Create a task from user input. */
|
|
84
145
|
function createTask(input, now, id) {
|
|
146
|
+
const tags = normalizeTags(input.tags);
|
|
85
147
|
return {
|
|
86
148
|
id,
|
|
87
149
|
title: input.title.trim(),
|
|
@@ -100,7 +162,8 @@ window.__ModuleLoader__.load({
|
|
|
100
162
|
...input.handover === void 0 ? {} : { handover: {
|
|
101
163
|
...input.handover,
|
|
102
164
|
bundledAt: now
|
|
103
|
-
} }
|
|
165
|
+
} },
|
|
166
|
+
...tags === void 0 ? {} : { tags }
|
|
104
167
|
};
|
|
105
168
|
}
|
|
106
169
|
/** Clone a task with an updated status and a fresh updatedAt. */
|
|
@@ -145,10 +208,10 @@ window.__ModuleLoader__.load({
|
|
|
145
208
|
//#endregion
|
|
146
209
|
//#region src/core/use-cases/task-archive.ts
|
|
147
210
|
/**
|
|
148
|
-
* Archive one task: only
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
211
|
+
* Archive one task: only a `running` task stays on the board (its runner
|
|
212
|
+
* still owns its lifecycle until the execution settles); every other status
|
|
213
|
+
* can be archived. Archiving disarms a schedule; already-archived tasks are
|
|
214
|
+
* a no-op.
|
|
152
215
|
*/
|
|
153
216
|
function applyArchiveTask(tasks, id, now) {
|
|
154
217
|
let applied = false;
|
|
@@ -338,7 +401,7 @@ window.__ModuleLoader__.load({
|
|
|
338
401
|
high = Number(b);
|
|
339
402
|
} else if (isDigits(range)) {
|
|
340
403
|
low = Number(range);
|
|
341
|
-
high =
|
|
404
|
+
high = stepRaw === void 0 ? low : max;
|
|
342
405
|
} else return false;
|
|
343
406
|
if (low < min || high > max || low > high) return false;
|
|
344
407
|
const step = stepRaw === void 0 ? 1 : isDigits(stepRaw) ? Number(stepRaw) : NaN;
|
|
@@ -513,7 +576,7 @@ window.__ModuleLoader__.load({
|
|
|
513
576
|
function applyUpdateTask(tasks, id, patch, now) {
|
|
514
577
|
return tasks.map((task) => {
|
|
515
578
|
if (task.id !== id) return task;
|
|
516
|
-
const { freeze: freezePatch, handover: handoverPatch, ...rest } = patch;
|
|
579
|
+
const { freeze: freezePatch, handover: handoverPatch, tags: tagsPatch, ...rest } = patch;
|
|
517
580
|
const workspaceId = "workspaceId" in patch ? normalizeTargetId(patch.workspaceId) : void 0;
|
|
518
581
|
const mode = "mode" in patch ? normalizeTargetId(patch.mode) : void 0;
|
|
519
582
|
const permission = "permission" in patch ? normalizePermission(task.permission, patch.permission) : void 0;
|
|
@@ -533,6 +596,7 @@ window.__ModuleLoader__.load({
|
|
|
533
596
|
...handoverPatch,
|
|
534
597
|
bundledAt: now
|
|
535
598
|
};
|
|
599
|
+
if ("tags" in patch) next.tags = tagsPatch == null ? void 0 : normalizeTags(tagsPatch);
|
|
536
600
|
if ("permission" in patch && patch.permission !== void 0 && patch.permission !== task.permission || "handover" in patch) next.permissionConfirmedAt = void 0;
|
|
537
601
|
if ("reuseSession" in patch) next.reuseSession = patch.reuseSession === true ? true : void 0;
|
|
538
602
|
if (workspaceId !== void 0 || "workspaceId" in patch) next.workspaceId = workspaceId;
|
|
@@ -751,9 +815,8 @@ window.__ModuleLoader__.load({
|
|
|
751
815
|
this.persistAndNotify();
|
|
752
816
|
}
|
|
753
817
|
/**
|
|
754
|
-
* Archive a
|
|
755
|
-
*
|
|
756
|
-
* lifecycle.
|
|
818
|
+
* Archive a task from any status but `running`, whose lifecycle the runner
|
|
819
|
+
* keeps exclusive ownership of until it settles.
|
|
757
820
|
* @returns true when applied.
|
|
758
821
|
*/
|
|
759
822
|
archiveTask(id) {
|
|
@@ -1395,6 +1458,7 @@ window.__ModuleLoader__.load({
|
|
|
1395
1458
|
task.reuseSession = row.reuseSession === true ? true : void 0;
|
|
1396
1459
|
task.freeze = normalizeFreeze(row.freeze);
|
|
1397
1460
|
task.handover = normalizeHandover(row.handover);
|
|
1461
|
+
task.tags = normalizeTags(row.tags);
|
|
1398
1462
|
task.permissionConfirmedAt = typeof row.permissionConfirmedAt === "number" && Number.isFinite(row.permissionConfirmedAt) ? row.permissionConfirmedAt : void 0;
|
|
1399
1463
|
tasks.push(task);
|
|
1400
1464
|
}
|
|
@@ -1535,6 +1599,17 @@ window.__ModuleLoader__.load({
|
|
|
1535
1599
|
"detail.handover": "交接包",
|
|
1536
1600
|
"detail.handover.bundledAt": "打包于 {time}",
|
|
1537
1601
|
"detail.handover.references": "引用",
|
|
1602
|
+
"new.tags": "标签(可选)",
|
|
1603
|
+
"new.tagsHint": "标签用于卡片徽章与顶栏筛选;填了「执行提示」的行会在每次执行前注入 Prompt,留空则只作展示。",
|
|
1604
|
+
"new.tagName": "标签名",
|
|
1605
|
+
"new.tagNamePlaceholder": "例如:工作",
|
|
1606
|
+
"new.tagPrompt": "执行提示(可选)",
|
|
1607
|
+
"new.tagPromptPlaceholder": "例如:产物归档到 02-工作/",
|
|
1608
|
+
"new.tagAdd": "添加标签",
|
|
1609
|
+
"new.tagRemove": "移除标签 {name}",
|
|
1610
|
+
"board.tagFilter": "按标签筛选",
|
|
1611
|
+
"board.tagFilterClear": "清除标签筛选",
|
|
1612
|
+
"board.tagEmpty": "没有同时带这些标签的任务",
|
|
1538
1613
|
"detail.permissionPending": "权限待确认:本卡有效权限({permission})高于会话默认,手动执行与定时调度都会被拒绝,需人工确认后才能运行。",
|
|
1539
1614
|
"detail.permissionConfirm": "确认权限绑定",
|
|
1540
1615
|
"detail.permissionConfirmed": "已确认权限绑定 · {time}",
|
|
@@ -1687,6 +1762,17 @@ window.__ModuleLoader__.load({
|
|
|
1687
1762
|
"detail.handover": "Handover bundle",
|
|
1688
1763
|
"detail.handover.bundledAt": "Bundled at {time}",
|
|
1689
1764
|
"detail.handover.references": "References",
|
|
1765
|
+
"new.tags": "Tags (optional)",
|
|
1766
|
+
"new.tagsHint": "Tags drive the card badges and the board filter; a row with an execution hint is injected ahead of the prompt on every run, an empty one is display-only.",
|
|
1767
|
+
"new.tagName": "Tag name",
|
|
1768
|
+
"new.tagNamePlaceholder": "e.g. Work",
|
|
1769
|
+
"new.tagPrompt": "Execution hint (optional)",
|
|
1770
|
+
"new.tagPromptPlaceholder": "e.g. Archive artefacts under 02-work/",
|
|
1771
|
+
"new.tagAdd": "Add tag",
|
|
1772
|
+
"new.tagRemove": "Remove tag {name}",
|
|
1773
|
+
"board.tagFilter": "Filter by tag",
|
|
1774
|
+
"board.tagFilterClear": "Clear tag filter",
|
|
1775
|
+
"board.tagEmpty": "No task carries all of these tags",
|
|
1690
1776
|
"detail.permissionPending": "Permission pending confirmation: this card's effective permission ({permission}) is above the session default; manual runs and cron are refused until a human confirms.",
|
|
1691
1777
|
"detail.permissionConfirm": "Confirm permission binding",
|
|
1692
1778
|
"detail.permissionConfirmed": "Permission confirmed · {time}",
|
|
@@ -1814,7 +1900,7 @@ window.__ModuleLoader__.load({
|
|
|
1814
1900
|
}
|
|
1815
1901
|
//#endregion
|
|
1816
1902
|
//#region \0dsh-css:packages/dsh-task-board/src/client/board.module.css.mjs
|
|
1817
|
-
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;container:_7D6uKa_task-board-view/inline-size}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{box-sizing:border-box;width:100%;height:36px;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 10px;font-size:13px;display:flex}._7D6uKa_entry:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._7D6uKa_entry[data-active]{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary);font-weight:600}._7D6uKa_entryIcon{flex:none;justify-content:center;align-items:center;width:24px;height:24px;display:inline-flex}._7D6uKa_entryIcon svg{width:18px;height:18px;display:block}._7D6uKa_entryLabel{text-overflow:ellipsis;overflow:hidden}[data-dsh-frame][data-sidebar-collapsed] ._7D6uKa_entry,[data-sidebar-collapsed] ._7D6uKa_entry{border-radius:50%;justify-content:center;width:36px;height:36px;margin:0 auto 12px;padding:0}[data-dsh-frame][data-sidebar-collapsed] ._7D6uKa_entryLabel,[data-sidebar-collapsed] ._7D6uKa_entryLabel{display:none}._7D6uKa_board{box-sizing:border-box;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_backButton{align-items:center;gap:4px;display:inline-flex}._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{overscroll-behavior-inline:contain;scrollbar-color:var(--dsw-alias-border-l3) var(--dsw-alias-interactive-bg-hover);scrollbar-width:thin;flex:1;grid-auto-columns:minmax(220px,1fr);grid-auto-flow:column;gap:12px;min-height:0;padding-bottom:6px;display:grid;overflow:auto hidden}._7D6uKa_columns::-webkit-scrollbar{height:10px}._7D6uKa_columns::-webkit-scrollbar-track{background:var(--dsw-alias-interactive-bg-hover);border-radius:999px}._7D6uKa_columns::-webkit-scrollbar-thumb{background:var(--dsw-alias-border-l3);background-clip:content-box;border:2px solid #0000;border-radius:999px}._7D6uKa_columns::-webkit-scrollbar-thumb:hover{background:var(--dsw-alias-border-l4);background-clip:content-box}._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}@container _7D6uKa_task-board-view (width<=768px){._7D6uKa_board{gap:10px;padding:10px}._7D6uKa_boardHeader{flex-wrap:wrap;align-items:center;gap:8px}._7D6uKa_backButton{flex:none;order:1}._7D6uKa_boardTitle{flex:auto;order:2}._7D6uKa_boardHeader>._7D6uKa_detailMeta{flex:1 0 100%;order:3;margin-left:0}._7D6uKa_search{flex:1 0 100%;order:4;min-width:0}._7D6uKa_boardHeader>button:not(._7D6uKa_backButton){flex:1 1 0;order:5;min-width:0}._7D6uKa_columns{scroll-snap-type:inline mandatory;scrollbar-width:none;-webkit-overflow-scrolling:touch;grid-auto-columns:86cqw;gap:10px;padding-inline:2px 14cqw;scroll-padding-inline:2px}._7D6uKa_columns::-webkit-scrollbar{display:none}._7D6uKa_column{scroll-snap-align:start;scroll-snap-stop:always}}@container _7D6uKa_task-board-view (width<=720px){._7D6uKa_boardHeader>._7D6uKa_detailMeta{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}}@container _7D6uKa_task-board-view (width<=600px){._7D6uKa_board{padding-inline:8px}}@media (width<=768px){[data-dsh-taskboard-view]{height:100dvh}._7D6uKa_entry,._7D6uKa_card,._7D6uKa_primaryButton,._7D6uKa_ghostButton,._7D6uKa_dangerButton,._7D6uKa_iconButton,._7D6uKa_linkButton,._7D6uKa_search,._7D6uKa_input,._7D6uKa_select,._7D6uKa_schedulePreset,._7D6uKa_scheduleToggle{min-height:44px}._7D6uKa_search,._7D6uKa_input,._7D6uKa_select,._7D6uKa_schedulePreset{box-sizing:border-box;font-size:16px}._7D6uKa_modalBackdrop{justify-content:stretch;align-items:stretch;width:100vw;height:100dvh}._7D6uKa_modal,._7D6uKa_detail{box-sizing:border-box;border:0;border-radius:0;width:100vw;height:100dvh;max-height:none}._7D6uKa_modal{padding-top:max(16px, env(safe-area-inset-top));padding-right:max(16px, env(safe-area-inset-right));padding-bottom:max(16px, env(safe-area-inset-bottom));padding-left:max(16px, env(safe-area-inset-left))}._7D6uKa_modalFooter{z-index:1;background:var(--dsw-alias-bg-base);flex-wrap:wrap;padding-top:8px;position:sticky;bottom:0}._7D6uKa_modalFooter>button{flex:120px}._7D6uKa_detailHeader{padding-top:max(12px, env(safe-area-inset-top));padding-right:max(14px, env(safe-area-inset-right));padding-left:max(14px, env(safe-area-inset-left));flex-wrap:wrap}._7D6uKa_detailTitle{min-width:0}._7D6uKa_detailBody{overscroll-behavior-y:contain;padding-right:max(14px, env(safe-area-inset-right));padding-left:max(14px, env(safe-area-inset-left))}._7D6uKa_detailFooter{padding-right:max(14px, env(safe-area-inset-right));padding-bottom:max(12px, env(safe-area-inset-bottom));padding-left:max(14px, env(safe-area-inset-left));flex-wrap:wrap}._7D6uKa_detailFooter>button{flex:96px}._7D6uKa_detailFooter>._7D6uKa_detailMeta{text-align:end;flex:1 0 100%;margin-left:0}._7D6uKa_scheduleRow{flex-direction:column;align-items:stretch}._7D6uKa_schedulePreset{width:100%}}._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}}";
|
|
1903
|
+
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;container:_7D6uKa_task-board-view/inline-size}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{box-sizing:border-box;width:100%;height:36px;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 10px;font-size:13px;display:flex}._7D6uKa_entry:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._7D6uKa_entry[data-active]{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary);font-weight:600}._7D6uKa_entryIcon{flex:none;justify-content:center;align-items:center;width:24px;height:24px;display:inline-flex}._7D6uKa_entryIcon svg{width:18px;height:18px;display:block}._7D6uKa_entryLabel{text-overflow:ellipsis;overflow:hidden}[data-dsh-frame][data-sidebar-collapsed] ._7D6uKa_entry,[data-sidebar-collapsed] ._7D6uKa_entry{border-radius:50%;justify-content:center;width:36px;height:36px;margin:0 auto 12px;padding:0}[data-dsh-frame][data-sidebar-collapsed] ._7D6uKa_entryLabel,[data-sidebar-collapsed] ._7D6uKa_entryLabel{display:none}._7D6uKa_board{box-sizing:border-box;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_backButton{align-items:center;gap:4px;display:inline-flex}._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{overscroll-behavior-inline:contain;scrollbar-color:var(--dsw-alias-border-l3) var(--dsw-alias-interactive-bg-hover);scrollbar-width:thin;flex:1;grid-auto-columns:minmax(220px,1fr);grid-auto-flow:column;gap:12px;min-height:0;padding-bottom:6px;display:grid;overflow:auto hidden}._7D6uKa_columns::-webkit-scrollbar{height:10px}._7D6uKa_columns::-webkit-scrollbar-track{background:var(--dsw-alias-interactive-bg-hover);border-radius:999px}._7D6uKa_columns::-webkit-scrollbar-thumb{background:var(--dsw-alias-border-l3);background-clip:content-box;border:2px solid #0000;border-radius:999px}._7D6uKa_columns::-webkit-scrollbar-thumb:hover{background:var(--dsw-alias-border-l4);background-clip:content-box}._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}@container _7D6uKa_task-board-view (width<=768px){._7D6uKa_board{gap:10px;padding:10px}._7D6uKa_boardHeader{flex-wrap:wrap;align-items:center;gap:8px}._7D6uKa_backButton{flex:none;order:1}._7D6uKa_boardTitle{flex:auto;order:2}._7D6uKa_boardHeader>._7D6uKa_detailMeta{flex:1 0 100%;order:3;margin-left:0}._7D6uKa_search{flex:1 0 100%;order:4;min-width:0}._7D6uKa_boardHeader>button:not(._7D6uKa_backButton){flex:1 1 0;order:5;min-width:0}._7D6uKa_columns{scroll-snap-type:inline mandatory;scrollbar-width:none;-webkit-overflow-scrolling:touch;grid-auto-columns:86cqw;gap:10px;padding-inline:2px 14cqw;scroll-padding-inline:2px}._7D6uKa_columns::-webkit-scrollbar{display:none}._7D6uKa_column{scroll-snap-align:start;scroll-snap-stop:always}}@container _7D6uKa_task-board-view (width<=720px){._7D6uKa_boardHeader>._7D6uKa_detailMeta{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}}@container _7D6uKa_task-board-view (width<=600px){._7D6uKa_board{padding-inline:8px}}@media (width<=768px){[data-dsh-taskboard-view]{height:100dvh}._7D6uKa_entry,._7D6uKa_card,._7D6uKa_primaryButton,._7D6uKa_ghostButton,._7D6uKa_dangerButton,._7D6uKa_iconButton,._7D6uKa_linkButton,._7D6uKa_search,._7D6uKa_input,._7D6uKa_select,._7D6uKa_schedulePreset,._7D6uKa_scheduleToggle{min-height:44px}._7D6uKa_search,._7D6uKa_input,._7D6uKa_select,._7D6uKa_schedulePreset{box-sizing:border-box;font-size:16px}._7D6uKa_modalBackdrop{justify-content:stretch;align-items:stretch;width:100vw;height:100dvh}._7D6uKa_modal,._7D6uKa_detail{box-sizing:border-box;border:0;border-radius:0;width:100vw;height:100dvh;max-height:none}._7D6uKa_modal{padding-top:max(16px, env(safe-area-inset-top));padding-right:max(16px, env(safe-area-inset-right));padding-bottom:max(16px, env(safe-area-inset-bottom));padding-left:max(16px, env(safe-area-inset-left))}._7D6uKa_modalFooter{z-index:1;background:var(--dsw-alias-bg-base);flex-wrap:wrap;padding-top:8px;position:sticky;bottom:0}._7D6uKa_modalFooter>button{flex:120px}._7D6uKa_detailHeader{padding-top:max(12px, env(safe-area-inset-top));padding-right:max(14px, env(safe-area-inset-right));padding-left:max(14px, env(safe-area-inset-left));flex-wrap:wrap}._7D6uKa_detailTitle{min-width:0}._7D6uKa_detailBody{overscroll-behavior-y:contain;padding-right:max(14px, env(safe-area-inset-right));padding-left:max(14px, env(safe-area-inset-left))}._7D6uKa_detailFooter{padding-right:max(14px, env(safe-area-inset-right));padding-bottom:max(12px, env(safe-area-inset-bottom));padding-left:max(14px, env(safe-area-inset-left));flex-wrap:wrap}._7D6uKa_detailFooter>button{flex:96px}._7D6uKa_detailFooter>._7D6uKa_detailMeta{text-align:end;flex:1 0 100%;margin-left:0}._7D6uKa_scheduleRow{flex-direction:column;align-items:stretch}._7D6uKa_schedulePreset{width:100%}}._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}}._7D6uKa_cardTags{flex-wrap:wrap;gap:4px;display:flex}._7D6uKa_cardTag{border:1px solid var(--dsh-task-tag-border);background:var(--dsh-task-tag-fill);max-width:100%;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;border-radius:999px;padding:0 7px;font-size:10px;line-height:16px;overflow:hidden}._7D6uKa_tagFilter{flex-wrap:wrap;align-items:center;gap:6px;margin:0 0 10px;display:flex}._7D6uKa_tagFilterLabel{color:var(--dsw-alias-label-tertiary);font-size:11px}._7D6uKa_tagChip{border:1px solid var(--dsh-task-tag-border);color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border-radius:999px;padding:1px 9px;font-family:inherit;font-size:11px;line-height:18px}._7D6uKa_tagChip[data-active=true]{background:var(--dsh-task-tag-fill);color:var(--dsw-alias-label-primary)}._7D6uKa_cardTag[data-tag-tone=\"0\"],._7D6uKa_tagChip[data-tag-tone=\"0\"]{--dsh-task-tag-fill:#4e93e82e;--dsh-task-tag-border:#4e93e866}._7D6uKa_cardTag[data-tag-tone=\"1\"],._7D6uKa_tagChip[data-tag-tone=\"1\"]{--dsh-task-tag-fill:#2ea36a2e;--dsh-task-tag-border:#2ea36a66}._7D6uKa_cardTag[data-tag-tone=\"2\"],._7D6uKa_tagChip[data-tag-tone=\"2\"]{--dsh-task-tag-fill:#d08a2a2e;--dsh-task-tag-border:#d08a2a66}._7D6uKa_cardTag[data-tag-tone=\"3\"],._7D6uKa_tagChip[data-tag-tone=\"3\"]{--dsh-task-tag-fill:#b456c82e;--dsh-task-tag-border:#b456c866}._7D6uKa_cardTag[data-tag-tone=\"4\"],._7D6uKa_tagChip[data-tag-tone=\"4\"]{--dsh-task-tag-fill:#cf5f7a2e;--dsh-task-tag-border:#cf5f7a66}._7D6uKa_cardTag[data-tag-tone=\"5\"],._7D6uKa_tagChip[data-tag-tone=\"5\"]{--dsh-task-tag-fill:#4a9fb52e;--dsh-task-tag-border:#4a9fb566}._7D6uKa_fieldHint{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.4}._7D6uKa_tagRow{align-items:center;gap:6px;display:flex}._7D6uKa_tagRow ._7D6uKa_input{flex:1 1 0;min-width:0}._7D6uKa_tagRow ._7D6uKa_ghostButton{flex:none}._7D6uKa_tagAddButton{align-self:flex-start}";
|
|
1818
1904
|
const tagId$1 = "@linxin666/dsh-client-ui-task-board/packages/dsh-task-board/src/client/board.module.css";
|
|
1819
1905
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
1820
1906
|
const tag = document.createElement("style");
|
|
@@ -1836,6 +1922,8 @@ window.__ModuleLoader__.load({
|
|
|
1836
1922
|
"cardSchedule": "_7D6uKa_cardSchedule",
|
|
1837
1923
|
"cardSession": "_7D6uKa_cardSession",
|
|
1838
1924
|
"cardSpinner": "_7D6uKa_cardSpinner",
|
|
1925
|
+
"cardTag": "_7D6uKa_cardTag",
|
|
1926
|
+
"cardTags": "_7D6uKa_cardTags",
|
|
1839
1927
|
"cardTime": "_7D6uKa_cardTime",
|
|
1840
1928
|
"cardTitle": "_7D6uKa_cardTitle",
|
|
1841
1929
|
"cards": "_7D6uKa_cards",
|
|
@@ -1865,6 +1953,7 @@ window.__ModuleLoader__.load({
|
|
|
1865
1953
|
"executionRow": "_7D6uKa_executionRow",
|
|
1866
1954
|
"executionTimes": "_7D6uKa_executionTimes",
|
|
1867
1955
|
"field": "_7D6uKa_field",
|
|
1956
|
+
"fieldHint": "_7D6uKa_fieldHint",
|
|
1868
1957
|
"fieldLabel": "_7D6uKa_fieldLabel",
|
|
1869
1958
|
"formError": "_7D6uKa_formError",
|
|
1870
1959
|
"ghostButton": "_7D6uKa_ghostButton",
|
|
@@ -1888,6 +1977,11 @@ window.__ModuleLoader__.load({
|
|
|
1888
1977
|
"select": "_7D6uKa_select",
|
|
1889
1978
|
"statusBadge": "_7D6uKa_statusBadge",
|
|
1890
1979
|
"statusDot": "_7D6uKa_statusDot",
|
|
1980
|
+
"tagAddButton": "_7D6uKa_tagAddButton",
|
|
1981
|
+
"tagChip": "_7D6uKa_tagChip",
|
|
1982
|
+
"tagFilter": "_7D6uKa_tagFilter",
|
|
1983
|
+
"tagFilterLabel": "_7D6uKa_tagFilterLabel",
|
|
1984
|
+
"tagRow": "_7D6uKa_tagRow",
|
|
1891
1985
|
"task-board-view": "_7D6uKa_task-board-view"
|
|
1892
1986
|
};
|
|
1893
1987
|
//#endregion
|
|
@@ -1913,6 +2007,8 @@ window.__ModuleLoader__.load({
|
|
|
1913
2007
|
];
|
|
1914
2008
|
//#endregion
|
|
1915
2009
|
//#region src/client/board/TaskForm.tsx
|
|
2010
|
+
/** DOM id shared by the tag-name inputs and their datalist (one board at a time). */
|
|
2011
|
+
const TAG_NAME_LIST_ID = "dsh-task-board-tag-names";
|
|
1916
2012
|
/** Modal overlay: closes on backdrop press, submits through the form. */
|
|
1917
2013
|
function ModalShell({ ariaLabel, title, error, pending, submitLabel, onSubmit, onClose, children }) {
|
|
1918
2014
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -2000,6 +2096,104 @@ window.__ModuleLoader__.load({
|
|
|
2000
2096
|
})
|
|
2001
2097
|
] });
|
|
2002
2098
|
}
|
|
2099
|
+
/**
|
|
2100
|
+
* Task labels (issue #1521): one row per label holding the badge name and an
|
|
2101
|
+
* optional execution hint. The name inputs offer the labels already used on the
|
|
2102
|
+
* board through a datalist, and picking one adopts its hint when the row has
|
|
2103
|
+
* none — so a business line is defined once and reused by every later task.
|
|
2104
|
+
*/
|
|
2105
|
+
function TaskTagFields({ tags, knownTags, onChange }) {
|
|
2106
|
+
const update = (index, patch) => {
|
|
2107
|
+
onChange(tags.map((tag, position) => position === index ? {
|
|
2108
|
+
...tag,
|
|
2109
|
+
...patch
|
|
2110
|
+
} : tag));
|
|
2111
|
+
};
|
|
2112
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2113
|
+
className: board_module_css_default.field,
|
|
2114
|
+
children: [
|
|
2115
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2116
|
+
className: board_module_css_default.fieldLabel,
|
|
2117
|
+
children: t("new.tags")
|
|
2118
|
+
}),
|
|
2119
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2120
|
+
className: board_module_css_default.fieldHint,
|
|
2121
|
+
children: t("new.tagsHint")
|
|
2122
|
+
}),
|
|
2123
|
+
tags.map((tag, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2124
|
+
className: board_module_css_default.tagRow,
|
|
2125
|
+
children: [
|
|
2126
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2127
|
+
className: board_module_css_default.input,
|
|
2128
|
+
list: TAG_NAME_LIST_ID,
|
|
2129
|
+
value: tag.name,
|
|
2130
|
+
maxLength: 32,
|
|
2131
|
+
placeholder: t("new.tagNamePlaceholder"),
|
|
2132
|
+
"aria-label": t("new.tagName"),
|
|
2133
|
+
onChange: (event) => {
|
|
2134
|
+
const name = event.target.value;
|
|
2135
|
+
const known = knownTags.find((candidate) => candidate.name === name);
|
|
2136
|
+
const adoptsHint = known?.promptPrefix !== void 0 && (tag.promptPrefix ?? "").trim() === "";
|
|
2137
|
+
update(index, adoptsHint ? {
|
|
2138
|
+
name,
|
|
2139
|
+
promptPrefix: known.promptPrefix
|
|
2140
|
+
} : { name });
|
|
2141
|
+
}
|
|
2142
|
+
}),
|
|
2143
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2144
|
+
className: board_module_css_default.input,
|
|
2145
|
+
value: tag.promptPrefix ?? "",
|
|
2146
|
+
maxLength: 200,
|
|
2147
|
+
placeholder: t("new.tagPromptPlaceholder"),
|
|
2148
|
+
"aria-label": t("new.tagPrompt"),
|
|
2149
|
+
onChange: (event) => {
|
|
2150
|
+
update(index, { promptPrefix: event.target.value });
|
|
2151
|
+
}
|
|
2152
|
+
}),
|
|
2153
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2154
|
+
type: "button",
|
|
2155
|
+
className: board_module_css_default.ghostButton,
|
|
2156
|
+
"aria-label": t("new.tagRemove", { name: tag.name }),
|
|
2157
|
+
onClick: () => {
|
|
2158
|
+
onChange(tags.filter((_, position) => position !== index));
|
|
2159
|
+
},
|
|
2160
|
+
children: "×"
|
|
2161
|
+
})
|
|
2162
|
+
]
|
|
2163
|
+
}, index)),
|
|
2164
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("datalist", {
|
|
2165
|
+
id: TAG_NAME_LIST_ID,
|
|
2166
|
+
children: knownTags.map((tag) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", { value: tag.name }, tag.name))
|
|
2167
|
+
}),
|
|
2168
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2169
|
+
type: "button",
|
|
2170
|
+
className: board_module_css_default.ghostButton + " " + board_module_css_default.tagAddButton,
|
|
2171
|
+
disabled: tags.length >= 8,
|
|
2172
|
+
onClick: () => {
|
|
2173
|
+
onChange([...tags, { name: "" }]);
|
|
2174
|
+
},
|
|
2175
|
+
children: ["+ ", t("new.tagAdd")]
|
|
2176
|
+
})
|
|
2177
|
+
]
|
|
2178
|
+
});
|
|
2179
|
+
}
|
|
2180
|
+
/**
|
|
2181
|
+
* Drop blank rows and trim what survives, so the wire always carries a valid
|
|
2182
|
+
* tag list (the protocol rejects a list with a blank name or an empty array).
|
|
2183
|
+
*/
|
|
2184
|
+
function cleanTags(tags) {
|
|
2185
|
+
const cleaned = [];
|
|
2186
|
+
for (const tag of tags) {
|
|
2187
|
+
const name = tag.name.trim();
|
|
2188
|
+
if (name === "") continue;
|
|
2189
|
+
const promptPrefix = tag.promptPrefix?.trim();
|
|
2190
|
+
cleaned.push(promptPrefix === void 0 || promptPrefix === "" ? { name } : {
|
|
2191
|
+
name,
|
|
2192
|
+
promptPrefix
|
|
2193
|
+
});
|
|
2194
|
+
}
|
|
2195
|
+
return cleaned;
|
|
2196
|
+
}
|
|
2003
2197
|
//#endregion
|
|
2004
2198
|
//#region src/client/board/NewTaskModal.tsx
|
|
2005
2199
|
/**
|
|
@@ -2023,6 +2217,7 @@ window.__ModuleLoader__.load({
|
|
|
2023
2217
|
const [freezeText, setFreezeText] = (0, react.useState)("");
|
|
2024
2218
|
const [freezeError, setFreezeError] = (0, react.useState)(void 0);
|
|
2025
2219
|
const [handoverText, setHandoverText] = (0, react.useState)(initialTask?.handover?.references !== void 0 ? initialTask.handover.references.join("\n") : "");
|
|
2220
|
+
const [tags, setTags] = (0, react.useState)(initialTask?.tags ?? []);
|
|
2026
2221
|
const [archiveOriginal, setArchiveOriginal] = (0, react.useState)(true);
|
|
2027
2222
|
const [error, setError] = (0, react.useState)(void 0);
|
|
2028
2223
|
const [pending, setPending] = (0, react.useState)(false);
|
|
@@ -2055,6 +2250,7 @@ window.__ModuleLoader__.load({
|
|
|
2055
2250
|
mode: mode === "" ? void 0 : mode,
|
|
2056
2251
|
permission: permission === "" ? void 0 : permission
|
|
2057
2252
|
};
|
|
2253
|
+
const tagList = cleanTags(tags);
|
|
2058
2254
|
setPending(true);
|
|
2059
2255
|
if (await controller.createTaskConfirmed({
|
|
2060
2256
|
title,
|
|
@@ -2067,6 +2263,7 @@ window.__ModuleLoader__.load({
|
|
|
2067
2263
|
permission: permission === "" ? void 0 : permission,
|
|
2068
2264
|
model: model === "" ? void 0 : model,
|
|
2069
2265
|
...reuseSession ? { reuseSession: true } : {},
|
|
2266
|
+
...tagList.length > 0 ? { tags: tagList } : {},
|
|
2070
2267
|
schedule: scheduleEnabled ? {
|
|
2071
2268
|
enabled: true,
|
|
2072
2269
|
cron: scheduleCron.trim()
|
|
@@ -2105,6 +2302,11 @@ window.__ModuleLoader__.load({
|
|
|
2105
2302
|
onDescriptionChange: setDescription,
|
|
2106
2303
|
onPromptChange: setPrompt
|
|
2107
2304
|
}),
|
|
2305
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TaskTagFields, {
|
|
2306
|
+
tags,
|
|
2307
|
+
knownTags: collectKnownTags(controller.getSnapshot().tasks),
|
|
2308
|
+
onChange: setTags
|
|
2309
|
+
}),
|
|
2108
2310
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
2109
2311
|
className: board_module_css_default.field,
|
|
2110
2312
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
@@ -2381,6 +2583,17 @@ window.__ModuleLoader__.load({
|
|
|
2381
2583
|
className: board_module_css_default.cardTitle,
|
|
2382
2584
|
children: task.title
|
|
2383
2585
|
}),
|
|
2586
|
+
task.tags !== void 0 && task.tags.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2587
|
+
className: board_module_css_default.cardTags,
|
|
2588
|
+
children: task.tags.map((tag) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2589
|
+
className: board_module_css_default.cardTag,
|
|
2590
|
+
"data-tag-tone": tagTone(tag.name),
|
|
2591
|
+
"data-dsh-part": "tag-badge",
|
|
2592
|
+
"data-tag-hint": tag.promptPrefix === void 0 ? void 0 : tag.promptPrefix,
|
|
2593
|
+
title: tag.promptPrefix === void 0 ? tag.name : tag.promptPrefix,
|
|
2594
|
+
children: tag.name
|
|
2595
|
+
}, tag.name))
|
|
2596
|
+
}),
|
|
2384
2597
|
task.description !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2385
2598
|
className: board_module_css_default.cardExcerpt,
|
|
2386
2599
|
children: task.description
|
|
@@ -2496,6 +2709,7 @@ window.__ModuleLoader__.load({
|
|
|
2496
2709
|
const [title, setTitle] = (0, react.useState)(task.title);
|
|
2497
2710
|
const [description, setDescription] = (0, react.useState)(task.description);
|
|
2498
2711
|
const [prompt, setPrompt] = (0, react.useState)(task.prompt);
|
|
2712
|
+
const [tags, setTags] = (0, react.useState)(task.tags ?? []);
|
|
2499
2713
|
const [error, setError] = (0, react.useState)(void 0);
|
|
2500
2714
|
const [pending, setPending] = (0, react.useState)(false);
|
|
2501
2715
|
const submit = async () => {
|
|
@@ -2504,18 +2718,21 @@ window.__ModuleLoader__.load({
|
|
|
2504
2718
|
return;
|
|
2505
2719
|
}
|
|
2506
2720
|
setPending(true);
|
|
2507
|
-
|
|
2721
|
+
const tagList = cleanTags(tags);
|
|
2722
|
+
const patch = {
|
|
2508
2723
|
title,
|
|
2509
2724
|
description,
|
|
2510
|
-
prompt
|
|
2511
|
-
|
|
2725
|
+
prompt,
|
|
2726
|
+
...tagList.length > 0 ? { tags: tagList } : task.tags === void 0 ? {} : { tags: null }
|
|
2727
|
+
};
|
|
2728
|
+
if (await controller.updateTask(task.id, patch)) {
|
|
2512
2729
|
onClose();
|
|
2513
2730
|
return;
|
|
2514
2731
|
}
|
|
2515
2732
|
setPending(false);
|
|
2516
2733
|
setError(controller.getSnapshot().transportError ?? t("new.required"));
|
|
2517
2734
|
};
|
|
2518
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
2735
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(ModalShell, {
|
|
2519
2736
|
ariaLabel: t("edit.title"),
|
|
2520
2737
|
title: t("edit.title"),
|
|
2521
2738
|
error,
|
|
@@ -2525,7 +2742,7 @@ window.__ModuleLoader__.load({
|
|
|
2525
2742
|
submit();
|
|
2526
2743
|
},
|
|
2527
2744
|
onClose,
|
|
2528
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TaskContentFields, {
|
|
2745
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TaskContentFields, {
|
|
2529
2746
|
title,
|
|
2530
2747
|
description,
|
|
2531
2748
|
prompt,
|
|
@@ -2535,7 +2752,11 @@ window.__ModuleLoader__.load({
|
|
|
2535
2752
|
},
|
|
2536
2753
|
onDescriptionChange: setDescription,
|
|
2537
2754
|
onPromptChange: setPrompt
|
|
2538
|
-
})
|
|
2755
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TaskTagFields, {
|
|
2756
|
+
tags,
|
|
2757
|
+
knownTags: collectKnownTags(controller.getSnapshot().tasks),
|
|
2758
|
+
onChange: setTags
|
|
2759
|
+
})]
|
|
2539
2760
|
});
|
|
2540
2761
|
}
|
|
2541
2762
|
//#endregion
|
|
@@ -3015,10 +3236,10 @@ window.__ModuleLoader__.load({
|
|
|
3015
3236
|
}),
|
|
3016
3237
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
3017
3238
|
className: board_module_css_default.executionList,
|
|
3018
|
-
children: current.handover.references.map((reference) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
|
|
3239
|
+
children: current.handover.references.map((reference, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
|
|
3019
3240
|
className: board_module_css_default.executionRow,
|
|
3020
3241
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: reference })
|
|
3021
|
-
}, reference))
|
|
3242
|
+
}, `${reference}-${index}`))
|
|
3022
3243
|
}),
|
|
3023
3244
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3024
3245
|
className: board_module_css_default.detailMeta,
|
|
@@ -3212,15 +3433,30 @@ window.__ModuleLoader__.load({
|
|
|
3212
3433
|
* active. Cards open the task detail (never execute directly); the header
|
|
3213
3434
|
* offers filter, new-task, and a back-to-chat escape.
|
|
3214
3435
|
*/
|
|
3215
|
-
/** Case-insensitive title/description/freeze-snapshot match. */
|
|
3436
|
+
/** Case-insensitive title/description/tag/freeze-snapshot match. */
|
|
3216
3437
|
function matchesFilter(task, filter) {
|
|
3217
3438
|
if (filter.trim() === "") return true;
|
|
3218
3439
|
const needle = filter.trim().toLowerCase();
|
|
3219
|
-
const haystacks = [
|
|
3440
|
+
const haystacks = [
|
|
3441
|
+
task.title,
|
|
3442
|
+
task.description,
|
|
3443
|
+
...(task.tags ?? []).map((tag) => tag.name)
|
|
3444
|
+
];
|
|
3220
3445
|
if (task.freeze !== void 0) haystacks.push(task.freeze.goal, task.freeze.progress, task.freeze.next);
|
|
3221
3446
|
return haystacks.some((text) => text.toLowerCase().includes(needle));
|
|
3222
3447
|
}
|
|
3223
3448
|
/**
|
|
3449
|
+
* Whether a task carries every selected label (issue #1521). Multi-select is
|
|
3450
|
+
* conjunctive: adding a label narrows the board instead of widening it, which
|
|
3451
|
+
* is the only reading that keeps "工作" selected from dragging unrelated cards
|
|
3452
|
+
* back in when a second label is added.
|
|
3453
|
+
*/
|
|
3454
|
+
function matchesTagFilter(task, selected) {
|
|
3455
|
+
if (selected.length === 0) return true;
|
|
3456
|
+
const names = new Set((task.tags ?? []).map((tag) => tag.name));
|
|
3457
|
+
return selected.every((name) => names.has(name));
|
|
3458
|
+
}
|
|
3459
|
+
/**
|
|
3224
3460
|
* Memoized per-card adapter: with a stable `onOpen` from the board and an
|
|
3225
3461
|
* immutable task record (only the changed card gets a new object ref), a card
|
|
3226
3462
|
* re-renders only when its own task changes — not when a sibling card status,
|
|
@@ -3241,10 +3477,15 @@ window.__ModuleLoader__.load({
|
|
|
3241
3477
|
const [snapshot, setSnapshot] = (0, react.useState)(controller.getSnapshot());
|
|
3242
3478
|
(0, react.useEffect)(() => controller.subscribe(() => setSnapshot(controller.getSnapshot())), [controller]);
|
|
3243
3479
|
const [filter, setFilter] = (0, react.useState)("");
|
|
3480
|
+
const [tagFilter, setTagFilter] = (0, react.useState)([]);
|
|
3244
3481
|
const [showNew, setShowNew] = (0, react.useState)(false);
|
|
3245
3482
|
const selected = selectedTaskOf(snapshot);
|
|
3246
3483
|
const archiveView = snapshot.archiveView;
|
|
3247
|
-
const
|
|
3484
|
+
const knownTags = collectKnownTags(snapshot.tasks);
|
|
3485
|
+
const visible = snapshot.tasks.filter((task) => (archiveView ? task.archivedAt !== void 0 : task.archivedAt === void 0) && matchesFilter(task, filter) && matchesTagFilter(task, tagFilter));
|
|
3486
|
+
const toggleTag = (0, react.useCallback)((name) => {
|
|
3487
|
+
setTagFilter((current) => current.includes(name) ? current.filter((entry) => entry !== name) : [...current, name]);
|
|
3488
|
+
}, []);
|
|
3248
3489
|
const openTask = (0, react.useCallback)((id) => {
|
|
3249
3490
|
controller.openTask(id);
|
|
3250
3491
|
}, [controller]);
|
|
@@ -3308,6 +3549,40 @@ window.__ModuleLoader__.load({
|
|
|
3308
3549
|
})
|
|
3309
3550
|
]
|
|
3310
3551
|
}),
|
|
3552
|
+
!archiveView && knownTags.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3553
|
+
className: board_module_css_default.tagFilter,
|
|
3554
|
+
"data-dsh-part": "tag-filter",
|
|
3555
|
+
children: [
|
|
3556
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3557
|
+
className: board_module_css_default.tagFilterLabel,
|
|
3558
|
+
children: t("board.tagFilter")
|
|
3559
|
+
}),
|
|
3560
|
+
knownTags.map((tag) => {
|
|
3561
|
+
const active = tagFilter.includes(tag.name);
|
|
3562
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3563
|
+
type: "button",
|
|
3564
|
+
className: board_module_css_default.tagChip,
|
|
3565
|
+
"data-dsh-part": "tag-chip",
|
|
3566
|
+
"data-tag-tone": tagTone(tag.name),
|
|
3567
|
+
"data-active": active ? "true" : void 0,
|
|
3568
|
+
"aria-pressed": active,
|
|
3569
|
+
title: tag.promptPrefix === void 0 ? tag.name : tag.promptPrefix,
|
|
3570
|
+
onClick: () => {
|
|
3571
|
+
toggleTag(tag.name);
|
|
3572
|
+
},
|
|
3573
|
+
children: tag.name
|
|
3574
|
+
}, tag.name);
|
|
3575
|
+
}),
|
|
3576
|
+
tagFilter.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3577
|
+
type: "button",
|
|
3578
|
+
className: board_module_css_default.linkButton,
|
|
3579
|
+
onClick: () => {
|
|
3580
|
+
setTagFilter([]);
|
|
3581
|
+
},
|
|
3582
|
+
children: t("board.tagFilterClear")
|
|
3583
|
+
})
|
|
3584
|
+
]
|
|
3585
|
+
}),
|
|
3311
3586
|
snapshot.transportError !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3312
3587
|
className: board_module_css_default.formError,
|
|
3313
3588
|
children: [
|
|
@@ -3347,7 +3622,7 @@ window.__ModuleLoader__.load({
|
|
|
3347
3622
|
onOpen: openTask
|
|
3348
3623
|
}, task.id)), visible.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3349
3624
|
className: board_module_css_default.columnEmpty,
|
|
3350
|
-
children: t("archive.empty")
|
|
3625
|
+
children: tagFilter.length > 0 ? t("board.tagEmpty") : t("archive.empty")
|
|
3351
3626
|
})]
|
|
3352
3627
|
})]
|
|
3353
3628
|
}) : COLUMNS.map((column) => {
|
|
@@ -3394,7 +3669,7 @@ window.__ModuleLoader__.load({
|
|
|
3394
3669
|
onOpen: openTask
|
|
3395
3670
|
}, task.id)), tasks.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3396
3671
|
className: board_module_css_default.columnEmpty,
|
|
3397
|
-
children: t("board.empty")
|
|
3672
|
+
children: tagFilter.length > 0 ? t("board.tagEmpty") : t("board.empty")
|
|
3398
3673
|
})]
|
|
3399
3674
|
})]
|
|
3400
3675
|
}, column.status);
|
|
@@ -3414,6 +3689,94 @@ window.__ModuleLoader__.load({
|
|
|
3414
3689
|
});
|
|
3415
3690
|
}
|
|
3416
3691
|
//#endregion
|
|
3692
|
+
//#region src/client/body-mutations.ts
|
|
3693
|
+
/** Cross-bundle registry key; `Symbol.for` so every module copy agrees. */
|
|
3694
|
+
const HUB_KEY = Symbol.for("dsh-web.body-mutation-hub");
|
|
3695
|
+
const INVALIDATION_ONLY = Symbol.for("dsh-web.body-mutation-invalidation");
|
|
3696
|
+
function needsRecords(subscribers) {
|
|
3697
|
+
for (const listener of subscribers) if (!listener[INVALIDATION_ONLY]) return true;
|
|
3698
|
+
return false;
|
|
3699
|
+
}
|
|
3700
|
+
/**
|
|
3701
|
+
* Subscribe to a coalesced DOM re-check without retaining mutation records.
|
|
3702
|
+
* The marked wrapper also works with an older hub, which delivers records
|
|
3703
|
+
* that it simply ignores until a page reload picks up the updated hub.
|
|
3704
|
+
*/
|
|
3705
|
+
function subscribeBodyInvalidations(subscriber) {
|
|
3706
|
+
const listener = () => {
|
|
3707
|
+
subscriber();
|
|
3708
|
+
};
|
|
3709
|
+
listener[INVALIDATION_ONLY] = true;
|
|
3710
|
+
return subscribeBodyMutations(listener);
|
|
3711
|
+
}
|
|
3712
|
+
/**
|
|
3713
|
+
* Subscribe to body-level childList mutations.
|
|
3714
|
+
* @param subscriber - called at most once per animation frame with the records
|
|
3715
|
+
* collected since the previous flush; must be safe to run repeatedly.
|
|
3716
|
+
* @returns the disposer removing this subscriber (and the observer when it was
|
|
3717
|
+
* the last one).
|
|
3718
|
+
*/
|
|
3719
|
+
function subscribeBodyMutations(subscriber) {
|
|
3720
|
+
if (typeof globalThis === "undefined" || typeof document === "undefined") return () => {};
|
|
3721
|
+
if (typeof MutationObserver !== "function") return () => {};
|
|
3722
|
+
const registry = globalThis;
|
|
3723
|
+
let hub = registry[HUB_KEY];
|
|
3724
|
+
if (hub === void 0) {
|
|
3725
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
3726
|
+
const created = {
|
|
3727
|
+
observer: void 0,
|
|
3728
|
+
subscribers,
|
|
3729
|
+
pending: [],
|
|
3730
|
+
scheduled: false
|
|
3731
|
+
};
|
|
3732
|
+
const flush = () => {
|
|
3733
|
+
created.frame = void 0;
|
|
3734
|
+
created.scheduled = false;
|
|
3735
|
+
const batch = created.pending;
|
|
3736
|
+
created.pending = [];
|
|
3737
|
+
for (const listener of [...subscribers]) {
|
|
3738
|
+
if (!subscribers.has(listener)) continue;
|
|
3739
|
+
try {
|
|
3740
|
+
listener(batch);
|
|
3741
|
+
} catch {}
|
|
3742
|
+
}
|
|
3743
|
+
};
|
|
3744
|
+
const schedule = () => {
|
|
3745
|
+
if (created.scheduled) return;
|
|
3746
|
+
created.scheduled = true;
|
|
3747
|
+
if (typeof requestAnimationFrame === "function") created.frame = requestAnimationFrame(flush);
|
|
3748
|
+
else flush();
|
|
3749
|
+
};
|
|
3750
|
+
created.observer = new MutationObserver((records) => {
|
|
3751
|
+
if (needsRecords(subscribers)) for (const record of records) created.pending.push(record);
|
|
3752
|
+
schedule();
|
|
3753
|
+
});
|
|
3754
|
+
created.observer.observe(document.body ?? document.documentElement, {
|
|
3755
|
+
childList: true,
|
|
3756
|
+
subtree: true
|
|
3757
|
+
});
|
|
3758
|
+
registry[HUB_KEY] = created;
|
|
3759
|
+
hub = created;
|
|
3760
|
+
}
|
|
3761
|
+
const active = hub;
|
|
3762
|
+
active.subscribers.add(subscriber);
|
|
3763
|
+
let subscribed = true;
|
|
3764
|
+
return () => {
|
|
3765
|
+
if (!subscribed) return;
|
|
3766
|
+
subscribed = false;
|
|
3767
|
+
active.subscribers.delete(subscriber);
|
|
3768
|
+
if (!needsRecords(active.subscribers)) active.pending = [];
|
|
3769
|
+
if (active.subscribers.size === 0 && registry[HUB_KEY] === active) {
|
|
3770
|
+
active.observer.disconnect();
|
|
3771
|
+
if (active.frame !== void 0 && typeof cancelAnimationFrame === "function") cancelAnimationFrame(active.frame);
|
|
3772
|
+
active.frame = void 0;
|
|
3773
|
+
active.pending = [];
|
|
3774
|
+
active.scheduled = false;
|
|
3775
|
+
delete registry[HUB_KEY];
|
|
3776
|
+
}
|
|
3777
|
+
};
|
|
3778
|
+
}
|
|
3779
|
+
//#endregion
|
|
3417
3780
|
//#region src/client/panel-mount-core.ts
|
|
3418
3781
|
/**
|
|
3419
3782
|
* Center-column panel takeover lifecycle.
|
|
@@ -3458,32 +3821,31 @@ window.__ModuleLoader__.load({
|
|
|
3458
3821
|
});
|
|
3459
3822
|
} catch {}
|
|
3460
3823
|
const ensure = () => {
|
|
3461
|
-
if (container !== void 0) {
|
|
3462
|
-
if (container.isConnected) return;
|
|
3824
|
+
if (container !== void 0 && !container.isConnected) {
|
|
3463
3825
|
root?.unmount();
|
|
3464
3826
|
root = void 0;
|
|
3465
3827
|
container.remove();
|
|
3466
3828
|
container = void 0;
|
|
3467
3829
|
}
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3830
|
+
if (container === void 0) {
|
|
3831
|
+
const column = conversationColumn();
|
|
3832
|
+
if (column === void 0) return;
|
|
3833
|
+
container = document.createElement("div");
|
|
3834
|
+
container.dataset[options.viewDatasetKey] = "";
|
|
3835
|
+
container.dataset.dshPlugin = options.pluginName;
|
|
3836
|
+
container.className = options.viewClassName;
|
|
3837
|
+
column.appendChild(container);
|
|
3838
|
+
}
|
|
3839
|
+
if (root !== void 0 || !options.isOpen()) return;
|
|
3475
3840
|
root = (0, react_dom_client.createRoot)(container);
|
|
3476
3841
|
options.render(root);
|
|
3477
3842
|
};
|
|
3478
|
-
const
|
|
3843
|
+
const unsubscribeBody = subscribeBodyInvalidations(() => {
|
|
3479
3844
|
ensure();
|
|
3480
3845
|
});
|
|
3481
|
-
waitObserver.observe(document.body, {
|
|
3482
|
-
childList: true,
|
|
3483
|
-
subtree: true
|
|
3484
|
-
});
|
|
3485
3846
|
const applyActive = () => {
|
|
3486
3847
|
if (options.isOpen()) {
|
|
3848
|
+
ensure();
|
|
3487
3849
|
document.documentElement.removeAttribute(options.siblingActiveAttribute);
|
|
3488
3850
|
document.documentElement.setAttribute(options.activeAttribute, "");
|
|
3489
3851
|
document.dispatchEvent(new CustomEvent(ACTIVATE_EVENT, { detail: options.panelName }));
|
|
@@ -3506,7 +3868,7 @@ window.__ModuleLoader__.load({
|
|
|
3506
3868
|
return () => {
|
|
3507
3869
|
document.removeEventListener("click", onClickSidebarRow, true);
|
|
3508
3870
|
document.removeEventListener(ACTIVATE_EVENT, onOtherActivate);
|
|
3509
|
-
|
|
3871
|
+
unsubscribeBody();
|
|
3510
3872
|
unsubscribe();
|
|
3511
3873
|
unsubscribeLocale?.();
|
|
3512
3874
|
document.documentElement.removeAttribute(options.activeAttribute);
|
|
@@ -3544,6 +3906,21 @@ window.__ModuleLoader__.load({
|
|
|
3544
3906
|
}
|
|
3545
3907
|
//#endregion
|
|
3546
3908
|
//#region src/client/sidebar-entry-core.ts
|
|
3909
|
+
/**
|
|
3910
|
+
* Shared sidebar entry injection core.
|
|
3911
|
+
*
|
|
3912
|
+
* dsh's sidebar shell exposes no slot an external plugin can register into,
|
|
3913
|
+
* so the entry row is injected between the shell's New Session button and the
|
|
3914
|
+
* workspace browser. The injection self-heals: a MutationObserver watches the
|
|
3915
|
+
* sidebar root and re-inserts the row whenever a React re-render displaces it
|
|
3916
|
+
* (re-insertion happens in the same frame, before paint, so no flicker).
|
|
3917
|
+
*
|
|
3918
|
+
* The row is plain DOM (no React tree) so it can never disturb the shell's
|
|
3919
|
+
* reconciliation; the view it toggles is a separate root owned by the caller.
|
|
3920
|
+
*
|
|
3921
|
+
* Packages receive this file as a generated copy via scripts/sync-shared.mjs;
|
|
3922
|
+
* edit the shared source and re-run the sync instead of editing a copy.
|
|
3923
|
+
*/
|
|
3547
3924
|
/** Find the sidebar shell root element, or undefined while not yet mounted. */
|
|
3548
3925
|
function sidebarRoot() {
|
|
3549
3926
|
const column = document.querySelector("[data-pane=\"sidebar\"], [class*=\"sidebarCol\"]");
|
|
@@ -3632,13 +4009,9 @@ window.__ModuleLoader__.load({
|
|
|
3632
4009
|
subtree: true
|
|
3633
4010
|
});
|
|
3634
4011
|
};
|
|
3635
|
-
const
|
|
4012
|
+
const unsubscribeBody = subscribeBodyInvalidations(() => {
|
|
3636
4013
|
tryPlace();
|
|
3637
4014
|
});
|
|
3638
|
-
waitObserver.observe(document.body, {
|
|
3639
|
-
childList: true,
|
|
3640
|
-
subtree: true
|
|
3641
|
-
});
|
|
3642
4015
|
const rootObserver = new MutationObserver(() => {
|
|
3643
4016
|
if (root === void 0 || !root.isConnected) {
|
|
3644
4017
|
placed = false;
|
|
@@ -3658,7 +4031,7 @@ window.__ModuleLoader__.load({
|
|
|
3658
4031
|
})();
|
|
3659
4032
|
tryPlace();
|
|
3660
4033
|
return () => {
|
|
3661
|
-
|
|
4034
|
+
unsubscribeBody();
|
|
3662
4035
|
rootObserver.disconnect();
|
|
3663
4036
|
unsubscribeRefresh?.();
|
|
3664
4037
|
unsubscribeActive?.();
|
|
@@ -4636,7 +5009,7 @@ window.__ModuleLoader__.load({
|
|
|
4636
5009
|
/** The building package's version, when the bundle carries it. */
|
|
4637
5010
|
function bakedVersion() {
|
|
4638
5011
|
try {
|
|
4639
|
-
return "0.3.
|
|
5012
|
+
return "0.3.22";
|
|
4640
5013
|
} catch {
|
|
4641
5014
|
return;
|
|
4642
5015
|
}
|
|
@@ -4719,7 +5092,8 @@ window.__ModuleLoader__.load({
|
|
|
4719
5092
|
"connection",
|
|
4720
5093
|
"settingsScope",
|
|
4721
5094
|
"locale",
|
|
4722
|
-
"remote"
|
|
5095
|
+
"remote",
|
|
5096
|
+
"remote.session"
|
|
4723
5097
|
];
|
|
4724
5098
|
/**
|
|
4725
5099
|
* Mount the task board.
|
|
@@ -4766,7 +5140,7 @@ window.__ModuleLoader__.load({
|
|
|
4766
5140
|
if (uiDisposer !== void 0) return;
|
|
4767
5141
|
const sessions = ctx.get("sessions");
|
|
4768
5142
|
const workspaces = ctx.get("workspaces");
|
|
4769
|
-
ctx.get("remote");
|
|
5143
|
+
const remote = ctx.get("remote");
|
|
4770
5144
|
const controller = new BoardController({
|
|
4771
5145
|
store: new LocalStorageTaskStore(),
|
|
4772
5146
|
transport: new HttpTaskBoardHostTransport(),
|
|
@@ -4788,29 +5162,55 @@ window.__ModuleLoader__.load({
|
|
|
4788
5162
|
disposers.push(workspaces.list.subscribe(pushWorkspaceOptions));
|
|
4789
5163
|
const pushModelOptions = async () => {
|
|
4790
5164
|
try {
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
const
|
|
4803
|
-
|
|
4804
|
-
const qualifiedId = g.provider ? `${g.provider}/${m.id}` : m.id;
|
|
5165
|
+
let models = [];
|
|
5166
|
+
let sessionRemote;
|
|
5167
|
+
try {
|
|
5168
|
+
sessionRemote = remote.session;
|
|
5169
|
+
} catch {
|
|
5170
|
+
sessionRemote = void 0;
|
|
5171
|
+
}
|
|
5172
|
+
if (typeof sessionRemote?.modelCatalog === "function") {
|
|
5173
|
+
const res = await sessionRemote.modelCatalog();
|
|
5174
|
+
if (res.ok && Array.isArray(res.value?.groups)) for (const g of res.value.groups) {
|
|
5175
|
+
const provider = g.id ?? g.provider;
|
|
5176
|
+
for (const m of g.models ?? []) {
|
|
5177
|
+
const qualifiedId = provider ? `${provider}/${m.id}` : m.id;
|
|
4805
5178
|
models.push({
|
|
4806
5179
|
id: qualifiedId,
|
|
4807
5180
|
name: m.name ?? m.id,
|
|
4808
|
-
provider
|
|
5181
|
+
provider
|
|
4809
5182
|
});
|
|
4810
5183
|
}
|
|
4811
5184
|
}
|
|
4812
|
-
if (models.length > 0) controller.setExecutionOptions({ models });
|
|
4813
5185
|
}
|
|
5186
|
+
if (models.length === 0) {
|
|
5187
|
+
const conn = ctx.get("connection");
|
|
5188
|
+
if (conn?.api) {
|
|
5189
|
+
if (typeof conn.api.llm?.discoverModels === "function") {
|
|
5190
|
+
const list = (await conn.api.llm.discoverModels())?.result?.value?.models;
|
|
5191
|
+
if (Array.isArray(list)) models = list.map((m) => ({
|
|
5192
|
+
id: m.id,
|
|
5193
|
+
name: m.name
|
|
5194
|
+
}));
|
|
5195
|
+
}
|
|
5196
|
+
const catalogFn = typeof conn.api.session?.modelCatalog === "function" ? conn.api.session.modelCatalog : typeof conn.api.sessions?.modelCatalog === "function" ? conn.api.sessions.modelCatalog : void 0;
|
|
5197
|
+
if (models.length === 0 && catalogFn !== void 0) {
|
|
5198
|
+
const groups = (await catalogFn())?.result?.value?.groups;
|
|
5199
|
+
if (Array.isArray(groups)) for (const g of groups) {
|
|
5200
|
+
const provider = g.id ?? g.provider;
|
|
5201
|
+
for (const m of g.models ?? []) {
|
|
5202
|
+
const qualifiedId = provider ? `${provider}/${m.id}` : m.id;
|
|
5203
|
+
models.push({
|
|
5204
|
+
id: qualifiedId,
|
|
5205
|
+
name: m.name ?? m.id,
|
|
5206
|
+
provider
|
|
5207
|
+
});
|
|
5208
|
+
}
|
|
5209
|
+
}
|
|
5210
|
+
}
|
|
5211
|
+
}
|
|
5212
|
+
}
|
|
5213
|
+
if (models.length > 0) controller.setExecutionOptions({ models });
|
|
4814
5214
|
} catch (error) {
|
|
4815
5215
|
console.error("[dsh-task-board] model options read failed", error);
|
|
4816
5216
|
}
|