@loomcycle/client 1.124.0 → 1.126.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/dist/types.d.ts CHANGED
@@ -187,6 +187,81 @@ export interface RunPromptResponse {
187
187
  system: PromptBlock[];
188
188
  input: PromptBlock[];
189
189
  }
190
+ /** Input for {@link LoomcycleClient.runFile} — one File-tool op on the inbox of
191
+ * a run, from outside the run (`POST /v1/runs/{run_id}/file`). The run is the
192
+ * path's; the fields are the tool's own, snake_case as on the wire. download
193
+ * and upload are not offered here: they need a run's HTTP allowlist. */
194
+ export type RunFileInput = {
195
+ op: "stat" | "ls" | "extract" | "import" | "keep" | "rm" | "clear";
196
+ /** stat / ls / rm / extract / import: `volume:inbox:<path>`, or a bare path in the inbox. */
197
+ path?: string;
198
+ /** keep: the inbox file to copy. */
199
+ from?: string;
200
+ /** keep: `volume:<name>:<path>` in a read-write dynamic volume of your tenant. */
201
+ to?: string;
202
+ overwrite?: boolean;
203
+ recursive?: boolean;
204
+ /** clear: one folder of the inbox to empty instead of all of it. */
205
+ prefix?: string;
206
+ images?: boolean;
207
+ max_rows?: number;
208
+ excerpt_chars?: number;
209
+ title?: string;
210
+ doc_path?: string;
211
+ scope?: string;
212
+ tags?: string[];
213
+ /** import: where the document came from, kept on it as a link back. */
214
+ source?: RunFileImportSource;
215
+ /** import: headings to add by line number, so a file whose structure is only
216
+ * in its numbering imports as sections. The file is not changed, so the
217
+ * document keeps the record of where it came from. */
218
+ headings?: RunFileImportHeading[];
219
+ };
220
+ /** import's `source`: the item's web link (a SharePoint `webUrl`, an email's
221
+ * `webLink`), never a download or upload link. */
222
+ export interface RunFileImportSource {
223
+ /** An http(s) link, at most 2048 bytes; a signature in its query is masked. */
224
+ url?: string;
225
+ kind?: "sharepoint" | "email" | "attachment" | "web" | "other";
226
+ /** One line, at most 300 characters. */
227
+ title?: string;
228
+ }
229
+ /** One entry of import's `headings`. Lines count from 1 in the file as it is;
230
+ * give entries in increasing line order. */
231
+ export type RunFileImportHeading =
232
+ /** The line itself becomes a heading; `lines` (1–10) joins a wrapped title. */
233
+ {
234
+ line: number;
235
+ level: 2 | 3 | 4 | 5 | 6;
236
+ as: "heading";
237
+ lines?: number;
238
+ }
239
+ /** A heading with `title` is inserted before the line, which stays body text. */
240
+ | {
241
+ line: number;
242
+ level: 2 | 3 | 4 | 5 | 6;
243
+ as: "marker";
244
+ title: string;
245
+ };
246
+ /** What {@link LoomcycleClient.downloadRunInboxFile} returns: one inbox file's
247
+ * bytes and what the server says about them. */
248
+ export interface RunInboxDownload {
249
+ /** The bytes (empty for a HEAD request). */
250
+ bytes: Uint8Array;
251
+ /** 200, or 206 for a range. */
252
+ status: number;
253
+ /** The type the server served: the recorded type when it is one a browser
254
+ * cannot run, else `application/octet-stream`. */
255
+ contentType: string;
256
+ /** The file's name, from Content-Disposition. */
257
+ filename: string;
258
+ /** SHA-256 (hex) of the file's bytes as served — the whole file, also for a range. */
259
+ sha256: string;
260
+ /** The producer the runtime recorded (`mcp:<server>/<tool>`, `http`, …), or
261
+ * `unknown` when the file changed since it was kept. */
262
+ origin: string;
263
+ headers: Headers;
264
+ }
190
265
  /** The reply from `GET /v1/runs/{run_id}/effective-config` — for every
191
266
  * overridable field, the value this run will actually use and which layer
192
267
  * decided it.
@@ -1361,6 +1436,11 @@ export interface ClientOptions {
1361
1436
  * When present, attached as `Authorization: Bearer <token>` on
1362
1437
  * every request. */
1363
1438
  authToken?: string;
1439
+ /** A source of short-lived bearers, instead of `authToken` (pass one or
1440
+ * the other): every request asks it for the token, and a 401 is retried
1441
+ * once with the token it hands back. An app signed in through loomcycle
1442
+ * passes an `OAuthTokenProvider`, which refreshes before expiry. */
1443
+ tokenProvider?: TokenProvider;
1364
1444
  /** Custom fetch implementation; defaults to global `fetch`.
1365
1445
  * Useful for testing (vi.fn()) or for runtimes that ship their
1366
1446
  * own fetch (e.g. node-fetch on older Node). */
