@ingram-cloud/sdk 1.1.0 → 1.4.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/client.js CHANGED
@@ -143,6 +143,13 @@ export class IngramCloud {
143
143
  body,
144
144
  }),
145
145
  },
146
+ /** End-user BYOK (#170): a smith's own provider keys, resolved ahead of the
147
+ * tenant's so the end-user's provider account is billed. Never read back. */
148
+ modelKeys: {
149
+ list: (pid, opts) => this.data("GET", `/smiths/${enc(pid)}/model_keys`, opts),
150
+ put: (pid, provider, body, opts) => this.json("PUT", `/smiths/${enc(pid)}/model_keys/${enc(provider)}`, { ...opts, body }),
151
+ delete: (pid, provider, opts) => this.empty("DELETE", `/smiths/${enc(pid)}/model_keys/${enc(provider)}`, opts),
152
+ },
146
153
  schedules: {
147
154
  list: (pid, opts) => this.data("GET", `/smiths/${enc(pid)}/schedules`, opts),
148
155
  create: (pid, body, opts) => this.json("POST", `/smiths/${enc(pid)}/schedules`, {
@@ -246,6 +253,13 @@ export class IngramCloud {
246
253
  rawBody: form,
247
254
  });
248
255
  },
256
+ /** The template's HTML bundle — the same bytes the agent's MCP endpoint
257
+ * serves, so a host can render a panel without vendoring a copy.
258
+ * Tenant-authed: call it server-side and proxy to your chat UI. */
259
+ content: (aid, name, opts) => this.request("GET", `/agents/${enc(aid)}/ui/${enc(name)}/content`, {
260
+ ...opts,
261
+ headers: { accept: "text/html", ...opts?.headers },
262
+ }).then((r) => r.text()),
249
263
  delete: (aid, name, opts) => this.json("DELETE", `/agents/${enc(aid)}/ui/${enc(name)}`, opts),
250
264
  },
251
265
  };
@@ -314,6 +328,9 @@ export class IngramCloud {
314
328
  usage = {
315
329
  /** Token/cost/run totals grouped by app, smith, model, or customer. */
316
330
  breakdown: (query, opts) => this.json("GET", "/usage", { ...opts, query }),
331
+ /** The raw billable-usage event ledger (keyset-paginated, newest first) — the
332
+ * per-event rows the breakdown aggregates. */
333
+ events: (query, opts) => this.page("/usage/events", query, opts),
317
334
  };
318
335
  // ── Files (the OpenAI Files API) ─────────────────────────────────────────
319
336
  files = {
@@ -381,7 +398,14 @@ export class IngramCloud {
381
398
  body,
382
399
  }),
383
400
  delete: (wid, opts) => this.empty("DELETE", `/tenant/webhooks/${enc(wid)}`, opts),
401
+ /** Rotate the signing secret, returning the new one exactly once. Pass
402
+ * `grace_seconds` to keep the old secret accepted during an overlap window. */
403
+ rotateSecret: (wid, body, opts) => this.json("POST", `/tenant/webhooks/${enc(wid)}/rotate_secret`, { ...opts, body: body ?? {} }),
384
404
  test: (wid, opts) => this.json("POST", `/tenant/webhooks/${enc(wid)}/test`, opts),
405
+ /** The persisted delivery attempts for a webhook (durable retry audit trail). */
406
+ deliveries: (wid, query, opts) => this.page(`/tenant/webhooks/${enc(wid)}/deliveries`, query, opts),
407
+ /** Force a fresh delivery attempt for one record (e.g. after the endpoint recovers). */
408
+ redeliver: (wid, did, opts) => this.json("POST", `/tenant/webhooks/${enc(wid)}/deliveries/${enc(did)}/redeliver`, opts),
385
409
  },
386
410
  providers: {
387
411
  list: (opts) => this.data("GET", "/tenant/providers", opts),
@@ -438,7 +462,19 @@ export class IngramCloud {
438
462
  delete: (opts) => this.empty("DELETE", "/tenant/email", opts),
439
463
  },
440
464
  };
441
- // ── Organization (org token: projects + billing) ────────────────────────
465
+ // ── Delegated connector consent (connector OAuth, #123) ─────────────────
466
+ // Tenant-admin token. The tenant's hosted consent page (the provider's
467
+ // `authorize_url`) reads the pending request, then completes or declines it
468
+ // server-to-server; the returned `redirect_url` is where to 302 the browser.
469
+ oauth = {
470
+ authorizeRequests: {
471
+ get: (requestId, opts) => this.json("GET", `/oauth/authorize-requests/${enc(requestId)}`, opts),
472
+ complete: (requestId, body, opts) => this.json("POST", `/oauth/authorize-requests/${enc(requestId)}/complete`, { ...opts, body }),
473
+ decline: (requestId, opts) => this.json("POST", `/oauth/authorize-requests/${enc(requestId)}/decline`, opts),
474
+ },
475
+ };
476
+ // ── Organization (org token: projects + tokens) ─────────────────────────
477
+ // Note: the `/v1/organization/billing/*` surface is not yet wrapped here.
442
478
  organization = {
443
479
  projects: {
444
480
  list: (opts) => this.data("GET", "/organization/projects", opts),
@@ -67,6 +67,8 @@ export const AgentDraft = z
67
67
  model: z.string().nullable(),
68
68
  enabled_hosted_tools: z.array(z.string()),
69
69
  vector_store_ids: z.array(z.string()),
70
+ /** Registered MCP servers this agent's smiths load, by name. Null = all. */
71
+ mcp_servers: z.array(z.string()).nullable(),
70
72
  auto_memory: z.boolean().nullable(),
71
73
  memory_consolidation: z.boolean().nullable(),
72
74
  variables: z.array(AgentVariable),
@@ -87,6 +89,8 @@ export const AgentOut = z
87
89
  rollout_version: z.number().int().nullable(),
88
90
  rollout_percent: z.number().int(),
89
91
  smith_count: z.number().int().optional(),
92
+ /** Newest run across every smith of this agent. Null until one runs. */
93
+ last_activity_at: z.string().nullable().optional(),
90
94
  created_at: z.string().nullable(),
91
95
  updated_at: z.string().nullable(),
92
96
  })
@@ -101,6 +105,7 @@ export const AgentVersionOut = z
101
105
  model: z.string().nullish(),
102
106
  enabled_hosted_tools: z.array(z.string()).optional(),
103
107
  vector_store_ids: z.array(z.string()).optional(),
108
+ mcp_servers: z.array(z.string()).nullish(),
104
109
  auto_memory: z.boolean().nullish(),
105
110
  memory_consolidation: z.boolean().nullish(),
106
111
  variables: z.array(AgentVariable).optional(),
@@ -123,6 +128,8 @@ export const AgentIn = z
123
128
  model: z.string().nullish(),
124
129
  enabled_hosted_tools: z.array(z.string()).nullish(),
125
130
  vector_store_ids: z.array(z.string()).nullish(),
