@ingram-tech/ingram-cloud-sdk 0.1.2 → 0.2.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.
@@ -0,0 +1,79 @@
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
+
15
+ // ── Config status (GET/PUT response) ─────────────────────────────────────────
16
+
17
+ /** App factory posture: whether the tenant has minted-app credentials stored. */
18
+ export const SlackFactoryStatus = z
19
+ .object({ configured: z.boolean() })
20
+ .meta({ id: "SlackFactoryStatus" });
21
+
22
+ /**
23
+ * The tenant's Slack posture, as `tenantStatus` builds it. `configured`,
24
+ * `factory`, and `oauth_redirect_url` are always emitted; the shared-app
25
+ * details (`bot_user_id`, `team_id`, `events_url`, `oauth_ready`) only appear
26
+ * once a shared app is configured, and `return_url` only when one is set.
27
+ */
28
+ export const SlackAppOut = z
29
+ .object({
30
+ configured: z.boolean(),
31
+ bot_user_id: z.string().optional(),
32
+ team_id: z.string().optional(),
33
+ events_url: z.string().optional(),
34
+ /** Shared app's OAuth client is set — "Add to Slack" installs work. */
35
+ oauth_ready: z.boolean().optional(),
36
+ oauth_redirect_url: z.string().optional(),
37
+ /** Where the OAuth redirect sends installers back (?slack=… appended). */
38
+ return_url: z.string().optional(),
39
+ /** App factory: mints per-smith Slack apps from the manifest template. */
40
+ factory: SlackFactoryStatus.optional(),
41
+ })
42
+ .meta({ id: "SlackAppOut" });
43
+
44
+ // ── Request bodies (PUT /v1/tenant/slack) ────────────────────────────────────
45
+
46
+ /**
47
+ * The app-factory block: a delegated app-config token pair plus the Slack app
48
+ * manifest template that minted per-smith apps are instantiated from.
49
+ */
50
+ export const SlackFactoryIn = z
51
+ .object({
52
+ config_token: z.string(),
53
+ config_refresh_token: z.string().nullish(),
54
+ manifest_template: z.record(z.string(), z.unknown()),
55
+ })
56
+ .meta({ id: "SlackFactoryIn" });
57
+
58
+ /**
59
+ * Register or rotate the tenant's Slack posture: a shared app (bot_token +
60
+ * signing_secret, optionally the OAuth client fields), a factory block, and/or
61
+ * the return_url. Every field is optional — the handler applies whichever
62
+ * blocks are present.
63
+ */
64
+ export const SlackAppIn = z
65
+ .object({
66
+ bot_token: z.string().nullish(),
67
+ signing_secret: z.string().nullish(),
68
+ client_id: z.string().nullish(),
69
+ client_secret: z.string().nullish(),
70
+ oauth_scopes: z.string().nullish(),
71
+ oauth_user_scopes: z.string().nullish(),
72
+ return_url: z.string().nullish(),
73
+ factory: SlackFactoryIn.nullish(),
74
+ })
75
+ .meta({ id: "SlackAppIn" });
76
+
77
+ // ── Inferred consumer-facing type (re-exported by ../responses) ──────────────
78
+
79
+ export type ICSlackApp = z.infer<typeof SlackAppOut>;
@@ -0,0 +1,48 @@
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
+
20
+ /** An immutable snapshot of a smith's effective behaviour config at one revision. */
21
+ export const SmithRevisionOut = z
22
+ .object({
23
+ version: z.number().int(),
24
+ snapshot: z.object({
25
+ instructions: z.string().nullish(),
26
+ model: z.string().nullish(),
27
+ enabled_hosted_tools: z.array(z.string()).optional(),
28
+ auto_memory: z.boolean().optional(),
29
+ }),
30
+ created_by: z.string().nullish(),
31
+ note: z.string().nullish(),
32
+ created_at: z.string().nullish(),
33
+ })
34
+ .meta({ id: "SmithRevisionOut" });
35
+
36
+ export const RevisionListOut = z
37
+ .object({ data: z.array(SmithRevisionOut) })
38
+ .meta({ id: "RevisionListOut" });
39
+
40
+ // ── Request bodies ──────────────────────────────────────────────────────────
41
+
42
+ export const RestoreIn = z
43
+ .object({ note: z.string().nullish() })
44
+ .meta({ id: "RestoreIn" });
45
+
46
+ // ── Inferred consumer-facing types (re-exported by ../responses) ─────────────
47
+
48
+ export type ICSmithRevision = z.infer<typeof SmithRevisionOut>;
@@ -0,0 +1,131 @@
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 blocks
14
+ * (`/v1/smiths/{id}/blocks`) are the smith's in-context "what the agent always
15
+ * knows" sub-resource.
16
+ *
17
+ * `.meta({ id })` names the component so the emitted OpenAPI references it as
18
+ * `#/components/schemas/<id>` rather than inlining it.
19
+ */
20
+ import { z } from "zod";
21
+
22
+ // ── Smith response ───────────────────────────────────────────────────────────
23
+
24
+ export const SmithOut = z
25
+ .object({
26
+ id: z.string(),
27
+ external_id: z.string().nullable(),
28
+ display_name: z.string().nullable(),
29
+ locale: z.string().nullable(),
30
+ timezone: z.string().nullable(),
31
+ /** The customer (billable party) this smith's usage rolls up to. */
32
+ customer_id: z.string().nullish(),
33
+ metadata: z.record(z.string(), z.unknown()).optional(),
34
+ // The *effective* agent config (agent-resolved when attached).
35
+ model: z.string(),
36
+ /** The raw instructions template (may contain {{ variables }}). */
37
+ instructions: z.string(),
38
+ /** What this smith actually runs with — {{ variables }} bound per-smith. */
39
+ rendered_instructions: z.string().nullish(),
40
+ enabled_hosted_tools: z.array(z.string()).optional(),
41
+ auto_memory: z.boolean().optional(),
42
+ /** How the config resolved: by reference, with overrides, or embedded. */
43
+ config_source: z.enum(["agent", "override", "custom"]).optional(),
44
+ agent_id: z.string().nullish(),
45
+ agent_version: z.number().int().nullish(),
46
+ pin: z.number().int().nullish(),
47
+ created_at: z.string(),
48
+ })
49
+ .meta({ id: "SmithOut" });
50
+
51
+ /** Cursor-paginated smith list: `data` + `has_more` (+ opaque `next_cursor`). */
52
+ export const SmithListOut = z
53
+ .object({
54
+ data: z.array(SmithOut),
55
+ has_more: z.boolean(),
56
+ next_cursor: z.string().nullish(),
57
+ })
58
+ .meta({ id: "SmithListOut" });
59
+
60
+ // ── Memory blocks (smith sub-resource) ───────────────────────────────────────
61
+
62
+ /** A core memory block — pinned, in-context text bounded by `char_limit`. */
63
+ export const BlockOut = z
64
+ .object({
65
+ id: z.string(),
66
+ label: z.string(),
67
+ description: z.string(),
68
+ value: z.string(),
69
+ char_limit: z.number().int(),
70
+ updated_at: z.string().nullable(),
71
+ })
72
+ .meta({ id: "BlockOut" });
73
+
74
+ /** Block list — the plain `{ data }` envelope (blocks don't paginate). */
75
+ export const BlockListOut = z
76
+ .object({ data: z.array(BlockOut) })
77
+ .meta({ id: "BlockListOut" });
78
+
79
+ /** Block-edit response — a single block wrapped in the `{ data }` envelope (the
80
+ * one-block sibling of the array `BlockListOut` that the block PATCH returns). */
81
+ export const BlockSingleOut = z
82
+ .object({ data: BlockOut })
83
+ .meta({ id: "BlockSingleOut" });
84
+
85
+ // ── Request bodies ──────────────────────────────────────────────────────────
86
+
87
+ export const SmithCreate = z
88
+ .object({
89
+ external_id: z.string().nullish(),
90
+ display_name: z.string().nullish(),
91
+ locale: z.string().nullish(),
92
+ timezone: z.string().nullish(),
93
+ customer_id: z.string().nullish(),
94
+ metadata: z.record(z.string(), z.unknown()).optional(),
95
+ agent_id: z.string().nullish(),
96
+ pin: z.number().int().nullish(),
97
+ model: z.string().nullish(),
98
+ instructions: z.string().nullish(),
99
+ enabled_hosted_tools: z.array(z.string()).nullish(),
100
+ auto_memory: z.boolean().nullish(),
101
+ })
102
+ .meta({ id: "SmithCreate" });
103
+
104
+ export const SmithPatch = z
105
+ .object({
106
+ display_name: z.string().nullish(),
107
+ locale: z.string().nullish(),
108
+ timezone: z.string().nullish(),
109
+ customer_id: z.string().nullish(),
110
+ metadata: z.record(z.string(), z.unknown()).nullish(),
111
+ agent_id: z.string().nullish(),
112
+ pin: z.number().int().nullish(),
113
+ model: z.string().nullish(),
114
+ instructions: z.string().nullish(),
115
+ enabled_hosted_tools: z.array(z.string()).nullish(),
116
+ auto_memory: z.boolean().nullish(),
117
+ })
118
+ .meta({ id: "SmithPatch" });
119
+
120
+ /** Edit a block's value — `replace` (default) or `append`. */
121
+ export const BlockPatch = z
122
+ .object({
123
+ value: z.string(),
124
+ mode: z.enum(["replace", "append"]).default("replace"),
125
+ })
126
+ .meta({ id: "BlockPatch" });
127
+
128
+ // ── Inferred consumer-facing types (re-exported by ../responses) ─────────────
129
+
130
+ export type ICSmith = z.infer<typeof SmithOut>;
131
+ export type ICBlock = z.infer<typeof BlockOut>;
@@ -0,0 +1,43 @@
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
+ /**
18
+ * The tenant's Telegram bot config status. The token itself is never returned;
19
+ * the optional fields are present only once `configured` is true (`has_token`
20
+ * appears on the read path, not the just-configured write response).
21
+ */
22
+ export const TelegramBotOut = z
23
+ .object({
24
+ configured: z.boolean(),
25
+ bot_username: z.string().optional(),
26
+ bot_id: z.number().int().optional(),
27
+ has_token: z.boolean().optional(),
28
+ webhook_url: z.string().optional(),
29
+ })
30
+ .meta({ id: "TelegramBotOut" });
31
+
32
+ // ── Request bodies ──────────────────────────────────────────────────────────
33
+
34
+ export const TelegramBotIn = z
35
+ .object({
36
+ bot_token: z.string(),
37
+ webhook_secret: z.string().nullish(),
38
+ })
39
+ .meta({ id: "TelegramBotIn" });
40
+
41
+ // ── Inferred consumer-facing types (re-exported by ../responses) ─────────────
42
+
43
+ export type ICTelegramBot = z.infer<typeof TelegramBotOut>;
@@ -0,0 +1,272 @@
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
+
16
+ // ── Events (poll mirror of the webhook firehose) ─────────────────────────────
17
+
18
+ /** One event in the `/v1/events` feed — the `{v:1}` envelope (sans `tenant_id`,
19
+ * which the feed omits since the tenant is implicit in the token). */
20
+ export const EventOut = z
21
+ .object({
22
+ /** Envelope schema version (always `1` today). */
23
+ v: z.number().int(),
24
+ id: z.string(),
25
+ type: z.string(),
26
+ smith_id: z.string().nullable(),
27
+ data: z.record(z.string(), z.unknown()),
28
+ created_at: z.string().nullable(),
29
+ })
30
+ .meta({ id: "EventOut" });
31
+
32
+ export const EventListOut = z
33
+ .object({ data: z.array(EventOut) })
34
+ .meta({ id: "EventListOut" });
35
+
36
+ // ── Webhooks ─────────────────────────────────────────────────────────────────
37
+
38
+ export const WebhookOut = z
39
+ .object({
40
+ id: z.string(),
41
+ url: z.string(),
42
+ events: z.array(z.string()),
43
+ active: z.boolean(),
44
+ created_at: z.string().nullable(),
45
+ })
46
+ .meta({ id: "WebhookOut" });
47
+
48
+ export const WebhookListOut = z
49
+ .object({ data: z.array(WebhookOut) })
50
+ .meta({ id: "WebhookListOut" });
51
+
52
+ /** The create response — the signing `secret` is returned EXACTLY ONCE, here. */
53
+ export const WebhookCreateOut = z
54
+ .object({
55
+ id: z.string(),
56
+ url: z.string(),
57
+ events: z.array(z.string()),
58
+ active: z.boolean(),
59
+ secret: z.string(),
60
+ })
61
+ .meta({ id: "WebhookCreateOut" });
62
+
63
+ /** The patch/delete-adjacent ack shape (just the id). */
64
+ export const WebhookIdOut = z
65
+ .object({ id: z.string() })
66
+ .meta({ id: "WebhookIdOut" });
67
+
68
+ export const WebhookIn = z
69
+ .object({
70
+ url: z.string(),
71
+ events: z.array(z.string()).default([]),
72
+ active: z.boolean().default(true),
73
+ })
74
+ .meta({ id: "WebhookIn" });
75
+
76
+ export const WebhookPatch = z
77
+ .object({
78
+ url: z.string().nullish(),
79
+ events: z.array(z.string()).nullish(),
80
+ active: z.boolean().nullish(),
81
+ })
82
+ .meta({ id: "WebhookPatch" });
83
+
84
+ // ── Tokens (mint / list / revoke RS256 JWTs) ─────────────────────────────────
85
+
86
+ /** A minted-token *summary* — the list/listing shape. The secret `token` is
87
+ * NEVER echoed here; it only appears in {@link MintedTokenOut} on create. */
88
+ export const TokenOut = z
89
+ .object({
90
+ id: z.string(),
91
+ name: z.string().nullable(),
92
+ sub: z.string(),
93
+ scopes: z.array(z.string()),
94
+ prefix: z.string().nullable(),
95
+ created_at: z.string().nullable(),
96
+ expires_at: z.string().nullable(),
97
+ revoked_at: z.string().nullable(),
98
+ })
99
+ .meta({ id: "TokenOut" });
100
+
101
+ export const TokenListOut = z
102
+ .object({ data: z.array(TokenOut) })
103
+ .meta({ id: "TokenListOut" });
104
+
105
+ /** The create response — carries the secret `token` exactly once. */
106
+ export const MintedTokenOut = z
107
+ .object({
108
+ id: z.string(),
109
+ token: z.string(),
110
+ scope: z.string(),
111
+ sub: z.string(),
112
+ scopes: z.array(z.string()),
113
+ expires_at: z.string().nullable(),
114
+ })
115
+ .meta({ id: "MintedTokenOut" });
116
+
117
+ export const TokenIn = z
118
+ .object({
119
+ scope: z.string().default("smith"),
120
+ smith_id: z.string().nullish(),
121
+ permissions: z.array(z.string()).nullish(),
122
+ ttl_seconds: z.number().int().nullish(),
123
+ name: z.string().nullish(),
124
+ })
125
+ .meta({ id: "TokenIn" });
126
+
127
+ // ── Usage (aggregated token usage across the tenant's runs, by day) ──────────
128
+
129
+ export const UsageOut = z
130
+ .object({
131
+ totals: z.object({
132
+ runs: z.number().int(),
133
+ input_tokens: z.number().int(),
134
+ output_tokens: z.number().int(),
135
+ total_tokens: z.number().int(),
136
+ }),
137
+ series: z.array(
138
+ z.object({
139
+ date: z.string(),
140
+ runs: z.number().int(),
141
+ total_tokens: z.number().int(),
142
+ }),
143
+ ),
144
+ })
145
+ .meta({ id: "UsageOut" });
146
+
147
+ // ── Model catalog + BYOK keys ────────────────────────────────────────────────
148
+
149
+ /** One selectable model in the `/v1/tenant/models` catalog. */
150
+ export const ModelOut = z
151
+ .object({
152
+ id: z.string(),
153
+ provider: z.string(),
154
+ label: z.string(),
155
+ available: z.boolean(),
156
+ /** Whose key a run would use: the tenant's ("byok") or IC's ("platform"). */
157
+ source: z.enum(["byok", "platform"]).nullish(),
158
+ })
159
+ .meta({ id: "ModelOut" });
160
+
161
+ /** A runnable backend in the model catalog (NB `base_url` is a *bool flag* — does
162
+ * the provider accept a base-url override — not a URL). */
163
+ export const ModelProviderOut = z
164
+ .object({
165
+ id: z.string(),
166
+ label: z.string(),
167
+ base_url: z.boolean(),
168
+ /** True when the platform fallback covers this provider (no tenant key). */
169
+ platform_key: z.boolean().optional(),
170
+ })
171
+ .meta({ id: "ModelProviderOut" });
172
+
173
+ export const ModelsListOut = z
174
+ .object({
175
+ data: z.array(ModelOut),
176
+ providers: z.array(ModelProviderOut),
177
+ })
178
+ .meta({ id: "ModelsListOut" });
179
+
180
+ /** A BYOK model key — the `api_key` is NEVER echoed, only its presence. */
181
+ export const ModelKeyOut = z
182
+ .object({
183
+ provider: z.string(),
184
+ base_url: z.string().nullable(),
185
+ has_key: z.boolean(),
186
+ updated_at: z.string().nullable(),
187
+ })
188
+ .meta({ id: "ModelKeyOut" });
189
+
190
+ export const ModelKeyListOut = z
191
+ .object({ data: z.array(ModelKeyOut) })
192
+ .meta({ id: "ModelKeyListOut" });
193
+
194
+ /** The PUT ack — never echoes the key, only presence + the (non-secret) base_url. */
195
+ export const ModelKeyConfiguredOut = z
196
+ .object({
197
+ provider: z.string(),
198
+ configured: z.boolean(),
199
+ base_url: z.string().nullable(),
200
+ })
201
+ .meta({ id: "ModelKeyConfiguredOut" });
202
+
203
+ export const ModelKeyIn = z
204
+ .object({
205
+ api_key: z.string(),
206
+ base_url: z.string().nullish(),
207
+ })
208
+ .meta({ id: "ModelKeyIn" });
209
+
210
+ // ── Providers (tenant OAuth client credentials) ──────────────────────────────
211
+
212
+ /** A provider's OAuth client config — the `client_secret` is NEVER echoed, only
213
+ * `has_client_secret`. */
214
+ export const ProviderOut = z
215
+ .object({
216
+ provider: z.string(),
217
+ client_id: z.string().nullable(),
218
+ token_uri: z.string().nullable(),
219
+ scopes_allowed: z.array(z.string()),
220
+ refresh_webhook: z.string().nullable(),
221
+ has_client_secret: z.boolean(),
222
+ })
223
+ .meta({ id: "ProviderOut" });
224
+
225
+ export const ProviderListOut = z
226
+ .object({ data: z.array(ProviderOut) })
227
+ .meta({ id: "ProviderListOut" });
228
+
229
+ /** The PUT ack. */
230
+ export const ProviderConfiguredOut = z
231
+ .object({
232
+ provider: z.string(),
233
+ configured: z.boolean(),
234
+ })
235
+ .meta({ id: "ProviderConfiguredOut" });
236
+
237
+ export const ProviderIn = z
238
+ .object({
239
+ client_id: z.string().nullish(),
240
+ client_secret: z.string().nullish(),
241
+ token_uri: z.string().nullish(),
242
+ scopes_allowed: z.array(z.string()).default([]),
243
+ refresh_webhook: z.string().nullish(),
244
+ })
245
+ .meta({ id: "ProviderIn" });
246
+
247
+ // ── Hosted-tool catalog ──────────────────────────────────────────────────────
248
+
249
+ /** One IC-hosted tool the catalog advertises. */
250
+ export const HostedToolOut = z
251
+ .object({
252
+ name: z.string(),
253
+ description: z.string(),
254
+ })
255
+ .meta({ id: "HostedToolOut" });
256
+
257
+ export const HostedToolsListOut = z
258
+ .object({ data: z.array(HostedToolOut) })
259
+ .meta({ id: "HostedToolsListOut" });
260
+
261
+ // ── Inferred consumer-facing types (re-exported by ../responses) ─────────────
262
+
263
+ export type ICEvent = z.infer<typeof EventOut>;
264
+ export type ICWebhook = z.infer<typeof WebhookOut>;
265
+ export type ICToken = z.infer<typeof TokenOut>;
266
+ export type ICMintedToken = z.infer<typeof MintedTokenOut>;
267
+ export type ICUsage = z.infer<typeof UsageOut>;
268
+ export type ICModel = z.infer<typeof ModelOut>;
269
+ export type ICModelProvider = z.infer<typeof ModelProviderOut>;
270
+ export type ICModelCatalog = z.infer<typeof ModelsListOut>;
271
+ export type ICModelKey = z.infer<typeof ModelKeyOut>;
272
+ export type ICProvider = z.infer<typeof ProviderOut>;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Hand-authored Zod schemas for the `whatsapp` 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
+ /**
18
+ * The tenant's WhatsApp Cloud API config status. Secrets are never returned;
19
+ * the optional fields are present only once `configured` is true.
20
+ *
21
+ * Two response paths share this shape: `GET /v1/tenant/whatsapp` (config
22
+ * status, exposes `has_app_secret`) and the just-configured `PUT` response
23
+ * (echoes back the `verify_token` to paste into Meta). `display_phone_number`
24
+ * is the E.164 number Meta has on file for the registered `phone_number_id`,
25
+ * and can be null until Meta reports it.
26
+ */
27
+ export const WhatsAppConfigOut = z
28
+ .object({
29
+ configured: z.boolean(),
30
+ phone_number_id: z.string().optional(),
31
+ display_phone_number: z.string().nullable().optional(),
32
+ has_app_secret: z.boolean().optional(),
33
+ webhook_url: z.string().optional(),
34
+ verify_token: z.string().optional(),
35
+ })
36
+ .meta({ id: "WhatsAppConfigOut" });
37
+
38
+ // ── Request bodies ──────────────────────────────────────────────────────────
39
+
40
+ export const WhatsAppConfigIn = z
41
+ .object({
42
+ // Optional at the shape layer so the handler's own validation runs and
43
+ // returns its specific `empty_config` code (rather than a pre-handler
44
+ // `invalid_request`); the handler requires both to be non-empty.
45
+ phone_number_id: z.string().optional(),
46
+ access_token: z.string().optional(),
47
+ app_secret: z.string().nullish(),
48
+ verify_token: z.string().nullish(),
49
+ business_id: z.string().nullish(),
50
+ })
51
+ .meta({ id: "WhatsAppConfigIn" });
52
+
53
+ // ── Inferred consumer-facing types (re-exported by ../responses) ─────────────
54
+
55
+ export type ICWhatsAppConfig = z.infer<typeof WhatsAppConfigOut>;