@@ -2045,19 +2125,34 @@ export interface UserSummary {
2045
2125
  registered?: boolean;
2046
2126
  display_name?: string;
2047
2127
  access_mode?: string;
2048
- status?: string;
2128
+ /** The registered user's status; `""` for a subject seen only in runs. */
2129
+ status?: UserStatus | (string & {});
2049
2130
  }
2050
2131
  export interface ListUsersResponse {
2051
2132
  users: UserSummary[];
2052
2133
  }
2053
- /** One first-class users-table row (POST/PATCH /v1/_users). The tenant is
2054
- * server-derived from the authenticated principal, never sent. */
2134
+ /** A first-class user's status.
2135
+ *
2136
+ * - `active` — the user may do what its access mode and bindings allow.
2137
+ * - `disabled` — refused everywhere; its delegated tokens are retired.
2138
+ * - `pending` — provisioned by a sign-in gate whose new users await
2139
+ * approval: the person can sign in, but every request is refused until
2140
+ * {@link LoomcycleClient.approveUser} makes the user `active`. Only a gate
2141
+ * puts a user here and only the approval takes one out, so createUser and
2142
+ * updateUser refuse it.
2143
+ *
2144
+ * Fields typed `UserStatus | (string & {})` still accept a status a newer
2145
+ * server adds. */
2146
+ export type UserStatus = "active" | "disabled" | "pending";
2147
+ /** One first-class users-table row (POST/PATCH /v1/_users). The tenant is the
2148
+ * authenticated principal's, or the one an admin or `auth:manage` caller
2149
+ * names with `opts.tenant`; it is never in the body. */
2055
2150
  export interface UserRecord {
2056
2151
  tenant_id: string;
2057
2152
  subject: string;
2058
2153
  display_name: string;
2059
2154
  access_mode: string;
2060
- status: string;
2155
+ status: UserStatus | (string & {});
2061
2156
  created_at: string;
2062
2157
  created_by: string;
2063
2158
  }
@@ -2067,14 +2162,18 @@ export interface CreateUserBody {
2067
2162
  /** "tenant" (default) collaborates on the tenant's shared primitives;
2068
2163
  * "isolated" confines the member to its own user scope. */
2069
2164
  access_mode?: string;
2070
- status?: string;
2165
+ /** Default `active`. `pending` is refused (400 `invalid_status`). */
2166
+ status?: "active" | "disabled" | (string & {});
2071
2167
  }
2072
2168
  /** PATCH body — an omitted key leaves the column unchanged; a present key
2073
2169
  * (even the empty string) is applied. */
2074
2170
  export interface UpdateUserBody {
2075
2171
  display_name?: string;
2076
2172
  access_mode?: string;
2077
- status?: string;
2173
+ /** `disabled` also retires the user's delegated tokens. `pending` is
2174
+ * refused (400 `invalid_status`), and `active` on a pending user with 409
2175
+ * `use_approve`: call {@link LoomcycleClient.approveUser} instead. */
2176
+ status?: "active" | "disabled" | (string & {});
2078
2177
  }
2079
2178
  /** The show-once result of POST /v1/_users/{subject}/tokens. `token` is the
2080
2179
  * plaintext bearer, returned exactly once and never retrievable again. */
@@ -2127,6 +2226,171 @@ export interface ListUserTokensResponse {
2127
2226
  subject: string;
2128
2227
  tokens: UserTokenMeta[];
2129
2228
  }