131
+ /** Scope runs to these registered MCP servers (by name). Null/omitted = all. */
132
+ mcp_servers: z.array(z.string()).nullish(),
126
133
  auto_memory: z.boolean().nullish(),
127
134
  memory_consolidation: z.boolean().nullish(),
128
135
  variables: z.array(AgentVariable).nullish(),
@@ -135,6 +142,9 @@ export const AgentPatch = z
135
142
  model: z.string().nullish(),
136
143
  enabled_hosted_tools: z.array(z.string()).nullish(),
137
144
  vector_store_ids: z.array(z.string()).nullish(),
145
+ /** Scope runs to these registered MCP servers (by name). An explicit null
146
+ * clears the restriction (= all); omitted leaves it unchanged. */
147
+ mcp_servers: z.array(z.string()).nullish(),
138
148
  auto_memory: z.boolean().nullish(),
139
149
  memory_consolidation: z.boolean().nullish(),
140
150
  variables: z.array(AgentVariable).nullish(),
@@ -31,7 +31,17 @@ export const DeploymentTarget = z
31
31
  * (`DeploymentIn.kind`) and the response (`DeploymentOut.kind`); the API derives
32
32
  * its accepted-kinds set from these options, so the enum is the discoverable list. */
33
33
  export const DeploymentKind = z
34
- .enum(["whatsapp", "telegram", "slack", "discord", "sms", "voice", "email", "mcp"])
34
+ .enum([
35
+ "whatsapp",
36
+ "telegram",
37
+ "slack",
38
+ "discord",
39
+ "sms",
40
+ "voice",
41
+ "email",
42
+ "mcp",
43
+ "web",
44
+ ])
35
45
  .meta({ id: "DeploymentKind" });
36
46
  export const DeploymentOut = z
37
47
  .object({
@@ -46,6 +56,9 @@ export const DeploymentOut = z
46
56
  /** The connectable MCP endpoint — present only for `kind: "mcp"`. Paste into
47
57
  * Claude / ChatGPT as the server URL; survives a later GET, not just create. */
48
58
  mcp_url: z.string().optional(),
59
+ /** The shareable hosted-page URL — present only for `kind: "web"`. Open in a
60
+ * browser to chat with the agent; survives a later GET, not just create. */
61
+ page_url: z.string().optional(),
49
62
  status: z.string(),
50
63
  created_at: z.string().nullable(),
51
64
  })
@@ -59,6 +72,7 @@ export const DeploymentListOut = pageOut(DeploymentOut, "DeploymentListOut");
59
72
  * - slack `provision`/`oauth_install`: `install_url`, `state`, optional `slack_app_id`.
60
73
  * - email `provision`: no extras (plain `DeploymentOut`).
61
74
  * - mcp: `mcp_url` (on the base `DeploymentOut`, so it also survives a GET).
75
+ * - web: `page_url` (on the base `DeploymentOut`, so it also survives a GET).
62
76
  * All are optional — which appear depends on the kind + setup mode.
63
77
  */
64
78
  export const DeploymentCreatedOut = DeploymentOut.extend({
package/dist/zod/mcp.js CHANGED
@@ -67,11 +67,17 @@ export const McpServerOut = z
67
67
  approval_policy: z.array(ApprovalRule).optional(),
68
68
  tools: z.array(McpTool),
69
69
  tools_refreshed_at: z.string().nullable(),
70
- /** `degraded` when the edge failed discovery or its secret can't be decoded
71
- * at run time; otherwise the stored lifecycle status. */
70
+ /** `degraded` when the edge failed discovery, its secret can't be decoded at
71
+ * run time, or its last `tools/call` failed at the transport level;
72
+ * otherwise the stored lifecycle status. */
72
73
  status: z.string(),
73
- /** Last discovery/runtime-load failure, or null when the edge is healthy. */
74
+ /** Last discovery/runtime-load failure, or null when discovery is healthy. */
74
75
  discovery_error: z.string().nullable(),
76
+ /** Last transport-level `tools/call` failure (network / HTTP status), or
77
+ * null. Discovery can succeed while calls fail — this catches that. Cleared
78
+ * by a successful call or a re-PUT. */
79
+ last_call_error: z.string().nullable(),
80
+ last_call_error_at: z.string().nullable(),
75
81
  created_at: z.string().nullable(),
76
82
  })
77
83
  .meta({ id: "McpServerOut" });
@@ -95,7 +101,9 @@ export const McpAuthIn = z
95
101
  })
96
102
  .meta({ id: "McpAuthIn" });
97
103
  /** Register or replace a server: supply a raw `url` + `auth`, or a `catalog`
98
- * slug (catalog defaults are stamped down, body fields override). */
104
+ * slug (catalog defaults are stamped down, body fields override). PUT is a
105
+ * full replace and `auth.kind` is required unless a catalog preset supplies
106
+ * it — there is no implicit `none`. */
99
107
  export const McpServerIn = z
100
108
  .object({
101
109
  url: z.string().nullish(),
@@ -63,6 +63,7 @@ export const TraceOut = z
63
63
  id: z.string(),
64
64
  smith_id: z.string(),
65
65
  app_id: z.string().nullable(),
66
+ run_id: z.string().nullable(),
66
67
  root_kind: ICSpanKindEnum,
67
68
  name: z.string(),
68
69
  status: z.string(),
@@ -25,8 +25,11 @@ export const SmithRevisionOut = z
25
25
  model: z.string().nullish(),
26
26
  enabled_hosted_tools: z.array(z.string()).optional(),
27
27
  vector_store_ids: z.array(z.string()).optional(),
28
- auto_memory: z.boolean().optional(),
29
- memory_consolidation: z.boolean().optional(),
28
+ mcp_servers: z.array(z.string()).nullish(),
29
+ // Nullish: a snapshot taken while the smith inherited a sparse agent
30
+ // version carries null (= the default) for these.
31
+ auto_memory: z.boolean().nullish(),
32
+ memory_consolidation: z.boolean().nullish(),
30
33
  }),
31
34
  created_by: z.string().nullish(),
32
35
  note: z.string().nullish(),
@@ -36,6 +36,8 @@ export const SmithOut = z
36
36
  rendered_instructions: z.string().nullish(),
37
37
  enabled_hosted_tools: z.array(z.string()).optional(),
38
38
  vector_store_ids: z.array(z.string()).optional(),
39
+ /** Registered MCP servers this smith's runs load, by name. Null = all. */
40
+ mcp_servers: z.array(z.string()).nullish(),
39
41
  auto_memory: z.boolean().optional(),
40
42
  memory_consolidation: z.boolean().optional(),
41
43
  /** How the config resolved: by reference, with overrides, or embedded. */
@@ -55,6 +57,7 @@ export const SmithOut = z
55
57
  instructions: z.string().nullable(),
56
58
  enabled_hosted_tools: z.array(z.string()),
57
59
  vector_store_ids: z.array(z.string()),
60
+ mcp_servers: z.array(z.string()).nullable(),
58
61
  auto_memory: z.boolean().nullable(),
