privateer-agent 0.12.53 → 0.12.54
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/extensions/privateer-context.ts +5 -0
- package/package.json +1 -1
- package/src/config/moat.ts +5 -1
- package/src/identity.ts +58 -0
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
RUNTIME_GUIDELINES_MARKER,
|
|
26
26
|
runtimeGuidelinesBlock,
|
|
27
27
|
} from "../src/context.ts";
|
|
28
|
+
import privateerIdentity from "../src/identity.ts";
|
|
28
29
|
|
|
29
30
|
// Honor Pi's own "disable context files" switch, so --no-context-files / -nc silences
|
|
30
31
|
// everything this extension injects, not just PRIVATEER.md — otherwise the flag would
|
|
@@ -33,6 +34,10 @@ const CONTEXT_FILES_DISABLED =
|
|
|
33
34
|
process.argv.includes("--no-context-files") || process.argv.includes("-nc");
|
|
34
35
|
|
|
35
36
|
export default function privateerContext(pi: any): void {
|
|
37
|
+
// Privateer's name and CLI in place of Pi's (src/identity.ts). Its own handler, ahead
|
|
38
|
+
// of the -nc gate below: that flag silences context files, not which command is safe.
|
|
39
|
+
privateerIdentity(pi);
|
|
40
|
+
|
|
36
41
|
// Inject the runtime guidelines + PRIVATEER.md into every turn's system prompt. The
|
|
37
42
|
// prompt is rebuilt per turn and chained across before_agent_start handlers, so
|
|
38
43
|
// appending here is idempotent for the turn; each marker guard makes its own block a
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "privateer-agent",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.54",
|
|
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",
|
package/src/config/moat.ts
CHANGED
|
@@ -291,7 +291,11 @@ export async function buildMoat(opts: MoatOptions): Promise<ExtensionFactory[]>
|
|
|
291
291
|
|
|
292
292
|
if (caps.context) {
|
|
293
293
|
const { default: privateerContext } = await import("../../extensions/privateer-context.ts");
|
|
294
|
-
factories.push(privateerContext);
|
|
294
|
+
factories.push(privateerContext); // carries privateerIdentity itself
|
|
295
|
+
} else {
|
|
296
|
+
// Every kind: the model is told it runs Privateer, never `pi`. See src/identity.ts.
|
|
297
|
+
const { default: privateerIdentity } = await import("../identity.ts");
|
|
298
|
+
factories.push(privateerIdentity);
|
|
295
299
|
}
|
|
296
300
|
|
|
297
301
|
if (caps.spawnSkills) {
|
package/src/identity.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Who the model thinks it is, and which command it reaches for.
|
|
2
|
+
//
|
|
3
|
+
// THE PROBLEM. Pi's stock system prompt opens "You are an expert coding assistant
|
|
4
|
+
// operating inside pi" and points the model at Pi's own README for questions about
|
|
5
|
+
// "pi itself" — a README that documents `pi -p`. So an agent asked to run a one-shot
|
|
6
|
+
// job, script itself, or hand work to another agent process typed `pi -p "…"`. That is
|
|
7
|
+
// not a cosmetic slip: bare `pi` runs with none of the moat — no permission gate, no
|
|
8
|
+
// --allow-spend / --approve-in-app, no privacy routing, no account — so the one
|
|
9
|
+
// invocation that most needs the spending gate was the one that skipped it.
|
|
10
|
+
//
|
|
11
|
+
// THE FIX. Rewrite Pi's self-description to name Privateer, relabel the Pi docs as the
|
|
12
|
+
// SDK docs they are (still the right reference for writing extensions), and append a
|
|
13
|
+
// short block stating the CLI the model must use. Registered on every surface: the
|
|
14
|
+
// discovered privateer-context shim (TUI, -p, subagent children, desktop) and the
|
|
15
|
+
// in-code moat for kinds that don't load that shim (src/config/moat.ts).
|
|
16
|
+
//
|
|
17
|
+
// Same "append, or say nothing" contract as privateer-context: a host that hands us no
|
|
18
|
+
// prompt string gets no rewrite, and a prompt already carrying the marker is left alone.
|
|
19
|
+
|
|
20
|
+
export const IDENTITY_MARKER = "<!-- privateer:identity -->";
|
|
21
|
+
|
|
22
|
+
const PI_PREAMBLE = "operating inside pi, a coding agent harness.";
|
|
23
|
+
const PI_DOCS_HEADER =
|
|
24
|
+
"Pi documentation (read only when the user asks about pi itself, its SDK, extensions, themes, skills, or TUI):";
|
|
25
|
+
|
|
26
|
+
export function privateerCliBlock(cmd: string = process.env.PRIVATEER_CMD || "privateer"): string {
|
|
27
|
+
return `\n\n${IDENTITY_MARKER}\n<privateer_cli>
|
|
28
|
+
You are running inside Privateer; its command is \`${cmd}\`. Privateer is built on the Pi SDK, but \`pi\` is NOT a command you may use: never run \`pi\`, \`pi -p\` or any other \`pi …\` invocation. It bypasses Privateer's permission gate, spending caps, privacy routing and account. Wherever Pi's docs show \`pi\`, the command here is \`${cmd}\`.
|
|
29
|
+
- One-shot / headless run (a script, a cron job, handing a task to a separate agent process): \`${cmd} -p "…"\`. It has no screen, so anything that needs approval is DENIED, including every billed media tool.
|
|
30
|
+
- Let that run spend on named billed tools, capped: \`${cmd} -p --allow-spend <tool[,tool…]> --max-calls <n> [--max-spend <usd>] "…"\`
|
|
31
|
+
- Or send each approval to the user's Privateer app: \`${cmd} -p --approve-in-app [--approval-timeout <seconds>] "…"\`
|
|
32
|
+
- A program that must answer approvals itself drives Privateer over ACP: \`${cmd} acp\`.
|
|
33
|
+
- For a sub-task inside this session, use a subagent tool if one is available rather than shelling out to a new process.
|
|
34
|
+
</privateer_cli>\n`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Rewrite Pi's self-description and append the CLI block. Returns `prompt` unchanged when already applied. */
|
|
38
|
+
export function applyIdentity(prompt: string, cmd?: string): string {
|
|
39
|
+
if (prompt.includes(IDENTITY_MARKER)) return prompt;
|
|
40
|
+
const out = prompt
|
|
41
|
+
.replace(PI_PREAMBLE, "operating inside Privateer, a privacy-first coding agent built on the Pi SDK.")
|
|
42
|
+
.replace(
|
|
43
|
+
PI_DOCS_HEADER,
|
|
44
|
+
"Pi SDK documentation (Privateer is built on Pi; read only when asked about writing extensions, themes, skills, prompt templates or TUI components — every `pi` command in these docs is `privateer` here):",
|
|
45
|
+
);
|
|
46
|
+
return out + privateerCliBlock(cmd);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** A before_agent_start extension that applies the identity rewrite. */
|
|
50
|
+
export default function privateerIdentity(pi: any): void {
|
|
51
|
+
pi.on("before_agent_start", (event: any) => {
|
|
52
|
+
const base = event?.systemPrompt;
|
|
53
|
+
if (typeof base !== "string") return;
|
|
54
|
+
const prompt = applyIdentity(base);
|
|
55
|
+
if (prompt === base) return;
|
|
56
|
+
return { systemPrompt: prompt };
|
|
57
|
+
});
|
|
58
|
+
}
|