Merge remote-tracking branch 'origin/master' into feat/send-unify

# Conflicts:
#	examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/session.jsonl
#	examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/stdout.expected.jsonl
#	packages/cordis/tool-cordis/src/api-catalog.ts
#	packages/pty/pty-local/tests/index.spec.ts
#	packages/session-query/session-query/tests/tracing.spec.ts
This commit is contained in:
Turtle
2026-07-23 22:41:45 +08:00
333 changed files with 10751 additions and 907 deletions

View File

@@ -45,13 +45,19 @@ function producer(overrides: Partial<Omit<TaskStart, 'run'> & TaskHooks> = {}) {
let settle!: (outcome: TaskOutcome) => void
let reject!: (error: unknown) => void
const cancels: (string | undefined)[] = []
const { kind = 'bash', label = 'sleep 60', owner, ...hookOverrides } = overrides
const { kind = 'bash', label = 'sleep 60', owner, outputLimitBytes, ...hookOverrides } = overrides
const hooks: TaskHooks = {
cancel(reason) { cancels.push(reason) },
done: new Promise<TaskOutcome>((res, rej) => { settle = res; reject = rej }),
...hookOverrides,
}
const spec: TaskStart = { kind, label, ...owner !== undefined ? { owner } : {}, run: () => hooks }
const spec: TaskStart = {
kind,
label,
...owner !== undefined ? { owner } : {},
...outputLimitBytes !== undefined ? { outputLimitBytes } : {},
run: () => hooks,
}
return { spec, settle, reject, cancels }
}
@@ -86,10 +92,11 @@ describe('TaskService.start', () => {
.toThrow('background tasks unavailable: no control surface is attached (load @deepseek-ai/dsh-tool-tasks)')
})
it('rejects an empty kind and an empty label', async () => {
it('rejects an empty kind, empty label, and invalid output limit', async () => {
const ctx = await harness()
expect(() => ctx.tasks.start(producer({ kind: '' as TaskKind }).spec)).toThrow('invalid task kind')
expect(() => ctx.tasks.start(producer({ label: '' }).spec)).toThrow('invalid task label')
expect(() => ctx.tasks.start(producer({ outputLimitBytes: 0 }).spec)).toThrow('outputLimitBytes')
})
it('issues kind-prefixed ids from per-kind counters', async () => {
@@ -119,6 +126,16 @@ describe('TaskService reads and settlement', () => {
expect(read.snapshot.finishedAt).toBeTypeOf('number')
})
it('projects a producer-owned model output limit into reads and snapshots', async () => {
const ctx = await harness()
const p = producer({ outputLimitBytes: 64, readOutput: () => 'delta' })
const id = ctx.tasks.start(p.spec)
expect(ctx.tasks.read(id)).toMatchObject({
text: 'delta', snapshot: { outputLimitBytes: 64 },
})
expect(ctx.tasks.get(id)).toMatchObject({ outputLimitBytes: 64 })
})
it('final-output kinds read empty while live, the outcome output idempotently once settled', async () => {
const ctx = await harness()
const p = producer({ kind: 'subagent', label: 'research task' })