@morlay/dsh-subagent 0.0.10 → 0.0.11-alpha.1
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.
- package/dist/index.d.mts +77 -120
- package/dist/index.mjs +43 -49
- package/dist/rows.d.mts +1 -3
- package/dist/rows.mjs +1 -2
- package/package.json +28 -28
- package/src/continuation-messages.ts +8 -3
- package/src/index.ts +5 -4
- package/src/manager.ts +16 -2
- package/src/vendor/dsh-subagent/activation.ts +81 -89
- package/src/vendor/dsh-subagent/archive-admission.ts +38 -45
- package/src/vendor/dsh-subagent/assistant-output.ts +17 -19
- package/src/vendor/dsh-subagent/catalog.ts +79 -111
- package/src/vendor/dsh-subagent/child-agent.ts +83 -92
- package/src/vendor/dsh-subagent/continuation-messages.ts +64 -68
- package/src/vendor/dsh-subagent/control-types.ts +71 -68
- package/src/vendor/dsh-subagent/control.ts +39 -55
- package/src/vendor/dsh-subagent/depth.ts +14 -18
- package/src/vendor/dsh-subagent/descriptor.ts +107 -113
- package/src/vendor/dsh-subagent/error.ts +3 -3
- package/src/vendor/dsh-subagent/index.ts +193 -254
- package/src/vendor/dsh-subagent/internal.ts +17 -21
- package/src/vendor/dsh-subagent/lifecycle.ts +48 -51
- package/src/vendor/dsh-subagent/list-children.ts +57 -65
- package/src/vendor/dsh-subagent/manager.ts +726 -862
- package/src/vendor/dsh-subagent/out-of-process.ts +59 -61
- package/src/vendor/dsh-subagent/projection-types.ts +40 -38
- package/src/vendor/dsh-subagent/projection.ts +85 -107
- package/src/vendor/dsh-subagent/structured.ts +48 -57
- package/src/vendor/dsh-subagent/types.ts +68 -68
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
* @module @deepseek-ai/dsh-subagent/internal
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { Agent } from
|
|
8
|
-
import type { ContentBlock, MessageId, MessageSource } from
|
|
9
|
-
import type { SessionId } from
|
|
10
|
-
import type { ToolDefinition } from
|
|
11
|
-
import type SubagentRuntime from
|
|
12
|
-
import type { SubagentDelivery } from
|
|
7
|
+
import type { Agent } from '@deepseek-ai/dsh-agent'
|
|
8
|
+
import type { ContentBlock, MessageId, MessageSource } from '@deepseek-ai/dsh-llm'
|
|
9
|
+
import type { SessionId } from '@deepseek-ai/dsh-session'
|
|
10
|
+
import type { ToolDefinition } from '@deepseek-ai/dsh-tools'
|
|
11
|
+
import type SubagentRuntime from './index.ts'
|
|
12
|
+
import type { SubagentDelivery } from './control-types.ts'
|
|
13
13
|
|
|
14
14
|
/** Process-stable identity carried only by the standard adjacent-Agent messaging tool. */
|
|
15
|
-
export const adjacentAgentSendMessageTool = Symbol.for(
|
|
15
|
+
export const adjacentAgentSendMessageTool = Symbol.for('dsh.subagent.adjacentAgentSendMessageTool')
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Mark the standard adjacent-Agent messaging tool without changing its model-visible schema.
|
|
@@ -20,8 +20,8 @@ export const adjacentAgentSendMessageTool = Symbol.for("dsh.subagent.adjacentAge
|
|
|
20
20
|
* @returns the same definition with its internal identity installed.
|
|
21
21
|
*/
|
|
22
22
|
export function markAdjacentAgentSendMessageTool(definition: ToolDefinition): ToolDefinition {
|
|
23
|
-
Object.defineProperty(definition, adjacentAgentSendMessageTool, { value: true })
|
|
24
|
-
return definition
|
|
23
|
+
Object.defineProperty(definition, adjacentAgentSendMessageTool, { value: true })
|
|
24
|
+
return definition
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/**
|
|
@@ -30,12 +30,8 @@ export function markAdjacentAgentSendMessageTool(definition: ToolDefinition): To
|
|
|
30
30
|
* @returns whether the definition carries the internal standard-tool identity.
|
|
31
31
|
*/
|
|
32
32
|
export function isAdjacentAgentSendMessageTool(definition: ToolDefinition | undefined): boolean {
|
|
33
|
-
return
|
|
34
|
-
definition
|
|
35
|
-
(definition as ToolDefinition & { [adjacentAgentSendMessageTool]?: true })[
|
|
36
|
-
adjacentAgentSendMessageTool
|
|
37
|
-
] === true
|
|
38
|
-
);
|
|
33
|
+
return definition !== undefined
|
|
34
|
+
&& (definition as ToolDefinition & { [adjacentAgentSendMessageTool]?: true })[adjacentAgentSendMessageTool] === true
|
|
39
35
|
}
|
|
40
36
|
|
|
41
37
|
/**
|
|
@@ -43,7 +39,7 @@ export function isAdjacentAgentSendMessageTool(definition: ToolDefinition | unde
|
|
|
43
39
|
* entry and this unbundled internal subpath.
|
|
44
40
|
* @internal
|
|
45
41
|
*/
|
|
46
|
-
export const deliverSubagentPrompt = Symbol.for(
|
|
42
|
+
export const deliverSubagentPrompt = Symbol.for('dsh.subagent.deliverPrompt')
|
|
47
43
|
|
|
48
44
|
/** Runtime face required by the host-only prompt adapters. */
|
|
49
45
|
export interface HostPromptDeliverer {
|
|
@@ -54,7 +50,7 @@ export interface HostPromptDeliverer {
|
|
|
54
50
|
source: MessageSource,
|
|
55
51
|
signal: AbortSignal,
|
|
56
52
|
delivery: SubagentDelivery,
|
|
57
|
-
): Promise<MessageId
|
|
53
|
+
): Promise<MessageId>
|
|
58
54
|
}
|
|
59
55
|
|
|
60
56
|
/**
|
|
@@ -81,8 +77,8 @@ export function queueHostSubagentPrompt(
|
|
|
81
77
|
content,
|
|
82
78
|
source,
|
|
83
79
|
signal,
|
|
84
|
-
|
|
85
|
-
)
|
|
80
|
+
'queue',
|
|
81
|
+
)
|
|
86
82
|
}
|
|
87
83
|
|
|
88
84
|
/**
|
|
@@ -109,6 +105,6 @@ export function steerHostSubagentPrompt(
|
|
|
109
105
|
content,
|
|
110
106
|
source,
|
|
111
107
|
signal,
|
|
112
|
-
|
|
113
|
-
)
|
|
108
|
+
'steer',
|
|
109
|
+
)
|
|
114
110
|
}
|
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
* @module @deepseek-ai/dsh-subagent/lifecycle
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { randomUUID } from
|
|
11
|
-
import type { Context } from
|
|
12
|
-
import type { Agent } from
|
|
13
|
-
import { foldConsumedWork } from
|
|
14
|
-
import type { SessionEvent, SessionId } from
|
|
15
|
-
import { SubagentRunId } from
|
|
16
|
-
import type { SubagentResult, SubagentRunEndInfo, SubagentRunInfo } from
|
|
10
|
+
import { randomUUID } from 'node:crypto'
|
|
11
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
12
|
+
import type { Agent } from '@deepseek-ai/dsh-agent'
|
|
13
|
+
import { foldConsumedWork } from '@deepseek-ai/dsh-agent'
|
|
14
|
+
import type { SessionEvent, SessionId } from '@deepseek-ai/dsh-session'
|
|
15
|
+
import { SubagentRunId } from './types.ts'
|
|
16
|
+
import type { SubagentResult, SubagentRunEndInfo, SubagentRunInfo } from './types.ts'
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Lifecycle observer for one activation's residency epoch. Package-private: the
|
|
@@ -25,7 +25,7 @@ export interface ActivationObserver {
|
|
|
25
25
|
* Publish the start edge once the epoch is resident.
|
|
26
26
|
* @param child - the resident local Agent, or undefined for an external execution.
|
|
27
27
|
*/
|
|
28
|
-
start(child?: Agent): void
|
|
28
|
+
start(child?: Agent): void
|
|
29
29
|
/**
|
|
30
30
|
* Publish the terminal edge exactly once, pairing this epoch's {@link start},
|
|
31
31
|
* after the disposal outcome is known. Called only for a resident epoch: a
|
|
@@ -33,7 +33,7 @@ export interface ActivationObserver {
|
|
|
33
33
|
* report a lifecycle the child never had.
|
|
34
34
|
* @param result - the captured result, with teardown failures applied.
|
|
35
35
|
*/
|
|
36
|
-
settle(result: SubagentResult): void
|
|
36
|
+
settle(result: SubagentResult): void
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
@@ -46,10 +46,10 @@ export interface ActivationObserver {
|
|
|
46
46
|
* a narrowed stand-in would silently change scope filtering.
|
|
47
47
|
*/
|
|
48
48
|
export type LifecycleEmitter = {
|
|
49
|
-
(name:
|
|
50
|
-
(name:
|
|
51
|
-
(name:
|
|
52
|
-
}
|
|
49
|
+
(name: 'subagent/start', info: SubagentRunInfo, parent: Agent): void
|
|
50
|
+
(name: 'subagent/end', info: SubagentRunEndInfo, parent: Agent): void
|
|
51
|
+
(name: 'subagent/provider-removed', info: string): void
|
|
52
|
+
}
|
|
53
53
|
|
|
54
54
|
/**
|
|
55
55
|
* Build the contained lifecycle emitter this seam publishes every edge through.
|
|
@@ -65,23 +65,24 @@ export function createLifecycleEmitter(
|
|
|
65
65
|
carrier: (parent: Agent) => object,
|
|
66
66
|
): LifecycleEmitter {
|
|
67
67
|
return (
|
|
68
|
-
name:
|
|
68
|
+
name: 'subagent/start' | 'subagent/end' | 'subagent/provider-removed',
|
|
69
69
|
info: SubagentRunInfo | SubagentRunEndInfo | string,
|
|
70
70
|
parent?: Agent,
|
|
71
71
|
): void => {
|
|
72
|
-
const dispatchArgs: unknown[] =
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
const dispatchArgs: unknown[] = parent === undefined
|
|
73
|
+
? [name, info]
|
|
74
|
+
: [carrier(parent), name, info]
|
|
75
|
+
for (const callback of ctx.events.dispatch('emit', dispatchArgs)) {
|
|
75
76
|
try {
|
|
76
|
-
const returned: unknown = callback(info)
|
|
77
|
+
const returned: unknown = callback(info)
|
|
77
78
|
void Promise.resolve(returned).catch((error: unknown) => {
|
|
78
|
-
ctx.logger.warn(`subagent: ${name} listener rejected: ${renderThrown(error)}`)
|
|
79
|
-
})
|
|
79
|
+
ctx.logger.warn(`subagent: ${name} listener rejected: ${renderThrown(error)}`)
|
|
80
|
+
})
|
|
80
81
|
} catch (error: unknown) {
|
|
81
|
-
ctx.logger.warn(`subagent: ${name} listener threw: ${renderThrown(error)}`)
|
|
82
|
+
ctx.logger.warn(`subagent: ${name} listener threw: ${renderThrown(error)}`)
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
|
-
}
|
|
85
|
+
}
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
/**
|
|
@@ -98,24 +99,20 @@ export function createActivationObserver(
|
|
|
98
99
|
childId: SessionId,
|
|
99
100
|
parent: Agent,
|
|
100
101
|
): ActivationObserver {
|
|
101
|
-
const identity = { runId: SubagentRunId(randomUUID()), provider, id: childId, local: false }
|
|
102
|
+
const identity = { runId: SubagentRunId(randomUUID()), provider, id: childId, local: false }
|
|
102
103
|
return {
|
|
103
104
|
start: (child?: Agent): void => {
|
|
104
|
-
identity.local = child !== undefined
|
|
105
|
-
emit(
|
|
105
|
+
identity.local = child !== undefined
|
|
106
|
+
emit('subagent/start', identity, parent)
|
|
106
107
|
},
|
|
107
108
|
settle: ({ stopReason, output }: SubagentResult): void => {
|
|
108
|
-
emit(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
...(output.length === 0 ? {} : { lastAssistantMessage: output }),
|
|
114
|
-
},
|
|
115
|
-
parent,
|
|
116
|
-
);
|
|
109
|
+
emit('subagent/end', {
|
|
110
|
+
...identity,
|
|
111
|
+
stopReason,
|
|
112
|
+
...output.length === 0 ? {} : { lastAssistantMessage: output },
|
|
113
|
+
}, parent)
|
|
117
114
|
},
|
|
118
|
-
}
|
|
115
|
+
}
|
|
119
116
|
}
|
|
120
117
|
|
|
121
118
|
/**
|
|
@@ -134,39 +131,39 @@ export function createActivationObserver(
|
|
|
134
131
|
* @returns its terminal stop reason; `completed` only for an epoch that both
|
|
135
132
|
* closed cleanly and had nothing left to run.
|
|
136
133
|
*/
|
|
137
|
-
export function epochStopReason(events: readonly SessionEvent[]): SubagentResult[
|
|
138
|
-
const { end, droppedUnrun } = foldConsumedWork(events)
|
|
134
|
+
export function epochStopReason(events: readonly SessionEvent[]): SubagentResult['stopReason'] {
|
|
135
|
+
const { end, droppedUnrun } = foldConsumedWork(events)
|
|
139
136
|
switch (end?.data.reason.kind) {
|
|
140
|
-
case
|
|
141
|
-
return
|
|
142
|
-
case
|
|
143
|
-
case
|
|
144
|
-
return
|
|
145
|
-
case
|
|
146
|
-
return
|
|
137
|
+
case 'max-tokens':
|
|
138
|
+
return 'max-tokens'
|
|
139
|
+
case 'aborted':
|
|
140
|
+
case 'interrupted':
|
|
141
|
+
return 'aborted'
|
|
142
|
+
case 'error':
|
|
143
|
+
return 'error'
|
|
147
144
|
// A pre-step rejection — a hook deny, a policy plugin — discarded input
|
|
148
145
|
// this epoch had claimed: the work was declined, not done.
|
|
149
|
-
case
|
|
150
|
-
return
|
|
146
|
+
case 'blocked':
|
|
147
|
+
return 'refusal'
|
|
151
148
|
// A clean ending and no accounting turn at all share one rule: the epoch
|
|
152
149
|
// finished what it was given unless a cancelled queue says otherwise.
|
|
153
150
|
case undefined:
|
|
154
|
-
case
|
|
155
|
-
return droppedUnrun ?
|
|
151
|
+
case 'completed':
|
|
152
|
+
return droppedUnrun ? 'aborted' : 'completed'
|
|
156
153
|
/* v8 ignore next 4 -- `forked` appears only in constructor seed history, while
|
|
157
154
|
* this function reads an epoch-owned suffix. `TurnEndReason` is merge-extensible,
|
|
158
155
|
* so a backend-added variant cannot be listed; treating an unnameable reason as
|
|
159
156
|
* success would report failed work as completed. */
|
|
160
157
|
default:
|
|
161
|
-
return
|
|
158
|
+
return 'error'
|
|
162
159
|
}
|
|
163
160
|
}
|
|
164
161
|
|
|
165
162
|
/** Render any listener-thrown value without letting coercion escape containment. */
|
|
166
163
|
function renderThrown(value: unknown): string {
|
|
167
164
|
try {
|
|
168
|
-
return value instanceof Error ? `${value.name}: ${value.message}` : String(value)
|
|
165
|
+
return value instanceof Error ? `${value.name}: ${value.message}` : String(value)
|
|
169
166
|
} catch {
|
|
170
|
-
return
|
|
167
|
+
return '<unrenderable thrown value>'
|
|
171
168
|
}
|
|
172
169
|
}
|
|
@@ -4,21 +4,21 @@
|
|
|
4
4
|
* @module @deepseek-ai/dsh-subagent
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { Context } from
|
|
8
|
-
import type { SessionId } from
|
|
9
|
-
import type { SubagentListEntry } from
|
|
10
|
-
import { SubagentError } from
|
|
11
|
-
import type { SubagentCatalogEntry } from
|
|
7
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
8
|
+
import type { SessionId } from '@deepseek-ai/dsh-session'
|
|
9
|
+
import type { SubagentListEntry } from './control-types.ts'
|
|
10
|
+
import { SubagentError } from './error.ts'
|
|
11
|
+
import type { SubagentCatalogEntry } from './projection-types.ts'
|
|
12
12
|
|
|
13
|
-
export type { SubagentListEntry } from
|
|
13
|
+
export type { SubagentListEntry } from './control-types.ts'
|
|
14
14
|
|
|
15
15
|
/** One catalog descendant with its direct parent and edge distance from the requested root. */
|
|
16
16
|
export type SubagentDescendantListEntry = SubagentListEntry & {
|
|
17
17
|
/** Parent whose catalog contains this child. */
|
|
18
|
-
readonly parentId: SessionId
|
|
18
|
+
readonly parentId: SessionId
|
|
19
19
|
/** Edge distance from the requested root; direct children are `1`. */
|
|
20
|
-
readonly depth: number
|
|
21
|
-
}
|
|
20
|
+
readonly depth: number
|
|
21
|
+
}
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Read one parent's durable catalog through a live-preferred Session observation.
|
|
@@ -33,24 +33,24 @@ export async function listChildren(
|
|
|
33
33
|
parentSessionId: SessionId,
|
|
34
34
|
signal?: AbortSignal,
|
|
35
35
|
): Promise<SubagentCatalogEntry[]> {
|
|
36
|
-
const query = ctx.get(
|
|
36
|
+
const query = ctx.get('sessionQuery')
|
|
37
37
|
if (query === undefined) {
|
|
38
38
|
throw new SubagentError(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
)
|
|
39
|
+
'listing subagents requires the sessionQuery service (load @deepseek-ai/dsh-session-query)',
|
|
40
|
+
'SUBAGENT_CONTROL_QUERY_UNAVAILABLE',
|
|
41
|
+
)
|
|
42
42
|
}
|
|
43
43
|
using parent = await query.observeSession(parentSessionId, {
|
|
44
|
-
...
|
|
45
|
-
})
|
|
46
|
-
const entries = parent.projections?.values.subagentCatalog
|
|
44
|
+
...signal === undefined ? {} : { signal },
|
|
45
|
+
})
|
|
46
|
+
const entries = parent.projections?.values.subagentCatalog
|
|
47
47
|
if (entries === undefined) {
|
|
48
48
|
throw new SubagentError(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
49
|
+
'listing subagents requires the registered subagentCatalog projection',
|
|
50
|
+
'SUBAGENT_CONTROL_PROJECTIONS_UNAVAILABLE',
|
|
51
|
+
)
|
|
52
52
|
}
|
|
53
|
-
return entries
|
|
53
|
+
return entries
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/**
|
|
@@ -66,76 +66,68 @@ export async function listDescendants(
|
|
|
66
66
|
rootSessionId: SessionId,
|
|
67
67
|
signal?: AbortSignal,
|
|
68
68
|
): Promise<SubagentDescendantListEntry[]> {
|
|
69
|
-
const sessions = ctx.get(
|
|
69
|
+
const sessions = ctx.get('sessions')
|
|
70
70
|
if (sessions === undefined) {
|
|
71
71
|
throw new SubagentError(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
)
|
|
72
|
+
'listing subagents requires the session store (load @deepseek-ai/dsh-session)',
|
|
73
|
+
'SUBAGENT_CONTROL_SESSION_STORE_UNAVAILABLE',
|
|
74
|
+
)
|
|
75
75
|
}
|
|
76
76
|
const readChildren = async (id: SessionId): Promise<SubagentCatalogEntry[]> => {
|
|
77
|
-
assertListingNotCancelled(signal)
|
|
78
|
-
let children: SubagentCatalogEntry[]
|
|
77
|
+
assertListingNotCancelled(signal)
|
|
78
|
+
let children: SubagentCatalogEntry[]
|
|
79
79
|
try {
|
|
80
|
-
children = await listChildren(ctx, id, signal)
|
|
80
|
+
children = await listChildren(ctx, id, signal)
|
|
81
81
|
} catch (error) {
|
|
82
|
-
assertListingNotCancelled(signal)
|
|
83
|
-
throw error
|
|
82
|
+
assertListingNotCancelled(signal)
|
|
83
|
+
throw error
|
|
84
84
|
}
|
|
85
|
-
assertListingNotCancelled(signal)
|
|
86
|
-
return children
|
|
87
|
-
}
|
|
85
|
+
assertListingNotCancelled(signal)
|
|
86
|
+
return children
|
|
87
|
+
}
|
|
88
88
|
const stack = (await readChildren(rootSessionId))
|
|
89
|
-
.map(
|
|
90
|
-
.reverse()
|
|
91
|
-
const visited = new Set<SessionId>([rootSessionId])
|
|
92
|
-
const result: SubagentDescendantListEntry[] = []
|
|
89
|
+
.map(entry => ({ entry, parentId: rootSessionId, depth: 1 }))
|
|
90
|
+
.reverse()
|
|
91
|
+
const visited = new Set<SessionId>([rootSessionId])
|
|
92
|
+
const result: SubagentDescendantListEntry[] = []
|
|
93
93
|
for (let position = stack.pop(); position !== undefined; position = stack.pop()) {
|
|
94
|
-
const { entry, parentId, depth } = position
|
|
95
|
-
if (visited.has(entry.id)) continue
|
|
96
|
-
visited.add(entry.id)
|
|
97
|
-
let children: SubagentCatalogEntry[]
|
|
94
|
+
const { entry, parentId, depth } = position
|
|
95
|
+
if (visited.has(entry.id)) continue
|
|
96
|
+
visited.add(entry.id)
|
|
97
|
+
let children: SubagentCatalogEntry[]
|
|
98
98
|
try {
|
|
99
|
-
children = entry.mode ===
|
|
99
|
+
children = entry.mode === 'external' ? [] : await readChildren(entry.id)
|
|
100
100
|
} catch (error) {
|
|
101
|
-
if (error instanceof SubagentError) throw error
|
|
102
|
-
const code = error instanceof Error &&
|
|
101
|
+
if (error instanceof SubagentError) throw error
|
|
102
|
+
const code = error instanceof Error && 'code' in error ? error.code : undefined
|
|
103
103
|
result.push({
|
|
104
|
-
kind:
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
code === "SESSION_QUERY_CORRUPT_SESSION" || code === "SESSION_QUERY_SOURCE_CONFLICT"
|
|
110
|
-
? "corrupt"
|
|
111
|
-
: "unavailable",
|
|
112
|
-
});
|
|
113
|
-
continue;
|
|
104
|
+
kind: 'diagnostic', id: entry.id, parentId, depth,
|
|
105
|
+
reason: code === 'SESSION_QUERY_CORRUPT_SESSION' || code === 'SESSION_QUERY_SOURCE_CONFLICT'
|
|
106
|
+
? 'corrupt' : 'unavailable',
|
|
107
|
+
})
|
|
108
|
+
continue
|
|
114
109
|
}
|
|
115
|
-
if (entry.mode ===
|
|
116
|
-
result.push({ kind:
|
|
110
|
+
if (entry.mode === 'unknown') {
|
|
111
|
+
result.push({ kind: 'diagnostic', id: entry.id, parentId, depth, reason: 'unsupported' })
|
|
117
112
|
} else {
|
|
118
|
-
const { createdAt: _createdAt, ...identity } = entry
|
|
113
|
+
const { createdAt: _createdAt, ...identity } = entry
|
|
119
114
|
result.push({
|
|
120
|
-
...identity,
|
|
121
|
-
|
|
122
|
-
parentId,
|
|
123
|
-
depth,
|
|
124
|
-
activity: sessions.get(entry.id) === undefined ? "inactive" : "running",
|
|
115
|
+
...identity, kind: 'child', parentId, depth,
|
|
116
|
+
activity: sessions.get(entry.id) === undefined ? 'inactive' : 'running',
|
|
125
117
|
hasChildren: children.length > 0,
|
|
126
|
-
})
|
|
118
|
+
})
|
|
127
119
|
}
|
|
128
120
|
// Catalog event order defines siblings; the stack visits the first one next.
|
|
129
121
|
for (const child of [...children].reverse()) {
|
|
130
|
-
stack.push({ entry: child, parentId: entry.id, depth: depth + 1 })
|
|
122
|
+
stack.push({ entry: child, parentId: entry.id, depth: depth + 1 })
|
|
131
123
|
}
|
|
132
124
|
}
|
|
133
|
-
return result
|
|
125
|
+
return result
|
|
134
126
|
}
|
|
135
127
|
|
|
136
128
|
/** Stop the complete traversal when its caller cancels. */
|
|
137
129
|
function assertListingNotCancelled(signal: AbortSignal | undefined): void {
|
|
138
130
|
if (signal?.aborted) {
|
|
139
|
-
throw new SubagentError(
|
|
131
|
+
throw new SubagentError('subagent listing was cancelled', 'CANCELLED')
|
|
140
132
|
}
|
|
141
133
|
}
|