@stephen1620/dsh-tomato-board 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["css","Modal","Button","Menu","IconRefreshOutline16","IconCloseOutline16","IconChevronDownOutline14"],"sources":["../../../packages/core/session/src/types.ts","../../../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, 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'\n\ninterface TomatoItem {\n itemKey: string\n title: string\n status: string\n itemType: string\n workspace: string\n creator: string\n priority: string\n tomatoUrl: string\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_TYPE_OPTIONS = ['测试缺陷', '缺陷', 'Bug', 'EnablerStory', 'Story', 'Task']\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'\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> } {\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 }\n } catch {\n return { types: new Set(), statuses: 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() {\n emit({ loading: true, error: null })\n try {\n const response = await fetch('/api/tomato-board/items', { 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 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 [search, setSearch] = useState('')\n const [blacklist, setBlacklist] = useState(readFilterBlacklist)\n const [mutedItems, setMutedItems] = useState(readMutedItems)\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 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 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 && (!normalizedSearch || [\n item.itemKey, item.title, item.itemType, item.status, item.workspace, item.creator, item.priority,\n ].join(' ').toLowerCase().includes(normalizedSearch))\n ))\n const typeOptions = [...new Set([...TOMATO_TYPE_OPTIONS, ...board.items.map(item => item.itemType).filter(Boolean)])]\n const statusOptions = [...new Set([\n ...TOMATO_STATUS_ORDER,\n ...board.items.map(item => item.status).filter(status => !TOMATO_STATUS_ORDER.includes(status)),\n ])]\n const statuses = [...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\n const toggleBlacklist = (kind: 'types' | 'statuses', 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 }))\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 return (\n <section ref={workbenchRef} className={css.workbench} aria-label=\"番茄工作台\">\n <header className={css.header}>\n <div>\n <h1>番茄工作台</h1>\n <p>{board.loading ? '正在读取番茄事项…' : `显示 ${filteredItems.length} / ${board.items.length} 个事项`}</p>\n </div>\n <div className={css.actions}>\n <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 className={css.filterMenu}>\n <summary aria-label=\"类型和状态筛选\" title=\"类型和状态筛选\">\n <span aria-hidden=\"true\">▽</span>\n {(blacklist.types.size > 0 || blacklist.statuses.size > 0) && <i />}\n </summary>\n <div className={css.filterPopover}>\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()}\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 </header>\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 className={css.lane} key={status} aria-labelledby={`tomato-lane-${status}`}>\n <header className={css.laneHeader}>\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 <span className={css.meta}>{[item.itemType, item.priority, item.creator].filter(Boolean).join(' · ')}</span>\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 {board.selectedItem ? <CreateConversationDialog ctx={ctx} item={board.selectedItem} /> : null}\n </section>\n )\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}\n type=\"button\"\n aria-pressed={!hidden.has(option)}\n onClick={() => onToggle(option)}\n >\n {option}\n </button>\n ))}\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 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={() => {\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 ))\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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"}