@stina/extension-api 0.44.0 → 0.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types.localization.ts","../src/messages.ts"],"sourcesContent":["/**\n * @stina/extension-api\n *\n * Types and utilities for building Stina extensions.\n *\n * Extensions should import from this package for type definitions.\n * The runtime (worker-side code) should import from '@stina/extension-api/runtime'.\n */\n\n// Localization\nexport type { LocalizedString } from './types.js'\nexport { resolveLocalizedString } from './types.js'\n\n// Types\nexport type {\n // Manifest\n ExtensionManifest,\n Platform,\n ExtensionContributions,\n ToolSettingsViewDefinition,\n ToolSettingsView,\n ToolSettingsListView,\n ToolSettingsListMapping,\n ToolSettingsComponentView,\n ToolSettingsActionDataSource,\n PanelDefinition,\n PanelView,\n PanelComponentView,\n PanelActionDataSource,\n PanelUnknownView,\n ProviderDefinition,\n ProviderConfigView,\n PromptContribution,\n PromptSection,\n ToolDefinition,\n ToolConfirmationConfig,\n CommandDefinition,\n\n // Permissions\n Permission,\n NetworkPermission,\n StoragePermission,\n UserDataPermission,\n CapabilityPermission,\n SystemPermission,\n\n // Context\n ExtensionContext,\n Disposable,\n NetworkAPI,\n SettingsAPI,\n ProvidersAPI,\n ToolsAPI,\n ActionsAPI,\n EventsAPI,\n SchedulerAPI,\n SchedulerJobRequest,\n SchedulerSchedule,\n SchedulerFirePayload,\n UserAPI,\n UserProfile,\n ChatAPI,\n ChatInstructionMessage,\n ConversationPresentation,\n LogAPI,\n\n // Background workers\n BackgroundWorkersAPI,\n BackgroundTaskConfig,\n BackgroundTaskCallback,\n BackgroundTaskContext,\n BackgroundTaskHealth,\n BackgroundRestartPolicy,\n\n // Storage and Secrets\n Query,\n QueryOptions,\n StorageAPI,\n SecretsAPI,\n StorageCollectionConfig,\n StorageContributions,\n\n // AI Provider\n AIProvider,\n ModelInfo,\n ModelCapabilities,\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolCall,\n\n // Duplex voice\n VoiceSessionOptions,\n VoiceSessionDescriptor,\n VoiceTransportRequest,\n\n // Tools\n Tool,\n ToolResult,\n\n // Actions\n Action,\n ActionResult,\n\n // Entry point\n ExtensionModule,\n} from './types.js'\n\n// Messages (for host implementation)\nexport type {\n HostToWorkerMessage,\n WorkerToHostMessage,\n ActivateMessage,\n DeactivateMessage,\n SettingsChangedMessage,\n ProviderChatRequestMessage,\n ProviderModelsRequestMessage,\n ToolExecuteRequestMessage,\n ToolExecuteResponseMessage,\n ActionExecuteRequestMessage,\n ActionExecuteResponseMessage,\n ResponseMessage,\n ReadyMessage,\n RequestMessage,\n RequestMethod,\n ProviderRegisteredMessage,\n ToolRegisteredMessage,\n ActionRegisteredMessage,\n StreamEventMessage,\n LogMessage,\n PendingRequest,\n // Background task messages\n BackgroundTaskStartMessage,\n BackgroundTaskStopMessage,\n BackgroundTaskRegisteredMessage,\n BackgroundTaskStatusMessage,\n BackgroundTaskHealthMessage,\n} from './messages.js'\n\nexport { generateMessageId } from './messages.js'\n\n// Component types (for extension UI components)\nexport type {\n // Icon Names\n HugeIconName,\n // Styling\n AllowedCSSProperty,\n ExtensionComponentStyle,\n // Base types\n ExtensionComponentData,\n // Iteration & Children\n ExtensionComponentIterator,\n ExtensionComponentChildren,\n // Actions\n ExtensionActionCall,\n ExtensionActionRef,\n // Data Sources & Panel Definition\n ExtensionDataSource,\n ExtensionPanelDefinition,\n // Component Props\n HeaderProps,\n LabelProps,\n ParagraphProps,\n ButtonProps,\n TextInputProps,\n PasswordInputProps,\n NumberInputProps,\n TextAreaProps,\n DateTimeInputProps,\n SelectProps,\n IconPickerProps,\n VerticalStackProps,\n HorizontalStackProps,\n GridProps,\n DividerProps,\n IconProps,\n IconButtonType,\n IconButtonProps,\n PanelAction,\n PanelProps,\n ToggleProps,\n CollapsibleProps,\n FrameVariant,\n FrameProps,\n ListProps,\n PillVariant,\n PillProps,\n CheckboxProps,\n MarkdownProps,\n TextPreviewProps,\n ModalProps,\n ConditionalGroupProps,\n} from './types.components.js'\n","/**\n * Localization Types\n *\n * Types and utilities for localized strings in extensions.\n */\n\n/**\n * A string that can be either a simple string or a map of language codes to localized strings.\n * When a simple string is provided, it's used as the default/fallback value.\n * When a map is provided, the appropriate language is selected at runtime.\n *\n * @example\n * // Simple string (backwards compatible)\n * name: \"Get Weather\"\n *\n * @example\n * // Localized strings\n * name: { en: \"Get Weather\", sv: \"Hämta väder\", de: \"Wetter abrufen\" }\n */\nexport type LocalizedString = string | Record<string, string>\n\n/**\n * Resolves a LocalizedString to an actual string value.\n * @param value The LocalizedString to resolve\n * @param lang The preferred language code (e.g., \"sv\", \"en\")\n * @param fallbackLang The fallback language code (defaults to \"en\")\n * @returns The resolved string value\n */\nexport function resolveLocalizedString(\n value: LocalizedString,\n lang: string,\n fallbackLang = 'en'\n): string {\n if (typeof value === 'string') {\n return value\n }\n // Try preferred language first, then fallback language, then first available, then empty string\n return value[lang] ?? value[fallbackLang] ?? Object.values(value)[0] ?? ''\n}\n","/**\n * Message protocol between Extension Host and Extension Workers\n */\n\nimport type {\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolResult,\n ActionResult,\n ModelInfo,\n SchedulerFirePayload,\n VoiceSessionOptions,\n VoiceSessionDescriptor,\n} from './types.js'\n\n// ============================================================================\n// Host → Worker Messages\n// ============================================================================\n\nexport type HostToWorkerMessage =\n | ActivateMessage\n | DeactivateMessage\n | SettingsChangedMessage\n | SchedulerFireMessage\n | ProviderChatRequestMessage\n | ProviderModelsRequestMessage\n | ProviderVoiceSessionRequestMessage\n | ToolExecuteRequestMessage\n | ActionExecuteRequestMessage\n | ResponseMessage\n | StreamingFetchChunkMessage\n | BackgroundTaskStartMessage\n | BackgroundTaskStopMessage\n\nexport interface ActivateMessage {\n type: 'activate'\n id: string\n payload: {\n extensionId: string\n extensionVersion: string\n storagePath: string\n permissions: string[]\n settings: Record<string, unknown>\n }\n}\n\nexport interface DeactivateMessage {\n type: 'deactivate'\n id: string\n}\n\nexport interface SettingsChangedMessage {\n type: 'settings-changed'\n id: string\n payload: {\n key: string\n value: unknown\n }\n}\n\nexport interface SchedulerFireMessage {\n type: 'scheduler-fire'\n id: string\n payload: SchedulerFirePayload\n}\n\nexport interface ProviderChatRequestMessage {\n type: 'provider-chat-request'\n id: string\n payload: {\n providerId: string\n messages: ChatMessage[]\n options: ChatOptions\n }\n}\n\nexport interface ProviderModelsRequestMessage {\n type: 'provider-models-request'\n id: string\n payload: {\n providerId: string\n options?: GetModelsOptions\n }\n}\n\nexport interface ProviderVoiceSessionRequestMessage {\n type: 'provider-voice-session-request'\n id: string\n payload: {\n providerId: string\n /**\n * `signal` is dropped on the way across: an AbortSignal cannot be\n * structured-cloned into a worker. Cancellation is handled by the host\n * rejecting the pending request instead.\n */\n options: Omit<VoiceSessionOptions, 'signal'>\n }\n}\n\nexport interface ToolExecuteRequestMessage {\n type: 'tool-execute-request'\n id: string\n payload: {\n toolId: string\n params: Record<string, unknown>\n /** User ID if the tool is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ActionExecuteRequestMessage {\n type: 'action-execute-request'\n id: string\n payload: {\n actionId: string\n params: Record<string, unknown>\n /** User ID if the action is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ResponseMessage {\n type: 'response'\n id: string\n payload: {\n requestId: string\n success: boolean\n data?: unknown\n error?: string\n }\n}\n\n/**\n * Message sent from host to worker with streaming fetch data chunks.\n * Used for streaming network responses (e.g., NDJSON streams from Ollama).\n */\nexport interface StreamingFetchChunkMessage {\n type: 'streaming-fetch-chunk'\n id: string\n payload: {\n requestId: string\n chunk: string\n done: boolean\n error?: string\n }\n}\n\n/**\n * Message sent from host to worker to start a registered background task.\n */\nexport interface BackgroundTaskStartMessage {\n type: 'background-task-start'\n id: string\n payload: {\n taskId: string\n }\n}\n\n/**\n * Message sent from host to worker to stop a running background task.\n */\nexport interface BackgroundTaskStopMessage {\n type: 'background-task-stop'\n id: string\n payload: {\n taskId: string\n }\n}\n\n// ============================================================================\n// Worker → Host Messages\n// ============================================================================\n\nexport type WorkerToHostMessage =\n | ReadyMessage\n | RequestMessage\n | ProviderRegisteredMessage\n | ToolRegisteredMessage\n | ActionRegisteredMessage\n | StreamEventMessage\n | LogMessage\n | ProviderModelsResponseMessage\n | ProviderVoiceSessionResponseMessage\n | ToolExecuteResponseMessage\n | ActionExecuteResponseMessage\n | StreamingFetchAckMessage\n | BackgroundTaskRegisteredMessage\n | BackgroundTaskStatusMessage\n | BackgroundTaskHealthMessage\n\nexport interface ReadyMessage {\n type: 'ready'\n}\n\n/**\n * Message sent from worker to host to acknowledge receipt of a streaming fetch chunk.\n * This enables backpressure control to prevent unbounded memory growth.\n */\nexport interface StreamingFetchAckMessage {\n type: 'streaming-fetch-ack'\n payload: {\n requestId: string\n }\n}\n\nexport interface RequestMessage {\n type: 'request'\n id: string\n method: RequestMethod\n payload: unknown\n}\n\nexport type RequestMethod =\n | 'network.fetch'\n | 'network.fetch-stream'\n | 'settings.getAll'\n | 'settings.get'\n | 'settings.set'\n | 'user.getProfile'\n | 'user.listIds'\n | 'events.emit'\n | 'scheduler.schedule'\n | 'scheduler.cancel'\n | 'scheduler.reportFireResult'\n | 'chat.appendInstruction'\n | 'database.execute'\n // Simple key-value storage methods\n | 'storage.set'\n | 'storage.keys'\n | 'storage.setForUser'\n | 'storage.keysForUser'\n // Collection-based storage methods\n | 'storage.put'\n | 'storage.get'\n | 'storage.delete'\n | 'storage.find'\n | 'storage.findOne'\n | 'storage.count'\n | 'storage.putMany'\n | 'storage.deleteMany'\n | 'storage.dropCollection'\n | 'storage.listCollections'\n | 'storage.putForUser'\n | 'storage.getForUser'\n | 'storage.deleteForUser'\n | 'storage.findForUser'\n | 'storage.findOneForUser'\n | 'storage.countForUser'\n | 'storage.putManyForUser'\n | 'storage.deleteManyForUser'\n | 'storage.dropCollectionForUser'\n | 'storage.listCollectionsForUser'\n // Secrets methods\n | 'secrets.set'\n | 'secrets.get'\n | 'secrets.delete'\n | 'secrets.list'\n | 'secrets.setForUser'\n | 'secrets.getForUser'\n | 'secrets.deleteForUser'\n | 'secrets.listForUser'\n // Tools cross-extension methods\n | 'tools.list'\n | 'tools.execute'\n\nexport interface ProviderRegisteredMessage {\n type: 'provider-registered'\n payload: {\n id: string\n name: string\n }\n}\n\nexport interface ToolRegisteredMessage {\n type: 'tool-registered'\n payload: {\n id: string\n name: string\n description: string\n parameters?: Record<string, unknown>\n }\n}\n\nexport interface ActionRegisteredMessage {\n type: 'action-registered'\n payload: {\n id: string\n }\n}\n\nexport interface StreamEventMessage {\n type: 'stream-event'\n payload: {\n requestId: string\n event: StreamEvent\n }\n}\n\nexport interface ProviderModelsResponseMessage {\n type: 'provider-models-response'\n payload: {\n requestId: string\n models: ModelInfo[]\n error?: string\n }\n}\n\nexport interface ProviderVoiceSessionResponseMessage {\n type: 'provider-voice-session-response'\n payload: {\n requestId: string\n /** Absent when `error` is set. */\n descriptor?: VoiceSessionDescriptor\n error?: string\n }\n}\n\nexport interface ToolExecuteResponseMessage {\n type: 'tool-execute-response'\n payload: {\n requestId: string\n result: ToolResult\n error?: string\n }\n}\n\nexport interface ActionExecuteResponseMessage {\n type: 'action-execute-response'\n payload: {\n requestId: string\n result: ActionResult\n error?: string\n }\n}\n\nexport interface LogMessage {\n type: 'log'\n payload: {\n level: 'debug' | 'info' | 'warn' | 'error'\n message: string\n data?: Record<string, unknown>\n }\n}\n\n/**\n * Message sent from worker to host when a background task is registered.\n */\nexport interface BackgroundTaskRegisteredMessage {\n type: 'background-task-registered'\n payload: {\n taskId: string\n name: string\n userId: string\n restartPolicy: {\n type: 'always' | 'on-failure' | 'never'\n maxRestarts?: number\n initialDelayMs?: number\n maxDelayMs?: number\n backoffMultiplier?: number\n }\n payload?: Record<string, unknown>\n }\n}\n\n/**\n * Message sent from worker to host with background task status updates.\n */\nexport interface BackgroundTaskStatusMessage {\n type: 'background-task-status'\n payload: {\n taskId: string\n status: 'running' | 'stopped' | 'completed' | 'failed'\n error?: string\n }\n}\n\n/**\n * Message sent from worker to host with background task health reports.\n */\nexport interface BackgroundTaskHealthMessage {\n type: 'background-task-health'\n payload: {\n taskId: string\n status: string\n timestamp: string\n }\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\nexport interface PendingRequest<T = unknown> {\n resolve: (value: T) => void\n reject: (error: Error) => void\n timeout: ReturnType<typeof setTimeout>\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC4BO,SAAS,uBACd,OACA,MACA,eAAe,MACP;AACR,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AAEA,SAAO,MAAM,IAAI,KAAK,MAAM,YAAY,KAAK,OAAO,OAAO,KAAK,EAAE,CAAC,KAAK;AAC1E;;;AC6WO,SAAS,oBAA4B;AAC1C,SAAO,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACjE;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types.localization.ts","../src/messages.ts"],"sourcesContent":["/**\n * @stina/extension-api\n *\n * Types and utilities for building Stina extensions.\n *\n * Extensions should import from this package for type definitions.\n * The runtime (worker-side code) should import from '@stina/extension-api/runtime'.\n */\n\n// Localization\nexport type { LocalizedString } from './types.js'\nexport { resolveLocalizedString } from './types.js'\n\n// Types\nexport type {\n // Manifest\n ExtensionManifest,\n Platform,\n ExtensionContributions,\n ToolSettingsViewDefinition,\n ToolSettingsView,\n ToolSettingsListView,\n ToolSettingsListMapping,\n ToolSettingsComponentView,\n ToolSettingsActionDataSource,\n PanelDefinition,\n PanelView,\n PanelComponentView,\n PanelActionDataSource,\n PanelUnknownView,\n ProviderDefinition,\n ProviderConfigView,\n PromptContribution,\n PromptSection,\n ToolDefinition,\n ToolConfirmationConfig,\n CommandDefinition,\n\n // Permissions\n Permission,\n NetworkPermission,\n StoragePermission,\n UserDataPermission,\n CapabilityPermission,\n SystemPermission,\n\n // Context\n ExtensionContext,\n Disposable,\n NetworkAPI,\n SettingsAPI,\n ProvidersAPI,\n ToolsAPI,\n ActionsAPI,\n EventsAPI,\n SchedulerAPI,\n SchedulerJobRequest,\n SchedulerSchedule,\n SchedulerFirePayload,\n UserAPI,\n UserProfile,\n ChatAPI,\n ChatInstructionMessage,\n ConversationPresentation,\n LogAPI,\n\n // Background workers\n BackgroundWorkersAPI,\n BackgroundTaskConfig,\n BackgroundTaskCallback,\n BackgroundTaskContext,\n BackgroundTaskHealth,\n BackgroundRestartPolicy,\n\n // Storage and Secrets\n Query,\n QueryOptions,\n StorageAPI,\n SecretsAPI,\n StorageCollectionConfig,\n StorageContributions,\n\n // AI Provider\n AIProvider,\n ModelInfo,\n ModelCapabilities,\n ChatMessage,\n ChatImage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolCall,\n\n // Duplex voice\n VoiceSessionOptions,\n VoiceSessionDescriptor,\n VoiceTransportRequest,\n\n // Tools\n Tool,\n ToolResult,\n\n // Actions\n Action,\n ActionResult,\n\n // Entry point\n ExtensionModule,\n} from './types.js'\n\n// Messages (for host implementation)\nexport type {\n HostToWorkerMessage,\n WorkerToHostMessage,\n ActivateMessage,\n DeactivateMessage,\n SettingsChangedMessage,\n ProviderChatRequestMessage,\n ProviderModelsRequestMessage,\n ToolExecuteRequestMessage,\n ToolExecuteResponseMessage,\n ActionExecuteRequestMessage,\n ActionExecuteResponseMessage,\n ResponseMessage,\n ReadyMessage,\n RequestMessage,\n RequestMethod,\n ProviderRegisteredMessage,\n ToolRegisteredMessage,\n ActionRegisteredMessage,\n StreamEventMessage,\n LogMessage,\n PendingRequest,\n // Background task messages\n BackgroundTaskStartMessage,\n BackgroundTaskStopMessage,\n BackgroundTaskRegisteredMessage,\n BackgroundTaskStatusMessage,\n BackgroundTaskHealthMessage,\n} from './messages.js'\n\nexport { generateMessageId } from './messages.js'\n\n// Component types (for extension UI components)\nexport type {\n // Icon Names\n HugeIconName,\n // Styling\n AllowedCSSProperty,\n ExtensionComponentStyle,\n // Base types\n ExtensionComponentData,\n // Iteration & Children\n ExtensionComponentIterator,\n ExtensionComponentChildren,\n // Actions\n ExtensionActionCall,\n ExtensionActionRef,\n // Data Sources & Panel Definition\n ExtensionDataSource,\n ExtensionPanelDefinition,\n // Component Props\n HeaderProps,\n LabelProps,\n ParagraphProps,\n ButtonProps,\n TextInputProps,\n PasswordInputProps,\n NumberInputProps,\n TextAreaProps,\n DateTimeInputProps,\n SelectProps,\n IconPickerProps,\n VerticalStackProps,\n HorizontalStackProps,\n GridProps,\n DividerProps,\n IconProps,\n IconButtonType,\n IconButtonProps,\n PanelAction,\n PanelProps,\n ToggleProps,\n CollapsibleProps,\n FrameVariant,\n FrameProps,\n ListProps,\n PillVariant,\n PillProps,\n CheckboxProps,\n MarkdownProps,\n TextPreviewProps,\n ModalProps,\n ConditionalGroupProps,\n} from './types.components.js'\n","/**\n * Localization Types\n *\n * Types and utilities for localized strings in extensions.\n */\n\n/**\n * A string that can be either a simple string or a map of language codes to localized strings.\n * When a simple string is provided, it's used as the default/fallback value.\n * When a map is provided, the appropriate language is selected at runtime.\n *\n * @example\n * // Simple string (backwards compatible)\n * name: \"Get Weather\"\n *\n * @example\n * // Localized strings\n * name: { en: \"Get Weather\", sv: \"Hämta väder\", de: \"Wetter abrufen\" }\n */\nexport type LocalizedString = string | Record<string, string>\n\n/**\n * Resolves a LocalizedString to an actual string value.\n * @param value The LocalizedString to resolve\n * @param lang The preferred language code (e.g., \"sv\", \"en\")\n * @param fallbackLang The fallback language code (defaults to \"en\")\n * @returns The resolved string value\n */\nexport function resolveLocalizedString(\n value: LocalizedString,\n lang: string,\n fallbackLang = 'en'\n): string {\n if (typeof value === 'string') {\n return value\n }\n // Try preferred language first, then fallback language, then first available, then empty string\n return value[lang] ?? value[fallbackLang] ?? Object.values(value)[0] ?? ''\n}\n","/**\n * Message protocol between Extension Host and Extension Workers\n */\n\nimport type {\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolResult,\n ActionResult,\n ModelInfo,\n SchedulerFirePayload,\n VoiceSessionOptions,\n VoiceSessionDescriptor,\n} from './types.js'\n\n// ============================================================================\n// Host → Worker Messages\n// ============================================================================\n\nexport type HostToWorkerMessage =\n | ActivateMessage\n | DeactivateMessage\n | SettingsChangedMessage\n | SchedulerFireMessage\n | ProviderChatRequestMessage\n | ProviderModelsRequestMessage\n | ProviderVoiceSessionRequestMessage\n | ToolExecuteRequestMessage\n | ActionExecuteRequestMessage\n | ResponseMessage\n | StreamingFetchChunkMessage\n | BackgroundTaskStartMessage\n | BackgroundTaskStopMessage\n\nexport interface ActivateMessage {\n type: 'activate'\n id: string\n payload: {\n extensionId: string\n extensionVersion: string\n storagePath: string\n permissions: string[]\n settings: Record<string, unknown>\n }\n}\n\nexport interface DeactivateMessage {\n type: 'deactivate'\n id: string\n}\n\nexport interface SettingsChangedMessage {\n type: 'settings-changed'\n id: string\n payload: {\n key: string\n value: unknown\n }\n}\n\nexport interface SchedulerFireMessage {\n type: 'scheduler-fire'\n id: string\n payload: SchedulerFirePayload\n}\n\nexport interface ProviderChatRequestMessage {\n type: 'provider-chat-request'\n id: string\n payload: {\n providerId: string\n messages: ChatMessage[]\n options: ChatOptions\n }\n}\n\nexport interface ProviderModelsRequestMessage {\n type: 'provider-models-request'\n id: string\n payload: {\n providerId: string\n options?: GetModelsOptions\n }\n}\n\nexport interface ProviderVoiceSessionRequestMessage {\n type: 'provider-voice-session-request'\n id: string\n payload: {\n providerId: string\n /**\n * `signal` is dropped on the way across: an AbortSignal cannot be\n * structured-cloned into a worker. Cancellation is handled by the host\n * rejecting the pending request instead.\n */\n options: Omit<VoiceSessionOptions, 'signal'>\n }\n}\n\nexport interface ToolExecuteRequestMessage {\n type: 'tool-execute-request'\n id: string\n payload: {\n toolId: string\n params: Record<string, unknown>\n /** User ID if the tool is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ActionExecuteRequestMessage {\n type: 'action-execute-request'\n id: string\n payload: {\n actionId: string\n params: Record<string, unknown>\n /** User ID if the action is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ResponseMessage {\n type: 'response'\n id: string\n payload: {\n requestId: string\n success: boolean\n data?: unknown\n error?: string\n }\n}\n\n/**\n * Message sent from host to worker with streaming fetch data chunks.\n * Used for streaming network responses (e.g., NDJSON streams from Ollama).\n */\nexport interface StreamingFetchChunkMessage {\n type: 'streaming-fetch-chunk'\n id: string\n payload: {\n requestId: string\n chunk: string\n done: boolean\n error?: string\n }\n}\n\n/**\n * Message sent from host to worker to start a registered background task.\n */\nexport interface BackgroundTaskStartMessage {\n type: 'background-task-start'\n id: string\n payload: {\n taskId: string\n }\n}\n\n/**\n * Message sent from host to worker to stop a running background task.\n */\nexport interface BackgroundTaskStopMessage {\n type: 'background-task-stop'\n id: string\n payload: {\n taskId: string\n }\n}\n\n// ============================================================================\n// Worker → Host Messages\n// ============================================================================\n\nexport type WorkerToHostMessage =\n | ReadyMessage\n | RequestMessage\n | ProviderRegisteredMessage\n | ToolRegisteredMessage\n | ActionRegisteredMessage\n | StreamEventMessage\n | LogMessage\n | ProviderModelsResponseMessage\n | ProviderVoiceSessionResponseMessage\n | ToolExecuteResponseMessage\n | ActionExecuteResponseMessage\n | StreamingFetchAckMessage\n | BackgroundTaskRegisteredMessage\n | BackgroundTaskStatusMessage\n | BackgroundTaskHealthMessage\n\nexport interface ReadyMessage {\n type: 'ready'\n}\n\n/**\n * Message sent from worker to host to acknowledge receipt of a streaming fetch chunk.\n * This enables backpressure control to prevent unbounded memory growth.\n */\nexport interface StreamingFetchAckMessage {\n type: 'streaming-fetch-ack'\n payload: {\n requestId: string\n }\n}\n\nexport interface RequestMessage {\n type: 'request'\n id: string\n method: RequestMethod\n payload: unknown\n}\n\nexport type RequestMethod =\n | 'network.fetch'\n | 'network.fetch-stream'\n | 'settings.getAll'\n | 'settings.get'\n | 'settings.set'\n | 'user.getProfile'\n | 'user.listIds'\n | 'events.emit'\n | 'scheduler.schedule'\n | 'scheduler.cancel'\n | 'scheduler.reportFireResult'\n | 'chat.appendInstruction'\n | 'database.execute'\n // Simple key-value storage methods\n | 'storage.set'\n | 'storage.keys'\n | 'storage.setForUser'\n | 'storage.keysForUser'\n // Collection-based storage methods\n | 'storage.put'\n | 'storage.get'\n | 'storage.delete'\n | 'storage.find'\n | 'storage.findOne'\n | 'storage.count'\n | 'storage.putMany'\n | 'storage.deleteMany'\n | 'storage.dropCollection'\n | 'storage.listCollections'\n | 'storage.putForUser'\n | 'storage.getForUser'\n | 'storage.deleteForUser'\n | 'storage.findForUser'\n | 'storage.findOneForUser'\n | 'storage.countForUser'\n | 'storage.putManyForUser'\n | 'storage.deleteManyForUser'\n | 'storage.dropCollectionForUser'\n | 'storage.listCollectionsForUser'\n // Secrets methods\n | 'secrets.set'\n | 'secrets.get'\n | 'secrets.delete'\n | 'secrets.list'\n | 'secrets.setForUser'\n | 'secrets.getForUser'\n | 'secrets.deleteForUser'\n | 'secrets.listForUser'\n // Tools cross-extension methods\n | 'tools.list'\n | 'tools.execute'\n\nexport interface ProviderRegisteredMessage {\n type: 'provider-registered'\n payload: {\n id: string\n name: string\n }\n}\n\nexport interface ToolRegisteredMessage {\n type: 'tool-registered'\n payload: {\n id: string\n name: string\n description: string\n parameters?: Record<string, unknown>\n }\n}\n\nexport interface ActionRegisteredMessage {\n type: 'action-registered'\n payload: {\n id: string\n }\n}\n\nexport interface StreamEventMessage {\n type: 'stream-event'\n payload: {\n requestId: string\n event: StreamEvent\n }\n}\n\nexport interface ProviderModelsResponseMessage {\n type: 'provider-models-response'\n payload: {\n requestId: string\n models: ModelInfo[]\n error?: string\n }\n}\n\nexport interface ProviderVoiceSessionResponseMessage {\n type: 'provider-voice-session-response'\n payload: {\n requestId: string\n /** Absent when `error` is set. */\n descriptor?: VoiceSessionDescriptor\n error?: string\n }\n}\n\nexport interface ToolExecuteResponseMessage {\n type: 'tool-execute-response'\n payload: {\n requestId: string\n result: ToolResult\n error?: string\n }\n}\n\nexport interface ActionExecuteResponseMessage {\n type: 'action-execute-response'\n payload: {\n requestId: string\n result: ActionResult\n error?: string\n }\n}\n\nexport interface LogMessage {\n type: 'log'\n payload: {\n level: 'debug' | 'info' | 'warn' | 'error'\n message: string\n data?: Record<string, unknown>\n }\n}\n\n/**\n * Message sent from worker to host when a background task is registered.\n */\nexport interface BackgroundTaskRegisteredMessage {\n type: 'background-task-registered'\n payload: {\n taskId: string\n name: string\n userId: string\n restartPolicy: {\n type: 'always' | 'on-failure' | 'never'\n maxRestarts?: number\n initialDelayMs?: number\n maxDelayMs?: number\n backoffMultiplier?: number\n }\n payload?: Record<string, unknown>\n }\n}\n\n/**\n * Message sent from worker to host with background task status updates.\n */\nexport interface BackgroundTaskStatusMessage {\n type: 'background-task-status'\n payload: {\n taskId: string\n status: 'running' | 'stopped' | 'completed' | 'failed'\n error?: string\n }\n}\n\n/**\n * Message sent from worker to host with background task health reports.\n */\nexport interface BackgroundTaskHealthMessage {\n type: 'background-task-health'\n payload: {\n taskId: string\n status: string\n timestamp: string\n }\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\nexport interface PendingRequest<T = unknown> {\n resolve: (value: T) => void\n reject: (error: Error) => void\n timeout: ReturnType<typeof setTimeout>\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC4BO,SAAS,uBACd,OACA,MACA,eAAe,MACP;AACR,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AAEA,SAAO,MAAM,IAAI,KAAK,MAAM,YAAY,KAAK,OAAO,OAAO,KAAK,EAAE,CAAC,KAAK;AAC1E;;;AC6WO,SAAS,oBAA4B;AAC1C,SAAO,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACjE;","names":[]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { H as HugeIconName, E as ExtensionContributions, S as SchedulerFirePayload, C as ChatMessage, a as ChatOptions, G as GetModelsOptions, V as VoiceSessionOptions, b as StreamEvent, M as ModelInfo, c as VoiceSessionDescriptor, T as ToolResult, A as ActionResult } from './types.tools-BZQrEs91.cjs';
2
- export { a7 as AIProvider, ac as Action, z as ActionsAPI, ae as AllowedCSSProperty, a0 as BackgroundRestartPolicy, Z as BackgroundTaskCallback, Y as BackgroundTaskConfig, _ as BackgroundTaskContext, $ as BackgroundTaskHealth, X as BackgroundWorkersAPI, aq as ButtonProps, O as ChatAPI, Q as ChatInstructionMessage, aO as CheckboxProps, aI as CollapsibleProps, u as CommandDefinition, aS as ConditionalGroupProps, R as ConversationPresentation, av as DateTimeInputProps, D as Disposable, aB as DividerProps, B as EventsAPI, aj as ExtensionActionCall, ak as ExtensionActionRef, ai as ExtensionComponentChildren, ag as ExtensionComponentData, ah as ExtensionComponentIterator, af as ExtensionComponentStyle, v as ExtensionContext, al as ExtensionDataSource, ad as ExtensionModule, am as ExtensionPanelDefinition, aK as FrameProps, aJ as FrameVariant, aA as GridProps, an as HeaderProps, az as HorizontalStackProps, aE as IconButtonProps, aD as IconButtonType, ax as IconPickerProps, aC as IconProps, ao as LabelProps, aL as ListProps, L as LocalizedString, W as LogAPI, aP as MarkdownProps, aR as ModalProps, a8 as ModelCapabilities, N as NetworkAPI, at as NumberInputProps, aF as PanelAction, l as PanelActionDataSource, k as PanelComponentView, P as PanelDefinition, aG as PanelProps, m as PanelUnknownView, j as PanelView, ap as ParagraphProps, as as PasswordInputProps, aN as PillProps, aM as PillVariant, p as PromptContribution, q as PromptSection, o as ProviderConfigView, n as ProviderDefinition, x as ProvidersAPI, a1 as Query, a2 as QueryOptions, F as SchedulerAPI, I as SchedulerJobRequest, J as SchedulerSchedule, a4 as SecretsAPI, aw as SelectProps, w as SettingsAPI, a3 as StorageAPI, a5 as StorageCollectionConfig, a6 as StorageContributions, au as TextAreaProps, ar as TextInputProps, aQ as TextPreviewProps, aH as ToggleProps, ab as Tool, a9 as ToolCall, t as ToolConfirmationConfig, s as ToolDefinition, i as ToolSettingsActionDataSource, h as ToolSettingsComponentView, g as ToolSettingsListMapping, f as ToolSettingsListView, e as ToolSettingsView, d as ToolSettingsViewDefinition, y as ToolsAPI, U as UserAPI, K as UserProfile, ay as VerticalStackProps, aa as VoiceTransportRequest, r as resolveLocalizedString } from './types.tools-BZQrEs91.cjs';
1
+ import { H as HugeIconName, E as ExtensionContributions, S as SchedulerFirePayload, C as ChatMessage, a as ChatOptions, G as GetModelsOptions, V as VoiceSessionOptions, b as StreamEvent, M as ModelInfo, c as VoiceSessionDescriptor, T as ToolResult, A as ActionResult } from './types.tools-XpXCoPrJ.cjs';
2
+ export { a7 as AIProvider, ad as Action, z as ActionsAPI, af as AllowedCSSProperty, a0 as BackgroundRestartPolicy, Z as BackgroundTaskCallback, Y as BackgroundTaskConfig, _ as BackgroundTaskContext, $ as BackgroundTaskHealth, X as BackgroundWorkersAPI, ar as ButtonProps, O as ChatAPI, a9 as ChatImage, Q as ChatInstructionMessage, aP as CheckboxProps, aJ as CollapsibleProps, u as CommandDefinition, aT as ConditionalGroupProps, R as ConversationPresentation, aw as DateTimeInputProps, D as Disposable, aC as DividerProps, B as EventsAPI, ak as ExtensionActionCall, al as ExtensionActionRef, aj as ExtensionComponentChildren, ah as ExtensionComponentData, ai as ExtensionComponentIterator, ag as ExtensionComponentStyle, v as ExtensionContext, am as ExtensionDataSource, ae as ExtensionModule, an as ExtensionPanelDefinition, aL as FrameProps, aK as FrameVariant, aB as GridProps, ao as HeaderProps, aA as HorizontalStackProps, aF as IconButtonProps, aE as IconButtonType, ay as IconPickerProps, aD as IconProps, ap as LabelProps, aM as ListProps, L as LocalizedString, W as LogAPI, aQ as MarkdownProps, aS as ModalProps, a8 as ModelCapabilities, N as NetworkAPI, au as NumberInputProps, aG as PanelAction, l as PanelActionDataSource, k as PanelComponentView, P as PanelDefinition, aH as PanelProps, m as PanelUnknownView, j as PanelView, aq as ParagraphProps, at as PasswordInputProps, aO as PillProps, aN as PillVariant, p as PromptContribution, q as PromptSection, o as ProviderConfigView, n as ProviderDefinition, x as ProvidersAPI, a1 as Query, a2 as QueryOptions, F as SchedulerAPI, I as SchedulerJobRequest, J as SchedulerSchedule, a4 as SecretsAPI, ax as SelectProps, w as SettingsAPI, a3 as StorageAPI, a5 as StorageCollectionConfig, a6 as StorageContributions, av as TextAreaProps, as as TextInputProps, aR as TextPreviewProps, aI as ToggleProps, ac as Tool, aa as ToolCall, t as ToolConfirmationConfig, s as ToolDefinition, i as ToolSettingsActionDataSource, h as ToolSettingsComponentView, g as ToolSettingsListMapping, f as ToolSettingsListView, e as ToolSettingsView, d as ToolSettingsViewDefinition, y as ToolsAPI, U as UserAPI, K as UserProfile, az as VerticalStackProps, ab as VoiceTransportRequest, r as resolveLocalizedString } from './types.tools-XpXCoPrJ.cjs';
3
3
 
