@uxnan/shared 0.0.4-alpha.20260703 → 0.0.5-alpha.20260711

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
@@ -13,7 +13,7 @@ equivalents (see
13
13
  [`architecture/02b-contracts-and-requirements.md`](../architecture/02b-contracts-and-requirements.md)
14
14
  §1 for the canonical contract list).
15
15
 
16
- > **Status:** implemented and stable — **61 JSON-RPC methods** + **8 streaming
16
+ > **Status:** implemented and stable — **62 JSON-RPC methods** + **8 streaming
17
17
  > notifications**, kept lock-step at build time with the `METHOD_NAMES` array and
18
18
  > the `StreamNotification` enum (a compile-time assertion in
19
19
  > `src/jsonrpc/method-registry.ts` fails the build on any drift). Changes are
@@ -52,7 +52,7 @@ flowchart TB
52
52
  | JSON-RPC | envelope types + constructors (`makeRequest`, `makeNotification`, `makeResponse`, `makeErrorResponse`), error codes (`JsonRpcErrorCode` + Uxnan-specific `-32000..-32008`), `RpcError`, typed method registry (`JsonRpcMethodRegistry` + `METHOD_NAMES`), `isKnownMethod` |
53
53
  | Streaming | `StreamNotification` enum + param types (`TurnStartedParams`, `MessageDeltaParams`, `ThinkingDeltaParams`, `ContentBlockParams`, `TurnCompletedParams`, `TurnUsage`, `TurnErrorParams`, `TurnAbortedParams`, `ModelResolvedParams`) |
54
54
  | E2EE | handshake messages (`clientHello` / `serverHello` / `clientAuth` / `ready`), `buildHandshakeTranscript`, `SecureEnvelope`, `PairingPayload` v2 (`relay` optional + `hosts: string[]`) with `Base64(utf8(JSON))` QR encoding |
55
- | Models | thread / turn / message (with `MessageContent` polymorphic blocks), git, workspace (incl. `browseDirs` + `exists`), project, auth, session/trust (`BridgeStatus` incl. `latestVersion?`/`updateAvailable?`), approval |
55
+ | Models | thread / turn / message (with `MessageContent` polymorphic blocks), git, workspace (incl. `browseDirs` + `exists`), project, auth, session/trust (`BridgeStatus` incl. `latestVersion?`/`updateAvailable?`), approval, question (interactive multiple-choice) |
56
56
  | Agents | `IAgentAdapter` (with `respondApproval`, `listModels`, `nativeSessionId`, `SendTurnOptions { threadId, turnId, text, service?, effort?, options?, attachments?, cwd?, accessMode? }`), `AgentModel` (incl. `version?`, `isDefault?`, `options?`, `contextWindow?`, `isLatestAlias?`), `AgentCapabilities` (incl. `images`, `approvals`, `reportsContextUsage`), `AgentConfig` (cwd, agentId, model, plus optional `binaryPath`/`extraArgs`) |
