@aexhq/sdk 0.77.0 → 0.79.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 CHANGED
@@ -21,8 +21,8 @@ console.log(await aex.account.get());
21
21
  ```
22
22
 
23
23
  `Aex` extends the pinned Brain client. Its sessions, registration, Events, Components and
24
- extension builders are Brain's implementations. SDK 0.77 uses Brain SDK 0.27 and Pi/Codex
25
- 6.2. Images and PDFs use HTTPS URLs; Aex owns attachment publication and expiry. Deploy the matching
24
+ extension builders are Brain's implementations. SDK 0.79 uses Brain SDK 0.29 and Pi/Codex
25
+ 7.0.1. Images and PDFs use HTTPS URLs; Aex owns attachment publication and expiry. Deploy the matching
26
26
  runtime and extensions together. Retained sessions require a compatibility check before upgrading.
27
27
  See https://aex.dev/docs
28
28
  for a complete session example.
@@ -39,7 +39,16 @@ and transforms before the handler. Ordinary objects strip extra properties and s
39
39
  reject them. Pi dispatches in parallel; coordinate shared resources in their owning Tool or
40
40
  Environment. The official loops explain unanswered calls after interruption without replaying them.
41
41
 
42
- Host Tools return ordinary successful output or a Brain `Outcome` directly. Structured errors retain
42
+ Tool return and completion are separate. `return ctx.finish(value)` emits an optional result
43
+ and finishes an ordinary Tool. Returning a value alone emits it and releases the synchronous
44
+ caller; the Tool remains open for `ctx.emitResult(value)` and `ctx.finish()` afterward.
45
+ Background observations wake the Agentloop, which chooses whether to call the model and what
46
+ to put in its transcript. Results and finish always enter the journal. Keep the host client
47
+ connected until all its Tools finish. Interrupt cancels unfinished Tools even while idle.
48
+ A forgotten finish stays open until the original deadline, cancellation or Environment loss;
49
+ without a deadline it can remain open indefinitely.
50
+
51
+ Host Tools accept ordinary successful output or a Brain `Outcome` directly. Structured errors retain
43
52
  code, message, retryable and details. The top-level statuses `ok`, `error`, `timeout`, `cancelled`
44
53
  and `unknown` declare outcomes; malformed envelopes fail validation, and only successful values
45
54
  pass through the output schema. Tool deadlines produce `timeout`, explicit cancellation produces
@@ -99,6 +108,7 @@ await account.keys.update(issued.key.id, { name: "Renamed app" });
99
108
  await account.keys.delete(issued.key.id);
100
109
  await account.account.get(); // includes billing status and limits
101
110
  await account.account.usage();
111
+ await account.account.modelUsage(sessionId);
102
112
  await account.account.logout();
103
113
  ```
104
114
 
@@ -108,3 +118,8 @@ contract for clients. The `@aexhq/cli` package handles opening the browser, PKCE
108
118
  loopback callback and local credential storage.
109
119
 
110
120
  Image and PDF uploads use the [attachment API](../../docs/attachments.md). `models(provider?)` forwards Brain's catalogue unchanged, with models.dev metadata when known. Brain validates model selections; Aex has no separate model allowlist.
121
+
122
+ Token usage reports separate recorded quantities and hosting charges from pending estimates.
123
+ Foreground and background calls use the same meter. Spending control is asynchronous;
124
+ `maxCostMicroUsd` remains a resource-operation ceiling, not a model token budget.
125
+ Your provider separately bills your model key. See [billing](../../docs/billing.md).
@@ -63,6 +63,18 @@ export interface Limits {
63
63
  upstream_timeout_secs: number;
64
64
  usage_max_age_secs: number;
65
65
  }
66
+ /**
67
+ * This interface was referenced by `AexContracts`'s JSON-Schema
68
+ * via the `definition` "TokenUsage".
69
+ */
70
+ export interface TokenUsage {
71
+ charged_micro_usd: number;
72
+ pending_estimate_micro_usd: number;
73
+ rated_micro_usd: number;
74
+ reported_input_tokens: number;
75
+ reported_output_tokens: number;
76
+ unmeasured_calls: number;
77
+ }
66
78
  /**
67
79
  * This interface was referenced by `AexContracts`'s JSON-Schema
68
80
  * via the `definition` "Usage".
@@ -72,6 +84,7 @@ export interface Usage {
72
84
  attachment_bytes: number;
73
85
  attachments: number;
74
86
  measured_at?: number | null;
87
+ model: TokenUsage;
75
88
  retained_bytes: number;
76
89
  sessions: number;
77
90
  }
@@ -155,6 +168,7 @@ export interface Pricebook {
155
168
  rates: {
156
169
  attachment_byte_secs?: Rate;
157
170
  egress_bytes?: Rate;
171
+ model_tokens?: Rate;
158
172
  sandbox_ms?: Rate;
159
173
  turn_ms?: Rate;
160
174
  };
@@ -175,12 +189,14 @@ export interface Rate {
175
189
  */