4
4
  /**
5
5
  * Permission Types
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { H as HugeIconName, E as ExtensionContributions, S as SchedulerFirePayload, C as ChatMessage, a as ChatOptions, G as GetModelsOptions, V as VoiceSessionOptions, b as StreamEvent, M as ModelInfo, c as VoiceSessionDescriptor, T as ToolResult, A as ActionResult } from './types.tools-BZQrEs91.js';
2
- export { a7 as AIProvider, ac as Action, z as ActionsAPI, ae as AllowedCSSProperty, a0 as BackgroundRestartPolicy, Z as BackgroundTaskCallback, Y as BackgroundTaskConfig, _ as BackgroundTaskContext, $ as BackgroundTaskHealth, X as BackgroundWorkersAPI, aq as ButtonProps, O as ChatAPI, Q as ChatInstructionMessage, aO as CheckboxProps, aI as CollapsibleProps, u as CommandDefinition, aS as ConditionalGroupProps, R as ConversationPresentation, av as DateTimeInputProps, D as Disposable, aB as DividerProps, B as EventsAPI, aj as ExtensionActionCall, ak as ExtensionActionRef, ai as ExtensionComponentChildren, ag as ExtensionComponentData, ah as ExtensionComponentIterator, af as ExtensionComponentStyle, v as ExtensionContext, al as ExtensionDataSource, ad as ExtensionModule, am as ExtensionPanelDefinition, aK as FrameProps, aJ as FrameVariant, aA as GridProps, an as HeaderProps, az as HorizontalStackProps, aE as IconButtonProps, aD as IconButtonType, ax as IconPickerProps, aC as IconProps, ao as LabelProps, aL as ListProps, L as LocalizedString, W as LogAPI, aP as MarkdownProps, aR as ModalProps, a8 as ModelCapabilities, N as NetworkAPI, at as NumberInputProps, aF as PanelAction, l as PanelActionDataSource, k as PanelComponentView, P as PanelDefinition, aG as PanelProps, m as PanelUnknownView, j as PanelView, ap as ParagraphProps, as as PasswordInputProps, aN as PillProps, aM as PillVariant, p as PromptContribution, q as PromptSection, o as ProviderConfigView, n as ProviderDefinition, x as ProvidersAPI, a1 as Query, a2 as QueryOptions, F as SchedulerAPI, I as SchedulerJobRequest, J as SchedulerSchedule, a4 as SecretsAPI, aw as SelectProps, w as SettingsAPI, a3 as StorageAPI, a5 as StorageCollectionConfig, a6 as StorageContributions, au as TextAreaProps, ar as TextInputProps, aQ as TextPreviewProps, aH as ToggleProps, ab as Tool, a9 as ToolCall, t as ToolConfirmationConfig, s as ToolDefinition, i as ToolSettingsActionDataSource, h as ToolSettingsComponentView, g as ToolSettingsListMapping, f as ToolSettingsListView, e as ToolSettingsView, d as ToolSettingsViewDefinition, y as ToolsAPI, U as UserAPI, K as UserProfile, ay as VerticalStackProps, aa as VoiceTransportRequest, r as resolveLocalizedString } from './types.tools-BZQrEs91.js';
1
+ import { H as HugeIconName, E as ExtensionContributions, S as SchedulerFirePayload, C as ChatMessage, a as ChatOptions, G as GetModelsOptions, V as VoiceSessionOptions, b as StreamEvent, M as ModelInfo, c as VoiceSessionDescriptor, T as ToolResult, A as ActionResult } from './types.tools-XpXCoPrJ.js';
2
+ export { a7 as AIProvider, ad as Action, z as ActionsAPI, af as AllowedCSSProperty, a0 as BackgroundRestartPolicy, Z as BackgroundTaskCallback, Y as BackgroundTaskConfig, _ as BackgroundTaskContext, $ as BackgroundTaskHealth, X as BackgroundWorkersAPI, ar as ButtonProps, O as ChatAPI, a9 as ChatImage, Q as ChatInstructionMessage, aP as CheckboxProps, aJ as CollapsibleProps, u as CommandDefinition, aT as ConditionalGroupProps, R as ConversationPresentation, aw as DateTimeInputProps, D as Disposable, aC as DividerProps, B as EventsAPI, ak as ExtensionActionCall, al as ExtensionActionRef, aj as ExtensionComponentChildren, ah as ExtensionComponentData, ai as ExtensionComponentIterator, ag as ExtensionComponentStyle, v as ExtensionContext, am as ExtensionDataSource, ae as ExtensionModule, an as ExtensionPanelDefinition, aL as FrameProps, aK as FrameVariant, aB as GridProps, ao as HeaderProps, aA as HorizontalStackProps, aF as IconButtonProps, aE as IconButtonType, ay as IconPickerProps, aD as IconProps, ap as LabelProps, aM as ListProps, L as LocalizedString, W as LogAPI, aQ as MarkdownProps, aS as ModalProps, a8 as ModelCapabilities, N as NetworkAPI, au as NumberInputProps, aG as PanelAction, l as PanelActionDataSource, k as PanelComponentView, P as PanelDefinition, aH as PanelProps, m as PanelUnknownView, j as PanelView, aq as ParagraphProps, at as PasswordInputProps, aO as PillProps, aN as PillVariant, p as PromptContribution, q as PromptSection, o as ProviderConfigView, n as ProviderDefinition, x as ProvidersAPI, a1 as Query, a2 as QueryOptions, F as SchedulerAPI, I as SchedulerJobRequest, J as SchedulerSchedule, a4 as SecretsAPI, ax as SelectProps, w as SettingsAPI, a3 as StorageAPI, a5 as StorageCollectionConfig, a6 as StorageContributions, av as TextAreaProps, as as TextInputProps, aR as TextPreviewProps, aI as ToggleProps, ac as Tool, aa as ToolCall, t as ToolConfirmationConfig, s as ToolDefinition, i as ToolSettingsActionDataSource, h as ToolSettingsComponentView, g as ToolSettingsListMapping, f as ToolSettingsListView, e as ToolSettingsView, d as ToolSettingsViewDefinition, y as ToolsAPI, U as UserAPI, K as UserProfile, az as VerticalStackProps, ab as VoiceTransportRequest, r as resolveLocalizedString } from './types.tools-XpXCoPrJ.js';
3
3
 
4
4
  /**
5
5
  * Permission Types
@@ -1,5 +1,5 @@
1
- import { ad as ExtensionModule } from './types.tools-BZQrEs91.cjs';
2
- export { a7 as AIProvider, ac as Action, A as ActionResult, a0 as BackgroundRestartPolicy, Z as BackgroundTaskCallback, Y as BackgroundTaskConfig, _ as BackgroundTaskContext, $ as BackgroundTaskHealth, X as BackgroundWorkersAPI, C as ChatMessage, a as ChatOptions, D as Disposable, aT as ExecutionContext, v as ExtensionContext, G as GetModelsOptions, a8 as ModelCapabilities, M as ModelInfo, a1 as Query, a2 as QueryOptions, a4 as SecretsAPI, a3 as StorageAPI, b as StreamEvent, ab as Tool, a9 as ToolCall, s as ToolDefinition, T as ToolResult, c as VoiceSessionDescriptor, V as VoiceSessionOptions, aa as VoiceTransportRequest } from './types.tools-BZQrEs91.cjs';
1
+ import { ae as ExtensionModule } from './types.tools-XpXCoPrJ.cjs';
2
+ export { a7 as AIProvider, ad as Action, A as ActionResult, a0 as BackgroundRestartPolicy, Z as BackgroundTaskCallback, Y as BackgroundTaskConfig, _ as BackgroundTaskContext, $ as BackgroundTaskHealth, X as BackgroundWorkersAPI, C as ChatMessage, a as ChatOptions, D as Disposable, aU as ExecutionContext, v as ExtensionContext, G as GetModelsOptions, a8 as ModelCapabilities, M as ModelInfo, a1 as Query, a2 as QueryOptions, a4 as SecretsAPI, a3 as StorageAPI, b as StreamEvent, ac as Tool, aa as ToolCall, s as ToolDefinition, T as ToolResult, c as VoiceSessionDescriptor, V as VoiceSessionOptions, ab as VoiceTransportRequest } from './types.tools-XpXCoPrJ.cjs';
3
3
 
4
4
  /**
5
5
  * Extension Runtime - Runs inside the worker
package/dist/runtime.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { ad as ExtensionModule } from './types.tools-BZQrEs91.js';
2
- export { a7 as AIProvider, ac as Action, A as ActionResult, a0 as BackgroundRestartPolicy, Z as BackgroundTaskCallback, Y as BackgroundTaskConfig, _ as BackgroundTaskContext, $ as BackgroundTaskHealth, X as BackgroundWorkersAPI, C as ChatMessage, a as ChatOptions, D as Disposable, aT as ExecutionContext, v as ExtensionContext, G as GetModelsOptions, a8 as ModelCapabilities, M as ModelInfo, a1 as Query, a2 as QueryOptions, a4 as SecretsAPI, a3 as StorageAPI, b as StreamEvent, ab as Tool, a9 as ToolCall, s as ToolDefinition, T as ToolResult, c as VoiceSessionDescriptor, V as VoiceSessionOptions, aa as VoiceTransportRequest } from './types.tools-BZQrEs91.js';
1
+ import { ae as ExtensionModule } from './types.tools-XpXCoPrJ.js';
2
+ export { a7 as AIProvider, ad as Action, A as ActionResult, a0 as BackgroundRestartPolicy, Z as BackgroundTaskCallback, Y as BackgroundTaskConfig, _ as BackgroundTaskContext, $ as BackgroundTaskHealth, X as BackgroundWorkersAPI, C as ChatMessage, a as ChatOptions, D as Disposable, aU as ExecutionContext, v as ExtensionContext, G as GetModelsOptions, a8 as ModelCapabilities, M as ModelInfo, a1 as Query, a2 as QueryOptions, a4 as SecretsAPI, a3 as StorageAPI, b as StreamEvent, ac as Tool, aa as ToolCall, s as ToolDefinition, T as ToolResult, c as VoiceSessionDescriptor, V as VoiceSessionOptions, ab as VoiceTransportRequest } from './types.tools-XpXCoPrJ.js';
3
3
 
4
4
  /**
5
5
  * Extension Runtime - Runs inside the worker
@@ -798,6 +798,15 @@ interface ModelCapabilities {
798
798
  * voice with one kind of credential and not another.
799
799
  */
