taskplane 0.25.2 → 0.25.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.
|
@@ -25,7 +25,7 @@ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
|
25
25
|
import { Type } from "@mariozechner/pi-ai";
|
|
26
26
|
import { writeFileSync, readFileSync, existsSync, mkdirSync, renameSync, unlinkSync } from "fs";
|
|
27
27
|
import { join, dirname } from "path";
|
|
28
|
-
import { spawn as nodeSpawn } from "child_process";
|
|
28
|
+
import { spawn as nodeSpawn, spawnSync } from "child_process";
|
|
29
29
|
import { randomBytes } from "crypto";
|
|
30
30
|
import { buildExpansionRequestId, type SegmentExpansionRequest } from "./types.ts";
|
|
31
31
|
|
|
@@ -359,32 +359,63 @@ export default function (pi: ExtensionAPI) {
|
|
|
359
359
|
/**
|
|
360
360
|
* Resolve the Pi CLI entrypoint path (same logic as agent-host.ts).
|
|
361
361
|
*/
|
|
362
|
+
let _npmRootCache: string | null = null;
|
|
363
|
+
function getNpmGlobalRoot(): string {
|
|
364
|
+
if (_npmRootCache !== null) return _npmRootCache;
|
|
365
|
+
try {
|
|
366
|
+
const result = spawnSync("npm", ["root", "-g"], { encoding: "utf-8", timeout: 5000, shell: true });
|
|
367
|
+
_npmRootCache = result.stdout?.trim() || "";
|
|
368
|
+
} catch { _npmRootCache = ""; }
|
|
369
|
+
return _npmRootCache;
|
|
370
|
+
}
|
|
371
|
+
|
|
362
372
|
function resolvePiCli(): string {
|
|
363
|
-
const relPath = join("
|
|
373
|
+
const relPath = join("@mariozechner", "pi-coding-agent", "dist", "cli.js");
|
|
364
374
|
const candidates: string[] = [];
|
|
365
|
-
|
|
375
|
+
|
|
376
|
+
// Dynamic: npm root -g (covers nvm, Homebrew, volta, and all custom prefixes)
|
|
377
|
+
const npmRoot = getNpmGlobalRoot();
|
|
378
|
+
if (npmRoot) candidates.push(join(npmRoot, relPath));
|
|
379
|
+
|
|
380
|
+
// Well-known static paths
|
|
366
381
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
382
|
+
if (process.env.APPDATA) candidates.push(join(process.env.APPDATA, "npm", "node_modules", relPath));
|
|
367
383
|
if (home) {
|
|
368
|
-
candidates.push(join(home, "AppData", "Roaming", "npm", relPath));
|
|
369
|
-
candidates.push(join(home, ".npm-global", "lib", relPath));
|
|
384
|
+
candidates.push(join(home, "AppData", "Roaming", "npm", "node_modules", relPath));
|
|
385
|
+
candidates.push(join(home, ".npm-global", "lib", "node_modules", relPath));
|
|
370
386
|
}
|
|
371
|
-
candidates.push(join("/usr", "local", "lib", relPath));
|
|
387
|
+
candidates.push(join("/usr", "local", "lib", "node_modules", relPath));
|
|
388
|
+
candidates.push(join("/opt", "homebrew", "lib", "node_modules", relPath));
|
|
389
|
+
|
|
372
390
|
for (const c of candidates) {
|
|
373
391
|
if (existsSync(c)) return c;
|
|
374
392
|
}
|
|
375
|
-
throw new Error("Cannot find Pi CLI entrypoint");
|
|
393
|
+
throw new Error("Cannot find Pi CLI entrypoint. Run: npm root -g to verify your npm global path.");
|
|
376
394
|
}
|
|
377
395
|
|
|
378
396
|
/**
|
|
379
397
|
* Load the reviewer system prompt from base template + local override.
|
|
380
398
|
*/
|
|
381
399
|
function loadReviewerPrompt(): string {
|
|
382
|
-
const
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
400
|
+
const relPath = join("taskplane", "templates", "agents", "task-reviewer.md");
|
|
401
|
+
const candidates: string[] = [];
|
|
402
|
+
|
|
403
|
+
// Dynamic: npm root -g
|
|
404
|
+
const npmRoot = getNpmGlobalRoot();
|
|
405
|
+
if (npmRoot) candidates.push(join(npmRoot, relPath));
|
|
406
|
+
|
|
407
|
+
// Well-known static paths
|
|
408
|
+
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
409
|
+
if (process.env.APPDATA) candidates.push(join(process.env.APPDATA, "npm", "node_modules", relPath));
|
|
410
|
+
if (home) {
|
|
411
|
+
candidates.push(join(home, "AppData", "Roaming", "npm", "node_modules", relPath));
|
|
412
|
+
candidates.push(join(home, ".npm-global", "lib", "node_modules", relPath));
|
|
413
|
+
}
|
|
414
|
+
candidates.push(join("/usr", "local", "lib", "node_modules", relPath));
|
|
415
|
+
candidates.push(join("/opt", "homebrew", "lib", "node_modules", relPath));
|
|
416
|
+
|
|
386
417
|
let basePrompt = "You are a code reviewer. Read the request and write your review to the specified output file.";
|
|
387
|
-
for (const p of
|
|
418
|
+
for (const p of candidates) {
|
|
388
419
|
try {
|
|
389
420
|
if (!existsSync(p)) continue;
|
|
390
421
|
const raw = readFileSync(p, "utf-8");
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* @since TP-104
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
import { spawn, type ChildProcess } from "child_process";
|
|
23
|
+
import { spawn, spawnSync, type ChildProcess } from "child_process";
|
|
24
24
|
import {
|
|
25
25
|
readFileSync, writeFileSync, appendFileSync, mkdirSync,
|
|
26
26
|
existsSync, readdirSync, renameSync,
|
|
@@ -55,46 +55,54 @@ import { appendMailboxAuditEvent } from "./mailbox.ts";
|
|
|
55
55
|
* with `shell: false`. This function resolves the underlying JS file.
|
|
56
56
|
*
|
|
57
57
|
* Resolution order:
|
|
58
|
-
* 1.
|
|
59
|
-
* 2.
|
|
60
|
-
* 3. /
|
|
58
|
+
* 1. npm root -g (dynamic — covers nvm, Homebrew, volta, custom prefix)
|
|
59
|
+
* 2. APPDATA/npm/node_modules/... (Windows)
|
|
60
|
+
* 3. HOME/.npm-global/lib/node_modules/...
|
|
61
|
+
* 4. /usr/local/lib/node_modules/...
|
|
62
|
+
* 5. /opt/homebrew/lib/node_modules/... (macOS Homebrew)
|
|
61
63
|
*
|
|
62
64
|
* @returns Absolute path to the Pi CLI JS entrypoint
|
|
63
65
|
* @throws Error if Pi CLI cannot be found
|
|
64
66
|
*
|
|
65
67
|
* @since TP-104
|
|
66
68
|
*/
|
|
69
|
+
let _npmGlobalRootCache: string | null = null;
|
|
70
|
+
function getNpmGlobalRoot(): string {
|
|
71
|
+
if (_npmGlobalRootCache !== null) return _npmGlobalRootCache;
|
|
72
|
+
try {
|
|
73
|
+
const result = spawnSync("npm", ["root", "-g"], { encoding: "utf-8", timeout: 5000, shell: true });
|
|
74
|
+
_npmGlobalRootCache = result.stdout?.trim() || "";
|
|
75
|
+
} catch {
|
|
76
|
+
_npmGlobalRootCache = "";
|
|
77
|
+
}
|
|
78
|
+
return _npmGlobalRootCache;
|
|
79
|
+
}
|
|
80
|
+
|
|
67
81
|
export function resolvePiCliPath(): string {
|
|
68
|
-
const relPath = join("
|
|
82
|
+
const relPath = join("@mariozechner", "pi-coding-agent", "dist", "cli.js");
|
|
69
83
|
const candidates: string[] = [];
|
|
70
84
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
85
|
+
// Dynamic first: covers nvm, Homebrew, volta, custom npm prefix
|
|
86
|
+
const npmRoot = getNpmGlobalRoot();
|
|
87
|
+
if (npmRoot) candidates.push(join(npmRoot, relPath));
|
|
88
|
+
|
|
89
|
+
// Well-known static fallbacks
|
|
74
90
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
91
|
+
if (process.env.APPDATA) candidates.push(join(process.env.APPDATA, "npm", "node_modules", relPath));
|
|
75
92
|
if (home) {
|
|
76
|
-
candidates.push(join(home, "AppData", "Roaming", "npm", relPath));
|
|
77
|
-
candidates.push(join(home, ".npm-global", "lib", relPath));
|
|
93
|
+
candidates.push(join(home, "AppData", "Roaming", "npm", "node_modules", relPath));
|
|
94
|
+
candidates.push(join(home, ".npm-global", "lib", "node_modules", relPath));
|
|
78
95
|
}
|
|
79
|
-
candidates.push(join("/usr", "local", "lib", relPath));
|
|
80
|
-
candidates.push(join("/opt", "homebrew", "lib", relPath));
|
|
81
|
-
|
|
82
|
-
// Dynamic: npm root -g
|
|
83
|
-
try {
|
|
84
|
-
const { spawnSync } = require("child_process");
|
|
85
|
-
const result = spawnSync("npm", ["root", "-g"], { encoding: "utf-8", timeout: 5000, shell: true });
|
|
86
|
-
if (result.stdout?.trim()) {
|
|
87
|
-
candidates.push(join(result.stdout.trim(), "@mariozechner", "pi-coding-agent", "dist", "cli.js"));
|
|
88
|
-
}
|
|
89
|
-
} catch { /* ignore */ }
|
|
96
|
+
candidates.push(join("/usr", "local", "lib", "node_modules", relPath));
|
|
97
|
+
candidates.push(join("/opt", "homebrew", "lib", "node_modules", relPath));
|
|
90
98
|
|
|
91
99
|
for (const candidate of candidates) {
|
|
92
100
|
if (existsSync(candidate)) return candidate;
|
|
93
101
|
}
|
|
94
102
|
|
|
95
103
|
throw new Error(
|
|
96
|
-
"Cannot find Pi CLI entrypoint (cli.js). Ensure pi is installed globally. " +
|
|
97
|
-
`
|
|
104
|
+
"Cannot find Pi CLI entrypoint (cli.js). Ensure pi is installed globally via 'pi install'. " +
|
|
105
|
+
`npm root -g: ${npmRoot || "(not found)"}`,
|
|
98
106
|
);
|
|
99
107
|
}
|
|
100
108
|
|