@ottimis/jack-provider-sdk 0.4.0 → 0.9.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 +2 -2
- package/dist/cjs/host.js +38 -0
- package/dist/cjs/host.js.map +1 -0
- package/dist/cjs/index.js +10 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/profiles.js +29 -0
- package/dist/cjs/profiles.js.map +1 -0
- package/dist/cjs/sandbox.js +34 -0
- package/dist/cjs/sandbox.js.map +1 -0
- package/dist/host.d.ts +161 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +37 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/profiles.d.ts +130 -0
- package/dist/profiles.d.ts.map +1 -0
- package/dist/profiles.js +28 -0
- package/dist/profiles.js.map +1 -0
- package/dist/provider.d.ts +81 -0
- package/dist/provider.d.ts.map +1 -1
- package/dist/sandbox.d.ts +104 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/dist/sandbox.js +33 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/usage.d.ts +38 -10
- package/dist/usage.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/host.ts +159 -0
- package/src/index.ts +10 -1
- package/src/profiles.ts +142 -0
- package/src/provider.ts +81 -0
- package/src/sandbox.ts +108 -0
- package/src/usage.ts +38 -10
package/src/profiles.ts
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Profiles — multiple isolated identities for a single provider.
|
|
3
|
+
*
|
|
4
|
+
* A "profile" is an isolated config/identity directory the provider's runtime
|
|
5
|
+
* can be pointed at via an env var (Claude `CLAUDE_CONFIG_DIR`, Codex
|
|
6
|
+
* `CODEX_HOME`, Gemini `GEMINI_CONFIG_DIR`, …). Two profiles = two distinct
|
|
7
|
+
* accounts / login states / agent customizations / history sets, all running
|
|
8
|
+
* the same provider binary.
|
|
9
|
+
*
|
|
10
|
+
* The user-facing scenario this exists for: an employee with separate
|
|
11
|
+
* "claude-personal" and "claude-work" shell aliases that point CLAUDE_CONFIG_DIR
|
|
12
|
+
* at different folders. The host turns that into a first-class concept —
|
|
13
|
+
* choosable per session, with a default per workspace-agent slot — instead of
|
|
14
|
+
* making the user re-shell their alias every time they switch context.
|
|
15
|
+
*
|
|
16
|
+
* Provider opts in by:
|
|
17
|
+
* - declaring `capabilities.profiles = true`
|
|
18
|
+
* - implementing `JackProvider.profiles` with a {@link ProfilesApi}
|
|
19
|
+
* - injecting the right env var inside `applyProfile`
|
|
20
|
+
*
|
|
21
|
+
* Storage of the profile *list* lives on the host's per-provider kv (provider
|
|
22
|
+
* stores it via `host.kv` at activation time). Storage of the profile
|
|
23
|
+
* *content* (auth, sessions, agents, history) lives inside `configDir` on
|
|
24
|
+
* disk and is the runtime's concern, not the host's — Jack never reads or
|
|
25
|
+
* writes inside `configDir`.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import type { AgentQueryOptions } from './backend'
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* One profile entry. `id` is host-generated and stable; the human edits
|
|
32
|
+
* `label` + `configDir` freely.
|
|
33
|
+
*
|
|
34
|
+
* `isDefault` is exclusive within a provider — exactly one profile carries
|
|
35
|
+
* the flag at any time. Provider implementations enforce that invariant in
|
|
36
|
+
* `update`/`create` (when `setDefault` is true, demote the previous default).
|
|
37
|
+
*/
|
|
38
|
+
export type ProviderProfile = {
|
|
39
|
+
/** Stable identifier — host-generated UUID; never edited by user. */
|
|
40
|
+
id: string
|
|
41
|
+
/** User-facing display label ("Work", "Personal", …). */
|
|
42
|
+
label: string
|
|
43
|
+
/** Absolute path to the runtime config dir on the host filesystem. */
|
|
44
|
+
configDir: string
|
|
45
|
+
/** Exactly one profile per provider carries this flag. */
|
|
46
|
+
isDefault: boolean
|
|
47
|
+
/** ISO 8601 — when the profile was first created in Jack's registry. */
|
|
48
|
+
createdAt: string
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Result of {@link ProfilesApi.probeProfile} — best-effort introspection of
|
|
53
|
+
* what's already stored under `configDir` so the UI can show the user
|
|
54
|
+
* "Connected as <X>" instead of an opaque path.
|
|
55
|
+
*
|
|
56
|
+
* Provider populates whichever fields it can read cheaply (no network
|
|
57
|
+
* round-trips) — fields it can't infer stay undefined.
|
|
58
|
+
*/
|
|
59
|
+
export type ProviderProfileProbe = {
|
|
60
|
+
/** True when the dir exists and looks like a valid runtime config. */
|
|
61
|
+
exists: boolean
|
|
62
|
+
/** True when the dir contains usable credentials. Tri-state: false = present-but-invalid, undefined = N/A. */
|
|
63
|
+
authenticated?: boolean
|
|
64
|
+
/** Human-readable identity hint (email, account label) when discoverable. */
|
|
65
|
+
accountLabel?: string
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Input shape for {@link ProfilesApi.create}. The `id` is host-generated by
|
|
70
|
+
* the provider implementation (typically `crypto.randomUUID()`); the caller
|
|
71
|
+
* supplies the human bits.
|
|
72
|
+
*/
|
|
73
|
+
export type CreateProfileInput = {
|
|
74
|
+
label: string
|
|
75
|
+
configDir: string
|
|
76
|
+
/** When true, the new profile becomes the default (demotes previous default). */
|
|
77
|
+
setDefault?: boolean
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Provider-owned profiles capability. Optional on {@link JackProvider} —
|
|
82
|
+
* absent = the provider's runtime always uses its implicit default config dir
|
|
83
|
+
* and the host hides every profiles-related affordance.
|
|
84
|
+
*/
|
|
85
|
+
export type ProfilesApi = {
|
|
86
|
+
/**
|
|
87
|
+
* Enumerate the registered profiles in stable order. Provider MUST seed
|
|
88
|
+
* a "Default" profile pointing at its implicit config dir on first call
|
|
89
|
+
* (lazy migration — preserves the user's existing setup without manual
|
|
90
|
+
* intervention).
|
|
91
|
+
*/
|
|
92
|
+
list(): Promise<ProviderProfile[]>
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Register a new profile. Provider generates the `id` and persists the
|
|
96
|
+
* row. Returns the freshly-created profile so the caller doesn't have to
|
|
97
|
+
* round-trip through `list()`.
|
|
98
|
+
*/
|
|
99
|
+
create(input: CreateProfileInput): Promise<ProviderProfile>
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Patch an existing profile. Empty patch = no-op. Setting `isDefault: true`
|
|
103
|
+
* demotes whichever profile currently holds the default flag.
|
|
104
|
+
*/
|
|
105
|
+
update(
|
|
106
|
+
id: string,
|
|
107
|
+
patch: Partial<Pick<ProviderProfile, 'label' | 'configDir' | 'isDefault'>>
|
|
108
|
+
): Promise<ProviderProfile>
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Remove a profile by id. MUST refuse to remove the last remaining profile
|
|
112
|
+
* (the provider always needs a default to fall back to). MUST refuse to
|
|
113
|
+
* remove the default profile when other profiles exist — caller has to
|
|
114
|
+
* promote a replacement first.
|
|
115
|
+
*
|
|
116
|
+
* Note: this only removes the registry entry. Files inside `configDir`
|
|
117
|
+
* stay on disk untouched — destructive cleanup is the user's responsibility
|
|
118
|
+
* (we never `rm -rf` a directory the user gave us).
|
|
119
|
+
*/
|
|
120
|
+
remove(id: string): Promise<void>
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Mutate spawn options in place to point the runtime at the chosen
|
|
124
|
+
* profile's `configDir`. Each provider injects its native env var
|
|
125
|
+
* (Claude: `CLAUDE_CONFIG_DIR`; Codex: `CODEX_HOME`; …) and any other
|
|
126
|
+
* spawn-time wiring the runtime needs.
|
|
127
|
+
*
|
|
128
|
+
* Called once per spawn by the host, after `applyKnowledgeContext` and
|
|
129
|
+
* `prepareSpawnOptions`. Unknown `profileId` MUST be a silent no-op
|
|
130
|
+
* (caller falls back to the implicit default behavior).
|
|
131
|
+
*/
|
|
132
|
+
applyProfile(options: AgentQueryOptions, profileId: string): Promise<void>
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Best-effort introspection of what's stored under `configDir` so the
|
|
136
|
+
* UI can show "Connected as X" / "Empty profile" hints. Provider returns
|
|
137
|
+
* what it can read cheaply (file presence, parsed credentials file) —
|
|
138
|
+
* no network calls. Optional: providers that can't introspect their
|
|
139
|
+
* own config dir omit this and the UI falls back to a path-only display.
|
|
140
|
+
*/
|
|
141
|
+
probeProfile?(configDir: string): Promise<ProviderProfileProbe>
|
|
142
|
+
}
|
package/src/provider.ts
CHANGED
|
@@ -17,6 +17,9 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import type { AgentBackend, AgentPermissionMode, AgentQueryOptions, McpServerSpec } from './backend'
|
|
20
|
+
import type { HostServices } from './host'
|
|
21
|
+
import type { ProfilesApi } from './profiles'
|
|
22
|
+
import type { SandboxApi } from './sandbox'
|
|
20
23
|
import type { UsageApi } from './usage'
|
|
21
24
|
import type { ZodType } from 'zod'
|
|
22
25
|
import type {
|
|
@@ -273,6 +276,28 @@ export type CapabilityMatrix = {
|
|
|
273
276
|
* usage bars and no Connect affordance is offered.
|
|
274
277
|
*/
|
|
275
278
|
usage: boolean
|
|
279
|
+
/**
|
|
280
|
+
* Provider supports multiple isolated config/identity directories
|
|
281
|
+
* ("profiles") — distinct accounts, login states, agent customizations,
|
|
282
|
+
* and history sets all selectable per-session at runtime. When `true`,
|
|
283
|
+
* {@link JackProvider.profiles} MUST be defined; the host renders the
|
|
284
|
+
* profile picker UI and routes spawn-time `applyProfile` calls.
|
|
285
|
+
*
|
|
286
|
+
* When `false` the provider's runtime always uses its implicit default
|
|
287
|
+
* config dir; the host hides every profile-related affordance.
|
|
288
|
+
*/
|
|
289
|
+
profiles: boolean
|
|
290
|
+
/**
|
|
291
|
+
* Provider can run inside Jack's Docker sandbox. When `true`,
|
|
292
|
+
* {@link JackProvider.sandbox} MUST be defined; the host enables the
|
|
293
|
+
* sandbox toggle in the new-session dialog and renders an entry for this
|
|
294
|
+
* provider in `Settings → Sandbox`.
|
|
295
|
+
*
|
|
296
|
+
* When `false` (or omitted), sandbox mode is unavailable for this
|
|
297
|
+
* provider — the toggle is hidden / disabled in the UI, and a spawn-time
|
|
298
|
+
* sandbox request returns a clear error.
|
|
299
|
+
*/
|
|
300
|
+
sandbox: boolean
|
|
276
301
|
/**
|
|
277
302
|
* Permission modes the provider actually supports. Drives the
|
|
278
303
|
* Shift-Tab cycle in the renderer (`MessageInputBar`) and any
|
|
@@ -291,6 +316,23 @@ export type CapabilityMatrix = {
|
|
|
291
316
|
* or settings); the catalog only governs UI affordances.
|
|
292
317
|
*/
|
|
293
318
|
permissionModes: readonly AgentPermissionMode[]
|
|
319
|
+
/**
|
|
320
|
+
* Suggested prompt-cache TTL in milliseconds — how long the provider's
|
|
321
|
+
* server-side prompt cache stays warm between user turns before a new
|
|
322
|
+
* cache-write is required. Optional: providers without prompt caching
|
|
323
|
+
* (or without a documented TTL) leave it undefined and the host hides
|
|
324
|
+
* the cache-countdown chip entirely for sessions on that provider.
|
|
325
|
+
*
|
|
326
|
+
* This is only the **suggested default**: the user can override per
|
|
327
|
+
* provider in `Settings → Prompt cache` and disable the chip outright.
|
|
328
|
+
* The host treats this as a UI-only countdown hint — never as a
|
|
329
|
+
* contract for actual cache eviction (the provider is the source of
|
|
330
|
+
* truth at request time).
|
|
331
|
+
*
|
|
332
|
+
* Claude declares 300_000 (5 min) per its prompt-caching docs. Codex
|
|
333
|
+
* and Gemini leave it undefined.
|
|
334
|
+
*/
|
|
335
|
+
cacheTtlMs?: number
|
|
294
336
|
}
|
|
295
337
|
|
|
296
338
|
/**
|
|
@@ -676,6 +718,45 @@ export type JackProvider = {
|
|
|
676
718
|
* decodes.
|
|
677
719
|
*/
|
|
678
720
|
usage?: UsageApi
|
|
721
|
+
/**
|
|
722
|
+
* Multi-profile capability — multiple isolated config/identity dirs
|
|
723
|
+
* selectable per session. See {@link ProfilesApi}. Optional; when
|
|
724
|
+
* undefined `capabilities.profiles` MUST be `false` and the host hides
|
|
725
|
+
* every profile-related affordance. When defined, the host calls
|
|
726
|
+
* `applyProfile(options, profileId)` once per spawn so the provider can
|
|
727
|
+
* inject its native config-dir env var (Claude `CLAUDE_CONFIG_DIR`,
|
|
728
|
+
* Codex `CODEX_HOME`, …).
|
|
729
|
+
*/
|
|
730
|
+
profiles?: ProfilesApi
|
|
731
|
+
/**
|
|
732
|
+
* Docker sandbox capability — provider declares the image, binary name,
|
|
733
|
+
* and config-dir mount the host needs to spawn a sandboxed session for
|
|
734
|
+
* this provider. See {@link SandboxApi}. Optional; when undefined
|
|
735
|
+
* `capabilities.sandbox` MUST be `false` and the host disables sandbox
|
|
736
|
+
* mode for this provider's sessions.
|
|
737
|
+
*/
|
|
738
|
+
sandbox?: SandboxApi
|
|
739
|
+
/**
|
|
740
|
+
* Optional one-shot activation hook. Called once by the host during
|
|
741
|
+
* registration with a {@link HostServices} bag scoped to this
|
|
742
|
+
* provider's id (kv namespace, auth partition prefix). Providers that
|
|
743
|
+
* need host-side primitives (encrypted credential storage, child auth
|
|
744
|
+
* windows, …) store the `host` reference and use it lazily; providers
|
|
745
|
+
* that are pure (Codex, Gemini today) leave this undefined.
|
|
746
|
+
*
|
|
747
|
+
* Activation MUST be idempotent: calling `activate(host)` twice with
|
|
748
|
+
* the same host is allowed and should not duplicate state. Activation
|
|
749
|
+
* happens at registration time — well before any session spawns —
|
|
750
|
+
* but providers MUST NOT block on network or disk here. Defer all I/O
|
|
751
|
+
* to the methods that actually need it.
|
|
752
|
+
*
|
|
753
|
+
* The host calls `activate` synchronously enough that
|
|
754
|
+
* `provider.usage`, `provider.persistedPermissions`, etc. can read
|
|
755
|
+
* `host` from a closure / captured variable in subsequent invocations.
|
|
756
|
+
* Async work inside `activate` is OK but the host won't await it
|
|
757
|
+
* before exposing the provider — it's "fire and let it complete".
|
|
758
|
+
*/
|
|
759
|
+
activate?(host: HostServices): void | Promise<void>
|
|
679
760
|
}
|
|
680
761
|
|
|
681
762
|
/**
|
package/src/sandbox.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SandboxApi — provider-declared Docker sandbox capability.
|
|
3
|
+
*
|
|
4
|
+
* Jack runs sessions in a Docker container ("sandbox mode") to isolate the
|
|
5
|
+
* provider's CLI from the host filesystem and network. The container itself
|
|
6
|
+
* is generic — Jack owns the Docker orchestration, security policy (CapDrop,
|
|
7
|
+
* memory cap, non-privileged), project mount, and user-defined shared
|
|
8
|
+
* volumes. The PROVIDER-SPECIFIC bits live here:
|
|
9
|
+
*
|
|
10
|
+
* - which image to pull (each provider needs its own CLI installed)
|
|
11
|
+
* - which binary name to invoke inside the container (used by the host to
|
|
12
|
+
* rewrite host-resolved absolute paths like
|
|
13
|
+
* `/Users/foo/.local/bin/claude` to a bare command the container's
|
|
14
|
+
* PATH resolves)
|
|
15
|
+
* - which config dir to mount (`~/.claude`, `~/.codex`, `~/.gemini`, …)
|
|
16
|
+
* - optional env extras
|
|
17
|
+
*
|
|
18
|
+
* A provider declaring `sandbox` opts itself into sandbox mode. The
|
|
19
|
+
* matching capability flag {@link CapabilityMatrix.sandbox} MUST be `true`
|
|
20
|
+
* — the host derives it from `provider.sandbox != null` at registration.
|
|
21
|
+
*
|
|
22
|
+
* Providers that don't declare `sandbox` (or set it to `undefined`) are
|
|
23
|
+
* treated as sandbox-incompatible: the host hides the toggle in the UI and
|
|
24
|
+
* blocks spawn-time requests with a clear error.
|
|
25
|
+
*
|
|
26
|
+
* The host's distribution model expects images at
|
|
27
|
+
* `ghcr.io/ottimis/jack-sandbox-<provider-id>:<X.Y.Z>` (monorepo
|
|
28
|
+
* `github.com/ottimis/JACK-sandbox`). Providers can point `defaultImage`
|
|
29
|
+
* elsewhere — third-party plugin authors who maintain their own image are
|
|
30
|
+
* free to host wherever they like.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Mount the provider's host-side config directory into the container.
|
|
35
|
+
* Most providers persist auth + sessions + per-user settings in a dotfile
|
|
36
|
+
* dir under `$HOME` (Claude `~/.claude`, Codex `~/.codex`, Gemini
|
|
37
|
+
* `~/.gemini`). The host mounts this dir into the container at
|
|
38
|
+
* {@link containerPath} so the CLI inside the container has access to the
|
|
39
|
+
* same auth state as the host.
|
|
40
|
+
*
|
|
41
|
+
* Read-only by default — the container shouldn't be writing back to the
|
|
42
|
+
* user's persistent config from inside the sandbox. Set `readOnly: false`
|
|
43
|
+
* only when the provider's CLI genuinely needs to mutate state inside the
|
|
44
|
+
* config dir (e.g. session JSONL append).
|
|
45
|
+
*/
|
|
46
|
+
export type SandboxConfigMount = {
|
|
47
|
+
/**
|
|
48
|
+
* Absolute host path. Provider implementations resolve this lazily — call
|
|
49
|
+
* `os.homedir()` + `path.join(...)` at the time `configMount` is read,
|
|
50
|
+
* not at module-load time, so test environments and per-process HOME
|
|
51
|
+
* overrides work correctly.
|
|
52
|
+
*/
|
|
53
|
+
hostPath: string
|
|
54
|
+
/** Absolute container path. */
|
|
55
|
+
containerPath: string
|
|
56
|
+
/** When `true`, the host adds `:ro` to the bind. Default: `true` recommended. */
|
|
57
|
+
readOnly: boolean
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Provider-declared Docker sandbox capability. Optional on
|
|
62
|
+
* {@link JackProvider}; when present the matching
|
|
63
|
+
* {@link CapabilityMatrix.sandbox} flag MUST be `true`.
|
|
64
|
+
*/
|
|
65
|
+
export interface SandboxApi {
|
|
66
|
+
/**
|
|
67
|
+
* Default image reference, pinned per provider release. Format:
|
|
68
|
+
* `<registry>/<repo>:<tag>`. Users can override per-provider via the host
|
|
69
|
+
* setting `sandbox.image.<providerId>`.
|
|
70
|
+
*
|
|
71
|
+
* For Jack's first-party providers the recommended location is
|
|
72
|
+
* `ghcr.io/ottimis/jack-sandbox-<providerId>:<X.Y.Z>` (monorepo built
|
|
73
|
+
* from `github.com/ottimis/JACK-sandbox`). Third-party plugins are free
|
|
74
|
+
* to host elsewhere.
|
|
75
|
+
*/
|
|
76
|
+
readonly defaultImage: string
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* CLI binary name as it should be invoked inside the container (e.g.
|
|
80
|
+
* `'claude'`, `'codex'`, `'gemini'`). Used by the host's spawner to
|
|
81
|
+
* rewrite host-resolved absolute binary paths to a bare command the
|
|
82
|
+
* container's PATH resolves.
|
|
83
|
+
*
|
|
84
|
+
* The image MUST install this binary at a location reachable from
|
|
85
|
+
* `$PATH` (typically `/usr/local/bin/<binaryName>` via `npm install -g`).
|
|
86
|
+
*/
|
|
87
|
+
readonly binaryName: string
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Mount the provider's host-side config directory into the container.
|
|
91
|
+
* Optional — providers that are stateless on the host (none today)
|
|
92
|
+
* leave this undefined.
|
|
93
|
+
*/
|
|
94
|
+
readonly configMount?: SandboxConfigMount
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Optional environment extras to inject into the container. Layered AFTER
|
|
98
|
+
* the spawn-arg env so provider-specific overrides can win, but BEFORE
|
|
99
|
+
* the user can override (the user-facing override is per-provider via
|
|
100
|
+
* the host setting, not per-env-var).
|
|
101
|
+
*
|
|
102
|
+
* Most provider env is already on `SpawnArgs.env` from the backend's
|
|
103
|
+
* spawn pipeline. Use this only when the SDK contract doesn't expose a
|
|
104
|
+
* cleaner channel — e.g. forcing a CLI to disable telemetry inside the
|
|
105
|
+
* sandbox even when the user has it on globally.
|
|
106
|
+
*/
|
|
107
|
+
envExtras?(): Record<string, string>
|
|
108
|
+
}
|
package/src/usage.ts
CHANGED
|
@@ -180,32 +180,60 @@ export type UsageConnectContext = {
|
|
|
180
180
|
* Provider-owned usage capability. Optional on {@link JackProvider};
|
|
181
181
|
* absent = host hides the chip's "Connect" affordance and the
|
|
182
182
|
* capability flag is `false`.
|
|
183
|
+
*
|
|
184
|
+
* Multi-profile contract (SDK 0.7.0):
|
|
185
|
+
* Every account-level method accepts an optional `profileId`. Providers
|
|
186
|
+
* that ALSO declare `capabilities.profiles=true` MUST honor the param —
|
|
187
|
+
* different profile = different account = different credentials, polled
|
|
188
|
+
* independently. When omitted, the provider resolves to its DEFAULT
|
|
189
|
+
* profile (back-compat with hosts that don't yet thread profileId).
|
|
190
|
+
*
|
|
191
|
+
* Providers without profiles support (`capabilities.profiles=false`)
|
|
192
|
+
* MAY ignore the param and behave as if every call were singleton —
|
|
193
|
+
* the omission stays the canonical caller behavior, the param is just
|
|
194
|
+
* ignored.
|
|
195
|
+
*
|
|
196
|
+
* `formatSessionMetrics` stays profile-agnostic: per-session metrics
|
|
197
|
+
* derive from the live process's context tokens (already pinned to the
|
|
198
|
+
* session's profile via `applyProfile` at spawn time).
|
|
183
199
|
*/
|
|
184
200
|
export type UsageApi = {
|
|
185
|
-
/**
|
|
186
|
-
|
|
201
|
+
/**
|
|
202
|
+
* Current connection state — used for chip display + gating.
|
|
203
|
+
* Profile-aware: omit `profileId` to query the default profile.
|
|
204
|
+
*/
|
|
205
|
+
status(profileId?: string): Promise<UsageStatus>
|
|
187
206
|
|
|
188
207
|
/**
|
|
189
208
|
* Open the provider's connect flow. Whatever modality the provider
|
|
190
209
|
* needs (login window, API-key picker, OAuth redirect) lives here.
|
|
210
|
+
* Profile-aware: omit `profileId` to bind credentials to the default
|
|
211
|
+
* profile. Different profileIds use isolated storage AND isolated
|
|
212
|
+
* login surfaces (e.g. distinct cookie partitions for Claude) so two
|
|
213
|
+
* accounts can sign in side by side.
|
|
191
214
|
*/
|
|
192
|
-
connect(ctx: UsageConnectContext): Promise<UsageConnectResult>
|
|
215
|
+
connect(ctx: UsageConnectContext, profileId?: string): Promise<UsageConnectResult>
|
|
193
216
|
|
|
194
217
|
/**
|
|
195
218
|
* When `connect()` returned `'choose'`, host calls this with the
|
|
196
219
|
* user's pick. Optional — providers that never choose omit it.
|
|
220
|
+
* Profile-aware: pass the SAME `profileId` you used for `connect()`.
|
|
197
221
|
*/
|
|
198
|
-
selectOption?(optionId: string): Promise<UsageConnectResult>
|
|
222
|
+
selectOption?(optionId: string, profileId?: string): Promise<UsageConnectResult>
|
|
199
223
|
|
|
200
|
-
/**
|
|
201
|
-
|
|
224
|
+
/**
|
|
225
|
+
* Drop credentials and stop any provider-side polling for the
|
|
226
|
+
* specified profile. Omit `profileId` to disconnect the default profile.
|
|
227
|
+
*/
|
|
228
|
+
disconnect(profileId?: string): Promise<void>
|
|
202
229
|
|
|
203
230
|
/**
|
|
204
|
-
* Fetch one fresh account-level snapshot
|
|
205
|
-
* fine when the provider has no billing surface
|
|
206
|
-
* stays `true` for the per-session bridge.
|
|
231
|
+
* Fetch one fresh account-level snapshot for the specified profile.
|
|
232
|
+
* Empty `metrics: []` is fine when the provider has no billing surface
|
|
233
|
+
* yet — the capability stays `true` for the per-session bridge.
|
|
234
|
+
* Omit `profileId` to fetch the default profile.
|
|
207
235
|
*/
|
|
208
|
-
fetch(): Promise<UsageSnapshot>
|
|
236
|
+
fetch(profileId?: string): Promise<UsageSnapshot>
|
|
209
237
|
|
|
210
238
|
/**
|
|
211
239
|
* Recommended poll cadence (seconds). Host clamps to its bounds.
|