@morlay/dsh-subagent 0.0.10 → 0.0.11-alpha.0
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,124 +4,98 @@
|
|
|
4
4
|
* @module @deepseek-ai/dsh-subagent/catalog
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { z } from
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
chunkedListSchema,
|
|
11
|
-
iterateChunkedList,
|
|
12
|
-
} from "@deepseek-ai/dsh-chunked-list";
|
|
13
|
-
import type { ChunkedList } from "@deepseek-ai/dsh-chunked-list";
|
|
7
|
+
import { z } from 'zod'
|
|
8
|
+
import { appendChunkedList, chunkedListSchema, iterateChunkedList } from '@deepseek-ai/dsh-chunked-list'
|
|
9
|
+
import type { ChunkedList } from '@deepseek-ai/dsh-chunked-list'
|
|
14
10
|
import type {
|
|
15
11
|
Session,
|
|
16
12
|
SessionEvent,
|
|
17
13
|
SessionHeader,
|
|
18
14
|
SessionId,
|
|
19
15
|
SessionLogOffset,
|
|
20
|
-
} from
|
|
21
|
-
import type { ProjectionDefinition } from
|
|
22
|
-
import type { SubagentCatalogEntry } from
|
|
16
|
+
} from '@deepseek-ai/dsh-session'
|
|
17
|
+
import type { ProjectionDefinition } from '@deepseek-ai/dsh-session-projection'
|
|
18
|
+
import type { SubagentCatalogEntry } from './projection-types.ts'
|
|
23
19
|
|
|
24
20
|
/** Catalog payload version emitted by local child creation. */
|
|
25
|
-
export const SUBAGENT_CATALOG_VERSION = 0
|
|
21
|
+
export const SUBAGENT_CATALOG_VERSION = 0
|
|
26
22
|
|
|
27
23
|
type KnownCatalogMode =
|
|
28
|
-
| { readonly mode:
|
|
29
|
-
| { readonly mode:
|
|
24
|
+
| { readonly mode: 'one-shot'; readonly label?: string }
|
|
25
|
+
| { readonly mode: 'continuable'; readonly label: string }
|
|
30
26
|
|
|
31
27
|
/** Parent catalog v0 records local modes, v1 adds unknown children, and v2 records external executions. */
|
|
32
|
-
export type SubagentCatalogEvent =
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
| { readonly version: 2; readonly mode: "external"; readonly label?: string }
|
|
42
|
-
);
|
|
28
|
+
export type SubagentCatalogEvent =
|
|
29
|
+
& {
|
|
30
|
+
readonly childId: SessionId
|
|
31
|
+
readonly childCreatedAt: number
|
|
32
|
+
} & (
|
|
33
|
+
| ({ readonly version: 0 } & KnownCatalogMode)
|
|
34
|
+
| ({ readonly version: 1 } & (KnownCatalogMode | { readonly mode: 'unknown'; readonly label?: string }))
|
|
35
|
+
| { readonly version: 2; readonly mode: 'external'; readonly label?: string }
|
|
36
|
+
)
|
|
43
37
|
|
|
44
|
-
declare module
|
|
38
|
+
declare module '@deepseek-ai/dsh-session/types' {
|
|
45
39
|
interface SessionEventMap {
|
|
46
40
|
/**
|
|
47
41
|
* A direct child's identity and available discovery fields.
|
|
48
42
|
* @param data - versioned parent-owned catalog entry.
|
|
49
43
|
*/
|
|
50
|
-
|
|
44
|
+
'subagent/catalog': SubagentCatalogEvent
|
|
51
45
|
}
|
|
52
46
|
}
|
|
53
47
|
|
|
54
48
|
/** Host fold state for one parent catalog. */
|
|
55
49
|
export interface SubagentCatalogState {
|
|
56
|
-
readonly inheritedEventCount: SessionLogOffset
|
|
57
|
-
readonly head?: ChunkedList<SubagentCatalogEvent> | undefined
|
|
50
|
+
readonly inheritedEventCount: SessionLogOffset
|
|
51
|
+
readonly head?: ChunkedList<SubagentCatalogEvent> | undefined
|
|
58
52
|
}
|
|
59
53
|
|
|
60
|
-
const sessionIdSchema = z.string() as unknown as z.ZodType<SessionId
|
|
61
|
-
const oneShotCatalogSchema = z
|
|
62
|
-
.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
.
|
|
70
|
-
|
|
71
|
-
.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
})
|
|
78
|
-
.strict();
|
|
79
|
-
const externalCatalogSchema = oneShotCatalogSchema.extend({
|
|
80
|
-
version: z.literal(2),
|
|
81
|
-
mode: z.literal("external"),
|
|
82
|
-
});
|
|
83
|
-
const unknownCatalogSchema = oneShotCatalogSchema.extend({
|
|
84
|
-
version: z.literal(1),
|
|
85
|
-
mode: z.literal("unknown"),
|
|
86
|
-
});
|
|
54
|
+
const sessionIdSchema = z.string() as unknown as z.ZodType<SessionId>
|
|
55
|
+
const oneShotCatalogSchema = z.object({
|
|
56
|
+
version: z.union([z.literal(0), z.literal(1)]),
|
|
57
|
+
childId: sessionIdSchema,
|
|
58
|
+
childCreatedAt: z.number().int().nonnegative(),
|
|
59
|
+
mode: z.literal('one-shot'),
|
|
60
|
+
label: z.string().optional(),
|
|
61
|
+
}).strict()
|
|
62
|
+
const continuableCatalogSchema = z.object({
|
|
63
|
+
version: z.union([z.literal(0), z.literal(1)]),
|
|
64
|
+
childId: sessionIdSchema,
|
|
65
|
+
childCreatedAt: z.number().int().nonnegative(),
|
|
66
|
+
mode: z.literal('continuable'),
|
|
67
|
+
label: z.string(),
|
|
68
|
+
}).strict()
|
|
69
|
+
const externalCatalogSchema = oneShotCatalogSchema.extend({ version: z.literal(2), mode: z.literal('external') })
|
|
70
|
+
const unknownCatalogSchema = oneShotCatalogSchema.extend({ version: z.literal(1), mode: z.literal('unknown') })
|
|
87
71
|
const eventDataSchema = z.union([
|
|
88
72
|
oneShotCatalogSchema,
|
|
89
73
|
externalCatalogSchema,
|
|
90
74
|
continuableCatalogSchema,
|
|
91
75
|
unknownCatalogSchema,
|
|
92
|
-
]) as z.ZodType<SubagentCatalogEvent
|
|
93
|
-
const viewSchema = z.array(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
) as z.ZodType<
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
inheritedEventCount: z.number().int().nonnegative() as unknown as z.ZodType<SessionLogOffset>,
|
|
116
|
-
head: chunkedListSchema(eventDataSchema).optional(),
|
|
117
|
-
})
|
|
118
|
-
.strict();
|
|
119
|
-
|
|
120
|
-
declare module "@deepseek-ai/dsh-session-projection/types" {
|
|
121
|
-
interface SessionProjectionStateMap {
|
|
122
|
-
subagentCatalog: SubagentCatalogState;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
76
|
+
]) as z.ZodType<SubagentCatalogEvent>
|
|
77
|
+
const viewSchema = z.array(z.union([
|
|
78
|
+
oneShotCatalogSchema.omit({ version: true, childId: true, childCreatedAt: true }).extend({
|
|
79
|
+
id: sessionIdSchema,
|
|
80
|
+
createdAt: oneShotCatalogSchema.shape.childCreatedAt,
|
|
81
|
+
}),
|
|
82
|
+
externalCatalogSchema.omit({ version: true, childId: true, childCreatedAt: true }).extend({
|
|
83
|
+
id: sessionIdSchema,
|
|
84
|
+
createdAt: externalCatalogSchema.shape.childCreatedAt,
|
|
85
|
+
}),
|
|
86
|
+
continuableCatalogSchema.omit({ version: true, childId: true, childCreatedAt: true }).extend({
|
|
87
|
+
id: sessionIdSchema,
|
|
88
|
+
createdAt: continuableCatalogSchema.shape.childCreatedAt,
|
|
89
|
+
}),
|
|
90
|
+
unknownCatalogSchema.omit({ version: true, childId: true, childCreatedAt: true }).extend({
|
|
91
|
+
id: sessionIdSchema,
|
|
92
|
+
createdAt: unknownCatalogSchema.shape.childCreatedAt,
|
|
93
|
+
}),
|
|
94
|
+
])) as z.ZodType<SubagentCatalogEntry[]>
|
|
95
|
+
const stateSchema: z.ZodType<SubagentCatalogState> = z.object({
|
|
96
|
+
inheritedEventCount: z.number().int().nonnegative() as unknown as z.ZodType<SessionLogOffset>,
|
|
97
|
+
head: chunkedListSchema(eventDataSchema).optional(),
|
|
98
|
+
}).strict()
|
|
125
99
|
|
|
126
100
|
/**
|
|
127
101
|
* Materialize complete and unknown-mode child identities from parent catalog events.
|
|
@@ -129,28 +103,26 @@ declare module "@deepseek-ai/dsh-session-projection/types" {
|
|
|
129
103
|
* @returns current direct-child rows in parent catalog event order.
|
|
130
104
|
*/
|
|
131
105
|
function subagentCatalogEntries(state: SubagentCatalogState): SubagentCatalogEntry[] {
|
|
132
|
-
const entries: SubagentCatalogEntry[] = []
|
|
106
|
+
const entries: SubagentCatalogEntry[] = []
|
|
133
107
|
for (const data of iterateChunkedList(state.head)) {
|
|
134
|
-
const { version: _version, childId, childCreatedAt, ...descriptor } = data
|
|
135
|
-
entries.push({ id: childId, createdAt: childCreatedAt, ...descriptor })
|
|
108
|
+
const { version: _version, childId, childCreatedAt, ...descriptor } = data
|
|
109
|
+
entries.push({ id: childId, createdAt: childCreatedAt, ...descriptor })
|
|
136
110
|
}
|
|
137
|
-
return entries
|
|
111
|
+
return entries
|
|
138
112
|
}
|
|
139
113
|
|
|
140
114
|
/** Parent-owned direct-child catalog projection; invalid own facts reject restoration. */
|
|
141
115
|
export const subagentCatalogProjectionDefinition = {
|
|
142
|
-
key:
|
|
116
|
+
key: 'subagentCatalog',
|
|
143
117
|
stateSchema,
|
|
144
|
-
init: (_header: SessionHeader, inheritedEventCount: SessionLogOffset) => ({
|
|
145
|
-
inheritedEventCount,
|
|
146
|
-
}),
|
|
118
|
+
init: (_header: SessionHeader, inheritedEventCount: SessionLogOffset) => ({ inheritedEventCount }),
|
|
147
119
|
apply: (state, event: SessionEvent) => {
|
|
148
|
-
if (event.type !==
|
|
149
|
-
return { ...state, head: appendChunkedList(state.head, eventDataSchema.parse(event.data)) }
|
|
120
|
+
if (event.type !== 'subagent/catalog' || event.seq < state.inheritedEventCount) return state
|
|
121
|
+
return { ...state, head: appendChunkedList(state.head, eventDataSchema.parse(event.data)) }
|
|
150
122
|
},
|
|
151
123
|
stateVersion: 6,
|
|
152
124
|
wire: { viewSchema, view: subagentCatalogEntries },
|
|
153
|
-
} satisfies ProjectionDefinition<
|
|
125
|
+
} satisfies ProjectionDefinition<'subagentCatalog', SubagentCatalogState>
|
|
154
126
|
|
|
155
127
|
/**
|
|
156
128
|
* Append a complete direct-child discovery fact to its parent Session.
|
|
@@ -161,19 +133,19 @@ export const subagentCatalogProjectionDefinition = {
|
|
|
161
133
|
export function establishCatalogChild(
|
|
162
134
|
parent: Session,
|
|
163
135
|
child: SessionHeader,
|
|
164
|
-
descriptor: { readonly mode:
|
|
136
|
+
descriptor: { readonly mode: 'continuable'; readonly label: string },
|
|
165
137
|
): void {
|
|
166
|
-
parent.append(
|
|
138
|
+
parent.append('subagent/catalog', {
|
|
167
139
|
version: SUBAGENT_CATALOG_VERSION,
|
|
168
140
|
childId: child.id,
|
|
169
141
|
childCreatedAt: child.createdAt,
|
|
170
142
|
mode: descriptor.mode,
|
|
171
143
|
label: descriptor.label,
|
|
172
|
-
})
|
|
144
|
+
})
|
|
173
145
|
}
|
|
174
146
|
|
|
175
147
|
/** Catalog payload version emitted by external execution creation. */
|
|
176
|
-
const EXTERNAL_SUBAGENT_CATALOG_VERSION = 2
|
|
148
|
+
const EXTERNAL_SUBAGENT_CATALOG_VERSION = 2
|
|
177
149
|
|
|
178
150
|
/**
|
|
179
151
|
* Record an external execution without a local child Session.
|
|
@@ -181,16 +153,12 @@ const EXTERNAL_SUBAGENT_CATALOG_VERSION = 2;
|
|
|
181
153
|
* @param childId - identity returned by the external provider.
|
|
182
154
|
* @param label - display label assigned by the caller.
|
|
183
155
|
*/
|
|
184
|
-
export function establishExternalCatalogChild(
|
|
185
|
-
parent
|
|
186
|
-
childId: SessionId,
|
|
187
|
-
label: string,
|
|
188
|
-
): void {
|
|
189
|
-
parent.append("subagent/catalog", {
|
|
156
|
+
export function establishExternalCatalogChild(parent: Session, childId: SessionId, label: string): void {
|
|
157
|
+
parent.append('subagent/catalog', {
|
|
190
158
|
version: EXTERNAL_SUBAGENT_CATALOG_VERSION,
|
|
191
159
|
childId,
|
|
192
160
|
childCreatedAt: Date.now(),
|
|
193
|
-
mode:
|
|
161
|
+
mode: 'external',
|
|
194
162
|
label,
|
|
195
|
-
})
|
|
163
|
+
})
|
|
196
164
|
}
|
|
@@ -6,36 +6,33 @@
|
|
|
6
6
|
* @module @deepseek-ai/dsh-subagent/child-agent
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import type { Context } from
|
|
10
|
-
import type { Agent, AgentOptions, CreateAgentOptions } from
|
|
11
|
-
import type { SandboxMode } from
|
|
12
|
-
import type { Session, SessionId } from
|
|
13
|
-
import type {} from
|
|
14
|
-
import type { ToolRestriction } from
|
|
9
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
10
|
+
import type { Agent, AgentOptions, CreateAgentOptions } from '@deepseek-ai/dsh-agent'
|
|
11
|
+
import type { SandboxMode } from '@deepseek-ai/dsh-sandbox'
|
|
12
|
+
import type { Session, SessionId } from '@deepseek-ai/dsh-session'
|
|
13
|
+
import type {} from '@deepseek-ai/dsh-system-prompt'
|
|
14
|
+
import type { ToolRestriction } from '@deepseek-ai/dsh-tools'
|
|
15
15
|
// Type-only: make `ctx.get('sandboxPolicy')`, `ctx.get('approval')`, and
|
|
16
16
|
// `ctx.get('permissionPresets')` resolve to their services when composed — delegation consumes them
|
|
17
17
|
// opportunistically (the documented `ctx.get` pattern), never as a hard dep —
|
|
18
18
|
// and merge the inherited permission session-event payloads.
|
|
19
|
-
import type {} from
|
|
20
|
-
import type {} from
|
|
21
|
-
import type {} from
|
|
19
|
+
import type {} from '@deepseek-ai/dsh-sandbox-policy'
|
|
20
|
+
import type {} from '@deepseek-ai/dsh-user-approval'
|
|
21
|
+
import type {} from '@deepseek-ai/dsh-permission-presets'
|
|
22
22
|
// Type-only: make `ctx.get('agentPresets')` resolve to the preset roster when
|
|
23
23
|
// composed — a child inherits its parent's composition opportunistically (the
|
|
24
24
|
// documented `ctx.get` pattern), never as a hard dep. A rosterless deployment
|
|
25
25
|
// keeps its model-facing rows on the host plane, where the child already sees
|
|
26
26
|
// them through the tool registry's global layer.
|
|
27
|
-
import type {} from
|
|
28
|
-
import { delegationDepthOf } from
|
|
29
|
-
import { SubagentError } from
|
|
27
|
+
import type {} from '@deepseek-ai/dsh-agent-preset-registry'
|
|
28
|
+
import { delegationDepthOf } from './depth.ts'
|
|
29
|
+
import { SubagentError } from './error.ts'
|
|
30
30
|
|
|
31
31
|
/** Thrown when starting a child would exceed the requested depth cap. */
|
|
32
32
|
export class SubagentDepthError extends Error {
|
|
33
|
-
constructor(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
) {
|
|
37
|
-
super(`subagent depth ${attemptedDepth} exceeds maxDepth ${maxDepth}`);
|
|
38
|
-
this.name = "SubagentDepthError";
|
|
33
|
+
constructor(public readonly attemptedDepth: number, public readonly maxDepth: number) {
|
|
34
|
+
super(`subagent depth ${attemptedDepth} exceeds maxDepth ${maxDepth}`)
|
|
35
|
+
this.name = 'SubagentDepthError'
|
|
39
36
|
}
|
|
40
37
|
}
|
|
41
38
|
|
|
@@ -50,14 +47,14 @@ export class SubagentDepthError extends Error {
|
|
|
50
47
|
* @throws {RangeError} when the resolved depth leaves the safe-integer range.
|
|
51
48
|
*/
|
|
52
49
|
export function resolveChildDepth(parent: Agent, maxDepth: number | undefined): number {
|
|
53
|
-
const childDepth = delegationDepthOf(parent) + 1
|
|
50
|
+
const childDepth = delegationDepthOf(parent) + 1
|
|
54
51
|
if (!Number.isSafeInteger(childDepth)) {
|
|
55
|
-
throw new RangeError(
|
|
52
|
+
throw new RangeError('subagent child depth exceeds the safe-integer range')
|
|
56
53
|
}
|
|
57
54
|
if (maxDepth !== undefined && childDepth > maxDepth) {
|
|
58
|
-
throw new SubagentDepthError(childDepth, maxDepth)
|
|
55
|
+
throw new SubagentDepthError(childDepth, maxDepth)
|
|
59
56
|
}
|
|
60
|
-
return childDepth
|
|
57
|
+
return childDepth
|
|
61
58
|
}
|
|
62
59
|
|
|
63
60
|
/**
|
|
@@ -69,22 +66,22 @@ export function resolveChildDepth(parent: Agent, maxDepth: number | undefined):
|
|
|
69
66
|
* @returns detached Agent options for child-option merging.
|
|
70
67
|
*/
|
|
71
68
|
export function parentAgentOptionsForDelegation(parent: Agent): AgentOptions {
|
|
72
|
-
const requestConfig = parent.session.requestHeader()?.config
|
|
73
|
-
if (requestConfig === undefined) return { ...parent.options }
|
|
69
|
+
const requestConfig = parent.session.requestHeader()?.config
|
|
70
|
+
if (requestConfig === undefined) return { ...parent.options }
|
|
74
71
|
const {
|
|
75
72
|
provider: _createdProvider,
|
|
76
73
|
model: _createdModel,
|
|
77
74
|
reasoningEffort: _createdReasoningEffort,
|
|
78
75
|
...createdOptions
|
|
79
|
-
} = parent.options
|
|
76
|
+
} = parent.options
|
|
80
77
|
return {
|
|
81
78
|
...createdOptions,
|
|
82
79
|
provider: requestConfig.provider,
|
|
83
80
|
model: requestConfig.model,
|
|
84
|
-
...
|
|
81
|
+
...requestConfig.reasoningEffort === undefined
|
|
85
82
|
? {}
|
|
86
|
-
: { reasoningEffort: requestConfig.reasoningEffort }
|
|
87
|
-
}
|
|
83
|
+
: { reasoningEffort: requestConfig.reasoningEffort },
|
|
84
|
+
}
|
|
88
85
|
}
|
|
89
86
|
|
|
90
87
|
/**
|
|
@@ -103,22 +100,22 @@ export function resolveChildAgentOptions(
|
|
|
103
100
|
requested: AgentOptions | undefined,
|
|
104
101
|
childDepth: number,
|
|
105
102
|
): AgentOptions {
|
|
106
|
-
const parentOptions = parentAgentOptionsForDelegation(parent)
|
|
107
|
-
const parentProvider = parentOptions.provider
|
|
108
|
-
const parentModel = parentOptions.model
|
|
109
|
-
const parentReasoningEffort = parentOptions.reasoningEffort
|
|
110
|
-
const parentMaxTokens = parentOptions.maxTokens
|
|
103
|
+
const parentOptions = parentAgentOptionsForDelegation(parent)
|
|
104
|
+
const parentProvider = parentOptions.provider
|
|
105
|
+
const parentModel = parentOptions.model
|
|
106
|
+
const parentReasoningEffort = parentOptions.reasoningEffort
|
|
107
|
+
const parentMaxTokens = parentOptions.maxTokens
|
|
111
108
|
const resolved: AgentOptions = {
|
|
112
|
-
...
|
|
113
|
-
...
|
|
114
|
-
...
|
|
115
|
-
...
|
|
109
|
+
...parentProvider !== undefined ? { provider: parentProvider } : {},
|
|
110
|
+
...parentModel !== undefined ? { model: parentModel } : {},
|
|
111
|
+
...parentReasoningEffort !== undefined ? { reasoningEffort: parentReasoningEffort } : {},
|
|
112
|
+
...parentMaxTokens !== undefined ? { maxTokens: parentMaxTokens } : {},
|
|
116
113
|
...requested,
|
|
117
114
|
subagentDepth: childDepth,
|
|
118
|
-
}
|
|
119
|
-
const routeChanged = resolved.provider !== parentProvider || resolved.model !== parentModel
|
|
120
|
-
if (routeChanged && requested?.reasoningEffort === undefined) delete resolved.reasoningEffort
|
|
121
|
-
return resolved
|
|
115
|
+
}
|
|
116
|
+
const routeChanged = resolved.provider !== parentProvider || resolved.model !== parentModel
|
|
117
|
+
if (routeChanged && requested?.reasoningEffort === undefined) delete resolved.reasoningEffort
|
|
118
|
+
return resolved
|
|
122
119
|
}
|
|
123
120
|
|
|
124
121
|
/**
|
|
@@ -140,30 +137,30 @@ export function childSessionMeta(
|
|
|
140
137
|
childDepth: number,
|
|
141
138
|
isSeeded: boolean,
|
|
142
139
|
selectedPreset?: string,
|
|
143
|
-
): NonNullable<CreateAgentOptions[
|
|
144
|
-
const parentHeader = parent.session.header
|
|
145
|
-
const agentPreset = selectedPreset ?? parent.ctx.get(
|
|
140
|
+
): NonNullable<CreateAgentOptions['meta']> {
|
|
141
|
+
const parentHeader = parent.session.header
|
|
142
|
+
const agentPreset = selectedPreset ?? parent.ctx.get('agentPresets')?.composedPreset(parent.ctx)
|
|
146
143
|
return {
|
|
147
|
-
...
|
|
148
|
-
...
|
|
144
|
+
...parentHeader.cwd !== undefined ? { cwd: parentHeader.cwd } : {},
|
|
145
|
+
...agentPreset === undefined ? {} : { agentPreset },
|
|
149
146
|
parentSession: parentHeader.id,
|
|
150
147
|
isSeeded,
|
|
151
148
|
// Navigation classification only; the descriptor remains the authority
|
|
152
149
|
// for mode and continuation capability.
|
|
153
|
-
origin:
|
|
150
|
+
origin: 'subagent',
|
|
154
151
|
// Durable: the recursion budget must survive persistence and resume.
|
|
155
152
|
delegationDepth: childDepth,
|
|
156
|
-
}
|
|
153
|
+
}
|
|
157
154
|
}
|
|
158
155
|
|
|
159
156
|
/** The scoped composition a child agent's creation window applies. */
|
|
160
157
|
export interface ChildComposition {
|
|
161
158
|
/** Independently mounted preset; omission shares the parent's standing generation. */
|
|
162
|
-
readonly agentPreset?: string | undefined
|
|
159
|
+
readonly agentPreset?: string | undefined
|
|
163
160
|
/** Historical descriptor persona reapplied only during cold resume. */
|
|
164
|
-
readonly persona?: string | undefined
|
|
161
|
+
readonly persona?: string | undefined
|
|
165
162
|
/** Historical descriptor tool restriction reapplied only during cold resume. */
|
|
166
|
-
readonly toolFilter?: ToolRestriction | undefined
|
|
163
|
+
readonly toolFilter?: ToolRestriction | undefined
|
|
167
164
|
}
|
|
168
165
|
|
|
169
166
|
/**
|
|
@@ -171,11 +168,11 @@ export interface ChildComposition {
|
|
|
171
168
|
* runtime-context contribution rather than a system-prompt section, so the
|
|
172
169
|
* deployment's system prompt stays uniform across parents and children.
|
|
173
170
|
*/
|
|
174
|
-
export const SUBAGENT_DELEGATION_CONTEXT
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
171
|
+
export const SUBAGENT_DELEGATION_CONTEXT
|
|
172
|
+
= 'You are a delegated subagent: your permission scope was fixed when you were started and cannot be '
|
|
173
|
+
+ 'widened from inside this session — operations that require approval are rejected automatically. '
|
|
174
|
+
+ 'When the task needs access beyond that scope, do not retry the denied operation; state the '
|
|
175
|
+
+ 'limitation in your reply so the delegating agent can handle it.'
|
|
179
176
|
|
|
180
177
|
/**
|
|
181
178
|
* Compose a child before publication and restore historical descriptor overrides.
|
|
@@ -192,35 +189,32 @@ export function applyChildComposition(
|
|
|
192
189
|
composition: ChildComposition,
|
|
193
190
|
): void | Promise<void> {
|
|
194
191
|
if (composition.agentPreset !== undefined) {
|
|
195
|
-
const presets = childCtx.get(
|
|
192
|
+
const presets = childCtx.get('agentPresets')
|
|
196
193
|
if (presets === undefined) {
|
|
197
|
-
throw new SubagentError(
|
|
198
|
-
"selecting a child agent preset requires the agent-presets service",
|
|
199
|
-
"PRESET_UNAVAILABLE",
|
|
200
|
-
);
|
|
194
|
+
throw new SubagentError('selecting a child agent preset requires the agent-presets service', 'PRESET_UNAVAILABLE')
|
|
201
195
|
}
|
|
202
196
|
return presets.mount(childCtx, composition.agentPreset).then(() => {
|
|
203
|
-
applyChildOverrides(childCtx, composition)
|
|
204
|
-
})
|
|
197
|
+
applyChildOverrides(childCtx, composition)
|
|
198
|
+
})
|
|
205
199
|
}
|
|
206
|
-
childCtx.get(
|
|
207
|
-
applyChildOverrides(childCtx, composition)
|
|
200
|
+
childCtx.get('agentPresets')?.composeFrom(childCtx, parent.ctx)
|
|
201
|
+
applyChildOverrides(childCtx, composition)
|
|
208
202
|
}
|
|
209
203
|
|
|
210
204
|
function applyChildOverrides(childCtx: Context, composition: ChildComposition): void {
|
|
211
205
|
childCtx.systemPrompt.context({
|
|
212
|
-
name:
|
|
213
|
-
order: childCtx.systemPrompt.getContextOrder(
|
|
206
|
+
name: 'subagent:delegation',
|
|
207
|
+
order: childCtx.systemPrompt.getContextOrder('SUBAGENT_DELEGATION'),
|
|
214
208
|
text: SUBAGENT_DELEGATION_CONTEXT,
|
|
215
|
-
})
|
|
209
|
+
})
|
|
216
210
|
if (composition.persona !== undefined) {
|
|
217
211
|
childCtx.systemPrompt.section({
|
|
218
|
-
name:
|
|
219
|
-
order: childCtx.systemPrompt.getSectionOrder(
|
|
212
|
+
name: 'deployment:persona-prefix',
|
|
213
|
+
order: childCtx.systemPrompt.getSectionOrder('DEPLOYMENT_PERSONA_PREFIX'),
|
|
220
214
|
text: composition.persona,
|
|
221
|
-
})
|
|
215
|
+
})
|
|
222
216
|
}
|
|
223
|
-
if (composition.toolFilter !== undefined) childCtx.tools.restrict(composition.toolFilter)
|
|
217
|
+
if (composition.toolFilter !== undefined) childCtx.tools.restrict(composition.toolFilter)
|
|
224
218
|
}
|
|
225
219
|
|
|
226
220
|
/** Policy seeded onto a child session's log at the delegation boundary. */
|
|
@@ -229,15 +223,15 @@ export interface DelegatedPolicyOverrides {
|
|
|
229
223
|
* The parent's current preset identity when it runs in Auto or Full access;
|
|
230
224
|
* the child keeps it under the pinned `never` approval policy.
|
|
231
225
|
*/
|
|
232
|
-
readonly permissionPreset:
|
|
226
|
+
readonly permissionPreset: 'auto' | 'danger-full-access' | undefined
|
|
233
227
|
/** The parent session's explicit sandbox-mode override, or `undefined` without one. */
|
|
234
|
-
readonly sandboxMode: SandboxMode | undefined
|
|
228
|
+
readonly sandboxMode: SandboxMode | undefined
|
|
235
229
|
/**
|
|
236
230
|
* `'never'` whenever the approval capability is composed, `undefined`
|
|
237
231
|
* otherwise: a delegated child acts only within the sandbox scope fixed at
|
|
238
232
|
* delegation, so its asks are rejected deterministically.
|
|
239
233
|
*/
|
|
240
|
-
readonly approvalPolicy:
|
|
234
|
+
readonly approvalPolicy: 'never' | undefined
|
|
241
235
|
}
|
|
242
236
|
|
|
243
237
|
/**
|
|
@@ -252,21 +246,21 @@ export interface DelegatedPolicyOverrides {
|
|
|
252
246
|
* @returns the sandbox override (or `undefined` without one) and the approval pin.
|
|
253
247
|
*/
|
|
254
248
|
export function captureDelegatedPolicyOverrides(parent: Agent): DelegatedPolicyOverrides {
|
|
255
|
-
const preset = parent.ctx.get(
|
|
249
|
+
const preset = parent.ctx.get('permissionPresets')?.current(parent.session)
|
|
256
250
|
return {
|
|
257
|
-
permissionPreset: preset ===
|
|
258
|
-
sandboxMode: parent.ctx.get(
|
|
259
|
-
approvalPolicy: parent.ctx.get(
|
|
260
|
-
}
|
|
251
|
+
permissionPreset: preset === 'auto' || preset === 'danger-full-access' ? preset : undefined,
|
|
252
|
+
sandboxMode: parent.ctx.get('sandboxPolicy')?.overrideOf(parent.session),
|
|
253
|
+
approvalPolicy: parent.ctx.get('approval') === undefined ? undefined : 'never',
|
|
254
|
+
}
|
|
261
255
|
}
|
|
262
256
|
|
|
263
257
|
/**
|
|
264
258
|
* Append the captured delegation policy onto the child's own log as
|
|
265
|
-
* `source: 'delegation'` events
|
|
259
|
+
* `source: 'delegation'` events after Session announcement and before Agent registration, so the
|
|
266
260
|
* child's effective policy is reconstructable from its log alone. Appends land
|
|
267
261
|
* after any fork seed, so fresh policy wins stale seed state; later child
|
|
268
262
|
* switches still win over these events.
|
|
269
|
-
* @param childSession - the
|
|
263
|
+
* @param childSession - the child's announced, writable Session.
|
|
270
264
|
* @param overrides - the policy captured at delegation.
|
|
271
265
|
*/
|
|
272
266
|
export function appendDelegatedPolicyOverrides(
|
|
@@ -274,27 +268,24 @@ export function appendDelegatedPolicyOverrides(
|
|
|
274
268
|
overrides: DelegatedPolicyOverrides,
|
|
275
269
|
): void {
|
|
276
270
|
if (overrides.sandboxMode !== undefined) {
|
|
277
|
-
childSession.append(
|
|
271
|
+
childSession.append('sandbox/mode', { mode: overrides.sandboxMode, source: 'delegation' })
|
|
278
272
|
}
|
|
279
273
|
if (overrides.approvalPolicy !== undefined) {
|
|
280
|
-
childSession.append(
|
|
281
|
-
policy: overrides.approvalPolicy,
|
|
282
|
-
source: "delegation",
|
|
283
|
-
});
|
|
274
|
+
childSession.append('approval/policy', { policy: overrides.approvalPolicy, source: 'delegation' })
|
|
284
275
|
}
|
|
285
276
|
if (overrides.permissionPreset !== undefined) {
|
|
286
|
-
childSession.append(
|
|
277
|
+
childSession.append('permission/preset', { preset: overrides.permissionPreset })
|
|
287
278
|
}
|
|
288
279
|
}
|
|
289
280
|
|
|
290
281
|
/** Identity and lineage inputs shared by every in-process child creation. */
|
|
291
282
|
export interface ChildCreateInputs {
|
|
292
283
|
/** The child's reserved session id. */
|
|
293
|
-
readonly sessionId: SessionId
|
|
284
|
+
readonly sessionId: SessionId
|
|
294
285
|
/** The delegating parent agent. */
|
|
295
|
-
readonly parent: Agent
|
|
286
|
+
readonly parent: Agent
|
|
296
287
|
/** The resolved delegation depth. */
|
|
297
|
-
readonly childDepth: number
|
|
288
|
+
readonly childDepth: number
|
|
298
289
|
/** How many leading seed events came from the parent's log. */
|
|
299
|
-
readonly lineageSeedLength: number
|
|
290
|
+
readonly lineageSeedLength: number
|
|
300
291
|
}
|