59
62
  memory_consolidation: z.boolean().nullable(),
60
63
  })
@@ -85,6 +88,8 @@ export const SmithCreate = z
85
88
  instructions: z.string().nullish(),
86
89
  enabled_hosted_tools: z.array(z.string()).nullish(),
87
90
  vector_store_ids: z.array(z.string()).nullish(),
91
+ /** Scope this smith's runs to these registered MCP servers (by name). */
92
+ mcp_servers: z.array(z.string()).nullish(),
88
93
  auto_memory: z.boolean().nullish(),
89
94
  memory_consolidation: z.boolean().nullish(),
90
95
  })
@@ -102,6 +107,9 @@ export const SmithPatch = z
102
107
  instructions: z.string().nullish(),
103
108
  enabled_hosted_tools: z.array(z.string()).nullish(),
104
109
  vector_store_ids: z.array(z.string()).nullish(),
110
+ /** Scope this smith's runs to these registered MCP servers (by name).
111
+ * Null clears the per-smith override (re-inherit the agent's value). */
112
+ mcp_servers: z.array(z.string()).nullish(),
105
113
  auto_memory: z.boolean().nullish(),
106
114
  memory_consolidation: z.boolean().nullish(),
107
115
  })
@@ -67,6 +67,49 @@ export const WebhookPatch = z
67
67
  active: z.boolean().nullish(),
68
68
  })
69
69
  .meta({ id: "WebhookPatch" });
70
+ /** Rotate a webhook's signing secret. `grace_seconds` keeps the outgoing secret
71
+ * valid for an overlap window (default 24h, 0 = cut over immediately, max 7d);
72
+ * during it every delivery is signed with both the new and old secret. */
73
+ export const WebhookRotateIn = z
74
+ .object({
75
+ grace_seconds: z.number().int().min(0).max(604800).default(86400),
76
+ })
77
+ .meta({ id: "WebhookRotateIn" });
78
+ /** The rotate response — the new signing `secret` is returned EXACTLY ONCE, here.
79
+ * `previous_secret_expires_at` is when the old secret stops being accepted. */
80
+ export const WebhookRotateOut = z
81
+ .object({
82
+ id: z.string(),
83
+ secret: z.string(),
84
+ previous_secret_expires_at: z.string().nullable(),
85
+ })
86
+ .meta({ id: "WebhookRotateOut" });
87
+ /** One persisted delivery attempt record for a webhook — the audit trail behind
88
+ * durable, retried delivery. `status` is `pending` | `succeeded` | `dead`. */
89
+ export const WebhookDeliveryOut = z
90
+ .object({
91
+ id: z.string(),
92
+ event_id: z.string(),
93
+ event_type: z.string(),
94
+ url: z.string(),
95
+ status: z.string(),
96
+ attempts: z.number(),
97
+ last_status: z.number().nullable(),
98
+ last_error: z.string(),
99
+ next_attempt_at: z.string().nullable(),
100
+ delivered_at: z.string().nullable(),
101
+ created_at: z.string().nullable(),
102
+ })
103
+ .meta({ id: "WebhookDeliveryOut" });
104
+ export const WebhookDeliveryListOut = pageOut(WebhookDeliveryOut, "WebhookDeliveryListOut");
105
+ /** The redeliver ack — the outcome of the forced re-attempt. */
106
+ export const WebhookRedeliverOut = z
107
+ .object({
108
+ delivery_id: z.string(),
109
+ delivered: z.boolean(),
110
+ status: z.number().nullable(),
111
+ })
112
+ .meta({ id: "WebhookRedeliverOut" });
70
113
  // ── Tokens (mint / list / revoke RS256 JWTs) ─────────────────────────────────
71
114
  /** A minted-token *summary* — the list/listing shape. The secret `token` is
72
115
  * NEVER echoed here; it only appears in {@link MintedTokenOut} on create. */
@@ -184,6 +227,7 @@ export const ProviderOut = z
184
227
  token_uri: z.string().nullable(),
185
228
  scopes_allowed: z.array(z.string()),
186
229
  refresh_webhook: z.string().nullable(),
230
+ authorize_url: z.string().nullable(),
187
231
  has_client_secret: z.boolean(),
188
232
  })
189
233
  .meta({ id: "ProviderOut" });
@@ -204,8 +248,34 @@ export const ProviderIn = z
204
248
  token_uri: z.string().nullish(),
205
249
  scopes_allowed: z.array(z.string()).default([]),
206
250
  refresh_webhook: z.string().nullish(),
251
+ /** Tenant-hosted connector consent page (#123): the connector OAuth
252
+ * authorize endpoint redirects the end-user here (`?request_id=…`)
253
+ * instead of rendering the built-in connect-token page. */
254
+ authorize_url: z.string().nullish(),
207
255
  })
208
256
  .meta({ id: "ProviderIn" });
257
+ // ── Delegated connector consent (connector OAuth, #123) ─────────────────────
258
+ /** Render data for a tenant-hosted consent page: the pending authorize request
259
+ * stashed by `GET /oauth/authorize` when the tenant's provider registers an
260
+ * `authorize_url`. */
261
+ export const AuthorizeRequestOut = z
262
+ .object({
263
+ client_name: z.string(),
264
+ target_name: z.string(),
265
+ tenant: z.string(),
266
+ resource: z.string(),
267
+ deployment_id: z.string(),
268
+ })
269
+ .meta({ id: "AuthorizeRequestOut" });
270
+ /** Complete the delegated grant: the tenant asserts (server-to-server) which
271
+ * smith the end-user authorized. */
272
+ export const AuthorizeCompleteIn = z
273
+ .object({ smith_id: z.string() })
274
+ .meta({ id: "AuthorizeCompleteIn" });
275
+ /** Where the tenant 302s the browser after completing or declining. */
276
+ export const AuthorizeRedirectOut = z
277
+ .object({ redirect_url: z.string() })
278
+ .meta({ id: "AuthorizeRedirectOut" });
209
279
  // ── Hosted-tool catalog ──────────────────────────────────────────────────────
210
280
  /** One tool hosted by Ingram Cloud that the catalog advertises. */
211
281
  export const HostedToolOut = z
@@ -7,9 +7,11 @@
7
7
  * filter grammar, and the `search_results.page` envelope are OpenAI's, wart for
8
8
  * wart (modify is `POST`, the batch object is `vector_store.files_batch`, the
9
9
  * search page uses a `next_page` token while CRUD lists use `first_id`/
10
- * `last_id`). `smith_id` is the one documented IC extension: it scopes a store
11
- * to a single smith ("" = tenant-wide), the same isolation boundary every other
12
- * smith-owned resource has. Expiration policies (`expires_after`), query
10
+ * `last_id`). Two documented IC extensions: `smith_id` scopes a store to a
11
+ * single smith ("" = tenant-wide), the same isolation boundary every other
12
+ * smith-owned resource has; `embedding_model` names the store's embedder,
13
+ * frozen at create (OpenAI pins one platform-wide, Gemini's File Search exposes
14
+ * it the same way). Expiration policies (`expires_after`), query
13
15
  * rewriting, and rankers are not implemented — the fields don't exist here
