@astralbeam/sdk 0.10.1 → 0.11.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.
@@ -1,7 +1,31 @@
1
- import { E as resolveApiUrl, T as isAstralBeamApiError, i as getChatConfig, m as getRunChatUrl, w as astralBeamChatFetch } from "./api-CaNIR6Af.js";
1
+ import { D as isAstralBeamApiError, E as astralBeamChatFetch, O as resolveApiUrl, c as getCurrentUser, g as getRunChatUrl, i as getChatConfig } from "./api-DrKgAIBT.js";
2
+ import { d as JWTInvalid, h as strictDecoder, r as isObject, s as decode } from "./type_checks-C-WTHaWs.js";
2
3
  //#region \0rolldown/runtime.js
3
4
  var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
4
5
  //#endregion
6
+ //#region node_modules/.deno/jose@6.2.9/node_modules/jose/dist/webapi/util/decode_jwt.js
7
+ function decodeJwt(jwt) {
8
+ if (typeof jwt !== "string") throw new JWTInvalid("JWTs must use Compact JWS serialization, JWT must be a string");
9
+ const { 1: payload, length } = jwt.split(".");
10
+ if (length === 5) throw new JWTInvalid("Only JWTs using Compact JWS serialization can be decoded");
11
+ if (length !== 3) throw new JWTInvalid("Invalid JWT");
12
+ if (!payload) throw new JWTInvalid("JWTs must contain a payload");
13
+ let decoded;
14
+ try {
15
+ decoded = decode(payload);
16
+ } catch {
17
+ throw new JWTInvalid("Failed to base64url decode the payload");
18
+ }
19
+ let result;
20
+ try {
21
+ result = JSON.parse(strictDecoder.decode(decoded));
22
+ } catch {
23
+ throw new JWTInvalid("Failed to parse the decoded payload as JSON");
24
+ }
25
+ if (!isObject(result)) throw new JWTInvalid("Invalid JWT Claims Set");
26
+ return result;
27
+ }
28
+ //#endregion
5
29
  //#region node_modules/.deno/@tanstack+ai-client@0.28.0/node_modules/@tanstack/ai-client/dist/esm/response-stream.js
