/** * `createSkaileApp` — the thin app SDK that makes an embedded app * agent-controllable. * * An app becomes a *capability peer*, mirroring how the runner behaves toward * the platform: * * 1. Opens an authenticated back-connection (via an {@link AppTransport}). * 2. Performs the app handshake — sends `app_hello`, awaits `app_hello_ack` * (binding the connection to `session + appId`) or `app_hello_nack` (refusal). * 3. Registers its `app.*` capabilities via `capability_register`, stamping * each with `origin:{kind:'app', appId}` and `side:'app'`. Register / * deregister mid-session is supported. * 4. Answers inbound `capability_invoked` events by running the local handler * and replying with `capability_result` (a thrown handler rides back as * `{ error }`). * * The approval round-trip for `requiresApproval` capabilities is handled * entirely platform-side: the gateway parks the invocation for user approval * and only forwards `capability_invoked` to the app *after* approval, so the * app just marks the capability and answers when asked. * * The peer reconnects and replays its registrations on a dropped socket, and on * a *retryable* refusal — the app boots independently of the session's agent * container and can win that race. See {@link ReconnectOptions}. * * @category App SDK * @since 3.4.0 */ import type { Capability } from "@skaile/workspaces/types"; import type { DefinedAppCapability } from "./define-app-capability.js"; import { type AppLogger } from "./logger.js"; import type { AppTransport } from "./transport.js"; /** Default timeout waiting for the gateway's `app_hello_ack`. */ export declare const DEFAULT_HELLO_TIMEOUT_MS = 10000; /** * Reconnect / retry policy. Set `reconnect: false` on {@link SkaileAppOptions} * to disable entirely (one attempt, no replay). * * @category App SDK * @since 3.5.0 */ export interface ReconnectOptions { /** Attempts before giving up. Default 5. */ maxAttempts?: number; /** First backoff delay in ms; doubles each attempt. Default 1000. */ baseMs?: number; /** Backoff ceiling in ms. Default 30000. */ maxMs?: number; } /** * The gateway refused the handshake. `retryable` mirrors the wire field: `true` * for a transient refusal (the agent container is not up yet), `false` for a * permanent one (bad token, `appId` not permitted). * * @category App SDK * @since 3.5.0 */ export declare class AppHandshakeRefusedError extends Error { readonly retryable: boolean; constructor(reason: string, retryable: boolean); } /** * Options for {@link createSkaileApp}. * * @category App SDK * @since 3.4.0 */ export interface SkaileAppOptions { /** The embedded app's stable id. Every registered capability is bound to it. */ appId: string; /** * The app back-connection. Inject {@link createWebSocketAppTransport} in * production or a fake in tests. The transport carries the injected session * identity as its connection credential. * * With `reconnect` enabled the transport must be able to produce a **fresh** * token per attempt — the gateway consumes it at `app_hello`. Pass a * `SessionTokenProvider` rather than a bare string. */ transport: AppTransport; /** Protocol version the SDK announces in `app_hello`. Defaults to the SDK's. */ protocolVersion?: string; /** Timeout waiting for `app_hello_ack`. Defaults to {@link DEFAULT_HELLO_TIMEOUT_MS}. */ helloTimeoutMs?: number; /** Logger for the SDK and (by default) capability handlers. Defaults to {@link noopLogger}. */ logger?: AppLogger; /** * Reconnect policy, or `false` to disable. Defaults to * `{maxAttempts:5, baseMs:1000, maxMs:30000}`. * * @since 3.5.0 */ reconnect?: ReconnectOptions | false; } /** Result of a successful handshake — the bound session context. */ export interface AppSession { sessionId: string; userId?: string; } /** * A connected (or connectable) Skaile app. Register capabilities before or * after {@link connect}; post-connect changes are pushed to the gateway * immediately. * * @category App SDK * @since 3.4.0 */ export interface SkaileApp { /** * Add (or replace, by name) an app capability. Registering the same name * again replaces it — mirrors the registry's replace-by-name semantics. When * already connected, a `capability_register` is sent immediately. */ registerCapability(cap: DefinedAppCapability): void; /** * Remove a capability by name. No-op when unknown. When connected, a * `capability_deregister` is sent immediately so the tool disappears from the * agent's catalog. */ deregisterCapability(name: string): void; /** Wire-format snapshot of the currently registered capabilities (origin stamped). */ readonly capabilities: readonly Capability[]; /** The bound session once connected; `null` before the handshake and while reconnecting. */ readonly session: AppSession | null; /** * Open the connection, perform the handshake, and register the current * capabilities. Resolves with the bound {@link AppSession}. Rejects if the * gateway refuses permanently, the handshake times out, or the transport * disconnects mid-handshake. A *retryable* refusal is retried per the * reconnect policy before rejecting. */ connect(): Promise; /** * Subscribe to session binding changes. Fires on **every** bind — including * the initial `connect()` — with the new {@link AppSession}, and with `null` * whenever the connection drops. Returns an unsubscribe function. * * @since 3.5.0 */ onSessionChange(handler: (session: AppSession | null) => void): () => void; /** Disconnect and tear down. Idempotent. Cancels any pending reconnect. */ close(): Promise; } /** * Create a {@link SkaileApp}. See the module doc for the peer lifecycle. * * @category App SDK * @since 3.4.0 */ export declare function createSkaileApp(options: SkaileAppOptions): SkaileApp; //# sourceMappingURL=app.d.ts.map