@astralbeam/sdk 0.7.0 → 0.10.1
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 +45 -53
- package/dist/api-CaNIR6Af.js +296 -0
- package/dist/api.d.ts +333 -0
- package/dist/api.js +2 -0
- package/dist/client.d.ts +5 -5
- package/dist/client.js +1 -1
- package/dist/{core-BF1G1dLe.js → core-Dr2IDA6j.js} +33 -33
- package/dist/core.d.ts +1 -1
- package/dist/core.js +1 -1
- package/dist/debug-BSzSiibd.js +1 -0
- package/dist/{index-CudekMKM.d.ts → index-BQBdZKyB.d.ts} +5 -5
- package/dist/react.d.ts +3 -3
- package/dist/react.js +5 -4
- package/dist/server.d.ts +18 -4
- package/dist/server.js +24 -7
- package/dist/widget-B6YT3G1i.js +79 -0
- package/package.json +15 -4
- package/dist/debug-DyjRg3e0.js +0 -1
- package/dist/widget-PZ-6BF36.js +0 -79
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @astralbeam/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Embed an agent chat sidebar in your web app, or build your own UI with the headless core. The widget isolates its styles in a shadow root.
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
6
|
npm install @astralbeam/sdk
|
|
@@ -22,29 +22,29 @@ export function Sidebar() {
|
|
|
22
22
|
import { mountAstralBeamChat } from "@astralbeam/sdk/client"
|
|
23
23
|
|
|
24
24
|
const handle = mountAstralBeamChat(document.getElementById("sidebar"), {})
|
|
25
|
-
// handle.update({ colorScheme: "dark" })
|
|
25
|
+
// Update with handle.update({ colorScheme: "dark" }), then clean up with handle.unmount().
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
- The widget fills its container, so give it a parent with a definite height (`min-h-0` in a flex column).
|
|
29
|
-
-
|
|
30
|
-
- `@astralbeam/sdk/client` ships no React
|
|
31
|
-
- No runtime dependencies
|
|
29
|
+
- Chat uses the hosted cloud by default. Tokens come from your application. For self-hosting, set `apiUrl` to your deployment’s `/api` base.
|
|
30
|
+
- `@astralbeam/sdk/client` ships no React. The chat loads as a lazy chunk with its own bundled copy.
|
|
31
|
+
- No runtime dependencies. `react` and `react-dom` are optional peers used only by `@astralbeam/sdk/react`.
|
|
32
32
|
- Mount it above your router if the transcript should survive page navigation.
|
|
33
33
|
|
|
34
34
|
## Authentication
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
Your server must authenticate the host session and mint a chat token before the widget can chat. Keep the API key server-only. See [Authentication](https://app.astralbeam.ai/docs/sdk/authentication).
|
|
37
37
|
|
|
38
38
|
```ts
|
|
39
|
-
import {
|
|
39
|
+
import { createAstralBeamToken } from "@astralbeam/sdk/server"
|
|
40
40
|
|
|
41
|
-
const apiKey = process.env.ASTRALBEAM_API_KEY // key_<
|
|
41
|
+
const apiKey = process.env.ASTRALBEAM_API_KEY // key_<organizationId>_<id>_abo_<secret>
|
|
42
42
|
|
|
43
43
|
export async function POST(request: Request) {
|
|
44
44
|
if (!apiKey) return Response.json({ error: "Not configured" }, { status: 503 })
|
|
45
45
|
const session = await getApplicationSession(request)
|
|
46
46
|
if (!session) return Response.json({ error: "Unauthenticated" }, { status: 401 })
|
|
47
|
-
const token = await
|
|
47
|
+
const token = await createAstralBeamToken({
|
|
48
48
|
apiKey,
|
|
49
49
|
user: {
|
|
50
50
|
id: session.user.id,
|
|
@@ -61,36 +61,28 @@ export async function POST(request: Request) {
|
|
|
61
61
|
}
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
- Provide stable tenant-local `user.id` and stable `tenant.id` values; names are optional, and set `user.admin` only from trusted state.
|
|
69
|
-
- Put custom tenant and tenant-user fields in their respective `metadata` JSON objects; never include secrets.
|
|
70
|
-
- SDK fields use camelCase; AstralBeam-owned JWT claims use snake_case, while `metadata` keys are preserved verbatim.
|
|
71
|
-
- Tokens use the API key's organization slug as issuer and the platform audience `astralbeam`; AstralBeam does not require or interpret `sub`.
|
|
72
|
-
- Tokens are signed, not encrypted: never put a secret in them.
|
|
73
|
-
- Lifetimes are 60–600 seconds; the SDK renews in memory before expiry.
|
|
74
|
-
- `fetchChatAuthToken` says where the chat auth token comes from: `{ url, ...init }`, which the widget calls as `fetch(url, init)` with a standard `RequestInit`, or a function returning `{ token }` (or a promise of it, or `undefined` when it cannot mint one).
|
|
75
|
-
- It defaults to `{ url: "/api/astralbeam/token" }`, posted with the page's cookies, and runs again on every renewal, so a rotating credential stays current.
|
|
64
|
+
- Authenticate once and derive stable `user.id` and `tenant.id` values from that trusted session.
|
|
65
|
+
- Keep API keys server-only. Tokens are signed, not encrypted, so their claims must contain no secrets.
|
|
66
|
+
- Return `Cache-Control: no-store` and fail closed when configuration or authentication is missing.
|
|
67
|
+
- For employee-facing Tenant management, use `createAstralBeamOrganizationToken`. The [API client guide](https://app.astralbeam.ai/docs/sdk/api) covers database-backed roles and browser integration.
|
|
76
68
|
|
|
77
69
|
## Options
|
|
78
70
|
|
|
79
|
-
Every option is also a prop on `<AstralBeamChat
|
|
80
|
-
|
|
81
|
-
| Option | Default | Meaning
|
|
82
|
-
| ------------------------------------ | ---------------------------------- |
|
|
83
|
-
| `agentId` | organization's default | `agent_<
|
|
84
|
-
| `apiUrl` | `https://app.astralbeam.ai/api` | Base URL of the AstralBeam API
|
|
85
|
-
| `
|
|
86
|
-
| `title`, `showHeader` | `"AstralBeam"`, `true` | Header text, and whether the header and reset button show
|
|
87
|
-
| `emptyTitle`, `emptyDescription` | generic copy | Headline and subtitle of the empty transcript
|
|
88
|
-
| `colorScheme`, `theme` | `"system"`, built-in palette | Light/dark/system, and shadcn token overrides
|
|
89
|
-
| `attachments` | `true` | `false` hides the feature, or pass limits
|
|
90
|
-
| `tools`, `widgets` | none | What the agent can do and draw in your app
|
|
91
|
-
| `sandboxPanel` | `false` | Collected sandbox panel: files with downloads, command log
|
|
92
|
-
| `header`, `empty`, `composerActions` | widget's own chrome | Host-rendered replacements (React props
|
|
93
|
-
| `debug` | `false` | Log
|
|
71
|
+
Every option is also a prop on `<AstralBeamChat>`. `handle.update(options)` applies any subset in place, and no option is fixed at mount. Details in [Configuration](https://app.astralbeam.ai/docs/sdk/configuration).
|
|
72
|
+
|
|
73
|
+
| Option | Default | Meaning |
|
|
74
|
+
| ------------------------------------ | ---------------------------------- | -------------------------------------------------------------------- |
|
|
75
|
+
| `agentId` | organization's default | `agent_<orgId>_<id>`, copied from the dashboard |
|
|
76
|
+
| `apiUrl` | `https://app.astralbeam.ai/api` | Base URL of the AstralBeam API. The widget calls `/v1/chat` there |
|
|
77
|
+
| `fetchAstralBeamToken` | `{ url: "/api/astralbeam/token" }` | Chat auth token endpoint as `{ url, ...RequestInit }`, or a minter |
|
|
78
|
+
| `title`, `showHeader` | `"AstralBeam"`, `true` | Header text, and whether the header and reset button show |
|
|
79
|
+
| `emptyTitle`, `emptyDescription` | generic copy | Headline and subtitle of the empty transcript |
|
|
80
|
+
| `colorScheme`, `theme` | `"system"`, built-in palette | Light/dark/system, and shadcn token overrides |
|
|
81
|
+
| `attachments` | `true` | `false` hides the feature, or pass limits |
|
|
82
|
+
| `tools`, `widgets` | none | What the agent can do and draw in your app |
|
|
83
|
+
| `sandboxPanel` | `false` | Collected sandbox panel: files with downloads, command log |
|
|
84
|
+
| `header`, `empty`, `composerActions` | widget's own chrome | Host-rendered replacements (React props. `slots` on the handle) |
|
|
85
|
+
| `debug` | `false` | Log SDK actions in the browser, with server logs in development only |
|
|
94
86
|
|
|
95
87
|
A `ref` on `<AstralBeamChat>` (and the vanilla handle) exposes `reset()` and `stop()` for hosts that draw their own controls.
|
|
96
88
|
|
|
@@ -117,24 +109,23 @@ widgets: {
|
|
|
117
109
|
```
|
|
118
110
|
|
|
119
111
|
- Schemas are plain JSON Schema, or any [Standard Schema](https://standardschema.dev) validator (Zod, Valibot, ArkType).
|
|
120
|
-
- Only a Standard Schema validates input in the browser
|
|
121
|
-
- `defineTool` and `defineWidget` type `execute`/`render` input from a Standard Schema's output.
|
|
122
|
-
- In React, `render` returns JSX in your own tree, so state, context, and handlers keep working.
|
|
123
|
-
- New tools and widgets reach the agent on its next run.
|
|
112
|
+
- Only a Standard Schema validates input in the browser. With plain JSON Schema, treat input as untrusted.
|
|
124
113
|
|
|
125
114
|
## Documentation
|
|
126
115
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
116
|
+
| Guide | Covers |
|
|
117
|
+
| ------------------------------------------------------------------------- | ------------------------------------------------------- |
|
|
118
|
+
| [API client](https://app.astralbeam.ai/docs/sdk/api) | Typed resource and chat requests with API keys or JWTs. |
|
|
119
|
+
| [Getting started](https://app.astralbeam.ai/docs/sdk/getting-started) | install, mount, layout requirements. |
|
|
120
|
+
| [Authentication](https://app.astralbeam.ai/docs/sdk/authentication) | the token endpoint and its security rules. |
|
|
121
|
+
| [Configuration](https://app.astralbeam.ai/docs/sdk/configuration) | every option, and what `update` can change. |
|
|
122
|
+
| [Theming](https://app.astralbeam.ai/docs/sdk/theming) | color schemes, CSS tokens, the shadow-root boundary. |
|
|
123
|
+
| [Tools and widgets](https://app.astralbeam.ai/docs/sdk/tools-and-widgets) | schemas, live state, rendering into the transcript. |
|
|
124
|
+
| [Attachments](https://app.astralbeam.ai/docs/sdk/attachments) | file kinds, limits, what the endpoint enforces. |
|
|
125
|
+
| [Limits](https://app.astralbeam.ai/docs/sdk/limits) | request, attachment, and sandbox limits. |
|
|
126
|
+
| [Sandbox](https://app.astralbeam.ai/docs/sdk/sandbox) | steps, the opt-in panel, downloads, inline images. |
|
|
127
|
+
| [Headless](https://app.astralbeam.ai/docs/sdk/headless) | own the whole chat UI on the same session. |
|
|
128
|
+
| [Security model](https://app.astralbeam.ai/docs/sdk/security) | who grants, who enforces, what the client can change. |
|
|
138
129
|
|
|
139
130
|
## Entry points
|
|
140
131
|
|
|
@@ -145,9 +136,10 @@ There is no root export. Conversation history is not built yet.
|
|
|
145
136
|
| `@astralbeam/sdk/client` | `mountAstralBeamChat`, the vanilla loader | none |
|
|
146
137
|
| `@astralbeam/sdk/core` | `createAstralBeamChat`, the headless session | none |
|
|
147
138
|
| `@astralbeam/sdk/react` | `<AstralBeamChat>`, `useAstralBeamChat` | `react`, `react-dom` |
|
|
148
|
-
| `@astralbeam/sdk/server` |
|
|
139
|
+
| `@astralbeam/sdk/server` | Tenant and organization token minters | none |
|
|
140
|
+
| `@astralbeam/sdk/api` | Resource and chat HTTP helpers | none |
|
|
149
141
|
|
|
150
|
-
Types resolve under every TypeScript module resolution mode, including
|
|
142
|
+
Types resolve under every TypeScript module resolution mode, including classic `"moduleResolution": "node"`. Requires TypeScript 5.0 or later because declarations use `const` type parameters, which fail to parse on TypeScript 4.x.
|
|
151
143
|
|
|
152
144
|
## Example
|
|
153
145
|
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
//#region src/lib/constants.ts
|
|
2
|
+
/** Base URL of the AstralBeam API when the mount options give none; versioned routes hang off it. */
|
|
3
|
+
const DEFAULT_API_URL = "https://app.astralbeam.ai/api";
|
|
4
|
+
/** Host endpoint that mints chat JWTs when the mount options give none. */
|
|
5
|
+
const DEFAULT_CHAT_AUTH_TOKEN_URL = "/api/astralbeam/token";
|
|
6
|
+
/** Color scheme used when the mount options and the React prop give none. */
|
|
7
|
+
const DEFAULT_COLOR_SCHEME = "system";
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/api/api.ts
|
|
10
|
+
function isAstralBeamApiError(error) {
|
|
11
|
+
return error instanceof Error && error.name === "AstralBeamApiError" && "status" in error && typeof error.status === "number";
|
|
12
|
+
}
|
|
13
|
+
function resolveApiUrl(path, apiUrl = DEFAULT_API_URL) {
|
|
14
|
+
return `${apiUrl.replace(/\/+$/, "")}${path.replace(/^\/api(?=\/)/, "")}`;
|
|
15
|
+
}
|
|
16
|
+
function isApiErrorBody(value, status) {
|
|
17
|
+
if (!value || typeof value !== "object") return false;
|
|
18
|
+
const body = value;
|
|
19
|
+
return body.status === status && typeof body.type === "string" && typeof body.title === "string" && typeof body.detail === "string" && (body.issues === void 0 || Array.isArray(body.issues) && body.issues.every((issue) => issue && typeof issue.path === "string" && typeof issue.message === "string"));
|
|
20
|
+
}
|
|
21
|
+
async function apiResponse(path, options) {
|
|
22
|
+
const { apiUrl, apiKey, astralBeamToken, fetchClient = globalThis.fetch, ...init } = options;
|
|
23
|
+
const headers = new Headers();
|
|
24
|
+
const entries = init.headers instanceof Headers ? init.headers.entries() : Array.isArray(init.headers) ? init.headers : Object.entries(init.headers ?? {});
|
|
25
|
+
for (const [name, value] of entries) headers.set(name, value);
|
|
26
|
+
headers.delete("authorization");
|
|
27
|
+
headers.delete("x-api-key");
|
|
28
|
+
if (apiKey) headers.set("x-api-key", apiKey);
|
|
29
|
+
if (astralBeamToken) headers.set("authorization", `Bearer ${astralBeamToken}`);
|
|
30
|
+
const response = await fetchClient(resolveApiUrl(path, apiUrl), {
|
|
31
|
+
...init,
|
|
32
|
+
headers
|
|
33
|
+
});
|
|
34
|
+
if (response.ok) return response;
|
|
35
|
+
const value = await response.json().catch((error) => {
|
|
36
|
+
if (!(error instanceof SyntaxError)) throw error;
|
|
37
|
+
});
|
|
38
|
+
const body = isApiErrorBody(value, response.status) ? value : void 0;
|
|
39
|
+
throw Object.assign(new Error(body?.detail ?? `AstralBeam API returned HTTP ${response.status}`), {
|
|
40
|
+
name: "AstralBeamApiError",
|
|
41
|
+
status: response.status,
|
|
42
|
+
headers: response.headers,
|
|
43
|
+
body
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
async function astralBeamApiFetch(path, options) {
|
|
47
|
+
return await (await apiResponse(path, options)).json();
|
|
48
|
+
}
|
|
49
|
+
function astralBeamJwtFetch(path, options) {
|
|
50
|
+
return astralBeamApiFetch(path, options);
|
|
51
|
+
}
|
|
52
|
+
function astralBeamChatFetch(path, options) {
|
|
53
|
+
return apiResponse(path, options);
|
|
54
|
+
}
|
|
55
|
+
function astralBeamFileFetch(path, options = {}) {
|
|
56
|
+
return apiResponse(path, options);
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/api/generated/api.ts
|
|
60
|
+
/**
|
|
61
|
+
* Generated by Orval. Do not edit by hand.
|
|
62
|
+
*/
|
|
63
|
+
const ListUsersForTenantFilterAdmin = {
|
|
64
|
+
true: "true",
|
|
65
|
+
false: "false"
|
|
66
|
+
};
|
|
67
|
+
const getListTenantsUrl = (params) => {
|
|
68
|
+
const normalizedParams = new URLSearchParams();
|
|
69
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
70
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : String(value));
|
|
71
|
+
});
|
|
72
|
+
const stringifiedParams = normalizedParams.toString();
|
|
73
|
+
return stringifiedParams.length > 0 ? `/api/v1/tenants?${stringifiedParams}` : `/api/v1/tenants`;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* List Tenants in internal ID order. q searches name or external ID as a case-insensitive literal substring. filter[external_id] adds an exact match. Organization keys and organization-management JWTs see their organization; admin tenant JWTs see only their signed Tenant. Keep filters unchanged when reusing cursors. Live listing, not a snapshot.
|
|
77
|
+
* @summary List Tenants
|
|
78
|
+
*/
|
|
79
|
+
const listTenants = (params, options) => {
|
|
80
|
+
return astralBeamApiFetch(getListTenantsUrl(params), {
|
|
81
|
+
...options,
|
|
82
|
+
method: "GET"
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
const getCreateTenantUrl = () => {
|
|
86
|
+
return `/api/v1/tenants`;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Create a Tenant with an exact customer-provided external_id. Requires an organization API key or organization-management JWT with a current owner/developer role. An external_id already used in this organization returns 409; creation never upserts.
|
|
90
|
+
* @summary Create a Tenant
|
|
91
|
+
*/
|
|
92
|
+
const createTenant = (createTenantInput, options) => {
|
|
93
|
+
const getHeaders = (h) => {
|
|
94
|
+
if (!h) return {};
|
|
95
|
+
if (h instanceof Headers) return Object.fromEntries(h.entries());
|
|
96
|
+
if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
|
|
97
|
+
const headers = {};
|
|
98
|
+
for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
|
|
99
|
+
return headers;
|
|
100
|
+
};
|
|
101
|
+
return astralBeamApiFetch(getCreateTenantUrl(), {
|
|
102
|
+
...options,
|
|
103
|
+
method: "POST",
|
|
104
|
+
headers: {
|
|
105
|
+
"Content-Type": "application/json",
|
|
106
|
+
...getHeaders(options?.headers)
|
|
107
|
+
},
|
|
108
|
+
body: JSON.stringify(createTenantInput)
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
const getGetTenantUrl = (id) => {
|
|
112
|
+
return `/api/v1/tenants/${encodeURIComponent(String(id))}`;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Get a Tenant by internal UUID, not external_id.
|
|
116
|
+
* @summary Get a Tenant
|
|
117
|
+
*/
|
|
118
|
+
const getTenant = (id, options) => {
|
|
119
|
+
return astralBeamApiFetch(getGetTenantUrl(id), {
|
|
120
|
+
...options,
|
|
121
|
+
method: "GET"
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
const getUpdateTenantUrl = (id) => {
|
|
125
|
+
return `/api/v1/tenants/${encodeURIComponent(String(id))}`;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Update supplied name/metadata fields only. Requires an organization API key or organization-management JWT with a current owner/developer role. name:null clears the name; metadata replaces the object. Last-write-wins; no upsert.
|
|
129
|
+
* @summary Update a Tenant
|
|
130
|
+
*/
|
|
131
|
+
const updateTenant = (id, updateTenantInput, options) => {
|
|
132
|
+
const getHeaders = (h) => {
|
|
133
|
+
if (!h) return {};
|
|
134
|
+
if (h instanceof Headers) return Object.fromEntries(h.entries());
|
|
135
|
+
if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
|
|
136
|
+
const headers = {};
|
|
137
|
+
for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
|
|
138
|
+
return headers;
|
|
139
|
+
};
|
|
140
|
+
return astralBeamApiFetch(getUpdateTenantUrl(id), {
|
|
141
|
+
...options,
|
|
142
|
+
method: "PATCH",
|
|
143
|
+
headers: {
|
|
144
|
+
"Content-Type": "application/json",
|
|
145
|
+
...getHeaders(options?.headers)
|
|
146
|
+
},
|
|
147
|
+
body: JSON.stringify(updateTenantInput)
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
const getListUsersForTenantUrl = (tenantId, params) => {
|
|
151
|
+
const normalizedParams = new URLSearchParams();
|
|
152
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
153
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : String(value));
|
|
154
|
+
});
|
|
155
|
+
const stringifiedParams = normalizedParams.toString();
|
|
156
|
+
return stringifiedParams.length > 0 ? `/api/v1/tenants/${encodeURIComponent(String(tenantId))}/tenant_users?${stringifiedParams}` : `/api/v1/tenants/${encodeURIComponent(String(tenantId))}/tenant_users`;
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* List users of one Tenant in internal ID order. q searches name or external ID as a case-insensitive literal substring. Exact filter[external_id] and filter[admin] combine with AND. No matching user returns an empty page; missing and out-of-scope Tenants return 404. Cursors cannot be reused for another Tenant or filter. Live listing, not a snapshot.
|
|
160
|
+
* @summary List TenantUsers
|
|
161
|
+
*/
|
|
162
|
+
const listUsersForTenant = (tenantId, params, options) => {
|
|
163
|
+
return astralBeamApiFetch(getListUsersForTenantUrl(tenantId, params), {
|
|
164
|
+
...options,
|
|
165
|
+
method: "GET"
|
|
166
|
+
});
|
|
167
|
+
};
|
|
168
|
+
const getCreateTenantUserUrl = (tenantId) => {
|
|
169
|
+
return `/api/v1/tenants/${encodeURIComponent(String(tenantId))}/tenant_users`;
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Create a TenantUser under the internal tenant_id path identifier, with a customer-provided tenant-local external_id. An external_id already used in this Tenant returns 409; the same external_id in another Tenant is allowed. Stored admin does not change signed JWT authority.
|
|
173
|
+
* @summary Create a TenantUser
|
|
174
|
+
*/
|
|
175
|
+
const createTenantUser = (tenantId, createTenantUserInput, options) => {
|
|
176
|
+
const getHeaders = (h) => {
|
|
177
|
+
if (!h) return {};
|
|
178
|
+
if (h instanceof Headers) return Object.fromEntries(h.entries());
|
|
179
|
+
if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
|
|
180
|
+
const headers = {};
|
|
181
|
+
for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
|
|
182
|
+
return headers;
|
|
183
|
+
};
|
|
184
|
+
return astralBeamApiFetch(getCreateTenantUserUrl(tenantId), {
|
|
185
|
+
...options,
|
|
186
|
+
method: "POST",
|
|
187
|
+
headers: {
|
|
188
|
+
"Content-Type": "application/json",
|
|
189
|
+
...getHeaders(options?.headers)
|
|
190
|
+
},
|
|
191
|
+
body: JSON.stringify(createTenantUserInput)
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
const getGetTenantUserUrl = (tenantId, id) => {
|
|
195
|
+
return `/api/v1/tenants/${encodeURIComponent(String(tenantId))}/tenant_users/${encodeURIComponent(String(id))}`;
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* Get a TenantUser by the internal tenant_id and id pair within the authorized scope. No identity upsert.
|
|
199
|
+
* @summary Get a TenantUser
|
|
200
|
+
*/
|
|
201
|
+
const getTenantUser = (tenantId, id, options) => {
|
|
202
|
+
return astralBeamApiFetch(getGetTenantUserUrl(tenantId, id), {
|
|
203
|
+
...options,
|
|
204
|
+
method: "GET"
|
|
205
|
+
});
|
|
206
|
+
};
|
|
207
|
+
const getUpdateTenantUserUrl = (tenantId, id) => {
|
|
208
|
+
return `/api/v1/tenants/${encodeURIComponent(String(tenantId))}/tenant_users/${encodeURIComponent(String(id))}`;
|
|
209
|
+
};
|
|
210
|
+
/**
|
|
211
|
+
* Update supplied name/metadata/admin fields only. Stored admin does not grant or revoke JWT authority. name:null clears the name; metadata replaces the object.
|
|
212
|
+
* @summary Update a TenantUser
|
|
213
|
+
*/
|
|
214
|
+
const updateTenantUser = (tenantId, id, updateTenantUserInput, options) => {
|
|
215
|
+
const getHeaders = (h) => {
|
|
216
|
+
if (!h) return {};
|
|
217
|
+
if (h instanceof Headers) return Object.fromEntries(h.entries());
|
|
218
|
+
if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
|
|
219
|
+
const headers = {};
|
|
220
|
+
for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
|
|
221
|
+
return headers;
|
|
222
|
+
};
|
|
223
|
+
return astralBeamApiFetch(getUpdateTenantUserUrl(tenantId, id), {
|
|
224
|
+
...options,
|
|
225
|
+
method: "PATCH",
|
|
226
|
+
headers: {
|
|
227
|
+
"Content-Type": "application/json",
|
|
228
|
+
...getHeaders(options?.headers)
|
|
229
|
+
},
|
|
230
|
+
body: JSON.stringify(updateTenantUserInput)
|
|
231
|
+
});
|
|
232
|
+
};
|
|
233
|
+
const getRunChatUrl = () => {
|
|
234
|
+
return `/api/v1/chat`;
|
|
235
|
+
};
|
|
236
|
+
/**
|
|
237
|
+
* Stream an AG-UI agent run using a tenant user JWT. No admin claim required. HTTP failures before streaming use AstralBeamApiError. Once streaming starts, failures use RUN_ERROR events. Tool results continue in a subsequent request. Disconnecting cancels the run. Limited to 20 requests per minute per organization, tenant, and user.
|
|
238
|
+
* @summary Run chat
|
|
239
|
+
*/
|
|
240
|
+
const runChat = (chatRunInput, options) => {
|
|
241
|
+
const getHeaders = (h) => {
|
|
242
|
+
if (!h) return {};
|
|
243
|
+
if (h instanceof Headers) return Object.fromEntries(h.entries());
|
|
244
|
+
if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
|
|
245
|
+
const headers = {};
|
|
246
|
+
for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
|
|
247
|
+
return headers;
|
|
248
|
+
};
|
|
249
|
+
return astralBeamChatFetch(getRunChatUrl(), {
|
|
250
|
+
...options,
|
|
251
|
+
method: "POST",
|
|
252
|
+
headers: {
|
|
253
|
+
"Content-Type": "application/json",
|
|
254
|
+
...getHeaders(options?.headers)
|
|
255
|
+
},
|
|
256
|
+
body: JSON.stringify(chatRunInput)
|
|
257
|
+
});
|
|
258
|
+
};
|
|
259
|
+
const getGetChatConfigUrl = (params) => {
|
|
260
|
+
const normalizedParams = new URLSearchParams();
|
|
261
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
262
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : String(value));
|
|
263
|
+
});
|
|
264
|
+
const stringifiedParams = normalizedParams.toString();
|
|
265
|
+
return stringifiedParams.length > 0 ? `/api/v1/chat/config?${stringifiedParams}` : `/api/v1/chat/config`;
|
|
266
|
+
};
|
|
267
|
+
/**
|
|
268
|
+
* Read the selected agent's attachment grant using a tenant user JWT. Omit agentId to use the organization's default agent. Client settings may narrow this grant, never widen it.
|
|
269
|
+
* @summary Get chat capabilities
|
|
270
|
+
*/
|
|
271
|
+
const getChatConfig = (params, options) => {
|
|
272
|
+
return astralBeamJwtFetch(getGetChatConfigUrl(params), {
|
|
273
|
+
...options,
|
|
274
|
+
method: "GET"
|
|
275
|
+
});
|
|
276
|
+
};
|
|
277
|
+
const getGetChatFileUrl = (params) => {
|
|
278
|
+
const normalizedParams = new URLSearchParams();
|
|
279
|
+
Object.entries(params || {}).forEach(([key, value]) => {
|
|
280
|
+
if (value !== void 0) normalizedParams.append(key, value === null ? "null" : String(value));
|
|
281
|
+
});
|
|
282
|
+
const stringifiedParams = normalizedParams.toString();
|
|
283
|
+
return stringifiedParams.length > 0 ? `/api/v1/chat/files?${stringifiedParams}` : `/api/v1/chat/files`;
|
|
284
|
+
};
|
|
285
|
+
/**
|
|
286
|
+
* Use the signed ticket returned when chat publishes an artifact. No bearer token is required. Returns the original bytes with a content-sniffed Content-Type and Content-Disposition filename. Invalid or expired tickets, a missing sandbox, and rejected artifact checks return 404. Provider or file-read failures return 500.
|
|
287
|
+
* @summary Download a chat artifact
|
|
288
|
+
*/
|
|
289
|
+
const getChatFile = (params, options) => {
|
|
290
|
+
return astralBeamFileFetch(getGetChatFileUrl(params), {
|
|
291
|
+
...options,
|
|
292
|
+
method: "GET"
|
|
293
|
+
});
|
|
294
|
+
};
|
|
295
|
+
//#endregion
|
|
296
|
+
export { updateTenantUser as C, DEFAULT_CHAT_AUTH_TOKEN_URL as D, resolveApiUrl as E, DEFAULT_COLOR_SCHEME as O, updateTenant as S, isAstralBeamApiError as T, getUpdateTenantUrl as _, getChatFile as a, listUsersForTenant as b, getGetChatConfigUrl as c, getGetTenantUserUrl as d, getListTenantsUrl as f, getTenantUser as g, getTenant as h, getChatConfig as i, getGetChatFileUrl as l, getRunChatUrl as m, createTenant as n, getCreateTenantUrl as o, getListUsersForTenantUrl as p, createTenantUser as r, getCreateTenantUserUrl as s, ListUsersForTenantFilterAdmin as t, getGetTenantUrl as u, getUpdateTenantUserUrl as v, astralBeamChatFetch as w, runChat as x, listTenants as y };
|