2229
+ /** One identity-provider account a user signs in with, from
2230
+ * GET /v1/_users/{subject}/identities. Never a secret. */
2231
+ export interface UserIdentity {
2232
+ /** The configured sign-in gate. */
2233
+ gate: string;
2234
+ /** The provider's issuer, when it reports one. */
2235
+ issuer?: string;
2236
+ /** The account's subject at the provider. */
2237
+ external_subject: string;
2238
+ email?: string;
2239
+ email_verified: boolean;
2240
+ created_at: string;
2241
+ /** Absent until the account has been used to sign in. */
2242
+ last_login_at?: string;
2243
+ }
2244
+ export interface UserIdentitiesResponse {
2245
+ subject: string;
2246
+ identities: UserIdentity[];
2247
+ }
2248
+ /** A sign-in gate's kind. Fields typed with it still accept a kind a newer
2249
+ * server adds. */
2250
+ export type AuthGateKind = "token" | "password" | "oidc" | "oauth" | "external" | "device" | (string & {});
2251
+ /** One configured sign-in gate, from GET /v1/_authgate. Never key material. */
2252
+ export interface AuthGate {
2253
+ name: string;
2254
+ kind: AuthGateKind;
2255
+ label: string;
2256
+ /** Whether a browser can sign in through it. */
2257
+ interactive: boolean;
2258
+ /** The gate's identity map, when it has one: whether it may provision
2259
+ * beyond the new-user floor, the tenant it maps to (or the claim naming
2260
+ * it) and how it provisions users. */
2261
+ trusted?: boolean;
2262
+ tenant?: string;
2263
+ tenant_claim?: string;
2264
+ provision?: string;
2265
+ /** An external gate's signing key. */
2266
+ key?: AuthGateKey;
2267
+ callback_url?: string;
2268
+ discovery_url?: string;
2269
+ /** With `probe: true`: what the external gate's discovery document said. */
2270
+ probe?: AuthGateProbe;
2271
+ /** An external gate's removal timing. */
2272
+ on_removed?: AuthGateRemoval;
2273
+ }
2274
+ /** An external gate's key as configured: algorithm, key id and fingerprint,
2275
+ * or for an HMAC secret the NAME of the env var holding it — never a key. */
2276
+ export interface AuthGateKey {
2277
+ alg: string;
2278
+ kid?: string;
2279
+ fingerprint?: string;
2280
+ secret_env?: string;
2281
+ }
2282
+ /** Durations, e.g. `168h0m0s`; `erase_after` may be `never`. */
2283
+ export interface AuthGateRemoval {
2284
+ unbind_after: string;
2285
+ erase_after: string;
2286
+ }
2287
+ export interface AuthGateProbe {
2288
+ reachable: boolean;
2289
+ /** The discovery document's HTTP status. */
2290
+ status?: number;
2291
+ /** A failure class (`unreachable`, `status`, …), never the response. */
2292
+ error?: string;
2293
+ name_matches: boolean;
2294
+ key_matches: boolean;
2295
+ capabilities?: string[];
2296
+ }
2297
+ export interface AuthGateListResponse {
2298
+ gates: AuthGate[];
2299
+ }
2300
+ /** POST /v1/_authgate/{gate}/invites. The tenant is `opts.tenant`, not a
2301
+ * field here. */
2302
+ export interface CreateInviteBody {
2303
+ /** An existing user to give a login at this gate. It keeps its access mode
2304
+ * and groups: the invite may restate but never raise them. Omitted, the
2305
+ * invite makes a new user when it is redeemed. */
2306
+ subject?: string;
2307
+ /** A new user's access mode, `tenant` or `isolated`; default the gate's
2308
+ * new-user floor. Beyond the floor only on a trusted gate (403
2309
+ * `beyond_floor` otherwise). */
2310
+ access_mode?: string;
2311
+ /** Groups for the new user; each must exist in the tenant. */
2312
+ groups?: string[];
2313
+ /** Fix the login the invitee gets; otherwise the invitee picks one (409
2314
+ * `login_taken` if it is in use at the gate). */
2315
+ login?: string;
2316
+ email?: string;
2317
+ /** How long the link lives, as a Go duration (`72h`); default and maximum
2318
+ * are the gate's. */
2319
+ ttl?: string;
2320
+ /** Where the person lands after redeeming: a path on the server, or one
2321
+ * of the gate's `allowed_return_to`. */
2322
+ return_to?: string;
2323
+ }
2324
+ /** A one-time invite link. `url` carries the code in its fragment: hand it to
2325
+ * the person and do not log it. It is shown once — listing invites never
2326
+ * returns it. */
2327
+ export interface CreatedInvite {
2328
+ invite_id: string;
2329
+ url: string;
2330
+ expires_at: string;
2331
+ }
2332
+ export type AuthInviteState = "live" | "redeemed" | "revoked" | "expired";
2333
+ /** One invite from GET /v1/_authgate/{gate}/invites. Never its code. */
2334
+ export interface AuthInvite {
2335
+ invite_id: string;
2336
+ gate: string;
2337
+ tenant_id: string;
2338
+ /** Set for an invite to an existing user. */
2339
+ subject?: string;
2340
+ access_mode?: string;
2341
+ groups: string[];
2342
+ login?: string;
2343
+ email?: string;
2344
+ return_to?: string;
2345
+ /** The owner invite of a tenant that has never had a user. */
2346
+ bootstrap?: boolean;
2347
+ created_by?: string;
2348
+ created_at: string;
2349
+ expires_at: string;
2350
+ state: AuthInviteState;
2351
+ redeemed_at?: string;
2352
+ redeemed_subject?: string;
2353
+ revoked_at?: string;
2354
+ }
2355
+ export interface AuthInviteListResponse {
2356
+ invites: AuthInvite[];
2357
+ }
2358
+ /** A one-time password-reset link; like {@link CreatedInvite}, `url`
2359
+ * carries the code and is shown once. */
2360
+ export interface CreatedPasswordReset {
2361
+ reset_id: string;
2362
+ url: string;
2363
+ expires_at: string;
2364
+ }
2365
+ /** A user's login at one gate, from GET /v1/_authgate/{gate}/identities. */
2366
+ export interface GateIdentity {
2367
+ gate: string;
2368
+ login: string;
2369
+ email?: string;
2370
+ email_verified: boolean;
2371
+ created_at: string;
2372
+ last_login_at?: string;
2373
+ /** Whether the user has a password set. */
2374
+ has_password: boolean;
2375
+ /** Whether the user has a confirmed authenticator. */
2376
+ has_totp: boolean;
2377
+ }
2378
+ export interface GateIdentitiesResponse {
2379
+ tenant_id: string;
2380
+ subject: string;
2381
+ identities: GateIdentity[];
2382
+ }
2383
+ /** GET /v1/_authgate/{gate}/tenant-status: what a website needs to decide
2384
+ * on an owner (bootstrap) invite, and nothing about who the users are. */
2385
+ export interface GateTenantStatus {
2386
+ tenant_id: string;
2387
+ /** Whether the tenant has a user now. */
2388
+ has_users: boolean;
2389
+ /** Whether it has ever had one; once true, no owner invite or owner create
2390
+ * by an `auth:manage` credential is possible again. */
2391
+ bootstrapped: boolean;
2392
+ bootstrap_invite_live: boolean;
2393
+ }
2130
2394
  /** One entry in the runnable-agent catalog — the name to run + its tier.
2131
2395
  * Intentionally lean: no operator metadata (versions, retired, hashes). */
