@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.
- package/dist/client.js +168 -15
- 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/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 +16 -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 +6 -8
- package/ts/client.ts +385 -51
- package/ts/index.ts +4 -0
- package/ts/responses.ts +40 -2
- package/ts/scopes.ts +57 -0
- package/ts/zod/.impeccable/hook.cache.json +1 -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/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 +18 -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/dist/client.js
CHANGED
|
@@ -31,6 +31,52 @@ function qs(query) {
|
|
|
31
31
|
const s = p.toString();
|
|
32
32
|
return s ? `?${s}` : "";
|
|
33
33
|
}
|
|
34
|
+
/** Build the multipart body `/v1/skills` accepts.
|
|
35
|
+
*
|
|
36
|
+
* The path rides the part's *filename*, slashes and all — that is how the
|
|
37
|
+
* bundle's directory structure survives a multipart body. `FormData` in Node,
|
|
38
|
+
* Bun and browsers all pass it through verbatim. */
|
|
39
|
+
function bundleForm(bundle) {
|
|
40
|
+
const form = new FormData();
|
|
41
|
+
if (bundle instanceof Blob) {
|
|
42
|
+
form.append("file", bundle, "bundle.zip");
|
|
43
|
+
return form;
|
|
44
|
+
}
|
|
45
|
+
for (const file of bundle) {
|
|
46
|
+
// A `Uint8Array`'s buffer type is generic (and may be a `SharedArrayBuffer`),
|
|
47
|
+
// which `Blob`'s constructor does not accept — copy into a fresh one, whose
|
|
48
|
+
// buffer is always a plain `ArrayBuffer`.
|
|
49
|
+
const part = typeof file.content === "string" || file.content instanceof Blob
|
|
50
|
+
? file.content
|
|
51
|
+
: new Uint8Array(file.content);
|
|
52
|
+
const blob = part instanceof Blob
|
|
53
|
+
? part
|
|
54
|
+
: new Blob([part], { type: mediaTypeFor(file.path) });
|
|
55
|
+
form.append("files[]", blob, file.path);
|
|
56
|
+
}
|
|
57
|
+
return form;
|
|
58
|
+
}
|
|
59
|
+
/** A `Blob` built from a string has no type of its own; the server falls back to
|
|
60
|
+
* `application/octet-stream` when a part carries none, which would make every
|
|
61
|
+
* text file non-indexable. Name the common ones from the extension. */
|
|
62
|
+
function mediaTypeFor(path) {
|
|
63
|
+
const ext = path.slice(path.lastIndexOf(".") + 1).toLowerCase();
|
|
64
|
+
const known = {
|
|
65
|
+
md: "text/markdown",
|
|
66
|
+
markdown: "text/markdown",
|
|
67
|
+
txt: "text/plain",
|
|
68
|
+
json: "application/json",
|
|
69
|
+
yaml: "text/yaml",
|
|
70
|
+
yml: "text/yaml",
|
|
71
|
+
csv: "text/csv",
|
|
72
|
+
py: "text/x-python",
|
|
73
|
+
sh: "text/x-shellscript",
|
|
74
|
+
js: "text/javascript",
|
|
75
|
+
ts: "text/typescript",
|
|
76
|
+
html: "text/html",
|
|
77
|
+
};
|
|
78
|
+
return known[ext] ?? "application/octet-stream";
|
|
79
|
+
}
|
|
34
80
|
export class IngramCloud {
|
|
35
81
|
token;
|
|
36
82
|
base;
|
|
@@ -121,14 +167,14 @@ export class IngramCloud {
|
|
|
121
167
|
}),
|
|
122
168
|
},
|
|
123
169
|
revisions: {
|
|
124
|
-
list: (pid, opts) => this.
|
|
170
|
+
list: (pid, query, opts) => this.page(`/smiths/${enc(pid)}/revisions`, query, opts),
|
|
125
171
|
restore: (pid, version, body = {}, opts) => this.json("POST", `/smiths/${enc(pid)}/revisions/${version}/restore`, {
|
|
126
172
|
...opts,
|
|
127
173
|
body,
|
|
128
174
|
}),
|
|
129
175
|
},
|
|
130
176
|
connections: {
|
|
131
|
-
list: (pid, opts) => this.
|
|
177
|
+
list: (pid, query, opts) => this.page(`/smiths/${enc(pid)}/connections`, query, opts),
|
|
132
178
|
get: (pid, cid, opts) => this.json("GET", `/smiths/${enc(pid)}/connections/${enc(cid)}`, opts),
|
|
133
179
|
create: (pid, body, opts) => this.json("POST", `/smiths/${enc(pid)}/connections`, {
|
|
134
180
|
...opts,
|
|
@@ -151,7 +197,7 @@ export class IngramCloud {
|
|
|
151
197
|
delete: (pid, provider, opts) => this.empty("DELETE", `/smiths/${enc(pid)}/model_keys/${enc(provider)}`, opts),
|
|
152
198
|
},
|
|
153
199
|
schedules: {
|
|
154
|
-
list: (pid, opts) => this.
|
|
200
|
+
list: (pid, query, opts) => this.page(`/smiths/${enc(pid)}/schedules`, query, opts),
|
|
155
201
|
create: (pid, body, opts) => this.json("POST", `/smiths/${enc(pid)}/schedules`, {
|
|
156
202
|
...opts,
|
|
157
203
|
body,
|
|
@@ -213,6 +259,7 @@ export class IngramCloud {
|
|
|
213
259
|
// ── Runs (tenant-wide feed) ─────────────────────────────────────────────
|
|
214
260
|
runs = {
|
|
215
261
|
list: (query, opts) => this.page("/runs", query, opts),
|
|
262
|
+
trace: (rid, opts) => this.json("GET", `/runs/${enc(rid)}/trace`, opts),
|
|
216
263
|
};
|
|
217
264
|
// ── Agents ──────────────────────────────────────────────────────────────
|
|
218
265
|
agents = {
|
|
@@ -222,7 +269,7 @@ export class IngramCloud {
|
|
|
222
269
|
update: (aid, body, opts) => this.json("PATCH", `/agents/${enc(aid)}`, { ...opts, body }),
|
|
223
270
|
delete: (aid, opts) => this.empty("DELETE", `/agents/${enc(aid)}`, opts),
|
|
224
271
|
versions: {
|
|
225
|
-
list: (aid, opts) => this.
|
|
272
|
+
list: (aid, query, opts) => this.page(`/agents/${enc(aid)}/versions`, query, opts),
|
|
226
273
|
/** Snapshot the draft as the next immutable version. */
|
|
227
274
|
publish: (aid, body = {}, opts) => this.json("POST", `/agents/${enc(aid)}/versions`, {
|
|
228
275
|
...opts,
|
|
@@ -246,7 +293,9 @@ export class IngramCloud {
|
|
|
246
293
|
* `{ name, csp?, permissions?, tool? }` sidecar. Replaces by name. */
|
|
247
294
|
put: (aid, html, meta, opts) => {
|
|
248
295
|
const form = new FormData();
|
|
249
|
-
form.append("file", html instanceof Blob
|
|
296
|
+
form.append("file", html instanceof Blob
|
|
297
|
+
? html
|
|
298
|
+
: new Blob([html], { type: "text/html" }), `${meta.name}.html`);
|
|
250
299
|
form.append("metadata", JSON.stringify(meta));
|
|
251
300
|
return this.json("POST", `/agents/${enc(aid)}/ui`, {
|
|
252
301
|
...opts,
|
|
@@ -260,12 +309,16 @@ export class IngramCloud {
|
|
|
260
309
|
...opts,
|
|
261
310
|
headers: { accept: "text/html", ...opts?.headers },
|
|
262
311
|
}).then((r) => r.text()),
|
|
263
|
-
delete: (aid, name, opts) => this.
|
|
312
|
+
delete: (aid, name, opts) => this.empty("DELETE", `/agents/${enc(aid)}/ui/${enc(name)}`, opts),
|
|
264
313
|
},
|
|
265
314
|
};
|
|
266
315
|
// ── Conversations (smith-scoped: pass `{ smith }` with a tenant token) ──
|
|
267
316
|
conversations = {
|
|
268
|
-
list
|
|
317
|
+
/** OpenAI `list` envelope; page forward with `after: page.last_id`. */
|
|
318
|
+
list: (query, opts) => this.json("GET", "/conversations", {
|
|
319
|
+
...opts,
|
|
320
|
+
query,
|
|
321
|
+
}),
|
|
269
322
|
create: (body = {}, opts) => this.json("POST", "/conversations", { ...opts, body }),
|
|
270
323
|
get: (cnvId, opts) => this.json("GET", `/conversations/${enc(cnvId)}`, opts),
|
|
271
324
|
/** OpenAI-style modify — a POST, not a PATCH. */
|
|
@@ -288,6 +341,13 @@ export class IngramCloud {
|
|
|
288
341
|
events = {
|
|
289
342
|
list: (query, opts) => this.page("/events", query, opts),
|
|
290
343
|
};
|
|
344
|
+
/** What arrived, before anything interpreted it — including arrivals that
|
|
345
|
+
* matched no smith (`smith_id: ""`). The `iev_` ids `deployment.inbound`
|
|
346
|
+
* carries resolve here. */
|
|
347
|
+
inboundEvents = {
|
|
348
|
+
list: (query, opts) => this.page("/inbound_events", query, opts),
|
|
349
|
+
get: (ievId, opts) => this.json("GET", `/inbound_events/${enc(ievId)}`, opts),
|
|
350
|
+
};
|
|
291
351
|
// ── Customers / budgets ─────────────────────────────────────────────────
|
|
292
352
|
customers = {
|
|
293
353
|
list: (query, opts) => this.page("/customers", query, opts),
|
|
@@ -297,7 +357,7 @@ export class IngramCloud {
|
|
|
297
357
|
delete: (cid, opts) => this.empty("DELETE", `/customers/${enc(cid)}`, opts),
|
|
298
358
|
};
|
|
299
359
|
budgets = {
|
|
300
|
-
list: (opts) => this.
|
|
360
|
+
list: (query, opts) => this.page("/budgets", query, opts),
|
|
301
361
|
create: (body, opts) => this.json("POST", "/budgets", { ...opts, body }),
|
|
302
362
|
get: (bid, opts) => this.json("GET", `/budgets/${enc(bid)}`, opts),
|
|
303
363
|
update: (bid, body, opts) => this.json("PATCH", `/budgets/${enc(bid)}`, { ...opts, body }),
|
|
@@ -320,10 +380,25 @@ export class IngramCloud {
|
|
|
320
380
|
list: (opts) => this.data("GET", "/catalog", opts),
|
|
321
381
|
get: (slug, opts) => this.json("GET", `/catalog/${enc(slug)}`, opts),
|
|
322
382
|
};
|
|
383
|
+
// ── Embeddings ──────────────────────────────────────────────────────────
|
|
384
|
+
/** Embed one string or a batch on the OpenAI-compatible wire. Pure tenant
|
|
385
|
+
* compute — no smith runs. Omit `model` for the project default. Reach for
|
|
386
|
+
* the `openai` SDK instead if you already hold one; this is the same route. */
|
|
387
|
+
embeddings = {
|
|
388
|
+
create: (body, opts) => this.json("POST", "/embeddings", { ...opts, body }),
|
|
389
|
+
};
|
|
323
390
|
// ── Observability ───────────────────────────────────────────────────────
|
|
324
391
|
traces = {
|
|
325
392
|
list: (query, opts) => this.page("/traces", query, opts),
|
|
326
393
|
get: (traceId, opts) => this.json("GET", `/traces/${enc(traceId)}`, opts),
|
|
394
|
+
/** Push spans from your own runtime or an OTel exporter. The tenant comes
|
|
395
|
+
* from the token; a smith-scoped token may only attribute to its own smith.
|
|
396
|
+
* Unknown `kind`s land as `runtime_event` rather than erroring. Returns the
|
|
397
|
+
* number written. */
|
|
398
|
+
ingest: (spans, opts) => this.json("POST", "/traces:ingest", {
|
|
399
|
+
...opts,
|
|
400
|
+
body: { spans },
|
|
401
|
+
}),
|
|
327
402
|
};
|
|
328
403
|
usage = {
|
|
329
404
|
/** Token/cost/run totals grouped by app, smith, model, or customer. */
|
|
@@ -352,10 +427,16 @@ export class IngramCloud {
|
|
|
352
427
|
// ── Vector stores (the OpenAI Vector Stores API) ─────────────────────────
|
|
353
428
|
vectorStores = {
|
|
354
429
|
create: (body, opts) => this.json("POST", "/vector_stores", { ...opts, body }),
|
|
355
|
-
list: (query, opts) => this.json("GET", "/vector_stores", {
|
|
430
|
+
list: (query, opts) => this.json("GET", "/vector_stores", {
|
|
431
|
+
...opts,
|
|
432
|
+
query,
|
|
433
|
+
}),
|
|
356
434
|
get: (vsId, opts) => this.json("GET", `/vector_stores/${enc(vsId)}`, opts),
|
|
357
435
|
/** Modify (OpenAI uses `POST`, not `PATCH`). */
|
|
358
|
-
update: (vsId, body, opts) => this.json("POST", `/vector_stores/${enc(vsId)}`, {
|
|
436
|
+
update: (vsId, body, opts) => this.json("POST", `/vector_stores/${enc(vsId)}`, {
|
|
437
|
+
...opts,
|
|
438
|
+
body,
|
|
439
|
+
}),
|
|
359
440
|
delete: (vsId, opts) => this.json("DELETE", `/vector_stores/${enc(vsId)}`, opts),
|
|
360
441
|
search: (vsId, body, opts) => this.json("POST", `/vector_stores/${enc(vsId)}/search`, {
|
|
361
442
|
...opts,
|
|
@@ -378,6 +459,34 @@ export class IngramCloud {
|
|
|
378
459
|
files: (vsId, batchId, query, opts) => this.json("GET", `/vector_stores/${enc(vsId)}/file_batches/${enc(batchId)}/files`, { ...opts, query }),
|
|
379
460
|
},
|
|
380
461
|
};
|
|
462
|
+
// ── Agent Skills — a folder anchored by SKILL.md, versioned, attached to
|
|
463
|
+
// agents. Upload takes either the bundle's files as path/content pairs, or
|
|
464
|
+
// the whole bundle as a zip Blob — the same two shapes /v1/skills accepts.
|
|
465
|
+
// Both are runtime-agnostic: nothing here touches a filesystem. ───────────
|
|
466
|
+
skills = {
|
|
467
|
+
list: (opts) => this.json("GET", "/skills", opts),
|
|
468
|
+
get: (id, opts) => this.json("GET", `/skills/${enc(id)}`, opts),
|
|
469
|
+
create: (bundle, opts) => this.json("POST", "/skills", {
|
|
470
|
+
...opts,
|
|
471
|
+
rawBody: bundleForm(bundle),
|
|
472
|
+
}),
|
|
473
|
+
/** Move `default_version` to an existing version. */
|
|
474
|
+
update: (id, body, opts) => this.json("POST", `/skills/${enc(id)}`, {
|
|
475
|
+
...opts,
|
|
476
|
+
body,
|
|
477
|
+
}),
|
|
478
|
+
delete: (id, opts) => this.request("DELETE", `/skills/${enc(id)}`, opts).then(() => undefined),
|
|
479
|
+
versions: {
|
|
480
|
+
list: (id, opts) => this.json("GET", `/skills/${enc(id)}/versions`, opts),
|
|
481
|
+
get: (id, version, opts) => this.json("GET", `/skills/${enc(id)}/versions/${version}`, opts),
|
|
482
|
+
create: (id, bundle, opts) => this.json("POST", `/skills/${enc(id)}/versions`, { ...opts, rawBody: bundleForm(bundle) }),
|
|
483
|
+
delete: (id, version, opts) => this.request("DELETE", `/skills/${enc(id)}/versions/${version}`, opts).then(() => undefined),
|
|
484
|
+
/** One file's bytes, or — with no `path` — the whole version as a zip.
|
|
485
|
+
* The raw `Response` (matching `files.content`), so a caller streams it
|
|
486
|
+
* through rather than buffering the whole zip into memory. */
|
|
487
|
+
content: (id, version, path, opts) => this.request("GET", `/skills/${enc(id)}/versions/${version}/content${path ? `?path=${encodeURIComponent(path)}` : ""}`, opts),
|
|
488
|
+
},
|
|
489
|
+
};
|
|
381
490
|
// ── Tenant config ───────────────────────────────────────────────────────
|
|
382
491
|
tenant = {
|
|
383
492
|
usage: (opts) => this.json("GET", "/tenant/usage", opts),
|
|
@@ -426,10 +535,13 @@ export class IngramCloud {
|
|
|
426
535
|
delete: (provider, opts) => this.empty("DELETE", `/tenant/model_keys/${enc(provider)}`, opts),
|
|
427
536
|
},
|
|
428
537
|
mcp: {
|
|
429
|
-
list: (opts) => this.
|
|
538
|
+
list: (query, opts) => this.page("/tenant/mcp", query, opts),
|
|
430
539
|
get: (name, opts) => this.json("GET", `/tenant/mcp/${enc(name)}`, opts),
|
|
431
540
|
/** Register or replace a server (full replace; probes `tools/list`). */
|
|
432
|
-
put: (name, body, opts) => this.json("PUT", `/tenant/mcp/${enc(name)}`, {
|
|
541
|
+
put: (name, body, opts) => this.json("PUT", `/tenant/mcp/${enc(name)}`, {
|
|
542
|
+
...opts,
|
|
543
|
+
body,
|
|
544
|
+
}),
|
|
433
545
|
refresh: (name, opts) => this.json("POST", `/tenant/mcp/${enc(name)}/refresh`, opts),
|
|
434
546
|
delete: (name, opts) => this.empty("DELETE", `/tenant/mcp/${enc(name)}`, opts),
|
|
435
547
|
},
|
|
@@ -473,11 +585,52 @@ export class IngramCloud {
|
|
|
473
585
|
decline: (requestId, opts) => this.json("POST", `/oauth/authorize-requests/${enc(requestId)}/decline`, opts),
|
|
474
586
|
},
|
|
475
587
|
};
|
|
476
|
-
// ── Organization (org token: projects
|
|
477
|
-
// Note: the `/v1/organization/billing/*` surface is not yet wrapped here.
|
|
588
|
+
// ── Organization (org token: projects, tokens, billing) ─────────────────
|
|
478
589
|
organization = {
|
|
590
|
+
/** Platform credits — the org wallet that funds every project's runs.
|
|
591
|
+
* Amounts are integer minor units of the wallet's `currency`. */
|
|
592
|
+
billing: {
|
|
593
|
+
balance: (opts) => this.json("GET", "/organization/billing/balance", opts),
|
|
594
|
+
/** Money in (top-ups, grants, codes) and out (usage debits), newest first. */
|
|
595
|
+
ledger: (query, opts) => this.page("/organization/billing/ledger", query, opts),
|
|
596
|
+
/** Per-project draw for a calendar month (`period`, `YYYY-MM`). */
|
|
597
|
+
usage: (query, opts) => this.json("GET", "/organization/billing/usage", {
|
|
598
|
+
...opts,
|
|
599
|
+
query,
|
|
600
|
+
}),
|
|
601
|
+
/** Daily per-project draw over a rolling window of `days`. */
|
|
602
|
+
usageSeries: (query, opts) => this.json("GET", "/organization/billing/usage/series", {
|
|
603
|
+
...opts,
|
|
604
|
+
query,
|
|
605
|
+
}),
|
|
606
|
+
/** Open a Stripe Checkout Session to top up; send the user to its `url`. */
|
|
607
|
+
checkout: (body, opts) => this.json("POST", "/organization/billing/checkout", { ...opts, body }),
|
|
608
|
+
/** Add a card with no charge, unlocking the one-time welcome credit. */
|
|
609
|
+
setup: (body, opts) => this.json("POST", "/organization/billing/setup", {
|
|
610
|
+
...opts,
|
|
611
|
+
body,
|
|
612
|
+
}),
|
|
613
|
+
redeem: (body, opts) => this.json("POST", "/organization/billing/redeem", { ...opts, body }),
|
|
614
|
+
/** Credit a returning Checkout Session. Safe to call twice — the ledger
|
|
615
|
+
* keys on the session id, so it can't double-credit. */
|
|
616
|
+
confirm: (body, opts) => this.json("POST", "/organization/billing/confirm", { ...opts, body }),
|
|
617
|
+
autoreload: {
|
|
618
|
+
get: (opts) => this.json("GET", "/organization/billing/autoreload", opts),
|
|
619
|
+
put: (body, opts) => this.json("PUT", "/organization/billing/autoreload", {
|
|
620
|
+
...opts,
|
|
621
|
+
body,
|
|
622
|
+
}),
|
|
623
|
+
},
|
|
624
|
+
/** Charge the saved card now. `amount_cents` defaults to the auto-reload amount. */
|
|
625
|
+
reload: (body, opts) => this.json("POST", "/organization/billing/reload", { ...opts, body: body ?? {} }),
|
|
626
|
+
/** A Stripe billing-portal URL for managing cards and invoices. */
|
|
627
|
+
portal: (query, opts) => this.json("GET", "/organization/billing/portal", {
|
|
628
|
+
...opts,
|
|
629
|
+
query,
|
|
630
|
+
}),
|
|
631
|
+
},
|
|
479
632
|
projects: {
|
|
480
|
-
list: (opts) => this.
|
|
633
|
+
list: (query, opts) => this.page("/organization/projects", query, opts),
|
|
481
634
|
create: (body, opts) => this.json("POST", "/organization/projects", {
|
|
482
635
|
...opts,
|
|
483
636
|
body,
|
package/dist/index.js
CHANGED
|
@@ -13,7 +13,11 @@
|
|
|
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";
|
package/dist/scopes.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The closed permission vocabulary a smith token may carry, in mint order.
|
|
3
|
+
*
|
|
4
|
+
* It lives here rather than in the API because it is wire contract: a caller
|
|
5
|
+
* minting a token has to name the scopes it wants (`permissions` is required —
|
|
6
|
+
* there is no "grant everything" default), and the console's token form needs
|
|
7
|
+
* the same list to offer full access. One definition, so a new scope reaches
|
|
8
|
+
* every minting surface at once instead of drifting into a stale copy.
|
|
9
|
+
*
|
|
10
|
+
* Not in here: the admin markers (`tenant:*`, `operator:*`) and the account key
|
|
11
|
+
* (`organization:*`). Those are postures, not permissions — they are never a
|
|
12
|
+
* legal `permissions` entry, and the API refuses them as unknown scopes.
|
|
13
|
+
*/
|
|
14
|
+
export const V1_SCOPES = [
|
|
15
|
+
"runs:read",
|
|
16
|
+
"runs:write",
|
|
17
|
+
"conversations:read",
|
|
18
|
+
"conversations:write",
|
|
19
|
+
"memories:read",
|
|
20
|
+
"memories:write",
|
|
21
|
+
"connections:read",
|
|
22
|
+
"connections:write",
|
|
23
|
+
"deployments:read",
|
|
24
|
+
"deployments:write",
|
|
25
|
+
"schedules:read",
|
|
26
|
+
"schedules:write",
|
|
27
|
+
"approvals:read",
|
|
28
|
+
"approvals:write",
|
|
29
|
+
"traces:read",
|
|
30
|
+
"traces:write",
|
|
31
|
+
"usage:read",
|
|
32
|
+
"usage:write",
|
|
33
|
+
"customers:read",
|
|
34
|
+
"customers:write",
|
|
35
|
+
"files:read",
|
|
36
|
+
"files:write",
|
|
37
|
+
"vector_stores:read",
|
|
38
|
+
"vector_stores:write",
|
|
39
|
+
// Smith-level provider keys (#170, end-user BYOK): an end-user sets their own
|
|
40
|
+
// key; a tenant token manages any of its smiths' keys.
|
|
41
|
+
"model_keys:read",
|
|
42
|
+
"model_keys:write",
|
|
43
|
+
// Agent Skills (#175): a tenant's skill bundles and their immutable versions.
|
|
44
|
+
"skills:read",
|
|
45
|
+
"skills:write",
|
|
46
|
+
// Embeddings: the stateless text→vector compute endpoint (POST /v1/embeddings).
|
|
47
|
+
// Write-only — it produces a result, it reads no stored state.
|
|
48
|
+
"embeddings:write",
|
|
49
|
+
];
|
|
50
|
+
/** The read half of the vocabulary — the scope set for a token that must not
|
|
51
|
+
* change anything. Derived, so it cannot fall behind {@link V1_SCOPES}. */
|
|
52
|
+
export const V1_READ_SCOPES = V1_SCOPES.filter((s) => s.endsWith(":read"));
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The acting principal — who a run or an event is attributable to.
|
|
3
|
+
*
|
|
4
|
+
* Resolved from the authenticated caller at the point of action and stamped on
|
|
5
|
+
* the record it produced; never inferred afterwards. Every event a run produces
|
|
6
|
+
* inherits the run's actor, so a whole turn is attributable to one identity.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
export const Actor = z
|
|
10
|
+
.object({
|
|
11
|
+
/** `smith` — a smith acted (a smith-bound token, or the smith itself on an
|
|
12
|
+
* autonomous turn); `tenant` — a tenant-admin token acted on a smith's
|
|
13
|
+
* behalf; `operator` — Ingram staff acted through the operator console. */
|
|
14
|
+
kind: z.enum(["smith", "tenant", "operator"]),
|
|
15
|
+
/** The smith id, tenant id, or operator email, per `kind`. */
|
|
16
|
+
id: z.string(),
|
|
17
|
+
/** `jti` of the token that authorized the action. Empty when no token
|
|
18
|
+
* acted — a scheduled or channel-driven turn the platform ran itself, or a
|
|
19
|
+
* console session, which signs a short-lived per-request token that is never
|
|
20
|
+
* registered. Read it with `email`: both empty means the platform acted. */
|
|
21
|
+
token_id: z.string(),
|
|
22
|
+
/** The human behind the action, when one is named — the signed-in console user
|
|
23
|
+
* or the Ingram operator. Empty for a machine caller (an API token, a smith
|
|
24
|
+
* acting for itself) and for autonomous work.
|
|
25
|
+
*
|
|
26
|
+
* This is what makes a config change attributable to a *person* rather than to
|
|
27
|
+
* the tenant they share: console mutations all carry `kind: "tenant"`, so
|
|
28
|
+
* without this every colleague's action looked identical. Defaulted rather than
|
|
29
|
+
* optional so records written before it existed read as "no human named"
|
|
30
|
+
* instead of failing to parse. */
|
|
31
|
+
email: z.string().default(""),
|
|
32
|
+
})
|
|
33
|
+
.meta({ id: "Actor" });
|
package/dist/zod/_page.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* The two `/v1` list envelopes, one definition each. Native resources page by
|
|
3
|
+
* keyset: `data` + the opaque `next_cursor` (null on the last page) + `has_more`
|
|
4
|
+
* — the cursor is an opaque, short-lived token; pass it straight back as
|
|
5
|
+
* `?cursor=`, never parse it. OpenAI-mirrored resources use the OpenAI `list`
|
|
6
|
+
* envelope instead: `object:"list"` + `first_id`/`last_id` + `has_more`, paged
|
|
7
|
+
* by passing `last_id` back as `?after=`.
|
|
6
8
|
*/
|
|
7
9
|
import { z } from "zod";
|
|
8
10
|
/** Wrap an item schema as a cursor-paginated list out, named `id` in the spec. */
|
|
@@ -15,3 +17,15 @@ export function pageOut(item, id) {
|
|
|
15
17
|
})
|
|
16
18
|
.meta({ id });
|
|
17
19
|
}
|
|
20
|
+
/** Wrap an item schema in the OpenAI `list` envelope, named `id` in the spec. */
|
|
21
|
+
export function oaiListOut(item, id) {
|
|
22
|
+
return z
|
|
23
|
+
.object({
|
|
24
|
+
object: z.literal("list"),
|
|
25
|
+
data: z.array(item),
|
|
26
|
+
first_id: z.string().nullable(),
|
|
27
|
+
last_id: z.string().nullable(),
|
|
28
|
+
has_more: z.boolean(),
|
|
29
|
+
})
|
|
30
|
+
.meta({ id });
|
|
31
|
+
}
|
package/dist/zod/agents.js
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { z } from "zod";
|
|
15
15
|
import { pageOut } from "./_page.js";
|
|
16
|
+
import { SkillRef } from "./skills.js";
|
|
16
17
|
/** A per-smith variable an agent declares; bound at run time. */
|
|
17
18
|
export const AgentVariable = z
|
|
18
19
|
.object({
|
|
@@ -69,6 +70,8 @@ export const AgentDraft = z
|
|
|
69
70
|
vector_store_ids: z.array(z.string()),
|
|
70
71
|
/** Registered MCP servers this agent's smiths load, by name. Null = all. */
|
|
71
72
|
mcp_servers: z.array(z.string()).nullable(),
|
|
73
|
+
/** Skills this agent's smiths carry. Frozen into the snapshot at publish. */
|
|
74
|
+
skills: z.array(SkillRef),
|
|
72
75
|
auto_memory: z.boolean().nullable(),
|
|
73
76
|
memory_consolidation: z.boolean().nullable(),
|
|
74
77
|
variables: z.array(AgentVariable),
|
|
@@ -106,6 +109,7 @@ export const AgentVersionOut = z
|
|
|
106
109
|
enabled_hosted_tools: z.array(z.string()).optional(),
|
|
107
110
|
vector_store_ids: z.array(z.string()).optional(),
|
|
108
111
|
mcp_servers: z.array(z.string()).nullish(),
|
|
112
|
+
skills: z.array(SkillRef).optional(),
|
|
109
113
|
auto_memory: z.boolean().nullish(),
|
|
110
114
|
memory_consolidation: z.boolean().nullish(),
|
|
111
115
|
variables: z.array(AgentVariable).optional(),
|
|
@@ -116,9 +120,7 @@ export const AgentVersionOut = z
|
|
|
116
120
|
created_at: z.string().nullable(),
|
|
117
121
|
})
|
|
118
122
|
.meta({ id: "AgentVersionOut" });
|
|
119
|
-
export const AgentVersionListOut =
|
|
120
|
-
.object({ data: z.array(AgentVersionOut) })
|
|
121
|
-
.meta({ id: "AgentVersionListOut" });
|
|
123
|
+
export const AgentVersionListOut = pageOut(AgentVersionOut, "AgentVersionListOut");
|
|
122
124
|
// ── Request bodies ──────────────────────────────────────────────────────────
|
|
123
125
|
export const AgentIn = z
|
|
124
126
|
.object({
|
|
@@ -130,6 +132,7 @@ export const AgentIn = z
|
|
|
130
132
|
vector_store_ids: z.array(z.string()).nullish(),
|
|
131
133
|
/** Scope runs to these registered MCP servers (by name). Null/omitted = all. */
|
|
132
134
|
mcp_servers: z.array(z.string()).nullish(),
|
|
135
|
+
skills: z.array(SkillRef).nullish(),
|
|
133
136
|
auto_memory: z.boolean().nullish(),
|
|
134
137
|
memory_consolidation: z.boolean().nullish(),
|
|
135
138
|
variables: z.array(AgentVariable).nullish(),
|
|
@@ -145,6 +148,7 @@ export const AgentPatch = z
|
|
|
145
148
|
/** Scope runs to these registered MCP servers (by name). An explicit null
|
|
146
149
|
* clears the restriction (= all); omitted leaves it unchanged. */
|
|
147
150
|
mcp_servers: z.array(z.string()).nullish(),
|
|
151
|
+
skills: z.array(SkillRef).nullish(),
|
|
148
152
|
auto_memory: z.boolean().nullish(),
|
|
149
153
|
memory_consolidation: z.boolean().nullish(),
|
|
150
154
|
variables: z.array(AgentVariable).nullish(),
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hand-authored Zod schemas for platform credits — the org wallet the tenant
|
|
3
|
+
* funds to pay *Ingram* (`/v1/organization/billing/*`). One wallet pools across
|
|
4
|
+
* all of the org's projects; every endpoint needs an organization-scoped token.
|
|
5
|
+
*
|
|
6
|
+
* Source of truth is the handler (`api/src/routes/billing.ts`), which imports
|
|
7
|
+
* these for request validation and response typing. Amounts are always integer
|
|
8
|
+
* **minor units** (cents) of `currency` (ISO-4217, lower-case) — never floats.
|
|
9
|
+
*
|
|
10
|
+
* The per-endpoint query schemas stay in the handler: they carry OpenAPI
|
|
11
|
+
* `param` metadata, and the client types query args as plain TS.
|
|
12
|
+
*
|
|
13
|
+
* `.meta({ id })` names the component so the emitted OpenAPI references it as
|
|
14
|
+
* `#/components/schemas/<id>` rather than inlining it.
|
|
15
|
+
*/
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
// ── Balance + ledger ────────────────────────────────────────────────────────
|
|
18
|
+
export const BalanceOut = z
|
|
19
|
+
.object({
|
|
20
|
+
/** ISO-4217, lower-case. Clients format `balance_cents` in this currency. */
|
|
21
|
+
currency: z.string(),
|
|
22
|
+
balance_cents: z.number().int(),
|
|
23
|
+
/** Whether the org has a Stripe Customer yet (materialized on first payment). */
|
|
24
|
+
stripe_customer: z.boolean(),
|
|
25
|
+
})
|
|
26
|
+
.meta({ id: "BalanceOut" });
|
|
27
|
+
/** One credit-ledger row. `amount_cents` is positive for money in (top-ups,
|
|
28
|
+
* grants, redeemed codes) and negative for usage debits. */
|
|
29
|
+
export const LedgerEntryOut = z
|
|
30
|
+
.object({
|
|
31
|
+
id: z.string(),
|
|
32
|
+
amount_cents: z.number().int(),
|
|
33
|
+
currency: z.string(),
|
|
34
|
+
kind: z.string(),
|
|
35
|
+
description: z.string(),
|
|
36
|
+
created_at: z.string().nullable(),
|
|
37
|
+
})
|
|
38
|
+
.meta({ id: "LedgerEntryOut" });
|
|
39
|
+
/** A page of ledger rows (keyset pagination). */
|
|
40
|
+
export const LedgerListOut = z
|
|
41
|
+
.object({
|
|
42
|
+
data: z.array(LedgerEntryOut),
|
|
43
|
+
next_cursor: z.string().nullable(),
|
|
44
|
+
has_more: z.boolean(),
|
|
45
|
+
})
|
|
46
|
+
.meta({ id: "LedgerListOut" });
|
|
47
|
+
// ── Per-project draw from the wallet ────────────────────────────────────────
|
|
48
|
+
/** One project's draw for a calendar month — which project is spending the
|
|
49
|
+
* shared funds, and against what cap. */
|
|
50
|
+
export const OrgUsageProject = z
|
|
51
|
+
.object({
|
|
52
|
+
project_id: z.string(),
|
|
53
|
+
name: z.string(),
|
|
54
|
+
/** Credits drawn this period (sum of the project's debit rows). */
|
|
55
|
+
drawn_cents: z.number().int(),
|
|
56
|
+
/** Tokens the project's runs consumed this period (priced daily rollup). */
|
|
57
|
+
tokens: z.number().int(),
|
|
58
|
+
/** The project's tenant-scope budget limit (billing currency, major units),
|
|
59
|
+
* or null when it draws freely from the org wallet. */
|
|
60
|
+
budget_limit: z.number().nullable(),
|
|
61
|
+
budget_action: z.string().nullable(),
|
|
62
|
+
})
|
|
63
|
+
.meta({ id: "OrgUsageProject" });
|
|
64
|
+
export const OrgUsageOut = z
|
|
65
|
+
.object({
|
|
66
|
+
period: z.string(),
|
|
67
|
+
currency: z.string(),
|
|
68
|
+
total_drawn_cents: z.number().int(),
|
|
69
|
+
total_tokens: z.number().int(),
|
|
70
|
+
projects: z.array(OrgUsageProject),
|
|
71
|
+
})
|
|
72
|
+
.meta({ id: "OrgUsageOut" });
|
|
73
|
+
/** One day/project draw. Points are sparse — a day with no draw is absent, and
|
|
74
|
+
* the client fills the gaps with zero. */
|
|
75
|
+
export const OrgUsageSeriesPoint = z
|
|
76
|
+
.object({
|
|
77
|
+
day: z.string(),
|
|
78
|
+
project_id: z.string(),
|
|
79
|
+
drawn_cents: z.number().int(),
|
|
80
|
+
})
|
|
81
|
+
.meta({ id: "OrgUsageSeriesPoint" });
|
|
82
|
+
export const OrgUsageSeriesOut = z
|
|
83
|
+
.object({
|
|
84
|
+
currency: z.string(),
|
|
85
|
+
from: z.string(),
|
|
86
|
+
to: z.string(),
|
|
87
|
+
/** Projects with any draw in the window, ranked by total draw. */
|
|
88
|
+
projects: z.array(z.object({ project_id: z.string(), name: z.string() })),
|
|
89
|
+
points: z.array(OrgUsageSeriesPoint),
|
|
90
|
+
})
|
|
91
|
+
.meta({ id: "OrgUsageSeriesOut" });
|
|
92
|
+
// ── Money movement ──────────────────────────────────────────────────────────
|
|
93
|
+
export const CheckoutIn = z
|
|
94
|
+
.object({
|
|
95
|
+
amount_cents: z.number().int(),
|
|
96
|
+
/** The console's own origin URL to return to; must carry the Stripe session
|
|
97
|
+
* template so the page can reflect the result. */
|
|
98
|
+
return_url: z.string(),
|
|
99
|
+
})
|
|
100
|
+
.meta({ id: "CheckoutIn" });
|
|
101
|
+
export const CheckoutOut = z.object({ url: z.string() }).meta({ id: "CheckoutOut" });
|
|
102
|
+
export const ConfirmIn = z.object({ session_id: z.string() }).meta({ id: "ConfirmIn" });
|
|
103
|
+
export const ConfirmOut = z
|
|
104
|
+
.object({ credited: z.boolean(), payment_status: z.string() })
|
|
105
|
+
.meta({ id: "ConfirmOut" });
|
|
106
|
+
/** Add a card with no charge (Stripe setup-mode Checkout); on success it unlocks
|
|
107
|
+
* the one-time welcome credit. Same return-url contract as checkout. */
|
|
108
|
+
export const SetupIn = z.object({ return_url: z.string() }).meta({ id: "SetupIn" });
|
|
109
|
+
export const SetupOut = z.object({ url: z.string() }).meta({ id: "SetupOut" });
|
|
110
|
+
/** Redeem a one-time credit code, matched case-insensitively. */
|
|
111
|
+
export const RedeemIn = z.object({ code: z.string() }).meta({ id: "RedeemIn" });
|
|
112
|
+
export const RedeemOut = z
|
|
113
|
+
.object({
|
|
114
|
+
amount_cents: z.number().int(),
|
|
115
|
+
currency: z.string(),
|
|
116
|
+
})
|
|
117
|
+
.meta({ id: "RedeemOut" });
|
|
118
|
+
export const AutoreloadOut = z
|
|
119
|
+
.object({
|
|
120
|
+
enabled: z.boolean(),
|
|
121
|
+
/** When the balance drops below `threshold_cents`, the saved card is charged
|
|
122
|
+
* for `amount_cents`. Both are integer minor units of the billing currency. */
|
|
123
|
+
threshold_cents: z.number().int(),
|
|
124
|
+
amount_cents: z.number().int(),
|
|
125
|
+
})
|
|
126
|
+
.meta({ id: "AutoreloadOut" });
|
|
127
|
+
/** Set the same shape you read back. */
|
|
128
|
+
export const AutoreloadIn = AutoreloadOut;
|
|
129
|
+
/** `amount_cents` is optional — it defaults to the configured auto-reload amount. */
|
|
130
|
+
export const ReloadIn = z
|
|
131
|
+
.object({ amount_cents: z.number().int().optional() })
|
|
132
|
+
.meta({ id: "ReloadIn" });
|
|
133
|
+
export const ReloadOut = z
|
|
134
|
+
.object({ credited: z.boolean(), payment_status: z.string() })
|
|
135
|
+
.meta({ id: "ReloadOut" });
|
|
136
|
+
export const PortalOut = z.object({ url: z.string() }).meta({ id: "PortalOut" });
|
package/dist/zod/budgets.js
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* `#/components/schemas/<id>` rather than inlining it.
|
|
13
13
|
*/
|
|
14
14
|
import { z } from "zod";
|
|
15
|
+
import { pageOut } from "./_page.js";
|
|
15
16
|
/** What a budget caps; `agent`/`smith`/`customer` budgets carry the id in
|
|
16
17
|
* `scope_id` (an agent design, a single smith, or one of your customers). */
|
|
17
18
|
export const BudgetScope = z.enum(["tenant", "agent", "smith", "customer"]);
|
|
@@ -40,9 +41,7 @@ export const BudgetStatusOut = BudgetOut.extend({
|
|
|
40
41
|
pct: z.number(),
|
|
41
42
|
over: z.boolean(),
|
|
42
43
|
}).meta({ id: "BudgetStatusOut" });
|
|
43
|
-
export const BudgetListOut =
|
|
44
|
-
.object({ data: z.array(BudgetOut) })
|
|
45
|
-
.meta({ id: "BudgetListOut" });
|
|
44
|
+
export const BudgetListOut = pageOut(BudgetOut, "BudgetListOut");
|
|
46
45
|
// ── Request bodies ──────────────────────────────────────────────────────────
|
|
47
46
|
export const BudgetIn = z
|
|
48
47
|
.object({
|
package/dist/zod/connections.js
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* `#/components/schemas/<id>` rather than inlining it.
|
|
19
19
|
*/
|
|
20
20
|
import { z } from "zod";
|
|
21
|
+
import { pageOut } from "./_page.js";
|
|
21
22
|
/** OAuth token material the tenant pushes in; IC stores it encrypted and never
|
|
22
23
|
* echoes it back. Only `kind: "oauth_tokens"` is accepted. */
|
|
23
24
|
export const Credential = z
|
|
@@ -41,9 +42,7 @@ export const ConnectionOut = z
|
|
|
41
42
|
created_at: z.string().nullable(),
|
|
42
43
|
})
|
|
43
44
|
.meta({ id: "ConnectionOut" });
|
|
44
|
-
export const ConnectionListOut =
|
|
45
|
-
.object({ data: z.array(ConnectionOut) })
|
|
46
|
-
.meta({ id: "ConnectionListOut" });
|
|
45
|
+
export const ConnectionListOut = pageOut(ConnectionOut, "ConnectionListOut");
|
|
47
46
|
// ── Request bodies ──────────────────────────────────────────────────────────
|
|
48
47
|
export const ConnectionIn = z
|
|
49
48
|
.object({
|