@ingram-cloud/sdk 1.4.0 → 1.5.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 (49) hide show
  1. package/dist/client.js +168 -15
  2. package/dist/index.js +4 -0
  3. package/dist/scopes.js +52 -0
  4. package/dist/zod/_actor.js +33 -0
  5. package/dist/zod/_page.js +18 -4
  6. package/dist/zod/agents.js +7 -3
  7. package/dist/zod/billing.js +136 -0
  8. package/dist/zod/budgets.js +2 -3
  9. package/dist/zod/connections.js +2 -3
  10. package/dist/zod/conversations.js +4 -11
  11. package/dist/zod/deployments.js +32 -0
  12. package/dist/zod/files.js +2 -9
  13. package/dist/zod/index.js +3 -0
  14. package/dist/zod/mcp.js +8 -10
  15. package/dist/zod/observability.js +38 -19
  16. package/dist/zod/projects.js +4 -4
  17. package/dist/zod/runs.js +16 -4
  18. package/dist/zod/schedules.js +2 -7
  19. package/dist/zod/skills.js +73 -0
  20. package/dist/zod/smith-revisions.js +2 -3
  21. package/dist/zod/smiths.js +6 -0
  22. package/dist/zod/tenant.js +24 -4
  23. package/dist/zod/vector-stores.js +6 -19
  24. package/package.json +6 -8
  25. package/ts/client.ts +385 -51
  26. package/ts/index.ts +4 -0
  27. package/ts/responses.ts +40 -2
  28. package/ts/scopes.ts +57 -0
  29. package/ts/zod/.impeccable/hook.cache.json +1 -0
  30. package/ts/zod/_actor.ts +36 -0
  31. package/ts/zod/_page.ts +19 -4
  32. package/ts/zod/agents.ts +7 -3
  33. package/ts/zod/billing.ts +168 -0
  34. package/ts/zod/budgets.ts +2 -3
  35. package/ts/zod/connections.ts +2 -3
  36. package/ts/zod/conversations.ts +7 -11
  37. package/ts/zod/deployments.ts +36 -0
  38. package/ts/zod/files.ts +2 -9
  39. package/ts/zod/index.ts +3 -0
  40. package/ts/zod/mcp.ts +8 -11
  41. package/ts/zod/observability.ts +74 -24
  42. package/ts/zod/projects.ts +4 -4
  43. package/ts/zod/runs.ts +18 -4
  44. package/ts/zod/schedules.ts +2 -7
  45. package/ts/zod/skills.ts +85 -0
  46. package/ts/zod/smith-revisions.ts +2 -3
  47. package/ts/zod/smiths.ts +6 -0
  48. package/ts/zod/tenant.ts +33 -5
  49. package/ts/zod/vector-stores.ts +9 -19