14
16
  * rather than being accepted and ignored.
15
17
  */
@@ -78,6 +80,11 @@ export const VectorStoreIn = z
78
80
  metadata: z.record(z.string(), z.unknown()).optional(),
79
81
  /** IC extension: own the store to one smith ("" / omitted = tenant-wide). */
80
82
  smith_id: z.string().optional(),
83
+ /** IC extension: the embedder to index and query this store with, frozen at
84
+ * create (omitted = the platform default). Any model your OpenAI-provider
85
+ * key can reach — including an EU-hosted OpenAI-compatible endpoint set as
86
+ * that key's `base_url` — of at most 1536 dimensions. */
87
+ embedding_model: z.string().optional(),
81
88
  })
82
89
  .meta({ id: "VectorStoreIn" });
83
90
  export const VectorStoreFileCounts = z.object({
@@ -105,6 +112,9 @@ export const VectorStoreOut = z
105
112
  metadata: z.record(z.string(), z.unknown()),
106
113
  /** IC extension: the owning smith ("" = tenant-wide). */
107
114
  smith_id: z.string(),
115
+ /** IC extension: the embedder this store is indexed and queried with,
116
+ * frozen at create. */
117
+ embedding_model: z.string(),
108
118
  })
109
119
  .meta({ id: "VectorStoreOut" });
110
120
  /** Vector stores, in OpenAI's `list` envelope. */
@@ -151,7 +161,12 @@ export const VectorStoreFileOut = z
151
161
  status: z.enum(["in_progress", "completed", "failed", "cancelled"]),
152
162
  last_error: z
153
163
  .object({
154
- code: z.enum(["server_error", "unsupported_file", "invalid_file"]),
164
+ code: z.enum([
165
+ "server_error",
166
+ "unsupported_file",
167
+ "no_text_layer",
168
+ "invalid_file",
169
+ ]),
155
170
  message: z.string(),
156
171
  })
157
172
  .nullable(),
@@ -174,6 +189,17 @@ export const VectorStoreFileUpdate = z
174
189
  attributes: VectorStoreAttributes.nullable(),
175
190
  })
176
191
  .meta({ id: "VectorStoreFileUpdate" });
192
+ /** The parsed text a file was indexed as, chunk by chunk, in OpenAI's
193
+ * `vector_store.file_content.page` envelope. The whole file is one page — the
194
+ * paging fields are the envelope's shape, not a promise of more. */
195
+ export const VectorStoreFileContentOut = z
196
+ .object({
197
+ object: z.literal("vector_store.file_content.page"),
198
+ data: z.array(z.object({ type: z.literal("text"), text: z.string() })),
199
+ has_more: z.literal(false),
200
+ next_page: z.null(),
201
+ })
202
+ .meta({ id: "VectorStoreFileContentOut" });
177
203
  export const VectorStoreFileDeleted = z
178
204
  .object({
179
205
  id: z.string(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ingram-cloud/sdk",
3
- "version": "1.1.0",
3
+ "version": "1.4.0",
4
4
  "description": "Typed wire contract + management-plane client for the Ingram Cloud API: Zod schemas to validate request/response bodies, TypeScript types for the JSON you read back, SSE/webhook event types, and a typed REST client.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -56,10 +56,10 @@
56
56
  "prepublishOnly": "bun run build"
57
57
  },
58
58
  "devDependencies": {
59
- "@ingram-tech/oxlint-config": "^0.2.1",
60
- "oxfmt": "^0.57.0",
61
- "oxlint": "^1.70.0",
62
- "typescript": "^6.0.0"
59
+ "@ingram-tech/oxlint-config": "^0.2.2",
60
+ "oxfmt": "^0.58.0",
61
+ "oxlint": "^1.73.0",
62
+ "typescript": "^6"
63
63
  },
64
64
  "dependencies": {
65
65
  "zod": "^4.4.3"
package/ts/client.ts CHANGED
@@ -29,6 +29,7 @@ import type {
29
29
  ICAgent,
30
30
  ICAgentVersion,
31
31
  ICApproval,
32
+ ICAuthorizeRequest,
32
33
  ICBudget,
33
34
  ICBudgetStatus,
34
35
  ICCatalogEntry,
@@ -63,11 +64,13 @@ import type {
63
64
  ICUiResource,
64
65
  ICUsage,
65
66
  ICUsageBreakdown,
67
+ ICUsageEvent,
66
68
  ICVectorStore,
67
69
  ICVectorStoreFile,
68
70
  ICVectorStoreFileBatch,
69
71
  ICVectorStoreSearchPage,
70
72
  ICWebhook,
73
+ ICWebhookDelivery,
71
74
  ICWhatsAppConfig,
72
75
  ICWorkingMemory,
73
76
  } from "./responses.js";
@@ -110,6 +113,8 @@ import type { RestoreIn } from "./zod/smith-revisions.js";
110
113
  import type { SmithCreate, SmithPatch } from "./zod/smiths.js";
111
114
  import type { TelegramBotIn } from "./zod/telegram.js";
112
115
  import type {
116
+ AuthorizeCompleteIn,
117
+ AuthorizeRedirectOut,
113
118
  HostedToolOut,
114
119
  ModelKeyConfiguredOut,
115
120
  ModelKeyIn,
@@ -119,6 +124,9 @@ import type {
119
124
  WebhookCreateOut,
120
125
  WebhookIn,
121
126
  WebhookPatch,
127
+ WebhookRedeliverOut,
128
+ WebhookRotateIn,
129
+ WebhookRotateOut,
122
130
  } from "./zod/tenant.js";
123
131
  import type { WhatsAppConfigIn } from "./zod/whatsapp.js";
124
132
 
@@ -445,6 +453,30 @@ export class IngramCloud {
445
453
  ),
446
454
  },
447
455
 
456
+ /** End-user BYOK (#170): a smith's own provider keys, resolved ahead of the
457
+ * tenant's so the end-user's provider account is billed. Never read back. */
458
+ modelKeys: {
459
+ list: (pid: string, opts?: RequestOptions) =>
460
+ this.data<ICModelKey>("GET", `/smiths/${enc(pid)}/model_keys`, opts),
461
+ put: (
462
+ pid: string,
463
+ provider: string,
464
+ body: z.input<typeof ModelKeyIn>,
465
+ opts?: RequestOptions,
466
+ ) =>
467
+ this.json<z.infer<typeof ModelKeyConfiguredOut>>(
468
+ "PUT",
469
+ `/smiths/${enc(pid)}/model_keys/${enc(provider)}`,
470
+ { ...opts, body },
471
+ ),
472
+ delete: (pid: string, provider: string, opts?: RequestOptions) =>
473
+ this.empty(
474
+ "DELETE",
475
+ `/smiths/${enc(pid)}/model_keys/${enc(provider)}`,
476
+ opts,
477
+ ),
478
+ },
479
+
448
480
  schedules: {
449
481
  list: (pid: string, opts?: RequestOptions) =>
450
482
  this.data<ICSchedule>("GET", `/smiths/${enc(pid)}/schedules`, opts),
@@ -653,6 +685,14 @@ export class IngramCloud {
653
685
  rawBody: form,
654
686
  });
655
687
  },
688
+ /** The template's HTML bundle — the same bytes the agent's MCP endpoint
689
+ * serves, so a host can render a panel without vendoring a copy.
690
+ * Tenant-authed: call it server-side and proxy to your chat UI. */
691
+ content: (aid: string, name: string, opts?: RequestOptions) =>
692
+ this.request("GET", `/agents/${enc(aid)}/ui/${enc(name)}/content`, {
693
+ ...opts,
694
+ headers: { accept: "text/html", ...opts?.headers },
695
+ }).then((r) => r.text()),
656
696
  delete: (aid: string, name: string, opts?: RequestOptions) =>
657
697
  this.json<{ name: string; deleted: boolean }>(
658
698
  "DELETE",
@@ -811,6 +851,18 @@ export class IngramCloud {
811
851
  },
812
852
  opts?: RequestOptions,
813
853
  ) => this.json<ICUsageBreakdown>("GET", "/usage", { ...opts, query }),
854
+ /** The raw billable-usage event ledger (keyset-paginated, newest first) — the
855
+ * per-event rows the breakdown aggregates. */
856
+ events: (
857
+ query?: PageOpts & {
858
+ smith_id?: string;
859
+ meter?: string;
860
+ customer_id?: string;
861
+ from?: string;
862
+ to?: string;
863
+ },
864
+ opts?: RequestOptions,
865
+ ) => this.page<ICUsageEvent>("/usage/events", query, opts),
814
866
  };
815
867
 
816
868
  // ── Files (the OpenAI Files API) ─────────────────────────────────────────
@@ -1016,12 +1068,38 @@ export class IngramCloud {
1016
1068
  }),
1017
1069
  delete: (wid: string, opts?: RequestOptions) =>
1018
1070
  this.empty("DELETE", `/tenant/webhooks/${enc(wid)}`, opts),
1071
+ /** Rotate the signing secret, returning the new one exactly once. Pass
1072
+ * `grace_seconds` to keep the old secret accepted during an overlap window. */
1073
+ rotateSecret: (
1074
+ wid: string,
1075
+ body?: z.input<typeof WebhookRotateIn>,
1076
+ opts?: RequestOptions,
1077
+ ) =>
1078
+ this.json<z.infer<typeof WebhookRotateOut>>(
1079
+ "POST",
1080
+ `/tenant/webhooks/${enc(wid)}/rotate_secret`,
1081
+ { ...opts, body: body ?? {} },
1082
+ ),
1019
1083
  test: (wid: string, opts?: RequestOptions) =>
1020
1084
  this.json<{ delivered: boolean }>(
1021
1085
  "POST",
1022
1086
  `/tenant/webhooks/${enc(wid)}/test`,
1023
1087
  opts,
1024
1088
  ),
1089
+ /** The persisted delivery attempts for a webhook (durable retry audit trail). */
1090
+ deliveries: (wid: string, query?: PageOpts, opts?: RequestOptions) =>
1091
+ this.page<ICWebhookDelivery>(
1092
+ `/tenant/webhooks/${enc(wid)}/deliveries`,
1093
+ query,
1094
+ opts,
1095
+ ),
1096
+ /** Force a fresh delivery attempt for one record (e.g. after the endpoint recovers). */
1097
+ redeliver: (wid: string, did: string, opts?: RequestOptions) =>
1098
+ this.json<z.infer<typeof WebhookRedeliverOut>>(
1099
+ "POST",
1100
+ `/tenant/webhooks/${enc(wid)}/deliveries/${enc(did)}/redeliver`,
1101
+ opts,
1102
+ ),
1025
1103
  },
