@stina/extension-api 1.17.0 → 1.18.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/types.contributions.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'\nexport { EXTENSION_SETTINGS_TOPICS } from './types.js'\n\n// Types\nexport type {\n // Manifest\n ExtensionManifest,\n Platform,\n ExtensionContributions,\n ToolSettingsViewDefinition,\n ExtensionSettingsTopic,\n ToolSettingsView,\n ToolSettingsListView,\n ToolSettingsListMapping,\n ToolSettingsComponentView,\n ToolSettingsActionDataSource,\n PanelDefinition,\n StatusCardDefinition,\n PanelView,\n PanelComponentView,\n PanelActionDataSource,\n PanelUnknownView,\n ProviderDefinition,\n ProviderConfigView,\n PromptContribution,\n PromptSection,\n ToolDefinition,\n ToolConfirmationConfig,\n CommandDefinition,\n AccountProvider,\n AccountContribution,\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 AttachmentsAPI,\n AttachmentContent,\n ConnectedAccountsAPI,\n ConnectedAccount,\n AccountAccessToken,\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 ChatFile,\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 ToolAttachment,\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 ClockProps,\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 // Purpose-built display components\n WeatherCondition,\n WeatherWind,\n WeatherNowProps,\n WeatherForecastStep,\n WeatherForecastProps,\n ChartKind,\n ChartSeries,\n ChartProps,\n StatTrend,\n StatTileProps,\n ProgressShape,\n ProgressColor,\n ProgressBarProps,\n KeyValueRow,\n KeyValueListProps,\n TimelineVariant,\n TimelineEntry,\n TimelineProps,\n NoteVariant,\n NoteProps,\n CalendarEventStatus,\n CalendarEventProps,\n AgendaEvent,\n AgendaDay,\n AgendaProps,\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 * Contribution Types\n *\n * Types for extension contributions: settings, panels, providers, tools, commands, prompts.\n */\n\nimport type { LocalizedString } from './types.localization.js'\nimport type { ExtensionComponentData } from './types.components.js'\n\n/**\n * What an extension can contribute to Stina\n */\nexport interface ExtensionContributions {\n /** Tool settings views for UI */\n toolSettings?: ToolSettingsViewDefinition[]\n /** Cards for the strip above the conversation list */\n statusCards?: StatusCardDefinition[]\n /** Right panel contributions */\n panels?: PanelDefinition[]\n /** AI providers */\n providers?: ProviderDefinition[]\n /** Tools for Stina to use */\n tools?: ToolDefinition[]\n /** Slash commands */\n commands?: CommandDefinition[]\n /** Prompt contributions for the system prompt */\n prompts?: PromptContribution[]\n /** External accounts the extension works through, signed in once in Stina's settings */\n accounts?: AccountContribution[]\n /** Storage collection declarations */\n storage?: {\n collections: {\n [name: string]: {\n /** Fields to index for fast queries */\n indexes?: string[]\n }\n }\n }\n}\n\n// ============================================================================\n// Connected Accounts\n// ============================================================================\n\n/**\n * An external account provider the host can sign in to on the user's behalf.\n *\n * Only Microsoft for now, and only through Microsoft Graph: mail and calendar\n * then share one sign-in and one token, instead of an IMAP token and a Graph\n * token that an admin has to approve separately.\n */\nexport type AccountProvider = 'microsoft'\n\n/**\n * What an extension needs from an account the user connects to Stina.\n *\n * Stina asks the provider for every scope that the enabled extensions declare,\n * all at once, so that the user - and, at work, their administrator - approves\n * one request instead of one per extension. Declaring a scope here is therefore\n * also what makes it show up in that request, and in the list of what is asked\n * for in the settings.\n *\n * @example\n * ```json\n * \"accounts\": [\n * {\n * \"provider\": \"microsoft\",\n * \"scopes\": [\"Calendars.ReadWrite\"],\n * \"reason\": { \"en\": \"Read and book events in your calendar\", \"sv\": \"Läsa och boka i din kalender\" }\n * }\n * ]\n * ```\n */\nexport interface AccountContribution {\n provider: AccountProvider\n /**\n * Microsoft Graph delegated permissions, by name: `Mail.Read`,\n * `Calendars.ReadWrite`. The host adds `offline_access` and `User.Read`\n * itself, so they are not declared here.\n */\n scopes: string[]\n /** Why the extension needs them, shown next to the scopes in the settings. */\n reason?: LocalizedString\n}\n\n// ============================================================================\n// Tool Settings Views\n// ============================================================================\n\n/**\n * What a settings view is about, which decides where Stina shows it.\n *\n * An extension never picks a place in the settings menu: the menu belongs to Stina and\n * changes between versions. It says what the view is *about*, and Stina puts each topic\n * where it belongs, the way `accounts`, `providers` and `statusCards` already work.\n *\n * - `accounts`: connects Stina to an account or a service (a mailbox, a calendar feed).\n * Shown with the other connected accounts.\n * - `notifications`: when and how the extension may get in touch. Shown with Stina's own\n * notification settings.\n * - `personal`: facts about the user the extension relies on (a home town for the\n * weather). Shown with the profile.\n * - `tracking`: things Stina keeps track of for the user that are worth looking through\n * now and then (people, projects, reminders). Gets its own row in the register.\n *\n * A view without a topic, or with one this version of Stina does not know, is shown on\n * the extension's own page. That is always a working place, only a less fitting one, so\n * a topic added later never breaks an older Stina.\n */\nexport type ExtensionSettingsTopic = 'accounts' | 'notifications' | 'personal' | 'tracking'\n\n/** Every topic this version of the API knows, in no particular order. */\nexport const EXTENSION_SETTINGS_TOPICS: readonly ExtensionSettingsTopic[] = [\n 'accounts',\n 'notifications',\n 'personal',\n 'tracking',\n]\n\n/**\n * Tool settings view definition (UI schema)\n */\nexport interface ToolSettingsViewDefinition {\n /** Unique view ID within the extension */\n id: string\n /** Display title */\n title: string\n /** Help text */\n description?: string\n /** What the view is about, and so where Stina shows it. See {@link ExtensionSettingsTopic}. */\n topic?: ExtensionSettingsTopic\n /** View configuration */\n view: ToolSettingsView\n}\n\n/**\n * Tool settings view types\n */\nexport type ToolSettingsView = ToolSettingsListView | ToolSettingsComponentView\n\n/**\n * List view backed by tools\n */\nexport interface ToolSettingsListView {\n /** View kind */\n kind: 'list'\n /** Tool ID for listing items */\n listToolId: string\n /** Tool ID for fetching details (optional) */\n getToolId?: string\n /** Tool ID for creating/updating items (optional) */\n upsertToolId?: string\n /** Tool ID for deleting items (optional) */\n deleteToolId?: string\n /** Mapping from tool data to UI fields */\n mapping: ToolSettingsListMapping\n /** Param name for search query (default: \"query\") */\n searchParam?: string\n /** Param name for limit (default: \"limit\") */\n limitParam?: string\n /** Param name for get/delete ID (default: \"id\") */\n idParam?: string\n /** Static params always sent to list tool */\n listParams?: Record<string, unknown>\n /**\n * Component-tree-based create/edit form. Fields bind to the current\n * item via `value: \"$item.<key>\"` (or `selectedValue` / `checked`),\n * and the host saves the resulting object via `upsertToolId` when\n * the user clicks \"Save\".\n */\n editView?: {\n /** Root component to render in the create/edit modal. */\n content: ExtensionComponentData\n }\n /** Optional grouping configuration. When set, items are visually grouped by this field. */\n groupBy?: ToolSettingsListGroupBy\n}\n\n/**\n * Configures grouping for a list view. Items are grouped by the value\n * of `key` on each item; groups appear in the order specified by `order`\n * (with unlisted groups falling back to alphabetical order at the end).\n */\nexport interface ToolSettingsListGroupBy {\n /** Key in each item used to determine group membership. */\n key: string\n /** Explicit ordering of group values. Groups not listed appear afterwards, sorted alphabetically. */\n order?: string[]\n /** Human-friendly labels per group value (rendered as section headers). Falls back to the raw value if missing. */\n labels?: Record<string, string>\n}\n\n/**\n * Mapping from tool list data to UI fields\n */\nexport interface ToolSettingsListMapping {\n /** Key for items array in tool result data */\n itemsKey: string\n /** Key for total count in tool result data */\n countKey?: string\n /** Key for item ID */\n idKey: string\n /** Key for item label */\n labelKey: string\n /** Key for item description */\n descriptionKey?: string\n /** Key for secondary label */\n secondaryKey?: string\n}\n\n/**\n * Component-based tool settings view using the declarative DSL.\n * Reuses the same structure as PanelComponentView for consistency.\n */\nexport interface ToolSettingsComponentView {\n /** View kind */\n kind: 'component'\n /** Data sources. Keys become scope variables (e.g., \"$settings\"). */\n data?: Record<string, ToolSettingsActionDataSource>\n /** Root component to render */\n content: ExtensionComponentData\n}\n\n/**\n * Action-based data source for tool settings.\n */\nexport interface ToolSettingsActionDataSource {\n /** Action ID to call for fetching data */\n action: string\n /** Parameters to pass to the action */\n params?: Record<string, unknown>\n /** Event names that trigger refresh */\n refreshOn?: string[]\n}\n\n// ============================================================================\n// Panels\n// ============================================================================\n\n/**\n * Panel definition for right panel views\n */\nexport interface PanelDefinition {\n /** Unique panel ID within the extension */\n id: string\n /** Display title */\n title: string\n /** Icon name (from huge-icons) */\n icon?: string\n /** Panel view schema */\n view: PanelView\n}\n\n/**\n * A card for the strip above the conversation list.\n *\n * The same declarative machinery as a panel, in a much smaller space and with\n * one rule that is not a style guide: a card says what is true right now. It\n * has no controls, because a sidebar is read in passing and anything the user\n * wants to do about what it says, they say in words.\n *\n * The user chooses which cards they want and in what order, so an extension\n * offering three is offering three, not imposing them.\n */\nexport interface StatusCardDefinition {\n /** Unique card ID within the extension */\n id: string\n /** What it is called where the user picks it */\n title: string\n /** Icon name (from huge-icons) */\n icon?: string\n /**\n * How much room it may take.\n *\n * Part of the contract rather than a guideline, because the sidebar is a few\n * hundred pixels wide and the first card written without a limit will be\n * written against a screen.\n *\n * - `line`: one row. A figure, a label, a pill.\n * - `block`: up to three rows.\n */\n size: 'line' | 'block'\n /** What it draws, and where the data comes from */\n view: PanelComponentView\n}\n\n/**\n * Panel view schema (declarative)\n */\nexport type PanelView = PanelComponentView | PanelUnknownView\n\nexport interface PanelUnknownView {\n /** View kind */\n kind: string\n /** Additional view configuration */\n [key: string]: unknown\n}\n\n/**\n * Action-based data source for declarative panels.\n * Uses actions (not tools) to fetch data.\n */\nexport interface PanelActionDataSource {\n /** Action ID to call for fetching data */\n action: string\n /** Parameters to pass to the action */\n params?: Record<string, unknown>\n /** Event names that should trigger a refresh of this data */\n refreshOn?: string[]\n}\n\n/**\n * Component-based panel view using the declarative DSL.\n * Data is fetched via actions, content is rendered via ExtensionComponent.\n */\nexport interface PanelComponentView {\n kind: 'component'\n /** Data sources available in the panel. Keys become variable names (e.g., \"$projects\"). */\n data?: Record<string, PanelActionDataSource>\n /** Root component to render */\n content: ExtensionComponentData\n}\n\n// ============================================================================\n// Providers\n// ============================================================================\n\n/**\n * Provider definition (metadata only, implementation in code)\n */\nexport interface ProviderDefinition {\n /** Provider ID */\n id: string\n /** Display name */\n name: string\n /** Description */\n description?: string\n /** Suggested default model when creating a new model configuration */\n suggestedDefaultModel?: string\n /** Default settings for this provider (e.g., { url: \"http://localhost:11434\" }) */\n defaultSettings?: Record<string, unknown>\n /**\n * Declarative configuration view rendered with the extensionComponent\n * system. The host owns the settings state — bind fields with\n * `value: \"$settings.<key>\"` and the host updates the model's\n * settingsOverride when the user edits. `onChangeAction` is optional\n * for input fields in this view; buttons can still use `onClickAction`\n * to call extension actions (e.g. OAuth, \"Test connection\").\n */\n configView?: ProviderConfigView\n /**\n * Extra settings shown only for models that report\n * `capabilities.voiceDuplex` — voice selection, transcription model, and\n * whatever else is specific to this provider's realtime backend.\n *\n * Same DSL and same `$settings.<key>` binding as {@link configView}; the host\n * renders it in its own section of the model editor and stores the values in\n * the same settingsOverride. Keep general provider settings in `configView`\n * so they stay visible for models without voice.\n */\n voiceConfigView?: ProviderConfigView\n}\n\n/**\n * Component-tree-based configuration view for a provider.\n */\nexport interface ProviderConfigView {\n /** Component tree describing the form. */\n content: import('./types.components.js').ExtensionComponentData\n}\n\n// ============================================================================\n// Tools\n// ============================================================================\n\n/**\n * Tool definition (metadata only, implementation in code)\n */\nexport interface ToolDefinition {\n /** Tool ID */\n id: string\n /**\n * Display name - can be a simple string or localized strings.\n * @example \"Get Weather\"\n * @example { en: \"Get Weather\", sv: \"Hämta väder\" }\n */\n name: LocalizedString\n /**\n * Description for Stina - can be a simple string or localized strings.\n * Note: The AI always receives the English description (or fallback) for consistency.\n * Localized descriptions are used for UI display only.\n * @example \"Fetches current weather for a location\"\n * @example { en: \"Fetches current weather\", sv: \"Hämtar aktuellt väder\" }\n */\n description: LocalizedString\n /** Parameter schema (JSON Schema) */\n parameters?: Record<string, unknown>\n /**\n * Whether this tool requires user confirmation before execution.\n * Defaults to true if not specified — tools require confirmation unless explicitly opted out.\n */\n requiresConfirmation?: boolean\n /**\n * Optional custom confirmation prompt to show the user.\n * Only used when confirmation is required.\n * @example { en: \"Allow sending email?\", sv: \"Tillåt att skicka e-post?\" }\n */\n confirmationPrompt?: LocalizedString\n}\n\n/**\n * @deprecated Use `requiresConfirmation` and `confirmationPrompt` directly on ToolDefinition instead.\n * Configuration for tool confirmation.\n */\nexport interface ToolConfirmationConfig {\n /**\n * Default confirmation prompt to show the user.\n * If not provided, a generic prompt like \"Allow {toolName} to run?\" is used.\n * @example { en: \"Allow sending email?\", sv: \"Tillåt att skicka e-post?\" }\n */\n prompt?: LocalizedString\n}\n\n// ============================================================================\n// Commands\n// ============================================================================\n\n/**\n * Command definition\n */\nexport interface CommandDefinition {\n /** Command ID (e.g., \"weather\" for /weather) */\n id: string\n /** Display name */\n name: string\n /** Description */\n description: string\n}\n\n// ============================================================================\n// Prompts\n// ============================================================================\n\nexport type PromptSection = 'system' | 'behavior' | 'tools'\n\nexport interface PromptContribution {\n /** Unique ID within the extension */\n id: string\n /** Optional title for the prompt chunk */\n title?: string\n /** Prompt section placement */\n section?: PromptSection\n /** Plain text prompt content */\n text?: string\n /** Optional localized prompt content (keyed by locale, e.g. \"en\", \"sv\") */\n i18n?: Record<string, string>\n /** Optional ordering hint (lower comes first) */\n order?: number\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 // Attachments\n | 'attachments.read'\n // Connected accounts\n | 'accounts.list'\n | 'accounts.getAccessToken'\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;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;;;AC0EO,IAAM,4BAA+D;AAAA,EAC1E;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACmSO,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/types.contributions.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'\nexport { EXTENSION_SETTINGS_TOPICS } from './types.js'\n\n// Types\nexport type {\n // Manifest\n ExtensionManifest,\n Platform,\n ExtensionContributions,\n ToolSettingsViewDefinition,\n ExtensionSettingsTopic,\n ToolSettingsView,\n ToolSettingsListView,\n ToolSettingsListMapping,\n ToolSettingsComponentView,\n ToolSettingsActionDataSource,\n PanelDefinition,\n StatusCardDefinition,\n PanelView,\n PanelComponentView,\n PanelActionDataSource,\n PanelUnknownView,\n ProviderDefinition,\n ProviderConfigView,\n PromptContribution,\n PromptSection,\n ToolDefinition,\n ToolConfirmationConfig,\n CommandDefinition,\n AccountProvider,\n AccountContribution,\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 AttachmentsAPI,\n AttachmentContent,\n ConnectedAccountsAPI,\n ConnectedAccount,\n AccountAccessToken,\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 ChatFile,\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 ToolAttachment,\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 ClockProps,\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 // Purpose-built display components\n WeatherCondition,\n WeatherWind,\n WeatherNowProps,\n WeatherForecastStep,\n WeatherForecastProps,\n ChartKind,\n ChartSeries,\n ChartProps,\n StatTrend,\n StatTileProps,\n ProgressShape,\n ProgressColor,\n ProgressBarProps,\n KeyValueRow,\n KeyValueListProps,\n TimelineVariant,\n TimelineEntry,\n TimelineProps,\n NoteVariant,\n NoteProps,\n CalendarEventStatus,\n CalendarEventProps,\n AgendaEvent,\n AgendaDay,\n AgendaProps,\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 * Contribution Types\n *\n * Types for extension contributions: settings, panels, providers, tools, commands, prompts.\n */\n\nimport type { LocalizedString } from './types.localization.js'\nimport type { ExtensionComponentData } from './types.components.js'\n\n/**\n * What an extension can contribute to Stina\n */\nexport interface ExtensionContributions {\n /** Tool settings views for UI */\n toolSettings?: ToolSettingsViewDefinition[]\n /** Cards for the strip above the conversation list */\n statusCards?: StatusCardDefinition[]\n /** Right panel contributions */\n panels?: PanelDefinition[]\n /** AI providers */\n providers?: ProviderDefinition[]\n /** Tools for Stina to use */\n tools?: ToolDefinition[]\n /** Slash commands */\n commands?: CommandDefinition[]\n /** Prompt contributions for the system prompt */\n prompts?: PromptContribution[]\n /** External accounts the extension works through, signed in once in Stina's settings */\n accounts?: AccountContribution[]\n /** Storage collection declarations */\n storage?: {\n collections: {\n [name: string]: {\n /** Fields to index for fast queries */\n indexes?: string[]\n }\n }\n }\n}\n\n// ============================================================================\n// Connected Accounts\n// ============================================================================\n\n/**\n * An external account provider the host can sign in to on the user's behalf.\n *\n * Only Microsoft for now, and only through Microsoft Graph: mail and calendar\n * then share one sign-in and one token, instead of an IMAP token and a Graph\n * token that an admin has to approve separately.\n */\nexport type AccountProvider = 'microsoft'\n\n/**\n * What an extension needs from an account the user connects to Stina.\n *\n * Stina asks the provider for every scope that the enabled extensions declare,\n * all at once, so that the user - and, at work, their administrator - approves\n * one request instead of one per extension. Declaring a scope here is therefore\n * also what makes it show up in that request, and in the list of what is asked\n * for in the settings.\n *\n * @example\n * ```json\n * \"accounts\": [\n * {\n * \"provider\": \"microsoft\",\n * \"scopes\": [\"Calendars.ReadWrite\"],\n * \"reason\": { \"en\": \"Read and book events in your calendar\", \"sv\": \"Läsa och boka i din kalender\" }\n * }\n * ]\n * ```\n */\nexport interface AccountContribution {\n provider: AccountProvider\n /**\n * Microsoft Graph delegated permissions, by name: `Mail.Read`,\n * `Calendars.ReadWrite`. The host adds `offline_access` and `User.Read`\n * itself, so they are not declared here.\n */\n scopes: string[]\n /** Why the extension needs them, shown next to the scopes in the settings. */\n reason?: LocalizedString\n}\n\n// ============================================================================\n// Tool Settings Views\n// ============================================================================\n\n/**\n * What a settings view is about, which decides where Stina shows it.\n *\n * An extension never picks a place in the settings menu: the menu belongs to Stina and\n * changes between versions. It says what the view is *about*, and Stina puts each topic\n * where it belongs, the way `accounts`, `providers` and `statusCards` already work.\n *\n * - `accounts`: connects Stina to an account or a service (a mailbox, a calendar feed).\n * Shown with the other connected accounts.\n * - `notifications`: when and how the extension may get in touch. Shown with Stina's own\n * notification settings.\n * - `personal`: facts about the user the extension relies on (a home town for the\n * weather). Shown with the profile.\n * - `tracking`: things Stina keeps track of for the user that are worth looking through\n * now and then (people, projects, reminders). Gets its own row in the register.\n *\n * A view without a topic, or with one this version of Stina does not know, is shown on\n * the extension's own page. That is always a working place, only a less fitting one, so\n * a topic added later never breaks an older Stina.\n */\nexport type ExtensionSettingsTopic = 'accounts' | 'notifications' | 'personal' | 'tracking'\n\n/** Every topic this version of the API knows, in no particular order. */\nexport const EXTENSION_SETTINGS_TOPICS: readonly ExtensionSettingsTopic[] = [\n 'accounts',\n 'notifications',\n 'personal',\n 'tracking',\n]\n\n/**\n * Tool settings view definition (UI schema)\n */\nexport interface ToolSettingsViewDefinition {\n /** Unique view ID within the extension */\n id: string\n /** Display title */\n title: LocalizedString\n /** Help text */\n description?: LocalizedString\n /** What the view is about, and so where Stina shows it. See {@link ExtensionSettingsTopic}. */\n topic?: ExtensionSettingsTopic\n /** View configuration */\n view: ToolSettingsView\n}\n\n/**\n * Tool settings view types\n */\nexport type ToolSettingsView = ToolSettingsListView | ToolSettingsComponentView\n\n/**\n * List view backed by tools\n */\nexport interface ToolSettingsListView {\n /** View kind */\n kind: 'list'\n /** Tool ID for listing items */\n listToolId: string\n /** Tool ID for fetching details (optional) */\n getToolId?: string\n /** Tool ID for creating/updating items (optional) */\n upsertToolId?: string\n /** Tool ID for deleting items (optional) */\n deleteToolId?: string\n /** Mapping from tool data to UI fields */\n mapping: ToolSettingsListMapping\n /** Param name for search query (default: \"query\") */\n searchParam?: string\n /** Param name for limit (default: \"limit\") */\n limitParam?: string\n /** Param name for get/delete ID (default: \"id\") */\n idParam?: string\n /** Static params always sent to list tool */\n listParams?: Record<string, unknown>\n /**\n * Component-tree-based create/edit form. Fields bind to the current\n * item via `value: \"$item.<key>\"` (or `selectedValue` / `checked`),\n * and the host saves the resulting object via `upsertToolId` when\n * the user clicks \"Save\".\n */\n editView?: {\n /** Root component to render in the create/edit modal. */\n content: ExtensionComponentData\n }\n /** Optional grouping configuration. When set, items are visually grouped by this field. */\n groupBy?: ToolSettingsListGroupBy\n}\n\n/**\n * Configures grouping for a list view. Items are grouped by the value\n * of `key` on each item; groups appear in the order specified by `order`\n * (with unlisted groups falling back to alphabetical order at the end).\n */\nexport interface ToolSettingsListGroupBy {\n /** Key in each item used to determine group membership. */\n key: string\n /** Explicit ordering of group values. Groups not listed appear afterwards, sorted alphabetically. */\n order?: string[]\n /** Human-friendly labels per group value (rendered as section headers). Falls back to the raw value if missing. */\n labels?: Record<string, LocalizedString>\n}\n\n/**\n * Mapping from tool list data to UI fields\n */\nexport interface ToolSettingsListMapping {\n /** Key for items array in tool result data */\n itemsKey: string\n /** Key for total count in tool result data */\n countKey?: string\n /** Key for item ID */\n idKey: string\n /** Key for item label */\n labelKey: string\n /** Key for item description */\n descriptionKey?: string\n /** Key for secondary label */\n secondaryKey?: string\n}\n\n/**\n * Component-based tool settings view using the declarative DSL.\n * Reuses the same structure as PanelComponentView for consistency.\n */\nexport interface ToolSettingsComponentView {\n /** View kind */\n kind: 'component'\n /** Data sources. Keys become scope variables (e.g., \"$settings\"). */\n data?: Record<string, ToolSettingsActionDataSource>\n /** Root component to render */\n content: ExtensionComponentData\n}\n\n/**\n * Action-based data source for tool settings.\n */\nexport interface ToolSettingsActionDataSource {\n /** Action ID to call for fetching data */\n action: string\n /** Parameters to pass to the action */\n params?: Record<string, unknown>\n /** Event names that trigger refresh */\n refreshOn?: string[]\n}\n\n// ============================================================================\n// Panels\n// ============================================================================\n\n/**\n * Panel definition for right panel views\n */\nexport interface PanelDefinition {\n /** Unique panel ID within the extension */\n id: string\n /** Display title */\n title: LocalizedString\n /** Icon name (from huge-icons) */\n icon?: string\n /** Panel view schema */\n view: PanelView\n}\n\n/**\n * A card for the strip above the conversation list.\n *\n * The same declarative machinery as a panel, in a much smaller space and with\n * one rule that is not a style guide: a card says what is true right now. It\n * has no controls, because a sidebar is read in passing and anything the user\n * wants to do about what it says, they say in words.\n *\n * The user chooses which cards they want and in what order, so an extension\n * offering three is offering three, not imposing them.\n */\nexport interface StatusCardDefinition {\n /** Unique card ID within the extension */\n id: string\n /** What it is called where the user picks it */\n title: LocalizedString\n /** Icon name (from huge-icons) */\n icon?: string\n /**\n * How much room it may take.\n *\n * Part of the contract rather than a guideline, because the sidebar is a few\n * hundred pixels wide and the first card written without a limit will be\n * written against a screen.\n *\n * - `line`: one row. A figure, a label, a pill.\n * - `block`: up to three rows.\n */\n size: 'line' | 'block'\n /** What it draws, and where the data comes from */\n view: PanelComponentView\n}\n\n/**\n * Panel view schema (declarative)\n */\nexport type PanelView = PanelComponentView | PanelUnknownView\n\nexport interface PanelUnknownView {\n /** View kind */\n kind: string\n /** Additional view configuration */\n [key: string]: unknown\n}\n\n/**\n * Action-based data source for declarative panels.\n * Uses actions (not tools) to fetch data.\n */\nexport interface PanelActionDataSource {\n /** Action ID to call for fetching data */\n action: string\n /** Parameters to pass to the action */\n params?: Record<string, unknown>\n /** Event names that should trigger a refresh of this data */\n refreshOn?: string[]\n}\n\n/**\n * Component-based panel view using the declarative DSL.\n * Data is fetched via actions, content is rendered via ExtensionComponent.\n */\nexport interface PanelComponentView {\n kind: 'component'\n /** Data sources available in the panel. Keys become variable names (e.g., \"$projects\"). */\n data?: Record<string, PanelActionDataSource>\n /** Root component to render */\n content: ExtensionComponentData\n}\n\n// ============================================================================\n// Providers\n// ============================================================================\n\n/**\n * Provider definition (metadata only, implementation in code)\n */\nexport interface ProviderDefinition {\n /** Provider ID */\n id: string\n /** Display name */\n name: string\n /** Description */\n description?: string\n /** Suggested default model when creating a new model configuration */\n suggestedDefaultModel?: string\n /** Default settings for this provider (e.g., { url: \"http://localhost:11434\" }) */\n defaultSettings?: Record<string, unknown>\n /**\n * Declarative configuration view rendered with the extensionComponent\n * system. The host owns the settings state — bind fields with\n * `value: \"$settings.<key>\"` and the host updates the model's\n * settingsOverride when the user edits. `onChangeAction` is optional\n * for input fields in this view; buttons can still use `onClickAction`\n * to call extension actions (e.g. OAuth, \"Test connection\").\n */\n configView?: ProviderConfigView\n /**\n * Extra settings shown only for models that report\n * `capabilities.voiceDuplex` — voice selection, transcription model, and\n * whatever else is specific to this provider's realtime backend.\n *\n * Same DSL and same `$settings.<key>` binding as {@link configView}; the host\n * renders it in its own section of the model editor and stores the values in\n * the same settingsOverride. Keep general provider settings in `configView`\n * so they stay visible for models without voice.\n */\n voiceConfigView?: ProviderConfigView\n}\n\n/**\n * Component-tree-based configuration view for a provider.\n */\nexport interface ProviderConfigView {\n /** Component tree describing the form. */\n content: import('./types.components.js').ExtensionComponentData\n}\n\n// ============================================================================\n// Tools\n// ============================================================================\n\n/**\n * Tool definition (metadata only, implementation in code)\n */\nexport interface ToolDefinition {\n /** Tool ID */\n id: string\n /**\n * Display name - can be a simple string or localized strings.\n * @example \"Get Weather\"\n * @example { en: \"Get Weather\", sv: \"Hämta väder\" }\n */\n name: LocalizedString\n /**\n * Description for Stina - can be a simple string or localized strings.\n * Note: The AI always receives the English description (or fallback) for consistency.\n * Localized descriptions are used for UI display only.\n * @example \"Fetches current weather for a location\"\n * @example { en: \"Fetches current weather\", sv: \"Hämtar aktuellt väder\" }\n */\n description: LocalizedString\n /** Parameter schema (JSON Schema) */\n parameters?: Record<string, unknown>\n /**\n * Whether this tool requires user confirmation before execution.\n * Defaults to true if not specified — tools require confirmation unless explicitly opted out.\n */\n requiresConfirmation?: boolean\n /**\n * Optional custom confirmation prompt to show the user.\n * Only used when confirmation is required.\n * @example { en: \"Allow sending email?\", sv: \"Tillåt att skicka e-post?\" }\n */\n confirmationPrompt?: LocalizedString\n}\n\n/**\n * @deprecated Use `requiresConfirmation` and `confirmationPrompt` directly on ToolDefinition instead.\n * Configuration for tool confirmation.\n */\nexport interface ToolConfirmationConfig {\n /**\n * Default confirmation prompt to show the user.\n * If not provided, a generic prompt like \"Allow {toolName} to run?\" is used.\n * @example { en: \"Allow sending email?\", sv: \"Tillåt att skicka e-post?\" }\n */\n prompt?: LocalizedString\n}\n\n// ============================================================================\n// Commands\n// ============================================================================\n\n/**\n * Command definition\n */\nexport interface CommandDefinition {\n /** Command ID (e.g., \"weather\" for /weather) */\n id: string\n /** Display name */\n name: string\n /** Description */\n description: string\n}\n\n// ============================================================================\n// Prompts\n// ============================================================================\n\nexport type PromptSection = 'system' | 'behavior' | 'tools'\n\nexport interface PromptContribution {\n /** Unique ID within the extension */\n id: string\n /** Optional title for the prompt chunk */\n title?: string\n /** Prompt section placement */\n section?: PromptSection\n /** Plain text prompt content */\n text?: string\n /** Optional localized prompt content (keyed by locale, e.g. \"en\", \"sv\") */\n i18n?: Record<string, string>\n /** Optional ordering hint (lower comes first) */\n order?: number\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 // Attachments\n | 'attachments.read'\n // Connected accounts\n | 'accounts.list'\n | 'accounts.getAccessToken'\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;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;;;AC0EO,IAAM,4BAA+D;AAAA,EAC1E;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACmSO,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-DswDxtun.cjs';
2
- export { ah as AIProvider, a3 as AccountAccessToken, z as AccountContribution, y as AccountProvider, ap as Action, K as ActionsAPI, bs as AgendaDay, br as AgendaEvent, bt as AgendaProps, ar as AllowedCSSProperty, a0 as AttachmentContent, $ as AttachmentsAPI, aa as BackgroundRestartPolicy, a7 as BackgroundTaskCallback, a6 as BackgroundTaskConfig, a8 as BackgroundTaskContext, a9 as BackgroundTaskHealth, a5 as BackgroundWorkersAPI, aE as ButtonProps, bq as CalendarEventProps, bp as CalendarEventStatus, ba as ChartKind, bc as ChartProps, bb as ChartSeries, Y as ChatAPI, ak as ChatFile, aj as ChatImage, Z as ChatInstructionMessage, b0 as CheckboxProps, aC as ClockProps, aW as CollapsibleProps, x as CommandDefinition, b4 as ConditionalGroupProps, a2 as ConnectedAccount, a1 as ConnectedAccountsAPI, _ as ConversationPresentation, aJ as DateTimeInputProps, D as Disposable, aP as DividerProps, d as EXTENSION_SETTINGS_TOPICS, O as EventsAPI, aw as ExtensionActionCall, ax as ExtensionActionRef, av as ExtensionComponentChildren, at as ExtensionComponentData, au as ExtensionComponentIterator, as as ExtensionComponentStyle, B as ExtensionContext, ay as ExtensionDataSource, aq as ExtensionModule, az as ExtensionPanelDefinition, f as ExtensionSettingsTopic, aY as FrameProps, aX as FrameVariant, aO as GridProps, aA as HeaderProps, aN as HorizontalStackProps, aS as IconButtonProps, aR as IconButtonType, aL as IconPickerProps, aQ as IconProps, bj as KeyValueListProps, bi as KeyValueRow, aB as LabelProps, aZ as ListProps, L as LocalizedString, a4 as LogAPI, b1 as MarkdownProps, b3 as ModalProps, ai as ModelCapabilities, N as NetworkAPI, bo as NoteProps, bn as NoteVariant, aH as NumberInputProps, aT as PanelAction, o as PanelActionDataSource, n as PanelComponentView, P as PanelDefinition, aU as PanelProps, p as PanelUnknownView, m as PanelView, aD as ParagraphProps, aG as PasswordInputProps, a$ as PillProps, a_ as PillVariant, bh as ProgressBarProps, bg as ProgressColor, bf as ProgressShape, t as PromptContribution, u as PromptSection, s as ProviderConfigView, q as ProviderDefinition, I as ProvidersAPI, ab as Query, ac as QueryOptions, Q as SchedulerAPI, R as SchedulerJobRequest, U as SchedulerSchedule, ae as SecretsAPI, aK as SelectProps, F as SettingsAPI, be as StatTileProps, bd as StatTrend, l as StatusCardDefinition, ad as StorageAPI, af as StorageCollectionConfig, ag as StorageContributions, aI as TextAreaProps, aF as TextInputProps, b2 as TextPreviewProps, bl as TimelineEntry, bm as TimelineProps, bk as TimelineVariant, aV as ToggleProps, an as Tool, ao as ToolAttachment, al as ToolCall, w as ToolConfirmationConfig, v as ToolDefinition, k as ToolSettingsActionDataSource, j as ToolSettingsComponentView, i as ToolSettingsListMapping, h as ToolSettingsListView, g as ToolSettingsView, e as ToolSettingsViewDefinition, J as ToolsAPI, W as UserAPI, X as UserProfile, aM as VerticalStackProps, am as VoiceTransportRequest, b5 as WeatherCondition, b9 as WeatherForecastProps, b8 as WeatherForecastStep, b7 as WeatherNowProps, b6 as WeatherWind, r as resolveLocalizedString } from './types.tools-DswDxtun.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-D_srSS_m.cjs';
2
+ export { ah as AIProvider, a3 as AccountAccessToken, z as AccountContribution, y as AccountProvider, ap as Action, K as ActionsAPI, bs as AgendaDay, br as AgendaEvent, bt as AgendaProps, ar as AllowedCSSProperty, a0 as AttachmentContent, $ as AttachmentsAPI, aa as BackgroundRestartPolicy, a7 as BackgroundTaskCallback, a6 as BackgroundTaskConfig, a8 as BackgroundTaskContext, a9 as BackgroundTaskHealth, a5 as BackgroundWorkersAPI, aE as ButtonProps, bq as CalendarEventProps, bp as CalendarEventStatus, ba as ChartKind, bc as ChartProps, bb as ChartSeries, Y as ChatAPI, ak as ChatFile, aj as ChatImage, Z as ChatInstructionMessage, b0 as CheckboxProps, aC as ClockProps, aW as CollapsibleProps, x as CommandDefinition, b4 as ConditionalGroupProps, a2 as ConnectedAccount, a1 as ConnectedAccountsAPI, _ as ConversationPresentation, aJ as DateTimeInputProps, D as Disposable, aP as DividerProps, d as EXTENSION_SETTINGS_TOPICS, O as EventsAPI, aw as ExtensionActionCall, ax as ExtensionActionRef, av as ExtensionComponentChildren, at as ExtensionComponentData, au as ExtensionComponentIterator, as as ExtensionComponentStyle, B as ExtensionContext, ay as ExtensionDataSource, aq as ExtensionModule, az as ExtensionPanelDefinition, f as ExtensionSettingsTopic, aY as FrameProps, aX as FrameVariant, aO as GridProps, aA as HeaderProps, aN as HorizontalStackProps, aS as IconButtonProps, aR as IconButtonType, aL as IconPickerProps, aQ as IconProps, bj as KeyValueListProps, bi as KeyValueRow, aB as LabelProps, aZ as ListProps, L as LocalizedString, a4 as LogAPI, b1 as MarkdownProps, b3 as ModalProps, ai as ModelCapabilities, N as NetworkAPI, bo as NoteProps, bn as NoteVariant, aH as NumberInputProps, aT as PanelAction, o as PanelActionDataSource, n as PanelComponentView, P as PanelDefinition, aU as PanelProps, p as PanelUnknownView, m as PanelView, aD as ParagraphProps, aG as PasswordInputProps, a$ as PillProps, a_ as PillVariant, bh as ProgressBarProps, bg as ProgressColor, bf as ProgressShape, t as PromptContribution, u as PromptSection, s as ProviderConfigView, q as ProviderDefinition, I as ProvidersAPI, ab as Query, ac as QueryOptions, Q as SchedulerAPI, R as SchedulerJobRequest, U as SchedulerSchedule, ae as SecretsAPI, aK as SelectProps, F as SettingsAPI, be as StatTileProps, bd as StatTrend, l as StatusCardDefinition, ad as StorageAPI, af as StorageCollectionConfig, ag as StorageContributions, aI as TextAreaProps, aF as TextInputProps, b2 as TextPreviewProps, bl as TimelineEntry, bm as TimelineProps, bk as TimelineVariant, aV as ToggleProps, an as Tool, ao as ToolAttachment, al as ToolCall, w as ToolConfirmationConfig, v as ToolDefinition, k as ToolSettingsActionDataSource, j as ToolSettingsComponentView, i as ToolSettingsListMapping, h as ToolSettingsListView, g as ToolSettingsView, e as ToolSettingsViewDefinition, J as ToolsAPI, W as UserAPI, X as UserProfile, aM as VerticalStackProps, am as VoiceTransportRequest, b5 as WeatherCondition, b9 as WeatherForecastProps, b8 as WeatherForecastStep, b7 as WeatherNowProps, b6 as WeatherWind, r as resolveLocalizedString } from './types.tools-D_srSS_m.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-DswDxtun.js';
2
- export { ah as AIProvider, a3 as AccountAccessToken, z as AccountContribution, y as AccountProvider, ap as Action, K as ActionsAPI, bs as AgendaDay, br as AgendaEvent, bt as AgendaProps, ar as AllowedCSSProperty, a0 as AttachmentContent, $ as AttachmentsAPI, aa as BackgroundRestartPolicy, a7 as BackgroundTaskCallback, a6 as BackgroundTaskConfig, a8 as BackgroundTaskContext, a9 as BackgroundTaskHealth, a5 as BackgroundWorkersAPI, aE as ButtonProps, bq as CalendarEventProps, bp as CalendarEventStatus, ba as ChartKind, bc as ChartProps, bb as ChartSeries, Y as ChatAPI, ak as ChatFile, aj as ChatImage, Z as ChatInstructionMessage, b0 as CheckboxProps, aC as ClockProps, aW as CollapsibleProps, x as CommandDefinition, b4 as ConditionalGroupProps, a2 as ConnectedAccount, a1 as ConnectedAccountsAPI, _ as ConversationPresentation, aJ as DateTimeInputProps, D as Disposable, aP as DividerProps, d as EXTENSION_SETTINGS_TOPICS, O as EventsAPI, aw as ExtensionActionCall, ax as ExtensionActionRef, av as ExtensionComponentChildren, at as ExtensionComponentData, au as ExtensionComponentIterator, as as ExtensionComponentStyle, B as ExtensionContext, ay as ExtensionDataSource, aq as ExtensionModule, az as ExtensionPanelDefinition, f as ExtensionSettingsTopic, aY as FrameProps, aX as FrameVariant, aO as GridProps, aA as HeaderProps, aN as HorizontalStackProps, aS as IconButtonProps, aR as IconButtonType, aL as IconPickerProps, aQ as IconProps, bj as KeyValueListProps, bi as KeyValueRow, aB as LabelProps, aZ as ListProps, L as LocalizedString, a4 as LogAPI, b1 as MarkdownProps, b3 as ModalProps, ai as ModelCapabilities, N as NetworkAPI, bo as NoteProps, bn as NoteVariant, aH as NumberInputProps, aT as PanelAction, o as PanelActionDataSource, n as PanelComponentView, P as PanelDefinition, aU as PanelProps, p as PanelUnknownView, m as PanelView, aD as ParagraphProps, aG as PasswordInputProps, a$ as PillProps, a_ as PillVariant, bh as ProgressBarProps, bg as ProgressColor, bf as ProgressShape, t as PromptContribution, u as PromptSection, s as ProviderConfigView, q as ProviderDefinition, I as ProvidersAPI, ab as Query, ac as QueryOptions, Q as SchedulerAPI, R as SchedulerJobRequest, U as SchedulerSchedule, ae as SecretsAPI, aK as SelectProps, F as SettingsAPI, be as StatTileProps, bd as StatTrend, l as StatusCardDefinition, ad as StorageAPI, af as StorageCollectionConfig, ag as StorageContributions, aI as TextAreaProps, aF as TextInputProps, b2 as TextPreviewProps, bl as TimelineEntry, bm as TimelineProps, bk as TimelineVariant, aV as ToggleProps, an as Tool, ao as ToolAttachment, al as ToolCall, w as ToolConfirmationConfig, v as ToolDefinition, k as ToolSettingsActionDataSource, j as ToolSettingsComponentView, i as ToolSettingsListMapping, h as ToolSettingsListView, g as ToolSettingsView, e as ToolSettingsViewDefinition, J as ToolsAPI, W as UserAPI, X as UserProfile, aM as VerticalStackProps, am as VoiceTransportRequest, b5 as WeatherCondition, b9 as WeatherForecastProps, b8 as WeatherForecastStep, b7 as WeatherNowProps, b6 as WeatherWind, r as resolveLocalizedString } from './types.tools-DswDxtun.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-D_srSS_m.js';
2
+ export { ah as AIProvider, a3 as AccountAccessToken, z as AccountContribution, y as AccountProvider, ap as Action, K as ActionsAPI, bs as AgendaDay, br as AgendaEvent, bt as AgendaProps, ar as AllowedCSSProperty, a0 as AttachmentContent, $ as AttachmentsAPI, aa as BackgroundRestartPolicy, a7 as BackgroundTaskCallback, a6 as BackgroundTaskConfig, a8 as BackgroundTaskContext, a9 as BackgroundTaskHealth, a5 as BackgroundWorkersAPI, aE as ButtonProps, bq as CalendarEventProps, bp as CalendarEventStatus, ba as ChartKind, bc as ChartProps, bb as ChartSeries, Y as ChatAPI, ak as ChatFile, aj as ChatImage, Z as ChatInstructionMessage, b0 as CheckboxProps, aC as ClockProps, aW as CollapsibleProps, x as CommandDefinition, b4 as ConditionalGroupProps, a2 as ConnectedAccount, a1 as ConnectedAccountsAPI, _ as ConversationPresentation, aJ as DateTimeInputProps, D as Disposable, aP as DividerProps, d as EXTENSION_SETTINGS_TOPICS, O as EventsAPI, aw as ExtensionActionCall, ax as ExtensionActionRef, av as ExtensionComponentChildren, at as ExtensionComponentData, au as ExtensionComponentIterator, as as ExtensionComponentStyle, B as ExtensionContext, ay as ExtensionDataSource, aq as ExtensionModule, az as ExtensionPanelDefinition, f as ExtensionSettingsTopic, aY as FrameProps, aX as FrameVariant, aO as GridProps, aA as HeaderProps, aN as HorizontalStackProps, aS as IconButtonProps, aR as IconButtonType, aL as IconPickerProps, aQ as IconProps, bj as KeyValueListProps, bi as KeyValueRow, aB as LabelProps, aZ as ListProps, L as LocalizedString, a4 as LogAPI, b1 as MarkdownProps, b3 as ModalProps, ai as ModelCapabilities, N as NetworkAPI, bo as NoteProps, bn as NoteVariant, aH as NumberInputProps, aT as PanelAction, o as PanelActionDataSource, n as PanelComponentView, P as PanelDefinition, aU as PanelProps, p as PanelUnknownView, m as PanelView, aD as ParagraphProps, aG as PasswordInputProps, a$ as PillProps, a_ as PillVariant, bh as ProgressBarProps, bg as ProgressColor, bf as ProgressShape, t as PromptContribution, u as PromptSection, s as ProviderConfigView, q as ProviderDefinition, I as ProvidersAPI, ab as Query, ac as QueryOptions, Q as SchedulerAPI, R as SchedulerJobRequest, U as SchedulerSchedule, ae as SecretsAPI, aK as SelectProps, F as SettingsAPI, be as StatTileProps, bd as StatTrend, l as StatusCardDefinition, ad as StorageAPI, af as StorageCollectionConfig, ag as StorageContributions, aI as TextAreaProps, aF as TextInputProps, b2 as TextPreviewProps, bl as TimelineEntry, bm as TimelineProps, bk as TimelineVariant, aV as ToggleProps, an as Tool, ao as ToolAttachment, al as ToolCall, w as ToolConfirmationConfig, v as ToolDefinition, k as ToolSettingsActionDataSource, j as ToolSettingsComponentView, i as ToolSettingsListMapping, h as ToolSettingsListView, g as ToolSettingsView, e as ToolSettingsViewDefinition, J as ToolsAPI, W as UserAPI, X as UserProfile, aM as VerticalStackProps, am as VoiceTransportRequest, b5 as WeatherCondition, b9 as WeatherForecastProps, b8 as WeatherForecastStep, b7 as WeatherNowProps, b6 as WeatherWind, r as resolveLocalizedString } from './types.tools-D_srSS_m.js';
3
3
 
