@esso0428/pi-subagents 0.15.0 → 0.15.2
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/CHANGELOG.md +10 -0
- package/README.md +2 -2
- package/dist/agent-manager.d.ts +8 -0
- package/dist/agent-manager.js +87 -19
- package/dist/agent-runner.js +85 -66
- package/dist/agent-types.js +45 -27
- package/dist/context.js +6 -2
- package/dist/cross-extension-rpc.js +9 -5
- package/dist/custom-agents.js +18 -15
- package/dist/default-agents.js +4 -1
- package/dist/enabled-models.js +16 -11
- package/dist/env.js +4 -1
- package/dist/group-join.js +5 -1
- package/dist/index.js +280 -221
- package/dist/invocation-config.js +6 -2
- package/dist/memory.js +34 -24
- package/dist/model-resolver.js +4 -1
- package/dist/nico-overrides.js +20 -14
- package/dist/output-file.js +21 -15
- package/dist/prompts.js +4 -1
- package/dist/schedule-store.js +21 -16
- package/dist/schedule.js +12 -8
- package/dist/settings.js +23 -15
- package/dist/skill-loader.js +23 -20
- package/dist/status-note.js +4 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.js +4 -1
- package/dist/ui/agent-widget.js +37 -23
- package/dist/ui/conversation-viewer.js +43 -39
- package/dist/ui/fleet-list.js +30 -24
- package/dist/ui/markdown-result.d.ts +3 -0
- package/dist/ui/markdown-result.js +53 -0
- package/dist/ui/schedule-menu.js +4 -1
- package/dist/ui/viewer-keys.js +10 -7
- package/dist/usage.js +10 -4
- package/dist/worktree.js +31 -26
- package/package.json +1 -1
- package/src/agent-manager.ts +72 -0
- package/src/agent-runner.ts +11 -3
- package/src/index.ts +39 -16
- package/src/types.ts +1 -0
- package/src/ui/markdown-result.ts +56 -0
- package/test/agent-manager-history.test.ts +84 -0
- package/test/ui/markdown-result.test.ts +45 -0
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* pi-agents — A pi extension providing Claude Code-style autonomous sub-agents.
|
|
3
4
|
*
|
|
@@ -9,29 +10,66 @@
|
|
|
9
10
|
* Commands:
|
|
10
11
|
* /agents — Interactive agent management menu
|
|
11
12
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
13
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
20
|
+
}) : (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
o[k2] = m[k];
|
|
23
|
+
}));
|
|
24
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
25
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
26
|
+
}) : function(o, v) {
|
|
27
|
+
o["default"] = v;
|
|
28
|
+
});
|
|
29
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
30
|
+
var ownKeys = function(o) {
|
|
31
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
32
|
+
var ar = [];
|
|
33
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
34
|
+
return ar;
|
|
35
|
+
};
|
|
36
|
+
return ownKeys(o);
|
|
37
|
+
};
|
|
38
|
+
return function (mod) {
|
|
39
|
+
if (mod && mod.__esModule) return mod;
|
|
40
|
+
var result = {};
|
|
41
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
42
|
+
__setModuleDefault(result, mod);
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
45
|
+
})();
|
|
46
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
+
exports.renderRunningAgentStatus = renderRunningAgentStatus;
|
|
48
|
+
exports.default = default_1;
|
|
49
|
+
const node_fs_1 = require("node:fs");
|
|
50
|
+
const node_path_1 = require("node:path");
|
|
51
|
+
const pi_coding_agent_1 = require("@earendil-works/pi-coding-agent");
|
|
52
|
+
const pi_tui_1 = require("@earendil-works/pi-tui");
|
|
53
|
+
const typebox_1 = require("@sinclair/typebox");
|
|
54
|
+
const agent_manager_js_1 = require("./agent-manager.js");
|
|
55
|
+
const agent_runner_js_1 = require("./agent-runner.js");
|
|
56
|
+
const agent_types_js_1 = require("./agent-types.js");
|
|
57
|
+
const cross_extension_rpc_js_1 = require("./cross-extension-rpc.js");
|
|
58
|
+
const custom_agents_js_1 = require("./custom-agents.js");
|
|
59
|
+
const enabled_models_js_1 = require("./enabled-models.js");
|
|
60
|
+
const group_join_js_1 = require("./group-join.js");
|
|
61
|
+
const invocation_config_js_1 = require("./invocation-config.js");
|
|
62
|
+
const model_resolver_js_1 = require("./model-resolver.js");
|
|
63
|
+
const output_file_js_1 = require("./output-file.js");
|
|
64
|
+
const schedule_js_1 = require("./schedule.js");
|
|
65
|
+
const schedule_store_js_1 = require("./schedule-store.js");
|
|
66
|
+
const settings_js_1 = require("./settings.js");
|
|
67
|
+
const status_note_js_1 = require("./status-note.js");
|
|
68
|
+
const agent_widget_js_1 = require("./ui/agent-widget.js");
|
|
69
|
+
const fleet_list_js_1 = require("./ui/fleet-list.js");
|
|
70
|
+
const markdown_result_js_1 = require("./ui/markdown-result.js");
|
|
71
|
+
const schedule_menu_js_1 = require("./ui/schedule-menu.js");
|
|
72
|
+
const usage_js_1 = require("./usage.js");
|
|
35
73
|
// ---- Shared helpers ----
|
|
36
74
|
/** Tool execute return value for a text response. */
|
|
37
75
|
function textResult(msg, details) {
|
|
@@ -69,16 +107,16 @@ function abortable(promise, signal) {
|
|
|
69
107
|
});
|
|
70
108
|
});
|
|
71
109
|
}
|
|
72
|
-
|
|
73
|
-
const container = new Container();
|
|
74
|
-
container.addChild(new Text(theme.fg("accent", frame) + (statsText ? " " + statsText : ""), 0, 0));
|
|
75
|
-
container.addChild(new Text(theme.fg("dim", ` ⎿ ${activity}`), 0, 0));
|
|
110
|
+
function renderRunningAgentStatus(frame, statsText, activity, theme) {
|
|
111
|
+
const container = new pi_tui_1.Container();
|
|
112
|
+
container.addChild(new pi_tui_1.Text(theme.fg("accent", frame) + (statsText ? " " + statsText : ""), 0, 0));
|
|
113
|
+
container.addChild(new pi_tui_1.Text(theme.fg("dim", ` ⎿ ${activity}`), 0, 0));
|
|
76
114
|
return container;
|
|
77
115
|
}
|
|
78
116
|
/** Format an agent's lifetime token total, or "" when zero. */
|
|
79
117
|
function formatLifetimeTokens(o) {
|
|
80
|
-
const t = getLifetimeTotal(o.lifetimeUsage);
|
|
81
|
-
return t > 0 ? formatTokens(t) : "";
|
|
118
|
+
const t = (0, usage_js_1.getLifetimeTotal)(o.lifetimeUsage);
|
|
119
|
+
return t > 0 ? (0, agent_widget_js_1.formatTokens)(t) : "";
|
|
82
120
|
}
|
|
83
121
|
/**
|
|
84
122
|
* Create an AgentActivity state and spawn callbacks for tracking tool usage.
|
|
@@ -122,7 +160,7 @@ function createActivityTracker(maxTurns, onStreamUpdate) {
|
|
|
122
160
|
state.session = session;
|
|
123
161
|
},
|
|
124
162
|
onAssistantUsage: (usage) => {
|
|
125
|
-
addUsage(state.lifetimeUsage, usage);
|
|
163
|
+
(0, usage_js_1.addUsage)(state.lifetimeUsage, usage);
|
|
126
164
|
onStreamUpdate?.();
|
|
127
165
|
},
|
|
128
166
|
};
|
|
@@ -163,8 +201,8 @@ function escapeXml(s) {
|
|
|
163
201
|
function formatTaskNotification(record, resultMaxLen) {
|
|
164
202
|
const status = getStatusLabel(record.status, record.error);
|
|
165
203
|
const durationMs = record.completedAt ? record.completedAt - record.startedAt : 0;
|
|
166
|
-
const totalTokens = getLifetimeTotal(record.lifetimeUsage);
|
|
167
|
-
const contextPercent = getSessionContextPercent(record.session);
|
|
204
|
+
const totalTokens = (0, usage_js_1.getLifetimeTotal)(record.lifetimeUsage);
|
|
205
|
+
const contextPercent = (0, usage_js_1.getSessionContextPercent)(record.session);
|
|
168
206
|
const ctxXml = contextPercent !== null ? `<context_percent>${Math.round(contextPercent)}</context_percent>` : "";
|
|
169
207
|
const compactXml = record.compactionCount ? `<compactions>${record.compactionCount}</compactions>` : "";
|
|
170
208
|
const resultPreview = record.result
|
|
@@ -178,7 +216,7 @@ function formatTaskNotification(record, resultMaxLen) {
|
|
|
178
216
|
record.toolCallId ? `<tool-use-id>${escapeXml(record.toolCallId)}</tool-use-id>` : null,
|
|
179
217
|
record.outputFile ? `<output-file>${escapeXml(record.outputFile)}</output-file>` : null,
|
|
180
218
|
`<status>${escapeXml(status)}</status>`,
|
|
181
|
-
`<summary>Agent "${escapeXml(record.description)}" ${record.status}${getStatusNote(record.status)}</summary>`,
|
|
219
|
+
`<summary>Agent "${escapeXml(record.description)}" ${record.status}${(0, status_note_js_1.getStatusNote)(record.status)}</summary>`,
|
|
182
220
|
`<result>${escapeXml(resultPreview)}</result>`,
|
|
183
221
|
`<usage><total_tokens>${totalTokens}</total_tokens><tool_uses>${record.toolUses}</tool_uses>${ctxXml}${compactXml}<duration_ms>${durationMs}</duration_ms></usage>`,
|
|
184
222
|
`</task-notification>`,
|
|
@@ -199,9 +237,11 @@ function buildDetails(base, record, activity, overrides) {
|
|
|
199
237
|
...overrides,
|
|
200
238
|
};
|
|
201
239
|
}
|
|
240
|
+
/** Maximum expanded notification body retained in message details. */
|
|
241
|
+
const MAX_NOTIFICATION_RESULT_TEXT_LENGTH = 20_000;
|
|
202
242
|
/** Build notification details for the custom message renderer. */
|
|
203
243
|
function buildNotificationDetails(record, resultMaxLen, activity) {
|
|
204
|
-
const totalTokens = getLifetimeTotal(record.lifetimeUsage);
|
|
244
|
+
const totalTokens = (0, usage_js_1.getLifetimeTotal)(record.lifetimeUsage);
|
|
205
245
|
return {
|
|
206
246
|
id: record.id,
|
|
207
247
|
description: record.description,
|
|
@@ -213,6 +253,11 @@ function buildNotificationDetails(record, resultMaxLen, activity) {
|
|
|
213
253
|
durationMs: record.completedAt ? record.completedAt - record.startedAt : 0,
|
|
214
254
|
outputFile: record.outputFile,
|
|
215
255
|
error: record.error,
|
|
256
|
+
resultText: record.result
|
|
257
|
+
? record.result.length > MAX_NOTIFICATION_RESULT_TEXT_LENGTH
|
|
258
|
+
? record.result.slice(0, MAX_NOTIFICATION_RESULT_TEXT_LENGTH) + "…"
|
|
259
|
+
: record.result
|
|
260
|
+
: undefined,
|
|
216
261
|
resultPreview: record.result
|
|
217
262
|
? record.result.length > resultMaxLen
|
|
218
263
|
? record.result.slice(0, resultMaxLen) + "…"
|
|
@@ -220,7 +265,7 @@ function buildNotificationDetails(record, resultMaxLen, activity) {
|
|
|
220
265
|
: "No output.",
|
|
221
266
|
};
|
|
222
267
|
}
|
|
223
|
-
|
|
268
|
+
function default_1(pi) {
|
|
224
269
|
// ---- Register custom notification renderer ----
|
|
225
270
|
pi.registerMessageRenderer("subagent-notification", (message, { expanded }, theme) => {
|
|
226
271
|
const d = message.details;
|
|
@@ -237,40 +282,49 @@ export default function (pi) {
|
|
|
237
282
|
// Line 2: stats
|
|
238
283
|
const parts = [];
|
|
239
284
|
if (d.turnCount > 0)
|
|
240
|
-
parts.push(formatTurns(d.turnCount, d.maxTurns));
|
|
285
|
+
parts.push((0, agent_widget_js_1.formatTurns)(d.turnCount, d.maxTurns));
|
|
241
286
|
if (d.toolUses > 0)
|
|
242
287
|
parts.push(`${d.toolUses} tool use${d.toolUses === 1 ? "" : "s"}`);
|
|
243
288
|
if (d.totalTokens > 0)
|
|
244
|
-
parts.push(formatTokens(d.totalTokens));
|
|
289
|
+
parts.push((0, agent_widget_js_1.formatTokens)(d.totalTokens));
|
|
245
290
|
if (d.durationMs > 0)
|
|
246
|
-
parts.push(formatMs(d.durationMs));
|
|
291
|
+
parts.push((0, agent_widget_js_1.formatMs)(d.durationMs));
|
|
247
292
|
if (parts.length) {
|
|
248
293
|
line += "\n " + parts.map(p => theme.fg("dim", p)).join(" " + theme.fg("dim", "·") + " ");
|
|
249
294
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
const lines = d.resultPreview.split("\n").slice(0, 30);
|
|
253
|
-
for (const l of lines)
|
|
254
|
-
line += "\n" + theme.fg("dim", ` ${l}`);
|
|
255
|
-
}
|
|
256
|
-
else {
|
|
295
|
+
if (!expanded) {
|
|
296
|
+
// Collapsed previews intentionally remain compact plain text.
|
|
257
297
|
const preview = d.resultPreview.split("\n")[0]?.slice(0, 80) ?? "";
|
|
258
298
|
line += "\n " + theme.fg("dim", `⎿ ${preview}`);
|
|
299
|
+
if (d.outputFile) {
|
|
300
|
+
line += "\n " + theme.fg("muted", `transcript: ${d.outputFile}`);
|
|
301
|
+
}
|
|
302
|
+
return line;
|
|
259
303
|
}
|
|
260
|
-
|
|
304
|
+
const container = new pi_tui_1.Container();
|
|
305
|
+
container.addChild(new pi_tui_1.Text(line, 0, 0));
|
|
306
|
+
container.addChild((0, markdown_result_js_1.createMarkdownResult)(d.resultText ?? d.resultPreview, theme, 30));
|
|
261
307
|
if (d.outputFile) {
|
|
262
|
-
|
|
308
|
+
container.addChild(new pi_tui_1.Text(theme.fg("muted", ` transcript: ${d.outputFile}`), 0, 0));
|
|
263
309
|
}
|
|
264
|
-
return
|
|
310
|
+
return container;
|
|
265
311
|
}
|
|
266
312
|
const all = [d, ...(d.others ?? [])];
|
|
267
|
-
|
|
313
|
+
if (!expanded)
|
|
314
|
+
return new pi_tui_1.Text(all.map(renderOne).join("\n"), 0, 0);
|
|
315
|
+
const container = new pi_tui_1.Container();
|
|
316
|
+
all.forEach((item, index) => {
|
|
317
|
+
if (index > 0)
|
|
318
|
+
container.addChild(new pi_tui_1.Spacer(1));
|
|
319
|
+
container.addChild(renderOne(item));
|
|
320
|
+
});
|
|
321
|
+
return container;
|
|
268
322
|
});
|
|
269
323
|
/** Reload agents from project/global custom agent dirs and merge with defaults (called on init and each Agent invocation). */
|
|
270
324
|
const reloadCustomAgents = () => {
|
|
271
|
-
const userAgents = loadCustomAgents(process.cwd());
|
|
272
|
-
registerAgents(userAgents);
|
|
273
|
-
applyNicoOverrides();
|
|
325
|
+
const userAgents = (0, custom_agents_js_1.loadCustomAgents)(process.cwd());
|
|
326
|
+
(0, agent_types_js_1.registerAgents)(userAgents);
|
|
327
|
+
(0, agent_types_js_1.applyNicoOverrides)();
|
|
274
328
|
};
|
|
275
329
|
// Initial load
|
|
276
330
|
reloadCustomAgents();
|
|
@@ -322,7 +376,7 @@ export default function (pi) {
|
|
|
322
376
|
widget.update();
|
|
323
377
|
}
|
|
324
378
|
// ---- Group join manager ----
|
|
325
|
-
const groupJoin = new GroupJoinManager((records, partial) => {
|
|
379
|
+
const groupJoin = new group_join_js_1.GroupJoinManager((records, partial) => {
|
|
326
380
|
for (const r of records) {
|
|
327
381
|
agentActivity.delete(r.id);
|
|
328
382
|
widget.markFinished(r.id);
|
|
@@ -362,7 +416,7 @@ export default function (pi) {
|
|
|
362
416
|
// tokens is omitted when nothing was ever produced (e.g. agent errored before
|
|
363
417
|
// any message_end fired), preserving prior payload shape.
|
|
364
418
|
const u = record.lifetimeUsage;
|
|
365
|
-
const total = getLifetimeTotal(u);
|
|
419
|
+
const total = (0, usage_js_1.getLifetimeTotal)(u);
|
|
366
420
|
const tokens = total > 0
|
|
367
421
|
? { input: u.input, output: u.output, total }
|
|
368
422
|
: undefined;
|
|
@@ -379,7 +433,7 @@ export default function (pi) {
|
|
|
379
433
|
};
|
|
380
434
|
}
|
|
381
435
|
// Background completion: route through group join or send individual nudge
|
|
382
|
-
const manager = new AgentManager((record) => {
|
|
436
|
+
const manager = new agent_manager_js_1.AgentManager((record) => {
|
|
383
437
|
// Emit lifecycle event based on terminal status
|
|
384
438
|
const isError = record.status === "error" || record.status === "stopped" || record.status === "aborted";
|
|
385
439
|
const eventData = buildEventData(record);
|
|
@@ -468,14 +522,14 @@ export default function (pi) {
|
|
|
468
522
|
// Session-scoped: store is constructed inside session_start once sessionId
|
|
469
523
|
// is available. Mirrors pi-chonky-tasks's session-scoped task store —
|
|
470
524
|
// schedules reset on /new, restore on /resume.
|
|
471
|
-
const scheduler = new SubagentScheduler();
|
|
525
|
+
const scheduler = new schedule_js_1.SubagentScheduler();
|
|
472
526
|
function startScheduler(ctx) {
|
|
473
527
|
try {
|
|
474
528
|
const sessionId = ctx.sessionManager?.getSessionId?.();
|
|
475
529
|
if (!sessionId)
|
|
476
530
|
return; // sessionId not yet available — try again on next event
|
|
477
|
-
const path = resolveStorePath(ctx.cwd, sessionId);
|
|
478
|
-
const store = new ScheduleStore(path);
|
|
531
|
+
const path = (0, schedule_store_js_1.resolveStorePath)(ctx.cwd, sessionId);
|
|
532
|
+
const store = new schedule_store_js_1.ScheduleStore(path);
|
|
479
533
|
scheduler.start(pi, ctx, manager, store);
|
|
480
534
|
pi.events.emit("subagents:scheduler_ready", { sessionId, jobCount: store.list().length });
|
|
481
535
|
}
|
|
@@ -491,10 +545,15 @@ export default function (pi) {
|
|
|
491
545
|
pi.on("session_start", async (_event, ctx) => {
|
|
492
546
|
currentCtx = ctx;
|
|
493
547
|
manager.clearCompleted(true);
|
|
548
|
+
const historicalRecords = ctx.sessionManager
|
|
549
|
+
.getBranch()
|
|
550
|
+
.filter((entry) => entry?.type === "custom" && entry.customType === "subagents:record")
|
|
551
|
+
.map((entry) => entry.data);
|
|
552
|
+
manager.restoreCompleted(historicalRecords);
|
|
494
553
|
// Guard mirrors the `!scheduler.isActive()` pattern below: session_start
|
|
495
554
|
// fires once per activation, but a double-bind must not leak listeners.
|
|
496
555
|
if (!rpcHandle) {
|
|
497
|
-
rpcHandle = registerRpcHandlers({
|
|
556
|
+
rpcHandle = (0, cross_extension_rpc_js_1.registerRpcHandlers)({
|
|
498
557
|
events: pi.events,
|
|
499
558
|
pi,
|
|
500
559
|
getCtx: () => currentCtx,
|
|
@@ -540,10 +599,10 @@ export default function (pi) {
|
|
|
540
599
|
// everything else; "off" = hide the widget entirely. Read live at render time.
|
|
541
600
|
let widgetMode = "background";
|
|
542
601
|
function getWidgetMode() { return widgetMode; }
|
|
543
|
-
const widget = new AgentWidget(manager, agentActivity, getWidgetMode);
|
|
602
|
+
const widget = new agent_widget_js_1.AgentWidget(manager, agentActivity, getWidgetMode);
|
|
544
603
|
function setWidgetMode(m) { widgetMode = m; widget.update(); }
|
|
545
604
|
// Claude Code-style FleetView: navigable list of main + subagents below the editor.
|
|
546
|
-
const fleet = new FleetList(manager, agentActivity);
|
|
605
|
+
const fleet = new fleet_list_js_1.FleetList(manager, agentActivity);
|
|
547
606
|
let fleetViewEnabled = true;
|
|
548
607
|
function isFleetViewEnabled() { return fleetViewEnabled; }
|
|
549
608
|
function setFleetViewEnabled(b) { fleetViewEnabled = b; fleet.setEnabled(b); }
|
|
@@ -584,7 +643,7 @@ export default function (pi) {
|
|
|
584
643
|
// State lives in agent-types.ts (isDefaultsDisabled) because registerAgents
|
|
585
644
|
// needs it; this wrapper just re-registers after flipping it.
|
|
586
645
|
function setDisableDefaultAgents(b) {
|
|
587
|
-
setDefaultsDisabled(b);
|
|
646
|
+
(0, agent_types_js_1.setDefaultsDisabled)(b);
|
|
588
647
|
reloadCustomAgents(); // re-register with new setting
|
|
589
648
|
}
|
|
590
649
|
// ---- Agent tool description mode ----
|
|
@@ -647,15 +706,15 @@ export default function (pi) {
|
|
|
647
706
|
const tools = cfg?.builtinToolNames;
|
|
648
707
|
if (!tools || tools.length === 0)
|
|
649
708
|
return "*";
|
|
650
|
-
const isFullSet = tools.length === BUILTIN_TOOL_NAMES.length
|
|
651
|
-
&& BUILTIN_TOOL_NAMES.every((t) => tools.includes(t));
|
|
709
|
+
const isFullSet = tools.length === agent_types_js_1.BUILTIN_TOOL_NAMES.length
|
|
710
|
+
&& agent_types_js_1.BUILTIN_TOOL_NAMES.every((t) => tools.includes(t));
|
|
652
711
|
return isFullSet ? "*" : tools.join(", ");
|
|
653
712
|
};
|
|
654
713
|
/** Build the full type list text dynamically from available agents only. */
|
|
655
714
|
const buildTypeListText = () => {
|
|
656
|
-
const available = getAvailableTypes();
|
|
715
|
+
const available = (0, agent_types_js_1.getAvailableTypes)();
|
|
657
716
|
return available.map((name) => {
|
|
658
|
-
const cfg = getAgentConfig(name);
|
|
717
|
+
const cfg = (0, agent_types_js_1.getAgentConfig)(name);
|
|
659
718
|
const modelSuffix = cfg?.model ? ` (${getModelLabelFromConfig(cfg.model)})` : "";
|
|
660
719
|
const toolsSuffix = ` (Tools: ${formatToolsSuffix(cfg)})`;
|
|
661
720
|
return `- ${name}: ${cfg?.description ?? name}${modelSuffix}${toolsSuffix}`;
|
|
@@ -667,8 +726,8 @@ export default function (pi) {
|
|
|
667
726
|
return (match ? match[0] : text).replace(/\s+/g, " ").trim();
|
|
668
727
|
};
|
|
669
728
|
/** Compact type list: one line per agent, first sentence only. */
|
|
670
|
-
const buildCompactTypeListText = () => getAvailableTypes().map((name) => {
|
|
671
|
-
const cfg = getAgentConfig(name);
|
|
729
|
+
const buildCompactTypeListText = () => (0, agent_types_js_1.getAvailableTypes)().map((name) => {
|
|
730
|
+
const cfg = (0, agent_types_js_1.getAgentConfig)(name);
|
|
672
731
|
return `- ${name}: ${firstSentence(cfg?.description ?? name)} (Tools: ${formatToolsSuffix(cfg)})`;
|
|
673
732
|
}).join("\n");
|
|
674
733
|
/** Derive a short model label from a model string. */
|
|
@@ -681,10 +740,10 @@ export default function (pi) {
|
|
|
681
740
|
// Apply persisted settings on startup and emit `subagents:settings_loaded`.
|
|
682
741
|
// Global + project merged; missing → defaults; corrupt file emits a warning
|
|
683
742
|
// to stderr and falls back to defaults.
|
|
684
|
-
applyAndEmitLoaded({
|
|
743
|
+
(0, settings_js_1.applyAndEmitLoaded)({
|
|
685
744
|
setMaxConcurrent: (n) => manager.setMaxConcurrent(n),
|
|
686
|
-
setDefaultMaxTurns,
|
|
687
|
-
setGraceTurns,
|
|
745
|
+
setDefaultMaxTurns: agent_runner_js_1.setDefaultMaxTurns,
|
|
746
|
+
setGraceTurns: agent_runner_js_1.setGraceTurns,
|
|
688
747
|
setDefaultJoinMode,
|
|
689
748
|
setSchedulingEnabled,
|
|
690
749
|
setScopeModels: setScopeModelsEnabled,
|
|
@@ -701,7 +760,7 @@ export default function (pi) {
|
|
|
701
760
|
// preserves Type.Object's inference when present and produces a
|
|
702
761
|
// `schedule`-free schema when absent — zero LLM-context cost in disabled mode.
|
|
703
762
|
const scheduleParamShape = {
|
|
704
|
-
schedule: Type.Optional(Type.String({
|
|
763
|
+
schedule: typebox_1.Type.Optional(typebox_1.Type.String({
|
|
705
764
|
description: 'Opt-in only — fire later instead of now. Omit to run immediately (the default, almost always correct). ' +
|
|
706
765
|
'Formats: 6-field cron ("0 0 9 * * 1" = 9am Mon), interval ("5m"/"1h"), one-shot ("+10m" or ISO). ' +
|
|
707
766
|
'Forces run_in_background; incompatible with inherit_context and resume. Returns job ID.',
|
|
@@ -717,7 +776,7 @@ export default function (pi) {
|
|
|
717
776
|
const compactAgentToolDescription = `Launch an autonomous agent for complex, multi-step tasks. Agent types:
|
|
718
777
|
${buildCompactTypeListText()}
|
|
719
778
|
|
|
720
|
-
Custom agents: .pi/agents/<name>.md (project) or ${getAgentDir()}/agents/<name>.md (global).
|
|
779
|
+
Custom agents: .pi/agents/<name>.md (project) or ${(0, pi_coding_agent_1.getAgentDir)()}/agents/<name>.md (global).
|
|
721
780
|
|
|
722
781
|
Notes:
|
|
723
782
|
- description: 3-5 words (shown in UI). Prompts must be self-contained — the agent has not seen this conversation.
|
|
@@ -730,7 +789,7 @@ Notes:
|
|
|
730
789
|
Available agent types and the tools they have access to:
|
|
731
790
|
${buildTypeListText()}
|
|
732
791
|
|
|
733
|
-
Custom agents can be defined in .pi/agents/<name>.md (project) or ${getAgentDir()}/agents/<name>.md (global) — they are picked up automatically. Project-level agents override global ones. Creating a .md file with the same name as a default agent overrides it.
|
|
792
|
+
Custom agents can be defined in .pi/agents/<name>.md (project) or ${(0, pi_coding_agent_1.getAgentDir)()}/agents/<name>.md (global) — they are picked up automatically. Project-level agents override global ones. Creating a .md file with the same name as a default agent overrides it.
|
|
734
793
|
|
|
735
794
|
When using the Agent tool, specify a subagent_type parameter to select which agent type to use.
|
|
736
795
|
|
|
@@ -775,7 +834,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
775
834
|
const vars = {
|
|
776
835
|
typeList: buildTypeListText,
|
|
777
836
|
compactTypeList: buildCompactTypeListText,
|
|
778
|
-
agentDir: getAgentDir,
|
|
837
|
+
agentDir: pi_coding_agent_1.getAgentDir,
|
|
779
838
|
scheduleGuideline: () => scheduleGuideline,
|
|
780
839
|
};
|
|
781
840
|
// Replacement callback (not a string) — agent descriptions may contain `$&` etc.
|
|
@@ -788,13 +847,13 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
788
847
|
};
|
|
789
848
|
const loadCustomToolDescription = () => {
|
|
790
849
|
for (const path of [
|
|
791
|
-
join(process.cwd(), ".pi", "agent-tool-description.md"),
|
|
792
|
-
join(getAgentDir(), "agent-tool-description.md"),
|
|
850
|
+
(0, node_path_1.join)(process.cwd(), ".pi", "agent-tool-description.md"),
|
|
851
|
+
(0, node_path_1.join)((0, pi_coding_agent_1.getAgentDir)(), "agent-tool-description.md"),
|
|
793
852
|
]) {
|
|
794
853
|
try {
|
|
795
|
-
if (!existsSync(path))
|
|
854
|
+
if (!(0, node_fs_1.existsSync)(path))
|
|
796
855
|
continue;
|
|
797
|
-
const text = readFileSync(path, "utf-8").trim();
|
|
856
|
+
const text = (0, node_fs_1.readFileSync)(path, "utf-8").trim();
|
|
798
857
|
if (text)
|
|
799
858
|
return renderToolDescriptionTemplate(text);
|
|
800
859
|
console.warn(`[pi-subagents] ${path} is empty — ignoring`);
|
|
@@ -817,8 +876,8 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
817
876
|
}
|
|
818
877
|
return fullAgentToolDescription;
|
|
819
878
|
})();
|
|
820
|
-
pi.registerTool(defineTool({
|
|
821
|
-
name: SUBAGENT_TOOL_NAMES.AGENT,
|
|
879
|
+
pi.registerTool((0, pi_coding_agent_1.defineTool)({
|
|
880
|
+
name: agent_runner_js_1.SUBAGENT_TOOL_NAMES.AGENT,
|
|
822
881
|
label: "Agent",
|
|
823
882
|
description: agentToolDescription,
|
|
824
883
|
promptSnippet: "Launch autonomous sub-agents for complex multi-step tasks",
|
|
@@ -828,54 +887,54 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
828
887
|
"When an agent runs in the background, you will be notified on completion — do not poll or sleep waiting for it. Continue with other work instead.",
|
|
829
888
|
"Trust but verify: an agent's summary describes intent, not outcome. When an agent writes or edits code, check the actual changes before reporting work as done.",
|
|
830
889
|
],
|
|
831
|
-
parameters: Type.Object({
|
|
832
|
-
prompt: Type.String({
|
|
890
|
+
parameters: typebox_1.Type.Object({
|
|
891
|
+
prompt: typebox_1.Type.String({
|
|
833
892
|
description: "The task for the agent to perform.",
|
|
834
893
|
}),
|
|
835
|
-
description: Type.String({
|
|
894
|
+
description: typebox_1.Type.String({
|
|
836
895
|
description: "A short (3-5 word) description of the task (shown in UI).",
|
|
837
896
|
}),
|
|
838
|
-
subagent_type: Type.String({
|
|
839
|
-
description: `The type of specialized agent to use. Available types: ${getAvailableTypes().join(", ")}. Custom agents from .pi/agents/*.md (project) or ${getAgentDir()}/agents/*.md (global) are also available.`,
|
|
897
|
+
subagent_type: typebox_1.Type.String({
|
|
898
|
+
description: `The type of specialized agent to use. Available types: ${(0, agent_types_js_1.getAvailableTypes)().join(", ")}. Custom agents from .pi/agents/*.md (project) or ${(0, pi_coding_agent_1.getAgentDir)()}/agents/*.md (global) are also available.`,
|
|
840
899
|
}),
|
|
841
|
-
model: Type.Optional(Type.String({
|
|
900
|
+
model: typebox_1.Type.Optional(typebox_1.Type.String({
|
|
842
901
|
description: 'Optional model override. Accepts "provider/modelId" or fuzzy name (e.g. "haiku", "sonnet"). Omit to use the agent type\'s default.',
|
|
843
902
|
})),
|
|
844
|
-
thinking: Type.Optional(Type.String({
|
|
903
|
+
thinking: typebox_1.Type.Optional(typebox_1.Type.String({
|
|
845
904
|
description: `Thinking level: ${THINKING_LEVELS.join(", ")}. Overrides agent default.`,
|
|
846
905
|
})),
|
|
847
|
-
max_turns: Type.Optional(Type.Number({
|
|
906
|
+
max_turns: typebox_1.Type.Optional(typebox_1.Type.Number({
|
|
848
907
|
description: "Maximum number of agentic turns before stopping. Omit for unlimited (default).",
|
|
849
908
|
minimum: 1,
|
|
850
909
|
})),
|
|
851
|
-
run_in_background: Type.Optional(Type.Boolean({
|
|
910
|
+
run_in_background: typebox_1.Type.Optional(typebox_1.Type.Boolean({
|
|
852
911
|
description: "Set to true to run in background. Returns agent ID immediately. You will be notified on completion.",
|
|
853
912
|
})),
|
|
854
|
-
resume: Type.Optional(Type.String({
|
|
913
|
+
resume: typebox_1.Type.Optional(typebox_1.Type.String({
|
|
855
914
|
description: "Optional agent ID to resume from. Continues from previous context.",
|
|
856
915
|
})),
|
|
857
|
-
isolated: Type.Optional(Type.Boolean({
|
|
916
|
+
isolated: typebox_1.Type.Optional(typebox_1.Type.Boolean({
|
|
858
917
|
description: "If true, agent gets no extension/MCP tools — only built-in tools.",
|
|
859
918
|
})),
|
|
860
|
-
inherit_context: Type.Optional(Type.Boolean({
|
|
919
|
+
inherit_context: typebox_1.Type.Optional(typebox_1.Type.Boolean({
|
|
861
920
|
description: "If true, fork parent conversation into the agent. Default: false (fresh context).",
|
|
862
921
|
})),
|
|
863
|
-
isolation: Type.Optional(Type.Literal("worktree", {
|
|
922
|
+
isolation: typebox_1.Type.Optional(typebox_1.Type.Literal("worktree", {
|
|
864
923
|
description: 'Set to "worktree" to run the agent in a temporary git worktree (isolated copy of the repo). Changes are saved to a branch on completion.',
|
|
865
924
|
})),
|
|
866
925
|
...scheduleParam,
|
|
867
926
|
}),
|
|
868
927
|
// ---- Custom rendering: Claude Code style ----
|
|
869
928
|
renderCall(args, theme) {
|
|
870
|
-
const displayName = args.subagent_type ? getDisplayName(args.subagent_type) : "Agent";
|
|
929
|
+
const displayName = args.subagent_type ? (0, agent_widget_js_1.getDisplayName)(args.subagent_type) : "Agent";
|
|
871
930
|
const desc = args.description ?? "";
|
|
872
|
-
return new Text("▸ " + theme.fg("toolTitle", theme.bold(displayName)) + (desc ? " " + theme.fg("muted", desc) : ""), 0, 0);
|
|
931
|
+
return new pi_tui_1.Text("▸ " + theme.fg("toolTitle", theme.bold(displayName)) + (desc ? " " + theme.fg("muted", desc) : ""), 0, 0);
|
|
873
932
|
},
|
|
874
933
|
renderResult(result, { expanded, isPartial }, theme) {
|
|
875
934
|
const details = result.details;
|
|
876
935
|
if (!details) {
|
|
877
936
|
const text = result.content[0]?.type === "text" ? result.content[0].text : "";
|
|
878
|
-
return new Text(text, 0, 0);
|
|
937
|
+
return new pi_tui_1.Text(text, 0, 0);
|
|
879
938
|
}
|
|
880
939
|
// Helper: build "haiku · thinking: high · ↻5≤30 · 3 tool uses · 33.8k tokens" stats string
|
|
881
940
|
const stats = (d) => {
|
|
@@ -885,27 +944,27 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
885
944
|
if (d.tags)
|
|
886
945
|
parts.push(...d.tags);
|
|
887
946
|
if (d.turnCount != null && d.turnCount > 0) {
|
|
888
|
-
parts.push(formatTurns(d.turnCount, d.maxTurns));
|
|
947
|
+
parts.push((0, agent_widget_js_1.formatTurns)(d.turnCount, d.maxTurns));
|
|
889
948
|
}
|
|
890
949
|
if (d.toolUses > 0)
|
|
891
950
|
parts.push(`${d.toolUses} tool use${d.toolUses === 1 ? "" : "s"}`);
|
|
892
951
|
if (d.tokens)
|
|
893
952
|
parts.push(d.tokens);
|
|
894
|
-
return parts.map(p => fgPreservingNestedStyles(theme, "dim", p)).join(" " + theme.fg("dim", "·") + " ");
|
|
953
|
+
return parts.map(p => (0, agent_widget_js_1.fgPreservingNestedStyles)(theme, "dim", p)).join(" " + theme.fg("dim", "·") + " ");
|
|
895
954
|
};
|
|
896
955
|
// ---- While running (streaming) ----
|
|
897
956
|
if (isPartial || details.status === "running") {
|
|
898
|
-
const frame = SPINNER[details.spinnerFrame ?? 0];
|
|
957
|
+
const frame = agent_widget_js_1.SPINNER[details.spinnerFrame ?? 0];
|
|
899
958
|
const s = stats(details);
|
|
900
959
|
return renderRunningAgentStatus(frame, s, details.activity ?? "thinking…", theme);
|
|
901
960
|
}
|
|
902
961
|
// ---- Background agent launched ----
|
|
903
962
|
if (details.status === "background") {
|
|
904
|
-
return new Text(theme.fg("dim", ` ⎿ Running in background (ID: ${details.agentId})`), 0, 0);
|
|
963
|
+
return new pi_tui_1.Text(theme.fg("dim", ` ⎿ Running in background (ID: ${details.agentId})`), 0, 0);
|
|
905
964
|
}
|
|
906
965
|
// ---- Completed / Steered ----
|
|
907
966
|
if (details.status === "completed" || details.status === "steered") {
|
|
908
|
-
const duration = formatMs(details.durationMs);
|
|
967
|
+
const duration = (0, agent_widget_js_1.formatMs)(details.durationMs);
|
|
909
968
|
const isSteered = details.status === "steered";
|
|
910
969
|
const icon = isSteered ? theme.fg("warning", "✓") : theme.fg("success", "✓");
|
|
911
970
|
const s = stats(details);
|
|
@@ -913,28 +972,28 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
913
972
|
line += " " + theme.fg("dim", "·") + " " + theme.fg("dim", duration);
|
|
914
973
|
if (expanded) {
|
|
915
974
|
const resultText = result.content[0]?.type === "text" ? result.content[0].text : "";
|
|
975
|
+
const container = new pi_tui_1.Container();
|
|
976
|
+
container.addChild(new pi_tui_1.Text(line, 0, 0));
|
|
916
977
|
if (resultText) {
|
|
917
|
-
|
|
918
|
-
for (const l of lines) {
|
|
919
|
-
line += "\n" + theme.fg("dim", ` ${l}`);
|
|
920
|
-
}
|
|
978
|
+
container.addChild((0, markdown_result_js_1.createMarkdownResult)(resultText, theme, 50));
|
|
921
979
|
if (resultText.split("\n").length > 50) {
|
|
922
|
-
|
|
980
|
+
container.addChild(new pi_tui_1.Text(theme.fg("muted", " ... (use get_subagent_result with verbose for full output)"), 0, 0));
|
|
923
981
|
}
|
|
924
982
|
}
|
|
983
|
+
return container;
|
|
925
984
|
}
|
|
926
985
|
else {
|
|
927
986
|
const doneText = isSteered ? "Wrapped up (turn limit)" : "Done";
|
|
928
987
|
line += "\n" + theme.fg("dim", ` ⎿ ${doneText}`);
|
|
929
988
|
}
|
|
930
|
-
return new Text(line, 0, 0);
|
|
989
|
+
return new pi_tui_1.Text(line, 0, 0);
|
|
931
990
|
}
|
|
932
991
|
// ---- Stopped (user-initiated abort) ----
|
|
933
992
|
if (details.status === "stopped") {
|
|
934
993
|
const s = stats(details);
|
|
935
994
|
let line = theme.fg("dim", "■") + (s ? " " + s : "");
|
|
936
995
|
line += "\n" + theme.fg("dim", " ⎿ Stopped");
|
|
937
|
-
return new Text(line, 0, 0);
|
|
996
|
+
return new pi_tui_1.Text(line, 0, 0);
|
|
938
997
|
}
|
|
939
998
|
// ---- Error / Aborted (hard max_turns) ----
|
|
940
999
|
const s = stats(details);
|
|
@@ -945,7 +1004,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
945
1004
|
else {
|
|
946
1005
|
line += "\n" + theme.fg("warning", " ⎿ Aborted (max turns exceeded)");
|
|
947
1006
|
}
|
|
948
|
-
return new Text(line, 0, 0);
|
|
1007
|
+
return new pi_tui_1.Text(line, 0, 0);
|
|
949
1008
|
},
|
|
950
1009
|
// ---- Execute ----
|
|
951
1010
|
execute: async (toolCallId, params, signal, onUpdate, ctx) => {
|
|
@@ -954,17 +1013,17 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
954
1013
|
// Reload custom agents so new project/global .md files are picked up without restart
|
|
955
1014
|
reloadCustomAgents();
|
|
956
1015
|
const rawType = params.subagent_type;
|
|
957
|
-
const resolved = resolveType(rawType);
|
|
1016
|
+
const resolved = (0, agent_types_js_1.resolveType)(rawType);
|
|
958
1017
|
const subagentType = resolved ?? "general-purpose";
|
|
959
1018
|
const fellBack = resolved === undefined;
|
|
960
|
-
const displayName = getDisplayName(subagentType);
|
|
1019
|
+
const displayName = (0, agent_widget_js_1.getDisplayName)(subagentType);
|
|
961
1020
|
// Get agent config (if any)
|
|
962
|
-
const customConfig = getAgentConfig(subagentType);
|
|
963
|
-
const resolvedConfig = resolveAgentInvocationConfig(customConfig, params);
|
|
1021
|
+
const customConfig = (0, agent_types_js_1.getAgentConfig)(subagentType);
|
|
1022
|
+
const resolvedConfig = (0, invocation_config_js_1.resolveAgentInvocationConfig)(customConfig, params);
|
|
964
1023
|
// Resolve model from agent config first; tool-call params only fill gaps.
|
|
965
1024
|
let model = ctx.model;
|
|
966
1025
|
if (resolvedConfig.modelInput) {
|
|
967
|
-
const resolved = resolveModel(resolvedConfig.modelInput, ctx.modelRegistry);
|
|
1026
|
+
const resolved = (0, model_resolver_js_1.resolveModel)(resolvedConfig.modelInput, ctx.modelRegistry);
|
|
968
1027
|
if (typeof resolved === "string") {
|
|
969
1028
|
if (resolvedConfig.modelFromParams)
|
|
970
1029
|
return textResult(resolved);
|
|
@@ -984,8 +1043,8 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
984
1043
|
// user authored/installed this agent or chose the parent's model; trust it).
|
|
985
1044
|
// See SubagentsSettings.scopeModels docstring for the full policy.
|
|
986
1045
|
if (isScopeModelsEnabled() && model) {
|
|
987
|
-
const allowed = resolveEnabledModels(readEnabledModels(ctx.cwd), ctx.modelRegistry, ctx.cwd);
|
|
988
|
-
if (allowed && !isModelInScope(model, allowed)) {
|
|
1046
|
+
const allowed = (0, enabled_models_js_1.resolveEnabledModels)((0, enabled_models_js_1.readEnabledModels)(ctx.cwd), ctx.modelRegistry, ctx.cwd);
|
|
1047
|
+
if (allowed && !(0, enabled_models_js_1.isModelInScope)(model, allowed)) {
|
|
989
1048
|
if (resolvedConfig.modelFromParams) {
|
|
990
1049
|
const list = [...allowed].sort().map(m => ` ${m}`).join("\n");
|
|
991
1050
|
return textResult(`Model not in scope: "${resolvedConfig.modelInput}".\n\n` +
|
|
@@ -1011,29 +1070,29 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1011
1070
|
const attachTranscript = (rec, agentId) => {
|
|
1012
1071
|
if (!rec || !outputTranscript)
|
|
1013
1072
|
return;
|
|
1014
|
-
rec.outputFile = createOutputFilePath(ctx.cwd, agentId, ctx.sessionManager.getSessionId());
|
|
1015
|
-
writeInitialEntry(rec.outputFile, agentId, params.prompt, ctx.cwd);
|
|
1073
|
+
rec.outputFile = (0, output_file_js_1.createOutputFilePath)(ctx.cwd, agentId, ctx.sessionManager.getSessionId());
|
|
1074
|
+
(0, output_file_js_1.writeInitialEntry)(rec.outputFile, agentId, params.prompt, ctx.cwd);
|
|
1016
1075
|
};
|
|
1017
1076
|
const parentModelId = ctx.model?.id;
|
|
1018
1077
|
const effectiveModelId = model?.id;
|
|
1019
1078
|
const modelName = effectiveModelId && effectiveModelId !== parentModelId
|
|
1020
1079
|
? (model?.name ?? effectiveModelId).replace(/^Claude\s+/i, "").toLowerCase()
|
|
1021
1080
|
: undefined;
|
|
1022
|
-
const effectiveMaxTurns = normalizeMaxTurns(resolvedConfig.maxTurns ?? getDefaultMaxTurns());
|
|
1081
|
+
const effectiveMaxTurns = (0, agent_runner_js_1.normalizeMaxTurns)(resolvedConfig.maxTurns ?? (0, agent_runner_js_1.getDefaultMaxTurns)());
|
|
1023
1082
|
const agentInvocation = {
|
|
1024
1083
|
modelName,
|
|
1025
1084
|
thinking,
|
|
1026
1085
|
// Explicit value only — the default fallback would just add noise.
|
|
1027
1086
|
// Normalize so `0` (unlimited) doesn't surface as a misleading "max turns: 0".
|
|
1028
|
-
maxTurns: normalizeMaxTurns(resolvedConfig.maxTurns),
|
|
1087
|
+
maxTurns: (0, agent_runner_js_1.normalizeMaxTurns)(resolvedConfig.maxTurns),
|
|
1029
1088
|
isolated,
|
|
1030
1089
|
inheritContext,
|
|
1031
1090
|
runInBackground,
|
|
1032
1091
|
isolation,
|
|
1033
1092
|
};
|
|
1034
1093
|
// Tool-result render shows the mode label too; viewer's header already does.
|
|
1035
|
-
const modeLabel = getPromptModeLabel(subagentType);
|
|
1036
|
-
const { tags: invocationTags } = buildInvocationTags(agentInvocation);
|
|
1094
|
+
const modeLabel = (0, agent_widget_js_1.getPromptModeLabel)(subagentType);
|
|
1095
|
+
const { tags: invocationTags } = (0, agent_widget_js_1.buildInvocationTags)(agentInvocation);
|
|
1037
1096
|
const agentTags = modeLabel ? [modeLabel, ...invocationTags] : invocationTags;
|
|
1038
1097
|
const detailBase = {
|
|
1039
1098
|
displayName,
|
|
@@ -1113,7 +1172,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1113
1172
|
origBgOnSession(session);
|
|
1114
1173
|
const rec = manager.getRecord(id);
|
|
1115
1174
|
if (rec?.outputFile) {
|
|
1116
|
-
rec.outputCleanup = streamToOutputFile(session, rec.outputFile, id, ctx.cwd);
|
|
1175
|
+
rec.outputCleanup = (0, output_file_js_1.streamToOutputFile)(session, rec.outputFile, id, ctx.cwd);
|
|
1117
1176
|
}
|
|
1118
1177
|
};
|
|
1119
1178
|
try {
|
|
@@ -1135,7 +1194,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1135
1194
|
}
|
|
1136
1195
|
// Set output file + join mode synchronously after spawn, before the
|
|
1137
1196
|
// event loop yields — onSessionCreated is async so this is safe.
|
|
1138
|
-
const joinMode = resolveJoinMode(defaultJoinMode, true);
|
|
1197
|
+
const joinMode = (0, invocation_config_js_1.resolveJoinMode)(defaultJoinMode, true);
|
|
1139
1198
|
const record = manager.getRecord(id);
|
|
1140
1199
|
if (record && joinMode) {
|
|
1141
1200
|
record.joinMode = joinMode;
|
|
@@ -1190,8 +1249,8 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1190
1249
|
maxTurns: fgState.maxTurns,
|
|
1191
1250
|
durationMs: Date.now() - startedAt,
|
|
1192
1251
|
status: "running",
|
|
1193
|
-
activity: describeActivity(fgState.activeTools, fgState.responseText),
|
|
1194
|
-
spinnerFrame: spinnerFrame % SPINNER.length,
|
|
1252
|
+
activity: (0, agent_widget_js_1.describeActivity)(fgState.activeTools, fgState.responseText),
|
|
1253
|
+
spinnerFrame: spinnerFrame % agent_widget_js_1.SPINNER.length,
|
|
1195
1254
|
};
|
|
1196
1255
|
onUpdate?.({
|
|
1197
1256
|
content: [{ type: "text", text: `${fgState.toolUses} tool uses...` }],
|
|
@@ -1219,7 +1278,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1219
1278
|
if (fgId) {
|
|
1220
1279
|
const rec = manager.getRecord(fgId);
|
|
1221
1280
|
if (rec?.outputFile) {
|
|
1222
|
-
rec.outputCleanup = streamToOutputFile(session, rec.outputFile, fgId, ctx.cwd);
|
|
1281
|
+
rec.outputCleanup = (0, output_file_js_1.streamToOutputFile)(session, rec.outputFile, fgId, ctx.cwd);
|
|
1223
1282
|
}
|
|
1224
1283
|
}
|
|
1225
1284
|
};
|
|
@@ -1267,7 +1326,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1267
1326
|
// "general-purpose" may itself be unregistered (defaults disabled, no
|
|
1268
1327
|
// user override) — getConfig then uses the hardcoded fallback config.
|
|
1269
1328
|
const fallbackNote = fellBack
|
|
1270
|
-
? `Note: Unknown agent type "${rawType}" — using ${resolveType("general-purpose") ? "general-purpose" : "the fallback agent config"}.\n\n`
|
|
1329
|
+
? `Note: Unknown agent type "${rawType}" — using ${(0, agent_types_js_1.resolveType)("general-purpose") ? "general-purpose" : "the fallback agent config"}.\n\n`
|
|
1271
1330
|
: "";
|
|
1272
1331
|
if (record.status === "error") {
|
|
1273
1332
|
// Error headline + any partial output the run produced before failing.
|
|
@@ -1277,24 +1336,24 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1277
1336
|
const statsParts = [`${record.toolUses} tool uses`];
|
|
1278
1337
|
if (tokenText)
|
|
1279
1338
|
statsParts.push(tokenText);
|
|
1280
|
-
return textResult(`${fallbackNote}Agent completed in ${formatMs(durationMs)} (${statsParts.join(", ")})${getStatusNote(record.status)}.\n\n` +
|
|
1339
|
+
return textResult(`${fallbackNote}Agent completed in ${(0, agent_widget_js_1.formatMs)(durationMs)} (${statsParts.join(", ")})${(0, status_note_js_1.getStatusNote)(record.status)}.\n\n` +
|
|
1281
1340
|
(record.result?.trim() || "No output."), details);
|
|
1282
1341
|
},
|
|
1283
1342
|
}));
|
|
1284
1343
|
// ---- get_subagent_result tool ----
|
|
1285
|
-
pi.registerTool(defineTool({
|
|
1286
|
-
name: SUBAGENT_TOOL_NAMES.GET_RESULT,
|
|
1344
|
+
pi.registerTool((0, pi_coding_agent_1.defineTool)({
|
|
1345
|
+
name: agent_runner_js_1.SUBAGENT_TOOL_NAMES.GET_RESULT,
|
|
1287
1346
|
label: "Get Agent Result",
|
|
1288
1347
|
description: "Check status and retrieve results from a background agent. Use the agent ID returned by Agent with run_in_background.",
|
|
1289
1348
|
promptSnippet: "Check status and retrieve results from a background agent",
|
|
1290
|
-
parameters: Type.Object({
|
|
1291
|
-
agent_id: Type.String({
|
|
1349
|
+
parameters: typebox_1.Type.Object({
|
|
1350
|
+
agent_id: typebox_1.Type.String({
|
|
1292
1351
|
description: "The agent ID to check.",
|
|
1293
1352
|
}),
|
|
1294
|
-
wait: Type.Optional(Type.Boolean({
|
|
1353
|
+
wait: typebox_1.Type.Optional(typebox_1.Type.Boolean({
|
|
1295
1354
|
description: "If true, wait for the agent to complete before returning. Default: false.",
|
|
1296
1355
|
})),
|
|
1297
|
-
verbose: Type.Optional(Type.Boolean({
|
|
1356
|
+
verbose: typebox_1.Type.Optional(typebox_1.Type.Boolean({
|
|
1298
1357
|
description: "If true, include the agent's full conversation (messages + tool calls). Default: false.",
|
|
1299
1358
|
})),
|
|
1300
1359
|
}),
|
|
@@ -1315,10 +1374,10 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1315
1374
|
if (record.promise)
|
|
1316
1375
|
await abortable(record.promise, signal);
|
|
1317
1376
|
}
|
|
1318
|
-
const displayName = getDisplayName(record.type);
|
|
1319
|
-
const duration = formatDuration(record.startedAt, record.completedAt);
|
|
1377
|
+
const displayName = (0, agent_widget_js_1.getDisplayName)(record.type);
|
|
1378
|
+
const duration = (0, agent_widget_js_1.formatDuration)(record.startedAt, record.completedAt);
|
|
1320
1379
|
const tokens = formatLifetimeTokens(record);
|
|
1321
|
-
const contextPercent = getSessionContextPercent(record.session);
|
|
1380
|
+
const contextPercent = (0, usage_js_1.getSessionContextPercent)(record.session);
|
|
1322
1381
|
const statsParts = [`Tool uses: ${record.toolUses}`];
|
|
1323
1382
|
if (tokens)
|
|
1324
1383
|
statsParts.push(tokens);
|
|
@@ -1328,7 +1387,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1328
1387
|
statsParts.push(`Compactions: ${record.compactionCount}`);
|
|
1329
1388
|
statsParts.push(`Duration: ${duration}`);
|
|
1330
1389
|
let output = `Agent: ${record.id}\n` +
|
|
1331
|
-
`Type: ${displayName} | Status: ${record.status}${getStatusNote(record.status)} | ${statsParts.join(" | ")}\n` +
|
|
1390
|
+
`Type: ${displayName} | Status: ${record.status}${(0, status_note_js_1.getStatusNote)(record.status)} | ${statsParts.join(" | ")}\n` +
|
|
1332
1391
|
`Description: ${record.description}\n\n`;
|
|
1333
1392
|
if (record.status === "running") {
|
|
1334
1393
|
output += "Agent is still running. Use wait: true or check back later.";
|
|
@@ -1346,7 +1405,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1346
1405
|
}
|
|
1347
1406
|
// Verbose: include full conversation
|
|
1348
1407
|
if (params.verbose && record.session) {
|
|
1349
|
-
const conversation = getAgentConversation(record.session);
|
|
1408
|
+
const conversation = (0, agent_runner_js_1.getAgentConversation)(record.session);
|
|
1350
1409
|
if (conversation) {
|
|
1351
1410
|
output += `\n\n--- Agent Conversation ---\n${conversation}`;
|
|
1352
1411
|
}
|
|
@@ -1355,17 +1414,17 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1355
1414
|
},
|
|
1356
1415
|
}));
|
|
1357
1416
|
// ---- steer_subagent tool ----
|
|
1358
|
-
pi.registerTool(defineTool({
|
|
1359
|
-
name: SUBAGENT_TOOL_NAMES.STEER,
|
|
1417
|
+
pi.registerTool((0, pi_coding_agent_1.defineTool)({
|
|
1418
|
+
name: agent_runner_js_1.SUBAGENT_TOOL_NAMES.STEER,
|
|
1360
1419
|
label: "Steer Agent",
|
|
1361
1420
|
description: "Send a steering message to a running agent. The message will interrupt the agent after its current tool execution " +
|
|
1362
1421
|
"and be injected into its conversation, allowing you to redirect its work mid-run. Only works on running agents.",
|
|
1363
1422
|
promptSnippet: "Send a steering message to redirect a running background agent",
|
|
1364
|
-
parameters: Type.Object({
|
|
1365
|
-
agent_id: Type.String({
|
|
1423
|
+
parameters: typebox_1.Type.Object({
|
|
1424
|
+
agent_id: typebox_1.Type.String({
|
|
1366
1425
|
description: "The agent ID to steer (must be currently running).",
|
|
1367
1426
|
}),
|
|
1368
|
-
message: Type.String({
|
|
1427
|
+
message: typebox_1.Type.String({
|
|
1369
1428
|
description: "The steering message to send. This will appear as a user message in the agent's conversation.",
|
|
1370
1429
|
}),
|
|
1371
1430
|
}),
|
|
@@ -1386,10 +1445,10 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1386
1445
|
return textResult(`Steering message queued for agent ${record.id}. It will be delivered once the session initializes.`);
|
|
1387
1446
|
}
|
|
1388
1447
|
try {
|
|
1389
|
-
await steerAgent(record.session, params.message);
|
|
1448
|
+
await (0, agent_runner_js_1.steerAgent)(record.session, params.message);
|
|
1390
1449
|
pi.events.emit("subagents:steered", { id: record.id, message: params.message });
|
|
1391
1450
|
const tokens = formatLifetimeTokens(record);
|
|
1392
|
-
const contextPercent = getSessionContextPercent(record.session);
|
|
1451
|
+
const contextPercent = (0, usage_js_1.getSessionContextPercent)(record.session);
|
|
1393
1452
|
const stateParts = [];
|
|
1394
1453
|
if (tokens)
|
|
1395
1454
|
stateParts.push(tokens);
|
|
@@ -1407,30 +1466,30 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1407
1466
|
},
|
|
1408
1467
|
}));
|
|
1409
1468
|
// ---- /agents interactive menu ----
|
|
1410
|
-
const projectAgentsDir = () => join(process.cwd(), ".pi", "agents");
|
|
1411
|
-
const workspaceAgentsDir = () => join(process.cwd(), ".agents", "agents");
|
|
1412
|
-
const personalAgentsDir = () => join(getAgentDir(), "agents");
|
|
1469
|
+
const projectAgentsDir = () => (0, node_path_1.join)(process.cwd(), ".pi", "agents");
|
|
1470
|
+
const workspaceAgentsDir = () => (0, node_path_1.join)(process.cwd(), ".agents", "agents");
|
|
1471
|
+
const personalAgentsDir = () => (0, node_path_1.join)((0, pi_coding_agent_1.getAgentDir)(), "agents");
|
|
1413
1472
|
/** Find the file path of a custom agent by name, in discovery-precedence order (project, workspace, then global). */
|
|
1414
1473
|
function findAgentFile(name) {
|
|
1415
|
-
const projectPath = join(projectAgentsDir(), `${name}.md`);
|
|
1416
|
-
if (existsSync(projectPath))
|
|
1474
|
+
const projectPath = (0, node_path_1.join)(projectAgentsDir(), `${name}.md`);
|
|
1475
|
+
if ((0, node_fs_1.existsSync)(projectPath))
|
|
1417
1476
|
return { path: projectPath, location: "project" };
|
|
1418
|
-
const workspacePath = join(workspaceAgentsDir(), `${name}.md`);
|
|
1419
|
-
if (existsSync(workspacePath))
|
|
1477
|
+
const workspacePath = (0, node_path_1.join)(workspaceAgentsDir(), `${name}.md`);
|
|
1478
|
+
if ((0, node_fs_1.existsSync)(workspacePath))
|
|
1420
1479
|
return { path: workspacePath, location: "workspace" };
|
|
1421
|
-
const personalPath = join(personalAgentsDir(), `${name}.md`);
|
|
1422
|
-
if (existsSync(personalPath))
|
|
1480
|
+
const personalPath = (0, node_path_1.join)(personalAgentsDir(), `${name}.md`);
|
|
1481
|
+
if ((0, node_fs_1.existsSync)(personalPath))
|
|
1423
1482
|
return { path: personalPath, location: "personal" };
|
|
1424
1483
|
return undefined;
|
|
1425
1484
|
}
|
|
1426
1485
|
function getModelLabel(type, registry) {
|
|
1427
|
-
const cfg = getAgentConfig(type);
|
|
1486
|
+
const cfg = (0, agent_types_js_1.getAgentConfig)(type);
|
|
1428
1487
|
if (!cfg?.model)
|
|
1429
1488
|
return "inherit"; // no model configured → really inherits parent
|
|
1430
1489
|
const label = getModelLabelFromConfig(cfg.model);
|
|
1431
1490
|
if (!registry)
|
|
1432
1491
|
return label;
|
|
1433
|
-
const resolved = resolveModel(cfg.model, registry);
|
|
1492
|
+
const resolved = (0, model_resolver_js_1.resolveModel)(cfg.model, registry);
|
|
1434
1493
|
// Configured but unresolvable: the runtime silently falls back to the parent
|
|
1435
1494
|
// model, so flag it (and the fallback) rather than hiding the config.
|
|
1436
1495
|
if (typeof resolved === "string")
|
|
@@ -1446,7 +1505,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1446
1505
|
}
|
|
1447
1506
|
async function showAgentsMenu(ctx) {
|
|
1448
1507
|
reloadCustomAgents();
|
|
1449
|
-
const allNames = getAllTypes();
|
|
1508
|
+
const allNames = (0, agent_types_js_1.getAllTypes)();
|
|
1450
1509
|
// Build select options
|
|
1451
1510
|
const options = [];
|
|
1452
1511
|
// Running agents entry (only if there are active agents)
|
|
@@ -1488,7 +1547,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1488
1547
|
await showAgentsMenu(ctx);
|
|
1489
1548
|
}
|
|
1490
1549
|
else if (choice.startsWith("Scheduled jobs (")) {
|
|
1491
|
-
await showSchedulesMenu(ctx, scheduler);
|
|
1550
|
+
await (0, schedule_menu_js_1.showSchedulesMenu)(ctx, scheduler);
|
|
1492
1551
|
await showAgentsMenu(ctx);
|
|
1493
1552
|
}
|
|
1494
1553
|
else if (choice === "Create new agent") {
|
|
@@ -1500,7 +1559,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1500
1559
|
}
|
|
1501
1560
|
}
|
|
1502
1561
|
async function showAllAgentsList(ctx) {
|
|
1503
|
-
const allNames = getAllTypes();
|
|
1562
|
+
const allNames = (0, agent_types_js_1.getAllTypes)();
|
|
1504
1563
|
if (allNames.length === 0) {
|
|
1505
1564
|
ctx.ui.notify("No agents.", "info");
|
|
1506
1565
|
return;
|
|
@@ -1521,7 +1580,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1521
1580
|
// full description renders below the highlighted row via SettingsList,
|
|
1522
1581
|
// exactly like the Settings menu — so long descriptions never wrap the list.
|
|
1523
1582
|
const items = allNames.map(name => {
|
|
1524
|
-
const cfg = getAgentConfig(name);
|
|
1583
|
+
const cfg = (0, agent_types_js_1.getAgentConfig)(name);
|
|
1525
1584
|
const disabled = cfg?.enabled === false;
|
|
1526
1585
|
const model = getModelLabel(name, ctx.modelRegistry);
|
|
1527
1586
|
return {
|
|
@@ -1534,22 +1593,22 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1534
1593
|
values: [model],
|
|
1535
1594
|
};
|
|
1536
1595
|
});
|
|
1537
|
-
const hasCustom = allNames.some(n => { const c = getAgentConfig(n); return c && !c.isDefault && c.enabled !== false; });
|
|
1538
|
-
const hasDisabled = allNames.some(n => getAgentConfig(n)?.enabled === false);
|
|
1596
|
+
const hasCustom = allNames.some(n => { const c = (0, agent_types_js_1.getAgentConfig)(n); return c && !c.isDefault && c.enabled !== false; });
|
|
1597
|
+
const hasDisabled = allNames.some(n => (0, agent_types_js_1.getAgentConfig)(n)?.enabled === false);
|
|
1539
1598
|
const legendParts = [];
|
|
1540
1599
|
if (hasCustom)
|
|
1541
1600
|
legendParts.push("• = project ◦ = global");
|
|
1542
1601
|
if (hasDisabled)
|
|
1543
1602
|
legendParts.push("✕ = disabled");
|
|
1544
1603
|
const selected = await ctx.ui.custom((_tui, _theme, _kb, done) => {
|
|
1545
|
-
const slTheme = getSettingsListTheme();
|
|
1546
|
-
const list = new SettingsList(items, Math.min(items.length, 12), slTheme, id => done(id), // Enter/Space on a row → return that agent's name
|
|
1604
|
+
const slTheme = (0, pi_coding_agent_1.getSettingsListTheme)();
|
|
1605
|
+
const list = new pi_tui_1.SettingsList(items, Math.min(items.length, 12), slTheme, id => done(id), // Enter/Space on a row → return that agent's name
|
|
1547
1606
|
() => done(undefined));
|
|
1548
|
-
const container = new Container();
|
|
1549
|
-
container.addChild(new Text("Agent types", 0, 0));
|
|
1607
|
+
const container = new pi_tui_1.Container();
|
|
1608
|
+
container.addChild(new pi_tui_1.Text("Agent types", 0, 0));
|
|
1550
1609
|
if (legendParts.length)
|
|
1551
|
-
container.addChild(new Text(slTheme.hint(legendParts.join(" ")), 0, 0));
|
|
1552
|
-
container.addChild(new Spacer(1));
|
|
1610
|
+
container.addChild(new pi_tui_1.Text(slTheme.hint(legendParts.join(" ")), 0, 0));
|
|
1611
|
+
container.addChild(new pi_tui_1.Spacer(1));
|
|
1553
1612
|
container.addChild(list);
|
|
1554
1613
|
return {
|
|
1555
1614
|
render: (w) => container.render(w),
|
|
@@ -1557,7 +1616,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1557
1616
|
handleInput: (data) => list.handleInput?.(data),
|
|
1558
1617
|
};
|
|
1559
1618
|
});
|
|
1560
|
-
if (selected && getAgentConfig(selected)) {
|
|
1619
|
+
if (selected && (0, agent_types_js_1.getAgentConfig)(selected)) {
|
|
1561
1620
|
await showAgentDetail(ctx, selected);
|
|
1562
1621
|
await showAllAgentsList(ctx);
|
|
1563
1622
|
}
|
|
@@ -1569,8 +1628,8 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1569
1628
|
return;
|
|
1570
1629
|
}
|
|
1571
1630
|
const options = agents.map(a => {
|
|
1572
|
-
const dn = getDisplayName(a.type);
|
|
1573
|
-
const dur = formatDuration(a.startedAt, a.completedAt);
|
|
1631
|
+
const dn = (0, agent_widget_js_1.getDisplayName)(a.type);
|
|
1632
|
+
const dur = (0, agent_widget_js_1.formatDuration)(a.startedAt, a.completedAt);
|
|
1574
1633
|
return `${dn} (${a.description}) · ${a.toolUses} tools · ${a.status} · ${dur}`;
|
|
1575
1634
|
});
|
|
1576
1635
|
const choice = await ctx.ui.select("Running agents", options);
|
|
@@ -1590,7 +1649,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1590
1649
|
ctx.ui.notify(`Agent is ${record.status === "queued" ? "queued" : "expired"} — no session available.`, "info");
|
|
1591
1650
|
return;
|
|
1592
1651
|
}
|
|
1593
|
-
const { ConversationViewer, VIEWPORT_HEIGHT_PCT } = await
|
|
1652
|
+
const { ConversationViewer, VIEWPORT_HEIGHT_PCT } = await Promise.resolve().then(() => __importStar(require("./ui/conversation-viewer.js")));
|
|
1594
1653
|
const session = record.session;
|
|
1595
1654
|
const activity = agentActivity.get(record.id);
|
|
1596
1655
|
await ctx.ui.custom((tui, theme, keybindings, done) => {
|
|
@@ -1605,7 +1664,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1605
1664
|
});
|
|
1606
1665
|
}
|
|
1607
1666
|
async function showAgentDetail(ctx, name) {
|
|
1608
|
-
const cfg = getAgentConfig(name);
|
|
1667
|
+
const cfg = (0, agent_types_js_1.getAgentConfig)(name);
|
|
1609
1668
|
if (!cfg) {
|
|
1610
1669
|
ctx.ui.notify(`Agent config not found for "${name}".`, "warning");
|
|
1611
1670
|
return;
|
|
@@ -1636,10 +1695,10 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1636
1695
|
if (!choice || choice === "Back")
|
|
1637
1696
|
return;
|
|
1638
1697
|
if (choice === "Edit" && file) {
|
|
1639
|
-
const content = readFileSync(file.path, "utf-8");
|
|
1698
|
+
const content = (0, node_fs_1.readFileSync)(file.path, "utf-8");
|
|
1640
1699
|
const edited = await ctx.ui.editor(`Edit ${name}`, content);
|
|
1641
1700
|
if (edited !== undefined && edited !== content) {
|
|
1642
|
-
const { writeFileSync } = await
|
|
1701
|
+
const { writeFileSync } = await Promise.resolve().then(() => __importStar(require("node:fs")));
|
|
1643
1702
|
writeFileSync(file.path, edited, "utf-8");
|
|
1644
1703
|
reloadCustomAgents();
|
|
1645
1704
|
ctx.ui.notify(`Updated ${file.path}`, "info");
|
|
@@ -1649,7 +1708,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1649
1708
|
if (file) {
|
|
1650
1709
|
const confirmed = await ctx.ui.confirm("Delete agent", `Delete ${name} from ${file.location} (${file.path})?`);
|
|
1651
1710
|
if (confirmed) {
|
|
1652
|
-
unlinkSync(file.path);
|
|
1711
|
+
(0, node_fs_1.unlinkSync)(file.path);
|
|
1653
1712
|
reloadCustomAgents();
|
|
1654
1713
|
ctx.ui.notify(`Deleted ${file.path}`, "info");
|
|
1655
1714
|
}
|
|
@@ -1658,7 +1717,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1658
1717
|
else if (choice === "Reset to default" && file) {
|
|
1659
1718
|
const confirmed = await ctx.ui.confirm("Reset to default", `Delete override ${file.path} and restore embedded default?`);
|
|
1660
1719
|
if (confirmed) {
|
|
1661
|
-
unlinkSync(file.path);
|
|
1720
|
+
(0, node_fs_1.unlinkSync)(file.path);
|
|
1662
1721
|
reloadCustomAgents();
|
|
1663
1722
|
ctx.ui.notify(`Restored default ${name}`, "info");
|
|
1664
1723
|
}
|
|
@@ -1682,9 +1741,9 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1682
1741
|
if (!location)
|
|
1683
1742
|
return;
|
|
1684
1743
|
const targetDir = location.startsWith("Project") ? projectAgentsDir() : personalAgentsDir();
|
|
1685
|
-
mkdirSync(targetDir, { recursive: true });
|
|
1686
|
-
const targetPath = join(targetDir, `${name}.md`);
|
|
1687
|
-
if (existsSync(targetPath)) {
|
|
1744
|
+
(0, node_fs_1.mkdirSync)(targetDir, { recursive: true });
|
|
1745
|
+
const targetPath = (0, node_path_1.join)(targetDir, `${name}.md`);
|
|
1746
|
+
if ((0, node_fs_1.existsSync)(targetPath)) {
|
|
1688
1747
|
const overwrite = await ctx.ui.confirm("Overwrite", `${targetPath} already exists. Overwrite?`);
|
|
1689
1748
|
if (!overwrite)
|
|
1690
1749
|
return;
|
|
@@ -1727,7 +1786,7 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1727
1786
|
if (cfg.isolation)
|
|
1728
1787
|
fmFields.push(`isolation: ${cfg.isolation}`);
|
|
1729
1788
|
const content = `---\n${fmFields.join("\n")}\n---\n\n${cfg.systemPrompt}\n`;
|
|
1730
|
-
const { writeFileSync } = await
|
|
1789
|
+
const { writeFileSync } = await Promise.resolve().then(() => __importStar(require("node:fs")));
|
|
1731
1790
|
writeFileSync(targetPath, content, "utf-8");
|
|
1732
1791
|
reloadCustomAgents();
|
|
1733
1792
|
ctx.ui.notify(`Ejected ${name} to ${targetPath}`, "info");
|
|
@@ -1737,13 +1796,13 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1737
1796
|
const file = findAgentFile(name);
|
|
1738
1797
|
if (file) {
|
|
1739
1798
|
// Existing file — set enabled: false in frontmatter (idempotent)
|
|
1740
|
-
const content = readFileSync(file.path, "utf-8");
|
|
1799
|
+
const content = (0, node_fs_1.readFileSync)(file.path, "utf-8");
|
|
1741
1800
|
if (content.includes("\nenabled: false\n")) {
|
|
1742
1801
|
ctx.ui.notify(`${name} is already disabled.`, "info");
|
|
1743
1802
|
return;
|
|
1744
1803
|
}
|
|
1745
1804
|
const updated = content.replace(/^---\n/, "---\nenabled: false\n");
|
|
1746
|
-
const { writeFileSync } = await
|
|
1805
|
+
const { writeFileSync } = await Promise.resolve().then(() => __importStar(require("node:fs")));
|
|
1747
1806
|
writeFileSync(file.path, updated, "utf-8");
|
|
1748
1807
|
reloadCustomAgents();
|
|
1749
1808
|
ctx.ui.notify(`Disabled ${name} (${file.path})`, "info");
|
|
@@ -1757,9 +1816,9 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1757
1816
|
if (!location)
|
|
1758
1817
|
return;
|
|
1759
1818
|
const targetDir = location.startsWith("Project") ? projectAgentsDir() : personalAgentsDir();
|
|
1760
|
-
mkdirSync(targetDir, { recursive: true });
|
|
1761
|
-
const targetPath = join(targetDir, `${name}.md`);
|
|
1762
|
-
const { writeFileSync } = await
|
|
1819
|
+
(0, node_fs_1.mkdirSync)(targetDir, { recursive: true });
|
|
1820
|
+
const targetPath = (0, node_path_1.join)(targetDir, `${name}.md`);
|
|
1821
|
+
const { writeFileSync } = await Promise.resolve().then(() => __importStar(require("node:fs")));
|
|
1763
1822
|
writeFileSync(targetPath, "---\nenabled: false\n---\n", "utf-8");
|
|
1764
1823
|
reloadCustomAgents();
|
|
1765
1824
|
ctx.ui.notify(`Disabled ${name} (${targetPath})`, "info");
|
|
@@ -1769,12 +1828,12 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1769
1828
|
const file = findAgentFile(name);
|
|
1770
1829
|
if (!file)
|
|
1771
1830
|
return;
|
|
1772
|
-
const content = readFileSync(file.path, "utf-8");
|
|
1831
|
+
const content = (0, node_fs_1.readFileSync)(file.path, "utf-8");
|
|
1773
1832
|
const updated = content.replace(/^(---\n)enabled: false\n/, "$1");
|
|
1774
|
-
const { writeFileSync } = await
|
|
1833
|
+
const { writeFileSync } = await Promise.resolve().then(() => __importStar(require("node:fs")));
|
|
1775
1834
|
// If the file was just a stub ("---\n---\n"), delete it to restore the built-in default
|
|
1776
1835
|
if (updated.trim() === "---\n---" || updated.trim() === "---\n---\n") {
|
|
1777
|
-
unlinkSync(file.path);
|
|
1836
|
+
(0, node_fs_1.unlinkSync)(file.path);
|
|
1778
1837
|
reloadCustomAgents();
|
|
1779
1838
|
ctx.ui.notify(`Enabled ${name} (removed ${file.path})`, "info");
|
|
1780
1839
|
}
|
|
@@ -1812,9 +1871,9 @@ Terse command-style prompts produce shallow, generic work.
|
|
|
1812
1871
|
const name = await ctx.ui.input("Agent name (filename, no spaces)");
|
|
1813
1872
|
if (!name)
|
|
1814
1873
|
return;
|
|
1815
|
-
mkdirSync(targetDir, { recursive: true });
|
|
1816
|
-
const targetPath = join(targetDir, `${name}.md`);
|
|
1817
|
-
if (existsSync(targetPath)) {
|
|
1874
|
+
(0, node_fs_1.mkdirSync)(targetDir, { recursive: true });
|
|
1875
|
+
const targetPath = (0, node_path_1.join)(targetDir, `${name}.md`);
|
|
1876
|
+
if ((0, node_fs_1.existsSync)(targetPath)) {
|
|
1818
1877
|
const overwrite = await ctx.ui.confirm("Overwrite", `${targetPath} already exists. Overwrite?`);
|
|
1819
1878
|
if (!overwrite)
|
|
1820
1879
|
return;
|
|
@@ -1868,7 +1927,7 @@ Write the file using the write tool. Only write the file, nothing else.`;
|
|
|
1868
1927
|
return;
|
|
1869
1928
|
}
|
|
1870
1929
|
reloadCustomAgents();
|
|
1871
|
-
if (existsSync(targetPath)) {
|
|
1930
|
+
if ((0, node_fs_1.existsSync)(targetPath)) {
|
|
1872
1931
|
ctx.ui.notify(`Created ${targetPath}`, "info");
|
|
1873
1932
|
}
|
|
1874
1933
|
else {
|
|
@@ -1890,7 +1949,7 @@ Write the file using the write tool. Only write the file, nothing else.`;
|
|
|
1890
1949
|
return;
|
|
1891
1950
|
let tools;
|
|
1892
1951
|
if (toolChoice === "all") {
|
|
1893
|
-
tools = BUILTIN_TOOL_NAMES.join(", ");
|
|
1952
|
+
tools = agent_types_js_1.BUILTIN_TOOL_NAMES.join(", ");
|
|
1894
1953
|
}
|
|
1895
1954
|
else if (toolChoice === "none") {
|
|
1896
1955
|
tools = "none";
|
|
@@ -1899,7 +1958,7 @@ Write the file using the write tool. Only write the file, nothing else.`;
|
|
|
1899
1958
|
tools = "read, bash, grep, find, ls";
|
|
1900
1959
|
}
|
|
1901
1960
|
else {
|
|
1902
|
-
const customTools = await ctx.ui.input("Tools (comma-separated)", BUILTIN_TOOL_NAMES.join(", "));
|
|
1961
|
+
const customTools = await ctx.ui.input("Tools (comma-separated)", agent_types_js_1.BUILTIN_TOOL_NAMES.join(", "));
|
|
1903
1962
|
if (!customTools)
|
|
1904
1963
|
return;
|
|
1905
1964
|
tools = customTools;
|
|
@@ -1947,14 +2006,14 @@ prompt_mode: replace
|
|
|
1947
2006
|
|
|
1948
2007
|
${systemPrompt}
|
|
1949
2008
|
`;
|
|
1950
|
-
mkdirSync(targetDir, { recursive: true });
|
|
1951
|
-
const targetPath = join(targetDir, `${name}.md`);
|
|
1952
|
-
if (existsSync(targetPath)) {
|
|
2009
|
+
(0, node_fs_1.mkdirSync)(targetDir, { recursive: true });
|
|
2010
|
+
const targetPath = (0, node_path_1.join)(targetDir, `${name}.md`);
|
|
2011
|
+
if ((0, node_fs_1.existsSync)(targetPath)) {
|
|
1953
2012
|
const overwrite = await ctx.ui.confirm("Overwrite", `${targetPath} already exists. Overwrite?`);
|
|
1954
2013
|
if (!overwrite)
|
|
1955
2014
|
return;
|
|
1956
2015
|
}
|
|
1957
|
-
const { writeFileSync } = await
|
|
2016
|
+
const { writeFileSync } = await Promise.resolve().then(() => __importStar(require("node:fs")));
|
|
1958
2017
|
writeFileSync(targetPath, content, "utf-8");
|
|
1959
2018
|
reloadCustomAgents();
|
|
1960
2019
|
ctx.ui.notify(`Created ${targetPath}`, "info");
|
|
@@ -1964,12 +2023,12 @@ ${systemPrompt}
|
|
|
1964
2023
|
maxConcurrent: manager.getMaxConcurrent(),
|
|
1965
2024
|
// 0 = unlimited — per SubagentsSettings.defaultMaxTurns docstring and
|
|
1966
2025
|
// normalizeMaxTurns() in agent-runner.ts (which maps 0 → undefined).
|
|
1967
|
-
defaultMaxTurns: getDefaultMaxTurns() ?? 0,
|
|
1968
|
-
graceTurns: getGraceTurns(),
|
|
2026
|
+
defaultMaxTurns: (0, agent_runner_js_1.getDefaultMaxTurns)() ?? 0,
|
|
2027
|
+
graceTurns: (0, agent_runner_js_1.getGraceTurns)(),
|
|
1969
2028
|
defaultJoinMode: getDefaultJoinMode(),
|
|
1970
2029
|
schedulingEnabled: isSchedulingEnabled(),
|
|
1971
2030
|
scopeModels: isScopeModelsEnabled(),
|
|
1972
|
-
disableDefaultAgents: isDefaultsDisabled(),
|
|
2031
|
+
disableDefaultAgents: (0, agent_types_js_1.isDefaultsDisabled)(),
|
|
1973
2032
|
toolDescriptionMode: getToolDescriptionMode(),
|
|
1974
2033
|
fleetView: isFleetViewEnabled(),
|
|
1975
2034
|
widgetMode: getWidgetMode(),
|
|
@@ -1980,8 +2039,8 @@ ${systemPrompt}
|
|
|
1980
2039
|
async function showSettings(ctx) {
|
|
1981
2040
|
function buildItems() {
|
|
1982
2041
|
const mc = manager.getMaxConcurrent();
|
|
1983
|
-
const dmt = getDefaultMaxTurns() ?? 0;
|
|
1984
|
-
const gt = getGraceTurns();
|
|
2042
|
+
const dmt = (0, agent_runner_js_1.getDefaultMaxTurns)() ?? 0;
|
|
2043
|
+
const gt = (0, agent_runner_js_1.getGraceTurns)();
|
|
1985
2044
|
return [
|
|
1986
2045
|
{
|
|
1987
2046
|
id: "maxConcurrent",
|
|
@@ -2029,7 +2088,7 @@ ${systemPrompt}
|
|
|
2029
2088
|
id: "disableDefaultAgents",
|
|
2030
2089
|
label: "Disable defaults",
|
|
2031
2090
|
description: "Hide built-in agents (general-purpose, Explore, Plan) — custom agents are unaffected",
|
|
2032
|
-
currentValue: isDefaultsDisabled() ? "on" : "off",
|
|
2091
|
+
currentValue: (0, agent_types_js_1.isDefaultsDisabled)() ? "on" : "off",
|
|
2033
2092
|
values: ["on", "off"],
|
|
2034
2093
|
},
|
|
2035
2094
|
{
|
|
@@ -2073,18 +2132,18 @@ ${systemPrompt}
|
|
|
2073
2132
|
else if (id === "defaultMaxTurns") {
|
|
2074
2133
|
const n = parseInt(value, 10);
|
|
2075
2134
|
if (n === 0) {
|
|
2076
|
-
setDefaultMaxTurns(undefined);
|
|
2135
|
+
(0, agent_runner_js_1.setDefaultMaxTurns)(undefined);
|
|
2077
2136
|
notifyApplied(ctx, "Default max turns set to unlimited");
|
|
2078
2137
|
}
|
|
2079
2138
|
else if (n >= 1) {
|
|
2080
|
-
setDefaultMaxTurns(n);
|
|
2139
|
+
(0, agent_runner_js_1.setDefaultMaxTurns)(n);
|
|
2081
2140
|
notifyApplied(ctx, `Default max turns set to ${n}`);
|
|
2082
2141
|
}
|
|
2083
2142
|
}
|
|
2084
2143
|
else if (id === "graceTurns") {
|
|
2085
2144
|
const n = parseInt(value, 10);
|
|
2086
2145
|
if (n >= 1) {
|
|
2087
|
-
setGraceTurns(n);
|
|
2146
|
+
(0, agent_runner_js_1.setGraceTurns)(n);
|
|
2088
2147
|
notifyApplied(ctx, `Grace turns set to ${n}`);
|
|
2089
2148
|
}
|
|
2090
2149
|
}
|
|
@@ -2139,26 +2198,26 @@ ${systemPrompt}
|
|
|
2139
2198
|
let currentIndex = 0;
|
|
2140
2199
|
const result = await ctx.ui.custom((_tui, _theme, _kb, done) => {
|
|
2141
2200
|
const items = buildItems();
|
|
2142
|
-
list = new SettingsList(items, items.length + 2, getSettingsListTheme(), (id, newValue) => {
|
|
2201
|
+
list = new pi_tui_1.SettingsList(items, items.length + 2, (0, pi_coding_agent_1.getSettingsListTheme)(), (id, newValue) => {
|
|
2143
2202
|
applyValue(id, newValue);
|
|
2144
2203
|
}, () => done(undefined));
|
|
2145
|
-
const container = new Container();
|
|
2146
|
-
container.addChild(new Text("⚙ Subagent Settings", 0, 0));
|
|
2147
|
-
container.addChild(new Spacer(1));
|
|
2204
|
+
const container = new pi_tui_1.Container();
|
|
2205
|
+
container.addChild(new pi_tui_1.Text("⚙ Subagent Settings", 0, 0));
|
|
2206
|
+
container.addChild(new pi_tui_1.Spacer(1));
|
|
2148
2207
|
container.addChild(list);
|
|
2149
2208
|
return {
|
|
2150
2209
|
render: (w) => container.render(w),
|
|
2151
2210
|
invalidate: () => container.invalidate(),
|
|
2152
2211
|
handleInput: (data) => {
|
|
2153
2212
|
// Track navigation so Enter knows the current field
|
|
2154
|
-
if (matchesKey(data, "up")) {
|
|
2213
|
+
if ((0, pi_tui_1.matchesKey)(data, "up")) {
|
|
2155
2214
|
currentIndex = Math.max(0, currentIndex - 1);
|
|
2156
2215
|
}
|
|
2157
|
-
else if (matchesKey(data, "down")) {
|
|
2216
|
+
else if ((0, pi_tui_1.matchesKey)(data, "down")) {
|
|
2158
2217
|
currentIndex = Math.min(items.length - 1, currentIndex + 1);
|
|
2159
2218
|
}
|
|
2160
2219
|
// Enter on numeric field → close and prompt for typed input
|
|
2161
|
-
if (matchesKey(data, Key.enter) && NUMERIC_IDS.has(items[currentIndex].id)) {
|
|
2220
|
+
if ((0, pi_tui_1.matchesKey)(data, pi_tui_1.Key.enter) && NUMERIC_IDS.has(items[currentIndex].id)) {
|
|
2162
2221
|
done(items[currentIndex].id);
|
|
2163
2222
|
return;
|
|
2164
2223
|
}
|
|
@@ -2171,8 +2230,8 @@ ${systemPrompt}
|
|
|
2171
2230
|
const current = result === "maxConcurrent"
|
|
2172
2231
|
? String(manager.getMaxConcurrent())
|
|
2173
2232
|
: result === "defaultMaxTurns"
|
|
2174
|
-
? String(getDefaultMaxTurns() ?? 0)
|
|
2175
|
-
: String(getGraceTurns());
|
|
2233
|
+
? String((0, agent_runner_js_1.getDefaultMaxTurns)() ?? 0)
|
|
2234
|
+
: String((0, agent_runner_js_1.getGraceTurns)());
|
|
2176
2235
|
const label = result === "maxConcurrent"
|
|
2177
2236
|
? "Max concurrency (1+)"
|
|
2178
2237
|
: result === "defaultMaxTurns"
|
|
@@ -2199,7 +2258,7 @@ ${systemPrompt}
|
|
|
2199
2258
|
// to warning so users aren't silently reverted on restart. Event fires regardless
|
|
2200
2259
|
// of outcome so listeners see the in-memory change.
|
|
2201
2260
|
function notifyApplied(ctx, successMsg) {
|
|
2202
|
-
const { message, level } = saveAndEmitChanged(snapshotSettings(), successMsg, (event, payload) => pi.events.emit(event, payload));
|
|
2261
|
+
const { message, level } = (0, settings_js_1.saveAndEmitChanged)(snapshotSettings(), successMsg, (event, payload) => pi.events.emit(event, payload));
|
|
2203
2262
|
ctx.ui.notify(message, level);
|
|
2204
2263
|
}
|
|
2205
2264
|
pi.registerCommand("agents", {
|