1026
1104
 
1027
1105
  providers: {
@@ -1146,7 +1224,40 @@ export class IngramCloud {
1146
1224
  },
1147
1225
  };
1148
1226
 
1149
- // ── Organization (org token: projects + billing) ────────────────────────
1227
+ // ── Delegated connector consent (connector OAuth, #123) ─────────────────
1228
+ // Tenant-admin token. The tenant's hosted consent page (the provider's
1229
+ // `authorize_url`) reads the pending request, then completes or declines it
1230
+ // server-to-server; the returned `redirect_url` is where to 302 the browser.
1231
+
1232
+ readonly oauth = {
1233
+ authorizeRequests: {
1234
+ get: (requestId: string, opts?: RequestOptions) =>
1235
+ this.json<ICAuthorizeRequest>(
1236
+ "GET",
1237
+ `/oauth/authorize-requests/${enc(requestId)}`,
1238
+ opts,
1239
+ ),
1240
+ complete: (
1241
+ requestId: string,
1242
+ body: z.input<typeof AuthorizeCompleteIn>,
1243
+ opts?: RequestOptions,
1244
+ ) =>
1245
+ this.json<z.infer<typeof AuthorizeRedirectOut>>(
1246
+ "POST",
1247
+ `/oauth/authorize-requests/${enc(requestId)}/complete`,
1248
+ { ...opts, body },
1249
+ ),
1250
+ decline: (requestId: string, opts?: RequestOptions) =>
1251
+ this.json<z.infer<typeof AuthorizeRedirectOut>>(
1252
+ "POST",
1253
+ `/oauth/authorize-requests/${enc(requestId)}/decline`,
1254
+ opts,
1255
+ ),
1256
+ },
1257
+ };
1258
+
1259
+ // ── Organization (org token: projects + tokens) ─────────────────────────
1260
+ // Note: the `/v1/organization/billing/*` surface is not yet wrapped here.
1150
1261
 