4
4
  /**
5
5
  * Permission Types
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.localization.ts","../src/types.contributions.ts"],"sourcesContent":["/**\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 * Contribution Types\n *\n * Types for extension contributions: settings, panels, providers, tools, commands, prompts.\n */\n\nimport type { LocalizedString } from './types.localization.js'\nimport type { ExtensionComponentData } from './types.components.js'\n\n/**\n * What an extension can contribute to Stina\n */\nexport interface ExtensionContributions {\n /** Tool settings views for UI */\n toolSettings?: ToolSettingsViewDefinition[]\n /** Cards for the strip above the conversation list */\n statusCards?: StatusCardDefinition[]\n /** Right panel contributions */\n panels?: PanelDefinition[]\n /** AI providers */\n providers?: ProviderDefinition[]\n /** Tools for Stina to use */\n tools?: ToolDefinition[]\n /** Slash commands */\n commands?: CommandDefinition[]\n /** Prompt contributions for the system prompt */\n prompts?: PromptContribution[]\n /** External accounts the extension works through, signed in once in Stina's settings */\n accounts?: AccountContribution[]\n /** Storage collection declarations */\n storage?: {\n collections: {\n [name: string]: {\n /** Fields to index for fast queries */\n indexes?: string[]\n }\n }\n }\n}\n\n// ============================================================================\n// Connected Accounts\n// ============================================================================\n\n/**\n * An external account provider the host can sign in to on the user's behalf.\n *\n * Only Microsoft for now, and only through Microsoft Graph: mail and calendar\n * then share one sign-in and one token, instead of an IMAP token and a Graph\n * token that an admin has to approve separately.\n */\nexport type AccountProvider = 'microsoft'\n\n/**\n * What an extension needs from an account the user connects to Stina.\n *\n * Stina asks the provider for every scope that the enabled extensions declare,\n * all at once, so that the user - and, at work, their administrator - approves\n * one request instead of one per extension. Declaring a scope here is therefore\n * also what makes it show up in that request, and in the list of what is asked\n * for in the settings.\n *\n * @example\n * ```json\n * \"accounts\": [\n * {\n * \"provider\": \"microsoft\",\n * \"scopes\": [\"Calendars.ReadWrite\"],\n * \"reason\": { \"en\": \"Read and book events in your calendar\", \"sv\": \"Läsa och boka i din kalender\" }\n * }\n * ]\n * ```\n */\nexport interface AccountContribution {\n provider: AccountProvider\n /**\n * Microsoft Graph delegated permissions, by name: `Mail.Read`,\n * `Calendars.ReadWrite`. The host adds `offline_access` and `User.Read`\n * itself, so they are not declared here.\n */\n scopes: string[]\n /** Why the extension needs them, shown next to the scopes in the settings. */\n reason?: LocalizedString\n}\n\n// ============================================================================\n// Tool Settings Views\n// ============================================================================\n\n/**\n * What a settings view is about, which decides where Stina shows it.\n *\n * An extension never picks a place in the settings menu: the menu belongs to Stina and\n * changes between versions. It says what the view is *about*, and Stina puts each topic\n * where it belongs, the way `accounts`, `providers` and `statusCards` already work.\n *\n * - `accounts`: connects Stina to an account or a service (a mailbox, a calendar feed).\n * Shown with the other connected accounts.\n * - `notifications`: when and how the extension may get in touch. Shown with Stina's own\n * notification settings.\n * - `personal`: facts about the user the extension relies on (a home town for the\n * weather). Shown with the profile.\n * - `tracking`: things Stina keeps track of for the user that are worth looking through\n * now and then (people, projects, reminders). Gets its own row in the register.\n *\n * A view without a topic, or with one this version of Stina does not know, is shown on\n * the extension's own page. That is always a working place, only a less fitting one, so\n * a topic added later never breaks an older Stina.\n */\nexport type ExtensionSettingsTopic = 'accounts' | 'notifications' | 'personal' | 'tracking'\n\n/** Every topic this version of the API knows, in no particular order. */\nexport const EXTENSION_SETTINGS_TOPICS: readonly ExtensionSettingsTopic[] = [\n 'accounts',\n 'notifications',\n 'personal',\n 'tracking',\n]\n\n/**\n * Tool settings view definition (UI schema)\n */\nexport interface ToolSettingsViewDefinition {\n /** Unique view ID within the extension */\n id: string\n /** Display title */\n title: string\n /** Help text */\n description?: string\n /** What the view is about, and so where Stina shows it. See {@link ExtensionSettingsTopic}. */\n topic?: ExtensionSettingsTopic\n /** View configuration */\n view: ToolSettingsView\n}\n\n/**\n * Tool settings view types\n */\nexport type ToolSettingsView = ToolSettingsListView | ToolSettingsComponentView\n\n/**\n * List view backed by tools\n */\nexport interface ToolSettingsListView {\n /** View kind */\n kind: 'list'\n /** Tool ID for listing items */\n listToolId: string\n /** Tool ID for fetching details (optional) */\n getToolId?: string\n /** Tool ID for creating/updating items (optional) */\n upsertToolId?: string\n /** Tool ID for deleting items (optional) */\n deleteToolId?: string\n /** Mapping from tool data to UI fields */\n mapping: ToolSettingsListMapping\n /** Param name for search query (default: \"query\") */\n searchParam?: string\n /** Param name for limit (default: \"limit\") */\n limitParam?: string\n /** Param name for get/delete ID (default: \"id\") */\n idParam?: string\n /** Static params always sent to list tool */\n listParams?: Record<string, unknown>\n /**\n * Component-tree-based create/edit form. Fields bind to the current\n * item via `value: \"$item.<key>\"` (or `selectedValue` / `checked`),\n * and the host saves the resulting object via `upsertToolId` when\n * the user clicks \"Save\".\n */\n editView?: {\n /** Root component to render in the create/edit modal. */\n content: ExtensionComponentData\n }\n /** Optional grouping configuration. When set, items are visually grouped by this field. */\n groupBy?: ToolSettingsListGroupBy\n}\n\n/**\n * Configures grouping for a list view. Items are grouped by the value\n * of `key` on each item; groups appear in the order specified by `order`\n * (with unlisted groups falling back to alphabetical order at the end).\n */\nexport interface ToolSettingsListGroupBy {\n /** Key in each item used to determine group membership. */\n key: string\n /** Explicit ordering of group values. Groups not listed appear afterwards, sorted alphabetically. */\n order?: string[]\n /** Human-friendly labels per group value (rendered as section headers). Falls back to the raw value if missing. */\n labels?: Record<string, string>\n}\n\n/**\n * Mapping from tool list data to UI fields\n */\nexport interface ToolSettingsListMapping {\n /** Key for items array in tool result data */\n itemsKey: string\n /** Key for total count in tool result data */\n countKey?: string\n /** Key for item ID */\n idKey: string\n /** Key for item label */\n labelKey: string\n /** Key for item description */\n descriptionKey?: string\n /** Key for secondary label */\n secondaryKey?: string\n}\n\n/**\n * Component-based tool settings view using the declarative DSL.\n * Reuses the same structure as PanelComponentView for consistency.\n */\nexport interface ToolSettingsComponentView {\n /** View kind */\n kind: 'component'\n /** Data sources. Keys become scope variables (e.g., \"$settings\"). */\n data?: Record<string, ToolSettingsActionDataSource>\n /** Root component to render */\n content: ExtensionComponentData\n}\n\n/**\n * Action-based data source for tool settings.\n */\nexport interface ToolSettingsActionDataSource {\n /** Action ID to call for fetching data */\n action: string\n /** Parameters to pass to the action */\n params?: Record<string, unknown>\n /** Event names that trigger refresh */\n refreshOn?: string[]\n}\n\n// ============================================================================\n// Panels\n// ============================================================================\n\n/**\n * Panel definition for right panel views\n */\nexport interface PanelDefinition {\n /** Unique panel ID within the extension */\n id: string\n /** Display title */\n title: string\n /** Icon name (from huge-icons) */\n icon?: string\n /** Panel view schema */\n view: PanelView\n}\n\n/**\n * A card for the strip above the conversation list.\n *\n * The same declarative machinery as a panel, in a much smaller space and with\n * one rule that is not a style guide: a card says what is true right now. It\n * has no controls, because a sidebar is read in passing and anything the user\n * wants to do about what it says, they say in words.\n *\n * The user chooses which cards they want and in what order, so an extension\n * offering three is offering three, not imposing them.\n */\nexport interface StatusCardDefinition {\n /** Unique card ID within the extension */\n id: string\n /** What it is called where the user picks it */\n title: string\n /** Icon name (from huge-icons) */\n icon?: string\n /**\n * How much room it may take.\n *\n * Part of the contract rather than a guideline, because the sidebar is a few\n * hundred pixels wide and the first card written without a limit will be\n * written against a screen.\n *\n * - `line`: one row. A figure, a label, a pill.\n * - `block`: up to three rows.\n */\n size: 'line' | 'block'\n /** What it draws, and where the data comes from */\n view: PanelComponentView\n}\n\n/**\n * Panel view schema (declarative)\n */\nexport type PanelView = PanelComponentView | PanelUnknownView\n\nexport interface PanelUnknownView {\n /** View kind */\n kind: string\n /** Additional view configuration */\n [key: string]: unknown\n}\n\n/**\n * Action-based data source for declarative panels.\n * Uses actions (not tools) to fetch data.\n */\nexport interface PanelActionDataSource {\n /** Action ID to call for fetching data */\n action: string\n /** Parameters to pass to the action */\n params?: Record<string, unknown>\n /** Event names that should trigger a refresh of this data */\n refreshOn?: string[]\n}\n\n/**\n * Component-based panel view using the declarative DSL.\n * Data is fetched via actions, content is rendered via ExtensionComponent.\n */\nexport interface PanelComponentView {\n kind: 'component'\n /** Data sources available in the panel. Keys become variable names (e.g., \"$projects\"). */\n data?: Record<string, PanelActionDataSource>\n /** Root component to render */\n content: ExtensionComponentData\n}\n\n// ============================================================================\n// Providers\n// ============================================================================\n\n/**\n * Provider definition (metadata only, implementation in code)\n */\nexport interface ProviderDefinition {\n /** Provider ID */\n id: string\n /** Display name */\n name: string\n /** Description */\n description?: string\n /** Suggested default model when creating a new model configuration */\n suggestedDefaultModel?: string\n /** Default settings for this provider (e.g., { url: \"http://localhost:11434\" }) */\n defaultSettings?: Record<string, unknown>\n /**\n * Declarative configuration view rendered with the extensionComponent\n * system. The host owns the settings state — bind fields with\n * `value: \"$settings.<key>\"` and the host updates the model's\n * settingsOverride when the user edits. `onChangeAction` is optional\n * for input fields in this view; buttons can still use `onClickAction`\n * to call extension actions (e.g. OAuth, \"Test connection\").\n */\n configView?: ProviderConfigView\n /**\n * Extra settings shown only for models that report\n * `capabilities.voiceDuplex` — voice selection, transcription model, and\n * whatever else is specific to this provider's realtime backend.\n *\n * Same DSL and same `$settings.<key>` binding as {@link configView}; the host\n * renders it in its own section of the model editor and stores the values in\n * the same settingsOverride. Keep general provider settings in `configView`\n * so they stay visible for models without voice.\n */\n voiceConfigView?: ProviderConfigView\n}\n\n/**\n * Component-tree-based configuration view for a provider.\n */\nexport interface ProviderConfigView {\n /** Component tree describing the form. */\n content: import('./types.components.js').ExtensionComponentData\n}\n\n// ============================================================================\n// Tools\n// ============================================================================\n\n/**\n * Tool definition (metadata only, implementation in code)\n */\nexport interface ToolDefinition {\n /** Tool ID */\n id: string\n /**\n * Display name - can be a simple string or localized strings.\n * @example \"Get Weather\"\n * @example { en: \"Get Weather\", sv: \"Hämta väder\" }\n */\n name: LocalizedString\n /**\n * Description for Stina - can be a simple string or localized strings.\n * Note: The AI always receives the English description (or fallback) for consistency.\n * Localized descriptions are used for UI display only.\n * @example \"Fetches current weather for a location\"\n * @example { en: \"Fetches current weather\", sv: \"Hämtar aktuellt väder\" }\n */\n description: LocalizedString\n /** Parameter schema (JSON Schema) */\n parameters?: Record<string, unknown>\n /**\n * Whether this tool requires user confirmation before execution.\n * Defaults to true if not specified — tools require confirmation unless explicitly opted out.\n */\n requiresConfirmation?: boolean\n /**\n * Optional custom confirmation prompt to show the user.\n * Only used when confirmation is required.\n * @example { en: \"Allow sending email?\", sv: \"Tillåt att skicka e-post?\" }\n */\n confirmationPrompt?: LocalizedString\n}\n\n/**\n * @deprecated Use `requiresConfirmation` and `confirmationPrompt` directly on ToolDefinition instead.\n * Configuration for tool confirmation.\n */\nexport interface ToolConfirmationConfig {\n /**\n * Default confirmation prompt to show the user.\n * If not provided, a generic prompt like \"Allow {toolName} to run?\" is used.\n * @example { en: \"Allow sending email?\", sv: \"Tillåt att skicka e-post?\" }\n */\n prompt?: LocalizedString\n}\n\n// ============================================================================\n// Commands\n// ============================================================================\n\n/**\n * Command definition\n */\nexport interface CommandDefinition {\n /** Command ID (e.g., \"weather\" for /weather) */\n id: string\n /** Display name */\n name: string\n /** Description */\n description: string\n}\n\n// ============================================================================\n// Prompts\n// ============================================================================\n\nexport type PromptSection = 'system' | 'behavior' | 'tools'\n\nexport interface PromptContribution {\n /** Unique ID within the extension */\n id: string\n /** Optional title for the prompt chunk */\n title?: string\n /** Prompt section placement */\n section?: PromptSection\n /** Plain text prompt content */\n text?: string\n /** Optional localized prompt content (keyed by locale, e.g. \"en\", \"sv\") */\n i18n?: Record<string, string>\n /** Optional ordering hint (lower comes first) */\n order?: number\n}\n"],"mappings":";;;;;;AA4BO,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;;;AC0EO,IAAM,4BAA+D;AAAA,EAC1E;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/types.localization.ts","../src/types.contributions.ts"],"sourcesContent":["/**\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 * Contribution Types\n *\n * Types for extension contributions: settings, panels, providers, tools, commands, prompts.\n */\n\nimport type { LocalizedString } from './types.localization.js'\nimport type { ExtensionComponentData } from './types.components.js'\n\n/**\n * What an extension can contribute to Stina\n */\nexport interface ExtensionContributions {\n /** Tool settings views for UI */\n toolSettings?: ToolSettingsViewDefinition[]\n /** Cards for the strip above the conversation list */\n statusCards?: StatusCardDefinition[]\n /** Right panel contributions */\n panels?: PanelDefinition[]\n /** AI providers */\n providers?: ProviderDefinition[]\n /** Tools for Stina to use */\n tools?: ToolDefinition[]\n /** Slash commands */\n commands?: CommandDefinition[]\n /** Prompt contributions for the system prompt */\n prompts?: PromptContribution[]\n /** External accounts the extension works through, signed in once in Stina's settings */\n accounts?: AccountContribution[]\n /** Storage collection declarations */\n storage?: {\n collections: {\n [name: string]: {\n /** Fields to index for fast queries */\n indexes?: string[]\n }\n }\n }\n}\n\n// ============================================================================\n// Connected Accounts\n// ============================================================================\n\n/**\n * An external account provider the host can sign in to on the user's behalf.\n *\n * Only Microsoft for now, and only through Microsoft Graph: mail and calendar\n * then share one sign-in and one token, instead of an IMAP token and a Graph\n * token that an admin has to approve separately.\n */\nexport type AccountProvider = 'microsoft'\n\n/**\n * What an extension needs from an account the user connects to Stina.\n *\n * Stina asks the provider for every scope that the enabled extensions declare,\n * all at once, so that the user - and, at work, their administrator - approves\n * one request instead of one per extension. Declaring a scope here is therefore\n * also what makes it show up in that request, and in the list of what is asked\n * for in the settings.\n *\n * @example\n * ```json\n * \"accounts\": [\n * {\n * \"provider\": \"microsoft\",\n * \"scopes\": [\"Calendars.ReadWrite\"],\n * \"reason\": { \"en\": \"Read and book events in your calendar\", \"sv\": \"Läsa och boka i din kalender\" }\n * }\n * ]\n * ```\n */\nexport interface AccountContribution {\n provider: AccountProvider\n /**\n * Microsoft Graph delegated permissions, by name: `Mail.Read`,\n * `Calendars.ReadWrite`. The host adds `offline_access` and `User.Read`\n * itself, so they are not declared here.\n */\n scopes: string[]\n /** Why the extension needs them, shown next to the scopes in the settings. */\n reason?: LocalizedString\n}\n\n// ============================================================================\n// Tool Settings Views\n// ============================================================================\n\n/**\n * What a settings view is about, which decides where Stina shows it.\n *\n * An extension never picks a place in the settings menu: the menu belongs to Stina and\n * changes between versions. It says what the view is *about*, and Stina puts each topic\n * where it belongs, the way `accounts`, `providers` and `statusCards` already work.\n *\n * - `accounts`: connects Stina to an account or a service (a mailbox, a calendar feed).\n * Shown with the other connected accounts.\n * - `notifications`: when and how the extension may get in touch. Shown with Stina's own\n * notification settings.\n * - `personal`: facts about the user the extension relies on (a home town for the\n * weather). Shown with the profile.\n * - `tracking`: things Stina keeps track of for the user that are worth looking through\n * now and then (people, projects, reminders). Gets its own row in the register.\n *\n * A view without a topic, or with one this version of Stina does not know, is shown on\n * the extension's own page. That is always a working place, only a less fitting one, so\n * a topic added later never breaks an older Stina.\n */\nexport type ExtensionSettingsTopic = 'accounts' | 'notifications' | 'personal' | 'tracking'\n\n/** Every topic this version of the API knows, in no particular order. */\nexport const EXTENSION_SETTINGS_TOPICS: readonly ExtensionSettingsTopic[] = [\n 'accounts',\n 'notifications',\n 'personal',\n 'tracking',\n]\n\n/**\n * Tool settings view definition (UI schema)\n */\nexport interface ToolSettingsViewDefinition {\n /** Unique view ID within the extension */\n id: string\n /** Display title */\n title: LocalizedString\n /** Help text */\n description?: LocalizedString\n /** What the view is about, and so where Stina shows it. See {@link ExtensionSettingsTopic}. */\n topic?: ExtensionSettingsTopic\n /** View configuration */\n view: ToolSettingsView\n}\n\n/**\n * Tool settings view types\n */\nexport type ToolSettingsView = ToolSettingsListView | ToolSettingsComponentView\n\n/**\n * List view backed by tools\n */\nexport interface ToolSettingsListView {\n /** View kind */\n kind: 'list'\n /** Tool ID for listing items */\n listToolId: string\n /** Tool ID for fetching details (optional) */\n getToolId?: string\n /** Tool ID for creating/updating items (optional) */\n upsertToolId?: string\n /** Tool ID for deleting items (optional) */\n deleteToolId?: string\n /** Mapping from tool data to UI fields */\n mapping: ToolSettingsListMapping\n /** Param name for search query (default: \"query\") */\n searchParam?: string\n /** Param name for limit (default: \"limit\") */\n limitParam?: string\n /** Param name for get/delete ID (default: \"id\") */\n idParam?: string\n /** Static params always sent to list tool */\n listParams?: Record<string, unknown>\n /**\n * Component-tree-based create/edit form. Fields bind to the current\n * item via `value: \"$item.<key>\"` (or `selectedValue` / `checked`),\n * and the host saves the resulting object via `upsertToolId` when\n * the user clicks \"Save\".\n */\n editView?: {\n /** Root component to render in the create/edit modal. */\n content: ExtensionComponentData\n }\n /** Optional grouping configuration. When set, items are visually grouped by this field. */\n groupBy?: ToolSettingsListGroupBy\n}\n\n/**\n * Configures grouping for a list view. Items are grouped by the value\n * of `key` on each item; groups appear in the order specified by `order`\n * (with unlisted groups falling back to alphabetical order at the end).\n */\nexport interface ToolSettingsListGroupBy {\n /** Key in each item used to determine group membership. */\n key: string\n /** Explicit ordering of group values. Groups not listed appear afterwards, sorted alphabetically. */\n order?: string[]\n /** Human-friendly labels per group value (rendered as section headers). Falls back to the raw value if missing. */\n labels?: Record<string, LocalizedString>\n}\n\n/**\n * Mapping from tool list data to UI fields\n */\nexport interface ToolSettingsListMapping {\n /** Key for items array in tool result data */\n itemsKey: string\n /** Key for total count in tool result data */\n countKey?: string\n /** Key for item ID */\n idKey: string\n /** Key for item label */\n labelKey: string\n /** Key for item description */\n descriptionKey?: string\n /** Key for secondary label */\n secondaryKey?: string\n}\n\n/**\n * Component-based tool settings view using the declarative DSL.\n * Reuses the same structure as PanelComponentView for consistency.\n */\nexport interface ToolSettingsComponentView {\n /** View kind */\n kind: 'component'\n /** Data sources. Keys become scope variables (e.g., \"$settings\"). */\n data?: Record<string, ToolSettingsActionDataSource>\n /** Root component to render */\n content: ExtensionComponentData\n}\n\n/**\n * Action-based data source for tool settings.\n */\nexport interface ToolSettingsActionDataSource {\n /** Action ID to call for fetching data */\n action: string\n /** Parameters to pass to the action */\n params?: Record<string, unknown>\n /** Event names that trigger refresh */\n refreshOn?: string[]\n}\n\n// ============================================================================\n// Panels\n// ============================================================================\n\n/**\n * Panel definition for right panel views\n */\nexport interface PanelDefinition {\n /** Unique panel ID within the extension */\n id: string\n /** Display title */\n title: LocalizedString\n /** Icon name (from huge-icons) */\n icon?: string\n /** Panel view schema */\n view: PanelView\n}\n\n/**\n * A card for the strip above the conversation list.\n *\n * The same declarative machinery as a panel, in a much smaller space and with\n * one rule that is not a style guide: a card says what is true right now. It\n * has no controls, because a sidebar is read in passing and anything the user\n * wants to do about what it says, they say in words.\n *\n * The user chooses which cards they want and in what order, so an extension\n * offering three is offering three, not imposing them.\n */\nexport interface StatusCardDefinition {\n /** Unique card ID within the extension */\n id: string\n /** What it is called where the user picks it */\n title: LocalizedString\n /** Icon name (from huge-icons) */\n icon?: string\n /**\n * How much room it may take.\n *\n * Part of the contract rather than a guideline, because the sidebar is a few\n * hundred pixels wide and the first card written without a limit will be\n * written against a screen.\n *\n * - `line`: one row. A figure, a label, a pill.\n * - `block`: up to three rows.\n */\n size: 'line' | 'block'\n /** What it draws, and where the data comes from */\n view: PanelComponentView\n}\n\n/**\n * Panel view schema (declarative)\n */\nexport type PanelView = PanelComponentView | PanelUnknownView\n\nexport interface PanelUnknownView {\n /** View kind */\n kind: string\n /** Additional view configuration */\n [key: string]: unknown\n}\n\n/**\n * Action-based data source for declarative panels.\n * Uses actions (not tools) to fetch data.\n */\nexport interface PanelActionDataSource {\n /** Action ID to call for fetching data */\n action: string\n /** Parameters to pass to the action */\n params?: Record<string, unknown>\n /** Event names that should trigger a refresh of this data */\n refreshOn?: string[]\n}\n\n/**\n * Component-based panel view using the declarative DSL.\n * Data is fetched via actions, content is rendered via ExtensionComponent.\n */\nexport interface PanelComponentView {\n kind: 'component'\n /** Data sources available in the panel. Keys become variable names (e.g., \"$projects\"). */\n data?: Record<string, PanelActionDataSource>\n /** Root component to render */\n content: ExtensionComponentData\n}\n\n// ============================================================================\n// Providers\n// ============================================================================\n\n/**\n * Provider definition (metadata only, implementation in code)\n */\nexport interface ProviderDefinition {\n /** Provider ID */\n id: string\n /** Display name */\n name: string\n /** Description */\n description?: string\n /** Suggested default model when creating a new model configuration */\n suggestedDefaultModel?: string\n /** Default settings for this provider (e.g., { url: \"http://localhost:11434\" }) */\n defaultSettings?: Record<string, unknown>\n /**\n * Declarative configuration view rendered with the extensionComponent\n * system. The host owns the settings state — bind fields with\n * `value: \"$settings.<key>\"` and the host updates the model's\n * settingsOverride when the user edits. `onChangeAction` is optional\n * for input fields in this view; buttons can still use `onClickAction`\n * to call extension actions (e.g. OAuth, \"Test connection\").\n */\n configView?: ProviderConfigView\n /**\n * Extra settings shown only for models that report\n * `capabilities.voiceDuplex` — voice selection, transcription model, and\n * whatever else is specific to this provider's realtime backend.\n *\n * Same DSL and same `$settings.<key>` binding as {@link configView}; the host\n * renders it in its own section of the model editor and stores the values in\n * the same settingsOverride. Keep general provider settings in `configView`\n * so they stay visible for models without voice.\n */\n voiceConfigView?: ProviderConfigView\n}\n\n/**\n * Component-tree-based configuration view for a provider.\n */\nexport interface ProviderConfigView {\n /** Component tree describing the form. */\n content: import('./types.components.js').ExtensionComponentData\n}\n\n// ============================================================================\n// Tools\n// ============================================================================\n\n/**\n * Tool definition (metadata only, implementation in code)\n */\nexport interface ToolDefinition {\n /** Tool ID */\n id: string\n /**\n * Display name - can be a simple string or localized strings.\n * @example \"Get Weather\"\n * @example { en: \"Get Weather\", sv: \"Hämta väder\" }\n */\n name: LocalizedString\n /**\n * Description for Stina - can be a simple string or localized strings.\n * Note: The AI always receives the English description (or fallback) for consistency.\n * Localized descriptions are used for UI display only.\n * @example \"Fetches current weather for a location\"\n * @example { en: \"Fetches current weather\", sv: \"Hämtar aktuellt väder\" }\n */\n description: LocalizedString\n /** Parameter schema (JSON Schema) */\n parameters?: Record<string, unknown>\n /**\n * Whether this tool requires user confirmation before execution.\n * Defaults to true if not specified — tools require confirmation unless explicitly opted out.\n */\n requiresConfirmation?: boolean\n /**\n * Optional custom confirmation prompt to show the user.\n * Only used when confirmation is required.\n * @example { en: \"Allow sending email?\", sv: \"Tillåt att skicka e-post?\" }\n */\n confirmationPrompt?: LocalizedString\n}\n\n/**\n * @deprecated Use `requiresConfirmation` and `confirmationPrompt` directly on ToolDefinition instead.\n * Configuration for tool confirmation.\n */\nexport interface ToolConfirmationConfig {\n /**\n * Default confirmation prompt to show the user.\n * If not provided, a generic prompt like \"Allow {toolName} to run?\" is used.\n * @example { en: \"Allow sending email?\", sv: \"Tillåt att skicka e-post?\" }\n */\n prompt?: LocalizedString\n}\n\n// ============================================================================\n// Commands\n// ============================================================================\n\n/**\n * Command definition\n */\nexport interface CommandDefinition {\n /** Command ID (e.g., \"weather\" for /weather) */\n id: string\n /** Display name */\n name: string\n /** Description */\n description: string\n}\n\n// ============================================================================\n// Prompts\n// ============================================================================\n\nexport type PromptSection = 'system' | 'behavior' | 'tools'\n\nexport interface PromptContribution {\n /** Unique ID within the extension */\n id: string\n /** Optional title for the prompt chunk */\n title?: string\n /** Prompt section placement */\n section?: PromptSection\n /** Plain text prompt content */\n text?: string\n /** Optional localized prompt content (keyed by locale, e.g. \"en\", \"sv\") */\n i18n?: Record<string, string>\n /** Optional ordering hint (lower comes first) */\n order?: number\n}\n"],"mappings":";;;;;;AA4BO,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;;;AC0EO,IAAM,4BAA+D;AAAA,EAC1E;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;","names":[]}
@@ -1,5 +1,5 @@
1
- import { aq as ExtensionModule } from './types.tools-DswDxtun.cjs';
2
- export { ah as AIProvider, a3 as AccountAccessToken, ap as Action, A as ActionResult, aa as BackgroundRestartPolicy, a7 as BackgroundTaskCallback, a6 as BackgroundTaskConfig, a8 as BackgroundTaskContext, a9 as BackgroundTaskHealth, a5 as BackgroundWorkersAPI, ak as ChatFile, aj as ChatImage, C as ChatMessage, a as ChatOptions, a2 as ConnectedAccount, a1 as ConnectedAccountsAPI, D as Disposable, bu as ExecutionContext, B as ExtensionContext, G as GetModelsOptions, ai as ModelCapabilities, M as ModelInfo, ab as Query, ac as QueryOptions, ae as SecretsAPI, ad as StorageAPI, b as StreamEvent, an as Tool, ao as ToolAttachment, al as ToolCall, v as ToolDefinition, T as ToolResult, c as VoiceSessionDescriptor, V as VoiceSessionOptions, am as VoiceTransportRequest } from './types.tools-DswDxtun.cjs';
1
+ import { aq as ExtensionModule } from './types.tools-D_srSS_m.cjs';
2
+ export { ah as AIProvider, a3 as AccountAccessToken, ap as Action, A as ActionResult, aa as BackgroundRestartPolicy, a7 as BackgroundTaskCallback, a6 as BackgroundTaskConfig, a8 as BackgroundTaskContext, a9 as BackgroundTaskHealth, a5 as BackgroundWorkersAPI, ak as ChatFile, aj as ChatImage, C as ChatMessage, a as ChatOptions, a2 as ConnectedAccount, a1 as ConnectedAccountsAPI, D as Disposable, bu as ExecutionContext, B as ExtensionContext, G as GetModelsOptions, ai as ModelCapabilities, M as ModelInfo, ab as Query, ac as QueryOptions, ae as SecretsAPI, ad as StorageAPI, b as StreamEvent, an as Tool, ao as ToolAttachment, al as ToolCall, v as ToolDefinition, T as ToolResult, c as VoiceSessionDescriptor, V as VoiceSessionOptions, am as VoiceTransportRequest } from './types.tools-D_srSS_m.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 { aq as ExtensionModule } from './types.tools-DswDxtun.js';
2
- export { ah as AIProvider, a3 as AccountAccessToken, ap as Action, A as ActionResult, aa as BackgroundRestartPolicy, a7 as BackgroundTaskCallback, a6 as BackgroundTaskConfig, a8 as BackgroundTaskContext, a9 as BackgroundTaskHealth, a5 as BackgroundWorkersAPI, ak as ChatFile, aj as ChatImage, C as ChatMessage, a as ChatOptions, a2 as ConnectedAccount, a1 as ConnectedAccountsAPI, D as Disposable, bu as ExecutionContext, B as ExtensionContext, G as GetModelsOptions, ai as ModelCapabilities, M as ModelInfo, ab as Query, ac as QueryOptions, ae as SecretsAPI, ad as StorageAPI, b as StreamEvent, an as Tool, ao as ToolAttachment, al as ToolCall, v as ToolDefinition, T as ToolResult, c as VoiceSessionDescriptor, V as VoiceSessionOptions, am as VoiceTransportRequest } from './types.tools-DswDxtun.js';
1
+ import { aq as ExtensionModule } from './types.tools-D_srSS_m.js';
2
+ export { ah as AIProvider, a3 as AccountAccessToken, ap as Action, A as ActionResult, aa as BackgroundRestartPolicy, a7 as BackgroundTaskCallback, a6 as BackgroundTaskConfig, a8 as BackgroundTaskContext, a9 as BackgroundTaskHealth, a5 as BackgroundWorkersAPI, ak as ChatFile, aj as ChatImage, C as ChatMessage, a as ChatOptions, a2 as ConnectedAccount, a1 as ConnectedAccountsAPI, D as Disposable, bu as ExecutionContext, B as ExtensionContext, G as GetModelsOptions, ai as ModelCapabilities, M as ModelInfo, ab as Query, ac as QueryOptions, ae as SecretsAPI, ad as StorageAPI, b as StreamEvent, an as Tool, ao as ToolAttachment, al as ToolCall, v as ToolDefinition, T as ToolResult, c as VoiceSessionDescriptor, V as VoiceSessionOptions, am as VoiceTransportRequest } from './types.tools-D_srSS_m.js';
3
3
 
4
4
  /**
5
5
  * Extension Runtime - Runs inside the worker