pi-subagents-j0k3r 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +8 -6
- package/index.ts +3 -1
- package/package.json +1 -1
- package/skills/subagents-configuration/SKILL.md +16 -13
- package/src/config.ts +30 -13
- package/src/tools.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.0 - 2026-06-27
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Added support for loading markdown-defined subagents from both `agents` and `subagents` directories globally and project-locally.
|
|
7
|
+
- Added startup warnings when duplicate names exist in `agents` and `subagents` at the same scope, while preserving `subagents` as the winning source.
|
|
8
|
+
- Enabled project Skill Registry configuration and ignored generated registry cache outputs.
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- Made `model_profiles` global-only so project-local `.pi/subagents.json` cannot override per-agent model/effort routing.
|
|
12
|
+
|
|
13
|
+
### Documentation
|
|
14
|
+
- Updated README and Subagents configuration skill guidance for `agents`/`subagents` source precedence and global-only model profiles.
|
|
15
|
+
|
|
3
16
|
## 1.0.1 - 2026-06-27
|
|
4
17
|
|
|
5
18
|
### Fixed
|
package/README.md
CHANGED
|
@@ -67,10 +67,12 @@ Subagents are markdown files with optional YAML-like frontmatter.
|
|
|
67
67
|
|
|
68
68
|
Load order:
|
|
69
69
|
|
|
70
|
-
1. Global user
|
|
71
|
-
2.
|
|
70
|
+
1. Global user agents from `$PI_CODING_AGENT_DIR/agents/*.md`.
|
|
71
|
+
2. Global user subagents from `$PI_CODING_AGENT_DIR/subagents/*.md`.
|
|
72
|
+
3. Project agents from `.pi/agents/*.md`.
|
|
73
|
+
4. Project subagents from `.pi/subagents/*.md`.
|
|
72
74
|
|
|
73
|
-
Project definitions override global definitions with the same normalized name.
|
|
75
|
+
Project definitions override global definitions with the same normalized name. Within the same scope, `subagents` definitions override `agents` definitions with the same normalized name and Pi shows a startup warning so the duplicate can be cleaned up.
|
|
74
76
|
|
|
75
77
|
Default global agent directory:
|
|
76
78
|
|
|
@@ -127,7 +129,7 @@ Config files:
|
|
|
127
129
|
.pi/subagents.json # project
|
|
128
130
|
```
|
|
129
131
|
|
|
130
|
-
Config resolves as a cascade: project `.pi/subagents.json` overrides global `~/.pi/agent/subagents.json`; missing project fields fall back to global config; fields missing from both fall back to built-in defaults.
|
|
132
|
+
Config resolves as a cascade: project `.pi/subagents.json` overrides global `~/.pi/agent/subagents.json`; missing project fields fall back to global config; fields missing from both fall back to built-in defaults. `model_profiles` are the explicit exception: per-agent model/effort routing is read only from the global `~/.pi/agent/subagents.json` or `$PI_CODING_AGENT_DIR/subagents.json`, and project-local `model_profiles` are ignored.
|
|
131
133
|
|
|
132
134
|
Example:
|
|
133
135
|
|
|
@@ -168,7 +170,7 @@ Example:
|
|
|
168
170
|
|---|---:|---|
|
|
169
171
|
| `default_model` | current orchestrator model | Fallback model for all subagents. Format: `provider/model-id`. |
|
|
170
172
|
| `default_effort` | current orchestrator effort | Fallback thinking effort. Also accepts `default_thinking_level` or `thinkingLevel`. |
|
|
171
|
-
| `model_profiles` | `{}` |
|
|
173
|
+
| `model_profiles` | `{}` | Global-only per-agent model/effort overrides. Project-local `.pi/subagents.json` `model_profiles` are ignored. |
|
|
172
174
|
| `timeout_ms` | `600000` | Total timeout per subagent task. |
|
|
173
175
|
| `stall_timeout_ms` | `120000` | Inactivity timeout for a subagent session. |
|
|
174
176
|
| `max_concurrency` | `5` | Max concurrent subagent tasks per cwd/config pair. |
|
|
@@ -392,7 +394,7 @@ This package bundles:
|
|
|
392
394
|
- `index.ts` and `src/**` — the Pi extension runtime.
|
|
393
395
|
- `skills/subagents-configuration/SKILL.md` — configuration guidance for agents that need to create or edit subagent definitions.
|
|
394
396
|
|
|
395
|
-
Subagent definitions are intentionally user/project configuration, not hard-coded package behavior. Add them globally in `$PI_CODING_AGENT_DIR/
|
|
397
|
+
Subagent definitions are intentionally user/project configuration, not hard-coded package behavior. Add them globally in `$PI_CODING_AGENT_DIR/agents/*.md` or `$PI_CODING_AGENT_DIR/subagents/*.md`, or project-locally in `.pi/agents/*.md` or `.pi/subagents/*.md`.
|
|
396
398
|
|
|
397
399
|
## Development
|
|
398
400
|
|
package/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SubagentManager } from './src/manager.js';
|
|
2
|
-
import { readSubagentsConfig } from './src/config.js';
|
|
2
|
+
import { readSubagentsConfig, subagentSourceWarnings } from './src/config.js';
|
|
3
3
|
import { registerSubagentTools, triggerClaudeBackgroundHandoff } from './src/tools.js';
|
|
4
4
|
import { runSubagentModelsCommand } from './src/model-profiles-ui.js';
|
|
5
5
|
import { SubagentsHistoryPanel } from './src/ui.js';
|
|
@@ -412,6 +412,8 @@ export default function subagentsExtension(pi: any): void {
|
|
|
412
412
|
|
|
413
413
|
pi.on?.('session_start', (_event: unknown, ctx: any) => {
|
|
414
414
|
clearClaudeBackgroundWidget();
|
|
415
|
+
const cwd = ctx?.cwd ?? process.cwd();
|
|
416
|
+
for (const warning of subagentSourceWarnings(cwd)) ctx?.ui?.notify?.(warning, 'warning');
|
|
415
417
|
if (typeof ctx?.ui?.setWidget !== 'function') return;
|
|
416
418
|
widgetCtx = ctx;
|
|
417
419
|
if (!installClaudeBackgroundWidget(ctx)) return;
|
package/package.json
CHANGED
|
@@ -19,10 +19,13 @@ Use this block as the machine-readable source for `.pi/skill-registry.json` gene
|
|
|
19
19
|
"domains": ["subagents-configuration", "subagent-config", "model-profile-config", "tool-allowlist-config", "subagent-history-config", "subagent-shortcut-config"],
|
|
20
20
|
"triggers": {
|
|
21
21
|
"paths": [
|
|
22
|
+
".pi/agents/**/*.md",
|
|
22
23
|
".pi/subagents/**/*.md",
|
|
23
24
|
".pi/subagents.json",
|
|
25
|
+
"agents/**/*.md",
|
|
24
26
|
"subagents/**/*.md",
|
|
25
27
|
"subagents.json",
|
|
28
|
+
"~/.pi/agent/agents/**/*.md",
|
|
26
29
|
"~/.pi/agent/subagents/**/*.md",
|
|
27
30
|
"~/.pi/agent/subagents.json"
|
|
28
31
|
],
|
|
@@ -88,11 +91,11 @@ Do not load this skill for ordinary subagent delegation/use (`subagent_run`, tas
|
|
|
88
91
|
- Prefer narrow tool allowlists per subagent. Do not grant write/bash tools unless the subagent purpose requires them.
|
|
89
92
|
- For SDD/PRD phase agents, prefer deterministic active-flow memory tools only: `memory_search`, `memory_get`, `memory_add`, and `memory_update`; avoid `memory_context` and `memory_recall` in subagent allowlists unless there is a specific reviewed need.
|
|
90
93
|
- For SDD phase agents, memory write tools may be allowed only for active SDD flow memory/artifacts according to `sdd-workflow`.
|
|
91
|
-
- Project
|
|
92
|
-
- Project definitions override global definitions with the same normalized name.
|
|
93
|
-
- Subagents config resolves as a cascade: project `.pi/subagents.json` overrides global `$PI_CODING_AGENT_DIR/subagents.json` or `~/.pi/agent/subagents.json`; missing project fields fall back to global config; fields missing from both fall back to built-in defaults. Communicate this precedence to users when explaining config behavior.
|
|
94
|
-
- `model_profiles` are
|
|
95
|
-
- Prefer configuring subagent `model` and `effort` in global
|
|
94
|
+
- Project subagent definitions live in `.pi/agents/*.md` and `.pi/subagents/*.md`; global user definitions live in `$PI_CODING_AGENT_DIR/agents/*.md`, `$PI_CODING_AGENT_DIR/subagents/*.md`, `~/.pi/agent/agents/*.md`, or `~/.pi/agent/subagents/*.md`.
|
|
95
|
+
- Project definitions override global definitions with the same normalized name. Within the same scope, definitions in `subagents` override definitions in `agents` with the same normalized name, and Pi should warn at session startup so users can clean up the duplicate.
|
|
96
|
+
- Subagents config resolves as a cascade: project `.pi/subagents.json` overrides global `$PI_CODING_AGENT_DIR/subagents.json` or `~/.pi/agent/subagents.json`; missing project fields fall back to global config; fields missing from both fall back to built-in defaults. Communicate this precedence to users when explaining config behavior, with the explicit exception that `model_profiles` are global-only.
|
|
97
|
+
- `model_profiles` are read only from global `$PI_CODING_AGENT_DIR/subagents.json` or `~/.pi/agent/subagents.json`; project-local `.pi/subagents.json` must not set or override subagent model/effort routing.
|
|
98
|
+
- Prefer configuring subagent `model` and `effort` in global `subagents.json` under `model_profiles`, not in project-local config or in the subagent markdown frontmatter. Markdown definitions should usually contain identity, description, tool allowlist, and behavioral instructions only.
|
|
96
99
|
- Nested subagent sessions should use `session_resources: "lean"` by default so the subagent markdown body becomes the nested session system prompt, the delegated user prompt contains only orchestrator context/task, and workflow skills, prompt templates, themes, context files, and startup context injections are not auto-loaded.
|
|
97
100
|
- In lean mode, extensions are loaded for allowlisted tools and tool-safety hooks only; prompt/context lifecycle hooks such as `before_agent_start` and `context` must not inject hidden messages into subagent turns.
|
|
98
101
|
- Subagent task history is stored globally under data storage, but rows remain project-scoped by `cwd`; history stores delegated prompt and subagent system prompt separately.
|
|
@@ -151,7 +154,7 @@ tools:
|
|
|
151
154
|
Instructions...
|
|
152
155
|
```
|
|
153
156
|
|
|
154
|
-
Configure routing separately in `subagents.json` when needed. If no profile/default is configured, the subagent inherits the current orchestrator model and thinking effort.
|
|
157
|
+
Configure model/effort routing separately in the global `subagents.json` when needed. If no global profile/default is configured, the subagent inherits the current orchestrator model and thinking effort.
|
|
155
158
|
|
|
156
159
|
```json
|
|
157
160
|
{
|
|
@@ -166,9 +169,9 @@ Configure routing separately in `subagents.json` when needed. If no profile/defa
|
|
|
166
169
|
|
|
167
170
|
Model/effort resolution order:
|
|
168
171
|
|
|
169
|
-
1. `model_profiles[agentName]` in `subagents.json`.
|
|
172
|
+
1. Global `model_profiles[agentName]` in `$PI_CODING_AGENT_DIR/subagents.json` or `~/.pi/agent/subagents.json`.
|
|
170
173
|
2. Markdown frontmatter `model` / `effort` only for explicit per-file overrides.
|
|
171
|
-
3. `default_model` / `default_effort`
|
|
174
|
+
3. `default_model` / `default_effort` from effective `subagents.json` config.
|
|
172
175
|
4. Current orchestrator model / effort.
|
|
173
176
|
|
|
174
177
|
## Decision Gates
|
|
@@ -176,16 +179,16 @@ Model/effort resolution order:
|
|
|
176
179
|
- If the subagent will modify files, run bash, or write memory, ask whether a full SDD workflow or stricter review is required.
|
|
177
180
|
- If the subagent needs human input, require a structured `interaction_required` request with enough prompt, payload, and expected-response data for the parent to answer.
|
|
178
181
|
- If a project wants many subagents or broad tools, recommend starting with read-only discovery agents and expanding deliberately.
|
|
179
|
-
- If model profiles are global
|
|
182
|
+
- If the user asks for project-local model profiles, explain that `model_profiles` are global-only and ask whether they want to update the global config instead.
|
|
180
183
|
|
|
181
184
|
## Execution Steps
|
|
182
185
|
|
|
183
186
|
1. Identify target scope: npm package install/update, global subagent, project subagent, global config, or project config, and explain the cascade when relevant: project-local config first, then global config for missing fields, then built-in defaults.
|
|
184
187
|
2. For package setup, inspect settings before editing; use `pi install npm:pi-subagents-j0k3r` when possible, or edit `~/.pi/agent/settings.json` only when the CLI is unavailable/broken. Prefer unpinned `npm:pi-subagents-j0k3r` unless the user asks for a fixed version.
|
|
185
|
-
3. Read existing subagent markdown/config before editing.
|
|
186
|
-
4. For new subagents, choose lowercase kebab-case names and clear trigger-focused descriptions.
|
|
188
|
+
3. Read existing subagent markdown/config before editing, checking both `agents` and `subagents` directories for the requested scope.
|
|
189
|
+
4. For new subagents, choose lowercase kebab-case names and clear trigger-focused descriptions. Prefer `subagents` for new definitions unless the user explicitly needs compatibility with an `agents` harness.
|
|
187
190
|
5. Set minimal tool allowlists; remove any `subagent_*` entries.
|
|
188
|
-
6. Configure `model_profiles
|
|
191
|
+
6. Configure `model_profiles` only in global `subagents.json` when the user wants explicit per-agent routing; project-local `model_profiles` are ignored. Configure `default_model` and `default_effort` in effective `subagents.json` only when the user wants defaults. Do not put model routing in subagent markdown unless the user explicitly asks for per-file overrides. Explain that unconfigured fields inherit from the orchestrator.
|
|
189
192
|
7. Configure `debug: true` only for temporary diagnostics; keep `debug: false` by default and remember logs are written under the executing project's `.pi` directory.
|
|
190
193
|
8. Validate JSON syntax for settings/subagents config and frontmatter/body structure for markdown agents.
|
|
191
194
|
9. When configuring OpenCode-mode history opening, prefer `history_panel_shortcut` with `ctrl+<letter>` or `ctrl+,` values and document any built-in shortcut conflicts.
|
|
@@ -200,7 +203,7 @@ Model/effort resolution order:
|
|
|
200
203
|
Return:
|
|
201
204
|
|
|
202
205
|
- Skill applied: `subagents-configuration`.
|
|
203
|
-
- Scope/path configured or reviewed
|
|
206
|
+
- Scope/path configured or reviewed, including whether definitions came from `agents` or `subagents`.
|
|
204
207
|
- Package settings and subagents/config fields added, changed, or preserved.
|
|
205
208
|
- Tool allowlist, system-prompt isolation, Context7 scope, memory-tool scope, debug logging, model/effort decisions, and inheritance behavior.
|
|
206
209
|
- Runtime behavior explained when relevant: task vs background, automatic notifications, `/subagents`, `ctrl+o`, and `subagent_result`.
|
package/src/config.ts
CHANGED
|
@@ -163,16 +163,6 @@ function parseModelProfiles(value: unknown): SubagentModelProfiles {
|
|
|
163
163
|
return profiles;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
function mergeModelProfiles(globalRaw: unknown, projectRaw: unknown): SubagentModelProfiles {
|
|
167
|
-
const globalProfiles = parseModelProfiles(globalRaw);
|
|
168
|
-
const projectProfiles = parseModelProfiles(projectRaw);
|
|
169
|
-
const merged: SubagentModelProfiles = { ...globalProfiles };
|
|
170
|
-
for (const [name, projectProfile] of Object.entries(projectProfiles)) {
|
|
171
|
-
merged[name] = { ...(merged[name] ?? {}), ...projectProfile };
|
|
172
|
-
}
|
|
173
|
-
return merged;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
166
|
function serializeModelRef(model: ModelRef): string {
|
|
177
167
|
return `${model.provider}/${model.id}`;
|
|
178
168
|
}
|
|
@@ -191,7 +181,7 @@ export function readSubagentsConfig(cwd: string): SubagentsConfig {
|
|
|
191
181
|
return {
|
|
192
182
|
default_model: parseModel(raw.default_model),
|
|
193
183
|
default_effort: parseEffort(raw.default_effort ?? raw.default_thinking_level ?? raw.thinkingLevel),
|
|
194
|
-
model_profiles:
|
|
184
|
+
model_profiles: parseModelProfiles(globalRaw.model_profiles),
|
|
195
185
|
timeout_ms: positiveInteger(raw.timeout_ms, DEFAULT_TIMEOUT_MS),
|
|
196
186
|
stall_timeout_ms: positiveInteger(raw.stall_timeout_ms, DEFAULT_STALL_TIMEOUT_MS),
|
|
197
187
|
max_concurrency: positiveInteger(raw.max_concurrency, DEFAULT_MAX_CONCURRENCY),
|
|
@@ -250,10 +240,37 @@ function loadSubagentsFromDir(dir: string): SubagentDefinition[] {
|
|
|
250
240
|
});
|
|
251
241
|
}
|
|
252
242
|
|
|
243
|
+
function agentsDirSources(cwd: string): Array<{ scope: 'global' | 'project'; kind: 'agents' | 'subagents'; dir: string }> {
|
|
244
|
+
const globalAgentDir = agentDir();
|
|
245
|
+
return [
|
|
246
|
+
{ scope: 'global', kind: 'agents', dir: path.join(globalAgentDir, 'agents') },
|
|
247
|
+
{ scope: 'global', kind: 'subagents', dir: path.join(globalAgentDir, 'subagents') },
|
|
248
|
+
{ scope: 'project', kind: 'agents', dir: path.join(cwd, '.pi', 'agents') },
|
|
249
|
+
{ scope: 'project', kind: 'subagents', dir: path.join(cwd, '.pi', 'subagents') },
|
|
250
|
+
];
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export function subagentSourceWarnings(cwd: string): string[] {
|
|
254
|
+
const warnings: string[] = [];
|
|
255
|
+
for (const scope of ['global', 'project'] as const) {
|
|
256
|
+
const sources = agentsDirSources(cwd).filter((source) => source.scope === scope);
|
|
257
|
+
const agents = loadSubagentsFromDir(sources.find((source) => source.kind === 'agents')!.dir);
|
|
258
|
+
const subagents = loadSubagentsFromDir(sources.find((source) => source.kind === 'subagents')!.dir);
|
|
259
|
+
const subagentNames = new Map(subagents.map((definition) => [definition.name, definition]));
|
|
260
|
+
for (const agent of agents) {
|
|
261
|
+
const subagent = subagentNames.get(agent.name);
|
|
262
|
+
if (!subagent) continue;
|
|
263
|
+
warnings.push(`Duplicate subagent name "${agent.name}" found in ${scope} agents and subagents directories; using subagents definition (${subagent.filePath}).`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return warnings;
|
|
267
|
+
}
|
|
268
|
+
|
|
253
269
|
export function loadSubagents(cwd: string): SubagentDefinition[] {
|
|
254
270
|
const byName = new Map<string, SubagentDefinition>();
|
|
255
|
-
for (const
|
|
256
|
-
|
|
271
|
+
for (const source of agentsDirSources(cwd)) {
|
|
272
|
+
for (const agent of loadSubagentsFromDir(source.dir)) byName.set(agent.name, agent);
|
|
273
|
+
}
|
|
257
274
|
return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
258
275
|
}
|
|
259
276
|
|
package/src/tools.ts
CHANGED
|
@@ -299,7 +299,7 @@ export function registerSubagentTools(pi: any, manager: SubagentManager): void {
|
|
|
299
299
|
name: 'subagent_list_agents',
|
|
300
300
|
label: 'Subagent List Agents',
|
|
301
301
|
description: 'List available markdown-defined subagents for delegation.',
|
|
302
|
-
promptSnippet: 'List available subagents loaded from
|
|
302
|
+
promptSnippet: 'List available subagents loaded from global/project agents and subagents markdown directories.',
|
|
303
303
|
parameters: Type.Object({}),
|
|
304
304
|
async execute(_id: string, _params: any, _signal: any, _onUpdate: any, ctx: any) {
|
|
305
305
|
try { const agents = manager.listAgents(ctx?.cwd ?? process.cwd()); return ok(`Found ${agents.length} subagent(s).`, { agents }); } catch (e) { return fail(e); }
|