@ingram-cloud/sdk 1.0.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.
Files changed (64) hide show
  1. package/README.md +74 -0
  2. package/dist/client.js +460 -0
  3. package/dist/events.js +108 -0
  4. package/dist/index.js +19 -0
  5. package/dist/responses.js +12 -0
  6. package/dist/schemas.js +4 -0
  7. package/dist/zod/_page.js +17 -0
  8. package/dist/zod/agents.js +176 -0
  9. package/dist/zod/approvals.js +38 -0
  10. package/dist/zod/budgets.js +62 -0
  11. package/dist/zod/catalog.js +49 -0
  12. package/dist/zod/connections.js +75 -0
  13. package/dist/zod/conversations.js +91 -0
  14. package/dist/zod/customers.js +53 -0
  15. package/dist/zod/deployments.js +81 -0
  16. package/dist/zod/discord.js +32 -0
  17. package/dist/zod/email.js +45 -0
  18. package/dist/zod/files.js +55 -0
  19. package/dist/zod/index.js +35 -0
  20. package/dist/zod/mcp.js +107 -0
  21. package/dist/zod/memories.js +43 -0
  22. package/dist/zod/observability.js +133 -0
  23. package/dist/zod/projects.js +58 -0
  24. package/dist/zod/runs.js +119 -0
  25. package/dist/zod/schedules.js +71 -0
  26. package/dist/zod/slack.js +69 -0
  27. package/dist/zod/smith-revisions.js +42 -0
  28. package/dist/zod/smiths.js +108 -0
  29. package/dist/zod/telegram.js +36 -0
  30. package/dist/zod/tenant.js +219 -0
  31. package/dist/zod/vector-stores.js +251 -0
  32. package/dist/zod/whatsapp.js +47 -0
  33. package/package.json +56 -0
  34. package/ts/client.ts +1187 -0
  35. package/ts/events.ts +119 -0
  36. package/ts/index.ts +20 -0
  37. package/ts/responses.ts +83 -0
  38. package/ts/schemas.ts +4 -0
  39. package/ts/zod/_page.ts +18 -0
  40. package/ts/zod/agents.ts +202 -0
  41. package/ts/zod/approvals.ts +44 -0
  42. package/ts/zod/budgets.ts +75 -0
  43. package/ts/zod/catalog.ts +57 -0
  44. package/ts/zod/connections.ts +87 -0
  45. package/ts/zod/conversations.ts +103 -0
  46. package/ts/zod/customers.ts +62 -0
  47. package/ts/zod/deployments.ts +93 -0
  48. package/ts/zod/discord.ts +39 -0
  49. package/ts/zod/email.ts +52 -0
  50. package/ts/zod/files.ts +62 -0
  51. package/ts/zod/index.ts +35 -0
  52. package/ts/zod/mcp.ts +123 -0
  53. package/ts/zod/memories.ts +53 -0
  54. package/ts/zod/observability.ts +155 -0
  55. package/ts/zod/projects.ts +68 -0
  56. package/ts/zod/runs.ts +135 -0
  57. package/ts/zod/schedules.ts +82 -0
  58. package/ts/zod/slack.ts +79 -0
  59. package/ts/zod/smith-revisions.ts +50 -0
  60. package/ts/zod/smiths.ts +118 -0
  61. package/ts/zod/telegram.ts +43 -0
  62. package/ts/zod/tenant.ts +267 -0
  63. package/ts/zod/vector-stores.ts +296 -0
  64. package/ts/zod/whatsapp.ts +54 -0
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Hand-authored Zod schemas for the `schedules` resource — cron-triggered runs
3
+ * on a smith's agent — the wire's source of truth, replacing the loose
4
+ * generated `schemas.ts` shapes for this resource.
5
+ *
6
+ * One source, three outputs: the API imports these into its `createRoute`
7
+ * definitions (validation + emitted OpenAPI), and the consumer-facing `IC*`
8
+ * types are `z.infer`red from them here and re-exported by `../responses`. No
9
+ * Zod is pulled into a type-only consumer — `responses.ts` re-exports these as
10
+ * `export type`.
11
+ *
12
+ * `.meta({ id })` names the component so the emitted OpenAPI references it as
13
+ * `#/components/schemas/<id>` rather than inlining it.
14
+ */
15
+ import { z } from "zod";
16
+ /** A schedule's stored input: messages replayed as the run input on each fire. */
17
+ const ScheduleInput = z.array(z.record(z.string(), z.unknown()));
18
+ export const ScheduleOut = z
19
+ .object({
20
+ id: z.string(),
21
+ name: z.string().nullable(),
22
+ cron: z.string(),
23
+ timezone: z.string(),
24
+ /** Messages replayed as the run input on each fire. */
25
+ input: ScheduleInput,
26
+ /** Thread the fired runs append to; null mints a fresh thread per fire. */
27
+ thread_id: z.string().nullable(),
28
+ /** Max overlapping fired runs before new fires are skipped. */
29
+ max_concurrent: z.number().int(),
30
+ enabled: z.boolean(),
31
+ next_fire_at: z.string().nullable(),
32
+ last_fire_at: z.string().nullable(),
33
+ created_at: z.string().nullable(),
34
+ })
35
+ .meta({ id: "ScheduleOut" });
36
+ export const ScheduleListOut = z
37
+ .object({ data: z.array(ScheduleOut) })
38
+ .meta({ id: "ScheduleListOut" });
39
+ /** `POST .../:sid/run_now` — the fire is enqueued onto the smith's serial delivery
40
+ * lane (not run inline), so the response acknowledges the queued delivery rather
41
+ * than a completed run. Poll `/v1/events` or the smith's runs for the outcome. */
42
+ export const ScheduleRunNowOut = z
43
+ .object({
44
+ schedule_id: z.string(),
45
+ delivery_id: z.string(),
46
+ status: z.literal("queued"),
47
+ })
48
+ .meta({ id: "ScheduleRunNowOut" });
49
+ // ── Request bodies ──────────────────────────────────────────────────────────
50
+ export const ScheduleIn = z
51
+ .object({
52
+ cron: z.string(),
53
+ name: z.string().nullish(),
54
+ timezone: z.string().default("UTC"),
55
+ input: ScheduleInput.default([]),
56
+ thread_id: z.string().nullish(),
57
+ max_concurrent: z.number().int().default(1),
58
+ enabled: z.boolean().default(true),
59
+ })
60
+ .meta({ id: "ScheduleIn" });
61
+ export const SchedulePatch = z
62
+ .object({
63
+ name: z.string().nullish(),
64
+ cron: z.string().nullish(),
65
+ timezone: z.string().nullish(),
66
+ input: ScheduleInput.nullish(),
67
+ thread_id: z.string().nullish(),
68
+ max_concurrent: z.number().int().nullish(),
69
+ enabled: z.boolean().nullish(),
70
+ })
71
+ .meta({ id: "SchedulePatch" });
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Hand-authored Zod schemas for the `slack` channel-config resource — the
3
+ * wire's source of truth for `PUT/GET /v1/tenant/slack`.
4
+ *
5
+ * One source, three outputs: the API imports these into its `createRoute`
6
+ * definitions (validation + emitted OpenAPI), and the consumer-facing `IC*`
7
+ * type is `z.infer`red here and re-exported by `../responses`. No Zod is pulled
8
+ * into a type-only consumer — `responses.ts` re-exports this as `export type`.
9
+ *
10
+ * `.meta({ id })` names the component so the emitted OpenAPI references it as
11
+ * `#/components/schemas/<id>` rather than inlining it.
12
+ */
13
+ import { z } from "zod";
14
+ // ── Config status (GET/PUT response) ─────────────────────────────────────────
15
+ /** App factory posture: whether the tenant has minted-app credentials stored. */
16
+ export const SlackFactoryStatus = z
17
+ .object({ configured: z.boolean() })
18
+ .meta({ id: "SlackFactoryStatus" });
19
+ /**
20
+ * The tenant's Slack posture, as `tenantStatus` builds it. `configured`,
21
+ * `factory`, and `oauth_redirect_url` are always emitted; the shared-app
22
+ * details (`bot_user_id`, `team_id`, `events_url`, `oauth_ready`) only appear
23
+ * once a shared app is configured, and `return_url` only when one is set.
24
+ */
25
+ export const SlackAppOut = z
26
+ .object({
27
+ configured: z.boolean(),
28
+ bot_user_id: z.string().optional(),
29
+ team_id: z.string().optional(),
30
+ events_url: z.string().optional(),
31
+ /** Shared app's OAuth client is set — "Add to Slack" installs work. */
32
+ oauth_ready: z.boolean().optional(),
33
+ oauth_redirect_url: z.string().optional(),
34
+ /** Where the OAuth redirect sends installers back (?slack=… appended). */
35
+ return_url: z.string().optional(),
36
+ /** App factory: mints per-smith Slack apps from the manifest template. */
37
+ factory: SlackFactoryStatus.optional(),
38
+ })
39
+ .meta({ id: "SlackAppOut" });
40
+ // ── Request bodies (PUT /v1/tenant/slack) ────────────────────────────────────
41
+ /**
42
+ * The app-factory block: a delegated app-config token pair plus the Slack app
43
+ * manifest template that minted per-smith apps are instantiated from.
44
+ */
45
+ export const SlackFactoryIn = z
46
+ .object({
47
+ config_token: z.string(),
48
+ config_refresh_token: z.string().nullish(),
49
+ manifest_template: z.record(z.string(), z.unknown()),
50
+ })
51
+ .meta({ id: "SlackFactoryIn" });
52
+ /**
53
+ * Register or rotate the tenant's Slack posture: a shared app (bot_token +
54
+ * signing_secret, optionally the OAuth client fields), a factory block, and/or
55
+ * the return_url. Every field is optional — the handler applies whichever
56
+ * blocks are present.
57
+ */
58
+ export const SlackAppIn = z
59
+ .object({
60
+ bot_token: z.string().nullish(),
61
+ signing_secret: z.string().nullish(),
62
+ client_id: z.string().nullish(),
63
+ client_secret: z.string().nullish(),
64
+ oauth_scopes: z.string().nullish(),
65
+ oauth_user_scopes: z.string().nullish(),
66
+ return_url: z.string().nullish(),
67
+ factory: SlackFactoryIn.nullish(),
68
+ })
69
+ .meta({ id: "SlackAppIn" });
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Hand-authored Zod schemas for the `smith-revisions` resource — the wire's
3
+ * source of truth for `/v1/smiths/{id}/revisions`.
4
+ *
5
+ * One source, three outputs: the API imports these into its `createRoute`
6
+ * definitions (validation + emitted OpenAPI), and the consumer-facing `IC*`
7
+ * type is `z.infer`red from them here and re-exported by `../responses`. No Zod
8
+ * is pulled into a type-only consumer — `responses.ts` re-exports as types.
9
+ *
10
+ * A smith's behaviour config (instructions / model / hosted tools / auto-memory)
11
+ * is mutable; every change is snapshotted as an immutable *revision* and an
12
+ * operator can roll back. History is append-only — a *restore* re-applies an old
13
+ * snapshot as a brand-new revision.
14
+ *
15
+ * `.meta({ id })` names the component so the emitted OpenAPI references it as
16
+ * `#/components/schemas/<id>` rather than inlining it.
17
+ */
18
+ import { z } from "zod";
19
+ /** An immutable snapshot of a smith's effective behaviour config at one revision. */
20
+ export const SmithRevisionOut = z
21
+ .object({
22
+ version: z.number().int(),
23
+ snapshot: z.object({
24
+ instructions: z.string().nullish(),
25
+ model: z.string().nullish(),
26
+ enabled_hosted_tools: z.array(z.string()).optional(),
27
+ vector_store_ids: z.array(z.string()).optional(),
28
+ auto_memory: z.boolean().optional(),
29
+ memory_consolidation: z.boolean().optional(),
30
+ }),
31
+ created_by: z.string().nullish(),
32
+ note: z.string().nullish(),
33
+ created_at: z.string().nullish(),
34
+ })
35
+ .meta({ id: "SmithRevisionOut" });
36
+ export const RevisionListOut = z
37
+ .object({ data: z.array(SmithRevisionOut) })
38
+ .meta({ id: "RevisionListOut" });
39
+ // ── Request bodies ──────────────────────────────────────────────────────────
40
+ export const RestoreIn = z
41
+ .object({ note: z.string().nullish() })
42
+ .meta({ id: "RestoreIn" });
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Hand-authored Zod schemas for the `smiths` resource — the wire's source of
3
+ * truth, replacing the loose generated `schemas.ts` shapes for this resource.
4
+ *
5
+ * One source, three outputs: the API imports these into its `createRoute`
6
+ * definitions (validation + emitted OpenAPI), and the consumer-facing `IC*`
7
+ * types are `z.infer`red from them here and re-exported by `../responses`. No
8
+ * Zod is pulled into a type-only consumer — `responses.ts` re-exports these as
9
+ * `export type`.
10
+ *
11
+ * A smith is one running clone of an agent (`/v1/smiths`, `smt_` ids), the unit
12
+ * of data isolation. Its identity fields live alongside its *effective* agent
13
+ * config (model/instructions/tools), flattened onto the resource. Memory is a
14
+ * separate sub-resource (`/v1/smiths/{id}/memory`, schemas in `./memories`).
15
+ *
16
+ * `.meta({ id })` names the component so the emitted OpenAPI references it as
17
+ * `#/components/schemas/<id>` rather than inlining it.
18
+ */
19
+ import { z } from "zod";
20
+ // ── Smith response ───────────────────────────────────────────────────────────
21
+ export const SmithOut = z
22
+ .object({
23
+ id: z.string(),
24
+ external_id: z.string().nullable(),
25
+ display_name: z.string().nullable(),
26
+ locale: z.string().nullable(),
27
+ timezone: z.string().nullable(),
28
+ /** The customer (billable party) this smith's usage rolls up to. */
29
+ customer_id: z.string().nullish(),
30
+ metadata: z.record(z.string(), z.unknown()).optional(),
31
+ // The *effective* agent config (agent-resolved when attached).
32
+ model: z.string(),
33
+ /** The raw instructions template (may contain {{ variables }}). */
34
+ instructions: z.string(),
35
+ /** What this smith actually runs with — {{ variables }} bound per-smith. */
36
+ rendered_instructions: z.string().nullish(),
37
+ enabled_hosted_tools: z.array(z.string()).optional(),
38
+ vector_store_ids: z.array(z.string()).optional(),
39
+ auto_memory: z.boolean().optional(),
40
+ memory_consolidation: z.boolean().optional(),
41
+ /** How the config resolved: by reference, with overrides, or embedded. */
42
+ config_source: z.enum(["agent", "override", "custom"]).optional(),
43
+ agent_id: z.string().nullish(),
44
+ agent_version: z.number().int().nullish(),
45
+ pin: z.number().int().nullish(),
46
+ /** Which config fields this smith overrides on top of its agent version.
47
+ * The rest track the agent. Empty for a clean reference or a standalone
48
+ * smith. Clear an override by PATCHing that field to `null`. */
49
+ override_keys: z.array(z.string()).optional(),
50
+ /** What each field reverts to — the agent version's value, before this
51
+ * smith's overrides. `null` for a standalone smith (nothing to inherit). */
52
+ inherited: z
53
+ .object({
54
+ model: z.string(),
55
+ instructions: z.string().nullable(),
56
+ enabled_hosted_tools: z.array(z.string()),
57
+ vector_store_ids: z.array(z.string()),
58
+ auto_memory: z.boolean().nullable(),
59
+ memory_consolidation: z.boolean().nullable(),
60
+ })
61
+ .nullish(),
62
+ created_at: z.string(),
63
+ })
64
+ .meta({ id: "SmithOut" });
65
+ /** Cursor-paginated smith list: `data` + `has_more` (+ opaque `next_cursor`). */
66
+ export const SmithListOut = z
67
+ .object({
68
+ data: z.array(SmithOut),
69
+ has_more: z.boolean(),
70
+ next_cursor: z.string().nullish(),
71
+ })
72
+ .meta({ id: "SmithListOut" });
73
+ // ── Request bodies ──────────────────────────────────────────────────────────
74
+ export const SmithCreate = z
75
+ .object({
76
+ external_id: z.string().nullish(),
77
+ display_name: z.string().nullish(),
78
+ locale: z.string().nullish(),
79
+ timezone: z.string().nullish(),
80
+ customer_id: z.string().nullish(),
81
+ metadata: z.record(z.string(), z.unknown()).optional(),
82
+ agent_id: z.string().nullish(),
83
+ pin: z.number().int().nullish(),
84
+ model: z.string().nullish(),
85
+ instructions: z.string().nullish(),
86
+ enabled_hosted_tools: z.array(z.string()).nullish(),
87
+ vector_store_ids: z.array(z.string()).nullish(),
88
+ auto_memory: z.boolean().nullish(),
89
+ memory_consolidation: z.boolean().nullish(),
90
+ })
91
+ .meta({ id: "SmithCreate" });
92
+ export const SmithPatch = z
93
+ .object({
94
+ display_name: z.string().nullish(),
95
+ locale: z.string().nullish(),
96
+ timezone: z.string().nullish(),
97
+ customer_id: z.string().nullish(),
98
+ metadata: z.record(z.string(), z.unknown()).nullish(),
99
+ agent_id: z.string().nullish(),
100
+ pin: z.number().int().nullish(),
101
+ model: z.string().nullish(),
102
+ instructions: z.string().nullish(),
103
+ enabled_hosted_tools: z.array(z.string()).nullish(),
104
+ vector_store_ids: z.array(z.string()).nullish(),
105
+ auto_memory: z.boolean().nullish(),
106
+ memory_consolidation: z.boolean().nullish(),
107
+ })
108
+ .meta({ id: "SmithPatch" });
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Hand-authored Zod schemas for the `telegram` channel-config resource — the
3
+ * wire's source of truth, replacing the loose generated shapes for this
4
+ * resource.
5
+ *
6
+ * One source, three outputs: the API imports these into its `createRoute`
7
+ * definitions (validation + emitted OpenAPI), and the consumer-facing `IC*`
8
+ * types are `z.infer`red from them here and re-exported by `../responses`. No
9
+ * Zod is pulled into a type-only consumer — `responses.ts` re-exports these as
10
+ * `export type`.
11
+ *
12
+ * `.meta({ id })` names the component so the emitted OpenAPI references it as
13
+ * `#/components/schemas/<id>` rather than inlining it.
14
+ */
15
+ import { z } from "zod";
16
+ /**
17
+ * The tenant's Telegram bot config status. The token itself is never returned;
18
+ * the optional fields are present only once `configured` is true (`has_token`
19
+ * appears on the read path, not the just-configured write response).
20
+ */
21
+ export const TelegramBotOut = z
22
+ .object({
23
+ configured: z.boolean(),
24
+ bot_username: z.string().optional(),
25
+ bot_id: z.number().int().optional(),
26
+ has_token: z.boolean().optional(),
27
+ webhook_url: z.string().optional(),
28
+ })
29
+ .meta({ id: "TelegramBotOut" });
30
+ // ── Request bodies ──────────────────────────────────────────────────────────
31
+ export const TelegramBotIn = z
32
+ .object({
33
+ bot_token: z.string(),
34
+ webhook_secret: z.string().nullish(),
35
+ })
36
+ .meta({ id: "TelegramBotIn" });
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Hand-authored Zod schemas for the `tenant` config plane — the grab-bag router
3
+ * (`api/src/routes/tenant.ts`) serving the events feed, hosted-tool catalog,
4
+ * BYOK model keys, the model catalog, OAuth client providers, minted tokens, the
5
+ * usage summary, and webhooks.
6
+ *
7
+ * One source, three outputs: the API imports these into its `createRoute`
8
+ * definitions (validation + emitted OpenAPI), and the consumer-facing `IC*`
9
+ * types are `z.infer`red from them here and re-exported by `../responses`.
10
+ *
11
+ * `.meta({ id })` names the component so the emitted OpenAPI references it as
12
+ * `#/components/schemas/<id>` rather than inlining it.
13
+ */
14
+ import { z } from "zod";
15
+ import { pageOut } from "./_page.js";
16
+ // ── Events (poll mirror of the webhook firehose) ─────────────────────────────
17
+ /** One event in the `/v1/events` feed — the `{v:1}` envelope (sans `tenant_id`,
18
+ * which the feed omits since the tenant is implicit in the token). */
19
+ export const EventOut = z
20
+ .object({
21
+ /** Envelope schema version (always `1` today). */
22
+ v: z.number().int(),
23
+ id: z.string(),
24
+ type: z.string(),
25
+ smith_id: z.string().nullable(),
26
+ data: z.record(z.string(), z.unknown()),
27
+ created_at: z.string().nullable(),
28
+ })
29
+ .meta({ id: "EventOut" });
30
+ export const EventListOut = pageOut(EventOut, "EventListOut");
31
+ // ── Webhooks ─────────────────────────────────────────────────────────────────
32
+ export const WebhookOut = z
33
+ .object({
34
+ id: z.string(),
35
+ url: z.string(),
36
+ events: z.array(z.string()),
37
+ active: z.boolean(),
38
+ created_at: z.string().nullable(),
39
+ })
40
+ .meta({ id: "WebhookOut" });
41
+ export const WebhookListOut = pageOut(WebhookOut, "WebhookListOut");
42
+ /** The create response — the signing `secret` is returned EXACTLY ONCE, here. */
43
+ export const WebhookCreateOut = z
44
+ .object({
45
+ id: z.string(),
46
+ url: z.string(),
47
+ events: z.array(z.string()),
48
+ active: z.boolean(),
49
+ secret: z.string(),
50
+ })
51
+ .meta({ id: "WebhookCreateOut" });
52
+ /** The patch/delete-adjacent ack shape (just the id). */
53
+ export const WebhookIdOut = z
54
+ .object({ id: z.string() })
55
+ .meta({ id: "WebhookIdOut" });
56
+ export const WebhookIn = z
57
+ .object({
58
+ url: z.string(),
59
+ events: z.array(z.string()).default([]),
60
+ active: z.boolean().default(true),
61
+ })
62
+ .meta({ id: "WebhookIn" });
63
+ export const WebhookPatch = z
64
+ .object({
65
+ url: z.string().nullish(),
66
+ events: z.array(z.string()).nullish(),
67
+ active: z.boolean().nullish(),
68
+ })
69
+ .meta({ id: "WebhookPatch" });
70
+ // ── Tokens (mint / list / revoke RS256 JWTs) ─────────────────────────────────
71
+ /** A minted-token *summary* — the list/listing shape. The secret `token` is
72
+ * NEVER echoed here; it only appears in {@link MintedTokenOut} on create. */
73
+ export const TokenOut = z
74
+ .object({
75
+ id: z.string(),
76
+ name: z.string().nullable(),
77
+ sub: z.string(),
78
+ scopes: z.array(z.string()),
79
+ prefix: z.string().nullable(),
80
+ created_at: z.string().nullable(),
81
+ expires_at: z.string().nullable(),
82
+ revoked_at: z.string().nullable(),
83
+ })
84
+ .meta({ id: "TokenOut" });
85
+ export const TokenListOut = pageOut(TokenOut, "TokenListOut");
86
+ /** The create response — carries the secret `token` exactly once. */
87
+ export const MintedTokenOut = z
88
+ .object({
89
+ id: z.string(),
90
+ token: z.string(),
91
+ scope: z.string(),
92
+ sub: z.string(),
93
+ scopes: z.array(z.string()),
94
+ expires_at: z.string().nullable(),
95
+ })
96
+ .meta({ id: "MintedTokenOut" });
97
+ export const TokenIn = z
98
+ .object({
99
+ scope: z.string().default("smith"),
100
+ smith_id: z.string().nullish(),
101
+ permissions: z.array(z.string()).nullish(),
102
+ ttl_seconds: z.number().int().nullish(),
103
+ name: z.string().nullish(),
104
+ })
105
+ .meta({ id: "TokenIn" });
106
+ // ── Usage (aggregated token usage across the tenant's runs, by day) ──────────
107
+ export const UsageOut = z
108
+ .object({
109
+ totals: z.object({
110
+ runs: z.number().int(),
111
+ input_tokens: z.number().int(),
112
+ output_tokens: z.number().int(),
113
+ total_tokens: z.number().int(),
114
+ }),
115
+ series: z.array(z.object({
116
+ date: z.string(),
117
+ runs: z.number().int(),
118
+ total_tokens: z.number().int(),
119
+ })),
120
+ })
121
+ .meta({ id: "UsageOut" });
122
+ // ── Model catalog + BYOK keys ────────────────────────────────────────────────
123
+ /** One selectable model in the `/v1/tenant/models` catalog. */
124
+ export const ModelOut = z
125
+ .object({
126
+ id: z.string(),
127
+ provider: z.string(),
128
+ label: z.string(),
129
+ available: z.boolean(),
130
+ /** Whose key a run would use: the tenant's ("byok") or Ingram-hosted ("hosted"). */
131
+ source: z.enum(["byok", "hosted"]).nullish(),
132
+ })
133
+ .meta({ id: "ModelOut" });
134
+ /** A runnable backend in the model catalog (NB `base_url` is a *bool flag* — does
135
+ * the provider accept a base-url override — not a URL). */
136
+ export const ModelProviderOut = z
137
+ .object({
138
+ id: z.string(),
139
+ label: z.string(),
140
+ base_url: z.boolean(),
141
+ /** True when Ingram hosts a key for this provider (runnable without a tenant key). */
142
+ hosted: z.boolean().optional(),
143
+ })
144
+ .meta({ id: "ModelProviderOut" });
145
+ export const ModelsListOut = z
146
+ .object({
147
+ data: z.array(ModelOut),
148
+ providers: z.array(ModelProviderOut),
149
+ })
150
+ .meta({ id: "ModelsListOut" });
151
+ /** A BYOK model key — the `api_key` is NEVER echoed, only its presence. */
152
+ export const ModelKeyOut = z
153
+ .object({
154
+ provider: z.string(),
155
+ base_url: z.string().nullable(),
156
+ has_key: z.boolean(),
157
+ updated_at: z.string().nullable(),
158
+ })
159
+ .meta({ id: "ModelKeyOut" });
160
+ export const ModelKeyListOut = z
161
+ .object({ data: z.array(ModelKeyOut) })
162
+ .meta({ id: "ModelKeyListOut" });
163
+ /** The PUT ack — never echoes the key, only presence + the (non-secret) base_url. */
164
+ export const ModelKeyConfiguredOut = z
165
+ .object({
166
+ provider: z.string(),
167
+ configured: z.boolean(),
168
+ base_url: z.string().nullable(),
169
+ })
170
+ .meta({ id: "ModelKeyConfiguredOut" });
171
+ export const ModelKeyIn = z
172
+ .object({
173
+ api_key: z.string(),
174
+ base_url: z.string().nullish(),
175
+ })
176
+ .meta({ id: "ModelKeyIn" });
177
+ // ── Providers (tenant OAuth client credentials) ──────────────────────────────
178
+ /** A provider's OAuth client config — the `client_secret` is NEVER echoed, only
179
+ * `has_client_secret`. */
180
+ export const ProviderOut = z
181
+ .object({
182
+ provider: z.string(),
183
+ client_id: z.string().nullable(),
184
+ token_uri: z.string().nullable(),
185
+ scopes_allowed: z.array(z.string()),
186
+ refresh_webhook: z.string().nullable(),
187
+ has_client_secret: z.boolean(),
188
+ })
189
+ .meta({ id: "ProviderOut" });
190
+ export const ProviderListOut = z
191
+ .object({ data: z.array(ProviderOut) })
192
+ .meta({ id: "ProviderListOut" });
193
+ /** The PUT ack. */
194
+ export const ProviderConfiguredOut = z
195
+ .object({
196
+ provider: z.string(),
197
+ configured: z.boolean(),
198
+ })
199
+ .meta({ id: "ProviderConfiguredOut" });
200
+ export const ProviderIn = z
201
+ .object({
202
+ client_id: z.string().nullish(),
203
+ client_secret: z.string().nullish(),
204
+ token_uri: z.string().nullish(),
205
+ scopes_allowed: z.array(z.string()).default([]),
206
+ refresh_webhook: z.string().nullish(),
207
+ })
208
+ .meta({ id: "ProviderIn" });
209
+ // ── Hosted-tool catalog ──────────────────────────────────────────────────────
210
+ /** One tool hosted by Ingram Cloud that the catalog advertises. */
211
+ export const HostedToolOut = z
212
+ .object({
213
+ name: z.string(),
214
+ description: z.string(),
215
+ })
216
+ .meta({ id: "HostedToolOut" });
217
+ export const HostedToolsListOut = z
218
+ .object({ data: z.array(HostedToolOut) })
219
+ .meta({ id: "HostedToolsListOut" });