framework
Version:
The (AI) Framework: turnkey, zero-config AI orchestration that wraps a coding-agent CLI (Claude Code) as a black box and takes you from an idea to a running app. Vite for AI.
119 lines • 5.81 kB
TypeScript
import type { BridgeEvent, BridgeHello, BridgeQuestion } from './bridge-endpoints.js';
/**
* An answer picked in the dashboard, on its way back to the session (#1237).
*
* `queued` until the extension fetches it, delivers it into the composer and acknowledges;
* then `sent`, or `failed` with the extension's reason. The id is what the acknowledgement
* references, so a stale ack from a tab that died mid-delivery cannot resolve a newer answer.
*/
export interface BridgeAnswer {
id: string;
sessionId: string;
label: string;
queuedAt: string;
state: 'queued' | 'sent' | 'failed';
note?: string;
}
/**
* The questions a Claude web session is parked on, keyed by its cloud session id (#1237).
*
* A cloud agent has no live local session to hang a choice gate on: #1231 ends the agent at the
* hand-off, so by the time the agent asks anything the agent is already `done`. The join back to
* an agent is `AgentMeta.sessionId`, which a web agent already carries because `CloudSession` reports
* the cloud id on its result.
*
* In memory on purpose. A question is only answerable while the session that asked it is still
* parked, and the bridge that reported it re-reports on reconnect, so surviving a daemon restart
* would preserve a question that may already have been answered elsewhere.
*/
/** The last time anything spoke to the bridge, and how it went. */
export interface BridgeContact {
at: string;
route: string;
status: number;
}
/** The extension's last version claim, and whether the doorway turned it away (#1519). */
export interface BridgeVersion {
got: string;
expected: string;
blocked: boolean;
at: string;
}
export declare class BridgeQuestions {
private readonly bySession;
private contact;
/**
* Note that something reached the bridge, whatever the outcome.
*
* Failures are recorded too, and that is the point: an extension that is misconfigured looks
* exactly like one that is not installed, because both leave no question behind. A refused
* request at least proves something is trying.
*/
recordContact(route: string, status: number): void;
private versionState;
/**
* What version the extension last claimed and whether it was refused for it (#1519).
*
* The accepted claims are recorded too, which is what clears a blocked banner: the moment an
* updated extension gets through, the last word is no longer a refusal.
*/
recordVersion(got: string, expected: string, blocked: boolean): void;
/** The last version claim, or undefined while nothing has stated one. */
version(): BridgeVersion | undefined;
private helloState;
/** What the injected page script last said about itself. */
recordHello(hello: BridgeHello): void;
/** The page script's last report, or undefined if none has ever arrived. */
hello(): BridgeHello | undefined;
/** The last contact, or undefined if nothing has ever reached the bridge. */
lastContact(): BridgeContact | undefined;
private readonly eventsBySession;
/**
* Record one transcript entry, keyed by its position.
*
* Keyed rather than appended because the page is re-read on every DOM change, so the same
* message arrives repeatedly and a growing list would be mostly duplicates. Position also lets
* a later read replace an earlier one, which is what a message still being streamed needs.
*/
recordEvent(event: BridgeEvent): void;
/** That session's transcript so far, in order. */
events(sessionId: string): BridgeEvent[];
private readonly answersBySession;
/** The fingerprint of the question each session's `sent` answer resolved. */
private readonly answeredBySession;
/**
* Record the question a session is parked on, replacing any earlier one for that session.
*
* A question identical to one an answer was already delivered for is dropped: the extension's
* worker forgets what it sent when it restarts, and the answered block stays in the page's DOM,
* so the same question would otherwise resurface as parked right after being answered.
*/
record(question: BridgeQuestion): void;
/**
* Queue an answer picked in the dashboard (#1237). Refuses anything but a label of the
* question currently parked, so the only text this can ever put in a composer is one the
* session itself offered.
*/
queueAnswer(sessionId: string, label: string): BridgeAnswer | string;
/** Withdraw a queued answer. Too late once the extension has delivered it. */
cancelAnswer(sessionId: string): boolean;
/** The answer waiting for the extension to deliver, if any. */
pendingAnswer(sessionId: string): BridgeAnswer | undefined;
/** The session's answer in whatever state, for the dashboard to render. */
answer(sessionId: string): BridgeAnswer | undefined;
/**
* The extension's word on what happened to a delivery. On success the question is resolved:
* it is dropped, and re-reports of the same block are ignored (see {@link record}).
*/
resolveAnswer(sessionId: string, id: string, ok: boolean, note?: string): void;
/** The question that session is parked on, if the bridge has reported one. */
get(sessionId: string): BridgeQuestion | undefined;
/** Every parked question, newest first. */
list(): BridgeQuestion[];
/** Drop a session's question, once it is answered or its agent is gone. */
clear(sessionId: string): void;
}
export declare function bridgeQuestions(): BridgeQuestions;
/** Replace the store. Tests only: a module singleton would otherwise leak between them. */
export declare function resetBridgeQuestions(): void;
//# sourceMappingURL=bridge-store.d.ts.map