2132
2396
  export interface RunnableAgent {
@@ -2161,6 +2425,8 @@ export interface WhoamiResponse {
2161
2425
  /** How the caller signed in. Absent on a server that predates Web UI
2162
2426
  * sessions. */
2163
2427
  auth?: WhoamiAuth;
2428
+ /** What narrows the caller's token below its scopes, when anything does. */
2429
+ restrictions?: TokenRestrictions;
2164
2430
  }
2165
2431
  /** GET /v1/_me's sign-in block. `mode` is always present; the rest only when
2166
2432
  * a Web UI session (not a bearer) authenticated the request. */
@@ -2175,6 +2441,10 @@ export interface WhoamiAuth {
2175
2441
  auth_time?: string;
2176
2442
  /** When the session stops authenticating unless renewed by activity. */
2177
2443
  session_expires_at?: string;
2444
+ /** `pending` when the session's user awaits approval: every other request
2445
+ * the session makes is refused until the user is approved. Absent
2446
+ * otherwise. */
2447
+ status?: "pending";
2178
2448
  }
2179
2449
  /** GET /v1/_me's capability summary. Bounded and non-secret: a fixed list of
2180
2450
  * Web UI pages, no per-instance data. */
@@ -2391,11 +2661,12 @@ export interface MemorySearchInput {
2391
2661
  *
2392
2662
  * The four document filters need a search that can return documents (no
2393
2663
  * `sources`, or `sources` including `"documents"`; otherwise 400
2394
- * `invalid_filter`), are refused on `scope: "tenant"` (400 `invalid_filter`),
2395
- * and need SQL Memory on the server (400 `filter_unavailable`). They resolve in
2396
- * the caller's own tenant. The response then carries {@link
2397
- * MemorySearchResponse.filter}. For chunk-level filters (type, status, tags, a
2398
- * validity instant) use `document({ op: "search" })`. */
2664
+ * `invalid_filter`) and SQL Memory on the server (400 `filter_unavailable`).
2665
+ * They resolve in the caller's own tenant. With a {@link documentsScope}
2666
+ * different from `scope` they aim at that scope's documents instead. The
2667
+ * response then carries {@link MemorySearchResponse.filter}. For chunk-level
2668
+ * filters (type, status, tags, a validity instant) use
2669
+ * `document({ op: "search" })`. */
2399
2670
  underPaths?: string[];
2400
2671
  /** Never return the chunks of documents named at or under these paths (sent as
2401
2672
  * `exclude_under_paths`). Documents only, as {@link underPaths}. */
@@ -2406,6 +2677,23 @@ export interface MemorySearchInput {
2406
2677
  /** Never return the chunks of these documents (sent as
2407
2678
  * `exclude_document_ids`). Documents only, as {@link underPaths}. */
2408
2679
  excludeDocumentIds?: string[];
2680
+ /** Also search the DOCUMENTS of this scope in the same call (sent as
2681
+ * `documents_scope`): for example a user's own notes together with the
2682
+ * tenant's reference documents. Both are ranked into one list under one
2683
+ * `topK`, and each entry then carries {@link MemorySearchEntry.scope}. Only
2684
+ * documents come from this scope; facts and notes still come from `scope`.
2685
+ * The four document filters aim at this scope's documents.
2686
+ *
2687
+ * Equal to `scope` (and {@link documentsScopeId} omitted or equal to
2688
+ * `scopeId`), it is the same as adding `"documents"` to `sources`. It cannot
2689
+ * be combined with `sources: ["traces"]` (400 `invalid_documents_scope`). A
2690
+ * caller whose access does not reach that scope's documents gets 403. */
2691
+ documentsScope?: "agent" | "user" | "tenant";
2692
+ /** The subject of {@link documentsScope} (sent as `documents_scope_id`): the
2693
+ * agent name or user id. Required when `documentsScope` is `"agent"` or
2694
+ * `"user"` and differs from `scope`; ignored for `"tenant"`. The tenant is
2695
+ * always the caller's own. */
2696
+ documentsScopeId?: string;
2409
2697
  }
