@stephen1620/dsh-tomato-board 0.2.0 → 0.3.1
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.md +13 -4
- package/lib/client.js +181 -70
- package/lib/client.js.map +1 -1
- package/lib/types/client/Tag.d.ts +21 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -39,15 +39,24 @@ npx @deepseek-ai/dsh plugin --profile desktop add .
|
|
|
39
39
|
|
|
40
40
|
### 迭代投入
|
|
41
41
|
|
|
42
|
-
-
|
|
42
|
+
- 顶部栏对齐 Harness 对话页样式;顶部 Tab 切换「事项看板 / 迭代投入」,迭代选择器支持切换迭代并记住上次选择。
|
|
43
43
|
- 左侧切换负责人,展示故事点总数、环形分布图和需求列表。
|
|
44
44
|
- 需求卡片与事项看板共用对话关联逻辑,点击打开已有对话或选择项目创建新对话;独立的 ↗ 按钮跳转番茄。
|
|
45
|
-
-
|
|
45
|
+
- 右侧团队以折叠卡片管理:创建、改名、删除团队,添加或移除成员,成员行以背景比例条展示故事点。
|
|
46
46
|
- 点击排行榜成员可切换左侧负责人;第一个团队默认展开并加载,其他团队按展开需要加载。
|
|
47
|
+
- 点击团队成员行可切换左侧负责人;第一个团队默认展开并加载,其他团队按展开需要加载。
|
|
47
48
|
- 团队、成员及负责人选择保存在当前浏览器,不同步到番茄或其他设备。
|
|
48
49
|
|
|
49
50
|
统计读取卡片的 `StoryPoint` 字段,仅包含所选迭代中的 `Story`、`EnablerStory` 和 `Task`,包含全部状态。未填写故事点的需求保留在列表,不参与总数和饼图;0 点保留为已估点记录,不占饼图面积。多负责人需求分别计入各负责人。需要调整故事点时,使用外链按钮进入番茄修改,然后刷新统计。
|
|
50
51
|
|
|
52
|
+
## 0.3.1 更新
|
|
53
|
+
|
|
54
|
+
团队成员行选中与悬停改为边框高亮(选中实线、悬停半透明),选中头像实心;SP 背景进度条不透明度提高一倍。
|
|
55
|
+
|
|
56
|
+
## 0.3.0 更新
|
|
57
|
+
|
|
58
|
+
顶部栏对齐 Harness 对话页样式;团队改为折叠卡片并支持创建、改名、删除与成员管理;全站统一胶囊 Tag 组件(仅类型带色);空间筛选改为多选下拉并按当前负责人事项派生;迭代统计严格限定 Story / EnablerStory / Task;需求卡片显示状态与未估点标记。
|
|
59
|
+
|
|
51
60
|
## 0.2.0 更新
|
|
52
61
|
|
|
53
62
|
新增「迭代投入」页面、多个团队管理和个人故事点分布;需求卡片支持打开 Harness 对话及独立跳转番茄;完善顶部栏、看板筛选与状态列排序。
|
|
@@ -78,11 +87,11 @@ command -v gitee
|
|
|
78
87
|
|
|
79
88
|
## 安装
|
|
80
89
|
|
|
81
|
-
当前版本:`0.
|
|
90
|
+
当前版本:`0.3.1`。已安装用户在对应 profile 目录升级:
|
|
82
91
|
|
|
83
92
|
```bash
|
|
84
93
|
cd ~/.dsh/profiles/desktop # Web 用户改为 web
|
|
85
|
-
pnpm add @stephen1620/dsh-tomato-board@0.
|
|
94
|
+
pnpm add @stephen1620/dsh-tomato-board@0.3.1
|
|
86
95
|
```
|
|
87
96
|
|
|
88
97
|
保留已有 `dsh.profile.bundles` 注册项,升级后完全退出并重新打开 Harness。
|
package/lib/client.js
CHANGED
|
@@ -18,13 +18,13 @@ window.__ModuleLoader__.load({
|
|
|
18
18
|
}
|
|
19
19
|
//#endregion
|
|
20
20
|
//#region \0dsh-css:/Users/gengfeng/deepseek-harness/packages/client/tomato-board/src/client/tomato-board.module.css.mjs
|
|
21
|
-
const css$1 = ".Y6kksa_sidebarAction{width:100%;min-height:36px;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;white-space:nowrap;transition:background var(--ds-transition-duration-fast) var(--ds-ease-in-out), border-color var(--ds-transition-duration-fast) var(--ds-ease-in-out);background:0 0;border:0;border-radius:10px;align-items:center;gap:9px;margin:0;padding:0 10px;display:flex}.Y6kksa_sidebarAction:hover{background:var(--dsw-alias-interactive-bg-hover)}.Y6kksa_topbarAction{border:1px solid var(--dsw-alias-border-l2);min-height:28px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-base);cursor:pointer;font:inherit;white-space:nowrap;border-radius:8px;align-items:center;gap:7px;padding:4px 9px;font-size:12px;font-weight:600;display:inline-flex}.Y6kksa_topbarAction:hover{border-color:color-mix(in srgb, var(--tomato-accent,var(--dsw-alias-state-error-primary)) 45%, var(--dsw-alias-border-l2));background:var(--dsw-alias-interactive-bg-hover)}.Y6kksa_topbarAction:focus-visible{outline:2px solid var(--tomato-accent,var(--dsw-alias-state-error-primary));outline-offset:2px}.Y6kksa_topbarAction .Y6kksa_tomatoIcon{border-radius:5px;width:16px;height:16px;font-size:10px}.Y6kksa_tomatoIcon{width:18px;height:18px;color:var(--dsw-alias-label-primary-inverted);background:var(--tomato-accent,var(--dsw-alias-state-error-primary));border-radius:6px;flex:none;place-items:center;font-size:11px;font-weight:750;display:inline-grid}.Y6kksa_transitionTrigger{align-items:center;gap:6px;display:inline-flex}.Y6kksa_transitionCaption{color:var(--dsw-alias-label-secondary);font-size:12px}.Y6kksa_transitionTrigger strong{color:var(--dsw-alias-label-primary);font-size:12px;font-weight:650}.Y6kksa_transitionDivider{background:var(--dsw-alias-border-l2);width:1px;height:14px;margin:0 2px}.Y6kksa_transitionAction{color:var(--tomato-accent,var(--dsw-alias-state-business-primary));font-size:12px;font-weight:650}.Y6kksa_transitionChevron{color:var(--tomato-accent,var(--dsw-alias-state-business-primary));transition:transform var(--ds-transition-duration-fast) var(--ds-ease-in-out)}.Y6kksa_transitionTrigger[aria-expanded=true] .Y6kksa_transitionChevron{transform:rotate(180deg)}.Y6kksa_workbench{--tomato-accent:#d35f45;--tomato-accent-soft:color-mix(in srgb, var(--tomato-accent) 12%, transparent);--tomato-accent-border:color-mix(in srgb, var(--tomato-accent) 48%, var(--dsw-alias-border-l2));min-width:0;height:100%;min-height:0;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-base);font-family:var(--dsw-font-family);flex-direction:column;flex:1;display:flex;position:relative}.Y6kksa_createDialog{width:min(480px,100%)}.Y6kksa_dialogBody{flex-direction:column;gap:12px;display:flex}.Y6kksa_dialogBody>span{color:var(--tomato-accent,var(--dsw-alias-state-error-primary));font-size:12px;font-weight:700}.Y6kksa_dialogBody code{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;font-size:13px}.Y6kksa_workspaceTrigger{justify-content:space-between;width:100%;display:flex}.Y6kksa_header{z-index:20;border-bottom:1px solid #0000;flex:none;padding:12px 28px 0 20px;position:relative}.Y6kksa_header:after{content:\"\";z-index:0;background:var(--dsw-alias-border-l2);pointer-events:none;height:1px;position:absolute;bottom:1px;left:0;right:0}.Y6kksa_titleRow{align-items:center;gap:10px;min-height:32px;display:flex}.Y6kksa_header h1{text-overflow:ellipsis;white-space:nowrap;border-radius:12px;flex:1;min-width:0;margin:0;padding:4px 8px;font-size:14px;font-weight:500;line-height:20px;overflow:hidden}.Y6kksa_pageTabs{z-index:1;gap:36px;margin-top:4px;padding-left:8px;display:flex;position:relative}.Y6kksa_pageTabs button{color:var(--dsw-alias-label-tertiary);cursor:pointer;font:inherit;background:0 0;border:0;padding:0 0 11px;font-size:13px;font-weight:500;line-height:16px;position:relative}.Y6kksa_pageTabs button:after{content:\"\";background:0 0;border-radius:2px;height:2px;position:absolute;bottom:1px;left:0;right:0}.Y6kksa_pageTabs button:hover,.Y6kksa_pageTabs button[aria-current=page]{color:var(--dsw-alias-state-business-primary)}.Y6kksa_pageTabs button[aria-current=page]:after{background:var(--dsw-alias-state-business-primary)}.Y6kksa_pageTabs button:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:3px}.Y6kksa_actions{z-index:1;align-items:center;gap:8px;min-height:32px;display:flex;position:relative}.Y6kksa_actions .Y6kksa_headerIconButton{width:28px;min-width:28px;height:28px;padding:0}.Y6kksa_searchField{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);border-radius:10px;align-items:center;gap:6px;width:220px;min-height:28px;padding:0 8px;display:flex}.Y6kksa_searchField input{min-width:0;color:inherit;font:inherit;background:0 0;border:0;outline:0;flex:1}.Y6kksa_searchField button{border:0;min-height:24px;padding:0 5px}.Y6kksa_filterMenu{position:relative}.Y6kksa_filterMenu summary{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);cursor:pointer;border-radius:10px;place-items:center;width:28px;height:28px;list-style:none;display:grid;position:relative}.Y6kksa_filterMenu summary::-webkit-details-marker{display:none}.Y6kksa_filterMenu summary i{background:var(--tomato-accent,var(--dsw-alias-state-error-primary));border-radius:50%;width:5px;height:5px;position:absolute;top:5px;right:5px}.Y6kksa_filterPopover{z-index:30;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);width:min(760px,100vw - 320px);box-shadow:var(--dsw-shadow-lv3);border-radius:16px;gap:12px;padding:14px;display:grid;position:absolute;top:calc(100% + 8px);right:0}.Y6kksa_assigneeFilter{align-items:flex-start;gap:12px;display:flex}.Y6kksa_assigneeFilter>span{width:36px;color:var(--dsw-alias-label-secondary);padding-top:8px;font-size:13px}.Y6kksa_assigneePicker{min-width:260px;position:relative}.Y6kksa_assigneeFilter .Y6kksa_assigneeTrigger{justify-content:space-between;align-items:center;gap:12px;width:100%;height:34px;padding:0 10px;display:flex}.Y6kksa_assigneeTrigger>span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.Y6kksa_assigneeDropdown{z-index:40;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);width:320px;box-shadow:var(--dsw-shadow-lv3);border-radius:10px;padding:8px;position:absolute;top:calc(100% + 5px);left:0}.Y6kksa_assigneeDropdown>input{border:1px solid var(--dsw-alias-border-l2);width:100%;height:32px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-base);font:inherit;border-radius:7px;outline:0;padding:0 9px}.Y6kksa_assigneeDropdown>input:focus{border-color:var(--tomato-accent,var(--dsw-alias-state-business-primary))}.Y6kksa_assigneeDropdown>[role=listbox]{max-height:260px;margin-top:7px;overflow:auto}.Y6kksa_assigneeDropdown [role=option]{width:100%;min-height:38px;color:var(--dsw-alias-label-primary);text-align:left;cursor:pointer;background:0 0;border:0;border-radius:7px;flex-direction:column;justify-content:center;align-items:flex-start;gap:2px;padding:6px 9px;display:flex}.Y6kksa_assigneeDropdown [role=option]:hover,.Y6kksa_assigneeDropdown [role=option][aria-selected=true]{background:var(--dsw-alias-interactive-bg-hover)}.Y6kksa_assigneeDropdown strong{font-size:12px;font-weight:550}.Y6kksa_assigneeDropdown small{color:var(--dsw-alias-label-secondary);font-size:10px}.Y6kksa_assigneeDropdown p{color:var(--dsw-alias-label-secondary);text-align:center;margin:0;padding:18px 8px;font-size:11px}.Y6kksa_filterRow{align-items:flex-start;gap:12px;display:flex}.Y6kksa_filterRow>span{width:36px;color:var(--dsw-alias-label-secondary);padding-top:7px;font-size:13px}.Y6kksa_filterRow>div{flex-wrap:wrap;flex:1;gap:7px;display:flex}.Y6kksa_filterRow button{min-height:30px;color:var(--dsw-alias-label-secondary);padding:3px 11px}.Y6kksa_filterRow .Y6kksa_selectedFilter{border-color:var(--tomato-accent,var(--dsw-alias-state-business-primary));color:var(--tomato-accent,var(--dsw-alias-state-business-primary));background:color-mix(in srgb, var(--tomato-accent,var(--dsw-alias-state-business-primary)) 10%, transparent)}.Y6kksa_filterRow .Y6kksa_typeFilter{border-color:color-mix(in srgb, var(--type-tone) 30%, var(--dsw-alias-border-l2));color:var(--type-tone);background:color-mix(in srgb, var(--type-tone) 7%, transparent);align-items:center;gap:6px;display:inline-flex}.Y6kksa_filterRow .Y6kksa_typeFilter i{background:var(--type-tone);width:7px;height:7px;box-shadow:0 0 0 2px color-mix(in srgb, var(--type-tone) 14%, transparent);border-radius:2px}.Y6kksa_filterRow .Y6kksa_typeFilter.Y6kksa_selectedFilter{border-color:color-mix(in srgb, var(--type-tone) 58%, var(--dsw-alias-border-l2));color:var(--type-tone);background:color-mix(in srgb, var(--type-tone) 16%, transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--type-tone) 10%, transparent)}.Y6kksa_filterRow .Y6kksa_typeFilter[aria-pressed=false]{opacity:.48;filter:saturate(.55)}.Y6kksa_error{color:var(--tomato-accent,var(--dsw-alias-state-error-primary));background:var(--dsw-alias-state-error-secondary);border-radius:12px;margin:16px 24px 0;padding:12px 14px}.Y6kksa_notice{color:var(--dsw-alias-label-secondary);margin:0;padding:8px 20px;font-size:11px}.Y6kksa_board{z-index:1;flex:1;align-items:flex-start;gap:12px;padding:8px 12px;display:flex;position:relative;overflow:auto}.Y6kksa_lane{border:1px solid var(--dsw-alias-border-l2);background:color-mix(in srgb, var(--dsw-alias-bg-module-platform) 86%, transparent);width:300px;min-width:300px;max-height:100%;transition:transform .16s var(--ds-ease-in-out), opacity .16s var(--ds-ease-in-out), box-shadow .16s var(--ds-ease-in-out);border-radius:16px;flex-direction:column;display:flex}.Y6kksa_laneDragging{opacity:.5;transform:scale(.985)}.Y6kksa_laneDropBefore{box-shadow:-4px 0 0 var(--tomato-accent,var(--dsw-alias-state-business-primary));transform:translate(8px)}.Y6kksa_laneDropAfter{box-shadow:4px 0 0 var(--tomato-accent,var(--dsw-alias-state-business-primary));transform:translate(-8px)}.Y6kksa_laneHeader{cursor:grab;user-select:none;justify-content:space-between;align-items:center;padding:12px 14px 10px;display:flex}.Y6kksa_laneHeader:active{cursor:grabbing}@media (prefers-reduced-motion:reduce){.Y6kksa_lane{transition:none}}.Y6kksa_laneHeader h2{margin:0;font-size:14px}.Y6kksa_laneHeader span{text-align:center;min-width:22px;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-overlay);border-radius:999px;padding:2px 6px;font-size:12px}.Y6kksa_cards{padding:0 8px 8px;overflow-y:auto}.Y6kksa_card{border:1px solid var(--dsw-alias-border-l2);min-width:0;max-width:100%;color:inherit;background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 96%, transparent);box-shadow:var(--dsw-shadow-lv1);text-align:left;transition:background var(--ds-transition-duration-fast) var(--ds-ease-in-out), border-color var(--ds-transition-duration-fast) var(--ds-ease-in-out), box-shadow var(--ds-transition-duration-fast) var(--ds-ease-in-out);cursor:pointer;border-radius:14px;flex-direction:column;gap:7px;margin-top:8px;padding:12px;text-decoration:none;display:flex;overflow:hidden}.Y6kksa_card:hover{border-color:var(--dsw-alias-border-l3);background:var(--dsw-alias-button-floating-hover);box-shadow:var(--dsw-shadow-lv2)}.Y6kksa_cardMuted{opacity:.46;filter:saturate(.2);box-shadow:none}.Y6kksa_cardMuted:hover{opacity:.62}.Y6kksa_card:focus-visible{outline:2px solid var(--tomato-accent,var(--dsw-alias-state-business-primary));outline-offset:2px}.Y6kksa_card strong,.Y6kksa_key,.Y6kksa_meta{overflow-wrap:anywhere;word-break:normal;min-width:0}.Y6kksa_cardTopline{justify-content:space-between;align-items:center;gap:8px;min-width:0;display:flex}.Y6kksa_cardButtons{align-items:center;gap:2px;display:inline-flex}.Y6kksa_muteButton,.Y6kksa_tomatoLink{border-radius:8px;flex:none;place-items:center;width:28px;min-width:28px;height:28px;min-height:28px;padding:0;line-height:1;display:inline-grid}.Y6kksa_muteButton{color:var(--dsw-alias-label-tertiary);font-size:9px}.Y6kksa_muteButton[aria-pressed=true]{color:var(--dsw-alias-label-primary)}.Y6kksa_card strong{font-size:14px;font-weight:600;line-height:1.45}.Y6kksa_key{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:650}.Y6kksa_cardMeta{flex-wrap:wrap;align-items:center;gap:5px;min-width:0;display:flex}.Y6kksa_typeTag,.Y6kksa_metaTag{overflow-wrap:anywhere;white-space:normal;border:1px solid #0000;border-radius:6px;flex:none;max-width:100%;padding:3px 7px;font-size:10px;line-height:1.3}.Y6kksa_typeTag{border-color:color-mix(in srgb, var(--type-tone) 38%, transparent);max-width:112px;color:var(--type-tone);background:color-mix(in srgb, var(--type-tone) 13%, transparent);letter-spacing:.02em;order:-1;font-weight:750}.Y6kksa_metaTag,.Y6kksa_workspaceTag,.Y6kksa_priorityTag,.Y6kksa_priorityTag[data-priority],.Y6kksa_creatorTag{color:var(--dsw-alias-label-secondary);border-color:color-mix(in srgb, var(--dsw-alias-border-l2) 82%, transparent);background:color-mix(in srgb, var(--dsw-alias-bg-overlay) 46%, transparent);font-weight:550}.Y6kksa_creatorTag:before{content:\"创建 \";opacity:.65;font-weight:500}.Y6kksa_empty{color:var(--dsw-alias-label-tertiary);margin:auto}@media (width<=820px){.Y6kksa_titleRow{flex-wrap:wrap}.Y6kksa_actions{flex-wrap:wrap;justify-content:flex-end}.Y6kksa_searchField{width:170px}}";
|
|
22
|
-
const tagId$
|
|
23
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$
|
|
21
|
+
const css$2 = ".Y6kksa_sidebarAction{width:100%;min-height:36px;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;white-space:nowrap;transition:background var(--ds-transition-duration-fast) var(--ds-ease-in-out), border-color var(--ds-transition-duration-fast) var(--ds-ease-in-out);background:0 0;border:0;border-radius:10px;align-items:center;gap:9px;margin:0;padding:0 10px;display:flex}.Y6kksa_sidebarAction:hover{background:var(--dsw-alias-interactive-bg-hover)}.Y6kksa_topbarAction{border:1px solid var(--dsw-alias-border-l2);min-height:28px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-base);cursor:pointer;font:inherit;white-space:nowrap;border-radius:8px;align-items:center;gap:7px;padding:4px 9px;font-size:12px;font-weight:600;display:inline-flex}.Y6kksa_topbarAction:hover{border-color:color-mix(in srgb, var(--tomato-accent,var(--dsw-alias-state-error-primary)) 45%, var(--dsw-alias-border-l2));background:var(--dsw-alias-interactive-bg-hover)}.Y6kksa_topbarAction:focus-visible{outline:2px solid var(--tomato-accent,var(--dsw-alias-state-error-primary));outline-offset:2px}.Y6kksa_topbarAction .Y6kksa_tomatoIcon{border-radius:5px;width:16px;height:16px;font-size:10px}.Y6kksa_tomatoIcon{width:18px;height:18px;color:var(--dsw-alias-label-primary-inverted);background:var(--tomato-accent,var(--dsw-alias-state-error-primary));border-radius:6px;flex:none;place-items:center;font-size:11px;font-weight:750;display:inline-grid}.Y6kksa_transitionTrigger{align-items:center;gap:6px;display:inline-flex}.Y6kksa_transitionCaption{color:var(--dsw-alias-label-secondary);font-size:12px}.Y6kksa_transitionTrigger strong{color:var(--dsw-alias-label-primary);font-size:12px;font-weight:650}.Y6kksa_transitionDivider{background:var(--dsw-alias-border-l2);width:1px;height:14px;margin:0 2px}.Y6kksa_transitionAction{color:var(--tomato-accent,var(--dsw-alias-state-business-primary));font-size:12px;font-weight:650}.Y6kksa_transitionChevron{color:var(--tomato-accent,var(--dsw-alias-state-business-primary));transition:transform var(--ds-transition-duration-fast) var(--ds-ease-in-out)}.Y6kksa_transitionTrigger[aria-expanded=true] .Y6kksa_transitionChevron{transform:rotate(180deg)}.Y6kksa_workbench{--tomato-accent:var(--dsw-alias-state-business-primary,#3478c8);--tomato-accent-soft:color-mix(in srgb, var(--tomato-accent) 12%, transparent);--tomato-accent-border:color-mix(in srgb, var(--tomato-accent) 48%, var(--dsw-alias-border-l2));min-width:0;height:100%;min-height:0;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-base);font-family:var(--dsw-font-family);flex-direction:column;flex:1;display:flex;position:relative}.Y6kksa_createDialog{width:min(480px,100%)}.Y6kksa_dialogBody{flex-direction:column;gap:12px;display:flex}.Y6kksa_dialogBody>span{color:var(--tomato-accent,var(--dsw-alias-state-error-primary));font-size:12px;font-weight:700}.Y6kksa_dialogBody code{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;font-size:13px}.Y6kksa_workspaceTrigger{justify-content:space-between;width:100%;display:flex}.Y6kksa_header{z-index:20;border-bottom:1px solid #0000;flex:none;padding:12px 28px 0 20px;position:relative}.Y6kksa_header:after{content:\"\";z-index:0;background:var(--dsw-alias-border-l2);pointer-events:none;height:1px;position:absolute;bottom:1px;left:0;right:0}.Y6kksa_titleRow{align-items:center;gap:10px;min-height:32px;display:flex}.Y6kksa_header h1{text-overflow:ellipsis;white-space:nowrap;border-radius:12px;flex:1;min-width:0;margin:0;padding:4px 8px;font-size:14px;font-weight:500;line-height:20px;overflow:hidden}.Y6kksa_pageTabs{z-index:1;gap:36px;margin-top:4px;padding-left:8px;display:flex;position:relative}.Y6kksa_pageTabs button{color:var(--dsw-alias-label-tertiary);cursor:pointer;font:inherit;background:0 0;border:0;padding:0 0 11px;font-size:13px;font-weight:500;line-height:16px;position:relative}.Y6kksa_pageTabs button:after{content:\"\";background:0 0;border-radius:2px;height:2px;position:absolute;bottom:1px;left:0;right:0}.Y6kksa_pageTabs button:hover,.Y6kksa_pageTabs button[aria-current=page]{color:var(--dsw-alias-state-business-primary)}.Y6kksa_pageTabs button[aria-current=page]:after{background:var(--dsw-alias-state-business-primary)}.Y6kksa_pageTabs button:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:3px}.Y6kksa_actions{z-index:1;align-items:center;gap:8px;min-height:32px;display:flex;position:relative}.Y6kksa_actions .Y6kksa_headerIconButton{width:28px;min-width:28px;height:28px;padding:0}.Y6kksa_searchField{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);border-radius:10px;align-items:center;gap:6px;width:220px;min-height:28px;padding:0 8px;display:flex}.Y6kksa_searchField input{min-width:0;color:inherit;font:inherit;background:0 0;border:0;outline:0;flex:1}.Y6kksa_searchField button{border:0;min-height:24px;padding:0 5px}.Y6kksa_filterMenu{position:relative}.Y6kksa_filterMenu summary{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);cursor:pointer;border-radius:10px;place-items:center;width:28px;height:28px;list-style:none;display:grid;position:relative}.Y6kksa_filterMenu summary::-webkit-details-marker{display:none}.Y6kksa_filterMenu summary i{background:var(--tomato-accent,var(--dsw-alias-state-error-primary));border-radius:50%;width:5px;height:5px;position:absolute;top:5px;right:5px}.Y6kksa_filterPopover{z-index:30;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);width:min(500px,100vw - 320px);box-shadow:var(--dsw-shadow-lv3);border-radius:16px;gap:10px;padding:12px;display:grid;position:absolute;top:calc(100% + 8px);right:0}.Y6kksa_assigneeFilter{align-items:flex-start;gap:12px;display:flex}.Y6kksa_assigneeFilter>span{width:48px;color:var(--dsw-alias-label-secondary);white-space:nowrap;flex:0 0 48px;padding-top:8px;font-size:13px}.Y6kksa_assigneePicker{min-width:260px;position:relative}.Y6kksa_assigneeFilter .Y6kksa_assigneeTrigger{border:1px solid color-mix(in srgb, var(--dsw-alias-border-l2) 82%, transparent);width:100%;height:30px;color:var(--dsw-alias-label-secondary);background:color-mix(in srgb, var(--dsw-alias-bg-overlay) 46%, transparent);border-radius:999px;justify-content:space-between;align-items:center;gap:12px;padding:0 8px 0 12px;font-size:12px;display:flex}.Y6kksa_assigneeFilter .Y6kksa_assigneeTrigger:hover{background:var(--dsw-alias-interactive-bg-hover)}.Y6kksa_assigneeTrigger>span{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.Y6kksa_assigneeDropdown{z-index:40;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);width:320px;box-shadow:var(--dsw-shadow-lv3);border-radius:10px;padding:8px;position:absolute;top:calc(100% + 5px);left:0}.Y6kksa_assigneeDropdown>input{border:1px solid var(--dsw-alias-border-l2);width:100%;height:32px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-base);font:inherit;border-radius:7px;outline:0;padding:0 9px}.Y6kksa_assigneeDropdown>input:focus{border-color:var(--tomato-accent,var(--dsw-alias-state-business-primary))}.Y6kksa_assigneeDropdown>[role=listbox]{max-height:260px;margin-top:7px;overflow:auto}.Y6kksa_assigneeDropdown [role=option]{width:100%;min-height:38px;color:var(--dsw-alias-label-primary);text-align:left;cursor:pointer;background:0 0;border:0;border-radius:7px;flex-direction:column;justify-content:center;align-items:flex-start;gap:2px;padding:6px 9px;display:flex}.Y6kksa_assigneeDropdown [role=option]:hover,.Y6kksa_assigneeDropdown [role=option][aria-selected=true]{background:var(--dsw-alias-interactive-bg-hover)}.Y6kksa_assigneeDropdown strong{font-size:12px;font-weight:550}.Y6kksa_assigneeDropdown small{color:var(--dsw-alias-label-secondary);font-size:10px}.Y6kksa_assigneeDropdown p{color:var(--dsw-alias-label-secondary);text-align:center;margin:0;padding:18px 8px;font-size:11px}.Y6kksa_filterRow{align-items:flex-start;gap:12px;display:flex}.Y6kksa_filterRow>span{width:48px;color:var(--dsw-alias-label-secondary);white-space:nowrap;flex:0 0 48px;padding-top:7px;font-size:13px}.Y6kksa_filterRow>div{flex-wrap:wrap;flex:1;gap:7px;display:flex}.Y6kksa_workspaceSelect{flex:1;min-width:0;display:block;position:relative}.Y6kksa_workspaceSelect>span{flex:1}.Y6kksa_filterRow .Y6kksa_workspaceTrigger{border:1px solid color-mix(in srgb, var(--dsw-alias-border-l2) 82%, transparent);width:100%;min-height:30px;color:var(--dsw-alias-label-secondary);background:color-mix(in srgb, var(--dsw-alias-bg-overlay) 46%, transparent);font:inherit;text-align:left;cursor:pointer;border-radius:999px;justify-content:space-between;align-items:center;gap:10px;padding:3px 8px 3px 12px;font-size:12px;display:flex}.Y6kksa_filterRow .Y6kksa_workspaceTrigger:hover{background:var(--dsw-alias-interactive-bg-hover)}.Y6kksa_filterRow .Y6kksa_workspaceTrigger>span{min-width:0;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.Y6kksa_workspaceChevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s;display:inline-flex}.Y6kksa_workspaceTrigger[aria-expanded=true] .Y6kksa_workspaceChevron{color:var(--tomato-accent,var(--dsw-alias-state-business-primary));transform:rotate(180deg)}.Y6kksa_error{color:var(--tomato-accent,var(--dsw-alias-state-error-primary));background:var(--dsw-alias-state-error-secondary);border-radius:12px;margin:16px 24px 0;padding:12px 14px}.Y6kksa_notice{color:var(--dsw-alias-label-secondary);margin:0;padding:8px 20px;font-size:11px}.Y6kksa_board{z-index:1;flex:1;align-items:flex-start;gap:12px;padding:8px 12px;display:flex;position:relative;overflow:auto}.Y6kksa_lane{border:1px solid var(--dsw-alias-border-l2);background:color-mix(in srgb, var(--dsw-alias-bg-module-platform) 86%, transparent);width:300px;min-width:300px;max-height:100%;transition:transform .16s var(--ds-ease-in-out), opacity .16s var(--ds-ease-in-out), box-shadow .16s var(--ds-ease-in-out);border-radius:16px;flex-direction:column;display:flex}.Y6kksa_laneDragging{opacity:.5;transform:scale(.985)}.Y6kksa_laneDropBefore{box-shadow:-4px 0 0 var(--tomato-accent,var(--dsw-alias-state-business-primary));transform:translate(8px)}.Y6kksa_laneDropAfter{box-shadow:4px 0 0 var(--tomato-accent,var(--dsw-alias-state-business-primary));transform:translate(-8px)}.Y6kksa_laneHeader{cursor:grab;user-select:none;justify-content:space-between;align-items:center;padding:12px 14px 10px;display:flex}.Y6kksa_laneHeader:active{cursor:grabbing}@media (prefers-reduced-motion:reduce){.Y6kksa_lane{transition:none}}.Y6kksa_laneHeader h2{margin:0;font-size:14px}.Y6kksa_laneHeader span{text-align:center;min-width:22px;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-overlay);border-radius:999px;padding:2px 6px;font-size:12px}.Y6kksa_cards{padding:0 8px 8px;overflow-y:auto}.Y6kksa_card{border:1px solid var(--dsw-alias-border-l2);min-width:0;max-width:100%;color:inherit;background:color-mix(in srgb, var(--dsw-alias-bg-layer-1) 96%, transparent);box-shadow:var(--dsw-shadow-lv1);text-align:left;transition:background var(--ds-transition-duration-fast) var(--ds-ease-in-out), border-color var(--ds-transition-duration-fast) var(--ds-ease-in-out), box-shadow var(--ds-transition-duration-fast) var(--ds-ease-in-out);cursor:pointer;border-radius:14px;flex-direction:column;gap:7px;margin-top:8px;padding:12px;text-decoration:none;display:flex;overflow:hidden}.Y6kksa_card:hover{border-color:var(--dsw-alias-border-l3);background:var(--dsw-alias-button-floating-hover);box-shadow:var(--dsw-shadow-lv2)}.Y6kksa_cardMuted{opacity:.46;filter:saturate(.2);box-shadow:none}.Y6kksa_cardMuted:hover{opacity:.62}.Y6kksa_card:focus-visible{outline:2px solid var(--tomato-accent,var(--dsw-alias-state-business-primary));outline-offset:2px}.Y6kksa_card strong,.Y6kksa_key,.Y6kksa_meta{overflow-wrap:anywhere;word-break:normal;min-width:0}.Y6kksa_cardTopline{justify-content:space-between;align-items:center;gap:8px;min-width:0;display:flex}.Y6kksa_cardButtons{align-items:center;gap:2px;display:inline-flex}.Y6kksa_muteButton,.Y6kksa_tomatoLink{border-radius:8px;flex:none;place-items:center;width:28px;min-width:28px;height:28px;min-height:28px;padding:0;line-height:1;display:inline-grid}.Y6kksa_muteButton{color:var(--dsw-alias-label-tertiary);font-size:9px}.Y6kksa_muteButton[aria-pressed=true]{color:var(--dsw-alias-label-primary)}.Y6kksa_card strong{font-size:14px;font-weight:600;line-height:1.45}.Y6kksa_key{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:650}.Y6kksa_cardMeta{flex-wrap:wrap;align-items:center;gap:5px;min-width:0;display:flex}.Y6kksa_empty{color:var(--dsw-alias-label-tertiary);margin:auto}@media (width<=820px){.Y6kksa_titleRow{flex-wrap:wrap}.Y6kksa_actions{flex-wrap:wrap;justify-content:flex-end}.Y6kksa_searchField{width:170px}}";
|
|
22
|
+
const tagId$2 = "@stephen1620/dsh-tomato-board/tomato-board.module.css";
|
|
23
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
|
|
24
24
|
const tag = document.createElement("style");
|
|
25
25
|
tag.dataset.plugin = "@stephen1620/dsh-tomato-board";
|
|
26
|
-
tag.dataset.pluginCss = tagId$
|
|
27
|
-
tag.textContent = css$
|
|
26
|
+
tag.dataset.pluginCss = tagId$2;
|
|
27
|
+
tag.textContent = css$2;
|
|
28
28
|
document.head.appendChild(tag);
|
|
29
29
|
}
|
|
30
30
|
var tomato_board_module_css_default = {
|
|
@@ -41,7 +41,6 @@ window.__ModuleLoader__.load({
|
|
|
41
41
|
"cardTopline": "Y6kksa_cardTopline",
|
|
42
42
|
"cards": "Y6kksa_cards",
|
|
43
43
|
"createDialog": "Y6kksa_createDialog",
|
|
44
|
-
"creatorTag": "Y6kksa_creatorTag",
|
|
45
44
|
"dialogBody": "Y6kksa_dialogBody",
|
|
46
45
|
"empty": "Y6kksa_empty",
|
|
47
46
|
"error": "Y6kksa_error",
|
|
@@ -57,13 +56,10 @@ window.__ModuleLoader__.load({
|
|
|
57
56
|
"laneDropBefore": "Y6kksa_laneDropBefore",
|
|
58
57
|
"laneHeader": "Y6kksa_laneHeader",
|
|
59
58
|
"meta": "Y6kksa_meta",
|
|
60
|
-
"metaTag": "Y6kksa_metaTag",
|
|
61
59
|
"muteButton": "Y6kksa_muteButton",
|
|
62
60
|
"notice": "Y6kksa_notice",
|
|
63
61
|
"pageTabs": "Y6kksa_pageTabs",
|
|
64
|
-
"priorityTag": "Y6kksa_priorityTag",
|
|
65
62
|
"searchField": "Y6kksa_searchField",
|
|
66
|
-
"selectedFilter": "Y6kksa_selectedFilter",
|
|
67
63
|
"sidebarAction": "Y6kksa_sidebarAction",
|
|
68
64
|
"titleRow": "Y6kksa_titleRow",
|
|
69
65
|
"tomatoIcon": "Y6kksa_tomatoIcon",
|
|
@@ -74,21 +70,20 @@ window.__ModuleLoader__.load({
|
|
|
74
70
|
"transitionChevron": "Y6kksa_transitionChevron",
|
|
75
71
|
"transitionDivider": "Y6kksa_transitionDivider",
|
|
76
72
|
"transitionTrigger": "Y6kksa_transitionTrigger",
|
|
77
|
-
"typeFilter": "Y6kksa_typeFilter",
|
|
78
|
-
"typeTag": "Y6kksa_typeTag",
|
|
79
73
|
"workbench": "Y6kksa_workbench",
|
|
80
|
-
"
|
|
74
|
+
"workspaceChevron": "Y6kksa_workspaceChevron",
|
|
75
|
+
"workspaceSelect": "Y6kksa_workspaceSelect",
|
|
81
76
|
"workspaceTrigger": "Y6kksa_workspaceTrigger"
|
|
82
77
|
};
|
|
83
78
|
//#endregion
|
|
84
79
|
//#region \0dsh-css:/Users/gengfeng/deepseek-harness/packages/client/tomato-board/src/client/story-points.module.css.mjs
|
|
85
|
-
const css = ".LfvjxG_page{--tomato-accent:var(--dsw-alias-state-business-primary,#3478c8);--tomato-accent-soft:color-mix(in srgb, var(--tomato-accent) 10%, transparent);min-height:0;color:var(--dsw-alias-label-primary,#292d32);flex:1;padding:14px 18px 18px;overflow:auto}.LfvjxG_page *{box-sizing:border-box}.LfvjxG_page button,.LfvjxG_page select,.LfvjxG_page input{font:inherit;color:inherit;border:1px solid var(--dsw-alias-border-l2,#dedfdf);background:var(--dsw-alias-bg-base,white);border-radius:8px;min-width:0;padding:8px 12px}.LfvjxG_page button{cursor:pointer;white-space:nowrap}.LfvjxG_page button:hover{background:var(--dsw-alias-interactive-bg-hover,#f4f4f2)}.LfvjxG_page button:disabled{opacity:.5;cursor:wait}.LfvjxG_page :focus-visible{outline:2px solid var(--tomato-accent);outline-offset:3px}.LfvjxG_page h3,.LfvjxG_page h4,.LfvjxG_page p{margin:0}.LfvjxG_panelHeader,.LfvjxG_listHeading,.LfvjxG_rankLabel{justify-content:space-between;align-items:center;gap:12px;display:flex}.LfvjxG_caption,.LfvjxG_footnote,.LfvjxG_itemText small,.LfvjxG_rankRow small,.LfvjxG_listHeading span{color:var(--dsw-alias-label-secondary,#797c80);font-size:12px;line-height:1.5}.LfvjxG_eyebrow{letter-spacing:1.6px;color:var(--dsw-alias-label-secondary,#797c80);font-size:10px;font-weight:650}.LfvjxG_headerControls{align-items:center;gap:8px;display:flex}.LfvjxG_headerControls label{color:var(--dsw-alias-label-secondary,#797c80);align-items:center;gap:7px;font-size:12px;display:flex}.LfvjxG_headerControls select{border:1px solid var(--dsw-alias-border-l2,#dedfdf);width:min(320px,34vw);min-width:0;height:28px;color:var(--dsw-alias-label-primary,#292d32);background:var(--dsw-alias-bg-base,white);font:inherit;border-radius:9px;padding:0 10px}.LfvjxG_headerIconButton{border-radius:8px;width:28px;min-width:28px;height:28px;min-height:28px;padding:0!important}.LfvjxG_columns{grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);align-items:start;gap:14px;display:grid}.LfvjxG_teamsHeader{border-bottom:1px solid var(--dsw-alias-border-l2,#e4e4df);justify-content:space-between;align-items:center;padding-bottom:12px;display:flex}.LfvjxG_teamsHeader h3{font-size:16px}.LfvjxG_addTeamButton{height:30px;font-weight:600;min-width:0!important;padding:0 10px!important;font-size:12px!important}.LfvjxG_teamEditor{background:var(--dsw-alias-interactive-bg-hover,#f3f3f1);border-radius:9px;align-items:center;gap:7px;margin:9px 0;padding:8px;display:flex}.LfvjxG_teamEditor input{flex:1;min-width:0}.LfvjxG_teamEditor button{padding:6px 8px;font-size:11px}.LfvjxG_teamAccordions{gap:8px;margin-top:10px;display:grid}.LfvjxG_teamAccordion{border:1px solid var(--dsw-alias-border-l2,#e4e4df);border-radius:10px;overflow:visible}.LfvjxG_teamAccordionHeader{align-items:center;gap:2px;min-height:42px;padding:4px 6px;display:flex}.LfvjxG_teamToggle{text-align:left;align-items:center;gap:8px;min-width:0;display:flex;background:0 0!important;border:0!important;padding:6px!important}.LfvjxG_teamToggle strong{text-overflow:ellipsis;min-width:0;font-size:13px;overflow:hidden}.LfvjxG_teamToggle small{color:var(--dsw-alias-label-secondary);font-size:10px}.LfvjxG_renameTeam{width:27px;height:27px;margin-left:-3px;min-width:27px!important;color:var(--dsw-alias-label-secondary)!important;background:0 0!important;border-color:#0000!important;padding:0!important}.LfvjxG_renameTeam:hover{color:var(--tomato-accent)!important}.LfvjxG_chevron{color:var(--dsw-alias-label-tertiary);font-size:18px;line-height:1;transition:transform .16s}.LfvjxG_teamToggle[aria-expanded=true] .LfvjxG_chevron{color:var(--tomato-accent);transform:rotate(90deg)}.LfvjxG_teamRowActions{gap:2px;margin-left:auto;display:flex}.LfvjxG_teamRowActions button{width:27px;min-width:27px;height:27px;color:var(--dsw-alias-label-secondary);background:0 0;border-color:#0000;padding:0}.LfvjxG_teamRowActions button:last-child:hover{color:var(--dsw-alias-state-error-primary,#bd4336)}.LfvjxG_teamBody{border-top:1px solid var(--dsw-alias-border-l2,#e4e4df);padding:10px 12px 12px;position:relative}.LfvjxG_teamBodyToolbar{color:var(--dsw-alias-label-secondary);justify-content:space-between;align-items:center;gap:8px;font-size:11px;display:flex}.LfvjxG_smallAddButton{border-radius:6px!important;padding:4px 7px!important;font-size:10px!important}.LfvjxG_teamBodyEmpty{color:var(--dsw-alias-label-secondary);text-align:center;padding:20px 8px 10px;font-size:11px}.LfvjxG_memberRow{align-items:center;gap:4px;display:flex}.LfvjxG_memberRow .LfvjxG_rankLabel{flex:1;min-width:0}.LfvjxG_rankIndex{font-variant-numeric:tabular-nums;flex:0 0 22px;width:22px;color:var(--dsw-alias-label-tertiary)!important}.LfvjxG_memberAvatar{background:var(--tomato-accent-soft);border-radius:9px;flex:0 0 28px;place-items:center;width:28px;height:28px;font-weight:750;display:inline-grid;color:var(--tomato-accent)!important;font-size:12px!important}.LfvjxG_memberIdentity{z-index:1;flex:1;gap:1px;min-width:0;display:grid;position:relative}.LfvjxG_memberIdentity strong{text-overflow:ellipsis;overflow:hidden}.LfvjxG_memberIdentity small{color:var(--dsw-alias-label-tertiary);font-size:10px;font-weight:400}.LfvjxG_rankFill{z-index:0;border-radius:inherit;background:color-mix(in srgb, var(--tomato-accent) 11%, transparent);pointer-events:none;max-width:100%;position:absolute;inset:0 auto 0 0}.LfvjxG_rankLabel>.LfvjxG_rankIndex,.LfvjxG_rankLabel>.LfvjxG_memberAvatar,.LfvjxG_rankLabel>b{z-index:1;position:relative}.LfvjxG_removeMember{opacity:0;width:25px;height:25px;min-width:25px!important;color:var(--dsw-alias-label-tertiary)!important;background:0 0!important;border-color:#0000!important;padding:0!important}.LfvjxG_memberRow:hover .LfvjxG_removeMember,.LfvjxG_removeMember:focus-visible{opacity:1}.LfvjxG_removeMember:hover{color:var(--dsw-alias-state-error-primary,#bd4336)!important}.LfvjxG_panel{border:1px solid var(--dsw-alias-border-l2,#e4e4df);background:var(--dsw-alias-bg-base,white);border-radius:14px;min-width:0;padding:16px}.LfvjxG_panelHeader{border-bottom:1px solid var(--dsw-alias-border-l2,#e4e4df);padding-bottom:12px}.LfvjxG_panelHeader h3{white-space:nowrap;font-size:16px}.LfvjxG_panelHeader select{max-width:65%;font-size:12px}.LfvjxG_panelHeader button{font-size:12px}.LfvjxG_summary{justify-content:space-between;align-items:center;gap:16px;padding:16px 0;display:flex}.LfvjxG_total{font-variant-numeric:tabular-nums;letter-spacing:-2px;font-size:48px;font-weight:600;line-height:1.15}.LfvjxG_total small{letter-spacing:0;color:var(--dsw-alias-label-secondary,#797c80);font-size:15px}.LfvjxG_pie{background:var(--dsw-alias-border-l2,#e7e7e2);width:136px;height:136px;box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--dsw-alias-border-l2,#ddd) 55%, transparent), 0 14px 36px #00000012;border-radius:50%;flex:0 0 136px;padding:17px;position:relative;transform:rotate(-90deg)}.LfvjxG_pie:after{content:\"\";border:1px solid color-mix(in srgb, var(--tomato-accent) 24%, transparent);border-radius:50%;position:absolute;inset:-6px}.LfvjxG_pie>div{z-index:1;background:var(--dsw-alias-bg-base,white);width:100%;height:100%;box-shadow:inset 0 0 0 1px var(--dsw-alias-border-l2,#e7e7e2);border-radius:50%;flex-direction:column;justify-content:center;align-items:center;display:flex;position:relative;transform:rotate(90deg)}.LfvjxG_pie strong{font-size:28px;line-height:1}.LfvjxG_pie span{letter-spacing:.08em;color:var(--dsw-alias-label-secondary,#797c80);margin-top:5px;font-size:10px}.LfvjxG_listHeading{padding:10px 0}.LfvjxG_listHeading h4{font-size:13px}.LfvjxG_item{border-top:1px solid var(--dsw-alias-border-l2,#e4e4df);align-items:center;gap:10px;padding:10px 12px;display:flex}.LfvjxG_dot{border-radius:3px;flex-shrink:0;width:8px;height:8px}.LfvjxG_itemText{flex:1;min-width:0}.LfvjxG_itemTitle{color:inherit;overflow-wrap:anywhere;font-size:13px;line-height:1.5;text-decoration:none}.LfvjxG_itemTitle:hover{text-decoration:underline}.LfvjxG_itemText small{margin-right:7px;font-size:10px;display:inline-block}.LfvjxG_statusTag{border:1px solid color-mix(in srgb, var(--tomato-accent) 26%, var(--dsw-alias-border-l2));color:var(--tomato-accent);background:var(--tomato-accent-soft);border-radius:999px;align-items:center;padding:2px 6px;font-size:10px;line-height:1.2;display:inline-flex}.LfvjxG_itemPoints{white-space:nowrap;font-variant-numeric:tabular-nums;font-size:12px}.LfvjxG_item button{padding:5px 8px;font-size:11px}.LfvjxG_chips{flex-wrap:wrap;gap:8px;margin:12px 0 8px;display:flex}.LfvjxG_chips>span{background:var(--dsw-alias-interactive-bg-hover,#f2f3f0);border-radius:6px;align-items:center;gap:6px;padding:3px 5px 3px 10px;font-size:12px;display:flex}.LfvjxG_chips button{background:0 0;border:0;padding:1px 5px}.LfvjxG_ranking{gap:3px;margin-top:8px;display:grid}.LfvjxG_rankRow{border-radius:9px}.LfvjxG_rankRow:hover{background:color-mix(in srgb, var(--dsw-alias-interactive-bg-hover,#f1f2ee) 70%, transparent)}.LfvjxG_rankLabel{text-align:left;background:0 0;border:0;border-radius:9px;gap:8px;width:100%;min-height:48px;padding:6px 4px;font-size:13px;position:relative}.LfvjxG_rankLabel:hover{color:var(--tomato-accent);background:0 0!important}.LfvjxG_rankLabel[aria-pressed=true]{color:var(--tomato-accent);background:var(--tomato-accent-soft)!important}.LfvjxG_rankLabel b{font-variant-numeric:tabular-nums;flex:none;font-size:13px}.LfvjxG_track{display:none}.LfvjxG_footnote{border-top:1px solid var(--dsw-alias-border-l2,#e4e4df);padding-top:12px;font-size:11px;margin-top:20px!important}.LfvjxG_empty{text-align:center;color:var(--dsw-alias-label-secondary,#797c80);padding:36px 12px;font-size:13px}.LfvjxG_empty h4{margin-bottom:8px}.LfvjxG_emptyIcon{color:var(--tomato-accent);margin-bottom:12px;font-size:32px;display:block}.LfvjxG_error{color:var(--dsw-alias-state-error-primary,#bd4336);overflow-wrap:anywhere;padding:10px 0;font-size:12px}.LfvjxG_notice{color:var(--dsw-alias-label-secondary,#797c80);padding:8px 0;font-size:12px}.LfvjxG_teamHeader{overflow:visible}.LfvjxG_addPeopleRoot{position:relative}.LfvjxG_addPeople{z-index:30;border:1px solid var(--dsw-alias-border-l2,#ddd);background:var(--dsw-alias-bg-layer-2,white);border-radius:12px;width:min(330px,72vw);padding:10px;position:absolute;top:calc(100% + 7px);right:0;box-shadow:0 16px 46px #0002}.LfvjxG_addPeopleTitle{justify-content:space-between;align-items:center;gap:10px;display:flex;margin:0 0 8px!important}.LfvjxG_addPeopleTitle strong{font-size:12px}.LfvjxG_addPeopleTitle button{justify-content:center;min-width:26px;height:26px;width:26px!important;padding:0!important}.LfvjxG_addPeople input{width:100%}.LfvjxG_addPeople>div:last-child{max-height:210px;margin-top:8px;overflow:auto}.LfvjxG_addPeople>div:last-child>button{text-align:left;border:0;gap:8px;width:100%;display:flex}.LfvjxG_addPeople small{opacity:.6;flex:1}@media (width<=1000px){.LfvjxG_columns{grid-template-columns:1fr}.LfvjxG_page{padding:14px}}@media (width<=620px){.LfvjxG_teamHeader{flex-direction:column;align-items:flex-start}.LfvjxG_teamActions{justify-content:flex-start}.LfvjxG_memberToolbar{flex-direction:column;align-items:stretch}}@media (width<=540px){.LfvjxG_page{padding:10px}.LfvjxG_panel{padding:12px}.LfvjxG_headerControls label>span{display:none}.LfvjxG_headerControls select{width:min(220px,55vw)}.LfvjxG_pie{flex-basis:120px;width:120px;height:120px;padding:16px}.LfvjxG_total{font-size:42px}.LfvjxG_item{gap:7px}}.LfvjxG_item[role=button]{cursor:pointer;border-radius:8px}.LfvjxG_item[role=button]:hover{background:var(--dsw-alias-interactive-bg-hover)}.LfvjxG_item[role=button]:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.LfvjxG_item .LfvjxG_tomatoLink{background:0 0;border:0;flex:none;width:28px;height:28px;padding:0}";
|
|
86
|
-
const tagId = "@stephen1620/dsh-tomato-board/story-points.module.css";
|
|
87
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
80
|
+
const css$1 = ".LfvjxG_page{--tomato-accent:var(--dsw-alias-state-business-primary,#3478c8);--tomato-accent-soft:color-mix(in srgb, var(--tomato-accent) 10%, transparent);min-height:0;color:var(--dsw-alias-label-primary,#292d32);flex:1;padding:14px 18px 18px;overflow:auto}.LfvjxG_page *{box-sizing:border-box}.LfvjxG_page button,.LfvjxG_page select,.LfvjxG_page input{font:inherit;color:inherit;border:1px solid var(--dsw-alias-border-l2,#dedfdf);background:var(--dsw-alias-bg-base,white);border-radius:8px;min-width:0;padding:8px 12px}.LfvjxG_page button{cursor:pointer;white-space:nowrap}.LfvjxG_page button:hover{background:var(--dsw-alias-interactive-bg-hover,#f4f4f2)}.LfvjxG_page button:disabled{opacity:.5;cursor:wait}.LfvjxG_page :focus-visible{outline:2px solid var(--tomato-accent);outline-offset:3px}.LfvjxG_page h3,.LfvjxG_page h4,.LfvjxG_page p{margin:0}.LfvjxG_panelHeader,.LfvjxG_listHeading,.LfvjxG_rankLabel{justify-content:space-between;align-items:center;gap:12px;display:flex}.LfvjxG_caption,.LfvjxG_footnote,.LfvjxG_itemText small,.LfvjxG_rankRow small,.LfvjxG_listHeading span{color:var(--dsw-alias-label-secondary,#797c80);font-size:12px;line-height:1.5}.LfvjxG_eyebrow{letter-spacing:1.6px;color:var(--dsw-alias-label-secondary,#797c80);font-size:10px;font-weight:650}.LfvjxG_headerControls{align-items:center;gap:8px;display:flex}.LfvjxG_headerControls label{color:var(--dsw-alias-label-secondary,#797c80);align-items:center;gap:7px;font-size:12px;display:flex}.LfvjxG_headerControls select{border:1px solid var(--dsw-alias-border-l2,#dedfdf);width:min(320px,34vw);min-width:0;height:28px;color:var(--dsw-alias-label-primary,#292d32);background:var(--dsw-alias-bg-base,white);font:inherit;border-radius:9px;padding:0 10px}.LfvjxG_headerIconButton{border-radius:8px;width:28px;min-width:28px;height:28px;min-height:28px;padding:0!important}.LfvjxG_columns{grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);align-items:start;gap:14px;display:grid}.LfvjxG_teamsHeader{border-bottom:1px solid var(--dsw-alias-border-l2,#e4e4df);justify-content:space-between;align-items:center;padding-bottom:12px;display:flex}.LfvjxG_teamsHeader h3{font-size:16px}.LfvjxG_addTeamButton{height:30px;font-weight:600;min-width:0!important;padding:0 10px!important;font-size:12px!important}.LfvjxG_teamEditor{background:var(--dsw-alias-interactive-bg-hover,#f3f3f1);border-radius:9px;align-items:center;gap:7px;margin:9px 0;padding:8px;display:flex}.LfvjxG_teamEditor input{flex:1;min-width:0}.LfvjxG_teamEditor button{padding:6px 8px;font-size:11px}.LfvjxG_teamAccordions{gap:8px;margin-top:10px;display:grid}.LfvjxG_teamAccordion{border:1px solid var(--dsw-alias-border-l2,#e4e4df);border-radius:10px;overflow:visible}.LfvjxG_teamAccordionHeader{align-items:center;gap:2px;min-height:42px;padding:4px 6px;display:flex}.LfvjxG_teamToggle{text-align:left;align-items:center;gap:8px;min-width:0;display:flex;background:0 0!important;border:0!important;padding:6px!important}.LfvjxG_teamToggle strong{text-overflow:ellipsis;min-width:0;font-size:13px;overflow:hidden}.LfvjxG_teamToggle small{color:var(--dsw-alias-label-secondary);font-size:10px}.LfvjxG_renameTeam{width:27px;height:27px;margin-left:-3px;min-width:27px!important;color:var(--dsw-alias-label-secondary)!important;background:0 0!important;border-color:#0000!important;padding:0!important}.LfvjxG_renameTeam:hover{color:var(--tomato-accent)!important}.LfvjxG_chevron{color:var(--dsw-alias-label-tertiary);font-size:18px;line-height:1;transition:transform .16s}.LfvjxG_teamToggle[aria-expanded=true] .LfvjxG_chevron{color:var(--tomato-accent);transform:rotate(90deg)}.LfvjxG_teamRowActions{gap:2px;margin-left:auto;display:flex}.LfvjxG_teamRowActions button{width:27px;min-width:27px;height:27px;color:var(--dsw-alias-label-secondary);background:0 0;border-color:#0000;padding:0}.LfvjxG_teamRowActions button:last-child:hover{color:var(--dsw-alias-state-error-primary,#bd4336)}.LfvjxG_teamBody{border-top:1px solid var(--dsw-alias-border-l2,#e4e4df);padding:10px 12px 12px;position:relative}.LfvjxG_teamBodyToolbar{color:var(--dsw-alias-label-secondary);justify-content:space-between;align-items:center;gap:8px;font-size:11px;display:flex}.LfvjxG_smallAddButton{border-radius:6px!important;padding:4px 7px!important;font-size:10px!important}.LfvjxG_teamBodyEmpty{color:var(--dsw-alias-label-secondary);text-align:center;padding:20px 8px 10px;font-size:11px}.LfvjxG_memberRow{align-items:center;gap:4px;display:flex}.LfvjxG_memberRow .LfvjxG_rankLabel{flex:1;min-width:0}.LfvjxG_rankIndex{font-variant-numeric:tabular-nums;flex:0 0 22px;width:22px;color:var(--dsw-alias-label-tertiary)!important}.LfvjxG_memberAvatar{background:var(--tomato-accent-soft);border-radius:9px;flex:0 0 28px;place-items:center;width:28px;height:28px;font-weight:750;display:inline-grid;color:var(--tomato-accent)!important;font-size:12px!important}.LfvjxG_memberIdentity{z-index:1;flex:1;gap:1px;min-width:0;display:grid;position:relative}.LfvjxG_memberIdentity strong{text-overflow:ellipsis;overflow:hidden}.LfvjxG_memberIdentity small{color:var(--dsw-alias-label-tertiary);font-size:10px;font-weight:400}.LfvjxG_rankFill{z-index:0;border-radius:inherit;background:color-mix(in srgb, var(--tomato-accent) 22%, transparent);pointer-events:none;max-width:100%;position:absolute;inset:0 auto 0 0}.LfvjxG_rankLabel>.LfvjxG_rankIndex,.LfvjxG_rankLabel>.LfvjxG_memberAvatar,.LfvjxG_rankLabel>b{z-index:1;position:relative}.LfvjxG_removeMember{opacity:0;width:25px;height:25px;min-width:25px!important;color:var(--dsw-alias-label-tertiary)!important;background:0 0!important;border-color:#0000!important;padding:0!important}.LfvjxG_memberRow:hover .LfvjxG_removeMember,.LfvjxG_removeMember:focus-visible{opacity:1}.LfvjxG_removeMember:hover{color:var(--dsw-alias-state-error-primary,#bd4336)!important}.LfvjxG_panel{border:1px solid var(--dsw-alias-border-l2,#e4e4df);background:var(--dsw-alias-bg-base,white);border-radius:14px;min-width:0;padding:16px}.LfvjxG_panelHeader{border-bottom:1px solid var(--dsw-alias-border-l2,#e4e4df);padding-bottom:12px}.LfvjxG_panelHeader h3{white-space:nowrap;font-size:16px}.LfvjxG_panelHeader select{max-width:65%;font-size:12px}.LfvjxG_panelHeader button{font-size:12px}.LfvjxG_summary{justify-content:space-between;align-items:center;gap:16px;padding:16px 0;display:flex}.LfvjxG_total{font-variant-numeric:tabular-nums;letter-spacing:-2px;font-size:48px;font-weight:600;line-height:1.15}.LfvjxG_total small{letter-spacing:0;color:var(--dsw-alias-label-secondary,#797c80);font-size:15px}.LfvjxG_pie{background:var(--dsw-alias-border-l2,#e7e7e2);width:136px;height:136px;box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--dsw-alias-border-l2,#ddd) 55%, transparent), 0 14px 36px #00000012;border-radius:50%;flex:0 0 136px;padding:17px;position:relative;transform:rotate(-90deg)}.LfvjxG_pie:after{content:\"\";border:1px solid color-mix(in srgb, var(--tomato-accent) 24%, transparent);border-radius:50%;position:absolute;inset:-6px}.LfvjxG_pie>div{z-index:1;background:var(--dsw-alias-bg-base,white);width:100%;height:100%;box-shadow:inset 0 0 0 1px var(--dsw-alias-border-l2,#e7e7e2);border-radius:50%;flex-direction:column;justify-content:center;align-items:center;display:flex;position:relative;transform:rotate(90deg)}.LfvjxG_pie strong{font-size:28px;line-height:1}.LfvjxG_pie span{letter-spacing:.08em;color:var(--dsw-alias-label-secondary,#797c80);margin-top:5px;font-size:10px}.LfvjxG_listHeading{padding:10px 0}.LfvjxG_listHeading h4{font-size:13px}.LfvjxG_item{border-top:1px solid var(--dsw-alias-border-l2,#e4e4df);align-items:center;gap:10px;padding:10px 12px;display:flex}.LfvjxG_dot{border-radius:3px;flex-shrink:0;width:8px;height:8px}.LfvjxG_itemText{flex:1;min-width:0}.LfvjxG_itemTitle{color:inherit;overflow-wrap:anywhere;font-size:13px;line-height:1.5;text-decoration:none}.LfvjxG_itemTitle:hover{text-decoration:underline}.LfvjxG_itemText small{margin-right:7px;font-size:10px;display:inline-block}.LfvjxG_itemPoints{white-space:nowrap;font-variant-numeric:tabular-nums;font-size:12px}.LfvjxG_item button{padding:5px 8px;font-size:11px}.LfvjxG_chips{flex-wrap:wrap;gap:8px;margin:12px 0 8px;display:flex}.LfvjxG_chips>span{background:var(--dsw-alias-interactive-bg-hover,#f2f3f0);border-radius:6px;align-items:center;gap:6px;padding:3px 5px 3px 10px;font-size:12px;display:flex}.LfvjxG_chips button{background:0 0;border:0;padding:1px 5px}.LfvjxG_ranking{gap:3px;margin-top:8px;display:grid}.LfvjxG_rankRow{border-radius:9px}.LfvjxG_rankLabel{text-align:left;background:0 0;border:0;border-radius:9px;gap:8px;width:100%;min-height:48px;padding:6px 4px;font-size:13px;position:relative}.LfvjxG_rankLabel:hover{color:var(--tomato-accent);box-shadow:inset 0 0 0 1.5px color-mix(in srgb, var(--tomato-accent) 45%, transparent);background:0 0!important}.LfvjxG_rankLabel[aria-pressed=true]{color:var(--tomato-accent);box-shadow:inset 0 0 0 1.5px var(--tomato-accent);background:0 0!important}.LfvjxG_rankLabel[aria-pressed=true] .LfvjxG_memberAvatar{background:var(--tomato-accent);color:#fff!important}.LfvjxG_rankLabel b{font-variant-numeric:tabular-nums;flex:none;font-size:13px}.LfvjxG_track{display:none}.LfvjxG_footnote{border-top:1px solid var(--dsw-alias-border-l2,#e4e4df);padding-top:12px;font-size:11px;margin-top:20px!important}.LfvjxG_empty{text-align:center;color:var(--dsw-alias-label-secondary,#797c80);padding:36px 12px;font-size:13px}.LfvjxG_empty h4{margin-bottom:8px}.LfvjxG_emptyIcon{color:var(--tomato-accent);margin-bottom:12px;font-size:32px;display:block}.LfvjxG_error{color:var(--dsw-alias-state-error-primary,#bd4336);overflow-wrap:anywhere;padding:10px 0;font-size:12px}.LfvjxG_notice{color:var(--dsw-alias-label-secondary,#797c80);padding:8px 0;font-size:12px}.LfvjxG_teamHeader{overflow:visible}.LfvjxG_addPeopleRoot{position:relative}.LfvjxG_addPeople{z-index:30;border:1px solid var(--dsw-alias-border-l2,#ddd);background:var(--dsw-alias-bg-layer-2,white);border-radius:12px;width:min(330px,72vw);padding:10px;position:absolute;top:calc(100% + 7px);right:0;box-shadow:0 16px 46px #0002}.LfvjxG_addPeopleTitle{justify-content:space-between;align-items:center;gap:10px;display:flex;margin:0 0 8px!important}.LfvjxG_addPeopleTitle strong{font-size:12px}.LfvjxG_addPeopleTitle button{justify-content:center;min-width:26px;height:26px;width:26px!important;padding:0!important}.LfvjxG_addPeople input{width:100%}.LfvjxG_addPeople>div:last-child{max-height:210px;margin-top:8px;overflow:auto}.LfvjxG_addPeople>div:last-child>button{text-align:left;border:0;gap:8px;width:100%;display:flex}.LfvjxG_addPeople small{opacity:.6;flex:1}@media (width<=1000px){.LfvjxG_columns{grid-template-columns:1fr}.LfvjxG_page{padding:14px}}@media (width<=620px){.LfvjxG_teamHeader{flex-direction:column;align-items:flex-start}.LfvjxG_teamActions{justify-content:flex-start}.LfvjxG_memberToolbar{flex-direction:column;align-items:stretch}}@media (width<=540px){.LfvjxG_page{padding:10px}.LfvjxG_panel{padding:12px}.LfvjxG_headerControls label>span{display:none}.LfvjxG_headerControls select{width:min(220px,55vw)}.LfvjxG_pie{flex-basis:120px;width:120px;height:120px;padding:16px}.LfvjxG_total{font-size:42px}.LfvjxG_item{gap:7px}}.LfvjxG_item[role=button]{cursor:pointer;border-radius:8px}.LfvjxG_item[role=button]:hover{background:var(--dsw-alias-interactive-bg-hover)}.LfvjxG_item[role=button]:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.LfvjxG_item .LfvjxG_tomatoLink{background:0 0;border:0;flex:none;width:28px;height:28px;padding:0}";
|
|
81
|
+
const tagId$1 = "@stephen1620/dsh-tomato-board/story-points.module.css";
|
|
82
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
88
83
|
const tag = document.createElement("style");
|
|
89
84
|
tag.dataset.plugin = "@stephen1620/dsh-tomato-board";
|
|
90
|
-
tag.dataset.pluginCss = tagId;
|
|
91
|
-
tag.textContent = css;
|
|
85
|
+
tag.dataset.pluginCss = tagId$1;
|
|
86
|
+
tag.textContent = css$1;
|
|
92
87
|
document.head.appendChild(tag);
|
|
93
88
|
}
|
|
94
89
|
var story_points_module_css_default = {
|
|
@@ -130,7 +125,6 @@ window.__ModuleLoader__.load({
|
|
|
130
125
|
"removeMember": "LfvjxG_removeMember",
|
|
131
126
|
"renameTeam": "LfvjxG_renameTeam",
|
|
132
127
|
"smallAddButton": "LfvjxG_smallAddButton",
|
|
133
|
-
"statusTag": "LfvjxG_statusTag",
|
|
134
128
|
"summary": "LfvjxG_summary",
|
|
135
129
|
"teamAccordion": "LfvjxG_teamAccordion",
|
|
136
130
|
"teamAccordionHeader": "LfvjxG_teamAccordionHeader",
|
|
@@ -149,6 +143,56 @@ window.__ModuleLoader__.load({
|
|
|
149
143
|
"track": "LfvjxG_track"
|
|
150
144
|
};
|
|
151
145
|
//#endregion
|
|
146
|
+
//#region \0dsh-css:/Users/gengfeng/deepseek-harness/packages/client/tomato-board/src/client/tag.module.css.mjs
|
|
147
|
+
const css = ".vN3RbG_tag{--tag-border-color:color-mix(in srgb, var(--dsw-alias-border-l2) 82%, transparent);--tag-text-color:var(--dsw-alias-label-secondary);--tag-bg-color:color-mix(in srgb, var(--dsw-alias-bg-overlay) 46%, transparent);--tag-weight:550;overflow-wrap:anywhere;border:1px solid var(--tag-border-color);max-width:100%;color:var(--tag-text-color);background:var(--tag-bg-color);font-size:10px;font-weight:var(--tag-weight);white-space:normal;border-radius:999px;flex:none;padding:2px 9px;line-height:1.4}.vN3RbG_toned{--tag-border-color:color-mix(in srgb, var(--tag-tone) 38%, transparent);--tag-text-color:var(--tag-tone);--tag-bg-color:color-mix(in srgb, var(--tag-tone) 13%, transparent);--tag-weight:700}.vN3RbG_tag.vN3RbG_toggle{cursor:pointer;min-height:26px;font:inherit;font-size:10px;font-weight:var(--tag-weight);align-items:center;padding:2px 10px;line-height:1.4;display:inline-flex}.vN3RbG_tag.vN3RbG_toggle:hover{background:var(--dsw-alias-interactive-bg-hover)}.vN3RbG_tag.vN3RbG_toned.vN3RbG_toggle:hover{background:color-mix(in srgb, var(--tag-tone) 18%, transparent)}.vN3RbG_tag.vN3RbG_toggle:focus-visible{outline:2px solid var(--tag-tone,var(--dsw-alias-state-business-primary));outline-offset:2px}.vN3RbG_off{opacity:.5;filter:saturate(.55)}";
|
|
148
|
+
const tagId = "@stephen1620/dsh-tomato-board/tag.module.css";
|
|
149
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
150
|
+
const tag = document.createElement("style");
|
|
151
|
+
tag.dataset.plugin = "@stephen1620/dsh-tomato-board";
|
|
152
|
+
tag.dataset.pluginCss = tagId;
|
|
153
|
+
tag.textContent = css;
|
|
154
|
+
document.head.appendChild(tag);
|
|
155
|
+
}
|
|
156
|
+
var tag_module_css_default = {
|
|
157
|
+
"off": "vN3RbG_off",
|
|
158
|
+
"tag": "vN3RbG_tag",
|
|
159
|
+
"toggle": "vN3RbG_toggle",
|
|
160
|
+
"toned": "vN3RbG_toned"
|
|
161
|
+
};
|
|
162
|
+
//#endregion
|
|
163
|
+
//#region src/client/Tag.tsx
|
|
164
|
+
/**
|
|
165
|
+
* The one tag chip used across the workbench — card metadata, filter chips and
|
|
166
|
+
* status labels. Static usage renders a span; interactive usage renders a
|
|
167
|
+
* toggle button. Only callers that pass `tone` get a colored chip (by
|
|
168
|
+
* convention just the item-type tags).
|
|
169
|
+
*/
|
|
170
|
+
function Tag({ children, tone, interactive = false, pressed, title, className, onClick }) {
|
|
171
|
+
const style = tone === void 0 ? void 0 : { "--tag-tone": tone };
|
|
172
|
+
const classes = [
|
|
173
|
+
tag_module_css_default.tag,
|
|
174
|
+
tone === void 0 ? "" : tag_module_css_default.toned,
|
|
175
|
+
interactive ? tag_module_css_default.toggle : "",
|
|
176
|
+
interactive && pressed === false ? tag_module_css_default.off : "",
|
|
177
|
+
className
|
|
178
|
+
].filter(Boolean).join(" ");
|
|
179
|
+
if (interactive) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
180
|
+
type: "button",
|
|
181
|
+
className: classes,
|
|
182
|
+
style,
|
|
183
|
+
title,
|
|
184
|
+
"aria-pressed": pressed,
|
|
185
|
+
onClick,
|
|
186
|
+
children
|
|
187
|
+
});
|
|
188
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
189
|
+
className: classes,
|
|
190
|
+
style,
|
|
191
|
+
title,
|
|
192
|
+
children
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
//#endregion
|
|
152
196
|
//#region src/client/StoryPoints.tsx
|
|
153
197
|
const LEGACY_TEAM_KEY = "taskboard.tomatoStoryTeam.v1";
|
|
154
198
|
const TEAMS_KEY = "taskboard.tomatoStoryTeams.v2";
|
|
@@ -501,10 +545,7 @@ window.__ModuleLoader__.load({
|
|
|
501
545
|
children: item.title
|
|
502
546
|
}),
|
|
503
547
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: item.itemKey }),
|
|
504
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
505
|
-
className: story_points_module_css_default.statusTag,
|
|
506
|
-
children: item.status
|
|
507
|
-
})
|
|
548
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tag, { children: item.status })
|
|
508
549
|
]
|
|
509
550
|
}),
|
|
510
551
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
|
|
@@ -748,6 +789,7 @@ window.__ModuleLoader__.load({
|
|
|
748
789
|
let state = {
|
|
749
790
|
open: false,
|
|
750
791
|
loading: false,
|
|
792
|
+
loaded: false,
|
|
751
793
|
items: [],
|
|
752
794
|
error: null,
|
|
753
795
|
selectedItem: null,
|
|
@@ -882,7 +924,8 @@ window.__ModuleLoader__.load({
|
|
|
882
924
|
if (!response.ok) throw new Error(body.error || `请求失败 (${response.status})`);
|
|
883
925
|
emit({
|
|
884
926
|
items: body.items ?? [],
|
|
885
|
-
truncated: body.truncated === true
|
|
927
|
+
truncated: body.truncated === true,
|
|
928
|
+
loaded: true
|
|
886
929
|
});
|
|
887
930
|
} catch (error) {
|
|
888
931
|
emit({ error: error instanceof Error ? error.message : "番茄事项读取失败" });
|
|
@@ -895,7 +938,9 @@ window.__ModuleLoader__.load({
|
|
|
895
938
|
disposeWorkbench = null;
|
|
896
939
|
emit({
|
|
897
940
|
open: false,
|
|
898
|
-
selectedItem: null
|
|
941
|
+
selectedItem: null,
|
|
942
|
+
loaded: false,
|
|
943
|
+
error: null
|
|
899
944
|
});
|
|
900
945
|
dispose?.();
|
|
901
946
|
}
|
|
@@ -1034,6 +1079,7 @@ window.__ModuleLoader__.load({
|
|
|
1034
1079
|
users: [],
|
|
1035
1080
|
workspaces: []
|
|
1036
1081
|
});
|
|
1082
|
+
const [directoryVersion, setDirectoryVersion] = (0, react.useState)(0);
|
|
1037
1083
|
const [laneOrder, setLaneOrder] = (0, react.useState)(readLaneOrder);
|
|
1038
1084
|
const [draggedLane, setDraggedLane] = (0, react.useState)(null);
|
|
1039
1085
|
const [dropLane, setDropLane] = (0, react.useState)(null);
|
|
@@ -1041,17 +1087,17 @@ window.__ModuleLoader__.load({
|
|
|
1041
1087
|
const previousLanePositions = (0, react.useRef)(/* @__PURE__ */ new Map());
|
|
1042
1088
|
const sessions = (0, react.useSyncExternalStore)((listener) => ctx.sessions.list.subscribe(listener), () => ctx.sessions.list.getSnapshot(), () => ctx.sessions.list.getSnapshot());
|
|
1043
1089
|
(0, react.useEffect)(() => {
|
|
1044
|
-
if (board.open && board.
|
|
1090
|
+
if (board.open && !board.loaded && !board.loading && !board.error) refresh();
|
|
1045
1091
|
}, [
|
|
1046
1092
|
board.error,
|
|
1047
|
-
board.
|
|
1093
|
+
board.loaded,
|
|
1048
1094
|
board.loading,
|
|
1049
1095
|
board.open
|
|
1050
1096
|
]);
|
|
1051
1097
|
(0, react.useEffect)(() => {
|
|
1052
1098
|
if (!board.open) return;
|
|
1053
1099
|
fetch("/api/tomato-board/filters", { headers: { accept: "application/json" } }).then((response) => response.ok ? response.json() : Promise.reject(/* @__PURE__ */ new Error(`HTTP ${response.status}`))).then((value) => setFilterDirectory(value)).catch(() => {});
|
|
1054
|
-
}, [board.open]);
|
|
1100
|
+
}, [board.open, directoryVersion]);
|
|
1055
1101
|
(0, react.useEffect)(() => {
|
|
1056
1102
|
if (!board.open) return;
|
|
1057
1103
|
const closeOnOutsideNavigation = (event) => {
|
|
@@ -1116,7 +1162,7 @@ window.__ModuleLoader__.load({
|
|
|
1116
1162
|
emit({ selectedItem: item });
|
|
1117
1163
|
}
|
|
1118
1164
|
const normalizedSearch = search.trim().toLowerCase();
|
|
1119
|
-
const filteredItems = board.items.filter((item) => !blacklist.types.has(item.itemType) && !blacklist.statuses.has(item.status) && !blacklist.workspaces.has(item.workspaceKey
|
|
1165
|
+
const filteredItems = board.items.filter((item) => !blacklist.types.has(item.itemType) && !blacklist.statuses.has(item.status) && !blacklist.workspaces.has(item.workspaceKey) && !blacklist.workspaces.has(item.workspaceName) && (!normalizedSearch || [
|
|
1120
1166
|
item.itemKey,
|
|
1121
1167
|
item.title,
|
|
1122
1168
|
item.itemType,
|
|
@@ -1129,27 +1175,42 @@ window.__ModuleLoader__.load({
|
|
|
1129
1175
|
].join(" ").toLowerCase().includes(normalizedSearch)));
|
|
1130
1176
|
const typeOptions = [...new Set(board.items.map((item) => item.itemType).filter(Boolean))].sort((left, right) => left.localeCompare(right));
|
|
1131
1177
|
const statusOptions = applyLaneOrder([...new Set([...TOMATO_STATUS_ORDER, ...board.items.map((item) => item.status).filter((status) => !TOMATO_STATUS_ORDER.includes(status))])], laneOrder);
|
|
1132
|
-
const workspaceOptions =
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1178
|
+
const workspaceOptions = (() => {
|
|
1179
|
+
const entries = /* @__PURE__ */ new Map();
|
|
1180
|
+
for (const item of board.items) {
|
|
1181
|
+
const value = item.workspaceKey || item.workspaceName || item.workspace;
|
|
1182
|
+
if (!value) continue;
|
|
1183
|
+
const label = item.workspaceName && item.workspaceKey && item.workspaceName !== item.workspaceKey ? `${item.workspaceName} (${item.workspaceKey})` : value;
|
|
1184
|
+
if (!entries.has(value)) entries.set(value, {
|
|
1185
|
+
value,
|
|
1186
|
+
label
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
return [...entries.values()];
|
|
1190
|
+
})();
|
|
1136
1191
|
const defaultStatuses = [...new Set([...TOMATO_STATUS_ORDER.filter((status) => filteredItems.some((item) => item.status === status)), ...filteredItems.map((item) => item.status).filter((status) => !TOMATO_STATUS_ORDER.includes(status))])];
|
|
1137
1192
|
const statuses = applyLaneOrder(defaultStatuses, laneOrder);
|
|
1138
|
-
const
|
|
1139
|
-
const nextValues = new Set(current[kind]);
|
|
1140
|
-
if (nextValues.has(value)) nextValues.delete(value);
|
|
1141
|
-
else nextValues.add(value);
|
|
1142
|
-
const next = {
|
|
1143
|
-
...current,
|
|
1144
|
-
[kind]: nextValues
|
|
1145
|
-
};
|
|
1193
|
+
const persistBlacklist = (next) => {
|
|
1146
1194
|
window.localStorage.setItem(TOMATO_FILTER_BLACKLIST_KEY, JSON.stringify({
|
|
1147
1195
|
types: [...next.types],
|
|
1148
1196
|
statuses: [...next.statuses],
|
|
1149
1197
|
workspaces: [...next.workspaces]
|
|
1150
1198
|
}));
|
|
1151
1199
|
return next;
|
|
1200
|
+
};
|
|
1201
|
+
const toggleBlacklist = (kind, value) => setBlacklist((current) => {
|
|
1202
|
+
const nextValues = new Set(current[kind]);
|
|
1203
|
+
if (nextValues.has(value)) nextValues.delete(value);
|
|
1204
|
+
else nextValues.add(value);
|
|
1205
|
+
return persistBlacklist({
|
|
1206
|
+
...current,
|
|
1207
|
+
[kind]: nextValues
|
|
1208
|
+
});
|
|
1152
1209
|
});
|
|
1210
|
+
const setWorkspaceFilterAll = (visible) => setBlacklist((current) => persistBlacklist({
|
|
1211
|
+
...current,
|
|
1212
|
+
workspaces: visible ? /* @__PURE__ */ new Set() : new Set(workspaceOptions.map((option) => option.value))
|
|
1213
|
+
}));
|
|
1153
1214
|
const toggleMutedItem = (itemKey) => setMutedItems((current) => {
|
|
1154
1215
|
const next = new Set(current);
|
|
1155
1216
|
if (next.has(itemKey)) next.delete(itemKey);
|
|
@@ -1228,7 +1289,8 @@ window.__ModuleLoader__.load({
|
|
|
1228
1289
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkspaceFilterRow, {
|
|
1229
1290
|
options: workspaceOptions,
|
|
1230
1291
|
hidden: blacklist.workspaces,
|
|
1231
|
-
onToggle: (value) => toggleBlacklist("workspaces", value)
|
|
1292
|
+
onToggle: (value) => toggleBlacklist("workspaces", value),
|
|
1293
|
+
onSetAll: setWorkspaceFilterAll
|
|
1232
1294
|
}),
|
|
1233
1295
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AssigneePicker, {
|
|
1234
1296
|
users: filterDirectory.users,
|
|
@@ -1261,7 +1323,10 @@ window.__ModuleLoader__.load({
|
|
|
1261
1323
|
title: "刷新番茄事项",
|
|
1262
1324
|
"aria-label": "刷新番茄事项",
|
|
1263
1325
|
disabled: board.loading,
|
|
1264
|
-
onClick: () =>
|
|
1326
|
+
onClick: () => {
|
|
1327
|
+
refresh(selectedAssignee);
|
|
1328
|
+
setDirectoryVersion((value) => value + 1);
|
|
1329
|
+
}
|
|
1265
1330
|
})
|
|
1266
1331
|
] }),
|
|
1267
1332
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
@@ -1410,26 +1475,21 @@ window.__ModuleLoader__.load({
|
|
|
1410
1475
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1411
1476
|
className: tomato_board_module_css_default.cardMeta,
|
|
1412
1477
|
children: [
|
|
1413
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
1414
|
-
|
|
1415
|
-
style: typeStyle(item.itemType),
|
|
1478
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tag, {
|
|
1479
|
+
tone: typeTone(item.itemType),
|
|
1416
1480
|
children: item.itemType
|
|
1417
1481
|
}),
|
|
1418
|
-
(item.workspaceName || item.workspaceKey) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
1419
|
-
className: `${tomato_board_module_css_default.metaTag} ${tomato_board_module_css_default.workspaceTag}`,
|
|
1482
|
+
(item.workspaceName || item.workspaceKey) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tag, {
|
|
1420
1483
|
title: "空间",
|
|
1421
1484
|
children: item.workspaceName && item.workspaceKey && item.workspaceName !== item.workspaceKey ? `${item.workspaceName} (${item.workspaceKey})` : item.workspaceKey || item.workspaceName
|
|
1422
1485
|
}),
|
|
1423
|
-
item.priority && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
1424
|
-
className: `${tomato_board_module_css_default.metaTag} ${tomato_board_module_css_default.priorityTag}`,
|
|
1425
|
-
"data-priority": priorityLabel(item.priority),
|
|
1486
|
+
item.priority && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tag, {
|
|
1426
1487
|
title: "优先级",
|
|
1427
1488
|
children: priorityLabel(item.priority)
|
|
1428
1489
|
}),
|
|
1429
|
-
item.creator && /* @__PURE__ */ (0, react_jsx_runtime.
|
|
1430
|
-
className: `${tomato_board_module_css_default.metaTag} ${tomato_board_module_css_default.creatorTag}`,
|
|
1490
|
+
item.creator && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Tag, {
|
|
1431
1491
|
title: "创建人",
|
|
1432
|
-
children: item.creator
|
|
1492
|
+
children: ["创建 ", item.creator]
|
|
1433
1493
|
})
|
|
1434
1494
|
]
|
|
1435
1495
|
})
|
|
@@ -1482,32 +1542,83 @@ window.__ModuleLoader__.load({
|
|
|
1482
1542
|
];
|
|
1483
1543
|
return palette[[...type].reduce((hash, char) => hash + char.charCodeAt(0), 0) % palette.length];
|
|
1484
1544
|
}
|
|
1485
|
-
function typeStyle(type) {
|
|
1486
|
-
return { "--type-tone": typeTone(type) };
|
|
1487
|
-
}
|
|
1488
1545
|
function FilterRow({ label, options, hidden, onToggle }) {
|
|
1489
1546
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1490
1547
|
className: tomato_board_module_css_default.filterRow,
|
|
1491
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: options.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
"aria-pressed": !hidden.has(option),
|
|
1548
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: options.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tag, {
|
|
1549
|
+
interactive: true,
|
|
1550
|
+
pressed: !hidden.has(option),
|
|
1551
|
+
tone: label === "类型" ? typeTone(option) : void 0,
|
|
1496
1552
|
onClick: () => onToggle(option),
|
|
1497
|
-
children:
|
|
1553
|
+
children: option
|
|
1498
1554
|
}, option)) })]
|
|
1499
1555
|
});
|
|
1500
1556
|
}
|
|
1501
|
-
|
|
1557
|
+
const WORKSPACE_SELECT_ALL = "workspace:select-all";
|
|
1558
|
+
const WORKSPACE_SELECT_NONE = "workspace:select-none";
|
|
1559
|
+
/** Multi-select workspace dropdown composed on the shared Menu primitive. */
|
|
1560
|
+
function WorkspaceFilterRow({ options, hidden, onToggle, onSetAll }) {
|
|
1561
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
1562
|
+
const rootRef = (0, react.useRef)(null);
|
|
1563
|
+
const visibleValues = options.filter((option) => !hidden.has(option.value)).map((option) => option.value);
|
|
1564
|
+
const summary = options.length === 0 ? "暂无空间" : hidden.size === 0 ? `全部空间 · ${options.length}` : visibleValues.length === 0 ? "未选择空间" : `已选空间 ${visibleValues.length} / ${options.length}`;
|
|
1565
|
+
(0, react.useEffect)(() => {
|
|
1566
|
+
if (!open) return;
|
|
1567
|
+
const onKey = (event) => {
|
|
1568
|
+
if (event.key === "Escape") {
|
|
1569
|
+
event.stopPropagation();
|
|
1570
|
+
setOpen(false);
|
|
1571
|
+
}
|
|
1572
|
+
};
|
|
1573
|
+
const root = rootRef.current;
|
|
1574
|
+
root?.addEventListener("keydown", onKey, true);
|
|
1575
|
+
return () => root?.removeEventListener("keydown", onKey, true);
|
|
1576
|
+
}, [open]);
|
|
1577
|
+
const items = options.map((option) => ({
|
|
1578
|
+
id: option.value,
|
|
1579
|
+
label: option.label
|
|
1580
|
+
}));
|
|
1581
|
+
const footer = [{
|
|
1582
|
+
id: WORKSPACE_SELECT_ALL,
|
|
1583
|
+
label: "全部显示"
|
|
1584
|
+
}, {
|
|
1585
|
+
id: WORKSPACE_SELECT_NONE,
|
|
1586
|
+
label: "全部隐藏"
|
|
1587
|
+
}];
|
|
1502
1588
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1503
1589
|
className: tomato_board_module_css_default.filterRow,
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1590
|
+
ref: rootRef,
|
|
1591
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "空间" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1592
|
+
className: tomato_board_module_css_default.workspaceSelect,
|
|
1593
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
1594
|
+
open,
|
|
1595
|
+
items,
|
|
1596
|
+
footer,
|
|
1597
|
+
selectedIds: visibleValues,
|
|
1598
|
+
onSelect: (id) => {
|
|
1599
|
+
if (id === WORKSPACE_SELECT_ALL) onSetAll(true);
|
|
1600
|
+
else if (id === WORKSPACE_SELECT_NONE) onSetAll(false);
|
|
1601
|
+
else onToggle(id);
|
|
1602
|
+
},
|
|
1603
|
+
onClose: () => {
|
|
1604
|
+
setOpen(false);
|
|
1605
|
+
},
|
|
1606
|
+
anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1607
|
+
type: "button",
|
|
1608
|
+
className: tomato_board_module_css_default.workspaceTrigger,
|
|
1609
|
+
"aria-expanded": open,
|
|
1610
|
+
title: summary,
|
|
1611
|
+
onClick: () => {
|
|
1612
|
+
setOpen(!open);
|
|
1613
|
+
},
|
|
1614
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: summary }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("i", {
|
|
1615
|
+
className: tomato_board_module_css_default.workspaceChevron,
|
|
1616
|
+
"aria-hidden": true,
|
|
1617
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, {})
|
|
1618
|
+
})]
|
|
1619
|
+
})
|
|
1620
|
+
})
|
|
1621
|
+
})]
|
|
1511
1622
|
});
|
|
1512
1623
|
}
|
|
1513
1624
|
function AssigneePicker({ users, value, onChange }) {
|
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["css","Button","IconRefreshOutline16","css","Modal","Button","Menu","IconRefreshOutline16","IconCloseOutline16","IconChevronDownOutline14"],"sources":["../../../packages/core/session/src/types.ts","../../../packages/client/tomato-board/src/client/StoryPoints.tsx","../../../packages/client/tomato-board/src/client/TomatoBoard.tsx"],"sourcesContent":["import type { Branded } from '@deepseek-ai/dsh-brand'\nimport type {\n AssistantMessage,\n ToolCallId,\n LlmCallConfig,\n LlmCallConfigAdapterDefaults,\n LlmFailure,\n StreamChunk,\n TokenUsage,\n ToolResultMessage,\n ToolSchema,\n UserMessage,\n} from '@deepseek-ai/dsh-llm'\nimport type { JsonValue } from './json.ts'\n\n// The lossless-JSON payload type belongs to this client-safe face too: a wire\n// contract carrying JSON data must not import the root entry, which merges\n// `ctx.sessions` (a Host-only SessionStore) into every consumer's program.\nexport type { JsonValue } from './json.ts'\n\n/** Identifies one session in the store (and its persistence artifacts). */\nexport type SessionId = Branded<'SessionId'>\n\n/**\n * Brand a string as a {@link SessionId}.\n * @param id - the raw session id string.\n * @returns the same string, branded (a compile-time cast — no runtime cost).\n */\nexport function SessionId(id: string): SessionId {\n return id as SessionId\n}\n\n/**\n * The on-disk session format version, stamped into every newly-written {@link SessionHeader}\n * and enforced by every persistence backend on load. The single source of truth for the\n * version — write sites and the load-time check all read it.\n * While the harness is unreleased it is pinned at `0`: no compatibility is\n * implied, incompatible logs are rejected, and no migration is provided.\n *\n * The version is a single monotonic integer with no major/minor split. Whether\n * a bump is needed is decided by what the WRITER emits, never by what a newer\n * reader can accept: bump exactly when an older runtime could no longer handle\n * a new log with full semantic correctness (\"parses without error\" is not\n * correctness — silently skipping content that shapes reconstruction is a\n * wrong read). Only structural changes reach that bar: the header shape, the\n * {@link SessionEvent} envelope, core event semantics, or the surface\n * mechanism (the {@link SurfaceEventType} set and {@link SurfaceOp} variants).\n * Adding an ordinary event type does not bump: the generated known-event guard\n * makes older runtimes refuse logs containing a type they do not understand.\n * When in doubt, bump: a near-identity upgrade step is almost free, a missed\n * bump makes older runtimes read new logs wrong silently. The full mechanism\n * (upgrade-step chain, in-memory view conversion, migrate-on-continue) is\n * recorded in the fail-closed-session-event-vocabulary Agent Note\n * (`.agents/notes/implemented/simplification/2026-08-25-fail-closed-session-event-vocabulary.md`).\n */\nexport const SESSION_FORMAT_VERSION = 0\n\n/**\n * Immutable validated storage metadata, kept outside the conversation event log.\n */\nexport interface SessionHeader {\n /**\n * On-disk format version, stamped from {@link SESSION_FORMAT_VERSION} when the\n * session is created. A persistence backend rejects any other version on load\n * (no migration — see the constant).\n */\n readonly version: number\n /** The session's id (mirrors the {@link Session}'s id). */\n readonly id: SessionId\n /** Non-negative safe-integer Unix epoch milliseconds when the session was created. */\n readonly createdAt: number\n /** Absolute working directory the session was created in (if any). */\n readonly cwd?: string\n /** The session this one was forked from (seed lineage), if any. */\n readonly parentSession?: SessionId\n /**\n * How many leading events were inherited through a seed. Persisting this\n * boundary lets resume and replay distinguish parent history from child work.\n */\n readonly seedLength?: number\n /**\n * Coarse product classification for a session created as a subagent child.\n * This is presentation metadata, not proof that the child is continuable.\n */\n readonly origin?: 'subagent'\n /**\n * Delegation depth: absent (zero) for a top-level session, parent depth + 1\n * for a subagent child. Persisted so a recursion budget survives restart and\n * resume — a runtime-only depth would reset a resumed child to top-level.\n */\n readonly delegationDepth?: number\n /**\n * Id of the agent preset this session's agent was composed from, when the\n * deployment composes per session. Durable because the preset decides the\n * session's tools and prompt: a resume that restored a different composition\n * would replay history the model can no longer act on.\n */\n readonly agentPreset?: string\n}\n\n/**\n * Options for creating a {@link Session} via the store. `seed` replays/forks\n * an existing event log; `meta` carries the caller-supplied storage fields the\n * store folds into a {@link SessionHeader}.\n */\nexport interface CreateSessionOptions {\n /** Initial replay or fork history supplied at construction. */\n readonly seed?: readonly SessionEvent[]\n /**\n * Storage metadata read once before publication. `seedLength` is explicit\n * because a resumed seed contains the full stored log, not only its inherited prefix.\n */\n readonly meta?: {\n readonly cwd?: string\n readonly parentSession?: SessionId\n readonly createdAt?: number\n readonly seedLength?: number\n readonly origin?: 'subagent'\n readonly delegationDepth?: number\n readonly agentPreset?: string\n }\n}\n\n/**\n * Fresh storage values transferred to {@link SessionStore.prepare} without a\n * second serialization copy. Callers retain no mutable aliases.\n */\nexport interface RestoredSessionOptions {\n /** Fresh detached storage events to validate and freeze in place. */\n readonly seed: SessionEvent[]\n /** Fresh detached storage metadata to validate and freeze in place. */\n readonly meta: SessionHeader\n /** Select the persistence ownership-transfer path. */\n readonly seedSource: 'persistence'\n}\n\n/** Inputs accepted while constructing an unpublished Session. */\nexport type PrepareSessionOptions =\n | (CreateSessionOptions & { readonly seedSource?: undefined })\n | RestoredSessionOptions\n\n/** Why an active agent driver was cancelled. */\nexport type AgentCancelCause =\n | { readonly kind: 'user' }\n | { readonly kind: 'parent' }\n | { readonly kind: 'hook'; readonly reason: string }\n | { readonly kind: 'disposed' }\n\n/** Durable cancellation cause, including imports whose original coarse record carried no cause. */\nexport type TurnEndCancelCause = AgentCancelCause | { readonly kind: 'legacy' }\n\n/**\n * Why a turn ended. Merge-extensible sum type.\n */\nexport interface TurnEndReasonMap {\n completed: { kind: 'completed' }\n /** A cancellation request interrupted the live turn. */\n aborted: { kind: 'aborted'; reason: TurnEndCancelCause }\n\n blocked: { kind: 'blocked' }\n /**\n * The turn failed. `error` is always a structured failure: the `LlmError`\n * facts verbatim, or `{ message: errorChain(error), code: 'UNKNOWN' }`\n * flattened from any other error.\n */\n error: { kind: 'error'; error: LlmFailure }\n /** At least one step reached its output-token ceiling, even if a plugin continued the turn. */\n 'max-tokens': { kind: 'max-tokens' }\n /**\n * A persistence backend closed a crash-orphaned turn on reload. The loop never\n * emits this marker, and the events recorded before the crash remain intact.\n */\n interrupted: { kind: 'interrupted' }\n}\n\n/** The union over {@link TurnEndReasonMap} — why a turn ended; plugins extend it by merging variants into the map. */\nexport type TurnEndReason = TurnEndReasonMap[keyof TurnEndReasonMap]\n\n/**\n * Logged request state outside derived history: call config, system prompt, and\n * tools. The latest full `request/header` snapshot reconstructs it; canonical\n * empty optional fields are absent.\n */\nexport interface EpochHeader {\n /** The conversation's call configuration (provider, model, reasoning effort, and sampling scalars). */\n config: LlmCallConfig\n /** Effective config fields materialized from the exact adapter rather than proposed by a caller. */\n adapterDefaults?: LlmCallConfigAdapterDefaults\n /** Rendered system prompt text; absent for a system-less request. */\n system?: string\n /** Assembled tool schemas; absent for a tool-less request. */\n tools?: ToolSchema[]\n}\n\n/** Registration-bound metadata for one resolved model route. */\nexport interface RequestContext {\n /** Registered provider route the metadata belongs to. */\n provider: string\n /** Provider-owned model id the metadata belongs to. */\n model: string\n /** Maximum combined request and response context in tokens, when advertised. */\n contextWindow?: number\n}\n\n/**\n * Why a `request/header` snapshot was appended: `'initial'` — the log's first\n * header (a new conversation); `'resume'` — a loop instance's first request\n * over a log that already has header events (process restart, fork seed);\n * `'change'` — a later request used a different header, with `startsSeries`\n * preserving a coincident series boundary; `'series'` — an unchanged header\n * began an explicitly distinct message series or followed a surface replacement.\n */\nexport type RequestHeaderReason = 'initial' | 'resume' | 'change' | 'series'\n\n/**\n * The merge-extensible, append-only source of truth for an agent interaction.\n * Message history is derived from this log. Every event is lossless JSON and\n * sequence numbers stay contiguous, including raw chunks, so persistence can\n * store the canonical log verbatim.\n */\nexport interface SessionEventMap {\n /**\n * Opens turn `turn` before the loop claims queued input or runs pre-step.\n * Rejection, empty input, cancellation, or failure may close it with no\n * step; otherwise the following identified `user/message` event or batch\n * records the messages entering the step.\n */\n 'turn/start': { turn: number }\n /**\n * Closes turn `turn` with the {@link TurnEndReason} that ended it. A turn\n * with no entered step has no `step/start` or `step/end`. The loop does not await a\n * flush at turn boundaries: `dsh-session-checkpoint-policy` owns the\n * per-request durability checkpoint, and consumers that read storage after\n * `whenIdle()` flush themselves. Success commits the turn; rejection is\n * reported live and does not prevent later work.\n */\n 'turn/end': { turn: number; reason: TurnEndReason }\n /** Opens step `step` of turn `turn` — one model call plus the tool executions it requested. */\n 'step/start': { turn: number; step: number }\n /** Closes step `step` of turn `turn`. */\n 'step/end': { turn: number; step: number }\n /**\n * A user-role message on the model-visible surface: a direct human prompt\n * (the queued message claimed for this turn), a synthetic `agent.inject()`\n * context (file-change notices, subdir AGENTS.md, skill content, cron\n * notifications, …), or an entered goal continuation round. All three\n * project their `content` verbatim; `source` tells them apart.\n */\n 'user/message': UserMessage\n /** Raw stream chunk — token-level replay fidelity. */\n 'assistant/chunk': { turn: number; step: number; chunk: StreamChunk }\n /**\n * Assembled assistant message for one step (derived history uses this).\n * Carries the step's `usage` when the adapter reported token accounting, so\n * the model output and its accounting travel together (there is no separate\n * usage record). `usage` is absent when the adapter reported none. A turn\n * cancelled mid-stream finalizes its delivered text/reasoning prefix as this\n * event with `interrupted: true`; undispatched tool calls are absent. The\n * marker distinguishes that prefix without re-deriving interruption from turn\n * boundaries. An aborted turn with no such event streamed no visible content.\n */\n 'assistant/message': { turn: number; step: number; message: AssistantMessage; usage?: TokenUsage; interrupted?: true }\n /**\n * The model requested one tool invocation: `name` with the raw `arguments`\n * JSON string exactly as the model produced it (unparsed). `callId` pairs the\n * call with its `tool/result`.\n */\n 'tool/call': { turn: number; step: number; callId: ToolCallId; name: string; arguments: string }\n /**\n * A completed tool call's model-facing result, optional internal failure\n * identity, and optional tool-private `meta` presentation payload. `meta` is\n * opaque to the core (the producing tool owns its shape and reads it back in\n * `presentResult`) but MUST be JSON-serializable: `Session.append`\n * runtime-validates all event data with `isJsonValue`, so a non-serializable\n * `meta` is rejected at the source, and the durable log reproduces the\n * identical card on replay. Absent\n * unless the tool attaches one (e.g. `dsh-tool-fs` carries its result-time\n * contextual diff here).\n */\n 'tool/result': {\n turn: number\n step: number\n message: ToolResultMessage\n error?: { name: string; code: string }\n meta?: JsonValue\n }\n /**\n * Full header for the next request, appended inside its step before dispatch.\n * It is log-only; the latest snapshot reconstructs the request header.\n */\n 'request/header': {\n header: EpochHeader\n reason: RequestHeaderReason\n /** A changed header also begins a distinct model-message series. */\n startsSeries?: true\n }\n /**\n * Route metadata for the next request, logged only when the route or capacity\n * changes. It does not participate in request reconstruction or header equality.\n */\n 'request/context': RequestContext\n /**\n * Marks the end of a constructor seed. Events before it have smaller seq\n * values and came from the seed (resume, fork, or replay); this lifecycle\n * produced none of them. This log-only event is the durable projection of\n * {@link Session.firstLiveSeq}. Its payload is empty — position and `time`\n * carry the meaning.\n *\n * Locate the LAST one in stored history. A seed already ending in one is not\n * re-marked, so reopening an untouched session does not grow its log per\n * pickup and the event need not be at the current `firstLiveSeq`.\n *\n * `Session`'s constructor is the only legitimate writer. The invariant\n * companion deliberately constrains nothing here, so a plugin appending one\n * would silently classify every live bracket before it as seed history.\n *\n * An owner of a standalone open/close bracket (`compaction/start` …\n * `compaction/end`) reads it because seed history and live work are otherwise\n * byte-identical: an unmatched opening marker before this event belongs to\n * an ended lifecycle, whatever ended it. NOT a liveness signal about other\n * writers — a concurrently live session holds its own boundary elsewhere,\n * so tolerating concurrent writers needs a signal beyond the log.\n */\n 'session/end-seed': Record<string, never>\n}\n\n/** The appendable event-type keys of {@link SessionEventMap}, plugin-merged extensions included. */\nexport type SessionEventType = keyof SessionEventMap\n\n/**\n * The subset of {@link SessionEventType} values whose events produce LLM\n * messages and are eligible to appear on the ordered surface. Only these\n * event types may carry {@link SurfaceOp} and {@link SessionEvent.sourceEventSeqs}.\n */\nexport type SurfaceEventType =\n | 'user/message'\n | 'assistant/message'\n | 'tool/result'\n\n/**\n * A {@link SessionEvent} that is **on** the ordered surface — its\n * `surfaceOp` is guaranteed present (mandatory), narrowed from a\n * surface-eligible {@link SessionEvent} by checking both `type` and\n * `surfaceOp` at runtime.\n *\n * Use the `isSurfaceEvent` type guard (in `surface.ts`) to narrow a\n * `SessionEvent` to this type.\n */\nexport type SurfaceEvent = SessionEvent<SurfaceEventType> & { surfaceOp: SurfaceOp }\n\n/**\n * How a session event entered the ordered surface. Only valid on\n * {@link SurfaceEventType} events.\n *\n * - `'append'`: added to the tail — normal path for user/assistant/tool\n * messages.\n * - `{ op: 'replace', start, end }`: replaces surface nodes from `start`\n * (inclusive) through `end` (inclusive) with this node. Both must exist as\n * surface nodes in the current surface. `start === end` replaces a single\n * node. The node's {@link SessionEvent.sourceEventSeqs} must include every\n * shadowed surface node. Used by compaction; any surface-replacing producer\n * may use it.\n */\nexport type SurfaceOp =\n | 'append'\n | { op: 'replace'; start: number; end: number }\n\n/**\n * Surface placement and cited source-event seqs for {@link Session.append}. Required on\n * message-producing events and forbidden on log-only events.\n */\nexport interface SurfaceIntent {\n surfaceOp: SurfaceOp\n /**\n * Complete set of known source-event seqs. `assistant/message` may use a\n * present empty array for a known empty provider stream; when the field is\n * absent, the event does not record which earlier events produced the message.\n * Other surface events require a non-empty set when this field is present.\n */\n sourceEventSeqs?: number[]\n}\n\n/**\n * One immutable entry in the session log.\n *\n * A proper discriminated union over `type` (not independent `type`/`data`\n * unions), so `switch (event.type)` narrows `event.data` without casts.\n *\n * The {@link sourceEventSeqs} and {@link surfaceOp} fields are conditional:\n * they only exist on {@link SurfaceEventType} variants (`user/message`,\n * `assistant/message`, `tool/result`).\n * Non-surface events (boundary markers, chunks, usage, errors) never carry\n * surface metadata — the compiler enforces this at `Session.append()`\n * call sites.\n */\nexport type SessionEvent<T extends SessionEventType = SessionEventType> = {\n [K in SessionEventType]: {\n type: K\n /** Monotonic sequence number within the session. */\n seq: number\n /** Unix epoch milliseconds. */\n time: number\n data: SessionEventMap[K]\n } & (K extends SurfaceEventType ? {\n /**\n * Seq numbers of earlier events that this event cites as sources\n * (e.g. the `assistant/chunk` seqs that built an `assistant/message`,\n * or the surface nodes shadowed by a compaction replace node). An\n * `assistant/message` may carry a present empty array for a known empty\n * provider stream; when the field is absent, the event does not record which\n * earlier events produced the message.\n */\n sourceEventSeqs?: number[]\n /** How this event entered the surface; absent for non-surface events. */\n surfaceOp?: SurfaceOp\n } : object)\n}[T]\n","import { useEffect, useMemo, useRef, useState } from 'react'\nimport type { Dispatch, ReactNode, SetStateAction } from 'react'\nimport { Button, IconRefreshOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'\nimport css from './story-points.module.css'\nimport type { TomatoItem } from './TomatoBoard'\n\ntype User = { username: string; name: string }\ntype Sprint = { sprintId: string; name: string; workspaceKey: string; status: string; startDate?: string }\ntype Item = TomatoItem & { storyPoints: number | null }\ntype Result = { items: Item[]; truncated: boolean }\ntype Team = { id: string; name: string; members: string[] }\nconst LEGACY_TEAM_KEY = 'taskboard.tomatoStoryTeam.v1'\nconst TEAMS_KEY = 'taskboard.tomatoStoryTeams.v2'\nconst SPRINT_KEY = 'taskboard.tomatoStorySprint.v1'\nconst OWNER_KEY = 'taskboard.tomatoStoryOwner.v1'\nconst colors = ['#d76b50', '#458e88', '#c79940', '#687fb2', '#976f9c', '#75914f', '#be7f92', '#698b9d']\nconst number = (value: number) => new Intl.NumberFormat('zh-CN', { maximumFractionDigits: 4 }).format(value)\nconst total = (items: Item[]) => items.reduce((sum, item) => sum + (item.storyPoints ?? 0), 0)\nconst savedValue = (key: string, fallback: string) => { try { return localStorage.getItem(key) || fallback } catch { return fallback } }\nconst teamId = () => `team-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`\nasync function json<T>(url: string, signal?: AbortSignal): Promise<T> {\n const response = await fetch(url, { signal: signal ?? null, cache: 'no-store', headers: { accept: 'application/json', 'cache-control': 'no-cache' } }); const text = await response.text(); let body: Record<string, unknown>\n try { body = text ? JSON.parse(text) as Record<string, unknown> : {} } catch { throw new Error(response.status === 404 || text.trim() === 'not found' ? '迭代故事点接口尚未加载,请完全重启 DSH Desktop' : `服务返回了无法识别的内容 (${response.status})`) }\n if (!response.ok) throw new Error(typeof body.error === 'string' ? body.error : `请求失败 (${response.status})`); return body as T\n}\nfunction readTeams(): Team[] {\n try {\n const saved: unknown = JSON.parse(localStorage.getItem(TEAMS_KEY) ?? '[]')\n if (Array.isArray(saved) && saved.length) return saved.flatMap(value => value && typeof value === 'object' ? [{ id: String((value as Team).id), name: String((value as Team).name), members: Array.isArray((value as Team).members) ? [...new Set((value as Team).members)] : [] }] : [])\n const legacy: unknown = JSON.parse(localStorage.getItem(LEGACY_TEAM_KEY) ?? '[]')\n return Array.isArray(legacy) && legacy.length ? [{ id: 'team-default', name: '默认团队', members: legacy.filter((value): value is string => typeof value === 'string') }] : []\n } catch { return [] }\n}\n\nexport function StoryPoints({ toolbarTarget, onOpenItem }: { toolbarTarget: Dispatch<SetStateAction<ReactNode>>; onOpenItem: (item: TomatoItem) => void }) {\n const [sprints, setSprints] = useState<Sprint[]>([]); const [users, setUsers] = useState<User[]>([])\n const [sprint, setSprint] = useState(() => savedValue(SPRINT_KEY, '')); const [owner, setOwner] = useState(() => savedValue(OWNER_KEY, 'currentUser()'))\n const [teams, setTeams] = useState(readTeams); const [openTeamId, setOpenTeamId] = useState(() => readTeams()[0]?.id ?? '')\n const [loadedTeams, setLoadedTeams] = useState<Set<string>>(() => { const first = readTeams()[0]?.id; return new Set(first ? [first] : []) }); const [teamDraft, setTeamDraft] = useState(''); const [teamEditor, setTeamEditor] = useState<{ mode: 'create' | 'rename'; id?: string } | null>(null)\n const [addingTeamId, setAddingTeamId] = useState(''); const addPeopleRef = useRef<HTMLDivElement>(null); const addPeopleInputRef = useRef<HTMLInputElement>(null); const [search, setSearch] = useState('')\n const [results, setResults] = useState<Record<string, Result>>({}); const [errors, setErrors] = useState<Record<string, string>>({}); const [directoryError, setDirectoryError] = useState(''); const [directoryLoading, setDirectoryLoading] = useState(true); const [version, setVersion] = useState(0); const [directoryVersion, setDirectoryVersion] = useState(0)\n useEffect(() => {\n const controller = new AbortController(); setDirectoryLoading(true); setDirectoryError('')\n void Promise.all([json<{ sprints: Sprint[] }>('/api/tomato-board/sprints', controller.signal), json<{ users: User[] }>('/api/tomato-board/filters', controller.signal)]).then(([data, directory]) => { const sorted = [...data.sprints].sort((a, b) => (b.startDate ?? '').localeCompare(a.startDate ?? '')); setSprints(sorted); setUsers(directory.users); setSprint(current => sorted.some(value => value.sprintId === current) ? current : sorted[0]?.sprintId || '') }).catch(error => { if (!controller.signal.aborted) setDirectoryError(error.message) }).finally(() => { if (!controller.signal.aborted) setDirectoryLoading(false) }); return () => controller.abort()\n }, [directoryVersion])\n useEffect(() => { try { localStorage.setItem(TEAMS_KEY, JSON.stringify(teams)) } catch {} }, [teams]); useEffect(() => { if (sprint) try { localStorage.setItem(SPRINT_KEY, sprint) } catch {} }, [sprint]); useEffect(() => { try { localStorage.setItem(OWNER_KEY, owner) } catch {} }, [owner])\n const openTeam = teams.find(team => team.id === openTeamId); const openMembers = openTeam?.members ?? []; const ownersKey = JSON.stringify([...new Set([owner, ...(loadedTeams.has(openTeamId) ? openMembers : [])])].sort())\n useEffect(() => {\n if (!sprint) return; const controller = new AbortController(); const owners = (JSON.parse(ownersKey) as string[]).filter(username => !results[username] && !errors[username])\n const worker = async () => { while (owners.length && !controller.signal.aborted) { const username = owners.shift()!; try { const data = await json<Result>(`/api/tomato-board/story-points?${new URLSearchParams({ sprint, assignee: username, refresh: String(version) })}`, controller.signal); if (!controller.signal.aborted) setResults(current => ({ ...current, [username]: data })) } catch (error) { if (!controller.signal.aborted) setErrors(current => ({ ...current, [username]: error instanceof Error ? error.message : '读取失败' })) } } }; void Promise.all([worker(), worker(), worker()]); return () => controller.abort()\n }, [sprint, ownersKey, version])\n const personal = results[owner]; const items = useMemo(() => [...(personal?.items ?? [])].sort((a, b) => (b.storyPoints ?? -1) - (a.storyPoints ?? -1) || a.itemKey.localeCompare(b.itemKey)), [personal]); const sum = total(items); const slices = items.filter(item => item.storyPoints !== null && item.storyPoints > 0); let offset = 0\n const gradient = slices.map((item, index) => { const start = offset; offset += item.storyPoints! / sum * 100; return `${colors[index % colors.length]} ${start}% ${offset}%` }).join(', '); const userName = (username: string) => username === 'currentUser()' ? '我' : users.find(user => user.username === username)?.name ?? username\n const toggleTeam = (id: string) => { setOpenTeamId(current => current === id ? '' : id); setLoadedTeams(current => new Set(current).add(id)); setAddingTeamId(''); setTeamEditor(null) }\n const ranking = openMembers.map(username => ({ username, result: results[username], points: total(results[username]?.items ?? []) })).sort((a, b) => Number(Boolean(b.result)) - Number(Boolean(a.result)) || b.points - a.points || a.username.localeCompare(b.username)); const max = Math.max(1, ...ranking.map(row => row.points)); const available = users.filter(user => !openMembers.includes(user.username) && `${user.name} ${user.username}`.toLowerCase().includes(search.toLowerCase()))\n const submitTeam = () => { const name = teamDraft.trim(); if (!name || !teamEditor) return; if (teamEditor.mode === 'create') { const team = { id: teamId(), name, members: [] }; setTeams(current => [...current, team]); setOpenTeamId(team.id); setLoadedTeams(current => new Set(current).add(team.id)) } else setTeams(current => current.map(team => team.id === teamEditor.id ? { ...team, name } : team)); setTeamDraft(''); setTeamEditor(null) }\n const deleteTeam = (id: string) => { setTeams(current => current.filter(team => team.id !== id)); if (openTeamId === id) setOpenTeamId(''); setLoadedTeams(current => { const next = new Set(current); next.delete(id); return next }) }\n const updateMembers = (id: string, updater: (values: string[]) => string[]) => setTeams(current => current.map(team => team.id === id ? { ...team, members: updater(team.members) } : team))\n useEffect(() => { if (!addingTeamId) return; const close = (event: PointerEvent) => { if (event.target instanceof Node && !addPeopleRef.current?.contains(event.target)) { setAddingTeamId(''); setSearch('') } }; document.addEventListener('pointerdown', close, true); requestAnimationFrame(() => addPeopleInputRef.current?.focus()); return () => document.removeEventListener('pointerdown', close, true) }, [addingTeamId])\n useEffect(() => { toolbarTarget(<div className={css.headerControls}><label><span>迭代</span><select aria-label=\"选择迭代\" value={sprint} disabled={directoryLoading} onChange={event => { setSprint(event.target.value); setResults({}); setErrors({}); setLoadedTeams(new Set()) }}>{!sprints.length && <option value=\"\">{directoryLoading ? '正在读取迭代…' : '暂无迭代'}</option>}{sprints.map(value => <option key={value.sprintId} value={value.sprintId}>{value.name} · {value.workspaceKey}{value.status === 'completed' ? '(已结束)' : ''}</option>)}</select></label><Button variant=\"toolbar\" size=\"sm\" className={css.headerIconButton} icon={<IconRefreshOutline16 />} title=\"刷新\" aria-label=\"刷新迭代故事点\" onClick={() => { setResults({}); setErrors({}); setVersion(value => value + 1); if (directoryError || !sprints.length) setDirectoryVersion(value => value + 1) }} /></div>); return () => toolbarTarget(null) }, [directoryError, directoryLoading, sprint, sprints, toolbarTarget])\n return <div className={css.page}>{directoryError && <p className={css.error}>{directoryError},请点击刷新重试。</p>}<div className={css.columns}>\n <section className={css.panel} aria-label=\"个人故事点\"><div className={css.panelHeader}><h3>个人分布</h3><select aria-label=\"选择个人负责人\" value={owner} onChange={event => setOwner(event.target.value)}><option value=\"currentUser()\">我负责的</option>{users.map(user => <option key={user.username} value={user.username}>{user.name} · {user.username}</option>)}</select></div>{errors[owner] ? <p className={css.error}>{errors[owner]}</p> : !personal ? <p className={css.empty}>{sprint ? '正在读取个人故事点…' : '请选择迭代'}</p> : <><div className={css.summary}><div><span className={css.eyebrow}>故事点总数</span><div className={css.total}>{number(sum)}<small> SP</small></div></div><div className={css.pie} style={{ background: gradient ? `conic-gradient(${gradient})` : undefined }}><div><strong>{slices.length}</strong><span>项占比</span></div></div></div><div className={css.listHeading}><h4>需求列表</h4><span>{items.length} 项</span></div>{!items.length && <p className={css.empty}>该负责人在本迭代暂无事项。</p>}<div>{items.map(item => <div className={css.item} key={item.itemKey} role=\"button\" tabIndex={0} aria-label={`打开 ${item.itemKey} 的对话`} onClick={() => onOpenItem(item)} onKeyDown={event => { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); onOpenItem(item) } }}><span className={css.dot} style={{ background: item.storyPoints && item.storyPoints > 0 ? colors[slices.indexOf(item) % colors.length] : 'var(--dsw-alias-border-l2, #ddd)' }} /><div className={css.itemText}><span className={css.itemTitle}>{item.title}</span><small>{item.itemKey}</small><span className={css.statusTag}>{item.status}</span></div><strong className={css.itemPoints}>{item.storyPoints === null ? '未估点' : `${number(item.storyPoints)} SP`}</strong><Button className={css.tomatoLink} variant=\"ghost\" size=\"sm\" title=\"在番茄中打开事项\" aria-label={`在番茄中打开 ${item.itemKey}`} onClick={event => { event.stopPropagation(); window.open(item.tomatoUrl, '_blank', 'noopener,noreferrer') }} onKeyDown={event => event.stopPropagation()}>↗</Button></div>)}</div></>}</section>\n <section className={css.panel} aria-label=\"团队故事点\"><div className={css.teamsHeader}><h3>团队分布</h3><button className={css.addTeamButton} aria-label=\"创建团队\" title=\"创建团队\" onClick={() => { setTeamEditor({ mode: 'create' }); setTeamDraft('') }}>+ 创建团队</button></div>{teamEditor?.mode === 'create' && <form className={css.teamEditor} onSubmit={event => { event.preventDefault(); submitTeam() }}><input autoFocus placeholder=\"团队名称\" value={teamDraft} onChange={event => setTeamDraft(event.target.value)} /><button type=\"button\" onClick={() => setTeamEditor(null)}>取消</button><button type=\"submit\">创建</button></form>}<div className={css.teamAccordions}>{teams.map(team => { const open = openTeamId === team.id; const rows = open ? ranking : []; return <article className={css.teamAccordion} key={team.id}><div className={css.teamAccordionHeader}><button className={css.teamToggle} aria-expanded={open} onClick={() => toggleTeam(team.id)}><span className={css.chevron}>›</span><strong>{team.name}</strong><small>{team.members.length} 人</small></button><button className={css.renameTeam} aria-label={`改名 ${team.name}`} title=\"改名\" onClick={() => { setTeamEditor({ mode: 'rename', id: team.id }); setTeamDraft(team.name); setOpenTeamId(team.id) }}>✎</button><div className={css.teamRowActions}><button aria-label={`删除 ${team.name}`} title=\"删除\" onClick={() => deleteTeam(team.id)}>×</button></div></div>{teamEditor?.mode === 'rename' && teamEditor.id === team.id && <form className={css.teamEditor} onSubmit={event => { event.preventDefault(); submitTeam() }}><input autoFocus value={teamDraft} onChange={event => setTeamDraft(event.target.value)} /><button type=\"button\" onClick={() => setTeamEditor(null)}>取消</button><button type=\"submit\">保存</button></form>}{open && <div className={css.teamBody}><div className={css.teamBodyToolbar}><span>{team.members.length ? '成员故事点' : '暂无成员'}</span><div ref={addingTeamId === team.id ? addPeopleRef : undefined} className={css.addPeopleRoot}><button className={css.smallAddButton} onClick={() => setAddingTeamId(current => current === team.id ? '' : team.id)}>+ 添加成员</button>{addingTeamId === team.id && <div className={css.addPeople} role=\"dialog\"><div className={css.addPeopleTitle}><strong>添加成员</strong><button onClick={() => setAddingTeamId('')}>×</button></div><input ref={addPeopleInputRef} value={search} onChange={event => setSearch(event.target.value)} placeholder=\"搜索姓名或用户名…\" /><div>{available.map(user => <button key={user.username} onClick={() => { updateMembers(team.id, current => [...current, user.username]); setAddingTeamId(''); setSearch('') }}>{user.name}<small>{user.username}</small><span>+</span></button>)}{!available.length && <p>没有可添加的成员</p>}</div></div>}</div></div><div className={css.ranking}>{rows.map((row, index) => <div key={row.username} className={css.rankRow}><div className={css.memberRow}><button className={css.rankLabel} aria-pressed={owner === row.username} onClick={() => setOwner(row.username)}><i className={css.rankFill} style={{ width: `${row.points / max * 100}%` }} /><span className={css.rankIndex}>{String(index + 1).padStart(2, '0')}</span><span className={css.memberAvatar}>{userName(row.username).slice(0, 1)}</span><span className={css.memberIdentity}><strong>{userName(row.username)}</strong><small>{row.result ? `${row.result.items.length} 个事项` : errors[row.username] ? '读取失败' : '读取中…'}</small></span><b>{row.result ? `${number(row.points)} SP` : '—'}</b></button><button className={css.removeMember} aria-label={`移除 ${userName(row.username)}`} title=\"移除成员\" onClick={() => updateMembers(team.id, current => current.filter(value => value !== row.username))}>×</button></div></div>)}</div>{!team.members.length && <div className={css.teamBodyEmpty}>添加成员后查看故事点分布</div>}</div>}</article> })}</div>{!teams.length && <div className={css.empty}>点击右上角加号创建团队。</div>}</section>\n </div></div>\n}\n","import { useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'\nimport type { Context } from '@deepseek-ai/cordis'\nimport type {} from '@deepseek-ai/dsh-api-session-controller/client'\nimport type { WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport type {} from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-layout/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-sidebar/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport {\n Button, IconChevronDownOutline14, IconCloseOutline16, IconRefreshOutline16, Menu, Modal,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport { SessionId } from '@deepseek-ai/dsh-session/types'\nimport css from './tomato-board.module.css'\nimport { StoryPoints } from './StoryPoints'\n\nexport interface TomatoItem {\n itemKey: string\n title: string\n status: string\n itemType: string\n workspace: string\n workspaceKey: string\n workspaceName: string\n creator: string\n assignees: string[]\n priority: string\n tomatoUrl: string\n}\n\ninterface FilterDirectory {\n users: Array<{ username: string; name: string }>\n workspaces: Array<{ key: string; name: string }>\n}\n\ninterface LaneOrder {\n head: string | null\n next: Record<string, string | null>\n}\n\ninterface TomatoTransition {\n transition: string\n targetStatus: string\n disabled: boolean\n disabledReason?: string\n}\n\ninterface TomatoTransitionState {\n currentStatus: string\n tomatoUrl: string\n transitions: TomatoTransition[]\n}\n\ninterface BoardState {\n open: boolean\n loading: boolean\n items: TomatoItem[]\n error: string | null\n selectedItem: TomatoItem | null\n truncated: boolean\n}\n\nlet state: BoardState = { open: false, loading: false, items: [], error: null, selectedItem: null, truncated: false }\nlet disposeWorkbench: (() => void) | null = null\nconst listeners = new Set<() => void>()\nconst emit = (patch: Partial<BoardState>) => {\n state = { ...state, ...patch }\n for (const listener of listeners) listener()\n}\nconst subscribe = (listener: () => void) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n}\nconst snapshot = () => state\n\n// 真实番茄事项 itemKey 形如 `Gitee-Test-2026-737`、`Proxima-1116`:字母前缀(可含连字符分段)+ 数字结尾。\n// 只匹配该格式可避免把任意 `[xxx]` 开头的普通对话标题(如 `[分析]`、`[每日复盘]`)误判为番茄事项,\n// 进而错误地在对话头上渲染出状态流转按钮并触发无意义的 CLI 调用。\nconst TOMATO_ITEM_KEY_PATTERN = /^\\[([A-Za-z][A-Za-z0-9]*(?:-[A-Za-z0-9]+)*-\\d+)\\]/u\n\nconst TOMATO_STATUS_ORDER = [\n '新建', 'Bugfix', '修复中', '开发中', '待测试', '测试中', '测试通过', '已完成',\n '已取消', '延期解决', '测试完成', '待开发', '不修复', '已挂起',\n]\nconst TOMATO_FILTER_BLACKLIST_KEY = 'taskboard.tomatoFilterBlacklist.v1'\nconst TOMATO_SESSION_LINKS_KEY = 'taskboard.tomatoSessionLinks.v1'\nconst TOMATO_MUTED_ITEMS_KEY = 'taskboard.tomatoMutedItems.v1'\nconst TOMATO_LANE_ORDER_KEY = 'taskboard.tomatoLaneOrder.v1'\n\nfunction readLaneOrder(): LaneOrder {\n try {\n const value = JSON.parse(window.localStorage.getItem(TOMATO_LANE_ORDER_KEY) ?? '{}')\n return {\n head: typeof value?.head === 'string' ? value.head : null,\n next: value?.next && typeof value.next === 'object' ? value.next as Record<string, string | null> : {},\n }\n } catch {\n return { head: null, next: {} }\n }\n}\n\nfunction laneOrderValues(order: LaneOrder): string[] {\n const values: string[] = []\n const seen = new Set<string>()\n let current = order.head\n while (current && !seen.has(current) && values.length < 1000) {\n values.push(current)\n seen.add(current)\n current = order.next[current] ?? null\n }\n return values\n}\n\nfunction createLaneOrder(values: string[]): LaneOrder {\n const next: Record<string, string | null> = {}\n values.forEach((value, index) => { next[value] = values[index + 1] ?? null })\n return { head: values[0] ?? null, next }\n}\n\nfunction applyLaneOrder(statuses: string[], order: LaneOrder): string[] {\n const available = new Set(statuses)\n const tracked = laneOrderValues(order).filter(status => available.has(status))\n const trackedSet = new Set(tracked)\n return [...tracked, ...statuses.filter(status => !trackedSet.has(status))]\n}\n\nfunction readSessionLinks(): Record<string, string> {\n try {\n const value = JSON.parse(window.localStorage.getItem(TOMATO_SESSION_LINKS_KEY) ?? '{}')\n return value && typeof value === 'object' ? value as Record<string, string> : {}\n } catch {\n return {}\n }\n}\n\nfunction linkedSessionId(itemKey: string): SessionId | '' {\n const value = readSessionLinks()[itemKey]\n return typeof value === 'string' && value ? SessionId(value) : ''\n}\n\nfunction saveSessionLink(itemKey: string, sessionId: SessionId) {\n const links = readSessionLinks()\n links[itemKey] = sessionId\n window.localStorage.setItem(TOMATO_SESSION_LINKS_KEY, JSON.stringify(links))\n}\n\nfunction readFilterBlacklist(): { types: Set<string>; statuses: Set<string>; workspaces: Set<string> } {\n try {\n const value = JSON.parse(window.localStorage.getItem(TOMATO_FILTER_BLACKLIST_KEY) ?? '{}')\n return {\n types: new Set(Array.isArray(value?.types) ? value.types.filter((item: unknown): item is string => typeof item === 'string') : []),\n statuses: new Set(Array.isArray(value?.statuses) ? value.statuses.filter((item: unknown): item is string => typeof item === 'string') : []),\n workspaces: new Set(Array.isArray(value?.workspaces) ? value.workspaces.filter((item: unknown): item is string => typeof item === 'string') : []),\n }\n } catch {\n return { types: new Set(), statuses: new Set(), workspaces: new Set() }\n }\n}\n\nfunction readMutedItems(): Set<string> {\n try {\n const value = JSON.parse(window.localStorage.getItem(TOMATO_MUTED_ITEMS_KEY) ?? '[]')\n return new Set(Array.isArray(value) ? value.filter((item): item is string => typeof item === 'string') : [])\n } catch {\n return new Set()\n }\n}\n\nasync function refresh(assignee = 'currentUser()') {\n emit({ loading: true, error: null })\n try {\n const query = new URLSearchParams({ assignee })\n const response = await fetch(`/api/tomato-board/items?${query}`, { headers: { accept: 'application/json' } })\n const body = await response.json() as { items?: TomatoItem[]; truncated?: boolean; error?: string }\n if (!response.ok) throw new Error(body.error || `请求失败 (${response.status})`)\n emit({ items: body.items ?? [], truncated: body.truncated === true })\n } catch (error) {\n emit({ error: error instanceof Error ? error.message : '番茄事项读取失败' })\n } finally {\n emit({ loading: false })\n }\n}\n\nfunction closeWorkbench() {\n const dispose = disposeWorkbench\n disposeWorkbench = null\n emit({ open: false, selectedItem: null })\n dispose?.()\n}\n\nfunction TomatoBoardAction({ wide, openWorkbench }: { wide: boolean; openWorkbench: () => void }) {\n return (\n <button className={css.sidebarAction} type=\"button\" title=\"番茄工作台\" onClick={openWorkbench}>\n <span className={css.tomatoIcon} aria-hidden=\"true\">T</span>\n {wide && <span>番茄工作台</span>}\n </button>\n )\n}\n\nfunction TomatoBoardTopbarAction({ openWorkbench }: { openWorkbench: () => void }) {\n return (\n <button className={css.topbarAction} type=\"button\" title=\"打开番茄工作台\" onClick={openWorkbench}>\n <span className={css.tomatoIcon} aria-hidden=\"true\">T</span>\n <span>番茄工作台</span>\n </button>\n )\n}\n\nfunction CreateConversationDialog({ ctx, item }: { ctx: Context; item: TomatoItem }) {\n const [workspaceId, setWorkspaceId] = useState('')\n const [workspaceMenuOpen, setWorkspaceMenuOpen] = useState(false)\n const [creating, setCreating] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const workspaces = useSyncExternalStore(\n listener => ctx.workspaces.list.subscribe(listener),\n () => ctx.workspaces.list.getSnapshot(),\n () => ctx.workspaces.list.getSnapshot(),\n )\n const selectedWorkspace = workspaces.items.find(workspace => workspace.workspaceId === workspaceId)\n\n async function createConversation() {\n if (!selectedWorkspace || creating) return\n setCreating(true)\n setError(null)\n try {\n const createdSessionId = await ctx.sessions.create({ workspaceId: selectedWorkspace.workspaceId })\n const session = ctx.sessions.binding(createdSessionId)?.session\n if (!session) throw new Error('新建对话未能在 Harness 中加载')\n const title = `[${item.itemKey}] ${item.title}`\n const renamed = await session.rename(title)\n if (!renamed.ok) throw new Error(`对话标题设置失败:${renamed.error.message}`)\n const prompt = [\n `请处理番茄事项 ${item.itemKey}。`,\n `标题:${item.title}`,\n `类型:${item.itemType || '未设置'}`,\n `状态:${item.status || '未设置'}`,\n `优先级:${item.priority || '未设置'}`,\n ].join('\\n')\n const prompted = await session.prompt([{ type: 'text', text: prompt }], 'queue')\n if (!prompted.ok) throw new Error(`事项上下文写入失败:${prompted.error.message}`)\n saveSessionLink(item.itemKey, createdSessionId)\n ctx.sessions.open(createdSessionId)\n closeWorkbench()\n } catch (reason) {\n setError(reason instanceof Error ? reason.message : 'Harness 对话创建失败')\n } finally {\n setCreating(false)\n }\n }\n\n return (\n <Modal\n open\n onClose={() => emit({ selectedItem: null })}\n title=\"选择处理该事项的仓库\"\n closeLabel=\"关闭\"\n description={item.title}\n className={css.createDialog!}\n footer={(\n <>\n <Button variant=\"ghost\" onClick={() => emit({ selectedItem: null })}>取消</Button>\n <Button variant=\"primary\" disabled={!selectedWorkspace || creating} onClick={() => void createConversation()}>\n {creating ? '正在创建…' : '创建并进入对话'}\n </Button>\n </>\n )}\n >\n <div className={css.dialogBody}>\n <span>{item.itemKey}</span>\n {error ? <div className={css.error} role=\"alert\">{error}</div> : null}\n <Menu\n open={workspaceMenuOpen}\n portal\n items={workspaces.items.map((workspace: WorkspaceView) => ({\n id: workspace.workspaceId,\n label: workspace.title,\n }))}\n selectedId={workspaceId || undefined}\n onSelect={id => {\n setWorkspaceId(id)\n setWorkspaceMenuOpen(false)\n }}\n onClose={() => setWorkspaceMenuOpen(false)}\n anchor={(\n <Button\n className={css.workspaceTrigger}\n variant=\"outline\"\n aria-haspopup=\"menu\"\n aria-expanded={workspaceMenuOpen}\n onClick={() => setWorkspaceMenuOpen(open => !open)}\n >\n <span>{selectedWorkspace?.title ?? '选择 Harness 项目…'}</span>\n <span aria-hidden=\"true\">⌄</span>\n </Button>\n )}\n />\n {selectedWorkspace ? <code>{selectedWorkspace.path}</code> : null}\n </div>\n </Modal>\n )\n}\n\nfunction TomatoBoardPanel({ ctx }: { ctx: Context }) {\n const board = useSyncExternalStore(subscribe, snapshot, snapshot)\n const workbenchRef = useRef<HTMLElement>(null)\n const filterMenuRef = useRef<HTMLDetailsElement>(null)\n const [page, setPage] = useState<'board' | 'points'>('board')\n const [storyToolbar, setStoryToolbar] = useState<React.ReactNode>(null)\n const [search, setSearch] = useState('')\n const [blacklist, setBlacklist] = useState(readFilterBlacklist)\n const [mutedItems, setMutedItems] = useState(readMutedItems)\n const [selectedAssignee, setSelectedAssignee] = useState('currentUser()')\n const [filterDirectory, setFilterDirectory] = useState<FilterDirectory>({ users: [], workspaces: [] })\n const [laneOrder, setLaneOrder] = useState(readLaneOrder)\n const [draggedLane, setDraggedLane] = useState<string | null>(null)\n const [dropLane, setDropLane] = useState<{ status: string; after: boolean } | null>(null)\n const laneElements = useRef(new Map<string, HTMLElement>())\n const previousLanePositions = useRef(new Map<string, DOMRect>())\n const sessions = useSyncExternalStore(\n listener => ctx.sessions.list.subscribe(listener),\n () => ctx.sessions.list.getSnapshot(),\n () => ctx.sessions.list.getSnapshot(),\n )\n\n useEffect(() => {\n if (board.open && board.items.length === 0 && !board.loading && !board.error) void refresh()\n }, [board.error, board.items.length, board.loading, board.open])\n useEffect(() => {\n if (!board.open) return\n void fetch('/api/tomato-board/filters', { headers: { accept: 'application/json' } })\n .then(response => response.ok ? response.json() : Promise.reject(new Error(`HTTP ${response.status}`)))\n .then(value => setFilterDirectory(value as FilterDirectory))\n .catch(() => {})\n }, [board.open])\n useEffect(() => {\n if (!board.open) return\n const closeOnOutsideNavigation = (event: PointerEvent) => {\n if (!(event.target instanceof Element)) return\n if (workbenchRef.current?.contains(event.target)) return\n if (event.target.closest('[role=\"dialog\"], [role=\"menu\"]')) return\n closeWorkbench()\n }\n document.addEventListener('pointerdown', closeOnOutsideNavigation, true)\n return () => document.removeEventListener('pointerdown', closeOnOutsideNavigation, true)\n }, [board.open])\n useEffect(() => {\n const closeFilterMenu = (event: PointerEvent) => {\n const menu = filterMenuRef.current\n if (menu?.open && event.target instanceof Node && !menu.contains(event.target)) menu.open = false\n }\n const closeFilterMenuOnEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && filterMenuRef.current?.open) filterMenuRef.current.open = false\n }\n document.addEventListener('pointerdown', closeFilterMenu, true)\n document.addEventListener('keydown', closeFilterMenuOnEscape)\n return () => {\n document.removeEventListener('pointerdown', closeFilterMenu, true)\n document.removeEventListener('keydown', closeFilterMenuOnEscape)\n }\n }, [])\n useLayoutEffect(() => {\n const previous = previousLanePositions.current\n if (previous.size === 0) return\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {\n previous.clear()\n return\n }\n for (const [status, element] of laneElements.current) {\n const before = previous.get(status)\n if (!before) continue\n const after = element.getBoundingClientRect()\n const deltaX = before.left - after.left\n const deltaY = before.top - after.top\n if (deltaX || deltaY) {\n element.animate(\n [{ transform: `translate(${deltaX}px, ${deltaY}px)` }, { transform: 'translate(0, 0)' }],\n { duration: 240, easing: 'cubic-bezier(.2,.8,.2,1)' },\n )\n }\n }\n previous.clear()\n }, [laneOrder])\n if (!board.open) return null\n\n function openItem(item: TomatoItem) {\n const stored = linkedSessionId(item.itemKey)\n const titlePrefix = `[${item.itemKey}]`\n const discovered = sessions.ids.find(id => {\n const summary = sessions.byId[id]\n return summary?.title?.startsWith(titlePrefix) || summary?.displayTitle.startsWith(titlePrefix)\n })\n const associated = stored && sessions.byId[stored] ? stored : discovered\n if (associated) {\n saveSessionLink(item.itemKey, associated)\n ctx.sessions.open(associated)\n closeWorkbench()\n return\n }\n emit({ selectedItem: item })\n }\n\n const normalizedSearch = search.trim().toLowerCase()\n const filteredItems = board.items.filter(item => (\n !blacklist.types.has(item.itemType)\n && !blacklist.statuses.has(item.status)\n && !blacklist.workspaces.has(item.workspaceKey || item.workspaceName || item.workspace)\n && (!normalizedSearch || [\n item.itemKey, item.title, item.itemType, item.status, item.workspaceKey, item.workspaceName, item.creator, item.assignees.join(' '), item.priority,\n ].join(' ').toLowerCase().includes(normalizedSearch))\n ))\n const typeOptions = [...new Set(board.items.map(item => item.itemType).filter(Boolean))].sort((left, right) => left.localeCompare(right))\n const statusOptions = applyLaneOrder([...new Set([\n ...TOMATO_STATUS_ORDER,\n ...board.items.map(item => item.status).filter(status => !TOMATO_STATUS_ORDER.includes(status)),\n ])], laneOrder)\n const workspaceOptions = [...new Map([\n ...filterDirectory.workspaces.map(workspace => [workspace.key || workspace.name, workspace.name && workspace.key && workspace.name !== workspace.key ? `${workspace.name} (${workspace.key})` : workspace.key || workspace.name] as const),\n ...board.items.map(item => [item.workspaceKey || item.workspaceName || item.workspace, item.workspaceName && item.workspaceKey && item.workspaceName !== item.workspaceKey ? `${item.workspaceName} (${item.workspaceKey})` : item.workspaceKey || item.workspaceName] as const),\n ].filter(([value]) => Boolean(value))).entries()].map(([value, label]) => ({ value, label }))\n const defaultStatuses = [...new Set([\n ...TOMATO_STATUS_ORDER.filter(status => filteredItems.some(item => item.status === status)),\n ...filteredItems.map(item => item.status).filter(status => !TOMATO_STATUS_ORDER.includes(status)),\n ])]\n const statuses = applyLaneOrder(defaultStatuses, laneOrder)\n\n const toggleBlacklist = (kind: 'types' | 'statuses' | 'workspaces', value: string) => setBlacklist(current => {\n const nextValues = new Set(current[kind])\n if (nextValues.has(value)) nextValues.delete(value)\n else nextValues.add(value)\n const next = { ...current, [kind]: nextValues }\n window.localStorage.setItem(TOMATO_FILTER_BLACKLIST_KEY, JSON.stringify({\n types: [...next.types],\n statuses: [...next.statuses],\n workspaces: [...next.workspaces],\n }))\n return next\n })\n\n const toggleMutedItem = (itemKey: string) => setMutedItems(current => {\n const next = new Set(current)\n if (next.has(itemKey)) next.delete(itemKey)\n else next.add(itemKey)\n window.localStorage.setItem(TOMATO_MUTED_ITEMS_KEY, JSON.stringify([...next]))\n return next\n })\n\n const moveLane = (dragged: string, target: string, after: boolean) => {\n if (dragged === target) return\n previousLanePositions.current = new Map([...laneElements.current].map(([status, element]) => [status, element.getBoundingClientRect()]))\n setLaneOrder(current => {\n const visible = applyLaneOrder(defaultStatuses, current).filter(status => status !== dragged)\n const targetIndex = visible.indexOf(target)\n visible.splice(targetIndex + (after ? 1 : 0), 0, dragged)\n const previousTracked = laneOrderValues(current)\n const trackedSet = new Set([...previousTracked, dragged, target])\n const hiddenTracked = previousTracked.filter(status => !visible.includes(status))\n const next = createLaneOrder([...visible.filter(status => trackedSet.has(status)), ...hiddenTracked])\n window.localStorage.setItem(TOMATO_LANE_ORDER_KEY, JSON.stringify(next))\n return next\n })\n }\n\n return (\n <section ref={workbenchRef} className={css.workbench} aria-label=\"番茄工作台\">\n <header className={css.header}>\n <div className={css.titleRow}>\n <h1>番茄工作台</h1>\n <div className={css.actions}>\n {page === 'points' && storyToolbar}\n {page === 'board' && <><label className={css.searchField}>\n <span aria-hidden=\"true\">⌕</span>\n <input\n type=\"search\"\n value={search}\n onChange={event => setSearch(event.target.value)}\n placeholder=\"搜索标题或 tag…\"\n aria-label=\"搜索标题或 tag\"\n />\n {search && <button type=\"button\" aria-label=\"清空搜索词\" onClick={() => setSearch('')}>×</button>}\n </label>\n <details ref={filterMenuRef} className={css.filterMenu}>\n <summary aria-label=\"空间、负责人、类型和状态筛选\" title=\"空间、负责人、类型和状态筛选\">\n <span aria-hidden=\"true\">▽</span>\n {(blacklist.types.size > 0 || blacklist.statuses.size > 0 || blacklist.workspaces.size > 0 || selectedAssignee !== 'currentUser()') && <i />}\n </summary>\n <div className={css.filterPopover}>\n <WorkspaceFilterRow options={workspaceOptions} hidden={blacklist.workspaces} onToggle={value => toggleBlacklist('workspaces', value)} />\n <AssigneePicker users={filterDirectory.users} value={selectedAssignee} onChange={value => { setSelectedAssignee(value); void refresh(value) }} />\n <FilterRow label=\"类型\" options={typeOptions} hidden={blacklist.types} onToggle={value => toggleBlacklist('types', value)} />\n <FilterRow label=\"状态\" options={statusOptions} hidden={blacklist.statuses} onToggle={value => toggleBlacklist('statuses', value)} />\n </div>\n </details>\n <Button\n variant=\"toolbar\"\n size=\"sm\"\n className={css.headerIconButton}\n icon={<IconRefreshOutline16 />}\n title=\"刷新番茄事项\"\n aria-label=\"刷新番茄事项\"\n disabled={board.loading}\n onClick={() => void refresh(selectedAssignee)}\n />\n </>}\n <Button\n variant=\"toolbar\"\n size=\"sm\"\n className={css.headerIconButton}\n icon={<IconCloseOutline16 />}\n title=\"关闭番茄工作台\"\n aria-label=\"关闭番茄工作台\"\n onClick={closeWorkbench}\n />\n </div>\n </div>\n <nav className={css.pageTabs} aria-label=\"番茄工作台页面\">\n <button type=\"button\" aria-current={page === 'board' ? 'page' : undefined} onClick={() => setPage('board')}>事项看板</button>\n <button type=\"button\" aria-current={page === 'points' ? 'page' : undefined} onClick={() => setPage('points')}>迭代投入</button>\n </nav>\n </header>\n {page === 'points' ? <StoryPoints toolbarTarget={setStoryToolbar} onOpenItem={openItem} /> : <>\n {board.error && <div className={css.error} role=\"alert\">{board.error}</div>}\n {board.truncated && <p className={css.notice} role=\"status\">事项数量已达配置上限,当前仅展示前 {board.items.length} 条。</p>}\n <div className={css.board}>\n {statuses.map(status => {\n const items = filteredItems.filter(item => item.status === status)\n return (\n <section\n ref={element => { if (element) laneElements.current.set(status, element); else laneElements.current.delete(status) }}\n className={`${css.lane} ${draggedLane === status ? css.laneDragging : ''} ${dropLane?.status === status ? (dropLane.after ? css.laneDropAfter : css.laneDropBefore) : ''}`}\n key={status}\n aria-labelledby={`tomato-lane-${status}`}\n onDragOver={event => {\n if (!draggedLane || draggedLane === status) return\n event.preventDefault()\n const bounds = event.currentTarget.getBoundingClientRect()\n setDropLane({ status, after: event.clientX >= bounds.left + bounds.width / 2 })\n }}\n onDrop={event => {\n event.preventDefault()\n if (draggedLane && dropLane?.status === status) moveLane(draggedLane, status, dropLane.after)\n setDraggedLane(null)\n setDropLane(null)\n }}\n >\n <header\n className={css.laneHeader}\n draggable\n title=\"拖拽调整泳道顺序\"\n onDragStart={event => {\n event.dataTransfer.effectAllowed = 'move'\n event.dataTransfer.setData('text/plain', status)\n const lane = event.currentTarget.parentElement\n if (lane) {\n const bounds = lane.getBoundingClientRect()\n event.dataTransfer.setDragImage(\n lane,\n Math.min(Math.max(event.clientX - bounds.left, 0), bounds.width),\n Math.min(Math.max(event.clientY - bounds.top, 0), bounds.height),\n )\n }\n setDraggedLane(status)\n }}\n onDragEnd={() => { setDraggedLane(null); setDropLane(null) }}\n >\n <h2 id={`tomato-lane-${status}`}>{status}</h2>\n <span>{items.length}</span>\n </header>\n <div className={css.cards}>\n {items.map(item => (\n <article\n className={`${css.card} ${mutedItems.has(item.itemKey) ? css.cardMuted : ''}`}\n key={item.itemKey}\n tabIndex={0}\n role=\"button\"\n onClick={() => openItem(item)}\n onKeyDown={event => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n openItem(item)\n }\n }}\n >\n <div className={css.cardTopline}>\n <span className={css.key}>{item.itemKey}</span>\n <div className={css.cardButtons}>\n <Button\n className={css.muteButton}\n variant=\"ghost\"\n size=\"sm\"\n title={mutedItems.has(item.itemKey) ? '取消置灰' : '置灰标记'}\n aria-label={mutedItems.has(item.itemKey) ? `取消置灰 ${item.itemKey}` : `置灰 ${item.itemKey}`}\n aria-pressed={mutedItems.has(item.itemKey)}\n onClick={event => {\n event.stopPropagation()\n toggleMutedItem(item.itemKey)\n }}\n onKeyDown={event => event.stopPropagation()}\n >\n ●\n </Button>\n <Button\n className={css.tomatoLink}\n variant=\"ghost\"\n size=\"sm\"\n title=\"在番茄中打开事项\"\n aria-label={`在番茄中打开 ${item.itemKey}`}\n onClick={event => {\n event.stopPropagation()\n window.open(item.tomatoUrl, '_blank', 'noopener,noreferrer')\n }}\n onKeyDown={event => event.stopPropagation()}\n >\n ↗\n </Button>\n </div>\n </div>\n <strong>{item.title}</strong>\n <div className={css.cardMeta}>\n <span className={css.typeTag} style={typeStyle(item.itemType)}>{item.itemType}</span>\n {(item.workspaceName || item.workspaceKey) && <span className={`${css.metaTag} ${css.workspaceTag}`} title=\"空间\">{item.workspaceName && item.workspaceKey && item.workspaceName !== item.workspaceKey ? `${item.workspaceName} (${item.workspaceKey})` : item.workspaceKey || item.workspaceName}</span>}\n {item.priority && <span className={`${css.metaTag} ${css.priorityTag}`} data-priority={priorityLabel(item.priority)} title=\"优先级\">{priorityLabel(item.priority)}</span>}\n {item.creator && <span className={`${css.metaTag} ${css.creatorTag}`} title=\"创建人\">{item.creator}</span>}\n </div>\n </article>\n ))}\n </div>\n </section>\n )\n })}\n {!board.loading && !board.error && statuses.length === 0 && (\n <div className={css.empty}>当前没有可显示的番茄事项</div>\n )}\n </div>\n </>}\n {board.selectedItem ? <CreateConversationDialog ctx={ctx} item={board.selectedItem} /> : null}\n </section>\n )\n}\n\nconst PRIORITY_LABELS: Record<string, string> = {\n '69e65065-4b34-4109-bca9-0154e548554a': 'P0',\n '8f7912a5-9176-4a79-a269-2269ac42b5a2': 'P1',\n 'ca8c3e43-3e7b-444d-8940-d0967d944921': 'P2',\n 'ec31e4c1-b55b-479d-be97-86d5f7bf38ef': 'P2',\n '1a3e1092-7d70-42ee-ad38-0e8d953c4c23': 'P3',\n 'faae52da-28c8-46fc-96dd-db9cdb28b557': 'P4',\n}\nconst priorityLabel = (value: string) => PRIORITY_LABELS[value] ?? value\n\nconst TYPE_TONES: Record<string, string> = {\n Story: '#2f7d72', EnablerStory: '#2777a8', Task: '#7b61a8', Bug: '#c34f43', 缺陷: '#c34f43', 测试缺陷: '#d06438', Epic: '#9a6b24', Feature: '#3f68ad',\n}\nfunction typeTone(type: string): string {\n if (TYPE_TONES[type]) return TYPE_TONES[type]\n const palette = ['#2f7d72', '#2777a8', '#7b61a8', '#c34f43', '#9a6b24', '#51753a', '#a14f78']\n return palette[[...type].reduce((hash, char) => hash + char.charCodeAt(0), 0) % palette.length]!\n}\nfunction typeStyle(type: string) {\n const tone = typeTone(type)\n return { '--type-tone': tone } as React.CSSProperties\n}\n\nfunction FilterRow({ label, options, hidden, onToggle }: {\n label: string\n options: string[]\n hidden: ReadonlySet<string>\n onToggle: (value: string) => void\n}) {\n return (\n <div className={css.filterRow}>\n <span>{label}</span>\n <div>\n {options.map(option => (\n <button\n key={option}\n className={`${hidden.has(option) ? '' : css.selectedFilter} ${label === '类型' ? css.typeFilter : ''}`}\n style={label === '类型' ? typeStyle(option) : undefined}\n type=\"button\"\n aria-pressed={!hidden.has(option)}\n onClick={() => onToggle(option)}\n >\n {label === '类型' && <i aria-hidden=\"true\" />}{option}\n </button>\n ))}\n </div>\n </div>\n )\n}\n\nfunction WorkspaceFilterRow({ options, hidden, onToggle }: {\n options: Array<{ value: string; label: string }>\n hidden: ReadonlySet<string>\n onToggle: (value: string) => void\n}) {\n return (\n <div className={css.filterRow}>\n <span>空间</span>\n <div>\n {options.map(option => (\n <button\n key={option.value}\n className={hidden.has(option.value) ? '' : css.selectedFilter}\n type=\"button\"\n aria-pressed={!hidden.has(option.value)}\n onClick={() => onToggle(option.value)}\n >\n {option.label}\n </button>\n ))}\n </div>\n </div>\n )\n}\n\nfunction AssigneePicker({ users, value, onChange }: {\n users: FilterDirectory['users']\n value: string\n onChange: (value: string) => void\n}) {\n const rootRef = useRef<HTMLDivElement>(null)\n const [open, setOpen] = useState(false)\n const [query, setQuery] = useState('')\n const options = useMemo(() => [{ username: 'currentUser()', name: '我负责的' }, ...users.filter(user => user.username !== 'currentUser()')], [users])\n const selected = options.find(option => option.username === value) ?? options[0]\n const needle = query.trim().toLowerCase()\n const filtered = needle\n ? options.filter(option => `${option.name} ${option.username}`.toLowerCase().includes(needle))\n : options\n\n useEffect(() => {\n if (!open) return\n const close = (event: PointerEvent) => {\n if (event.target instanceof Node && !rootRef.current?.contains(event.target)) setOpen(false)\n }\n document.addEventListener('pointerdown', close, true)\n return () => document.removeEventListener('pointerdown', close, true)\n }, [open])\n\n return (\n <div className={css.assigneeFilter}>\n <span>负责人</span>\n <div ref={rootRef} className={css.assigneePicker}>\n <Button variant=\"outline\" size=\"sm\" className={css.assigneeTrigger} aria-haspopup=\"listbox\" aria-expanded={open} onClick={() => { setOpen(current => !current); setQuery('') }}>\n <span>{selected?.name ?? value}</span><IconChevronDownOutline14 />\n </Button>\n {open ? (\n <div className={css.assigneeDropdown}>\n <input autoFocus type=\"search\" value={query} onChange={event => setQuery(event.target.value)} placeholder=\"搜索昵称或用户名…\" aria-label=\"搜索负责人\" />\n <div role=\"listbox\" aria-label=\"负责人\">\n {filtered.map(option => (\n <button key={option.username} type=\"button\" role=\"option\" aria-selected={option.username === value} onClick={() => { onChange(option.username); setOpen(false); setQuery('') }}>\n <strong>{option.name}</strong>{option.name !== option.username && option.username !== 'currentUser()' ? <small>{option.username}</small> : null}\n </button>\n ))}\n {filtered.length === 0 ? <p>没有匹配的负责人</p> : null}\n </div>\n </div>\n ) : null}\n </div>\n </div>\n )\n}\n\nfunction TomatoConversationShortcut({ ctx, sessionId, useSessions }: PropsRuntime<'conversation.session.header.actions'> & { ctx: Context }) {\n const itemKey = useSessions(state => {\n const summary = state.byId[sessionId]\n const title = summary?.title ?? summary?.displayTitle ?? ''\n const match = TOMATO_ITEM_KEY_PATTERN.exec(title)?.[1]?.trim()\n if (!match) return ''\n // 仅当该对话确实由番茄工作台创建并记录在本机映射中时,才认定它是番茄事项对话。\n // 这样即便普通新建对话的标题恰好命中 itemKey 格式,也不会被误带上状态流转 UI。\n return linkedSessionId(match) === sessionId ? match : ''\n })\n const [menuOpen, setMenuOpen] = useState(false)\n const [loading, setLoading] = useState(false)\n const [transitioning, setTransitioning] = useState(false)\n const [transitionState, setTransitionState] = useState<TomatoTransitionState>({\n currentStatus: '',\n tomatoUrl: '',\n transitions: [],\n })\n const [transitionError, setTransitionError] = useState<string | null>(null)\n\n useEffect(() => {\n if (!itemKey) return\n const controller = new AbortController()\n setLoading(true)\n setTransitionError(null)\n setTransitionState({ currentStatus: '', tomatoUrl: '', transitions: [] })\n void fetch(`/api/tomato-board/transitions/${encodeURIComponent(itemKey)}`, {\n headers: { accept: 'application/json' },\n signal: controller.signal,\n }).then(async response => {\n const body = await response.json() as TomatoTransitionState & { error?: string }\n if (!response.ok) throw new Error(body.error || `请求失败 (${response.status})`)\n setTransitionState({\n currentStatus: body.currentStatus || '',\n tomatoUrl: body.tomatoUrl || '',\n transitions: body.transitions ?? [],\n })\n }).catch(error => {\n if (error instanceof Error && error.name === 'AbortError') return\n setTransitionError(error instanceof Error ? error.message : '番茄流转状态读取失败')\n }).finally(() => {\n if (!controller.signal.aborted) setLoading(false)\n })\n return () => controller.abort()\n }, [itemKey])\n\n if (!itemKey) return null\n\n async function transitionTo(transitionName: string) {\n if (transitioning) return\n setMenuOpen(false)\n setTransitioning(true)\n setTransitionError(null)\n try {\n const query = new URLSearchParams({ transition: transitionName })\n const response = await fetch(`/api/tomato-board/transition/${encodeURIComponent(itemKey)}?${query}`, {\n method: 'POST',\n headers: { accept: 'application/json' },\n })\n const body = await response.json() as {\n currentStatus?: string\n error?: string\n details?: { stderr?: string; stdout?: string }\n }\n if (!response.ok) {\n const selected = transitionState.transitions.find(transition => transition.transition === transitionName)\n const failure = [body.error, body.details?.stderr, body.details?.stdout].filter(Boolean).join('\\n')\n const requiredFieldsMissing = /字段.{0,24}必填|必填.{0,24}字段|流转前需填写/u.test(failure)\n if (selected?.targetStatus === '待测试' && requiredFieldsMissing) {\n const session = ctx.sessions.binding(sessionId)?.session\n if (!session) throw new Error('当前 Harness 对话未加载,无法交给 AI 继续处理')\n const prompt = [\n `番茄事项 ${itemKey} 流转到「待测试」失败,CLI 提示存在必填字段缺失。`,\n '请先读取番茄事项详情,并结合当前对话和仓库代码进行分析。',\n '基于证据补齐并回读确认以下字段:根因分析、RD引入原因分析、原因描述、修复版本、解决方案。',\n '不要编造业务事实;证据不足时先向我确认。',\n '只有这些字段已经持久化且回读一致后,才能重新执行「修复完成」流转到「待测试」,最后再次回读状态验证。',\n `CLI 失败信息:${failure || '未返回具体原因'}`,\n ].join('\\n')\n const prompted = await session.prompt([{ type: 'text', text: prompt }], 'queue')\n if (!prompted.ok) throw new Error(`无法把流转任务交给 AI:${prompted.error.message}`)\n setTransitionError('必填字段缺失,已交给当前对话中的 AI 分析并继续处理')\n return\n }\n throw new Error(failure || `请求失败 (${response.status})`)\n }\n const transitionsResponse = await fetch(`/api/tomato-board/transitions/${encodeURIComponent(itemKey)}`, {\n headers: { accept: 'application/json' },\n })\n const transitionsBody = await transitionsResponse.json() as TomatoTransitionState & { error?: string }\n if (!transitionsResponse.ok) {\n throw new Error(transitionsBody.error || `状态刷新失败 (${transitionsResponse.status})`)\n }\n setTransitionState({\n currentStatus: transitionsBody.currentStatus || body.currentStatus || '',\n tomatoUrl: transitionsBody.tomatoUrl || '',\n transitions: transitionsBody.transitions ?? [],\n })\n } catch (error) {\n setTransitionError(error instanceof Error ? error.message : '番茄事项流转失败')\n } finally {\n setTransitioning(false)\n }\n }\n\n const availableTransitions = transitionState.transitions.filter(transition => !transition.disabled)\n const delegatedToAgent = transitionError?.startsWith('必填字段缺失') === true\n const transitionTitle = transitionError\n ? delegatedToAgent ? transitionError : `番茄流转失败:${transitionError}`\n : loading\n ? '正在查询番茄事项状态'\n : availableTransitions.length === 0\n ? `当前状态「${transitionState.currentStatus || '未知'}」没有可用流转`\n : `当前状态:${transitionState.currentStatus || '未知'}`\n return (\n <>\n <Menu\n open={menuOpen}\n portal\n align=\"end\"\n items={transitionState.transitions.map(transition => ({\n id: transition.transition,\n label: `流转到 ${transition.targetStatus}`,\n disabled: transition.disabled,\n }))}\n onSelect={transitionName => void transitionTo(transitionName)}\n onClose={() => setMenuOpen(false)}\n anchor={(\n <Button\n variant=\"toolbar\"\n size=\"sm\"\n className={css.transitionTrigger}\n title={transitionTitle}\n aria-label={transitionTitle}\n aria-haspopup=\"menu\"\n aria-expanded={menuOpen}\n disabled={loading || transitioning || availableTransitions.length === 0}\n onClick={() => setMenuOpen(open => !open)}\n >\n {transitioning || delegatedToAgent || transitionError\n ? transitioning ? '正在流转…' : delegatedToAgent ? 'AI 已接手' : '流转失败'\n : (\n <>\n <span className={css.transitionCaption}>状态</span>\n <strong>{transitionState.currentStatus || '查询中…'}</strong>\n {availableTransitions.length > 0 ? (\n <>\n <span className={css.transitionDivider} aria-hidden=\"true\" />\n <span className={css.transitionAction}>流转</span>\n <IconChevronDownOutline14 className={css.transitionChevron} />\n </>\n ) : null}\n </>\n )}\n </Button>\n )}\n />\n <Button\n variant=\"toolbar\"\n size=\"sm\"\n title=\"在番茄中打开事项\"\n aria-label={`在番茄中打开 ${itemKey}`}\n disabled={!transitionState.tomatoUrl}\n onClick={() => window.open(transitionState.tomatoUrl, '_blank', 'noopener,noreferrer')}\n >\n 番茄 ↗\n </Button>\n </>\n )\n}\n\nexport const inject = ['slots', 'sessions', 'workspaces']\n\nexport function apply(ctx: Context): void {\n const openWorkbench = () => {\n if (disposeWorkbench) return\n emit({ open: true })\n disposeWorkbench = ctx.slots.register(\n { name: 'conversation', priority: -100 },\n () => <TomatoBoardPanel ctx={ctx} />,\n )\n }\n ctx.slots.inject('conversation.session.header.actions', () => ctx.slots.register(\n { name: 'conversation.session.header.actions', id: 'tomato-shortcut', order: 12 },\n props => <TomatoConversationShortcut {...props} ctx={ctx} />,\n ))\n ctx.slots.inject('sidebar.footer.action', () => ctx.slots.register(\n { name: 'sidebar.footer.action', id: 'tomato-board' },\n props => <TomatoBoardAction {...props} openWorkbench={openWorkbench} />,\n ))\n // The shell's session header is the visible top bar in the Web client. Keep the\n // sidebar shortcut as a compact fallback for narrow or collapsed layouts.\n ctx.slots.inject('conversation.session.header.actions', () => ctx.slots.register(\n { name: 'conversation.session.header.actions', id: 'tomato-board-topbar', order: 11 },\n () => <TomatoBoardTopbarAction openWorkbench={openWorkbench} />,\n ))\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["css","css","Button","IconRefreshOutline16","css","Modal","Button","Menu","IconRefreshOutline16","IconCloseOutline16","IconChevronDownOutline14"],"sources":["../../../packages/core/session/src/types.ts","../../../packages/client/tomato-board/src/client/Tag.tsx","../../../packages/client/tomato-board/src/client/StoryPoints.tsx","../../../packages/client/tomato-board/src/client/TomatoBoard.tsx"],"sourcesContent":["import type { Branded } from '@deepseek-ai/dsh-brand'\nimport type {\n AssistantMessage,\n ToolCallId,\n LlmCallConfig,\n LlmCallConfigAdapterDefaults,\n LlmFailure,\n StreamChunk,\n TokenUsage,\n ToolResultMessage,\n ToolSchema,\n UserMessage,\n} from '@deepseek-ai/dsh-llm'\nimport type { JsonValue } from './json.ts'\n\n// The lossless-JSON payload type belongs to this client-safe face too: a wire\n// contract carrying JSON data must not import the root entry, which merges\n// `ctx.sessions` (a Host-only SessionStore) into every consumer's program.\nexport type { JsonValue } from './json.ts'\n\n/** Identifies one session in the store (and its persistence artifacts). */\nexport type SessionId = Branded<'SessionId'>\n\n/**\n * Brand a string as a {@link SessionId}.\n * @param id - the raw session id string.\n * @returns the same string, branded (a compile-time cast — no runtime cost).\n */\nexport function SessionId(id: string): SessionId {\n return id as SessionId\n}\n\n/**\n * The on-disk session format version, stamped into every newly-written {@link SessionHeader}\n * and enforced by every persistence backend on load. The single source of truth for the\n * version — write sites and the load-time check all read it.\n * While the harness is unreleased it is pinned at `0`: no compatibility is\n * implied, incompatible logs are rejected, and no migration is provided.\n *\n * The version is a single monotonic integer with no major/minor split. Whether\n * a bump is needed is decided by what the WRITER emits, never by what a newer\n * reader can accept: bump exactly when an older runtime could no longer handle\n * a new log with full semantic correctness (\"parses without error\" is not\n * correctness — silently skipping content that shapes reconstruction is a\n * wrong read). Only structural changes reach that bar: the header shape, the\n * {@link SessionEvent} envelope, core event semantics, or the surface\n * mechanism (the {@link SurfaceEventType} set and {@link SurfaceOp} variants).\n * Adding an ordinary event type does not bump: the generated known-event guard\n * makes older runtimes refuse logs containing a type they do not understand.\n * When in doubt, bump: a near-identity upgrade step is almost free, a missed\n * bump makes older runtimes read new logs wrong silently. The full mechanism\n * (upgrade-step chain, in-memory view conversion, migrate-on-continue) is\n * recorded in the fail-closed-session-event-vocabulary Agent Note\n * (`.agents/notes/implemented/simplification/2026-08-25-fail-closed-session-event-vocabulary.md`).\n */\nexport const SESSION_FORMAT_VERSION = 0\n\n/**\n * Immutable validated storage metadata, kept outside the conversation event log.\n */\nexport interface SessionHeader {\n /**\n * On-disk format version, stamped from {@link SESSION_FORMAT_VERSION} when the\n * session is created. A persistence backend rejects any other version on load\n * (no migration — see the constant).\n */\n readonly version: number\n /** The session's id (mirrors the {@link Session}'s id). */\n readonly id: SessionId\n /** Non-negative safe-integer Unix epoch milliseconds when the session was created. */\n readonly createdAt: number\n /** Absolute working directory the session was created in (if any). */\n readonly cwd?: string\n /** The session this one was forked from (seed lineage), if any. */\n readonly parentSession?: SessionId\n /**\n * How many leading events were inherited through a seed. Persisting this\n * boundary lets resume and replay distinguish parent history from child work.\n */\n readonly seedLength?: number\n /**\n * Coarse product classification for a session created as a subagent child.\n * This is presentation metadata, not proof that the child is continuable.\n */\n readonly origin?: 'subagent'\n /**\n * Delegation depth: absent (zero) for a top-level session, parent depth + 1\n * for a subagent child. Persisted so a recursion budget survives restart and\n * resume — a runtime-only depth would reset a resumed child to top-level.\n */\n readonly delegationDepth?: number\n /**\n * Id of the agent preset this session's agent was composed from, when the\n * deployment composes per session. Durable because the preset decides the\n * session's tools and prompt: a resume that restored a different composition\n * would replay history the model can no longer act on.\n */\n readonly agentPreset?: string\n}\n\n/**\n * Options for creating a {@link Session} via the store. `seed` replays/forks\n * an existing event log; `meta` carries the caller-supplied storage fields the\n * store folds into a {@link SessionHeader}.\n */\nexport interface CreateSessionOptions {\n /** Initial replay or fork history supplied at construction. */\n readonly seed?: readonly SessionEvent[]\n /**\n * Storage metadata read once before publication. `seedLength` is explicit\n * because a resumed seed contains the full stored log, not only its inherited prefix.\n */\n readonly meta?: {\n readonly cwd?: string\n readonly parentSession?: SessionId\n readonly createdAt?: number\n readonly seedLength?: number\n readonly origin?: 'subagent'\n readonly delegationDepth?: number\n readonly agentPreset?: string\n }\n}\n\n/**\n * Fresh storage values transferred to {@link SessionStore.prepare} without a\n * second serialization copy. Callers retain no mutable aliases.\n */\nexport interface RestoredSessionOptions {\n /** Fresh detached storage events to validate and freeze in place. */\n readonly seed: SessionEvent[]\n /** Fresh detached storage metadata to validate and freeze in place. */\n readonly meta: SessionHeader\n /** Select the persistence ownership-transfer path. */\n readonly seedSource: 'persistence'\n}\n\n/** Inputs accepted while constructing an unpublished Session. */\nexport type PrepareSessionOptions =\n | (CreateSessionOptions & { readonly seedSource?: undefined })\n | RestoredSessionOptions\n\n/** Why an active agent driver was cancelled. */\nexport type AgentCancelCause =\n | { readonly kind: 'user' }\n | { readonly kind: 'parent' }\n | { readonly kind: 'hook'; readonly reason: string }\n | { readonly kind: 'disposed' }\n\n/** Durable cancellation cause, including imports whose original coarse record carried no cause. */\nexport type TurnEndCancelCause = AgentCancelCause | { readonly kind: 'legacy' }\n\n/**\n * Why a turn ended. Merge-extensible sum type.\n */\nexport interface TurnEndReasonMap {\n completed: { kind: 'completed' }\n /** A cancellation request interrupted the live turn. */\n aborted: { kind: 'aborted'; reason: TurnEndCancelCause }\n\n blocked: { kind: 'blocked' }\n /**\n * The turn failed. `error` is always a structured failure: the `LlmError`\n * facts verbatim, or `{ message: errorChain(error), code: 'UNKNOWN' }`\n * flattened from any other error.\n */\n error: { kind: 'error'; error: LlmFailure }\n /** At least one step reached its output-token ceiling, even if a plugin continued the turn. */\n 'max-tokens': { kind: 'max-tokens' }\n /**\n * A persistence backend closed a crash-orphaned turn on reload. The loop never\n * emits this marker, and the events recorded before the crash remain intact.\n */\n interrupted: { kind: 'interrupted' }\n}\n\n/** The union over {@link TurnEndReasonMap} — why a turn ended; plugins extend it by merging variants into the map. */\nexport type TurnEndReason = TurnEndReasonMap[keyof TurnEndReasonMap]\n\n/**\n * Logged request state outside derived history: call config, system prompt, and\n * tools. The latest full `request/header` snapshot reconstructs it; canonical\n * empty optional fields are absent.\n */\nexport interface EpochHeader {\n /** The conversation's call configuration (provider, model, reasoning effort, and sampling scalars). */\n config: LlmCallConfig\n /** Effective config fields materialized from the exact adapter rather than proposed by a caller. */\n adapterDefaults?: LlmCallConfigAdapterDefaults\n /** Rendered system prompt text; absent for a system-less request. */\n system?: string\n /** Assembled tool schemas; absent for a tool-less request. */\n tools?: ToolSchema[]\n}\n\n/** Registration-bound metadata for one resolved model route. */\nexport interface RequestContext {\n /** Registered provider route the metadata belongs to. */\n provider: string\n /** Provider-owned model id the metadata belongs to. */\n model: string\n /** Maximum combined request and response context in tokens, when advertised. */\n contextWindow?: number\n}\n\n/**\n * Why a `request/header` snapshot was appended: `'initial'` — the log's first\n * header (a new conversation); `'resume'` — a loop instance's first request\n * over a log that already has header events (process restart, fork seed);\n * `'change'` — a later request used a different header, with `startsSeries`\n * preserving a coincident series boundary; `'series'` — an unchanged header\n * began an explicitly distinct message series or followed a surface replacement.\n */\nexport type RequestHeaderReason = 'initial' | 'resume' | 'change' | 'series'\n\n/**\n * The merge-extensible, append-only source of truth for an agent interaction.\n * Message history is derived from this log. Every event is lossless JSON and\n * sequence numbers stay contiguous, including raw chunks, so persistence can\n * store the canonical log verbatim.\n */\nexport interface SessionEventMap {\n /**\n * Opens turn `turn` before the loop claims queued input or runs pre-step.\n * Rejection, empty input, cancellation, or failure may close it with no\n * step; otherwise the following identified `user/message` event or batch\n * records the messages entering the step.\n */\n 'turn/start': { turn: number }\n /**\n * Closes turn `turn` with the {@link TurnEndReason} that ended it. A turn\n * with no entered step has no `step/start` or `step/end`. The loop does not await a\n * flush at turn boundaries: `dsh-session-checkpoint-policy` owns the\n * per-request durability checkpoint, and consumers that read storage after\n * `whenIdle()` flush themselves. Success commits the turn; rejection is\n * reported live and does not prevent later work.\n */\n 'turn/end': { turn: number; reason: TurnEndReason }\n /** Opens step `step` of turn `turn` — one model call plus the tool executions it requested. */\n 'step/start': { turn: number; step: number }\n /** Closes step `step` of turn `turn`. */\n 'step/end': { turn: number; step: number }\n /**\n * A user-role message on the model-visible surface: a direct human prompt\n * (the queued message claimed for this turn), a synthetic `agent.inject()`\n * context (file-change notices, subdir AGENTS.md, skill content, cron\n * notifications, …), or an entered goal continuation round. All three\n * project their `content` verbatim; `source` tells them apart.\n */\n 'user/message': UserMessage\n /** Raw stream chunk — token-level replay fidelity. */\n 'assistant/chunk': { turn: number; step: number; chunk: StreamChunk }\n /**\n * Assembled assistant message for one step (derived history uses this).\n * Carries the step's `usage` when the adapter reported token accounting, so\n * the model output and its accounting travel together (there is no separate\n * usage record). `usage` is absent when the adapter reported none. A turn\n * cancelled mid-stream finalizes its delivered text/reasoning prefix as this\n * event with `interrupted: true`; undispatched tool calls are absent. The\n * marker distinguishes that prefix without re-deriving interruption from turn\n * boundaries. An aborted turn with no such event streamed no visible content.\n */\n 'assistant/message': { turn: number; step: number; message: AssistantMessage; usage?: TokenUsage; interrupted?: true }\n /**\n * The model requested one tool invocation: `name` with the raw `arguments`\n * JSON string exactly as the model produced it (unparsed). `callId` pairs the\n * call with its `tool/result`.\n */\n 'tool/call': { turn: number; step: number; callId: ToolCallId; name: string; arguments: string }\n /**\n * A completed tool call's model-facing result, optional internal failure\n * identity, and optional tool-private `meta` presentation payload. `meta` is\n * opaque to the core (the producing tool owns its shape and reads it back in\n * `presentResult`) but MUST be JSON-serializable: `Session.append`\n * runtime-validates all event data with `isJsonValue`, so a non-serializable\n * `meta` is rejected at the source, and the durable log reproduces the\n * identical card on replay. Absent\n * unless the tool attaches one (e.g. `dsh-tool-fs` carries its result-time\n * contextual diff here).\n */\n 'tool/result': {\n turn: number\n step: number\n message: ToolResultMessage\n error?: { name: string; code: string }\n meta?: JsonValue\n }\n /**\n * Full header for the next request, appended inside its step before dispatch.\n * It is log-only; the latest snapshot reconstructs the request header.\n */\n 'request/header': {\n header: EpochHeader\n reason: RequestHeaderReason\n /** A changed header also begins a distinct model-message series. */\n startsSeries?: true\n }\n /**\n * Route metadata for the next request, logged only when the route or capacity\n * changes. It does not participate in request reconstruction or header equality.\n */\n 'request/context': RequestContext\n /**\n * Marks the end of a constructor seed. Events before it have smaller seq\n * values and came from the seed (resume, fork, or replay); this lifecycle\n * produced none of them. This log-only event is the durable projection of\n * {@link Session.firstLiveSeq}. Its payload is empty — position and `time`\n * carry the meaning.\n *\n * Locate the LAST one in stored history. A seed already ending in one is not\n * re-marked, so reopening an untouched session does not grow its log per\n * pickup and the event need not be at the current `firstLiveSeq`.\n *\n * `Session`'s constructor is the only legitimate writer. The invariant\n * companion deliberately constrains nothing here, so a plugin appending one\n * would silently classify every live bracket before it as seed history.\n *\n * An owner of a standalone open/close bracket (`compaction/start` …\n * `compaction/end`) reads it because seed history and live work are otherwise\n * byte-identical: an unmatched opening marker before this event belongs to\n * an ended lifecycle, whatever ended it. NOT a liveness signal about other\n * writers — a concurrently live session holds its own boundary elsewhere,\n * so tolerating concurrent writers needs a signal beyond the log.\n */\n 'session/end-seed': Record<string, never>\n}\n\n/** The appendable event-type keys of {@link SessionEventMap}, plugin-merged extensions included. */\nexport type SessionEventType = keyof SessionEventMap\n\n/**\n * The subset of {@link SessionEventType} values whose events produce LLM\n * messages and are eligible to appear on the ordered surface. Only these\n * event types may carry {@link SurfaceOp} and {@link SessionEvent.sourceEventSeqs}.\n */\nexport type SurfaceEventType =\n | 'user/message'\n | 'assistant/message'\n | 'tool/result'\n\n/**\n * A {@link SessionEvent} that is **on** the ordered surface — its\n * `surfaceOp` is guaranteed present (mandatory), narrowed from a\n * surface-eligible {@link SessionEvent} by checking both `type` and\n * `surfaceOp` at runtime.\n *\n * Use the `isSurfaceEvent` type guard (in `surface.ts`) to narrow a\n * `SessionEvent` to this type.\n */\nexport type SurfaceEvent = SessionEvent<SurfaceEventType> & { surfaceOp: SurfaceOp }\n\n/**\n * How a session event entered the ordered surface. Only valid on\n * {@link SurfaceEventType} events.\n *\n * - `'append'`: added to the tail — normal path for user/assistant/tool\n * messages.\n * - `{ op: 'replace', start, end }`: replaces surface nodes from `start`\n * (inclusive) through `end` (inclusive) with this node. Both must exist as\n * surface nodes in the current surface. `start === end` replaces a single\n * node. The node's {@link SessionEvent.sourceEventSeqs} must include every\n * shadowed surface node. Used by compaction; any surface-replacing producer\n * may use it.\n */\nexport type SurfaceOp =\n | 'append'\n | { op: 'replace'; start: number; end: number }\n\n/**\n * Surface placement and cited source-event seqs for {@link Session.append}. Required on\n * message-producing events and forbidden on log-only events.\n */\nexport interface SurfaceIntent {\n surfaceOp: SurfaceOp\n /**\n * Complete set of known source-event seqs. `assistant/message` may use a\n * present empty array for a known empty provider stream; when the field is\n * absent, the event does not record which earlier events produced the message.\n * Other surface events require a non-empty set when this field is present.\n */\n sourceEventSeqs?: number[]\n}\n\n/**\n * One immutable entry in the session log.\n *\n * A proper discriminated union over `type` (not independent `type`/`data`\n * unions), so `switch (event.type)` narrows `event.data` without casts.\n *\n * The {@link sourceEventSeqs} and {@link surfaceOp} fields are conditional:\n * they only exist on {@link SurfaceEventType} variants (`user/message`,\n * `assistant/message`, `tool/result`).\n * Non-surface events (boundary markers, chunks, usage, errors) never carry\n * surface metadata — the compiler enforces this at `Session.append()`\n * call sites.\n */\nexport type SessionEvent<T extends SessionEventType = SessionEventType> = {\n [K in SessionEventType]: {\n type: K\n /** Monotonic sequence number within the session. */\n seq: number\n /** Unix epoch milliseconds. */\n time: number\n data: SessionEventMap[K]\n } & (K extends SurfaceEventType ? {\n /**\n * Seq numbers of earlier events that this event cites as sources\n * (e.g. the `assistant/chunk` seqs that built an `assistant/message`,\n * or the surface nodes shadowed by a compaction replace node). An\n * `assistant/message` may carry a present empty array for a known empty\n * provider stream; when the field is absent, the event does not record which\n * earlier events produced the message.\n */\n sourceEventSeqs?: number[]\n /** How this event entered the surface; absent for non-surface events. */\n surfaceOp?: SurfaceOp\n } : object)\n}[T]\n","import type { CSSProperties, ReactNode } from 'react'\nimport css from './tag.module.css'\n\nexport interface TagProps {\n children: ReactNode\n /** Tint color (hex or CSS color var). Omit for the neutral card-meta look. */\n tone?: string | undefined\n /** Render as a toggle button (filter chips) instead of a static span. */\n interactive?: boolean\n /** Toggle state for interactive tags; false renders the dimmed-off look. */\n pressed?: boolean | undefined\n title?: string | undefined\n className?: string | undefined\n onClick?: (() => void) | undefined\n}\n\n/**\n * The one tag chip used across the workbench — card metadata, filter chips and\n * status labels. Static usage renders a span; interactive usage renders a\n * toggle button. Only callers that pass `tone` get a colored chip (by\n * convention just the item-type tags).\n */\nexport function Tag({ children, tone, interactive = false, pressed, title, className, onClick }: TagProps) {\n const style = tone === undefined ? undefined : { '--tag-tone': tone } as CSSProperties\n const classes = [\n css.tag,\n tone === undefined ? '' : css.toned,\n interactive ? css.toggle : '',\n interactive && pressed === false ? css.off : '',\n className,\n ].filter(Boolean).join(' ')\n if (interactive) {\n return (\n <button type=\"button\" className={classes} style={style} title={title} aria-pressed={pressed} onClick={onClick}>\n {children}\n </button>\n )\n }\n return <span className={classes} style={style} title={title}>{children}</span>\n}\n","import { useEffect, useMemo, useRef, useState } from 'react'\nimport type { Dispatch, ReactNode, SetStateAction } from 'react'\nimport { Button, IconRefreshOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'\nimport css from './story-points.module.css'\nimport { Tag } from './Tag'\nimport type { TomatoItem } from './TomatoBoard'\n\ntype User = { username: string; name: string }\ntype Sprint = { sprintId: string; name: string; workspaceKey: string; status: string; startDate?: string }\ntype Item = TomatoItem & { storyPoints: number | null }\ntype Result = { items: Item[]; truncated: boolean }\ntype Team = { id: string; name: string; members: string[] }\nconst LEGACY_TEAM_KEY = 'taskboard.tomatoStoryTeam.v1'\nconst TEAMS_KEY = 'taskboard.tomatoStoryTeams.v2'\nconst SPRINT_KEY = 'taskboard.tomatoStorySprint.v1'\nconst OWNER_KEY = 'taskboard.tomatoStoryOwner.v1'\nconst colors = ['#d76b50', '#458e88', '#c79940', '#687fb2', '#976f9c', '#75914f', '#be7f92', '#698b9d']\nconst number = (value: number) => new Intl.NumberFormat('zh-CN', { maximumFractionDigits: 4 }).format(value)\nconst total = (items: Item[]) => items.reduce((sum, item) => sum + (item.storyPoints ?? 0), 0)\nconst savedValue = (key: string, fallback: string) => { try { return localStorage.getItem(key) || fallback } catch { return fallback } }\nconst teamId = () => `team-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`\nasync function json<T>(url: string, signal?: AbortSignal): Promise<T> {\n const response = await fetch(url, { signal: signal ?? null, cache: 'no-store', headers: { accept: 'application/json', 'cache-control': 'no-cache' } }); const text = await response.text(); let body: Record<string, unknown>\n try { body = text ? JSON.parse(text) as Record<string, unknown> : {} } catch { throw new Error(response.status === 404 || text.trim() === 'not found' ? '迭代故事点接口尚未加载,请完全重启 DSH Desktop' : `服务返回了无法识别的内容 (${response.status})`) }\n if (!response.ok) throw new Error(typeof body.error === 'string' ? body.error : `请求失败 (${response.status})`); return body as T\n}\nfunction readTeams(): Team[] {\n try {\n const saved: unknown = JSON.parse(localStorage.getItem(TEAMS_KEY) ?? '[]')\n if (Array.isArray(saved) && saved.length) return saved.flatMap(value => value && typeof value === 'object' ? [{ id: String((value as Team).id), name: String((value as Team).name), members: Array.isArray((value as Team).members) ? [...new Set((value as Team).members)] : [] }] : [])\n const legacy: unknown = JSON.parse(localStorage.getItem(LEGACY_TEAM_KEY) ?? '[]')\n return Array.isArray(legacy) && legacy.length ? [{ id: 'team-default', name: '默认团队', members: legacy.filter((value): value is string => typeof value === 'string') }] : []\n } catch { return [] }\n}\n\nexport function StoryPoints({ toolbarTarget, onOpenItem }: { toolbarTarget: Dispatch<SetStateAction<ReactNode>>; onOpenItem: (item: TomatoItem) => void }) {\n const [sprints, setSprints] = useState<Sprint[]>([]); const [users, setUsers] = useState<User[]>([])\n const [sprint, setSprint] = useState(() => savedValue(SPRINT_KEY, '')); const [owner, setOwner] = useState(() => savedValue(OWNER_KEY, 'currentUser()'))\n const [teams, setTeams] = useState(readTeams); const [openTeamId, setOpenTeamId] = useState(() => readTeams()[0]?.id ?? '')\n const [loadedTeams, setLoadedTeams] = useState<Set<string>>(() => { const first = readTeams()[0]?.id; return new Set(first ? [first] : []) }); const [teamDraft, setTeamDraft] = useState(''); const [teamEditor, setTeamEditor] = useState<{ mode: 'create' | 'rename'; id?: string } | null>(null)\n const [addingTeamId, setAddingTeamId] = useState(''); const addPeopleRef = useRef<HTMLDivElement>(null); const addPeopleInputRef = useRef<HTMLInputElement>(null); const [search, setSearch] = useState('')\n const [results, setResults] = useState<Record<string, Result>>({}); const [errors, setErrors] = useState<Record<string, string>>({}); const [directoryError, setDirectoryError] = useState(''); const [directoryLoading, setDirectoryLoading] = useState(true); const [version, setVersion] = useState(0); const [directoryVersion, setDirectoryVersion] = useState(0)\n useEffect(() => {\n const controller = new AbortController(); setDirectoryLoading(true); setDirectoryError('')\n void Promise.all([json<{ sprints: Sprint[] }>('/api/tomato-board/sprints', controller.signal), json<{ users: User[] }>('/api/tomato-board/filters', controller.signal)]).then(([data, directory]) => { const sorted = [...data.sprints].sort((a, b) => (b.startDate ?? '').localeCompare(a.startDate ?? '')); setSprints(sorted); setUsers(directory.users); setSprint(current => sorted.some(value => value.sprintId === current) ? current : sorted[0]?.sprintId || '') }).catch(error => { if (!controller.signal.aborted) setDirectoryError(error.message) }).finally(() => { if (!controller.signal.aborted) setDirectoryLoading(false) }); return () => controller.abort()\n }, [directoryVersion])\n useEffect(() => { try { localStorage.setItem(TEAMS_KEY, JSON.stringify(teams)) } catch {} }, [teams]); useEffect(() => { if (sprint) try { localStorage.setItem(SPRINT_KEY, sprint) } catch {} }, [sprint]); useEffect(() => { try { localStorage.setItem(OWNER_KEY, owner) } catch {} }, [owner])\n const openTeam = teams.find(team => team.id === openTeamId); const openMembers = openTeam?.members ?? []; const ownersKey = JSON.stringify([...new Set([owner, ...(loadedTeams.has(openTeamId) ? openMembers : [])])].sort())\n useEffect(() => {\n if (!sprint) return; const controller = new AbortController(); const owners = (JSON.parse(ownersKey) as string[]).filter(username => !results[username] && !errors[username])\n const worker = async () => { while (owners.length && !controller.signal.aborted) { const username = owners.shift()!; try { const data = await json<Result>(`/api/tomato-board/story-points?${new URLSearchParams({ sprint, assignee: username, refresh: String(version) })}`, controller.signal); if (!controller.signal.aborted) setResults(current => ({ ...current, [username]: data })) } catch (error) { if (!controller.signal.aborted) setErrors(current => ({ ...current, [username]: error instanceof Error ? error.message : '读取失败' })) } } }; void Promise.all([worker(), worker(), worker()]); return () => controller.abort()\n }, [sprint, ownersKey, version])\n const personal = results[owner]; const items = useMemo(() => [...(personal?.items ?? [])].sort((a, b) => (b.storyPoints ?? -1) - (a.storyPoints ?? -1) || a.itemKey.localeCompare(b.itemKey)), [personal]); const sum = total(items); const slices = items.filter(item => item.storyPoints !== null && item.storyPoints > 0); let offset = 0\n const gradient = slices.map((item, index) => { const start = offset; offset += item.storyPoints! / sum * 100; return `${colors[index % colors.length]} ${start}% ${offset}%` }).join(', '); const userName = (username: string) => username === 'currentUser()' ? '我' : users.find(user => user.username === username)?.name ?? username\n const toggleTeam = (id: string) => { setOpenTeamId(current => current === id ? '' : id); setLoadedTeams(current => new Set(current).add(id)); setAddingTeamId(''); setTeamEditor(null) }\n const ranking = openMembers.map(username => ({ username, result: results[username], points: total(results[username]?.items ?? []) })).sort((a, b) => Number(Boolean(b.result)) - Number(Boolean(a.result)) || b.points - a.points || a.username.localeCompare(b.username)); const max = Math.max(1, ...ranking.map(row => row.points)); const available = users.filter(user => !openMembers.includes(user.username) && `${user.name} ${user.username}`.toLowerCase().includes(search.toLowerCase()))\n const submitTeam = () => { const name = teamDraft.trim(); if (!name || !teamEditor) return; if (teamEditor.mode === 'create') { const team = { id: teamId(), name, members: [] }; setTeams(current => [...current, team]); setOpenTeamId(team.id); setLoadedTeams(current => new Set(current).add(team.id)) } else setTeams(current => current.map(team => team.id === teamEditor.id ? { ...team, name } : team)); setTeamDraft(''); setTeamEditor(null) }\n const deleteTeam = (id: string) => { setTeams(current => current.filter(team => team.id !== id)); if (openTeamId === id) setOpenTeamId(''); setLoadedTeams(current => { const next = new Set(current); next.delete(id); return next }) }\n const updateMembers = (id: string, updater: (values: string[]) => string[]) => setTeams(current => current.map(team => team.id === id ? { ...team, members: updater(team.members) } : team))\n useEffect(() => { if (!addingTeamId) return; const close = (event: PointerEvent) => { if (event.target instanceof Node && !addPeopleRef.current?.contains(event.target)) { setAddingTeamId(''); setSearch('') } }; document.addEventListener('pointerdown', close, true); requestAnimationFrame(() => addPeopleInputRef.current?.focus()); return () => document.removeEventListener('pointerdown', close, true) }, [addingTeamId])\n useEffect(() => { toolbarTarget(<div className={css.headerControls}><label><span>迭代</span><select aria-label=\"选择迭代\" value={sprint} disabled={directoryLoading} onChange={event => { setSprint(event.target.value); setResults({}); setErrors({}); setLoadedTeams(new Set()) }}>{!sprints.length && <option value=\"\">{directoryLoading ? '正在读取迭代…' : '暂无迭代'}</option>}{sprints.map(value => <option key={value.sprintId} value={value.sprintId}>{value.name} · {value.workspaceKey}{value.status === 'completed' ? '(已结束)' : ''}</option>)}</select></label><Button variant=\"toolbar\" size=\"sm\" className={css.headerIconButton} icon={<IconRefreshOutline16 />} title=\"刷新\" aria-label=\"刷新迭代故事点\" onClick={() => { setResults({}); setErrors({}); setVersion(value => value + 1); if (directoryError || !sprints.length) setDirectoryVersion(value => value + 1) }} /></div>); return () => toolbarTarget(null) }, [directoryError, directoryLoading, sprint, sprints, toolbarTarget])\n return <div className={css.page}>{directoryError && <p className={css.error}>{directoryError},请点击刷新重试。</p>}<div className={css.columns}>\n <section className={css.panel} aria-label=\"个人故事点\"><div className={css.panelHeader}><h3>个人分布</h3><select aria-label=\"选择个人负责人\" value={owner} onChange={event => setOwner(event.target.value)}><option value=\"currentUser()\">我负责的</option>{users.map(user => <option key={user.username} value={user.username}>{user.name} · {user.username}</option>)}</select></div>{errors[owner] ? <p className={css.error}>{errors[owner]}</p> : !personal ? <p className={css.empty}>{sprint ? '正在读取个人故事点…' : '请选择迭代'}</p> : <><div className={css.summary}><div><span className={css.eyebrow}>故事点总数</span><div className={css.total}>{number(sum)}<small> SP</small></div></div><div className={css.pie} style={{ background: gradient ? `conic-gradient(${gradient})` : undefined }}><div><strong>{slices.length}</strong><span>项占比</span></div></div></div><div className={css.listHeading}><h4>需求列表</h4><span>{items.length} 项</span></div>{!items.length && <p className={css.empty}>该负责人在本迭代暂无事项。</p>}<div>{items.map(item => <div className={css.item} key={item.itemKey} role=\"button\" tabIndex={0} aria-label={`打开 ${item.itemKey} 的对话`} onClick={() => onOpenItem(item)} onKeyDown={event => { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); onOpenItem(item) } }}><span className={css.dot} style={{ background: item.storyPoints && item.storyPoints > 0 ? colors[slices.indexOf(item) % colors.length] : 'var(--dsw-alias-border-l2, #ddd)' }} /><div className={css.itemText}><span className={css.itemTitle}>{item.title}</span><small>{item.itemKey}</small><Tag>{item.status}</Tag></div><strong className={css.itemPoints}>{item.storyPoints === null ? '未估点' : `${number(item.storyPoints)} SP`}</strong><Button className={css.tomatoLink} variant=\"ghost\" size=\"sm\" title=\"在番茄中打开事项\" aria-label={`在番茄中打开 ${item.itemKey}`} onClick={event => { event.stopPropagation(); window.open(item.tomatoUrl, '_blank', 'noopener,noreferrer') }} onKeyDown={event => event.stopPropagation()}>↗</Button></div>)}</div></>}</section>\n <section className={css.panel} aria-label=\"团队故事点\"><div className={css.teamsHeader}><h3>团队分布</h3><button className={css.addTeamButton} aria-label=\"创建团队\" title=\"创建团队\" onClick={() => { setTeamEditor({ mode: 'create' }); setTeamDraft('') }}>+ 创建团队</button></div>{teamEditor?.mode === 'create' && <form className={css.teamEditor} onSubmit={event => { event.preventDefault(); submitTeam() }}><input autoFocus placeholder=\"团队名称\" value={teamDraft} onChange={event => setTeamDraft(event.target.value)} /><button type=\"button\" onClick={() => setTeamEditor(null)}>取消</button><button type=\"submit\">创建</button></form>}<div className={css.teamAccordions}>{teams.map(team => { const open = openTeamId === team.id; const rows = open ? ranking : []; return <article className={css.teamAccordion} key={team.id}><div className={css.teamAccordionHeader}><button className={css.teamToggle} aria-expanded={open} onClick={() => toggleTeam(team.id)}><span className={css.chevron}>›</span><strong>{team.name}</strong><small>{team.members.length} 人</small></button><button className={css.renameTeam} aria-label={`改名 ${team.name}`} title=\"改名\" onClick={() => { setTeamEditor({ mode: 'rename', id: team.id }); setTeamDraft(team.name); setOpenTeamId(team.id) }}>✎</button><div className={css.teamRowActions}><button aria-label={`删除 ${team.name}`} title=\"删除\" onClick={() => deleteTeam(team.id)}>×</button></div></div>{teamEditor?.mode === 'rename' && teamEditor.id === team.id && <form className={css.teamEditor} onSubmit={event => { event.preventDefault(); submitTeam() }}><input autoFocus value={teamDraft} onChange={event => setTeamDraft(event.target.value)} /><button type=\"button\" onClick={() => setTeamEditor(null)}>取消</button><button type=\"submit\">保存</button></form>}{open && <div className={css.teamBody}><div className={css.teamBodyToolbar}><span>{team.members.length ? '成员故事点' : '暂无成员'}</span><div ref={addingTeamId === team.id ? addPeopleRef : undefined} className={css.addPeopleRoot}><button className={css.smallAddButton} onClick={() => setAddingTeamId(current => current === team.id ? '' : team.id)}>+ 添加成员</button>{addingTeamId === team.id && <div className={css.addPeople} role=\"dialog\"><div className={css.addPeopleTitle}><strong>添加成员</strong><button onClick={() => setAddingTeamId('')}>×</button></div><input ref={addPeopleInputRef} value={search} onChange={event => setSearch(event.target.value)} placeholder=\"搜索姓名或用户名…\" /><div>{available.map(user => <button key={user.username} onClick={() => { updateMembers(team.id, current => [...current, user.username]); setAddingTeamId(''); setSearch('') }}>{user.name}<small>{user.username}</small><span>+</span></button>)}{!available.length && <p>没有可添加的成员</p>}</div></div>}</div></div><div className={css.ranking}>{rows.map((row, index) => <div key={row.username} className={css.rankRow}><div className={css.memberRow}><button className={css.rankLabel} aria-pressed={owner === row.username} onClick={() => setOwner(row.username)}><i className={css.rankFill} style={{ width: `${row.points / max * 100}%` }} /><span className={css.rankIndex}>{String(index + 1).padStart(2, '0')}</span><span className={css.memberAvatar}>{userName(row.username).slice(0, 1)}</span><span className={css.memberIdentity}><strong>{userName(row.username)}</strong><small>{row.result ? `${row.result.items.length} 个事项` : errors[row.username] ? '读取失败' : '读取中…'}</small></span><b>{row.result ? `${number(row.points)} SP` : '—'}</b></button><button className={css.removeMember} aria-label={`移除 ${userName(row.username)}`} title=\"移除成员\" onClick={() => updateMembers(team.id, current => current.filter(value => value !== row.username))}>×</button></div></div>)}</div>{!team.members.length && <div className={css.teamBodyEmpty}>添加成员后查看故事点分布</div>}</div>}</article> })}</div>{!teams.length && <div className={css.empty}>点击右上角加号创建团队。</div>}</section>\n </div></div>\n}\n","import { useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'\nimport type { Context } from '@deepseek-ai/cordis'\nimport type {} from '@deepseek-ai/dsh-api-session-controller/client'\nimport type { WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport type {} from '@deepseek-ai/dsh-api-workspace-controller/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-layout/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-sidebar/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport {\n Button, IconChevronDownOutline14, IconCloseOutline16, IconRefreshOutline16, Menu, Modal,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { MenuEntry } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport { SessionId } from '@deepseek-ai/dsh-session/types'\nimport css from './tomato-board.module.css'\nimport { StoryPoints } from './StoryPoints'\nimport { Tag } from './Tag'\n\nexport interface TomatoItem {\n itemKey: string\n title: string\n status: string\n itemType: string\n workspace: string\n workspaceKey: string\n workspaceName: string\n creator: string\n assignees: string[]\n priority: string\n tomatoUrl: string\n}\n\ninterface FilterDirectory {\n users: Array<{ username: string; name: string }>\n workspaces: Array<{ key: string; name: string }>\n}\n\ninterface LaneOrder {\n head: string | null\n next: Record<string, string | null>\n}\n\ninterface TomatoTransition {\n transition: string\n targetStatus: string\n disabled: boolean\n disabledReason?: string\n}\n\ninterface TomatoTransitionState {\n currentStatus: string\n tomatoUrl: string\n transitions: TomatoTransition[]\n}\n\ninterface BoardState {\n open: boolean\n loading: boolean\n // 本次打开期间已成功加载过一次的标记:空列表也算加载完成,\n // 用来区分「还没加载」和「加载了但结果为空」。\n loaded: boolean\n items: TomatoItem[]\n error: string | null\n selectedItem: TomatoItem | null\n truncated: boolean\n}\n\nlet state: BoardState = { open: false, loading: false, loaded: false, items: [], error: null, selectedItem: null, truncated: false }\nlet disposeWorkbench: (() => void) | null = null\nconst listeners = new Set<() => void>()\nconst emit = (patch: Partial<BoardState>) => {\n state = { ...state, ...patch }\n for (const listener of listeners) listener()\n}\nconst subscribe = (listener: () => void) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n}\nconst snapshot = () => state\n\n// 真实番茄事项 itemKey 形如 `Gitee-Test-2026-737`、`Proxima-1116`:字母前缀(可含连字符分段)+ 数字结尾。\n// 只匹配该格式可避免把任意 `[xxx]` 开头的普通对话标题(如 `[分析]`、`[每日复盘]`)误判为番茄事项,\n// 进而错误地在对话头上渲染出状态流转按钮并触发无意义的 CLI 调用。\nconst TOMATO_ITEM_KEY_PATTERN = /^\\[([A-Za-z][A-Za-z0-9]*(?:-[A-Za-z0-9]+)*-\\d+)\\]/u\n\nconst TOMATO_STATUS_ORDER = [\n '新建', 'Bugfix', '修复中', '开发中', '待测试', '测试中', '测试通过', '已完成',\n '已取消', '延期解决', '测试完成', '待开发', '不修复', '已挂起',\n]\nconst TOMATO_FILTER_BLACKLIST_KEY = 'taskboard.tomatoFilterBlacklist.v1'\nconst TOMATO_SESSION_LINKS_KEY = 'taskboard.tomatoSessionLinks.v1'\nconst TOMATO_MUTED_ITEMS_KEY = 'taskboard.tomatoMutedItems.v1'\nconst TOMATO_LANE_ORDER_KEY = 'taskboard.tomatoLaneOrder.v1'\n\nfunction readLaneOrder(): LaneOrder {\n try {\n const value = JSON.parse(window.localStorage.getItem(TOMATO_LANE_ORDER_KEY) ?? '{}')\n return {\n head: typeof value?.head === 'string' ? value.head : null,\n next: value?.next && typeof value.next === 'object' ? value.next as Record<string, string | null> : {},\n }\n } catch {\n return { head: null, next: {} }\n }\n}\n\nfunction laneOrderValues(order: LaneOrder): string[] {\n const values: string[] = []\n const seen = new Set<string>()\n let current = order.head\n while (current && !seen.has(current) && values.length < 1000) {\n values.push(current)\n seen.add(current)\n current = order.next[current] ?? null\n }\n return values\n}\n\nfunction createLaneOrder(values: string[]): LaneOrder {\n const next: Record<string, string | null> = {}\n values.forEach((value, index) => { next[value] = values[index + 1] ?? null })\n return { head: values[0] ?? null, next }\n}\n\nfunction applyLaneOrder(statuses: string[], order: LaneOrder): string[] {\n const available = new Set(statuses)\n const tracked = laneOrderValues(order).filter(status => available.has(status))\n const trackedSet = new Set(tracked)\n return [...tracked, ...statuses.filter(status => !trackedSet.has(status))]\n}\n\nfunction readSessionLinks(): Record<string, string> {\n try {\n const value = JSON.parse(window.localStorage.getItem(TOMATO_SESSION_LINKS_KEY) ?? '{}')\n return value && typeof value === 'object' ? value as Record<string, string> : {}\n } catch {\n return {}\n }\n}\n\nfunction linkedSessionId(itemKey: string): SessionId | '' {\n const value = readSessionLinks()[itemKey]\n return typeof value === 'string' && value ? SessionId(value) : ''\n}\n\nfunction saveSessionLink(itemKey: string, sessionId: SessionId) {\n const links = readSessionLinks()\n links[itemKey] = sessionId\n window.localStorage.setItem(TOMATO_SESSION_LINKS_KEY, JSON.stringify(links))\n}\n\nfunction readFilterBlacklist(): { types: Set<string>; statuses: Set<string>; workspaces: Set<string> } {\n try {\n const value = JSON.parse(window.localStorage.getItem(TOMATO_FILTER_BLACKLIST_KEY) ?? '{}')\n return {\n types: new Set(Array.isArray(value?.types) ? value.types.filter((item: unknown): item is string => typeof item === 'string') : []),\n statuses: new Set(Array.isArray(value?.statuses) ? value.statuses.filter((item: unknown): item is string => typeof item === 'string') : []),\n workspaces: new Set(Array.isArray(value?.workspaces) ? value.workspaces.filter((item: unknown): item is string => typeof item === 'string') : []),\n }\n } catch {\n return { types: new Set(), statuses: new Set(), workspaces: new Set() }\n }\n}\n\nfunction readMutedItems(): Set<string> {\n try {\n const value = JSON.parse(window.localStorage.getItem(TOMATO_MUTED_ITEMS_KEY) ?? '[]')\n return new Set(Array.isArray(value) ? value.filter((item): item is string => typeof item === 'string') : [])\n } catch {\n return new Set()\n }\n}\n\nasync function refresh(assignee = 'currentUser()') {\n emit({ loading: true, error: null })\n try {\n const query = new URLSearchParams({ assignee })\n const response = await fetch(`/api/tomato-board/items?${query}`, { headers: { accept: 'application/json' } })\n const body = await response.json() as { items?: TomatoItem[]; truncated?: boolean; error?: string }\n if (!response.ok) throw new Error(body.error || `请求失败 (${response.status})`)\n emit({ items: body.items ?? [], truncated: body.truncated === true, loaded: true })\n } catch (error) {\n emit({ error: error instanceof Error ? error.message : '番茄事项读取失败' })\n } finally {\n emit({ loading: false })\n }\n}\n\nfunction closeWorkbench() {\n const dispose = disposeWorkbench\n disposeWorkbench = null\n // 关闭时清掉 loaded 和 error:下次打开工作台会重新拉取一次最新数据。\n emit({ open: false, selectedItem: null, loaded: false, error: null })\n dispose?.()\n}\n\nfunction TomatoBoardAction({ wide, openWorkbench }: { wide: boolean; openWorkbench: () => void }) {\n return (\n <button className={css.sidebarAction} type=\"button\" title=\"番茄工作台\" onClick={openWorkbench}>\n <span className={css.tomatoIcon} aria-hidden=\"true\">T</span>\n {wide && <span>番茄工作台</span>}\n </button>\n )\n}\n\nfunction TomatoBoardTopbarAction({ openWorkbench }: { openWorkbench: () => void }) {\n return (\n <button className={css.topbarAction} type=\"button\" title=\"打开番茄工作台\" onClick={openWorkbench}>\n <span className={css.tomatoIcon} aria-hidden=\"true\">T</span>\n <span>番茄工作台</span>\n </button>\n )\n}\n\nfunction CreateConversationDialog({ ctx, item }: { ctx: Context; item: TomatoItem }) {\n const [workspaceId, setWorkspaceId] = useState('')\n const [workspaceMenuOpen, setWorkspaceMenuOpen] = useState(false)\n const [creating, setCreating] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const workspaces = useSyncExternalStore(\n listener => ctx.workspaces.list.subscribe(listener),\n () => ctx.workspaces.list.getSnapshot(),\n () => ctx.workspaces.list.getSnapshot(),\n )\n const selectedWorkspace = workspaces.items.find(workspace => workspace.workspaceId === workspaceId)\n\n async function createConversation() {\n if (!selectedWorkspace || creating) return\n setCreating(true)\n setError(null)\n try {\n const createdSessionId = await ctx.sessions.create({ workspaceId: selectedWorkspace.workspaceId })\n const session = ctx.sessions.binding(createdSessionId)?.session\n if (!session) throw new Error('新建对话未能在 Harness 中加载')\n const title = `[${item.itemKey}] ${item.title}`\n const renamed = await session.rename(title)\n if (!renamed.ok) throw new Error(`对话标题设置失败:${renamed.error.message}`)\n const prompt = [\n `请处理番茄事项 ${item.itemKey}。`,\n `标题:${item.title}`,\n `类型:${item.itemType || '未设置'}`,\n `状态:${item.status || '未设置'}`,\n `优先级:${item.priority || '未设置'}`,\n ].join('\\n')\n const prompted = await session.prompt([{ type: 'text', text: prompt }], 'queue')\n if (!prompted.ok) throw new Error(`事项上下文写入失败:${prompted.error.message}`)\n saveSessionLink(item.itemKey, createdSessionId)\n ctx.sessions.open(createdSessionId)\n closeWorkbench()\n } catch (reason) {\n setError(reason instanceof Error ? reason.message : 'Harness 对话创建失败')\n } finally {\n setCreating(false)\n }\n }\n\n return (\n <Modal\n open\n onClose={() => emit({ selectedItem: null })}\n title=\"选择处理该事项的仓库\"\n closeLabel=\"关闭\"\n description={item.title}\n className={css.createDialog!}\n footer={(\n <>\n <Button variant=\"ghost\" onClick={() => emit({ selectedItem: null })}>取消</Button>\n <Button variant=\"primary\" disabled={!selectedWorkspace || creating} onClick={() => void createConversation()}>\n {creating ? '正在创建…' : '创建并进入对话'}\n </Button>\n </>\n )}\n >\n <div className={css.dialogBody}>\n <span>{item.itemKey}</span>\n {error ? <div className={css.error} role=\"alert\">{error}</div> : null}\n <Menu\n open={workspaceMenuOpen}\n portal\n items={workspaces.items.map((workspace: WorkspaceView) => ({\n id: workspace.workspaceId,\n label: workspace.title,\n }))}\n selectedId={workspaceId || undefined}\n onSelect={id => {\n setWorkspaceId(id)\n setWorkspaceMenuOpen(false)\n }}\n onClose={() => setWorkspaceMenuOpen(false)}\n anchor={(\n <Button\n className={css.workspaceTrigger}\n variant=\"outline\"\n aria-haspopup=\"menu\"\n aria-expanded={workspaceMenuOpen}\n onClick={() => setWorkspaceMenuOpen(open => !open)}\n >\n <span>{selectedWorkspace?.title ?? '选择 Harness 项目…'}</span>\n <span aria-hidden=\"true\">⌄</span>\n </Button>\n )}\n />\n {selectedWorkspace ? <code>{selectedWorkspace.path}</code> : null}\n </div>\n </Modal>\n )\n}\n\nfunction TomatoBoardPanel({ ctx }: { ctx: Context }) {\n const board = useSyncExternalStore(subscribe, snapshot, snapshot)\n const workbenchRef = useRef<HTMLElement>(null)\n const filterMenuRef = useRef<HTMLDetailsElement>(null)\n const [page, setPage] = useState<'board' | 'points'>('board')\n const [storyToolbar, setStoryToolbar] = useState<React.ReactNode>(null)\n const [search, setSearch] = useState('')\n const [blacklist, setBlacklist] = useState(readFilterBlacklist)\n const [mutedItems, setMutedItems] = useState(readMutedItems)\n const [selectedAssignee, setSelectedAssignee] = useState('currentUser()')\n const [filterDirectory, setFilterDirectory] = useState<FilterDirectory>({ users: [], workspaces: [] })\n const [directoryVersion, setDirectoryVersion] = useState(0)\n const [laneOrder, setLaneOrder] = useState(readLaneOrder)\n const [draggedLane, setDraggedLane] = useState<string | null>(null)\n const [dropLane, setDropLane] = useState<{ status: string; after: boolean } | null>(null)\n const laneElements = useRef(new Map<string, HTMLElement>())\n const previousLanePositions = useRef(new Map<string, DOMRect>())\n const sessions = useSyncExternalStore(\n listener => ctx.sessions.list.subscribe(listener),\n () => ctx.sessions.list.getSnapshot(),\n () => ctx.sessions.list.getSnapshot(),\n )\n\n useEffect(() => {\n // 用 loaded 而不是 items.length 判断:成功返回空列表时也算加载完成,\n // 否则 loading 变回 false 会再次命中本 effect,形成无限请求循环。\n if (board.open && !board.loaded && !board.loading && !board.error) void refresh()\n }, [board.error, board.loaded, board.loading, board.open])\n useEffect(() => {\n if (!board.open) return\n void fetch('/api/tomato-board/filters', { headers: { accept: 'application/json' } })\n .then(response => response.ok ? response.json() : Promise.reject(new Error(`HTTP ${response.status}`)))\n .then(value => setFilterDirectory(value as FilterDirectory))\n .catch(() => {})\n }, [board.open, directoryVersion])\n useEffect(() => {\n if (!board.open) return\n const closeOnOutsideNavigation = (event: PointerEvent) => {\n if (!(event.target instanceof Element)) return\n if (workbenchRef.current?.contains(event.target)) return\n if (event.target.closest('[role=\"dialog\"], [role=\"menu\"]')) return\n closeWorkbench()\n }\n document.addEventListener('pointerdown', closeOnOutsideNavigation, true)\n return () => document.removeEventListener('pointerdown', closeOnOutsideNavigation, true)\n }, [board.open])\n useEffect(() => {\n const closeFilterMenu = (event: PointerEvent) => {\n const menu = filterMenuRef.current\n if (menu?.open && event.target instanceof Node && !menu.contains(event.target)) menu.open = false\n }\n const closeFilterMenuOnEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && filterMenuRef.current?.open) filterMenuRef.current.open = false\n }\n document.addEventListener('pointerdown', closeFilterMenu, true)\n document.addEventListener('keydown', closeFilterMenuOnEscape)\n return () => {\n document.removeEventListener('pointerdown', closeFilterMenu, true)\n document.removeEventListener('keydown', closeFilterMenuOnEscape)\n }\n }, [])\n useLayoutEffect(() => {\n const previous = previousLanePositions.current\n if (previous.size === 0) return\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {\n previous.clear()\n return\n }\n for (const [status, element] of laneElements.current) {\n const before = previous.get(status)\n if (!before) continue\n const after = element.getBoundingClientRect()\n const deltaX = before.left - after.left\n const deltaY = before.top - after.top\n if (deltaX || deltaY) {\n element.animate(\n [{ transform: `translate(${deltaX}px, ${deltaY}px)` }, { transform: 'translate(0, 0)' }],\n { duration: 240, easing: 'cubic-bezier(.2,.8,.2,1)' },\n )\n }\n }\n previous.clear()\n }, [laneOrder])\n if (!board.open) return null\n\n function openItem(item: TomatoItem) {\n const stored = linkedSessionId(item.itemKey)\n const titlePrefix = `[${item.itemKey}]`\n const discovered = sessions.ids.find(id => {\n const summary = sessions.byId[id]\n return summary?.title?.startsWith(titlePrefix) || summary?.displayTitle.startsWith(titlePrefix)\n })\n const associated = stored && sessions.byId[stored] ? stored : discovered\n if (associated) {\n saveSessionLink(item.itemKey, associated)\n ctx.sessions.open(associated)\n closeWorkbench()\n return\n }\n emit({ selectedItem: item })\n }\n\n const normalizedSearch = search.trim().toLowerCase()\n const filteredItems = board.items.filter(item => (\n !blacklist.types.has(item.itemType)\n && !blacklist.statuses.has(item.status)\n && !blacklist.workspaces.has(item.workspaceKey)\n && !blacklist.workspaces.has(item.workspaceName)\n && (!normalizedSearch || [\n item.itemKey, item.title, item.itemType, item.status, item.workspaceKey, item.workspaceName, item.creator, item.assignees.join(' '), item.priority,\n ].join(' ').toLowerCase().includes(normalizedSearch))\n ))\n const typeOptions = [...new Set(board.items.map(item => item.itemType).filter(Boolean))].sort((left, right) => left.localeCompare(right))\n const statusOptions = applyLaneOrder([...new Set([\n ...TOMATO_STATUS_ORDER,\n ...board.items.map(item => item.status).filter(status => !TOMATO_STATUS_ORDER.includes(status)),\n ])], laneOrder)\n // Workspace options derive purely from the current assignee's items (the\n // board query is already assignee-scoped server-side), so the count is\n // however many workspaces that assignee actually spans — never the logged-in\n // account's full directory. The item filter checks key AND name so both\n // identity forms hide correctly.\n const workspaceOptions = (() => {\n const entries = new Map<string, { value: string; label: string }>()\n for (const item of board.items) {\n const value = item.workspaceKey || item.workspaceName || item.workspace\n if (!value) continue\n const label = item.workspaceName && item.workspaceKey && item.workspaceName !== item.workspaceKey ? `${item.workspaceName} (${item.workspaceKey})` : value\n if (!entries.has(value)) entries.set(value, { value, label })\n }\n return [...entries.values()]\n })()\n const defaultStatuses = [...new Set([\n ...TOMATO_STATUS_ORDER.filter(status => filteredItems.some(item => item.status === status)),\n ...filteredItems.map(item => item.status).filter(status => !TOMATO_STATUS_ORDER.includes(status)),\n ])]\n const statuses = applyLaneOrder(defaultStatuses, laneOrder)\n\n const persistBlacklist = (next: typeof blacklist) => {\n window.localStorage.setItem(TOMATO_FILTER_BLACKLIST_KEY, JSON.stringify({\n types: [...next.types],\n statuses: [...next.statuses],\n workspaces: [...next.workspaces],\n }))\n return next\n }\n const toggleBlacklist = (kind: 'types' | 'statuses' | 'workspaces', value: string) => setBlacklist(current => {\n const nextValues = new Set(current[kind])\n if (nextValues.has(value)) nextValues.delete(value)\n else nextValues.add(value)\n return persistBlacklist({ ...current, [kind]: nextValues })\n })\n const setWorkspaceFilterAll = (visible: boolean) => setBlacklist(current => persistBlacklist({\n ...current,\n workspaces: visible ? new Set<string>() : new Set(workspaceOptions.map(option => option.value)),\n }))\n\n const toggleMutedItem = (itemKey: string) => setMutedItems(current => {\n const next = new Set(current)\n if (next.has(itemKey)) next.delete(itemKey)\n else next.add(itemKey)\n window.localStorage.setItem(TOMATO_MUTED_ITEMS_KEY, JSON.stringify([...next]))\n return next\n })\n\n const moveLane = (dragged: string, target: string, after: boolean) => {\n if (dragged === target) return\n previousLanePositions.current = new Map([...laneElements.current].map(([status, element]) => [status, element.getBoundingClientRect()]))\n setLaneOrder(current => {\n const visible = applyLaneOrder(defaultStatuses, current).filter(status => status !== dragged)\n const targetIndex = visible.indexOf(target)\n visible.splice(targetIndex + (after ? 1 : 0), 0, dragged)\n const previousTracked = laneOrderValues(current)\n const trackedSet = new Set([...previousTracked, dragged, target])\n const hiddenTracked = previousTracked.filter(status => !visible.includes(status))\n const next = createLaneOrder([...visible.filter(status => trackedSet.has(status)), ...hiddenTracked])\n window.localStorage.setItem(TOMATO_LANE_ORDER_KEY, JSON.stringify(next))\n return next\n })\n }\n\n return (\n <section ref={workbenchRef} className={css.workbench} aria-label=\"番茄工作台\">\n <header className={css.header}>\n <div className={css.titleRow}>\n <h1>番茄工作台</h1>\n <div className={css.actions}>\n {page === 'points' && storyToolbar}\n {page === 'board' && <><label className={css.searchField}>\n <span aria-hidden=\"true\">⌕</span>\n <input\n type=\"search\"\n value={search}\n onChange={event => setSearch(event.target.value)}\n placeholder=\"搜索标题或 tag…\"\n aria-label=\"搜索标题或 tag\"\n />\n {search && <button type=\"button\" aria-label=\"清空搜索词\" onClick={() => setSearch('')}>×</button>}\n </label>\n <details ref={filterMenuRef} className={css.filterMenu}>\n <summary aria-label=\"空间、负责人、类型和状态筛选\" title=\"空间、负责人、类型和状态筛选\">\n <span aria-hidden=\"true\">▽</span>\n {(blacklist.types.size > 0 || blacklist.statuses.size > 0 || blacklist.workspaces.size > 0 || selectedAssignee !== 'currentUser()') && <i />}\n </summary>\n <div className={css.filterPopover}>\n <WorkspaceFilterRow options={workspaceOptions} hidden={blacklist.workspaces} onToggle={value => toggleBlacklist('workspaces', value)} onSetAll={setWorkspaceFilterAll} />\n <AssigneePicker users={filterDirectory.users} value={selectedAssignee} onChange={value => { setSelectedAssignee(value); void refresh(value) }} />\n <FilterRow label=\"类型\" options={typeOptions} hidden={blacklist.types} onToggle={value => toggleBlacklist('types', value)} />\n <FilterRow label=\"状态\" options={statusOptions} hidden={blacklist.statuses} onToggle={value => toggleBlacklist('statuses', value)} />\n </div>\n </details>\n <Button\n variant=\"toolbar\"\n size=\"sm\"\n className={css.headerIconButton}\n icon={<IconRefreshOutline16 />}\n title=\"刷新番茄事项\"\n aria-label=\"刷新番茄事项\"\n disabled={board.loading}\n onClick={() => { void refresh(selectedAssignee); setDirectoryVersion(value => value + 1) }}\n />\n </>}\n <Button\n variant=\"toolbar\"\n size=\"sm\"\n className={css.headerIconButton}\n icon={<IconCloseOutline16 />}\n title=\"关闭番茄工作台\"\n aria-label=\"关闭番茄工作台\"\n onClick={closeWorkbench}\n />\n </div>\n </div>\n <nav className={css.pageTabs} aria-label=\"番茄工作台页面\">\n <button type=\"button\" aria-current={page === 'board' ? 'page' : undefined} onClick={() => setPage('board')}>事项看板</button>\n <button type=\"button\" aria-current={page === 'points' ? 'page' : undefined} onClick={() => setPage('points')}>迭代投入</button>\n </nav>\n </header>\n {page === 'points' ? <StoryPoints toolbarTarget={setStoryToolbar} onOpenItem={openItem} /> : <>\n {board.error && <div className={css.error} role=\"alert\">{board.error}</div>}\n {board.truncated && <p className={css.notice} role=\"status\">事项数量已达配置上限,当前仅展示前 {board.items.length} 条。</p>}\n <div className={css.board}>\n {statuses.map(status => {\n const items = filteredItems.filter(item => item.status === status)\n return (\n <section\n ref={element => { if (element) laneElements.current.set(status, element); else laneElements.current.delete(status) }}\n className={`${css.lane} ${draggedLane === status ? css.laneDragging : ''} ${dropLane?.status === status ? (dropLane.after ? css.laneDropAfter : css.laneDropBefore) : ''}`}\n key={status}\n aria-labelledby={`tomato-lane-${status}`}\n onDragOver={event => {\n if (!draggedLane || draggedLane === status) return\n event.preventDefault()\n const bounds = event.currentTarget.getBoundingClientRect()\n setDropLane({ status, after: event.clientX >= bounds.left + bounds.width / 2 })\n }}\n onDrop={event => {\n event.preventDefault()\n if (draggedLane && dropLane?.status === status) moveLane(draggedLane, status, dropLane.after)\n setDraggedLane(null)\n setDropLane(null)\n }}\n >\n <header\n className={css.laneHeader}\n draggable\n title=\"拖拽调整泳道顺序\"\n onDragStart={event => {\n event.dataTransfer.effectAllowed = 'move'\n event.dataTransfer.setData('text/plain', status)\n const lane = event.currentTarget.parentElement\n if (lane) {\n const bounds = lane.getBoundingClientRect()\n event.dataTransfer.setDragImage(\n lane,\n Math.min(Math.max(event.clientX - bounds.left, 0), bounds.width),\n Math.min(Math.max(event.clientY - bounds.top, 0), bounds.height),\n )\n }\n setDraggedLane(status)\n }}\n onDragEnd={() => { setDraggedLane(null); setDropLane(null) }}\n >\n <h2 id={`tomato-lane-${status}`}>{status}</h2>\n <span>{items.length}</span>\n </header>\n <div className={css.cards}>\n {items.map(item => (\n <article\n className={`${css.card} ${mutedItems.has(item.itemKey) ? css.cardMuted : ''}`}\n key={item.itemKey}\n tabIndex={0}\n role=\"button\"\n onClick={() => openItem(item)}\n onKeyDown={event => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n openItem(item)\n }\n }}\n >\n <div className={css.cardTopline}>\n <span className={css.key}>{item.itemKey}</span>\n <div className={css.cardButtons}>\n <Button\n className={css.muteButton}\n variant=\"ghost\"\n size=\"sm\"\n title={mutedItems.has(item.itemKey) ? '取消置灰' : '置灰标记'}\n aria-label={mutedItems.has(item.itemKey) ? `取消置灰 ${item.itemKey}` : `置灰 ${item.itemKey}`}\n aria-pressed={mutedItems.has(item.itemKey)}\n onClick={event => {\n event.stopPropagation()\n toggleMutedItem(item.itemKey)\n }}\n onKeyDown={event => event.stopPropagation()}\n >\n ●\n </Button>\n <Button\n className={css.tomatoLink}\n variant=\"ghost\"\n size=\"sm\"\n title=\"在番茄中打开事项\"\n aria-label={`在番茄中打开 ${item.itemKey}`}\n onClick={event => {\n event.stopPropagation()\n window.open(item.tomatoUrl, '_blank', 'noopener,noreferrer')\n }}\n onKeyDown={event => event.stopPropagation()}\n >\n ↗\n </Button>\n </div>\n </div>\n <strong>{item.title}</strong>\n <div className={css.cardMeta}>\n <Tag tone={typeTone(item.itemType)}>{item.itemType}</Tag>\n {(item.workspaceName || item.workspaceKey) && <Tag title=\"空间\">{item.workspaceName && item.workspaceKey && item.workspaceName !== item.workspaceKey ? `${item.workspaceName} (${item.workspaceKey})` : item.workspaceKey || item.workspaceName}</Tag>}\n {item.priority && <Tag title=\"优先级\">{priorityLabel(item.priority)}</Tag>}\n {item.creator && <Tag title=\"创建人\">创建 {item.creator}</Tag>}\n </div>\n </article>\n ))}\n </div>\n </section>\n )\n })}\n {!board.loading && !board.error && statuses.length === 0 && (\n <div className={css.empty}>当前没有可显示的番茄事项</div>\n )}\n </div>\n </>}\n {board.selectedItem ? <CreateConversationDialog ctx={ctx} item={board.selectedItem} /> : null}\n </section>\n )\n}\n\nconst PRIORITY_LABELS: Record<string, string> = {\n '69e65065-4b34-4109-bca9-0154e548554a': 'P0',\n '8f7912a5-9176-4a79-a269-2269ac42b5a2': 'P1',\n 'ca8c3e43-3e7b-444d-8940-d0967d944921': 'P2',\n 'ec31e4c1-b55b-479d-be97-86d5f7bf38ef': 'P2',\n '1a3e1092-7d70-42ee-ad38-0e8d953c4c23': 'P3',\n 'faae52da-28c8-46fc-96dd-db9cdb28b557': 'P4',\n}\nconst priorityLabel = (value: string) => PRIORITY_LABELS[value] ?? value\n\nconst TYPE_TONES: Record<string, string> = {\n Story: '#2f7d72', EnablerStory: '#2777a8', Task: '#7b61a8', Bug: '#c34f43', 缺陷: '#c34f43', 测试缺陷: '#d06438', Epic: '#9a6b24', Feature: '#3f68ad',\n}\nfunction typeTone(type: string): string {\n if (TYPE_TONES[type]) return TYPE_TONES[type]\n const palette = ['#2f7d72', '#2777a8', '#7b61a8', '#c34f43', '#9a6b24', '#51753a', '#a14f78']\n return palette[[...type].reduce((hash, char) => hash + char.charCodeAt(0), 0) % palette.length]!\n}\n\nfunction FilterRow({ label, options, hidden, onToggle }: {\n label: string\n options: string[]\n hidden: ReadonlySet<string>\n onToggle: (value: string) => void\n}) {\n return (\n <div className={css.filterRow}>\n <span>{label}</span>\n <div>\n {options.map(option => (\n <Tag\n key={option}\n interactive\n pressed={!hidden.has(option)}\n tone={label === '类型' ? typeTone(option) : undefined}\n onClick={() => onToggle(option)}\n >\n {option}\n </Tag>\n ))}\n </div>\n </div>\n )\n}\n\nconst WORKSPACE_SELECT_ALL = 'workspace:select-all'\nconst WORKSPACE_SELECT_NONE = 'workspace:select-none'\n\n/** Multi-select workspace dropdown composed on the shared Menu primitive. */\nfunction WorkspaceFilterRow({ options, hidden, onToggle, onSetAll }: {\n options: Array<{ value: string; label: string }>\n hidden: ReadonlySet<string>\n onToggle: (value: string) => void\n onSetAll: (visible: boolean) => void\n}) {\n const [open, setOpen] = useState(false)\n const rootRef = useRef<HTMLDivElement>(null)\n const visibleValues = options.filter(option => !hidden.has(option.value)).map(option => option.value)\n const summary = options.length === 0\n ? '暂无空间'\n : hidden.size === 0\n ? `全部空间 · ${options.length}`\n : visibleValues.length === 0\n ? '未选择空间'\n : `已选空间 ${visibleValues.length} / ${options.length}`\n // First Esc closes this dropdown only; the host filter popover stays open.\n useEffect(() => {\n if (!open) return\n const onKey = (event: KeyboardEvent) => {\n if (event.key === 'Escape') { event.stopPropagation(); setOpen(false) }\n }\n const root = rootRef.current\n root?.addEventListener('keydown', onKey, true)\n return () => root?.removeEventListener('keydown', onKey, true)\n }, [open])\n const items: MenuEntry[] = options.map(option => ({ id: option.value, label: option.label }))\n const footer: MenuEntry[] = [\n { id: WORKSPACE_SELECT_ALL, label: '全部显示' },\n { id: WORKSPACE_SELECT_NONE, label: '全部隐藏' },\n ]\n return (\n <div className={css.filterRow} ref={rootRef}>\n <span>空间</span>\n <div className={css.workspaceSelect}>\n <Menu\n open={open}\n items={items}\n footer={footer}\n selectedIds={visibleValues}\n onSelect={(id) => {\n if (id === WORKSPACE_SELECT_ALL) onSetAll(true)\n else if (id === WORKSPACE_SELECT_NONE) onSetAll(false)\n else onToggle(id)\n }}\n onClose={() => { setOpen(false) }}\n anchor={\n <button\n type=\"button\"\n className={css.workspaceTrigger}\n aria-expanded={open}\n title={summary}\n onClick={() => { setOpen(!open) }}\n >\n <span>{summary}</span>\n <i className={css.workspaceChevron} aria-hidden><IconChevronDownOutline14 /></i>\n </button>\n }\n />\n </div>\n </div>\n )\n}\n\nfunction AssigneePicker({ users, value, onChange }: {\n users: FilterDirectory['users']\n value: string\n onChange: (value: string) => void\n}) {\n const rootRef = useRef<HTMLDivElement>(null)\n const [open, setOpen] = useState(false)\n const [query, setQuery] = useState('')\n const options = useMemo(() => [{ username: 'currentUser()', name: '我负责的' }, ...users.filter(user => user.username !== 'currentUser()')], [users])\n const selected = options.find(option => option.username === value) ?? options[0]\n const needle = query.trim().toLowerCase()\n const filtered = needle\n ? options.filter(option => `${option.name} ${option.username}`.toLowerCase().includes(needle))\n : options\n\n useEffect(() => {\n if (!open) return\n const close = (event: PointerEvent) => {\n if (event.target instanceof Node && !rootRef.current?.contains(event.target)) setOpen(false)\n }\n document.addEventListener('pointerdown', close, true)\n return () => document.removeEventListener('pointerdown', close, true)\n }, [open])\n\n return (\n <div className={css.assigneeFilter}>\n <span>负责人</span>\n <div ref={rootRef} className={css.assigneePicker}>\n <Button variant=\"outline\" size=\"sm\" className={css.assigneeTrigger} aria-haspopup=\"listbox\" aria-expanded={open} onClick={() => { setOpen(current => !current); setQuery('') }}>\n <span>{selected?.name ?? value}</span><IconChevronDownOutline14 />\n </Button>\n {open ? (\n <div className={css.assigneeDropdown}>\n <input autoFocus type=\"search\" value={query} onChange={event => setQuery(event.target.value)} placeholder=\"搜索昵称或用户名…\" aria-label=\"搜索负责人\" />\n <div role=\"listbox\" aria-label=\"负责人\">\n {filtered.map(option => (\n <button key={option.username} type=\"button\" role=\"option\" aria-selected={option.username === value} onClick={() => { onChange(option.username); setOpen(false); setQuery('') }}>\n <strong>{option.name}</strong>{option.name !== option.username && option.username !== 'currentUser()' ? <small>{option.username}</small> : null}\n </button>\n ))}\n {filtered.length === 0 ? <p>没有匹配的负责人</p> : null}\n </div>\n </div>\n ) : null}\n </div>\n </div>\n )\n}\n\nfunction TomatoConversationShortcut({ ctx, sessionId, useSessions }: PropsRuntime<'conversation.session.header.actions'> & { ctx: Context }) {\n const itemKey = useSessions(state => {\n const summary = state.byId[sessionId]\n const title = summary?.title ?? summary?.displayTitle ?? ''\n const match = TOMATO_ITEM_KEY_PATTERN.exec(title)?.[1]?.trim()\n if (!match) return ''\n // 仅当该对话确实由番茄工作台创建并记录在本机映射中时,才认定它是番茄事项对话。\n // 这样即便普通新建对话的标题恰好命中 itemKey 格式,也不会被误带上状态流转 UI。\n return linkedSessionId(match) === sessionId ? match : ''\n })\n const [menuOpen, setMenuOpen] = useState(false)\n const [loading, setLoading] = useState(false)\n const [transitioning, setTransitioning] = useState(false)\n const [transitionState, setTransitionState] = useState<TomatoTransitionState>({\n currentStatus: '',\n tomatoUrl: '',\n transitions: [],\n })\n const [transitionError, setTransitionError] = useState<string | null>(null)\n\n useEffect(() => {\n if (!itemKey) return\n const controller = new AbortController()\n setLoading(true)\n setTransitionError(null)\n setTransitionState({ currentStatus: '', tomatoUrl: '', transitions: [] })\n void fetch(`/api/tomato-board/transitions/${encodeURIComponent(itemKey)}`, {\n headers: { accept: 'application/json' },\n signal: controller.signal,\n }).then(async response => {\n const body = await response.json() as TomatoTransitionState & { error?: string }\n if (!response.ok) throw new Error(body.error || `请求失败 (${response.status})`)\n setTransitionState({\n currentStatus: body.currentStatus || '',\n tomatoUrl: body.tomatoUrl || '',\n transitions: body.transitions ?? [],\n })\n }).catch(error => {\n if (error instanceof Error && error.name === 'AbortError') return\n setTransitionError(error instanceof Error ? error.message : '番茄流转状态读取失败')\n }).finally(() => {\n if (!controller.signal.aborted) setLoading(false)\n })\n return () => controller.abort()\n }, [itemKey])\n\n if (!itemKey) return null\n\n async function transitionTo(transitionName: string) {\n if (transitioning) return\n setMenuOpen(false)\n setTransitioning(true)\n setTransitionError(null)\n try {\n const query = new URLSearchParams({ transition: transitionName })\n const response = await fetch(`/api/tomato-board/transition/${encodeURIComponent(itemKey)}?${query}`, {\n method: 'POST',\n headers: { accept: 'application/json' },\n })\n const body = await response.json() as {\n currentStatus?: string\n error?: string\n details?: { stderr?: string; stdout?: string }\n }\n if (!response.ok) {\n const selected = transitionState.transitions.find(transition => transition.transition === transitionName)\n const failure = [body.error, body.details?.stderr, body.details?.stdout].filter(Boolean).join('\\n')\n const requiredFieldsMissing = /字段.{0,24}必填|必填.{0,24}字段|流转前需填写/u.test(failure)\n if (selected?.targetStatus === '待测试' && requiredFieldsMissing) {\n const session = ctx.sessions.binding(sessionId)?.session\n if (!session) throw new Error('当前 Harness 对话未加载,无法交给 AI 继续处理')\n const prompt = [\n `番茄事项 ${itemKey} 流转到「待测试」失败,CLI 提示存在必填字段缺失。`,\n '请先读取番茄事项详情,并结合当前对话和仓库代码进行分析。',\n '基于证据补齐并回读确认以下字段:根因分析、RD引入原因分析、原因描述、修复版本、解决方案。',\n '不要编造业务事实;证据不足时先向我确认。',\n '只有这些字段已经持久化且回读一致后,才能重新执行「修复完成」流转到「待测试」,最后再次回读状态验证。',\n `CLI 失败信息:${failure || '未返回具体原因'}`,\n ].join('\\n')\n const prompted = await session.prompt([{ type: 'text', text: prompt }], 'queue')\n if (!prompted.ok) throw new Error(`无法把流转任务交给 AI:${prompted.error.message}`)\n setTransitionError('必填字段缺失,已交给当前对话中的 AI 分析并继续处理')\n return\n }\n throw new Error(failure || `请求失败 (${response.status})`)\n }\n const transitionsResponse = await fetch(`/api/tomato-board/transitions/${encodeURIComponent(itemKey)}`, {\n headers: { accept: 'application/json' },\n })\n const transitionsBody = await transitionsResponse.json() as TomatoTransitionState & { error?: string }\n if (!transitionsResponse.ok) {\n throw new Error(transitionsBody.error || `状态刷新失败 (${transitionsResponse.status})`)\n }\n setTransitionState({\n currentStatus: transitionsBody.currentStatus || body.currentStatus || '',\n tomatoUrl: transitionsBody.tomatoUrl || '',\n transitions: transitionsBody.transitions ?? [],\n })\n } catch (error) {\n setTransitionError(error instanceof Error ? error.message : '番茄事项流转失败')\n } finally {\n setTransitioning(false)\n }\n }\n\n const availableTransitions = transitionState.transitions.filter(transition => !transition.disabled)\n const delegatedToAgent = transitionError?.startsWith('必填字段缺失') === true\n const transitionTitle = transitionError\n ? delegatedToAgent ? transitionError : `番茄流转失败:${transitionError}`\n : loading\n ? '正在查询番茄事项状态'\n : availableTransitions.length === 0\n ? `当前状态「${transitionState.currentStatus || '未知'}」没有可用流转`\n : `当前状态:${transitionState.currentStatus || '未知'}`\n return (\n <>\n <Menu\n open={menuOpen}\n portal\n align=\"end\"\n items={transitionState.transitions.map(transition => ({\n id: transition.transition,\n label: `流转到 ${transition.targetStatus}`,\n disabled: transition.disabled,\n }))}\n onSelect={transitionName => void transitionTo(transitionName)}\n onClose={() => setMenuOpen(false)}\n anchor={(\n <Button\n variant=\"toolbar\"\n size=\"sm\"\n className={css.transitionTrigger}\n title={transitionTitle}\n aria-label={transitionTitle}\n aria-haspopup=\"menu\"\n aria-expanded={menuOpen}\n disabled={loading || transitioning || availableTransitions.length === 0}\n onClick={() => setMenuOpen(open => !open)}\n >\n {transitioning || delegatedToAgent || transitionError\n ? transitioning ? '正在流转…' : delegatedToAgent ? 'AI 已接手' : '流转失败'\n : (\n <>\n <span className={css.transitionCaption}>状态</span>\n <strong>{transitionState.currentStatus || '查询中…'}</strong>\n {availableTransitions.length > 0 ? (\n <>\n <span className={css.transitionDivider} aria-hidden=\"true\" />\n <span className={css.transitionAction}>流转</span>\n <IconChevronDownOutline14 className={css.transitionChevron} />\n </>\n ) : null}\n </>\n )}\n </Button>\n )}\n />\n <Button\n variant=\"toolbar\"\n size=\"sm\"\n title=\"在番茄中打开事项\"\n aria-label={`在番茄中打开 ${itemKey}`}\n disabled={!transitionState.tomatoUrl}\n onClick={() => window.open(transitionState.tomatoUrl, '_blank', 'noopener,noreferrer')}\n >\n 番茄 ↗\n </Button>\n </>\n )\n}\n\nexport const inject = ['slots', 'sessions', 'workspaces']\n\nexport function apply(ctx: Context): void {\n const openWorkbench = () => {\n if (disposeWorkbench) return\n emit({ open: true })\n disposeWorkbench = ctx.slots.register(\n { name: 'conversation', priority: -100 },\n () => <TomatoBoardPanel ctx={ctx} />,\n )\n }\n ctx.slots.inject('conversation.session.header.actions', () => ctx.slots.register(\n { name: 'conversation.session.header.actions', id: 'tomato-shortcut', order: 12 },\n props => <TomatoConversationShortcut {...props} ctx={ctx} />,\n ))\n ctx.slots.inject('sidebar.footer.action', () => ctx.slots.register(\n { name: 'sidebar.footer.action', id: 'tomato-board' },\n props => <TomatoBoardAction {...props} openWorkbench={openWorkbench} />,\n ))\n // The shell's session header is the visible top bar in the Web client. Keep the\n // sidebar shortcut as a compact fallback for narrow or collapsed layouts.\n ctx.slots.inject('conversation.session.header.actions', () => ctx.slots.register(\n { name: 'conversation.session.header.actions', id: 'tomato-board-topbar', order: 11 },\n () => <TomatoBoardTopbarAction openWorkbench={openWorkbench} />,\n ))\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface TagProps {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
/** Tint color (hex or CSS color var). Omit for the neutral card-meta look. */
|
|
5
|
+
tone?: string | undefined;
|
|
6
|
+
/** Render as a toggle button (filter chips) instead of a static span. */
|
|
7
|
+
interactive?: boolean;
|
|
8
|
+
/** Toggle state for interactive tags; false renders the dimmed-off look. */
|
|
9
|
+
pressed?: boolean | undefined;
|
|
10
|
+
title?: string | undefined;
|
|
11
|
+
className?: string | undefined;
|
|
12
|
+
onClick?: (() => void) | undefined;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The one tag chip used across the workbench — card metadata, filter chips and
|
|
16
|
+
* status labels. Static usage renders a span; interactive usage renders a
|
|
17
|
+
* toggle button. Only callers that pass `tone` get a colored chip (by
|
|
18
|
+
* convention just the item-type tags).
|
|
19
|
+
*/
|
|
20
|
+
export declare function Tag({ children, tone, interactive, pressed, title, className, onClick }: TagProps): import("react").JSX.Element;
|
|
21
|
+
//# sourceMappingURL=Tag.d.ts.map
|