@agimon-ai/doompi-task 0.0.1-alpha.83 → 0.0.1-alpha.85

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.
@@ -330,10 +330,10 @@ var task_server_default = defineServerTool(task_server_default$1);
330
330
  //#endregion
331
331
  //#region generated/server.ts
332
332
  const at = (value, context) => typeof value === "function" ? value(context) : value;
333
- const via = (identity, value) => ({
333
+ const via = (identity, value) => value === void 0 ? void 0 : {
334
334
  ...identity,
335
335
  ...value
336
- });
336
+ };
337
337
  const facet = defineServerPlugin({
338
338
  name: "@agimon-ai/doompi-task",
339
339
  global: () => ({ get channels() {
@@ -1 +1 @@
1
- {"version":3,"file":"server.mjs","names":["contribution","contribution","contribution","contribution","contribution","channelTaskGraph","rootSession","commandTasks","resourceTaskBoard","toolTask"],"sources":["../../src/types/webTasks.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/root.server.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/extensions/(backend)/channel/_lib/task-graph.ts","../../src/extensions/(backend)/channel/task-graph.server.ts","../../src/services/taskTool/index.ts","../../src/extensions/workspaces/sessions/(backend)/command/_lib/tasks.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/tasks.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/_lib/task-board.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/task-board.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/_lib/task.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/task.server.ts","../../generated/server.ts"],"sourcesContent":["/** Browser-safe task view published by the cockpit hub channel. */\nexport const TASKS_CHANNEL_TYPE = 'task_graph';\n\nexport type WebTaskStatus = 'pending' | 'in_progress' | 'completed' | 'failed' | 'deleted';\n\nexport interface WebTask {\n id: number;\n subject: string;\n description?: string;\n activeForm?: string;\n status: WebTaskStatus;\n blockedBy: number[];\n owner?: string;\n updatedAt?: string;\n delegation?: {\n agent?: string;\n state?: string;\n };\n}\n\nexport interface WebTasksPayload {\n tasks: WebTask[];\n rev: number;\n}\n","import { DOOM_DELEGATION_SERVICE, readDoomDelegationService } from '@agimon-ai/doompi-core/delegation';\nimport { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport { getDelegationTimeoutMs, getMaxTasks, getStoreTtlMs } from '../../../../../services/config';\nimport { DelegationManager } from '../../../../../services/delegation';\nimport { createNodeDelegationPlatform } from '../../../../../services/delegationPlatform';\nimport {\n removeLegacyStoreDirectoryAsync,\n resolveSessionKey,\n sweepStoreFilesAsync,\n} from '../../../../../services/paths';\nimport { TaskStore } from '../../../../../services/taskStore';\nimport { TASKS_CHANNEL_TYPE } from '../../../../../types/webTasks';\n\nconst SOURCE = '@agimon-ai/doompi-task';\n\n/** The notification body: one line, since `client.notify` collapses the rest anyway. */\nfunction headlineOf(content: string): string {\n return content.split('\\n').find((line) => line.trim().length > 0) ?? content;\n}\n\nconst root = defineRoot(({ host: serverHost, agent: host }: DoomServerPluginContext) => {\n if (!host) throw new Error('Task session requires the headless host.');\n const execution = host.context;\n if (serverHost.context.directEvents === undefined)\n throw new Error('Task headless facet requires the session direct event bus.');\n const directEvents = serverHost.context.directEvents;\n const maxTasks = getMaxTasks(execution.environment);\n const store = new TaskStore({\n env: execution.environment,\n onCommitted: (_previous, committed) => {\n execution.client.setStatus(SOURCE, `tasks: ${committed.tasks.length}`);\n directEvents.publish(TASKS_CHANNEL_TYPE, execution.sessionId, committed);\n },\n });\n store.configureSession(resolveSessionKey(execution.sessionId, execution.environment));\n let notifications: Promise<void> = Promise.resolve();\n const manager = new DelegationManager({\n store,\n cwd: execution.cwd,\n platform: createNodeDelegationPlatform(execution.environment),\n getSessionId: () => execution.sessionId,\n notify: (message, options) => {\n // `DelegationNotifier` is Pi's `sendMessage` shape, and the Pi facet\n // forwards it verbatim (`root.cli.ts`). A headless session has no such\n // single call, so the three jobs are done by hand:\n //\n // toast `client.notify` - operator-facing only, flattened to one\n // line and capped at 4096 chars, and the model never sees a\n // custom entry. It gets the headline, not the whole result.\n // transcript `session.appendCustomEntry` under the same custom type,\n // carrying the full multi-line content.\n // wake `session.admitPrompt(content, 'steer')` - the only call\n // that puts the completion in front of the model.\n // `session.prompt(_, 'steer')` is enqueue-only and parks the\n // message on an idle lane, which is why a finished subagent\n // used to leave the agent sitting idle.\n //\n // Sequenced so two delegations settling in the same tick each observe\n // settled lane state rather than racing.\n notifications = notifications\n .then(async () => {\n await execution.client.notify({ body: headlineOf(message.content), level: 'info' });\n await execution.session.appendCustomEntry(message.customType, { content: message.content });\n // `triggerTurn: false` has no faithful headless mapping - there is no\n // way to reach model context without starting or joining a turn - so\n // it stays a toast, as it is today. `DelegationManager` always sends\n // `true`, so this is defensive rather than live.\n if (options?.triggerTurn === false) return;\n // Matching the voice facet, which also refuses rather than degrading:\n // `session.prompt(_, 'steer')` is NOT a fallback here, because it is\n // enqueue-only and would park the message on an idle lane - the\n // original bug.\n if (!execution.session.admitPrompt) throw new Error('The session cannot admit a task notification.');\n await execution.session.admitPrompt(message.content, 'steer');\n })\n .catch((error: unknown) => {\n // Mirrors `onNotifyError` below. The delegation is already committed,\n // so a failed notification costs the model its wake-up, not the\n // result, and must not stall later notifications.\n void execution.client.notify({ body: String(error), level: 'warning' });\n });\n },\n onChange: () => execution.client.setStatus(SOURCE, `tasks: ${store.snapshot.tasks.length}`),\n runTimeoutMs: getDelegationTimeoutMs(execution.environment),\n onNotifyError: (error) => void execution.client.notify({ body: String(error), level: 'warning' }),\n });\n return {\n value: { store, manager, maxTasks },\n services: [\n (serviceContextOwner: Context) => {\n serviceContextOwner.inject([DOOM_DELEGATION_SERVICE], (serviceContext) => {\n const service = readDoomDelegationService(serviceContext);\n if (service) manager.bind(serviceContext, service);\n });\n },\n ],\n activities: [\n {\n name: SOURCE,\n async start(activityContext) {\n store.configureSession(resolveSessionKey(activityContext.sessionId, activityContext.environment));\n await removeLegacyStoreDirectoryAsync(store.storePath, activityContext.cwd);\n if (!activityContext.environment.DOOM_TASK_STORE_PATH)\n await sweepStoreFilesAsync(store.storePath, getStoreTtlMs(activityContext.environment));\n await store.readAsync();\n await manager.reconcile();\n execution.client.setStatus(SOURCE, `tasks: ${store.snapshot.tasks.length}`);\n return () => {\n manager.reset();\n execution.client.setStatus(SOURCE, undefined);\n };\n },\n },\n ],\n onDispose() {\n manager.dispose();\n store.dispose();\n },\n };\n});\n\nexport type TaskServerScope = Awaited<ReturnType<typeof root>>['value'];\nexport default root;\n","import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/root.server';\n\nexport default defineRoot(contribution);\n","import type { DoomHubChannelSource, DoomHubSessionScope, DoomHubChannel } from '@agimon-ai/doompi-core/hubChannel';\n\nimport type { TaskDocument } from '../../../../models/task';\nimport { resolveStorePath } from '../../../../services/paths';\nimport { TaskStore } from '../../../../services/taskStore';\nimport { TASKS_CHANNEL_TYPE, type WebTask, type WebTasksPayload } from '../../../../types/webTasks';\n\ninterface TaskStoreSource {\n readonly snapshot: TaskDocument;\n read(): TaskDocument;\n dispose(): void;\n}\n\nfunction isTaskDocument(value: unknown): value is TaskDocument {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as TaskDocument).rev === 'number' &&\n Array.isArray((value as TaskDocument).tasks)\n );\n}\n\nexport interface TasksChannelOptions {\n /** Injectable for tests. The default opens the session tree's durable task store. */\n storeFor?: (scope: DoomHubSessionScope) => TaskStoreSource;\n}\n\nfunction present(document: TaskDocument): WebTasksPayload {\n const tasks: WebTask[] = document.tasks.flatMap((task) => {\n if (task.status === 'deleted') return [];\n const view: WebTask = {\n id: task.id,\n subject: task.subject,\n status: task.status,\n blockedBy: task.blockedBy ?? [],\n };\n if (task.description) view.description = task.description;\n if (task.activeForm) view.activeForm = task.activeForm;\n if (task.owner) view.owner = task.owner;\n if (task.updatedAt) view.updatedAt = task.updatedAt;\n if (task.delegation) {\n view.delegation = {\n ...(task.delegation.agent === undefined ? {} : { agent: task.delegation.agent }),\n ...(task.delegation.state === undefined ? {} : { state: task.delegation.state }),\n };\n }\n return [view];\n });\n return { tasks, rev: document.rev };\n}\n\n/** Publishes each managed session's durable task graph and follows direct session commits. */\nexport function createTasksChannel(options: TasksChannelOptions = {}): DoomHubChannel {\n return {\n frameType: TASKS_CHANNEL_TYPE,\n start(host) {\n const stores = new Map<string, { store: TaskStoreSource; unsubscribe: () => void; latest?: TaskDocument }>();\n const open = (scope: DoomHubSessionScope): void => {\n if (stores.has(scope.sessionId)) return;\n let store = options.storeFor?.(scope);\n if (store === undefined) {\n if (scope.environment === undefined)\n throw new Error(`Task channel requires an admitted environment for session '${scope.sessionId}'.`);\n store = new TaskStore({\n cwd: scope.cwd,\n env: scope.environment,\n storePath: resolveStorePath(scope.cwd, scope.environment, scope.sessionId),\n });\n }\n store.read();\n const source = { store, unsubscribe: () => undefined as void };\n stores.set(scope.sessionId, source);\n source.unsubscribe = host.directEvents.subscribe(\n TASKS_CHANNEL_TYPE,\n scope.sessionId,\n (payload) => {\n if (!isTaskDocument(payload)) return;\n const current = stores.get(scope.sessionId);\n if (current === undefined) return;\n current.latest = payload;\n host.publish(scope.sessionId, present(payload));\n },\n { replayLatest: true },\n );\n };\n const close = (sessionId: string): void => {\n const source = stores.get(sessionId);\n if (!source) return;\n source.unsubscribe();\n source.store.dispose();\n stores.delete(sessionId);\n };\n for (const scope of host.sessions()) open(scope);\n\n const source: DoomHubChannelSource = {\n payloadFor(scope) {\n open(scope);\n const source = stores.get(scope.sessionId);\n const document = source?.latest ?? source?.store.snapshot;\n return document === undefined ? undefined : present(document);\n },\n sessionAdded: open,\n sessionRemoved: close,\n close() {\n for (const sessionId of stores.keys()) close(sessionId);\n },\n };\n return source;\n },\n };\n}\n\nexport default createTasksChannel;\n","import { defineChannel } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/task-graph';\n\nexport default defineChannel(contribution);\n","import type { DoomHeadlessTool, DoomHeadlessToolResult } from '@agimon-ai/doompi-core/headless';\nimport { Check } from 'typebox/value';\n\nimport type { TaskMutationParams } from '../../models/task';\nimport { TaskParamsSchema, type TaskParams, type TaskAssignmentParams } from '../../schemas/task';\nimport type { DelegationManager } from '../delegation';\nimport { applyTaskMutation, isCommittingOp, type ReducerAction } from '../reducer';\nimport { buildAssignmentResult, buildTextResult, buildToolResult, formatAssignmentResults } from '../taskResult';\nimport type { TaskStore } from '../taskStore';\n\nfunction output(value: unknown): DoomHeadlessToolResult {\n if (typeof value === 'object' && value !== null && 'content' in value) return value as DoomHeadlessToolResult;\n const text = typeof value === 'string' ? value : JSON.stringify(value, null, 2);\n return { content: [{ type: 'text', text }], details: value };\n}\n\nfunction failure(error: unknown): DoomHeadlessToolResult {\n return { content: [{ type: 'text', text: error instanceof Error ? error.message : String(error) }], isError: true };\n}\n\nexport async function reducerAction(\n store: TaskStore,\n action: ReducerAction,\n params: TaskMutationParams,\n maxTasks: number,\n): Promise<DoomHeadlessToolResult> {\n const { document, value } = await store.mutate((current) => {\n const result = applyTaskMutation(current, action, params, undefined, maxTasks);\n return { ...(isCommittingOp(result.op) ? { document: result.document } : {}), value: result };\n });\n if (value.op.kind === 'error') throw new Error(value.op.message);\n return buildToolResult(action, params, document, value.op);\n}\n\ninterface AssignmentItemResult {\n index: number;\n id: number;\n agent: string;\n ok: boolean;\n message: string;\n}\n\nasync function assignmentBatch(\n manager: DelegationManager,\n assignments: readonly TaskAssignmentParams[],\n signal?: AbortSignal,\n): Promise<AssignmentItemResult[]> {\n const result: AssignmentItemResult[] = [];\n for (const [index, assignment] of assignments.entries()) {\n try {\n const outcome = await manager.assign(assignment.id, {\n agent: assignment.agent,\n inlineAgent: assignment.inlineAgent,\n instructions: assignment.instructions,\n relevantFiles: assignment.relevantFiles,\n priorFindings: assignment.priorFindings,\n model: assignment.model,\n ...(assignment.context === 'fork' || assignment.context === 'fresh' ? { context: assignment.context } : {}),\n signal,\n });\n result.push({ index, id: assignment.id, agent: assignment.agent, ...outcome });\n } catch (error) {\n result.push({ index, id: assignment.id, agent: assignment.agent, ok: false, message: String(error) });\n }\n }\n return result;\n}\n\nexport function createHeadlessTaskTool(\n store: TaskStore,\n manager: DelegationManager,\n maxTasks: number,\n): DoomHeadlessTool<typeof TaskParamsSchema> {\n return {\n name: 'task',\n label: 'Task',\n description: 'Maintain a persistent task graph and delegate ready tasks to background agents.',\n parameters: TaskParamsSchema,\n promptSnippet: 'Track complex work persistently and delegate ready tasks',\n executionMode: 'serial',\n async execute(_toolCallId, rawParams, signal, onUpdate) {\n if (!Check(TaskParamsSchema, rawParams)) return failure('Invalid task parameters.');\n const params = rawParams as TaskParams;\n try {\n if (params.action === 'assign') {\n if (!params.assignments?.length) throw new Error('assign requires a non-empty assignments[] array');\n onUpdate?.(\n output(`Delegating ${params.assignments.length} task${params.assignments.length === 1 ? '' : 's'}...`),\n );\n const items = await assignmentBatch(manager, params.assignments, signal);\n const assigned = items.filter((item) => item.ok).map((item) => item.id);\n const text = formatAssignmentResults(items);\n if (assigned.length === 0) throw new Error(text);\n return buildAssignmentResult(params as TaskMutationParams, store.snapshot, text, {\n assigned,\n failed: items.length - assigned.length,\n });\n }\n if (params.action === 'cancel') {\n const outcome = await manager.cancel(params.id ?? Number.NaN);\n if (!outcome.ok) throw new Error(outcome.message);\n return buildTextResult('cancel', params as TaskMutationParams, store.snapshot, outcome.message);\n }\n return reducerAction(store, params.action as ReducerAction, params as TaskMutationParams, maxTasks);\n } catch (error) {\n return failure(error);\n }\n },\n };\n}\n","import type { WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomHeadlessExecutionContext } from '@agimon-ai/doompi-core/headless';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport { COMMAND_NAME } from '../../../../../../constants/task';\nimport { reducerAction } from '../../../../../../services/taskTool';\nimport type { TaskServerScope } from '../../_lib/root.server';\n\nexport default (context: WithRoot<DoomServerPluginContext, TaskServerScope>) => ({\n name: COMMAND_NAME,\n description: 'List or clear the persistent task graph.',\n async execute(args: string, commandContext: DoomHeadlessExecutionContext) {\n const action = args.trim() === 'clear' ? 'clear' : 'list';\n const response = await reducerAction(context.root.store, action, { action }, context.root.maxTasks);\n const content = response.content[0];\n await commandContext.client.notify({\n body: content?.type === 'text' ? content.text : 'No tasks',\n level: 'info',\n });\n },\n});\n","import { defineServerCommand } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/tasks.server';\n\nexport default defineServerCommand(contribution);\n","import type { WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport { activeTaskSnapshots, formatTaskSnapshots } from '../../../../../../services/contextContribution';\nimport type { TaskServerScope } from '../../_lib/root.server';\n\nexport default (context: WithRoot<DoomServerPluginContext, TaskServerScope>) => ({\n name: 'doompi/task-board',\n kind: 'context' as const,\n /**\n * The same bounded projection the Pi facet renders: open work only, one line each.\n * Dumping the whole TaskDocument put every completed task plus the store's own\n * version/rev/nextId bookkeeping in the prompt, and an idle board still cost a\n * paragraph. '' is dropped by the prompt composer.\n */\n read: () => {\n const rendered = formatTaskSnapshots(activeTaskSnapshots(context.root.store.snapshot.tasks));\n return rendered === '(no active tasks)' ? '' : rendered;\n },\n});\n","import { defineResource } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/task-board.server';\n\nexport default defineResource(contribution);\n","import { defineServerTool, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport { createHeadlessTaskTool } from '../../../../../../services/taskTool';\nimport type { TaskServerScope } from '../../_lib/root.server';\n\nexport default defineServerTool((context: WithRoot<DoomServerPluginContext, TaskServerScope>) =>\n createHeadlessTaskTool(context.root.store, context.root.manager, context.root.maxTasks),\n);\n","import { defineServerTool } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/task.server';\n\nexport default defineServerTool(contribution);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport channelTaskGraph from '../src/extensions/(backend)/channel/task-graph.server';\nimport commandTasks from '../src/extensions/workspaces/sessions/(backend)/command/tasks.server';\nimport resourceTaskBoard from '../src/extensions/workspaces/sessions/(backend)/resource/task-board.server';\nimport toolTask from '../src/extensions/workspaces/sessions/(backend)/tool/task.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T => ({ ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/doompi-task',\n global: () => ({\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'task_graph' }, channelTaskGraph())]; },\n }),\n workspace: () => ({\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'task_graph' }, channelTaskGraph())]; },\n }),\n session: async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'task_graph' }, channelTaskGraph())]; },\n get commands(): DoomServerSessionPlugin['commands'] { return [via({ name: 'tasks' }, at(commandTasks, contextSession))]; },\n get resources(): DoomServerSessionPlugin['resources'] { return [at(resourceTaskBoard, contextSession)]; },\n get tools(): DoomServerSessionPlugin['tools'] { return [via({ name: 'task' }, at(toolTask, contextSession))]; },\n services: [...(scopeSession.services ?? [])],\n get activities(): DoomServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":"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"}
1
+ {"version":3,"file":"server.mjs","names":["contribution","contribution","contribution","contribution","contribution","channelTaskGraph","rootSession","commandTasks","resourceTaskBoard","toolTask"],"sources":["../../src/types/webTasks.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/root.server.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/extensions/(backend)/channel/_lib/task-graph.ts","../../src/extensions/(backend)/channel/task-graph.server.ts","../../src/services/taskTool/index.ts","../../src/extensions/workspaces/sessions/(backend)/command/_lib/tasks.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/tasks.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/_lib/task-board.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/task-board.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/_lib/task.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/task.server.ts","../../generated/server.ts"],"sourcesContent":["/** Browser-safe task view published by the cockpit hub channel. */\nexport const TASKS_CHANNEL_TYPE = 'task_graph';\n\nexport type WebTaskStatus = 'pending' | 'in_progress' | 'completed' | 'failed' | 'deleted';\n\nexport interface WebTask {\n id: number;\n subject: string;\n description?: string;\n activeForm?: string;\n status: WebTaskStatus;\n blockedBy: number[];\n owner?: string;\n updatedAt?: string;\n delegation?: {\n agent?: string;\n state?: string;\n };\n}\n\nexport interface WebTasksPayload {\n tasks: WebTask[];\n rev: number;\n}\n","import { DOOM_DELEGATION_SERVICE, readDoomDelegationService } from '@agimon-ai/doompi-core/delegation';\nimport { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport { getDelegationTimeoutMs, getMaxTasks, getStoreTtlMs } from '../../../../../services/config';\nimport { DelegationManager } from '../../../../../services/delegation';\nimport { createNodeDelegationPlatform } from '../../../../../services/delegationPlatform';\nimport {\n removeLegacyStoreDirectoryAsync,\n resolveSessionKey,\n sweepStoreFilesAsync,\n} from '../../../../../services/paths';\nimport { TaskStore } from '../../../../../services/taskStore';\nimport { TASKS_CHANNEL_TYPE } from '../../../../../types/webTasks';\n\nconst SOURCE = '@agimon-ai/doompi-task';\n\n/** The notification body: one line, since `client.notify` collapses the rest anyway. */\nfunction headlineOf(content: string): string {\n return content.split('\\n').find((line) => line.trim().length > 0) ?? content;\n}\n\nconst root = defineRoot(({ host: serverHost, agent: host }: DoomServerPluginContext) => {\n if (!host) throw new Error('Task session requires the headless host.');\n const execution = host.context;\n if (serverHost.context.directEvents === undefined)\n throw new Error('Task headless facet requires the session direct event bus.');\n const directEvents = serverHost.context.directEvents;\n const maxTasks = getMaxTasks(execution.environment);\n const store = new TaskStore({\n env: execution.environment,\n onCommitted: (_previous, committed) => {\n execution.client.setStatus(SOURCE, `tasks: ${committed.tasks.length}`);\n directEvents.publish(TASKS_CHANNEL_TYPE, execution.sessionId, committed);\n },\n });\n store.configureSession(resolveSessionKey(execution.sessionId, execution.environment));\n let notifications: Promise<void> = Promise.resolve();\n const manager = new DelegationManager({\n store,\n cwd: execution.cwd,\n platform: createNodeDelegationPlatform(execution.environment),\n getSessionId: () => execution.sessionId,\n notify: (message, options) => {\n // `DelegationNotifier` is Pi's `sendMessage` shape, and the Pi facet\n // forwards it verbatim (`root.cli.ts`). A headless session has no such\n // single call, so the three jobs are done by hand:\n //\n // toast `client.notify` - operator-facing only, flattened to one\n // line and capped at 4096 chars, and the model never sees a\n // custom entry. It gets the headline, not the whole result.\n // transcript `session.appendCustomEntry` under the same custom type,\n // carrying the full multi-line content.\n // wake `session.admitPrompt(content, 'steer')` - the only call\n // that puts the completion in front of the model.\n // `session.prompt(_, 'steer')` is enqueue-only and parks the\n // message on an idle lane, which is why a finished subagent\n // used to leave the agent sitting idle.\n //\n // Sequenced so two delegations settling in the same tick each observe\n // settled lane state rather than racing.\n notifications = notifications\n .then(async () => {\n await execution.client.notify({ body: headlineOf(message.content), level: 'info' });\n await execution.session.appendCustomEntry(message.customType, { content: message.content });\n // `triggerTurn: false` has no faithful headless mapping - there is no\n // way to reach model context without starting or joining a turn - so\n // it stays a toast, as it is today. `DelegationManager` always sends\n // `true`, so this is defensive rather than live.\n if (options?.triggerTurn === false) return;\n // Matching the voice facet, which also refuses rather than degrading:\n // `session.prompt(_, 'steer')` is NOT a fallback here, because it is\n // enqueue-only and would park the message on an idle lane - the\n // original bug.\n if (!execution.session.admitPrompt) throw new Error('The session cannot admit a task notification.');\n await execution.session.admitPrompt(message.content, 'steer');\n })\n .catch((error: unknown) => {\n // Mirrors `onNotifyError` below. The delegation is already committed,\n // so a failed notification costs the model its wake-up, not the\n // result, and must not stall later notifications.\n void execution.client.notify({ body: String(error), level: 'warning' });\n });\n },\n onChange: () => execution.client.setStatus(SOURCE, `tasks: ${store.snapshot.tasks.length}`),\n runTimeoutMs: getDelegationTimeoutMs(execution.environment),\n onNotifyError: (error) => void execution.client.notify({ body: String(error), level: 'warning' }),\n });\n return {\n value: { store, manager, maxTasks },\n services: [\n (serviceContextOwner: Context) => {\n serviceContextOwner.inject([DOOM_DELEGATION_SERVICE], (serviceContext) => {\n const service = readDoomDelegationService(serviceContext);\n if (service) manager.bind(serviceContext, service);\n });\n },\n ],\n activities: [\n {\n name: SOURCE,\n async start(activityContext) {\n store.configureSession(resolveSessionKey(activityContext.sessionId, activityContext.environment));\n await removeLegacyStoreDirectoryAsync(store.storePath, activityContext.cwd);\n if (!activityContext.environment.DOOM_TASK_STORE_PATH)\n await sweepStoreFilesAsync(store.storePath, getStoreTtlMs(activityContext.environment));\n await store.readAsync();\n await manager.reconcile();\n execution.client.setStatus(SOURCE, `tasks: ${store.snapshot.tasks.length}`);\n return () => {\n manager.reset();\n execution.client.setStatus(SOURCE, undefined);\n };\n },\n },\n ],\n onDispose() {\n manager.dispose();\n store.dispose();\n },\n };\n});\n\nexport type TaskServerScope = Awaited<ReturnType<typeof root>>['value'];\nexport default root;\n","import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/root.server';\n\nexport default defineRoot(contribution);\n","import type { DoomHubChannelSource, DoomHubSessionScope, DoomHubChannel } from '@agimon-ai/doompi-core/hubChannel';\n\nimport type { TaskDocument } from '../../../../models/task';\nimport { resolveStorePath } from '../../../../services/paths';\nimport { TaskStore } from '../../../../services/taskStore';\nimport { TASKS_CHANNEL_TYPE, type WebTask, type WebTasksPayload } from '../../../../types/webTasks';\n\ninterface TaskStoreSource {\n readonly snapshot: TaskDocument;\n read(): TaskDocument;\n dispose(): void;\n}\n\nfunction isTaskDocument(value: unknown): value is TaskDocument {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as TaskDocument).rev === 'number' &&\n Array.isArray((value as TaskDocument).tasks)\n );\n}\n\nexport interface TasksChannelOptions {\n /** Injectable for tests. The default opens the session tree's durable task store. */\n storeFor?: (scope: DoomHubSessionScope) => TaskStoreSource;\n}\n\nfunction present(document: TaskDocument): WebTasksPayload {\n const tasks: WebTask[] = document.tasks.flatMap((task) => {\n if (task.status === 'deleted') return [];\n const view: WebTask = {\n id: task.id,\n subject: task.subject,\n status: task.status,\n blockedBy: task.blockedBy ?? [],\n };\n if (task.description) view.description = task.description;\n if (task.activeForm) view.activeForm = task.activeForm;\n if (task.owner) view.owner = task.owner;\n if (task.updatedAt) view.updatedAt = task.updatedAt;\n if (task.delegation) {\n view.delegation = {\n ...(task.delegation.agent === undefined ? {} : { agent: task.delegation.agent }),\n ...(task.delegation.state === undefined ? {} : { state: task.delegation.state }),\n };\n }\n return [view];\n });\n return { tasks, rev: document.rev };\n}\n\n/** Publishes each managed session's durable task graph and follows direct session commits. */\nexport function createTasksChannel(options: TasksChannelOptions = {}): DoomHubChannel {\n return {\n frameType: TASKS_CHANNEL_TYPE,\n start(host) {\n const stores = new Map<string, { store: TaskStoreSource; unsubscribe: () => void; latest?: TaskDocument }>();\n const open = (scope: DoomHubSessionScope): void => {\n if (stores.has(scope.sessionId)) return;\n let store = options.storeFor?.(scope);\n if (store === undefined) {\n if (scope.environment === undefined)\n throw new Error(`Task channel requires an admitted environment for session '${scope.sessionId}'.`);\n store = new TaskStore({\n cwd: scope.cwd,\n env: scope.environment,\n storePath: resolveStorePath(scope.cwd, scope.environment, scope.sessionId),\n });\n }\n store.read();\n const source = { store, unsubscribe: () => undefined as void };\n stores.set(scope.sessionId, source);\n source.unsubscribe = host.directEvents.subscribe(\n TASKS_CHANNEL_TYPE,\n scope.sessionId,\n (payload) => {\n if (!isTaskDocument(payload)) return;\n const current = stores.get(scope.sessionId);\n if (current === undefined) return;\n current.latest = payload;\n host.publish(scope.sessionId, present(payload));\n },\n { replayLatest: true },\n );\n };\n const close = (sessionId: string): void => {\n const source = stores.get(sessionId);\n if (!source) return;\n source.unsubscribe();\n source.store.dispose();\n stores.delete(sessionId);\n };\n for (const scope of host.sessions()) open(scope);\n\n const source: DoomHubChannelSource = {\n payloadFor(scope) {\n open(scope);\n const source = stores.get(scope.sessionId);\n const document = source?.latest ?? source?.store.snapshot;\n return document === undefined ? undefined : present(document);\n },\n sessionAdded: open,\n sessionRemoved: close,\n close() {\n for (const sessionId of stores.keys()) close(sessionId);\n },\n };\n return source;\n },\n };\n}\n\nexport default createTasksChannel;\n","import { defineChannel } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/task-graph';\n\nexport default defineChannel(contribution);\n","import type { DoomHeadlessTool, DoomHeadlessToolResult } from '@agimon-ai/doompi-core/headless';\nimport { Check } from 'typebox/value';\n\nimport type { TaskMutationParams } from '../../models/task';\nimport { TaskParamsSchema, type TaskParams, type TaskAssignmentParams } from '../../schemas/task';\nimport type { DelegationManager } from '../delegation';\nimport { applyTaskMutation, isCommittingOp, type ReducerAction } from '../reducer';\nimport { buildAssignmentResult, buildTextResult, buildToolResult, formatAssignmentResults } from '../taskResult';\nimport type { TaskStore } from '../taskStore';\n\nfunction output(value: unknown): DoomHeadlessToolResult {\n if (typeof value === 'object' && value !== null && 'content' in value) return value as DoomHeadlessToolResult;\n const text = typeof value === 'string' ? value : JSON.stringify(value, null, 2);\n return { content: [{ type: 'text', text }], details: value };\n}\n\nfunction failure(error: unknown): DoomHeadlessToolResult {\n return { content: [{ type: 'text', text: error instanceof Error ? error.message : String(error) }], isError: true };\n}\n\nexport async function reducerAction(\n store: TaskStore,\n action: ReducerAction,\n params: TaskMutationParams,\n maxTasks: number,\n): Promise<DoomHeadlessToolResult> {\n const { document, value } = await store.mutate((current) => {\n const result = applyTaskMutation(current, action, params, undefined, maxTasks);\n return { ...(isCommittingOp(result.op) ? { document: result.document } : {}), value: result };\n });\n if (value.op.kind === 'error') throw new Error(value.op.message);\n return buildToolResult(action, params, document, value.op);\n}\n\ninterface AssignmentItemResult {\n index: number;\n id: number;\n agent: string;\n ok: boolean;\n message: string;\n}\n\nasync function assignmentBatch(\n manager: DelegationManager,\n assignments: readonly TaskAssignmentParams[],\n signal?: AbortSignal,\n): Promise<AssignmentItemResult[]> {\n const result: AssignmentItemResult[] = [];\n for (const [index, assignment] of assignments.entries()) {\n try {\n const outcome = await manager.assign(assignment.id, {\n agent: assignment.agent,\n inlineAgent: assignment.inlineAgent,\n instructions: assignment.instructions,\n relevantFiles: assignment.relevantFiles,\n priorFindings: assignment.priorFindings,\n model: assignment.model,\n ...(assignment.context === 'fork' || assignment.context === 'fresh' ? { context: assignment.context } : {}),\n signal,\n });\n result.push({ index, id: assignment.id, agent: assignment.agent, ...outcome });\n } catch (error) {\n result.push({ index, id: assignment.id, agent: assignment.agent, ok: false, message: String(error) });\n }\n }\n return result;\n}\n\nexport function createHeadlessTaskTool(\n store: TaskStore,\n manager: DelegationManager,\n maxTasks: number,\n): DoomHeadlessTool<typeof TaskParamsSchema> {\n return {\n name: 'task',\n label: 'Task',\n description: 'Maintain a persistent task graph and delegate ready tasks to background agents.',\n parameters: TaskParamsSchema,\n promptSnippet: 'Track complex work persistently and delegate ready tasks',\n executionMode: 'serial',\n async execute(_toolCallId, rawParams, signal, onUpdate) {\n if (!Check(TaskParamsSchema, rawParams)) return failure('Invalid task parameters.');\n const params = rawParams as TaskParams;\n try {\n if (params.action === 'assign') {\n if (!params.assignments?.length) throw new Error('assign requires a non-empty assignments[] array');\n onUpdate?.(\n output(`Delegating ${params.assignments.length} task${params.assignments.length === 1 ? '' : 's'}...`),\n );\n const items = await assignmentBatch(manager, params.assignments, signal);\n const assigned = items.filter((item) => item.ok).map((item) => item.id);\n const text = formatAssignmentResults(items);\n if (assigned.length === 0) throw new Error(text);\n return buildAssignmentResult(params as TaskMutationParams, store.snapshot, text, {\n assigned,\n failed: items.length - assigned.length,\n });\n }\n if (params.action === 'cancel') {\n const outcome = await manager.cancel(params.id ?? Number.NaN);\n if (!outcome.ok) throw new Error(outcome.message);\n return buildTextResult('cancel', params as TaskMutationParams, store.snapshot, outcome.message);\n }\n return reducerAction(store, params.action as ReducerAction, params as TaskMutationParams, maxTasks);\n } catch (error) {\n return failure(error);\n }\n },\n };\n}\n","import type { WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomHeadlessExecutionContext } from '@agimon-ai/doompi-core/headless';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport { COMMAND_NAME } from '../../../../../../constants/task';\nimport { reducerAction } from '../../../../../../services/taskTool';\nimport type { TaskServerScope } from '../../_lib/root.server';\n\nexport default (context: WithRoot<DoomServerPluginContext, TaskServerScope>) => ({\n name: COMMAND_NAME,\n description: 'List or clear the persistent task graph.',\n async execute(args: string, commandContext: DoomHeadlessExecutionContext) {\n const action = args.trim() === 'clear' ? 'clear' : 'list';\n const response = await reducerAction(context.root.store, action, { action }, context.root.maxTasks);\n const content = response.content[0];\n await commandContext.client.notify({\n body: content?.type === 'text' ? content.text : 'No tasks',\n level: 'info',\n });\n },\n});\n","import { defineServerCommand } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/tasks.server';\n\nexport default defineServerCommand(contribution);\n","import type { WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport { activeTaskSnapshots, formatTaskSnapshots } from '../../../../../../services/contextContribution';\nimport type { TaskServerScope } from '../../_lib/root.server';\n\nexport default (context: WithRoot<DoomServerPluginContext, TaskServerScope>) => ({\n name: 'doompi/task-board',\n kind: 'context' as const,\n /**\n * The same bounded projection the Pi facet renders: open work only, one line each.\n * Dumping the whole TaskDocument put every completed task plus the store's own\n * version/rev/nextId bookkeeping in the prompt, and an idle board still cost a\n * paragraph. '' is dropped by the prompt composer.\n */\n read: () => {\n const rendered = formatTaskSnapshots(activeTaskSnapshots(context.root.store.snapshot.tasks));\n return rendered === '(no active tasks)' ? '' : rendered;\n },\n});\n","import { defineResource } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/task-board.server';\n\nexport default defineResource(contribution);\n","import { defineServerTool, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport { createHeadlessTaskTool } from '../../../../../../services/taskTool';\nimport type { TaskServerScope } from '../../_lib/root.server';\n\nexport default defineServerTool((context: WithRoot<DoomServerPluginContext, TaskServerScope>) =>\n createHeadlessTaskTool(context.root.store, context.root.manager, context.root.maxTasks),\n);\n","import { defineServerTool } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/task.server';\n\nexport default defineServerTool(contribution);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport channelTaskGraph from '../src/extensions/(backend)/channel/task-graph.server';\nimport commandTasks from '../src/extensions/workspaces/sessions/(backend)/command/tasks.server';\nimport resourceTaskBoard from '../src/extensions/workspaces/sessions/(backend)/resource/task-board.server';\nimport toolTask from '../src/extensions/workspaces/sessions/(backend)/tool/task.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/doompi-task',\n global: () => ({\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'task_graph' }, channelTaskGraph())]; },\n }),\n workspace: () => ({\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'task_graph' }, channelTaskGraph())]; },\n }),\n session: async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'task_graph' }, channelTaskGraph())]; },\n get commands(): DoomServerSessionPlugin['commands'] { return [via({ name: 'tasks' }, at(commandTasks, contextSession))]; },\n get resources(): DoomServerSessionPlugin['resources'] { return [at(resourceTaskBoard, contextSession)]; },\n get tools(): DoomServerSessionPlugin['tools'] { return [via({ name: 'task' }, at(toolTask, contextSession))]; },\n services: [...(scopeSession.services ?? [])],\n get activities(): DoomServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":"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"}
@@ -983,10 +983,10 @@ function TaskToolMessage({ args, result, output, running, isError }) {
983
983
  var task_web_default = defineToolRenderer({ message: TaskToolMessage });
984
984
  //#endregion
985
985
  //#region generated/web.ts
986
- const via = (identity, value) => ({
986
+ const via = (identity, value) => value === void 0 ? void 0 : {
987
987
  ...identity,
988
988
  ...value
989
- });
989
+ };
990
990
  const webPlugin = defineWebPlugin({
991
991
  id: "task",
992
992
  session: {
@@ -1 +1 @@
1
- {"version":3,"file":"web.mjs","names":["isRecord","STATUS_TONE","activityGroupTasks","channelTaskGraph","fillTasks","toolTask"],"sources":["../../src/types/webTasks.ts","../../src/extensions/workspaces/sessions/(frontend)/channel/_lib/tasksStore.ts","../../src/extensions/workspaces/sessions/(frontend)/activity-group/tasks.web.ts","../../src/extensions/workspaces/sessions/(frontend)/channel/task-graph.web.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_lib/TaskDetailDialog.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_lib/TasksActivitySection.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/Tasks.activity.tasks.web.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_lib/taskToolFormat.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_lib/TaskToolMessage.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/task.web.tsx","../../generated/web.ts"],"sourcesContent":["/** Browser-safe task view published by the cockpit hub channel. */\nexport const TASKS_CHANNEL_TYPE = 'task_graph';\n\nexport type WebTaskStatus = 'pending' | 'in_progress' | 'completed' | 'failed' | 'deleted';\n\nexport interface WebTask {\n id: number;\n subject: string;\n description?: string;\n activeForm?: string;\n status: WebTaskStatus;\n blockedBy: number[];\n owner?: string;\n updatedAt?: string;\n delegation?: {\n agent?: string;\n state?: string;\n };\n}\n\nexport interface WebTasksPayload {\n tasks: WebTask[];\n rev: number;\n}\n","import { defineSessionStore, type SessionFrameSender } from '@agimon-ai/doompi-core/web';\n\nimport { TASKS_CHANNEL_TYPE, type WebTask, type WebTasksPayload } from '../../../../../../types/webTasks';\n\nexport interface TasksSession {\n tasks: WebTask[];\n rev: number;\n}\n\nexport const tasks = defineSessionStore<TasksSession>({ tasks: [], rev: 0 });\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction parseTask(value: unknown): WebTask | null {\n if (!isRecord(value) || typeof value.id !== 'number' || typeof value.subject !== 'string') return null;\n if (!['pending', 'in_progress', 'completed', 'failed'].includes(String(value.status))) return null;\n const task: WebTask = {\n id: value.id,\n subject: value.subject,\n status: value.status as WebTask['status'],\n blockedBy: Array.isArray(value.blockedBy)\n ? value.blockedBy.filter((id): id is number => typeof id === 'number')\n : [],\n };\n if (typeof value.description === 'string') task.description = value.description;\n if (typeof value.activeForm === 'string') task.activeForm = value.activeForm;\n if (typeof value.owner === 'string') task.owner = value.owner;\n if (typeof value.updatedAt === 'string') task.updatedAt = value.updatedAt;\n if (isRecord(value.delegation)) {\n task.delegation = {};\n if (typeof value.delegation.agent === 'string') task.delegation.agent = value.delegation.agent;\n if (typeof value.delegation.state === 'string') task.delegation.state = value.delegation.state;\n }\n return task;\n}\n\nexport const tasksChannel = tasks.channel<WebTasksPayload>({\n channel: TASKS_CHANNEL_TYPE,\n parse(input) {\n if (!isRecord(input) || !Array.isArray(input.tasks) || typeof input.rev !== 'number') return null;\n return { tasks: input.tasks.map(parseTask).filter((task): task is WebTask => task !== null), rev: input.rev };\n },\n reduce: (_current, payload) => payload,\n});\n\n/** The fields the cockpit lets a human change on a task. */\nexport interface TaskEditDraft {\n subject: string;\n description: string;\n status: WebTask['status'];\n}\n\nexport function taskEditDraft(task: WebTask): TaskEditDraft {\n return { subject: task.subject, description: task.description ?? '', status: task.status };\n}\n\nfunction changedFields(task: WebTask, draft: TaskEditDraft): string[] {\n const changes: string[] = [];\n const subject = draft.subject.trim();\n const description = draft.description.trim();\n if (subject && subject !== task.subject) changes.push(`set subject to \"${subject}\"`);\n if (description !== (task.description ?? '').trim()) {\n changes.push(description ? `set description to \"${description}\"` : 'clear the description');\n }\n if (draft.status !== task.status) changes.push(`set status to ${draft.status}`);\n return changes;\n}\n\n/**\n * The agent stays the only writer of task state, so an edit leaves the cockpit\n * as one prompt naming exactly the fields the human changed. Nothing changed\n * means nothing to send.\n */\nexport function taskEditInstruction(task: WebTask, draft: TaskEditDraft): string | null {\n const changes = changedFields(task, draft);\n if (changes.length === 0) return null;\n return `Update task #${task.id}: ${changes.join('; ')}. Change nothing else and keep the dependency graph valid.`;\n}\n\nexport function requestTaskEdit(\n send: SessionFrameSender,\n sessionId: string,\n task: WebTask,\n draft: TaskEditDraft,\n): boolean {\n const message = taskEditInstruction(task, draft);\n if (message === null) return false;\n send(sessionId, { type: 'prompt', message });\n return true;\n}\n\n/** Steering for the subagent that owns a delegated task. */\nexport function taskMessageInstruction(taskId: number, agent: string, message: string): string {\n return `Steer the ${agent} run working on task #${taskId} with this message, then update the task if its plan changed: ${message.trim()}`;\n}\n\nexport function requestTaskMessage(\n send: SessionFrameSender,\n sessionId: string,\n taskId: number,\n agent: string,\n message: string,\n): void {\n send(sessionId, { type: 'prompt', message: taskMessageInstruction(taskId, agent, message) });\n}\n\nexport function requestTaskRemoval(send: SessionFrameSender, sessionId: string, taskId: number): void {\n send(sessionId, {\n type: 'prompt',\n message: `Remove task #${taskId}. Also remove or repair every dependency that references it so the remaining task graph is valid.`,\n });\n}\n","import { defineActivityGroup } from '@agimon-ai/doompi-core/web';\n\nimport { tasks } from '../channel/_lib/tasksStore';\n\n/**\n * The live task board in the session Activity dock.\n *\n * Active means a delegated run is still out, not that the list has entries. A\n * pending task waits for this agent's next turn and reports to nobody, so\n * counting it as running would leave the dock badge, the top bar and the\n * timeline's background-work notice claiming work that nothing will finish.\n */\nexport default defineActivityGroup({\n keys: 't l',\n statusKey: '@agimon-ai/doompi-task',\n marksBackgroundWork: false,\n activeSource: {\n subscribe(listener: () => void) {\n const subscription = tasks.store.subscribe(listener);\n return () => subscription.unsubscribe();\n },\n isActive(sessionId: string | null) {\n return tasks\n .select(tasks.store.state, sessionId)\n .tasks.some((task) => task.delegation?.state === 'requested' || task.delegation?.state === 'running');\n },\n },\n order: 65,\n});\n","import { defineChannelFile } from '@agimon-ai/doompi-core/web';\n\nimport { tasksChannel } from './_lib/tasksStore';\n\nexport default defineChannelFile(tasksChannel);\n","import type { SessionFrameSender } from '@agimon-ai/doompi-core/web';\nimport {\n Button,\n Dialog,\n DialogBody,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Input,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Textarea,\n} from '@agimon-ai/doompi-web-components';\nimport { type ReactNode, useState } from 'react';\n\nimport type { WebTask, WebTaskStatus } from '../../../../../../types/webTasks';\nimport { requestTaskEdit, requestTaskMessage, taskEditDraft, type TaskEditDraft } from '../../channel/_lib/tasksStore';\n\n/** How the one task dialog is opened: reading it, changing it, or steering its run. */\nexport type TaskDialogMode = 'view' | 'edit' | 'message';\n\nconst STATUS_CHOICES: readonly WebTaskStatus[] = ['pending', 'in_progress', 'completed', 'failed'];\nconst DESCRIPTION_ROWS = 5;\nconst MESSAGE_ROWS = 4;\n\nfunction FieldLabel({ children }: { children: string }) {\n return <span className=\"text-2xs font-bold tracking-widest text-doom-faint\">{children}</span>;\n}\n\nfunction Field({ label, children }: { label: string; children: ReactNode }) {\n return (\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{label}</FieldLabel>\n {children}\n </div>\n );\n}\n\nfunction ReadOnlyValue({ value, testId }: { value: string; testId: string }) {\n return (\n <span data-testid={testId} className=\"whitespace-pre-wrap break-words text-sm leading-relaxed text-doom-dim\">\n {value}\n </span>\n );\n}\n\nfunction TaskFacts({ task }: { task: WebTask }) {\n return (\n <div className=\"flex flex-wrap gap-5\">\n <Field label=\"STATUS\">\n <ReadOnlyValue testId=\"task-detail-status\" value={task.status.replace('_', ' ')} />\n </Field>\n {task.activeForm ? (\n <Field label=\"ACTIVE FORM\">\n <ReadOnlyValue testId=\"task-detail-active-form\" value={task.activeForm} />\n </Field>\n ) : null}\n {task.owner ? (\n <Field label=\"OWNER\">\n <ReadOnlyValue testId=\"task-detail-owner\" value={task.owner} />\n </Field>\n ) : null}\n {task.delegation?.agent ? (\n <Field label=\"DELEGATED TO\">\n <ReadOnlyValue\n testId=\"task-detail-agent\"\n value={\n task.delegation.state ? `${task.delegation.agent} · ${task.delegation.state}` : task.delegation.agent\n }\n />\n </Field>\n ) : null}\n {task.blockedBy.length > 0 ? (\n <Field label=\"BLOCKED BY\">\n <ReadOnlyValue testId=\"task-detail-blocked-by\" value={task.blockedBy.map((id) => `#${id}`).join(', ')} />\n </Field>\n ) : null}\n {task.updatedAt ? (\n <Field label=\"UPDATED\">\n <ReadOnlyValue testId=\"task-detail-updated\" value={task.updatedAt} />\n </Field>\n ) : null}\n </div>\n );\n}\n\n/**\n * One task, read first and changed second. Every change leaves as a prompt the\n * session can see, so the agent remains the only writer of task state.\n */\nexport function TaskDetailDialog({\n task,\n sessionId,\n mode: initialMode,\n send,\n onClose,\n}: {\n task: WebTask;\n sessionId: string;\n mode: TaskDialogMode;\n send: SessionFrameSender;\n onClose: () => void;\n}) {\n const [mode, setMode] = useState<TaskDialogMode>(initialMode);\n const [draft, setDraft] = useState<TaskEditDraft>(() => taskEditDraft(task));\n const [message, setMessage] = useState('');\n const agent = task.delegation?.agent;\n\n const submitEdit = (): void => {\n if (requestTaskEdit(send, sessionId, task, draft)) onClose();\n };\n const submitMessage = (): void => {\n if (!message.trim() || !agent) return;\n requestTaskMessage(send, sessionId, task.id, agent, message);\n onClose();\n };\n\n return (\n <Dialog\n open\n onOpenChange={(open) => {\n if (!open) onClose();\n }}\n >\n <DialogContent width=\"lg\" data-testid=\"task-detail-dialog\" data-mode={mode} aria-describedby={undefined}>\n <DialogHeader>\n <div className=\"flex min-w-0 flex-col items-start gap-1 sm:flex-row sm:items-center sm:gap-2.5\">\n <span className=\"text-2xs text-doom-faint\">task #{task.id}</span>\n <DialogTitle data-testid=\"task-detail-title\" className=\"max-w-full break-words\">\n {task.subject}\n </DialogTitle>\n </div>\n </DialogHeader>\n <DialogBody>\n {mode === 'view' ? (\n <>\n <Field label=\"DESCRIPTION\">\n <ReadOnlyValue\n testId=\"task-detail-description\"\n value={task.description ?? 'no description on this task'}\n />\n </Field>\n <TaskFacts task={task} />\n <DialogFooter>\n <span className=\"min-w-0 flex-1\" />\n {agent ? (\n <Button\n variant=\"outline\"\n size=\"xs\"\n data-testid=\"task-detail-open-message\"\n onClick={() => setMode('message')}\n >\n message agent\n </Button>\n ) : null}\n <Button variant=\"primary\" size=\"xs\" data-testid=\"task-detail-open-edit\" onClick={() => setMode('edit')}>\n edit\n </Button>\n </DialogFooter>\n </>\n ) : null}\n\n {mode === 'edit' ? (\n <>\n <Field label=\"SUBJECT\">\n <Input\n data-testid=\"task-detail-subject-input\"\n autoFocus\n value={draft.subject}\n onChange={(event) => setDraft({ ...draft, subject: event.target.value })}\n />\n </Field>\n <Field label=\"DESCRIPTION\">\n <Textarea\n data-testid=\"task-detail-description-input\"\n rows={DESCRIPTION_ROWS}\n value={draft.description}\n placeholder=\"what this task covers\"\n onChange={(event) => setDraft({ ...draft, description: event.target.value })}\n />\n </Field>\n <Field label=\"STATUS\">\n <Select\n value={draft.status}\n onValueChange={(value) => setDraft({ ...draft, status: value as WebTaskStatus })}\n >\n <SelectTrigger\n data-testid=\"task-detail-status-input\"\n className=\"h-7 w-full min-w-0 text-xs sm:min-w-[200px]\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {STATUS_CHOICES.map((status) => (\n <SelectItem key={status} value={status}>\n {status.replace('_', ' ')}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </Field>\n <DialogFooter className=\"flex-wrap sm:flex-nowrap\">\n <span className=\"w-full text-2xs text-doom-faint sm:w-auto\">\n saved as one prompt naming only the fields you changed\n </span>\n <span className=\"min-w-0 flex-1\" />\n <Button variant=\"outline\" size=\"xs\" data-testid=\"task-detail-cancel\" onClick={onClose}>\n cancel\n </Button>\n <Button variant=\"primary\" size=\"xs\" data-testid=\"task-detail-save\" onClick={submitEdit}>\n save\n </Button>\n </DialogFooter>\n </>\n ) : null}\n\n {mode === 'message' && agent ? (\n <>\n <Field label={`MESSAGE TO ${agent.toUpperCase()}`}>\n <Textarea\n data-testid=\"task-detail-message-input\"\n autoFocus\n rows={MESSAGE_ROWS}\n value={message}\n placeholder=\"guidance for the run working on this task\"\n onChange={(event) => setMessage(event.target.value)}\n />\n </Field>\n <DialogFooter className=\"flex-wrap sm:flex-nowrap\">\n <span className=\"w-full text-2xs text-doom-faint sm:w-auto\">\n steers the run, it does not edit the task\n </span>\n <span className=\"min-w-0 flex-1\" />\n <Button variant=\"outline\" size=\"xs\" data-testid=\"task-detail-cancel\" onClick={onClose}>\n cancel\n </Button>\n <Button variant=\"primary\" size=\"xs\" data-testid=\"task-detail-send\" onClick={submitMessage}>\n send\n </Button>\n </DialogFooter>\n </>\n ) : null}\n </DialogBody>\n </DialogContent>\n </Dialog>\n );\n}\n","import type { WebPluginSlotProps } from '@agimon-ai/doompi-core/web';\nimport {\n Button,\n ChevronDownIcon,\n ChevronRightIcon,\n Dot,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n EditIcon,\n KebabIcon,\n MessageIcon,\n TrashIcon,\n type DotTone,\n} from '@agimon-ai/doompi-web-components';\nimport { useStore } from '@tanstack/react-store';\nimport { useState } from 'react';\n\nimport type { WebTask } from '../../../../../../types/webTasks';\nimport { requestTaskRemoval, tasks } from '../../channel/_lib/tasksStore';\nimport { TaskDetailDialog, type TaskDialogMode } from './TaskDetailDialog';\n\nconst STATUS_TONE: Readonly<Record<WebTask['status'], DotTone>> = {\n pending: 'muted',\n in_progress: 'yellow',\n completed: 'green',\n failed: 'red',\n deleted: 'muted',\n};\n\ninterface DialogState {\n taskId: number;\n mode: TaskDialogMode;\n}\n\nfunction TaskRow({\n task,\n sessionId,\n sendSessionFrame,\n openDialog,\n}: {\n task: WebTask;\n sessionId: string;\n sendSessionFrame: WebPluginSlotProps['sendSessionFrame'];\n openDialog: (mode: TaskDialogMode) => void;\n}) {\n const detail = task.status === 'in_progress' ? task.activeForm : task.description;\n const agent = task.delegation?.agent;\n return (\n <div\n data-testid={`activity-task-${task.id}`}\n data-task-status={task.status}\n className=\"flex flex-col gap-1 rounded-md px-1 py-1\"\n >\n <div className=\"grid min-w-0 grid-cols-[auto_minmax(0,1fr)_auto_auto] items-center gap-x-1.5\">\n <Dot tone={STATUS_TONE[task.status]} pulse={task.status === 'in_progress'} />\n <button\n type=\"button\"\n data-testid={`activity-task-title-${task.id}`}\n title={task.subject}\n onClick={() => openDialog('view')}\n className={`min-w-0 truncate text-left text-xs font-bold hover:underline ${task.status === 'failed' ? 'text-doom-red' : task.status === 'completed' ? 'text-doom-dim' : 'text-doom-hi'}`}\n >\n <span className=\"text-doom-faint\">#{task.id}</span> {task.subject}\n </button>\n <span className=\"shrink-0 text-2xs text-doom-faint\">{task.status.replace('_', ' ')}</span>\n {task.status !== 'completed' && task.status !== 'deleted' ? (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n data-testid={`activity-task-menu-${task.id}`}\n aria-label={`task #${task.id} actions`}\n title={`task #${task.id} actions`}\n className=\"self-center shrink-0 text-doom-faint hover:bg-doom-deep hover:text-doom-hi data-[state=open]:bg-doom-deep data-[state=open]:text-doom-hi\"\n >\n <KebabIcon className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent data-testid={`activity-task-menu-list-${task.id}`}>\n <DropdownMenuItem data-testid={`activity-task-edit-${task.id}`} onSelect={() => openDialog('edit')}>\n <EditIcon className=\"h-3 w-3\" />\n Edit\n </DropdownMenuItem>\n {agent ? (\n <DropdownMenuItem\n data-testid={`activity-task-message-${task.id}`}\n onSelect={() => openDialog('message')}\n >\n <MessageIcon className=\"h-3 w-3\" />\n Message agent\n </DropdownMenuItem>\n ) : null}\n <DropdownMenuItem\n variant=\"destructive\"\n data-testid={`activity-task-remove-${task.id}`}\n onSelect={() => requestTaskRemoval(sendSessionFrame, sessionId, task.id)}\n >\n <TrashIcon className=\"h-3 w-3\" />\n Remove\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n ) : null}\n </div>\n {detail || agent || task.blockedBy.length > 0 ? (\n <span className=\"truncate pl-3 text-2xs text-doom-faint\">\n {agent ? `[${agent}] ` : ''}\n {detail ?? ''}\n {task.blockedBy.length > 0 ? ` · blocked by ${task.blockedBy.map((id) => `#${id}`).join(', ')}` : ''}\n </span>\n ) : null}\n </div>\n );\n}\n\n/**\n * Session task graph in the activity dock. Empty graphs have no cockpit presence.\n *\n * This fills the `tasks` activity group, so the dock has already drawn the\n * heading, the key chip and the section frame. Rendering rows only keeps the\n * group titled once.\n */\nexport function TasksActivitySection({ sessionId, sendSessionFrame }: WebPluginSlotProps) {\n const sessionTasks = useStore(tasks.store, (state) => tasks.select(state, sessionId).tasks);\n const [historyOpen, setHistoryOpen] = useState(false);\n const [dialog, setDialog] = useState<DialogState>();\n if (sessionId === null || sessionTasks.length === 0) return null;\n\n const active = sessionTasks.filter((task) => task.status === 'pending' || task.status === 'in_progress');\n const history = sessionTasks.filter((task) => task.status === 'completed' || task.status === 'failed');\n const dialogTask = dialog ? sessionTasks.find((task) => task.id === dialog.taskId) : undefined;\n return (\n <div className=\"flex flex-col gap-2\">\n {active.length > 0 ? (\n <div className=\"flex flex-col gap-0.5\">\n {active.map((task) => (\n <TaskRow\n key={task.id}\n task={task}\n sessionId={sessionId}\n sendSessionFrame={sendSessionFrame}\n openDialog={(mode) => setDialog({ taskId: task.id, mode })}\n />\n ))}\n </div>\n ) : null}\n {history.length > 0 ? (\n <div className=\"flex flex-col gap-0.5\">\n <Button\n variant=\"ghost\"\n size=\"xs\"\n aria-expanded={historyOpen}\n onClick={() => setHistoryOpen((open) => !open)}\n className=\"justify-start gap-1.5 rounded-md px-1 py-0.5 hover:bg-doom-panel\"\n >\n {historyOpen ? (\n <ChevronDownIcon className=\"h-2.5 w-2.5 text-doom-faint\" />\n ) : (\n <ChevronRightIcon className=\"h-2.5 w-2.5 text-doom-faint\" />\n )}\n <span className=\"text-xs font-bold text-doom-dim\">session</span>\n <span className=\"text-2xs text-doom-faint\">{history.length}</span>\n </Button>\n {historyOpen ? (\n <div className=\"flex flex-col gap-0.5 pl-2\">\n {history.map((task) => (\n <TaskRow\n key={task.id}\n task={task}\n sessionId={sessionId}\n sendSessionFrame={sendSessionFrame}\n openDialog={(mode) => setDialog({ taskId: task.id, mode })}\n />\n ))}\n </div>\n ) : null}\n </div>\n ) : null}\n {dialog && dialogTask ? (\n <TaskDetailDialog\n key={`${dialogTask.id}-${dialog.mode}`}\n task={dialogTask}\n sessionId={sessionId}\n mode={dialog.mode}\n send={sendSessionFrame}\n onClose={() => setDialog(undefined)}\n />\n ) : null}\n </div>\n );\n}\n","import { defineFill } from '@agimon-ai/doompi-core/web';\n\nimport { TasksActivitySection } from './_lib/TasksActivitySection';\n\nexport default defineFill({ component: TasksActivitySection });\n","/**\n * Pure view logic for the task tool card, the browser counterpart of\n * the session frontend's shared format helpers (renderTaskCall, renderTaskResult). The plugin may reach\n * only its own files and src/types, so the store shapes it reads are\n * restated here as the wire JSON of a tool_execution frame.\n */\n\nexport type TaskStatus = 'pending' | 'in_progress' | 'completed' | 'failed' | 'deleted';\nexport type TaskAction = 'upsert' | 'list' | 'get' | 'delete' | 'clear' | 'assign' | 'cancel';\n\nexport const STATUS_GLYPH: Record<TaskStatus, string> = {\n pending: '○',\n in_progress: '◐',\n completed: '●',\n failed: '✗',\n deleted: '⊘',\n};\n\nexport const STATUS_LABEL: Record<TaskStatus, string> = {\n pending: 'pending',\n in_progress: 'in progress',\n completed: 'completed',\n failed: 'failed',\n deleted: 'deleted',\n};\n\nexport const ACTION_GLYPH: Record<TaskAction, string> = {\n upsert: '✎',\n delete: '×',\n get: '›',\n list: '☰',\n clear: '∅',\n assign: '⇒',\n cancel: '⊗',\n};\n\n/**\n * `upsert` is two operations behind one name, so a homogeneous batch narrows to\n * the glyph the operator already reads: `+` means new work appeared, `→` means\n * work moved. A mixed batch keeps the neutral write glyph.\n */\nconst UPSERT_CREATE_GLYPH = '+';\nconst UPSERT_UPDATE_GLYPH = '→';\n/** Task rows kept in a collapsed result, before the card is expanded. */\nconst TRANSCRIPT_TASK_ROWS = 8;\nconst TASK_STATUSES: readonly TaskStatus[] = ['pending', 'in_progress', 'completed', 'failed', 'deleted'];\nconst TASK_ACTIONS: readonly TaskAction[] = ['upsert', 'list', 'get', 'delete', 'clear', 'assign', 'cancel'];\nconst INLINE_WHITESPACE = /\\s+/gu;\n\n/** One task as the result details carry it (src/models/task.ts Task). */\nexport interface TaskView {\n id: number;\n subject: string;\n status: TaskStatus;\n activeForm?: string;\n blockedBy?: number[];\n delegation?: { agent?: string; state?: string };\n}\n\n/** The result details (src/models/task.ts TaskDetails), narrowed to what the card reads. */\nexport interface TaskDetailsView {\n action: TaskAction;\n params: Record<string, unknown>;\n tasks: TaskView[];\n error?: string;\n upsert?: { applied: number[]; failed: number };\n assignment?: { assigned: number[]; failed: number };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isStatus(value: unknown): value is TaskStatus {\n return typeof value === 'string' && (TASK_STATUSES as readonly string[]).includes(value);\n}\n\nfunction isAction(value: unknown): value is TaskAction {\n return typeof value === 'string' && (TASK_ACTIONS as readonly string[]).includes(value);\n}\n\nfunction taskView(value: unknown): TaskView | null {\n if (!isRecord(value) || typeof value.id !== 'number' || typeof value.subject !== 'string') return null;\n if (!isStatus(value.status)) return null;\n const task: TaskView = { id: value.id, subject: value.subject, status: value.status };\n if (typeof value.activeForm === 'string') task.activeForm = value.activeForm;\n if (Array.isArray(value.blockedBy)) {\n task.blockedBy = value.blockedBy.filter((id): id is number => typeof id === 'number');\n }\n if (isRecord(value.delegation)) {\n task.delegation = {};\n if (typeof value.delegation.agent === 'string') task.delegation.agent = value.delegation.agent;\n if (typeof value.delegation.state === 'string') task.delegation.state = value.delegation.state;\n }\n return task;\n}\n\nfunction idList(value: unknown): number[] {\n return Array.isArray(value) ? value.filter((id): id is number => typeof id === 'number') : [];\n}\n\n/** Narrows the wire details; null when they are not a task result at all. */\nexport function taskDetailsView(details: unknown): TaskDetailsView | null {\n if (!isRecord(details) || !isAction(details.action) || !Array.isArray(details.tasks)) return null;\n const view: TaskDetailsView = {\n action: details.action,\n params: isRecord(details.params) ? details.params : {},\n tasks: details.tasks.map(taskView).filter((task): task is TaskView => task !== null),\n };\n if (typeof details.error === 'string') view.error = details.error;\n if (isRecord(details.upsert)) {\n view.upsert = {\n applied: idList(details.upsert.applied),\n failed: typeof details.upsert.failed === 'number' ? details.upsert.failed : 0,\n };\n }\n if (isRecord(details.assignment)) {\n view.assignment = {\n assigned: idList(details.assignment.assigned),\n failed: typeof details.assignment.failed === 'number' ? details.assignment.failed : 0,\n };\n }\n return view;\n}\n\n/** `#id` for the wire's id, which the TUI would resolve to a subject through the store. */\nfunction idLabel(value: unknown): string {\n return typeof value === 'number' || typeof value === 'string' ? `#${value}` : '#?';\n}\n\n/** Keep dynamic content on one line. */\nfunction inlineText(text: string): string {\n return text.replace(INLINE_WHITESPACE, ' ').trim();\n}\n\nexport type TaskCallTone = 'dim' | 'accent';\n\n/** The call header: glyph, action, then the subject or a count, as renderTaskCall lays it out. */\nexport interface TaskCallView {\n glyph: string;\n action: string;\n subject?: string;\n subjectTone: TaskCallTone;\n /** The assignee (`→ agent`) or the list filter. */\n detail?: string;\n}\n\nfunction upsertGlyph(items: readonly Record<string, unknown>[]): string {\n if (items.length === 0) return ACTION_GLYPH.upsert;\n if (items.every((item) => item.id === undefined)) return UPSERT_CREATE_GLYPH;\n if (items.every((item) => item.id !== undefined)) return UPSERT_UPDATE_GLYPH;\n return ACTION_GLYPH.upsert;\n}\n\n/**\n * The TUI resolves an id to its subject through the task store; the card has\n * no store and shows `#id` until the result names the task.\n */\nexport function taskCallView(args: Record<string, unknown>): TaskCallView {\n const action = typeof args.action === 'string' ? args.action : 'task';\n if (!isAction(action)) return { glyph: '?', action, subjectTone: 'dim' };\n const items = action === 'upsert' && Array.isArray(args.tasks) ? args.tasks.filter(isRecord) : [];\n const view: TaskCallView = {\n glyph: action === 'upsert' ? upsertGlyph(items) : ACTION_GLYPH[action],\n action,\n subjectTone: 'dim',\n };\n\n if (action === 'upsert') {\n // One entry reads exactly as create or update did; a batch reads as a count\n // rather than a subject it would have to pick arbitrarily.\n if (items.length === 1) {\n const only = items[0] ?? {};\n if (only.id === undefined) {\n if (typeof only.subject === 'string') view.subject = inlineText(only.subject);\n } else {\n view.subject = typeof only.subject === 'string' ? inlineText(only.subject) : idLabel(only.id);\n view.subjectTone = 'accent';\n }\n } else if (items.length > 1) {\n view.subject = `${items.length} tasks`;\n }\n } else if (action === 'assign') {\n const assignments = Array.isArray(args.assignments) ? args.assignments.filter(isRecord) : [];\n if (assignments.length === 1) {\n const only = assignments[0] ?? {};\n view.subject = idLabel(only.id);\n view.subjectTone = 'accent';\n if (typeof only.agent === 'string') view.detail = `→ ${only.agent}`;\n } else if (assignments.length > 1) {\n view.subject = `${assignments.length} tasks`;\n }\n } else if ((action === 'get' || action === 'delete' || action === 'cancel') && args.id !== undefined) {\n view.subject = idLabel(args.id);\n view.subjectTone = 'accent';\n } else if (action === 'list' && isStatus(args.status)) {\n view.detail = STATUS_LABEL[args.status];\n }\n return view;\n}\n\n/** One row of the result: the task line on the left, its status flushed right. */\nexport interface TaskRow {\n id: number;\n glyph: string;\n subject: string;\n status: TaskStatus;\n /** Struck through: the task is done with. */\n closed: boolean;\n agent?: string;\n activeForm?: string;\n blockedBy: number[];\n}\n\nexport type TaskResultTone = 'running' | 'ok' | 'error' | 'warning';\n\nexport interface TaskResultView {\n rows: TaskRow[];\n /** Error text lines when the tool threw or the reducer reported an error. */\n errorLines: string[];\n status: { glyph: string; tone: TaskResultTone; text: string } | null;\n}\n\nexport function taskRow(task: TaskView): TaskRow {\n const row: TaskRow = {\n id: task.id,\n glyph: STATUS_GLYPH[task.status],\n subject: inlineText(task.subject),\n status: task.status,\n closed: task.status === 'completed' || task.status === 'deleted',\n blockedBy: task.blockedBy ?? [],\n };\n if (task.delegation?.agent) row.agent = inlineText(task.delegation.agent);\n if (task.status === 'in_progress' && task.activeForm) row.activeForm = inlineText(task.activeForm);\n return row;\n}\n\nfunction nonEmptyLines(text: string): string[] {\n return text.split('\\n').filter((line) => line.trim().length > 0);\n}\n\n/**\n * The rows `list` reported to the model: `details.tasks` is the whole\n * document, so the call's filters apply again here or the card would disagree\n * with the text the model was given.\n */\nfunction listedTasks(details: TaskDetailsView): TaskView[] {\n let view = details.tasks;\n if (details.params.includeDeleted !== true) view = view.filter((task) => task.status !== 'deleted');\n if (isStatus(details.params.status)) view = view.filter((task) => task.status === details.params.status);\n return view;\n}\n\nfunction byIds(details: TaskDetailsView, ids: readonly number[]): TaskView[] {\n return ids.flatMap((id) => details.tasks.find((task) => task.id === id) ?? []);\n}\n\nfunction batch(\n tasks: readonly TaskView[],\n failed: number,\n verb: string,\n expanded: boolean,\n): Pick<TaskResultView, 'rows' | 'status'> {\n // One applied task and nothing failed is the common case: keep the single\n // row it has always had rather than dressing it as a bulk report.\n if (tasks.length === 1 && failed === 0) return { rows: [taskRow(tasks[0] as TaskView)], status: null };\n const shown = expanded ? tasks : tasks.slice(0, TRANSCRIPT_TASK_ROWS);\n let summary = `${tasks.length} ${verb}`;\n if (failed > 0) summary += ` · ${failed} failed`;\n if (tasks.length > shown.length) summary += ` · ${tasks.length - shown.length} more`;\n return {\n rows: shown.map(taskRow),\n status: { glyph: failed > 0 ? '!' : '✓', tone: failed > 0 ? 'warning' : 'ok', text: summary },\n };\n}\n\nexport function taskResultView(input: {\n details: unknown;\n output: string;\n expanded: boolean;\n isPartial: boolean;\n isError: boolean;\n}): TaskResultView {\n const details = taskDetailsView(input.details);\n\n // Running. `assign` and `cancel` stream a placeholder before the run settles.\n if (input.isPartial) {\n const text = nonEmptyLines(input.output).at(-1) ?? 'working';\n return { rows: [], errorLines: [], status: { glyph: '◐', tone: 'running', text } };\n }\n\n // Failed. Every failure path throws, so Pi hands back error text and no\n // details; without this the card would show a green tick on a failure.\n if (input.isError || details?.error !== undefined) {\n const all = nonEmptyLines(details?.error ?? input.output);\n if (all.length <= 1) return { rows: [], errorLines: [], status: { glyph: '✗', tone: 'error', text: all[0] ?? '' } };\n const errorLines = input.expanded ? all : all.slice(0, TRANSCRIPT_TASK_ROWS);\n return { rows: [], errorLines, status: { glyph: '✗', tone: 'error', text: '' } };\n }\n\n if (details === null) return { rows: [], errorLines: [], status: { glyph: '✓', tone: 'ok', text: '' } };\n\n if (details.action === 'list') {\n const tasks = listedTasks(details);\n const shown = input.expanded ? tasks : tasks.slice(0, TRANSCRIPT_TASK_ROWS);\n let summary = tasks.length === 0 ? 'no tasks' : `${tasks.length} task${tasks.length === 1 ? '' : 's'}`;\n if (tasks.length > shown.length) summary += ` · ${tasks.length - shown.length} more`;\n return { rows: shown.map(taskRow), errorLines: [], status: { glyph: '✓', tone: 'ok', text: summary } };\n }\n\n if (details.action === 'clear') {\n return { rows: [], errorLines: [], status: { glyph: '✓', tone: 'ok', text: 'cleared' } };\n }\n\n if (details.action === 'assign' && details.assignment) {\n const assigned = byIds(details, details.assignment.assigned);\n return { errorLines: [], ...batch(assigned, details.assignment.failed, 'assigned', input.expanded) };\n }\n\n if (details.action === 'upsert') {\n const touched = byIds(details, details.upsert?.applied ?? []);\n return { errorLines: [], ...batch(touched, details.upsert?.failed ?? 0, 'applied', input.expanded) };\n }\n\n // The single task an id-bearing action acted on, so the card names it rather than a bare tick.\n const id = details.params.id;\n const task = typeof id === 'number' ? details.tasks.find((candidate) => candidate.id === id) : undefined;\n if (!task) return { rows: [], errorLines: [], status: { glyph: '✓', tone: 'ok', text: '' } };\n return { rows: [taskRow(task)], errorLines: [], status: null };\n}\n","import type { ToolMessageRenderProps } from '@agimon-ai/doompi-core/web';\nimport {\n MessageItem,\n MessageItemBody,\n MessageItemHeader,\n MessageItemStatus,\n type StatusTone,\n toolTone,\n} from '@agimon-ai/doompi-web-components';\n\nimport {\n STATUS_LABEL,\n type TaskResultTone,\n type TaskRow,\n type TaskStatus,\n taskCallView,\n taskResultView,\n} from './taskToolFormat';\n\nconst STATUS_TONE: Record<TaskStatus, string> = {\n pending: 'text-doom-dim',\n in_progress: 'text-doom-yellow',\n completed: 'text-doom-green',\n failed: 'text-doom-red',\n deleted: 'text-doom-faint',\n};\n\nconst RESULT_TONE: Record<TaskResultTone, StatusTone> = {\n running: 'running',\n ok: 'ok',\n error: 'error',\n warning: 'running',\n};\n\n/** One task row: status glyph, id, subject and chips on the left, the status label flushed right. */\nfunction TaskRowLine({ row }: { row: TaskRow }) {\n return (\n <li data-testid=\"tool-result-task-row\" data-task-id={row.id} className=\"flex items-baseline gap-2\">\n <span className={`shrink-0 ${STATUS_TONE[row.status]}`}>{row.glyph}</span>\n <span className=\"shrink-0 text-doom-faint\">#{row.id}</span>\n <span\n className={`min-w-0 flex-1 truncate ${row.closed ? 'text-doom-faint line-through' : row.status === 'in_progress' ? 'text-doom-blue' : 'text-doom-text'}`}\n >\n {row.subject}\n {row.agent ? <span className=\"text-doom-faint\"> [{row.agent}]</span> : null}\n {row.activeForm ? <span className=\"text-doom-faint\"> ({row.activeForm})</span> : null}\n {row.blockedBy.length > 0 ? (\n <span className=\"text-doom-faint\"> ⛓ {row.blockedBy.map((id) => `#${id}`).join(',')}</span>\n ) : null}\n </span>\n <span className={`shrink-0 ${STATUS_TONE[row.status]}`}>{STATUS_LABEL[row.status]}</span>\n </li>\n );\n}\n\n/**\n * The task tool's timeline item: `glyph action subject` with the assignee or\n * list filter in the header, as renderTaskCall shows it; the rows the action\n * touched, then the batch or list summary, in the body, as renderTaskResult\n * lays it out.\n */\nexport function TaskToolMessage({ args, result, output, running, isError }: ToolMessageRenderProps) {\n const call = taskCallView(args);\n const collapsed = taskResultView({ details: result?.details, output, expanded: false, isPartial: running, isError });\n const full = taskResultView({ details: result?.details, output, expanded: true, isPartial: running, isError });\n const hidden = full.rows.length - collapsed.rows.length + (full.errorLines.length - collapsed.errorLines.length);\n return (\n <MessageItem tone={toolTone({ running, isError })} expandable={hidden > 0}>\n {({ expanded }) => {\n const view = expanded ? full : collapsed;\n const empty = view.rows.length === 0 && view.errorLines.length === 0 && view.status === null;\n return (\n <>\n <MessageItemHeader title=\"task\">\n <span data-testid=\"tool-call-task\" className=\"flex min-w-0 flex-1 items-center gap-1.5\">\n <span className=\"shrink-0 text-doom-text\">\n {call.glyph} {call.action}\n </span>\n {call.subject ? (\n <span\n className={`min-w-0 truncate ${call.subjectTone === 'accent' ? 'text-doom-blue' : 'text-doom-dim'}`}\n >\n {call.subject}\n </span>\n ) : null}\n {call.detail ? <span className=\"shrink-0 text-doom-faint\">{call.detail}</span> : null}\n </span>\n </MessageItemHeader>\n {empty ? null : (\n <MessageItemBody data-testid=\"tool-result-task\" className=\"flex flex-col gap-1\">\n {view.rows.length > 0 ? (\n <ul className=\"flex flex-col gap-0.5\">\n {view.rows.map((row) => (\n <TaskRowLine key={row.id} row={row} />\n ))}\n </ul>\n ) : null}\n {view.errorLines.length > 0 ? (\n <pre className=\"whitespace-pre-wrap break-words font-mono text-doom-dim\">\n {view.errorLines.join('\\n')}\n </pre>\n ) : null}\n {!expanded && hidden > 0 ? <MessageItemStatus expands>{hidden} more</MessageItemStatus> : null}\n {view.status ? (\n <MessageItemStatus\n data-testid=\"tool-result-task-status\"\n tone={RESULT_TONE[view.status.tone]}\n glyph={view.status.glyph}\n >\n {view.status.text}\n </MessageItemStatus>\n ) : null}\n </MessageItemBody>\n )}\n </>\n );\n }}\n </MessageItem>\n );\n}\n","import { defineToolRenderer } from '@agimon-ai/doompi-core/web';\n\nimport { TaskToolMessage } from './_lib/TaskToolMessage';\n\nexport default defineToolRenderer({ message: TaskToolMessage });\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineWebPlugin, type WebPluginContributions } from '@agimon-ai/doompi-core/web';\n\nimport activityGroupTasks from '../src/extensions/workspaces/sessions/(frontend)/activity-group/tasks.web';\nimport channelTaskGraph from '../src/extensions/workspaces/sessions/(frontend)/channel/task-graph.web';\nimport fillTasks from '../src/extensions/workspaces/sessions/(frontend)/fill/Tasks.activity.tasks.web';\nimport toolTask from '../src/extensions/workspaces/sessions/(frontend)/tool/task.web';\n\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T => ({ ...identity, ...(value as object) }) as T;\n\nexport const webPlugin = defineWebPlugin({\n id: 'task',\n session: {\n get activityGroups(): WebPluginContributions['activityGroups'] { return [via({ name: 'tasks' }, activityGroupTasks)]; },\n get channels(): WebPluginContributions['channels'] { return [via({ channel: 'task_graph' }, channelTaskGraph)]; },\n get fills(): WebPluginContributions['fills'] { return [via({ slot: 'activity.tasks', id: 'tasks' }, fillTasks)]; },\n get toolRenderers(): WebPluginContributions['toolRenderers'] { return [via({ tools: ['task'] }, toolTask)]; },\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"web.mjs","names":["isRecord","STATUS_TONE","activityGroupTasks","channelTaskGraph","fillTasks","toolTask"],"sources":["../../src/types/webTasks.ts","../../src/extensions/workspaces/sessions/(frontend)/channel/_lib/tasksStore.ts","../../src/extensions/workspaces/sessions/(frontend)/activity-group/tasks.web.ts","../../src/extensions/workspaces/sessions/(frontend)/channel/task-graph.web.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_lib/TaskDetailDialog.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_lib/TasksActivitySection.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/Tasks.activity.tasks.web.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_lib/taskToolFormat.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_lib/TaskToolMessage.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/task.web.tsx","../../generated/web.ts"],"sourcesContent":["/** Browser-safe task view published by the cockpit hub channel. */\nexport const TASKS_CHANNEL_TYPE = 'task_graph';\n\nexport type WebTaskStatus = 'pending' | 'in_progress' | 'completed' | 'failed' | 'deleted';\n\nexport interface WebTask {\n id: number;\n subject: string;\n description?: string;\n activeForm?: string;\n status: WebTaskStatus;\n blockedBy: number[];\n owner?: string;\n updatedAt?: string;\n delegation?: {\n agent?: string;\n state?: string;\n };\n}\n\nexport interface WebTasksPayload {\n tasks: WebTask[];\n rev: number;\n}\n","import { defineSessionStore, type SessionFrameSender } from '@agimon-ai/doompi-core/web';\n\nimport { TASKS_CHANNEL_TYPE, type WebTask, type WebTasksPayload } from '../../../../../../types/webTasks';\n\nexport interface TasksSession {\n tasks: WebTask[];\n rev: number;\n}\n\nexport const tasks = defineSessionStore<TasksSession>({ tasks: [], rev: 0 });\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction parseTask(value: unknown): WebTask | null {\n if (!isRecord(value) || typeof value.id !== 'number' || typeof value.subject !== 'string') return null;\n if (!['pending', 'in_progress', 'completed', 'failed'].includes(String(value.status))) return null;\n const task: WebTask = {\n id: value.id,\n subject: value.subject,\n status: value.status as WebTask['status'],\n blockedBy: Array.isArray(value.blockedBy)\n ? value.blockedBy.filter((id): id is number => typeof id === 'number')\n : [],\n };\n if (typeof value.description === 'string') task.description = value.description;\n if (typeof value.activeForm === 'string') task.activeForm = value.activeForm;\n if (typeof value.owner === 'string') task.owner = value.owner;\n if (typeof value.updatedAt === 'string') task.updatedAt = value.updatedAt;\n if (isRecord(value.delegation)) {\n task.delegation = {};\n if (typeof value.delegation.agent === 'string') task.delegation.agent = value.delegation.agent;\n if (typeof value.delegation.state === 'string') task.delegation.state = value.delegation.state;\n }\n return task;\n}\n\nexport const tasksChannel = tasks.channel<WebTasksPayload>({\n channel: TASKS_CHANNEL_TYPE,\n parse(input) {\n if (!isRecord(input) || !Array.isArray(input.tasks) || typeof input.rev !== 'number') return null;\n return { tasks: input.tasks.map(parseTask).filter((task): task is WebTask => task !== null), rev: input.rev };\n },\n reduce: (_current, payload) => payload,\n});\n\n/** The fields the cockpit lets a human change on a task. */\nexport interface TaskEditDraft {\n subject: string;\n description: string;\n status: WebTask['status'];\n}\n\nexport function taskEditDraft(task: WebTask): TaskEditDraft {\n return { subject: task.subject, description: task.description ?? '', status: task.status };\n}\n\nfunction changedFields(task: WebTask, draft: TaskEditDraft): string[] {\n const changes: string[] = [];\n const subject = draft.subject.trim();\n const description = draft.description.trim();\n if (subject && subject !== task.subject) changes.push(`set subject to \"${subject}\"`);\n if (description !== (task.description ?? '').trim()) {\n changes.push(description ? `set description to \"${description}\"` : 'clear the description');\n }\n if (draft.status !== task.status) changes.push(`set status to ${draft.status}`);\n return changes;\n}\n\n/**\n * The agent stays the only writer of task state, so an edit leaves the cockpit\n * as one prompt naming exactly the fields the human changed. Nothing changed\n * means nothing to send.\n */\nexport function taskEditInstruction(task: WebTask, draft: TaskEditDraft): string | null {\n const changes = changedFields(task, draft);\n if (changes.length === 0) return null;\n return `Update task #${task.id}: ${changes.join('; ')}. Change nothing else and keep the dependency graph valid.`;\n}\n\nexport function requestTaskEdit(\n send: SessionFrameSender,\n sessionId: string,\n task: WebTask,\n draft: TaskEditDraft,\n): boolean {\n const message = taskEditInstruction(task, draft);\n if (message === null) return false;\n send(sessionId, { type: 'prompt', message });\n return true;\n}\n\n/** Steering for the subagent that owns a delegated task. */\nexport function taskMessageInstruction(taskId: number, agent: string, message: string): string {\n return `Steer the ${agent} run working on task #${taskId} with this message, then update the task if its plan changed: ${message.trim()}`;\n}\n\nexport function requestTaskMessage(\n send: SessionFrameSender,\n sessionId: string,\n taskId: number,\n agent: string,\n message: string,\n): void {\n send(sessionId, { type: 'prompt', message: taskMessageInstruction(taskId, agent, message) });\n}\n\nexport function requestTaskRemoval(send: SessionFrameSender, sessionId: string, taskId: number): void {\n send(sessionId, {\n type: 'prompt',\n message: `Remove task #${taskId}. Also remove or repair every dependency that references it so the remaining task graph is valid.`,\n });\n}\n","import { defineActivityGroup } from '@agimon-ai/doompi-core/web';\n\nimport { tasks } from '../channel/_lib/tasksStore';\n\n/**\n * The live task board in the session Activity dock.\n *\n * Active means a delegated run is still out, not that the list has entries. A\n * pending task waits for this agent's next turn and reports to nobody, so\n * counting it as running would leave the dock badge, the top bar and the\n * timeline's background-work notice claiming work that nothing will finish.\n */\nexport default defineActivityGroup({\n keys: 't l',\n statusKey: '@agimon-ai/doompi-task',\n marksBackgroundWork: false,\n activeSource: {\n subscribe(listener: () => void) {\n const subscription = tasks.store.subscribe(listener);\n return () => subscription.unsubscribe();\n },\n isActive(sessionId: string | null) {\n return tasks\n .select(tasks.store.state, sessionId)\n .tasks.some((task) => task.delegation?.state === 'requested' || task.delegation?.state === 'running');\n },\n },\n order: 65,\n});\n","import { defineChannelFile } from '@agimon-ai/doompi-core/web';\n\nimport { tasksChannel } from './_lib/tasksStore';\n\nexport default defineChannelFile(tasksChannel);\n","import type { SessionFrameSender } from '@agimon-ai/doompi-core/web';\nimport {\n Button,\n Dialog,\n DialogBody,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Input,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Textarea,\n} from '@agimon-ai/doompi-web-components';\nimport { type ReactNode, useState } from 'react';\n\nimport type { WebTask, WebTaskStatus } from '../../../../../../types/webTasks';\nimport { requestTaskEdit, requestTaskMessage, taskEditDraft, type TaskEditDraft } from '../../channel/_lib/tasksStore';\n\n/** How the one task dialog is opened: reading it, changing it, or steering its run. */\nexport type TaskDialogMode = 'view' | 'edit' | 'message';\n\nconst STATUS_CHOICES: readonly WebTaskStatus[] = ['pending', 'in_progress', 'completed', 'failed'];\nconst DESCRIPTION_ROWS = 5;\nconst MESSAGE_ROWS = 4;\n\nfunction FieldLabel({ children }: { children: string }) {\n return <span className=\"text-2xs font-bold tracking-widest text-doom-faint\">{children}</span>;\n}\n\nfunction Field({ label, children }: { label: string; children: ReactNode }) {\n return (\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{label}</FieldLabel>\n {children}\n </div>\n );\n}\n\nfunction ReadOnlyValue({ value, testId }: { value: string; testId: string }) {\n return (\n <span data-testid={testId} className=\"whitespace-pre-wrap break-words text-sm leading-relaxed text-doom-dim\">\n {value}\n </span>\n );\n}\n\nfunction TaskFacts({ task }: { task: WebTask }) {\n return (\n <div className=\"flex flex-wrap gap-5\">\n <Field label=\"STATUS\">\n <ReadOnlyValue testId=\"task-detail-status\" value={task.status.replace('_', ' ')} />\n </Field>\n {task.activeForm ? (\n <Field label=\"ACTIVE FORM\">\n <ReadOnlyValue testId=\"task-detail-active-form\" value={task.activeForm} />\n </Field>\n ) : null}\n {task.owner ? (\n <Field label=\"OWNER\">\n <ReadOnlyValue testId=\"task-detail-owner\" value={task.owner} />\n </Field>\n ) : null}\n {task.delegation?.agent ? (\n <Field label=\"DELEGATED TO\">\n <ReadOnlyValue\n testId=\"task-detail-agent\"\n value={\n task.delegation.state ? `${task.delegation.agent} · ${task.delegation.state}` : task.delegation.agent\n }\n />\n </Field>\n ) : null}\n {task.blockedBy.length > 0 ? (\n <Field label=\"BLOCKED BY\">\n <ReadOnlyValue testId=\"task-detail-blocked-by\" value={task.blockedBy.map((id) => `#${id}`).join(', ')} />\n </Field>\n ) : null}\n {task.updatedAt ? (\n <Field label=\"UPDATED\">\n <ReadOnlyValue testId=\"task-detail-updated\" value={task.updatedAt} />\n </Field>\n ) : null}\n </div>\n );\n}\n\n/**\n * One task, read first and changed second. Every change leaves as a prompt the\n * session can see, so the agent remains the only writer of task state.\n */\nexport function TaskDetailDialog({\n task,\n sessionId,\n mode: initialMode,\n send,\n onClose,\n}: {\n task: WebTask;\n sessionId: string;\n mode: TaskDialogMode;\n send: SessionFrameSender;\n onClose: () => void;\n}) {\n const [mode, setMode] = useState<TaskDialogMode>(initialMode);\n const [draft, setDraft] = useState<TaskEditDraft>(() => taskEditDraft(task));\n const [message, setMessage] = useState('');\n const agent = task.delegation?.agent;\n\n const submitEdit = (): void => {\n if (requestTaskEdit(send, sessionId, task, draft)) onClose();\n };\n const submitMessage = (): void => {\n if (!message.trim() || !agent) return;\n requestTaskMessage(send, sessionId, task.id, agent, message);\n onClose();\n };\n\n return (\n <Dialog\n open\n onOpenChange={(open) => {\n if (!open) onClose();\n }}\n >\n <DialogContent width=\"lg\" data-testid=\"task-detail-dialog\" data-mode={mode} aria-describedby={undefined}>\n <DialogHeader>\n <div className=\"flex min-w-0 flex-col items-start gap-1 sm:flex-row sm:items-center sm:gap-2.5\">\n <span className=\"text-2xs text-doom-faint\">task #{task.id}</span>\n <DialogTitle data-testid=\"task-detail-title\" className=\"max-w-full break-words\">\n {task.subject}\n </DialogTitle>\n </div>\n </DialogHeader>\n <DialogBody>\n {mode === 'view' ? (\n <>\n <Field label=\"DESCRIPTION\">\n <ReadOnlyValue\n testId=\"task-detail-description\"\n value={task.description ?? 'no description on this task'}\n />\n </Field>\n <TaskFacts task={task} />\n <DialogFooter>\n <span className=\"min-w-0 flex-1\" />\n {agent ? (\n <Button\n variant=\"outline\"\n size=\"xs\"\n data-testid=\"task-detail-open-message\"\n onClick={() => setMode('message')}\n >\n message agent\n </Button>\n ) : null}\n <Button variant=\"primary\" size=\"xs\" data-testid=\"task-detail-open-edit\" onClick={() => setMode('edit')}>\n edit\n </Button>\n </DialogFooter>\n </>\n ) : null}\n\n {mode === 'edit' ? (\n <>\n <Field label=\"SUBJECT\">\n <Input\n data-testid=\"task-detail-subject-input\"\n autoFocus\n value={draft.subject}\n onChange={(event) => setDraft({ ...draft, subject: event.target.value })}\n />\n </Field>\n <Field label=\"DESCRIPTION\">\n <Textarea\n data-testid=\"task-detail-description-input\"\n rows={DESCRIPTION_ROWS}\n value={draft.description}\n placeholder=\"what this task covers\"\n onChange={(event) => setDraft({ ...draft, description: event.target.value })}\n />\n </Field>\n <Field label=\"STATUS\">\n <Select\n value={draft.status}\n onValueChange={(value) => setDraft({ ...draft, status: value as WebTaskStatus })}\n >\n <SelectTrigger\n data-testid=\"task-detail-status-input\"\n className=\"h-7 w-full min-w-0 text-xs sm:min-w-[200px]\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {STATUS_CHOICES.map((status) => (\n <SelectItem key={status} value={status}>\n {status.replace('_', ' ')}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </Field>\n <DialogFooter className=\"flex-wrap sm:flex-nowrap\">\n <span className=\"w-full text-2xs text-doom-faint sm:w-auto\">\n saved as one prompt naming only the fields you changed\n </span>\n <span className=\"min-w-0 flex-1\" />\n <Button variant=\"outline\" size=\"xs\" data-testid=\"task-detail-cancel\" onClick={onClose}>\n cancel\n </Button>\n <Button variant=\"primary\" size=\"xs\" data-testid=\"task-detail-save\" onClick={submitEdit}>\n save\n </Button>\n </DialogFooter>\n </>\n ) : null}\n\n {mode === 'message' && agent ? (\n <>\n <Field label={`MESSAGE TO ${agent.toUpperCase()}`}>\n <Textarea\n data-testid=\"task-detail-message-input\"\n autoFocus\n rows={MESSAGE_ROWS}\n value={message}\n placeholder=\"guidance for the run working on this task\"\n onChange={(event) => setMessage(event.target.value)}\n />\n </Field>\n <DialogFooter className=\"flex-wrap sm:flex-nowrap\">\n <span className=\"w-full text-2xs text-doom-faint sm:w-auto\">\n steers the run, it does not edit the task\n </span>\n <span className=\"min-w-0 flex-1\" />\n <Button variant=\"outline\" size=\"xs\" data-testid=\"task-detail-cancel\" onClick={onClose}>\n cancel\n </Button>\n <Button variant=\"primary\" size=\"xs\" data-testid=\"task-detail-send\" onClick={submitMessage}>\n send\n </Button>\n </DialogFooter>\n </>\n ) : null}\n </DialogBody>\n </DialogContent>\n </Dialog>\n );\n}\n","import type { WebPluginSlotProps } from '@agimon-ai/doompi-core/web';\nimport {\n Button,\n ChevronDownIcon,\n ChevronRightIcon,\n Dot,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n EditIcon,\n KebabIcon,\n MessageIcon,\n TrashIcon,\n type DotTone,\n} from '@agimon-ai/doompi-web-components';\nimport { useStore } from '@tanstack/react-store';\nimport { useState } from 'react';\n\nimport type { WebTask } from '../../../../../../types/webTasks';\nimport { requestTaskRemoval, tasks } from '../../channel/_lib/tasksStore';\nimport { TaskDetailDialog, type TaskDialogMode } from './TaskDetailDialog';\n\nconst STATUS_TONE: Readonly<Record<WebTask['status'], DotTone>> = {\n pending: 'muted',\n in_progress: 'yellow',\n completed: 'green',\n failed: 'red',\n deleted: 'muted',\n};\n\ninterface DialogState {\n taskId: number;\n mode: TaskDialogMode;\n}\n\nfunction TaskRow({\n task,\n sessionId,\n sendSessionFrame,\n openDialog,\n}: {\n task: WebTask;\n sessionId: string;\n sendSessionFrame: WebPluginSlotProps['sendSessionFrame'];\n openDialog: (mode: TaskDialogMode) => void;\n}) {\n const detail = task.status === 'in_progress' ? task.activeForm : task.description;\n const agent = task.delegation?.agent;\n return (\n <div\n data-testid={`activity-task-${task.id}`}\n data-task-status={task.status}\n className=\"flex flex-col gap-1 rounded-md px-1 py-1\"\n >\n <div className=\"grid min-w-0 grid-cols-[auto_minmax(0,1fr)_auto_auto] items-center gap-x-1.5\">\n <Dot tone={STATUS_TONE[task.status]} pulse={task.status === 'in_progress'} />\n <button\n type=\"button\"\n data-testid={`activity-task-title-${task.id}`}\n title={task.subject}\n onClick={() => openDialog('view')}\n className={`min-w-0 truncate text-left text-xs font-bold hover:underline ${task.status === 'failed' ? 'text-doom-red' : task.status === 'completed' ? 'text-doom-dim' : 'text-doom-hi'}`}\n >\n <span className=\"text-doom-faint\">#{task.id}</span> {task.subject}\n </button>\n <span className=\"shrink-0 text-2xs text-doom-faint\">{task.status.replace('_', ' ')}</span>\n {task.status !== 'completed' && task.status !== 'deleted' ? (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n data-testid={`activity-task-menu-${task.id}`}\n aria-label={`task #${task.id} actions`}\n title={`task #${task.id} actions`}\n className=\"self-center shrink-0 text-doom-faint hover:bg-doom-deep hover:text-doom-hi data-[state=open]:bg-doom-deep data-[state=open]:text-doom-hi\"\n >\n <KebabIcon className=\"h-3 w-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent data-testid={`activity-task-menu-list-${task.id}`}>\n <DropdownMenuItem data-testid={`activity-task-edit-${task.id}`} onSelect={() => openDialog('edit')}>\n <EditIcon className=\"h-3 w-3\" />\n Edit\n </DropdownMenuItem>\n {agent ? (\n <DropdownMenuItem\n data-testid={`activity-task-message-${task.id}`}\n onSelect={() => openDialog('message')}\n >\n <MessageIcon className=\"h-3 w-3\" />\n Message agent\n </DropdownMenuItem>\n ) : null}\n <DropdownMenuItem\n variant=\"destructive\"\n data-testid={`activity-task-remove-${task.id}`}\n onSelect={() => requestTaskRemoval(sendSessionFrame, sessionId, task.id)}\n >\n <TrashIcon className=\"h-3 w-3\" />\n Remove\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n ) : null}\n </div>\n {detail || agent || task.blockedBy.length > 0 ? (\n <span className=\"truncate pl-3 text-2xs text-doom-faint\">\n {agent ? `[${agent}] ` : ''}\n {detail ?? ''}\n {task.blockedBy.length > 0 ? ` · blocked by ${task.blockedBy.map((id) => `#${id}`).join(', ')}` : ''}\n </span>\n ) : null}\n </div>\n );\n}\n\n/**\n * Session task graph in the activity dock. Empty graphs have no cockpit presence.\n *\n * This fills the `tasks` activity group, so the dock has already drawn the\n * heading, the key chip and the section frame. Rendering rows only keeps the\n * group titled once.\n */\nexport function TasksActivitySection({ sessionId, sendSessionFrame }: WebPluginSlotProps) {\n const sessionTasks = useStore(tasks.store, (state) => tasks.select(state, sessionId).tasks);\n const [historyOpen, setHistoryOpen] = useState(false);\n const [dialog, setDialog] = useState<DialogState>();\n if (sessionId === null || sessionTasks.length === 0) return null;\n\n const active = sessionTasks.filter((task) => task.status === 'pending' || task.status === 'in_progress');\n const history = sessionTasks.filter((task) => task.status === 'completed' || task.status === 'failed');\n const dialogTask = dialog ? sessionTasks.find((task) => task.id === dialog.taskId) : undefined;\n return (\n <div className=\"flex flex-col gap-2\">\n {active.length > 0 ? (\n <div className=\"flex flex-col gap-0.5\">\n {active.map((task) => (\n <TaskRow\n key={task.id}\n task={task}\n sessionId={sessionId}\n sendSessionFrame={sendSessionFrame}\n openDialog={(mode) => setDialog({ taskId: task.id, mode })}\n />\n ))}\n </div>\n ) : null}\n {history.length > 0 ? (\n <div className=\"flex flex-col gap-0.5\">\n <Button\n variant=\"ghost\"\n size=\"xs\"\n aria-expanded={historyOpen}\n onClick={() => setHistoryOpen((open) => !open)}\n className=\"justify-start gap-1.5 rounded-md px-1 py-0.5 hover:bg-doom-panel\"\n >\n {historyOpen ? (\n <ChevronDownIcon className=\"h-2.5 w-2.5 text-doom-faint\" />\n ) : (\n <ChevronRightIcon className=\"h-2.5 w-2.5 text-doom-faint\" />\n )}\n <span className=\"text-xs font-bold text-doom-dim\">session</span>\n <span className=\"text-2xs text-doom-faint\">{history.length}</span>\n </Button>\n {historyOpen ? (\n <div className=\"flex flex-col gap-0.5 pl-2\">\n {history.map((task) => (\n <TaskRow\n key={task.id}\n task={task}\n sessionId={sessionId}\n sendSessionFrame={sendSessionFrame}\n openDialog={(mode) => setDialog({ taskId: task.id, mode })}\n />\n ))}\n </div>\n ) : null}\n </div>\n ) : null}\n {dialog && dialogTask ? (\n <TaskDetailDialog\n key={`${dialogTask.id}-${dialog.mode}`}\n task={dialogTask}\n sessionId={sessionId}\n mode={dialog.mode}\n send={sendSessionFrame}\n onClose={() => setDialog(undefined)}\n />\n ) : null}\n </div>\n );\n}\n","import { defineFill } from '@agimon-ai/doompi-core/web';\n\nimport { TasksActivitySection } from './_lib/TasksActivitySection';\n\nexport default defineFill({ component: TasksActivitySection });\n","/**\n * Pure view logic for the task tool card, the browser counterpart of\n * the session frontend's shared format helpers (renderTaskCall, renderTaskResult). The plugin may reach\n * only its own files and src/types, so the store shapes it reads are\n * restated here as the wire JSON of a tool_execution frame.\n */\n\nexport type TaskStatus = 'pending' | 'in_progress' | 'completed' | 'failed' | 'deleted';\nexport type TaskAction = 'upsert' | 'list' | 'get' | 'delete' | 'clear' | 'assign' | 'cancel';\n\nexport const STATUS_GLYPH: Record<TaskStatus, string> = {\n pending: '○',\n in_progress: '◐',\n completed: '●',\n failed: '✗',\n deleted: '⊘',\n};\n\nexport const STATUS_LABEL: Record<TaskStatus, string> = {\n pending: 'pending',\n in_progress: 'in progress',\n completed: 'completed',\n failed: 'failed',\n deleted: 'deleted',\n};\n\nexport const ACTION_GLYPH: Record<TaskAction, string> = {\n upsert: '✎',\n delete: '×',\n get: '›',\n list: '☰',\n clear: '∅',\n assign: '⇒',\n cancel: '⊗',\n};\n\n/**\n * `upsert` is two operations behind one name, so a homogeneous batch narrows to\n * the glyph the operator already reads: `+` means new work appeared, `→` means\n * work moved. A mixed batch keeps the neutral write glyph.\n */\nconst UPSERT_CREATE_GLYPH = '+';\nconst UPSERT_UPDATE_GLYPH = '→';\n/** Task rows kept in a collapsed result, before the card is expanded. */\nconst TRANSCRIPT_TASK_ROWS = 8;\nconst TASK_STATUSES: readonly TaskStatus[] = ['pending', 'in_progress', 'completed', 'failed', 'deleted'];\nconst TASK_ACTIONS: readonly TaskAction[] = ['upsert', 'list', 'get', 'delete', 'clear', 'assign', 'cancel'];\nconst INLINE_WHITESPACE = /\\s+/gu;\n\n/** One task as the result details carry it (src/models/task.ts Task). */\nexport interface TaskView {\n id: number;\n subject: string;\n status: TaskStatus;\n activeForm?: string;\n blockedBy?: number[];\n delegation?: { agent?: string; state?: string };\n}\n\n/** The result details (src/models/task.ts TaskDetails), narrowed to what the card reads. */\nexport interface TaskDetailsView {\n action: TaskAction;\n params: Record<string, unknown>;\n tasks: TaskView[];\n error?: string;\n upsert?: { applied: number[]; failed: number };\n assignment?: { assigned: number[]; failed: number };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isStatus(value: unknown): value is TaskStatus {\n return typeof value === 'string' && (TASK_STATUSES as readonly string[]).includes(value);\n}\n\nfunction isAction(value: unknown): value is TaskAction {\n return typeof value === 'string' && (TASK_ACTIONS as readonly string[]).includes(value);\n}\n\nfunction taskView(value: unknown): TaskView | null {\n if (!isRecord(value) || typeof value.id !== 'number' || typeof value.subject !== 'string') return null;\n if (!isStatus(value.status)) return null;\n const task: TaskView = { id: value.id, subject: value.subject, status: value.status };\n if (typeof value.activeForm === 'string') task.activeForm = value.activeForm;\n if (Array.isArray(value.blockedBy)) {\n task.blockedBy = value.blockedBy.filter((id): id is number => typeof id === 'number');\n }\n if (isRecord(value.delegation)) {\n task.delegation = {};\n if (typeof value.delegation.agent === 'string') task.delegation.agent = value.delegation.agent;\n if (typeof value.delegation.state === 'string') task.delegation.state = value.delegation.state;\n }\n return task;\n}\n\nfunction idList(value: unknown): number[] {\n return Array.isArray(value) ? value.filter((id): id is number => typeof id === 'number') : [];\n}\n\n/** Narrows the wire details; null when they are not a task result at all. */\nexport function taskDetailsView(details: unknown): TaskDetailsView | null {\n if (!isRecord(details) || !isAction(details.action) || !Array.isArray(details.tasks)) return null;\n const view: TaskDetailsView = {\n action: details.action,\n params: isRecord(details.params) ? details.params : {},\n tasks: details.tasks.map(taskView).filter((task): task is TaskView => task !== null),\n };\n if (typeof details.error === 'string') view.error = details.error;\n if (isRecord(details.upsert)) {\n view.upsert = {\n applied: idList(details.upsert.applied),\n failed: typeof details.upsert.failed === 'number' ? details.upsert.failed : 0,\n };\n }\n if (isRecord(details.assignment)) {\n view.assignment = {\n assigned: idList(details.assignment.assigned),\n failed: typeof details.assignment.failed === 'number' ? details.assignment.failed : 0,\n };\n }\n return view;\n}\n\n/** `#id` for the wire's id, which the TUI would resolve to a subject through the store. */\nfunction idLabel(value: unknown): string {\n return typeof value === 'number' || typeof value === 'string' ? `#${value}` : '#?';\n}\n\n/** Keep dynamic content on one line. */\nfunction inlineText(text: string): string {\n return text.replace(INLINE_WHITESPACE, ' ').trim();\n}\n\nexport type TaskCallTone = 'dim' | 'accent';\n\n/** The call header: glyph, action, then the subject or a count, as renderTaskCall lays it out. */\nexport interface TaskCallView {\n glyph: string;\n action: string;\n subject?: string;\n subjectTone: TaskCallTone;\n /** The assignee (`→ agent`) or the list filter. */\n detail?: string;\n}\n\nfunction upsertGlyph(items: readonly Record<string, unknown>[]): string {\n if (items.length === 0) return ACTION_GLYPH.upsert;\n if (items.every((item) => item.id === undefined)) return UPSERT_CREATE_GLYPH;\n if (items.every((item) => item.id !== undefined)) return UPSERT_UPDATE_GLYPH;\n return ACTION_GLYPH.upsert;\n}\n\n/**\n * The TUI resolves an id to its subject through the task store; the card has\n * no store and shows `#id` until the result names the task.\n */\nexport function taskCallView(args: Record<string, unknown>): TaskCallView {\n const action = typeof args.action === 'string' ? args.action : 'task';\n if (!isAction(action)) return { glyph: '?', action, subjectTone: 'dim' };\n const items = action === 'upsert' && Array.isArray(args.tasks) ? args.tasks.filter(isRecord) : [];\n const view: TaskCallView = {\n glyph: action === 'upsert' ? upsertGlyph(items) : ACTION_GLYPH[action],\n action,\n subjectTone: 'dim',\n };\n\n if (action === 'upsert') {\n // One entry reads exactly as create or update did; a batch reads as a count\n // rather than a subject it would have to pick arbitrarily.\n if (items.length === 1) {\n const only = items[0] ?? {};\n if (only.id === undefined) {\n if (typeof only.subject === 'string') view.subject = inlineText(only.subject);\n } else {\n view.subject = typeof only.subject === 'string' ? inlineText(only.subject) : idLabel(only.id);\n view.subjectTone = 'accent';\n }\n } else if (items.length > 1) {\n view.subject = `${items.length} tasks`;\n }\n } else if (action === 'assign') {\n const assignments = Array.isArray(args.assignments) ? args.assignments.filter(isRecord) : [];\n if (assignments.length === 1) {\n const only = assignments[0] ?? {};\n view.subject = idLabel(only.id);\n view.subjectTone = 'accent';\n if (typeof only.agent === 'string') view.detail = `→ ${only.agent}`;\n } else if (assignments.length > 1) {\n view.subject = `${assignments.length} tasks`;\n }\n } else if ((action === 'get' || action === 'delete' || action === 'cancel') && args.id !== undefined) {\n view.subject = idLabel(args.id);\n view.subjectTone = 'accent';\n } else if (action === 'list' && isStatus(args.status)) {\n view.detail = STATUS_LABEL[args.status];\n }\n return view;\n}\n\n/** One row of the result: the task line on the left, its status flushed right. */\nexport interface TaskRow {\n id: number;\n glyph: string;\n subject: string;\n status: TaskStatus;\n /** Struck through: the task is done with. */\n closed: boolean;\n agent?: string;\n activeForm?: string;\n blockedBy: number[];\n}\n\nexport type TaskResultTone = 'running' | 'ok' | 'error' | 'warning';\n\nexport interface TaskResultView {\n rows: TaskRow[];\n /** Error text lines when the tool threw or the reducer reported an error. */\n errorLines: string[];\n status: { glyph: string; tone: TaskResultTone; text: string } | null;\n}\n\nexport function taskRow(task: TaskView): TaskRow {\n const row: TaskRow = {\n id: task.id,\n glyph: STATUS_GLYPH[task.status],\n subject: inlineText(task.subject),\n status: task.status,\n closed: task.status === 'completed' || task.status === 'deleted',\n blockedBy: task.blockedBy ?? [],\n };\n if (task.delegation?.agent) row.agent = inlineText(task.delegation.agent);\n if (task.status === 'in_progress' && task.activeForm) row.activeForm = inlineText(task.activeForm);\n return row;\n}\n\nfunction nonEmptyLines(text: string): string[] {\n return text.split('\\n').filter((line) => line.trim().length > 0);\n}\n\n/**\n * The rows `list` reported to the model: `details.tasks` is the whole\n * document, so the call's filters apply again here or the card would disagree\n * with the text the model was given.\n */\nfunction listedTasks(details: TaskDetailsView): TaskView[] {\n let view = details.tasks;\n if (details.params.includeDeleted !== true) view = view.filter((task) => task.status !== 'deleted');\n if (isStatus(details.params.status)) view = view.filter((task) => task.status === details.params.status);\n return view;\n}\n\nfunction byIds(details: TaskDetailsView, ids: readonly number[]): TaskView[] {\n return ids.flatMap((id) => details.tasks.find((task) => task.id === id) ?? []);\n}\n\nfunction batch(\n tasks: readonly TaskView[],\n failed: number,\n verb: string,\n expanded: boolean,\n): Pick<TaskResultView, 'rows' | 'status'> {\n // One applied task and nothing failed is the common case: keep the single\n // row it has always had rather than dressing it as a bulk report.\n if (tasks.length === 1 && failed === 0) return { rows: [taskRow(tasks[0] as TaskView)], status: null };\n const shown = expanded ? tasks : tasks.slice(0, TRANSCRIPT_TASK_ROWS);\n let summary = `${tasks.length} ${verb}`;\n if (failed > 0) summary += ` · ${failed} failed`;\n if (tasks.length > shown.length) summary += ` · ${tasks.length - shown.length} more`;\n return {\n rows: shown.map(taskRow),\n status: { glyph: failed > 0 ? '!' : '✓', tone: failed > 0 ? 'warning' : 'ok', text: summary },\n };\n}\n\nexport function taskResultView(input: {\n details: unknown;\n output: string;\n expanded: boolean;\n isPartial: boolean;\n isError: boolean;\n}): TaskResultView {\n const details = taskDetailsView(input.details);\n\n // Running. `assign` and `cancel` stream a placeholder before the run settles.\n if (input.isPartial) {\n const text = nonEmptyLines(input.output).at(-1) ?? 'working';\n return { rows: [], errorLines: [], status: { glyph: '◐', tone: 'running', text } };\n }\n\n // Failed. Every failure path throws, so Pi hands back error text and no\n // details; without this the card would show a green tick on a failure.\n if (input.isError || details?.error !== undefined) {\n const all = nonEmptyLines(details?.error ?? input.output);\n if (all.length <= 1) return { rows: [], errorLines: [], status: { glyph: '✗', tone: 'error', text: all[0] ?? '' } };\n const errorLines = input.expanded ? all : all.slice(0, TRANSCRIPT_TASK_ROWS);\n return { rows: [], errorLines, status: { glyph: '✗', tone: 'error', text: '' } };\n }\n\n if (details === null) return { rows: [], errorLines: [], status: { glyph: '✓', tone: 'ok', text: '' } };\n\n if (details.action === 'list') {\n const tasks = listedTasks(details);\n const shown = input.expanded ? tasks : tasks.slice(0, TRANSCRIPT_TASK_ROWS);\n let summary = tasks.length === 0 ? 'no tasks' : `${tasks.length} task${tasks.length === 1 ? '' : 's'}`;\n if (tasks.length > shown.length) summary += ` · ${tasks.length - shown.length} more`;\n return { rows: shown.map(taskRow), errorLines: [], status: { glyph: '✓', tone: 'ok', text: summary } };\n }\n\n if (details.action === 'clear') {\n return { rows: [], errorLines: [], status: { glyph: '✓', tone: 'ok', text: 'cleared' } };\n }\n\n if (details.action === 'assign' && details.assignment) {\n const assigned = byIds(details, details.assignment.assigned);\n return { errorLines: [], ...batch(assigned, details.assignment.failed, 'assigned', input.expanded) };\n }\n\n if (details.action === 'upsert') {\n const touched = byIds(details, details.upsert?.applied ?? []);\n return { errorLines: [], ...batch(touched, details.upsert?.failed ?? 0, 'applied', input.expanded) };\n }\n\n // The single task an id-bearing action acted on, so the card names it rather than a bare tick.\n const id = details.params.id;\n const task = typeof id === 'number' ? details.tasks.find((candidate) => candidate.id === id) : undefined;\n if (!task) return { rows: [], errorLines: [], status: { glyph: '✓', tone: 'ok', text: '' } };\n return { rows: [taskRow(task)], errorLines: [], status: null };\n}\n","import type { ToolMessageRenderProps } from '@agimon-ai/doompi-core/web';\nimport {\n MessageItem,\n MessageItemBody,\n MessageItemHeader,\n MessageItemStatus,\n type StatusTone,\n toolTone,\n} from '@agimon-ai/doompi-web-components';\n\nimport {\n STATUS_LABEL,\n type TaskResultTone,\n type TaskRow,\n type TaskStatus,\n taskCallView,\n taskResultView,\n} from './taskToolFormat';\n\nconst STATUS_TONE: Record<TaskStatus, string> = {\n pending: 'text-doom-dim',\n in_progress: 'text-doom-yellow',\n completed: 'text-doom-green',\n failed: 'text-doom-red',\n deleted: 'text-doom-faint',\n};\n\nconst RESULT_TONE: Record<TaskResultTone, StatusTone> = {\n running: 'running',\n ok: 'ok',\n error: 'error',\n warning: 'running',\n};\n\n/** One task row: status glyph, id, subject and chips on the left, the status label flushed right. */\nfunction TaskRowLine({ row }: { row: TaskRow }) {\n return (\n <li data-testid=\"tool-result-task-row\" data-task-id={row.id} className=\"flex items-baseline gap-2\">\n <span className={`shrink-0 ${STATUS_TONE[row.status]}`}>{row.glyph}</span>\n <span className=\"shrink-0 text-doom-faint\">#{row.id}</span>\n <span\n className={`min-w-0 flex-1 truncate ${row.closed ? 'text-doom-faint line-through' : row.status === 'in_progress' ? 'text-doom-blue' : 'text-doom-text'}`}\n >\n {row.subject}\n {row.agent ? <span className=\"text-doom-faint\"> [{row.agent}]</span> : null}\n {row.activeForm ? <span className=\"text-doom-faint\"> ({row.activeForm})</span> : null}\n {row.blockedBy.length > 0 ? (\n <span className=\"text-doom-faint\"> ⛓ {row.blockedBy.map((id) => `#${id}`).join(',')}</span>\n ) : null}\n </span>\n <span className={`shrink-0 ${STATUS_TONE[row.status]}`}>{STATUS_LABEL[row.status]}</span>\n </li>\n );\n}\n\n/**\n * The task tool's timeline item: `glyph action subject` with the assignee or\n * list filter in the header, as renderTaskCall shows it; the rows the action\n * touched, then the batch or list summary, in the body, as renderTaskResult\n * lays it out.\n */\nexport function TaskToolMessage({ args, result, output, running, isError }: ToolMessageRenderProps) {\n const call = taskCallView(args);\n const collapsed = taskResultView({ details: result?.details, output, expanded: false, isPartial: running, isError });\n const full = taskResultView({ details: result?.details, output, expanded: true, isPartial: running, isError });\n const hidden = full.rows.length - collapsed.rows.length + (full.errorLines.length - collapsed.errorLines.length);\n return (\n <MessageItem tone={toolTone({ running, isError })} expandable={hidden > 0}>\n {({ expanded }) => {\n const view = expanded ? full : collapsed;\n const empty = view.rows.length === 0 && view.errorLines.length === 0 && view.status === null;\n return (\n <>\n <MessageItemHeader title=\"task\">\n <span data-testid=\"tool-call-task\" className=\"flex min-w-0 flex-1 items-center gap-1.5\">\n <span className=\"shrink-0 text-doom-text\">\n {call.glyph} {call.action}\n </span>\n {call.subject ? (\n <span\n className={`min-w-0 truncate ${call.subjectTone === 'accent' ? 'text-doom-blue' : 'text-doom-dim'}`}\n >\n {call.subject}\n </span>\n ) : null}\n {call.detail ? <span className=\"shrink-0 text-doom-faint\">{call.detail}</span> : null}\n </span>\n </MessageItemHeader>\n {empty ? null : (\n <MessageItemBody data-testid=\"tool-result-task\" className=\"flex flex-col gap-1\">\n {view.rows.length > 0 ? (\n <ul className=\"flex flex-col gap-0.5\">\n {view.rows.map((row) => (\n <TaskRowLine key={row.id} row={row} />\n ))}\n </ul>\n ) : null}\n {view.errorLines.length > 0 ? (\n <pre className=\"whitespace-pre-wrap break-words font-mono text-doom-dim\">\n {view.errorLines.join('\\n')}\n </pre>\n ) : null}\n {!expanded && hidden > 0 ? <MessageItemStatus expands>{hidden} more</MessageItemStatus> : null}\n {view.status ? (\n <MessageItemStatus\n data-testid=\"tool-result-task-status\"\n tone={RESULT_TONE[view.status.tone]}\n glyph={view.status.glyph}\n >\n {view.status.text}\n </MessageItemStatus>\n ) : null}\n </MessageItemBody>\n )}\n </>\n );\n }}\n </MessageItem>\n );\n}\n","import { defineToolRenderer } from '@agimon-ai/doompi-core/web';\n\nimport { TaskToolMessage } from './_lib/TaskToolMessage';\n\nexport default defineToolRenderer({ message: TaskToolMessage });\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineWebPlugin, type WebPluginContributions } from '@agimon-ai/doompi-core/web';\n\nimport activityGroupTasks from '../src/extensions/workspaces/sessions/(frontend)/activity-group/tasks.web';\nimport channelTaskGraph from '../src/extensions/workspaces/sessions/(frontend)/channel/task-graph.web';\nimport fillTasks from '../src/extensions/workspaces/sessions/(frontend)/fill/Tasks.activity.tasks.web';\nimport toolTask from '../src/extensions/workspaces/sessions/(frontend)/tool/task.web';\n\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const webPlugin = defineWebPlugin({\n id: 'task',\n session: {\n get activityGroups(): WebPluginContributions['activityGroups'] { return [via({ name: 'tasks' }, activityGroupTasks)]; },\n get channels(): WebPluginContributions['channels'] { return [via({ channel: 'task_graph' }, channelTaskGraph)]; },\n get fills(): WebPluginContributions['fills'] { return [via({ slot: 'activity.tasks', id: 'tasks' }, fillTasks)]; },\n get toolRenderers(): WebPluginContributions['toolRenderers'] { return [via({ tools: ['task'] }, toolTask)]; },\n },\n});\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/doompi-task",
3
- "version": "0.0.1-alpha.83",
3
+ "version": "0.0.1-alpha.85",
4
4
  "description": "Persistent, dependency-aware task graphs and subagent delegation for Pi coding sessions.",
5
5
  "keywords": [
6
6
  "ai",
@@ -161,15 +161,15 @@
161
161
  "registry": "https://registry.npmjs.org/"
162
162
  },
163
163
  "dependencies": {
164
- "@agimon-ai/doompi-core": "0.0.1-alpha.83",
165
- "@agimon-ai/doompi-telemetry": "0.0.1-alpha.79",
166
- "@agimon-ai/doompi-ui": "0.0.1-alpha.83",
167
- "@agimon-ai/doompi-web-components": "0.0.1-alpha.41",
164
+ "@agimon-ai/doompi-core": "0.0.1-alpha.85",
165
+ "@agimon-ai/doompi-telemetry": "0.0.1-alpha.80",
166
+ "@agimon-ai/doompi-ui": "0.0.1-alpha.85",
167
+ "@agimon-ai/doompi-web-components": "0.0.1-alpha.43",
168
168
  "@deepseek-ai/cordis": "4.0.2",
169
169
  "typebox": "1.3.34"
170
170
  },
171
171
  "devDependencies": {
172
- "@agimon-ai/doompi-build": "0.0.1-alpha.11",
172
+ "@agimon-ai/doompi-build": "0.0.1-alpha.12",
173
173
  "@earendil-works/pi-coding-agent": "0.87.1",
174
174
  "@earendil-works/pi-tui": "0.87.1",
175
175
  "@tanstack/react-store": "0.11.1",