@bacnh85/pi-subagent 0.16.0 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/extensions/index.ts +22 -1
- package/extensions/roles-panel.ts +32 -4
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.16.1 (2026-08-29)
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `/subagent` argument completion: keywords (`list|all|agents|roles|reload|
|
|
8
|
+
refresh|history`), discovered agent names, and `@role` refs.
|
|
9
|
+
- Roles editor rows now offer inline model suggestions (Tab to pick, Enter
|
|
10
|
+
keeps typed text) when run against @bacnh85/pi-config-panel >= 0.1.1; the
|
|
11
|
+
package stays compilable and fully functional on 0.1.0 (suggestions simply
|
|
12
|
+
absent), so no dependency floor bump is required.
|
|
13
|
+
|
|
3
14
|
## 0.16.0 (2026-08-23)
|
|
4
15
|
|
|
5
16
|
### Features
|
package/extensions/index.ts
CHANGED
|
@@ -329,6 +329,20 @@ export default function (pi: ExtensionAPI) {
|
|
|
329
329
|
});
|
|
330
330
|
pi.registerCommand("subagent", {
|
|
331
331
|
description: "Configure model roles (/subagent), list agents (/subagent list), agent details (/subagent <name>), role detail (/subagent @role), reload definitions (/subagent reload), history (/subagent history)",
|
|
332
|
+
getArgumentCompletions: (prefix) => {
|
|
333
|
+
const ctx = currentCtx;
|
|
334
|
+
const keywords = ["list", "all", "agents", "roles", "reload", "refresh", "history"];
|
|
335
|
+
const vocab = [...keywords];
|
|
336
|
+
if (ctx) {
|
|
337
|
+
const discovery = discoverAgents(ctx.cwd, "both", bundledAgentsDir);
|
|
338
|
+
vocab.push(...discovery.agents.map((a) => a.name));
|
|
339
|
+
try { vocab.push(...Object.keys(readSubagentRoles(ctx).roles).map((r) => `@${r}`)); } catch { /* roles optional */ }
|
|
340
|
+
}
|
|
341
|
+
const q = prefix.trim().toLowerCase();
|
|
342
|
+
const items = vocab.filter((v) => v.toLowerCase().startsWith(q))
|
|
343
|
+
.map((v) => ({ value: v, label: v, description: keywords.includes(v) ? "subagent command" : "agent / role" }));
|
|
344
|
+
return items.length > 0 ? items : null;
|
|
345
|
+
},
|
|
332
346
|
handler: async (args, ctx) => {
|
|
333
347
|
const cmd = args.trim().toLowerCase();
|
|
334
348
|
const discovery = discoverAgents(ctx.cwd, "both", bundledAgentsDir);
|
|
@@ -387,10 +401,17 @@ export default function (pi: ExtensionAPI) {
|
|
|
387
401
|
}
|
|
388
402
|
const current = readSubagentRolesGlobal();
|
|
389
403
|
const working = buildRolesPanelCfg(discovery.agents, current);
|
|
404
|
+
const panelOptions = {
|
|
405
|
+
models: () => {
|
|
406
|
+
try { return ctx.modelRegistry.getAvailable().map((m) => `${m.provider}/${m.id}`); }
|
|
407
|
+
catch { return []; }
|
|
408
|
+
},
|
|
409
|
+
roles: () => [...Object.keys(DEFAULT_ROLES), ...Object.keys(readSubagentRolesGlobal().roles)],
|
|
410
|
+
};
|
|
390
411
|
await openConfigPanel({
|
|
391
412
|
ctx,
|
|
392
413
|
cfg: working,
|
|
393
|
-
build: (cfg) => buildRows(cfg, discovery.agents),
|
|
414
|
+
build: (cfg) => buildRows(cfg, discovery.agents, panelOptions),
|
|
394
415
|
title: "Subagent model roles",
|
|
395
416
|
onSave: (saved, editedKeys) => {
|
|
396
417
|
if (!(saved && editedKeys && editedKeys.size > 0)) return;
|
|
@@ -14,6 +14,15 @@ import { homedir } from "node:os";
|
|
|
14
14
|
import { dirname, join } from "node:path";
|
|
15
15
|
import { row } from "@bacnh85/pi-config-panel";
|
|
16
16
|
import type { PanelGroup } from "@bacnh85/pi-config-panel";
|
|
17
|
+
|
|
18
|
+
// ponytail: local structural type — the kernel only reads value/label/
|
|
19
|
+
// description, so this stays compatible with the published 0.1.0 range while
|
|
20
|
+
// completion support ships in 0.1.1 (no static import of new kernel symbols).
|
|
21
|
+
interface CompletionItem {
|
|
22
|
+
value: string;
|
|
23
|
+
label?: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
}
|
|
17
26
|
import type { AgentConfig } from "./agents.ts";
|
|
18
27
|
import { DEFAULT_ROLES, readSubagentRoles, type RolesConfig } from "./roles.ts";
|
|
19
28
|
|
|
@@ -83,6 +92,14 @@ export interface RolesPanelCfg {
|
|
|
83
92
|
agentModels: Record<string, string>;
|
|
84
93
|
}
|
|
85
94
|
|
|
95
|
+
/** Completion sources for the panel's model rows (lazy — resolved per keypress). */
|
|
96
|
+
export interface RolesPanelOptions {
|
|
97
|
+
/** Available model refs (`provider/id`), sorted; may be empty before registry sync. */
|
|
98
|
+
models: () => string[];
|
|
99
|
+
/** Known role names (defaults + configured), offered as `@role` on agent rows. */
|
|
100
|
+
roles: () => string[];
|
|
101
|
+
}
|
|
102
|
+
|
|
86
103
|
/** Seed a working config from current effective settings + bundled agents. */
|
|
87
104
|
export function buildRolesPanelCfg(agents: AgentConfig[], current: RolesConfig): RolesPanelCfg {
|
|
88
105
|
const roleNames = new Set([...Object.keys(DEFAULT_ROLES), ...Object.keys(current.roles)]);
|
|
@@ -98,21 +115,32 @@ export function buildRolesPanelCfg(agents: AgentConfig[], current: RolesConfig):
|
|
|
98
115
|
return cfg;
|
|
99
116
|
}
|
|
100
117
|
|
|
101
|
-
/** Build panel groups. Role rows first, then one override row per agent.
|
|
102
|
-
|
|
118
|
+
/** Build panel groups. Role rows first, then one override row per agent.
|
|
119
|
+
* `options` adds inline model/@role completions when provided (optional so
|
|
120
|
+
* existing unit tests and non-TUI callers stay unchanged). */
|
|
121
|
+
export function buildRows(cfg: RolesPanelCfg, agents: AgentConfig[], options?: RolesPanelOptions): PanelGroup[] {
|
|
103
122
|
const defaultChain = (name: string) => Array.isArray(DEFAULT_ROLES[name]) ? (DEFAULT_ROLES[name] as string[]).join(", ") : String(DEFAULT_ROLES[name] ?? "");
|
|
123
|
+
const modelItems = (): CompletionItem[] =>
|
|
124
|
+
(options?.models() ?? []).sort().map((ref) => ({ value: ref }));
|
|
125
|
+
const roleItems = (): CompletionItem[] =>
|
|
126
|
+
(options?.roles() ?? []).map((name) => ({ value: `@${name}`, description: "role chain" }));
|
|
127
|
+
// ponytail: opts spread keeps this compilable against kernel 0.1.0 (whose
|
|
128
|
+
// row() opts type lacks `completions`); the runtime contract is additive and
|
|
129
|
+
// 0.1.1+ consumes the field. Drop the cast when the dep floor moves to 0.1.1.
|
|
130
|
+
const withCompletions = (completions: () => CompletionItem[]) =>
|
|
131
|
+
({ completions }) as unknown as { mask?: boolean };
|
|
104
132
|
const roleRows = Object.keys(cfg.roles).sort().map((name) => {
|
|
105
133
|
// Label shows the default chain so blank is meaningful.
|
|
106
134
|
return row(`role.${name}`, `@${name} (default: ${defaultChain(name) || "none"})`, "string", cfg.roles[name], (v) => {
|
|
107
135
|
cfg.roles[name] = String(v ?? "").trim();
|
|
108
|
-
});
|
|
136
|
+
}, withCompletions(modelItems));
|
|
109
137
|
});
|
|
110
138
|
const agentRows = agents.map((agent) =>
|
|
111
139
|
row(`agent.${agent.name}`, agent.name, "string", cfg.agentModels[agent.name] ?? "", (v) => {
|
|
112
140
|
const value = String(v ?? "").trim();
|
|
113
141
|
if (value) cfg.agentModels[agent.name] = value;
|
|
114
142
|
else delete cfg.agentModels[agent.name];
|
|
115
|
-
}),
|
|
143
|
+
}, withCompletions(() => [...modelItems(), ...roleItems()])),
|
|
116
144
|
);
|
|
117
145
|
return [
|
|
118
146
|
{ key: "roles", label: "Model roles (chain, blank = default)", rows: roleRows },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bacnh85/pi-subagent",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.1",
|
|
4
4
|
"description": "In-process subagents for Pi with isolated SDK sessions, parallel and chained delegation, and inspectable threads.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -62,9 +62,9 @@
|
|
|
62
62
|
"check": "npm run typecheck && npm test"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
|
-
"@earendil-works/pi-coding-agent": ">=0.80.0 <0.85.0",
|
|
66
|
-
"@earendil-works/pi-ai": ">=0.80.0 <0.85.0",
|
|
67
65
|
"@earendil-works/pi-agent-core": ">=0.80.0 <0.85.0",
|
|
66
|
+
"@earendil-works/pi-ai": ">=0.80.0 <0.85.0",
|
|
67
|
+
"@earendil-works/pi-coding-agent": ">=0.80.0 <0.85.0",
|
|
68
68
|
"@earendil-works/pi-tui": ">=0.80.0 <0.85.0",
|
|
69
69
|
"typebox": ">=1.3.0 <2.0.0"
|
|
70
70
|
},
|
|
@@ -74,14 +74,14 @@
|
|
|
74
74
|
"devDependencies": {
|
|
75
75
|
"@earendil-works/pi-agent-core": "^0.84.0",
|
|
76
76
|
"@earendil-works/pi-ai": "^0.84.0",
|
|
77
|
-
"@earendil-works/pi-coding-agent": "^0.84.
|
|
78
|
-
"@earendil-works/pi-tui": "^0.84.
|
|
77
|
+
"@earendil-works/pi-coding-agent": "^0.84.3",
|
|
78
|
+
"@earendil-works/pi-tui": "^0.84.3",
|
|
79
79
|
"@types/mocha": "^10.0.10",
|
|
80
80
|
"@types/node": "^20.19.43",
|
|
81
81
|
"mocha": "^11.8.0",
|
|
82
82
|
"tsx": "^4.22.4",
|
|
83
|
-
"
|
|
84
|
-
"
|
|
83
|
+
"typebox": "^1.3.1",
|
|
84
|
+
"typescript": "^5.9.3"
|
|
85
85
|
},
|
|
86
86
|
"overrides": {
|
|
87
87
|
"serialize-javascript@>=5.0.0 <7.0.5": "^7.0.5",
|