800
800
  voiceDuplex?: boolean;
801
+ /**
802
+ * The model can be shown images alongside the text of a message.
803
+ *
804
+ * Report this per model *and* per auth mode, like `voiceDuplex`: the same
805
+ * provider often serves both a vision model and a text-only one, and a picture
806
+ * sent to the latter is at best ignored and at worst an error mid-conversation.
807
+ * Stina uses it to decide whether the paperclip is offered at all.
808
+ */
809
+ vision?: boolean;
801
810
  }
802
811
  /**
803
812
  * How the client wants to connect to the voice session.
@@ -885,11 +894,37 @@ interface VoiceSessionOptions {
885
894
  interface ChatMessage {
886
895
  role: 'user' | 'assistant' | 'system' | 'tool';
887
896
  content: string;
897
+ /**
898
+ * Images the user attached to this message, already decoded and ready to send.
899
+ *
900
+ * Additive: a provider that ignores the field behaves exactly as it did before,
901
+ * which is why the text is still in `content` rather than being moved into a
902
+ * parts array. A provider that supports vision should report
903
+ * `capabilities.vision` and fold these into whatever multimodal shape its API
904
+ * expects.
905
+ *
906
+ * Only ever `image/jpeg` or `image/png` — see `ChatAttachmentDTO` for why.
907
+ */
908
+ images?: ChatImage[];
888
909
  /** For assistant messages: tool calls made by the model */
