@formspec-org/chat
    Preparing search index...

    @formspec-org/chat

    formspec-chat

    Pure TypeScript core for conversational form building. Provides session orchestration, AI adapter integration, source tracing, issue tracking, definition diffing, template management, and session persistence. No React or DOM dependencies.

    npm install formspec-chat
    
    import {
    ChatSession,
    DeterministicAdapter,
    SessionStore,
    TemplateLibrary,
    } from 'formspec-chat';

    // Create a session with the offline adapter
    const session = new ChatSession({ adapter: new DeterministicAdapter() });

    // Send a message — generates an initial scaffold on the first call,
    // then refines the form on subsequent calls
    const reply = await session.sendMessage('I need a patient intake form');

    // Access the generated definition
    const definition = session.getDefinition();

    // Export as JSON
    const json = session.exportJSON();

    // Persist the session
    const store = new SessionStore(localStorage);
    store.save(session.toState());

    // Restore it later
    const state = store.load(session.id);
    const restored = ChatSession.fromState(state, new DeterministicAdapter());
    ChatSession          Orchestrates the conversation loop.
    ├── AIAdapter Interface. Plug in any AI provider.
    │ └── DeterministicAdapter Offline fallback. Uses templates + heuristics.
    ├── SourceTraceManager Tracks provenance: which message or upload produced each field.
    ├── IssueQueue Collects problems (missing config, contradictions, low confidence).
    └── diff() Computes added/removed/modified keys between two definitions.

    TemplateLibrary Five built-in archetypes (housing intake, grant application,
    patient intake, compliance checklist, employee onboarding).

    SessionStore Serializes and loads sessions via a StorageBackend interface.
    Accepts localStorage in the browser or any in-memory map in tests.

    validateProviderConfig Validates a ProviderConfig before passing it to an adapter.
    new ChatSession(options: { adapter: AIAdapter; id?: string })
    
    Method Returns Description
    sendMessage(content) Promise<ChatMessage> Send a user turn. Generates a scaffold on the first call; refines on subsequent calls.
    startFromTemplate(templateId) Promise<void> Initialize from a built-in template.
    startFromUpload(attachment) Promise<void> Extract structure from an uploaded file, then scaffold.
    getDefinition() FormDefinition | null Current form definition.
    getLastDiff() DefinitionDiff | null Structural diff from the most recent refinement.
    getMessages() ChatMessage[] Full message history.
    getTraces() SourceTrace[] All source traces.
    getTracesForElement(path) SourceTrace[] Traces for a specific field path.
    getIssues() Issue[] All issues.
    getOpenIssueCount() number Count of unresolved issues.
    resolveIssue(id) void Mark an issue resolved.
    deferIssue(id) void Mark an issue deferred.
    exportJSON() FormDefinition Export the current definition. Throws if none exists.
    toState() ChatSessionState Serialize the full session for storage.
    onChange(listener) () => void Subscribe to state changes. Returns an unsubscribe function.
    ChatSession.fromState(state, adapter) ChatSession Restore a session from serialized state.

    Implement this interface to connect any AI provider.

    interface AIAdapter {
    generateScaffold(request: ScaffoldRequest): Promise<ScaffoldResult>;
    refineForm(messages: ChatMessage[], current: FormDefinition, instruction: string): Promise<ScaffoldResult>;
    extractFromFile(attachment: Attachment): Promise<string>;
    isAvailable(): Promise<boolean>;
    }

    ScaffoldRequest is a discriminated union:

    type ScaffoldRequest =
    | { type: 'template'; templateId: string }
    | { type: 'conversation'; messages: ChatMessage[] }
    | { type: 'upload'; extractedContent: string };

    Offline fallback. Always available — no API key required. Matches conversation text to one of five built-in templates using keyword scoring. Cannot meaningfully refine forms; returns an info-level issue when refineForm is called.

    Tracks which message, upload, or template produced each form element.

    manager.addTrace(trace)
    manager.getTracesForElement(path) // by field path
    manager.getTracesForSource(sourceId) // by message or attachment ID
    manager.removeTracesForElement(path)
    manager.toJSON() / SourceTraceManager.fromJSON(data)

    Collects and tracks problems found during generation.

    queue.addIssue({ severity, category, title, description, sourceIds })
    queue.resolveIssue(id)
    queue.deferIssue(id)
    queue.reopenIssue(id)
    queue.getOpenIssues()
    queue.getIssuesByElement(path)
    queue.getIssueCount() // { open, resolved, deferred }
    queue.toJSON() / IssueQueue.fromJSON(data)

    Issue severities: 'error' | 'warning' | 'info' Issue categories: 'missing-config' | 'contradiction' | 'low-confidence' | 'validation'

    Computes a structural diff between two form definitions.

    const { added, removed, modified } = diff(previousDefinition, newDefinition);
    // added, removed, modified are string[] of item keys
    const library = new TemplateLibrary();
    library.getAll() // Template[]
    library.getById(id) // Template | undefined

    Built-in template IDs: housing-intake, grant-application, patient-intake, compliance-checklist, employee-onboarding.

    const store = new SessionStore(backend);  // backend implements StorageBackend
    store.save(state)
    store.load(id) // ChatSessionState | null
    store.delete(id)
    store.list() // SessionSummary[], most recent first

    StorageBackend requires only getItem, setItem, and removeItem. Pass localStorage in the browser or a Map-backed object in tests.

    const errors = validateProviderConfig({ provider: 'anthropic', apiKey: '...' });
    // ProviderValidationError[] — empty means valid

    Valid providers: 'anthropic' | 'google' | 'openai'

    All types export from the package root:

    import type {
    ChatMessage, Attachment,
    SourceTrace, SourceType,
    Issue, IssueSeverity, IssueCategory, IssueStatus,
    ScaffoldResult, ScaffoldRequest,
    AIAdapter,
    ProviderConfig, ProviderType,
    Template,
    ChatSessionState, ChatProjectSnapshot,
    StorageBackend, SessionSummary,
    } from 'formspec-chat';
    • formspec-types — shared Formspec type definitions (peer dependency)

    No runtime dependencies beyond formspec-types. No React, no DOM.