pi-subagents 0.8.5 → 0.9.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 +16 -0
- package/agents.ts +10 -5
- package/async-execution.ts +4 -0
- package/package.json +1 -1
- package/pi-spawn.ts +22 -1
- package/subagent-runner.ts +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.9.0] - 2026-02-17
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **Builtin agents** — the extension now ships with a default set of agent definitions in `agents/`. These are loaded with lowest priority so user and project agents always override them. New users get a useful set of agents out of the box without manual setup.
|
|
9
|
+
- `scout` — fast codebase recon (claude-haiku-4-5)
|
|
10
|
+
- `planner` — implementation plans from context (claude-opus-4-6, thinking: high)
|
|
11
|
+
- `worker` — general-purpose execution (claude-sonnet-4-6)
|
|
12
|
+
- `reviewer` — validates implementation against plans (gpt-5.2, thinking: high)
|
|
13
|
+
- `code-reviewer` — bug hunting and code review (claude-opus-4-6, thinking: high)
|
|
14
|
+
- `context-builder` — analyzes requirements and codebase (claude-sonnet-4-6)
|
|
15
|
+
- `researcher` — autonomous web research with search, evaluation, and synthesis (claude-sonnet-4-6)
|
|
16
|
+
- **`"builtin"` agent source** — new third tier in agent discovery. Priority: builtin < user < project. Builtin agents appear in listings with a `[builtin]` badge and cannot be modified or deleted through management actions (create a same-named user agent to override instead).
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
- Async subagent session sharing no longer fails with `ERR_PACKAGE_PATH_NOT_EXPORTED`. The runner tried `require.resolve("@mariozechner/pi-coding-agent/package.json")` to find pi's HTML export module, but pi's `exports` map doesn't include that subpath. The fix resolves the package root in the main pi process by walking up from `process.argv[1]` and passes it to the spawned runner through the config, bypassing `require.resolve` entirely. The Windows CLI resolution fallback in `getPiSpawnCommand` benefits from the same walk-up function.
|
|
20
|
+
|
|
5
21
|
## [0.8.5] - 2026-02-16
|
|
6
22
|
|
|
7
23
|
### Fixed
|
package/agents.ts
CHANGED
|
@@ -11,6 +11,8 @@ import { mergeAgentsForScope } from "./agent-selection.js";
|
|
|
11
11
|
|
|
12
12
|
export type AgentScope = "user" | "project" | "both";
|
|
13
13
|
|
|
14
|
+
export type AgentSource = "builtin" | "user" | "project";
|
|
15
|
+
|
|
14
16
|
export interface AgentConfig {
|
|
15
17
|
name: string;
|
|
16
18
|
description: string;
|
|
@@ -19,7 +21,7 @@ export interface AgentConfig {
|
|
|
19
21
|
model?: string;
|
|
20
22
|
thinking?: string;
|
|
21
23
|
systemPrompt: string;
|
|
22
|
-
source:
|
|
24
|
+
source: AgentSource;
|
|
23
25
|
filePath: string;
|
|
24
26
|
skills?: string[];
|
|
25
27
|
extensions?: string[];
|
|
@@ -44,7 +46,7 @@ export interface ChainStepConfig {
|
|
|
44
46
|
export interface ChainConfig {
|
|
45
47
|
name: string;
|
|
46
48
|
description: string;
|
|
47
|
-
source:
|
|
49
|
+
source: AgentSource;
|
|
48
50
|
filePath: string;
|
|
49
51
|
steps: ChainStepConfig[];
|
|
50
52
|
extraFields?: Record<string, string>;
|
|
@@ -85,7 +87,7 @@ function parseFrontmatter(content: string): { frontmatter: Record<string, string
|
|
|
85
87
|
return { frontmatter, body };
|
|
86
88
|
}
|
|
87
89
|
|
|
88
|
-
function loadAgentsFromDir(dir: string, source:
|
|
90
|
+
function loadAgentsFromDir(dir: string, source: AgentSource): AgentConfig[] {
|
|
89
91
|
const agents: AgentConfig[] = [];
|
|
90
92
|
|
|
91
93
|
if (!fs.existsSync(dir)) {
|
|
@@ -184,7 +186,7 @@ function loadAgentsFromDir(dir: string, source: "user" | "project"): AgentConfig
|
|
|
184
186
|
return agents;
|
|
185
187
|
}
|
|
186
188
|
|
|
187
|
-
function loadChainsFromDir(dir: string, source:
|
|
189
|
+
function loadChainsFromDir(dir: string, source: AgentSource): ChainConfig[] {
|
|
188
190
|
const chains: ChainConfig[] = [];
|
|
189
191
|
|
|
190
192
|
if (!fs.existsSync(dir)) {
|
|
@@ -240,13 +242,16 @@ function findNearestProjectAgentsDir(cwd: string): string | null {
|
|
|
240
242
|
}
|
|
241
243
|
}
|
|
242
244
|
|
|
245
|
+
const BUILTIN_AGENTS_DIR = path.join(os.homedir(), ".pi", "agent", "extensions", "subagent", "agents");
|
|
246
|
+
|
|
243
247
|
export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryResult {
|
|
244
248
|
const userDir = path.join(os.homedir(), ".pi", "agent", "agents");
|
|
245
249
|
const projectAgentsDir = findNearestProjectAgentsDir(cwd);
|
|
246
250
|
|
|
251
|
+
const builtinAgents = loadAgentsFromDir(BUILTIN_AGENTS_DIR, "builtin");
|
|
247
252
|
const userAgents = scope === "project" ? [] : loadAgentsFromDir(userDir, "user");
|
|
248
253
|
const projectAgents = scope === "user" || !projectAgentsDir ? [] : loadAgentsFromDir(projectAgentsDir, "project");
|
|
249
|
-
const agents = mergeAgentsForScope(scope, userAgents, projectAgents);
|
|
254
|
+
const agents = mergeAgentsForScope(scope, userAgents, projectAgents, builtinAgents);
|
|
250
255
|
|
|
251
256
|
return { agents, projectAgentsDir };
|
|
252
257
|
}
|
package/async-execution.ts
CHANGED
|
@@ -13,6 +13,7 @@ import type { AgentConfig } from "./agents.js";
|
|
|
13
13
|
import { applyThinkingSuffix } from "./execution.js";
|
|
14
14
|
import { injectSingleOutputInstruction, resolveSingleOutputPath } from "./single-output.js";
|
|
15
15
|
import { isParallelStep, resolveStepBehavior, type ChainStep, type SequentialStep, type StepOverrides } from "./settings.js";
|
|
16
|
+
import { resolvePiPackageRoot } from "./pi-spawn.js";
|
|
16
17
|
import { buildSkillInjection, normalizeSkillInput, resolveSkills } from "./skills.js";
|
|
17
18
|
import {
|
|
18
19
|
type ArtifactConfig,
|
|
@@ -23,6 +24,7 @@ import {
|
|
|
23
24
|
} from "./types.js";
|
|
24
25
|
|
|
25
26
|
const require = createRequire(import.meta.url);
|
|
27
|
+
const piPackageRoot = resolvePiPackageRoot();
|
|
26
28
|
const jitiCliPath: string | undefined = (() => {
|
|
27
29
|
const candidates: Array<() => string> = [
|
|
28
30
|
() => path.join(path.dirname(require.resolve("jiti/package.json")), "lib/jiti-cli.mjs"),
|
|
@@ -188,6 +190,7 @@ export function executeAsyncChain(
|
|
|
188
190
|
sessionDir: sessionRoot ? path.join(sessionRoot, `async-${id}`) : undefined,
|
|
189
191
|
asyncDir,
|
|
190
192
|
sessionId: ctx.currentSessionId,
|
|
193
|
+
piPackageRoot,
|
|
191
194
|
},
|
|
192
195
|
id,
|
|
193
196
|
runnerCwd,
|
|
@@ -265,6 +268,7 @@ export function executeAsyncSingle(
|
|
|
265
268
|
sessionDir: sessionRoot ? path.join(sessionRoot, `async-${id}`) : undefined,
|
|
266
269
|
asyncDir,
|
|
267
270
|
sessionId: ctx.currentSessionId,
|
|
271
|
+
piPackageRoot,
|
|
268
272
|
},
|
|
269
273
|
id,
|
|
270
274
|
runnerCwd,
|
package/package.json
CHANGED
package/pi-spawn.ts
CHANGED
|
@@ -4,6 +4,22 @@ import * as path from "node:path";
|
|
|
4
4
|
|
|
5
5
|
const require = createRequire(import.meta.url);
|
|
6
6
|
|
|
7
|
+
export function resolvePiPackageRoot(): string | undefined {
|
|
8
|
+
try {
|
|
9
|
+
const entry = process.argv[1];
|
|
10
|
+
if (!entry) return undefined;
|
|
11
|
+
let dir = path.dirname(fs.realpathSync(entry));
|
|
12
|
+
while (dir !== path.dirname(dir)) {
|
|
13
|
+
try {
|
|
14
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(dir, "package.json"), "utf-8"));
|
|
15
|
+
if (pkg.name === "@mariozechner/pi-coding-agent") return dir;
|
|
16
|
+
} catch {}
|
|
17
|
+
dir = path.dirname(dir);
|
|
18
|
+
}
|
|
19
|
+
} catch {}
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
7
23
|
export interface PiSpawnDeps {
|
|
8
24
|
platform?: NodeJS.Platform;
|
|
9
25
|
execPath?: string;
|
|
@@ -11,6 +27,7 @@ export interface PiSpawnDeps {
|
|
|
11
27
|
existsSync?: (filePath: string) => boolean;
|
|
12
28
|
readFileSync?: (filePath: string, encoding: "utf-8") => string;
|
|
13
29
|
resolvePackageJson?: () => string;
|
|
30
|
+
piPackageRoot?: string;
|
|
14
31
|
}
|
|
15
32
|
|
|
16
33
|
export interface PiSpawnCommand {
|
|
@@ -40,7 +57,11 @@ export function resolveWindowsPiCliScript(deps: PiSpawnDeps = {}): string | unde
|
|
|
40
57
|
}
|
|
41
58
|
|
|
42
59
|
try {
|
|
43
|
-
const resolvePackageJson = deps.resolvePackageJson ?? (() =>
|
|
60
|
+
const resolvePackageJson = deps.resolvePackageJson ?? (() => {
|
|
61
|
+
const root = deps.piPackageRoot ?? resolvePiPackageRoot();
|
|
62
|
+
if (root) return path.join(root, "package.json");
|
|
63
|
+
return require.resolve("@mariozechner/pi-coding-agent/package.json");
|
|
64
|
+
});
|
|
44
65
|
const packageJsonPath = resolvePackageJson();
|
|
45
66
|
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8")) as {
|
|
46
67
|
bin?: string | Record<string, string>;
|
package/subagent-runner.ts
CHANGED
|
@@ -44,6 +44,7 @@ interface SubagentRunConfig {
|
|
|
44
44
|
sessionDir?: string;
|
|
45
45
|
asyncDir: string;
|
|
46
46
|
sessionId?: string | null;
|
|
47
|
+
piPackageRoot?: string;
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
interface StepResult {
|
|
@@ -134,8 +135,8 @@ function runPiStreaming(
|
|
|
134
135
|
});
|
|
135
136
|
}
|
|
136
137
|
|
|
137
|
-
async function exportSessionHtml(sessionFile: string, outputDir: string): Promise<string> {
|
|
138
|
-
const pkgRoot = path.dirname(require.resolve("@mariozechner/pi-coding-agent/package.json"));
|
|
138
|
+
async function exportSessionHtml(sessionFile: string, outputDir: string, piPackageRoot?: string): Promise<string> {
|
|
139
|
+
const pkgRoot = piPackageRoot ?? path.dirname(require.resolve("@mariozechner/pi-coding-agent/package.json"));
|
|
139
140
|
const exportModulePath = path.join(pkgRoot, "dist", "core", "export-html", "index.js");
|
|
140
141
|
const moduleUrl = pathToFileURL(exportModulePath).href;
|
|
141
142
|
const mod = await import(moduleUrl);
|
|
@@ -516,7 +517,7 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
|
|
|
516
517
|
sessionFile = findLatestSessionFile(config.sessionDir) ?? undefined;
|
|
517
518
|
if (sessionFile) {
|
|
518
519
|
try {
|
|
519
|
-
const htmlPath = await exportSessionHtml(sessionFile, config.sessionDir);
|
|
520
|
+
const htmlPath = await exportSessionHtml(sessionFile, config.sessionDir, config.piPackageRoot);
|
|
520
521
|
const share = createShareLink(htmlPath);
|
|
521
522
|
if ("error" in share) shareError = share.error;
|
|
522
523
|
else {
|