889
910
  tool_calls?: ToolCall[];
890
911
  /** For tool messages: the ID of the tool call this is a response to */
891
912
  tool_call_id?: string;
892
913
  }
914
+ /**
915
+ * One image on a chat message, carried as bytes rather than as a URL.
916
+ *
917
+ * A URL would have to be reachable *from the provider*, and Stina commonly runs
918
+ * on a home server talking to a model on the same LAN or on the machine next to
919
+ * it. There is no address that is both private enough and reachable enough, so
920
+ * the bytes travel with the request.
921
+ */
922
+ interface ChatImage {
923
+ /** `image/jpeg` or `image/png`. */
924
+ mime: string;
925
+ /** The image itself, base64 with no data-URI prefix. */
926
+ data: string;
927
+ }
893
928
  /**
894
929
  * A tool call made by the model
895
930
  */
@@ -1547,6 +1582,12 @@ interface ConversationPresentation {
1547
1582
  * preview. Finished builds, deliveries, completed jobs.
1548
1583
  * - `insight` — Stina's own observation or suggestion rather than an extension's
1549
1584
  * report. Rendered in her own voice with a soft accent panel.
1585
+ *
1586
+ * The variant also picks how the entry is decorated, so that two kinds of card
1587
+ * never resolve to the same picture: `note`, `message` and `status` are drawn
1588
+ * light, on an accent rail, while `event`, `digest` and `insight` sit on a
1589
+ * filled plate. Severity governs how strongly that decoration is drawn, never
1590
+ * which of the two it is.
1550
1591
  */
1551
1592
  variant?: 'note' | 'event' | 'message' | 'digest' | 'status' | 'insight';
1552
1593
  /**
@@ -1570,6 +1611,19 @@ interface ConversationPresentation {
1570
1611
  at?: string;
1571
1612
  /** Who sent it. Only used by `variant: 'message'`. */
1572
1613
  sender?: LocalizedString;
1614
+ /**
1615
+ * The domain the message came from, which lets the list show the sender's own
1616
+ * icon in place of their initials. Only used by `variant: 'message'`.
1617
+ *
1618
+ * Report it in whatever form you hold it — `plex.tv`, `no-reply@plex.tv`, or
1619
+ * `Plex <no-reply@plex.tv>` all work, and the domain is taken out and
1620
+ * normalised for you. Never localised: it is an identifier, not a label.
1621
+ *
1622
+ * Stina fetches the icon herself, from her own server, and caches it. Nothing
1623
+ * about the message is sent anywhere, and no third-party icon service is
1624
+ * consulted; a domain that has no icon simply falls back to the initials.
1625
+ */
1626
+ senderDomain?: string;
1573
1627
  /**
1574
1628
  * The collected items. Only used by `variant: 'digest'`; at most three are
1575
1629
  * rendered, and `count` reports the true total when there are more.
@@ -1905,4 +1959,4 @@ interface ActionResult {
1905
1959
  error?: string;
1906
1960
  }
1907
1961
 
1908
- export { type BackgroundTaskHealth as $, type ActionResult as A, type EventsAPI as B, type ChatMessage as C, type Disposable as D, type ExtensionContributions as E, type SchedulerAPI as F, type GetModelsOptions as G, type HugeIconName as H, type SchedulerJobRequest as I, type SchedulerSchedule as J, type UserProfile as K, type LocalizedString as L, type ModelInfo as M, type NetworkAPI as N, type ChatAPI as O, type PanelDefinition as P, type ChatInstructionMessage as Q, type ConversationPresentation as R, type SchedulerFirePayload as S, type ToolResult as T, type UserAPI as U, type VoiceSessionOptions as V, type LogAPI as W, type BackgroundWorkersAPI as X, type BackgroundTaskConfig as Y, type BackgroundTaskCallback as Z, type BackgroundTaskContext as _, type ChatOptions as a, type BackgroundRestartPolicy as a0, type Query as a1, type QueryOptions as a2, type StorageAPI as a3, type SecretsAPI as a4, type StorageCollectionConfig as a5, type StorageContributions as a6, type AIProvider as a7, type ModelCapabilities as a8, type ToolCall as a9, type GridProps as aA, type DividerProps as aB, type IconProps as aC, type IconButtonType as aD, type IconButtonProps as aE, type PanelAction as aF, type PanelProps as aG, type ToggleProps as aH, type CollapsibleProps as aI, type FrameVariant as aJ, type FrameProps as aK, type ListProps as aL, type PillVariant as aM, type PillProps as aN, type CheckboxProps as aO, type MarkdownProps as aP, type TextPreviewProps as aQ, type ModalProps as aR, type ConditionalGroupProps as aS, type ExecutionContext as aT, type VoiceTransportRequest as aa, type Tool as ab, type Action as ac, type ExtensionModule as ad, type AllowedCSSProperty as ae, type ExtensionComponentStyle as af, type ExtensionComponentData as ag, type ExtensionComponentIterator as ah, type ExtensionComponentChildren as ai, type ExtensionActionCall as aj, type ExtensionActionRef as ak, type ExtensionDataSource as al, type ExtensionPanelDefinition as am, type HeaderProps as an, type LabelProps as ao, type ParagraphProps as ap, type ButtonProps as aq, type TextInputProps as ar, type PasswordInputProps as as, type NumberInputProps as at, type TextAreaProps as au, type DateTimeInputProps as av, type SelectProps as aw, type IconPickerProps as ax, type VerticalStackProps as ay, type HorizontalStackProps as az, type StreamEvent as b, type VoiceSessionDescriptor as c, type ToolSettingsViewDefinition as d, type ToolSettingsView as e, type ToolSettingsListView as f, type ToolSettingsListMapping as g, type ToolSettingsComponentView as h, type ToolSettingsActionDataSource as i, type PanelView as j, type PanelComponentView as k, type PanelActionDataSource as l, type PanelUnknownView as m, type ProviderDefinition as n, type ProviderConfigView as o, type PromptContribution as p, type PromptSection as q, resolveLocalizedString as r, type ToolDefinition as s, type ToolConfirmationConfig as t, type CommandDefinition as u, type ExtensionContext as v, type SettingsAPI as w, type ProvidersAPI as x, type ToolsAPI as y, type ActionsAPI as z };
1962
+ export { type BackgroundTaskHealth as $, type ActionResult as A, type EventsAPI as B, type ChatMessage as C, type Disposable as D, type ExtensionContributions as E, type SchedulerAPI as F, type GetModelsOptions as G, type HugeIconName as H, type SchedulerJobRequest as I, type SchedulerSchedule as J, type UserProfile as K, type LocalizedString as L, type ModelInfo as M, type NetworkAPI as N, type ChatAPI as O, type PanelDefinition as P, type ChatInstructionMessage as Q, type ConversationPresentation as R, type SchedulerFirePayload as S, type ToolResult as T, type UserAPI as U, type VoiceSessionOptions as V, type LogAPI as W, type BackgroundWorkersAPI as X, type BackgroundTaskConfig as Y, type BackgroundTaskCallback as Z, type BackgroundTaskContext as _, type ChatOptions as a, type BackgroundRestartPolicy as a0, type Query as a1, type QueryOptions as a2, type StorageAPI as a3, type SecretsAPI as a4, type StorageCollectionConfig as a5, type StorageContributions as a6, type AIProvider as a7, type ModelCapabilities as a8, type ChatImage as a9, type HorizontalStackProps as aA, type GridProps as aB, type DividerProps as aC, type IconProps as aD, type IconButtonType as aE, type IconButtonProps as aF, type PanelAction as aG, type PanelProps as aH, type ToggleProps as aI, type CollapsibleProps as aJ, type FrameVariant as aK, type FrameProps as aL, type ListProps as aM, type PillVariant as aN, type PillProps as aO, type CheckboxProps as aP, type MarkdownProps as aQ, type TextPreviewProps as aR, type ModalProps as aS, type ConditionalGroupProps as aT, type ExecutionContext as aU, type ToolCall as aa, type VoiceTransportRequest as ab, type Tool as ac, type Action as ad, type ExtensionModule as ae, type AllowedCSSProperty as af, type ExtensionComponentStyle as ag, type ExtensionComponentData as ah, type ExtensionComponentIterator as ai, type ExtensionComponentChildren as aj, type ExtensionActionCall as ak, type ExtensionActionRef as al, type ExtensionDataSource as am, type ExtensionPanelDefinition as an, type HeaderProps as ao, type LabelProps as ap, type ParagraphProps as aq, type ButtonProps as ar, type TextInputProps as as, type PasswordInputProps as at, type NumberInputProps as au, type TextAreaProps as av, type DateTimeInputProps as aw, type SelectProps as ax, type IconPickerProps as ay, type VerticalStackProps as az, type StreamEvent as b, type VoiceSessionDescriptor as c, type ToolSettingsViewDefinition as d, type ToolSettingsView as e, type ToolSettingsListView as f, type ToolSettingsListMapping as g, type ToolSettingsComponentView as h, type ToolSettingsActionDataSource as i, type PanelView as j, type PanelComponentView as k, type PanelActionDataSource as l, type PanelUnknownView as m, type ProviderDefinition as n, type ProviderConfigView as o, type PromptContribution as p, type PromptSection as q, resolveLocalizedString as r, type ToolDefinition as s, type ToolConfirmationConfig as t, type CommandDefinition as u, type ExtensionContext as v, type SettingsAPI as w, type ProvidersAPI as x, type ToolsAPI as y, type ActionsAPI as z };
@@ -798,6 +798,15 @@ interface ModelCapabilities {
798
798
  * voice with one kind of credential and not another.
799
799
  */
800
800
  voiceDuplex?: boolean;
801
+ /**
802
+ * The model can be shown images alongside the text of a message.
803
+ *
804
+ * Report this per model *and* per auth mode, like `voiceDuplex`: the same
805
+ * provider often serves both a vision model and a text-only one, and a picture
806
+ * sent to the latter is at best ignored and at worst an error mid-conversation.
807
+ * Stina uses it to decide whether the paperclip is offered at all.
808
+ */
809
+ vision?: boolean;
801
810
  }
