@ingram-tech/ingram-cloud-sdk 0.1.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/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@ingram-tech/ingram-cloud-sdk",
3
+ "version": "0.1.0",
4
+ "description": "The Ingram Cloud /v1 API wire contract in TypeScript: Zod request/response schemas (generated from the OpenAPI spec), hand-authored SSE/webhook event types, and the JSON response types. The source of truth for the wire shapes.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "homepage": "https://cloud.ingram.tech",
8
+ "keywords": ["ingram-cloud", "ingram", "sdk", "api", "wire", "zod", "openapi"],
9
+ "files": ["ts", "openapi.json"],
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "exports": {
14
+ ".": "./ts/index.ts",
15
+ "./schemas": "./ts/schemas.ts",
16
+ "./responses": "./ts/responses.ts",
17
+ "./openapi.json": "./openapi.json"
18
+ },
19
+ "scripts": {
20
+ "generate": "mkdir -p ts && openapi-zod-client openapi.json -o ts/schemas.ts --export-schemas && bun scripts/strip-client.ts",
21
+ "typecheck": "tsc --noEmit",
22
+ "lint": "oxlint",
23
+ "format": "oxfmt --write ."
24
+ },
25
+ "devDependencies": {
26
+ "@ingram-tech/oxlint-config": "^0.2.1",
27
+ "openapi-zod-client": "^1.18.3",
28
+ "oxfmt": "^0.54.0",
29
+ "oxlint": "^1.70.0",
30
+ "typescript": "^6.0.0"
31
+ },
32
+ "dependencies": {
33
+ "zod": "^4.4.3"
34
+ }
35
+ }
package/ts/events.ts ADDED
@@ -0,0 +1,114 @@
1
+ /**
2
+ * The Ingram Cloud event types — HAND-AUTHORED (not generated).
3
+ *
4
+ * Two event surfaces ride the native `{v:1}` envelope and are deliberately NOT in
5
+ * `openapi.json`: OpenAPI can't describe an SSE frame sequence (even OpenAI's own
6
+ * spec doesn't type its stream chunks — SDKs hand-define them). So these live
7
+ * here, hand-authored, and must be kept in step with
8
+ * `web/src/content/docs/events.md` (the canonical catalog).
9
+ *
10
+ * 1. {@link webhookEvent} — the append-only feed / webhook delivery envelope
11
+ * (`GET /v1/events`, signed webhook POSTs).
12
+ * 2. {@link streamFrame} — the live SSE run-stream frames (`POST .../runs` with
13
+ * `stream:true`), i.e. `runs.py::_stream`.
14
+ *
15
+ * `data` is `.passthrough()` on purpose: the catalog documents the *notable*
16
+ * fields per type, not an exhaustive closed shape — same philosophy as the
17
+ * `extra="allow"` response models. Consumers narrow on `type` / `event`.
18
+ */
19
+ import { z } from "zod";
20
+
21
+ // ─── Feed / webhook event types (docs/events.md "Event type catalog") ────────
22
+ export const EVENT_TYPES = [
23
+ "run.started",
24
+ "run.paused",
25
+ "run.completed",
26
+ "run.failed",
27
+ "run.cancelled",
28
+ "tool_call.requested",
29
+ "tool_call.completed",
30
+ "approval.required",
31
+ "approval.resolved",
32
+ "connection.required",
33
+ "unbound_message",
34
+ "message.completed",
35
+ "memory.consolidated",
36
+ "budget.threshold",
37
+ "usage.summary",
38
+ "channel.bound",
39
+ "channel.inbound",
40
+ "slack.app_provisioned",
41
+ "slack.install",
42
+ "slack.uninstalled",
43
+ "email.send_failed",
44
+ "webhook.test",
45
+ ] as const;
46
+
47
+ export const eventType = z.enum(EVENT_TYPES);
48
+ export type EventType = z.infer<typeof eventType>;
49
+
50
+ /**
51
+ * The envelope carried identically by the `/v1/events` feed and signed webhook
52
+ * POSTs. `type` is a plain string (not the enum) so a forward-added type still
53
+ * parses; compare against {@link EVENT_TYPES} / {@link eventType} when narrowing.
54
+ */
55
+ export const webhookEvent = z
56
+ .object({
57
+ v: z.literal(1),
58
+ id: z.string(),
59
+ type: z.string(),
60
+ created_at: z.string(),
61
+ tenant_id: z.string(),
62
+ smith_id: z.string().nullable().optional(),
63
+ data: z.record(z.string(), z.unknown()).default({}),
64
+ })
65
+ .passthrough();
66
+ export type WebhookEvent = z.infer<typeof webhookEvent>;
67
+
68
+ // ─── Native SSE run-stream frames (runs.py::_stream `{v:1, run_id, ...}`) ─────
69
+ // The SSE `event:` line becomes `event`; the frame's data fields sit alongside
70
+ // `v` / `run_id`. `tool.executing` / `tool.completed` are live-only (no feed
71
+ // mirror) — the one thing no standard expresses yet (see CLAUDE.md).
72
+ export const STREAM_EVENTS = [
73
+ "run.started",
74
+ "message.delta",
75
+ "tool.executing",
76
+ "tool.completed",
77
+ "run.paused",
78
+ "approval.required",
79
+ "tool_call.requested",
80
+ "run.completed",
81
+ "run.failed",
82
+ "run.cancelled",
83
+ "run.duplicate",
84
+ "message.completed",
85
+ ] as const;
86
+
87
+ export const streamEventName = z.enum(STREAM_EVENTS);
88
+ export type StreamEventName = z.infer<typeof streamEventName>;
89
+
90
+ export const streamFrame = z
91
+ .object({
92
+ event: z.string(),
93
+ v: z.number().optional(),
94
+ run_id: z.string().optional(),
95
+ })
96
+ .passthrough();
97
+ export type StreamFrame = z.infer<typeof streamFrame>;
98
+
99
+ // ─── A few well-known `data` shapes (convenience; still passthrough) ─────────
100
+ export const messageDeltaData = z.object({ delta: z.string() }).passthrough();
101
+ export const runCompletedData = z
102
+ .object({
103
+ stop_reason: z.string(),
104
+ usage: z.record(z.string(), z.unknown()).optional(),
105
+ })
106
+ .passthrough();
107
+ export const approvalRequiredData = z
108
+ .object({
109
+ approval_id: z.string(),
110
+ tool: z.string().nullable().optional(),
111
+ args: z.record(z.string(), z.unknown()).optional(),
112
+ })
113
+ .passthrough();
114
+ export const toolActivityData = z.object({ tool: z.string().nullable() }).passthrough();
package/ts/index.ts ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The Ingram Cloud API wire contract, in TypeScript.
3
+ *
4
+ * GENERATED — do not edit `schemas.ts` by hand. It is produced from
5
+ * `../openapi.json`, the hand-maintained source of truth for the wire:
6
+ *
7
+ * bun run generate # regenerate schemas.ts from openapi.json
8
+ *
9
+ * `schemas` is the named map of Zod schemas for the request/response bodies.
10
+ * It's used to validate the API's wire shapes in the `api/` test suite; this
11
+ * package is the source of truth for those shapes, not an HTTP client.
12
+ *
13
+ * `./events` is the hand-authored half: the `{v:1}` webhook/feed envelope and the
14
+ * SSE run-stream frames, which OpenAPI can't express. Together they make the
15
+ * contract complete — generated request/response bodies + hand-authored streams.
16
+ *
17
+ * See `../README.md`.
18
+ */
19
+ export { schemas } from "./schemas";
20
+ export * from "./events";
21
+ export type * from "./responses";
@@ -0,0 +1,434 @@
1
+ /**
2
+ * Hand-authored TypeScript types for the `/v1` JSON response bodies.
3
+ *
4
+ * The consumer-facing companion to the generated `schemas.ts` Zod schemas: these
5
+ * are lightweight, ergonomic mirrors of the wire response shapes, meant to be
6
+ * imported by API consumers (e.g. the console) to type the JSON they read back.
7
+ * `schemas.ts` validates wire shapes in the api/ test suite; these describe the
8
+ * same bodies as plain TS interfaces with no runtime/Zod dependency.
9
+ */
10
+
11
+ export interface ICSmith {
12
+ id: string;
13
+ external_id: string | null;
14
+ display_name: string | null;
15
+ locale: string | null;
16
+ timezone: string | null;
17
+ /** The customer (billable party) this smith's usage rolls up to. */
18
+ customer_id?: string | null;
19
+ metadata?: Record<string, unknown>;
20
+ // The *effective* agent config (agent-resolved when attached).
21
+ model: string;
22
+ /** The raw instructions template (may contain {{ variables }}). */
23
+ instructions: string;
24
+ /** What this smith actually runs with — {{ variables }} bound per-smith. */
25
+ rendered_instructions?: string | null;
26
+ enabled_hosted_tools?: string[];
27
+ auto_memory?: boolean;
28
+ /** How the config resolved: by reference, with overrides, or embedded. */
29
+ config_source?: "agent" | "override" | "custom";
30
+ agent_id?: string | null;
31
+ agent_version?: number | null;
32
+ pin?: number | null;
33
+ created_at: string;
34
+ }
35
+ export interface ICBlock {
36
+ id: string;
37
+ label: string;
38
+ description: string;
39
+ value: string;
40
+ char_limit: number;
41
+ updated_at: string | null;
42
+ }
43
+ export interface ICMemory {
44
+ id: string;
45
+ category: string | null;
46
+ subject: string | null;
47
+ content: string;
48
+ source: string | null;
49
+ created_at: string | null;
50
+ updated_at: string | null;
51
+ }
52
+ export interface ICToolCall {
53
+ tool_call_id: string;
54
+ tool: string;
55
+ args: Record<string, unknown>;
56
+ execution: string;
57
+ }
58
+ export interface ICRun {
59
+ id: string;
60
+ smith_id: string;
61
+ thread_id: string;
62
+ status: string;
63
+ channel: string;
64
+ input: Array<{ role: string; content: string }>;
65
+ output: { content?: string; tool_calls?: ICToolCall[] } | null;
66
+ stop_reason: string | null;
67
+ usage: Record<string, number> | null;
68
+ metadata?: Record<string, unknown>;
69
+ created_at: string | null;
70
+ updated_at: string | null;
71
+ }
72
+ export interface ICRunEvent {
73
+ seq: number;
74
+ type: string;
75
+ data: Record<string, unknown>;
76
+ created_at: string | null;
77
+ }
78
+ export interface ICConnection {
79
+ id: string;
80
+ provider: string;
81
+ scopes: string[];
82
+ status: string;
83
+ expires_at: string | null;
84
+ metadata?: Record<string, unknown>;
85
+ created_at: string | null;
86
+ }
87
+ export interface ICChannel {
88
+ id: string;
89
+ kind: string;
90
+ address: string;
91
+ provider: string | null;
92
+ provider_metadata?: Record<string, unknown>;
93
+ /** Names of the encrypted secret fields that are set (values never returned). */
94
+ secret_keys?: string[];
95
+ status: string;
96
+ created_at: string | null;
97
+ }
98
+ export interface ICSchedule {
99
+ id: string;
100
+ name: string | null;
101
+ cron: string;
102
+ timezone: string;
103
+ enabled: boolean;
104
+ next_fire_at: string | null;
105
+ last_fire_at: string | null;
106
+ created_at: string | null;
107
+ }
108
+ export interface ICApproval {
109
+ id: string;
110
+ run_id: string | null;
111
+ smith_id: string | null;
112
+ tool_call_id: string | null;
113
+ tool: string | null;
114
+ args: Record<string, unknown>;
115
+ status: string;
116
+ actor: string | null;
117
+ reason: string | null;
118
+ created_at: string | null;
119
+ resolved_at: string | null;
120
+ }
121
+ export interface ICEvent {
122
+ id: string;
123
+ type: string;
124
+ smith_id: string | null;
125
+ data: Record<string, unknown>;
126
+ created_at: string | null;
127
+ }
128
+ export interface ICMcpTool {
129
+ name: string;
130
+ description: string | null;
131
+ /** Effective gate: server destructiveHint OR an approval_policy match. */
132
+ requires_approval: boolean;
133
+ /** Passes the default-deny tool_allowlist (always true when no allow-list). */
134
+ enabled: boolean;
135
+ }
136
+ export interface ICApprovalRule {
137
+ match: string;
138
+ require?: string;
139
+ }
140
+ export interface ICMcpServer {
141
+ id: string;
142
+ name: string;
143
+ url: string;
144
+ auth: { kind: string; provider: string | null; client_mode?: string };
145
+ /** tenant_owned | tenant_registered | catalog. */
146
+ origin?: string;
147
+ catalog_slug?: string | null;
148
+ /** null = expose all discovered tools; otherwise the default-deny set. */
149
+ tool_allowlist?: string[] | null;
150
+ approval_policy?: ICApprovalRule[];
151
+ tools: ICMcpTool[];
152
+ tools_refreshed_at: string | null;
153
+ /** `degraded` when the edge failed discovery or its secret can't be decoded at
154
+ * run time; otherwise the stored lifecycle status. */
155
+ status: string;
156
+ /** Last discovery/runtime-load failure, or null when the edge is healthy. */
157
+ discovery_error: string | null;
158
+ created_at: string | null;
159
+ }
160
+ export interface ICCatalogEntry {
161
+ slug: string;
162
+ display_name: string;
163
+ description: string;
164
+ mcp_url: string;
165
+ auth: { kind: string; provider: string | null; client_mode: string };
166
+ scopes: string[];
167
+ default_allowlist: string[] | null;
168
+ default_approval_policy: ICApprovalRule[];
169
+ logo_url: string | null;
170
+ docs_url: string | null;
171
+ }
172
+ export interface ICWebhook {
173
+ id: string;
174
+ url: string;
175
+ events: string[];
176
+ active: boolean;
177
+ created_at: string | null;
178
+ }
179
+ export interface ICToken {
180
+ id: string;
181
+ name: string | null;
182
+ sub: string;
183
+ scopes: string[];
184
+ prefix: string | null;
185
+ created_at: string | null;
186
+ expires_at: string | null;
187
+ revoked_at: string | null;
188
+ }
189
+ export interface ICUsage {
190
+ totals: {
191
+ runs: number;
192
+ input_tokens: number;
193
+ output_tokens: number;
194
+ total_tokens: number;
195
+ };
196
+ series: Array<{ date: string; runs: number; total_tokens: number }>;
197
+ }
198
+ export interface ICProvider {
199
+ provider: string;
200
+ client_id: string | null;
201
+ has_client_secret: boolean;
202
+ token_uri: string | null;
203
+ scopes_allowed: string[];
204
+ refresh_webhook: string | null;
205
+ }
206
+ export interface ICModel {
207
+ id: string;
208
+ provider: string;
209
+ label: string;
210
+ available: boolean;
211
+ /** Whose key a run would use: the tenant's ("byok") or IC's ("platform"). */
212
+ source?: "byok" | "platform" | null;
213
+ }
214
+ export interface ICModelProvider {
215
+ id: string;
216
+ label: string;
217
+ base_url: boolean;
218
+ /** True when the platform fallback covers this provider (no tenant key). */
219
+ platform_key?: boolean;
220
+ }
221
+ export interface ICModelCatalog {
222
+ data: ICModel[];
223
+ providers: ICModelProvider[];
224
+ }
225
+ export interface ICModelKey {
226
+ provider: string;
227
+ base_url: string | null;
228
+ has_key: boolean;
229
+ updated_at: string | null;
230
+ }
231
+
232
+ /** Span kinds emitted by the observability backend. */
233
+ export type ICSpanKind =
234
+ | "run"
235
+ | "model_call"
236
+ | "tool_call"
237
+ | "memory_op"
238
+ | "retrieval"
239
+ | "sub_agent"
240
+ | "runtime_event";
241
+
242
+ /** A single timed unit of work inside a trace. */
243
+ export interface ICSpan {
244
+ id: string;
245
+ trace_id: string;
246
+ parent_span_id: string | null;
247
+ kind: ICSpanKind;
248
+ name: string;
249
+ status: string;
250
+ started_at: string;
251
+ ended_at: string | null;
252
+ duration_ms: number | null;
253
+ model: string | null;
254
+ input_tokens: number | null;
255
+ output_tokens: number | null;
256
+ cost: number | null;
257
+ attributes: Record<string, unknown>;
258
+ }
259
+
260
+ /** A span node in the nested `span_tree` (same shape + children). */
261
+ export interface ICSpanNode extends ICSpan {
262
+ children: ICSpanNode[];
263
+ }
264
+
265
+ /** Top-level trace — one end-to-end agent operation. */
266
+ export interface ICTrace {
267
+ id: string;
268
+ smith_id: string;
269
+ app_id: string | null;
270
+ root_kind: ICSpanKind;
271
+ name: string;
272
+ status: string;
273
+ started_at: string;
274
+ ended_at: string | null;
275
+ duration_ms: number | null;
276
+ total_tokens: number | null;
277
+ total_cost: number | null;
278
+ attributes: Record<string, unknown>;
279
+ }
280
+
281
+ /** A trace plus its flat spans and nested tree. */
282
+ export interface ICTraceDetail extends ICTrace {
283
+ spans: ICSpan[];
284
+ span_tree: ICSpanNode[];
285
+ }
286
+
287
+ /** Aggregated usage grouped by app, smith, model, or customer. */
288
+ export interface ICUsageBreakdown {
289
+ group_by: "app" | "smith" | "model" | "customer";
290
+ totals: { tokens: number; cost: number; run_count: number };
291
+ groups: Array<{
292
+ app?: string | null;
293
+ smith?: string | null;
294
+ model?: string | null;
295
+ // Customer-grouped views label unassigned usage `principal:<smith id>`.
296
+ customer?: string | null;
297
+ tokens: number;
298
+ cost: number;
299
+ run_count: number;
300
+ }>;
301
+ /** Custom billable events aggregated per meter over the same filters. */
302
+ meters?: Array<{
303
+ meter: string;
304
+ customer?: string | null;
305
+ quantity: number;
306
+ events: number;
307
+ }>;
308
+ }
309
+
310
+ export interface ICMintedToken {
311
+ id: string;
312
+ token: string;
313
+ scope: string;
314
+ sub: string;
315
+ scopes: string[];
316
+ expires_at: string | null;
317
+ }
318
+
319
+ export interface ICTelegramBot {
320
+ configured: boolean;
321
+ bot_username?: string;
322
+ bot_id?: number;
323
+ has_token?: boolean;
324
+ webhook_url?: string;
325
+ }
326
+
327
+ export interface ICSlackApp {
328
+ configured: boolean;
329
+ bot_user_id?: string;
330
+ team_id?: string;
331
+ events_url?: string;
332
+ /** Shared app's OAuth client is set — "Add to Slack" installs work. */
333
+ oauth_ready?: boolean;
334
+ oauth_redirect_url?: string;
335
+ /** Where the OAuth redirect sends installers back (?slack=… appended). */
336
+ return_url?: string;
337
+ /** App factory: mints per-smith Slack apps from the manifest template. */
338
+ factory?: { configured: boolean };
339
+ }
340
+
341
+ export interface ICEmailConfig {
342
+ configured: boolean;
343
+ from_domain?: string;
344
+ display_name?: string | null;
345
+ has_token?: boolean;
346
+ inbound_url?: string;
347
+ /** Only present on PUT (shown once) — wire it into the inbound worker. */
348
+ inbound_secret?: string;
349
+ }
350
+
351
+ export interface ICCustomer {
352
+ id: string;
353
+ name: string;
354
+ external_ids: Record<string, string>;
355
+ metadata: Record<string, unknown>;
356
+ smith_count?: number;
357
+ created_at: string | null;
358
+ }
359
+
360
+ export interface ICBudget {
361
+ id: string;
362
+ scope: "tenant" | "smith" | "customer";
363
+ scope_id?: string | null;
364
+ period: string;
365
+ limit_usd: number;
366
+ action: "warn" | "block";
367
+ created_at?: string | null;
368
+ }
369
+ export interface ICBudgetStatus extends ICBudget {
370
+ period_start: string;
371
+ period_key: string;
372
+ spent: number;
373
+ pct: number;
374
+ over: boolean;
375
+ }
376
+
377
+ export interface ICSmithRevision {
378
+ version: number;
379
+ snapshot: {
380
+ instructions?: string | null;
381
+ model?: string | null;
382
+ enabled_hosted_tools?: string[];
383
+ auto_memory?: boolean;
384
+ };
385
+ created_by?: string | null;
386
+ note?: string | null;
387
+ created_at?: string | null;
388
+ }
389
+
390
+ /** A per-smith variable an agent declares; bound at run time. */
391
+ export interface ICAgentVariable {
392
+ name: string;
393
+ default?: string | null;
394
+ description?: string | null;
395
+ required?: boolean;
396
+ }
397
+
398
+ export interface ICAgent {
399
+ id: string;
400
+ /** Immutable, project-unique IaC reconcile key. Null for the default agent. */
401
+ slug: string | null;
402
+ /** Free, mutable display label (not unique). */
403
+ name: string;
404
+ /** True for the lazily-created default agent (can't be deleted). */
405
+ is_default: boolean;
406
+ /** The mutable draft head — what the next publish snapshots. */
407
+ draft: {
408
+ instructions: string | null;
409
+ model: string | null;
410
+ enabled_hosted_tools: string[];
411
+ auto_memory: boolean | null;
412
+ variables: ICAgentVariable[];
413
+ };
414
+ active_version: number | null;
415
+ rollout_version: number | null;
416
+ rollout_percent: number;
417
+ smith_count?: number;
418
+ created_at: string | null;
419
+ updated_at: string | null;
420
+ }
421
+
422
+ export interface ICAgentVersion {
423
+ version: number;
424
+ snapshot: {
425
+ instructions?: string | null;
426
+ model?: string | null;
427
+ enabled_hosted_tools?: string[];
428
+ auto_memory?: boolean | null;
429
+ variables?: ICAgentVariable[];
430
+ };
431
+ created_by?: string | null;
432
+ note?: string | null;
433
+ created_at?: string | null;
434
+ }