2410
2698
  /** What a document filter on {@link LoomcycleClient.memorySearch} resolved to —
2411
2699
  * present on the response ONLY when a filter was sent. */
@@ -2427,6 +2715,9 @@ export interface MemorySearchDocumentFilter {
2427
2715
  * false while access-control rules can deny the caller reading part of the
2428
2716
  * scope — the counts then cover only documents it may read. */
2429
2717
  inverted: boolean;
2718
+ /** The scope the filter resolved in — present when it aimed at a
2719
+ * {@link MemorySearchInput.documentsScope} different from `scope`. */
2720
+ scope?: "agent" | "user" | "tenant";
2430
2721
  }
2431
2722
  /** The observed-time predicate on {@link MemorySearchInput}. Timestamps are
2432
2723
  * RFC3339 instants — resolve phrases like "the first weekend of October"
@@ -2501,6 +2792,10 @@ export interface MemorySearchEntry {
2501
2792
  kind: "description" | "claim" | "question";
2502
2793
  text: string;
2503
2794
  };
2795
+ /** The scope this hit came from — present on every entry when the request
2796
+ * set a {@link MemorySearchInput.documentsScope} different from `scope`, so
2797
+ * the caller's own memory can be told from the other scope's documents. */
2798
+ scope?: "agent" | "user" | "tenant";
2504
2799
  }