1151
1262
  readonly organization = {
1152
1263
  projects: {
package/ts/responses.ts CHANGED
@@ -52,6 +52,7 @@ export type {
52
52
  ICTrace,
53
53
  ICTraceDetail,
54
54
  ICUsageBreakdown,
55
+ ICUsageEvent,
55
56
  } from "./zod/observability.js";
56
57
  export type { ICProject } from "./zod/projects.js";
57
58
  export type { ICRun, ICRunUsage, ICInputMessage, ICRunEvent } from "./zod/runs.js";
@@ -63,6 +64,7 @@ export type { ICTelegramBot } from "./zod/telegram.js";
63
64
  export type {
64
65
  ICEvent,
65
66
  ICWebhook,
67
+ ICWebhookDelivery,
66
68
  ICToken,
67
69
  ICMintedToken,
68
70
  ICUsage,
@@ -71,6 +73,7 @@ export type {
71
73
  ICModelCatalog,
72
74
  ICModelKey,
73
75
  ICProvider,
76
+ ICAuthorizeRequest,
74
77
  } from "./zod/tenant.js";
75
78
  export type { ICWhatsAppConfig } from "./zod/whatsapp.js";
76
79
  export type {
package/ts/zod/agents.ts CHANGED
@@ -72,6 +72,8 @@ export const AgentDraft = z
72
72
  model: z.string().nullable(),
73
73
  enabled_hosted_tools: z.array(z.string()),
74
74
  vector_store_ids: z.array(z.string()),
75
+ /** Registered MCP servers this agent's smiths load, by name. Null = all. */
76
+ mcp_servers: z.array(z.string()).nullable(),
75
77
  auto_memory: z.boolean().nullable(),
76
78
  memory_consolidation: z.boolean().nullable(),
77
79
  variables: z.array(AgentVariable),
@@ -93,6 +95,8 @@ export const AgentOut = z
93
95
  rollout_version: z.number().int().nullable(),
94
96
  rollout_percent: z.number().int(),
95
97
  smith_count: z.number().int().optional(),
98
+ /** Newest run across every smith of this agent. Null until one runs. */
99
+ last_activity_at: z.string().nullable().optional(),
96
100
  created_at: z.string().nullable(),
97
101
  updated_at: z.string().nullable(),
98
102
  })
@@ -109,6 +113,7 @@ export const AgentVersionOut = z
109
113
  model: z.string().nullish(),
110
114
  enabled_hosted_tools: z.array(z.string()).optional(),
111
115
  vector_store_ids: z.array(z.string()).optional(),
116
+ mcp_servers: z.array(z.string()).nullish(),
112
117
  auto_memory: z.boolean().nullish(),
113
118
  memory_consolidation: z.boolean().nullish(),
114
119
  variables: z.array(AgentVariable).optional(),
@@ -134,6 +139,8 @@ export const AgentIn = z
134
139
  model: z.string().nullish(),
135
140
  enabled_hosted_tools: z.array(z.string()).nullish(),
136
141
  vector_store_ids: z.array(z.string()).nullish(),
142
+ /** Scope runs to these registered MCP servers (by name). Null/omitted = all. */
143
+ mcp_servers: z.array(z.string()).nullish(),
137
144
  auto_memory: z.boolean().nullish(),
138
145
  memory_consolidation: z.boolean().nullish(),
139
146
  variables: z.array(AgentVariable).nullish(),
@@ -147,6 +154,9 @@ export const AgentPatch = z
147
154
  model: z.string().nullish(),
148
155
  enabled_hosted_tools: z.array(z.string()).nullish(),
149
156
  vector_store_ids: z.array(z.string()).nullish(),
157
+ /** Scope runs to these registered MCP servers (by name). An explicit null
158
+ * clears the restriction (= all); omitted leaves it unchanged. */
159
+ mcp_servers: z.array(z.string()).nullish(),
150
160
  auto_memory: z.boolean().nullish(),
151
161
  memory_consolidation: z.boolean().nullish(),
152
162
  variables: z.array(AgentVariable).nullish(),
@@ -33,7 +33,17 @@ export const DeploymentTarget = z
33
33
  * (`DeploymentIn.kind`) and the response (`DeploymentOut.kind`); the API derives
34
34
  * its accepted-kinds set from these options, so the enum is the discoverable list. */
35
35
  export const DeploymentKind = z
36
- .enum(["whatsapp", "telegram", "slack", "discord", "sms", "voice", "email", "mcp"])
36
+ .enum([
37
+ "whatsapp",
38
+ "telegram",
39
+ "slack",
40
+ "discord",
41
+ "sms",
42
+ "voice",
43
+ "email",
44
+ "mcp",
45
+ "web",
46
+ ])
37
47
  .meta({ id: "DeploymentKind" });
38
48
 
39
49
  export const DeploymentOut = z
@@ -49,6 +59,9 @@ export const DeploymentOut = z
49
59
  /** The connectable MCP endpoint — present only for `kind: "mcp"`. Paste into
50
60
  * Claude / ChatGPT as the server URL; survives a later GET, not just create. */
51
61
  mcp_url: z.string().optional(),
62
+ /** The shareable hosted-page URL — present only for `kind: "web"`. Open in a
63
+ * browser to chat with the agent; survives a later GET, not just create. */
64
+ page_url: z.string().optional(),
52
65
  status: z.string(),
53
66
  created_at: z.string().nullable(),
54
67
  })
@@ -64,6 +77,7 @@ export const DeploymentListOut = pageOut(DeploymentOut, "DeploymentListOut");
64
77
  * - slack `provision`/`oauth_install`: `install_url`, `state`, optional `slack_app_id`.
65
78
  * - email `provision`: no extras (plain `DeploymentOut`).
66
79
  * - mcp: `mcp_url` (on the base `DeploymentOut`, so it also survives a GET).
80
+ * - web: `page_url` (on the base `DeploymentOut`, so it also survives a GET).
67
81
  * All are optional — which appear depends on the kind + setup mode.
68
82
  */
69
83
  export const DeploymentCreatedOut = DeploymentOut.extend({
package/ts/zod/mcp.ts CHANGED
@@ -72,11 +72,17 @@ export const McpServerOut = z
72
72
  approval_policy: z.array(ApprovalRule).optional(),
73
73
  tools: z.array(McpTool),
74
74
  tools_refreshed_at: z.string().nullable(),
75
- /** `degraded` when the edge failed discovery or its secret can't be decoded
76
- * at run time; otherwise the stored lifecycle status. */
75
+ /** `degraded` when the edge failed discovery, its secret can't be decoded at
76
+ * run time, or its last `tools/call` failed at the transport level;
77
+ * otherwise the stored lifecycle status. */
77
78
  status: z.string(),
78
- /** Last discovery/runtime-load failure, or null when the edge is healthy. */
79
+ /** Last discovery/runtime-load failure, or null when discovery is healthy. */
79
80
  discovery_error: z.string().nullable(),
81
+ /** Last transport-level `tools/call` failure (network / HTTP status), or
82
+ * null. Discovery can succeed while calls fail — this catches that. Cleared
83
+ * by a successful call or a re-PUT. */
84
+ last_call_error: z.string().nullable(),
85
+ last_call_error_at: z.string().nullable(),
80
86
  created_at: z.string().nullable(),
81
87
  })
82
88
  .meta({ id: "McpServerOut" });
@@ -105,7 +111,9 @@ export const McpAuthIn = z
105
111
  .meta({ id: "McpAuthIn" });
106
112
 
107
113
  /** Register or replace a server: supply a raw `url` + `auth`, or a `catalog`
108
- * slug (catalog defaults are stamped down, body fields override). */
114
+ * slug (catalog defaults are stamped down, body fields override). PUT is a
115
+ * full replace and `auth.kind` is required unless a catalog preset supplies
116
+ * it — there is no implicit `none`. */
109
117
  export const McpServerIn = z
