@astralbeam/sdk 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -29
- package/dist/client.d.ts +14 -9
- package/dist/client.js +1 -1
- package/dist/{core-BZxnUlwg.js → core-BF1G1dLe.js} +99 -47
- package/dist/core.d.ts +2 -2
- package/dist/core.js +2 -2
- package/dist/{index-8NUgB59m.d.ts → index-CudekMKM.d.ts} +148 -25
- package/dist/react.d.ts +11 -50
- package/dist/react.js +8 -15
- package/dist/server.d.ts +28 -43
- package/dist/server.js +53 -84
- package/dist/widget-PZ-6BF36.js +79 -0
- package/package.json +4 -18
- package/dist/vue.d.ts +0 -4
- package/dist/vue.js +0 -4
- package/dist/widget-DiGFLZyX.js +0 -79
|
@@ -3305,6 +3305,47 @@ interface ToolDefinition {
|
|
|
3305
3305
|
*/
|
|
3306
3306
|
execute: (input: Record<string, unknown>) => unknown | Promise<unknown>;
|
|
3307
3307
|
}
|
|
3308
|
+
/**
|
|
3309
|
+
* Limits and accepted types for the composer's file attachments. Every field is optional;
|
|
3310
|
+
* omitting the whole option leaves attachments enabled with the defaults below.
|
|
3311
|
+
*/
|
|
3312
|
+
interface AstralBeamChatAttachmentOptions {
|
|
3313
|
+
/** Hides the attach button (and ignores drops and pastes) when `false`. Default `true`. */
|
|
3314
|
+
enabled?: boolean | undefined;
|
|
3315
|
+
/** How many files one message may carry. Default `5`. */
|
|
3316
|
+
maxFiles?: number | undefined;
|
|
3317
|
+
/**
|
|
3318
|
+
* Ceiling for a single file, in bytes. The widget also applies its own per-kind caps
|
|
3319
|
+
* (5 MB image, 10 MB PDF, 1 MB text file), so the smaller of the two wins.
|
|
3320
|
+
*/
|
|
3321
|
+
maxFileBytes?: number | undefined;
|
|
3322
|
+
/** Ceiling for all files on one message, in bytes. Default 20 MB. */
|
|
3323
|
+
maxTotalBytes?: number | undefined;
|
|
3324
|
+
/**
|
|
3325
|
+
* Narrows what the composer takes, as MIME types or `type/*` patterns (`["image/*"]` for
|
|
3326
|
+
* images only). Omit to accept everything the chat endpoint supports: PNG, JPEG, WebP and
|
|
3327
|
+
* GIF images, PDFs, and text files (which the endpoint reads as text for the agent).
|
|
3328
|
+
*/
|
|
3329
|
+
accept?: readonly string[] | undefined;
|
|
3330
|
+
}
|
|
3331
|
+
/**
|
|
3332
|
+
* Draws host content into `container`, a light-DOM element the widget projects into the
|
|
3333
|
+
* named area. May return a cleanup, called when the slot is replaced and on unmount.
|
|
3334
|
+
*/
|
|
3335
|
+
type AstralBeamChatSlotRenderer = (container: HTMLElement) => (() => void) | void;
|
|
3336
|
+
/** Host-rendered replacements for the widget's own chrome; each renders in the host page's style. */
|
|
3337
|
+
interface AstralBeamChatSlots {
|
|
3338
|
+
/** Replaces the header's content (title and reset button); `showHeader: false` still hides the row. */
|
|
3339
|
+
header?: AstralBeamChatSlotRenderer | undefined;
|
|
3340
|
+
/** Replaces the empty-transcript state (icon, headline, and subtitle). */
|
|
3341
|
+
empty?: AstralBeamChatSlotRenderer | undefined;
|
|
3342
|
+
/** Extra controls at the end of the composer's button row, next to send. */
|
|
3343
|
+
composerActions?: AstralBeamChatSlotRenderer | undefined;
|
|
3344
|
+
}
|
|
3345
|
+
/** Color scheme of the chat widget; `"system"` follows the OS `prefers-color-scheme` setting. */
|
|
3346
|
+
type AstralBeamChatColorScheme = "light" | "dark" | "system";
|
|
3347
|
+
/** Overrides for the widget's theming CSS variables, keyed by custom-property name (`"--primary"`). */
|
|
3348
|
+
type AstralBeamChatThemeVariables = Record<`--${string}`, string>;
|
|
3308
3349
|
/**
|
|
3309
3350
|
* A token endpoint to call: `{ url, ...init }`, which the widget calls as `fetch(url, init)` with
|
|
3310
3351
|
* this object's remaining, standard `RequestInit` fields. The init defaults to `POST`,
|
|
@@ -3315,18 +3356,91 @@ interface AstralBeamChatAuthTokenRequest extends RequestInit {
|
|
|
3315
3356
|
url: string;
|
|
3316
3357
|
}
|
|
3317
3358
|
/**
|
|
3318
|
-
* Where the widget's short-lived chat
|
|
3359
|
+
* Where the widget's short-lived chat auth token comes from: an endpoint to POST, or a function that
|
|
3319
3360
|
* mints the token in the host page and returns `{ token }`, optionally as a promise.
|
|
3320
3361
|
*
|
|
3321
3362
|
* Either form runs again on every renewal — near expiry and after a token is rejected — so a
|
|
3322
3363
|
* rotating credential stays current rather than being captured once. A function that returns
|
|
3323
3364
|
* `undefined`, or throws, fails authentication closed; the composer's retry link asks again.
|
|
3324
3365
|
*/
|
|
3325
|
-
type
|
|
3366
|
+
type AstralBeamChatAuthTokenSource = AstralBeamChatAuthTokenRequest | (() => {
|
|
3326
3367
|
token: string;
|
|
3327
3368
|
} | undefined | Promise<{
|
|
3328
3369
|
token: string;
|
|
3329
3370
|
} | undefined>);
|
|
3371
|
+
/**
|
|
3372
|
+
* Custom values for the CSS variables the widget's shadcn theme exposes (`--background`,
|
|
3373
|
+
* `--primary`, `--radius`, and the `--font-sans`/`--font-heading`/`--font-mono` stacks, ...),
|
|
3374
|
+
* mirroring shadcn's `:root`/`.dark` split: `light` is the base applied in both color schemes,
|
|
3375
|
+
* and `dark` overrides it when the resolved scheme is dark.
|
|
3376
|
+
*/
|
|
3377
|
+
interface AstralBeamChatTheme {
|
|
3378
|
+
light?: AstralBeamChatThemeVariables | undefined;
|
|
3379
|
+
dark?: AstralBeamChatThemeVariables | undefined;
|
|
3380
|
+
}
|
|
3381
|
+
/**
|
|
3382
|
+
* Every option of the drop-in chat widget, and the one documented source the React props and the
|
|
3383
|
+
* headless core options are derived from. Each is optional and accepts an explicit `undefined`, so
|
|
3384
|
+
* a host with `exactOptionalPropertyTypes` can pass a value it does not have yet.
|
|
3385
|
+
*/
|
|
3386
|
+
interface MountAstralBeamChatOptions {
|
|
3387
|
+
/**
|
|
3388
|
+
* Public ID of the organization-owned agent. Omit it to use the organization's default agent,
|
|
3389
|
+
* which the dashboard's agents page selects. A change answers the next run with the new agent
|
|
3390
|
+
* and keeps the transcript, which that agent then sees as history.
|
|
3391
|
+
*/
|
|
3392
|
+
agentId?: string | undefined;
|
|
3393
|
+
/** Name shown in the widget's header. Default `"AstralBeam"`. */
|
|
3394
|
+
title?: string | undefined;
|
|
3395
|
+
/**
|
|
3396
|
+
* Shows the widget's header, which carries the title and the reset button. `false` hides both
|
|
3397
|
+
* and gives the transcript the full height. Default `true`.
|
|
3398
|
+
*/
|
|
3399
|
+
showHeader?: boolean | undefined;
|
|
3400
|
+
/** Headline shown on the empty transcript. Default `"Ask the assistant"`. */
|
|
3401
|
+
emptyTitle?: string | undefined;
|
|
3402
|
+
/** Subtitle shown under the empty transcript's headline. Default describes the app's tools and widgets. */
|
|
3403
|
+
emptyDescription?: string | undefined;
|
|
3404
|
+
/**
|
|
3405
|
+
* Base URL of the AstralBeam API; the widget calls `/chat` and its subroutes under it. Read for
|
|
3406
|
+
* every request, so a change moves the next one. Default `"https://app.astralbeam.ai/api"`, the
|
|
3407
|
+
* hosted cloud; self-hosted deployments must set their own origin.
|
|
3408
|
+
*/
|
|
3409
|
+
apiUrl?: string | undefined;
|
|
3410
|
+
/**
|
|
3411
|
+
* Where the short-lived chat auth token comes from: `{ url, ...RequestInit }` for a token
|
|
3412
|
+
* endpoint, or a function that mints `{ token }` in the host page. Read for every token, so a
|
|
3413
|
+
* change applies to the next one, which is minted when the cached token nears expiry. Default
|
|
3414
|
+
* `{ url: "/api/astralbeam/token" }`, posted with the page's cookies.
|
|
3415
|
+
*/
|
|
3416
|
+
fetchChatAuthToken?: AstralBeamChatAuthTokenSource | undefined;
|
|
3417
|
+
/** Host-defined tools the agent can call, executed in the host page, keyed by tool name. */
|
|
3418
|
+
tools?: Record<string, ToolDefinition> | undefined;
|
|
3419
|
+
/** Host-defined widgets the agent can render inline in the conversation, keyed by identifier. */
|
|
3420
|
+
widgets?: Record<string, WidgetDefinition> | undefined;
|
|
3421
|
+
/** Host-rendered replacements for parts of the widget's chrome; see `AstralBeamChatSlots`. */
|
|
3422
|
+
slots?: AstralBeamChatSlots | undefined;
|
|
3423
|
+
/**
|
|
3424
|
+
* Shows the collected sandbox panel (every file the agent wrote, with downloads, and the full
|
|
3425
|
+
* command log) above the composer once the sandbox has done work. Off by default: the
|
|
3426
|
+
* transcript already shows each step where it happened. Default `false`.
|
|
3427
|
+
*/
|
|
3428
|
+
sandboxPanel?: boolean | undefined;
|
|
3429
|
+
/**
|
|
3430
|
+
* File attachments in the composer, on by default. `false` turns them off; an options object
|
|
3431
|
+
* narrows the limits and accepted types.
|
|
3432
|
+
*/
|
|
3433
|
+
attachments?: boolean | AstralBeamChatAttachmentOptions | undefined;
|
|
3434
|
+
/** Color scheme of the widget. Default `"system"`. */
|
|
3435
|
+
colorScheme?: AstralBeamChatColorScheme | undefined;
|
|
3436
|
+
/** Custom values for the widget's theming CSS variables, per color scheme. */
|
|
3437
|
+
theme?: AstralBeamChatTheme | undefined;
|
|
3438
|
+
/**
|
|
3439
|
+
* Logs every SDK action to the browser console with UTC timestamps and full payloads,
|
|
3440
|
+
* and asks the endpoint (via the forwarded props) to log its side of the run too.
|
|
3441
|
+
*/
|
|
3442
|
+
debug?: boolean | undefined;
|
|
3443
|
+
}
|
|
3330
3444
|
//#endregion
|
|
3331
3445
|
//#region src/lib/debug.d.ts
|
|
3332
3446
|
declare const CATEGORY_COLORS: {
|
|
@@ -3608,26 +3722,38 @@ interface WidgetRenderRequest {
|
|
|
3608
3722
|
props: Record<string, unknown>;
|
|
3609
3723
|
/** Keys the render: a repeat of the same call replaces its own render, not another's. */
|
|
3610
3724
|
toolCallId: string;
|
|
3611
|
-
}
|
|
3612
|
-
interface AstralBeamChatCoreOptions {
|
|
3613
|
-
/** Public ID of the organization-owned agent; omitted, the organization's default answers. */
|
|
3614
|
-
agentId?: string | undefined;
|
|
3615
|
-
/** Base URL of the AstralBeam API; `/chat` hangs off it. Default the hosted cloud. */
|
|
3616
|
-
apiUrl?: string | undefined;
|
|
3617
3725
|
/**
|
|
3618
|
-
*
|
|
3619
|
-
*
|
|
3620
|
-
* Default `{ url: "/api/astralbeam/token" }`.
|
|
3726
|
+
* Drops this session's copy of the render's cleanup, for a host that disposed the render itself;
|
|
3727
|
+
* without it the cleanup — and the DOM it captures — is held until the next reset.
|
|
3621
3728
|
*/
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3729
|
+
release: () => void;
|
|
3730
|
+
}
|
|
3731
|
+
/**
|
|
3732
|
+
* Mirrors of the underlying chat client's stream lifecycle, for a consumer that logs or traces the
|
|
3733
|
+
* raw run; the drop-in widget passes its debug console logger here.
|
|
3734
|
+
*/
|
|
3735
|
+
interface ChatStreamCallbacks {
|
|
3736
|
+
onChunk?: ((chunk: StreamChunk) => void) | undefined;
|
|
3737
|
+
onResponse?: ((response?: Response) => void) | undefined;
|
|
3738
|
+
onFinish?: ((message: UIMessage) => void) | undefined;
|
|
3739
|
+
onError?: ((error: Error) => void) | undefined;
|
|
3740
|
+
}
|
|
3741
|
+
/**
|
|
3742
|
+
* The transport and tool options of the drop-in widget, minus everything about its UI, plus this
|
|
3743
|
+
* session's own rendering hooks. The shared options are documented on `MountAstralBeamChatOptions`.
|
|
3744
|
+
*/
|
|
3745
|
+
interface AstralBeamChatCoreOptions extends Pick<MountAstralBeamChatOptions, "agentId" | "apiUrl" | "fetchChatAuthToken" | "tools" | "debug"> {
|
|
3746
|
+
/** Widgets declared to the agent, without a `render`; `onRenderWidget` is asked to draw them. */
|
|
3626
3747
|
widgets?: Record<string, WidgetDeclaration> | undefined;
|
|
3627
3748
|
/** Draws an agent-requested widget however the host wants; may return a cleanup. */
|
|
3628
3749
|
onRenderWidget?: ((request: WidgetRenderRequest) => (() => void) | void) | undefined;
|
|
3629
|
-
/**
|
|
3630
|
-
|
|
3750
|
+
/** Stream lifecycle callbacks, read per event so they follow an update. */
|
|
3751
|
+
streamCallbacks?: ChatStreamCallbacks | undefined;
|
|
3752
|
+
}
|
|
3753
|
+
/** One tool as declared to the agent: its name, and the `metadata.title` that labels it. */
|
|
3754
|
+
interface AgentToolInfo {
|
|
3755
|
+
name: string;
|
|
3756
|
+
title: string | undefined;
|
|
3631
3757
|
}
|
|
3632
3758
|
interface AstralBeamChatState {
|
|
3633
3759
|
messages: UIMessage[];
|
|
@@ -3639,6 +3765,8 @@ interface AstralBeamChatState {
|
|
|
3639
3765
|
capabilities: {
|
|
3640
3766
|
attachments: boolean;
|
|
3641
3767
|
};
|
|
3768
|
+
/** The tool set currently declared to the agent, in declaration order. */
|
|
3769
|
+
agentTools: readonly AgentToolInfo[];
|
|
3642
3770
|
sandboxStatus: SandboxStatus | undefined;
|
|
3643
3771
|
sandbox: SandboxActivity;
|
|
3644
3772
|
}
|
|
@@ -3657,6 +3785,8 @@ interface AstralBeamChatCore {
|
|
|
3657
3785
|
addToolResult: ChatClient["addToolResult"];
|
|
3658
3786
|
/** Stops the in-flight generation; the transcript keeps what already streamed. */
|
|
3659
3787
|
stop: () => void;
|
|
3788
|
+
/** Mints a fresh chat auth token, ignoring the cached one; for a retry after a failure. */
|
|
3789
|
+
retryAuthentication: () => void;
|
|
3660
3790
|
/** Re-runs the last exchange. */
|
|
3661
3791
|
reload: () => Promise<void>;
|
|
3662
3792
|
/** Clears the conversation and disposes live widget renders. */
|
|
@@ -3724,14 +3854,7 @@ interface TypedToolDefinition<S extends ParametersSchema = JsonSchemaObject> {
|
|
|
3724
3854
|
parameters?: S;
|
|
3725
3855
|
execute: (input: InferParameters<S>) => unknown | Promise<unknown>;
|
|
3726
3856
|
}
|
|
3727
|
-
interface TypedWidgetDefinition<S extends ParametersSchema = JsonSchemaObject> {
|
|
3728
|
-
description: string;
|
|
3729
|
-
parameters?: S;
|
|
3730
|
-
render: (props: InferParameters<S>, container: HTMLElement) => (() => void) | void;
|
|
3731
|
-
}
|
|
3732
3857
|
/** Declares a host tool; a Standard Schema `parameters` types (and validates) `execute`'s input. */
|
|
3733
3858
|
declare function defineTool<const S extends ParametersSchema = JsonSchemaObject>(tool: TypedToolDefinition<S>): ToolDefinition;
|
|
3734
|
-
/** Declares a host widget; a Standard Schema `parameters` types (and validates) `render`'s props. */
|
|
3735
|
-
declare function defineWidget<const S extends ParametersSchema = JsonSchemaObject>(widget: TypedWidgetDefinition<S>): WidgetDefinition;
|
|
3736
3859
|
//#endregion
|
|
3737
|
-
export {
|
|
3860
|
+
export { RenderWidgetInput as A, ToolDefinition as B, AstralBeamChatState as C, ChatAuthenticationState as D, createAstralBeamChat as E, SandboxStatus as F, InferParameters as I, JsonSchemaObject as L, SandboxArtifact as M, SandboxCommandRun as N, WidgetDeclaration as O, SandboxFileWrite as P, ParametersSchema as R, AstralBeamChatCoreOptions as S, WidgetRenderRequest as T, hasPendingToolRun as _, SANDBOX_PUBLISH_ARTIFACT_TOOL as a, AgentToolInfo as b, SANDBOX_STATUS_EVENT as c, describeSandboxCommandRun as d, isSandboxTool as f, sandboxRefusal as g, readSandboxFileWrite as h, SANDBOX_LIST_FILES_TOOL as i, SandboxActivity as j, buildAgentTools as k, SANDBOX_WRITE_FILE_TOOL as l, readSandboxCommandRun as m, ASK_QUESTIONNAIRE_TOOL as n, SANDBOX_READ_FILE_TOOL as o, readSandboxArtifact as p, RENDER_WIDGET_TOOL as r, SANDBOX_RUN_COMMAND_TOOL as s, defineTool as t, collectSandboxActivity as u, isSettledToolCall as v, ChatStreamCallbacks as w, AstralBeamChatCore as x, lastPartInProgress as y, StandardSchemaV1 as z };
|
package/dist/react.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as AstralBeamChatState, S as AstralBeamChatCoreOptions, x as AstralBeamChatCore } from "./index-
|
|
1
|
+
import { C as AstralBeamChatState, S as AstralBeamChatCoreOptions, x as AstralBeamChatCore } from "./index-CudekMKM.js";
|
|
2
2
|
import { ReactNode } from "react";
|
|
3
|
-
import { AstralBeamChatAttachmentOptions, AstralBeamChatAuthTokenRequest,
|
|
3
|
+
import { AstralBeamChatAttachmentOptions, AstralBeamChatAuthTokenRequest, AstralBeamChatAuthTokenSource, AstralBeamChatColorScheme, AstralBeamChatTheme, InferParameters, JsonSchemaObject, MountAstralBeamChatOptions, ParametersSchema, ToolDefinition, WidgetDefinition as WidgetDefinition$1, defineTool } from "@astralbeam/sdk/client";
|
|
4
4
|
|
|
5
5
|
//#region src/react/index.d.ts
|
|
6
6
|
interface WidgetDefinition extends Omit<WidgetDefinition$1, "render"> {
|
|
@@ -38,60 +38,21 @@ interface AstralBeamChatRef {
|
|
|
38
38
|
/** Stops the in-flight generation, if any; the transcript keeps what already streamed. */
|
|
39
39
|
stop: () => void;
|
|
40
40
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
title?: string;
|
|
50
|
-
/**
|
|
51
|
-
* Shows the widget's header with the title and the reset button; `false` hides both and gives
|
|
52
|
-
* the transcript the full height. Default `true`.
|
|
53
|
-
*/
|
|
54
|
-
showHeader?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Every mount option as a prop, with the DOM-rendering fields replaced by React ones: a widget
|
|
43
|
+
* renders JSX, and the chrome slots take nodes instead of renderers. The shared options are
|
|
44
|
+
* documented once, on `MountAstralBeamChatOptions`.
|
|
45
|
+
*/
|
|
46
|
+
interface AstralBeamChatProps extends Omit<MountAstralBeamChatOptions, "widgets" | "slots"> {
|
|
47
|
+
/** Host-defined widgets the agent can render inline in the conversation, keyed by identifier. */
|
|
48
|
+
widgets?: Record<string, WidgetDefinition> | undefined;
|
|
55
49
|
/** Replaces the header's content with the host's own React content; `showHeader` still applies. */
|
|
56
50
|
header?: ReactNode;
|
|
57
51
|
/** Replaces the empty-transcript state with the host's own React content. */
|
|
58
52
|
empty?: ReactNode;
|
|
59
53
|
/** Extra host controls at the end of the composer's button row, next to send. */
|
|
60
54
|
composerActions?: ReactNode;
|
|
61
|
-
/** Headline shown on the empty transcript. Default `"Ask the assistant"`. */
|
|
62
|
-
emptyTitle?: string;
|
|
63
|
-
/** Subtitle under the empty transcript's headline. */
|
|
64
|
-
emptyDescription?: string;
|
|
65
|
-
/**
|
|
66
|
-
* Base URL of the AstralBeam API; the widget calls `/chat` under it. Read per request, so a
|
|
67
|
-
* change moves the next one. Default the hosted cloud.
|
|
68
|
-
*/
|
|
69
|
-
apiUrl?: string;
|
|
70
|
-
/**
|
|
71
|
-
* Where the short-lived chat JWT comes from: `{ url, ...RequestInit }` for a token endpoint, or
|
|
72
|
-
* a function minting `{ token }`, optionally a promise, in the host app. Read per token, and
|
|
73
|
-
* the function form runs in the host's React tree, so an inline closure over current auth state
|
|
74
|
-
* is fine and needs no memoization. Default `{ url: "/api/astralbeam/token" }`.
|
|
75
|
-
*/
|
|
76
|
-
generateAuthToken?: AstralBeamChatGenerateAuthToken;
|
|
77
|
-
/** Host-defined tools the agent can call, executed in the host's React app, keyed by name. */
|
|
78
|
-
tools?: Record<string, ToolDefinition>;
|
|
79
|
-
/** Host-defined widgets the agent can render inline in the conversation, keyed by identifier. */
|
|
80
|
-
widgets?: Record<string, WidgetDefinition>;
|
|
81
|
-
/** Color scheme of the chat widget. Default `"system"`. */
|
|
82
|
-
colorScheme?: AstralBeamChatColorScheme;
|
|
83
|
-
/** Custom values for the widget's theming CSS variables, per color scheme. */
|
|
84
|
-
theme?: AstralBeamChatTheme | undefined;
|
|
85
|
-
/** File attachments in the composer, on by default; `false` turns them off. */
|
|
86
|
-
attachments?: boolean | AstralBeamChatAttachmentOptions;
|
|
87
|
-
/** Shows the collected sandbox panel (files with downloads, command log) above the composer. Default `false`. */
|
|
88
|
-
sandboxPanel?: boolean;
|
|
89
|
-
/**
|
|
90
|
-
* Logs every SDK action to the browser console with UTC timestamps and full payloads,
|
|
91
|
-
* and asks the endpoint to log its side of the run too.
|
|
92
|
-
*/
|
|
93
|
-
debug?: boolean;
|
|
94
55
|
}
|
|
95
56
|
declare const AstralBeamChat: import("react").ForwardRefExoticComponent<AstralBeamChatProps & import("react").RefAttributes<AstralBeamChatRef>>;
|
|
96
57
|
//#endregion
|
|
97
|
-
export { AstralBeamChat, type AstralBeamChatAttachmentOptions, type AstralBeamChatAuthTokenRequest, type
|
|
58
|
+
export { AstralBeamChat, type AstralBeamChatAttachmentOptions, type AstralBeamChatAuthTokenRequest, type AstralBeamChatAuthTokenSource, type AstralBeamChatColorScheme, type AstralBeamChatCore, type AstralBeamChatCoreOptions, AstralBeamChatProps, AstralBeamChatRef, type AstralBeamChatState, type AstralBeamChatTheme, type InferParameters, type ParametersSchema, type ToolDefinition, TypedReactWidgetDefinition, UseAstralBeamChatResult, WidgetDefinition, defineTool, defineWidget, useAstralBeamChat };
|
package/dist/react.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as DEFAULT_COLOR_SCHEME, r as createAstralBeamChat } from "./core-
|
|
1
|
+
import { C as DEFAULT_COLOR_SCHEME, n as CORE_OPTION_KEYS, r as createAstralBeamChat } from "./core-BF1G1dLe.js";
|
|
2
2
|
import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
3
3
|
import { createPortal } from "react-dom";
|
|
4
4
|
import { defineTool, mountAstralBeamChat } from "@astralbeam/sdk/client";
|
|
@@ -15,19 +15,12 @@ function defineWidget(widget) {
|
|
|
15
15
|
* state stay live and nothing needs a remount.
|
|
16
16
|
*/
|
|
17
17
|
function useAstralBeamChat(options) {
|
|
18
|
-
const
|
|
18
|
+
const coreRef = useRef(null);
|
|
19
|
+
coreRef.current ??= createAstralBeamChat(options);
|
|
20
|
+
const core = coreRef.current;
|
|
19
21
|
useEffect(() => {
|
|
20
22
|
core.updateOptions(options);
|
|
21
|
-
}, [
|
|
22
|
-
core,
|
|
23
|
-
options.agentId,
|
|
24
|
-
options.apiUrl,
|
|
25
|
-
options.generateAuthToken,
|
|
26
|
-
options.tools,
|
|
27
|
-
options.widgets,
|
|
28
|
-
options.onRenderWidget,
|
|
29
|
-
options.debug
|
|
30
|
-
]);
|
|
23
|
+
}, [core, ...CORE_OPTION_KEYS.map((key) => options[key])]);
|
|
31
24
|
useEffect(() => () => core.dispose(), [core]);
|
|
32
25
|
return {
|
|
33
26
|
...useSyncExternalStore(core.subscribe, core.getState, core.getState),
|
|
@@ -39,7 +32,7 @@ function useAstralBeamChat(options) {
|
|
|
39
32
|
core
|
|
40
33
|
};
|
|
41
34
|
}
|
|
42
|
-
const AstralBeamChat = forwardRef(function AstralBeamChat({ agentId, title, showHeader, header, empty, composerActions, emptyTitle, emptyDescription, apiUrl,
|
|
35
|
+
const AstralBeamChat = forwardRef(function AstralBeamChat({ agentId, title, showHeader, header, empty, composerActions, emptyTitle, emptyDescription, apiUrl, fetchChatAuthToken, tools, widgets = {}, colorScheme = DEFAULT_COLOR_SCHEME, theme, attachments, sandboxPanel, debug }, ref) {
|
|
43
36
|
const targetRef = useRef(null);
|
|
44
37
|
const handleRef = useRef(null);
|
|
45
38
|
const [activeRenders, setActiveRenders] = useState(/* @__PURE__ */ new Map());
|
|
@@ -106,7 +99,7 @@ const AstralBeamChat = forwardRef(function AstralBeamChat({ agentId, title, show
|
|
|
106
99
|
const live = useMemo(() => ({
|
|
107
100
|
agentId,
|
|
108
101
|
apiUrl,
|
|
109
|
-
|
|
102
|
+
fetchChatAuthToken,
|
|
110
103
|
title,
|
|
111
104
|
showHeader,
|
|
112
105
|
emptyTitle,
|
|
@@ -122,7 +115,7 @@ const AstralBeamChat = forwardRef(function AstralBeamChat({ agentId, title, show
|
|
|
122
115
|
}), [
|
|
123
116
|
agentId,
|
|
124
117
|
apiUrl,
|
|
125
|
-
|
|
118
|
+
fetchChatAuthToken,
|
|
126
119
|
title,
|
|
127
120
|
showHeader,
|
|
128
121
|
emptyTitle,
|
package/dist/server.d.ts
CHANGED
|
@@ -1,57 +1,42 @@
|
|
|
1
|
-
import * as Schema from "effect/Schema";
|
|
2
|
-
|
|
3
1
|
//#region src/server/index.d.ts
|
|
4
|
-
declare const
|
|
5
|
-
declare const
|
|
6
|
-
declare const
|
|
7
|
-
declare const
|
|
8
|
-
declare const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
readonly
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
readonly
|
|
16
|
-
|
|
17
|
-
readonly admin: Schema.optional<Schema.Boolean>;
|
|
18
|
-
readonly metadata: Schema.optional<Schema.$Record<Schema.String, Schema.Codec<Schema.Json, Schema.Json, never, never>>>;
|
|
19
|
-
}>;
|
|
2
|
+
declare const CHAT_AUTH_TOKEN_AUDIENCE = "astralbeam";
|
|
3
|
+
declare const CHAT_AUTH_TOKEN_TYPE = "astralbeam+jwt";
|
|
4
|
+
declare const CHAT_AUTH_TOKEN_VERSION = 4;
|
|
5
|
+
declare const CHAT_AUTH_TOKEN_LIFETIME_SECONDS = 300;
|
|
6
|
+
declare const CHAT_AUTH_TOKEN_MAX_LIFETIME_SECONDS = 600;
|
|
7
|
+
/** A JSON value, which is all a `metadata` object may hold: the token carries it verbatim. */
|
|
8
|
+
type JsonValue = string | number | boolean | null | readonly JsonValue[] | {
|
|
9
|
+
readonly [key: string]: JsonValue;
|
|
10
|
+
};
|
|
11
|
+
/** A `metadata` object: caller-owned keys, preserved verbatim in the token's claims. */
|
|
12
|
+
type JsonMetadata = {
|
|
13
|
+
readonly [key: string]: JsonValue;
|
|
14
|
+
};
|
|
20
15
|
/** Tenant identity from the Organization's application, including JSON metadata. */
|
|
21
|
-
|
|
16
|
+
interface Tenant {
|
|
17
|
+
readonly id: string;
|
|
18
|
+
readonly name?: string | undefined;
|
|
19
|
+
readonly metadata?: JsonMetadata | undefined;
|
|
20
|
+
}
|
|
22
21
|
/** User of an Organization's Tenant who interacts with AstralBeam. */
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
interface TenantUser {
|
|
23
|
+
readonly id: string;
|
|
24
|
+
readonly name?: string | undefined;
|
|
25
|
+
readonly admin?: boolean | undefined;
|
|
26
|
+
readonly metadata?: JsonMetadata | undefined;
|
|
27
|
+
}
|
|
28
|
+
interface CreateChatAuthTokenOptions<TTenantUser extends TenantUser = TenantUser, TTenant extends Tenant = Tenant> {
|
|
25
29
|
readonly apiKey: string;
|
|
26
30
|
readonly user: TTenantUser;
|
|
27
31
|
readonly tenant: TTenant;
|
|
28
32
|
readonly expiresInSeconds?: number | undefined;
|
|
29
33
|
}
|
|
30
|
-
interface CreateAstralBeamTokenRouteOptions<TSession extends object = object, TTenantUser extends TenantUser = TenantUser, TTenant extends Tenant = Tenant> {
|
|
31
|
-
/** The full API key, or a thunk read per request; missing or empty answers 503. */
|
|
32
|
-
readonly apiKey: string | undefined | (() => string | undefined);
|
|
33
|
-
/**
|
|
34
|
-
* Authenticates the request against the application's own session. Returning nothing, or
|
|
35
|
-
* throwing, answers 401.
|
|
36
|
-
*/
|
|
37
|
-
readonly authenticate: (request: Request) => TSession | null | undefined | Promise<TSession | null | undefined>;
|
|
38
|
-
/** Maps the authenticated session to the tenant user minted into the token. */
|
|
39
|
-
readonly user: (session: TSession) => TTenantUser;
|
|
40
|
-
/** Maps the same authenticated session to the tenant minted into the token. */
|
|
41
|
-
readonly tenant: (session: TSession) => TTenant;
|
|
42
|
-
readonly expiresInSeconds?: number | undefined;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Builds the fetch-standard `POST` handler for an application's token endpoint, owning the
|
|
46
|
-
* method check, the unconfigured-key 503, the unauthenticated 401, and the `no-store` header.
|
|
47
|
-
*/
|
|
48
|
-
declare function createAstralBeamTokenRoute<TSession extends object, TTenantUser extends TenantUser = TenantUser, TTenant extends Tenant = Tenant>(options: CreateAstralBeamTokenRouteOptions<TSession, TTenantUser, TTenant>): (request: Request) => Promise<Response>;
|
|
49
34
|
/** Creates the short-lived bearer token returned by an application's server auth endpoint. */
|
|
50
|
-
declare function
|
|
35
|
+
declare function createChatAuthToken<TTenantUser extends TenantUser = TenantUser, TTenant extends Tenant = Tenant>({
|
|
51
36
|
apiKey,
|
|
52
37
|
user,
|
|
53
38
|
tenant,
|
|
54
39
|
expiresInSeconds
|
|
55
|
-
}:
|
|
40
|
+
}: CreateChatAuthTokenOptions<TTenantUser, TTenant>): Promise<string>;
|
|
56
41
|
//#endregion
|
|
57
|
-
export {
|
|
42
|
+
export { CHAT_AUTH_TOKEN_AUDIENCE, CHAT_AUTH_TOKEN_LIFETIME_SECONDS, CHAT_AUTH_TOKEN_MAX_LIFETIME_SECONDS, CHAT_AUTH_TOKEN_TYPE, CHAT_AUTH_TOKEN_VERSION, CreateChatAuthTokenOptions, JsonMetadata, JsonValue, Tenant, TenantUser, createChatAuthToken };
|
package/dist/server.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as Schema from "effect/Schema";
|
|
2
1
|
//#region node_modules/.deno/jose@6.2.9/node_modules/jose/dist/webapi/lib/buffer_utils.js
|
|
3
2
|
const encoder = new TextEncoder();
|
|
4
3
|
const decoder = new TextDecoder();
|
|
@@ -638,50 +637,29 @@ var SignJWT = class {
|
|
|
638
637
|
};
|
|
639
638
|
//#endregion
|
|
640
639
|
//#region src/server/index.ts
|
|
641
|
-
const
|
|
642
|
-
const
|
|
643
|
-
const
|
|
644
|
-
const
|
|
645
|
-
const
|
|
646
|
-
const
|
|
640
|
+
const CHAT_AUTH_TOKEN_AUDIENCE = "astralbeam";
|
|
641
|
+
const CHAT_AUTH_TOKEN_TYPE = "astralbeam+jwt";
|
|
642
|
+
const CHAT_AUTH_TOKEN_VERSION = 4;
|
|
643
|
+
const CHAT_AUTH_TOKEN_LIFETIME_SECONDS = 300;
|
|
644
|
+
const CHAT_AUTH_TOKEN_MAX_LIFETIME_SECONDS = 600;
|
|
645
|
+
const CHAT_AUTH_TOKEN_MAX_BYTES = 16384;
|
|
647
646
|
const IDENTITY_MAX_BYTES = 8192;
|
|
647
|
+
const EXTERNAL_ID_MAX_LENGTH = 255;
|
|
648
|
+
const API_KEY_PATTERN = /^key_[0-9a-z-]{1,63}_[0-9a-z-]{1,63}_abo_[A-Za-z]{64}$/;
|
|
649
|
+
const TENANT_FIELDS = [
|
|
650
|
+
"id",
|
|
651
|
+
"name",
|
|
652
|
+
"metadata"
|
|
653
|
+
];
|
|
654
|
+
const TENANT_USER_FIELDS = [
|
|
655
|
+
"id",
|
|
656
|
+
"name",
|
|
657
|
+
"admin",
|
|
658
|
+
"metadata"
|
|
659
|
+
];
|
|
648
660
|
const textEncoder = new TextEncoder();
|
|
649
|
-
const SlugSchema = Schema.String.pipe(Schema.check(Schema.isPattern(/^[0-9a-z-]{1,63}$/)));
|
|
650
|
-
const ApiKeySecretSchema = Schema.String.pipe(Schema.check(Schema.isPattern(/^abo_[A-Za-z]{64}$/)));
|
|
651
|
-
const ApiKeySchema = Schema.TemplateLiteral([
|
|
652
|
-
"key_",
|
|
653
|
-
SlugSchema,
|
|
654
|
-
"_",
|
|
655
|
-
SlugSchema,
|
|
656
|
-
"_",
|
|
657
|
-
ApiKeySecretSchema
|
|
658
|
-
]);
|
|
659
|
-
const isApiKey = Schema.is(ApiKeySchema);
|
|
660
|
-
const MetadataSchema = Schema.JsonObject.annotate({ message: "metadata must be a JSON object" });
|
|
661
|
-
const TenantExternalIdSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => value.length >= 1 && value.length <= 255, { message: "tenant.id must be a 1-255 character string" })));
|
|
662
|
-
const TenantUserExternalIdSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => value.length >= 1 && value.length <= 255, { message: "user.id must be a 1-255 character string" })));
|
|
663
|
-
const TenantSchema = Schema.Struct({
|
|
664
|
-
id: TenantExternalIdSchema,
|
|
665
|
-
name: Schema.optional(Schema.String),
|
|
666
|
-
metadata: Schema.optional(MetadataSchema)
|
|
667
|
-
});
|
|
668
|
-
const TenantUserSchema = Schema.Struct({
|
|
669
|
-
id: TenantUserExternalIdSchema,
|
|
670
|
-
name: Schema.optional(Schema.String),
|
|
671
|
-
admin: Schema.optional(Schema.Boolean),
|
|
672
|
-
metadata: Schema.optional(MetadataSchema)
|
|
673
|
-
});
|
|
674
|
-
const IdentitySchema = Schema.Struct({
|
|
675
|
-
user: TenantUserSchema,
|
|
676
|
-
tenant: TenantSchema
|
|
677
|
-
}).pipe(Schema.check(Schema.makeFilter((value) => textEncoder.encode(JSON.stringify(value)).byteLength <= IDENTITY_MAX_BYTES, { message: `user and tenant must not exceed ${IDENTITY_MAX_BYTES} bytes` })));
|
|
678
|
-
const decodeIdentity = Schema.decodeUnknownSync(IdentitySchema, {
|
|
679
|
-
errors: "all",
|
|
680
|
-
onExcessProperty: "error",
|
|
681
|
-
reportInput: false
|
|
682
|
-
});
|
|
683
661
|
function parseApiKey(apiKey) {
|
|
684
|
-
if (!
|
|
662
|
+
if (!API_KEY_PATTERN.test(apiKey)) throw new Error("apiKey must match key_<organization>_<key>_abo_<secret>");
|
|
685
663
|
const separator = apiKey.lastIndexOf("_abo_");
|
|
686
664
|
const keyId = apiKey.slice(0, separator);
|
|
687
665
|
const keySecret = apiKey.slice(separator + 1);
|
|
@@ -691,53 +669,44 @@ function parseApiKey(apiKey) {
|
|
|
691
669
|
keySecret
|
|
692
670
|
};
|
|
693
671
|
}
|
|
672
|
+
function isPlainObject(value) {
|
|
673
|
+
if (typeof value !== "object" || value === null) return false;
|
|
674
|
+
const prototype = Object.getPrototypeOf(value);
|
|
675
|
+
return prototype === Object.prototype || prototype === null;
|
|
676
|
+
}
|
|
677
|
+
function isJsonValue(value) {
|
|
678
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return true;
|
|
679
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
680
|
+
if (Array.isArray(value)) return value.every(isJsonValue);
|
|
681
|
+
return isPlainObject(value) && Object.values(value).every(isJsonValue);
|
|
682
|
+
}
|
|
683
|
+
function validateIdentity(label, value, isUser) {
|
|
684
|
+
if (!isPlainObject(value)) throw new Error(`${label} must be an object`);
|
|
685
|
+
const fields = isUser ? TENANT_USER_FIELDS : TENANT_FIELDS;
|
|
686
|
+
for (const key of Object.keys(value)) if (!fields.includes(key)) throw new Error(`${label} has an unknown field "${key}"`);
|
|
687
|
+
const { id, name, admin, metadata } = value;
|
|
688
|
+
if (typeof id !== "string" || id.length < 1 || id.length > EXTERNAL_ID_MAX_LENGTH) throw new Error(`${label}.id must be a 1-${EXTERNAL_ID_MAX_LENGTH} character string`);
|
|
689
|
+
if (name !== void 0 && typeof name !== "string") throw new Error(`${label}.name must be a string`);
|
|
690
|
+
if (isUser && admin !== void 0 && typeof admin !== "boolean") throw new Error(`${label}.admin must be a boolean`);
|
|
691
|
+
if (metadata !== void 0 && !(isPlainObject(metadata) && isJsonValue(metadata))) throw new Error(`${label}.metadata must be a JSON object`);
|
|
692
|
+
}
|
|
694
693
|
function validatedIdentity(user, tenant) {
|
|
695
|
-
|
|
694
|
+
validateIdentity("user", user, true);
|
|
695
|
+
validateIdentity("tenant", tenant, false);
|
|
696
|
+
const json = JSON.stringify({
|
|
696
697
|
user,
|
|
697
698
|
tenant
|
|
698
|
-
})
|
|
699
|
+
});
|
|
700
|
+
if (textEncoder.encode(json).byteLength > IDENTITY_MAX_BYTES) throw new Error(`user and tenant must not exceed ${IDENTITY_MAX_BYTES} bytes`);
|
|
701
|
+
return JSON.parse(json);
|
|
699
702
|
}
|
|
700
703
|
async function signingKey(secret) {
|
|
701
704
|
const digest = await crypto.subtle.digest("SHA-256", textEncoder.encode(secret));
|
|
702
705
|
return textEncoder.encode(encode(new Uint8Array(digest)));
|
|
703
706
|
}
|
|
704
|
-
function tokenRouteResponse(body, status) {
|
|
705
|
-
return Response.json(body, {
|
|
706
|
-
status,
|
|
707
|
-
headers: { "cache-control": "no-store" }
|
|
708
|
-
});
|
|
709
|
-
}
|
|
710
|
-
/**
|
|
711
|
-
* Builds the fetch-standard `POST` handler for an application's token endpoint, owning the
|
|
712
|
-
* method check, the unconfigured-key 503, the unauthenticated 401, and the `no-store` header.
|
|
713
|
-
*/
|
|
714
|
-
function createAstralBeamTokenRoute(options) {
|
|
715
|
-
return async (request) => {
|
|
716
|
-
if (request.method !== "POST") return tokenRouteResponse({ error: "Use POST" }, 405);
|
|
717
|
-
const apiKey = typeof options.apiKey === "function" ? options.apiKey() : options.apiKey;
|
|
718
|
-
if (!apiKey) return tokenRouteResponse({ error: "The AstralBeam API key is not configured" }, 503);
|
|
719
|
-
let session;
|
|
720
|
-
try {
|
|
721
|
-
session = await options.authenticate(request);
|
|
722
|
-
} catch {
|
|
723
|
-
session = void 0;
|
|
724
|
-
}
|
|
725
|
-
if (!session) return tokenRouteResponse({ error: "The session could not be verified" }, 401);
|
|
726
|
-
try {
|
|
727
|
-
return tokenRouteResponse({ token: await createAstralBeamChatToken({
|
|
728
|
-
apiKey,
|
|
729
|
-
user: options.user(session),
|
|
730
|
-
tenant: options.tenant(session),
|
|
731
|
-
...options.expiresInSeconds === void 0 ? {} : { expiresInSeconds: options.expiresInSeconds }
|
|
732
|
-
}) }, 200);
|
|
733
|
-
} catch {
|
|
734
|
-
return tokenRouteResponse({ error: "The chat token could not be created" }, 500);
|
|
735
|
-
}
|
|
736
|
-
};
|
|
737
|
-
}
|
|
738
707
|
/** Creates the short-lived bearer token returned by an application's server auth endpoint. */
|
|
739
|
-
async function
|
|
740
|
-
if (!Number.isInteger(expiresInSeconds) || expiresInSeconds < 60 || expiresInSeconds > 600) throw new Error("
|
|
708
|
+
async function createChatAuthToken({ apiKey, user, tenant, expiresInSeconds = 300 }) {
|
|
709
|
+
if (!Number.isInteger(expiresInSeconds) || expiresInSeconds < 60 || expiresInSeconds > 600) throw new Error("chat auth tokens must live for 60-600 seconds");
|
|
741
710
|
const { keyId, organizationSlug, keySecret } = parseApiKey(apiKey);
|
|
742
711
|
const identity = validatedIdentity(user, tenant);
|
|
743
712
|
const now = Math.floor(Date.now() / 1e3);
|
|
@@ -747,11 +716,11 @@ async function createAstralBeamChatToken({ apiKey, user, tenant, expiresInSecond
|
|
|
747
716
|
tenant: identity.tenant
|
|
748
717
|
}).setProtectedHeader({
|
|
749
718
|
alg: "HS256",
|
|
750
|
-
typ:
|
|
719
|
+
typ: CHAT_AUTH_TOKEN_TYPE,
|
|
751
720
|
kid: keyId
|
|
752
|
-
}).setIssuer(organizationSlug).setAudience(
|
|
753
|
-
if (textEncoder.encode(token).byteLength >
|
|
721
|
+
}).setIssuer(organizationSlug).setAudience(CHAT_AUTH_TOKEN_AUDIENCE).setIssuedAt(now).setExpirationTime(now + expiresInSeconds).sign(await signingKey(keySecret));
|
|
722
|
+
if (textEncoder.encode(token).byteLength > CHAT_AUTH_TOKEN_MAX_BYTES) throw new Error(`chat auth tokens must not exceed ${CHAT_AUTH_TOKEN_MAX_BYTES} bytes`);
|
|
754
723
|
return token;
|
|
755
724
|
}
|
|
756
725
|
//#endregion
|
|
757
|
-
export {
|
|
726
|
+
export { CHAT_AUTH_TOKEN_AUDIENCE, CHAT_AUTH_TOKEN_LIFETIME_SECONDS, CHAT_AUTH_TOKEN_MAX_LIFETIME_SECONDS, CHAT_AUTH_TOKEN_TYPE, CHAT_AUTH_TOKEN_VERSION, createChatAuthToken };
|