802
811
  /**
803
812
  * How the client wants to connect to the voice session.
@@ -885,11 +894,37 @@ interface VoiceSessionOptions {
885
894
  interface ChatMessage {
886
895
  role: 'user' | 'assistant' | 'system' | 'tool';
887
896
  content: string;
897
+ /**
898
+ * Images the user attached to this message, already decoded and ready to send.
899
+ *
900
+ * Additive: a provider that ignores the field behaves exactly as it did before,
901
+ * which is why the text is still in `content` rather than being moved into a
902
+ * parts array. A provider that supports vision should report
903
+ * `capabilities.vision` and fold these into whatever multimodal shape its API
904
+ * expects.
905
+ *
906
+ * Only ever `image/jpeg` or `image/png` — see `ChatAttachmentDTO` for why.
907
+ */
908
+ images?: ChatImage[];
888
909
  /** For assistant messages: tool calls made by the model */
889
910
  tool_calls?: ToolCall[];
890
911
  /** For tool messages: the ID of the tool call this is a response to */
891
912
  tool_call_id?: string;
892
913
  }
914
+ /**
915
+ * One image on a chat message, carried as bytes rather than as a URL.
916
+ *
917
+ * A URL would have to be reachable *from the provider*, and Stina commonly runs
918
+ * on a home server talking to a model on the same LAN or on the machine next to
919
+ * it. There is no address that is both private enough and reachable enough, so
920
+ * the bytes travel with the request.
921
+ */
922
+ interface ChatImage {
923
+ /** `image/jpeg` or `image/png`. */
924
+ mime: string;
925
+ /** The image itself, base64 with no data-URI prefix. */
926
+ data: string;
927
+ }
893
928
  /**
894
929
  * A tool call made by the model
895
930
  */