110
118
  .object({
111
119
  url: z.string().nullish(),
@@ -67,6 +67,7 @@ export const TraceOut = z
67
67
  id: z.string(),
68
68
  smith_id: z.string(),
69
69
  app_id: z.string().nullable(),
70
+ run_id: z.string().nullable(),
70
71
  root_kind: ICSpanKindEnum,
71
72
  name: z.string(),
72
73
  status: z.string(),
@@ -153,3 +154,4 @@ export type ICSpanNode = z.infer<typeof SpanNodeOut>;
153
154
  export type ICTrace = z.infer<typeof TraceOut>;
154
155
  export type ICTraceDetail = z.infer<typeof TraceDetailOut>;
155
156
  export type ICUsageBreakdown = z.infer<typeof UsageBreakdownOut>;
157
+ export type ICUsageEvent = z.infer<typeof UsageEventOut>;
@@ -26,8 +26,11 @@ export const SmithRevisionOut = z
26
26
  model: z.string().nullish(),
27
27
  enabled_hosted_tools: z.array(z.string()).optional(),
28
28
  vector_store_ids: z.array(z.string()).optional(),
29
- auto_memory: z.boolean().optional(),
30
- memory_consolidation: z.boolean().optional(),
29
+ mcp_servers: z.array(z.string()).nullish(),
30
+ // Nullish: a snapshot taken while the smith inherited a sparse agent
31
+ // version carries null (= the default) for these.
32
+ auto_memory: z.boolean().nullish(),
33
+ memory_consolidation: z.boolean().nullish(),
31
34
  }),
32
35
  created_by: z.string().nullish(),
33
36
  note: z.string().nullish(),
package/ts/zod/smiths.ts CHANGED
@@ -38,6 +38,8 @@ export const SmithOut = z
38
38
  rendered_instructions: z.string().nullish(),
39
39
  enabled_hosted_tools: z.array(z.string()).optional(),
40
40
  vector_store_ids: z.array(z.string()).optional(),
41
+ /** Registered MCP servers this smith's runs load, by name. Null = all. */
42
+ mcp_servers: z.array(z.string()).nullish(),
41
43
  auto_memory: z.boolean().optional(),
42
44
  memory_consolidation: z.boolean().optional(),
43
45
  /** How the config resolved: by reference, with overrides, or embedded. */
@@ -57,6 +59,7 @@ export const SmithOut = z
57
59
  instructions: z.string().nullable(),
58
60
  enabled_hosted_tools: z.array(z.string()),
59
61
  vector_store_ids: z.array(z.string()),
62
+ mcp_servers: z.array(z.string()).nullable(),
60
63
  auto_memory: z.boolean().nullable(),
61
64
  memory_consolidation: z.boolean().nullable(),
62
65
  })
@@ -90,6 +93,8 @@ export const SmithCreate = z
90
93
  instructions: z.string().nullish(),
91
94
  enabled_hosted_tools: z.array(z.string()).nullish(),
92
95
  vector_store_ids: z.array(z.string()).nullish(),
96
+ /** Scope this smith's runs to these registered MCP servers (by name). */
97
+ mcp_servers: z.array(z.string()).nullish(),
93
98
  auto_memory: z.boolean().nullish(),
94
99
  memory_consolidation: z.boolean().nullish(),
95
100
  })
@@ -108,6 +113,9 @@ export const SmithPatch = z
108
113
  instructions: z.string().nullish(),
109
114
  enabled_hosted_tools: z.array(z.string()).nullish(),
110
115
  vector_store_ids: z.array(z.string()).nullish(),
116
+ /** Scope this smith's runs to these registered MCP servers (by name).
117
+ * Null clears the per-smith override (re-inherit the agent's value). */
118
+ mcp_servers: z.array(z.string()).nullish(),
111
119
  auto_memory: z.boolean().nullish(),
112
120
  memory_consolidation: z.boolean().nullish(),
113
121
  })
package/ts/zod/tenant.ts CHANGED
@@ -78,6 +78,54 @@ export const WebhookPatch = z
78
78
  })
79
79
  .meta({ id: "WebhookPatch" });
80
80
 
81
+ /** Rotate a webhook's signing secret. `grace_seconds` keeps the outgoing secret
82
+ * valid for an overlap window (default 24h, 0 = cut over immediately, max 7d);
83
+ * during it every delivery is signed with both the new and old secret. */
84
+ export const WebhookRotateIn = z
85
+ .object({
86
+ grace_seconds: z.number().int().min(0).max(604800).default(86400),
87
+ })
88
+ .meta({ id: "WebhookRotateIn" });
89
+
90
+ /** The rotate response — the new signing `secret` is returned EXACTLY ONCE, here.
91
+ * `previous_secret_expires_at` is when the old secret stops being accepted. */
92
+ export const WebhookRotateOut = z
93
+ .object({
94
+ id: z.string(),
95
+ secret: z.string(),
96
+ previous_secret_expires_at: z.string().nullable(),
97
+ })
98
+ .meta({ id: "WebhookRotateOut" });
99
+
100
+ /** One persisted delivery attempt record for a webhook — the audit trail behind
101
+ * durable, retried delivery. `status` is `pending` | `succeeded` | `dead`. */
102
+ export const WebhookDeliveryOut = z
103
+ .object({
104
+ id: z.string(),
105
+ event_id: z.string(),
106
+ event_type: z.string(),
107
+ url: z.string(),
108
+ status: z.string(),
109
+ attempts: z.number(),
110
+ last_status: z.number().nullable(),
111
+ last_error: z.string(),
112
+ next_attempt_at: z.string().nullable(),
113
+ delivered_at: z.string().nullable(),
114
+ created_at: z.string().nullable(),
115
+ })
116
+ .meta({ id: "WebhookDeliveryOut" });
117
+
118
+ export const WebhookDeliveryListOut = pageOut(WebhookDeliveryOut, "WebhookDeliveryListOut");
119
+
120
+ /** The redeliver ack — the outcome of the forced re-attempt. */
121
+ export const WebhookRedeliverOut = z
122
+ .object({
123
+ delivery_id: z.string(),
124
+ delivered: z.boolean(),
125
+ status: z.number().nullable(),
126
+ })
127
+ .meta({ id: "WebhookRedeliverOut" });
128
+
81
129
  // ── Tokens (mint / list / revoke RS256 JWTs) ─────────────────────────────────
82
130
 
83
131
  /** A minted-token *summary* — the list/listing shape. The secret `token` is
@@ -213,6 +261,7 @@ export const ProviderOut = z
213
261
  token_uri: z.string().nullable(),
214
262
  scopes_allowed: z.array(z.string()),
215
263
  refresh_webhook: z.string().nullable(),
264
+ authorize_url: z.string().nullable(),
216
265
  has_client_secret: z.boolean(),
217
266
  })
218
267
  .meta({ id: "ProviderOut" });
@@ -236,9 +285,39 @@ export const ProviderIn = z
236
285
  token_uri: z.string().nullish(),
237
286
  scopes_allowed: z.array(z.string()).default([]),
238
287
  refresh_webhook: z.string().nullish(),
288
+ /** Tenant-hosted connector consent page (#123): the connector OAuth
289
+ * authorize endpoint redirects the end-user here (`?request_id=…`)
290
+ * instead of rendering the built-in connect-token page. */
291
+ authorize_url: z.string().nullish(),
239
292
  })