176
190
  export interface Wallet {
177
191
  accepted_pricebook?: string | null;
192
+ accepted_rates?: Pricebook | null;
178
193
  available_micro_usd: number;
179
194
  balance_micro_usd: number;
180
195
  currency: string;
181
196
  mode: BillingMode;
182
197
  offered_pricebook?: Pricebook | null;
183
198
  payment_mode?: Mode | null;
199
+ pending_estimate_micro_usd: number;
184
200
  reserved_micro_usd: number;
185
201
  spend_limit_micro_usd?: number | null;
186
202
  spent_this_month_micro_usd: number;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export * from "@aexhq/brain";
2
2
  export type * from "./generated.js";
3
3
  import { Brain, type BrainOptions } from "@aexhq/brain";
4
- import type { EnvironmentCatalog } from "./generated.js";
4
+ import type { EnvironmentCatalog, TokenUsage } from "./generated.js";
5
5
  import type { Attachment, Account, Usage, ApiKey, IssuedKey, KeyInput, LoginGrantInput, LoginGrant, LoginExchange, AccountSession, Wallet, BillingSettings, LedgerPage, Topup, TopupInput, Refund, RefundInput, SyncPayment } from "./generated.js";
6
6
  export type AexConnection = Omit<BrainOptions, "token" | "baseUrl"> & {
7
7
  baseUrl?: string;
@@ -18,7 +18,7 @@ export type AexOptions = AexConnection & {
18
18
  export declare class Aex extends Brain {
19
19
  private readonly maxCostMicroUsd?;
20
20
  constructor({ apiKey, accountToken, maxCostMicroUsd, ...options }: AexOptions);
21
- /** The ceiling applies separately to each admitted operation. Model BYOK charges remain with the provider. */
21
+ /** Resource and legacy turn reservations use this ceiling; token hosting follows the account limit. */
22
22
  request<T>(method: string, path: string, body?: unknown, idempotencyKey?: string, contentType?: string, signal?: AbortSignal, extraHeaders?: HeadersInit): Promise<T>;
23
23
  static exchangeLogin(input: LoginExchange, options?: AexConnection): Promise<AccountSession>;
24
24
  readonly attachments: {
@@ -35,6 +35,7 @@ export declare class Aex extends Brain {
35
35
  readonly account: {
36
36
  get: () => Promise<Account>;
37
37
  usage: () => Promise<Usage>;
38
+ modelUsage: (sessionId: string) => Promise<TokenUsage>;
38
39
  logout: () => Promise<void>;
39
40
  authorizeLogin: (input: LoginGrantInput) => Promise<LoginGrant>;
40
41
  };
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ export class Aex extends Brain {
14
14
  nonnegativeInteger(maxCostMicroUsd, "maxCostMicroUsd");
15
15
  this.maxCostMicroUsd = maxCostMicroUsd;
16
16
  }
17
- /** The ceiling applies separately to each admitted operation. Model BYOK charges remain with the provider. */
17
+ /** Resource and legacy turn reservations use this ceiling; token hosting follows the account limit. */
18
18
  request(method, path, body, idempotencyKey, contentType = "application/json", signal, extraHeaders) {
19
19
  const headers = new Headers(extraHeaders);
20
20
  if (this.maxCostMicroUsd !== undefined && !headers.has("x-aex-max-cost-micro-usd"))
@@ -46,6 +46,7 @@ export class Aex extends Brain {
46
46
  account = {
47
47
  get: () => this.request("GET", "/v1/account"),
48
48
  usage: () => this.request("GET", "/v1/usage"),
49
+ modelUsage: (sessionId) => this.request("GET", `/v1/usage/${encodeURIComponent(sessionId)}`),
49
50
  logout: () => this.request("DELETE", "/v1/account/session"),
50
51
  authorizeLogin: (input) => this.request("POST", "/v1/auth/grants", input),
51
52
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aexhq/sdk",
3
- "version": "0.77.0",
3
+ "version": "0.79.0",
4
4
  "description": "Aex accounts and hosted sessions using the Brain SDK",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -28,7 +28,7 @@
28
28
  "tag": "next"
29
29
  },
30
30
  "dependencies": {
31
- "@aexhq/brain": "0.27.0"
31
+ "@aexhq/brain": "0.29.0"
32
32
  },
33
33
  "scripts": {
34
34
  "gen": "node ../../tools/sdk-contracts.mjs",