@@ -1547,6 +1582,12 @@ interface ConversationPresentation {
1547
1582
  * preview. Finished builds, deliveries, completed jobs.
1548
1583
  * - `insight` — Stina's own observation or suggestion rather than an extension's
1549
1584
  * report. Rendered in her own voice with a soft accent panel.
1585
+ *
1586
+ * The variant also picks how the entry is decorated, so that two kinds of card
1587
+ * never resolve to the same picture: `note`, `message` and `status` are drawn
1588
+ * light, on an accent rail, while `event`, `digest` and `insight` sit on a
1589
+ * filled plate. Severity governs how strongly that decoration is drawn, never
1590
+ * which of the two it is.
1550
1591
  */
1551
1592
  variant?: 'note' | 'event' | 'message' | 'digest' | 'status' | 'insight';
1552
1593
  /**
@@ -1570,6 +1611,19 @@ interface ConversationPresentation {
1570
1611
  at?: string;
1571
1612
  /** Who sent it. Only used by `variant: 'message'`. */
1572
1613
  sender?: LocalizedString;
1614
+ /**
1615
+ * The domain the message came from, which lets the list show the sender's own
1616
+ * icon in place of their initials. Only used by `variant: 'message'`.
1617
+ *
1618
+ * Report it in whatever form you hold it — `plex.tv`, `no-reply@plex.tv`, or
1619
+ * `Plex <no-reply@plex.tv>` all work, and the domain is taken out and
1620
+ * normalised for you. Never localised: it is an identifier, not a label.
1621
+ *
1622
+ * Stina fetches the icon herself, from her own server, and caches it. Nothing
1623
+ * about the message is sent anywhere, and no third-party icon service is
1624
+ * consulted; a domain that has no icon simply falls back to the initials.
1625
+ */
1626
+ senderDomain?: string;
1573
1627
  /**
1574
1628
  * The collected items. Only used by `variant: 'digest'`; at most three are
1575
1629
  * rendered, and `count` reports the true total when there are more.
@@ -1905,4 +1959,4 @@ interface ActionResult {
1905
1959
  error?: string;
1906
1960
  }
1907
1961
 
1908
- export { type BackgroundTaskHealth as $, type ActionResult as A, type EventsAPI as B, type ChatMessage as C, type Disposable as D, type ExtensionContributions as E, type SchedulerAPI as F, type GetModelsOptions as G, type HugeIconName as H, type SchedulerJobRequest as I, type SchedulerSchedule as J, type UserProfile as K, type LocalizedString as L, type ModelInfo as M, type NetworkAPI as N, type ChatAPI as O, type PanelDefinition as P, type ChatInstructionMessage as Q, type ConversationPresentation as R, type SchedulerFirePayload as S, type ToolResult as T, type UserAPI as U, type VoiceSessionOptions as V, type LogAPI as W, type BackgroundWorkersAPI as X, type BackgroundTaskConfig as Y, type BackgroundTaskCallback as Z, type BackgroundTaskContext as _, type ChatOptions as a, type BackgroundRestartPolicy as a0, type Query as a1, type QueryOptions as a2, type StorageAPI as a3, type SecretsAPI as a4, type StorageCollectionConfig as a5, type StorageContributions as a6, type AIProvider as a7, type ModelCapabilities as a8, type ToolCall as a9, type GridProps as aA, type DividerProps as aB, type IconProps as aC, type IconButtonType as aD, type IconButtonProps as aE, type PanelAction as aF, type PanelProps as aG, type ToggleProps as aH, type CollapsibleProps as aI, type FrameVariant as aJ, type FrameProps as aK, type ListProps as aL, type PillVariant as aM, type PillProps as aN, type CheckboxProps as aO, type MarkdownProps as aP, type TextPreviewProps as aQ, type ModalProps as aR, type ConditionalGroupProps as aS, type ExecutionContext as aT, type VoiceTransportRequest as aa, type Tool as ab, type Action as ac, type ExtensionModule as ad, type AllowedCSSProperty as ae, type ExtensionComponentStyle as af, type ExtensionComponentData as ag, type ExtensionComponentIterator as ah, type ExtensionComponentChildren as ai, type ExtensionActionCall as aj, type ExtensionActionRef as ak, type ExtensionDataSource as al, type ExtensionPanelDefinition as am, type HeaderProps as an, type LabelProps as ao, type ParagraphProps as ap, type ButtonProps as aq, type TextInputProps as ar, type PasswordInputProps as as, type NumberInputProps as at, type TextAreaProps as au, type DateTimeInputProps as av, type SelectProps as aw, type IconPickerProps as ax, type VerticalStackProps as ay, type HorizontalStackProps as az, type StreamEvent as b, type VoiceSessionDescriptor as c, type ToolSettingsViewDefinition as d, type ToolSettingsView as e, type ToolSettingsListView as f, type ToolSettingsListMapping as g, type ToolSettingsComponentView as h, type ToolSettingsActionDataSource as i, type PanelView as j, type PanelComponentView as k, type PanelActionDataSource as l, type PanelUnknownView as m, type ProviderDefinition as n, type ProviderConfigView as o, type PromptContribution as p, type PromptSection as q, resolveLocalizedString as r, type ToolDefinition as s, type ToolConfirmationConfig as t, type CommandDefinition as u, type ExtensionContext as v, type SettingsAPI as w, type ProvidersAPI as x, type ToolsAPI as y, type ActionsAPI as z };
1962
+ export { type BackgroundTaskHealth as $, type ActionResult as A, type EventsAPI as B, type ChatMessage as C, type Disposable as D, type ExtensionContributions as E, type SchedulerAPI as F, type GetModelsOptions as G, type HugeIconName as H, type SchedulerJobRequest as I, type SchedulerSchedule as J, type UserProfile as K, type LocalizedString as L, type ModelInfo as M, type NetworkAPI as N, type ChatAPI as O, type PanelDefinition as P, type ChatInstructionMessage as Q, type ConversationPresentation as R, type SchedulerFirePayload as S, type ToolResult as T, type UserAPI as U, type VoiceSessionOptions as V, type LogAPI as W, type BackgroundWorkersAPI as X, type BackgroundTaskConfig as Y, type BackgroundTaskCallback as Z, type BackgroundTaskContext as _, type ChatOptions as a, type BackgroundRestartPolicy as a0, type Query as a1, type QueryOptions as a2, type StorageAPI as a3, type SecretsAPI as a4, type StorageCollectionConfig as a5, type StorageContributions as a6, type AIProvider as a7, type ModelCapabilities as a8, type ChatImage as a9, type HorizontalStackProps as aA, type GridProps as aB, type DividerProps as aC, type IconProps as aD, type IconButtonType as aE, type IconButtonProps as aF, type PanelAction as aG, type PanelProps as aH, type ToggleProps as aI, type CollapsibleProps as aJ, type FrameVariant as aK, type FrameProps as aL, type ListProps as aM, type PillVariant as aN, type PillProps as aO, type CheckboxProps as aP, type MarkdownProps as aQ, type TextPreviewProps as aR, type ModalProps as aS, type ConditionalGroupProps as aT, type ExecutionContext as aU, type ToolCall as aa, type VoiceTransportRequest as ab, type Tool as ac, type Action as ad, type ExtensionModule as ae, type AllowedCSSProperty as af, type ExtensionComponentStyle as ag, type ExtensionComponentData as ah, type ExtensionComponentIterator as ai, type ExtensionComponentChildren as aj, type ExtensionActionCall as ak, type ExtensionActionRef as al, type ExtensionDataSource as am, type ExtensionPanelDefinition as an, type HeaderProps as ao, type LabelProps as ap, type ParagraphProps as aq, type ButtonProps as ar, type TextInputProps as as, type PasswordInputProps as at, type NumberInputProps as au, type TextAreaProps as av, type DateTimeInputProps as aw, type SelectProps as ax, type IconPickerProps as ay, type VerticalStackProps as az, type StreamEvent as b, type VoiceSessionDescriptor as c, type ToolSettingsViewDefinition as d, type ToolSettingsView as e, type ToolSettingsListView as f, type ToolSettingsListMapping as g, type ToolSettingsComponentView as h, type ToolSettingsActionDataSource as i, type PanelView as j, type PanelComponentView as k, type PanelActionDataSource as l, type PanelUnknownView as m, type ProviderDefinition as n, type ProviderConfigView as o, type PromptContribution as p, type PromptSection as q, resolveLocalizedString as r, type ToolDefinition as s, type ToolConfirmationConfig as t, type CommandDefinition as u, type ExtensionContext as v, type SettingsAPI as w, type ProvidersAPI as x, type ToolsAPI as y, type ActionsAPI as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stina/extension-api",
3
- "version": "0.44.0",
3
+ "version": "0.52.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
package/src/index.ts CHANGED
@@ -85,6 +85,7 @@ export type {
85
85
  ModelInfo,
86
86
  ModelCapabilities,
87
87
  ChatMessage,
88
+ ChatImage,
88
89
  ChatOptions,
89
90
  GetModelsOptions,
90
91
  StreamEvent,
@@ -352,6 +352,12 @@ export interface ConversationPresentation {
352
352
  * preview. Finished builds, deliveries, completed jobs.
353
353
  * - `insight` — Stina's own observation or suggestion rather than an extension's
354
354
  * report. Rendered in her own voice with a soft accent panel.
355
+ *
356
+ * The variant also picks how the entry is decorated, so that two kinds of card
357
+ * never resolve to the same picture: `note`, `message` and `status` are drawn
358
+ * light, on an accent rail, while `event`, `digest` and `insight` sit on a
359
+ * filled plate. Severity governs how strongly that decoration is drawn, never
360
+ * which of the two it is.
355
361
  */
356
362
  variant?: 'note' | 'event' | 'message' | 'digest' | 'status' | 'insight'
357
363
  /**
@@ -375,6 +381,19 @@ export interface ConversationPresentation {
375
381
  at?: string
376
382
  /** Who sent it. Only used by `variant: 'message'`. */
377
383
  sender?: LocalizedString
384
+ /**
385
+ * The domain the message came from, which lets the list show the sender's own
386
+ * icon in place of their initials. Only used by `variant: 'message'`.
387
+ *
388
+ * Report it in whatever form you hold it — `plex.tv`, `no-reply@plex.tv`, or
389
+ * `Plex <no-reply@plex.tv>` all work, and the domain is taken out and
390
+ * normalised for you. Never localised: it is an identifier, not a label.
391
+ *
392
+ * Stina fetches the icon herself, from her own server, and caches it. Nothing
393
+ * about the message is sent anywhere, and no third-party icon service is
394
+ * consulted; a domain that has no icon simply falls back to the initials.
395
+ */
396
+ senderDomain?: string
378
397
  /**
379
398
  * The collected items. Only used by `variant: 'digest'`; at most three are
380
399
  * rendered, and `count` reports the true total when there are more.
@@ -82,6 +82,16 @@ export interface ModelCapabilities {
82
82
  * voice with one kind of credential and not another.
83
83
  */
84
84
  voiceDuplex?: boolean
85
+
86
+ /**
87
+ * The model can be shown images alongside the text of a message.
88
+ *
89
+ * Report this per model *and* per auth mode, like `voiceDuplex`: the same
90
+ * provider often serves both a vision model and a text-only one, and a picture
91
+ * sent to the latter is at best ignored and at worst an error mid-conversation.
92
+ * Stina uses it to decide whether the paperclip is offered at all.
93
+ */
94
+ vision?: boolean
85
95
  }