240
293
  .meta({ id: "ProviderIn" });
241
294
 
295
+ // ── Delegated connector consent (connector OAuth, #123) ─────────────────────
296
+
297
+ /** Render data for a tenant-hosted consent page: the pending authorize request
298
+ * stashed by `GET /oauth/authorize` when the tenant's provider registers an
299
+ * `authorize_url`. */
300
+ export const AuthorizeRequestOut = z
301
+ .object({
302
+ client_name: z.string(),
303
+ target_name: z.string(),
304
+ tenant: z.string(),
305
+ resource: z.string(),
306
+ deployment_id: z.string(),
307
+ })
308
+ .meta({ id: "AuthorizeRequestOut" });
309
+
310
+ /** Complete the delegated grant: the tenant asserts (server-to-server) which
311
+ * smith the end-user authorized. */
312
+ export const AuthorizeCompleteIn = z
313
+ .object({ smith_id: z.string() })
314
+ .meta({ id: "AuthorizeCompleteIn" });
315
+
316
+ /** Where the tenant 302s the browser after completing or declining. */
317
+ export const AuthorizeRedirectOut = z
318
+ .object({ redirect_url: z.string() })
319
+ .meta({ id: "AuthorizeRedirectOut" });
320
+
242
321
  // ── Hosted-tool catalog ──────────────────────────────────────────────────────
243
322
 
244
323
  /** One tool hosted by Ingram Cloud that the catalog advertises. */
@@ -257,6 +336,7 @@ export const HostedToolsListOut = z
257
336
 
258
337
  export type ICEvent = z.infer<typeof EventOut>;
259
338
  export type ICWebhook = z.infer<typeof WebhookOut>;
339
+ export type ICWebhookDelivery = z.infer<typeof WebhookDeliveryOut>;
260
340
  export type ICToken = z.infer<typeof TokenOut>;
261
341
  export type ICMintedToken = z.infer<typeof MintedTokenOut>;
262
342
  export type ICUsage = z.infer<typeof UsageOut>;
@@ -265,3 +345,4 @@ export type ICModelProvider = z.infer<typeof ModelProviderOut>;
265
345
  export type ICModelCatalog = z.infer<typeof ModelsListOut>;
266
346
  export type ICModelKey = z.infer<typeof ModelKeyOut>;
267
347
  export type ICProvider = z.infer<typeof ProviderOut>;
348
+ export type ICAuthorizeRequest = z.infer<typeof AuthorizeRequestOut>;
@@ -7,9 +7,11 @@
7
7
  * filter grammar, and the `search_results.page` envelope are OpenAI's, wart for
8
8
  * wart (modify is `POST`, the batch object is `vector_store.files_batch`, the
9
9
  * search page uses a `next_page` token while CRUD lists use `first_id`/
10
- * `last_id`). `smith_id` is the one documented IC extension: it scopes a store
11
- * to a single smith ("" = tenant-wide), the same isolation boundary every other
12
- * smith-owned resource has. Expiration policies (`expires_after`), query
10
+ * `last_id`). Two documented IC extensions: `smith_id` scopes a store to a
11
+ * single smith ("" = tenant-wide), the same isolation boundary every other
12
+ * smith-owned resource has; `embedding_model` names the store's embedder,
13
+ * frozen at create (OpenAI pins one platform-wide, Gemini's File Search exposes
14
+ * it the same way). Expiration policies (`expires_after`), query
13
15
  * rewriting, and rankers are not implemented — the fields don't exist here
14
16
  * rather than being accepted and ignored.
15
17
  */
@@ -95,6 +97,11 @@ export const VectorStoreIn = z
95
97
  metadata: z.record(z.string(), z.unknown()).optional(),
96
98
  /** IC extension: own the store to one smith ("" / omitted = tenant-wide). */
97
99
  smith_id: z.string().optional(),
100
+ /** IC extension: the embedder to index and query this store with, frozen at
101
+ * create (omitted = the platform default). Any model your OpenAI-provider
102
+ * key can reach — including an EU-hosted OpenAI-compatible endpoint set as
103
+ * that key's `base_url` — of at most 1536 dimensions. */
104
+ embedding_model: z.string().optional(),
98
105
  })
99
106
  .meta({ id: "VectorStoreIn" });
100
107
 
@@ -124,6 +131,9 @@ export const VectorStoreOut = z
124
131
  metadata: z.record(z.string(), z.unknown()),
125
132
  /** IC extension: the owning smith ("" = tenant-wide). */
126
133
  smith_id: z.string(),
134
+ /** IC extension: the embedder this store is indexed and queried with,
135
+ * frozen at create. */
136
+ embedding_model: z.string(),
127
137
  })
128
138
  .meta({ id: "VectorStoreOut" });
129
139
 
@@ -176,7 +186,12 @@ export const VectorStoreFileOut = z
176
186
  status: z.enum(["in_progress", "completed", "failed", "cancelled"]),
177
187
  last_error: z
178
188
  .object({
179
- code: z.enum(["server_error", "unsupported_file", "invalid_file"]),
189
+ code: z.enum([
190
+ "server_error",
191
+ "unsupported_file",
192
+ "no_text_layer",
193
+ "invalid_file",
194
+ ]),
180
195
  message: z.string(),
181
196
  })
182
197
  .nullable(),
@@ -202,6 +217,18 @@ export const VectorStoreFileUpdate = z
202
217
  })
203
218
  .meta({ id: "VectorStoreFileUpdate" });
204
219
 
220
+ /** The parsed text a file was indexed as, chunk by chunk, in OpenAI's
221
+ * `vector_store.file_content.page` envelope. The whole file is one page — the
222
+ * paging fields are the envelope's shape, not a promise of more. */
223
+ export const VectorStoreFileContentOut = z
224
+ .object({
225
+ object: z.literal("vector_store.file_content.page"),
226
+ data: z.array(z.object({ type: z.literal("text"), text: z.string() })),
227
+ has_more: z.literal(false),
228
+ next_page: z.null(),
229
+ })
230
+ .meta({ id: "VectorStoreFileContentOut" });
231
+
205
232
  export const VectorStoreFileDeleted = z
206
233
  .object({
207
234
  id: z.string(),
@@ -291,6 +318,7 @@ export const VectorStoreSearchOut = z
291
318
 
292
319
  export type ICVectorStore = z.infer<typeof VectorStoreOut>;
293
320
  export type ICVectorStoreFile = z.infer<typeof VectorStoreFileOut>;
321
+ export type ICVectorStoreFileContentPage = z.infer<typeof VectorStoreFileContentOut>;
294
322
  export type ICVectorStoreFileBatch = z.infer<typeof VectorStoreFileBatchOut>;
295
323
  export type ICVectorStoreSearchPage = z.infer<typeof VectorStoreSearchOut>;
296
324
  export type ICVectorStoreAttributes = z.infer<typeof VectorStoreAttributes>;