@ingram-cloud/sdk 1.4.0 → 1.6.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/README.md +34 -35
- package/dist/client.js +240 -23
- package/dist/index.js +4 -0
- package/dist/scopes.js +52 -0
- package/dist/zod/_actor.js +33 -0
- package/dist/zod/_page.js +18 -4
- package/dist/zod/agents.js +7 -3
- package/dist/zod/approvals.js +9 -0
- package/dist/zod/billing.js +136 -0
- package/dist/zod/budgets.js +2 -3
- package/dist/zod/connections.js +2 -3
- package/dist/zod/conversations.js +4 -11
- package/dist/zod/deployments.js +32 -0
- package/dist/zod/files.js +2 -9
- package/dist/zod/index.js +3 -0
- package/dist/zod/mcp.js +8 -10
- package/dist/zod/observability.js +38 -19
- package/dist/zod/projects.js +4 -4
- package/dist/zod/runs.js +19 -4
- package/dist/zod/schedules.js +2 -7
- package/dist/zod/skills.js +73 -0
- package/dist/zod/smith-revisions.js +2 -3
- package/dist/zod/smiths.js +6 -0
- package/dist/zod/tenant.js +24 -4
- package/dist/zod/vector-stores.js +6 -19
- package/package.json +25 -18
- package/ts/client.ts +456 -60
- package/ts/index.ts +4 -0
- package/ts/responses.ts +40 -2
- package/ts/scopes.ts +57 -0
- package/ts/zod/_actor.ts +36 -0
- package/ts/zod/_page.ts +19 -4
- package/ts/zod/agents.ts +7 -3
- package/ts/zod/approvals.ts +9 -0
- package/ts/zod/billing.ts +168 -0
- package/ts/zod/budgets.ts +2 -3
- package/ts/zod/connections.ts +2 -3
- package/ts/zod/conversations.ts +7 -11
- package/ts/zod/deployments.ts +36 -0
- package/ts/zod/files.ts +2 -9
- package/ts/zod/index.ts +3 -0
- package/ts/zod/mcp.ts +8 -11
- package/ts/zod/observability.ts +74 -24
- package/ts/zod/projects.ts +4 -4
- package/ts/zod/runs.ts +21 -4
- package/ts/zod/schedules.ts +2 -7
- package/ts/zod/skills.ts +85 -0
- package/ts/zod/smith-revisions.ts +2 -3
- package/ts/zod/smiths.ts +6 -0
- package/ts/zod/tenant.ts +33 -5
- 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
|
|
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. */
|
|
@@ -205,6 +238,61 @@ export interface PageOpts {
|
|
|
205
238
|
|
|
206
239
|
const enc = encodeURIComponent;
|
|
207
240
|
|
|
241
|
+
/** Attempts per request, including the first. Small on purpose: the server
|
|
242
|
+
* tells us when to come back, so this is a bound on pathological cases, not
|
|
243
|
+
* a backoff strategy. */
|
|
244
|
+
const MAX_ATTEMPTS = 4;
|
|
245
|
+
|
|
246
|
+
/** Longest we will sit out one `Retry-After`. A server (or an intermediary that
|
|
247
|
+
* never heard of this API) can name an hour; a client library must not silently
|
|
248
|
+
* block a caller for one. Past this we stop retrying and surface the refusal, so
|
|
249
|
+
* the caller decides. */
|
|
250
|
+
const MAX_WAIT_MS = 60_000;
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* How long this response says to wait, or null if it does not say — which is
|
|
254
|
+
* itself the answer: a 402 carries no `Retry-After` because the wallet will not
|
|
255
|
+
* refill because we asked twice.
|
|
256
|
+
*
|
|
257
|
+
* RFC 9110 allows both forms, and intermediaries do send the date one, so parse
|
|
258
|
+
* both. Anything unparseable is "no usable instruction", never a zero-delay
|
|
259
|
+
* hammer at an upstream that is already struggling.
|
|
260
|
+
*/
|
|
261
|
+
function retryAfterMs(res: Response, now: number): number | null {
|
|
262
|
+
const raw = res.headers.get("retry-after")?.trim();
|
|
263
|
+
if (!raw) return null;
|
|
264
|
+
const seconds = Number(raw);
|
|
265
|
+
const ms = Number.isFinite(seconds) ? seconds * 1000 : Date.parse(raw) - now;
|
|
266
|
+
if (!Number.isFinite(ms)) return null;
|
|
267
|
+
return Math.max(0, ms);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** Retry only what retrying can fix, and only when told how long to wait. */
|
|
271
|
+
function retryDelay(res: Response, now: number): number | null {
|
|
272
|
+
if (res.status !== 429 && res.status !== 503) return null;
|
|
273
|
+
const ms = retryAfterMs(res, now);
|
|
274
|
+
return ms === null || ms > MAX_WAIT_MS ? null : ms;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/** The `Retry-After` wait, abortable: a caller cancelling mid-wait should not
|
|
278
|
+
* sit out the rest of a Retry-After that can be tens of seconds — reject as
|
|
279
|
+
* soon as `signal` fires, the same way an aborted `transport()` call would. */
|
|
280
|
+
function sleep(ms: number, signal: AbortSignal | undefined): Promise<void> {
|
|
281
|
+
if (!signal) return new Promise((resolve) => setTimeout(resolve, ms));
|
|
282
|
+
if (signal.aborted) return Promise.reject(signal.reason ?? new Error("aborted"));
|
|
283
|
+
return new Promise((resolve, reject) => {
|
|
284
|
+
const timer = setTimeout(() => {
|
|
285
|
+
signal.removeEventListener("abort", onAbort);
|
|
286
|
+
resolve();
|
|
287
|
+
}, ms);
|
|
288
|
+
const onAbort = () => {
|
|
289
|
+
clearTimeout(timer);
|
|
290
|
+
reject(signal.reason ?? new Error("aborted"));
|
|
291
|
+
};
|
|
292
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
|
|
208
296
|
function qs(query: Query | undefined): string {
|
|
209
297
|
if (!query) return "";
|
|
210
298
|
const p = new URLSearchParams();
|
|
@@ -216,6 +304,66 @@ function qs(query: Query | undefined): string {
|
|
|
216
304
|
return s ? `?${s}` : "";
|
|
217
305
|
}
|
|
218
306
|
|
|
307
|
+
/** One file of a bundle, as the caller holds it. The path is relative to — and
|
|
308
|
+
* includes — the skill's root directory, e.g. `invoice-review/SKILL.md`. */
|
|
309
|
+
export interface SkillFileInput {
|
|
310
|
+
path: string;
|
|
311
|
+
content: string | Blob | Uint8Array;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** A bundle to upload: its files, or the whole thing zipped. */
|
|
315
|
+
export type SkillBundle = SkillFileInput[] | Blob;
|
|
316
|
+
|
|
317
|
+
/** Build the multipart body `/v1/skills` accepts.
|
|
318
|
+
*
|
|
319
|
+
* The path rides the part's *filename*, slashes and all — that is how the
|
|
320
|
+
* bundle's directory structure survives a multipart body. `FormData` in Node,
|
|
321
|
+
* Bun and browsers all pass it through verbatim. */
|
|
322
|
+
function bundleForm(bundle: SkillBundle): FormData {
|
|
323
|
+
const form = new FormData();
|
|
324
|
+
if (bundle instanceof Blob) {
|
|
325
|
+
form.append("file", bundle, "bundle.zip");
|
|
326
|
+
return form;
|
|
327
|
+
}
|
|
328
|
+
for (const file of bundle) {
|
|
329
|
+
// A `Uint8Array`'s buffer type is generic (and may be a `SharedArrayBuffer`),
|
|
330
|
+
// which `Blob`'s constructor does not accept — copy into a fresh one, whose
|
|
331
|
+
// buffer is always a plain `ArrayBuffer`.
|
|
332
|
+
const part =
|
|
333
|
+
typeof file.content === "string" || file.content instanceof Blob
|
|
334
|
+
? file.content
|
|
335
|
+
: new Uint8Array(file.content);
|
|
336
|
+
const blob =
|
|
337
|
+
part instanceof Blob
|
|
338
|
+
? part
|
|
339
|
+
: new Blob([part], { type: mediaTypeFor(file.path) });
|
|
340
|
+
form.append("files[]", blob, file.path);
|
|
341
|
+
}
|
|
342
|
+
return form;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/** A `Blob` built from a string has no type of its own; the server falls back to
|
|
346
|
+
* `application/octet-stream` when a part carries none, which would make every
|
|
347
|
+
* text file non-indexable. Name the common ones from the extension. */
|
|
348
|
+
function mediaTypeFor(path: string): string {
|
|
349
|
+
const ext = path.slice(path.lastIndexOf(".") + 1).toLowerCase();
|
|
350
|
+
const known: Record<string, string> = {
|
|
351
|
+
md: "text/markdown",
|
|
352
|
+
markdown: "text/markdown",
|
|
353
|
+
txt: "text/plain",
|
|
354
|
+
json: "application/json",
|
|
355
|
+
yaml: "text/yaml",
|
|
356
|
+
yml: "text/yaml",
|
|
357
|
+
csv: "text/csv",
|
|
358
|
+
py: "text/x-python",
|
|
359
|
+
sh: "text/x-shellscript",
|
|
360
|
+
js: "text/javascript",
|
|
361
|
+
ts: "text/typescript",
|
|
362
|
+
html: "text/html",
|
|
363
|
+
};
|
|
364
|
+
return known[ext] ?? "application/octet-stream";
|
|
365
|
+
}
|
|
366
|
+
|
|
219
367
|
export class IngramCloud {
|
|
220
368
|
private readonly token: IngramCloudOptions["token"];
|
|
221
369
|
private readonly base: string;
|
|
@@ -254,15 +402,22 @@ export class IngramCloud {
|
|
|
254
402
|
...(opts.smith ? { "ic-smith-id": opts.smith } : {}),
|
|
255
403
|
...opts.headers,
|
|
256
404
|
};
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
405
|
+
let res!: Response;
|
|
406
|
+
for (let attempt = 1; ; attempt++) {
|
|
407
|
+
res = await this.transport(`${this.base}/v1${path}${qs(opts.query)}`, {
|
|
408
|
+
...this.requestInit,
|
|
409
|
+
method,
|
|
410
|
+
headers,
|
|
411
|
+
body:
|
|
412
|
+
opts.rawBody ??
|
|
413
|
+
(opts.body !== undefined ? JSON.stringify(opts.body) : undefined),
|
|
414
|
+
signal: opts.signal,
|
|
415
|
+
});
|
|
416
|
+
if (res.ok || attempt >= MAX_ATTEMPTS) break;
|
|
417
|
+
const wait = retryDelay(res, Date.now());
|
|
418
|
+
if (wait === null) break;
|
|
419
|
+
await sleep(wait, opts.signal);
|
|
420
|
+
}
|
|
266
421
|
if (!res.ok) {
|
|
267
422
|
const body = await res.text().catch(() => "");
|
|
268
423
|
let code = `http_${res.status}`;
|
|
@@ -374,10 +529,10 @@ export class IngramCloud {
|
|
|
374
529
|
},
|
|
375
530
|
|
|
376
531
|
revisions: {
|
|
377
|
-
list: (pid: string, opts?: RequestOptions) =>
|
|
378
|
-
this.
|
|
379
|
-
"GET",
|
|
532
|
+
list: (pid: string, query?: PageOpts, opts?: RequestOptions) =>
|
|
533
|
+
this.page<ICSmithRevision>(
|
|
380
534
|
`/smiths/${enc(pid)}/revisions`,
|
|
535
|
+
query,
|
|
381
536
|
opts,
|
|
382
537
|
),
|
|
383
538
|
restore: (
|
|
@@ -397,8 +552,12 @@ export class IngramCloud {
|
|
|
397
552
|
},
|
|
398
553
|
|
|
399
554
|
connections: {
|
|
400
|
-
list: (
|
|
401
|
-
|
|
555
|
+
list: (
|
|
556
|
+
pid: string,
|
|
557
|
+
query?: PageOpts & { provider?: string },
|
|
558
|
+
opts?: RequestOptions,
|
|
559
|
+
) =>
|
|
560
|
+
this.page<ICConnection>(`/smiths/${enc(pid)}/connections`, query, opts),
|
|
402
561
|
get: (pid: string, cid: string, opts?: RequestOptions) =>
|
|
403
562
|
this.json<ICConnection>(
|
|
404
563
|
"GET",
|
|
@@ -478,8 +637,8 @@ export class IngramCloud {
|
|
|
478
637
|
},
|
|
479
638
|
|
|
480
639
|
schedules: {
|
|
481
|
-
list: (pid: string, opts?: RequestOptions) =>
|
|
482
|
-
this.
|
|
640
|
+
list: (pid: string, query?: PageOpts, opts?: RequestOptions) =>
|
|
641
|
+
this.page<ICSchedule>(`/smiths/${enc(pid)}/schedules`, query, opts),
|
|
483
642
|
create: (
|
|
484
643
|
pid: string,
|
|
485
644
|
body: z.input<typeof ScheduleIn>,
|
|
@@ -605,6 +764,8 @@ export class IngramCloud {
|
|
|
605
764
|
},
|
|
606
765
|
opts?: RequestOptions,
|
|
607
766
|
) => this.page<ICRun>("/runs", query, opts),
|
|
767
|
+
trace: (rid: string, opts?: RequestOptions) =>
|
|
768
|
+
this.json<ICTraceDetail>("GET", `/runs/${enc(rid)}/trace`, opts),
|
|
608
769
|
};
|
|
609
770
|
|
|
610
771
|
// ── Agents ──────────────────────────────────────────────────────────────
|
|
@@ -625,8 +786,8 @@ export class IngramCloud {
|
|
|
625
786
|
this.empty("DELETE", `/agents/${enc(aid)}`, opts),
|
|
626
787
|
|
|
627
788
|
versions: {
|
|
628
|
-
list: (aid: string, opts?: RequestOptions) =>
|
|
629
|
-
this.
|
|
789
|
+
list: (aid: string, query?: PageOpts, opts?: RequestOptions) =>
|
|
790
|
+
this.page<ICAgentVersion>(`/agents/${enc(aid)}/versions`, query, opts),
|
|
630
791
|
/** Snapshot the draft as the next immutable version. */
|
|
631
792
|
publish: (
|
|
632
793
|
aid: string,
|
|
@@ -664,7 +825,11 @@ export class IngramCloud {
|
|
|
664
825
|
list: (aid: string, opts?: RequestOptions) =>
|
|
665
826
|
this.data<ICUiResource>("GET", `/agents/${enc(aid)}/ui`, opts),
|
|
666
827
|
get: (aid: string, name: string, opts?: RequestOptions) =>
|
|
667
|
-
this.json<ICUiResource>(
|
|
828
|
+
this.json<ICUiResource>(
|
|
829
|
+
"GET",
|
|
830
|
+
`/agents/${enc(aid)}/ui/${enc(name)}`,
|
|
831
|
+
opts,
|
|
832
|
+
),
|
|
668
833
|
/** Upload/replace a template — `html` is the bundle, `meta` its
|
|
669
834
|
* `{ name, csp?, permissions?, tool? }` sidecar. Replaces by name. */
|
|
670
835
|
put: (
|
|
@@ -676,7 +841,9 @@ export class IngramCloud {
|
|
|
676
841
|
const form = new FormData();
|
|
677
842
|
form.append(
|
|
678
843
|
"file",
|
|
679
|
-
html instanceof Blob
|
|
844
|
+
html instanceof Blob
|
|
845
|
+
? html
|
|
846
|
+
: new Blob([html], { type: "text/html" }),
|
|
680
847
|
`${meta.name}.html`,
|
|
681
848
|
);
|
|
682
849
|
form.append("metadata", JSON.stringify(meta));
|
|
@@ -694,19 +861,22 @@ export class IngramCloud {
|
|
|
694
861
|
headers: { accept: "text/html", ...opts?.headers },
|
|
695
862
|
}).then((r) => r.text()),
|
|
696
863
|
delete: (aid: string, name: string, opts?: RequestOptions) =>
|
|
697
|
-
this.
|
|
698
|
-
"DELETE",
|
|
699
|
-
`/agents/${enc(aid)}/ui/${enc(name)}`,
|
|
700
|
-
opts,
|
|
701
|
-
),
|
|
864
|
+
this.empty("DELETE", `/agents/${enc(aid)}/ui/${enc(name)}`, opts),
|
|
702
865
|
},
|
|
703
866
|
};
|
|
704
867
|
|
|
705
868
|
// ── Conversations (smith-scoped: pass `{ smith }` with a tenant token) ──
|
|
706
869
|
|
|
707
870
|
readonly conversations = {
|
|
708
|
-
list
|
|
709
|
-
|
|
871
|
+
/** OpenAI `list` envelope; page forward with `after: page.last_id`. */
|
|
872
|
+
list: (
|
|
873
|
+
query?: { limit?: number; order?: "asc" | "desc"; after?: string },
|
|
874
|
+
opts?: RequestOptions,
|
|
875
|
+
) =>
|
|
876
|
+
this.json<ICOaiList<ICConversation>>("GET", "/conversations", {
|
|
877
|
+
...opts,
|
|
878
|
+
query,
|
|
879
|
+
}),
|
|
710
880
|
create: (
|
|
711
881
|
body: z.input<typeof ConversationCreate> = {},
|
|
712
882
|
opts?: RequestOptions,
|
|
@@ -753,6 +923,18 @@ export class IngramCloud {
|
|
|
753
923
|
) => this.page<ICEvent>("/events", query, opts),
|
|
754
924
|
};
|
|
755
925
|
|
|
926
|
+
/** What arrived, before anything interpreted it — including arrivals that
|
|
927
|
+
* matched no smith (`smith_id: ""`). The `iev_` ids `deployment.inbound`
|
|
928
|
+
* carries resolve here. */
|
|
929
|
+
readonly inboundEvents = {
|
|
930
|
+
list: (
|
|
931
|
+
query?: PageOpts & { source?: string; smith_id?: string; since?: string },
|
|
932
|
+
opts?: RequestOptions,
|
|
933
|
+
) => this.page<ICInboundEvent>("/inbound_events", query, opts),
|
|
934
|
+
get: (ievId: string, opts?: RequestOptions) =>
|
|
935
|
+
this.json<ICInboundEvent>("GET", `/inbound_events/${enc(ievId)}`, opts),
|
|
936
|
+
};
|
|
937
|
+
|
|
756
938
|
// ── Customers / budgets ─────────────────────────────────────────────────
|
|
757
939
|
|
|
758
940
|
readonly customers = {
|
|
@@ -773,7 +955,8 @@ export class IngramCloud {
|
|
|
773
955
|
};
|
|
774
956
|
|
|
775
957
|
readonly budgets = {
|
|
776
|
-
list: (opts?: RequestOptions) =>
|
|
958
|
+
list: (query?: PageOpts, opts?: RequestOptions) =>
|
|
959
|
+
this.page<ICBudget>("/budgets", query, opts),
|
|
777
960
|
create: (body: z.input<typeof BudgetIn>, opts?: RequestOptions) =>
|
|
778
961
|
this.json<ICBudget>("POST", "/budgets", { ...opts, body }),
|
|
779
962
|
get: (bid: string, opts?: RequestOptions) =>
|
|
@@ -822,6 +1005,18 @@ export class IngramCloud {
|
|
|
822
1005
|
this.json<ICCatalogEntry>("GET", `/catalog/${enc(slug)}`, opts),
|
|
823
1006
|
};
|
|
824
1007
|
|
|
1008
|
+
// ── Embeddings ──────────────────────────────────────────────────────────
|
|
1009
|
+
|
|
1010
|
+
/** Embed one string or a batch on the OpenAI-compatible wire. Pure tenant
|
|
1011
|
+
* compute — no smith runs. Omit `model` for the project default. Reach for
|
|
1012
|
+
* the `openai` SDK instead if you already hold one; this is the same route. */
|
|
1013
|
+
readonly embeddings = {
|
|
1014
|
+
create: (
|
|
1015
|
+
body: { input: string | string[]; model?: string },
|
|
1016
|
+
opts?: RequestOptions,
|
|
1017
|
+
) => this.json<ICEmbeddingList>("POST", "/embeddings", { ...opts, body }),
|
|
1018
|
+
};
|
|
1019
|
+
|
|
825
1020
|
// ── Observability ───────────────────────────────────────────────────────
|
|
826
1021
|
|
|
827
1022
|
readonly traces = {
|
|
@@ -836,6 +1031,15 @@ export class IngramCloud {
|
|
|
836
1031
|
) => this.page<ICTrace>("/traces", query, opts),
|
|
837
1032
|
get: (traceId: string, opts?: RequestOptions) =>
|
|
838
1033
|
this.json<ICTraceDetail>("GET", `/traces/${enc(traceId)}`, opts),
|
|
1034
|
+
/** Push spans from your own runtime or an OTel exporter. The tenant comes
|
|
1035
|
+
* from the token; a smith-scoped token may only attribute to its own smith.
|
|
1036
|
+
* Unknown `kind`s land as `runtime_event` rather than erroring. Returns the
|
|
1037
|
+
* number written. */
|
|
1038
|
+
ingest: (spans: ICSpanIn[], opts?: RequestOptions) =>
|
|
1039
|
+
this.json<{ accepted: number }>("POST", "/traces:ingest", {
|
|
1040
|
+
...opts,
|
|
1041
|
+
body: { spans },
|
|
1042
|
+
}),
|
|
839
1043
|
};
|
|
840
1044
|
|
|
841
1045
|
readonly usage = {
|
|
@@ -885,7 +1089,12 @@ export class IngramCloud {
|
|
|
885
1089
|
},
|
|
886
1090
|
/** Uploads only (OpenAI `list` envelope); inline files stay unlisted. */
|
|
887
1091
|
list: (
|
|
888
|
-
query?: {
|
|
1092
|
+
query?: {
|
|
1093
|
+
purpose?: string;
|
|
1094
|
+
after?: string;
|
|
1095
|
+
limit?: number;
|
|
1096
|
+
order?: "asc" | "desc";
|
|
1097
|
+
},
|
|
889
1098
|
opts?: RequestOptions,
|
|
890
1099
|
) => this.json<ICFileList>("GET", "/files", { ...opts, query }),
|
|
891
1100
|
get: (id: string, opts?: RequestOptions) =>
|
|
@@ -894,7 +1103,11 @@ export class IngramCloud {
|
|
|
894
1103
|
content: (id: string, opts?: RequestOptions) =>
|
|
895
1104
|
this.request("GET", `/files/${enc(id)}/content`, opts),
|
|
896
1105
|
delete: (id: string, opts?: RequestOptions) =>
|
|
897
|
-
this.json<{ id: string; deleted: true }>(
|
|
1106
|
+
this.json<{ id: string; deleted: true }>(
|
|
1107
|
+
"DELETE",
|
|
1108
|
+
`/files/${enc(id)}`,
|
|
1109
|
+
opts,
|
|
1110
|
+
),
|
|
898
1111
|
};
|
|
899
1112
|
|
|
900
1113
|
// ── Vector stores (the OpenAI Vector Stores API) ─────────────────────────
|
|
@@ -903,14 +1116,18 @@ export class IngramCloud {
|
|
|
903
1116
|
create: (body: z.input<typeof VectorStoreIn>, opts?: RequestOptions) =>
|
|
904
1117
|
this.json<ICVectorStore>("POST", "/vector_stores", { ...opts, body }),
|
|
905
1118
|
list: (
|
|
906
|
-
query?: {
|
|
1119
|
+
query?: {
|
|
1120
|
+
limit?: number;
|
|
1121
|
+
order?: "asc" | "desc";
|
|
1122
|
+
after?: string;
|
|
1123
|
+
before?: string;
|
|
1124
|
+
},
|
|
907
1125
|
opts?: RequestOptions,
|
|
908
1126
|
) =>
|
|
909
|
-
this.json<
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
),
|
|
1127
|
+
this.json<ICOaiList<ICVectorStore>>("GET", "/vector_stores", {
|
|
1128
|
+
...opts,
|
|
1129
|
+
query,
|
|
1130
|
+
}),
|
|
914
1131
|
get: (vsId: string, opts?: RequestOptions) =>
|
|
915
1132
|
this.json<ICVectorStore>("GET", `/vector_stores/${enc(vsId)}`, opts),
|
|
916
1133
|
/** Modify (OpenAI uses `POST`, not `PATCH`). */
|
|
@@ -918,7 +1135,11 @@ export class IngramCloud {
|
|
|
918
1135
|
vsId: string,
|
|
919
1136
|
body: z.input<typeof VectorStorePatch>,
|
|
920
1137
|
opts?: RequestOptions,
|
|
921
|
-
) =>
|
|
1138
|
+
) =>
|
|
1139
|
+
this.json<ICVectorStore>("POST", `/vector_stores/${enc(vsId)}`, {
|
|
1140
|
+
...opts,
|
|
1141
|
+
body,
|
|
1142
|
+
}),
|
|
922
1143
|
delete: (vsId: string, opts?: RequestOptions) =>
|
|
923
1144
|
this.json<{ id: string; deleted: true }>(
|
|
924
1145
|
"DELETE",
|
|
@@ -930,10 +1151,14 @@ export class IngramCloud {
|
|
|
930
1151
|
body: z.input<typeof VectorStoreSearchIn>,
|
|
931
1152
|
opts?: RequestOptions,
|
|
932
1153
|
) =>
|
|
933
|
-
this.json<ICVectorStoreSearchPage>(
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
1154
|
+
this.json<ICVectorStoreSearchPage>(
|
|
1155
|
+
"POST",
|
|
1156
|
+
`/vector_stores/${enc(vsId)}/search`,
|
|
1157
|
+
{
|
|
1158
|
+
...opts,
|
|
1159
|
+
body,
|
|
1160
|
+
},
|
|
1161
|
+
),
|
|
937
1162
|
|
|
938
1163
|
files: {
|
|
939
1164
|
create: (
|
|
@@ -941,10 +1166,14 @@ export class IngramCloud {
|
|
|
941
1166
|
body: z.input<typeof VectorStoreFileIn>,
|
|
942
1167
|
opts?: RequestOptions,
|
|
943
1168
|
) =>
|
|
944
|
-
this.json<ICVectorStoreFile>(
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
1169
|
+
this.json<ICVectorStoreFile>(
|
|
1170
|
+
"POST",
|
|
1171
|
+
`/vector_stores/${enc(vsId)}/files`,
|
|
1172
|
+
{
|
|
1173
|
+
...opts,
|
|
1174
|
+
body,
|
|
1175
|
+
},
|
|
1176
|
+
),
|
|
948
1177
|
list: (
|
|
949
1178
|
vsId: string,
|
|
950
1179
|
query?: {
|
|
@@ -956,7 +1185,7 @@ export class IngramCloud {
|
|
|
956
1185
|
},
|
|
957
1186
|
opts?: RequestOptions,
|
|
958
1187
|
) =>
|
|
959
|
-
this.json<
|
|
1188
|
+
this.json<ICOaiList<ICVectorStoreFile>>(
|
|
960
1189
|
"GET",
|
|
961
1190
|
`/vector_stores/${enc(vsId)}/files`,
|
|
962
1191
|
{ ...opts, query },
|
|
@@ -1012,7 +1241,12 @@ export class IngramCloud {
|
|
|
1012
1241
|
files: (
|
|
1013
1242
|
vsId: string,
|
|
1014
1243
|
batchId: string,
|
|
1015
|
-
query?: {
|
|
1244
|
+
query?: {
|
|
1245
|
+
limit?: number;
|
|
1246
|
+
order?: "asc" | "desc";
|
|
1247
|
+
after?: string;
|
|
1248
|
+
filter?: string;
|
|
1249
|
+
},
|
|
1016
1250
|
opts?: RequestOptions,
|
|
1017
1251
|
) =>
|
|
1018
1252
|
this.json<{ data: ICVectorStoreFile[]; has_more: boolean }>(
|
|
@@ -1023,6 +1257,81 @@ export class IngramCloud {
|
|
|
1023
1257
|
},
|
|
1024
1258
|
};
|
|
1025
1259
|
|
|
1260
|
+
// ── Agent Skills — a folder anchored by SKILL.md, versioned, attached to
|
|
1261
|
+
// agents. Upload takes either the bundle's files as path/content pairs, or
|
|
1262
|
+
// the whole bundle as a zip Blob — the same two shapes /v1/skills accepts.
|
|
1263
|
+
// Both are runtime-agnostic: nothing here touches a filesystem. ───────────
|
|
1264
|
+
|
|
1265
|
+
readonly skills = {
|
|
1266
|
+
list: (opts?: RequestOptions) =>
|
|
1267
|
+
this.json<{ object: "list"; data: z.infer<typeof Skill>[] }>(
|
|
1268
|
+
"GET",
|
|
1269
|
+
"/skills",
|
|
1270
|
+
opts,
|
|
1271
|
+
),
|
|
1272
|
+
get: (id: string, opts?: RequestOptions) =>
|
|
1273
|
+
this.json<z.infer<typeof Skill>>("GET", `/skills/${enc(id)}`, opts),
|
|
1274
|
+
create: (bundle: SkillBundle, opts?: RequestOptions) =>
|
|
1275
|
+
this.json<z.infer<typeof Skill>>("POST", "/skills", {
|
|
1276
|
+
...opts,
|
|
1277
|
+
rawBody: bundleForm(bundle),
|
|
1278
|
+
}),
|
|
1279
|
+
/** Move `default_version` to an existing version. */
|
|
1280
|
+
update: (
|
|
1281
|
+
id: string,
|
|
1282
|
+
body: z.input<typeof SkillUpdateIn>,
|
|
1283
|
+
opts?: RequestOptions,
|
|
1284
|
+
) =>
|
|
1285
|
+
this.json<z.infer<typeof Skill>>("POST", `/skills/${enc(id)}`, {
|
|
1286
|
+
...opts,
|
|
1287
|
+
body,
|
|
1288
|
+
}),
|
|
1289
|
+
delete: (id: string, opts?: RequestOptions) =>
|
|
1290
|
+
this.request("DELETE", `/skills/${enc(id)}`, opts).then(() => undefined),
|
|
1291
|
+
versions: {
|
|
1292
|
+
list: (id: string, opts?: RequestOptions) =>
|
|
1293
|
+
this.json<{ object: "list"; data: z.infer<typeof SkillVersion>[] }>(
|
|
1294
|
+
"GET",
|
|
1295
|
+
`/skills/${enc(id)}/versions`,
|
|
1296
|
+
opts,
|
|
1297
|
+
),
|
|
1298
|
+
get: (id: string, version: number, opts?: RequestOptions) =>
|
|
1299
|
+
this.json<z.infer<typeof SkillVersion>>(
|
|
1300
|
+
"GET",
|
|
1301
|
+
`/skills/${enc(id)}/versions/${version}`,
|
|
1302
|
+
opts,
|
|
1303
|
+
),
|
|
1304
|
+
create: (id: string, bundle: SkillBundle, opts?: RequestOptions) =>
|
|
1305
|
+
this.json<z.infer<typeof SkillVersion>>(
|
|
1306
|
+
"POST",
|
|
1307
|
+
`/skills/${enc(id)}/versions`,
|
|
1308
|
+
{ ...opts, rawBody: bundleForm(bundle) },
|
|
1309
|
+
),
|
|
1310
|
+
delete: (id: string, version: number, opts?: RequestOptions) =>
|
|
1311
|
+
this.request(
|
|
1312
|
+
"DELETE",
|
|
1313
|
+
`/skills/${enc(id)}/versions/${version}`,
|
|
1314
|
+
opts,
|
|
1315
|
+
).then(() => undefined),
|
|
1316
|
+
/** One file's bytes, or — with no `path` — the whole version as a zip.
|
|
1317
|
+
* The raw `Response` (matching `files.content`), so a caller streams it
|
|
1318
|
+
* through rather than buffering the whole zip into memory. */
|
|
1319
|
+
content: (
|
|
1320
|
+
id: string,
|
|
1321
|
+
version: number,
|
|
1322
|
+
path?: string,
|
|
1323
|
+
opts?: RequestOptions,
|
|
1324
|
+
) =>
|
|
1325
|
+
this.request(
|
|
1326
|
+
"GET",
|
|
1327
|
+
`/skills/${enc(id)}/versions/${version}/content${
|
|
1328
|
+
path ? `?path=${encodeURIComponent(path)}` : ""
|
|
1329
|
+
}`,
|
|
1330
|
+
opts,
|
|
1331
|
+
),
|
|
1332
|
+
},
|
|
1333
|
+
};
|
|
1334
|
+
|
|
1026
1335
|
// ── Tenant config ───────────────────────────────────────────────────────
|
|
1027
1336
|
|
|
1028
1337
|
readonly tenant = {
|
|
@@ -1150,8 +1459,8 @@ export class IngramCloud {
|
|
|
1150
1459
|
},
|
|
1151
1460
|
|
|
1152
1461
|
mcp: {
|
|
1153
|
-
list: (opts?: RequestOptions) =>
|
|
1154
|
-
this.
|
|
1462
|
+
list: (query?: PageOpts, opts?: RequestOptions) =>
|
|
1463
|
+
this.page<ICMcpServer>("/tenant/mcp", query, opts),
|
|
1155
1464
|
get: (name: string, opts?: RequestOptions) =>
|
|
1156
1465
|
this.json<ICMcpServer>("GET", `/tenant/mcp/${enc(name)}`, opts),
|
|
1157
1466
|
/** Register or replace a server (full replace; probes `tools/list`). */
|
|
@@ -1160,13 +1469,12 @@ export class IngramCloud {
|
|
|
1160
1469
|
body: z.input<typeof McpServerIn>,
|
|
1161
1470
|
opts?: RequestOptions,
|
|
1162
1471
|
) =>
|
|
1163
|
-
this.json<
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
),
|
|
1472
|
+
this.json<ICMcpServer>("PUT", `/tenant/mcp/${enc(name)}`, {
|
|
1473
|
+
...opts,
|
|
1474
|
+
body,
|
|
1475
|
+
}),
|
|
1168
1476
|
refresh: (name: string, opts?: RequestOptions) =>
|
|
1169
|
-
this.json<
|
|
1477
|
+
this.json<ICMcpServer>(
|
|
1170
1478
|
"POST",
|
|
1171
1479
|
`/tenant/mcp/${enc(name)}/refresh`,
|
|
1172
1480
|
opts,
|
|
@@ -1256,13 +1564,101 @@ export class IngramCloud {
|
|
|
1256
1564
|
},
|
|
1257
1565
|
};
|
|
1258
1566
|
|
|
1259
|
-
// ── Organization (org token: projects
|
|
1260
|
-
// Note: the `/v1/organization/billing/*` surface is not yet wrapped here.
|
|
1567
|
+
// ── Organization (org token: projects, tokens, billing) ─────────────────
|
|
1261
1568
|
|
|
1262
1569
|
readonly organization = {
|
|
1570
|
+
/** Platform credits — the org wallet that funds every project's runs.
|
|
1571
|
+
* Amounts are integer minor units of the wallet's `currency`. */
|
|
1572
|
+
billing: {
|
|
1573
|
+
balance: (opts?: RequestOptions) =>
|
|
1574
|
+
this.json<ICBalance>("GET", "/organization/billing/balance", opts),
|
|
1575
|
+
/** Money in (top-ups, grants, codes) and out (usage debits), newest first. */
|
|
1576
|
+
ledger: (
|
|
1577
|
+
query?: PageOpts & { direction?: "credit" | "debit" },
|
|
1578
|
+
opts?: RequestOptions,
|
|
1579
|
+
) => this.page<ICLedgerEntry>("/organization/billing/ledger", query, opts),
|
|
1580
|
+
/** Per-project draw for a calendar month (`period`, `YYYY-MM`). */
|
|
1581
|
+
usage: (query?: { period?: string }, opts?: RequestOptions) =>
|
|
1582
|
+
this.json<ICOrgUsage>("GET", "/organization/billing/usage", {
|
|
1583
|
+
...opts,
|
|
1584
|
+
query,
|
|
1585
|
+
}),
|
|
1586
|
+
/** Daily per-project draw over a rolling window of `days`. */
|
|
1587
|
+
usageSeries: (query?: { days?: number }, opts?: RequestOptions) =>
|
|
1588
|
+
this.json<ICOrgUsageSeries>(
|
|
1589
|
+
"GET",
|
|
1590
|
+
"/organization/billing/usage/series",
|
|
1591
|
+
{
|
|
1592
|
+
...opts,
|
|
1593
|
+
query,
|
|
1594
|
+
},
|
|
1595
|
+
),
|
|
1596
|
+
/** Open a Stripe Checkout Session to top up; send the user to its `url`. */
|
|
1597
|
+
checkout: (body: z.input<typeof CheckoutIn>, opts?: RequestOptions) =>
|
|
1598
|
+
this.json<z.infer<typeof CheckoutOut>>(
|
|
1599
|
+
"POST",
|
|
1600
|
+
"/organization/billing/checkout",
|
|
1601
|
+
{ ...opts, body },
|
|
1602
|
+
),
|
|
1603
|
+
/** Add a card with no charge, unlocking the one-time welcome credit. */
|
|
1604
|
+
setup: (body: z.input<typeof SetupIn>, opts?: RequestOptions) =>
|
|
1605
|
+
this.json<z.infer<typeof SetupOut>>(
|
|
1606
|
+
"POST",
|
|
1607
|
+
"/organization/billing/setup",
|
|
1608
|
+
{
|
|
1609
|
+
...opts,
|
|
1610
|
+
body,
|
|
1611
|
+
},
|
|
1612
|
+
),
|
|
1613
|
+
redeem: (body: z.input<typeof RedeemIn>, opts?: RequestOptions) =>
|
|
1614
|
+
this.json<z.infer<typeof RedeemOut>>(
|
|
1615
|
+
"POST",
|
|
1616
|
+
"/organization/billing/redeem",
|
|
1617
|
+
{ ...opts, body },
|
|
1618
|
+
),
|
|
1619
|
+
/** Credit a returning Checkout Session. Safe to call twice — the ledger
|
|
1620
|
+
* keys on the session id, so it can't double-credit. */
|
|
1621
|
+
confirm: (body: z.input<typeof ConfirmIn>, opts?: RequestOptions) =>
|
|
1622
|
+
this.json<z.infer<typeof ConfirmOut>>(
|
|
1623
|
+
"POST",
|
|
1624
|
+
"/organization/billing/confirm",
|
|
1625
|
+
{ ...opts, body },
|
|
1626
|
+
),
|
|
1627
|
+
autoreload: {
|
|
1628
|
+
get: (opts?: RequestOptions) =>
|
|
1629
|
+
this.json<ICAutoreload>(
|
|
1630
|
+
"GET",
|
|
1631
|
+
"/organization/billing/autoreload",
|
|
1632
|
+
opts,
|
|
1633
|
+
),
|
|
1634
|
+
put: (body: z.input<typeof AutoreloadIn>, opts?: RequestOptions) =>
|
|
1635
|
+
this.json<ICAutoreload>("PUT", "/organization/billing/autoreload", {
|
|
1636
|
+
...opts,
|
|
1637
|
+
body,
|
|
1638
|
+
}),
|
|
1639
|
+
},
|
|
1640
|
+
/** Charge the saved card now. `amount_cents` defaults to the auto-reload amount. */
|
|
1641
|
+
reload: (body?: z.input<typeof ReloadIn>, opts?: RequestOptions) =>
|
|
1642
|
+
this.json<z.infer<typeof ReloadOut>>(
|
|
1643
|
+
"POST",
|
|
1644
|
+
"/organization/billing/reload",
|
|
1645
|
+
{ ...opts, body: body ?? {} },
|
|
1646
|
+
),
|
|
1647
|
+
/** A Stripe billing-portal URL for managing cards and invoices. */
|
|
1648
|
+
portal: (query: { return_url: string }, opts?: RequestOptions) =>
|
|
1649
|
+
this.json<z.infer<typeof PortalOut>>(
|
|
1650
|
+
"GET",
|
|
1651
|
+
"/organization/billing/portal",
|
|
1652
|
+
{
|
|
1653
|
+
...opts,
|
|
1654
|
+
query,
|
|
1655
|
+
},
|
|
1656
|
+
),
|
|
1657
|
+
},
|
|
1658
|
+
|
|
1263
1659
|
projects: {
|
|
1264
|
-
list: (opts?: RequestOptions) =>
|
|
1265
|
-
this.
|
|
1660
|
+
list: (query?: PageOpts & { name?: string }, opts?: RequestOptions) =>
|
|
1661
|
+
this.page<ICProject>("/organization/projects", query, opts),
|
|
1266
1662
|
create: (body: z.input<typeof ProjectIn>, opts?: RequestOptions) =>
|
|
1267
1663
|
this.json<ICProject>("POST", "/organization/projects", {
|
|
1268
1664
|
...opts,
|