taskplane 0.25.1 → 0.25.3
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,60 @@ export default function (pi: ExtensionAPI) {
|
|
|
359
359
|
/**
|
|
360
360
|
* Resolve the Pi CLI entrypoint path (same logic as agent-host.ts).
|
|
361
361
|
*/
|
|
362
|
+
function getNpmGlobalRoot(): string {
|
|
363
|
+
try {
|
|
364
|
+
const result = spawnSync("npm", ["root", "-g"], { encoding: "utf-8", timeout: 5000, shell: true });
|
|
365
|
+
return result.stdout?.trim() || "";
|
|
366
|
+
} catch { return ""; }
|
|
367
|
+
}
|
|
368
|
+
|
|
362
369
|
function resolvePiCli(): string {
|
|
363
|
-
const relPath = join("
|
|
370
|
+
const relPath = join("@mariozechner", "pi-coding-agent", "dist", "cli.js");
|
|
364
371
|
const candidates: string[] = [];
|
|
365
|
-
|
|
372
|
+
|
|
373
|
+
// Dynamic: npm root -g (covers nvm, Homebrew, volta, and all custom prefixes)
|
|
374
|
+
const npmRoot = getNpmGlobalRoot();
|
|
375
|
+
if (npmRoot) candidates.push(join(npmRoot, relPath));
|
|
376
|
+
|
|
377
|
+
// Well-known static paths
|
|
366
378
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
379
|
+
if (process.env.APPDATA) candidates.push(join(process.env.APPDATA, "npm", "node_modules", relPath));
|
|
367
380
|
if (home) {
|
|
368
|
-
candidates.push(join(home, "AppData", "Roaming", "npm", relPath));
|
|
369
|
-
candidates.push(join(home, ".npm-global", "lib", relPath));
|
|
381
|
+
candidates.push(join(home, "AppData", "Roaming", "npm", "node_modules", relPath));
|
|
382
|
+
candidates.push(join(home, ".npm-global", "lib", "node_modules", relPath));
|
|
370
383
|
}
|
|
371
|
-
candidates.push(join("/usr", "local", "lib", relPath));
|
|
384
|
+
candidates.push(join("/usr", "local", "lib", "node_modules", relPath));
|
|
385
|
+
candidates.push(join("/opt", "homebrew", "lib", "node_modules", relPath));
|
|
386
|
+
|
|
372
387
|
for (const c of candidates) {
|
|
373
388
|
if (existsSync(c)) return c;
|
|
374
389
|
}
|
|
375
|
-
throw new Error("Cannot find Pi CLI entrypoint");
|
|
390
|
+
throw new Error("Cannot find Pi CLI entrypoint. Run: npm root -g to verify your npm global path.");
|
|
376
391
|
}
|
|
377
392
|
|
|
378
393
|
/**
|
|
379
394
|
* Load the reviewer system prompt from base template + local override.
|
|
380
395
|
*/
|
|
381
396
|
function loadReviewerPrompt(): string {
|
|
382
|
-
const
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
397
|
+
const relPath = join("taskplane", "templates", "agents", "task-reviewer.md");
|
|
398
|
+
const candidates: string[] = [];
|
|
399
|
+
|
|
400
|
+
// Dynamic: npm root -g
|
|
401
|
+
const npmRoot = getNpmGlobalRoot();
|
|
402
|
+
if (npmRoot) candidates.push(join(npmRoot, relPath));
|
|
403
|
+
|
|
404
|
+
// Well-known static paths
|
|
405
|
+
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
406
|
+
if (process.env.APPDATA) candidates.push(join(process.env.APPDATA, "npm", "node_modules", relPath));
|
|
407
|
+
if (home) {
|
|
408
|
+
candidates.push(join(home, "AppData", "Roaming", "npm", "node_modules", relPath));
|
|
409
|
+
candidates.push(join(home, ".npm-global", "lib", "node_modules", relPath));
|
|
410
|
+
}
|
|
411
|
+
candidates.push(join("/usr", "local", "lib", "node_modules", relPath));
|
|
412
|
+
candidates.push(join("/opt", "homebrew", "lib", "node_modules", relPath));
|
|
413
|
+
|
|
386
414
|
let basePrompt = "You are a code reviewer. Read the request and write your review to the specified output file.";
|
|
387
|
-
for (const p of
|
|
415
|
+
for (const p of candidates) {
|
|
388
416
|
try {
|
|
389
417
|
if (!existsSync(p)) continue;
|
|
390
418
|
const raw = readFileSync(p, "utf-8");
|
|
@@ -2126,31 +2126,20 @@ function parseAgentFile(filePath: string): { fm: Record<string, string>; body: s
|
|
|
2126
2126
|
* @since TP-117
|
|
2127
2127
|
*/
|
|
2128
2128
|
function loadBaseAgentPrompt(agentName: string): string {
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
//
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
candidates.push(join(home, "AppData", "Roaming", "npm", relPath));
|
|
2137
|
-
candidates.push(join(home, ".npm-global", "lib", relPath));
|
|
2138
|
-
}
|
|
2139
|
-
candidates.push(join("/usr", "local", "lib", relPath));
|
|
2140
|
-
candidates.push(join("/opt", "homebrew", "lib", relPath));
|
|
2141
|
-
|
|
2142
|
-
// Dynamic: npm root -g
|
|
2129
|
+
// Use the same robust resolution as resolveTaskplanePackageFile, which
|
|
2130
|
+
// handles all npm setups (nvm, Homebrew, volta, Windows, etc.) via
|
|
2131
|
+
// npm root -g caching and well-known fallback paths.
|
|
2132
|
+
// This avoids loadBaseAgentPrompt silently returning "" (which would
|
|
2133
|
+
// cause the worker to skip reviews because the review_step instructions
|
|
2134
|
+
// live in the base template, not the local .pi/agents/ override).
|
|
2135
|
+
const relPath = join("templates", "agents", `${agentName}.md`);
|
|
2143
2136
|
try {
|
|
2144
|
-
const
|
|
2145
|
-
if (
|
|
2146
|
-
|
|
2137
|
+
const resolved = resolveTaskplanePackageFile(process.cwd(), relPath);
|
|
2138
|
+
if (existsSync(resolved)) {
|
|
2139
|
+
const def = parseAgentFile(resolved);
|
|
2140
|
+
if (def?.body) return def.body;
|
|
2147
2141
|
}
|
|
2148
|
-
} catch { /*
|
|
2149
|
-
|
|
2150
|
-
for (const p of candidates) {
|
|
2151
|
-
const def = parseAgentFile(p);
|
|
2152
|
-
if (def?.body) return def.body;
|
|
2153
|
-
}
|
|
2142
|
+
} catch { /* fall through */ }
|
|
2154
2143
|
return "";
|
|
2155
2144
|
}
|
|
2156
2145
|
|