fix(tasks): address task API review feedback
The public kill result used the awkward phrase already-terminal. Rename it to already-finished and keep the model-facing response aligned; not-alive would be inaccurate because a force-failed registry record can still correspond to orphaned producer work. Task kinds were open strings even though producer namespaces are an extension point. Add the merge-extensible TaskKindMap and derived TaskKind, cover consumer declarations in task and bundle tests, and retain the runtime non-empty check for untyped callers. With exactOptionalPropertyTypes, owner?: Agent | undefined allowed an explicit undefined value that no caller needs. Tighten the property to owner?: Agent so unowned work is expressed by omitting it. Record the requested task-service/backend split as a follow-up, using a systemd-backed runtime as a concrete candidate without guessing its durability and ownership contract in this PR. Regenerate the type and Cordis catalogs so public docs match the declarations.
This commit is contained in:
@@ -4,7 +4,13 @@ import { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import AgentRegistry, { AgentId } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import TaskService, { TaskId } from '@deepseek-ai/dsh-tasks'
|
||||
import type { TaskHooks, TaskOutcome, TaskSnapshot, TaskStart } from '@deepseek-ai/dsh-tasks'
|
||||
import type { TaskHooks, TaskKind, TaskOutcome, TaskSnapshot, TaskStart } from '@deepseek-ai/dsh-tasks'
|
||||
|
||||
declare module '@deepseek-ai/dsh-tasks' {
|
||||
interface TaskKindMap {
|
||||
workflow: 'workflow'
|
||||
}
|
||||
}
|
||||
|
||||
const agentScopeDisposers = new WeakMap<Agent, () => Promise<void>>()
|
||||
|
||||
@@ -81,7 +87,7 @@ describe('TaskService.start', () => {
|
||||
|
||||
it('rejects an empty kind and an empty label', async () => {
|
||||
const ctx = await harness()
|
||||
expect(() => ctx.tasks.start(producer({ kind: '' }).spec)).toThrow('invalid task kind')
|
||||
expect(() => ctx.tasks.start(producer({ kind: '' as TaskKind }).spec)).toThrow('invalid task kind')
|
||||
expect(() => ctx.tasks.start(producer({ label: '' }).spec)).toThrow('invalid task label')
|
||||
})
|
||||
|
||||
@@ -90,6 +96,7 @@ describe('TaskService.start', () => {
|
||||
expect(ctx.tasks.start(producer().spec)).toBe('bash-1')
|
||||
expect(ctx.tasks.start(producer().spec)).toBe('bash-2')
|
||||
expect(ctx.tasks.start(producer({ kind: 'subagent' }).spec)).toBe('subagent-1')
|
||||
expect(ctx.tasks.start(producer({ kind: 'workflow' }).spec)).toBe('workflow-1')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -222,13 +229,13 @@ describe('TaskService.kill', () => {
|
||||
expect(seen[0]).toMatchObject({ id, status: 'killed', reported: true })
|
||||
})
|
||||
|
||||
it('reports an already-terminal task instead of failing', async () => {
|
||||
it('reports an already-finished task instead of failing', async () => {
|
||||
const ctx = await harness()
|
||||
const p = producer()
|
||||
const id = ctx.tasks.start(p.spec)
|
||||
p.settle({ status: 'completed' })
|
||||
await tick()
|
||||
expect(ctx.tasks.kill(id)).toBe('already-terminal')
|
||||
expect(ctx.tasks.kill(id)).toBe('already-finished')
|
||||
})
|
||||
|
||||
it('propagates a throwing producer cancel and leaves the task untouched', async () => {
|
||||
@@ -254,7 +261,7 @@ describe('TaskService.kill', () => {
|
||||
expect(seen[0]).toMatchObject({ id, reported: false }) // notice would still fire
|
||||
|
||||
broken = false
|
||||
expect(ctx.tasks.kill(id)).toBe('already-terminal')
|
||||
expect(ctx.tasks.kill(id)).toBe('already-finished')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -299,7 +306,7 @@ describe('TaskService.wait', () => {
|
||||
expect(ctx.tasks.get(id).status).toBe('running')
|
||||
})
|
||||
|
||||
it('returns immediately for an already-terminal task', async () => {
|
||||
it('returns immediately for an already-finished task', async () => {
|
||||
const ctx = await harness()
|
||||
const p = producer()
|
||||
const id = ctx.tasks.start(p.spec)
|
||||
|
||||
Reference in New Issue
Block a user