57
57
  | Version | `compareVersions` / `isNewerVersion` — dependency-free SemVer precedence (used by the bridge's npm update check) |
58
58
  | Validation | Ajv validators for requests, responses, envelopes, pairing payload, push payloads |
@@ -3,7 +3,11 @@
3
3
  *
4
4
  * Source: architecture/02a-system-architecture.md §5.8.2 (adapters).
5
5
  */
6
- export type AgentId = 'codex' | 'opencode' | 'claude-code' | 'gemini-cli' | 'pi-agent' | 'aider'
6
+ export type AgentId = 'codex' | 'opencode' | 'claude-code' | 'gemini-cli' | 'pi-agent'
7
+ /** Zero — open-source Go coding agent, driven over the Agent Client Protocol. */
8
+ | 'zero'
9
+ /** Grok — xAI's coding CLI, driven over the Agent Client Protocol (`grok agent stdio`). */
10
+ | 'grok'
7
11
  /** Built-in reference/dev agent that echoes the prompt (no external CLI). */
8
12
  | 'echo';
9
13
  export interface AgentCapabilities {
@@ -24,6 +28,14 @@ export interface AgentCapabilities {
24
28
  * OpenCode) and the meter stays hidden.
25
29
  */
26
30
  reportsContextUsage?: boolean;
31
+ /**
32
+ * Agent runs in autonomous ("YOLO") mode by default — it acts and edits
33
+ * without per-action approval prompts because its headless CLI exposes no
34
+ * pre-tool approval channel. The phone surfaces this so the user knows Pi
35
+ * (and any such agent) will not ask before running tools. Optional; absent/
36
+ * false means the agent either gates tools or is pending approval wiring.
37
+ */
38
+ autonomous?: boolean;
27
39
  }
28
40
  /**
29
41
  * A registered agent the phone can pick for a thread, returned by `agent/list`.
@@ -22,5 +22,7 @@ export * from './models/workspace.js';
22
22
  export * from './models/project.js';
23
23
  export * from './models/session.js';
24
24
  export * from './models/approval.js';
25
+ export * from './models/question.js';
26
+ export * from './models/usage.js';
25
27
  export * from './validators/validate.js';
26
28
  export * from './validators/json-schema/schemas.js';
package/dist/src/index.js CHANGED
@@ -28,6 +28,8 @@ export * from './models/workspace.js';
28
28
  export * from './models/project.js';
29
29
  export * from './models/session.js';
30
30
  export * from './models/approval.js';
31
+ export * from './models/question.js';
32
+ export * from './models/usage.js';
31
33
  // Validators
32
34
  export * from './validators/validate.js';
33
35
  export * from './validators/json-schema/schemas.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,gBAAgB,CAAC;AAE/B,WAAW;AACX,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAE3C,OAAO;AACP,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAE1C,SAAS;AACT,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAE1C,UAAU;AACV,cAAc,sBAAsB,CAAC;AAErC,gBAAgB;AAChB,cAAc,iCAAiC,CAAC;AAEhD,SAAS;AACT,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AAErC,aAAa;AACb,cAAc,0BAA0B,CAAC;AACzC,cAAc,qCAAqC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,gBAAgB,CAAC;AAE/B,WAAW;AACX,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAE3C,OAAO;AACP,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAE1C,SAAS;AACT,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAE1C,UAAU;AACV,cAAc,sBAAsB,CAAC;AAErC,gBAAgB;AAChB,cAAc,iCAAiC,CAAC;AAEhD,SAAS;AACT,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAElC,aAAa;AACb,cAAc,0BAA0B,CAAC;AACzC,cAAc,qCAAqC,CAAC"}
@@ -3,5 +3,5 @@
3
3
  * compile-time {@link JsonRpcMethodRegistry} via the assertion below.
4
4
  */
5
5
  import type { JsonRpcMethodName } from './methods.js';
6
- export declare const METHOD_NAMES: readonly ["thread/list", "thread/read", "thread/start", "thread/resume", "thread/fork", "thread/setModel", "thread/rename", "thread/setAccessMode", "thread/archive", "thread/unarchive", "thread/delete", "turn/list", "turn/read", "turn/send", "turn/cancel", "git/status", "git/diff", "git/commit", "git/push", "git/pull", "git/checkout", "git/createBranch", "git/createWorktree", "git/stage", "git/unstage", "git/discard", "git/createPr", "git/undoCommit", "git/branches", "git/switchBranch", "git/revert", "git/deleteBranch", "git/removeWorktree", "git/log", "git/commitShow", "workspace/readFile", "workspace/readImage", "workspace/list", "workspace/searchFiles", "workspace/browseDirs", "workspace/checkpoint", "workspace/diffCheckpoint", "workspace/applyCheckpoint", "workspace/applyPatch", "workspace/exists", "project/list", "project/resolve", "agent/list", "agent/models", "auth/status", "auth/login", "auth/logout", "notifications/register", "notifications/update", "notifications/unregister", "bridge/status", "bridge/generatePairingQr", "bridge/connectedPhones", "bridge/disconnectPhone", "bridge/trustedDevices", "bridge/removeTrustedDevice"];
6
+ export declare const METHOD_NAMES: readonly ["thread/list", "thread/read", "thread/start", "thread/resume", "thread/fork", "thread/setModel", "thread/rename", "thread/setAccessMode", "thread/archive", "thread/unarchive", "thread/delete", "turn/list", "turn/read", "turn/send", "turn/cancel", "git/status", "git/diff", "git/commit", "git/push", "git/pull", "git/checkout", "git/createBranch", "git/createWorktree", "git/stage", "git/unstage", "git/discard", "git/createPr", "git/undoCommit", "git/branches", "git/switchBranch", "git/revert", "git/deleteBranch", "git/removeWorktree", "git/log", "git/commitShow", "workspace/readFile", "workspace/readImage", "workspace/list", "workspace/searchFiles", "workspace/browseDirs", "workspace/checkpoint", "workspace/diffCheckpoint", "workspace/applyCheckpoint", "workspace/applyPatch", "workspace/exists", "project/list", "project/resolve", "agent/list", "agent/models", "agent/usageStats", "auth/status", "auth/login", "auth/logout", "notifications/register", "notifications/update", "notifications/unregister", "bridge/status", "bridge/generatePairingQr", "bridge/connectedPhones", "bridge/disconnectPhone", "bridge/trustedDevices", "bridge/removeTrustedDevice"];
7
7
  export declare function isKnownMethod(method: string): method is JsonRpcMethodName;
@@ -53,6 +53,7 @@ export const METHOD_NAMES = [
53
53
  // Agents
54
54
  'agent/list',
55
55
  'agent/models',
56
+ 'agent/usageStats',
56
57
  // Auth
57
58
  'auth/status',
58
59
  'auth/login',
@@ -1 +1 @@
1
- {"version":3,"file":"method-registry.js","sourceRoot":"","sources":["../../../src/jsonrpc/method-registry.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,kBAAkB;IAClB,aAAa;IACb,aAAa;IACb,cAAc;IACd,eAAe;IACf,aAAa;IACb,iBAAiB;IACjB,eAAe;IACf,sBAAsB;IACtB,gBAAgB;IAChB,kBAAkB;IAClB,eAAe;IACf,WAAW;IACX,WAAW;IACX,WAAW;IACX,aAAa;IACb,MAAM;IACN,YAAY;IACZ,UAAU;IACV,YAAY;IACZ,UAAU;IACV,UAAU;IACV,cAAc;IACd,kBAAkB;IAClB,oBAAoB;IACpB,WAAW;IACX,aAAa;IACb,aAAa;IACb,cAAc;IACd,gBAAgB;IAChB,cAAc;IACd,kBAAkB;IAClB,YAAY;IACZ,kBAAkB;IAClB,oBAAoB;IACpB,SAAS;IACT,gBAAgB;IAChB,YAAY;IACZ,oBAAoB;IACpB,qBAAqB;IACrB,gBAAgB;IAChB,uBAAuB;IACvB,sBAAsB;IACtB,sBAAsB;IACtB,0BAA0B;IAC1B,2BAA2B;IAC3B,sBAAsB;IACtB,kBAAkB;IAClB,WAAW;IACX,cAAc;IACd,iBAAiB;IACjB,SAAS;IACT,YAAY;IACZ,cAAc;IACd,OAAO;IACP,aAAa;IACb,YAAY;IACZ,aAAa;IACb,uBAAuB;IACvB,wBAAwB;IACxB,sBAAsB;IACtB,0BAA0B;IAC1B,iBAAiB;IACjB,eAAe;IACf,0BAA0B;IAC1B,wBAAwB;IACxB,wBAAwB;IACxB,uBAAuB;IACvB,4BAA4B;CACpB,CAAC;AAQX,MAAM,sBAAsB,GAAqB,IAAI,CAAC;AACtD,MAAM,sBAAsB,GAAqB,IAAI,CAAC;AACtD,KAAK,sBAAsB,CAAC;AAC5B,KAAK,sBAAsB,CAAC;AAE5B,MAAM,eAAe,GAAwB,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;AAEnE,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,OAAO,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC"}
1
+ {"version":3,"file":"method-registry.js","sourceRoot":"","sources":["../../../src/jsonrpc/method-registry.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,kBAAkB;IAClB,aAAa;IACb,aAAa;IACb,cAAc;IACd,eAAe;IACf,aAAa;IACb,iBAAiB;IACjB,eAAe;IACf,sBAAsB;IACtB,gBAAgB;IAChB,kBAAkB;IAClB,eAAe;IACf,WAAW;IACX,WAAW;IACX,WAAW;IACX,aAAa;IACb,MAAM;IACN,YAAY;IACZ,UAAU;IACV,YAAY;IACZ,UAAU;IACV,UAAU;IACV,cAAc;IACd,kBAAkB;IAClB,oBAAoB;IACpB,WAAW;IACX,aAAa;IACb,aAAa;IACb,cAAc;IACd,gBAAgB;IAChB,cAAc;IACd,kBAAkB;IAClB,YAAY;IACZ,kBAAkB;IAClB,oBAAoB;IACpB,SAAS;IACT,gBAAgB;IAChB,YAAY;IACZ,oBAAoB;IACpB,qBAAqB;IACrB,gBAAgB;IAChB,uBAAuB;IACvB,sBAAsB;IACtB,sBAAsB;IACtB,0BAA0B;IAC1B,2BAA2B;IAC3B,sBAAsB;IACtB,kBAAkB;IAClB,WAAW;IACX,cAAc;IACd,iBAAiB;IACjB,SAAS;IACT,YAAY;IACZ,cAAc;IACd,kBAAkB;IAClB,OAAO;IACP,aAAa;IACb,YAAY;IACZ,aAAa;IACb,uBAAuB;IACvB,wBAAwB;IACxB,sBAAsB;IACtB,0BAA0B;IAC1B,iBAAiB;IACjB,eAAe;IACf,0BAA0B;IAC1B,wBAAwB;IACxB,wBAAwB;IACxB,uBAAuB;IACvB,4BAA4B;CACpB,CAAC;AAQX,MAAM,sBAAsB,GAAqB,IAAI,CAAC;AACtD,MAAM,sBAAsB,GAAqB,IAAI,CAAC;AACtD,KAAK,sBAAsB,CAAC;AAC5B,KAAK,sBAAsB,CAAC;AAE5B,MAAM,eAAe,GAAwB,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;AAEnE,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,OAAO,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC"}
@@ -10,9 +10,11 @@ import type { GitBranchList, GitBranchResult, GitCommitDetails, GitCommitResult,
10
10
  import type { ApplyResult, BrowseResult, Checkpoint, CheckpointDiff, FileContent, ImageContent, PatchChange, TurnAttachment, WorkspaceExistsResult, WorkspaceListing, SearchFilesParams, WorkspaceSearchResult } from '../models/workspace.js';
11
11
  import type { AuthStatus, Project } from '../models/project.js';
12
12
  import type { ApprovalResponse } from '../models/approval.js';
13
+ import type { QuestionResponse } from '../models/question.js';
13
14
  import type { BridgeStatus, ConnectedPhone, TrustedDevice } from '../models/session.js';
14
15
  import type { PairingPayload } from '../e2ee/pairing-payload.js';
15
16
  import type { AgentDescriptor, AgentId, AgentModel } from '../agents/agent-capabilities.js';
17
+ import type { UsageStatsParams, UsageStatsResult } from '../models/usage.js';
16
18
  import type { PushPlatform } from '../notifications/push-payload.js';
17
19
  export interface ListThreadsParams {
18
20
  projectId?: string;
@@ -74,6 +76,12 @@ export interface TurnSendParams {
74
76
  * is not required.
75
77
  */
76
78
  approvalResponse?: ApprovalResponse;
79
+ /**
80
+ * Reply to a pending question the agent asked (no new turn is created). The
81
+ * bridge routes the chosen answers to the agent adapter. When present, `text`
82
+ * is not required.
83
+ */
84
+ questionResponse?: QuestionResponse;
77
85
  }
78
86
  export interface ThreadSetModelParams {
79
87
  threadId: string;
@@ -468,6 +476,10 @@ export interface JsonRpcMethodRegistry {
468
476
  params: AgentModelsParams;
469
477
  result: AgentModelsResult;
470
478
  };
479
+ 'agent/usageStats': {
480
+ params: UsageStatsParams;
481
+ result: UsageStatsResult;
482
+ };
471
483
  'auth/status': {
472
484
  params: {
473
485
  agentId: AgentId;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Interactive question contracts.
3
+ *
4
+ * An agent that needs the user to CHOOSE among options (not just approve/reject
5
+ * an action) emits a `question` content block (on `stream/content/block`); the
6
+ * phone renders an interactive picker and replies via `turn/send { questionResponse }`.
7
+ * The bridge routes the chosen answers back to the agent adapter. This mirrors
8
+ * the {@link ApprovalResponse} flow but carries multiple-choice answers instead
9
+ * of a binary decision.
10
+ *
11
+ * Source: architecture/02a-system-architecture.md §6.2.
12
+ */
13
+ /** One selectable option of a {@link QuestionItem}. */
14
+ export interface QuestionOption {
15
+ /** Display text the user picks (also the value echoed back as the answer). */
16
+ label: string;
17
+ /** Optional one-line explanation of what choosing this option means. */
18
+ description?: string;
19
+ }
20
+ /** A single question with its options. */
21
+ export interface QuestionItem {
22
+ /** The full question text. */
23
+ question: string;
24
+ /** Optional short label/category for the question. */
25
+ header?: string;
26
+ /** The choices the user may pick from. */
27
+ options: QuestionOption[];
28
+ /** Whether more than one option may be selected (defaults to single-select). */
29
+ multiple?: boolean;
30
+ }
31
+ /**
32
+ * Payload of a `question` content block. The phone decodes this into its
33
+ * interactive question card. `questionId` is the bridge handle the user echoes
34
+ * back in {@link QuestionResponse.questionId}.
35
+ */
36
+ export interface QuestionRequestBlock {
37
+ type: 'question';
38
+ /** Bridge id the phone echoes back in `questionResponse.questionId`. */
39
+ questionId: string;
40
+ /** The questions to ask (usually one; an agent may batch a few). */
41
+ questions: QuestionItem[];
42
+ }
43
+ /**
44
+ * The user's reply to a pending question, carried on `turn/send`. `answers` is
45
+ * one entry per question (in order), each an array of the chosen option
46
+ * `label`s (one for single-select, several for a `multiple` question, empty when
47
+ * the user skipped that question).
48
+ */
49
+ export interface QuestionResponse {
50
+ /** The id from the question request the user is answering. */
51
+ questionId: string;
52
+ /** Chosen option labels, per question, in question order. */
53
+ answers: string[][];
54
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Interactive question contracts.
3
+ *
4
+ * An agent that needs the user to CHOOSE among options (not just approve/reject
5
+ * an action) emits a `question` content block (on `stream/content/block`); the
6
+ * phone renders an interactive picker and replies via `turn/send { questionResponse }`.
7
+ * The bridge routes the chosen answers back to the agent adapter. This mirrors
8
+ * the {@link ApprovalResponse} flow but carries multiple-choice answers instead
9
+ * of a binary decision.
10
+ *
11
+ * Source: architecture/02a-system-architecture.md §6.2.
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=question.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question.js","sourceRoot":"","sources":["../../../src/models/question.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * AI-provider usage statistics: quota/rate windows, plan/account, credit
3
+ * balance and local token tallies read from a coding CLI's on-disk state — its
4
+ * stored OAuth token (→ the provider's official usage API) and/or its local
5
+ * session logs.
6
+ *
7
+ * Surfaced in the desktop's Settings → Providers section and, over the bridge,
8
+ * on the phone. The access path is per-runtime by design (02a §5.8.10): the
9
+ * desktop reads these files natively in Rust; the bridge reads them in TS so a
10
+ * paired phone — which cannot see the PC's disk directly — gets the same data
11
+ * over `agent/usageStats`. The Dart equivalents live in uxnanmobile and are kept
12
+ * in sync manually (see 02e-bridge-integration.md §4.2).
13
+ *
14
+ * Posture: only the CLI's own stored token is read — never browser cookies or
15
+ * user-pasted API keys.
16
+ */
17
+ /** A coding CLI whose usage we read from its own stored token. */
18
+ export type UsageProvider = 'codex' | 'claude' | 'copilot' | 'gemini';
19
+ /** Outcome of reading one provider's usage. */
20
+ export type UsageStatus =
21
+ /** Fresh quota/credit data was read. */
22
+ 'ok'
23
+ /** CLI is present but not signed in (no usable token). */
24
+ | 'authRequired'
25
+ /** CLI / its config directory is not present on this machine. */
26
+ | 'notInstalled'
27
+ /** Read/network/parse failure — see {@link ProviderUsage.message}. */
28
+ | 'error';
29
+ /** How the data was obtained, for the UI's provenance label. Every wired
30
+ * provider reads its quota from the CLI's own signed-in token. */
31
+ export type UsageSource = 'token';
32
+ /**
33
+ * A single quota/rate window, expressed as a used-percentage with an optional
34
+ * reset time — the atomic unit a provider reports (e.g. a 5-hour session, a
35
+ * weekly cap, or a model-specific window).
36
+ */
37
+ export interface UsageWindow {
38
+ /** Stable id (e.g. `session5h`, `weekly`, `opusWeekly`) — used by the
39
+ * status-bar picker to remember which windows to surface. */
40
+ id: string;
41
+ /** Human label (English; the UI localizes known ids, else shows this). */
42
+ label: string;
43
+ /** Consumed fraction of this window, clamped to 0–100. */
44
+ usedPercent: number;
45
+ /** Window length in minutes (300 = 5h, 10080 = 7d, 1440 = 24h), when known. */
46
+ windowMinutes?: number;
47
+ /** When the window resets (epoch ms), when the provider reports it. */
48
+ resetsAt?: number;
49
+ }
50
+ /** A monetary / credit balance, kept separate from the percentage windows. */
51
+ export interface CreditBalance {
52
+ /** Amount consumed this period, in `currency`. */
53
+ used: number;
54
+ /** Spend/credit cap, when the provider exposes one. */
55
+ limit?: number;
56
+ /** ISO-4217 code (`USD`, `EUR`, …) or `credits` for non-currency units. */
57
+ currency: string;
58
+ /** Period label (English; e.g. `Monthly`, `Credits`). */
59
+ period: string;
60
+ /** When the balance resets (epoch ms), when known. */
61
+ resetsAt?: number;
62
+ }
63
+ /** One provider's usage snapshot. */
64
+ export interface ProviderUsage {
65
+ provider: UsageProvider;
66
+ status: UsageStatus;
67
+ /** How `windows`/`credit` were obtained (absent for states with no data). */
68
+ source?: UsageSource;
69
+ account?: {
70
+ email?: string;
71
+ organization?: string;
72
+ plan?: string;
73
+ };
74
+ /** Quota/rate windows (percentage-based). Empty when none apply. */
75
+ windows: UsageWindow[];
76
+ credit?: CreditBalance;
77
+ /** When this snapshot was produced (epoch ms). */
78
+ updatedAt: number;
79
+ /** Error/hint message for `error` / `authRequired` / `notInstalled` states. */
80
+ message?: string;
81
+ }
82
+ /**
83
+ * `agent/usageStats` request: read usage for exactly these providers — only the
84
+ * ones the user activated. The reader never polls providers not listed here, so
85
+ * inactive providers cost nothing.
86
+ */
87
+ export interface UsageStatsParams {
88
+ providers: UsageProvider[];
89
+ }
90
+ export interface UsageStatsResult {
91
+ usage: ProviderUsage[];
92
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * AI-provider usage statistics: quota/rate windows, plan/account, credit
3
+ * balance and local token tallies read from a coding CLI's on-disk state — its
4
+ * stored OAuth token (→ the provider's official usage API) and/or its local
5
+ * session logs.
6
+ *
7
+ * Surfaced in the desktop's Settings → Providers section and, over the bridge,
8
+ * on the phone. The access path is per-runtime by design (02a §5.8.10): the
9
+ * desktop reads these files natively in Rust; the bridge reads them in TS so a
10
+ * paired phone — which cannot see the PC's disk directly — gets the same data
11
+ * over `agent/usageStats`. The Dart equivalents live in uxnanmobile and are kept
12
+ * in sync manually (see 02e-bridge-integration.md §4.2).
13
+ *
14
+ * Posture: only the CLI's own stored token is read — never browser cookies or
15
+ * user-pasted API keys.
16
+ */
17
+ export {};
18
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../../../src/models/usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uxnan/shared",
3
- "version": "0.0.4-alpha.20260703",
3
+ "version": "0.0.5-alpha.20260711",
4
4
  "description": "Shared JSON-RPC and E2EE contracts for the Uxnan ecosystem (bridge, relay, mobile).",
5
5
  "license": "MPL-2.0",
6
6
  "author": "Luis Donaldo Gamas Vazquez",