返回源码地图

packages/subagent/subagent/src/run-settlement.ts

main snapshot · da00f7f5358f · 正文引用章节 13;完整原文可核对,不声称全文件人工逐行审计

完整原文供逐行核对;页面收录不代表每行都经过人工语义审核。MIT 许可见 许可证。

1/**
2 * Settlement of one ONE-SHOT subagent run into a background-Task outcome. Only
3 * the one-shot background path uses Jobs; continuable children have no Task,
4 * no per-message result, and no Task cancellation.
5 *
6 * @module @deepseek-ai/dsh-subagent/run-settlement
7 */
8
9import type { ContentBlock } from '@deepseek-ai/dsh-llm'
10import type { JobOutcome } from '@deepseek-ai/dsh-jobs'
11import type { SubagentResult, SubagentRun } from './types.ts'
12
13/** Flatten a child's final output blocks to the task's final text. */
14function finalText(blocks: readonly ContentBlock[]): string {
15 return blocks
16 .filter((block): block is Extract<ContentBlock, { type: 'text' }> => block.type === 'text')
17 .map(block => block.text)
18 .join('')
19}
20
21/** Render a failed stop reason with optional provider-authored detail. */
22function failureDetail(result: SubagentResult): string {
23 const stopReason = result.stopReason
24 return result.diagnostic === undefined
25 ? stopReason
26 : `${stopReason}; diagnostic: ${result.diagnostic}`
27}
28
29/**
30 * Map a child result to the task outcome: completed carries final text, local
31 * cancellation (`aborted` without a diagnostic) is killed, and provider-
32 * diagnosed remote aborts plus every other reason are failed without partial
33 * output.
34 * @param result - child terminal result.
35 * @returns outcome for the `ctx.jobs` registration.
36 */
37function runOutcome(result: SubagentResult): JobOutcome {
38 switch (result.stopReason) {
39 case 'completed':
40 return { status: 'completed', result: finalText(result.output) }
41 case 'aborted':
42 return result.diagnostic === undefined
43 ? { status: 'killed' }
44 : { status: 'failed', detail: failureDetail(result) }
45 case 'error':
46 case 'max-tokens':
47 case 'refusal':
48 return { status: 'failed', detail: failureDetail(result) }
49 // Merge-extensible reasons remain failures with provider-authored detail.
50 default:
51 return { status: 'failed', detail: failureDetail(result) }
52 }
53}
54
55/**
56 * Await the child result, dispose the run, then return its task outcome. Result
57 * and disposal failures become `failed`; when both fail, both details survive.
58 * @param run - live run to settle and release.
59 * @returns outcome after child resources are released.
60 */
61export async function settleRun(run: SubagentRun): Promise<JobOutcome> {
62 let outcome: JobOutcome
63 try {
64 outcome = runOutcome(await run.result)
65 } catch (error: unknown) {
66 outcome = { status: 'failed', detail: String(error) }
67 }
68 try {
69 await run.dispose()
70 } catch (error: unknown) {
71 const prefix = outcome.detail === undefined ? '' : `${outcome.detail}; `
72 return { status: 'failed', detail: `${prefix}dispose failed: ${String(error)}` }
73 }
74 return outcome
75}