@pi-ohm/subagents 0.6.4-dev.25614589665.1.cd7b959 → 0.6.4-dev.25632661332.1.3bf351f
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/agent-controller.d.ts +76 -0
- package/dist/agent-controller.js +443 -0
- package/dist/config.d.ts +12 -2
- package/dist/config.js +39 -12
- package/dist/extension.d.ts +4 -3
- package/dist/extension.js +5 -2
- package/dist/schema.d.ts +12 -0
- package/dist/schema.js +45 -0
- package/package.json +6 -5
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { AgentToolResult, ExtensionAPI, ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { Api, Model, Static, Type } from "@earendil-works/pi-ai";
|
|
3
|
+
import { Result } from "better-result";
|
|
4
|
+
import { ThinkingLevel } from "@earendil-works/pi-agent-core";
|
|
5
|
+
|
|
6
|
+
//#region src/agent-controller.d.ts
|
|
7
|
+
declare const SpawnAgentArgsSchema: Type.TObject<{
|
|
8
|
+
task_name: Type.TString;
|
|
9
|
+
prompt: Type.TString;
|
|
10
|
+
summary: Type.TString;
|
|
11
|
+
agent_type: Type.TOptional<Type.TString>;
|
|
12
|
+
model: Type.TOptional<Type.TString>;
|
|
13
|
+
thinking: Type.TOptional<Type.TUnion<[Type.TLiteral<"off">, Type.TLiteral<"minimal">, Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">, Type.TLiteral<"xhigh">]>>;
|
|
14
|
+
max_turns: Type.TOptional<Type.TNumber>;
|
|
15
|
+
run_in_background: Type.TOptional<Type.TBoolean>;
|
|
16
|
+
fork_context: Type.TOptional<Type.TBoolean>;
|
|
17
|
+
}>;
|
|
18
|
+
declare const SendAgentInputArgsSchema: Type.TObject<{
|
|
19
|
+
target: Type.TString;
|
|
20
|
+
prompt: Type.TString;
|
|
21
|
+
mode: Type.TOptional<Type.TUnion<[Type.TLiteral<"prompt">, Type.TLiteral<"steer">, Type.TLiteral<"follow_up">]>>;
|
|
22
|
+
}>;
|
|
23
|
+
declare const WaitAgentArgsSchema: Type.TObject<{
|
|
24
|
+
targets: Type.TArray<Type.TString>;
|
|
25
|
+
timeout_ms: Type.TOptional<Type.TNumber>;
|
|
26
|
+
}>;
|
|
27
|
+
declare const CloseAgentArgsSchema: Type.TObject<{
|
|
28
|
+
target: Type.TString;
|
|
29
|
+
}>;
|
|
30
|
+
declare const ResumeAgentArgsSchema: Type.TObject<{
|
|
31
|
+
id: Type.TString;
|
|
32
|
+
}>;
|
|
33
|
+
declare const GetAgentResultArgsSchema: Type.TObject<{
|
|
34
|
+
target: Type.TString;
|
|
35
|
+
}>;
|
|
36
|
+
declare const ListAgentsArgsSchema: Type.TObject<{
|
|
37
|
+
path_prefix: Type.TOptional<Type.TString>;
|
|
38
|
+
}>;
|
|
39
|
+
type SpawnAgentArgs = Static<typeof SpawnAgentArgsSchema>;
|
|
40
|
+
type SendAgentInputArgs = Static<typeof SendAgentInputArgsSchema>;
|
|
41
|
+
type WaitAgentArgs = Static<typeof WaitAgentArgsSchema>;
|
|
42
|
+
type CloseAgentArgs = Static<typeof CloseAgentArgsSchema>;
|
|
43
|
+
type ResumeAgentArgs = Static<typeof ResumeAgentArgsSchema>;
|
|
44
|
+
type GetAgentResultArgs = Static<typeof GetAgentResultArgsSchema>;
|
|
45
|
+
type ListAgentsArgs = Static<typeof ListAgentsArgsSchema>;
|
|
46
|
+
interface ResolvedSpawnConfig {
|
|
47
|
+
readonly agentType: string;
|
|
48
|
+
readonly model: Model<Api>;
|
|
49
|
+
readonly modelKey: string;
|
|
50
|
+
readonly agentDir: string;
|
|
51
|
+
readonly thinking: ThinkingLevel;
|
|
52
|
+
readonly tools?: readonly string[];
|
|
53
|
+
readonly prompt: string;
|
|
54
|
+
}
|
|
55
|
+
declare function registerAgentControllerTool(pi: Pick<ExtensionAPI, "registerTool" | "appendEntry" | "getThinkingLevel" | "on">): void;
|
|
56
|
+
declare function createSubagentToolRuntime(pi: Pick<ExtensionAPI, "appendEntry" | "getThinkingLevel">): SubagentToolRuntime;
|
|
57
|
+
interface SubagentToolRuntime {
|
|
58
|
+
spawn(params: SpawnAgentArgs, ctx: ToolContext): Promise<AgentToolResult<unknown>>;
|
|
59
|
+
send(params: SendAgentInputArgs, ctx: ToolContext): Promise<AgentToolResult<unknown>>;
|
|
60
|
+
wait(params: WaitAgentArgs, ctx: ToolContext): Promise<AgentToolResult<unknown>>;
|
|
61
|
+
close(params: CloseAgentArgs, ctx: ToolContext): Promise<AgentToolResult<unknown>>;
|
|
62
|
+
resume(params: ResumeAgentArgs, ctx: ToolContext): Promise<AgentToolResult<unknown>>;
|
|
63
|
+
get(params: GetAgentResultArgs, ctx: ToolContext): Promise<AgentToolResult<unknown>>;
|
|
64
|
+
list(params: ListAgentsArgs, ctx: ToolContext): Promise<AgentToolResult<unknown>>;
|
|
65
|
+
dispose(): Promise<void>;
|
|
66
|
+
}
|
|
67
|
+
type ToolContext = Parameters<ToolDefinition["execute"]>[4];
|
|
68
|
+
declare function createSubagentTools(runtime: SubagentToolRuntime): readonly ToolDefinition[];
|
|
69
|
+
declare function resolveSpawnConfig(input: {
|
|
70
|
+
readonly cwd: string;
|
|
71
|
+
readonly params: SpawnAgentArgs;
|
|
72
|
+
readonly currentModel?: Model<Api>;
|
|
73
|
+
readonly currentThinking?: ThinkingLevel;
|
|
74
|
+
}): Promise<Result<ResolvedSpawnConfig, Error>>;
|
|
75
|
+
//#endregion
|
|
76
|
+
export { SubagentToolRuntime, createSubagentToolRuntime, createSubagentTools, registerAgentControllerTool, resolveSpawnConfig };
|
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
import { isSubagentRuntimeConfig, resolveSubagentProfileRuntimeConfig, subagentsConfigModule } from "./config.js";
|
|
2
|
+
import { AuthStorage, ModelRegistry, defineTool } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { Type, getModels, getProviders } from "@earendil-works/pi-ai";
|
|
5
|
+
import { Result } from "better-result";
|
|
6
|
+
import { PipController, createSdkPipRunner } from "@pi-ohm/core/pip";
|
|
7
|
+
import { loadConfig, pickConfig, resolveExtensionConfigDir } from "@pi-ohm/core/config";
|
|
8
|
+
|
|
9
|
+
//#region src/agent-controller.ts
|
|
10
|
+
const defaultModel = "openai-codex/gpt-5.4-mini:medium";
|
|
11
|
+
const ThinkingLevelSchema = Type.Union([
|
|
12
|
+
Type.Literal("off"),
|
|
13
|
+
Type.Literal("minimal"),
|
|
14
|
+
Type.Literal("low"),
|
|
15
|
+
Type.Literal("medium"),
|
|
16
|
+
Type.Literal("high"),
|
|
17
|
+
Type.Literal("xhigh")
|
|
18
|
+
]);
|
|
19
|
+
const SpawnAgentArgsSchema = Type.Object({
|
|
20
|
+
task_name: Type.String({ minLength: 1 }),
|
|
21
|
+
prompt: Type.String({ minLength: 1 }),
|
|
22
|
+
summary: Type.String({ minLength: 1 }),
|
|
23
|
+
agent_type: Type.Optional(Type.String({ minLength: 1 })),
|
|
24
|
+
model: Type.Optional(Type.String({ minLength: 1 })),
|
|
25
|
+
thinking: Type.Optional(ThinkingLevelSchema),
|
|
26
|
+
max_turns: Type.Optional(Type.Number()),
|
|
27
|
+
run_in_background: Type.Optional(Type.Boolean()),
|
|
28
|
+
fork_context: Type.Optional(Type.Boolean())
|
|
29
|
+
});
|
|
30
|
+
const SendAgentInputArgsSchema = Type.Object({
|
|
31
|
+
target: Type.String({ minLength: 1 }),
|
|
32
|
+
prompt: Type.String({ minLength: 1 }),
|
|
33
|
+
mode: Type.Optional(Type.Union([
|
|
34
|
+
Type.Literal("prompt"),
|
|
35
|
+
Type.Literal("steer"),
|
|
36
|
+
Type.Literal("follow_up")
|
|
37
|
+
]))
|
|
38
|
+
});
|
|
39
|
+
const WaitAgentArgsSchema = Type.Object({
|
|
40
|
+
targets: Type.Array(Type.String({ minLength: 1 })),
|
|
41
|
+
timeout_ms: Type.Optional(Type.Number())
|
|
42
|
+
});
|
|
43
|
+
const CloseAgentArgsSchema = Type.Object({ target: Type.String({ minLength: 1 }) });
|
|
44
|
+
const ResumeAgentArgsSchema = Type.Object({ id: Type.String({ minLength: 1 }) });
|
|
45
|
+
const GetAgentResultArgsSchema = Type.Object({ target: Type.String({ minLength: 1 }) });
|
|
46
|
+
const ListAgentsArgsSchema = Type.Object({ path_prefix: Type.Optional(Type.String()) });
|
|
47
|
+
function registerAgentControllerTool(pi) {
|
|
48
|
+
const runtime = createSubagentToolRuntime(pi);
|
|
49
|
+
for (const tool of createSubagentTools(runtime)) pi.registerTool(tool);
|
|
50
|
+
pi.on("session_shutdown", async () => {
|
|
51
|
+
await runtime.dispose();
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function createSubagentToolRuntime(pi) {
|
|
55
|
+
const controllers = new Map();
|
|
56
|
+
return {
|
|
57
|
+
async spawn(params, ctx) {
|
|
58
|
+
const parentSessionId = ctx.sessionManager.getSessionId();
|
|
59
|
+
const record = getRecord(controllers, parentSessionId);
|
|
60
|
+
const config = await resolveSpawnConfig({
|
|
61
|
+
cwd: ctx.cwd,
|
|
62
|
+
params,
|
|
63
|
+
currentModel: ctx.model,
|
|
64
|
+
currentThinking: pi.getThinkingLevel()
|
|
65
|
+
});
|
|
66
|
+
if (Result.isError(config)) return toolError(config.error.message);
|
|
67
|
+
const key = controllerKey(config.value);
|
|
68
|
+
const currentController = record.controllers.get(key);
|
|
69
|
+
const created = currentController ? Result.ok(currentController) : createPipController({
|
|
70
|
+
pi,
|
|
71
|
+
config: config.value
|
|
72
|
+
});
|
|
73
|
+
if (Result.isError(created)) return toolError(created.error.message);
|
|
74
|
+
const controller = created.value;
|
|
75
|
+
if (!currentController) record.controllers.set(key, controller);
|
|
76
|
+
if (ctx.hasUI) ctx.ui.notify(`subagent spawned: ${params.task_name}`, "info");
|
|
77
|
+
const spawned = await controller.spawn({
|
|
78
|
+
ownerPackage: "@pi-ohm/subagents",
|
|
79
|
+
role: config.value.agentType,
|
|
80
|
+
parentSessionId,
|
|
81
|
+
cwd: ctx.cwd,
|
|
82
|
+
prompt: config.value.prompt,
|
|
83
|
+
runInBackground: params.run_in_background ?? true,
|
|
84
|
+
parentSessionFile: params.fork_context ? ctx.sessionManager.getSessionFile() : undefined
|
|
85
|
+
});
|
|
86
|
+
if (Result.isError(spawned)) return toolError(spawned.error.message);
|
|
87
|
+
record.taskIds.set(params.task_name, spawned.value.pipId);
|
|
88
|
+
record.taskControllers.set(spawned.value.pipId, controller);
|
|
89
|
+
if (ctx.hasUI && spawned.value.status.state !== "running") {
|
|
90
|
+
ctx.ui.notify(`subagent finished: ${params.task_name} (${spawned.value.status.state})`, "info");
|
|
91
|
+
}
|
|
92
|
+
return toolOk({
|
|
93
|
+
task_name: params.task_name,
|
|
94
|
+
task_id: spawned.value.pipId,
|
|
95
|
+
nickname: null,
|
|
96
|
+
child_session_path: spawned.value.childSessionPath,
|
|
97
|
+
status: spawned.value.status
|
|
98
|
+
});
|
|
99
|
+
},
|
|
100
|
+
async send(params, ctx) {
|
|
101
|
+
const record = getRecord(controllers, ctx.sessionManager.getSessionId());
|
|
102
|
+
const pipId = resolveTarget(record, params.target);
|
|
103
|
+
const controller = resolveController(record, pipId);
|
|
104
|
+
if (!controller) return toolError(`Subagent '${params.target}' was not found`);
|
|
105
|
+
const sent = await controller.send({
|
|
106
|
+
pipId,
|
|
107
|
+
prompt: params.prompt,
|
|
108
|
+
mode: params.mode
|
|
109
|
+
});
|
|
110
|
+
if (Result.isError(sent)) return toolError(sent.error.message);
|
|
111
|
+
return toolOk(sent.value);
|
|
112
|
+
},
|
|
113
|
+
async wait(params, ctx) {
|
|
114
|
+
const record = getRecord(controllers, ctx.sessionManager.getSessionId());
|
|
115
|
+
const statuses = {};
|
|
116
|
+
for (const target of params.targets) {
|
|
117
|
+
const pipId = resolveTarget(record, target);
|
|
118
|
+
const controller = resolveController(record, pipId);
|
|
119
|
+
if (!controller) {
|
|
120
|
+
statuses[target] = { state: "not_found" };
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const waited = await controller.wait({
|
|
124
|
+
pipIds: [pipId],
|
|
125
|
+
timeoutMs: params.timeout_ms
|
|
126
|
+
});
|
|
127
|
+
if (Result.isError(waited)) return toolError(waited.error.message);
|
|
128
|
+
statuses[target] = waited.value.statuses[pipId] ?? { state: "not_found" };
|
|
129
|
+
}
|
|
130
|
+
return toolOk({
|
|
131
|
+
statuses,
|
|
132
|
+
timedOut: false
|
|
133
|
+
});
|
|
134
|
+
},
|
|
135
|
+
async close(params, ctx) {
|
|
136
|
+
const record = getRecord(controllers, ctx.sessionManager.getSessionId());
|
|
137
|
+
const pipId = resolveTarget(record, params.target);
|
|
138
|
+
const controller = resolveController(record, pipId);
|
|
139
|
+
if (!controller) return toolError(`Subagent '${params.target}' was not found`);
|
|
140
|
+
const closed = await controller.close({ pipId });
|
|
141
|
+
if (Result.isError(closed)) return toolError(closed.error.message);
|
|
142
|
+
if (ctx.hasUI) ctx.ui.notify(`subagent closed: ${params.target}`, "info");
|
|
143
|
+
return toolOk(closed.value);
|
|
144
|
+
},
|
|
145
|
+
async resume(params, ctx) {
|
|
146
|
+
const record = getRecord(controllers, ctx.sessionManager.getSessionId());
|
|
147
|
+
const pipId = resolveTarget(record, params.id);
|
|
148
|
+
const controller = resolveController(record, pipId);
|
|
149
|
+
if (!controller) return toolError(`Subagent '${params.id}' was not found`);
|
|
150
|
+
const resumed = await controller.resume({ pipId });
|
|
151
|
+
if (Result.isError(resumed)) return toolError(resumed.error.message);
|
|
152
|
+
return toolOk(resumed.value);
|
|
153
|
+
},
|
|
154
|
+
async get(params, ctx) {
|
|
155
|
+
const record = getRecord(controllers, ctx.sessionManager.getSessionId());
|
|
156
|
+
const pipId = resolveTarget(record, params.target);
|
|
157
|
+
const controller = resolveController(record, pipId);
|
|
158
|
+
if (!controller) return toolError(`Subagent '${params.target}' was not found`);
|
|
159
|
+
const found = await controller.get({ pipId });
|
|
160
|
+
if (Result.isError(found)) return toolError(found.error.message);
|
|
161
|
+
return toolOk({
|
|
162
|
+
target: params.target,
|
|
163
|
+
status: found.value.status,
|
|
164
|
+
result: statusResult(found.value.status),
|
|
165
|
+
session_path: found.value.childSessionPath
|
|
166
|
+
});
|
|
167
|
+
},
|
|
168
|
+
async list(params, ctx) {
|
|
169
|
+
const record = getRecord(controllers, ctx.sessionManager.getSessionId());
|
|
170
|
+
const agents = [];
|
|
171
|
+
for (const [agentName, pipId] of record.taskIds.entries()) {
|
|
172
|
+
if (params.path_prefix && !agentName.startsWith(params.path_prefix)) continue;
|
|
173
|
+
const controller = resolveController(record, pipId);
|
|
174
|
+
const found = controller ? await controller.get({ pipId }) : Result.ok(undefined);
|
|
175
|
+
const status = Result.isOk(found) && found.value ? found.value.status : { state: "not_found" };
|
|
176
|
+
agents.push({
|
|
177
|
+
agent_name: agentName,
|
|
178
|
+
agent_status: status,
|
|
179
|
+
task_id: pipId,
|
|
180
|
+
last_task_message: null
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
return toolOk({ agents });
|
|
184
|
+
},
|
|
185
|
+
async dispose() {
|
|
186
|
+
for (const record of controllers.values()) {
|
|
187
|
+
for (const [pipId, controller] of record.taskControllers.entries()) {
|
|
188
|
+
await controller.close({ pipId });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
controllers.clear();
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function createSubagentTools(runtime) {
|
|
196
|
+
return [
|
|
197
|
+
defineTool({
|
|
198
|
+
name: "spawn_agent",
|
|
199
|
+
label: "Spawn Agent",
|
|
200
|
+
description: "Spawn a Pi-backed subagent session and submit the initial prompt.",
|
|
201
|
+
parameters: SpawnAgentArgsSchema,
|
|
202
|
+
execute: async (_toolCallId, params, _signal, _onUpdate, ctx) => runtime.spawn(params, ctx)
|
|
203
|
+
}),
|
|
204
|
+
defineTool({
|
|
205
|
+
name: "send_agent_input",
|
|
206
|
+
label: "Send Agent Input",
|
|
207
|
+
description: "Send follow-up input to an existing subagent session.",
|
|
208
|
+
parameters: SendAgentInputArgsSchema,
|
|
209
|
+
execute: async (_toolCallId, params, _signal, _onUpdate, ctx) => runtime.send(params, ctx)
|
|
210
|
+
}),
|
|
211
|
+
defineTool({
|
|
212
|
+
name: "wait_agent",
|
|
213
|
+
label: "Wait Agent",
|
|
214
|
+
description: "Wait for one or more subagents and return their current statuses.",
|
|
215
|
+
parameters: WaitAgentArgsSchema,
|
|
216
|
+
execute: async (_toolCallId, params, _signal, _onUpdate, ctx) => runtime.wait(params, ctx)
|
|
217
|
+
}),
|
|
218
|
+
defineTool({
|
|
219
|
+
name: "close_agent",
|
|
220
|
+
label: "Close Agent",
|
|
221
|
+
description: "Close a subagent session.",
|
|
222
|
+
parameters: CloseAgentArgsSchema,
|
|
223
|
+
execute: async (_toolCallId, params, _signal, _onUpdate, ctx) => runtime.close(params, ctx)
|
|
224
|
+
}),
|
|
225
|
+
defineTool({
|
|
226
|
+
name: "resume_agent",
|
|
227
|
+
label: "Resume Agent",
|
|
228
|
+
description: "Resume a known subagent session in the current parent session runtime.",
|
|
229
|
+
parameters: ResumeAgentArgsSchema,
|
|
230
|
+
execute: async (_toolCallId, params, _signal, _onUpdate, ctx) => runtime.resume(params, ctx)
|
|
231
|
+
}),
|
|
232
|
+
defineTool({
|
|
233
|
+
name: "get_agent_result",
|
|
234
|
+
label: "Get Agent Result",
|
|
235
|
+
description: "Get status and result text for a subagent session.",
|
|
236
|
+
parameters: GetAgentResultArgsSchema,
|
|
237
|
+
execute: async (_toolCallId, params, _signal, _onUpdate, ctx) => runtime.get(params, ctx)
|
|
238
|
+
}),
|
|
239
|
+
defineTool({
|
|
240
|
+
name: "list_agents",
|
|
241
|
+
label: "List Agents",
|
|
242
|
+
description: "List subagents known to the current parent session runtime.",
|
|
243
|
+
parameters: ListAgentsArgsSchema,
|
|
244
|
+
execute: async (_toolCallId, params, _signal, _onUpdate, ctx) => runtime.list(params, ctx)
|
|
245
|
+
})
|
|
246
|
+
];
|
|
247
|
+
}
|
|
248
|
+
function getRecord(map, parentSessionId) {
|
|
249
|
+
const current = map.get(parentSessionId);
|
|
250
|
+
if (current) return current;
|
|
251
|
+
const record = createControllerRecord();
|
|
252
|
+
map.set(parentSessionId, record);
|
|
253
|
+
return record;
|
|
254
|
+
}
|
|
255
|
+
function createControllerRecord() {
|
|
256
|
+
return {
|
|
257
|
+
taskIds: new Map(),
|
|
258
|
+
taskControllers: new Map(),
|
|
259
|
+
controllers: new Map()
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
function createPipController(input) {
|
|
263
|
+
return Result.ok(new PipController({
|
|
264
|
+
runner: createSdkPipRunner({
|
|
265
|
+
model: input.config.model,
|
|
266
|
+
agentDir: input.config.agentDir,
|
|
267
|
+
thinkingLevel: input.config.thinking,
|
|
268
|
+
tools: input.config.tools
|
|
269
|
+
}),
|
|
270
|
+
entries: { write(entry) {
|
|
271
|
+
input.pi.appendEntry("pi-ohm.pip", entry);
|
|
272
|
+
return Result.ok(entry.pipId);
|
|
273
|
+
} }
|
|
274
|
+
}));
|
|
275
|
+
}
|
|
276
|
+
function controllerKey(config) {
|
|
277
|
+
return `${config.modelKey}:${config.thinking}:${config.tools?.join(",") ?? "default"}`;
|
|
278
|
+
}
|
|
279
|
+
async function resolveSpawnConfig(input) {
|
|
280
|
+
const loaded = await loadConfig({
|
|
281
|
+
cwd: input.cwd,
|
|
282
|
+
modules: [subagentsConfigModule]
|
|
283
|
+
});
|
|
284
|
+
if (Result.isError(loaded)) return Result.err(loaded.error);
|
|
285
|
+
const subagents = pickConfig({
|
|
286
|
+
loaded: loaded.value,
|
|
287
|
+
module: subagentsConfigModule,
|
|
288
|
+
is: isSubagentRuntimeConfig
|
|
289
|
+
});
|
|
290
|
+
if (Result.isError(subagents)) return Result.err(subagents.error);
|
|
291
|
+
const agentType = input.params.agent_type?.trim() || input.params.task_name.trim();
|
|
292
|
+
const currentModelPattern = input.currentModel ? modelKey(input.currentModel) : undefined;
|
|
293
|
+
const baseProfile = resolveSubagentProfileRuntimeConfig({
|
|
294
|
+
config: { subagents: subagents.value },
|
|
295
|
+
subagentId: agentType,
|
|
296
|
+
modelPattern: input.params.model ?? currentModelPattern
|
|
297
|
+
});
|
|
298
|
+
const profile = resolveSubagentProfileRuntimeConfig({
|
|
299
|
+
config: { subagents: subagents.value },
|
|
300
|
+
subagentId: agentType,
|
|
301
|
+
modelPattern: input.params.model ?? baseProfile?.model ?? currentModelPattern
|
|
302
|
+
});
|
|
303
|
+
const agentDir = resolveExtensionConfigDir();
|
|
304
|
+
const modelSpec = Result.try({
|
|
305
|
+
try: () => parseModelSpec({
|
|
306
|
+
agentDir,
|
|
307
|
+
spec: input.params.model ?? profile?.model,
|
|
308
|
+
currentModel: input.currentModel
|
|
309
|
+
}),
|
|
310
|
+
catch: (cause) => cause instanceof Error ? cause : new Error(String(cause))
|
|
311
|
+
});
|
|
312
|
+
if (Result.isError(modelSpec)) return Result.err(modelSpec.error);
|
|
313
|
+
const thinking = input.params.thinking ?? profile?.thinking ?? (input.params.model || profile?.model ? modelSpec.value.thinkingLevel : input.currentThinking) ?? modelSpec.value.thinkingLevel;
|
|
314
|
+
return Result.ok({
|
|
315
|
+
agentType,
|
|
316
|
+
model: modelSpec.value.model,
|
|
317
|
+
modelKey: modelSpec.value.modelKey,
|
|
318
|
+
agentDir,
|
|
319
|
+
thinking,
|
|
320
|
+
tools: resolveTools(profile),
|
|
321
|
+
prompt: resolvePrompt({
|
|
322
|
+
profile,
|
|
323
|
+
prompt: input.params.prompt
|
|
324
|
+
})
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
function modelKey(model) {
|
|
328
|
+
return `${model.provider}/${model.id}`;
|
|
329
|
+
}
|
|
330
|
+
function resolveTools(profile) {
|
|
331
|
+
if (!profile?.tools) return undefined;
|
|
332
|
+
const denied = new Set(Object.entries(profile.permissions).filter((entry) => entry[1] === "deny").map((entry) => entry[0]));
|
|
333
|
+
const tools = profile.tools.filter((tool) => !denied.has(tool.trim().toLowerCase()));
|
|
334
|
+
if (tools.length === 0) return undefined;
|
|
335
|
+
return tools;
|
|
336
|
+
}
|
|
337
|
+
function resolvePrompt(input) {
|
|
338
|
+
if (!input.profile?.prompt) return input.prompt;
|
|
339
|
+
return `${input.profile.prompt}\n\nTask:\n${input.prompt}`;
|
|
340
|
+
}
|
|
341
|
+
function resolveTarget(record, target) {
|
|
342
|
+
return record.taskIds.get(target) ?? target;
|
|
343
|
+
}
|
|
344
|
+
function resolveController(record, pipId) {
|
|
345
|
+
return record.taskControllers.get(pipId);
|
|
346
|
+
}
|
|
347
|
+
function parseModelSpec(input) {
|
|
348
|
+
if (!input.spec && input.currentModel) {
|
|
349
|
+
return {
|
|
350
|
+
model: input.currentModel,
|
|
351
|
+
modelKey: modelKey(input.currentModel),
|
|
352
|
+
thinkingLevel: "medium"
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
const spec = input.spec ?? defaultModel;
|
|
356
|
+
const slash = spec.indexOf("/");
|
|
357
|
+
if (slash <= 0 || slash >= spec.length - 1) {
|
|
358
|
+
throw new Error(`Invalid subagent model '${spec}'. Expected '<provider>/<model>'`);
|
|
359
|
+
}
|
|
360
|
+
const colon = spec.lastIndexOf(":");
|
|
361
|
+
const provider = spec.slice(0, slash).trim();
|
|
362
|
+
const modelId = spec.slice(slash + 1, colon > slash ? colon : undefined).trim();
|
|
363
|
+
if (provider.length === 0 || modelId.length === 0) {
|
|
364
|
+
throw new Error(`Invalid subagent model '${spec}'. Expected '<provider>/<model>'`);
|
|
365
|
+
}
|
|
366
|
+
const thinkingLevel = parseThinkingLevel(colon > slash ? spec.slice(colon + 1) : "medium");
|
|
367
|
+
const registry = ModelRegistry.create(AuthStorage.create(path.join(input.agentDir, "auth.json")), path.join(input.agentDir, "models.json"));
|
|
368
|
+
const registeredModel = registry.find(provider, modelId);
|
|
369
|
+
if (registeredModel) return {
|
|
370
|
+
model: registeredModel,
|
|
371
|
+
modelKey: `${provider}/${modelId}`,
|
|
372
|
+
thinkingLevel
|
|
373
|
+
};
|
|
374
|
+
const knownProvider = getProviders().find((candidate) => candidate === provider);
|
|
375
|
+
const model = knownProvider ? getModels(knownProvider).find((candidate) => candidate.id === modelId) ?? createExternalModel({
|
|
376
|
+
provider,
|
|
377
|
+
modelId
|
|
378
|
+
}) : createExternalModel({
|
|
379
|
+
provider,
|
|
380
|
+
modelId
|
|
381
|
+
});
|
|
382
|
+
return {
|
|
383
|
+
model,
|
|
384
|
+
modelKey: `${provider}/${modelId}`,
|
|
385
|
+
thinkingLevel
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
function createExternalModel(input) {
|
|
389
|
+
const api = input.provider;
|
|
390
|
+
return {
|
|
391
|
+
id: input.modelId,
|
|
392
|
+
name: input.modelId,
|
|
393
|
+
api,
|
|
394
|
+
provider: input.provider,
|
|
395
|
+
baseUrl: "",
|
|
396
|
+
reasoning: true,
|
|
397
|
+
input: ["text"],
|
|
398
|
+
cost: {
|
|
399
|
+
input: 0,
|
|
400
|
+
output: 0,
|
|
401
|
+
cacheRead: 0,
|
|
402
|
+
cacheWrite: 0
|
|
403
|
+
},
|
|
404
|
+
contextWindow: 128e3,
|
|
405
|
+
maxTokens: 8192
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
function parseThinkingLevel(input) {
|
|
409
|
+
const level = input.trim().toLowerCase();
|
|
410
|
+
if (level === "off") return "off";
|
|
411
|
+
if (level === "minimal") return "minimal";
|
|
412
|
+
if (level === "low") return "low";
|
|
413
|
+
if (level === "medium") return "medium";
|
|
414
|
+
if (level === "high") return "high";
|
|
415
|
+
if (level === "xhigh") return "xhigh";
|
|
416
|
+
throw new Error(`Unknown subagent thinking level '${input}'`);
|
|
417
|
+
}
|
|
418
|
+
function statusResult(status) {
|
|
419
|
+
if (status.state === "completed") return status.result;
|
|
420
|
+
if (status.state === "errored") return status.error;
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
423
|
+
function toolOk(value) {
|
|
424
|
+
return {
|
|
425
|
+
content: [{
|
|
426
|
+
type: "text",
|
|
427
|
+
text: JSON.stringify(value, null, 2)
|
|
428
|
+
}],
|
|
429
|
+
details: value
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
function toolError(message) {
|
|
433
|
+
return {
|
|
434
|
+
content: [{
|
|
435
|
+
type: "text",
|
|
436
|
+
text: JSON.stringify({ error: message }, null, 2)
|
|
437
|
+
}],
|
|
438
|
+
details: { error: message }
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
//#endregion
|
|
443
|
+
export { createSubagentToolRuntime, createSubagentTools, registerAgentControllerTool, resolveSpawnConfig };
|
package/dist/config.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SubagentProfilePatch, SubagentProfilePatchSchema, SubagentProfileVariantMapPatchSchema, SubagentProfileVariantPatch, SubagentProfileVariantPatchSchema, SubagentToolPermissionDecisionPatch, SubagentToolPermissionDecisionSchema, SubagentToolPermissionMapSchema, parseSubagentProfilePatch, parseSubagentProfileVariantPatch } from "./schema.js";
|
|
2
|
-
import { Type } from "typebox";
|
|
3
2
|
import * as _$_pi_ohm_core_config0 from "@pi-ohm/core/config";
|
|
3
|
+
import { Type } from "typebox";
|
|
4
4
|
|
|
5
5
|
//#region src/config.d.ts
|
|
6
6
|
declare const SubagentsConfigSchema: Type.TRecord<"^.*$", Type.TUnknown>;
|
|
@@ -9,6 +9,9 @@ interface SubagentsConfig {
|
|
|
9
9
|
}
|
|
10
10
|
interface SubagentProfileRuntimeConfig {
|
|
11
11
|
model?: string;
|
|
12
|
+
thinking?: SubagentThinkingLevel;
|
|
13
|
+
tools?: readonly string[];
|
|
14
|
+
maxTurns?: number;
|
|
12
15
|
prompt?: string;
|
|
13
16
|
description?: string;
|
|
14
17
|
whenToUse?: readonly string[];
|
|
@@ -18,6 +21,9 @@ interface SubagentProfileRuntimeConfig {
|
|
|
18
21
|
type SubagentToolPermissionDecision = "allow" | "deny" | "inherit";
|
|
19
22
|
interface SubagentProfileVariantRuntimeConfig {
|
|
20
23
|
model?: string;
|
|
24
|
+
thinking?: SubagentThinkingLevel;
|
|
25
|
+
tools?: readonly string[];
|
|
26
|
+
maxTurns?: number;
|
|
21
27
|
prompt?: string;
|
|
22
28
|
description?: string;
|
|
23
29
|
whenToUse?: readonly string[];
|
|
@@ -25,6 +31,9 @@ interface SubagentProfileVariantRuntimeConfig {
|
|
|
25
31
|
}
|
|
26
32
|
interface ResolvedSubagentProfileRuntimeConfig {
|
|
27
33
|
model?: string;
|
|
34
|
+
thinking?: SubagentThinkingLevel;
|
|
35
|
+
tools?: readonly string[];
|
|
36
|
+
maxTurns?: number;
|
|
28
37
|
prompt?: string;
|
|
29
38
|
description?: string;
|
|
30
39
|
whenToUse?: readonly string[];
|
|
@@ -43,6 +52,7 @@ interface SubagentRuntimeConfig {
|
|
|
43
52
|
profiles: Record<string, SubagentProfileRuntimeConfig>;
|
|
44
53
|
}
|
|
45
54
|
type SubagentBackend = "none" | "interactive-shell" | "interactive-sdk" | "custom-plugin";
|
|
55
|
+
type SubagentThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
|
|
46
56
|
interface RuntimeConfigWithSubagents {
|
|
47
57
|
readonly subagents?: SubagentRuntimeConfig;
|
|
48
58
|
}
|
|
@@ -66,4 +76,4 @@ declare function resolveSubagentProfileRuntimeConfig(input: {
|
|
|
66
76
|
}): ResolvedSubagentProfileRuntimeConfig | undefined;
|
|
67
77
|
declare function isSubagentRuntimeConfig(value: unknown): value is SubagentRuntimeConfig;
|
|
68
78
|
//#endregion
|
|
69
|
-
export { DEFAULT_SUBAGENT_RUNTIME_CONFIG, ResolvedSubagentProfileRuntimeConfig, SubagentBackend, type SubagentProfilePatch, SubagentProfilePatchSchema, SubagentProfileRuntimeConfig, SubagentProfileVariantMapPatchSchema, type SubagentProfileVariantPatch, SubagentProfileVariantPatchSchema, SubagentProfileVariantRuntimeConfig, SubagentRuntimeConfig, SubagentToolPermissionDecision, type SubagentToolPermissionDecisionPatch, SubagentToolPermissionDecisionSchema, SubagentToolPermissionMapSchema, SubagentsConfig, SubagentsConfigSchema, getSubagentConfiguredModel, getSubagentProfileRuntimeConfig, isSubagentRuntimeConfig, mergeSubagentRuntimeConfig, normalizeSubagentModelOverride, parseSubagentProfilePatch, parseSubagentProfileVariantPatch, resolveSubagentProfileRuntimeConfig, resolveSubagentVariantPattern, subagentsConfigModule };
|
|
79
|
+
export { DEFAULT_SUBAGENT_RUNTIME_CONFIG, ResolvedSubagentProfileRuntimeConfig, SubagentBackend, type SubagentProfilePatch, SubagentProfilePatchSchema, SubagentProfileRuntimeConfig, SubagentProfileVariantMapPatchSchema, type SubagentProfileVariantPatch, SubagentProfileVariantPatchSchema, SubagentProfileVariantRuntimeConfig, SubagentRuntimeConfig, SubagentThinkingLevel, SubagentToolPermissionDecision, type SubagentToolPermissionDecisionPatch, SubagentToolPermissionDecisionSchema, SubagentToolPermissionMapSchema, SubagentsConfig, SubagentsConfigSchema, getSubagentConfiguredModel, getSubagentProfileRuntimeConfig, isSubagentRuntimeConfig, mergeSubagentRuntimeConfig, normalizeSubagentModelOverride, parseSubagentProfilePatch, parseSubagentProfileVariantPatch, resolveSubagentProfileRuntimeConfig, resolveSubagentVariantPattern, subagentsConfigModule };
|
package/dist/config.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SubagentProfilePatchSchema, SubagentProfileVariantMapPatchSchema, SubagentProfileVariantPatchSchema, SubagentToolPermissionDecisionSchema, SubagentToolPermissionMapSchema, parseSubagentProfilePatch, parseSubagentProfileVariantPatch } from "./schema.js";
|
|
2
2
|
import { Result } from "better-result";
|
|
3
|
-
import { Type } from "typebox";
|
|
4
3
|
import { registerConfig } from "@pi-ohm/core/config";
|
|
4
|
+
import { Type } from "typebox";
|
|
5
5
|
|
|
6
6
|
//#region src/config.ts
|
|
7
7
|
const SubagentsConfigSchema = Type.Record(Type.String({ minLength: 1 }), Type.Unknown());
|
|
@@ -34,14 +34,6 @@ const SUBAGENT_RUNTIME_RESERVED_KEYS = new Set([
|
|
|
34
34
|
"permissions",
|
|
35
35
|
"profiles"
|
|
36
36
|
]);
|
|
37
|
-
const SUBAGENT_THINKING_LEVELS = new Set([
|
|
38
|
-
"off",
|
|
39
|
-
"minimal",
|
|
40
|
-
"low",
|
|
41
|
-
"medium",
|
|
42
|
-
"high",
|
|
43
|
-
"xhigh"
|
|
44
|
-
]);
|
|
45
37
|
function isJsonMap(value) {
|
|
46
38
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
47
39
|
}
|
|
@@ -62,6 +54,26 @@ function normalizePositiveInteger(value, fallback) {
|
|
|
62
54
|
if (!Number.isInteger(value) || value <= 0) return fallback;
|
|
63
55
|
return value;
|
|
64
56
|
}
|
|
57
|
+
function normalizeOptionalPositiveInteger(value) {
|
|
58
|
+
if (typeof value !== "number") return undefined;
|
|
59
|
+
if (!Number.isInteger(value) || value <= 0) return undefined;
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
function isSubagentThinkingLevel(value) {
|
|
63
|
+
return value === "off" || value === "minimal" || value === "low" || value === "medium" || value === "high" || value === "xhigh";
|
|
64
|
+
}
|
|
65
|
+
function normalizeThinking(value) {
|
|
66
|
+
if (typeof value !== "string") return undefined;
|
|
67
|
+
const normalized = value.trim().toLowerCase();
|
|
68
|
+
if (!isSubagentThinkingLevel(normalized)) return undefined;
|
|
69
|
+
return normalized;
|
|
70
|
+
}
|
|
71
|
+
function normalizeStringList(value) {
|
|
72
|
+
if (!Array.isArray(value)) return undefined;
|
|
73
|
+
const normalized = value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter((entry) => entry.length > 0);
|
|
74
|
+
if (normalized.length === 0) return undefined;
|
|
75
|
+
return normalized;
|
|
76
|
+
}
|
|
65
77
|
function normalizeSubagentBackend(value, fallback) {
|
|
66
78
|
if (value === "none" || value === "interactive-shell" || value === "interactive-sdk" || value === "custom-plugin") {
|
|
67
79
|
return value;
|
|
@@ -131,7 +143,7 @@ function stripThinkingSuffix(modelId) {
|
|
|
131
143
|
return trimmed;
|
|
132
144
|
}
|
|
133
145
|
const suffix = trimmed.slice(colonIndex + 1).trim().toLowerCase();
|
|
134
|
-
if (!
|
|
146
|
+
if (!isSubagentThinkingLevel(suffix)) {
|
|
135
147
|
return trimmed;
|
|
136
148
|
}
|
|
137
149
|
return trimmed.slice(0, colonIndex).trim();
|
|
@@ -140,6 +152,9 @@ function mergeSubagentVariantConfig(patch, fallback) {
|
|
|
140
152
|
const parsedPatch = parseSubagentProfileVariantPatch(patch);
|
|
141
153
|
if (!parsedPatch) return fallback;
|
|
142
154
|
const model = normalizeSubagentModelOverride(parsedPatch.model);
|
|
155
|
+
const thinking = normalizeThinking(parsedPatch.thinking);
|
|
156
|
+
const tools = normalizeStringList(parsedPatch.tools);
|
|
157
|
+
const maxTurns = normalizeOptionalPositiveInteger(parsedPatch.maxTurns);
|
|
143
158
|
const prompt = parsedPatch.prompt;
|
|
144
159
|
const description = parsedPatch.description;
|
|
145
160
|
const whenToUse = parsedPatch.whenToUse;
|
|
@@ -148,12 +163,15 @@ function mergeSubagentVariantConfig(patch, fallback) {
|
|
|
148
163
|
const merged = {
|
|
149
164
|
...fallback,
|
|
150
165
|
...model ? { model } : {},
|
|
166
|
+
...thinking ? { thinking } : {},
|
|
167
|
+
...tools ? { tools } : {},
|
|
168
|
+
...maxTurns ? { maxTurns } : {},
|
|
151
169
|
...prompt ? { prompt } : {},
|
|
152
170
|
...description ? { description } : {},
|
|
153
171
|
...whenToUse ? { whenToUse } : {},
|
|
154
172
|
...Object.keys(permissions).length > 0 ? { permissions } : {}
|
|
155
173
|
};
|
|
156
|
-
const hasValues = merged.model !== undefined || merged.prompt !== undefined || merged.description !== undefined || merged.whenToUse !== undefined || merged.permissions !== undefined;
|
|
174
|
+
const hasValues = merged.model !== undefined || merged.thinking !== undefined || merged.tools !== undefined || merged.maxTurns !== undefined || merged.prompt !== undefined || merged.description !== undefined || merged.whenToUse !== undefined || merged.permissions !== undefined;
|
|
157
175
|
if (!hasValues) return undefined;
|
|
158
176
|
return merged;
|
|
159
177
|
}
|
|
@@ -174,6 +192,9 @@ function mergeSubagentProfileConfig(patch, fallback) {
|
|
|
174
192
|
const parsedPatch = parseSubagentProfilePatch(patch);
|
|
175
193
|
if (!parsedPatch) return fallback;
|
|
176
194
|
const model = normalizeSubagentModelOverride(parsedPatch.model);
|
|
195
|
+
const thinking = normalizeThinking(parsedPatch.thinking);
|
|
196
|
+
const tools = normalizeStringList(parsedPatch.tools);
|
|
197
|
+
const maxTurns = normalizeOptionalPositiveInteger(parsedPatch.maxTurns);
|
|
177
198
|
const prompt = parsedPatch.prompt;
|
|
178
199
|
const description = parsedPatch.description;
|
|
179
200
|
const whenToUse = parsedPatch.whenToUse;
|
|
@@ -183,13 +204,16 @@ function mergeSubagentProfileConfig(patch, fallback) {
|
|
|
183
204
|
const merged = {
|
|
184
205
|
...fallback,
|
|
185
206
|
...model ? { model } : {},
|
|
207
|
+
...thinking ? { thinking } : {},
|
|
208
|
+
...tools ? { tools } : {},
|
|
209
|
+
...maxTurns ? { maxTurns } : {},
|
|
186
210
|
...prompt ? { prompt } : {},
|
|
187
211
|
...description ? { description } : {},
|
|
188
212
|
...whenToUse ? { whenToUse } : {},
|
|
189
213
|
...Object.keys(permissions).length > 0 ? { permissions } : {},
|
|
190
214
|
...Object.keys(variants).length > 0 ? { variants } : {}
|
|
191
215
|
};
|
|
192
|
-
const hasValues = merged.model !== undefined || merged.prompt !== undefined || merged.description !== undefined || merged.whenToUse !== undefined || merged.permissions !== undefined || merged.variants !== undefined;
|
|
216
|
+
const hasValues = merged.model !== undefined || merged.thinking !== undefined || merged.tools !== undefined || merged.maxTurns !== undefined || merged.prompt !== undefined || merged.description !== undefined || merged.whenToUse !== undefined || merged.permissions !== undefined || merged.variants !== undefined;
|
|
193
217
|
if (!hasValues) return undefined;
|
|
194
218
|
return merged;
|
|
195
219
|
}
|
|
@@ -320,6 +344,9 @@ function resolveSubagentProfileRuntimeConfig(input) {
|
|
|
320
344
|
});
|
|
321
345
|
return {
|
|
322
346
|
model: variant?.model ?? profile.model,
|
|
347
|
+
thinking: variant?.thinking ?? profile.thinking,
|
|
348
|
+
tools: variant?.tools ?? profile.tools,
|
|
349
|
+
maxTurns: variant?.maxTurns ?? profile.maxTurns,
|
|
323
350
|
prompt: variant?.prompt ?? profile.prompt,
|
|
324
351
|
description: variant?.description ?? profile.description,
|
|
325
352
|
whenToUse: variant?.whenToUse ?? profile.whenToUse,
|
package/dist/extension.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { SubagentToolRuntime, createSubagentToolRuntime, createSubagentTools, registerAgentControllerTool, resolveSpawnConfig } from "./agent-controller.js";
|
|
1
2
|
import { SubagentProfilePatch, SubagentProfilePatchSchema, SubagentProfileVariantMapPatchSchema, SubagentProfileVariantPatch, SubagentProfileVariantPatchSchema, SubagentToolPermissionDecisionPatch, SubagentToolPermissionDecisionSchema, SubagentToolPermissionMapSchema, parseSubagentProfilePatch, parseSubagentProfileVariantPatch } from "./schema.js";
|
|
2
|
-
import { DEFAULT_SUBAGENT_RUNTIME_CONFIG, ResolvedSubagentProfileRuntimeConfig, SubagentBackend, SubagentProfileRuntimeConfig, SubagentProfileVariantRuntimeConfig, SubagentRuntimeConfig, SubagentToolPermissionDecision, SubagentsConfig, SubagentsConfigSchema, getSubagentConfiguredModel, getSubagentProfileRuntimeConfig, isSubagentRuntimeConfig, mergeSubagentRuntimeConfig, normalizeSubagentModelOverride, resolveSubagentProfileRuntimeConfig, resolveSubagentVariantPattern, subagentsConfigModule } from "./config.js";
|
|
3
|
+
import { DEFAULT_SUBAGENT_RUNTIME_CONFIG, ResolvedSubagentProfileRuntimeConfig, SubagentBackend, SubagentProfileRuntimeConfig, SubagentProfileVariantRuntimeConfig, SubagentRuntimeConfig, SubagentThinkingLevel, SubagentToolPermissionDecision, SubagentsConfig, SubagentsConfigSchema, getSubagentConfiguredModel, getSubagentProfileRuntimeConfig, isSubagentRuntimeConfig, mergeSubagentRuntimeConfig, normalizeSubagentModelOverride, resolveSubagentProfileRuntimeConfig, resolveSubagentVariantPattern, subagentsConfigModule } from "./config.js";
|
|
3
4
|
import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
4
5
|
|
|
5
6
|
//#region src/extension.d.ts
|
|
6
|
-
declare function registerSubagentsExtension(
|
|
7
|
+
declare function registerSubagentsExtension(pi: ExtensionAPI): void;
|
|
7
8
|
//#endregion
|
|
8
|
-
export { DEFAULT_SUBAGENT_RUNTIME_CONFIG, ResolvedSubagentProfileRuntimeConfig, SubagentBackend, SubagentProfilePatch, SubagentProfilePatchSchema, SubagentProfileRuntimeConfig, SubagentProfileVariantMapPatchSchema, SubagentProfileVariantPatch, SubagentProfileVariantPatchSchema, SubagentProfileVariantRuntimeConfig, SubagentRuntimeConfig, SubagentToolPermissionDecision, SubagentToolPermissionDecisionPatch, SubagentToolPermissionDecisionSchema, SubagentToolPermissionMapSchema, SubagentsConfig, SubagentsConfigSchema, registerSubagentsExtension as default, getSubagentConfiguredModel, getSubagentProfileRuntimeConfig, isSubagentRuntimeConfig, mergeSubagentRuntimeConfig, normalizeSubagentModelOverride, parseSubagentProfilePatch, parseSubagentProfileVariantPatch, resolveSubagentProfileRuntimeConfig, resolveSubagentVariantPattern, subagentsConfigModule };
|
|
9
|
+
export { DEFAULT_SUBAGENT_RUNTIME_CONFIG, ResolvedSubagentProfileRuntimeConfig, SubagentBackend, SubagentProfilePatch, SubagentProfilePatchSchema, SubagentProfileRuntimeConfig, SubagentProfileVariantMapPatchSchema, SubagentProfileVariantPatch, SubagentProfileVariantPatchSchema, SubagentProfileVariantRuntimeConfig, SubagentRuntimeConfig, SubagentThinkingLevel, SubagentToolPermissionDecision, SubagentToolPermissionDecisionPatch, SubagentToolPermissionDecisionSchema, SubagentToolPermissionMapSchema, SubagentToolRuntime, SubagentsConfig, SubagentsConfigSchema, createSubagentToolRuntime, createSubagentTools, registerSubagentsExtension as default, getSubagentConfiguredModel, getSubagentProfileRuntimeConfig, isSubagentRuntimeConfig, mergeSubagentRuntimeConfig, normalizeSubagentModelOverride, parseSubagentProfilePatch, parseSubagentProfileVariantPatch, registerAgentControllerTool, resolveSpawnConfig, resolveSubagentProfileRuntimeConfig, resolveSubagentVariantPattern, subagentsConfigModule };
|
package/dist/extension.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { SubagentProfilePatchSchema, SubagentProfileVariantMapPatchSchema, SubagentProfileVariantPatchSchema, SubagentToolPermissionDecisionSchema, SubagentToolPermissionMapSchema, parseSubagentProfilePatch, parseSubagentProfileVariantPatch } from "./schema.js";
|
|
2
2
|
import { DEFAULT_SUBAGENT_RUNTIME_CONFIG, SubagentsConfigSchema, getSubagentConfiguredModel, getSubagentProfileRuntimeConfig, isSubagentRuntimeConfig, mergeSubagentRuntimeConfig, normalizeSubagentModelOverride, resolveSubagentProfileRuntimeConfig, resolveSubagentVariantPattern, subagentsConfigModule } from "./config.js";
|
|
3
|
+
import { createSubagentToolRuntime, createSubagentTools, registerAgentControllerTool, resolveSpawnConfig } from "./agent-controller.js";
|
|
3
4
|
|
|
4
5
|
//#region src/extension.ts
|
|
5
|
-
function registerSubagentsExtension(
|
|
6
|
+
function registerSubagentsExtension(pi) {
|
|
7
|
+
registerAgentControllerTool(pi);
|
|
8
|
+
}
|
|
6
9
|
|
|
7
10
|
//#endregion
|
|
8
|
-
export { DEFAULT_SUBAGENT_RUNTIME_CONFIG, SubagentProfilePatchSchema, SubagentProfileVariantMapPatchSchema, SubagentProfileVariantPatchSchema, SubagentToolPermissionDecisionSchema, SubagentToolPermissionMapSchema, SubagentsConfigSchema, registerSubagentsExtension as default, getSubagentConfiguredModel, getSubagentProfileRuntimeConfig, isSubagentRuntimeConfig, mergeSubagentRuntimeConfig, normalizeSubagentModelOverride, parseSubagentProfilePatch, parseSubagentProfileVariantPatch, resolveSubagentProfileRuntimeConfig, resolveSubagentVariantPattern, subagentsConfigModule };
|
|
11
|
+
export { DEFAULT_SUBAGENT_RUNTIME_CONFIG, SubagentProfilePatchSchema, SubagentProfileVariantMapPatchSchema, SubagentProfileVariantPatchSchema, SubagentToolPermissionDecisionSchema, SubagentToolPermissionMapSchema, SubagentsConfigSchema, createSubagentToolRuntime, createSubagentTools, registerSubagentsExtension as default, getSubagentConfiguredModel, getSubagentProfileRuntimeConfig, isSubagentRuntimeConfig, mergeSubagentRuntimeConfig, normalizeSubagentModelOverride, parseSubagentProfilePatch, parseSubagentProfileVariantPatch, registerAgentControllerTool, resolveSpawnConfig, resolveSubagentProfileRuntimeConfig, resolveSubagentVariantPattern, subagentsConfigModule };
|
package/dist/schema.d.ts
CHANGED
|
@@ -5,6 +5,9 @@ declare const SubagentToolPermissionDecisionSchema: Type.TUnion<[Type.TLiteral<"
|
|
|
5
5
|
declare const SubagentToolPermissionMapSchema: Type.TRecord<"^.*$", Type.TUnion<[Type.TLiteral<"allow">, Type.TLiteral<"deny">, Type.TLiteral<"inherit">, Type.TLiteral<"ask">]>>;
|
|
6
6
|
declare const SubagentProfileVariantPatchSchema: Type.TObject<{
|
|
7
7
|
model: Type.TOptional<Type.TString>;
|
|
8
|
+
thinking: Type.TOptional<Type.TUnion<[Type.TLiteral<"off">, Type.TLiteral<"minimal">, Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">, Type.TLiteral<"xhigh">]>>;
|
|
9
|
+
tools: Type.TOptional<Type.TArray<Type.TString>>;
|
|
10
|
+
maxTurns: Type.TOptional<Type.TInteger>;
|
|
8
11
|
prompt: Type.TOptional<Type.TString>;
|
|
9
12
|
description: Type.TOptional<Type.TString>;
|
|
10
13
|
whenToUse: Type.TOptional<Type.TArray<Type.TString>>;
|
|
@@ -12,6 +15,9 @@ declare const SubagentProfileVariantPatchSchema: Type.TObject<{
|
|
|
12
15
|
}>;
|
|
13
16
|
declare const SubagentProfileVariantMapPatchSchema: Type.TRecord<"^.*$", Type.TObject<{
|
|
14
17
|
model: Type.TOptional<Type.TString>;
|
|
18
|
+
thinking: Type.TOptional<Type.TUnion<[Type.TLiteral<"off">, Type.TLiteral<"minimal">, Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">, Type.TLiteral<"xhigh">]>>;
|
|
19
|
+
tools: Type.TOptional<Type.TArray<Type.TString>>;
|
|
20
|
+
maxTurns: Type.TOptional<Type.TInteger>;
|
|
15
21
|
prompt: Type.TOptional<Type.TString>;
|
|
16
22
|
description: Type.TOptional<Type.TString>;
|
|
17
23
|
whenToUse: Type.TOptional<Type.TArray<Type.TString>>;
|
|
@@ -19,12 +25,18 @@ declare const SubagentProfileVariantMapPatchSchema: Type.TRecord<"^.*$", Type.TO
|
|
|
19
25
|
}>>;
|
|
20
26
|
declare const SubagentProfilePatchSchema: Type.TObject<{
|
|
21
27
|
model: Type.TOptional<Type.TString>;
|
|
28
|
+
thinking: Type.TOptional<Type.TUnion<[Type.TLiteral<"off">, Type.TLiteral<"minimal">, Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">, Type.TLiteral<"xhigh">]>>;
|
|
29
|
+
tools: Type.TOptional<Type.TArray<Type.TString>>;
|
|
30
|
+
maxTurns: Type.TOptional<Type.TInteger>;
|
|
22
31
|
prompt: Type.TOptional<Type.TString>;
|
|
23
32
|
description: Type.TOptional<Type.TString>;
|
|
24
33
|
whenToUse: Type.TOptional<Type.TArray<Type.TString>>;
|
|
25
34
|
permissions: Type.TOptional<Type.TRecord<"^.*$", Type.TUnion<[Type.TLiteral<"allow">, Type.TLiteral<"deny">, Type.TLiteral<"inherit">, Type.TLiteral<"ask">]>>>;
|
|
26
35
|
variants: Type.TOptional<Type.TRecord<"^.*$", Type.TObject<{
|
|
27
36
|
model: Type.TOptional<Type.TString>;
|
|
37
|
+
thinking: Type.TOptional<Type.TUnion<[Type.TLiteral<"off">, Type.TLiteral<"minimal">, Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">, Type.TLiteral<"xhigh">]>>;
|
|
38
|
+
tools: Type.TOptional<Type.TArray<Type.TString>>;
|
|
39
|
+
maxTurns: Type.TOptional<Type.TInteger>;
|
|
28
40
|
prompt: Type.TOptional<Type.TString>;
|
|
29
41
|
description: Type.TOptional<Type.TString>;
|
|
30
42
|
whenToUse: Type.TOptional<Type.TArray<Type.TString>>;
|
package/dist/schema.js
CHANGED
|
@@ -13,6 +13,16 @@ const SubagentToolPermissionDecisionSchema = Type.Union([
|
|
|
13
13
|
const SubagentToolPermissionMapSchema = Type.Record(NonEmptyStringSchema, SubagentToolPermissionDecisionSchema);
|
|
14
14
|
const SubagentProfileVariantPatchSchema = Type.Object({
|
|
15
15
|
model: Type.Optional(NonEmptyStringSchema),
|
|
16
|
+
thinking: Type.Optional(Type.Union([
|
|
17
|
+
Type.Literal("off"),
|
|
18
|
+
Type.Literal("minimal"),
|
|
19
|
+
Type.Literal("low"),
|
|
20
|
+
Type.Literal("medium"),
|
|
21
|
+
Type.Literal("high"),
|
|
22
|
+
Type.Literal("xhigh")
|
|
23
|
+
])),
|
|
24
|
+
tools: Type.Optional(NonEmptyStringArraySchema),
|
|
25
|
+
maxTurns: Type.Optional(Type.Integer({ minimum: 1 })),
|
|
16
26
|
prompt: Type.Optional(NonEmptyStringSchema),
|
|
17
27
|
description: Type.Optional(NonEmptyStringSchema),
|
|
18
28
|
whenToUse: Type.Optional(NonEmptyStringArraySchema),
|
|
@@ -21,6 +31,16 @@ const SubagentProfileVariantPatchSchema = Type.Object({
|
|
|
21
31
|
const SubagentProfileVariantMapPatchSchema = Type.Record(NonEmptyStringSchema, SubagentProfileVariantPatchSchema);
|
|
22
32
|
const SubagentProfilePatchSchema = Type.Object({
|
|
23
33
|
model: Type.Optional(NonEmptyStringSchema),
|
|
34
|
+
thinking: Type.Optional(Type.Union([
|
|
35
|
+
Type.Literal("off"),
|
|
36
|
+
Type.Literal("minimal"),
|
|
37
|
+
Type.Literal("low"),
|
|
38
|
+
Type.Literal("medium"),
|
|
39
|
+
Type.Literal("high"),
|
|
40
|
+
Type.Literal("xhigh")
|
|
41
|
+
])),
|
|
42
|
+
tools: Type.Optional(NonEmptyStringArraySchema),
|
|
43
|
+
maxTurns: Type.Optional(Type.Integer({ minimum: 1 })),
|
|
24
44
|
prompt: Type.Optional(NonEmptyStringSchema),
|
|
25
45
|
description: Type.Optional(NonEmptyStringSchema),
|
|
26
46
|
whenToUse: Type.Optional(NonEmptyStringArraySchema),
|
|
@@ -42,6 +62,19 @@ function toTrimmedStringArray(value) {
|
|
|
42
62
|
if (normalized.length === 0) return undefined;
|
|
43
63
|
return normalized;
|
|
44
64
|
}
|
|
65
|
+
function toPositiveInteger(value) {
|
|
66
|
+
if (typeof value !== "number") return undefined;
|
|
67
|
+
if (!Number.isInteger(value) || value <= 0) return undefined;
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
function toThinking(value) {
|
|
71
|
+
const trimmed = toTrimmedString(value)?.toLowerCase();
|
|
72
|
+
if (!trimmed) return undefined;
|
|
73
|
+
if (trimmed !== "off" && trimmed !== "minimal" && trimmed !== "low" && trimmed !== "medium" && trimmed !== "high" && trimmed !== "xhigh") {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
return trimmed;
|
|
77
|
+
}
|
|
45
78
|
function normalizeSubagentPermissionMapInput(value) {
|
|
46
79
|
if (!isObjectRecord(value)) return undefined;
|
|
47
80
|
const normalized = {};
|
|
@@ -63,12 +96,18 @@ function normalizeSubagentPermissionMapInput(value) {
|
|
|
63
96
|
function normalizeSubagentProfileVariantPatchInput(input) {
|
|
64
97
|
if (!isObjectRecord(input)) return input;
|
|
65
98
|
const model = toTrimmedString(Reflect.get(input, "model"));
|
|
99
|
+
const thinking = toThinking(Reflect.get(input, "thinking"));
|
|
100
|
+
const tools = toTrimmedStringArray(Reflect.get(input, "tools"));
|
|
101
|
+
const maxTurns = toPositiveInteger(Reflect.get(input, "maxTurns"));
|
|
66
102
|
const prompt = toTrimmedString(Reflect.get(input, "prompt"));
|
|
67
103
|
const description = toTrimmedString(Reflect.get(input, "description"));
|
|
68
104
|
const whenToUse = toTrimmedStringArray(Reflect.get(input, "whenToUse"));
|
|
69
105
|
const permissions = normalizeSubagentPermissionMapInput(Reflect.get(input, "permissions"));
|
|
70
106
|
return {
|
|
71
107
|
...model ? { model } : {},
|
|
108
|
+
...thinking ? { thinking } : {},
|
|
109
|
+
...tools ? { tools } : {},
|
|
110
|
+
...maxTurns ? { maxTurns } : {},
|
|
72
111
|
...prompt ? { prompt } : {},
|
|
73
112
|
...description ? { description } : {},
|
|
74
113
|
...whenToUse ? { whenToUse } : {},
|
|
@@ -95,6 +134,9 @@ function normalizeSubagentProfileVariantMapInput(input) {
|
|
|
95
134
|
function normalizeSubagentProfilePatchInput(input) {
|
|
96
135
|
if (!isObjectRecord(input)) return input;
|
|
97
136
|
const model = toTrimmedString(Reflect.get(input, "model"));
|
|
137
|
+
const thinking = toThinking(Reflect.get(input, "thinking"));
|
|
138
|
+
const tools = toTrimmedStringArray(Reflect.get(input, "tools"));
|
|
139
|
+
const maxTurns = toPositiveInteger(Reflect.get(input, "maxTurns"));
|
|
98
140
|
const prompt = toTrimmedString(Reflect.get(input, "prompt"));
|
|
99
141
|
const description = toTrimmedString(Reflect.get(input, "description"));
|
|
100
142
|
const whenToUse = toTrimmedStringArray(Reflect.get(input, "whenToUse"));
|
|
@@ -102,6 +144,9 @@ function normalizeSubagentProfilePatchInput(input) {
|
|
|
102
144
|
const variants = normalizeSubagentProfileVariantMapInput(Reflect.get(input, "variants"));
|
|
103
145
|
return {
|
|
104
146
|
...model ? { model } : {},
|
|
147
|
+
...thinking ? { thinking } : {},
|
|
148
|
+
...tools ? { tools } : {},
|
|
149
|
+
...maxTurns ? { maxTurns } : {},
|
|
105
150
|
...prompt ? { prompt } : {},
|
|
106
151
|
...description ? { description } : {},
|
|
107
152
|
...whenToUse ? { whenToUse } : {},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-ohm/subagents",
|
|
3
|
-
"version": "0.6.4-dev.
|
|
3
|
+
"version": "0.6.4-dev.25632661332.1.3bf351f",
|
|
4
4
|
"homepage": "https://github.com/pi-ohm/pi-ohm/tree/dev/packages/subagents#readme",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -30,14 +30,15 @@
|
|
|
30
30
|
"provenance": true
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
|
-
"build": "vp pack src/extension.ts src/config.ts"
|
|
33
|
+
"build": "vp pack src/extension.ts src/config.ts src/agent-controller.ts"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@earendil-works/pi-agent-core": "0.74.0",
|
|
37
|
+
"@earendil-works/pi-ai": "0.74.0",
|
|
37
38
|
"@earendil-works/pi-coding-agent": "0.74.0",
|
|
38
|
-
"@pi-ohm/core": "0.6.4-dev.
|
|
39
|
-
"@pi-ohm/tui": "0.6.4-dev.
|
|
40
|
-
"better-result": "
|
|
39
|
+
"@pi-ohm/core": "0.6.4-dev.25632661332.1.3bf351f",
|
|
40
|
+
"@pi-ohm/tui": "0.6.4-dev.25632661332.1.3bf351f",
|
|
41
|
+
"better-result": "2.9.2",
|
|
41
42
|
"typebox": "^1.0.68",
|
|
42
43
|
"zod": "^4"
|
|
43
44
|
},
|