import { AgentActivitySessionSettings, AgentActivityComposerOptions } from '@tutti-os/agent-activity-core'; /** * Sparse pre-session settings a launcher composer can draft. Structurally * identical to AgentGUIQuickComposerSettings; declared here so the core stays * free of React-adjacent imports. */ type ComposerSettingsDraft = Pick; interface ComposerSettingsContext { agentTargetId: string; cwd: string | null; } /** * Host ports. fetchOptions must resolve against the exact target/cwd/settings * signature; rememberDefaults persists explicit user picks into the canonical * per-target composer-defaults ledger (write failures are non-blocking). */ interface ComposerSettingsCorePorts { fetchOptions(input: { agentTargetId: string; cwd: string | null; settings: ComposerSettingsDraft | null; }): Promise; rememberDefaults?(agentTargetId: string, patch: ComposerSettingsDraft): Promise | void; /** Non-blocking failure telemetry (e.g. a defaults write that was dropped). */ reportDiagnostic?(event: string, details: Record): void; } /** * Options lifecycle is a fenced state record rather than a phase enum: * `refreshing` derives from revision counters and `options` always holds the * last good catalog, so a failed refresh can never blank the menu. */ interface ComposerSettingsState { agentTargetId: string; cwd: string | null; draft: ComposerSettingsDraft; /** Latest issued fetch revision; bumped by context and settings changes. */ fetchRevision: number; /** Latest revision that settled (applied or failed). */ settledRevision: number; /** Last good options for the current target; null until the first success. */ options: AgentActivityComposerOptions | null; /** Error message from the latest settled fetch, null after a success. */ errorMessage: string | null; } interface ComposerSettingsCoreSnapshot { agentTargetId: string; cwd: string | null; /** Explicit user picks only. */ draft: ComposerSettingsDraft; /** Last good options; never cleared by a failed refresh. */ options: AgentActivityComposerOptions | null; /** A fetch is in flight. */ refreshing: boolean; /** No options have ever loaded for this target. */ initialLoading: boolean; /** The latest settled fetch failed; `options` is the previous good copy. */ degraded: boolean; errorMessage: string | null; /** * draft ⊕ options.effectiveSettings — the exact values the composer * displays. Submissions must carry these verbatim so the daemon never * re-interprets empty fields ("display what you send"). */ resolvedSettings: ComposerSettingsDraft; } /** * Host-agnostic composer settings policy: owns the sparse settings draft and * the fenced options lifecycle, seeds display from the daemon's * defaults-merged effectiveSettings, and writes explicit picks back to the * canonical per-target defaults ledger through a port. Views bind through the * external-store contract (stable subscribe/getSnapshot references). */ declare class ComposerSettingsCore { private readonly ports; private state; private snapshot; private readonly listeners; private disposed; private pendingDefaults; private defaultsWriteInFlight; constructor(ports: ComposerSettingsCorePorts, context: ComposerSettingsContext); readonly getSnapshot: () => ComposerSettingsCoreSnapshot; readonly subscribe: (listener: () => void) => (() => void); /** * Target changes reset draft and options (per-target facts) and drop any * unwritten defaults patch for the previous target; cwd-only changes keep * the draft. Either way the current catalog is re-fetched and any in-flight * response is fenced out. */ setContext(context: ComposerSettingsContext): void; /** Merge explicit picks, refresh against them, and persist them. */ setSettings(patch: ComposerSettingsDraft): void; refresh(): void; /** * The exact values the composer currently displays; submissions must carry * them verbatim so empty fields are never re-interpreted downstream. */ resolveSubmitSettings(): ComposerSettingsDraft; dispose(): void; private startFetch; /** * Trailing-edge coalescing: one write in flight, later picks merge into a * single pending patch, and the pending patch is re-drained after the * in-flight write settles. Write failures are dropped — persistence must * never block or fail the composer. */ private queueRememberDefaults; private drainRememberDefaults; private emit; } declare function projectComposerSettingsSnapshot(state: ComposerSettingsState): ComposerSettingsCoreSnapshot; /** * draft ⊕ effectiveSettings: every field the target supports becomes an * explicit value once options are loaded. This is both what the composer * displays and what a submission must carry. */ declare function resolveComposerSettings(draft: ComposerSettingsDraft, options: AgentActivityComposerOptions | null): ComposerSettingsDraft; export { type ComposerSettingsContext, ComposerSettingsCore, type ComposerSettingsCorePorts, type ComposerSettingsCoreSnapshot, type ComposerSettingsDraft, projectComposerSettingsSnapshot, resolveComposerSettings };