@adonis-agora/agent
Version:
Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.
86 lines • 5.25 kB
TypeScript
import type { StandardSchemaV1 } from '@standard-schema/spec';
import { type ReactNode } from 'react';
import { type StyleProp, type ViewStyle } from 'react-native';
import { type WebViewProps } from 'react-native-webview';
import type { UiAction } from '../../genui/actions.js';
import { type SandboxPolicy, type SandboxProps } from '../../genui/sandbox.js';
import type { JsonSchema } from '../../genui/schema.js';
import type { SandboxRefusal } from '../../react/core/genui/sandbox.js';
import type { GenuiRenderer } from '../../react/core/genui/types.js';
import { type FetchLike, type NativeSandboxConfigSource } from './sandbox-assets.js';
import { type NativeSandboxTheme } from './sandbox-host.js';
/** What a drawn component calls to hand an action back to the agent (the next user turn). */
export type GenuiActionHandler = (action: UiAction) => void;
export interface NativeSandboxRendererOptions {
/**
* The policy the frame runs under. Default: the one the catalog's definition carries (through the
* enclosing `GenuiProvider`'s catalog), else none — no network, the default limits.
*/
policy?: SandboxPolicy;
/** Checks the values of every `agent.send(…)` (a Zod object, any Standard Schema, or a JSON Schema). */
schema?: StandardSchemaV1 | JsonSchema;
/** Last word on an action before it is sent — e.g. an `Alert`. Falsy → dropped (`declined`). */
confirm?: (action: UiAction) => boolean | Promise<boolean>;
/** Where actions go. Default: the enclosing `GenuiActionProvider` / `GenuiProvider onAction`. */
onAction?: GenuiActionHandler;
/** Something the frame sent was refused — the same reasons as the web renderer's. */
onRefused?: (refusal: SandboxRefusal) => void;
/** An uncaught error in the generated code, or the view lost (it navigated, its process died). */
onError?: (message: string) => void;
/**
* The app's design tokens, as CSS custom properties on the frame's `:root` (the web renderer reads
* them off its page). An object, or a hook returning one — called while rendering, so it may use
* hooks (`() => useAppTheme()`); a change reaches a drawn view without reloading it. `false`: off.
*/
theme?: NativeSandboxTheme | false | (() => NativeSandboxTheme | null | undefined);
/**
* Tailwind and the kit: an object (assets inline or by url), a url answering `GET <agent>/config`,
* a loader, or `false`. Default: `GET <baseUrl>/config` with a `baseUrl`, else theme only.
*/
config?: NativeSandboxConfigSource;
/**
* The agent's absolute url (`https://api.example.com/agent`): where the config is fetched from by
* default, and what the relative urls it names resolve against.
*/
baseUrl?: string;
/** The `fetch` for the config and assets. Default: the global one. */
fetch?: FetchLike;
/** What to draw while nothing is drawable yet. Default: a box of `initialHeight` with the placeholder lines. */
placeholder?: (state: {
height: number;
messages: string[];
title?: string;
}) => ReactNode;
/** Extra style for the WebView (its height is the content's). */
style?: StyleProp<ViewStyle>;
}
/**
* The WebView props every sandbox gets. JavaScript runs inside it; it stores nothing (no DOM
* storage, incognito, no cache, no cookies), reads no file, opens no window, loads no mixed content,
* shows no link preview, does not scroll (the host sizes it to its content) and goes nowhere: every
* URL reaches `onShouldStartLoadWithRequest` (the whitelist lets them through — a URL it refuses
* would be handed to `Linking.openURL`), which allows only the inline document.
*/
export declare const NATIVE_SANDBOX_WEBVIEW_PROPS: Readonly<WebViewProps>;
/**
* A React Native renderer for the sandbox component (`Sandbox`): the model's HTML, CSS and JS in a
* hardened `react-native-webview` ({@link NATIVE_SANDBOX_WEBVIEW_PROPS}) — the same document as the
* web renderer's iframe (`buildSandboxDocument`, the same CSP: no network unless the policy lists an
* origin), sized to its content.
*
* It streams like the web one: a placeholder of `initialHeight`, a preview of the styled markup (no
* code runs), then the live view, whose code is posted in as it closes. The only bridge is the one
* the document carries: `ReactNativeWebView.postMessage` out (ready, resize, error, `agent.send`),
* `injectJavaScript` dispatching a `message` event in (render, run, theme, jsx). Everything the
* WebView says is checked as the web host checks it — length capped before parsing, the frame's
* token, size, interval and count limits, JSON only, `schema`, `confirm` — and an accepted
* `agent.send` is handed on as a `UiAction`.
*
* ```tsx
* <GenuiProvider registry={{ Sandbox: createNativeSandboxRenderer({ theme: () => useSandboxTheme() }) }} onAction={chat.sendUiAction}>
* ```
*/
export declare function createNativeSandboxRenderer(options?: NativeSandboxRendererOptions): GenuiRenderer<SandboxProps>;
/** The native sandbox renderer with its defaults (theme from nothing, no Tailwind, no kit). */
export declare const NativeSandboxView: GenuiRenderer<SandboxProps>;
//# sourceMappingURL=sandbox.d.ts.map