privateer-agent 0.12.27 → 0.12.29
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/bin/privateer-launch.mjs +50 -0
- package/bin/privateer-splash.mjs +18 -1
- package/bin/privateer.cmd +3 -0
- package/extensions/privateer-context.ts +18 -8
- package/package.json +5 -4
- package/patches/{@earendil-works+pi-coding-agent+0.84.1.patch → @earendil-works+pi-coding-agent+0.84.4.patch} +210 -86
- package/src/config/moatManifest.json +25 -22
- package/src/context.ts +9 -0
- package/src/remote/remoteBridge.ts +10 -3
package/bin/privateer-launch.mjs
CHANGED
|
@@ -35,6 +35,21 @@ const HERE = path.dirname(fileURLToPath(import.meta.url)); // bin/
|
|
|
35
35
|
const REPO = path.resolve(HERE, "..");
|
|
36
36
|
const isWin = process.platform === "win32";
|
|
37
37
|
|
|
38
|
+
// On Windows, ensure the console output code page is UTF-8 (65001).
|
|
39
|
+
// Without this, raw UTF-8 writes to stdout/stderr (such as fs.writeSync(2, ...) in the
|
|
40
|
+
// boot splash worker) are decoded through the OEM code page (CP437/850), turning
|
|
41
|
+
// Unicode wave blocks and emojis into 3-byte mojibake that wraps and floods the console.
|
|
42
|
+
if (isWin) {
|
|
43
|
+
try {
|
|
44
|
+
const chcp = process.env.SystemRoot
|
|
45
|
+
? path.join(process.env.SystemRoot, "System32", "chcp.com")
|
|
46
|
+
: "chcp.com";
|
|
47
|
+
spawnSync(chcp, ["65001"], { stdio: "ignore", windowsHide: true });
|
|
48
|
+
} catch {
|
|
49
|
+
/* best effort */
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
38
53
|
const PRIVATEER_HOME = process.env.PRIVATEER_HOME || path.join(os.homedir(), ".privateer");
|
|
39
54
|
const ENV_FILE = path.join(REPO, ".env"); // dev-only; a real install has none
|
|
40
55
|
const AGENT_DIR = path.join(PRIVATEER_HOME, "agent");
|
|
@@ -64,6 +79,38 @@ function sweepLegacyShims() {
|
|
|
64
79
|
}
|
|
65
80
|
}
|
|
66
81
|
|
|
82
|
+
// Pi's shell tools spill oversized command output to `$TMPDIR/pi-{bash,powershell,
|
|
83
|
+
// output}-<hex>.log` and hand the model the path — a good design, with no other half:
|
|
84
|
+
// NOTHING in Pi ever deletes them. Two `grep -rn` calls that wandered into node_modules
|
|
85
|
+
// left 630MB of minified JS in one developer's tmpdir, inside a 640MB/22-file pile that
|
|
86
|
+
// had been accumulating for weeks. macOS clears /var/folders only on its own schedule
|
|
87
|
+
// and Linux distros vary, so on a long-lived machine this is simply a leak.
|
|
88
|
+
//
|
|
89
|
+
// A day is the useful window: the path is only ever quoted into a live session, so a log
|
|
90
|
+
// outlives its usefulness the moment that session ends. Silent and best-effort — the acp
|
|
91
|
+
// branch's stdout is a JSON-RPC stream, and a tmpdir we can't read is not a launch
|
|
92
|
+
// problem. Name-matched before stat so the common case is one readdir.
|
|
93
|
+
const BASH_LOG_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
94
|
+
const BASH_LOG_RE = /^pi-(?:bash|powershell|output)-[0-9a-f]{16}\.log$/;
|
|
95
|
+
|
|
96
|
+
function sweepBashLogs() {
|
|
97
|
+
try {
|
|
98
|
+
const dir = os.tmpdir();
|
|
99
|
+
const cutoff = Date.now() - BASH_LOG_MAX_AGE_MS;
|
|
100
|
+
for (const name of fs.readdirSync(dir)) {
|
|
101
|
+
if (!BASH_LOG_RE.test(name)) continue;
|
|
102
|
+
const file = path.join(dir, name);
|
|
103
|
+
try {
|
|
104
|
+
if (fs.statSync(file).mtimeMs < cutoff) fs.rmSync(file, { force: true });
|
|
105
|
+
} catch {
|
|
106
|
+
/* raced with another session, or not ours to delete — either way, skip it. */
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
} catch {
|
|
110
|
+
/* unreadable tmpdir; the logs stay. */
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
67
114
|
// --- bundle detection ------------------------------------------------------
|
|
68
115
|
// A self-contained bundle ships its own pinned Node at "$REPO/node[.exe]" plus a
|
|
69
116
|
// BUNDLE_INFO.json marker (built by scripts/build-bundle.mjs). When present we use
|
|
@@ -279,6 +326,7 @@ if (sub === "update") {
|
|
|
279
326
|
// `daemon` is a hidden back-compat alias for the pre-rename command name.
|
|
280
327
|
else if (sub === "harbor" || sub === "daemon") {
|
|
281
328
|
sweepLegacyShims(); // a harbor-only machine upgrades too — see the function's note
|
|
329
|
+
sweepBashLogs();
|
|
282
330
|
const nodeArgs = fs.existsSync(ENV_FILE) ? [`--env-file=${ENV_FILE}`] : [];
|
|
283
331
|
// A resident background process, stopped by launchd/systemd/scripts with a plain
|
|
284
332
|
// `kill` — which reaches only this launcher. See runToCompletion.
|
|
@@ -304,6 +352,7 @@ else if (sub === "verify") {
|
|
|
304
352
|
// stray stdout line breaks the JSON-RPC stream and the host disconnects.
|
|
305
353
|
else if (sub === "acp") {
|
|
306
354
|
sweepLegacyShims(); // silent: only ever removes files
|
|
355
|
+
sweepBashLogs(); // silent too
|
|
307
356
|
const nodeArgs = fs.existsSync(ENV_FILE) ? [`--env-file=${ENV_FILE}`] : [];
|
|
308
357
|
// Long-lived and driven over stdio by an editor, which stops it by terminating
|
|
309
358
|
// the process rather than by a keystroke. Same leak, same fix.
|
|
@@ -329,6 +378,7 @@ else {
|
|
|
329
378
|
// to drop one, and clear out any shim an older release left behind.
|
|
330
379
|
fs.mkdirSync(EXT_DIR, { recursive: true });
|
|
331
380
|
sweepLegacyShims();
|
|
381
|
+
sweepBashLogs();
|
|
332
382
|
|
|
333
383
|
// Resolve every moat entry point to an absolute path, to be passed to Pi as `-e`.
|
|
334
384
|
// Dependencies resolve by walking the node_modules chain, NOT as REPO/node_modules: npm
|
package/bin/privateer-splash.mjs
CHANGED
|
@@ -38,6 +38,8 @@
|
|
|
38
38
|
//
|
|
39
39
|
// The wave is drawn on STDERR; stdout belongs to the TUI's canvas.
|
|
40
40
|
|
|
41
|
+
import { spawnSync } from "node:child_process";
|
|
42
|
+
import path from "node:path";
|
|
41
43
|
import { Worker } from "node:worker_threads";
|
|
42
44
|
|
|
43
45
|
const enabled =
|
|
@@ -46,6 +48,20 @@ const enabled =
|
|
|
46
48
|
!process.env.PRIVATEER_NO_SPLASH &&
|
|
47
49
|
!process.env.CI;
|
|
48
50
|
|
|
51
|
+
// On Windows, ensure the console output code page is UTF-8 (65001) before the worker
|
|
52
|
+
// thread starts drawing. If privateer was launched via npm/npx or direct node rather
|
|
53
|
+
// than privateer.cmd, the console might still be on OEM CP437.
|
|
54
|
+
if (enabled && process.platform === "win32") {
|
|
55
|
+
try {
|
|
56
|
+
const chcp = process.env.SystemRoot
|
|
57
|
+
? path.join(process.env.SystemRoot, "System32", "chcp.com")
|
|
58
|
+
: "chcp.com";
|
|
59
|
+
spawnSync(chcp, ["65001"], { stdio: "ignore", windowsHide: true });
|
|
60
|
+
} catch {
|
|
61
|
+
/* best effort */
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
49
65
|
// Bytes of stdout after TUI.start() that mean "this is the first frame, not a control
|
|
50
66
|
// sequence". Everything Pi writes between raw mode and the frame is short (the paste
|
|
51
67
|
// toggle, a Kitty protocol query, the cursor hide, an OSC window title — 42 bytes all
|
|
@@ -72,7 +88,8 @@ if (enabled) {
|
|
|
72
88
|
|
|
73
89
|
// Room for " ⚓ " + wave + message + elapsed, clamped so a narrow terminal doesn't
|
|
74
90
|
// wrap (a wrapped line survives our `\r\x1b[K` erase only on its last row).
|
|
75
|
-
const
|
|
91
|
+
const cols = err.columns && err.columns > 0 ? err.columns : 80;
|
|
92
|
+
const width = Math.max(6, Math.min(28, cols - 34));
|
|
76
93
|
|
|
77
94
|
// The worker source is plain logic with no escape sequences of its own — every ANSI
|
|
78
95
|
// string is handed over in workerData, so nothing here has to survive two rounds of
|
package/bin/privateer.cmd
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
@echo off
|
|
2
|
+
REM Ensure console output code page is UTF-8 so Unicode blocks and emojis render
|
|
3
|
+
REM correctly without CP437 mojibake or line-wrapping cascades.
|
|
4
|
+
chcp 65001 >nul 2>&1
|
|
2
5
|
REM Windows entry point for a Privateer bundle. Mirrors the unix bin/privateer-tui
|
|
3
6
|
REM shim: run the bundled Node against the shared cross-platform launcher. %~dp0 is
|
|
4
7
|
REM this file's dir (<app>\bin\), so ..\node.exe is the bundled runtime.
|
|
@@ -13,7 +13,14 @@
|
|
|
13
13
|
// advertises /init. After /init we emit the shared context-changed signal so that line
|
|
14
14
|
// refreshes at once. See src/context.ts for the discovery/formatting details.
|
|
15
15
|
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
contextBlock,
|
|
18
|
+
writeTemplate,
|
|
19
|
+
emitContextChanged,
|
|
20
|
+
CONTEXT_BLOCK_MARKER,
|
|
21
|
+
RUNTIME_GUIDELINES_MARKER,
|
|
22
|
+
runtimeGuidelinesBlock,
|
|
23
|
+
} from "../src/context.ts";
|
|
17
24
|
|
|
18
25
|
// Honor Pi's own "disable context files" switch, so --no-context-files / -nc silences
|
|
19
26
|
// PRIVATEER.md too (not just AGENTS.md/CLAUDE.md) — otherwise the flag would half-work.
|
|
@@ -25,13 +32,16 @@ export default function privateerContext(pi: any): void {
|
|
|
25
32
|
// and chained across before_agent_start handlers, so appending here is idempotent for
|
|
26
33
|
// the turn; the marker guard makes it a no-op if an earlier handler already added it.
|
|
27
34
|
pi.on("before_agent_start", (event: any) => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
let prompt: string = event?.systemPrompt ?? "";
|
|
36
|
+
if (!prompt.includes(RUNTIME_GUIDELINES_MARKER)) {
|
|
37
|
+
prompt += runtimeGuidelinesBlock();
|
|
38
|
+
}
|
|
39
|
+
if (!CONTEXT_FILES_DISABLED && !prompt.includes(CONTEXT_BLOCK_MARKER)) {
|
|
40
|
+
const cwd = event?.systemPromptOptions?.cwd ?? process.cwd();
|
|
41
|
+
const block = contextBlock(cwd);
|
|
42
|
+
if (block) prompt += block;
|
|
43
|
+
}
|
|
44
|
+
return { systemPrompt: prompt };
|
|
35
45
|
});
|
|
36
46
|
|
|
37
47
|
// /init — scaffold a PRIVATEER.md in the working directory. Never clobbers an existing
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "privateer-agent",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.29",
|
|
4
4
|
"description": "Privacy-first terminal coding agent — bring your own model across 20 providers (Anthropic, OpenAI, OpenRouter, Google, local Ollama…). Safe-by-default permissions, MCP, sub-agents, workflows, and verifiable TEE inference. Built on the Pi toolkit.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -69,9 +69,9 @@
|
|
|
69
69
|
"node": ">=22.19.0"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"@earendil-works/pi-ai": "0.84.
|
|
73
|
-
"@earendil-works/pi-coding-agent": "0.84.
|
|
74
|
-
"@earendil-works/pi-tui": "0.84.
|
|
72
|
+
"@earendil-works/pi-ai": "0.84.4",
|
|
73
|
+
"@earendil-works/pi-coding-agent": "0.84.4",
|
|
74
|
+
"@earendil-works/pi-tui": "0.84.4",
|
|
75
75
|
"@juicesharp/rpiv-ask-user-question": "2.2.0",
|
|
76
76
|
"@juicesharp/rpiv-web-tools": "1.20.0",
|
|
77
77
|
"@noble/ciphers": "2.2.0",
|
|
@@ -80,6 +80,7 @@
|
|
|
80
80
|
"@phala/dcap-qvl": "0.5.2",
|
|
81
81
|
"@zed-industries/agent-client-protocol": "0.4.5",
|
|
82
82
|
"patch-package": "8.0.1",
|
|
83
|
+
"pi-background-tasks": "2.4.2",
|
|
83
84
|
"pi-mcp-adapter": "2.11.0",
|
|
84
85
|
"pi-privacy": "0.13.0",
|
|
85
86
|
"pi-subagents": "0.34.0",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/config.js b/node_modules/@earendil-works/pi-coding-agent/dist/config.js
|
|
2
|
-
index
|
|
2
|
+
index f04269f..536e030 100644
|
|
3
3
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/config.js
|
|
4
4
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/config.js
|
|
5
|
-
@@ -
|
|
5
|
+
@@ -401,6 +401,64 @@ export const APP_NAME = piConfigName || "pi";
|
|
6
6
|
export const APP_TITLE = piConfigName ? APP_NAME : "π";
|
|
7
7
|
export const CONFIG_DIR_NAME = pkg.piConfig?.configDir || ".pi";
|
|
8
8
|
export const VERSION = pkg.version || "0.0.0";
|
|
@@ -68,7 +68,7 @@ index 4600b23..075ecae 100644
|
|
|
68
68
|
export const ENV_AGENT_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_DIR`;
|
|
69
69
|
export const ENV_SESSION_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_SESSION_DIR`;
|
|
70
70
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js b/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js
|
|
71
|
-
index
|
|
71
|
+
index fd82b71..5e0821c 100644
|
|
72
72
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js
|
|
73
73
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js
|
|
74
74
|
@@ -38,6 +38,111 @@ import { createLocalBashOperations } from "./tools/bash.js";
|
|
@@ -207,7 +207,7 @@ index ce8a9a2..679e584 100644
|
|
|
207
207
|
throw new Error(`Authentication failed for "${model.provider}". ` +
|
|
208
208
|
`Credentials may have expired or network is unavailable. ` +
|
|
209
209
|
`Run '/login ${model.provider}' to re-authenticate.`);
|
|
210
|
-
@@ -
|
|
210
|
+
@@ -380,6 +495,16 @@ export class AgentSession {
|
|
211
211
|
}
|
|
212
212
|
}
|
|
213
213
|
}
|
|
@@ -224,7 +224,7 @@ index ce8a9a2..679e584 100644
|
|
|
224
224
|
// Emit to extensions first
|
|
225
225
|
await this._emitExtensionEvent(event);
|
|
226
226
|
// Notify all listeners
|
|
227
|
-
@@ -
|
|
227
|
+
@@ -801,6 +926,33 @@ export class AgentSession {
|
|
228
228
|
finalError: msg.errorMessage,
|
|
229
229
|
});
|
|
230
230
|
this._retryAttempt = 0;
|
|
@@ -258,7 +258,7 @@ index ce8a9a2..679e584 100644
|
|
|
258
258
|
}
|
|
259
259
|
if (await this._checkCompaction(msg)) {
|
|
260
260
|
return true;
|
|
261
|
-
@@ -
|
|
261
|
+
@@ -882,6 +1034,14 @@ export class AgentSession {
|
|
262
262
|
if (!hasConfiguredAuth) {
|
|
263
263
|
const isOAuth = this._modelRuntime.isUsingOAuth(this.model.provider);
|
|
264
264
|
if (isOAuth) {
|
|
@@ -273,7 +273,7 @@ index ce8a9a2..679e584 100644
|
|
|
273
273
|
throw new Error(`Authentication failed for "${this.model.provider}". ` +
|
|
274
274
|
`Credentials may have expired or network is unavailable. ` +
|
|
275
275
|
`Run '/login ${this.model.provider}' to re-authenticate.`);
|
|
276
|
-
@@ -
|
|
276
|
+
@@ -891,7 +1051,13 @@ export class AgentSession {
|
|
277
277
|
// Check if we need to compact before sending (catches aborted responses).
|
|
278
278
|
// The user's new prompt is sent below, so do not call agent.continue() here.
|
|
279
279
|
const lastAssistant = this._findLastAssistantMessage();
|
|
@@ -288,7 +288,7 @@ index ce8a9a2..679e584 100644
|
|
|
288
288
|
await this._checkCompaction(lastAssistant, false);
|
|
289
289
|
}
|
|
290
290
|
// Build messages array (custom message if any, then user message)
|
|
291
|
-
@@ -
|
|
291
|
+
@@ -2242,6 +2408,27 @@ export class AgentSession {
|
|
292
292
|
// Context overflow is handled by compaction, not retry.
|
|
293
293
|
if (isContextOverflow(message, this.model?.contextWindow ?? 0))
|
|
294
294
|
return false;
|
|
@@ -316,7 +316,7 @@ index ce8a9a2..679e584 100644
|
|
|
316
316
|
return isRetryableAssistantError(message);
|
|
317
317
|
}
|
|
318
318
|
/**
|
|
319
|
-
@@ -
|
|
319
|
+
@@ -2287,7 +2474,11 @@ export class AgentSession {
|
|
320
320
|
this._retryAttempt--;
|
|
321
321
|
return false;
|
|
322
322
|
}
|
|
@@ -375,7 +375,7 @@ index 197bccc..bc9ac3f 100644
|
|
|
375
375
|
//# sourceMappingURL=auth-guidance.js.map
|
|
376
376
|
|
|
377
377
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/loader.js b/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/loader.js
|
|
378
|
-
index
|
|
378
|
+
index bb022d4..382ff2b 100644
|
|
379
379
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/loader.js
|
|
380
380
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/loader.js
|
|
381
381
|
@@ -18,7 +18,7 @@ import { createJiti } from "jiti/static";
|
|
@@ -387,7 +387,7 @@ index 324d30a..e613e92 100644
|
|
|
387
387
|
// NOTE: This import works because loader.ts exports are NOT re-exported from index.ts,
|
|
388
388
|
// avoiding a circular dependency. Extensions can import from @earendil-works/pi-coding-agent.
|
|
389
389
|
import * as _bundledPiCodingAgent from "../../index.js";
|
|
390
|
-
@@ -
|
|
390
|
+
@@ -621,9 +621,23 @@ export async function discoverAndLoadExtensions(configuredPaths, cwd, agentDir =
|
|
391
391
|
}
|
|
392
392
|
}
|
|
393
393
|
};
|
|
@@ -415,19 +415,19 @@ index 324d30a..e613e92 100644
|
|
|
415
415
|
const globalExtDir = path.join(resolvedAgentDir, "extensions");
|
|
416
416
|
addPaths(discoverExtensionsInDir(globalExtDir));
|
|
417
417
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js b/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js
|
|
418
|
-
index
|
|
418
|
+
index 696e98c..7585930 100644
|
|
419
419
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js
|
|
420
420
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js
|
|
421
|
-
@@ -
|
|
421
|
+
@@ -24,7 +24,7 @@ import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
422
422
|
import ignore from "ignore";
|
|
423
423
|
import { minimatch } from "minimatch";
|
|
424
|
-
import { maxSatisfying, rcompare, satisfies, valid, validRange } from "semver";
|
|
424
|
+
import { gt, maxSatisfying, rcompare, satisfies, valid, validRange } from "semver";
|
|
425
425
|
-import { CONFIG_DIR_NAME } from "../config.js";
|
|
426
426
|
+import { projectConfigDirs, projectConfigWriteDir, resolveProjectConfigPath } from "../config.js";
|
|
427
427
|
import { spawnProcess, spawnProcessSync } from "../utils/child-process.js";
|
|
428
428
|
import { parseGitUrl } from "../utils/git.js";
|
|
429
429
|
import { canonicalizePath, isLocalPath, markPathIgnoredByCloudSync, resolvePath } from "../utils/paths.js";
|
|
430
|
-
@@ -
|
|
430
|
+
@@ -711,23 +711,29 @@ export class DefaultPackageManager {
|
|
431
431
|
const packageSources = this.dedupePackages(allPackages);
|
|
432
432
|
await this.resolvePackageSources(packageSources, accumulator, onMissing);
|
|
433
433
|
const globalBaseDir = this.agentDir;
|
|
@@ -464,7 +464,7 @@ index e806af3..9b00ebd 100644
|
|
|
464
464
|
return this.toResolvedPaths(accumulator);
|
|
465
465
|
}
|
|
466
466
|
async resolveExtensionSources(sources, options) {
|
|
467
|
-
@@ -
|
|
467
|
+
@@ -1681,13 +1687,30 @@ export class DefaultPackageManager {
|
|
468
468
|
writeFileSync(ignorePath, "*\n!.gitignore\n", "utf-8");
|
|
469
469
|
}
|
|
470
470
|
}
|
|
@@ -496,7 +496,7 @@ index e806af3..9b00ebd 100644
|
|
|
496
496
|
}
|
|
497
497
|
return join(this.agentDir, "npm");
|
|
498
498
|
}
|
|
499
|
-
@@ -
|
|
499
|
+
@@ -1726,7 +1749,9 @@ export class DefaultPackageManager {
|
|
500
500
|
}
|
|
501
501
|
if (scope === "project") {
|
|
502
502
|
this.assertProjectTrustedForScope(scope);
|
|
@@ -507,7 +507,7 @@ index e806af3..9b00ebd 100644
|
|
|
507
507
|
}
|
|
508
508
|
return join(this.agentDir, "npm", "node_modules", source.name);
|
|
509
509
|
}
|
|
510
|
-
@@ -
|
|
510
|
+
@@ -1762,7 +1787,7 @@ export class DefaultPackageManager {
|
|
511
511
|
}
|
|
512
512
|
if (scope === "project") {
|
|
513
513
|
this.assertProjectTrustedForScope(scope);
|
|
@@ -516,7 +516,7 @@ index e806af3..9b00ebd 100644
|
|
|
516
516
|
}
|
|
517
517
|
return join(this.agentDir, "git");
|
|
518
518
|
}
|
|
519
|
-
@@ -
|
|
519
|
+
@@ -1785,7 +1810,7 @@ export class DefaultPackageManager {
|
|
520
520
|
getBaseDirForScope(scope) {
|
|
521
521
|
if (scope === "project") {
|
|
522
522
|
this.assertProjectTrustedForScope(scope);
|
|
@@ -525,7 +525,7 @@ index e806af3..9b00ebd 100644
|
|
|
525
525
|
}
|
|
526
526
|
if (scope === "user") {
|
|
527
527
|
return this.agentDir;
|
|
528
|
-
@@ -
|
|
528
|
+
@@ -1796,7 +1821,30 @@ export class DefaultPackageManager {
|
|
529
529
|
return resolvePath(input, this.cwd, { homeDir: getHomeDir(), trim: true });
|
|
530
530
|
}
|
|
531
531
|
resolvePathFromBase(input, baseDir) {
|
|
@@ -557,7 +557,7 @@ index e806af3..9b00ebd 100644
|
|
|
557
557
|
}
|
|
558
558
|
collectPackageResources(packageRoot, accumulator, filter, metadata) {
|
|
559
559
|
if (filter) {
|
|
560
|
-
@@ -
|
|
560
|
+
@@ -1936,19 +1984,24 @@ export class DefaultPackageManager {
|
|
561
561
|
this.addResource(target, f, metadata, enabledPaths.has(f));
|
|
562
562
|
}
|
|
563
563
|
}
|
|
@@ -586,7 +586,7 @@ index e806af3..9b00ebd 100644
|
|
|
586
586
|
const userOverrides = {
|
|
587
587
|
extensions: (globalSettings.extensions ?? []),
|
|
588
588
|
skills: (globalSettings.skills ?? []),
|
|
589
|
-
@@ -
|
|
589
|
+
@@ -1967,12 +2020,12 @@ export class DefaultPackageManager {
|
|
590
590
|
prompts: join(globalBaseDir, "prompts"),
|
|
591
591
|
themes: join(globalBaseDir, "themes"),
|
|
592
592
|
};
|
|
@@ -605,7 +605,7 @@ index e806af3..9b00ebd 100644
|
|
|
605
605
|
const userAgentsSkillsDir = join(getHomeDir(), ".agents", "skills");
|
|
606
606
|
const projectTrusted = this.settingsManager.isProjectTrusted();
|
|
607
607
|
const projectAgentsSkillDirs = projectTrusted
|
|
608
|
-
@@ -
|
|
608
|
+
@@ -1986,10 +2039,13 @@ export class DefaultPackageManager {
|
|
609
609
|
}
|
|
610
610
|
};
|
|
611
611
|
if (projectTrusted) {
|
|
@@ -623,7 +623,7 @@ index e806af3..9b00ebd 100644
|
|
|
623
623
|
}
|
|
624
624
|
// Project skills from .agents/ (each with its own baseDir)
|
|
625
625
|
for (const agentsSkillsDir of projectAgentsSkillDirs) {
|
|
626
|
-
@@ -
|
|
626
|
+
@@ -2001,8 +2057,11 @@ export class DefaultPackageManager {
|
|
627
627
|
addResources("skills", collectAutoSkillEntries(agentsSkillsDir, "agents"), agentsMetadata, projectOverrides.skills, agentsBaseDir);
|
|
628
628
|
}
|
|
629
629
|
if (projectTrusted) {
|
|
@@ -638,17 +638,17 @@ index e806af3..9b00ebd 100644
|
|
|
638
638
|
// User extensions from ~/.pi/agent/
|
|
639
639
|
addResources("extensions", collectAutoExtensionEntries(userDirs.extensions), userMetadata, userOverrides.extensions, globalBaseDir);
|
|
640
640
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/core/project-trust.js b/node_modules/@earendil-works/pi-coding-agent/dist/core/project-trust.js
|
|
641
|
-
index
|
|
641
|
+
index 2f85768..328b27b 100644
|
|
642
642
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/core/project-trust.js
|
|
643
643
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/core/project-trust.js
|
|
644
644
|
@@ -1,8 +1,8 @@
|
|
645
|
-
-import { CONFIG_DIR_NAME } from "../config.js";
|
|
646
|
-
+import { formatProjectConfigDirNames } from "../config.js";
|
|
645
|
+
-import { APP_NAME, CONFIG_DIR_NAME } from "../config.js";
|
|
646
|
+
+import { APP_NAME, formatProjectConfigDirNames } from "../config.js";
|
|
647
647
|
import { emitProjectTrustEvent } from "./extensions/runner.js";
|
|
648
648
|
import { getProjectTrustOptions, hasTrustRequiringProjectResources, } from "./trust-manager.js";
|
|
649
649
|
function formatProjectTrustPrompt(cwd) {
|
|
650
|
-
- return `Trust project folder?\n${cwd}\n\nThis allows
|
|
651
|
-
+ return `Trust project folder?\n${cwd}\n\nThis allows
|
|
650
|
+
- return `Trust project folder?\n${cwd}\n\nThis allows ${APP_NAME} to load ${CONFIG_DIR_NAME} settings and resources, install missing project packages, and execute project extensions.`;
|
|
651
|
+
+ return `Trust project folder?\n${cwd}\n\nThis allows ${APP_NAME} to load ${formatProjectConfigDirNames()} settings and resources, install missing project packages, and execute project extensions.`;
|
|
652
652
|
}
|
|
653
653
|
async function selectProjectTrustOption(cwd, ctx) {
|
|
654
654
|
const options = getProjectTrustOptions(cwd, { includeSessionOnly: true });
|
|
@@ -696,7 +696,7 @@ index 3700c08..79cb85e 100644
|
|
|
696
696
|
// 3. Load explicit prompt paths
|
|
697
697
|
for (const rawPath of promptPaths) {
|
|
698
698
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/core/resource-loader.js b/node_modules/@earendil-works/pi-coding-agent/dist/core/resource-loader.js
|
|
699
|
-
index
|
|
699
|
+
index c5ed4d7..d9f50ae 100644
|
|
700
700
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/core/resource-loader.js
|
|
701
701
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/core/resource-loader.js
|
|
702
702
|
@@ -1,7 +1,7 @@
|
|
@@ -707,8 +707,8 @@ index 97af6cd..74d5d52 100644
|
|
|
707
707
|
+import { findProjectConfigPath, projectConfigDirCandidates, projectConfigDirs } from "../config.js";
|
|
708
708
|
import { loadThemeFromPath } from "../modes/interactive/theme/theme.js";
|
|
709
709
|
import { canonicalizePath, isLocalPath, resolvePath } from "../utils/paths.js";
|
|
710
|
-
import {
|
|
711
|
-
@@ -
|
|
710
|
+
import { stripBom } from "../utils/text.js";
|
|
711
|
+
@@ -625,12 +625,14 @@ export class DefaultResourceLoader {
|
|
712
712
|
join(this.agentDir, "themes"),
|
|
713
713
|
join(this.agentDir, "extensions"),
|
|
714
714
|
];
|
|
@@ -729,7 +729,7 @@ index 97af6cd..74d5d52 100644
|
|
|
729
729
|
for (const root of agentRoots) {
|
|
730
730
|
if (this.isUnderPath(normalizedPath, root)) {
|
|
731
731
|
return { path: filePath, source: "local", scope: "user", origin: "top-level", baseDir: root };
|
|
732
|
-
@@ -
|
|
732
|
+
@@ -669,7 +671,11 @@ export class DefaultResourceLoader {
|
|
733
733
|
const themes = [];
|
|
734
734
|
const diagnostics = [];
|
|
735
735
|
if (includeDefaults) {
|
|
@@ -742,7 +742,7 @@ index 97af6cd..74d5d52 100644
|
|
|
742
742
|
for (const dir of defaultDirs) {
|
|
743
743
|
this.loadThemesFromDir(dir, themes, diagnostics);
|
|
744
744
|
}
|
|
745
|
-
@@ -
|
|
745
|
+
@@ -807,8 +813,9 @@ export class DefaultResourceLoader {
|
|
746
746
|
return { themes: Array.from(seen.values()), diagnostics };
|
|
747
747
|
}
|
|
748
748
|
discoverSystemPromptFile() {
|
|
@@ -754,7 +754,7 @@ index 97af6cd..74d5d52 100644
|
|
|
754
754
|
return projectPath;
|
|
755
755
|
}
|
|
756
756
|
const globalPath = join(this.agentDir, "SYSTEM.md");
|
|
757
|
-
@@ -
|
|
757
|
+
@@ -818,8 +825,9 @@ export class DefaultResourceLoader {
|
|
758
758
|
return undefined;
|
|
759
759
|
}
|
|
760
760
|
discoverAppendSystemPromptFile() {
|
|
@@ -767,7 +767,7 @@ index 97af6cd..74d5d52 100644
|
|
|
767
767
|
}
|
|
768
768
|
const globalPath = join(this.agentDir, "APPEND_SYSTEM.md");
|
|
769
769
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js b/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js
|
|
770
|
-
index
|
|
770
|
+
index f0f936e..ad164d2 100644
|
|
771
771
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js
|
|
772
772
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js
|
|
773
773
|
@@ -2,7 +2,7 @@ import { randomUUID } from "crypto";
|
|
@@ -777,11 +777,11 @@ index cb06c10..41fb90c 100644
|
|
|
777
777
|
-import { CONFIG_DIR_NAME, getAgentDir } from "../config.js";
|
|
778
778
|
+import { getAgentDir, projectConfigDirCandidates, projectConfigWriteDir } from "../config.js";
|
|
779
779
|
import { normalizePath, resolvePath } from "../utils/paths.js";
|
|
780
|
+
import { stripBom } from "../utils/text.js";
|
|
780
781
|
import { DEFAULT_HTTP_IDLE_TIMEOUT_MS, parseHttpIdleTimeoutMs } from "./http-dispatcher.js";
|
|
781
|
-
function
|
|
782
|
-
|
|
783
|
-
}
|
|
784
|
-
return undefined;
|
|
782
|
+
@@ -45,14 +45,112 @@ function toSettingsError(scope, error, path) {
|
|
783
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
784
|
+
};
|
|
785
785
|
}
|
|
786
786
|
+/**
|
|
787
787
|
+ * Privateer patch: drop the keys of `settings` that are byte-identical to `base`.
|
|
@@ -893,7 +893,7 @@ index cb06c10..41fb90c 100644
|
|
|
893
893
|
}
|
|
894
894
|
acquireLockSyncWithRetry(path) {
|
|
895
895
|
const maxAttempts = 10;
|
|
896
|
-
@@ -
|
|
896
|
+
@@ -79,7 +177,13 @@ export class FileSettingsStorage {
|
|
897
897
|
throw lastError ?? new Error("Failed to acquire settings lock");
|
|
898
898
|
}
|
|
899
899
|
withLock(scope, fn) {
|
|
@@ -908,7 +908,16 @@ index cb06c10..41fb90c 100644
|
|
|
908
908
|
const dir = dirname(path);
|
|
909
909
|
let release;
|
|
910
910
|
try {
|
|
911
|
-
@@ -
|
|
911
|
+
@@ -157,7 +261,7 @@ export class SettingsManager {
|
|
912
|
+
const storage = new FileSettingsStorage(resolvedCwd, resolvedAgentDir);
|
|
913
|
+
return SettingsManager.fromStorageWithPaths(storage, options, {
|
|
914
|
+
global: join(resolvedAgentDir, "settings.json"),
|
|
915
|
+
- project: join(resolvedCwd, CONFIG_DIR_NAME, "settings.json"),
|
|
916
|
+
+ project: join(projectConfigWriteDir(resolvedCwd), "settings.json"),
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
/** Create a SettingsManager from an arbitrary storage backend */
|
|
920
|
+
@@ -610,7 +714,15 @@ export class SettingsManager {
|
|
912
921
|
getProviderRetrySettings() {
|
|
913
922
|
return {
|
|
914
923
|
timeoutMs: this.settings.retry?.provider?.timeoutMs,
|
|
@@ -926,7 +935,7 @@ index cb06c10..41fb90c 100644
|
|
|
926
935
|
};
|
|
927
936
|
}
|
|
928
937
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/core/skills.js b/node_modules/@earendil-works/pi-coding-agent/dist/core/skills.js
|
|
929
|
-
index
|
|
938
|
+
index 56cf7a3..2a32170 100644
|
|
930
939
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/core/skills.js
|
|
931
940
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/core/skills.js
|
|
932
941
|
@@ -1,7 +1,7 @@
|
|
@@ -938,7 +947,7 @@ index 4e7e784..7383a2b 100644
|
|
|
938
947
|
import { parseFrontmatter } from "../utils/frontmatter.js";
|
|
939
948
|
import { canonicalizePath, resolvePath } from "../utils/paths.js";
|
|
940
949
|
import { createSyntheticSourceInfo } from "./source-info.js";
|
|
941
|
-
@@ -
|
|
950
|
+
@@ -346,10 +346,15 @@ export function loadSkills(options) {
|
|
942
951
|
}
|
|
943
952
|
if (includeDefaults) {
|
|
944
953
|
addSkills(loadSkillsFromDirInternal(join(resolvedAgentDir, "skills"), "user", true));
|
|
@@ -956,7 +965,7 @@ index 4e7e784..7383a2b 100644
|
|
|
956
965
|
const isUnderPath = (target, root) => {
|
|
957
966
|
const normalizedRoot = resolve(root);
|
|
958
967
|
if (target === normalizedRoot) {
|
|
959
|
-
@@ -
|
|
968
|
+
@@ -362,7 +367,7 @@ export function loadSkills(options) {
|
|
960
969
|
if (!includeDefaults) {
|
|
961
970
|
if (isUnderPath(resolvedPath, userSkillsDir))
|
|
962
971
|
return "user";
|
|
@@ -965,8 +974,121 @@ index 4e7e784..7383a2b 100644
|
|
|
965
974
|
return "project";
|
|
966
975
|
}
|
|
967
976
|
return "path";
|
|
977
|
+
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/output-accumulator.js b/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/output-accumulator.js
|
|
978
|
+
index 7241668..7b79305 100644
|
|
979
|
+
--- a/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/output-accumulator.js
|
|
980
|
+
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/output-accumulator.js
|
|
981
|
+
@@ -10,6 +10,30 @@ function defaultTempFilePath(prefix) {
|
|
982
|
+
function byteLength(text) {
|
|
983
|
+
return Buffer.byteLength(text, "utf-8");
|
|
984
|
+
}
|
|
985
|
+
+// --- Privateer patch: per-line cap on the DISPLAY tail --------------------------
|
|
986
|
+
+//
|
|
987
|
+
+// Stock Pi bounds tool output two ways — 2000 lines and 50KB — but never bounds a
|
|
988
|
+
+// single LINE. One minified line is enough to spend the whole budget: a bare
|
|
989
|
+
+// `grep -rn <term> .` that wanders into node_modules matches inside
|
|
990
|
+
+// typescript.js or an Expo web bundle, and those "lines" are megabytes wide. The
|
|
991
|
+
+// observed shape is a 331MB capture whose entire visible output was 390 lines,
|
|
992
|
+
+// of which the model saw one — the tail of a single line of minified JS. The
|
|
993
|
+
+// context window pays 50KB for nothing, and the truncation notice reads as noise
|
|
994
|
+
+// because nothing about it says "your grep hit a bundle".
|
|
995
|
+
+//
|
|
996
|
+
+// So cap what goes into the display tail at one line's worth of characters and
|
|
997
|
+
+// mark the elision. Accounting (totalDecodedBytes, totalLines, currentLineBytes)
|
|
998
|
+
+// still measures the REAL stream, so "Showing lines X-Y of Z" stays honest, and
|
|
999
|
+
+// the temp file still receives every raw byte — `Full output:` means what it
|
|
1000
|
+
+// says. Only the bytes we hand the model change: 25+ real lines instead of one
|
|
1001
|
+
+// blob.
|
|
1002
|
+
+//
|
|
1003
|
+
+// 2000 rather than grep's 500 (GREP_MAX_LINE_LENGTH): a 2000-char line is already
|
|
1004
|
+
+// ~25 terminal rows, so ordinary output — stack traces, long JSON, compiler
|
|
1005
|
+
+// diagnostics — passes through untouched, while the pathological case is capped
|
|
1006
|
+
+// three orders of magnitude below where it hurts.
|
|
1007
|
+
+const DEFAULT_MAX_LINE_CHARS = 2000;
|
|
1008
|
+
+const LINE_ELISION = "... [line truncated]";
|
|
1009
|
+
/**
|
|
1010
|
+
* Incrementally tracks streaming output with bounded memory.
|
|
1011
|
+
*
|
|
1012
|
+
@@ -32,6 +56,11 @@ export class OutputAccumulator {
|
|
1013
|
+
completedLines = 0;
|
|
1014
|
+
totalLines = 0;
|
|
1015
|
+
currentLineBytes = 0;
|
|
1016
|
+
+ // Privateer patch: per-line display cap, carried across chunk boundaries
|
|
1017
|
+
+ // because a long line rarely arrives in one read().
|
|
1018
|
+
+ maxLineChars;
|
|
1019
|
+
+ lineCharsEmitted = 0;
|
|
1020
|
+
+ lineElided = false;
|
|
1021
|
+
hasOpenLine = false;
|
|
1022
|
+
finished = false;
|
|
1023
|
+
tempFilePath;
|
|
1024
|
+
@@ -40,6 +69,8 @@ export class OutputAccumulator {
|
|
1025
|
+
this.maxLines = options.maxLines ?? DEFAULT_MAX_LINES;
|
|
1026
|
+
this.maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
|
|
1027
|
+
this.maxRollingBytes = Math.max(this.maxBytes * 2, 1);
|
|
1028
|
+
+ // Privateer patch: 0 or less disables the cap.
|
|
1029
|
+
+ this.maxLineChars = options.maxLineChars ?? DEFAULT_MAX_LINE_CHARS;
|
|
1030
|
+
this.tempFilePrefix = options.tempFilePrefix ?? "pi-output";
|
|
1031
|
+
}
|
|
1032
|
+
append(data) {
|
|
1033
|
+
@@ -122,8 +153,11 @@ export class OutputAccumulator {
|
|
1034
|
+
}
|
|
1035
|
+
const bytes = byteLength(text);
|
|
1036
|
+
this.totalDecodedBytes += bytes;
|
|
1037
|
+
- this.tailText += text;
|
|
1038
|
+
- this.tailBytes += bytes;
|
|
1039
|
+
+ // Privateer patch: the tail is what the model and the TUI see, so it is the
|
|
1040
|
+
+ // only thing capped. Every counter below still sees the full `text`.
|
|
1041
|
+
+ const display = this.capLongLines(text);
|
|
1042
|
+
+ this.tailText += display;
|
|
1043
|
+
+ this.tailBytes += byteLength(display);
|
|
1044
|
+
if (this.tailBytes > this.maxRollingBytes * 2) {
|
|
1045
|
+
this.trimTail();
|
|
1046
|
+
}
|
|
1047
|
+
@@ -145,6 +179,42 @@ export class OutputAccumulator {
|
|
1048
|
+
}
|
|
1049
|
+
this.totalLines = this.completedLines + (this.hasOpenLine ? 1 : 0);
|
|
1050
|
+
}
|
|
1051
|
+
+ /**
|
|
1052
|
+
+ * Privateer patch: emit at most `maxLineChars` characters per line, followed by
|
|
1053
|
+
+ * one elision marker, dropping the rest of that line until its newline.
|
|
1054
|
+
+ *
|
|
1055
|
+
+ * Streaming, so the per-line counters live on the instance: a 5MB line arrives
|
|
1056
|
+
+ * as hundreds of chunks and every one of them must know the line is already
|
|
1057
|
+
+ * spent.
|
|
1058
|
+
+ */
|
|
1059
|
+
+ capLongLines(text) {
|
|
1060
|
+
+ if (this.maxLineChars <= 0) {
|
|
1061
|
+
+ return text;
|
|
1062
|
+
+ }
|
|
1063
|
+
+ let out = "";
|
|
1064
|
+
+ let i = 0;
|
|
1065
|
+
+ while (i < text.length) {
|
|
1066
|
+
+ const nl = text.indexOf("\n", i);
|
|
1067
|
+
+ const segment = text.slice(i, nl === -1 ? text.length : nl);
|
|
1068
|
+
+ const room = Math.max(this.maxLineChars - this.lineCharsEmitted, 0);
|
|
1069
|
+
+ if (room > 0) {
|
|
1070
|
+
+ out += segment.slice(0, room);
|
|
1071
|
+
+ this.lineCharsEmitted += Math.min(segment.length, room);
|
|
1072
|
+
+ }
|
|
1073
|
+
+ if (segment.length > room && !this.lineElided) {
|
|
1074
|
+
+ out += LINE_ELISION;
|
|
1075
|
+
+ this.lineElided = true;
|
|
1076
|
+
+ }
|
|
1077
|
+
+ if (nl === -1) {
|
|
1078
|
+
+ break;
|
|
1079
|
+
+ }
|
|
1080
|
+
+ out += "\n";
|
|
1081
|
+
+ this.lineCharsEmitted = 0;
|
|
1082
|
+
+ this.lineElided = false;
|
|
1083
|
+
+ i = nl + 1;
|
|
1084
|
+
+ }
|
|
1085
|
+
+ return out;
|
|
1086
|
+
+ }
|
|
1087
|
+
trimTail() {
|
|
1088
|
+
const buffer = Buffer.from(this.tailText, "utf-8");
|
|
1089
|
+
if (buffer.length <= this.maxRollingBytes) {
|
|
968
1090
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/core/trust-manager.js b/node_modules/@earendil-works/pi-coding-agent/dist/core/trust-manager.js
|
|
969
|
-
index
|
|
1091
|
+
index 0877ee7..faa2559 100644
|
|
970
1092
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/core/trust-manager.js
|
|
971
1093
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/core/trust-manager.js
|
|
972
1094
|
@@ -2,7 +2,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
@@ -976,9 +1098,9 @@ index 17af938..6d97caa 100644
|
|
|
976
1098
|
-import { CONFIG_DIR_NAME } from "../config.js";
|
|
977
1099
|
+import { projectConfigDirCandidates } from "../config.js";
|
|
978
1100
|
import { canonicalizePath, resolvePath } from "../utils/paths.js";
|
|
1101
|
+
import { stripBom } from "../utils/text.js";
|
|
979
1102
|
const TRUST_REQUIRING_PROJECT_CONFIG_RESOURCES = [
|
|
980
|
-
|
|
981
|
-
@@ -150,9 +150,13 @@ export function hasTrustRequiringProjectResources(cwd) {
|
|
1103
|
+
@@ -151,9 +151,13 @@ export function hasTrustRequiringProjectResources(cwd) {
|
|
982
1104
|
const homeDir = canonicalizePath(resolvePath(process.env.HOME || homedir()));
|
|
983
1105
|
const userAgentsSkillsDir = join(homeDir, ".agents", "skills");
|
|
984
1106
|
let currentDir = canonicalizePath(resolvePath(cwd));
|
|
@@ -996,7 +1118,7 @@ index 17af938..6d97caa 100644
|
|
|
996
1118
|
while (true) {
|
|
997
1119
|
const agentsSkillsDir = join(currentDir, ".agents", "skills");
|
|
998
1120
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/index.d.ts b/node_modules/@earendil-works/pi-coding-agent/dist/index.d.ts
|
|
999
|
-
index
|
|
1121
|
+
index 3e9241d..bfbfcbf 100644
|
|
1000
1122
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/index.d.ts
|
|
1001
1123
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/index.d.ts
|
|
1002
1124
|
@@ -1,7 +1,7 @@
|
|
@@ -1007,9 +1129,9 @@ index 7d3e24c..578ada5 100644
|
|
|
1007
1129
|
+export { AuthStorage, readStoredCredential } from "./core/auth-storage.ts";
|
|
1008
1130
|
export { type BranchPreparation, type BranchSummaryResult, type CollectEntriesResult, type CompactionResult, type CutPointResult, calculateContextTokens, collectEntriesForBranchSummary, compact, DEFAULT_COMPACTION_SETTINGS, estimateTokens, type FileOperations, findCutPoint, findTurnStartIndex, type GenerateBranchSummaryOptions, generateBranchSummary, generateSummary, generateSummaryWithUsage, getLastAssistantUsage, prepareBranchEntries, serializeConversation, shouldCompact, } from "./core/compaction/index.ts";
|
|
1009
1131
|
export { createEventBus, type EventBus, type EventBusController } from "./core/event-bus.ts";
|
|
1010
|
-
export type { AgentEndEvent, AgentSettledEvent, AgentStartEvent, AgentToolResult, AgentToolUpdateCallback, AppKeybinding, AutocompleteProviderFactory, BashToolCallEvent, BeforeAgentStartEvent, BeforeAgentStartEventResult, BeforeProviderHeadersEvent, BeforeProviderRequestEvent, BeforeProviderRequestEventResult, BuildSystemPromptOptions, CompactOptions, ContextEvent, ContextUsage, CustomToolCallEvent, EditToolCallEvent, EntryRenderer, EntryRenderOptions, ExecOptions, ExecResult, Extension, ExtensionActions, ExtensionAPI, ExtensionCommandContext, ExtensionCommandContextActions, ExtensionContext, ExtensionContextActions, ExtensionError, ExtensionEvent, ExtensionFactory, ExtensionFlag, ExtensionHandler, ExtensionRuntime, ExtensionShortcut, ExtensionUIContext, ExtensionUIDialogOptions, ExtensionWidgetOptions, FindToolCallEvent, GrepToolCallEvent, InlineExtension, InputEvent, InputEventResult, InputSource, KeybindingsManager, LoadExtensionsResult, LsToolCallEvent, MarkdownTransformContext, MarkdownTransformer, MessageEndEvent, MessageRenderer, MessageRenderOptions, MessageStartEvent, MessageUpdateEvent, ProjectTrustContext, ProjectTrustEvent, ProjectTrustEventDecision, ProjectTrustEventResult, ProjectTrustHandler, ProviderConfig, ProviderModelConfig, ReadToolCallEvent, RegisteredCommand, RegisteredTool, ResolvedCommand, SessionBeforeCompactEvent, SessionBeforeForkEvent, SessionBeforeSwitchEvent, SessionBeforeTreeEvent, SessionCompactEvent, SessionInfoChangedEvent, SessionShutdownEvent, SessionStartEvent, SessionTreeEvent, SlashCommandInfo, SlashCommandSource, SourceInfo, TerminalInputHandler, ToolCallEvent, ToolCallEventResult, ToolDefinition, ToolExecutionEndEvent, ToolExecutionMode, ToolExecutionStartEvent, ToolExecutionUpdateEvent, ToolInfo, ToolRenderResultOptions, ToolResultEvent, TurnEndEvent, TurnStartEvent, UserBashEvent, UserBashEventResult, WidgetPlacement, WorkingIndicatorOptions, WriteToolCallEvent, } from "./core/extensions/index.ts";
|
|
1132
|
+
export type { AgentEndEvent, AgentSettledEvent, AgentStartEvent, AgentToolResult, AgentToolUpdateCallback, AppKeybinding, AutocompleteProviderFactory, BashToolCallEvent, BeforeAgentStartEvent, BeforeAgentStartEventResult, BeforeProviderHeadersEvent, BeforeProviderRequestEvent, BeforeProviderRequestEventResult, BuildSystemPromptOptions, CompactOptions, ContextEvent, ContextUsage, CustomToolCallEvent, EditToolCallEvent, EntryRenderer, EntryRenderOptions, ExecOptions, ExecResult, Extension, ExtensionActions, ExtensionAPI, ExtensionCommandContext, ExtensionCommandContextActions, ExtensionContext, ExtensionContextActions, ExtensionError, ExtensionEvent, ExtensionFactory, ExtensionFlag, ExtensionHandler, ExtensionRuntime, ExtensionShortcut, ExtensionUIContext, ExtensionUIDialogOptions, ExtensionWidgetOptions, FindToolCallEvent, GrepToolCallEvent, InlineExtension, InputEvent, InputEventResult, InputSource, KeybindingsManager, LoadExtensionsResult, LsToolCallEvent, MarkdownTransformContext, MarkdownTransformer, MessageEndEvent, MessageRenderer, MessageRenderOptions, MessageStartEvent, MessageUpdateEvent, PowerShellToolCallEvent, ProjectTrustContext, ProjectTrustEvent, ProjectTrustEventDecision, ProjectTrustEventResult, ProjectTrustHandler, ProviderConfig, ProviderModelConfig, ReadToolCallEvent, RegisteredCommand, RegisteredTool, ResolvedCommand, SessionBeforeCompactEvent, SessionBeforeForkEvent, SessionBeforeSwitchEvent, SessionBeforeTreeEvent, SessionCompactEvent, SessionInfoChangedEvent, SessionShutdownEvent, SessionStartEvent, SessionTreeEvent, SlashCommandInfo, SlashCommandSource, SourceInfo, TerminalInputHandler, ToolCallEvent, ToolCallEventResult, ToolDefinition, ToolExecutionEndEvent, ToolExecutionMode, ToolExecutionStartEvent, ToolExecutionUpdateEvent, ToolInfo, ToolRenderResultOptions, ToolResultEvent, TurnEndEvent, TurnStartEvent, UIPromptEndEvent, UIPromptKind, UIPromptStartEvent, UserBashEvent, UserBashEventResult, WidgetPlacement, WorkingIndicatorOptions, WriteToolCallEvent, } from "./core/extensions/index.ts";
|
|
1011
1133
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/index.js b/node_modules/@earendil-works/pi-coding-agent/dist/index.js
|
|
1012
|
-
index
|
|
1134
|
+
index 01017cd..c2b8722 100644
|
|
1013
1135
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/index.js
|
|
1014
1136
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/index.js
|
|
1015
1137
|
@@ -3,7 +3,7 @@ export { parseArgs } from "./cli/args.js";
|
|
@@ -1022,10 +1144,10 @@ index 76d728e..2b2c892 100644
|
|
|
1022
1144
|
export { calculateContextTokens, collectEntriesForBranchSummary, compact, DEFAULT_COMPACTION_SETTINGS, estimateTokens, findCutPoint, findTurnStartIndex, generateBranchSummary, generateSummary, generateSummaryWithUsage, getLastAssistantUsage, prepareBranchEntries, serializeConversation, shouldCompact, } from "./core/compaction/index.js";
|
|
1023
1145
|
export { createEventBus } from "./core/event-bus.js";
|
|
1024
1146
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/main.js b/node_modules/@earendil-works/pi-coding-agent/dist/main.js
|
|
1025
|
-
index
|
|
1147
|
+
index 940e0f4..c0f3d11 100644
|
|
1026
1148
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/main.js
|
|
1027
1149
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/main.js
|
|
1028
|
-
@@ -
|
|
1150
|
+
@@ -795,7 +795,58 @@ export async function main(args, options) {
|
|
1029
1151
|
if (exitCode !== 0) {
|
|
1030
1152
|
process.exitCode = exitCode;
|
|
1031
1153
|
}
|
|
@@ -1086,7 +1208,7 @@ index 5ff9c80..5b91d5f 100644
|
|
|
1086
1208
|
//# sourceMappingURL=main.js.map
|
|
1087
1209
|
|
|
1088
1210
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/migrations.js b/node_modules/@earendil-works/pi-coding-agent/dist/migrations.js
|
|
1089
|
-
index
|
|
1211
|
+
index 072268a..472ee6d 100644
|
|
1090
1212
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/migrations.js
|
|
1091
1213
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/migrations.js
|
|
1092
1214
|
@@ -4,7 +4,7 @@
|
|
@@ -1096,9 +1218,9 @@ index e3a5ccf..a561a8a 100644
|
|
|
1096
1218
|
-import { CONFIG_DIR_NAME, getAgentDir, getBinDir } from "./config.js";
|
|
1097
1219
|
+import { getAgentDir, getBinDir, projectConfigDirs } from "./config.js";
|
|
1098
1220
|
import { migrateKeybindingsConfig } from "./core/keybindings.js";
|
|
1221
|
+
import { stripBom } from "./utils/text.js";
|
|
1099
1222
|
const MIGRATION_GUIDE_URL = "https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration";
|
|
1100
|
-
|
|
1101
|
-
@@ -230,14 +230,17 @@ function checkDeprecatedExtensionDirs(baseDir, label) {
|
|
1223
|
+
@@ -231,14 +231,17 @@ function checkDeprecatedExtensionDirs(baseDir, label) {
|
|
1102
1224
|
*/
|
|
1103
1225
|
function migrateExtensionSystem(cwd) {
|
|
1104
1226
|
const agentDir = getAgentDir();
|
|
@@ -1410,16 +1532,18 @@ index 1d9f046..c0326e3 100644
|
|
|
1410
1532
|
return lines;
|
|
1411
1533
|
}
|
|
1412
1534
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/tool-execution.js b/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/tool-execution.js
|
|
1413
|
-
index
|
|
1535
|
+
index c33fc39..060a38f 100644
|
|
1414
1536
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/tool-execution.js
|
|
1415
1537
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/tool-execution.js
|
|
1416
|
-
@@ -1,
|
|
1538
|
+
@@ -1,10 +1,37 @@
|
|
1417
1539
|
-import { Box, Container, getCapabilities, Image, Spacer, Text } from "@earendil-works/pi-tui";
|
|
1418
1540
|
+import { Box, Container, getCapabilities, Image, Spacer, visibleWidth, Text } from "@earendil-works/pi-tui";
|
|
1419
1541
|
import { createAllToolDefinitions } from "../../../core/tools/index.js";
|
|
1420
1542
|
import { getTextOutput as getRenderedTextOutput } from "../../../core/tools/render-utils.js";
|
|
1421
1543
|
import { convertToPng } from "../../../utils/image-convert.js";
|
|
1422
1544
|
import { theme } from "../theme/theme.js";
|
|
1545
|
+
import { keyHint } from "./keybinding-hints.js";
|
|
1546
|
+
const FALLBACK_PREVIEW_LINES = 10;
|
|
1423
1547
|
+/**
|
|
1424
1548
|
+ * Privateer: mark a failed tool call inline on its title line.
|
|
1425
1549
|
+ *
|
|
@@ -1450,7 +1574,7 @@ index 3f93cc6..50a2a99 100644
|
|
|
1450
1574
|
export class ToolExecutionComponent extends Container {
|
|
1451
1575
|
contentBox;
|
|
1452
1576
|
contentText;
|
|
1453
|
-
@@ -
|
|
1577
|
+
@@ -45,8 +72,13 @@ export class ToolExecutionComponent extends Container {
|
|
1454
1578
|
// Always create all shell variants. contentBox is used for default renderer-based composition.
|
|
1455
1579
|
// selfRenderContainer is used when the tool renders its own framing.
|
|
1456
1580
|
// contentText is reserved for generic fallback rendering when no tool definition exists.
|
|
@@ -1466,7 +1590,7 @@ index 3f93cc6..50a2a99 100644
|
|
|
1466
1590
|
this.selfRenderContainer = new Container();
|
|
1467
1591
|
if (this.hasRendererDefinition()) {
|
|
1468
1592
|
this.addChild(this.getRenderShell() === "self" ? this.selfRenderContainer : this.contentBox);
|
|
1469
|
-
@@ -
|
|
1593
|
+
@@ -108,6 +140,13 @@ export class ToolExecutionComponent extends Container {
|
|
1470
1594
|
createCallFallback() {
|
|
1471
1595
|
return new Text(theme.fg("toolTitle", theme.bold(this.toolName)), 0, 0);
|
|
1472
1596
|
}
|
|
@@ -1480,7 +1604,7 @@ index 3f93cc6..50a2a99 100644
|
|
|
1480
1604
|
createResultFallback() {
|
|
1481
1605
|
const output = this.getTextOutput();
|
|
1482
1606
|
if (!output) {
|
|
1483
|
-
@@ -
|
|
1607
|
+
@@ -227,19 +266,22 @@ export class ToolExecutionComponent extends Container {
|
|
1484
1608
|
renderContainer.clear();
|
|
1485
1609
|
const callRenderer = this.getCallRenderer();
|
|
1486
1610
|
if (!callRenderer) {
|
|
@@ -1506,7 +1630,7 @@ index 3f93cc6..50a2a99 100644
|
|
|
1506
1630
|
hasContent = true;
|
|
1507
1631
|
}
|
|
1508
1632
|
}
|
|
1509
|
-
@@ -
|
|
1633
|
+
@@ -311,7 +353,8 @@ export class ToolExecutionComponent extends Container {
|
|
1510
1634
|
return getRenderedTextOutput(this.result, this.showImages);
|
|
1511
1635
|
}
|
|
1512
1636
|
formatToolExecution() {
|
|
@@ -1517,19 +1641,19 @@ index 3f93cc6..50a2a99 100644
|
|
|
1517
1641
|
if (content) {
|
|
1518
1642
|
text += `\n\n${content}`;
|
|
1519
1643
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js b/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js
|
|
1520
|
-
index
|
|
1644
|
+
index a27754f..61a1fff 100644
|
|
1521
1645
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js
|
|
1522
1646
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js
|
|
1523
1647
|
@@ -10,7 +10,7 @@ import * as TuiLayouts from "@earendil-works/pi-tui";
|
|
1524
|
-
import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TuiAltScreen, TuiMainScreen, visibleWidth, } from "@earendil-works/pi-tui";
|
|
1648
|
+
import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Markdown, matchesKey, ProcessTerminal, Spacer, setCapabilityOverrides, setKeybindings, Text, TruncatedText, TuiAltScreen, TuiMainScreen, visibleWidth, } from "@earendil-works/pi-tui";
|
|
1525
1649
|
import chalk from "chalk";
|
|
1526
|
-
import { spawn
|
|
1527
|
-
-import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath,
|
|
1528
|
-
+import { APP_NAME, APP_TITLE, formatProjectConfigDirNames, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath,
|
|
1650
|
+
import { spawn } from "child_process";
|
|
1651
|
+
-import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath, VERSION, } from "../../config.js";
|
|
1652
|
+
+import { APP_NAME, APP_TITLE, formatProjectConfigDirNames, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath, VERSION, } from "../../config.js";
|
|
1529
1653
|
import { parseSkillBlock } from "../../core/agent-session.js";
|
|
1530
1654
|
import { SessionImportFileNotFoundError } from "../../core/agent-session-runtime.js";
|
|
1531
1655
|
import { CACHE_TTL_MS, collectCacheMisses, computeCacheWaste, detectCacheMiss, } from "../../core/cache-stats.js";
|
|
1532
|
-
@@ -
|
|
1656
|
+
@@ -126,7 +126,12 @@ export function formatResumeCommand(sessionManager) {
|
|
1533
1657
|
const sessionFile = sessionManager.getSessionFile();
|
|
1534
1658
|
if (!sessionFile || !fs.existsSync(sessionFile))
|
|
1535
1659
|
return undefined;
|
|
@@ -1543,7 +1667,7 @@ index 42e655d..606c7cc 100644
|
|
|
1543
1667
|
if (!sessionManager.usesDefaultSessionDir()) {
|
|
1544
1668
|
args.push("--session-dir", quoteIfNeeded(sessionManager.getSessionDir()));
|
|
1545
1669
|
}
|
|
1546
|
-
@@ -
|
|
1670
|
+
@@ -232,6 +237,54 @@ export function createInteractiveTuiReference(getTui) {
|
|
1547
1671
|
getPrototypeOf: () => Reflect.getPrototypeOf(getTui()),
|
|
1548
1672
|
});
|
|
1549
1673
|
}
|
|
@@ -1598,7 +1722,7 @@ index 42e655d..606c7cc 100644
|
|
|
1598
1722
|
export class InteractiveMode {
|
|
1599
1723
|
runtimeHost;
|
|
1600
1724
|
renderer;
|
|
1601
|
-
@@ -
|
|
1725
|
+
@@ -439,9 +492,15 @@ export class InteractiveMode {
|
|
1602
1726
|
}
|
|
1603
1727
|
getBuiltInCommandConflictDiagnostics(extensionRunner) {
|
|
1604
1728
|
const builtinNames = new Set(BUILTIN_SLASH_COMMANDS.map((command) => command.name));
|
|
@@ -1615,7 +1739,7 @@ index 42e655d..606c7cc 100644
|
|
|
1615
1739
|
.map((command) => ({
|
|
1616
1740
|
type: "warning",
|
|
1617
1741
|
message: command.invocationName === command.name
|
|
1618
|
-
@@ -
|
|
1742
|
+
@@ -815,20 +874,18 @@ export class InteractiveMode {
|
|
1619
1743
|
this.showNewVersionNotification(newRelease);
|
|
1620
1744
|
}
|
|
1621
1745
|
});
|
|
@@ -1648,7 +1772,7 @@ index 42e655d..606c7cc 100644
|
|
|
1648
1772
|
// Check tmux keyboard setup asynchronously
|
|
1649
1773
|
this.checkTmuxKeyboardSetup().then((warning) => {
|
|
1650
1774
|
if (warning) {
|
|
1651
|
-
@@ -
|
|
1775
|
+
@@ -2393,7 +2450,17 @@ export class InteractiveMode {
|
|
1652
1776
|
if (text === "/model" || text.startsWith("/model ")) {
|
|
1653
1777
|
const searchTerm = text.startsWith("/model ") ? text.slice(7).trim() : undefined;
|
|
1654
1778
|
this.editor.setText("");
|
|
@@ -1666,8 +1790,8 @@ index 42e655d..606c7cc 100644
|
|
|
1666
1790
|
+ }
|
|
1667
1791
|
return;
|
|
1668
1792
|
}
|
|
1669
|
-
if (text === "/
|
|
1670
|
-
@@ -
|
|
1793
|
+
if (text === "/thinking" || text.startsWith("/thinking ")) {
|
|
1794
|
+
@@ -2465,12 +2532,42 @@ export class InteractiveMode {
|
|
1671
1795
|
if (text === "/login" || text.startsWith("/login ")) {
|
|
1672
1796
|
const providerRef = text.startsWith("/login ") ? text.slice(7).trim() : undefined;
|
|
1673
1797
|
this.editor.setText("");
|
|
@@ -1712,7 +1836,7 @@ index 42e655d..606c7cc 100644
|
|
|
1712
1836
|
return;
|
|
1713
1837
|
}
|
|
1714
1838
|
if (text === "/new") {
|
|
1715
|
-
@@ -
|
|
1839
|
+
@@ -3164,7 +3261,7 @@ export class InteractiveMode {
|
|
1716
1840
|
if (this.chatContainer.children.length > 0) {
|
|
1717
1841
|
this.chatContainer.addChild(new Spacer(1));
|
|
1718
1842
|
}
|
|
@@ -1721,7 +1845,7 @@ index 42e655d..606c7cc 100644
|
|
|
1721
1845
|
}
|
|
1722
1846
|
async getUserInput() {
|
|
1723
1847
|
const queuedInput = this.pendingUserInputs.shift();
|
|
1724
|
-
@@ -
|
|
1848
|
+
@@ -3504,7 +3601,17 @@ export class InteractiveMode {
|
|
1725
1849
|
}
|
|
1726
1850
|
showError(errorMessage) {
|
|
1727
1851
|
this.chatContainer.addChild(new Spacer(1));
|
|
@@ -1741,10 +1865,10 @@ index 42e655d..606c7cc 100644
|
|
|
1741
1865
|
}
|
|
1742
1866
|
showWarning(warningMessage) {
|
|
1743
1867
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/dark.json b/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/dark.json
|
|
1744
|
-
index
|
|
1868
|
+
index 01d1e02..c591e1d 100644
|
|
1745
1869
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/dark.json
|
|
1746
1870
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/dark.json
|
|
1747
|
-
@@ -
|
|
1871
|
+
@@ -41,9 +41,9 @@
|
|
1748
1872
|
"customMessageBg": "customMsgBg",
|
|
1749
1873
|
"customMessageText": "text",
|
|
1750
1874
|
"customMessageLabel": "#9575cd",
|
|
@@ -1758,10 +1882,10 @@ index 9db9cbd..b370180 100644
|
|
|
1758
1882
|
"toolOutput": "gray",
|
|
1759
1883
|
|
|
1760
1884
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/light.json b/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/light.json
|
|
1761
|
-
index
|
|
1885
|
+
index 0fde42b..cc3b7c5 100644
|
|
1762
1886
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/light.json
|
|
1763
1887
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/light.json
|
|
1764
|
-
@@ -
|
|
1888
|
+
@@ -40,9 +40,9 @@
|
|
1765
1889
|
"customMessageBg": "customMsgBg",
|
|
1766
1890
|
"customMessageText": "text",
|
|
1767
1891
|
"customMessageLabel": "#7e57c2",
|
|
@@ -1775,11 +1899,11 @@ index 74ef3d1..709a21d 100644
|
|
|
1775
1899
|
"toolOutput": "mediumGray",
|
|
1776
1900
|
|
|
1777
1901
|
diff --git a/node_modules/@earendil-works/pi-coding-agent/dist/package-manager-cli.js b/node_modules/@earendil-works/pi-coding-agent/dist/package-manager-cli.js
|
|
1778
|
-
index
|
|
1902
|
+
index 3f101e6..51c7f73 100644
|
|
1779
1903
|
--- a/node_modules/@earendil-works/pi-coding-agent/dist/package-manager-cli.js
|
|
1780
1904
|
+++ b/node_modules/@earendil-works/pi-coding-agent/dist/package-manager-cli.js
|
|
1781
|
-
@@ -
|
|
1782
|
-
import
|
|
1905
|
+
@@ -5,7 +5,7 @@ import chalk from "chalk";
|
|
1906
|
+
import lockfile from "proper-lockfile";
|
|
1783
1907
|
import { selectConfig } from "./cli/config-selector.js";
|
|
1784
1908
|
import { createProjectTrustContext } from "./cli/project-trust.js";
|
|
1785
1909
|
-import { APP_NAME, CONFIG_DIR_NAME, detectInstallMethod, getAgentDir, getPackageDir, getSelfUpdateCommand, getSelfUpdateUnavailableInstruction, PACKAGE_NAME, VERSION, } from "./config.js";
|
|
@@ -1787,7 +1911,7 @@ index 4230b18..f47e80f 100644
|
|
|
1787
1911
|
import { ModelRuntime } from "./core/model-runtime.js";
|
|
1788
1912
|
import { DefaultPackageManager } from "./core/package-manager.js";
|
|
1789
1913
|
import { resolveProjectTrusted } from "./core/project-trust.js";
|
|
1790
|
-
@@ -
|
|
1914
|
+
@@ -221,7 +221,7 @@ Without -l, starts in global settings (~/${CONFIG_DIR_NAME}/agent/settings.json)
|
|
1791
1915
|
Press Tab in the TUI to switch between global and project-local modes.
|
|
1792
1916
|
|
|
1793
1917
|
Options:
|
|
@@ -1796,7 +1920,7 @@ index 4230b18..f47e80f 100644
|
|
|
1796
1920
|
-a, --approve Trust project-local files for this command with -l
|
|
1797
1921
|
-na, --no-approve Ignore project-local files for this command with -l
|
|
1798
1922
|
`);
|
|
1799
|
-
@@ -
|
|
1923
|
+
@@ -235,7 +235,7 @@ function printPackageCommandHelp(command) {
|
|
1800
1924
|
Install a package and add it to settings.
|
|
1801
1925
|
|
|
1802
1926
|
Options:
|
|
@@ -1805,7 +1929,7 @@ index 4230b18..f47e80f 100644
|
|
|
1805
1929
|
-a, --approve Trust project-local files for this command
|
|
1806
1930
|
-na, --no-approve Ignore project-local files for this command
|
|
1807
1931
|
|
|
1808
|
-
@@ -
|
|
1932
|
+
@@ -256,7 +256,7 @@ Remove a package and its source from settings.
|
|
1809
1933
|
Alias: ${APP_NAME} uninstall <source> [-l]
|
|
1810
1934
|
|
|
1811
1935
|
Options:
|
|
@@ -1,28 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$comment": "The one list of extensions Privateer ships. Read by bin/privateer-launch.mjs (shim install, dependency-free, pre-patch) and src/config/moatManifest.ts (RESERVED + profile composition). JSON so both a plain .mjs and the TS side can read it without a build step. See moatManifest.ts for the field contract.",
|
|
3
|
-
"shims": [
|
|
4
|
-
{ "name": "privateer-brand", "entry": "extensions/privateer-brand.ts", "note": "banner, ⚓ badge, /signin /signout" },
|
|
5
|
-
{ "name": "privateer-context", "entry": "extensions/privateer-context.ts", "note": "PRIVATEER.md context + /init" },
|
|
6
|
-
{ "name": "privateer-gate", "entry": "extensions/privateer-gate.ts", "note": "the permission gate (moat)" },
|
|
7
|
-
{ "name": "privateer-account", "entry": "extensions/privateer-account.ts", "note": "account inference provider" },
|
|
8
|
-
{ "name": "privateer-models", "entry": "extensions/privateer-models.ts", "note": "/models picker w/ privacy shields" },
|
|
9
|
-
{ "name": "privateer-posture", "entry": "extensions/privateer-posture.ts", "note": "live attestation shield" },
|
|
10
|
-
{ "name": "privateer-tools", "entry": "extensions/privateer-tools.ts", "note": "Privateer tool pack" },
|
|
11
|
-
{ "name": "privateer-privacy", "entry": "extensions/privateer-privacy.ts", "note": "pi-privacy + account tier resolver" },
|
|
12
|
-
{ "name": "privateer-connect", "entry": "extensions/privateer-connect.ts", "note": "/connect — MCP connector manager" },
|
|
13
|
-
{ "name": "privateer-media", "entry": "extensions/privateer-media.ts", "note": "image/video/speech/music + ffmpeg compose" },
|
|
14
|
-
{ "name": "privateer-desktop", "entry": "extensions/privateer-desktop.ts", "note": "/desktop — open the Privateer desktop app" },
|
|
15
|
-
{ "name": "privateer-hints", "entry": "extensions/privateer-hints.ts", "note": "rotating tips in the working line + /hints" },
|
|
16
|
-
{ "name": "privateer-update", "entry": "extensions/privateer-update.ts", "note": "tool pack updates in place — banner flag + /update" },
|
|
17
|
-
{ "name": "privateer-speak", "entry": "extensions/privateer-speak.ts", "note": "spoken responses (/speak) + voice input (/talk) — pi-speak + confidential account TTS/STT" },
|
|
18
|
-
{ "name": "privateer-web", "entry": "extensions/privateer-web.ts", "note": "web_search/web_fetch — account search when signed in, else the user's own provider (rpiv-web-tools)" },
|
|
19
|
-
{ "name": "rpiv-ask-user-question", "dep": ["@juicesharp/rpiv-ask-user-question", "index.ts"], "note": "ask_user_question" },
|
|
20
|
-
{ "name": "pi-mcp-adapter", "dep": ["pi-mcp-adapter", "index.ts"], "note": "MCP servers as first-class tools" },
|
|
21
|
-
{ "name": "pi-subagents", "dep": ["pi-subagents", "src", "extension", "index.ts"], "note": "bounded parallel sub-agents" }
|
|
22
|
-
],
|
|
23
|
-
"retired": ["pi-privacy", "pi-web-access", "pi-hypa", "rpiv-web-tools"],
|
|
24
3
|
"reservedAliases": [
|
|
25
4
|
"@juicesharp/rpiv-web-tools",
|
|
26
|
-
"@juicesharp/rpiv-ask-user-question"
|
|
5
|
+
"@juicesharp/rpiv-ask-user-question",
|
|
6
|
+
"background-tasks"
|
|
7
|
+
],
|
|
8
|
+
"retired": ["pi-privacy", "pi-web-access", "pi-hypa", "rpiv-web-tools"],
|
|
9
|
+
"shims": [
|
|
10
|
+
{ "entry": "extensions/privateer-brand.ts", "name": "privateer-brand", "note": "banner, ⚓ badge, /signin /signout" },
|
|
11
|
+
{ "entry": "extensions/privateer-context.ts", "name": "privateer-context", "note": "PRIVATEER.md context + /init" },
|
|
12
|
+
{ "entry": "extensions/privateer-gate.ts", "name": "privateer-gate", "note": "the permission gate (moat)" },
|
|
13
|
+
{ "entry": "extensions/privateer-account.ts", "name": "privateer-account", "note": "account inference provider" },
|
|
14
|
+
{ "entry": "extensions/privateer-models.ts", "name": "privateer-models", "note": "/models picker w/ privacy shields" },
|
|
15
|
+
{ "entry": "extensions/privateer-posture.ts", "name": "privateer-posture", "note": "live attestation shield" },
|
|
16
|
+
{ "entry": "extensions/privateer-tools.ts", "name": "privateer-tools", "note": "Privateer tool pack" },
|
|
17
|
+
{ "entry": "extensions/privateer-privacy.ts", "name": "privateer-privacy", "note": "pi-privacy + account tier resolver" },
|
|
18
|
+
{ "entry": "extensions/privateer-connect.ts", "name": "privateer-connect", "note": "/connect — MCP connector manager" },
|
|
19
|
+
{ "entry": "extensions/privateer-media.ts", "name": "privateer-media", "note": "image/video/speech/music + ffmpeg compose" },
|
|
20
|
+
{ "entry": "extensions/privateer-desktop.ts", "name": "privateer-desktop", "note": "/desktop — open the Privateer desktop app" },
|
|
21
|
+
{ "entry": "extensions/privateer-hints.ts", "name": "privateer-hints", "note": "rotating tips in the working line + /hints" },
|
|
22
|
+
{ "entry": "extensions/privateer-update.ts", "name": "privateer-update", "note": "tool pack updates in place — banner flag + /update" },
|
|
23
|
+
{ "entry": "extensions/privateer-speak.ts", "name": "privateer-speak", "note": "spoken responses (/speak) + voice input (/talk) — pi-speak + confidential account TTS/STT" },
|
|
24
|
+
{ "entry": "extensions/privateer-web.ts", "name": "privateer-web", "note": "web_search/web_fetch — account search when signed in, else the user's own provider (rpiv-web-tools)" },
|
|
25
|
+
{ "dep": ["@juicesharp/rpiv-ask-user-question", "index.ts"], "name": "rpiv-ask-user-question", "note": "ask_user_question" },
|
|
26
|
+
{ "dep": ["pi-mcp-adapter", "index.ts"], "name": "pi-mcp-adapter", "note": "MCP servers as first-class tools" },
|
|
27
|
+
{ "dep": ["pi-subagents", "src", "extension", "index.ts"], "name": "pi-subagents", "note": "bounded parallel sub-agents" },
|
|
28
|
+
{ "dep": ["pi-background-tasks", "extensions", "anthropic-attribution.ts"], "name": "anthropic-attribution", "note": "Anthropic OAuth attribution and prompt sanitization" },
|
|
29
|
+
{ "dep": ["pi-background-tasks", "extensions", "background-tasks.ts"], "name": "pi-background-tasks", "note": "durable background tasks, delegated agents, and fusion" }
|
|
27
30
|
]
|
|
28
31
|
}
|
package/src/context.ts
CHANGED
|
@@ -93,6 +93,15 @@ export function discoverContextFiles(cwd: string = process.cwd()): ContextFile[]
|
|
|
93
93
|
// A unique sentinel opening the injected block, so before_agent_start can no-op if the
|
|
94
94
|
// block is already present in the chained system prompt (defensive against re-entrancy).
|
|
95
95
|
export const CONTEXT_BLOCK_MARKER = "<!-- privateer:PRIVATEER.md -->";
|
|
96
|
+
export const RUNTIME_GUIDELINES_MARKER = "<!-- privateer:runtime-guidelines -->";
|
|
97
|
+
|
|
98
|
+
export function runtimeGuidelinesBlock(): string {
|
|
99
|
+
return `\n\n${RUNTIME_GUIDELINES_MARKER}\n<environment_guidelines>
|
|
100
|
+
- Node.js environment: Node.js (v22+) is guaranteed to be available in Privateer. Prefer \`node -e "..."\` or small Node.js scripts for quick scripting, calculations, or JSON processing instead of assuming \`python\` or \`python3\` is installed.
|
|
101
|
+
- Search fallback: If \`rg\` (ripgrep) is missing or returns "command not found", fall back to standard POSIX \`grep -rn <pattern> <path>\` or \`find <path>\`.
|
|
102
|
+
- Missing system dependencies: If an essential external tool (e.g. \`git\`, \`python\`, \`rg\`) is missing and needed, check its presence (\`command -v <tool>\`), explain clearly what is missing, and offer to install it using the host package manager (e.g. \`brew install\`, \`xcode-select --install\`, \`winget install\`, \`apt install\`) upon user approval.
|
|
103
|
+
</environment_guidelines>\n`;
|
|
104
|
+
}
|
|
96
105
|
|
|
97
106
|
// Format the discovered files into a system-prompt fragment using the same framing Pi
|
|
98
107
|
// applies to AGENTS.md (see core/system-prompt.js), so the model can't tell the two
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
// to "deny".
|
|
12
12
|
|
|
13
13
|
import { randomUUID } from "node:crypto";
|
|
14
|
+
import { noQuarterActive, setNoQuarter } from "../permissions/noQuarter.ts";
|
|
14
15
|
import type { EngineEvent } from "../engine/events.ts";
|
|
15
16
|
import type { PermissionRequest } from "../permissions/gate.ts";
|
|
16
17
|
import type { AskOutcome } from "../permissions/modeGate.ts";
|
|
@@ -169,7 +170,7 @@ export interface RemoteBridgeConfig {
|
|
|
169
170
|
export class RemoteBridge {
|
|
170
171
|
private relay?: RelayLike;
|
|
171
172
|
private remote = false;
|
|
172
|
-
private noQuarter =
|
|
173
|
+
private noQuarter = noQuarterActive();
|
|
173
174
|
private readonly pending = new Map<string, (d: AskOutcome) => void>();
|
|
174
175
|
private readonly pendingSelects = new Map<string, (v: string | null) => void>();
|
|
175
176
|
private readonly pendingInputs = new Map<string, (v: string | null) => void>();
|
|
@@ -282,9 +283,15 @@ export class RemoteBridge {
|
|
|
282
283
|
onFilesSearch: (id, query) => this.cfg.onFilesSearch?.(id, query),
|
|
283
284
|
onNoQuarter: (on) => {
|
|
284
285
|
this.noQuarter = on;
|
|
286
|
+
setNoQuarter(on);
|
|
285
287
|
this.relay?.sendNoQuarter(on); // echo the ack back so the app's toggle syncs
|
|
286
288
|
},
|
|
287
|
-
onControllerAttached: () =>
|
|
289
|
+
onControllerAttached: () => {
|
|
290
|
+
if (this.noQuarter || noQuarterActive()) {
|
|
291
|
+
this.relay?.sendNoQuarter(true);
|
|
292
|
+
}
|
|
293
|
+
this.cfg.onControllerAttached?.();
|
|
294
|
+
},
|
|
288
295
|
// The app left while we're still running. Same posture as a dropped socket: stop
|
|
289
296
|
// treating the turn as remote (the gate must not wait on a controller that isn't
|
|
290
297
|
// there) and fail every pending approval closed. The turn itself keeps going —
|
|
@@ -310,7 +317,7 @@ export class RemoteBridge {
|
|
|
310
317
|
// ── gate hooks (passed into the GateController) ─────────────────────────────
|
|
311
318
|
|
|
312
319
|
getRemote = (): boolean => this.remote;
|
|
313
|
-
getNoQuarter = (): boolean => this.noQuarter;
|
|
320
|
+
getNoQuarter = (): boolean => this.noQuarter || noQuarterActive();
|
|
314
321
|
|
|
315
322
|
// The gate's remote approver: relay the request to the app and await its
|
|
316
323
|
// allow/deny. Fail closed if no controller, on abort, or on disconnect. (The gate
|