@maxiaochao/pi-toolkit 0.13.3 → 0.13.4

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 CHANGED
@@ -1,3 +1,7 @@
1
+ ## 2026-10-22 - v0.13.4
2
+
3
+ - herdr-subagents v0.7.3: keep Persona selection lists concise
4
+
1
5
  ## 2026-10-21 - v0.13.3
2
6
 
3
7
  - codex-edit v0.2.0: persist personal routing rules in the Pi agent directory across package updates
@@ -9,6 +13,7 @@
9
13
 
10
14
  ## Unreleased
11
15
 
16
+ - Herdr Subagents: show only Persona names and descriptions in model-facing selection lists, preserving diagnostics and detailed user-facing inspection.
12
17
  - Make Agent Team user-invoked only through `/skill:agent-team`, hidden from automatic model selection.
13
18
  - Add `npm run release:check -- vX.Y.Z` to wait for GitHub publication and verify exact npm versions, remote tags, integrity, and all tarball contents against the release commit, including coordinated child releases.
14
19
 
package/README.md CHANGED
@@ -42,7 +42,7 @@ Each child README owns its feature description, motivation or upstream alignment
42
42
 
43
43
  Codex Edit personal routing rules belong in `~/.pi/agent/codex-edit.json`, not inside `node_modules`. User fields override bundled defaults; `models` replaces the complete default list. The file survives package updates and is shared by parent sessions and explicitly configured subagents using the same agent directory. Use `/reload` after editing it, and start new subagents. See [Codex Edit configuration](packages/codex-edit/README.md#configuration).
44
44
 
45
- Herdr Subagents tasks require an explicit `agent` Persona; no default `worker` is selected. Choose `reviewer` for independent reviews of proposals, designs, documents, implementations, or analysis; `explorer` for codebase investigation; `worker` for file-changing work; and `analyst` for charter-defined agent-team roles. See [built-in Personas](packages/herdr-subagents/README.md#built-in-personas) for selection guidance and the distinction between parent-facing descriptions and child instructions. Personas can opt into local extension files or npm/git Pi packages through `extensions`. Set top-level `defaultExtensions` in `~/.pi/agent/herdr-subagents.json` (or project `.pi/herdr-subagents.json`) to share a fallback list; Persona-specific lists take precedence, and `[]` clears inherited sources. This uses native Pi package semantics: package-provided skills, prompt templates, and themes may also load, and `--no-skills` does not exclude explicitly selected package skills. See the [extension-source contract](packages/herdr-subagents/README.md#explicit-extension-sources-and-pi-packages) for precedence, isolation, and examples. The [real Herdr smoke test](packages/herdr-subagents/TESTING.md) preserves the configured analyst model and explicit authentication extensions while isolating unrelated settings.
45
+ Herdr Subagents tasks require an explicit `agent` Persona; no default `worker` is selected. Choose `reviewer` for independent reviews of proposals, designs, documents, implementations, or analysis; `explorer` for codebase investigation; `worker` for file-changing work; and `analyst` for charter-defined agent-team roles. Control `list` returns names and descriptions for selection, plus configuration diagnostics when present; use `/herdr-subagents agents` and `settings` for detailed configuration. See [built-in Personas](packages/herdr-subagents/README.md#built-in-personas) for selection guidance and the distinction between parent-facing descriptions and child instructions. Personas can opt into local extension files or npm/git Pi packages through `extensions`. Set top-level `defaultExtensions` in `~/.pi/agent/herdr-subagents.json` (or project `.pi/herdr-subagents.json`) to share a fallback list; Persona-specific lists take precedence, and `[]` clears inherited sources. This uses native Pi package semantics: package-provided skills, prompt templates, and themes may also load, and `--no-skills` does not exclude explicitly selected package skills. See the [extension-source contract](packages/herdr-subagents/README.md#explicit-extension-sources-and-pi-packages) for precedence, isolation, and examples. The [real Herdr smoke test](packages/herdr-subagents/TESTING.md) preserves the configured analyst model and explicit authentication extensions while isolating unrelated settings.
46
46
 
47
47
  Multiple standalone children may be installed together. `pi-openai-account-pool` may also be installed alongside the complete toolkit because the toolkit does not embed it. Every other child in the table above, including `pi-background-tasks`, is embedded, so a second install exposes the same resource twice.
48
48
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maxiaochao/pi-toolkit",
3
- "version": "0.13.3",
3
+ "version": "0.13.4",
4
4
  "description": "Personal pi coding agent toolkit: background tasks, scheduler, /btw, /cache_export, apply_patch, browser automation, and bundled theme/skills.",
5
5
  "type": "module",
6
6
  "workspaces": [
@@ -1,3 +1,8 @@
1
+ ## 2026-10-22 - v0.7.3
2
+
3
+ - keep Persona selection lists concise
4
+ - Limit model-facing Persona listings and unknown-Persona suggestions to names and descriptions. Preserve configuration diagnostics, detailed result metadata, and the `/herdr-subagents agents` and `settings` inspection commands.
5
+
1
6
  ## 2026-10-21 - v0.7.2
2
7
 
3
8
  - clarify final answer submission through subagent_report
@@ -119,7 +119,7 @@ A batch containing a write-capable Persona must explicitly or effectively use `c
119
119
 
120
120
  | Action | `runId` | Purpose |
121
121
  | --- | --- | --- |
122
- | `list` | Not accepted | List effective Personas, resolved options, and diagnostics. |
122
+ | `list` | Not accepted | List Persona names and descriptions for task selection, plus configuration diagnostics when present. |
123
123
  | `status` | Required | Show one run and its task states. |
124
124
  | `history` | Not accepted | List durable project-local run history. |
125
125
  | `cancel` | Required | Cancel an active run. |
@@ -127,6 +127,8 @@ A batch containing a write-capable Persona must explicitly or effectively use `c
127
127
 
128
128
  Settled tasks are immutable. Follow-up work starts a new task or run; there is no resume/respond lifecycle.
129
129
 
130
+ The model-facing `list` text does not expand tools, skills, extensions, models, thinking levels, or configuration sources. Describe routing-relevant capabilities and constraints in each Persona's description. Use `/herdr-subagents agents` and `/herdr-subagents settings` for detailed configuration; full resolved data remains in the tool result's `details` metadata.
131
+
130
132
  ### Slash command
131
133
 
132
134
  `/herdr-subagents` supports:
@@ -9,7 +9,8 @@ npm test --workspace @maxiaochao/pi-herdr-subagents
9
9
  It verifies:
10
10
 
11
11
  - global/project `defaultExtensions` replacement, trimming, source attribution, Persona JSON/Markdown precedence, explicit empty-list clearing, invalid-value diagnostics, and per-call reloads;
12
- - resolved defaults in control listings, settings output, and child CLI arguments while preserving mandatory extensions;
12
+ - concise Persona names/descriptions in model-facing listings and unknown-Persona errors, including empty lists and visible configuration diagnostics;
13
+ - resolved defaults in control result metadata, settings output, and child CLI arguments while preserving mandatory extensions;
13
14
  - strict serial start order at concurrency one;
14
15
  - bounded read-only parallelism;
15
16
  - ordered results despite concurrent completion;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maxiaochao/pi-herdr-subagents",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "Run inspectable interactive Pi subagent batches through Herdr.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -60,10 +60,7 @@ export function listText(discovery: SubagentConfiguration): string {
60
60
  const lines = ["Available Herdr Subagents personas:"];
61
61
  if (discovery.personas.length === 0) lines.push("- (none)");
62
62
  for (const agent of discovery.personas) {
63
- const model = agent.model ?? "unresolved";
64
- const tools = agent.tools?.join(", ") ?? "Pi default built-in tools";
65
- const skills = agent.skills.join(", ") || "none";
66
- lines.push(`- ${agent.name}: ${agent.description} (source: ${agent.source}; access: ${agent.access}; model: ${model} [${agent.modelSource}]; thinking: ${agent.thinking ?? "default"}; tools: ${tools}; skills: ${skills}; extensions: ${agent.extensions.join(", ") || "none"} [${agent.extensionsSource}])`);
63
+ lines.push(`- ${agent.name}: ${agent.description}`);
67
64
  }
68
65
  if (discovery.diagnostics.length > 0) {
69
66
  lines.push("", "Persona diagnostics:", ...discovery.diagnostics.map((diagnostic) => `- ${diagnostic}`));
@@ -4,7 +4,7 @@ import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
5
  import { loadSubagentConfiguration } from "../src/config.ts";
6
6
  import { childPiArgs } from "../src/live-agent.ts";
7
- import { executeHerdrSubagentsControl } from "../src/tool.ts";
7
+ import { executeHerdrSubagentsControl, listText } from "../src/tool.ts";
8
8
 
9
9
  const root = mkdtempSync(join(tmpdir(), "herdr-default-extensions-"));
10
10
  const agents = join(root, "agents");
@@ -88,7 +88,18 @@ try {
88
88
  const response = await executeHerdrSubagentsControl({ action: "list" }, undefined, undefined, { cwd: root }, { agentsDirectory: agents, configurationPaths: paths });
89
89
  assert.deepEqual(response.details.agents.find(({ name }) => name === "plain").extensions, ["./updated.ts"]);
90
90
  assert.deepEqual(response.details.settings.defaultExtensions, ["./updated.ts"]);
91
- assert.match(response.content[0].text, /extensions: \.\/updated\.ts \[project\]/);
91
+ const expectedListing = [
92
+ "Available Herdr Subagents personas:",
93
+ "- cleared: Configuration fixture",
94
+ "- pinned: Configuration fixture",
95
+ "- plain: Configuration fixture",
96
+ ].join("\n");
97
+ assert.equal(response.content[0].text, expectedListing, "Model-facing listings must contain only Persona names and descriptions");
98
+ assert.equal(listText({ ...configuration, personas: [] }), "Available Herdr Subagents personas:\n- (none)");
99
+ write(paths.projectConfig, { defaultExtensions: "./invalid.ts" });
100
+ const diagnosed = await executeHerdrSubagentsControl({ action: "list" }, undefined, undefined, { cwd: root }, { agentsDirectory: agents, configurationPaths: paths });
101
+ assert.equal(diagnosed.content[0].text, `${expectedListing}\n\nPersona diagnostics:\n- project defaultExtensions must be an array of non-empty strings`, "Concise listings must still surface invalid configuration");
102
+ assert.deepEqual(diagnosed.details.diagnostics, ["project defaultExtensions must be an array of non-empty strings"]);
92
103
  write(paths.projectConfig, { defaultExtensions: [] });
93
104
  const cleared = persona(load());
94
105
  assert.deepEqual(cleared.extensions, []);
@@ -97,7 +108,7 @@ try {
97
108
  assert.ok(clearedArgs.some((arg) => arg.endsWith("/extensions/subagent-report.ts")));
98
109
  assert.ok(!clearedArgs.includes("./updated.ts"));
99
110
  assert.deepEqual(selected.extensions, ["./updated.ts"]);
100
- console.log("PASS defaults reach child arguments and control listings, reload per call, and preserve mandatory extensions");
111
+ console.log("PASS concise Persona listings preserve diagnostics and detailed metadata; defaults reach child arguments and reload per call");
101
112
  } finally {
102
113
  rmSync(root, { recursive: true, force: true });
103
114
  }
@@ -142,7 +142,7 @@ async function run(tasks, concurrency, herdr = fakeHerdr(), signal) {
142
142
  assert.match(laterMissing.content[0].text, /tasks\[1\]\.agent.*required/);
143
143
  const unknown = await execute({ tasks: [{ ...missing, agent: "unknown-persona" }] });
144
144
  assert.equal(unknown.isError, true);
145
- assert.match(unknown.content[0].text, /Unknown persona 'unknown-persona'/);
145
+ assert.equal(unknown.content[0].text, `Unknown persona 'unknown-persona'.\n\n${listed.content[0].text}`, "Unknown-Persona errors must reuse the concise selection list");
146
146
  assert.deepEqual(herdr.starts, [], "Invalid requests must not start an Agent");
147
147
  assert.equal(existsSync(join(root, ".pi", "herdr-subagents", "runs")), false, "Invalid requests must not create run records");
148
148
 
@@ -287,6 +287,8 @@ assert.throws(() => applyTaskStatus(terminal, "running"), /terminal tasks are im
287
287
  const notifications = [];
288
288
  await configuredCommands.get("herdr-subagents").handler("settings", { cwd: lifecycleRoot, ui: { notify(message) { notifications.push(message); } } });
289
289
  assert.match(notifications[0], /defaultExtensions=\[\] \(project\)/, "Settings must show empty defaults and their source");
290
+ await configuredCommands.get("herdr-subagents").handler("agents", { cwd: lifecycleRoot, ui: { notify(message) { notifications.push(message); } } });
291
+ assert.match(notifications[1], /: (?:package|global|project), (?:read|write), model=.*thinking=.*tools=.*skills=.*extensions=/, "User-facing inspection must retain detailed configuration fields");
290
292
  }
291
293
 
292
294
  {
@@ -661,7 +661,7 @@ try {
661
661
  const extensionHistory = await listSubagentHistory(extensionRoot);
662
662
  check("history exposes saved extension sources", JSON.stringify(extensionHistory[0]?.tasks[0]?.extensions) === JSON.stringify(extensionSources));
663
663
  const extensionList = await executeHerdrSubagents({ action: "list" }, undefined, undefined, { cwd: extensionRoot }, extensionDependencies);
664
- check("persona listing shows extension sources and their precedence", extensionList.content[0].text.includes("npm:@example/pi-tools@1.0.0") && extensionList.content[0].text.includes("project persona"));
664
+ check("persona listing keeps extension configuration in metadata only", !extensionList.content[0].text.includes("npm:@example/pi-tools@1.0.0") && extensionList.details.agents[0].extensionsSource === "project persona" && JSON.stringify(extensionList.details.agents[0].extensions) === JSON.stringify(extensionSources));
665
665
  writeFileSync(extensionPaths.projectConfig, JSON.stringify({ personas: { routed: { extensions: [] } } }));
666
666
  check("empty project extension list clears lower-precedence sources", extensionPersona()?.extensions?.length === 0 && extensionPersona()?.extensionsSource === "project persona");
667
667
  const extensionResumeHerdr = fakeHerdr();