package/ts/client.ts CHANGED
@@ -30,6 +30,8 @@ import type {
30
30
  ICAgentVersion,
31
31
  ICApproval,
32
32
  ICAuthorizeRequest,
33
+ ICAutoreload,
34
+ ICBalance,
33
35
  ICBudget,
34
36
  ICBudgetStatus,
35
37
  ICCatalogEntry,
@@ -41,13 +43,18 @@ import type {
41
43
  ICDeploymentCreated,
42
44
  ICDiscordApp,
43
45
  ICEmailConfig,
46
+ ICEmbeddingList,
44
47
  ICEvent,
45
48
  ICFile,
46
49
  ICFileList,
50
+ ICInboundEvent,
51
+ ICLedgerEntry,
47
52
  ICMcpServer,
48
53
  ICMintedToken,
49
54
  ICModelCatalog,
50
55
  ICModelKey,
56
+ ICOrgUsage,
57
+ ICOrgUsageSeries,
51
58
  ICProject,
52
59
  ICProvider,
53
60
  ICRecallHit,
@@ -57,6 +64,7 @@ import type {
57
64
  ICSlackApp,
58
65
  ICSmith,
59
66
  ICSmithRevision,
67
+ ICSpanIn,
60
68
  ICTelegramBot,
61
69
  ICToken,
62
70
  ICTrace,
@@ -83,6 +91,20 @@ import type {
83
91
  RolloutIn,
84
92
  UiResourceIn,
85
93
  } from "./zod/agents.js";
94
+ import type {
95
+ AutoreloadIn,
96
+ CheckoutIn,
97
+ CheckoutOut,
98
+ ConfirmIn,
99
+ ConfirmOut,
100
+ PortalOut,
101
+ RedeemIn,
102
+ RedeemOut,
103
+ ReloadIn,
104
+ ReloadOut,
105
+ SetupIn,
106
+ SetupOut,
107
+ } from "./zod/billing.js";
86
108
  import type { BudgetIn, BudgetPatch } from "./zod/budgets.js";
87
109
  import type {
88
110
  AuthorizeIn,
@@ -95,10 +117,11 @@ import type { CustomerCreate, CustomerPatch } from "./zod/customers.js";
95
117
  import type { DeploymentIn, DeploymentPatch } from "./zod/deployments.js";
96
118
  import type { DiscordAppIn } from "./zod/discord.js";
97
119
  import type { EmailConfigIn } from "./zod/email.js";
98
- import type { McpServerIn, McpServerWriteOut } from "./zod/mcp.js";
120
+ import type { McpServerIn } from "./zod/mcp.js";
99
121
  import type { RecallBody, WorkingMemorySet } from "./zod/memories.js";
100
122
  import type { ProjectIn, ProjectTokenIn, ProjectTokenOut } from "./zod/projects.js";
101
123
  import type { RunIn, Submit } from "./zod/runs.js";
124
+ import type { Skill, SkillUpdateIn, SkillVersion } from "./zod/skills.js";
102
125
  import type {
103
126
  VectorStoreFileBatchIn,
104
127
  VectorStoreFileIn,
@@ -143,6 +166,16 @@ export interface ICPage<T> {
143
166
  has_more: boolean;
144
167
  }
145
168
 
169
+ /** An OpenAI-dialect list page (`object:"list"` — files, vector stores,
170
+ * conversations). Page forward by passing `last_id` back as `after`. */
171
+ export interface ICOaiList<T> {
172
+ object: "list";
173
+ data: T[];
174
+ first_id: string | null;
175
+ last_id: string | null;
176
+ has_more: boolean;
177
+ }
178
+
146
179
  /** A non-2xx `/v1` response: HTTP status + the error envelope's `code`.
147
180
  * `message` carries the full context (method, path, status); `detail` is the
148
181
  * envelope's bare `error.message`, suitable for user-facing copy. */
@@ -216,6 +249,66 @@ function qs(query: Query | undefined): string {
216
249
  return s ? `?${s}` : "";
217
250
  }
218
251
 
252
+ /** One file of a bundle, as the caller holds it. The path is relative to — and
253
+ * includes — the skill's root directory, e.g. `invoice-review/SKILL.md`. */
254
+ export interface SkillFileInput {
255
+ path: string;
256
+ content: string | Blob | Uint8Array;
257
+ }
258
+
259
+ /** A bundle to upload: its files, or the whole thing zipped. */
260
+ export type SkillBundle = SkillFileInput[] | Blob;
261
+
262
+ /** Build the multipart body `/v1/skills` accepts.
263
+ *
264
+ * The path rides the part's *filename*, slashes and all — that is how the
265
+ * bundle's directory structure survives a multipart body. `FormData` in Node,
266
+ * Bun and browsers all pass it through verbatim. */
267
+ function bundleForm(bundle: SkillBundle): FormData {
268
+ const form = new FormData();
269
+ if (bundle instanceof Blob) {
270
+ form.append("file", bundle, "bundle.zip");
271
+ return form;
272
+ }
273
+ for (const file of bundle) {
274
+ // A `Uint8Array`'s buffer type is generic (and may be a `SharedArrayBuffer`),
275
+ // which `Blob`'s constructor does not accept — copy into a fresh one, whose
276
+ // buffer is always a plain `ArrayBuffer`.
277
+ const part =
278
+ typeof file.content === "string" || file.content instanceof Blob
279
+ ? file.content
280
+ : new Uint8Array(file.content);
281
+ const blob =
282
+ part instanceof Blob
283
+ ? part
284
+ : new Blob([part], { type: mediaTypeFor(file.path) });
285
+ form.append("files[]", blob, file.path);
286
+ }
287
+ return form;
288
+ }
289
+
290
+ /** A `Blob` built from a string has no type of its own; the server falls back to
291
+ * `application/octet-stream` when a part carries none, which would make every
292
+ * text file non-indexable. Name the common ones from the extension. */
293
+ function mediaTypeFor(path: string): string {
294
+ const ext = path.slice(path.lastIndexOf(".") + 1).toLowerCase();
295
+ const known: Record<string, string> = {
296
+ md: "text/markdown",
297
+ markdown: "text/markdown",
298
+ txt: "text/plain",
299
+ json: "application/json",
300
+ yaml: "text/yaml",
301
+ yml: "text/yaml",
302
+ csv: "text/csv",
303
+ py: "text/x-python",
304
+ sh: "text/x-shellscript",
305
+ js: "text/javascript",
306
+ ts: "text/typescript",
307
+ html: "text/html",
308
+ };
309
+ return known[ext] ?? "application/octet-stream";
310
+ }
311
+
219
312
  export class IngramCloud {
220
313
  private readonly token: IngramCloudOptions["token"];
221
314
  private readonly base: string;
@@ -374,10 +467,10 @@ export class IngramCloud {
374
467
  },
375
468
 
376
469
  revisions: {
377
- list: (pid: string, opts?: RequestOptions) =>
378
- this.data<ICSmithRevision>(
379
- "GET",
470
+ list: (pid: string, query?: PageOpts, opts?: RequestOptions) =>
471
+ this.page<ICSmithRevision>(
380
472
  `/smiths/${enc(pid)}/revisions`,
473
+ query,
381
474
  opts,
382
475
  ),
383
476
  restore: (
@@ -397,8 +490,12 @@ export class IngramCloud {
397
490
  },
398
491
 
399
492
  connections: {
400
- list: (pid: string, opts?: RequestOptions) =>
401
- this.data<ICConnection>("GET", `/smiths/${enc(pid)}/connections`, opts),
493
+ list: (
494
+ pid: string,
495
+ query?: PageOpts & { provider?: string },
496
+ opts?: RequestOptions,
497
+ ) =>
498
+ this.page<ICConnection>(`/smiths/${enc(pid)}/connections`, query, opts),
402
499
  get: (pid: string, cid: string, opts?: RequestOptions) =>
403
500
  this.json<ICConnection>(
404
501
  "GET",
@@ -478,8 +575,8 @@ export class IngramCloud {
478
575
  },
479
576
 
480
577
  schedules: {
481
- list: (pid: string, opts?: RequestOptions) =>
482
- this.data<ICSchedule>("GET", `/smiths/${enc(pid)}/schedules`, opts),
578
+ list: (pid: string, query?: PageOpts, opts?: RequestOptions) =>
579
+ this.page<ICSchedule>(`/smiths/${enc(pid)}/schedules`, query, opts),
483
580
  create: (
484
581
  pid: string,
485
582
  body: z.input<typeof ScheduleIn>,
@@ -605,6 +702,8 @@ export class IngramCloud {
605
702
  },
606
703
  opts?: RequestOptions,
607
704
  ) => this.page<ICRun>("/runs", query, opts),
705
+ trace: (rid: string, opts?: RequestOptions) =>
706
+ this.json<ICTraceDetail>("GET", `/runs/${enc(rid)}/trace`, opts),
608
707
  };
609
708
 
610
709
  // ── Agents ──────────────────────────────────────────────────────────────
@@ -625,8 +724,8 @@ export class IngramCloud {
625
724
  this.empty("DELETE", `/agents/${enc(aid)}`, opts),
626
725
 
627
726
  versions: {
628
- list: (aid: string, opts?: RequestOptions) =>
629
- this.data<ICAgentVersion>("GET", `/agents/${enc(aid)}/versions`, opts),
727
+ list: (aid: string, query?: PageOpts, opts?: RequestOptions) =>
728
+ this.page<ICAgentVersion>(`/agents/${enc(aid)}/versions`, query, opts),
630
729
  /** Snapshot the draft as the next immutable version. */
631
730
  publish: (
632
731
  aid: string,
@@ -664,7 +763,11 @@ export class IngramCloud {
664
763
  list: (aid: string, opts?: RequestOptions) =>
665
764
  this.data<ICUiResource>("GET", `/agents/${enc(aid)}/ui`, opts),
666
765
  get: (aid: string, name: string, opts?: RequestOptions) =>
667
- this.json<ICUiResource>("GET", `/agents/${enc(aid)}/ui/${enc(name)}`, opts),
766
+ this.json<ICUiResource>(
767
+ "GET",
768
+ `/agents/${enc(aid)}/ui/${enc(name)}`,
769
+ opts,
770
+ ),
668
771
  /** Upload/replace a template — `html` is the bundle, `meta` its
669
772
  * `{ name, csp?, permissions?, tool? }` sidecar. Replaces by name. */
670
773
  put: (
@@ -676,7 +779,9 @@ export class IngramCloud {
676
779
  const form = new FormData();
677
780
  form.append(
678
781
  "file",
679
- html instanceof Blob ? html : new Blob([html], { type: "text/html" }),
782
+ html instanceof Blob
783
+ ? html
784
+ : new Blob([html], { type: "text/html" }),
680
785
  `${meta.name}.html`,
681
786
  );
682
787
  form.append("metadata", JSON.stringify(meta));
@@ -694,19 +799,22 @@ export class IngramCloud {
694
799
  headers: { accept: "text/html", ...opts?.headers },
695
800
  }).then((r) => r.text()),
696
801
  delete: (aid: string, name: string, opts?: RequestOptions) =>
697
- this.json<{ name: string; deleted: boolean }>(
698
- "DELETE",
699
- `/agents/${enc(aid)}/ui/${enc(name)}`,
700
- opts,
701
- ),
802
+ this.empty("DELETE", `/agents/${enc(aid)}/ui/${enc(name)}`, opts),
702
803
  },
703
804
  };
704
805
 
705
806
  // ── Conversations (smith-scoped: pass `{ smith }` with a tenant token) ──
706
807
 
707
808
  readonly conversations = {
708
- list: (query?: PageOpts, opts?: RequestOptions) =>
709
- this.page<ICConversation>("/conversations", query, opts),
809
+ /** OpenAI `list` envelope; page forward with `after: page.last_id`. */
810
+ list: (
811
+ query?: { limit?: number; order?: "asc" | "desc"; after?: string },
812
+ opts?: RequestOptions,
813
+ ) =>
814
+ this.json<ICOaiList<ICConversation>>("GET", "/conversations", {
815
+ ...opts,
816
+ query,
817
+ }),
710
818
  create: (
711
819
  body: z.input<typeof ConversationCreate> = {},
712
820
  opts?: RequestOptions,
@@ -753,6 +861,18 @@ export class IngramCloud {
753
861
  ) => this.page<ICEvent>("/events", query, opts),
754
862
  };
755
863
 
864
+ /** What arrived, before anything interpreted it — including arrivals that
865
+ * matched no smith (`smith_id: ""`). The `iev_` ids `deployment.inbound`
866
+ * carries resolve here. */
867
+ readonly inboundEvents = {
868
+ list: (
869
+ query?: PageOpts & { source?: string; smith_id?: string; since?: string },
870
+ opts?: RequestOptions,
871
+ ) => this.page<ICInboundEvent>("/inbound_events", query, opts),
872
+ get: (ievId: string, opts?: RequestOptions) =>
873
+ this.json<ICInboundEvent>("GET", `/inbound_events/${enc(ievId)}`, opts),
874
+ };
875
+
756
876
  // ── Customers / budgets ─────────────────────────────────────────────────
757
877
 
758
878
  readonly customers = {
@@ -773,7 +893,8 @@ export class IngramCloud {
773
893
  };
774
894
 
775
895
  readonly budgets = {
776
- list: (opts?: RequestOptions) => this.data<ICBudget>("GET", "/budgets", opts),
896
+ list: (query?: PageOpts, opts?: RequestOptions) =>
897
+ this.page<ICBudget>("/budgets", query, opts),
777
898
  create: (body: z.input<typeof BudgetIn>, opts?: RequestOptions) =>
778
899
  this.json<ICBudget>("POST", "/budgets", { ...opts, body }),
779
900
  get: (bid: string, opts?: RequestOptions) =>
@@ -822,6 +943,18 @@ export class IngramCloud {
822
943
  this.json<ICCatalogEntry>("GET", `/catalog/${enc(slug)}`, opts),
823
944
  };
824
945
 
946
+ // ── Embeddings ──────────────────────────────────────────────────────────
947
+
948
+ /** Embed one string or a batch on the OpenAI-compatible wire. Pure tenant
949
+ * compute — no smith runs. Omit `model` for the project default. Reach for
950
+ * the `openai` SDK instead if you already hold one; this is the same route. */
951
+ readonly embeddings = {
952
+ create: (
953
+ body: { input: string | string[]; model?: string },
954
+ opts?: RequestOptions,
955
+ ) => this.json<ICEmbeddingList>("POST", "/embeddings", { ...opts, body }),
956
+ };
957
+
825
958
  // ── Observability ───────────────────────────────────────────────────────
826
959
 
827
960
  readonly traces = {
@@ -836,6 +969,15 @@ export class IngramCloud {
836
969
  ) => this.page<ICTrace>("/traces", query, opts),
837
970
  get: (traceId: string, opts?: RequestOptions) =>
838
971
  this.json<ICTraceDetail>("GET", `/traces/${enc(traceId)}`, opts),
972
+ /** Push spans from your own runtime or an OTel exporter. The tenant comes
973
+ * from the token; a smith-scoped token may only attribute to its own smith.
974
+ * Unknown `kind`s land as `runtime_event` rather than erroring. Returns the
975
+ * number written. */
976
+ ingest: (spans: ICSpanIn[], opts?: RequestOptions) =>
977
+ this.json<{ accepted: number }>("POST", "/traces:ingest", {
978
+ ...opts,
979
+ body: { spans },
980
+ }),
839
981
  };
840
982
 
841
983
  readonly usage = {
@@ -885,7 +1027,12 @@ export class IngramCloud {
885
1027
  },
886
1028
  /** Uploads only (OpenAI `list` envelope); inline files stay unlisted. */
887
1029
  list: (
888
- query?: { purpose?: string; after?: string; limit?: number; order?: "asc" | "desc" },
1030
+ query?: {
1031
+ purpose?: string;
1032
+ after?: string;
1033
+ limit?: number;
1034
+ order?: "asc" | "desc";
1035
+ },
889
1036
  opts?: RequestOptions,
890
1037
  ) => this.json<ICFileList>("GET", "/files", { ...opts, query }),
891
1038
  get: (id: string, opts?: RequestOptions) =>
@@ -894,7 +1041,11 @@ export class IngramCloud {
894
1041
  content: (id: string, opts?: RequestOptions) =>
895
1042
  this.request("GET", `/files/${enc(id)}/content`, opts),
896
1043
  delete: (id: string, opts?: RequestOptions) =>
897
- this.json<{ id: string; deleted: true }>("DELETE", `/files/${enc(id)}`, opts),
1044
+ this.json<{ id: string; deleted: true }>(
1045
+ "DELETE",
1046
+ `/files/${enc(id)}`,
1047
+ opts,
1048
+ ),
898
1049
  };
899
1050
 
900
1051
  // ── Vector stores (the OpenAI Vector Stores API) ─────────────────────────
@@ -903,14 +1054,18 @@ export class IngramCloud {
903
1054
  create: (body: z.input<typeof VectorStoreIn>, opts?: RequestOptions) =>
904
1055
  this.json<ICVectorStore>("POST", "/vector_stores", { ...opts, body }),
905
1056
  list: (
906
- query?: { limit?: number; order?: "asc" | "desc"; after?: string; before?: string },
1057
+ query?: {
1058
+ limit?: number;
1059
+ order?: "asc" | "desc";
1060
+ after?: string;
1061
+ before?: string;
1062
+ },
907
1063
  opts?: RequestOptions,
908
1064
  ) =>
909
- this.json<{ data: ICVectorStore[]; first_id: string | null; last_id: string | null; has_more: boolean }>(
910
- "GET",
911
- "/vector_stores",
912
- { ...opts, query },
913
- ),
1065
+ this.json<ICOaiList<ICVectorStore>>("GET", "/vector_stores", {
1066
+ ...opts,
1067
+ query,
1068
+ }),
914
1069
  get: (vsId: string, opts?: RequestOptions) =>
915
1070
  this.json<ICVectorStore>("GET", `/vector_stores/${enc(vsId)}`, opts),
916
1071
  /** Modify (OpenAI uses `POST`, not `PATCH`). */
@@ -918,7 +1073,11 @@ export class IngramCloud {
918
1073
  vsId: string,
919
1074
  body: z.input<typeof VectorStorePatch>,
920
1075
  opts?: RequestOptions,
921
- ) => this.json<ICVectorStore>("POST", `/vector_stores/${enc(vsId)}`, { ...opts, body }),
1076
+ ) =>
1077
+ this.json<ICVectorStore>("POST", `/vector_stores/${enc(vsId)}`, {
1078
+ ...opts,
1079
+ body,
1080
+ }),
922
1081
  delete: (vsId: string, opts?: RequestOptions) =>
923
1082
  this.json<{ id: string; deleted: true }>(
924
1083
  "DELETE",
@@ -930,10 +1089,14 @@ export class IngramCloud {
930
1089
  body: z.input<typeof VectorStoreSearchIn>,
931
1090
  opts?: RequestOptions,
932
1091
  ) =>
933
- this.json<ICVectorStoreSearchPage>("POST", `/vector_stores/${enc(vsId)}/search`, {
934
- ...opts,
935
- body,
936
- }),
1092
+ this.json<ICVectorStoreSearchPage>(
1093
+ "POST",
1094
+ `/vector_stores/${enc(vsId)}/search`,
1095
+ {
1096
+ ...opts,
1097
+ body,
1098
+ },
1099
+ ),
937
1100
 
938
1101
  files: {
939
1102
  create: (
@@ -941,10 +1104,14 @@ export class IngramCloud {
941
1104
  body: z.input<typeof VectorStoreFileIn>,
942
1105
  opts?: RequestOptions,
943
1106
  ) =>
944
- this.json<ICVectorStoreFile>("POST", `/vector_stores/${enc(vsId)}/files`, {
945
- ...opts,
946
- body,
947
- }),
1107
+ this.json<ICVectorStoreFile>(
1108
+ "POST",
1109
+ `/vector_stores/${enc(vsId)}/files`,
1110
+ {
1111
+ ...opts,
1112
+ body,
1113
+ },
1114
+ ),
948
1115
  list: (
949
1116
  vsId: string,
950
1117
  query?: {
@@ -956,7 +1123,7 @@ export class IngramCloud {
956
1123
  },
957
1124
  opts?: RequestOptions,
958
1125
  ) =>
959
- this.json<{ data: ICVectorStoreFile[]; first_id: string | null; last_id: string | null; has_more: boolean }>(
1126
+ this.json<ICOaiList<ICVectorStoreFile>>(
960
1127
  "GET",
961
1128
  `/vector_stores/${enc(vsId)}/files`,
962
1129
  { ...opts, query },
@@ -1012,7 +1179,12 @@ export class IngramCloud {
1012
1179
  files: (
1013
1180
  vsId: string,
1014
1181
  batchId: string,
1015
- query?: { limit?: number; order?: "asc" | "desc"; after?: string; filter?: string },
1182
+ query?: {
1183
+ limit?: number;
1184
+ order?: "asc" | "desc";
1185
+ after?: string;
1186
+ filter?: string;
1187
+ },
1016
1188
  opts?: RequestOptions,
1017
1189
  ) =>
1018
1190
  this.json<{ data: ICVectorStoreFile[]; has_more: boolean }>(
@@ -1023,6 +1195,81 @@ export class IngramCloud {
1023
1195
  },
1024
1196
  };
1025
1197
 
1198
+ // ── Agent Skills — a folder anchored by SKILL.md, versioned, attached to
1199
+ // agents. Upload takes either the bundle's files as path/content pairs, or
1200
+ // the whole bundle as a zip Blob — the same two shapes /v1/skills accepts.
1201
+ // Both are runtime-agnostic: nothing here touches a filesystem. ───────────
1202
+
1203
+ readonly skills = {
1204
+ list: (opts?: RequestOptions) =>
1205
+ this.json<{ object: "list"; data: z.infer<typeof Skill>[] }>(
1206
+ "GET",
1207
+ "/skills",
1208
+ opts,
1209
+ ),
1210
+ get: (id: string, opts?: RequestOptions) =>
1211
+ this.json<z.infer<typeof Skill>>("GET", `/skills/${enc(id)}`, opts),
1212
+ create: (bundle: SkillBundle, opts?: RequestOptions) =>
1213
+ this.json<z.infer<typeof Skill>>("POST", "/skills", {
1214
+ ...opts,
1215
+ rawBody: bundleForm(bundle),
1216
+ }),
1217
+ /** Move `default_version` to an existing version. */
1218
+ update: (
1219
+ id: string,
1220
+ body: z.input<typeof SkillUpdateIn>,
1221
+ opts?: RequestOptions,
1222
+ ) =>
1223
+ this.json<z.infer<typeof Skill>>("POST", `/skills/${enc(id)}`, {
1224
+ ...opts,
1225
+ body,
1226
+ }),
1227
+ delete: (id: string, opts?: RequestOptions) =>
1228
+ this.request("DELETE", `/skills/${enc(id)}`, opts).then(() => undefined),
1229
+ versions: {
1230
+ list: (id: string, opts?: RequestOptions) =>
1231
+ this.json<{ object: "list"; data: z.infer<typeof SkillVersion>[] }>(
1232
+ "GET",
1233
+ `/skills/${enc(id)}/versions`,
1234
+ opts,
1235
+ ),
1236
+ get: (id: string, version: number, opts?: RequestOptions) =>
1237
+ this.json<z.infer<typeof SkillVersion>>(
1238
+ "GET",
1239
+ `/skills/${enc(id)}/versions/${version}`,
1240
+ opts,
1241
+ ),
1242
+ create: (id: string, bundle: SkillBundle, opts?: RequestOptions) =>
1243
+ this.json<z.infer<typeof SkillVersion>>(
1244
+ "POST",
1245
+ `/skills/${enc(id)}/versions`,
1246
+ { ...opts, rawBody: bundleForm(bundle) },
1247
+ ),
1248
+ delete: (id: string, version: number, opts?: RequestOptions) =>
1249
+ this.request(
1250
+ "DELETE",
1251
+ `/skills/${enc(id)}/versions/${version}`,
1252
+ opts,
1253
+ ).then(() => undefined),
1254
+ /** One file's bytes, or — with no `path` — the whole version as a zip.
1255
+ * The raw `Response` (matching `files.content`), so a caller streams it
1256
+ * through rather than buffering the whole zip into memory. */
1257
+ content: (
1258
+ id: string,
1259
+ version: number,
1260
+ path?: string,
1261
+ opts?: RequestOptions,
1262
+ ) =>
1263
+ this.request(
1264
+ "GET",
1265
+ `/skills/${enc(id)}/versions/${version}/content${
1266
+ path ? `?path=${encodeURIComponent(path)}` : ""
1267
+ }`,
1268
+ opts,
1269
+ ),
1270
+ },
1271
+ };
1272
+
1026
1273
  // ── Tenant config ───────────────────────────────────────────────────────
1027
1274
 
1028
1275
  readonly tenant = {
@@ -1150,8 +1397,8 @@ export class IngramCloud {
1150
1397
  },
1151
1398
 
1152
1399
  mcp: {
1153
- list: (opts?: RequestOptions) =>
1154
- this.data<ICMcpServer>("GET", "/tenant/mcp", opts),
1400
+ list: (query?: PageOpts, opts?: RequestOptions) =>
1401
+ this.page<ICMcpServer>("/tenant/mcp", query, opts),
1155
1402
  get: (name: string, opts?: RequestOptions) =>
1156
1403
  this.json<ICMcpServer>("GET", `/tenant/mcp/${enc(name)}`, opts),
1157
1404
  /** Register or replace a server (full replace; probes `tools/list`). */
@@ -1160,13 +1407,12 @@ export class IngramCloud {
1160
1407
  body: z.input<typeof McpServerIn>,
1161
1408
  opts?: RequestOptions,
1162
1409
  ) =>
1163
- this.json<z.infer<typeof McpServerWriteOut>>(
1164
- "PUT",
1165
- `/tenant/mcp/${enc(name)}`,
1166
- { ...opts, body },
1167
- ),
1410
+ this.json<ICMcpServer>("PUT", `/tenant/mcp/${enc(name)}`, {
1411
+ ...opts,
1412
+ body,
1413
+ }),
1168
1414
  refresh: (name: string, opts?: RequestOptions) =>
1169
- this.json<z.infer<typeof McpServerWriteOut>>(
1415
+ this.json<ICMcpServer>(
1170
1416
  "POST",
1171
1417
  `/tenant/mcp/${enc(name)}/refresh`,
1172
1418
  opts,
@@ -1256,13 +1502,101 @@ export class IngramCloud {
1256
1502
  },
1257
1503
  };
1258
1504
 
1259
- // ── Organization (org token: projects + tokens) ─────────────────────────
1260
- // Note: the `/v1/organization/billing/*` surface is not yet wrapped here.
1505
+ // ── Organization (org token: projects, tokens, billing) ─────────────────
1261
1506
 
1262
1507
  readonly organization = {
1508
+ /** Platform credits — the org wallet that funds every project's runs.
1509
+ * Amounts are integer minor units of the wallet's `currency`. */
1510
+ billing: {
1511
+ balance: (opts?: RequestOptions) =>
1512
+ this.json<ICBalance>("GET", "/organization/billing/balance", opts),
1513
+ /** Money in (top-ups, grants, codes) and out (usage debits), newest first. */
1514
+ ledger: (
1515
+ query?: PageOpts & { direction?: "credit" | "debit" },
1516
+ opts?: RequestOptions,
1517
+ ) => this.page<ICLedgerEntry>("/organization/billing/ledger", query, opts),
1518
+ /** Per-project draw for a calendar month (`period`, `YYYY-MM`). */
1519
+ usage: (query?: { period?: string }, opts?: RequestOptions) =>
1520
+ this.json<ICOrgUsage>("GET", "/organization/billing/usage", {
1521
+ ...opts,
1522
+ query,
1523
+ }),
1524
+ /** Daily per-project draw over a rolling window of `days`. */
1525
+ usageSeries: (query?: { days?: number }, opts?: RequestOptions) =>
1526
+ this.json<ICOrgUsageSeries>(
1527
+ "GET",
1528
+ "/organization/billing/usage/series",
1529
+ {
1530
+ ...opts,
1531
+ query,
1532
+ },
1533
+ ),
1534
+ /** Open a Stripe Checkout Session to top up; send the user to its `url`. */
1535
+ checkout: (body: z.input<typeof CheckoutIn>, opts?: RequestOptions) =>
1536
+ this.json<z.infer<typeof CheckoutOut>>(
1537
+ "POST",
1538
+ "/organization/billing/checkout",
1539
+ { ...opts, body },
1540
+ ),
1541
+ /** Add a card with no charge, unlocking the one-time welcome credit. */
1542
+ setup: (body: z.input<typeof SetupIn>, opts?: RequestOptions) =>
1543
+ this.json<z.infer<typeof SetupOut>>(
1544
+ "POST",
1545
+ "/organization/billing/setup",
1546
+ {
1547
+ ...opts,
1548
+ body,
1549
+ },
1550
+ ),
1551
+ redeem: (body: z.input<typeof RedeemIn>, opts?: RequestOptions) =>
1552
+ this.json<z.infer<typeof RedeemOut>>(
1553
+ "POST",
1554
+ "/organization/billing/redeem",
1555
+ { ...opts, body },
1556
+ ),
1557
+ /** Credit a returning Checkout Session. Safe to call twice — the ledger
1558
+ * keys on the session id, so it can't double-credit. */
1559
+ confirm: (body: z.input<typeof ConfirmIn>, opts?: RequestOptions) =>
1560
+ this.json<z.infer<typeof ConfirmOut>>(
1561
+ "POST",
1562
+ "/organization/billing/confirm",
1563
+ { ...opts, body },
1564
+ ),
1565
+ autoreload: {
1566
+ get: (opts?: RequestOptions) =>
1567
+ this.json<ICAutoreload>(
1568
+ "GET",
1569
+ "/organization/billing/autoreload",
1570
+ opts,
1571
+ ),
1572
+ put: (body: z.input<typeof AutoreloadIn>, opts?: RequestOptions) =>
1573
+ this.json<ICAutoreload>("PUT", "/organization/billing/autoreload", {
1574
+ ...opts,
1575
+ body,
1576
+ }),
1577
+ },
1578
+ /** Charge the saved card now. `amount_cents` defaults to the auto-reload amount. */
1579
+ reload: (body?: z.input<typeof ReloadIn>, opts?: RequestOptions) =>
1580
+ this.json<z.infer<typeof ReloadOut>>(
1581
+ "POST",
1582
+ "/organization/billing/reload",
1583
+ { ...opts, body: body ?? {} },
1584
+ ),
1585
+ /** A Stripe billing-portal URL for managing cards and invoices. */
1586
+ portal: (query: { return_url: string }, opts?: RequestOptions) =>
1587
+ this.json<z.infer<typeof PortalOut>>(
1588
+ "GET",
1589
+ "/organization/billing/portal",
1590
+ {
1591
+ ...opts,
1592
+ query,
1593
+ },
1594
+ ),
1595
+ },
1596
+
1263
1597
  projects: {
1264
- list: (opts?: RequestOptions) =>
1265
- this.data<ICProject>("GET", "/organization/projects", opts),
1598
+ list: (query?: PageOpts & { name?: string }, opts?: RequestOptions) =>
1599
+ this.page<ICProject>("/organization/projects", query, opts),
1266
1600
  create: (body: z.input<typeof ProjectIn>, opts?: RequestOptions) =>
1267
1601
  this.json<ICProject>("POST", "/organization/projects", {
1268
1602
  ...opts,
package/ts/index.ts CHANGED
@@ -13,8 +13,12 @@
13
13
  * `./events` is the hand-authored `{v:1}` webhook/feed envelope and the SSE
14
14
  * run-stream frames, which OpenAPI can't express.
15
15
  *
16
+ * `./scopes` is the closed permission vocabulary a smith token may carry — you
17
+ * must name the scopes you want when minting one.
18
+ *
16
19
  * See `../README.md`.
17
20
  */
18
21
  export { schemas } from "./schemas.js";
19
22
  export * from "./events.js";
23
+ export * from "./scopes.js";
20
24
  export type * from "./responses.js";