nuabase 2.3.5 → 2.3.7
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/README.md
CHANGED
|
@@ -172,7 +172,7 @@ Every call returns a discriminated union. When `success` is `false`, you get an
|
|
|
172
172
|
| `engine` | `'http'` \| `'local-agent'` | Whether an LLM provider's API or a coding agent on this machine answered. |
|
|
173
173
|
| `schemaEnforcement` | `'in-prompt'` \| `'native'` | Whether the schema was described in the prompt or enforced by the engine. Output is validated either way. |
|
|
174
174
|
| `provider` | `string` | `engine: 'http'` only. The LLM provider. |
|
|
175
|
-
| `agent` | `'claude-code'` \| `'codex'` | `engine: 'local-agent'` only. Which coding agent answered. |
|
|
175
|
+
| `agent` | `'claude-code'` \| `'codex'` \| `'pi'` | `engine: 'local-agent'` only. Which coding agent answered. |
|
|
176
176
|
| `costUsdEstimate` | `number \| undefined` | `engine: 'local-agent'` only. The agent's own estimate. On a subscription this is not what you pay. |
|
|
177
177
|
|
|
178
178
|
**Error**
|
|
@@ -233,13 +233,13 @@ const agents = await detectLocalAgents();
|
|
|
233
233
|
// [{ agent: 'claude-code', installed: true, loggedIn: true, version: '...', binaryPath: '...' }, ...]
|
|
234
234
|
```
|
|
235
235
|
|
|
236
|
-
This runs a coding-agent CLI already installed and logged in on this machine, in its headless mode (`claude -p` or `
|
|
236
|
+
This runs a coding-agent CLI already installed and logged in on this machine, in its headless mode (`claude -p`, `codex exec`, or `pi --mode json`). Calls use the user's own logged-in subscription or provider login, so no API key is needed. `get()` and `list()` behave as with providers: the output is validated against your schema and typed the same way. Queue operations are not supported. `nuabase/local-agent` is a separate entry point so that browser bundles of `nuabase` never include it.
|
|
237
237
|
|
|
238
238
|
The agent is set up once, when you create it. If you install an agent or log in after that, create a new one.
|
|
239
239
|
|
|
240
240
|
**`localAgent(config)`** sets up a named agent. It throws right away if the agent's executable cannot be found; if the agent is not logged in, the first call fails with that error.
|
|
241
241
|
|
|
242
|
-
- `agent: 'claude-code' | 'codex'`
|
|
242
|
+
- `agent: 'claude-code' | 'codex' | 'pi'`
|
|
243
243
|
- `binaryPath?: string` – Path to the agent executable. Defaults to looking it up on `PATH`. On Windows, point this at a native executable; `.cmd` shims are not supported.
|
|
244
244
|
- and the options below.
|
|
245
245
|
|
|
@@ -247,13 +247,13 @@ The agent is set up once, when you create it. If you install an agent or log in
|
|
|
247
247
|
|
|
248
248
|
Options for both:
|
|
249
249
|
|
|
250
|
-
- `model?: string` – The agent's own model name, e.g. `'haiku'` for Claude Code, for calls that name no model. Defaults to the agent's default. Per-call `model: { alias }` works for aliases the agent understands (`haiku`, `sonnet`, `opus` for Claude Code).
|
|
250
|
+
- `model?: string` – The agent's own model name, e.g. `'haiku'` for Claude Code, for calls that name no model. Defaults to the agent's default. Per-call `model: { alias }` works for aliases the agent understands (`haiku`, `sonnet`, `opus` for Claude Code). Codex and Pi have no aliases: pass one of their own model names, and for Pi a `provider/id` name such as `'openrouter/z-ai/glm-5.2'`.
|
|
251
251
|
- `timeoutMs?: number` – Per-call limit. Defaults to `180000`.
|
|
252
252
|
- `concurrency?: number` – Maximum agent processes at once. Defaults to `2`.
|
|
253
253
|
- `auth?: 'subscription' | 'inherit'` – `subscription` (default) hides `ANTHROPIC_API_KEY`, `OPENAI_API_KEY` and similar variables from the agent so it bills the logged-in plan rather than an API key.
|
|
254
254
|
- `logger?` – An object with `debug`, `info`, `warn` and `error` methods, where calls and retries are logged. Defaults to the console.
|
|
255
255
|
|
|
256
|
-
How it works: each call runs the agent in a fresh, empty temporary directory with its tools, project settings and MCP servers turned off. The schema is wrapped as `{ value: ... }` (the agents require an object at the top level) and passed to the agent's own schema option. Codex only accepts OpenAI strict-mode schemas, so a schema with optional properties or open-ended objects is instead described in the prompt, and the output is validated as usual. If an agent rejects a schema, the call is retried with the schema in the prompt. `maxTokens` has no CLI equivalent and is ignored. Calls count against the user's plan limits; check each vendor's terms before offering this to other users.
|
|
256
|
+
How it works: each call runs the agent in a fresh, empty temporary directory with its tools, project settings and MCP servers turned off. The schema is wrapped as `{ value: ... }` (the agents require an object at the top level) and passed to the agent's own schema option. Codex only accepts OpenAI strict-mode schemas, so a schema with optional properties or open-ended objects is instead described in the prompt, and the output is validated as usual. Pi has no schema flag at all, so its schemas are always described in the prompt. If an agent rejects a schema, the call is retried with the schema in the prompt. `maxTokens` has no CLI equivalent and is ignored. Calls count against the user's plan limits; check each vendor's terms before offering this to other users.
|
|
257
257
|
|
|
258
258
|
### Methods
|
|
259
259
|
|
package/dist/cjs/local-agent.cjs
CHANGED
|
@@ -367,6 +367,161 @@ ${result.stderr}`.trim();
|
|
|
367
367
|
return codex;
|
|
368
368
|
}
|
|
369
369
|
|
|
370
|
+
var pi = {};
|
|
371
|
+
|
|
372
|
+
var hasRequiredPi;
|
|
373
|
+
function requirePi() {
|
|
374
|
+
if (hasRequiredPi) return pi;
|
|
375
|
+
hasRequiredPi = 1;
|
|
376
|
+
Object.defineProperty(pi, "__esModule", { value: true });
|
|
377
|
+
pi.piAdapter = void 0;
|
|
378
|
+
const failure_classification_1 = requireFailureClassification();
|
|
379
|
+
const SYSTEM_PROMPT = [
|
|
380
|
+
"You are a data transformation function called by a program.",
|
|
381
|
+
"You have no tools. Follow the instructions in the user message exactly",
|
|
382
|
+
"and reply only with the requested JSON."
|
|
383
|
+
].join(" ");
|
|
384
|
+
pi.piAdapter = {
|
|
385
|
+
id: "pi",
|
|
386
|
+
binaryName: "pi",
|
|
387
|
+
// Every environment credential Pi's providers recognize. Under `auth:
|
|
388
|
+
// "subscription"` these are removed so Pi bills its own `auth.json` login.
|
|
389
|
+
apiKeyEnvVars: [
|
|
390
|
+
"AI_GATEWAY_API_KEY",
|
|
391
|
+
"ANT_LING_API_KEY",
|
|
392
|
+
"ANTHROPIC_API_KEY",
|
|
393
|
+
"ANTHROPIC_AUTH_TOKEN",
|
|
394
|
+
"ANTHROPIC_OAUTH_TOKEN",
|
|
395
|
+
"AWS_ACCESS_KEY_ID",
|
|
396
|
+
"AWS_SECRET_ACCESS_KEY",
|
|
397
|
+
"AWS_SESSION_TOKEN",
|
|
398
|
+
"AZURE_OPENAI_API_KEY",
|
|
399
|
+
"BASETEN_API_KEY",
|
|
400
|
+
"CEREBRAS_API_KEY",
|
|
401
|
+
"CLOUDFLARE_API_KEY",
|
|
402
|
+
"COPILOT_GITHUB_TOKEN",
|
|
403
|
+
"DEEPSEEK_API_KEY",
|
|
404
|
+
"FIREWORKS_API_KEY",
|
|
405
|
+
"GEMINI_API_KEY",
|
|
406
|
+
"GOOGLE_API_KEY",
|
|
407
|
+
"GOOGLE_CLOUD_API_KEY",
|
|
408
|
+
"GROQ_API_KEY",
|
|
409
|
+
"HF_TOKEN",
|
|
410
|
+
"KIMI_API_KEY",
|
|
411
|
+
"META_API_KEY",
|
|
412
|
+
"MINIMAX_API_KEY",
|
|
413
|
+
"MINIMAX_CN_API_KEY",
|
|
414
|
+
"MISTRAL_API_KEY",
|
|
415
|
+
"MOONSHOT_API_KEY",
|
|
416
|
+
"NVIDIA_API_KEY",
|
|
417
|
+
"OPENAI_API_KEY",
|
|
418
|
+
"OPENCODE_API_KEY",
|
|
419
|
+
"OPENROUTER_API_KEY",
|
|
420
|
+
"QWEN_TOKEN_PLAN_API_KEY",
|
|
421
|
+
"QWEN_TOKEN_PLAN_CN_API_KEY",
|
|
422
|
+
"RADIUS_API_KEY",
|
|
423
|
+
"TOGETHER_API_KEY",
|
|
424
|
+
"XAI_API_KEY",
|
|
425
|
+
"XIAOMI_API_KEY",
|
|
426
|
+
"XIAOMI_TOKEN_PLAN_AMS_API_KEY",
|
|
427
|
+
"XIAOMI_TOKEN_PLAN_CN_API_KEY",
|
|
428
|
+
"XIAOMI_TOKEN_PLAN_SGP_API_KEY",
|
|
429
|
+
"ZAI_API_KEY",
|
|
430
|
+
"ZAI_CODING_CN_API_KEY"
|
|
431
|
+
],
|
|
432
|
+
// Pi uses its own `provider/id` model names; set one with localAgent({ model }).
|
|
433
|
+
modelAliases: {},
|
|
434
|
+
nativeSchema() {
|
|
435
|
+
return null;
|
|
436
|
+
},
|
|
437
|
+
buildInvocation(request, model) {
|
|
438
|
+
const args = [
|
|
439
|
+
"--mode",
|
|
440
|
+
"json",
|
|
441
|
+
"--no-session",
|
|
442
|
+
"--no-tools",
|
|
443
|
+
"--no-builtin-tools",
|
|
444
|
+
"--no-extensions",
|
|
445
|
+
"--no-skills",
|
|
446
|
+
"--no-prompt-templates",
|
|
447
|
+
"--no-themes",
|
|
448
|
+
"--no-context-files",
|
|
449
|
+
"--system-prompt",
|
|
450
|
+
SYSTEM_PROMPT,
|
|
451
|
+
"--offline"
|
|
452
|
+
];
|
|
453
|
+
if (model !== void 0) {
|
|
454
|
+
args.push("--model", model);
|
|
455
|
+
}
|
|
456
|
+
return { args, stdin: request.prompt };
|
|
457
|
+
},
|
|
458
|
+
readResult(result, request) {
|
|
459
|
+
const events = parseEvents(result.stdout);
|
|
460
|
+
const assistant = events.filter((event) => event.type === "message_end" && event.message?.role === "assistant").map((event) => event.message).pop();
|
|
461
|
+
if (assistant && (assistant.stopReason === "error" || assistant.errorMessage)) {
|
|
462
|
+
return failed((0, failure_classification_1.classifyAgentFailure)("pi", assistant.errorMessage ?? "pi stopped with an error"));
|
|
463
|
+
}
|
|
464
|
+
const retryFailed = events.find((event) => event.type === "auto_retry_end" && event.success === false);
|
|
465
|
+
if (retryFailed) {
|
|
466
|
+
return failed((0, failure_classification_1.classifyAgentFailure)("pi", retryFailed.finalError ?? "auto retry failed"));
|
|
467
|
+
}
|
|
468
|
+
if (!assistant) {
|
|
469
|
+
return failed((0, failure_classification_1.classifyAgentFailure)("pi", `exited with code ${result.exitCode} without a reply: ${(0, failure_classification_1.stderrTail)(result)}`));
|
|
470
|
+
}
|
|
471
|
+
const text = (assistant.content ?? []).filter((block) => block.type === "text").map((block) => block.text ?? "").join("");
|
|
472
|
+
const usage = assistant.usage ?? {};
|
|
473
|
+
const promptTokens = (usage.input ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);
|
|
474
|
+
const completionTokens = usage.output ?? 0;
|
|
475
|
+
const reported = {
|
|
476
|
+
usage: { promptTokens, completionTokens, totalTokens: promptTokens + completionTokens },
|
|
477
|
+
model: assistant.model,
|
|
478
|
+
costUsdEstimate: usage.cost?.total
|
|
479
|
+
};
|
|
480
|
+
if (request.enforcement.kind === "in-prompt") {
|
|
481
|
+
return { kind: "answered", answer: { kind: "text", text }, ...reported };
|
|
482
|
+
}
|
|
483
|
+
let envelope;
|
|
484
|
+
try {
|
|
485
|
+
envelope = JSON.parse(text);
|
|
486
|
+
} catch {
|
|
487
|
+
return failed({ kind: "transient", message: `pi reply is not JSON: ${text}` });
|
|
488
|
+
}
|
|
489
|
+
return { kind: "answered", answer: { kind: "structured", envelope }, ...reported };
|
|
490
|
+
},
|
|
491
|
+
// Pi has no provider-agnostic login check: `pi auth check` requires --provider
|
|
492
|
+
// or --model, and the provider differs per user (it is not known until Pi's
|
|
493
|
+
// settings are read). Report installed Pi as logged in; the first real call
|
|
494
|
+
// surfaces any auth error, which classifyAgentFailure marks fatal.
|
|
495
|
+
loginStatusArgs: ["--version"],
|
|
496
|
+
readLoginStatus(result) {
|
|
497
|
+
return {
|
|
498
|
+
loggedIn: result.exitCode === 0,
|
|
499
|
+
detail: "installed; auth is verified on the first call"
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
function failed(failure) {
|
|
504
|
+
return { kind: "failed", failure };
|
|
505
|
+
}
|
|
506
|
+
function parseEvents(stdout) {
|
|
507
|
+
const events = [];
|
|
508
|
+
for (const line of stdout.split("\n")) {
|
|
509
|
+
const trimmed = line.replace(/\r$/, "").trim();
|
|
510
|
+
if (!trimmed.startsWith("{"))
|
|
511
|
+
continue;
|
|
512
|
+
try {
|
|
513
|
+
const parsed = JSON.parse(trimmed);
|
|
514
|
+
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
515
|
+
events.push(parsed);
|
|
516
|
+
}
|
|
517
|
+
} catch {
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return events;
|
|
521
|
+
}
|
|
522
|
+
return pi;
|
|
523
|
+
}
|
|
524
|
+
|
|
370
525
|
var hasRequiredAdapters;
|
|
371
526
|
function requireAdapters() {
|
|
372
527
|
if (hasRequiredAdapters) return adapters;
|
|
@@ -375,9 +530,11 @@ function requireAdapters() {
|
|
|
375
530
|
adapters.AGENT_ADAPTERS = void 0;
|
|
376
531
|
const claude_code_1 = requireClaudeCode();
|
|
377
532
|
const codex_1 = requireCodex();
|
|
533
|
+
const pi_1 = requirePi();
|
|
378
534
|
adapters.AGENT_ADAPTERS = {
|
|
379
535
|
"claude-code": claude_code_1.claudeCodeAdapter,
|
|
380
|
-
codex: codex_1.codexAdapter
|
|
536
|
+
codex: codex_1.codexAdapter,
|
|
537
|
+
pi: pi_1.piAdapter
|
|
381
538
|
};
|
|
382
539
|
return adapters;
|
|
383
540
|
}
|
|
@@ -392,7 +549,7 @@ function requireAgentId() {
|
|
|
392
549
|
Object.defineProperty(exports$1, "__esModule", { value: true });
|
|
393
550
|
exports$1.LOCAL_AGENT_IDS = void 0;
|
|
394
551
|
exports$1.isLocalAgentId = isLocalAgentId;
|
|
395
|
-
exports$1.LOCAL_AGENT_IDS = ["claude-code", "codex"];
|
|
552
|
+
exports$1.LOCAL_AGENT_IDS = ["claude-code", "codex", "pi"];
|
|
396
553
|
const LOCAL_AGENT_ID_SET = new Set(exports$1.LOCAL_AGENT_IDS);
|
|
397
554
|
function isLocalAgentId(value) {
|
|
398
555
|
return typeof value === "string" && LOCAL_AGENT_ID_SET.has(value);
|
package/dist/esm/local-agent.mjs
CHANGED
|
@@ -364,6 +364,161 @@ ${result.stderr}`.trim();
|
|
|
364
364
|
return codex;
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
+
var pi = {};
|
|
368
|
+
|
|
369
|
+
var hasRequiredPi;
|
|
370
|
+
function requirePi() {
|
|
371
|
+
if (hasRequiredPi) return pi;
|
|
372
|
+
hasRequiredPi = 1;
|
|
373
|
+
Object.defineProperty(pi, "__esModule", { value: true });
|
|
374
|
+
pi.piAdapter = void 0;
|
|
375
|
+
const failure_classification_1 = requireFailureClassification();
|
|
376
|
+
const SYSTEM_PROMPT = [
|
|
377
|
+
"You are a data transformation function called by a program.",
|
|
378
|
+
"You have no tools. Follow the instructions in the user message exactly",
|
|
379
|
+
"and reply only with the requested JSON."
|
|
380
|
+
].join(" ");
|
|
381
|
+
pi.piAdapter = {
|
|
382
|
+
id: "pi",
|
|
383
|
+
binaryName: "pi",
|
|
384
|
+
// Every environment credential Pi's providers recognize. Under `auth:
|
|
385
|
+
// "subscription"` these are removed so Pi bills its own `auth.json` login.
|
|
386
|
+
apiKeyEnvVars: [
|
|
387
|
+
"AI_GATEWAY_API_KEY",
|
|
388
|
+
"ANT_LING_API_KEY",
|
|
389
|
+
"ANTHROPIC_API_KEY",
|
|
390
|
+
"ANTHROPIC_AUTH_TOKEN",
|
|
391
|
+
"ANTHROPIC_OAUTH_TOKEN",
|
|
392
|
+
"AWS_ACCESS_KEY_ID",
|
|
393
|
+
"AWS_SECRET_ACCESS_KEY",
|
|
394
|
+
"AWS_SESSION_TOKEN",
|
|
395
|
+
"AZURE_OPENAI_API_KEY",
|
|
396
|
+
"BASETEN_API_KEY",
|
|
397
|
+
"CEREBRAS_API_KEY",
|
|
398
|
+
"CLOUDFLARE_API_KEY",
|
|
399
|
+
"COPILOT_GITHUB_TOKEN",
|
|
400
|
+
"DEEPSEEK_API_KEY",
|
|
401
|
+
"FIREWORKS_API_KEY",
|
|
402
|
+
"GEMINI_API_KEY",
|
|
403
|
+
"GOOGLE_API_KEY",
|
|
404
|
+
"GOOGLE_CLOUD_API_KEY",
|
|
405
|
+
"GROQ_API_KEY",
|
|
406
|
+
"HF_TOKEN",
|
|
407
|
+
"KIMI_API_KEY",
|
|
408
|
+
"META_API_KEY",
|
|
409
|
+
"MINIMAX_API_KEY",
|
|
410
|
+
"MINIMAX_CN_API_KEY",
|
|
411
|
+
"MISTRAL_API_KEY",
|
|
412
|
+
"MOONSHOT_API_KEY",
|
|
413
|
+
"NVIDIA_API_KEY",
|
|
414
|
+
"OPENAI_API_KEY",
|
|
415
|
+
"OPENCODE_API_KEY",
|
|
416
|
+
"OPENROUTER_API_KEY",
|
|
417
|
+
"QWEN_TOKEN_PLAN_API_KEY",
|
|
418
|
+
"QWEN_TOKEN_PLAN_CN_API_KEY",
|
|
419
|
+
"RADIUS_API_KEY",
|
|
420
|
+
"TOGETHER_API_KEY",
|
|
421
|
+
"XAI_API_KEY",
|
|
422
|
+
"XIAOMI_API_KEY",
|
|
423
|
+
"XIAOMI_TOKEN_PLAN_AMS_API_KEY",
|
|
424
|
+
"XIAOMI_TOKEN_PLAN_CN_API_KEY",
|
|
425
|
+
"XIAOMI_TOKEN_PLAN_SGP_API_KEY",
|
|
426
|
+
"ZAI_API_KEY",
|
|
427
|
+
"ZAI_CODING_CN_API_KEY"
|
|
428
|
+
],
|
|
429
|
+
// Pi uses its own `provider/id` model names; set one with localAgent({ model }).
|
|
430
|
+
modelAliases: {},
|
|
431
|
+
nativeSchema() {
|
|
432
|
+
return null;
|
|
433
|
+
},
|
|
434
|
+
buildInvocation(request, model) {
|
|
435
|
+
const args = [
|
|
436
|
+
"--mode",
|
|
437
|
+
"json",
|
|
438
|
+
"--no-session",
|
|
439
|
+
"--no-tools",
|
|
440
|
+
"--no-builtin-tools",
|
|
441
|
+
"--no-extensions",
|
|
442
|
+
"--no-skills",
|
|
443
|
+
"--no-prompt-templates",
|
|
444
|
+
"--no-themes",
|
|
445
|
+
"--no-context-files",
|
|
446
|
+
"--system-prompt",
|
|
447
|
+
SYSTEM_PROMPT,
|
|
448
|
+
"--offline"
|
|
449
|
+
];
|
|
450
|
+
if (model !== void 0) {
|
|
451
|
+
args.push("--model", model);
|
|
452
|
+
}
|
|
453
|
+
return { args, stdin: request.prompt };
|
|
454
|
+
},
|
|
455
|
+
readResult(result, request) {
|
|
456
|
+
const events = parseEvents(result.stdout);
|
|
457
|
+
const assistant = events.filter((event) => event.type === "message_end" && event.message?.role === "assistant").map((event) => event.message).pop();
|
|
458
|
+
if (assistant && (assistant.stopReason === "error" || assistant.errorMessage)) {
|
|
459
|
+
return failed((0, failure_classification_1.classifyAgentFailure)("pi", assistant.errorMessage ?? "pi stopped with an error"));
|
|
460
|
+
}
|
|
461
|
+
const retryFailed = events.find((event) => event.type === "auto_retry_end" && event.success === false);
|
|
462
|
+
if (retryFailed) {
|
|
463
|
+
return failed((0, failure_classification_1.classifyAgentFailure)("pi", retryFailed.finalError ?? "auto retry failed"));
|
|
464
|
+
}
|
|
465
|
+
if (!assistant) {
|
|
466
|
+
return failed((0, failure_classification_1.classifyAgentFailure)("pi", `exited with code ${result.exitCode} without a reply: ${(0, failure_classification_1.stderrTail)(result)}`));
|
|
467
|
+
}
|
|
468
|
+
const text = (assistant.content ?? []).filter((block) => block.type === "text").map((block) => block.text ?? "").join("");
|
|
469
|
+
const usage = assistant.usage ?? {};
|
|
470
|
+
const promptTokens = (usage.input ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);
|
|
471
|
+
const completionTokens = usage.output ?? 0;
|
|
472
|
+
const reported = {
|
|
473
|
+
usage: { promptTokens, completionTokens, totalTokens: promptTokens + completionTokens },
|
|
474
|
+
model: assistant.model,
|
|
475
|
+
costUsdEstimate: usage.cost?.total
|
|
476
|
+
};
|
|
477
|
+
if (request.enforcement.kind === "in-prompt") {
|
|
478
|
+
return { kind: "answered", answer: { kind: "text", text }, ...reported };
|
|
479
|
+
}
|
|
480
|
+
let envelope;
|
|
481
|
+
try {
|
|
482
|
+
envelope = JSON.parse(text);
|
|
483
|
+
} catch {
|
|
484
|
+
return failed({ kind: "transient", message: `pi reply is not JSON: ${text}` });
|
|
485
|
+
}
|
|
486
|
+
return { kind: "answered", answer: { kind: "structured", envelope }, ...reported };
|
|
487
|
+
},
|
|
488
|
+
// Pi has no provider-agnostic login check: `pi auth check` requires --provider
|
|
489
|
+
// or --model, and the provider differs per user (it is not known until Pi's
|
|
490
|
+
// settings are read). Report installed Pi as logged in; the first real call
|
|
491
|
+
// surfaces any auth error, which classifyAgentFailure marks fatal.
|
|
492
|
+
loginStatusArgs: ["--version"],
|
|
493
|
+
readLoginStatus(result) {
|
|
494
|
+
return {
|
|
495
|
+
loggedIn: result.exitCode === 0,
|
|
496
|
+
detail: "installed; auth is verified on the first call"
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
function failed(failure) {
|
|
501
|
+
return { kind: "failed", failure };
|
|
502
|
+
}
|
|
503
|
+
function parseEvents(stdout) {
|
|
504
|
+
const events = [];
|
|
505
|
+
for (const line of stdout.split("\n")) {
|
|
506
|
+
const trimmed = line.replace(/\r$/, "").trim();
|
|
507
|
+
if (!trimmed.startsWith("{"))
|
|
508
|
+
continue;
|
|
509
|
+
try {
|
|
510
|
+
const parsed = JSON.parse(trimmed);
|
|
511
|
+
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
512
|
+
events.push(parsed);
|
|
513
|
+
}
|
|
514
|
+
} catch {
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
return events;
|
|
518
|
+
}
|
|
519
|
+
return pi;
|
|
520
|
+
}
|
|
521
|
+
|
|
367
522
|
var hasRequiredAdapters;
|
|
368
523
|
function requireAdapters() {
|
|
369
524
|
if (hasRequiredAdapters) return adapters;
|
|
@@ -372,9 +527,11 @@ function requireAdapters() {
|
|
|
372
527
|
adapters.AGENT_ADAPTERS = void 0;
|
|
373
528
|
const claude_code_1 = requireClaudeCode();
|
|
374
529
|
const codex_1 = requireCodex();
|
|
530
|
+
const pi_1 = requirePi();
|
|
375
531
|
adapters.AGENT_ADAPTERS = {
|
|
376
532
|
"claude-code": claude_code_1.claudeCodeAdapter,
|
|
377
|
-
codex: codex_1.codexAdapter
|
|
533
|
+
codex: codex_1.codexAdapter,
|
|
534
|
+
pi: pi_1.piAdapter
|
|
378
535
|
};
|
|
379
536
|
return adapters;
|
|
380
537
|
}
|
|
@@ -389,7 +546,7 @@ function requireAgentId() {
|
|
|
389
546
|
Object.defineProperty(exports$1, "__esModule", { value: true });
|
|
390
547
|
exports$1.LOCAL_AGENT_IDS = void 0;
|
|
391
548
|
exports$1.isLocalAgentId = isLocalAgentId;
|
|
392
|
-
exports$1.LOCAL_AGENT_IDS = ["claude-code", "codex"];
|
|
549
|
+
exports$1.LOCAL_AGENT_IDS = ["claude-code", "codex", "pi"];
|
|
393
550
|
const LOCAL_AGENT_ID_SET = new Set(exports$1.LOCAL_AGENT_IDS);
|
|
394
551
|
function isLocalAgentId(value) {
|
|
395
552
|
return typeof value === "string" && LOCAL_AGENT_ID_SET.has(value);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/** Supported coding-agent CLIs, in the order findLocalAgent() tries them. */
|
|
2
|
-
export declare const LOCAL_AGENT_IDS: readonly ["claude-code", "codex"];
|
|
2
|
+
export declare const LOCAL_AGENT_IDS: readonly ["claude-code", "codex", "pi"];
|
|
3
3
|
export type LocalAgentId = (typeof LOCAL_AGENT_IDS)[number];
|
|
4
4
|
export declare function isLocalAgentId(value: unknown): value is LocalAgentId;
|
package/package.json
CHANGED