6
30
  var UnsupportedResponseStreamError = class extends Error {
7
31
  missingFeature;
@@ -7828,29 +7852,24 @@ function buildHostTools(tools, debug) {
7828
7852
  //#region src/core/auth.ts
7829
7853
  const REFRESH_SKEW_MS = 6e4;
7830
7854
  const MAX_TOKEN_LENGTH = 16384;
7831
- function tokenExpiry(token) {
7855
+ function tokenTiming(token) {
7832
7856
  if (token.length > MAX_TOKEN_LENGTH) throw new Error("The chat auth token is too large");
7833
- const parts = token.split(".");
7834
- if (parts.length !== 3 || !parts[1]) throw new Error("The chat auth token is not a JWT");
7835
- const encoded = parts[1].replaceAll("-", "+").replaceAll("_", "/");
7836
- const padded = encoded.padEnd(Math.ceil(encoded.length / 4) * 4, "=");
7837
- let payload;
7838
- try {
7839
- payload = JSON.parse(atob(padded));
7840
- } catch {
7841
- throw new Error("The chat auth token has an invalid payload");
7842
- }
7843
- const exp = payload?.exp;
7857
+ const { exp, iat, user } = decodeJwt(token);
7844
7858
  if (!Number.isInteger(exp) || Number(exp) <= 0) throw new Error("The chat auth token has no valid expiry");
7845
- return Number(exp) * 1e3;
7846
- }
7847
- function bearerToken(headers) {
7848
- const authorization = headers.get("authorization");
7849
- return authorization?.startsWith("Bearer ") ? authorization.slice(7) : void 0;
7859
+ const expiresAt = Number(exp) * 1e3;
7860
+ const lifetime = iat === void 0 ? 3e5 : expiresAt - iat * 1e3;
7861
+ const margin = Math.min(REFRESH_SKEW_MS, lifetime * .2);
7862
+ const tenantAdmin = user?.admin === true;
7863
+ return {
7864
+ expiresAt,
7865
+ refreshAt: expiresAt - margin,
7866
+ tenantAdmin
7867
+ };
7850
7868
  }
7851
7869
  async function requestChatAuthToken(options, signal) {
7852
7870
  const { fetchAstralBeamToken, fetchClient } = options;
7853
7871
  if (typeof fetchAstralBeamToken === "function") return (await fetchAstralBeamToken())?.token;
7872
+ if (!fetchAstralBeamToken) throw new Error("Provide fetchAstralBeamToken.");
7854
7873
  const { url, ...init } = fetchAstralBeamToken;
7855
7874
  const headers = new Headers(init.headers);
7856
7875
  if (!headers.has("accept")) headers.set("accept", "application/json");
@@ -7862,43 +7881,120 @@ async function requestChatAuthToken(options, signal) {
7862
7881
  headers,
7863
7882
  signal: init.signal ? AbortSignal.any([signal, init.signal]) : signal
7864
7883
  });
7865
- if (!response.ok) throw new Error(`Authentication endpoint returned HTTP ${response.status}`);
7884
+ if (!response.ok) throw Object.assign(/* @__PURE__ */ new Error(`Authentication endpoint returned HTTP ${response.status}`), {
7885
+ status: response.status,
7886
+ headers: response.headers
7887
+ });
7866
7888
  return (await response.json())?.token;
7867
7889
  }
7890
+ const initialAuthenticationState = { status: "loading" };
7891
+ function createChatAuthentication(options) {
7892
+ return {
7893
+ ...options,
7894
+ fetchAstralBeamToken: options.fetchAstralBeamToken,
7895
+ session: {
7896
+ cached: void 0,
7897
+ refreshPromise: void 0,
7898
+ abortController: new AbortController(),
7899
+ state: initialAuthenticationState,
7900
+ listeners: /* @__PURE__ */ new Set()
7901
+ },
7902
+ fetchClient: globalThis.fetch.bind(globalThis),
7903
+ debug: void 0
7904
+ };
7905
+ }
7906
+ function authenticationState(options) {
7907
+ return options.session.state;
7908
+ }
7909
+ function subscribeAuthentication(options, listener) {
7910
+ const { listeners } = options.session;
7911
+ listeners.add(listener);
7912
+ return () => {
7913
+ listeners.delete(listener);
7914
+ };
7915
+ }
7916
+ function publishAuthentication(options, state) {
7917
+ options.session.state = state;
7918
+ for (const listener of options.session.listeners) listener();
7919
+ }
7920
+ function updateAuthentication(options, next) {
7921
+ if (options.apiUrl !== next.apiUrl) {
7922
+ disposeChatAuthentication(options);
7923
+ options.session.abortController = new AbortController();
7924
+ publishAuthentication(options, { status: "loading" });
7925
+ }
7926
+ options.apiUrl = next.apiUrl;
7927
+ options.fetchAstralBeamToken = next.fetchAstralBeamToken;
7928
+ }
7929
+ function authenticationIdentity(current, tenantAdmin) {
7930
+ return JSON.stringify([
7931
+ current.scope,
7932
+ current.organization.id,
7933
+ current.scope === "tenant" ? current.tenant.id : null,
7934
+ current.user.id,
7935
+ tenantAdmin !== void 0 ? current.scope === "tenant" ? tenantAdmin : current.user.role : null
7936
+ ]);
7937
+ }
7868
7938
  async function loadChatAuthToken(options) {
7869
- const { session, onStateChange, debug } = options;
7939
+ const { session, debug, apiUrl } = options;
7870
7940
  const { signal } = session.abortController;
7871
7941
  const source = typeof options.fetchAstralBeamToken === "function" ? "fetchAstralBeamToken" : "Authentication endpoint";
7872
7942
  try {
7873
- const token = await requestChatAuthToken(options, signal);
7874
- if (typeof token !== "string" || !token) throw new Error(`${source} did not return a token`);
7875
- const expiresAt = tokenExpiry(token);
7876
- if (expiresAt <= Date.now()) throw new Error(`${source} returned an expired token`);
7877
- session.cached = {
7878
- value: token,
7879
- expiresAt
7880
- };
7881
- onStateChange({ status: "ready" });
7882
- debug?.("auth", "chat authentication ready", { expiresAt: new Date(expiresAt) });
7883
- return token;
7884
- } catch (cause) {
7885
- const error = cause instanceof Error ? cause : /* @__PURE__ */ new Error("Chat authentication failed");
7886
- if (!signal.aborted) {
7887
- onStateChange({
7888
- status: "error",
7889
- error
7943
+ for (let attempt = 0; attempt < 2; attempt++) {
7944
+ const token = await requestChatAuthToken(options, signal);
7945
+ signal.throwIfAborted();
7946
+ if (typeof token !== "string" || !token) throw new Error(`${source} did not return a token`);
7947
+ const { expiresAt, refreshAt, tenantAdmin } = tokenTiming(token);
7948
+ if (expiresAt <= Date.now()) throw new Error(`${source} returned an expired token`);
7949
+ if (!Number.isFinite(refreshAt) || refreshAt <= Date.now() || expiresAt - Date.now() < 5e3) throw new Error(`${source} returned a token too close to expiry`);
7950
+ let currentUser;
7951
+ try {
7952
+ currentUser = await getCurrentUser({
7953
+ apiUrl,
7954
+ astralBeamToken: token,
7955
+ fetchClient: options.fetchClient,
7956
+ signal,
7957
+ cache: "no-store",
7958
+ credentials: "omit"
7959
+ });
7960
+ } catch (error) {
7961
+ if (!attempt && options.retryUnauthorized !== false && isAstralBeamApiError(error) && error.status === 401) continue;
7962
+ throw error;
7963
+ }
7964
+ signal.throwIfAborted();
7965
+ if (options.scope && options.scope !== currentUser.scope) throw new Error(`Expected ${options.scope} authentication`);
7966
+ session.cached = {
7967
+ value: token,
7968
+ expiresAt,
7969
+ refreshAt,
7970
+ synchronizedAt: Date.now(),
7971
+ tenantAdmin
7972
+ };
7973
+ publishAuthentication(options, {
7974
+ status: "ready",
7975
+ currentUser
7890
7976
  });
7891
- debug?.("error", `chat authentication failed: ${error.message}`);
7977
+ debug?.("auth", "authentication ready", { expiresAt: new Date(expiresAt) });
7978
+ return token;
7892
7979
  }
7980
+ throw new Error("Authentication failed");
7981
+ } catch (cause) {
7982
+ signal.throwIfAborted();
7983
+ const error = cause instanceof Error ? cause : /* @__PURE__ */ new Error("Authentication failed");
7984
+ session.cached = void 0;
7985
+ publishAuthentication(options, {
7986
+ status: "error",
7987
+ error
7988
+ });
7893
7989
  throw error;
7894
7990
  }
7895
7991
  }
7896
7992
  async function getValidChatAuthToken(options) {
7897
- const { session, force = false, onStateChange } = options;
7898
- const now = Date.now();
7899
- if (!force && session.cached && session.cached.expiresAt - now > REFRESH_SKEW_MS) return session.cached.value;
7993
+ const { session, force = false } = options;
7994
+ session.abortController.signal.throwIfAborted();
7900
7995
  if (session.refreshPromise) return await session.refreshPromise;
7901
- onStateChange({ status: "loading" });
7996
+ if (!force && session.cached && session.cached.refreshAt > Date.now()) return session.cached.value;
7997
+ if (!session.cached || session.cached.expiresAt <= Date.now()) publishAuthentication(options, { status: "loading" });
7902
7998
  const refresh = loadChatAuthToken(options);
7903
7999
  session.refreshPromise = refresh;
7904
8000
  try {
@@ -7907,6 +8003,15 @@ async function getValidChatAuthToken(options) {
7907
8003
  if (session.refreshPromise === refresh) session.refreshPromise = void 0;
7908
8004
  }
7909
8005
  }
8006
+ function refreshRejectedAuthentication(options, token) {
8007
+ const rejectedCurrentToken = !token || options.session.cached?.value === token;
8008
+ if (rejectedCurrentToken) options.session.cached = void 0;
8009
+ return getValidChatAuthToken({
8010
+ ...options,
8011
+ force: rejectedCurrentToken,
8012
+ retryUnauthorized: false
8013
+ });
8014
+ }
7910
8015
  async function initializeChatAuthentication(options) {
7911
8016
  if (options.session.abortController.signal.aborted) options.session.abortController = new AbortController();
7912
8017
  await getValidChatAuthToken(options);
@@ -7914,28 +8019,86 @@ async function initializeChatAuthentication(options) {
7914
8019
  function disposeChatAuthentication({ session }) {
7915
8020
  session.abortController.abort();
7916
8021
  session.refreshPromise = void 0;
8022
+ session.cached = void 0;
8023
+ session.state = initialAuthenticationState;
7917
8024
  }
7918
8025
  async function fetchAuthenticatedChat(options) {
7919
8026
  const { input, init, session, fetchClient, debug } = options;
8027
+ const previous = authenticationState(options);
7920
8028
  const response = await fetchClient(input, init);
7921
8029
  if (response.status !== 401 || session.abortController.signal.aborted) return response;
7922
- const usedToken = bearerToken(new Headers(init?.headers));
7923
- const rejectedCurrentToken = !usedToken || session.cached?.value === usedToken;
7924
- if (rejectedCurrentToken) session.cached = void 0;
7925
- debug?.("auth", "chat auth token was rejected; refreshing once");
7926
- const token = await getValidChatAuthToken({
7927
- ...options,
7928
- force: rejectedCurrentToken
7929
- });
7930
8030
  const headers = new Headers(init?.headers);
7931
- headers.set("authorization", `Bearer ${token}`);
8031
+ const authorization = headers.get("authorization");
8032
+ const usedToken = authorization?.startsWith("Bearer ") ? authorization.slice(7) : void 0;
8033
+ debug?.("auth", "chat auth token was rejected; refreshing once");
7932
8034
  await response.body?.cancel();
8035
+ const token = await refreshRejectedAuthentication(options, usedToken);
8036
+ const current = authenticationState(options);
8037
+ if (previous.status !== "ready" || current.status !== "ready" || authenticationIdentity(previous.currentUser) !== authenticationIdentity(current.currentUser)) throw new DOMException("Identity changed", "AbortError");
8038
+ init?.signal?.throwIfAborted();
8039
+ headers.set("authorization", `Bearer ${token}`);
7933
8040
  return await fetchClient(input, {
7934
8041
  ...init,
7935
8042
  headers
7936
8043
  });
7937
8044
  }
7938
8045
  //#endregion
8046
+ //#region src/core/auth-lifecycle.ts
8047
+ function startAuthentication(options) {
8048
+ let timer;
8049
+ const events = new AbortController();
8050
+ let retries = 0;
8051
+ const visible = () => typeof document === "undefined" || document.visibilityState !== "hidden" && globalThis.navigator?.onLine !== false;
8052
+ const refresh = () => {
8053
+ if (events.signal.aborted || !visible()) return;
8054
+ getValidChatAuthToken({
8055
+ ...options,
8056
+ force: true
8057
+ }).catch(() => {});
8058
+ };
8059
+ const schedule = () => {
8060
+ clearTimeout(timer);
8061
+ if (events.signal.aborted || typeof document === "undefined" || !visible()) return;
8062
+ const state = authenticationState(options);
8063
+ if (state.status === "ready") {
8064
+ retries = 0;
8065
+ timer = setTimeout(refresh, Math.max(1e3, options.session.cached.refreshAt - Date.now()));
8066
+ } else if (state.status === "error" && retries < 3) {
8067
+ const error = state.error;
8068
+ if (error.status !== void 0 && error.status !== 429 && error.status < 500) return;
8069
+ if (error.status === void 0 && !(error instanceof TypeError)) return;
8070
+ const retryAfter = error.headers?.get("retry-after");
8071
+ const delay = retryAfter ? /^\d+$/.test(retryAfter) ? Number(retryAfter) * 1e3 : Date.parse(retryAfter) - Date.now() : 0;
8072
+ timer = setTimeout(refresh, Math.max(1e3 * 2 ** retries++, Number.isFinite(delay) ? delay : 0));
8073
+ }
8074
+ };
8075
+ const foreground = () => {
8076
+ if (!visible()) {
8077
+ clearTimeout(timer);
8078
+ return;
8079
+ }
8080
+ const cached = options.session.cached;
8081
+ if (!cached || Date.now() - cached.synchronizedAt >= 6e4 || cached.refreshAt <= Date.now()) refresh();
8082
+ else schedule();
8083
+ };
8084
+ const unsubscribe = subscribeAuthentication(options, schedule);
8085
+ if (typeof document !== "undefined") {
8086
+ for (const event of [
8087
+ "focus",
8088
+ "online",
8089
+ "offline"
8090
+ ]) globalThis.addEventListener(event, foreground, { signal: events.signal });
8091
+ document.addEventListener("visibilitychange", foreground, { signal: events.signal });
8092
+ }
8093
+ initializeChatAuthentication(options).catch(() => {});
8094
+ schedule();
8095
+ return () => {
8096
+ events.abort();
8097
+ clearTimeout(timer);
8098
+ unsubscribe();
8099
+ };
8100
+ }
8101
+ //#endregion
7939
8102
  //#region src/core/messages.ts
7940
8103
  function isSettledToolCall(part) {
7941
8104
  return part.state === "complete" || part.state === "error" || part.output !== void 0;
@@ -8081,7 +8244,7 @@ function sameAgentTools(current, next) {
8081
8244
  * transcript state, with no markup. The drop-in widget is one consumer; a host that owns its
8082
8245
  * whole UI is another.
8083
8246
  */
8084
- function createAstralBeamChat(options) {
8247
+ function createAstralBeamChat(options, deferStart = false) {
8085
8248
  let live = { ...options };
8086
8249
  let debug = createDebugLogger(live.debug);
8087
8250
  const listeners = /* @__PURE__ */ new Set();
@@ -8105,26 +8268,31 @@ function createAstralBeamChat(options) {
8105
8268
  };
8106
8269
  for (const listener of listeners) listener();
8107
8270
  };
8108
- const authentication = {
8109
- fetchAstralBeamToken: live.fetchAstralBeamToken ?? { url: "/api/astralbeam/token" },
8110
- session: {
8111
- cached: void 0,
8112
- refreshPromise: void 0,
8113
- abortController: new AbortController()
8114
- },
8115
- onStateChange: (auth) => update({ auth }),
8116
- fetchClient: globalThis.fetch.bind(globalThis),
8117
- debug
8118
- };
8119
- initializeChatAuthentication(authentication).catch(() => void 0);
8271
+ const authentication = createChatAuthentication({
8272
+ apiUrl: live.apiUrl,
8273
+ scope: "tenant",
8274
+ fetchAstralBeamToken: live.fetchAstralBeamToken ?? { url: "/api/astralbeam/token" }
8275
+ });
8276
+ let stopAuthentication;
8277
+ let unsubscribeAuthentication;
8278
+ let identity;
8279
+ let started = false;
8120
8280
  let capabilitiesGeneration = 0;
8281
+ let capabilityIdentity;
8121
8282
  const resolveCapabilities = async () => {
8122
8283
  const generation = ++capabilitiesGeneration;
8123
8284
  try {
8124
8285
  const token = await getValidChatAuthToken(authentication);
8286
+ if (generation !== capabilitiesGeneration) return;
8125
8287
  const body = await getChatConfig(live.agentId ? { agentId: live.agentId } : {}, {
8126
- apiUrl: live.apiUrl,
8127
- astralBeamToken: token
8288
+ apiUrl: authentication.apiUrl,
8289
+ astralBeamToken: token,
8290
+ signal: authentication.session.abortController.signal,
8291
+ fetchClient: (input, init) => fetchAuthenticatedChat({
8292
+ ...authentication,
8293
+ input,
8294
+ init
8295
+ })
8128
8296
  });
8129
8297
  if (generation !== capabilitiesGeneration) return;
8130
8298
  const attachments = body.capabilities?.attachments !== false;
@@ -8134,7 +8302,6 @@ function createAstralBeamChat(options) {
8134
8302
  debug?.("error", "agent capabilities could not be resolved; keeping the defaults", error);
8135
8303
  }
8136
8304
  };
8137
- resolveCapabilities();
8138
8305
  const renderCleanups = /* @__PURE__ */ new Map();
8139
8306
  const disposeRenders = () => {
8140
8307
  for (const cleanup of renderCleanups.values()) cleanup();
@@ -8184,11 +8351,13 @@ function createAstralBeamChat(options) {
8184
8351
  ...live.agentId ? { agentId: live.agentId } : {},
8185
8352
  ...live.debug ? { debug: true } : {}
8186
8353
  });
8187
- const connection = fetchServerSentEvents(() => resolveApiUrl(getRunChatUrl(), live.apiUrl), async () => {
8354
+ const connection = fetchServerSentEvents(() => resolveApiUrl(getRunChatUrl(), authentication.apiUrl), async () => {
8355
+ const previousIdentity = identity;
8188
8356
  const token = await getValidChatAuthToken(authentication);
8357
+ if (previousIdentity !== void 0 && previousIdentity !== identity) throw new DOMException("Identity changed", "AbortError");
8189
8358
  return { fetchClient: (_input, init) => astralBeamChatFetch(getRunChatUrl(), {
8190
8359
  ...init,
8191
- apiUrl: live.apiUrl,
8360
+ apiUrl: authentication.apiUrl,
8192
8361
  astralBeamToken: token,
8193
8362
  fetchClient: (input, request) => fetchAuthenticatedChat({
8194
8363
  ...authentication,
@@ -8259,7 +8428,41 @@ function createAstralBeamChat(options) {
8259
8428
  }
8260
8429
  }
8261
8430
  };
8431
+ const observeAuthentication = () => {
8432
+ const auth = authenticationState(authentication);
8433
+ if (auth.status === "ready") {
8434
+ const nextIdentity = authenticationIdentity(auth.currentUser);
8435
+ if (identity !== void 0 && identity !== nextIdentity) {
8436
+ client.stop();
8437
+ client.clear();
8438
+ disposeRenders();
8439
+ update({
8440
+ messages: [],
8441
+ sandbox: {
8442
+ files: [],
8443
+ commands: []
8444
+ },
8445
+ sandboxStatus: void 0
8446
+ });
8447
+ }
8448
+ identity = nextIdentity;
8449
+ if (capabilityIdentity !== nextIdentity) {
8450
+ capabilityIdentity = nextIdentity;
8451
+ resolveCapabilities();
8452
+ }
8453
+ }
8454
+ update({ auth });
8455
+ };
8456
+ const start = () => {
8457
+ if (started) return;
8458
+ started = true;
8459
+ unsubscribeAuthentication = subscribeAuthentication(authentication, observeAuthentication);
8460
+ observeAuthentication();
8461
+ stopAuthentication = startAuthentication(authentication);
8462
+ };
8463
+ if (!deferStart) start();
8262
8464
  return {
8465
+ start,
8263
8466
  getState: () => state,
8264
8467
  subscribe: (listener) => {
8265
8468
  listeners.add(listener);
@@ -8273,13 +8476,16 @@ function createAstralBeamChat(options) {
8273
8476
  ...next
8274
8477
  };
8275
8478
  debug = createDebugLogger(live.debug);
8276
- authentication.fetchAstralBeamToken = live.fetchAstralBeamToken ?? { url: "/api/astralbeam/token" };
8479
+ updateAuthentication(authentication, {
8480
+ apiUrl: live.apiUrl,
8481
+ fetchAstralBeamToken: live.fetchAstralBeamToken ?? { url: "/api/astralbeam/token" }
8482
+ });
8277
8483
  authentication.debug = debug;
8278
8484
  client.updateOptions({
8279
8485
  tools: declareTools(),
8280
8486
  forwardedProps: forwardedProps()
8281
8487
  });
8282
- if (live.agentId !== agent || live.apiUrl !== apiUrl) resolveCapabilities();
8488
+ if (started && (live.agentId !== agent || live.apiUrl !== apiUrl)) resolveCapabilities();
8283
8489
  },
8284
8490
  sendMessage: (content) => {
8285
8491
  settleDanglingToolCalls();
@@ -8310,8 +8516,16 @@ function createAstralBeamChat(options) {
8310
8516
  },
8311
8517
  dispose: () => {
8312
8518
  disposeRenders();
8313
- client.dispose();
8519
+ client.stop();
8520
+ capabilitiesGeneration++;
8521
+ capabilityIdentity = void 0;
8522
+ stopAuthentication?.();
8523
+ unsubscribeAuthentication?.();
8314
8524
  disposeChatAuthentication(authentication);
8525
+ started = false;
8526
+ queueMicrotask(() => {
8527
+ if (!started) client.dispose();
8528
+ });
8315
8529
  listeners.clear();
8316
8530
  }
8317
8531
  };
package/dist/core.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { A as RenderWidgetInput, B as ToolDefinition, C as AstralBeamChatState, D as ChatAuthenticationState, E as createAstralBeamChat, F as SandboxStatus, I as InferParameters, L as JsonSchemaObject, M as SandboxArtifact, N as SandboxCommandRun, O as WidgetDeclaration, P as SandboxFileWrite, R as ParametersSchema, S as AstralBeamChatCoreOptions, T as WidgetRenderRequest, _ as hasPendingToolRun, a as SANDBOX_PUBLISH_ARTIFACT_TOOL, b as AgentToolInfo, c as SANDBOX_STATUS_EVENT, d as describeSandboxCommandRun, f as isSandboxTool, g as sandboxRefusal, h as readSandboxFileWrite, i as SANDBOX_LIST_FILES_TOOL, j as SandboxActivity, k as buildAgentTools, l as SANDBOX_WRITE_FILE_TOOL, m as readSandboxCommandRun, n as ASK_QUESTIONNAIRE_TOOL, o as SANDBOX_READ_FILE_TOOL, p as readSandboxArtifact, r as RENDER_WIDGET_TOOL, s as SANDBOX_RUN_COMMAND_TOOL, t as defineTool, u as collectSandboxActivity, v as isSettledToolCall, w as ChatStreamCallbacks, x as AstralBeamChatCore, y as lastPartInProgress, z as StandardSchemaV1 } from "./index-BQBdZKyB.js";
1
+ import { A as RenderWidgetInput, B as JsonSchemaObject, C as AstralBeamChatState, D as ChatAuthenticationState, E as createAstralBeamChat, F as SandboxStatus, H as StandardSchemaV1, M as SandboxArtifact, N as SandboxCommandRun, O as WidgetDeclaration, P as SandboxFileWrite, S as AstralBeamChatCoreOptions, T as WidgetRenderRequest, U as ToolDefinition, V as ParametersSchema, _ as hasPendingToolRun, a as SANDBOX_PUBLISH_ARTIFACT_TOOL, b as AgentToolInfo, c as SANDBOX_STATUS_EVENT, d as describeSandboxCommandRun, f as isSandboxTool, g as sandboxRefusal, h as readSandboxFileWrite, i as SANDBOX_LIST_FILES_TOOL, j as SandboxActivity, k as buildAgentTools, l as SANDBOX_WRITE_FILE_TOOL, m as readSandboxCommandRun, n as ASK_QUESTIONNAIRE_TOOL, o as SANDBOX_READ_FILE_TOOL, p as readSandboxArtifact, r as RENDER_WIDGET_TOOL, s as SANDBOX_RUN_COMMAND_TOOL, t as defineTool, u as collectSandboxActivity, v as isSettledToolCall, w as ChatStreamCallbacks, x as AstralBeamChatCore, y as lastPartInProgress, z as InferParameters } from "./index-C4uH8CV1.js";
2
2
  export { ASK_QUESTIONNAIRE_TOOL, type AgentToolInfo, type AstralBeamChatCore, type AstralBeamChatCoreOptions, type AstralBeamChatState, type ChatAuthenticationState, type ChatStreamCallbacks, type InferParameters, type JsonSchemaObject, type ParametersSchema, RENDER_WIDGET_TOOL, type RenderWidgetInput, SANDBOX_LIST_FILES_TOOL, SANDBOX_PUBLISH_ARTIFACT_TOOL, SANDBOX_READ_FILE_TOOL, SANDBOX_RUN_COMMAND_TOOL, SANDBOX_STATUS_EVENT, SANDBOX_WRITE_FILE_TOOL, type SandboxActivity, type SandboxArtifact, type SandboxCommandRun, type SandboxFileWrite, type SandboxStatus, type StandardSchemaV1, type ToolDefinition, type WidgetDeclaration, type WidgetRenderRequest, buildAgentTools, collectSandboxActivity, createAstralBeamChat, defineTool, describeSandboxCommandRun, hasPendingToolRun, isSandboxTool, isSettledToolCall, lastPartInProgress, readSandboxArtifact, readSandboxCommandRun, readSandboxFileWrite, sandboxRefusal };
package/dist/core.js CHANGED
@@ -1,2 +1,2 @@
1
- import { S as SANDBOX_WRITE_FILE_TOOL, _ as SANDBOX_LIST_FILES_TOOL, a as describeSandboxCommandRun, b as SANDBOX_RUN_COMMAND_TOOL, c as readSandboxCommandRun, d as hasPendingToolRun, f as isSettledToolCall, g as RENDER_WIDGET_TOOL, h as ASK_QUESTIONNAIRE_TOOL, i as collectSandboxActivity, l as readSandboxFileWrite, m as buildAgentTools, o as isSandboxTool, p as lastPartInProgress, r as createAstralBeamChat, s as readSandboxArtifact, t as defineTool, u as sandboxRefusal, v as SANDBOX_PUBLISH_ARTIFACT_TOOL, x as SANDBOX_STATUS_EVENT, y as SANDBOX_READ_FILE_TOOL } from "./core-Dr2IDA6j.js";
1
+ import { S as SANDBOX_WRITE_FILE_TOOL, _ as SANDBOX_LIST_FILES_TOOL, a as describeSandboxCommandRun, b as SANDBOX_RUN_COMMAND_TOOL, c as readSandboxCommandRun, d as hasPendingToolRun, f as isSettledToolCall, g as RENDER_WIDGET_TOOL, h as ASK_QUESTIONNAIRE_TOOL, i as collectSandboxActivity, l as readSandboxFileWrite, m as buildAgentTools, o as isSandboxTool, p as lastPartInProgress, r as createAstralBeamChat, s as readSandboxArtifact, t as defineTool, u as sandboxRefusal, v as SANDBOX_PUBLISH_ARTIFACT_TOOL, x as SANDBOX_STATUS_EVENT, y as SANDBOX_READ_FILE_TOOL } from "./core-xh4NLb1l.js";
2
2
  export { ASK_QUESTIONNAIRE_TOOL, RENDER_WIDGET_TOOL, SANDBOX_LIST_FILES_TOOL, SANDBOX_PUBLISH_ARTIFACT_TOOL, SANDBOX_READ_FILE_TOOL, SANDBOX_RUN_COMMAND_TOOL, SANDBOX_STATUS_EVENT, SANDBOX_WRITE_FILE_TOOL, buildAgentTools, collectSandboxActivity, createAstralBeamChat, defineTool, describeSandboxCommandRun, hasPendingToolRun, isSandboxTool, isSettledToolCall, lastPartInProgress, readSandboxArtifact, readSandboxCommandRun, readSandboxFileWrite, sandboxRefusal };
@@ -0,0 +1 @@
1
+ const e=e=>`background:${e};color:#fff;border-radius:3px;padding:1px 5px`,t=`${e(`#7c3aed`)};font-weight:600`,n={mount:`#7c3aed`,auth:`#be185d`,theme:`#8b5cf6`,send:`#2563eb`,run:`#0891b2`,stream:`#0e7490`,text:`#16a34a`,reasoning:`#64748b`,tool:`#d97706`,widget:`#db2777`,attachment:`#0d9488`,sandbox:`#0369a1`,questionnaire:`#9333ea`,status:`#475569`,error:`#dc2626`};function r(r){if(r)return(r,i,a)=>{console.log(`%cAstralBeam%c ${new Date().toISOString().slice(11,19)} %c${r}%c ${i}`,t,`color:#94a3b8;font-weight:400`,e(n[r]),``,...a===void 0?[]:[a])}}export{r as t};
@@ -0,0 +1 @@
1
+ export { };
@@ -1,3 +1,5 @@
1
+ import { f as CurrentUser } from "./api-CWgQSDaI.js";
2
+
1
3
  //#region node_modules/.deno/@standard-schema+spec@1.1.0/node_modules/@standard-schema/spec/dist/index.d.ts
2
4
  /** The Standard Typed interface. This is a base type extended by other specs. */
3
5
  interface StandardTypedV1<Input = unknown, Output = Input> {
@@ -3262,7 +3264,7 @@ interface StandardSchemaV1<Input = unknown, Output = Input> {
3262
3264
  * Input type `defineTool`/`defineWidget` derive from a `parameters` schema: a Standard Schema's
3263
3265
  * validated output, or untyped props for a plain JSON Schema, which nothing validates in the browser.
3264
3266
  */
3265
- type InferParameters<S extends ParametersSchema> = S extends StandardSchemaV1<any, infer O> ? O : Record<string, unknown>;
3267
+ type InferParameters<S extends ParametersSchema> = S extends StandardSchemaV1<unknown, infer O> ? O : Record<string, unknown>;
3266
3268
  /** A plain JSON Schema object, the same shape tool definitions use for their parameters. */
3267
3269
  interface JsonSchemaObject {
3268
3270
  type: "object";
@@ -3303,7 +3305,7 @@ interface ToolDefinition {
3303
3305
  * Runs in the host page with the agent-chosen input. The resolved value is returned
3304
3306
  * to the agent as the tool result; a thrown error is returned as a tool error.
3305
3307
  */
3306
- execute: (input: Record<string, unknown>) => unknown | Promise<unknown>;
3308
+ execute: (input: Record<string, unknown>) => unknown;
3307
3309
  }
3308
3310
  /**
3309
3311
  * Limits and accepted types for the composer's file attachments. Every field is optional;
@@ -3435,6 +3437,8 @@ interface MountAstralBeamChatOptions {
3435
3437
  colorScheme?: AstralBeamChatColorScheme | undefined;
3436
3438
  /** Custom values for the widget's theming CSS variables, per color scheme. */
3437
3439
  theme?: AstralBeamChatTheme | undefined;
3440
+ /** Trusted application CSS, scoped to this widget's shadow root. */
3441
+ customCss?: string | undefined;
3438
3442
  /**
3439
3443
  * Logs every SDK action to the browser console with UTC timestamps and full payloads,
3440
3444
  * and asks the endpoint (via the forwarded props) to log its side of the run too.
@@ -3710,6 +3714,7 @@ type ChatAuthenticationState = {
3710
3714
  status: "loading";
3711
3715
  } | {
3712
3716
  status: "ready";
3717
+ currentUser: CurrentUser;
3713
3718
  } | {
3714
3719
  status: "error";
3715
3720
  error: Error;
@@ -3771,6 +3776,8 @@ interface AstralBeamChatState {
3771
3776
  sandbox: SandboxActivity;
3772
3777
  }
3773
3778
  interface AstralBeamChatCore {
3779
+ /** Start browser side effects after a React commit. Vanilla sessions start automatically. */
3780
+ start: () => void;
3774
3781
  getState: () => AstralBeamChatState;
3775
3782
  /** Notifies on every state change; returns the unsubscribe. */
3776
3783
  subscribe: (listener: () => void) => () => void;
@@ -3799,7 +3806,7 @@ interface AstralBeamChatCore {
3799
3806
  * transcript state, with no markup. The drop-in widget is one consumer; a host that owns its
3800
3807
  * whole UI is another.
3801
3808
  */
3802
- declare function createAstralBeamChat(options: AstralBeamChatCoreOptions): AstralBeamChatCore;
3809
+ declare function createAstralBeamChat(options: AstralBeamChatCoreOptions, deferStart?: boolean): AstralBeamChatCore;
3803
3810
  //#endregion
3804
3811
  //#region src/core/messages.d.ts
3805
3812
  declare function isSettledToolCall(part: {
@@ -3852,9 +3859,9 @@ interface TypedToolDefinition<S extends ParametersSchema = JsonSchemaObject> {
3852
3859
  description: string;
3853
3860
  metadata?: Record<string, unknown> | undefined;
3854
3861
  parameters?: S;
3855
- execute: (input: InferParameters<S>) => unknown | Promise<unknown>;
3862
+ execute: (input: InferParameters<S>) => unknown;
3856
3863
  }
3857
3864
  /** Declares a host tool; a Standard Schema `parameters` types (and validates) `execute`'s input. */
3858
3865
  declare function defineTool<const S extends ParametersSchema = JsonSchemaObject>(tool: TypedToolDefinition<S>): ToolDefinition;
3859
3866
  //#endregion
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 };
3867
+ export { RenderWidgetInput as A, JsonSchemaObject as B, AstralBeamChatState as C, ChatAuthenticationState as D, createAstralBeamChat as E, SandboxStatus as F, StandardSchemaV1 as H, AstralBeamChatColorScheme as I, AstralBeamChatTheme as L, SandboxArtifact as M, SandboxCommandRun as N, WidgetDeclaration as O, SandboxFileWrite as P, AstralBeamTokenSource as R, AstralBeamChatCoreOptions as S, WidgetRenderRequest as T, ToolDefinition as U, ParametersSchema as V, 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, InferParameters as z };