@oai404iao/pi-subagent 0.2.0 → 0.4.0-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/README.md +266 -75
- package/agents/worker.md +1 -1
- package/config.example.json +4 -1
- package/config.schema.json +29 -4
- package/package.json +9 -6
- package/src/agent-state.ts +125 -0
- package/src/agent-sync.ts +64 -53
- package/src/agents.ts +3 -22
- package/src/catalog.ts +59 -7
- package/src/completion-mailbox.ts +656 -0
- package/src/config.ts +57 -6
- package/src/coordinator.ts +2476 -205
- package/src/descriptor.ts +118 -12
- package/src/index.ts +177 -27
- package/src/mailbox.ts +451 -0
- package/src/providers.ts +223 -28
- package/src/render.ts +25 -8
- package/src/scheduler.ts +173 -0
- package/src/schemas.ts +114 -11
- package/src/task-path.ts +188 -0
- package/src/types.ts +74 -15
package/src/schemas.ts
CHANGED
|
@@ -17,6 +17,15 @@ function agentNameParameter(agentNames?: readonly string[]) {
|
|
|
17
17
|
function delegationFields(agentNames?: readonly string[]) {
|
|
18
18
|
return {
|
|
19
19
|
agent: agentNameParameter(agentNames),
|
|
20
|
+
task_name: Type.Optional(
|
|
21
|
+
Type.String({
|
|
22
|
+
description:
|
|
23
|
+
"Stable readable child path segment; lowercase letters, digits, hyphens, and underscores",
|
|
24
|
+
pattern: "^[a-z0-9][a-z0-9_-]{0,63}$",
|
|
25
|
+
minLength: 1,
|
|
26
|
+
maxLength: 64,
|
|
27
|
+
}),
|
|
28
|
+
),
|
|
20
29
|
description: Type.String({
|
|
21
30
|
description: "Short 3-5 word display label for the delegated task",
|
|
22
31
|
minLength: 1,
|
|
@@ -29,6 +38,27 @@ function delegationFields(agentNames?: readonly string[]) {
|
|
|
29
38
|
};
|
|
30
39
|
}
|
|
31
40
|
|
|
41
|
+
const ContextParameters = Type.Object(
|
|
42
|
+
{
|
|
43
|
+
mode: StringEnum(
|
|
44
|
+
["fresh", "all_completed", "last_n_completed"] as const,
|
|
45
|
+
{
|
|
46
|
+
description:
|
|
47
|
+
"Parent context inherited once when the child is created",
|
|
48
|
+
},
|
|
49
|
+
),
|
|
50
|
+
completed_turns: Type.Optional(
|
|
51
|
+
Type.Integer({
|
|
52
|
+
description:
|
|
53
|
+
"Number of completed parent turns for last_n_completed",
|
|
54
|
+
minimum: 1,
|
|
55
|
+
maximum: 100,
|
|
56
|
+
}),
|
|
57
|
+
),
|
|
58
|
+
},
|
|
59
|
+
{ additionalProperties: false },
|
|
60
|
+
);
|
|
61
|
+
|
|
32
62
|
function forkDelegationFields(agentNames?: readonly string[]) {
|
|
33
63
|
return {
|
|
34
64
|
...delegationFields(agentNames),
|
|
@@ -45,10 +75,14 @@ function createDelegationParameters(
|
|
|
45
75
|
agentNames?: readonly string[],
|
|
46
76
|
) {
|
|
47
77
|
const fields = delegationFields(agentNames);
|
|
78
|
+
const contextualFields = {
|
|
79
|
+
...fields,
|
|
80
|
+
context: Type.Optional(ContextParameters),
|
|
81
|
+
};
|
|
48
82
|
return Type.Object(
|
|
49
83
|
enableRunInBackground
|
|
50
84
|
? {
|
|
51
|
-
...
|
|
85
|
+
...contextualFields,
|
|
52
86
|
run_in_background: Type.Optional(
|
|
53
87
|
Type.Boolean({
|
|
54
88
|
description:
|
|
@@ -56,7 +90,7 @@ function createDelegationParameters(
|
|
|
56
90
|
}),
|
|
57
91
|
),
|
|
58
92
|
}
|
|
59
|
-
:
|
|
93
|
+
: contextualFields,
|
|
60
94
|
{ additionalProperties: false },
|
|
61
95
|
);
|
|
62
96
|
}
|
|
@@ -75,19 +109,56 @@ export function delegationParameters(
|
|
|
75
109
|
return createDelegationParameters(enableRunInBackground, agentNames);
|
|
76
110
|
}
|
|
77
111
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
)
|
|
112
|
+
function createForkDelegationParameters(
|
|
113
|
+
enableRunInBackground: boolean,
|
|
114
|
+
agentNames?: readonly string[],
|
|
115
|
+
) {
|
|
116
|
+
const fields = forkDelegationFields(agentNames);
|
|
117
|
+
return Type.Object(
|
|
118
|
+
enableRunInBackground
|
|
119
|
+
? {
|
|
120
|
+
...fields,
|
|
121
|
+
run_in_background: Type.Optional(
|
|
122
|
+
Type.Boolean({
|
|
123
|
+
description:
|
|
124
|
+
"Run as a continuable inherited-context background child. Fork remains foreground by default.",
|
|
125
|
+
}),
|
|
126
|
+
),
|
|
127
|
+
}
|
|
128
|
+
: fields,
|
|
129
|
+
{ additionalProperties: false },
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export const ForegroundForkDelegationParameters =
|
|
134
|
+
createForkDelegationParameters(false);
|
|
135
|
+
|
|
136
|
+
export const ForkDelegationParameters =
|
|
137
|
+
createForkDelegationParameters(true);
|
|
82
138
|
|
|
83
|
-
export function forkDelegationParameters(
|
|
84
|
-
|
|
85
|
-
|
|
139
|
+
export function forkDelegationParameters(
|
|
140
|
+
agentNames?: readonly string[],
|
|
141
|
+
enableRunInBackground = true,
|
|
142
|
+
) {
|
|
143
|
+
if (agentNames === undefined) {
|
|
144
|
+
return enableRunInBackground
|
|
145
|
+
? ForkDelegationParameters
|
|
146
|
+
: ForegroundForkDelegationParameters;
|
|
147
|
+
}
|
|
148
|
+
return createForkDelegationParameters(
|
|
149
|
+
enableRunInBackground,
|
|
150
|
+
agentNames,
|
|
151
|
+
);
|
|
86
152
|
}
|
|
87
153
|
|
|
88
154
|
export const SendMessageParameters = Type.Object(
|
|
89
155
|
{
|
|
90
|
-
subagent_id: Type.String({
|
|
156
|
+
subagent_id: Type.String({
|
|
157
|
+
description:
|
|
158
|
+
"Readable absolute/relative task path or durable id of a direct continuable child",
|
|
159
|
+
minLength: 1,
|
|
160
|
+
maxLength: 4096,
|
|
161
|
+
}),
|
|
91
162
|
message: Type.String({
|
|
92
163
|
description: "Message to enqueue as the child's next FIFO turn",
|
|
93
164
|
minLength: 1,
|
|
@@ -96,11 +167,43 @@ export const SendMessageParameters = Type.Object(
|
|
|
96
167
|
{ additionalProperties: false },
|
|
97
168
|
);
|
|
98
169
|
|
|
170
|
+
export const FollowupTaskParameters = Type.Object(
|
|
171
|
+
{
|
|
172
|
+
subagent_id: Type.String({
|
|
173
|
+
description:
|
|
174
|
+
"Readable absolute/relative task path or durable id of a direct mailbox-v2 continuable child",
|
|
175
|
+
minLength: 1,
|
|
176
|
+
maxLength: 4096,
|
|
177
|
+
}),
|
|
178
|
+
},
|
|
179
|
+
{ additionalProperties: false },
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
export const DEFAULT_WAIT_AGENT_TIMEOUT_MS = 30_000;
|
|
183
|
+
export const MAX_WAIT_AGENT_TIMEOUT_MS = 120_000;
|
|
184
|
+
|
|
185
|
+
export const WaitAgentParameters = Type.Object(
|
|
186
|
+
{
|
|
187
|
+
timeout_ms: Type.Optional(
|
|
188
|
+
Type.Integer({
|
|
189
|
+
description:
|
|
190
|
+
"Maximum event-driven wait in milliseconds before returning a timeout",
|
|
191
|
+
minimum: 0,
|
|
192
|
+
maximum: MAX_WAIT_AGENT_TIMEOUT_MS,
|
|
193
|
+
default: DEFAULT_WAIT_AGENT_TIMEOUT_MS,
|
|
194
|
+
}),
|
|
195
|
+
),
|
|
196
|
+
},
|
|
197
|
+
{ additionalProperties: false },
|
|
198
|
+
);
|
|
199
|
+
|
|
99
200
|
export const InterruptParameters = Type.Object(
|
|
100
201
|
{
|
|
101
202
|
agent_id: Type.String({
|
|
102
|
-
description:
|
|
203
|
+
description:
|
|
204
|
+
"Readable absolute/relative task path or durable id of a live descendant whose current turn should stop",
|
|
103
205
|
minLength: 1,
|
|
206
|
+
maxLength: 4096,
|
|
104
207
|
}),
|
|
105
208
|
},
|
|
106
209
|
{ additionalProperties: false },
|
package/src/task-path.ts
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
SubagentDescriptor,
|
|
3
|
+
SubagentTask,
|
|
4
|
+
} from "./types.ts";
|
|
5
|
+
|
|
6
|
+
export const ROOT_TASK_PATH = "/root";
|
|
7
|
+
export const LEGACY_TASK_NAMESPACE = ".legacy";
|
|
8
|
+
export const MAX_TASK_NAME_LENGTH = 64;
|
|
9
|
+
export const MAX_TASK_PATH_LENGTH = 4096;
|
|
10
|
+
|
|
11
|
+
const TASK_NAME_PATTERN = /^[a-z0-9][a-z0-9_-]{0,63}$/;
|
|
12
|
+
const AGENT_ID_PATTERN =
|
|
13
|
+
/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
14
|
+
|
|
15
|
+
function pathSegments(path: string): string[] {
|
|
16
|
+
if (path.length > MAX_TASK_PATH_LENGTH) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
`task path exceeds ${MAX_TASK_PATH_LENGTH} characters`,
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
if (!path.startsWith("/") || path.endsWith("/") || path.includes("//")) {
|
|
22
|
+
throw new Error(`task path must be a canonical absolute path under ${ROOT_TASK_PATH}`);
|
|
23
|
+
}
|
|
24
|
+
const segments = path.slice(1).split("/");
|
|
25
|
+
if (segments[0] !== "root") {
|
|
26
|
+
throw new Error(`task path must be rooted at ${ROOT_TASK_PATH}`);
|
|
27
|
+
}
|
|
28
|
+
return segments;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function validateTaskName(value: string): string {
|
|
32
|
+
if (!TASK_NAME_PATTERN.test(value)) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
"task_name must contain 1-64 lowercase ASCII letters, digits, hyphens, or underscores and start with a letter or digit",
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
if (value === "root" || value === LEGACY_TASK_NAMESPACE) {
|
|
38
|
+
throw new Error(`task_name "${value}" is reserved`);
|
|
39
|
+
}
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function validateTaskPath(path: string): string {
|
|
44
|
+
if (path === ROOT_TASK_PATH) return path;
|
|
45
|
+
const segments = pathSegments(path);
|
|
46
|
+
for (let index = 1; index < segments.length; index++) {
|
|
47
|
+
const segment = segments[index]!;
|
|
48
|
+
if (
|
|
49
|
+
index === 1
|
|
50
|
+
&& segment === LEGACY_TASK_NAMESPACE
|
|
51
|
+
) {
|
|
52
|
+
const legacyId = segments[index + 1];
|
|
53
|
+
if (!legacyId || !AGENT_ID_PATTERN.test(legacyId)) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`legacy task paths must use ${ROOT_TASK_PATH}/${LEGACY_TASK_NAMESPACE}/<agent-id>`,
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
index++;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
validateTaskName(segment);
|
|
62
|
+
}
|
|
63
|
+
return path;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function taskPath(parentPath: string, name: string): string {
|
|
67
|
+
validateTaskPath(parentPath);
|
|
68
|
+
validateTaskName(name);
|
|
69
|
+
const path = `${parentPath}/${name}`;
|
|
70
|
+
return validateTaskPath(path);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function legacyTaskPath(agentId: string): string {
|
|
74
|
+
if (!AGENT_ID_PATTERN.test(agentId)) {
|
|
75
|
+
throw new Error("legacy task path requires a UUIDv7 agent id");
|
|
76
|
+
}
|
|
77
|
+
return `${ROOT_TASK_PATH}/${LEGACY_TASK_NAMESPACE}/${agentId}`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function descriptorTaskPath(
|
|
81
|
+
descriptor: SubagentDescriptor,
|
|
82
|
+
): string {
|
|
83
|
+
return descriptor.version === 3
|
|
84
|
+
? descriptor.task.path
|
|
85
|
+
: legacyTaskPath(descriptor.agentId);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function descriptorTask(
|
|
89
|
+
descriptor: SubagentDescriptor,
|
|
90
|
+
): SubagentTask {
|
|
91
|
+
if (descriptor.version === 3) return { ...descriptor.task };
|
|
92
|
+
return {
|
|
93
|
+
name: descriptor.agentId,
|
|
94
|
+
path: legacyTaskPath(descriptor.agentId),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function validateDescriptorTask(task: SubagentTask): SubagentTask {
|
|
99
|
+
const name = validateTaskName(task.name);
|
|
100
|
+
const path = validateTaskPath(task.path);
|
|
101
|
+
if (path === ROOT_TASK_PATH || path.split("/").at(-1) !== name) {
|
|
102
|
+
throw new Error("task.path must end with task.name");
|
|
103
|
+
}
|
|
104
|
+
return { name, path };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function slugTaskName(value: string): string {
|
|
108
|
+
const normalized = value
|
|
109
|
+
.normalize("NFKD")
|
|
110
|
+
.replace(/\p{Mark}/gu, "")
|
|
111
|
+
.toLowerCase()
|
|
112
|
+
.replace(/[^a-z0-9_-]+/g, "-")
|
|
113
|
+
.replace(/[-_]{2,}/g, "-")
|
|
114
|
+
.replace(/^[-_]+|[-_]+$/g, "")
|
|
115
|
+
.slice(0, MAX_TASK_NAME_LENGTH)
|
|
116
|
+
.replace(/[-_]+$/g, "");
|
|
117
|
+
const candidate =
|
|
118
|
+
!normalized || normalized === "root" || normalized === LEGACY_TASK_NAMESPACE
|
|
119
|
+
? "task"
|
|
120
|
+
: normalized;
|
|
121
|
+
return validateTaskName(candidate);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function numberedTaskName(base: string, ordinal: number): string {
|
|
125
|
+
validateTaskName(base);
|
|
126
|
+
if (!Number.isSafeInteger(ordinal) || ordinal < 2) {
|
|
127
|
+
throw new Error("task name ordinal must be an integer of at least 2");
|
|
128
|
+
}
|
|
129
|
+
const suffix = `-${ordinal}`;
|
|
130
|
+
const prefix = base
|
|
131
|
+
.slice(0, MAX_TASK_NAME_LENGTH - suffix.length)
|
|
132
|
+
.replace(/[-_]+$/g, "");
|
|
133
|
+
return validateTaskName(`${prefix || "task"}${suffix}`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function resolveTaskPath(
|
|
137
|
+
basePath: string,
|
|
138
|
+
reference: string,
|
|
139
|
+
): string {
|
|
140
|
+
validateTaskPath(basePath);
|
|
141
|
+
if (!reference.trim() || reference !== reference.trim()) {
|
|
142
|
+
throw new Error("task path reference must be a non-empty trimmed string");
|
|
143
|
+
}
|
|
144
|
+
if (reference.length > MAX_TASK_PATH_LENGTH) {
|
|
145
|
+
throw new Error(
|
|
146
|
+
`task path reference exceeds ${MAX_TASK_PATH_LENGTH} characters`,
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
if (reference.includes("//") || (reference.length > 1 && reference.endsWith("/"))) {
|
|
150
|
+
throw new Error("task path reference contains an empty segment");
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const absolute = reference.startsWith("/");
|
|
154
|
+
const segments = absolute ? ["root"] : pathSegments(basePath);
|
|
155
|
+
const input = absolute ? reference.slice(1).split("/") : reference.split("/");
|
|
156
|
+
if (absolute && input.shift() !== "root") {
|
|
157
|
+
throw new Error(`absolute task paths must be rooted at ${ROOT_TASK_PATH}`);
|
|
158
|
+
}
|
|
159
|
+
for (const segment of input) {
|
|
160
|
+
if (!segment || segment === ".") continue;
|
|
161
|
+
if (segment === "..") {
|
|
162
|
+
if (segments.length === 1) {
|
|
163
|
+
throw new Error(`task path reference cannot escape ${ROOT_TASK_PATH}`);
|
|
164
|
+
}
|
|
165
|
+
segments.pop();
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (segment === LEGACY_TASK_NAMESPACE) {
|
|
169
|
+
segments.push(segment);
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
if (
|
|
173
|
+
segments.at(-1) === LEGACY_TASK_NAMESPACE
|
|
174
|
+
&& AGENT_ID_PATTERN.test(segment)
|
|
175
|
+
) {
|
|
176
|
+
segments.push(segment);
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
validateTaskName(segment);
|
|
180
|
+
segments.push(segment);
|
|
181
|
+
}
|
|
182
|
+
const resolved = `/${segments.join("/")}`;
|
|
183
|
+
return validateTaskPath(resolved);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function isAgentId(value: string): boolean {
|
|
187
|
+
return AGENT_ID_PATTERN.test(value);
|
|
188
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -2,20 +2,36 @@ import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
|
|
|
2
2
|
import type { Usage } from "@earendil-works/pi-ai";
|
|
3
3
|
|
|
4
4
|
export type AgentScope = "user" | "project" | "both";
|
|
5
|
-
|
|
5
|
+
/** Sources that runtime discovery is allowed to activate. */
|
|
6
|
+
export type AgentSource = "user" | "project";
|
|
7
|
+
/** `bundled` is retained only for reading descriptors written by older releases. */
|
|
8
|
+
export type AgentSnapshotSource = AgentSource | "bundled";
|
|
6
9
|
export type ReportDelivery = "wakeup" | "quiet";
|
|
10
|
+
export type BackgroundProtocol = "legacy" | "mailbox-v2";
|
|
7
11
|
export type SubagentMode = "one-shot" | "continuable";
|
|
8
12
|
export type SubagentProviderName = "spawn" | "fork";
|
|
9
13
|
export type SubagentStopReason = "completed" | "aborted" | "error" | "max-tokens";
|
|
14
|
+
export type ContextInheritance =
|
|
15
|
+
| { mode: "fresh" }
|
|
16
|
+
| { mode: "all_completed" }
|
|
17
|
+
| { mode: "last_n_completed"; completedTurns: number };
|
|
18
|
+
|
|
19
|
+
export interface SubagentTask {
|
|
20
|
+
name: string;
|
|
21
|
+
path: string;
|
|
22
|
+
}
|
|
10
23
|
|
|
11
24
|
export interface SubagentSettings {
|
|
12
25
|
agentScope: AgentScope;
|
|
13
|
-
syncBundledAgents: boolean;
|
|
14
26
|
maxDepth: number;
|
|
15
27
|
enableRunInBackground: boolean;
|
|
16
28
|
defaultBackground: boolean;
|
|
29
|
+
maxConcurrentBackgroundRuns: number;
|
|
30
|
+
maxIdleRuntimes: number;
|
|
31
|
+
backgroundProtocol?: BackgroundProtocol;
|
|
17
32
|
reportDelivery: ReportDelivery;
|
|
18
33
|
inheritExtensions: boolean;
|
|
34
|
+
openAIIdentity: boolean;
|
|
19
35
|
maxOutputBytes: number;
|
|
20
36
|
}
|
|
21
37
|
|
|
@@ -37,7 +53,7 @@ export interface AgentSnapshot {
|
|
|
37
53
|
model?: string;
|
|
38
54
|
thinking?: ThinkingLevel;
|
|
39
55
|
systemPrompt: string;
|
|
40
|
-
source:
|
|
56
|
+
source: AgentSnapshotSource;
|
|
41
57
|
}
|
|
42
58
|
|
|
43
59
|
export interface ResolvedModel {
|
|
@@ -47,21 +63,29 @@ export interface ResolvedModel {
|
|
|
47
63
|
|
|
48
64
|
export interface SubagentRuntimeSnapshot {
|
|
49
65
|
agentScope: AgentScope;
|
|
50
|
-
syncBundledAgents: boolean;
|
|
51
66
|
maxDepth: number;
|
|
52
67
|
enableRunInBackground: boolean;
|
|
53
68
|
defaultBackground: boolean;
|
|
69
|
+
maxConcurrentBackgroundRuns: number;
|
|
70
|
+
maxIdleRuntimes: number;
|
|
71
|
+
backgroundProtocol: BackgroundProtocol;
|
|
54
72
|
reportDelivery: ReportDelivery;
|
|
55
73
|
inheritExtensions: boolean;
|
|
74
|
+
openAIIdentity: boolean;
|
|
56
75
|
maxOutputBytes: number;
|
|
57
76
|
}
|
|
58
77
|
|
|
59
|
-
|
|
60
|
-
version: 1;
|
|
78
|
+
interface SubagentDescriptorBase {
|
|
61
79
|
mode: SubagentMode;
|
|
62
80
|
provider: SubagentProviderName;
|
|
63
81
|
label: string;
|
|
64
|
-
|
|
82
|
+
/** Durable pi-subagent control identity, independent of provider wire ids. */
|
|
83
|
+
agentId: string;
|
|
84
|
+
/** Durable control identity of the delegating pi-subagent. */
|
|
85
|
+
parentAgentId: string;
|
|
86
|
+
/** Pi session lookup key of the delegating agent; never used as a wire id. */
|
|
87
|
+
parentPiSessionId: string;
|
|
88
|
+
/** Path of the parent's session file at delegation time (attribute, not identity). */
|
|
65
89
|
parentSessionFile?: string;
|
|
66
90
|
depth: number;
|
|
67
91
|
cwd: string;
|
|
@@ -72,14 +96,32 @@ export interface SubagentDescriptor {
|
|
|
72
96
|
runtime: SubagentRuntimeSnapshot;
|
|
73
97
|
}
|
|
74
98
|
|
|
99
|
+
export interface SubagentDescriptorV2 extends SubagentDescriptorBase {
|
|
100
|
+
version: 2;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface SubagentDescriptorV3 extends SubagentDescriptorBase {
|
|
104
|
+
version: 3;
|
|
105
|
+
task: SubagentTask;
|
|
106
|
+
context: ContextInheritance;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export type SubagentDescriptor =
|
|
110
|
+
| SubagentDescriptorV2
|
|
111
|
+
| SubagentDescriptorV3;
|
|
112
|
+
|
|
75
113
|
export interface SubagentUsage extends Usage {
|
|
76
114
|
turns: number;
|
|
77
115
|
}
|
|
78
116
|
|
|
79
117
|
export interface SubagentRunResult {
|
|
80
|
-
|
|
118
|
+
agentId: string;
|
|
119
|
+
turnId: string;
|
|
120
|
+
piSessionId?: string;
|
|
81
121
|
sessionFile?: string;
|
|
82
122
|
output: string;
|
|
123
|
+
outputTruncated?: boolean;
|
|
124
|
+
omittedBytes?: number;
|
|
83
125
|
stopReason: SubagentStopReason;
|
|
84
126
|
usage: SubagentUsage;
|
|
85
127
|
}
|
|
@@ -92,9 +134,13 @@ export interface TraceItem {
|
|
|
92
134
|
|
|
93
135
|
export interface DelegationDetails {
|
|
94
136
|
kind: "delegation";
|
|
95
|
-
|
|
137
|
+
agentId: string;
|
|
138
|
+
taskPath: string;
|
|
139
|
+
turnId?: string;
|
|
140
|
+
piSessionId?: string;
|
|
96
141
|
provider: SubagentProviderName;
|
|
97
142
|
mode: SubagentMode;
|
|
143
|
+
context: ContextInheritance;
|
|
98
144
|
agent: string;
|
|
99
145
|
label: string;
|
|
100
146
|
depth: number;
|
|
@@ -108,23 +154,35 @@ export interface DelegationDetails {
|
|
|
108
154
|
|
|
109
155
|
export interface ControlDetails {
|
|
110
156
|
kind: "control";
|
|
111
|
-
action: "send" | "interrupt" | "list" | "report";
|
|
112
|
-
|
|
157
|
+
action: "send" | "followup" | "wait" | "interrupt" | "list" | "report";
|
|
158
|
+
agentId?: string;
|
|
159
|
+
taskPath?: string;
|
|
160
|
+
messageId?: string;
|
|
161
|
+
turnId?: string;
|
|
162
|
+
pendingMessages?: number;
|
|
163
|
+
claimedMessages?: number;
|
|
164
|
+
completionIds?: string[];
|
|
165
|
+
timedOut?: boolean;
|
|
166
|
+
unreadUpdates?: number;
|
|
113
167
|
}
|
|
114
168
|
|
|
115
169
|
export interface CatalogChild {
|
|
116
170
|
kind: "child";
|
|
117
|
-
|
|
118
|
-
|
|
171
|
+
agentId: string;
|
|
172
|
+
parentAgentId: string;
|
|
173
|
+
taskPath: string;
|
|
174
|
+
parentTaskPath: string;
|
|
119
175
|
depth: number;
|
|
120
176
|
descriptor: SubagentDescriptor;
|
|
121
177
|
sessionFile?: string;
|
|
122
178
|
status: "running" | "idle" | "ready";
|
|
179
|
+
pendingMessages: number;
|
|
180
|
+
unreadUpdates: number;
|
|
123
181
|
}
|
|
124
182
|
|
|
125
183
|
export interface CatalogDiagnostic {
|
|
126
184
|
kind: "diagnostic";
|
|
127
|
-
|
|
185
|
+
piSessionId: string;
|
|
128
186
|
reason: "corrupt" | "unavailable";
|
|
129
187
|
sessionFile?: string;
|
|
130
188
|
parentSessionFile?: string;
|
|
@@ -135,7 +193,8 @@ export type CatalogEntry = CatalogChild | CatalogDiagnostic;
|
|
|
135
193
|
|
|
136
194
|
export interface ParentMessageDetails {
|
|
137
195
|
kind: "report" | "settled";
|
|
138
|
-
|
|
196
|
+
childAgentId: string;
|
|
197
|
+
taskPath?: string;
|
|
139
198
|
label: string;
|
|
140
199
|
stopReason?: SubagentStopReason;
|
|
141
200
|
truncated?: boolean;
|