chore: adapt the tasks/workflow/teams work to DSH 0.1.7-rc.1 (rebase onto v0.21.1)
Rebases the whole branch onto main's new 0.1.7-rc.1 baseline and lands the adaptation the new host contract requires: the ui-primitives icon family rename (Icon<Name><14|16> -> Icon<Name>Regular/Medium, with the 14px defaults pinned back explicitly) and the StateDot redraw, the rewritten dsh-settings surface (entry-id namespace, DSH schemastery with collected volatile returns, configure auto:false), session format v4 (producer-owned source kind plus the rewritten tool-result shape, parsers accepting both), the client snapshot move to projectionsBySession.subagentCatalog with the jobs.list route behind it, the ^0.1.7-rc.1 peer floor with vendor and bare-import devDeps, the reduced chunk set mirrored in all eight places, and the capability hand-backs (read-only previews, terminal, browser). Verified: typecheck and lint clean; 119 files / 1200 tests; build with no old contract residue in the bundles; mount e2e 7/7; the tasks page still passes its 70-assertion real-browser contract.
This commit is contained in:
+23
-20
@@ -1,14 +1,14 @@
|
||||
/**
|
||||
* The unified view model of the Tasks page: one ordered node list the graph
|
||||
* canvas AND the tree mode both render (same data, same fold state). Pure
|
||||
* derivation over the sessions list feed (byId lineage + per-parent
|
||||
* catalogs), the live activity map, the folded workflow runs, and the
|
||||
* optional team view — kept framework-free for node-environment unit tests.
|
||||
* derivation over the sessions list feed (byId lineage + the host's
|
||||
* per-session `subagentCatalog` projection views), the live activity map, the
|
||||
* folded workflow runs, and the optional team view — kept framework-free for
|
||||
* node-environment unit tests.
|
||||
*
|
||||
* Shape rules:
|
||||
* - agent rows walk the lazy per-parent catalogs in pre-order (the same
|
||||
* recursion the classic tree used); Side Chat threads and diagnostic rows
|
||||
* never become nodes;
|
||||
* - agent rows walk the per-parent catalog views in pre-order (the same
|
||||
* recursion the classic tree used); Side Chat threads never become nodes;
|
||||
* - a workflow run hangs under its ORIGIN agent; member agents that already
|
||||
* exist as the origin's catalog children are RE-PARENTED under the run
|
||||
* node, members without a catalog row are synthesized from the run's own
|
||||
@@ -22,14 +22,14 @@
|
||||
import type {
|
||||
SidebarSessionSummary,
|
||||
SidebarSubagentAddress,
|
||||
SidebarSubagentCatalog,
|
||||
SidebarSubagentChildEntry,
|
||||
SidebarSubagentCatalogEntry,
|
||||
SidebarTeamMemberView,
|
||||
SidebarTeamTaskView,
|
||||
} from '../context-types.ts'
|
||||
import type { LastActivity } from '../subagent-activity.ts'
|
||||
import type { WorkflowRunView } from '../workflow-runs.ts'
|
||||
import { isSideThreadSummary } from './subagent-detect.ts'
|
||||
import { childActivity, isKnownLeaf, type SubagentCatalogView } from './subagent-catalog.ts'
|
||||
|
||||
/** Display state of one agent node (drives the dot + fold candidacy). */
|
||||
export type TasksNodeState = 'running' | 'idle' | 'done' | 'error'
|
||||
@@ -52,7 +52,8 @@ export interface TasksAgentNode {
|
||||
label: string
|
||||
/** The summary's display title when it differs from the label. */
|
||||
title?: string
|
||||
mode?: 'one-shot' | 'continuable'
|
||||
/** The catalog row's mode; `unknown` claims neither and renders nothing. */
|
||||
mode?: SidebarSubagentCatalogEntry['mode']
|
||||
state: TasksNodeState
|
||||
/** The catalog's raw activity word (the secondary line localizes it). */
|
||||
activity: 'running' | 'inactive'
|
||||
@@ -103,7 +104,8 @@ export type TasksNode = TasksAgentNode | TasksWorkflowNode | TasksFoldNode
|
||||
/** Inputs of the model build (all already-resolved client mirrors). */
|
||||
export interface TasksModelInput {
|
||||
byId: Readonly<Record<string, SidebarSessionSummary>>
|
||||
catalogs: Readonly<Record<string, SidebarSubagentCatalog | undefined>>
|
||||
/** Per-parent catalog views (DSH 0.1.7 projectors, see {@link subagentCatalogs}). */
|
||||
catalogs: Readonly<Record<string, SubagentCatalogView | undefined>>
|
||||
rootId: string
|
||||
currentSessionId: string
|
||||
live: Readonly<Record<string, LastActivity | undefined>>
|
||||
@@ -117,7 +119,7 @@ export interface TasksModelInput {
|
||||
|
||||
/** Human label of one catalog child (the classic rule). */
|
||||
function childLabel(
|
||||
entry: SidebarSubagentChildEntry,
|
||||
entry: SidebarSubagentCatalogEntry,
|
||||
summary: SidebarSessionSummary | undefined,
|
||||
): string {
|
||||
return entry.label ?? summary?.displayTitle ?? entry.id
|
||||
@@ -196,26 +198,27 @@ export function buildTasksModel(input: TasksModelInput): TasksNode[] {
|
||||
const knownAgentIds = new Set<string>()
|
||||
for (const catalog of Object.values(catalogs)) {
|
||||
if (catalog?.state !== 'ready') continue
|
||||
for (const entry of catalog.entries) {
|
||||
if (entry.kind === 'child') knownAgentIds.add(entry.id)
|
||||
}
|
||||
for (const entry of catalog.entries) knownAgentIds.add(entry.id)
|
||||
}
|
||||
// The local children lists of `appendChildren` are built lazily per parent,
|
||||
// so this global set is what makes the guard below order-independent.
|
||||
|
||||
/** The agent children of one parent, in catalog order (side threads and
|
||||
* diagnostics excluded), with workflow runs appended in start order. */
|
||||
/** The agent children of one parent, in catalog order (side threads
|
||||
* excluded), with workflow runs appended in start order. */
|
||||
const appendChildren = (parentId: string): void => {
|
||||
const catalog = catalogs[parentId]
|
||||
const entries = catalog?.state === 'ready' ? catalog.entries : []
|
||||
const agentChildren: TasksAgentNode[] = []
|
||||
for (const entry of entries) {
|
||||
if (entry.kind !== 'child') continue
|
||||
const summary = byId[entry.id]
|
||||
if (summary !== undefined && isSideThreadSummary(summary)) continue
|
||||
if (entry.label?.startsWith('Side: ') ?? false) continue
|
||||
const team = teamOf(entry.id)
|
||||
const state: TasksNodeState = entry.activity === 'running'
|
||||
// DSH 0.1.7's catalog row carries the identity only: the live channel
|
||||
// folds RUNNING children (absence = not running) and a row keeps its
|
||||
// disclosure unless its own catalog is known-empty.
|
||||
const activity = childActivity(live, entry.id)
|
||||
const state: TasksNodeState = activity === 'running'
|
||||
? 'running'
|
||||
: team !== undefined ? teamState(team.status) : 'done'
|
||||
agentChildren.push({
|
||||
@@ -227,12 +230,12 @@ export function buildTasksModel(input: TasksModelInput): TasksNode[] {
|
||||
? { title: summary.displayTitle } : {}),
|
||||
mode: entry.mode,
|
||||
state,
|
||||
activity: entry.activity,
|
||||
activity,
|
||||
current: entry.id === currentSessionId,
|
||||
...(live[entry.id] !== undefined ? { live: live[entry.id] } : {}),
|
||||
...(team !== undefined ? { team } : {}),
|
||||
...(tasksByNode.get(entry.id) !== undefined ? { tasks: tasksByNode.get(entry.id) } : {}),
|
||||
hasChildren: entry.hasChildren,
|
||||
hasChildren: !isKnownLeaf(catalogs, entry.id),
|
||||
childAddress: { parentSessionId: parentId, childSessionId: entry.id, mode: entry.mode },
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user