privateer-agent 0.14.5 → 0.14.6
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/headless-flags.d.mts +10 -0
- package/bin/headless-flags.mjs +71 -0
- package/bin/privateer-launch.mjs +26 -7
- package/package.json +1 -1
- package/src/config/whatsNew.json +3 -3
package/bin/headless-flags.d.mts
CHANGED
|
@@ -30,3 +30,13 @@ export function extractPrivateFlag(args: string[]): boolean;
|
|
|
30
30
|
export function privateProblem(args: string[]): string | null;
|
|
31
31
|
|
|
32
32
|
export function authProblem(args: string[], cmd?: string): string | null;
|
|
33
|
+
|
|
34
|
+
/** `auth check|print-*` for the privateer provider, answered by the launcher; null for Pi. */
|
|
35
|
+
export function privateerAuthAnswer(
|
|
36
|
+
args: string[],
|
|
37
|
+
signedIn: boolean,
|
|
38
|
+
cmd?: string,
|
|
39
|
+
): { out: string; err: string; code: number } | null;
|
|
40
|
+
|
|
41
|
+
/** `auth --help` with our command name and the provider agents look for. */
|
|
42
|
+
export function authHelp(cmd?: string): string;
|
package/bin/headless-flags.mjs
CHANGED
|
@@ -204,3 +204,74 @@ export function authProblem(args, cmd = "privateer") {
|
|
|
204
204
|
`Nothing was sent to a model. To sign in, run \`${cmd}\` and type /login.`,
|
|
205
205
|
].join("\n");
|
|
206
206
|
}
|
|
207
|
+
|
|
208
|
+
// The value of --provider / --model in `args`, in either `--flag v` or `--flag=v` form.
|
|
209
|
+
function flagValue(args, flag) {
|
|
210
|
+
for (let i = 0; i < args.length; i++) {
|
|
211
|
+
if (args[i] === flag) return args[i + 1];
|
|
212
|
+
if (args[i].startsWith(flag + "=")) return args[i].slice(flag.length + 1);
|
|
213
|
+
}
|
|
214
|
+
return undefined;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* `auth check|print-api-key|print-bearer-token` for the `privateer` provider, answered
|
|
219
|
+
* here. Pi runs these with no extensions loaded, and `privateer` is registered by ours,
|
|
220
|
+
* so Pi always said `provider_not_found` — and agents probing a signed-in machine with
|
|
221
|
+
* the exact command `auth status` suggests concluded it was signed out. Readiness comes
|
|
222
|
+
* from the account login (the same file `auth status` reads); the per-launch session
|
|
223
|
+
* in auth.json is minted from it. The account token is never printed: it's the login
|
|
224
|
+
* itself, and nothing outside Privateer can use it as a provider key anyway.
|
|
225
|
+
*
|
|
226
|
+
* Returns { out, err, code } to print, or null for Pi to handle.
|
|
227
|
+
*/
|
|
228
|
+
export function privateerAuthAnswer(args, signedIn, cmd = "privateer") {
|
|
229
|
+
if (args[0] !== "auth" || !AUTH_SUBCOMMANDS.includes(args[1])) return null;
|
|
230
|
+
if (args.includes("--help") || args.includes("-h")) return null;
|
|
231
|
+
const provider = flagValue(args, "--provider");
|
|
232
|
+
const model = flagValue(args, "--model");
|
|
233
|
+
if (provider !== "privateer" && !(provider === undefined && model?.startsWith("privateer/"))) return null;
|
|
234
|
+
|
|
235
|
+
const run = `${cmd} -p "<task>"`;
|
|
236
|
+
if (args[1] !== "check") {
|
|
237
|
+
return {
|
|
238
|
+
out: "",
|
|
239
|
+
err: [
|
|
240
|
+
`${cmd} auth ${args[1]}: the privateer provider's credential is your account login, and it isn't printed.`,
|
|
241
|
+
signedIn ? `This machine is signed in — run a task with: ${run}` : `Sign in first: run \`${cmd}\` and type /login.`,
|
|
242
|
+
].join("\n"),
|
|
243
|
+
code: 1,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
if (args.includes("--credentials")) {
|
|
247
|
+
// Pi's contract: --credentials emits the credential or reports it unavailable.
|
|
248
|
+
const result = { status: "not_ready", provider: "privateer", reason: "credential_not_available" };
|
|
249
|
+
return { out: args.includes("--json") ? JSON.stringify(result) : result.status, err: "", code: 1 };
|
|
250
|
+
}
|
|
251
|
+
const result = signedIn
|
|
252
|
+
? { status: "ready", provider: "privateer", authType: "oauth" }
|
|
253
|
+
: { status: "not_ready", provider: "privateer", reason: "credentials_not_configured" };
|
|
254
|
+
return {
|
|
255
|
+
out: args.includes("--json") ? JSON.stringify(result) : result.status,
|
|
256
|
+
err: signedIn ? "" : `Not signed in: run \`${cmd}\` and type /login.`,
|
|
257
|
+
code: signedIn ? 0 : 1,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/** `auth --help` with our command name, the provider agents look for, and how to run a task. */
|
|
262
|
+
export function authHelp(cmd = "privateer") {
|
|
263
|
+
return [
|
|
264
|
+
"Usage:",
|
|
265
|
+
` ${cmd} auth status`,
|
|
266
|
+
` ${cmd} auth check [--provider <provider>] [--model <model>] [--json] [--credentials] [--no-refresh]`,
|
|
267
|
+
` ${cmd} auth print-api-key [--provider <provider>] [--model <model>]`,
|
|
268
|
+
` ${cmd} auth print-bearer-token [--provider <provider>] [--model <model>] [--min-expiry <duration>]`,
|
|
269
|
+
"",
|
|
270
|
+
"status reports whether this machine is signed in to a Privateer account.",
|
|
271
|
+
"check and print-* need --provider or --model. Your account's models are provider",
|
|
272
|
+
`\`privateer\`: \`${cmd} auth check --provider privateer\`. Its credential is the account`,
|
|
273
|
+
"login and is never printed. Other providers (openai, anthropic, …) use their own keys.",
|
|
274
|
+
"",
|
|
275
|
+
`To run a task non-interactively once signed in: ${cmd} -p "<task>"`,
|
|
276
|
+
].join("\n");
|
|
277
|
+
}
|
package/bin/privateer-launch.mjs
CHANGED
|
@@ -29,7 +29,7 @@ import path from "node:path";
|
|
|
29
29
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
30
30
|
import { applyPatchesIfNeeded, resolveDep } from "./apply-patches.mjs";
|
|
31
31
|
import { routeUpdate } from "./update-route.mjs";
|
|
32
|
-
import { APPROVE_IN_APP_ENV, CLI_SPEND_ENV, PI_SUBCOMMANDS, PRIVATE_ENV, authProblem, extractHeadlessFlags, extractPrivateFlag, privateProblem } from "./headless-flags.mjs";
|
|
32
|
+
import { APPROVE_IN_APP_ENV, CLI_SPEND_ENV, PI_SUBCOMMANDS, PRIVATE_ENV, authHelp, authProblem, extractHeadlessFlags, privateerAuthAnswer, extractPrivateFlag, privateProblem } from "./headless-flags.mjs";
|
|
33
33
|
import { runToCompletion } from "./run-to-completion.mjs";
|
|
34
34
|
import { modelArgs } from "./model-args.mjs";
|
|
35
35
|
import { filterRespawnArgs, listTerminals, requestFresh, runSupervised } from "./fresh-supervisor.mjs";
|
|
@@ -669,6 +669,16 @@ else if (PI_SUBCOMMANDS.includes(sub)) {
|
|
|
669
669
|
printAuthStatus(cmd);
|
|
670
670
|
process.exit(0);
|
|
671
671
|
}
|
|
672
|
+
if (sub === "auth" && (args[1] === undefined || args[1] === "help" || args.includes("--help") || args.includes("-h"))) {
|
|
673
|
+
console.log(authHelp(cmd));
|
|
674
|
+
process.exit(0);
|
|
675
|
+
}
|
|
676
|
+
const own = sub === "auth" ? privateerAuthAnswer(args, accountSignedIn(), cmd) : null;
|
|
677
|
+
if (own) {
|
|
678
|
+
if (own.out) console.log(own.out);
|
|
679
|
+
if (own.err) process.stderr.write(own.err + "\n");
|
|
680
|
+
process.exit(own.code);
|
|
681
|
+
}
|
|
672
682
|
const CLI = resolveDep(REPO, "@earendil-works/pi-coding-agent", "dist", "cli.js");
|
|
673
683
|
if (!CLI || !fs.existsSync(CLI)) {
|
|
674
684
|
console.error(
|
|
@@ -1030,13 +1040,21 @@ function warnKeylessLaunch() {
|
|
|
1030
1040
|
|
|
1031
1041
|
// `privateer auth status` — the question people (and agents) actually ask, answered
|
|
1032
1042
|
// from local state only: no network, nothing sent anywhere, and no secret printed.
|
|
1033
|
-
function
|
|
1034
|
-
let creds = null;
|
|
1043
|
+
function readAccountCredentials() {
|
|
1035
1044
|
try {
|
|
1036
|
-
creds = JSON.parse(fs.readFileSync(path.join(PRIVATEER_HOME, "credentials.json"), "utf8"));
|
|
1037
|
-
|
|
1045
|
+
const creds = JSON.parse(fs.readFileSync(path.join(PRIVATEER_HOME, "credentials.json"), "utf8"));
|
|
1046
|
+
return creds && typeof creds.accessToken === "string" ? creds : null;
|
|
1047
|
+
} catch { return null; /* absent or unreadable → signed out */ }
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
function accountSignedIn() {
|
|
1051
|
+
return readAccountCredentials() !== null;
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
function printAuthStatus(cmd) {
|
|
1055
|
+
const creds = readAccountCredentials();
|
|
1038
1056
|
const lines = [];
|
|
1039
|
-
if (creds
|
|
1057
|
+
if (creds) {
|
|
1040
1058
|
const who = creds.user?.email || "your account";
|
|
1041
1059
|
lines.push(`Privateer account: signed in as ${who}${creds.serverBaseUrl ? ` (${creds.serverBaseUrl})` : ""}`);
|
|
1042
1060
|
lines.push(" This checks the local login only; a session revoked from the app shows up on the next request.");
|
|
@@ -1046,7 +1064,8 @@ function printAuthStatus(cmd) {
|
|
|
1046
1064
|
}
|
|
1047
1065
|
const keys = ["ANTHROPIC_API_KEY", "OPENAI_API_KEY", "OPENROUTER_API_KEY", "TINFOIL_API_KEY", "PRIVATEER_API_KEY"].filter(haveKey);
|
|
1048
1066
|
lines.push(`Provider keys in the environment: ${keys.length ? keys.join(", ") : "none"}`);
|
|
1049
|
-
lines.push(`
|
|
1067
|
+
lines.push(`Your account's models are provider \`privateer\`: ${cmd} auth check --provider privateer`);
|
|
1068
|
+
if (creds) lines.push(`To run a task non-interactively: ${cmd} -p "<task>"`);
|
|
1050
1069
|
console.log(lines.join("\n"));
|
|
1051
1070
|
}
|
|
1052
1071
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "privateer-agent",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.6",
|
|
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/whatsNew.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$comment": "The banner's What's New list, newest first: the two to four things a returning user should notice, not a changelog. `reviewedFor` is the release this list was last looked at for. A release can't ship until it equals package.json's version (scripts/check-whats-new.mjs, run by `npm test` and by release.yml before anything builds), so every release, patches included, is a deliberate look at this list. If nothing new is worth a line, bumping `reviewedFor` alone is the answer. `since` is the release an entry arrived in. `cmd` is shown in the accent colour.",
|
|
3
|
-
"reviewedFor": "0.14.
|
|
3
|
+
"reviewedFor": "0.14.6",
|
|
4
4
|
"items": [
|
|
5
|
+
{ "text": "API keys can expire and carry their own credit limit — set them in the app", "since": "0.14.6" },
|
|
5
6
|
{ "text": "Save to Cargo with no app attached — it lands on your next app open", "since": "0.14.4" },
|
|
6
7
|
{ "text": "Several privateer -p runs at once no longer sign each other out", "since": "0.14.3" },
|
|
7
|
-
{ "text": "A reply cut off at the output limit picks back up on its own", "since": "0.14.2" }
|
|
8
|
-
{ "text": "Chat channels as a login service: privateer channels install", "since": "0.14.1" }
|
|
8
|
+
{ "text": "A reply cut off at the output limit picks back up on its own", "since": "0.14.2" }
|
|
9
9
|
]
|
|
10
10
|
}
|