pi-cohort 7.1.1 → 7.1.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
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [7.1.2] - 2026-09-29
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- `typebox` moves from `dependencies` to an optional `peerDependencies: "*"` entry, which silences pi's "Host-provided extension packages must be declared in peerDependencies" startup warning and removes the second typebox copy from consumer installs. The detached async runner keeps working without its own copy: `spawnRunner` now passes pi's own `typebox`, `typebox/compile`, and `typebox/value` files to the bare jiti child through `JITI_ALIAS`, the same alias map pi's extension loader applies in-process, so the `Cannot find module 'typebox/compile'` crash from [#9](https://github.com/jjuraszek/pi-cohort/issues/9) stays fixed.
|
|
8
|
+
|
|
3
9
|
## [7.1.1] - 2026-09-24
|
|
4
10
|
|
|
5
11
|
### Changed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-cohort",
|
|
3
|
-
"version": "7.1.
|
|
3
|
+
"version": "7.1.2",
|
|
4
4
|
"description": "Delegate Pi work to focused child agents: code review, scouting, implementation, parallel audits, saved chains, and background jobs.",
|
|
5
5
|
"author": "Jacek Juraszek",
|
|
6
6
|
"license": "MIT",
|
|
@@ -64,7 +64,8 @@
|
|
|
64
64
|
"@earendil-works/pi-agent-core": "*",
|
|
65
65
|
"@earendil-works/pi-ai": "*",
|
|
66
66
|
"@earendil-works/pi-coding-agent": ">=0.85.0",
|
|
67
|
-
"@earendil-works/pi-tui": "*"
|
|
67
|
+
"@earendil-works/pi-tui": "*",
|
|
68
|
+
"typebox": "*"
|
|
68
69
|
},
|
|
69
70
|
"peerDependenciesMeta": {
|
|
70
71
|
"@earendil-works/pi-agent-core": {
|
|
@@ -78,16 +79,19 @@
|
|
|
78
79
|
},
|
|
79
80
|
"@earendil-works/pi-tui": {
|
|
80
81
|
"optional": true
|
|
82
|
+
},
|
|
83
|
+
"typebox": {
|
|
84
|
+
"optional": true
|
|
81
85
|
}
|
|
82
86
|
},
|
|
83
87
|
"dependencies": {
|
|
84
|
-
"jiti": "^2.7.0"
|
|
85
|
-
"typebox": "^1.3.11"
|
|
88
|
+
"jiti": "^2.7.0"
|
|
86
89
|
},
|
|
87
90
|
"devDependencies": {
|
|
88
91
|
"@earendil-works/pi-agent-core": "^0.85.0",
|
|
89
92
|
"@earendil-works/pi-ai": "^0.85.0",
|
|
90
93
|
"@earendil-works/pi-coding-agent": "^0.85.0",
|
|
91
|
-
"@earendil-works/pi-tui": "^0.85.0"
|
|
94
|
+
"@earendil-works/pi-tui": "^0.85.0",
|
|
95
|
+
"typebox": "^1.3.11"
|
|
92
96
|
}
|
|
93
97
|
}
|
|
@@ -14,7 +14,7 @@ import { injectSingleOutputInstruction, normalizeSingleOutputOverride, resolvePa
|
|
|
14
14
|
import { buildChainInstructions, isDynamicParallelStep, isParallelStep, resolveStepBehavior, suppressProgressForReadOnlyTask, writeInitialProgressFile, type ChainStep, type ResolvedStepBehavior, type SequentialStep, type StepOverrides } from "../../shared/settings.ts";
|
|
15
15
|
import type { RunnerStep } from "../shared/parallel-utils.ts";
|
|
16
16
|
import { resolvePiPackageRoot } from "../shared/pi-spawn.ts";
|
|
17
|
-
import { ensureJitiCliPath } from "../shared/jiti-cli.ts";
|
|
17
|
+
import { ensureJitiCliPath, resolveHostModuleAliases } from "../shared/jiti-cli.ts";
|
|
18
18
|
export { createJitiCliResolver } from "../shared/jiti-cli.ts";
|
|
19
19
|
import { buildSkillInjection, normalizeSkillInput, resolveSkillsWithFallback } from "../../agents/skills.ts";
|
|
20
20
|
import { resolveChildCwd } from "../../shared/utils.ts";
|
|
@@ -145,7 +145,7 @@ export function isAsyncAvailable(): boolean {
|
|
|
145
145
|
* Falls back to ignored stdio if the log file cannot be opened; the parent always
|
|
146
146
|
* closes its copy of the fd, on every exit path.
|
|
147
147
|
*/
|
|
148
|
-
export function spawnDetachedWithLog(command: string, args: string[], cwd: string, asyncDir: string, spawnImpl: typeof spawn = spawn): { pid?: number; error?: string } {
|
|
148
|
+
export function spawnDetachedWithLog(command: string, args: string[], cwd: string, asyncDir: string, spawnImpl: typeof spawn = spawn, env?: NodeJS.ProcessEnv): { pid?: number; error?: string } {
|
|
149
149
|
let fd: number | undefined;
|
|
150
150
|
try {
|
|
151
151
|
try {
|
|
@@ -156,6 +156,7 @@ export function spawnDetachedWithLog(command: string, args: string[], cwd: strin
|
|
|
156
156
|
}
|
|
157
157
|
const proc = spawnImpl(command, args, {
|
|
158
158
|
cwd,
|
|
159
|
+
env,
|
|
159
160
|
detached: true,
|
|
160
161
|
stdio: fd === undefined ? "ignore" : ["ignore", fd, fd],
|
|
161
162
|
windowsHide: true,
|
|
@@ -187,7 +188,7 @@ export function spawnRunner(
|
|
|
187
188
|
suffix: string,
|
|
188
189
|
cwd: string,
|
|
189
190
|
asyncDir: string,
|
|
190
|
-
deps: { ensureJiti?: () => string | undefined; spawnImpl?: typeof spawn } = {},
|
|
191
|
+
deps: { ensureJiti?: () => string | undefined; spawnImpl?: typeof spawn; hostAliases?: () => Record<string, string> } = {},
|
|
191
192
|
): { pid?: number; error?: string } {
|
|
192
193
|
const ensureJiti = deps.ensureJiti ?? ensureJitiCliPath;
|
|
193
194
|
const jitiCliPath = ensureJiti();
|
|
@@ -209,7 +210,12 @@ export function spawnRunner(
|
|
|
209
210
|
fs.writeFileSync(cfgPath, JSON.stringify(cfg));
|
|
210
211
|
const runner = path.join(path.dirname(fileURLToPath(import.meta.url)), "subagent-runner.ts");
|
|
211
212
|
|
|
212
|
-
|
|
213
|
+
const aliases = (deps.hostAliases ?? resolveHostModuleAliases)();
|
|
214
|
+
const env = Object.keys(aliases).length > 0
|
|
215
|
+
? { ...process.env, JITI_ALIAS: JSON.stringify(aliases) }
|
|
216
|
+
: process.env;
|
|
217
|
+
|
|
218
|
+
return spawnDetachedWithLog(process.execPath, [jitiCliPath, runner, cfgPath], cwd, asyncDir, deps.spawnImpl ?? spawn, env);
|
|
213
219
|
}
|
|
214
220
|
|
|
215
221
|
/**
|
|
@@ -24,17 +24,23 @@ function resolveJitiCliFromPackageJson(packageJsonPath: string): string | undefi
|
|
|
24
24
|
return undefined;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
() => require.resolve(
|
|
27
|
+
function hostResolveCandidates(specifier: string): Array<() => string | undefined> {
|
|
28
|
+
return [
|
|
29
|
+
() => require.resolve(specifier),
|
|
30
30
|
() => piPackageRoot
|
|
31
|
-
? createRequire(path.join(piPackageRoot, "package.json")).resolve(
|
|
31
|
+
? createRequire(path.join(piPackageRoot, "package.json")).resolve(specifier)
|
|
32
32
|
: undefined,
|
|
33
33
|
() => {
|
|
34
34
|
if (!process.argv[1]) return undefined;
|
|
35
35
|
const piEntry = fs.realpathSync(process.argv[1]);
|
|
36
|
-
return createRequire(piEntry).resolve(
|
|
36
|
+
return createRequire(piEntry).resolve(specifier);
|
|
37
37
|
},
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function resolveJitiCliPath(): string | undefined {
|
|
42
|
+
const candidates = [
|
|
43
|
+
...hostResolveCandidates("jiti/package.json"),
|
|
38
44
|
() => piPackageRoot ? path.join(piPackageRoot, "node_modules", "jiti", "package.json") : undefined,
|
|
39
45
|
];
|
|
40
46
|
for (const candidate of candidates) {
|
|
@@ -50,6 +56,31 @@ function resolveJitiCliPath(): string | undefined {
|
|
|
50
56
|
return undefined;
|
|
51
57
|
}
|
|
52
58
|
|
|
59
|
+
function resolveFromHost(specifier: string): string | undefined {
|
|
60
|
+
for (const candidate of hostResolveCandidates(specifier)) {
|
|
61
|
+
try {
|
|
62
|
+
const resolved = candidate();
|
|
63
|
+
if (resolved) return resolved;
|
|
64
|
+
} catch {
|
|
65
|
+
// Candidate not available in this install, continue probing.
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Pi's extension loader aliases these to its own copies; the detached runner boots
|
|
72
|
+
// under the bare jiti CLI, so it gets the same map through JITI_ALIAS.
|
|
73
|
+
const HOST_ALIASED_SPECIFIERS = ["typebox", "typebox/compile", "typebox/value"];
|
|
74
|
+
|
|
75
|
+
export function resolveHostModuleAliases(): Record<string, string> {
|
|
76
|
+
const aliases: Record<string, string> = {};
|
|
77
|
+
for (const specifier of HOST_ALIASED_SPECIFIERS) {
|
|
78
|
+
const resolved = resolveFromHost(specifier);
|
|
79
|
+
if (resolved) aliases[specifier] = resolved;
|
|
80
|
+
}
|
|
81
|
+
return aliases;
|
|
82
|
+
}
|
|
83
|
+
|
|
53
84
|
export function createJitiCliResolver(deps: { resolve?: () => string | undefined; exists?: (p: string) => boolean } = {}): () => string | undefined {
|
|
54
85
|
const resolve = deps.resolve ?? resolveJitiCliPath;
|
|
55
86
|
const exists = deps.exists ?? ((p: string) => fs.existsSync(p));
|