2505
2800
  export interface MemorySearchResponse {
2506
2801
  scope: string;
@@ -2518,6 +2813,11 @@ export interface MemorySearchResponse {
2518
2813
  /** What the document filter resolved to — present only when one was sent
2519
2814
  * ({@link MemorySearchInput.underPaths} and its siblings). */
2520
2815
  filter?: MemorySearchDocumentFilter;
2816
+ /** The second scope searched for documents and its store scope id ("" for
2817
+ * tenant) — present only when the request set a
2818
+ * {@link MemorySearchInput.documentsScope} different from `scope`. */
2819
+ documents_scope?: "agent" | "user" | "tenant";
2820
+ documents_scope_id?: string;
2521
2821
  }
2522
2822
  export interface MemoryTimeFilter {
2523
2823
  mode: "prefer" | "require";
@@ -4342,6 +4642,16 @@ export interface AgentTranscription {
4342
4642
  /** At most the operator's `transcription.stt.max_minutes_per_run`. */
4343
4643
  max_minutes_per_run?: number;
4344
4644
  }
4645
+ /** An agent's text-to-speech settings. It can switch speech off for the agent
4646
+ * and lower the operator's per-run character cap; it can never raise it or
4647
+ * pick an engine, a model or a voice list. */
4648
+ export interface AgentSpeech {
4649
+ /** Whether the agent may speak. Default `true` when the operator configured
4650
+ * an engine; `false` switches it off for this agent. */
4651
+ enabled?: boolean;
4652
+ /** At most the operator's `speech.max_chars_per_run`. */
4653
+ max_chars_per_run?: number;
4654
+ }
4345
4655
  /** The `context` block of an {@link AgentDefOverlay}: {@link ContextOptions}
4346
4656
  * in its wire spelling — see there for what each field does. A fork merges it
4347
4657
  * per field, and the spawn tree inherits it. */
@@ -4538,6 +4848,8 @@ export interface AgentDefOverlay {
4538
4848
  compaction?: AgentCompaction;
4539
4849
  /** OCR and speech-to-text settings, merged per field. */
4540
4850
  transcription?: AgentTranscription;
4851
+ /** Text-to-speech settings, merged per field. */
4852
+ speech?: AgentSpeech;
4541
4853
  /** How history is distilled, merged per field. */
4542
4854
  context?: AgentContext;
4543
4855
  /** Volumes the file and exec tools may resolve paths against. None declared
@@ -5409,7 +5721,17 @@ export interface LLMEmbeddingsResponse {
5409
5721
  usage: LLMEmbeddingsUsage;
5410
5722
  }
5411
5723
  /** A whitelisted grouping dimension for the usage report. */
5412
- export type UsageDimension = "tenant" | "user" | "provider" | "model" | "source";
5724
+ export type UsageDimension = "tenant" | "user" | "provider" | "model" | "source"
5725
+ /** What the calls were for (see `UsageAggregate.purpose`). */
5726
+ | "purpose"
5727
+ /** The model tier the calls were resolved through; "pinned" for a named model. */
5728
+ | "tier" | "user_tier"
5729
+ /** The agent that made the calls — the per-call detail window only. */
5730
+ | "agent"
5731
+ /** foreground | background, derived from the purpose. */
5732
+ | "class";
5733
+ /** The period a usage report splits its window into (UTC; weeks start Monday). */
5734
+ export type UsageBucket = "hour" | "day" | "week" | "month";
5413
5735
  /** One grouped row of a usage report; only the grouped dimensions are set. */
5414
5736
  export interface UsageAggregate {
5415
5737
  tenant_id?: string;
@@ -5418,6 +5740,21 @@ export interface UsageAggregate {
5418
5740
  model?: string;
5419
5741
  /** operator | tenant | user */
5420
5742
  credential_source?: string;
5743
+ /** chat | gateway | consolidation | rerank | decision | compaction | recap |
5744
+ * unit_generation | image_description | embedding | ocr | stt | tts — set
5745
+ * when grouped by `purpose`. */
5746
+ purpose?: string;
5747
+ tier?: string;
5748
+ user_tier?: string;
5749
+ agent?: string;
5750
+ /** foreground | background — set when grouped by `class`. */
5751
+ class?: string;
5752
+ /** RFC 3339 start of the UTC period the row sums, when a bucket was asked for. */
5753
+ period?: string;
5754
+ /** The row folds every value of the first dimension outside `top`. */
5755
+ other?: boolean;
5756
+ /** Characters text-to-speech and embedding calls sent; absent when none. */
5757
+ input_chars?: number;
5421
5758
  input_tokens: number;
5422
5759
  output_tokens: number;
5423
5760
  cache_creation_tokens: number;
@@ -5426,12 +5763,20 @@ export interface UsageAggregate {
5426
5763
  currency?: string;
5427
5764
  call_count: number;
5428
5765
  unpriced_calls: number;
5766
+ /** Seconds of audio the group's speech calls transcribed (stt) or produced
5767
+ * (tts), the unit a per-minute price is computed from; absent when it has none. */
5768
+ audio_seconds?: number;
5429
5769
  }
5430
5770
  export interface UsageReportResponse {
5431
5771
  group_by: string[];
5432
5772
  from?: string;
5433
5773
  to?: string;
5774
+ bucket?: UsageBucket;
5434
5775
  rows: UsageAggregate[];
5776
+ /** The oldest instant the per-call ledger holds; before it only whole days
5777
+ * survive, so hour buckets and the agent dimension stop there. Absent when
5778
+ * nothing is archived. */
5779
+ detail_since?: string;
5435
5780
  }
5436
5781
  /** A per-scope token budget (RFC AW) plus its live month-to-date usage.
5437
5782
  * `soft_limit` / `hard_limit` are absent when that tier is unset (no ceiling
@@ -6754,3 +7099,239 @@ export interface AuthzSimulateResponse {
6754
7099
  /** Lists the draft's bindings name that no layer has. */
6755
7100
  missing_acls: string[] | null;
6756
7101
  }
7102
+ /** The authorization server's metadata (RFC 8414), from
7103
+ * `GET /.well-known/oauth-authorization-server`. Published only when the
7104
+ * server knows its public address (`LOOMCYCLE_PUBLIC_URL`). */
7105
+ export interface OAuthServerMetadata {
7106
+ issuer: string;
7107
+ authorization_endpoint: string;
7108
+ token_endpoint: string;
7109
+ revocation_endpoint: string;
7110
+ response_types_supported: string[];
7111
+ grant_types_supported: string[];
7112
+ code_challenge_methods_supported: string[];
7113
+ token_endpoint_auth_methods_supported: string[];
7114
+ revocation_endpoint_auth_methods_supported: string[];
7115
+ /** The server adds `iss` to every authorization response (RFC 9207). */
7116
+ authorization_response_iss_parameter_supported: boolean;
7117
+ }
7118
+ /** The token endpoint's answer (RFC 6749 §5.1). */
7119
+ export interface OAuthTokenResponse {
7120
+ access_token: string;
7121
+ /** Always `Bearer`. */
7122
+ token_type: string;
7123
+ /** Seconds the access token lives. */
7124
+ expires_in: number;
7125
+ /** Single use: each refresh returns a new one and spends the old one.
7126
+ * Presenting a spent one ends the whole sign-in. */
7127
+ refresh_token: string;
7128
+ }
7129
+ /** A token answer with the moment the access token expires — what a caller
7130
+ * persists. */
7131
+ export interface OAuthTokenSet extends OAuthTokenResponse {
7132
+ /** When the access token expires, in milliseconds since the epoch
7133
+ * (`Date.now()` at receipt plus `expires_in`). */
7134
+ expires_at: number;
7135
+ }
7136
+ /** Input to `LoomcycleOAuth.beginAuthorize`. */
7137
+ export interface BeginAuthorizeOptions {
7138
+ /** The app's registered client id. */
7139
+ clientId: string;
7140
+ /** One of the app's registered redirect URIs, exactly (a loopback one may
7141
+ * carry any port). */
7142
+ redirectUri: string;
7143
+ /** An opaque value to round-trip; a random one is generated when omitted.
7144
+ * 1 to 1024 characters. */
7145
+ state?: string;
7146
+ }
7147
+ /** What `LoomcycleOAuth.beginAuthorize` returns. Persist `verifier` and
7148
+ * `state` (session storage, never a URL) until the redirect comes back, then
7149
+ * send the person to `url`. */
7150
+ export interface AuthorizeRequest {
7151
+ url: string;
7152
+ /** The PKCE code verifier. A secret until the exchange: keep it out of
7153
+ * URLs and logs. */
7154
+ verifier: string;
7155
+ state: string;
7156
+ }
7157
+ /** The parameters the server puts on the redirect back to the app: `code`
7158
+ * on success, `error` (+ `error_description`) otherwise, `state` as sent,
7159
+ * and `iss` when the server knows its issuer (RFC 9207). */
7160
+ export interface AuthorizeResponseParams {
7161
+ code?: string;
7162
+ state?: string;
7163
+ iss?: string;
7164
+ error?: string;
7165
+ error_description?: string;
7166
+ }
7167
+ /** Input to `LoomcycleOAuth.completeAuthorize`: the redirect's parameters
7168
+ * plus what `beginAuthorize` returned. */
7169
+ export interface CompleteAuthorizeOptions extends AuthorizeResponseParams {
7170
+ /** The `state` beginAuthorize returned; a redirect carrying any other is
7171
+ * refused before the code is used. */
7172
+ expectedState: string;
7173
+ verifier: string;
7174
+ clientId: string;
7175
+ /** The same redirect URI the authorization request named. */
7176
+ redirectUri: string;
7177
+ signal?: AbortSignal;
7178
+ }
7179
+ /** Input to `LoomcycleOAuth.refresh`. */
7180
+ export interface RefreshTokenOptions {
7181
+ refreshToken: string;
7182
+ clientId: string;
7183
+ signal?: AbortSignal;
7184
+ }
7185
+ /** Input to `LoomcycleOAuth.revoke`. */
7186
+ export interface RevokeTokenOptions {
7187
+ /** A refresh token (ends the whole sign-in) or an access token (ends that
7188
+ * token only). */
7189
+ token: string;
7190
+ clientId: string;
7191
+ signal?: AbortSignal;
7192
+ }
7193
+ /** Supplies the bearer for every request of a `LoomcycleClient` built with
7194
+ * `tokenProvider` instead of `authToken`. `OAuthTokenProvider` implements it
7195
+ * for an app sign-in; any other source of short-lived tokens can too. */
7196
+ export interface TokenProvider {
7197
+ /** The token for the next request, refreshed ahead of expiry; undefined
7198
+ * sends none. A throw fails the request with that error. */
7199
+ getToken(): Promise<string | undefined>;
7200
+ /** Called at most once per request, after the server answered 401 to
7201
+ * `rejected`: a different token to retry with once, or undefined to let
7202
+ * the 401 stand. */
7203
+ onUnauthorized?(rejected: string | undefined): Promise<string | undefined>;
7204
+ }
7205
+ /** A client's refresh-token lifetimes: Go durations or whole days (`"7d"`). */
7206
+ export interface AppClientRefresh {
7207
+ idle?: string;
7208
+ absolute?: string;
7209
+ }
7210
+ /** An app client's definition: an entry of the config's `auth.clients`, and
7211
+ * the body of a ClientDef. */
7212
+ export interface AppClientConfig {
7213
+ /** `public`, the only kind: the app holds no secret and PKCE binds a code
7214
+ * to it. */
7215
+ kind: string;
7216
+ /** The name the login page shows. */
7217
+ label?: string;
7218
+ /** Exact https URIs, loopback URIs (any port, exact path) and private-use
7219
+ * scheme URIs (`myapp://callback`). */
7220
+ redirect_uris: string[];
7221
+ /** Origins allowed to call the token and revoke endpoints from a browser:
7222
+ * https, loopback, `chrome-extension://`, `moz-extension://`, `tauri://`. */
7223
+ allowed_origins?: string[];
7224
+ /** Go duration, 1m to 24h; default 1h. */
7225
+ access_token_ttl?: string;
7226
+ refresh?: AppClientRefresh;
7227
+ /** Narrows every token the client's sign-ins mint, as a token's
7228
+ * restrictions record does. */
7229
+ restrictions?: Record<string, unknown>;
7230
+ }
7231
+ /** The body of `POST /v1/_clientdef`. */
7232
+ export interface ClientDefInput {
7233
+ op: "create" | "update" | "get" | "list" | "retire" | "verify";
7234
+ /** The client id. Unique across the deployment, retired names included. */
7235
+ name?: string;
7236
+ def_id?: string;
7237
+ client?: AppClientConfig;
7238
+ description?: string;
7239
+ /** Admin only. On create: the tenant whose people the client signs in, ""
7240
+ * (the default) for every tenant. On list: focus one tenant. A tenant
7241
+ * operator's clients are always its own tenant's. */
7242
+ tenant?: string;
7243
+ /** verify: the content hash to compare with the deployed one. */
7244
+ content_sha256?: string;
7245
+ }
7246
+ /** A runtime-registered client (a ClientDef version). */
7247
+ export interface ClientDefRecord {
7248
+ name: string;
7249
+ source: "def";
7250
+ def_id: string;
7251
+ version: number;
7252
+ /** The tenant whose people it signs in; "" for every tenant. */
7253
+ tenant_id: string;
7254
+ all_tenants: boolean;
7255
+ label: string;
7256
+ redirect_uris: string[];
7257
+ /** The definition as stored. */
7258
+ client: AppClientConfig;
7259
+ description: string;
7260
+ content_sha256: string;
7261
+ created_at: string;
7262
+ created_by: string;
7263
+ created_by_tenant: string;
7264
+ read_only: false;
7265
+ }
7266
+ /** A client declared in the server's config: read only through the API. */
7267
+ export interface ConfigAppClient {
7268
+ name: string;
7269
+ source: "config";
7270
+ label: string;
7271
+ all_tenants: true;
7272
+ tenant_id: string;
7273
+ redirect_uris: string[];
7274
+ allowed_origins: string[];
7275
+ access_token_ttl: string;
7276
+ refresh_idle: string;
7277
+ refresh_absolute: string;
7278
+ read_only: true;
7279
+ }
7280
+ /** A client as `get` and `list` report it. */
7281
+ export type AppClientEntry = ClientDefRecord | ConfigAppClient;
7282
+ /** `op: "list"`: the clients the caller may see, config ones included. */
7283
+ export interface ClientDefListResponse {
7284
+ clients: AppClientEntry[];
7285
+ }
7286
+ /** `op: "verify"`: whether a client is deployed and matches a hash. An absent
7287
+ * client (or one the caller may not see) answers `deployed: false`. */
7288
+ export interface ClientDefVerifyResult {
7289
+ name: string;
7290
+ deployed: boolean;
7291
+ current_def_id?: string;
7292
+ current_sha256?: string;
7293
+ version?: number;
7294
+ matches: boolean;
7295
+ }
7296
+ /** `op: "retire"`. */
7297
+ export interface ClientDefRetireResult {
7298
+ name: string;
7299
+ retired: boolean;
7300
+ }
7301
+ /** One row of `GET /v1/_clientdef/names`. */
7302
+ export interface ClientDefNameSummary {
7303
+ name: string;
7304
+ source: "def" | "config";
7305
+ tenant_id: string;
7306
+ label: string;
7307
+ read_only: boolean;
7308
+ }
7309
+ export interface ClientDefNamesResponse {
7310
+ names: ClientDefNameSummary[];
7311
+ }
7312
+ /** What to show the person: open `verificationUri` and type `userCode`, or
7313
+ * open `verificationUriComplete`, which carries the code. */
7314
+ export interface DeviceLoginPrompt {
7315
+ userCode: string;
7316
+ verificationUri: string;
7317
+ verificationUriComplete?: string;
7318
+ /** Seconds until the code expires. */
7319
+ expiresIn: number;
7320
+ }
7321
+ export interface DeviceLoginOptions {
7322
+ /** How the client names itself on the approval page (default "loomcycle-ts"). */
7323
+ clientId?: string;
7324
+ /** Called once with the code to show; polling starts after it returns. */
7325
+ onPrompt: (prompt: DeviceLoginPrompt) => void | Promise<void>;
7326
+ signal?: AbortSignal;
7327
+ }
7328
+ /** The token issued to the person who approved the login: their own member
7329
+ * token, never wider than the session they approved from and never living
7330
+ * past it. Keep it in an OS credential store, never a plain file. */
7331
+ export interface DeviceLoginResult {
7332
+ accessToken: string;
7333
+ tokenType: string;
7334
+ /** Seconds until the token expires. */
7335
+ expiresIn?: number;
7336
+ scope?: string[];
7337
+ }