86
96
 
87
97
  /**
@@ -167,12 +177,39 @@ export interface VoiceSessionOptions {
167
177
  export interface ChatMessage {
168
178
  role: 'user' | 'assistant' | 'system' | 'tool'
169
179
  content: string
180
+ /**
181
+ * Images the user attached to this message, already decoded and ready to send.
182
+ *
183
+ * Additive: a provider that ignores the field behaves exactly as it did before,
184
+ * which is why the text is still in `content` rather than being moved into a
185
+ * parts array. A provider that supports vision should report
186
+ * `capabilities.vision` and fold these into whatever multimodal shape its API
187
+ * expects.
188
+ *
189
+ * Only ever `image/jpeg` or `image/png` — see `ChatAttachmentDTO` for why.
190
+ */
191
+ images?: ChatImage[]
170
192
  /** For assistant messages: tool calls made by the model */
171
193
  tool_calls?: ToolCall[]
172
194
  /** For tool messages: the ID of the tool call this is a response to */
173
195
  tool_call_id?: string
174
196
  }
175
197
 
198
+ /**
199
+ * One image on a chat message, carried as bytes rather than as a URL.
200
+ *
201
+ * A URL would have to be reachable *from the provider*, and Stina commonly runs
202
+ * on a home server talking to a model on the same LAN or on the machine next to
203
+ * it. There is no address that is both private enough and reachable enough, so
204
+ * the bytes travel with the request.
205
+ */
206
+ export interface ChatImage {
207
+ /** `image/jpeg` or `image/png`. */
208
+ mime: string
209
+ /** The image itself, base64 with no data-URI prefix. */
210
+ data: string
211
+ }
212
+
176
213
  /**
177
214
  * A tool call made by the model
178
215
  */
package/src/types.ts CHANGED
@@ -57,6 +57,7 @@ export type {
57
57
  ModelInfo,
58
58
  ModelCapabilities,
59
59
  ChatMessage,
60
+ ChatImage,
60
61
  ToolCall,
61
62
  ChatOptions,
62
63
  GetModelsOptions,