@cortexkit/pi-anthropic-auth 1.22.0 → 2.0.0
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 +60 -54
- package/dist/commands.d.ts +23 -2
- package/dist/commands.js +58 -238
- package/dist/convert.d.ts +5 -0
- package/dist/convert.js +152 -38
- package/dist/custody.d.ts +13 -0
- package/dist/custody.js +33 -0
- package/dist/effort-history.d.ts +15 -0
- package/dist/effort-history.js +40 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +188 -37
- package/dist/native-commands.d.ts +2 -0
- package/dist/native-commands.js +347 -0
- package/dist/native.d.ts +71 -0
- package/dist/native.js +308 -0
- package/dist/paths.d.ts +13 -0
- package/dist/paths.js +48 -2
- package/dist/stream.d.ts +17 -1
- package/dist/stream.js +609 -243
- package/dist/transcript.d.ts +19 -0
- package/dist/transcript.js +122 -0
- package/dist/transport.d.ts +5 -0
- package/dist/transport.js +30 -0
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,109 +1,115 @@
|
|
|
1
1
|
# @cortexkit/pi-anthropic-auth
|
|
2
2
|
|
|
3
|
-
Pi package for CortexKit Anthropic OAuth support. It
|
|
3
|
+
Pi package for CortexKit Anthropic OAuth support. It replaces the implementation of Pi's built-in Anthropic provider, keeping the `anthropic` provider ID and model IDs, and is backed by the shared `@cortexkit/anthropic-auth-core` package.
|
|
4
4
|
|
|
5
|
-
The Pi provider catalog includes Claude Fable 5 (`claude-fable-5`) and 5.1 (`claude-fable-5-1`), limited-access Claude Mythos 5 (`claude-mythos-5`) and 5.1 (`claude-mythos-5-1`), Claude Opus 5 (`claude-opus-5`), Claude Opus 4.8, Claude Opus 4.5, Claude Sonnet 4.5, and Claude Sonnet 5 (`claude-sonnet-5`). Fable/Mythos reasoning uses Anthropic adaptive thinking with `thinking.display: "summarized"` and `output_config.effort`; the package does not send rejected manual `thinking.budget_tokens` for those models.
|
|
5
|
+
The Pi provider catalog includes Claude Fable 5 (`claude-fable-5`) and 5.1 (`claude-fable-5-1`), limited-access Claude Mythos 5 (`claude-mythos-5`) and 5.1 (`claude-mythos-5-1`), Claude Opus 5 (`claude-opus-5`), Claude Opus 5.5 (`claude-opus-5-5`), Claude Haiku 5.5 (`claude-haiku-5-5`), Claude Opus 4.8, Claude Opus 4.5, Claude Sonnet 4.5, Claude Sonnet 5 (`claude-sonnet-5`), and Claude Sonnet 5.5 (`claude-sonnet-5-5`). Fable/Mythos reasoning uses Anthropic adaptive thinking with `thinking.display: "summarized"` and `output_config.effort`; the package does not send rejected manual `thinking.budget_tokens` for those models. Opus 5.5 requires adaptive thinking, while Sonnet 5.5 also supports a `between_tools` mode for applications that explicitly turn off up-front thinking. This Pi provider sends adaptive thinking with summarized display for both models. For Sonnet 5.5 it exposes `low` through `max` effort, but not `minimal` (unsupported by the model) or `off` (Pi's simple-provider options cannot request `between_tools`). OAuth Fable 5.1 sessions add effort changes as system messages instead of rewriting earlier history, preserving cached prompt content.
|
|
6
|
+
|
|
7
|
+
Replayed thinking signatures refer to the messages, instructions and tools that preceded the thinking block. If those earlier inputs change, `thinkingBinding.prefixMismatchBehavior` controls how OAuth Fable 5.1, Opus 5.5, Sonnet 5.5 and Haiku 5.5 requests handle that mismatch: `account-default` sends no local override and uses Anthropic's account settings; `error` rejects the request; `drop_block` removes the affected thinking blocks. These controls require adaptive thinking.
|
|
8
|
+
|
|
9
|
+
Haiku 5.5 has a 1M context, 128K output and summarized adaptive thinking with `low` through `max` effort. Haiku 5.5 does not support `minimal` effort. The model accepts disabled thinking, but Pi's simple-provider options cannot request it, so Pi does not expose an `off` level. Standard input/output rates are $0.10/$0.50 per million tokens; all rates increase fivefold above 100K total input including cache. Pi's native pricing tiers apply the selected rates to the whole request, including both cache lifetimes.
|
|
6
10
|
|
|
7
11
|
This package is part of the CortexKit Anthropic Auth monorepo, which supports both OpenCode (`@cortexkit/opencode-anthropic-auth`) and Pi (`@cortexkit/pi-anthropic-auth`) through the same shared core logic.
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
> [!IMPORTANT]
|
|
14
|
+
> These instructions describe the upcoming native release, which is not yet published.
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
## Setup (recommended)
|
|
17
|
+
|
|
18
|
+
Setup is an *offline* step: every OpenCode, LiteCode, and Pi process must be closed while it runs. Offline does not mean without network; setup still uses the network, for example to install packages and to sign in to Claude. Quit those processes, then run the setup command from the OpenCode package:
|
|
12
19
|
|
|
13
20
|
```bash
|
|
14
|
-
|
|
21
|
+
bunx @cortexkit/opencode-anthropic-auth setup
|
|
15
22
|
```
|
|
16
23
|
|
|
17
|
-
|
|
24
|
+
What setup does: it installs this extension with `pi install` and migrates Pi to its local account pool, or, if you choose it, enrolls Pi in the Claustrum vault (Claustrum is a local credential-vault service; `ck` is its command-line tool). Useful flags: `--yes` (no prompts), `--dry-run`, `--login` (sign in to Claude during setup), `--claustrum` / `--no-claustrum`, and `--remove-pi-auth` (consent, with `--yes`, to moving Pi's stored Anthropic login). `--login` and `--claustrum` cannot be combined.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
Install with Pi's package manager:
|
|
18
31
|
|
|
19
32
|
```bash
|
|
20
33
|
pi install npm:@cortexkit/pi-anthropic-auth
|
|
21
34
|
```
|
|
22
35
|
|
|
36
|
+
To pin a release, replace `VERSION` with its version number and keep the quotes: `pi install "npm:@cortexkit/pi-anthropic-auth@VERSION"`.
|
|
37
|
+
|
|
23
38
|
To try it for one run without changing Pi settings:
|
|
24
39
|
|
|
25
40
|
```bash
|
|
26
41
|
pi -e npm:@cortexkit/pi-anthropic-auth
|
|
27
42
|
```
|
|
28
43
|
|
|
29
|
-
|
|
44
|
+
The extension keeps Pi's `anthropic` provider ID and the model IDs listed above. It authenticates from the local account pool or the Claustrum vault, not from Pi's `/login anthropic` credential. Run setup before starting Pi.
|
|
30
45
|
|
|
31
|
-
|
|
32
|
-
/login anthropic
|
|
33
|
-
```
|
|
46
|
+
## Accounts and custody
|
|
34
47
|
|
|
35
|
-
|
|
48
|
+
Pi takes Claude credentials from one source, selected by Pi's own Claustrum enrollment record (`~/.local/state/cortexkit/anthropic-auth/pi-enrollment.json`, or `PI_ANTHROPIC_AUTH_CLAUSTRUM_ENROLLMENT_FILE`):
|
|
36
49
|
|
|
37
|
-
|
|
50
|
+
- **Local custody** (default): the local account pool at `~/.pi/agent/anthropic-auth-pool.json`, with private credential state in `anthropic-auth-pool-state.json`. The pool holds Pi's Claude OAuth accounts (one main account, tried first by default, plus fallbacks) and API-key fallback routes. Its files are created next to the old sidecar path, so `PI_ANTHROPIC_AUTH_FILE` moves them too. Every Pi process shares this pool; OpenCode keeps a separate one.
|
|
51
|
+
- **Vault custody**: the Claustrum vault, through the `anthropic-auth-pi` enrollment and read access to the `anthropic-native` credential category. Setup grants this with `ck auth grant --principal enrolled:anthropic-auth-pi --selector-kind category --selector anthropic-native --operation read`.
|
|
38
52
|
|
|
39
|
-
|
|
40
|
-
~/.pi/agent/anthropic-auth.json
|
|
41
|
-
```
|
|
53
|
+
If the enrollment record cannot be read, Pi refuses the requests this extension would serve until the record is repaired or Pi is disconnected. An approved enrollment keeps Pi on the vault even if its token file is missing, so Pi refuses rather than falling back to local accounts. See [the custody contract](https://github.com/cortexkit/anthropic-auth/blob/main/docs/custody-state-machine.md) for details.
|
|
42
54
|
|
|
43
|
-
|
|
55
|
+
### Local custody
|
|
44
56
|
|
|
45
|
-
|
|
57
|
+
Setup imports your fallback Claude OAuth accounts, paid API-key fallback routes, and settings from the old sidecar file (`~/.pi/agent/anthropic-auth.json`, or `PI_ANTHROPIC_AUTH_FILE`) into the pool; the old file is not read afterwards. Pi normally uses its stored login instead of the extension's credentials, so with your consent setup also moves Pi's stored Anthropic OAuth login into the pool as the main account. Until then, Pi refuses to serve with `Pi still has a host Anthropic OAuth credential. Run offline setup to migrate it and approve its removal before using the native pool.`
|
|
46
58
|
|
|
47
|
-
|
|
59
|
+
Before importing a stored main OAuth login, migration checks the Claude account UUID in the legacy main profile. That profile's recorded token fingerprint (a hash) must match the hash of the host login's current access token; migration does not query Anthropic for identity. If it cannot, it changes nothing and asks you to run `bunx @cortexkit/opencode-anthropic-auth setup --login --no-claustrum`. After setup completes, you can add or replace logins from Pi: open `/claude` and use **Start OAuth sign-in** and **Finish OAuth sign-in**. The first account becomes the main account; later sign-ins add fallback accounts.
|
|
48
60
|
|
|
49
|
-
|
|
50
|
-
/claude-cache
|
|
51
|
-
/claude-cache on
|
|
52
|
-
/claude-cache off
|
|
53
|
-
/claude-cache mode explicit
|
|
54
|
-
/claude-cache mode automatic
|
|
55
|
-
/claude-cache mode hybrid
|
|
61
|
+
### Vault custody
|
|
56
62
|
|
|
57
|
-
/
|
|
58
|
-
/claude-cachekeep always
|
|
59
|
-
/claude-cachekeep 09-23
|
|
60
|
-
/claude-cachekeep off
|
|
63
|
+
Run `bunx @cortexkit/opencode-anthropic-auth setup --claustrum` with the Claustrum daemon running and `ck` installed. Setup writes Pi's enrollment and, with your consent, Pi's auth file. It does not read, import, or change the local pool, its metadata, or routing assignments, and it never copies local OAuth accounts into the vault. If Pi has a stored Anthropic login (OAuth or API key), setup asks for consent, moves it into a private, owner-only stash (`pi-auth-slot/anthropic.json` in the directory of Pi's enrollment record), and leaves an inert placeholder API key in Pi's auth file. The placeholder is a fixed, non-secret value that no provider accepts.
|
|
61
64
|
|
|
62
|
-
|
|
63
|
-
/claude-prime on
|
|
64
|
-
/claude-prime off
|
|
65
|
+
While enrolled, Pi serves only vault accounts; vault accounts added with `ck auth login --provider anthropic` are discovered without a restart. Local accounts are not used, refreshed, quota-polled, kept warm by cache keepalive, or shown, and they return unchanged after disconnect. If the vault has no usable Claude account, requests refuse: add accounts with `ck auth login --provider anthropic`, or disconnect.
|
|
65
66
|
|
|
66
|
-
|
|
67
|
-
/claude-dump on
|
|
68
|
-
/claude-dump off
|
|
67
|
+
**Disconnect from the vault** in `/claude` asks for confirmation, restores the stashed login byte-for-byte, then ends Pi's enrollment. If Pi's auth file already holds a different login, disconnect stops and keeps both logins and the enrollment so you can resolve them with setup. **Disconnect from the vault** is also offered when the enrollment record cannot be read. If the local pool has never been migrated, stop the hosts and run `setup --no-claustrum` before serving local accounts; disconnect does not perform migration.
|
|
69
68
|
|
|
70
|
-
|
|
71
|
-
/claude-fast on
|
|
72
|
-
/claude-fast off
|
|
69
|
+
## Settings
|
|
73
70
|
|
|
74
|
-
|
|
75
|
-
/claude-routing main-first
|
|
76
|
-
/claude-routing fallback-first
|
|
77
|
-
/claude-routing sticky-balanced
|
|
78
|
-
/claude-routing reset
|
|
71
|
+
The pool stores the same settings as the OpenCode package: `routing`, `claudeCache`, `cacheKeep`, `prime`, `claudeFast`, `thinkingBinding`, `dump`, `relay`, and the fallback accounts. While Pi is enrolled in the vault, settings are kept separately in `anthropic-auth-vault-settings.json`. `thinkingBinding.prefixMismatchBehavior` accepts `account-default` (default), `error`, or `drop_block` when a Fable 5.1 OAuth request reuses reasoning with an Anthropic signature from an earlier reply after the preceding messages, instructions, or tools change. Sticky session assignments are stored in `anthropic-auth-pool-routing-state.json` (`anthropic-auth-vault-routing-state.json` while enrolled) with SHA-256-hashed session IDs.
|
|
79
72
|
|
|
80
|
-
/claude
|
|
81
|
-
/claude-account reset-backoff
|
|
73
|
+
## The /claude menu
|
|
82
74
|
|
|
83
|
-
|
|
84
|
-
```
|
|
75
|
+
Pi registers one command, `/claude`. It opens a menu; each action collects its own parameters, and typed arguments are rejected with a pointer to the menu. Without a UI, `/claude` prints the status sections only.
|
|
85
76
|
|
|
86
|
-
|
|
77
|
+
| Group | Status | Actions |
|
|
78
|
+
| --- | --- | --- |
|
|
79
|
+
| Accounts | Account status and usage | Enable account, Disable account, Remove account, Move account up, Move account down, Reset account backoff, Reset host enrollment, Add API-key fallback, Start OAuth sign-in, Finish OAuth sign-in, Custody setup guidance, Disconnect from the vault |
|
|
80
|
+
| Quota | Quota summary | — |
|
|
81
|
+
| Routing | Routing status | Routing mode (`main-first`, `fallback-first`, `sticky-balanced`), Reset routing session |
|
|
82
|
+
| Cache | Cache status, Cache keep status | Enable cache, Disable cache, Cache mode (`explicit`, `automatic`, `hybrid`), Keep cache warm always, Disable cache keep, Cache keep window, Cache keep for subagents (`on`/`off`) |
|
|
83
|
+
| Diagnostics | Dump status, Logging status | Enable request dumps, Disable request dumps, Logging level (`error`, `warn`, `info`, `debug`, `trace`) |
|
|
84
|
+
| Extras | Fast mode status, Prime quota window status | Enable fast mode, Disable fast mode |
|
|
85
|
+
|
|
86
|
+
In local custody, every Accounts action except **Disconnect from the vault** is offered. While Pi is enrolled, or when its enrollment cannot be read, the Accounts group shows only enable, disable, **Reset account backoff**, and **Disconnect from the vault**. **Remove account**, **Reset host enrollment**, and **Disconnect from the vault** ask for confirmation. Killswitch, quota refresh, Prime on/off, and lane start are OpenCode-only.
|
|
87
|
+
|
|
88
|
+
**Reset account backoff** clears the main OAuth refresh backoff and its matching quota backoff. Persisted refresh backoffs are bound to the refresh token that produced them, so replacing a rejected credential immediately clears the backoff left by the old refresh token. **Quota summary** reports quota for the accounts of the active custody source. **Routing mode** → `fallback-first` prefers usable OAuth fallback accounts before the main account; `main-first` restores the default. `sticky-balanced` assigns each Pi session to an OAuth account according to current 5-hour, 7-day, and model-specific quota headroom, then keeps the session on that account (session affinity), persisting the assignment across transient failures and process restarts. Changing the session model discards the old assignment before quota-based reselection. **Reset routing session** clears the current Pi session's assignment. Direct Opus sessions prefer usable accounts whose Fable quota (the separate weekly limit for Claude Fable models) is exhausted, saving the other accounts for Fable sessions. API-key routes are sent directly to their configured Anthropic-compatible base URL, such as Kie's `https://api.kie.ai/claude`, but Pi only uses them after the main OAuth model response reports HTTP 429 or a streaming rate-limit error and a live quota check confirms 0% remaining. **Keep cache warm always** keeps active hybrid caches warm while Pi remains open; **Cache keep window** limits prewarms to a local time window. Both send `max_tokens: 0` pre-warm requests about five minutes before the 1-hour TTL expires. **Cache keep status** lists live tracked sessions across Pi processes through a temporary lease registry that stores only session IDs and cache timing. **Enable fast mode** adds Anthropic `speed: "fast"` plus the `fast-mode-2026-02-01` beta header for supported Opus models (`claude-opus-4-8`, `claude-opus-5`, and `claude-opus-5-5`).
|
|
87
89
|
|
|
88
90
|
### Claude quota window priming
|
|
89
91
|
|
|
90
|
-
Priming is off by default. When enabled from OpenCode
|
|
92
|
+
Priming is off by default. When enabled from OpenCode's `/claude` menu with **Enable Prime**, it watches each OAuth account's 5-hour quota reset and sends one minimal `claude-haiku-4-5` request about one minute after a confirmed reset. This starts the next window without waiting for a normal prompt. Usage is measured from response accounting.
|
|
93
|
+
|
|
94
|
+
For an idle account with no cached reset time, one minimal request starts a usage window; the follow-up quota check learns its reset time. When several processes share an account store, each tries to create a claim file for that account and reset; creating the file is atomic, so exactly one process succeeds and sends the request.
|
|
95
|
+
|
|
96
|
+
Claim files live in a temporary directory, separated by account store and credential lineage. Cleanup removes files older than six hours. Ordinary token refresh keeps the lineage; a new sign-in starts a new one. Private runtime state stores cumulative priming usage counters, not a history of primed windows. Legacy claim files are not migrated. Without the old claim, the new scheduler can treat an already primed window as unclaimed and send one extra request.
|
|
91
97
|
|
|
92
|
-
|
|
98
|
+
Pi's menu shows **Prime quota window status** only; turn priming on or off with **Enable Prime** or **Disable Prime** in OpenCode's `/claude` menu.
|
|
93
99
|
|
|
94
|
-
|
|
100
|
+
## Anthropic-compatible proxy overrides
|
|
95
101
|
|
|
96
|
-
|
|
102
|
+
API-key fallback routes honor `ANTHROPIC_CUSTOM_HEADERS`, `ANTHROPIC_MODEL`, and `ANTHROPIC_DEFAULT_{SONNET,OPUS,HAIKU,FABLE}_MODEL`. These variables never alter OAuth requests. Custom headers may add proxy metadata but cannot replace route authentication, Anthropic protocol headers, body framing, or internal correlation headers; a configuration containing an invalid or protected header is ignored as a whole. Versioned provider base paths are preserved without duplicating `/v1`.
|
|
97
103
|
|
|
98
104
|
## Relay
|
|
99
105
|
|
|
100
|
-
The Pi package can use
|
|
106
|
+
The Pi package can use a user-owned Cloudflare relay over HTTP or WebSocket transport. When setup migrates Pi, it imports an existing `relay` block from Pi's old sidecar file (`~/.pi/agent/anthropic-auth.json`, or `PI_ANTHROPIC_AUTH_FILE`). The relay setup helper in the OpenCode package CLI provisions a Worker and saves its settings in OpenCode's local account pool; it does not configure Pi:
|
|
101
107
|
|
|
102
108
|
```bash
|
|
103
109
|
CLOUDFLARE_API_TOKEN=... CLOUDFLARE_ACCOUNT_ID=... bunx @cortexkit/opencode-anthropic-auth relay setup
|
|
104
110
|
```
|
|
105
111
|
|
|
106
|
-
|
|
112
|
+
The `/claude` menu has no relay actions.
|
|
107
113
|
|
|
108
114
|
## License
|
|
109
115
|
|
package/dist/commands.d.ts
CHANGED
|
@@ -1,2 +1,23 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
1
|
+
import { type NativeMenuCommandId, type NativeMenuDispatch, type NativeUiOptions } from '@cortexkit/anthropic-auth-core';
|
|
2
|
+
import { type ExtensionAPI } from '@earendil-works/pi-coding-agent';
|
|
3
|
+
/** Backend callbacks use native authority; the renderer never receives credentials. */
|
|
4
|
+
export interface PiNativeCommands {
|
|
5
|
+
dispatch: NativeMenuDispatch;
|
|
6
|
+
readStatus: (command: Exclude<NativeMenuCommandId, 'start'>, invocation: {
|
|
7
|
+
sessionId?: string;
|
|
8
|
+
}) => Promise<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Reads Pi's credential custody for each menu open and apply. When left
|
|
11
|
+
* out, the enrollment record the environment points to is read; there is
|
|
12
|
+
* no local fallback.
|
|
13
|
+
*/
|
|
14
|
+
readMode?: NativeUiOptions['readMode'];
|
|
15
|
+
readAccounts?: NativeUiOptions['readAccounts'];
|
|
16
|
+
/**
|
|
17
|
+
* Disconnects Pi from the vault. When left out, Core first restores the
|
|
18
|
+
* Anthropic sign-in that enrollment set aside in Pi's own auth file, then
|
|
19
|
+
* ends Pi's enrollment.
|
|
20
|
+
*/
|
|
21
|
+
disconnectVault?: NativeUiOptions['disconnectVault'];
|
|
22
|
+
}
|
|
23
|
+
export declare function registerCommands(pi: ExtensionAPI, backend: PiNativeCommands): void;
|
package/dist/commands.js
CHANGED
|
@@ -1,247 +1,67 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
: enabled;
|
|
21
|
-
const nextMode = action.type === 'mode' ? action.mode : mode;
|
|
22
|
-
if (action.type === 'enable') {
|
|
23
|
-
await setCache1hPersistentEnabled(true, undefined, path);
|
|
24
|
-
}
|
|
25
|
-
else if (action.type === 'disable') {
|
|
26
|
-
await setCache1hPersistentEnabled(false, undefined, path);
|
|
27
|
-
}
|
|
28
|
-
else if (action.type === 'mode') {
|
|
29
|
-
await setCache1hPersistentMode(action.mode, path);
|
|
30
|
-
}
|
|
31
|
-
notify(ctx, executeCache1hCommand({
|
|
32
|
-
argumentsText: args ?? '',
|
|
33
|
-
enabled: nextEnabled,
|
|
34
|
-
mode: nextMode,
|
|
35
|
-
}), action.type === 'usage' ? 'warning' : 'info');
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
pi.registerCommand(CLAUDE_CACHE_KEEP_COMMAND_NAME, {
|
|
39
|
-
description: 'Keep hybrid Claude cache warm always or during a local time window',
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { createNativeUi, disconnectNativeVaultForHost, openNativePiAuthSlot, readNativeEnrollmentMode, runPiCommandMenu, } from '@cortexkit/anthropic-auth-core';
|
|
3
|
+
import { getAgentDir } from '@earendil-works/pi-coding-agent';
|
|
4
|
+
/**
|
|
5
|
+
* Pi's default disconnect. The auth file is the one Pi's SDK uses
|
|
6
|
+
* (getAgentDir() honours PI_CODING_AGENT_DIR); Core chooses the private
|
|
7
|
+
* stash and placeholder, so setup and disconnect always agree on them.
|
|
8
|
+
*/
|
|
9
|
+
const disconnectPi = () => disconnectNativeVaultForHost({
|
|
10
|
+
host: 'pi',
|
|
11
|
+
env: process.env,
|
|
12
|
+
slot: openNativePiAuthSlot({
|
|
13
|
+
env: process.env,
|
|
14
|
+
authPath: join(getAgentDir(), 'auth.json'),
|
|
15
|
+
}),
|
|
16
|
+
});
|
|
17
|
+
export function registerCommands(pi, backend) {
|
|
18
|
+
pi.registerCommand('claude', {
|
|
19
|
+
description: 'Claude accounts, quota, routing, limits, cache and diagnostics',
|
|
40
20
|
handler: async (args, ctx) => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const action = parseCacheKeepCommandAction(args ?? '');
|
|
44
|
-
if (action.type === 'window') {
|
|
45
|
-
storage = await setCacheKeepPersistentWindow(action.startHour, action.endHour, path);
|
|
46
|
-
}
|
|
47
|
-
else if (action.type === 'always') {
|
|
48
|
-
storage = await setCacheKeepPersistentAlways(path);
|
|
49
|
-
}
|
|
50
|
-
else if (action.type === 'disable') {
|
|
51
|
-
storage = await setCacheKeepPersistentEnabled(false, path);
|
|
52
|
-
}
|
|
53
|
-
else if (action.type === 'subagents') {
|
|
54
|
-
storage = await setCacheKeepSubagentsEnabled(action.enabled, path);
|
|
55
|
-
}
|
|
56
|
-
const trackedSessionDetails = await getPiTrackedCacheKeepSessions();
|
|
57
|
-
const nextPrewarmAt = trackedSessionDetails.length
|
|
58
|
-
? Math.min(...trackedSessionDetails.map((session) => session.nextPrewarmAt))
|
|
59
|
-
: undefined;
|
|
60
|
-
notify(ctx, executeCacheKeepCommand({
|
|
61
|
-
argumentsText: args ?? '',
|
|
62
|
-
enabled: isCacheKeepPersistentlyEnabled(storage),
|
|
63
|
-
always: isCacheKeepAlways(storage),
|
|
64
|
-
window: getCacheKeepWindow(storage),
|
|
65
|
-
hybridActive: isCacheKeepHybridActive(storage),
|
|
66
|
-
trackedSessions: trackedSessionDetails.length,
|
|
67
|
-
trackedSessionDetails,
|
|
68
|
-
nextPrewarmAt,
|
|
69
|
-
}), action.type === 'usage' ? 'warning' : 'info');
|
|
70
|
-
},
|
|
71
|
-
});
|
|
72
|
-
pi.registerCommand('claude-dump', {
|
|
73
|
-
description: 'Show or configure Anthropic request/relay dumping',
|
|
74
|
-
handler: async (args, ctx) => {
|
|
75
|
-
const path = getPiAccountStoragePath();
|
|
76
|
-
const storage = await loadAccounts(path);
|
|
77
|
-
const action = parseDumpCommandAction(args ?? '');
|
|
78
|
-
const enabled = isDumpPersistentlyEnabled(storage);
|
|
79
|
-
const nextEnabled = action.type === 'enable'
|
|
80
|
-
? true
|
|
81
|
-
: action.type === 'disable'
|
|
82
|
-
? false
|
|
83
|
-
: enabled;
|
|
84
|
-
if (action.type === 'enable') {
|
|
85
|
-
await setDumpPersistentEnabled(true, path);
|
|
86
|
-
setDumpEnabled(true);
|
|
87
|
-
}
|
|
88
|
-
else if (action.type === 'disable') {
|
|
89
|
-
await setDumpPersistentEnabled(false, path);
|
|
90
|
-
setDumpEnabled(false);
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
setDumpEnabled(enabled);
|
|
94
|
-
}
|
|
95
|
-
notify(ctx, executeDumpCommand({ argumentsText: args ?? '', enabled: nextEnabled }), action.type === 'usage' ? 'warning' : 'info');
|
|
96
|
-
},
|
|
97
|
-
});
|
|
98
|
-
pi.registerCommand('claude-fast', {
|
|
99
|
-
description: 'Show or configure Anthropic fast mode for supported Opus models',
|
|
100
|
-
handler: async (args, ctx) => {
|
|
101
|
-
const path = getPiAccountStoragePath();
|
|
102
|
-
const storage = await loadAccounts(path);
|
|
103
|
-
const action = parseFastModeCommandAction(args ?? '');
|
|
104
|
-
const enabled = isFastModePersistentlyEnabled(storage);
|
|
105
|
-
const nextEnabled = action.type === 'enable'
|
|
106
|
-
? true
|
|
107
|
-
: action.type === 'disable'
|
|
108
|
-
? false
|
|
109
|
-
: enabled;
|
|
110
|
-
if (action.type === 'enable') {
|
|
111
|
-
await setFastModePersistentEnabled(true, path);
|
|
112
|
-
}
|
|
113
|
-
else if (action.type === 'disable') {
|
|
114
|
-
await setFastModePersistentEnabled(false, path);
|
|
115
|
-
}
|
|
116
|
-
notify(ctx, executeFastModeCommand({
|
|
117
|
-
argumentsText: args ?? '',
|
|
118
|
-
enabled: nextEnabled,
|
|
119
|
-
}), action.type === 'usage' ? 'warning' : 'info');
|
|
120
|
-
},
|
|
121
|
-
});
|
|
122
|
-
pi.registerCommand(CLAUDE_ROUTING_COMMAND_NAME, {
|
|
123
|
-
description: 'Show or change Claude account routing mode',
|
|
124
|
-
handler: async (args, ctx) => {
|
|
125
|
-
const path = getPiAccountStoragePath();
|
|
126
|
-
let storage = await loadAccounts(path);
|
|
127
|
-
const action = parseRoutingCommandAction(args ?? '');
|
|
128
|
-
if (action.type === 'mode') {
|
|
129
|
-
storage = await setRoutingMode(action.mode, path);
|
|
130
|
-
}
|
|
131
|
-
else if (action.type === 'reset') {
|
|
132
|
-
await clearPiStickyRoutingSession(path, ctx.sessionManager.getSessionId());
|
|
133
|
-
}
|
|
134
|
-
notify(ctx, executeRoutingCommand({
|
|
135
|
-
argumentsText: args ?? '',
|
|
136
|
-
mode: getRoutingMode(storage),
|
|
137
|
-
}), action.type === 'usage' ? 'warning' : 'info');
|
|
138
|
-
},
|
|
139
|
-
});
|
|
140
|
-
pi.registerCommand('claude-quota', {
|
|
141
|
-
description: 'Show Claude quota state for fallback accounts',
|
|
142
|
-
handler: async (_args, ctx) => {
|
|
143
|
-
const storage = await loadAccounts(getPiAccountStoragePath());
|
|
144
|
-
notify(ctx, buildClaudeQuotaSummary({
|
|
145
|
-
accounts: buildFallbackQuotaSummaries(storage),
|
|
146
|
-
now: Date.now(),
|
|
147
|
-
}));
|
|
148
|
-
},
|
|
149
|
-
});
|
|
150
|
-
pi.registerCommand(CLAUDE_ACCOUNT_COMMAND_NAME, {
|
|
151
|
-
description: 'List, enable/disable, reorder, or remove fallback accounts',
|
|
152
|
-
handler: async (args, ctx) => {
|
|
153
|
-
const path = getPiAccountStoragePath();
|
|
154
|
-
const storage = await loadAccounts(path);
|
|
155
|
-
const action = parseAccountCommandAction(args ?? '');
|
|
156
|
-
const result = executeAccountCommand({
|
|
157
|
-
argumentsText: args ?? '',
|
|
158
|
-
storage: storage ?? createEmptyStorage(),
|
|
159
|
-
claustrum: action.type === 'status'
|
|
160
|
-
? await detectClaustrumConnection()
|
|
161
|
-
: undefined,
|
|
162
|
-
});
|
|
163
|
-
if (!result.updated) {
|
|
164
|
-
notify(ctx, result.text);
|
|
21
|
+
if (args?.trim()) {
|
|
22
|
+
ctx.ui.notify('Use /claude to open the menu. Action parameters are collected in the selected action; custody changes require offline setup.', 'warning');
|
|
165
23
|
return;
|
|
166
24
|
}
|
|
167
|
-
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
25
|
+
const disconnect = backend.disconnectVault ?? disconnectPi;
|
|
26
|
+
const menu = createNativeUi({
|
|
27
|
+
host: 'pi',
|
|
28
|
+
dispatch: backend.dispatch,
|
|
29
|
+
readStatus: backend.readStatus,
|
|
30
|
+
readAccounts: backend.readAccounts,
|
|
31
|
+
readMode: backend.readMode ??
|
|
32
|
+
(() => readNativeEnrollmentMode('pi', process.env)),
|
|
33
|
+
disconnectVault: async (options) => {
|
|
34
|
+
const result = await disconnect(options);
|
|
35
|
+
// Reload after successful or already-inactive enrollment so Pi sees
|
|
36
|
+
// any restored sign-in. Reload failure cannot undo the completed
|
|
37
|
+
// disconnect, so report it separately without exposing the exception.
|
|
38
|
+
if (result === 'disconnected' || result === 'idle') {
|
|
39
|
+
try {
|
|
40
|
+
await ctx.modelRegistry.refresh();
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
ctx.ui.notify('Vault enrollment is inactive, but Pi could not reload its saved sign-in. Restart Pi before sending another request.', 'error');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
},
|
|
48
|
+
interactive: ctx.hasUI,
|
|
49
|
+
});
|
|
50
|
+
const sessionId = ctx.sessionManager.getSessionId();
|
|
51
|
+
if (ctx.hasUI) {
|
|
52
|
+
await runPiCommandMenu(menu, ctx.ui, { sessionId });
|
|
187
53
|
}
|
|
188
|
-
else
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
const mainIdentity = nextStorage.mainAccountId;
|
|
195
|
-
const quotaError = nextStorage.quota?.mainLastQuotaApiError;
|
|
196
|
-
if (!quotaError?.accountIdentity ||
|
|
197
|
-
!mainIdentity ||
|
|
198
|
-
quotaError.accountIdentity === mainIdentity) {
|
|
199
|
-
nextStorage.quota = nextStorage.quota ?? {};
|
|
200
|
-
nextStorage.quota.mainLastQuotaApiError = undefined;
|
|
201
|
-
const nextQuotaErrorGeneration = (nextStorage.quota.mainQuotaErrorGeneration ?? 0) + 1;
|
|
202
|
-
nextStorage.quota.mainQuotaErrorGeneration = Math.max(nextStorage.quota.mainQuotaErrorGeneration ?? 0, nextQuotaErrorGeneration);
|
|
203
|
-
nextStorage.quota.mainQuotaErrorClearedAt =
|
|
204
|
-
mergeMainQuotaErrorClearedAt(nextStorage.quota.mainQuotaErrorClearedAt, Date.now());
|
|
205
|
-
}
|
|
206
|
-
await saveAccountState(nextStorage, path, {
|
|
207
|
-
mainRefresh: true,
|
|
208
|
-
mainQuota: true,
|
|
54
|
+
else {
|
|
55
|
+
// A scripted invocation can inspect status, but cannot answer prompts or
|
|
56
|
+
// silently confirm a destructive action.
|
|
57
|
+
const payload = await menu.open({
|
|
58
|
+
sessionId,
|
|
59
|
+
notify: (message, kind) => ctx.ui.notify(message, kind),
|
|
209
60
|
});
|
|
61
|
+
ctx.ui.notify(payload.menu.sections
|
|
62
|
+
.map((section) => `${section.title}\n${section.lines.join('\n')}`)
|
|
63
|
+
.join('\n\n'), 'info');
|
|
210
64
|
}
|
|
211
|
-
notify(ctx, result.text);
|
|
212
|
-
},
|
|
213
|
-
});
|
|
214
|
-
pi.registerCommand('claude-logging', {
|
|
215
|
-
description: 'Show or set the plugin log level',
|
|
216
|
-
handler: async (args, ctx) => {
|
|
217
|
-
const path = getPiAccountStoragePath();
|
|
218
|
-
const storage = await loadAccounts(path);
|
|
219
|
-
const action = parseLoggingCommandAction(args ?? '');
|
|
220
|
-
const currentLevel = getPersistedLogLevel(storage) ?? 'info';
|
|
221
|
-
// Wire persistent log-level mutation
|
|
222
|
-
let level = currentLevel;
|
|
223
|
-
if (action.type === 'level') {
|
|
224
|
-
await setLogLevelPersistent(action.level, path);
|
|
225
|
-
level = action.level;
|
|
226
|
-
}
|
|
227
|
-
notify(ctx, executeLoggingCommand({ argumentsText: args ?? '', level }));
|
|
228
|
-
},
|
|
229
|
-
});
|
|
230
|
-
pi.registerCommand(CLAUDE_PRIME_COMMAND_NAME, {
|
|
231
|
-
description: "Show each OAuth account's five-hour quota window state",
|
|
232
|
-
handler: async (_args, ctx) => {
|
|
233
|
-
// Pi has no live PrimeManager; render persisted counters and the
|
|
234
|
-
// next-due timestamp from stored quota snapshots. Always pass
|
|
235
|
-
// `argumentsText: 'status'` to the pure executor so on/off args
|
|
236
|
-
// are display-only — Pi cannot toggle the setting.
|
|
237
|
-
const path = getPiAccountStoragePath();
|
|
238
|
-
const storage = await loadAccounts(path);
|
|
239
|
-
const accounts = buildPrimeAccountStatuses(storage, { now: Date.now() });
|
|
240
|
-
notify(ctx, executePrimeCommand({
|
|
241
|
-
argumentsText: 'status',
|
|
242
|
-
enabled: isPrimePersistentlyEnabled(storage),
|
|
243
|
-
accounts,
|
|
244
|
-
}).text);
|
|
245
65
|
},
|
|
246
66
|
});
|
|
247
67
|
}
|
package/dist/convert.d.ts
CHANGED
|
@@ -13,12 +13,16 @@ export type AnthropicRequestBody = {
|
|
|
13
13
|
} | {
|
|
14
14
|
type: 'adaptive';
|
|
15
15
|
display: 'summarized';
|
|
16
|
+
block_binding?: {
|
|
17
|
+
prefix_mismatch_behavior: Exclude<ThinkingPrefixMismatchBehavior, 'account-default'>;
|
|
18
|
+
};
|
|
16
19
|
};
|
|
17
20
|
output_config?: {
|
|
18
21
|
effort: string;
|
|
19
22
|
};
|
|
20
23
|
cache_control?: {
|
|
21
24
|
type: 'ephemeral';
|
|
25
|
+
ttl?: '1h';
|
|
22
26
|
};
|
|
23
27
|
speed?: 'fast';
|
|
24
28
|
};
|
|
@@ -32,4 +36,5 @@ export declare function buildAnthropicRequest(modelId: string, context: Context,
|
|
|
32
36
|
}): Promise<{
|
|
33
37
|
body: AnthropicRequestBody;
|
|
34
38
|
bodyText: string;
|
|
39
|
+
hostTools: Tool[];
|
|
35
40
|
}>;
|