@k9o/core 1.1.1 → 1.3.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/CHANGELOG.md +49 -0
- package/README.md +169 -16
- package/dist/{chunk-O2ZTV6YN.js → chunk-KC4EDMBF.js} +61 -3
- package/dist/chunk-KC4EDMBF.js.map +1 -0
- package/dist/{chunk-2NDFTHUB.js → chunk-UL53GNYM.js} +23 -5
- package/dist/chunk-UL53GNYM.js.map +1 -0
- package/dist/http.d.ts +2 -0
- package/dist/http.js +2 -1
- package/dist/index.d.ts +563 -517
- package/dist/index.js +170 -421
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/url-grammar.d.ts +32 -16
- package/dist/url-grammar.js +5 -1
- package/package.json +4 -4
- package/src/audit.ts +16 -26
- package/src/compute/llms.ts +55 -33
- package/src/functions.ts +60 -27
- package/src/http.ts +5 -1
- package/src/index.ts +16 -17
- package/src/me.ts +69 -85
- package/src/migrations.ts +61 -11
- package/src/org.ts +138 -140
- package/src/orgs.ts +16 -3
- package/src/policies.ts +63 -24
- package/src/projects.ts +58 -22
- package/src/realtime.ts +21 -200
- package/src/region.ts +83 -3
- package/src/storage-buckets.ts +17 -5
- package/src/studio/workflows.ts +8 -8
- package/src/types.ts +3 -3
- package/src/url-grammar.ts +52 -25
- package/dist/chunk-2NDFTHUB.js.map +0 -1
- package/dist/chunk-O2ZTV6YN.js.map +0 -1
- package/src/metadata.ts +0 -130
package/dist/types.d.ts
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* canonical org subdomain `https://<orgSlug>.api.k9o.io`. Pass an explicit host to override — an explicit `<orgSlug>` subdomain,
|
|
28
28
|
* or a self-hosted / Sovereign-Control host, or a dev host — used as-is.
|
|
29
29
|
* - `fetch` — custom fetch implementation (defaults to global)
|
|
30
|
-
* - `retryConfig` — retry/backoff config
|
|
30
|
+
* - `retryConfig` — retry/backoff config for idempotent requests
|
|
31
31
|
* - `defaultHeaders` — headers merged into every request
|
|
32
32
|
*/
|
|
33
33
|
type CreateClientOptions = {
|
|
@@ -40,8 +40,8 @@ type CreateClientOptions = {
|
|
|
40
40
|
defaultHeaders?: Record<string, string> | undefined;
|
|
41
41
|
};
|
|
42
42
|
/**
|
|
43
|
-
* Retry config.
|
|
44
|
-
*
|
|
43
|
+
* Retry config. Only GET, HEAD, OPTIONS and DELETE are retried, on network failure and on
|
|
44
|
+
* HTTP 429, 502, 503 and 504.
|
|
45
45
|
*/
|
|
46
46
|
type RetryConfig = {
|
|
47
47
|
maxRetries: number;
|
package/dist/url-grammar.d.ts
CHANGED
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
* URL grammar.
|
|
3
3
|
*
|
|
4
4
|
* Canonical URL shapes:
|
|
5
|
-
* - Member-plane (project-scoped): `<orgSlug>.api
|
|
6
|
-
* - Org-plane (org-scoped): `<orgSlug>.api
|
|
7
|
-
* - Platform-plane (cross-org): `api
|
|
5
|
+
* - Member-plane (project-scoped): `<orgSlug>.api.<apex>/@<projectSlug>/<sub-resource>/...`
|
|
6
|
+
* - Org-plane (org-scoped): `<orgSlug>.api.<apex>/<resource>/...`
|
|
7
|
+
* - Platform-plane (cross-org): `api.<apex>/discovery/...` + `api.<apex>/auth/...` etc.
|
|
8
|
+
*
|
|
9
|
+
* `<apex>` is whatever the deployment uses (public cloud, internal, air-gapped, localhost);
|
|
10
|
+
* the SDK takes the host from the baseUrl it is given and never matches it against a list.
|
|
8
11
|
*
|
|
9
12
|
* The `baseUrl` passed to `createClient` is the gateway host root —
|
|
10
|
-
* scheme + host (+ optional port)
|
|
13
|
+
* scheme + host (+ optional port) Path-bearing baseUrls
|
|
11
14
|
* are rejected with `K9O_INVALID_BASE_URL`.
|
|
12
15
|
*
|
|
13
16
|
* The SDK constructs URLs by composing `baseUrl + path-from-builder`.
|
|
@@ -32,18 +35,31 @@
|
|
|
32
35
|
* - query / fragment (`https://api.k9o.io?x=1`)
|
|
33
36
|
*/
|
|
34
37
|
declare function validateBaseUrl(baseUrl: string): string;
|
|
38
|
+
/** The convenience default when the caller passes no baseUrl. A default value only: never used to parse a host. */
|
|
39
|
+
declare const DEFAULT_BASE_URL = "https://api.k9o.io";
|
|
40
|
+
/** The structure of a gateway API host, read from the host itself. */
|
|
41
|
+
type ApiHost = {
|
|
42
|
+
/** First label of an org host (`acme` in `acme.api.corp.internal`); null for a platform host (`api.corp.internal`). */
|
|
43
|
+
orgSlug: string | null;
|
|
44
|
+
/** `api` or `api-staging`: the label that marks a gateway host. */
|
|
45
|
+
family: "api" | "api-staging";
|
|
46
|
+
/** 4-character region code when the host is regional (`api-de01`), else null (region-free). */
|
|
47
|
+
region: string | null;
|
|
48
|
+
/** Everything after the gateway label (`corp.internal`, `k9o.io`): the apex, never matched against a list. */
|
|
49
|
+
apex: string;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Read the org slug and region out of a gateway host without knowing its apex. The gateway label is `api` or
|
|
53
|
+
* `api-staging`, optionally followed by `-<rgn>`; the label before it is the org slug and whatever follows it is the
|
|
54
|
+
* apex. Returns null for any other shape (localhost, an IP, a single-label host, a host with no gateway label), which
|
|
55
|
+
* callers use exactly as given.
|
|
56
|
+
*/
|
|
57
|
+
declare function parseApiHost(host: string): ApiHost | null;
|
|
35
58
|
/**
|
|
36
|
-
* Resolve the effective baseUrl. `baseUrl` is
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* `https://<orgSlug>.<apex>`. An explicit `<orgSlug>` subdomain, a
|
|
41
|
-
* self-hosted / Sovereign host, or a dev host (anything not in that set)
|
|
42
|
-
* passes through unchanged — `orgSlug` is intentionally NOT validated or
|
|
43
|
-
* composed onto a non-apex host (fixed 2026-08-30: this used to silently
|
|
44
|
-
* ignore `orgSlug` for `api-staging.k9o.io` too, not just genuine
|
|
45
|
-
* self-hosted/custom hosts, since only the literal production apex string
|
|
46
|
-
* was checked).
|
|
59
|
+
* Resolve the effective baseUrl. `baseUrl` is OPTIONAL: omitted, it defaults to {@link DEFAULT_BASE_URL} (the public
|
|
60
|
+
* cloud, a convenience only). When the (validated) host is a platform host (`api.<apex>` or `api-staging.<apex>`, any
|
|
61
|
+
* apex) and `orgSlug` is supplied, the canonical org host `<orgSlug>.<host>` is composed. Any other host (an org host
|
|
62
|
+
* already, an internal or air-gapped host, localhost) passes through unchanged; `orgSlug` is then only sent as a header.
|
|
47
63
|
*/
|
|
48
64
|
declare function resolveBaseUrl(baseUrl: string | undefined, orgSlug?: string): string;
|
|
49
65
|
declare function validateSlug(slug: string, kind: "org" | "project"): void;
|
|
@@ -72,4 +88,4 @@ declare function orgPath(resource: string): string;
|
|
|
72
88
|
*/
|
|
73
89
|
declare function platformPath(resource: string): string;
|
|
74
90
|
|
|
75
|
-
export { orgPath, platformPath, projectPath, resolveBaseUrl, validateBaseUrl, validateSlug };
|
|
91
|
+
export { type ApiHost, DEFAULT_BASE_URL, orgPath, parseApiHost, platformPath, projectPath, resolveBaseUrl, validateBaseUrl, validateSlug };
|
package/dist/url-grammar.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
|
+
DEFAULT_BASE_URL,
|
|
2
3
|
orgPath,
|
|
4
|
+
parseApiHost,
|
|
3
5
|
platformPath,
|
|
4
6
|
projectPath,
|
|
5
7
|
resolveBaseUrl,
|
|
6
8
|
validateBaseUrl,
|
|
7
9
|
validateSlug
|
|
8
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-UL53GNYM.js";
|
|
9
11
|
import "./chunk-LJZ45UA2.js";
|
|
10
12
|
export {
|
|
13
|
+
DEFAULT_BASE_URL,
|
|
11
14
|
orgPath,
|
|
15
|
+
parseApiHost,
|
|
12
16
|
platformPath,
|
|
13
17
|
projectPath,
|
|
14
18
|
resolveBaseUrl,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k9o/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Kilimanjaro platform SDK — createClient + data-plane + projects + migrations + functions + studio (workflows/dashboards) + compute.llms + realtime subscriptions + KError + meta accessor sugar. Composes with @k9o/gate (auth) and @k9o/extensions (extension consumption).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -60,9 +60,9 @@
|
|
|
60
60
|
"url": "https://github.com/k9o-dev/sdk-typescript"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@k9o/gate": "1.
|
|
64
|
-
"@k9o/extensions": "1.
|
|
65
|
-
"@k9o/kibo": "1.
|
|
63
|
+
"@k9o/gate": "1.3.0",
|
|
64
|
+
"@k9o/extensions": "1.3.0",
|
|
65
|
+
"@k9o/kibo": "1.3.0"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"bun-types": "^1.1.0",
|
package/src/audit.ts
CHANGED
|
@@ -4,25 +4,21 @@
|
|
|
4
4
|
* Backed by the gateway audit-log routes.
|
|
5
5
|
*
|
|
6
6
|
* Wire mapping:
|
|
7
|
-
* - `query({
|
|
7
|
+
* - `query({ eventType, actorId, after, before, limit, cursor })`
|
|
8
8
|
* → GET /@<slug>/audit-log?...
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* `feedback_error_code_namespace_boundary_and_prefix.md` cement.
|
|
10
|
+
* Option names are the gateway's query parameter names. The endpoint
|
|
11
|
+
* accepts cursor-paginated reverse-chronological queries. `eventType` is
|
|
12
|
+
* the audit-event name (e.g. `data.write.access.insert`).
|
|
14
13
|
*
|
|
15
|
-
* Returns audit events with full context payload
|
|
16
|
-
* targetId / payload / occurredAt / requestId / traceId.
|
|
14
|
+
* Returns audit events with full context payload.
|
|
17
15
|
*/
|
|
18
16
|
|
|
19
17
|
import { request, type HttpClientConfig } from "./http.ts";
|
|
20
18
|
import { projectPath } from "./url-grammar.ts";
|
|
21
19
|
import type { Envelope } from "./envelope.ts";
|
|
22
20
|
|
|
23
|
-
/**
|
|
24
|
-
* Audit event record `_sys.audit_log` shape.
|
|
25
|
-
*/
|
|
21
|
+
/** Audit event record. */
|
|
26
22
|
export type AuditEvent = {
|
|
27
23
|
id: string;
|
|
28
24
|
/** Dotted namespace (e.g. `data.write.access.insert`). */
|
|
@@ -37,18 +33,14 @@ export type AuditEvent = {
|
|
|
37
33
|
};
|
|
38
34
|
|
|
39
35
|
export type AuditQueryOpts = {
|
|
40
|
-
/**
|
|
41
|
-
|
|
42
|
-
/** ISO 8601 upper bound (exclusive). */
|
|
43
|
-
until?: string | undefined;
|
|
44
|
-
/** Filter by event type (exact match; future cycles may add prefix-match). */
|
|
45
|
-
type?: string | undefined;
|
|
36
|
+
/** Filter by event type. */
|
|
37
|
+
eventType?: string | undefined;
|
|
46
38
|
/** Filter by actor. */
|
|
47
39
|
actorId?: string | undefined;
|
|
48
|
-
/**
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
|
|
40
|
+
/** ISO 8601 lower bound: only events after this instant. */
|
|
41
|
+
after?: string | undefined;
|
|
42
|
+
/** ISO 8601 upper bound: only events before this instant. */
|
|
43
|
+
before?: string | undefined;
|
|
52
44
|
/** Page size (per-tier max bounded server-side). */
|
|
53
45
|
limit?: number | undefined;
|
|
54
46
|
/** Cursor from prior response. */
|
|
@@ -68,9 +60,8 @@ export function makeAuditNamespace(config: HttpClientConfig) {
|
|
|
68
60
|
* Query the audit log. Returns reverse-chronological events matching
|
|
69
61
|
* all supplied filters (AND composition).
|
|
70
62
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* endpoint); platform-level audit is admin-only (separate surface).
|
|
63
|
+
* Requires the `AUDIT_READER` role at minimum. This endpoint is
|
|
64
|
+
* project-scoped.
|
|
74
65
|
*/
|
|
75
66
|
async query(opts?: AuditQueryOpts): Promise<Envelope<ReadonlyArray<AuditEvent>>> {
|
|
76
67
|
const slug = requireProjectSlug(config);
|
|
@@ -83,8 +74,7 @@ export function makeAuditNamespace(config: HttpClientConfig) {
|
|
|
83
74
|
|
|
84
75
|
/**
|
|
85
76
|
* Convenience: live-tail recent events. Currently single-shot read
|
|
86
|
-
* with `
|
|
87
|
-
* (SSE) lands when the streaming layer ships pattern.
|
|
77
|
+
* with `after` defaulted to "1 minute ago".
|
|
88
78
|
*/
|
|
89
79
|
async tail(opts?: { sinceMinutes?: number; limit?: number }): Promise<Envelope<ReadonlyArray<AuditEvent>>> {
|
|
90
80
|
const slug = requireProjectSlug(config);
|
|
@@ -93,7 +83,7 @@ export function makeAuditNamespace(config: HttpClientConfig) {
|
|
|
93
83
|
return request(config, {
|
|
94
84
|
method: "GET",
|
|
95
85
|
path: projectPath(slug, "audit-log"),
|
|
96
|
-
query: { since, limit: opts?.limit ?? 100 },
|
|
86
|
+
query: { after: since, limit: opts?.limit ?? 100 },
|
|
97
87
|
});
|
|
98
88
|
},
|
|
99
89
|
};
|
package/src/compute/llms.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Compute LLMs SDK — `client.compute.llms.*`.
|
|
3
3
|
*
|
|
4
|
-
* Compute LLMs registry
|
|
5
|
-
*
|
|
4
|
+
* Compute LLMs registry: a curated model library, four endpoints and
|
|
5
|
+
* per-model tier gating.
|
|
6
6
|
*
|
|
7
|
-
* Wire mapping (project-plane
|
|
7
|
+
* Wire mapping (project-plane):
|
|
8
8
|
* - list() → GET /@<slug>/compute/llms
|
|
9
9
|
* - read(modelId) → GET /@<slug>/compute/llms/<model-id>
|
|
10
10
|
* - invoke(modelId, ...) → POST /@<slug>/compute/llms/<model-id>/invoke
|
|
11
11
|
* - invokeStream(modelId,...) → POST /@<slug>/compute/llms/<model-id>/invoke-stream (SSE)
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* RBAC: list/read against all cohort roles; invoke + invokeStream require
|
|
14
|
+
* PROJECT_AUTHOR or PROJECT_ADMIN (LLM cost gate). External-provider models
|
|
15
|
+
* answer 501 `K9O_NOT_IMPLEMENTED` until the provider client is built.
|
|
16
|
+
* Surfaces K9O_LLM_PROVIDER_UNAVAILABLE (503), K9O_MODEL_NOT_DECLARED and
|
|
17
|
+
* K9O_TIER_FEATURE_GATED.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
import { request, requestStream, type HttpClientConfig } from "../http.ts";
|
|
@@ -22,7 +22,7 @@ import { projectPath } from "../url-grammar.ts";
|
|
|
22
22
|
import type { Envelope } from "../envelope.ts";
|
|
23
23
|
import { parseSseStream } from "../internal/sse.ts";
|
|
24
24
|
|
|
25
|
-
/** Curated
|
|
25
|
+
/** Curated model ids. */
|
|
26
26
|
export type LLMModelId =
|
|
27
27
|
| "mistral-7b"
|
|
28
28
|
| "mistral-8x7b"
|
|
@@ -37,7 +37,7 @@ export type LLMModelId =
|
|
|
37
37
|
export type LLMProviderClass = "self-hosted" | "external";
|
|
38
38
|
export type LLMModality = "text-completion" | "text-completion+tool-use" | "embeddings";
|
|
39
39
|
|
|
40
|
-
/** Model metadata
|
|
40
|
+
/** Model metadata with per-model cost. */
|
|
41
41
|
export type LLMModel = {
|
|
42
42
|
id: LLMModelId;
|
|
43
43
|
providerClass: LLMProviderClass;
|
|
@@ -46,35 +46,54 @@ export type LLMModel = {
|
|
|
46
46
|
tierGate: string;
|
|
47
47
|
contextWindow: number;
|
|
48
48
|
capabilities: ReadonlyArray<string>;
|
|
49
|
-
/** Per-model token cost
|
|
49
|
+
/** Per-model token cost. */
|
|
50
50
|
costPerMillionInputTokens: number;
|
|
51
51
|
costPerMillionOutputTokens: number;
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
-
/** Inference parameters
|
|
54
|
+
/** Inference parameters the route reads; sent flat in the request body. */
|
|
55
55
|
export type LLMInvokeParams = {
|
|
56
|
+
/** 1 to 32000. */
|
|
56
57
|
maxTokens?: number;
|
|
58
|
+
/** 0 to 2. */
|
|
57
59
|
temperature?: number;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
/** Free-form usage label recorded with the call. */
|
|
61
|
+
usageType?: string;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/** Token counts the model server reported for a call. */
|
|
65
|
+
export type LLMUsage = {
|
|
66
|
+
promptTokens: number;
|
|
67
|
+
completionTokens: number;
|
|
68
|
+
totalTokens: number;
|
|
61
69
|
};
|
|
62
70
|
|
|
63
|
-
/** Synchronous inference response `/invoke`. */
|
|
71
|
+
/** Synchronous inference response from `/invoke`. */
|
|
64
72
|
export type LLMResponse = {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
73
|
+
modelId: string;
|
|
74
|
+
/** The generated text. */
|
|
75
|
+
content: string;
|
|
76
|
+
finishReason: string | null;
|
|
77
|
+
usage: LLMUsage;
|
|
78
|
+
usageType: string;
|
|
68
79
|
};
|
|
69
80
|
|
|
70
|
-
/**
|
|
81
|
+
/**
|
|
82
|
+
* One chunk of the `/invoke-stream` response: the model server's OpenAI-style
|
|
83
|
+
* chat-completion chunk, passed through unchanged. Read incremental text from
|
|
84
|
+
* `choices[0].delta.content`; the final chunk may carry `usage`.
|
|
85
|
+
*/
|
|
71
86
|
export type LLMStreamChunk = {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
87
|
+
id?: string;
|
|
88
|
+
object?: string;
|
|
89
|
+
model?: string;
|
|
90
|
+
choices?: ReadonlyArray<{
|
|
91
|
+
index?: number;
|
|
92
|
+
delta?: { role?: string; content?: string | null };
|
|
93
|
+
finish_reason?: string | null;
|
|
94
|
+
}>;
|
|
95
|
+
usage?: { prompt_tokens?: number; completion_tokens?: number; total_tokens?: number } | null;
|
|
96
|
+
[key: string]: unknown;
|
|
78
97
|
};
|
|
79
98
|
|
|
80
99
|
export type LLMInvokeInput = {
|
|
@@ -82,7 +101,11 @@ export type LLMInvokeInput = {
|
|
|
82
101
|
params?: LLMInvokeParams;
|
|
83
102
|
};
|
|
84
103
|
|
|
85
|
-
|
|
104
|
+
function invokeBody(input: LLMInvokeInput): Record<string, unknown> {
|
|
105
|
+
return { prompt: input.prompt, ...input.params };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Error codes specific to LLM calls. */
|
|
86
109
|
export const LLM_ERROR_CODES = {
|
|
87
110
|
PROVIDER_UNAVAILABLE: "K9O_LLM_PROVIDER_UNAVAILABLE",
|
|
88
111
|
} as const;
|
|
@@ -120,24 +143,23 @@ export function makeLlmsNamespace(config: HttpClientConfig) {
|
|
|
120
143
|
return request(config, {
|
|
121
144
|
method: "POST",
|
|
122
145
|
path: projectPath(slug, `compute/llms/${encodeURIComponent(modelId)}/invoke`),
|
|
123
|
-
body:
|
|
146
|
+
body: invokeBody(input),
|
|
124
147
|
});
|
|
125
148
|
},
|
|
126
149
|
|
|
127
150
|
/**
|
|
128
151
|
* POST /@<slug>/compute/llms/<model-id>/invoke-stream — streaming
|
|
129
|
-
* inference (SSE;
|
|
152
|
+
* inference (SSE; the model server's OpenAI-style chunks).
|
|
130
153
|
* Returns an async iterable of `LLMStreamChunk` — caller writes
|
|
131
154
|
* `for await (const chunk of client.compute.llms.invokeStream(...))`.
|
|
132
|
-
* The SDK handles SSE framing internally
|
|
133
|
-
* `feedback_sdk_abstracted_primitive_default_to_richer_interaction.md`.
|
|
155
|
+
* The SDK handles SSE framing internally.
|
|
134
156
|
*/
|
|
135
157
|
async *invokeStream(modelId: LLMModelId | string, input: LLMInvokeInput): AsyncGenerator<LLMStreamChunk, void, void> {
|
|
136
158
|
const slug = requireProjectSlug(config);
|
|
137
159
|
const response = await requestStream(config, {
|
|
138
160
|
method: "POST",
|
|
139
161
|
path: projectPath(slug, `compute/llms/${encodeURIComponent(modelId)}/invoke-stream`),
|
|
140
|
-
body:
|
|
162
|
+
body: invokeBody(input),
|
|
141
163
|
accept: "text/event-stream",
|
|
142
164
|
});
|
|
143
165
|
// requestStream guarantees a non-null body on 2xx.
|
|
@@ -148,7 +170,7 @@ export function makeLlmsNamespace(config: HttpClientConfig) {
|
|
|
148
170
|
|
|
149
171
|
export function makeComputeNamespace(config: HttpClientConfig) {
|
|
150
172
|
return {
|
|
151
|
-
/** LLM registry + inference — `client.compute.llms
|
|
173
|
+
/** LLM registry + inference — `client.compute.llms.*` . */
|
|
152
174
|
llms: makeLlmsNamespace(config),
|
|
153
175
|
};
|
|
154
176
|
}
|
package/src/functions.ts
CHANGED
|
@@ -4,15 +4,14 @@
|
|
|
4
4
|
* Backed by the gateway functions and invoke routes.
|
|
5
5
|
*
|
|
6
6
|
* Wire mapping:
|
|
7
|
-
* - `deploy({ name, runtime,
|
|
7
|
+
* - `deploy({ name, runtime, tier, artifactKey, version })` → POST /@<slug>/functions
|
|
8
8
|
* - `list()` → GET /@<slug>/functions
|
|
9
9
|
* - `get(name)` → GET /@<slug>/functions/<name>
|
|
10
10
|
* - `delete(name)` → DELETE /@<slug>/functions/<name>
|
|
11
11
|
* - `invoke(name, payload)` → POST /@<slug>/functions/<name>/invoke
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
* function
|
|
15
|
-
* `deploying`; the function is ready when status flips to `active`.
|
|
13
|
+
* Deploy requires PROJECT_ADMIN and returns with status `deploying`; the
|
|
14
|
+
* function is ready when status flips to `active`.
|
|
16
15
|
*/
|
|
17
16
|
|
|
18
17
|
import { request, type HttpClientConfig } from "./http.ts";
|
|
@@ -26,23 +25,45 @@ export type FunctionRecord = {
|
|
|
26
25
|
/** `fn_<base62>`. */
|
|
27
26
|
id: string;
|
|
28
27
|
name: string;
|
|
29
|
-
runtime: "
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
runtime: DeployFunctionInput["runtime"];
|
|
29
|
+
tier: "gateway" | "sandbox";
|
|
30
|
+
entryPoint: string;
|
|
31
|
+
version: string;
|
|
32
|
+
status: "deploying" | "active" | "error" | "retired";
|
|
33
|
+
/** Who manages the function: a developer deploy, or an extension (`extension:<id>`). */
|
|
34
|
+
source: string;
|
|
35
|
+
description: string | null;
|
|
32
36
|
createdAt: string;
|
|
33
|
-
|
|
37
|
+
deployedAt: string | null;
|
|
38
|
+
retiredAt: string | null;
|
|
39
|
+
errorDetail: string | null;
|
|
34
40
|
};
|
|
35
41
|
|
|
36
42
|
/**
|
|
37
|
-
* Deploy input. The
|
|
38
|
-
*
|
|
43
|
+
* Deploy input. The function's bytes are uploaded first (the gateway's
|
|
44
|
+
* function-artifact upload returns the `artifactKey`); deploy references
|
|
45
|
+
* that artifact.
|
|
39
46
|
*/
|
|
40
47
|
export type DeployFunctionInput = {
|
|
48
|
+
/** Function name (1 to 128 characters). */
|
|
41
49
|
name: string;
|
|
42
|
-
runtime: "
|
|
43
|
-
|
|
44
|
-
tier
|
|
45
|
-
|
|
50
|
+
runtime: "bun" | "python" | "go" | "java" | "kotlin" | "dotnet" | "swift" | "php" | "ruby" | "rust" | "tinygo" | "zig" | "assemblyscript";
|
|
51
|
+
/** `gateway` runs WebAssembly in the gateway; `sandbox` runs an OCI image archive. */
|
|
52
|
+
tier: "gateway" | "sandbox";
|
|
53
|
+
/** Content-addressed key of the uploaded artifact. */
|
|
54
|
+
artifactKey: string;
|
|
55
|
+
/** Version label for this deploy (1 to 64 characters). */
|
|
56
|
+
version: string;
|
|
57
|
+
description?: string | undefined;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/** Optional invoke controls; property names are the gateway's. */
|
|
61
|
+
export type InvokeFunctionOptions = {
|
|
62
|
+
/** Run asynchronously instead of waiting for the result. */
|
|
63
|
+
background?: boolean | undefined;
|
|
64
|
+
delegation?: { token: string; invokeSessionId?: string | undefined } | undefined;
|
|
65
|
+
onBehalfOf?: string | undefined;
|
|
66
|
+
confinedTo?: string | undefined;
|
|
46
67
|
};
|
|
47
68
|
|
|
48
69
|
function requireProjectSlug(config: HttpClientConfig): string {
|
|
@@ -54,7 +75,22 @@ function requireProjectSlug(config: HttpClientConfig): string {
|
|
|
54
75
|
|
|
55
76
|
export function makeFunctionsNamespace(config: HttpClientConfig) {
|
|
56
77
|
return {
|
|
57
|
-
/**
|
|
78
|
+
/**
|
|
79
|
+
* Upload a function artifact and get back its content-addressed `artifactKey`, to pass to `deploy`.
|
|
80
|
+
* `POST /@<projectSlug>/functions/artifacts` with the raw bytes: a WebAssembly module for the gateway tier (up to
|
|
81
|
+
* 16 MiB) or an OCI image archive for the sandbox tier (up to 256 MiB). Uploading the same bytes again returns the same key.
|
|
82
|
+
*/
|
|
83
|
+
async uploadArtifact(bytes: Uint8Array | ArrayBuffer | Blob, kind: "wasm" | "tar"): Promise<Envelope<{ artifactKey: string }>> {
|
|
84
|
+
const slug = requireProjectSlug(config);
|
|
85
|
+
return request(config, {
|
|
86
|
+
method: "POST",
|
|
87
|
+
path: projectPath(slug, "functions/artifacts"),
|
|
88
|
+
rawBody: bytes,
|
|
89
|
+
headers: { "content-type": kind === "wasm" ? "application/wasm" : "application/x-tar" },
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
/** Deploy or redeploy a function from an uploaded artifact. Returns the function record with status. */
|
|
58
94
|
async deploy(input: DeployFunctionInput): Promise<Envelope<FunctionRecord>> {
|
|
59
95
|
const slug = requireProjectSlug(config);
|
|
60
96
|
return request(config, {
|
|
@@ -65,7 +101,7 @@ export function makeFunctionsNamespace(config: HttpClientConfig) {
|
|
|
65
101
|
},
|
|
66
102
|
|
|
67
103
|
/** List deployed functions (cursor pagination). */
|
|
68
|
-
async list(opts?: { limit?: number; cursor?: string; status?: FunctionRecord["status"] }): Promise<Envelope<ReadonlyArray<FunctionRecord>>> {
|
|
104
|
+
async list(opts?: { limit?: number; cursor?: string; status?: FunctionRecord["status"]; tier?: FunctionRecord["tier"]; source?: string }): Promise<Envelope<ReadonlyArray<FunctionRecord>>> {
|
|
69
105
|
const slug = requireProjectSlug(config);
|
|
70
106
|
return request(config, {
|
|
71
107
|
method: "GET",
|
|
@@ -83,8 +119,8 @@ export function makeFunctionsNamespace(config: HttpClientConfig) {
|
|
|
83
119
|
});
|
|
84
120
|
},
|
|
85
121
|
|
|
86
|
-
/** Retire a function. Returns
|
|
87
|
-
async delete(name: string): Promise<Envelope<
|
|
122
|
+
/** Retire a function. Returns the retired record; the function name enters a 24h cooldown. */
|
|
123
|
+
async delete(name: string): Promise<Envelope<FunctionRecord>> {
|
|
88
124
|
const slug = requireProjectSlug(config);
|
|
89
125
|
return request(config, {
|
|
90
126
|
method: "DELETE",
|
|
@@ -93,21 +129,18 @@ export function makeFunctionsNamespace(config: HttpClientConfig) {
|
|
|
93
129
|
},
|
|
94
130
|
|
|
95
131
|
/**
|
|
96
|
-
* Invoke a function. The `payload` is
|
|
97
|
-
*
|
|
98
|
-
* in the standard
|
|
99
|
-
*
|
|
100
|
-
* Per: invoke authority is per-function (declared in the
|
|
101
|
-
* function manifest). Per: streaming responses use the
|
|
102
|
-
* subscription/async-iterator pattern; this method covers the
|
|
132
|
+
* Invoke a function. The `payload` is sent as the `payload` field of
|
|
133
|
+
* the request body and passed to the function runtime verbatim; the
|
|
134
|
+
* gateway returns whatever the function returns wrapped in the standard
|
|
135
|
+
* envelope. Invoke authority is per function. This method covers the
|
|
103
136
|
* request-response variant only.
|
|
104
137
|
*/
|
|
105
|
-
async invoke<TResult = unknown, TPayload = unknown>(name: string, payload
|
|
138
|
+
async invoke<TResult = unknown, TPayload = unknown>(name: string, payload?: TPayload, options?: InvokeFunctionOptions): Promise<Envelope<TResult>> {
|
|
106
139
|
const slug = requireProjectSlug(config);
|
|
107
140
|
return request(config, {
|
|
108
141
|
method: "POST",
|
|
109
142
|
path: projectPath(slug, `functions/${encodeURIComponent(name)}/invoke`),
|
|
110
|
-
body: payload,
|
|
143
|
+
body: { ...(payload !== undefined ? { payload } : {}), ...(options ?? {}) },
|
|
111
144
|
});
|
|
112
145
|
},
|
|
113
146
|
};
|
package/src/http.ts
CHANGED
|
@@ -53,6 +53,8 @@ export type RequestInit = {
|
|
|
53
53
|
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
54
54
|
path: string;
|
|
55
55
|
body?: unknown;
|
|
56
|
+
/** Send these bytes as the body, unchanged, with the `content-type` given in `headers` (for binary routes). Wins over `body`. */
|
|
57
|
+
rawBody?: Uint8Array | ArrayBuffer | Blob | undefined;
|
|
56
58
|
/** Per-call bearer override (wins over config.apiKey). */
|
|
57
59
|
bearerToken?: string | undefined;
|
|
58
60
|
/** Per-call additional headers (merged with config.defaultHeaders + auth). */
|
|
@@ -109,7 +111,9 @@ export async function requestOnce<T>(
|
|
|
109
111
|
method: init.method,
|
|
110
112
|
headers,
|
|
111
113
|
};
|
|
112
|
-
if (init.
|
|
114
|
+
if (init.rawBody !== undefined) {
|
|
115
|
+
requestInit["body"] = init.rawBody;
|
|
116
|
+
} else if (init.body !== undefined) {
|
|
113
117
|
if (typeof FormData !== "undefined" && init.body instanceof FormData) {
|
|
114
118
|
// Multipart: the runtime sets the content type (with its boundary); never JSON-encode it.
|
|
115
119
|
requestInit["body"] = init.body;
|