@stina/extension-api 0.19.0 → 0.20.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.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +62 -3
- package/dist/index.d.ts +62 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/runtime.cjs +35 -42
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.cts +2 -2
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.js +35 -42
- package/dist/runtime.js.map +1 -1
- package/dist/{types-kRt2DzdL.d.cts → types.tools-DgCozsOW.d.cts} +231 -217
- package/dist/{types-kRt2DzdL.d.ts → types.tools-DgCozsOW.d.ts} +231 -217
- package/package.json +1 -1
- package/src/runtime.ts +46 -47
- package/src/types.context.ts +399 -0
- package/src/types.contributions.ts +404 -0
- package/src/types.localization.ts +39 -0
- package/src/types.manifest.ts +45 -0
- package/src/types.permissions.ts +48 -0
- package/src/types.provider.ts +111 -0
- package/src/types.tools.ts +70 -0
- package/src/types.ts +92 -1037
package/dist/index.cjs
CHANGED
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/messages.ts"],"sourcesContent":["/**\n * @stina/extension-api\n *\n * Types and utilities for building Stina extensions.\n *\n * Extensions should import from this package for type definitions.\n * The runtime (worker-side code) should import from '@stina/extension-api/runtime'.\n */\n\n// Localization\nexport type { LocalizedString } from './types.js'\nexport { resolveLocalizedString } from './types.js'\n\n// Types\nexport type {\n // Manifest\n ExtensionManifest,\n Platform,\n ExtensionContributions,\n SettingDefinition,\n SettingOptionsMapping,\n SettingCreateMapping,\n ToolSettingsViewDefinition,\n ToolSettingsView,\n ToolSettingsListView,\n ToolSettingsListMapping,\n ToolSettingsComponentView,\n ToolSettingsActionDataSource,\n PanelDefinition,\n PanelView,\n PanelComponentView,\n PanelActionDataSource,\n PanelUnknownView,\n ProviderDefinition,\n PromptContribution,\n PromptSection,\n ToolDefinition,\n CommandDefinition,\n\n // Provider Configuration Schema\n ProviderConfigSchema,\n ProviderConfigProperty,\n ProviderConfigPropertyType,\n ProviderConfigSelectOption,\n ProviderConfigValidation,\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 DatabaseAPI,\n StorageAPI,\n LogAPI,\n\n // AI Provider\n AIProvider,\n ModelInfo,\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolCall,\n\n // Tools\n Tool,\n ToolResult,\n\n // Actions\n Action,\n ActionResult,\n\n // Entry point\n ExtensionModule,\n} from './types.js'\n\n// Messages (for host implementation)\nexport type {\n HostToWorkerMessage,\n WorkerToHostMessage,\n ActivateMessage,\n DeactivateMessage,\n SettingsChangedMessage,\n ProviderChatRequestMessage,\n ProviderModelsRequestMessage,\n ToolExecuteRequestMessage,\n ToolExecuteResponseMessage,\n ActionExecuteRequestMessage,\n ActionExecuteResponseMessage,\n ResponseMessage,\n ReadyMessage,\n RequestMessage,\n RequestMethod,\n ProviderRegisteredMessage,\n ToolRegisteredMessage,\n ActionRegisteredMessage,\n StreamEventMessage,\n LogMessage,\n PendingRequest,\n} from './messages.js'\n\nexport { generateMessageId } from './messages.js'\n\n// Component types (for extension UI components)\nexport type {\n // Styling\n AllowedCSSProperty,\n ExtensionComponentStyle,\n // Base types\n ExtensionComponentData,\n // Iteration & Children\n ExtensionComponentIterator,\n ExtensionComponentChildren,\n // Actions\n ExtensionActionCall,\n ExtensionActionRef,\n // Data Sources & Panel Definition\n ExtensionDataSource,\n ExtensionPanelDefinition,\n // Component Props\n HeaderProps,\n LabelProps,\n ParagraphProps,\n ButtonProps,\n TextInputProps,\n DateTimeInputProps,\n SelectProps,\n VerticalStackProps,\n HorizontalStackProps,\n GridProps,\n DividerProps,\n IconProps,\n IconButtonType,\n IconButtonProps,\n PanelAction,\n PanelProps,\n ToggleProps,\n CollapsibleProps,\n PillVariant,\n PillProps,\n CheckboxProps,\n MarkdownProps,\n ModalProps,\n} from './types.components.js'\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/**\n * Extension manifest format (manifest.json)\n */\nexport interface ExtensionManifest {\n /** Unique identifier (e.g., \"ollama-provider\") */\n id: string\n /** Human-readable name */\n name: string\n /** Version string (semver) */\n version: string\n /** Short description */\n description: string\n /** Author information */\n author: {\n name: string\n url?: string\n }\n /** Repository URL */\n repository?: string\n /** License identifier */\n license?: string\n /** Minimum Stina version required */\n engines?: {\n stina: string\n }\n /** Supported platforms */\n platforms?: Platform[]\n /** Entry point file (relative to extension root) */\n main: string\n /** Required permissions */\n permissions: Permission[]\n /** What the extension contributes */\n contributes?: ExtensionContributions\n}\n\nexport type Platform = 'web' | 'electron' | 'tui'\n\n/**\n * What an extension can contribute to Stina\n */\nexport interface ExtensionContributions {\n /** User-configurable settings */\n settings?: SettingDefinition[]\n /** Tool settings views for UI */\n toolSettings?: ToolSettingsViewDefinition[]\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}\n\n/**\n * Setting definition for the UI\n */\nexport interface SettingDefinition {\n /** Setting ID (namespaced automatically) */\n id: string\n /** Display title */\n title: string\n /** Help text */\n description?: string\n /** Setting type */\n type: 'string' | 'number' | 'boolean' | 'select'\n /** Default value */\n default?: unknown\n /** For select type: available options */\n options?: { value: string; label: string }[]\n /** For select type: load options from tool */\n optionsToolId?: string\n /** Params for options tool */\n optionsParams?: Record<string, unknown>\n /** Mapping for options tool response */\n optionsMapping?: SettingOptionsMapping\n /** Tool ID for creating a new option */\n createToolId?: string\n /** Label for create action */\n createLabel?: string\n /** Fields for create form */\n createFields?: SettingDefinition[]\n /** Static params always sent to create tool */\n createParams?: Record<string, unknown>\n /** Mapping for create tool response */\n createMapping?: SettingCreateMapping\n /** Validation rules */\n validation?: {\n required?: boolean\n min?: number\n max?: number\n pattern?: string\n }\n}\n\n/**\n * Mapping for select field options from tool response\n */\nexport interface SettingOptionsMapping {\n /** Key for items array in tool result data */\n itemsKey: string\n /** Key for option value */\n valueKey: string\n /** Key for option label */\n labelKey: string\n /** Optional key for description */\n descriptionKey?: string\n}\n\n/**\n * Mapping for create tool response\n */\nexport interface SettingCreateMapping {\n /** Key for result data object */\n resultKey?: string\n /** Key for option value (defaults to \"id\") */\n valueKey: string\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 /** View configuration */\n view: ToolSettingsView\n /** Fields for create/edit forms (uses SettingDefinition) */\n fields?: SettingDefinition[]\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\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: import('./types.components.js').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 * 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 * 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: import('./types.components.js').ExtensionComponentData\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 /** Schema for provider-specific configuration UI */\n configSchema?: ProviderConfigSchema\n}\n\n// ============================================================================\n// Prompt Contributions\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// ============================================================================\n// Provider Configuration Schema\n// ============================================================================\n\n/**\n * Schema for provider-specific configuration.\n * Used to generate UI forms for configuring provider settings.\n */\nexport interface ProviderConfigSchema {\n /** Property definitions */\n properties: Record<string, ProviderConfigProperty>\n /** Display order of properties in UI (optional, defaults to object key order) */\n order?: string[]\n}\n\n/**\n * Property types for provider configuration\n */\nexport type ProviderConfigPropertyType =\n | 'string'\n | 'number'\n | 'boolean'\n | 'select'\n | 'password'\n | 'url'\n\n/**\n * Single property in a provider configuration schema.\n * Defines how a setting should be rendered and validated in the UI.\n */\nexport interface ProviderConfigProperty {\n /** Property type - determines UI control */\n type: ProviderConfigPropertyType\n /** Display label */\n title: string\n /** Help text shown below the input */\n description?: string\n /** Default value */\n default?: unknown\n /** Whether the field is required */\n required?: boolean\n /** Placeholder text for input fields */\n placeholder?: string\n /** For 'select' type: static options */\n options?: ProviderConfigSelectOption[]\n /** Validation rules */\n validation?: ProviderConfigValidation\n}\n\n/**\n * Option for select-type properties\n */\nexport interface ProviderConfigSelectOption {\n /** Value stored in settings */\n value: string\n /** Display label */\n label: string\n}\n\n/**\n * Validation rules for a property\n */\nexport interface ProviderConfigValidation {\n /** Regex pattern the value must match */\n pattern?: string\n /** Minimum string length */\n minLength?: number\n /** Maximum string length */\n maxLength?: number\n /** Minimum number value */\n min?: number\n /** Maximum number value */\n max?: number\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\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// Permissions\n// ============================================================================\n\nexport type Permission =\n | NetworkPermission\n | StoragePermission\n | UserDataPermission\n | CapabilityPermission\n | SystemPermission\n\n/** Network access permissions */\nexport type NetworkPermission =\n | 'network:*'\n | `network:localhost`\n | `network:localhost:${number}`\n | `network:${string}`\n\n/** Storage permissions */\nexport type StoragePermission = 'database.own' | 'storage.local'\n\n/** User data permissions */\nexport type UserDataPermission =\n | 'user.profile.read'\n | 'user.location.read'\n | 'chat.history.read'\n | 'chat.current.read'\n\n/** Capability permissions */\nexport type CapabilityPermission =\n | 'provider.register'\n | 'tools.register'\n | 'actions.register'\n | 'settings.register'\n | 'commands.register'\n | 'panels.register'\n | 'events.emit'\n | 'scheduler.register'\n | 'chat.message.write'\n\n/** System permissions */\nexport type SystemPermission =\n | 'files.read'\n | 'files.write'\n | 'clipboard.read'\n | 'clipboard.write'\n\n// ============================================================================\n// Extension Context (API available to extensions)\n// ============================================================================\n\n/**\n * Disposable resource that can be cleaned up\n */\nexport interface Disposable {\n dispose(): void\n}\n\n/**\n * Context provided to extension's activate function.\n *\n * ## User ID Context\n *\n * The `userId` field provides the current user context for extensions. It is set when:\n * - A tool is executed by a user\n * - An action is executed by a user\n * - A scheduled job fires (if the job was created with a userId)\n *\n * For extension activation, `userId` is undefined since activation happens at system level.\n * Extensions should check for `userId` in their tool/action handlers to access user-specific data.\n *\n * @example\n * ```typescript\n * // In a tool execute handler:\n * execute: async (params, context) => {\n * if (context.userId) {\n * // User-specific logic\n * const userData = await storage.getForUser(context.userId, 'preferences')\n * }\n * }\n * ```\n */\nexport interface ExtensionContext {\n /** Extension metadata */\n readonly extension: {\n readonly id: string\n readonly version: string\n readonly storagePath: string\n }\n\n /**\n * Current user ID if in a user context, undefined for global/system operations.\n * Set when tools or actions are executed by a user, or when a user-scoped job fires.\n */\n readonly userId?: string\n\n /** Network access (if permitted) */\n readonly network?: NetworkAPI\n\n /** Settings access (if permitted) */\n readonly settings?: SettingsAPI\n\n /** Provider registration (if permitted) */\n readonly providers?: ProvidersAPI\n\n /** Tool registration (if permitted) */\n readonly tools?: ToolsAPI\n\n /** Action registration (if permitted) */\n readonly actions?: ActionsAPI\n\n /** Event emission (if permitted) */\n readonly events?: EventsAPI\n\n /** Scheduler access (if permitted) */\n readonly scheduler?: SchedulerAPI\n\n /** User data access (if permitted) */\n readonly user?: UserAPI\n\n /** Chat access (if permitted) */\n readonly chat?: ChatAPI\n\n /** Database access (if permitted) */\n readonly database?: DatabaseAPI\n\n /** Local storage (if permitted) */\n readonly storage?: StorageAPI\n\n /** Logging (always available) */\n readonly log: LogAPI\n}\n\n/**\n * Network API for making HTTP requests\n */\nexport interface NetworkAPI {\n /**\n * Fetch a URL (permissions are enforced by host)\n */\n fetch(url: string, options?: RequestInit): Promise<Response>\n\n /**\n * Streaming fetch for responses like NDJSON or SSE.\n * Yields text chunks as they arrive from the server.\n *\n * @throws {Error} If the request fails or encounters a network error.\n * The error message will contain details about the failure.\n *\n * @example\n * ```typescript\n * try {\n * for await (const chunk of context.network.fetchStream(url, options)) {\n * // Process each chunk (may contain partial lines)\n * buffer += chunk\n * }\n * } catch (error) {\n * console.error('Streaming fetch failed:', error.message)\n * }\n * ```\n */\n fetchStream(url: string, options?: RequestInit): AsyncGenerator<string, void, unknown>\n}\n\n/**\n * Settings API for reading/writing extension settings\n */\nexport interface SettingsAPI {\n /**\n * Get all settings for this extension\n */\n getAll<T extends Record<string, unknown>>(): Promise<T>\n\n /**\n * Get a specific setting value\n */\n get<T>(key: string): Promise<T | undefined>\n\n /**\n * Set a setting value\n */\n set(key: string, value: unknown): Promise<void>\n\n /**\n * Listen for setting changes\n */\n onChange(callback: (key: string, value: unknown) => void): Disposable\n}\n\n/**\n * Providers API for registering AI providers\n */\nexport interface ProvidersAPI {\n /**\n * Register an AI provider\n */\n register(provider: AIProvider): Disposable\n}\n\n/**\n * Tools API for registering tools\n */\nexport interface ToolsAPI {\n /**\n * Register a tool that Stina can use\n */\n register(tool: Tool): Disposable\n}\n\n/**\n * Actions API for registering UI actions\n */\nexport interface ActionsAPI {\n /**\n * Register an action that UI components can invoke\n */\n register(action: Action): Disposable\n}\n\n/**\n * Events API for notifying the host\n */\nexport interface EventsAPI {\n /**\n * Emit a named event with optional payload\n */\n emit(name: string, payload?: Record<string, unknown>): Promise<void>\n}\n\n/**\n * Scheduler schedule types\n */\nexport type SchedulerSchedule =\n | { type: 'at'; at: string }\n | { type: 'cron'; cron: string; timezone?: string }\n | { type: 'interval'; everyMs: number }\n\n/**\n * Scheduler job request\n */\nexport interface SchedulerJobRequest {\n id: string\n schedule: SchedulerSchedule\n payload?: Record<string, unknown>\n misfire?: 'run_once' | 'skip'\n /**\n * Optional user ID for user-scoped jobs.\n * If set, the job is associated with a specific user and the userId\n * will be passed to the extension when the job fires.\n */\n userId?: string\n}\n\n/**\n * Scheduler fire payload\n */\nexport interface SchedulerFirePayload {\n id: string\n payload?: Record<string, unknown>\n scheduledFor: string\n firedAt: string\n delayMs: number\n /** User ID if this is a user-scoped job, undefined if global */\n userId?: string\n}\n\n/**\n * Scheduler API for registering jobs\n */\nexport interface SchedulerAPI {\n schedule(job: SchedulerJobRequest): Promise<void>\n cancel(jobId: string): Promise<void>\n onFire(callback: (payload: SchedulerFirePayload) => void): Disposable\n}\n\n/**\n * User profile data\n */\nexport interface UserProfile {\n firstName?: string\n nickname?: string\n language?: string\n timezone?: string\n}\n\n/**\n * User API for profile access\n */\nexport interface UserAPI {\n getProfile(): Promise<UserProfile>\n}\n\n/**\n * Chat instruction message\n */\nexport interface ChatInstructionMessage {\n text: string\n conversationId?: string\n}\n\n/**\n * Chat API for appending instructions\n */\nexport interface ChatAPI {\n appendInstruction(message: ChatInstructionMessage): Promise<void>\n}\n\n/**\n * Database API for extension-specific tables\n */\nexport interface DatabaseAPI {\n /**\n * Execute a SQL query (only extension's prefixed tables allowed)\n */\n execute<T = unknown>(sql: string, params?: unknown[]): Promise<T[]>\n}\n\n/**\n * Simple key-value storage API with support for user-scoped storage.\n *\n * ## Global vs User-Scoped Storage\n *\n * Extensions have access to two types of storage:\n * - **Global storage**: Shared across all users, accessed via `get()`, `set()`, etc.\n * - **User-scoped storage**: Isolated per user, accessed via `getForUser()`, `setForUser()`, etc.\n *\n * Use global storage for extension-wide settings and user-scoped storage for\n * user preferences, session data, or any data that should be private to a user.\n *\n * @example\n * ```typescript\n * // Global storage (extension-wide)\n * await storage.set('apiEndpoint', 'https://api.example.com')\n * const endpoint = await storage.get<string>('apiEndpoint')\n *\n * // User-scoped storage (per-user)\n * if (context.userId) {\n * await storage.setForUser(context.userId, 'preferences', { theme: 'dark' })\n * const prefs = await storage.getForUser<Preferences>(context.userId, 'preferences')\n * }\n * ```\n */\nexport interface StorageAPI {\n /**\n * Get a value by key (global/extension-scoped)\n */\n get<T>(key: string): Promise<T | undefined>\n\n /**\n * Set a value (global/extension-scoped)\n */\n set(key: string, value: unknown): Promise<void>\n\n /**\n * Delete a key (global/extension-scoped)\n */\n delete(key: string): Promise<void>\n\n /**\n * Get all keys (global/extension-scoped)\n */\n keys(): Promise<string[]>\n\n /**\n * Get a value by key for a specific user (user-scoped)\n * @param userId The user ID\n * @param key The storage key\n */\n getForUser<T>(userId: string, key: string): Promise<T | undefined>\n\n /**\n * Set a value for a specific user (user-scoped)\n * @param userId The user ID\n * @param key The storage key\n * @param value The value to store\n */\n setForUser(userId: string, key: string, value: unknown): Promise<void>\n\n /**\n * Delete a key for a specific user (user-scoped)\n * @param userId The user ID\n * @param key The storage key\n */\n deleteForUser(userId: string, key: string): Promise<void>\n\n /**\n * Get all keys for a specific user (user-scoped)\n * @param userId The user ID\n */\n keysForUser(userId: string): Promise<string[]>\n}\n\n/**\n * Logging API\n */\nexport interface LogAPI {\n debug(message: string, data?: Record<string, unknown>): void\n info(message: string, data?: Record<string, unknown>): void\n warn(message: string, data?: Record<string, unknown>): void\n error(message: string, data?: Record<string, unknown>): void\n}\n\n// ============================================================================\n// AI Provider Types\n// ============================================================================\n\n/**\n * AI provider implementation\n */\nexport interface AIProvider {\n /** Provider ID (must match manifest) */\n id: string\n /** Display name */\n name: string\n\n /**\n * Get available models from this provider\n * @param options Optional settings for the provider (e.g., URL)\n */\n getModels(options?: GetModelsOptions): Promise<ModelInfo[]>\n\n /**\n * Chat completion with streaming\n */\n chat(\n messages: ChatMessage[],\n options: ChatOptions\n ): AsyncGenerator<StreamEvent, void, unknown>\n\n /**\n * Optional: Generate embeddings\n */\n embed?(texts: string[]): Promise<number[][]>\n}\n\n/**\n * Model information\n */\nexport interface ModelInfo {\n /** Model ID */\n id: string\n /** Display name */\n name: string\n /** Description */\n description?: string\n /** Context window size */\n contextLength?: number\n}\n\n/**\n * Chat message\n */\nexport interface ChatMessage {\n role: 'user' | 'assistant' | 'system' | 'tool'\n content: string\n /** For assistant messages: tool calls made by the model */\n tool_calls?: ToolCall[]\n /** For tool messages: the ID of the tool call this is a response to */\n tool_call_id?: string\n}\n\n/**\n * A tool call made by the model\n */\nexport interface ToolCall {\n /** Unique ID for this tool call */\n id: string\n /** Tool name/ID to invoke */\n name: string\n /** Arguments for the tool (as parsed object) */\n arguments: Record<string, unknown>\n}\n\n/**\n * Options for chat completion\n */\nexport interface ChatOptions {\n /** Model to use */\n model?: string\n /** Temperature (0-1) */\n temperature?: number\n /** Maximum tokens to generate */\n maxTokens?: number\n /** Abort signal for cancellation */\n signal?: AbortSignal\n /** Provider-specific settings from model configuration */\n settings?: Record<string, unknown>\n /** Available tools for this request */\n tools?: ToolDefinition[]\n}\n\n/**\n * Options for getModels\n */\nexport interface GetModelsOptions {\n /** Provider-specific settings (e.g., URL for Ollama) */\n settings?: Record<string, unknown>\n}\n\n/**\n * Streaming events from chat\n */\nexport type StreamEvent =\n | { type: 'content'; text: string }\n | { type: 'thinking'; text: string }\n | { type: 'tool_start'; name: string; input: unknown; toolCallId: string }\n | { type: 'tool_end'; name: string; output: unknown; toolCallId: string }\n | { type: 'done'; usage?: { inputTokens: number; outputTokens: number } }\n | { type: 'error'; message: string }\n\n// ============================================================================\n// Tool Types\n// ============================================================================\n\n/**\n * Tool implementation\n */\nexport interface Tool {\n /** Tool ID (must match manifest) */\n id: string\n /** Display name */\n name: string\n /** Description for Stina */\n description: string\n /** Parameter schema (JSON Schema) */\n parameters?: Record<string, unknown>\n\n /**\n * Execute the tool\n */\n execute(params: Record<string, unknown>): Promise<ToolResult>\n}\n\n/**\n * Tool execution result\n */\nexport interface ToolResult {\n /** Whether the tool succeeded */\n success: boolean\n /** Result data (for Stina to use) */\n data?: unknown\n /** Human-readable message */\n message?: string\n /** Error message if failed */\n error?: string\n}\n\n// ============================================================================\n// Action Types (for UI interactions, separate from Tools)\n// ============================================================================\n\n/**\n * Action implementation for UI interactions.\n * Actions are invoked by UI components, not by Stina (AI).\n */\nexport interface Action {\n /** Action ID (unique within the extension) */\n id: string\n\n /**\n * Execute the action\n * @param params Parameters from the UI component (with $-values already resolved)\n */\n execute(params: Record<string, unknown>): Promise<ActionResult>\n}\n\n/**\n * Action execution result\n */\nexport interface ActionResult {\n /** Whether the action succeeded */\n success: boolean\n /** Result data (returned to UI) */\n data?: unknown\n /** Error message if failed */\n error?: string\n}\n\n// ============================================================================\n// Extension Entry Point\n// ============================================================================\n\n/**\n * Extension entry point interface\n */\nexport interface ExtensionModule {\n /**\n * Called when extension is activated\n */\n activate(context: ExtensionContext): void | Disposable | Promise<void | Disposable>\n\n /**\n * Called when extension is deactivated\n */\n deactivate?(): void | Promise<void>\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} 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 | ToolExecuteRequestMessage\n | ActionExecuteRequestMessage\n | ResponseMessage\n | StreamingFetchChunkMessage\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 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// 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 | ToolExecuteResponseMessage\n | ActionExecuteResponseMessage\n | StreamingFetchAckMessage\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 | 'events.emit'\n | 'scheduler.schedule'\n | 'scheduler.cancel'\n | 'chat.appendInstruction'\n | 'database.execute'\n | 'storage.get'\n | 'storage.set'\n | 'storage.delete'\n | 'storage.keys'\n | 'storage.getForUser'\n | 'storage.setForUser'\n | 'storage.deleteForUser'\n | 'storage.keysForUser'\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 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// 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;;;ACsBO,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;;;ACgPO,SAAS,oBAA4B;AAC1C,SAAO,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACjE;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types.localization.ts","../src/messages.ts"],"sourcesContent":["/**\n * @stina/extension-api\n *\n * Types and utilities for building Stina extensions.\n *\n * Extensions should import from this package for type definitions.\n * The runtime (worker-side code) should import from '@stina/extension-api/runtime'.\n */\n\n// Localization\nexport type { LocalizedString } from './types.js'\nexport { resolveLocalizedString } from './types.js'\n\n// Types\nexport type {\n // Manifest\n ExtensionManifest,\n Platform,\n ExtensionContributions,\n SettingDefinition,\n SettingOptionsMapping,\n SettingCreateMapping,\n ToolSettingsViewDefinition,\n ToolSettingsView,\n ToolSettingsListView,\n ToolSettingsListMapping,\n ToolSettingsComponentView,\n ToolSettingsActionDataSource,\n PanelDefinition,\n PanelView,\n PanelComponentView,\n PanelActionDataSource,\n PanelUnknownView,\n ProviderDefinition,\n PromptContribution,\n PromptSection,\n ToolDefinition,\n CommandDefinition,\n\n // Provider Configuration Schema\n ProviderConfigSchema,\n ProviderConfigProperty,\n ProviderConfigPropertyType,\n ProviderConfigSelectOption,\n ProviderConfigValidation,\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 DatabaseAPI,\n StorageAPI,\n LogAPI,\n\n // AI Provider\n AIProvider,\n ModelInfo,\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolCall,\n\n // Tools\n Tool,\n ToolResult,\n\n // Actions\n Action,\n ActionResult,\n\n // Entry point\n ExtensionModule,\n} from './types.js'\n\n// Messages (for host implementation)\nexport type {\n HostToWorkerMessage,\n WorkerToHostMessage,\n ActivateMessage,\n DeactivateMessage,\n SettingsChangedMessage,\n ProviderChatRequestMessage,\n ProviderModelsRequestMessage,\n ToolExecuteRequestMessage,\n ToolExecuteResponseMessage,\n ActionExecuteRequestMessage,\n ActionExecuteResponseMessage,\n ResponseMessage,\n ReadyMessage,\n RequestMessage,\n RequestMethod,\n ProviderRegisteredMessage,\n ToolRegisteredMessage,\n ActionRegisteredMessage,\n StreamEventMessage,\n LogMessage,\n PendingRequest,\n} from './messages.js'\n\nexport { generateMessageId } from './messages.js'\n\n// Component types (for extension UI components)\nexport type {\n // Styling\n AllowedCSSProperty,\n ExtensionComponentStyle,\n // Base types\n ExtensionComponentData,\n // Iteration & Children\n ExtensionComponentIterator,\n ExtensionComponentChildren,\n // Actions\n ExtensionActionCall,\n ExtensionActionRef,\n // Data Sources & Panel Definition\n ExtensionDataSource,\n ExtensionPanelDefinition,\n // Component Props\n HeaderProps,\n LabelProps,\n ParagraphProps,\n ButtonProps,\n TextInputProps,\n DateTimeInputProps,\n SelectProps,\n VerticalStackProps,\n HorizontalStackProps,\n GridProps,\n DividerProps,\n IconProps,\n IconButtonType,\n IconButtonProps,\n PanelAction,\n PanelProps,\n ToggleProps,\n CollapsibleProps,\n PillVariant,\n PillProps,\n CheckboxProps,\n MarkdownProps,\n ModalProps,\n} from './types.components.js'\n","/**\n * Localization Types\n *\n * Types and utilities for localized strings in extensions.\n */\n\n/**\n * A string that can be either a simple string or a map of language codes to localized strings.\n * When a simple string is provided, it's used as the default/fallback value.\n * When a map is provided, the appropriate language is selected at runtime.\n *\n * @example\n * // Simple string (backwards compatible)\n * name: \"Get Weather\"\n *\n * @example\n * // Localized strings\n * name: { en: \"Get Weather\", sv: \"Hämta väder\", de: \"Wetter abrufen\" }\n */\nexport type LocalizedString = string | Record<string, string>\n\n/**\n * Resolves a LocalizedString to an actual string value.\n * @param value The LocalizedString to resolve\n * @param lang The preferred language code (e.g., \"sv\", \"en\")\n * @param fallbackLang The fallback language code (defaults to \"en\")\n * @returns The resolved string value\n */\nexport function resolveLocalizedString(\n value: LocalizedString,\n lang: string,\n fallbackLang = 'en'\n): string {\n if (typeof value === 'string') {\n return value\n }\n // Try preferred language first, then fallback language, then first available, then empty string\n return value[lang] ?? value[fallbackLang] ?? Object.values(value)[0] ?? ''\n}\n","/**\n * Message protocol between Extension Host and Extension Workers\n */\n\nimport type {\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolResult,\n ActionResult,\n ModelInfo,\n SchedulerFirePayload,\n} 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 | ToolExecuteRequestMessage\n | ActionExecuteRequestMessage\n | ResponseMessage\n | StreamingFetchChunkMessage\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 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// 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 | ToolExecuteResponseMessage\n | ActionExecuteResponseMessage\n | StreamingFetchAckMessage\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 | 'events.emit'\n | 'scheduler.schedule'\n | 'scheduler.cancel'\n | 'chat.appendInstruction'\n | 'database.execute'\n | 'storage.get'\n | 'storage.set'\n | 'storage.delete'\n | 'storage.keys'\n | 'storage.getForUser'\n | 'storage.setForUser'\n | 'storage.deleteForUser'\n | 'storage.keysForUser'\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 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// Utility Types\n// ============================================================================\n\nexport interface PendingRequest<T = unknown> {\n resolve: (value: T) => void\n reject: (error: Error) => void\n timeout: ReturnType<typeof setTimeout>\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC4BO,SAAS,uBACd,OACA,MACA,eAAe,MACP;AACR,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AAEA,SAAO,MAAM,IAAI,KAAK,MAAM,YAAY,KAAK,OAAO,OAAO,KAAK,EAAE,CAAC,KAAK;AAC1E;;;AC0OO,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,64 @@
|
|
|
1
|
-
import { S as SchedulerFirePayload, C as ChatMessage, a as ChatOptions, G as GetModelsOptions, b as StreamEvent, M as ModelInfo, T as ToolResult, A as ActionResult } from './types-
|
|
2
|
-
export {
|
|
1
|
+
import { E as ExtensionContributions, S as SchedulerFirePayload, C as ChatMessage, a as ChatOptions, G as GetModelsOptions, b as StreamEvent, M as ModelInfo, T as ToolResult, A as ActionResult } from './types.tools-DgCozsOW.cjs';
|
|
2
|
+
export { $ as AIProvider, a2 as Action, J as ActionsAPI, a4 as AllowedCSSProperty, ag as ButtonProps, W as ChatAPI, X as ChatInstructionMessage, ax as CheckboxProps, au as CollapsibleProps, u as CommandDefinition, Y as DatabaseAPI, ai as DateTimeInputProps, D as Disposable, an as DividerProps, K as EventsAPI, a9 as ExtensionActionCall, aa as ExtensionActionRef, a8 as ExtensionComponentChildren, a6 as ExtensionComponentData, a7 as ExtensionComponentIterator, a5 as ExtensionComponentStyle, B as ExtensionContext, ab as ExtensionDataSource, a3 as ExtensionModule, ac as ExtensionPanelDefinition, am as GridProps, ad as HeaderProps, al as HorizontalStackProps, aq as IconButtonProps, ap as IconButtonType, ao as IconProps, ae as LabelProps, L as LocalizedString, _ as LogAPI, ay as MarkdownProps, az as ModalProps, N as NetworkAPI, ar as PanelAction, n as PanelActionDataSource, m as PanelComponentView, P as PanelDefinition, as as PanelProps, o as PanelUnknownView, l as PanelView, af as ParagraphProps, aw as PillProps, av as PillVariant, q as PromptContribution, s as PromptSection, w as ProviderConfigProperty, x as ProviderConfigPropertyType, v as ProviderConfigSchema, y as ProviderConfigSelectOption, z as ProviderConfigValidation, p as ProviderDefinition, H as ProvidersAPI, O as SchedulerAPI, Q as SchedulerJobRequest, R as SchedulerSchedule, aj as SelectProps, e as SettingCreateMapping, c as SettingDefinition, d as SettingOptionsMapping, F as SettingsAPI, Z as StorageAPI, ah as TextInputProps, at as ToggleProps, a1 as Tool, a0 as ToolCall, t as ToolDefinition, k as ToolSettingsActionDataSource, j as ToolSettingsComponentView, i as ToolSettingsListMapping, h as ToolSettingsListView, g as ToolSettingsView, f as ToolSettingsViewDefinition, I as ToolsAPI, U as UserAPI, V as UserProfile, ak as VerticalStackProps, r as resolveLocalizedString } from './types.tools-DgCozsOW.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Permission Types
|
|
6
|
+
*
|
|
7
|
+
* Defines all permission types for extensions.
|
|
8
|
+
*/
|
|
9
|
+
type Permission = NetworkPermission | StoragePermission | UserDataPermission | CapabilityPermission | SystemPermission;
|
|
10
|
+
/** Network access permissions */
|
|
11
|
+
type NetworkPermission = 'network:*' | `network:localhost` | `network:localhost:${number}` | `network:${string}`;
|
|
12
|
+
/** Storage permissions */
|
|
13
|
+
type StoragePermission = 'database.own' | 'storage.local';
|
|
14
|
+
/** User data permissions */
|
|
15
|
+
type UserDataPermission = 'user.profile.read' | 'user.location.read' | 'chat.history.read' | 'chat.current.read';
|
|
16
|
+
/** Capability permissions */
|
|
17
|
+
type CapabilityPermission = 'provider.register' | 'tools.register' | 'actions.register' | 'settings.register' | 'commands.register' | 'panels.register' | 'events.emit' | 'scheduler.register' | 'chat.message.write';
|
|
18
|
+
/** System permissions */
|
|
19
|
+
type SystemPermission = 'files.read' | 'files.write' | 'clipboard.read' | 'clipboard.write';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Manifest Types
|
|
23
|
+
*
|
|
24
|
+
* Types for extension manifest files (manifest.json).
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Extension manifest format (manifest.json)
|
|
29
|
+
*/
|
|
30
|
+
interface ExtensionManifest {
|
|
31
|
+
/** Unique identifier (e.g., "ollama-provider") */
|
|
32
|
+
id: string;
|
|
33
|
+
/** Human-readable name */
|
|
34
|
+
name: string;
|
|
35
|
+
/** Version string (semver) */
|
|
36
|
+
version: string;
|
|
37
|
+
/** Short description */
|
|
38
|
+
description: string;
|
|
39
|
+
/** Author information */
|
|
40
|
+
author: {
|
|
41
|
+
name: string;
|
|
42
|
+
url?: string;
|
|
43
|
+
};
|
|
44
|
+
/** Repository URL */
|
|
45
|
+
repository?: string;
|
|
46
|
+
/** License identifier */
|
|
47
|
+
license?: string;
|
|
48
|
+
/** Minimum Stina version required */
|
|
49
|
+
engines?: {
|
|
50
|
+
stina: string;
|
|
51
|
+
};
|
|
52
|
+
/** Supported platforms */
|
|
53
|
+
platforms?: Platform[];
|
|
54
|
+
/** Entry point file (relative to extension root) */
|
|
55
|
+
main: string;
|
|
56
|
+
/** Required permissions */
|
|
57
|
+
permissions: Permission[];
|
|
58
|
+
/** What the extension contributes */
|
|
59
|
+
contributes?: ExtensionContributions;
|
|
60
|
+
}
|
|
61
|
+
type Platform = 'web' | 'electron' | 'tui';
|
|
3
62
|
|
|
4
63
|
/**
|
|
5
64
|
* Message protocol between Extension Host and Extension Workers
|
|
@@ -187,4 +246,4 @@ interface PendingRequest<T = unknown> {
|
|
|
187
246
|
*/
|
|
188
247
|
declare function generateMessageId(): string;
|
|
189
248
|
|
|
190
|
-
export { type ActionExecuteRequestMessage, type ActionExecuteResponseMessage, type ActionRegisteredMessage, ActionResult, type ActivateMessage, ChatMessage, ChatOptions, type DeactivateMessage, GetModelsOptions, type HostToWorkerMessage, type LogMessage, ModelInfo, type PendingRequest, type ProviderChatRequestMessage, type ProviderModelsRequestMessage, type ProviderRegisteredMessage, type ReadyMessage, type RequestMessage, type RequestMethod, type ResponseMessage, SchedulerFirePayload, type SettingsChangedMessage, StreamEvent, type StreamEventMessage, type ToolExecuteRequestMessage, type ToolExecuteResponseMessage, type ToolRegisteredMessage, ToolResult, type WorkerToHostMessage, generateMessageId };
|
|
249
|
+
export { type ActionExecuteRequestMessage, type ActionExecuteResponseMessage, type ActionRegisteredMessage, ActionResult, type ActivateMessage, type CapabilityPermission, ChatMessage, ChatOptions, type DeactivateMessage, ExtensionContributions, type ExtensionManifest, GetModelsOptions, type HostToWorkerMessage, type LogMessage, ModelInfo, type NetworkPermission, type PendingRequest, type Permission, type Platform, type ProviderChatRequestMessage, type ProviderModelsRequestMessage, type ProviderRegisteredMessage, type ReadyMessage, type RequestMessage, type RequestMethod, type ResponseMessage, SchedulerFirePayload, type SettingsChangedMessage, type StoragePermission, StreamEvent, type StreamEventMessage, type SystemPermission, type ToolExecuteRequestMessage, type ToolExecuteResponseMessage, type ToolRegisteredMessage, ToolResult, type UserDataPermission, type WorkerToHostMessage, generateMessageId };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
|
-
import { S as SchedulerFirePayload, C as ChatMessage, a as ChatOptions, G as GetModelsOptions, b as StreamEvent, M as ModelInfo, T as ToolResult, A as ActionResult } from './types-
|
|
2
|
-
export {
|
|
1
|
+
import { E as ExtensionContributions, S as SchedulerFirePayload, C as ChatMessage, a as ChatOptions, G as GetModelsOptions, b as StreamEvent, M as ModelInfo, T as ToolResult, A as ActionResult } from './types.tools-DgCozsOW.js';
|
|
2
|
+
export { $ as AIProvider, a2 as Action, J as ActionsAPI, a4 as AllowedCSSProperty, ag as ButtonProps, W as ChatAPI, X as ChatInstructionMessage, ax as CheckboxProps, au as CollapsibleProps, u as CommandDefinition, Y as DatabaseAPI, ai as DateTimeInputProps, D as Disposable, an as DividerProps, K as EventsAPI, a9 as ExtensionActionCall, aa as ExtensionActionRef, a8 as ExtensionComponentChildren, a6 as ExtensionComponentData, a7 as ExtensionComponentIterator, a5 as ExtensionComponentStyle, B as ExtensionContext, ab as ExtensionDataSource, a3 as ExtensionModule, ac as ExtensionPanelDefinition, am as GridProps, ad as HeaderProps, al as HorizontalStackProps, aq as IconButtonProps, ap as IconButtonType, ao as IconProps, ae as LabelProps, L as LocalizedString, _ as LogAPI, ay as MarkdownProps, az as ModalProps, N as NetworkAPI, ar as PanelAction, n as PanelActionDataSource, m as PanelComponentView, P as PanelDefinition, as as PanelProps, o as PanelUnknownView, l as PanelView, af as ParagraphProps, aw as PillProps, av as PillVariant, q as PromptContribution, s as PromptSection, w as ProviderConfigProperty, x as ProviderConfigPropertyType, v as ProviderConfigSchema, y as ProviderConfigSelectOption, z as ProviderConfigValidation, p as ProviderDefinition, H as ProvidersAPI, O as SchedulerAPI, Q as SchedulerJobRequest, R as SchedulerSchedule, aj as SelectProps, e as SettingCreateMapping, c as SettingDefinition, d as SettingOptionsMapping, F as SettingsAPI, Z as StorageAPI, ah as TextInputProps, at as ToggleProps, a1 as Tool, a0 as ToolCall, t as ToolDefinition, k as ToolSettingsActionDataSource, j as ToolSettingsComponentView, i as ToolSettingsListMapping, h as ToolSettingsListView, g as ToolSettingsView, f as ToolSettingsViewDefinition, I as ToolsAPI, U as UserAPI, V as UserProfile, ak as VerticalStackProps, r as resolveLocalizedString } from './types.tools-DgCozsOW.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Permission Types
|
|
6
|
+
*
|
|
7
|
+
* Defines all permission types for extensions.
|
|
8
|
+
*/
|
|
9
|
+
type Permission = NetworkPermission | StoragePermission | UserDataPermission | CapabilityPermission | SystemPermission;
|
|
10
|
+
/** Network access permissions */
|
|
11
|
+
type NetworkPermission = 'network:*' | `network:localhost` | `network:localhost:${number}` | `network:${string}`;
|
|
12
|
+
/** Storage permissions */
|
|
13
|
+
type StoragePermission = 'database.own' | 'storage.local';
|
|
14
|
+
/** User data permissions */
|
|
15
|
+
type UserDataPermission = 'user.profile.read' | 'user.location.read' | 'chat.history.read' | 'chat.current.read';
|
|
16
|
+
/** Capability permissions */
|
|
17
|
+
type CapabilityPermission = 'provider.register' | 'tools.register' | 'actions.register' | 'settings.register' | 'commands.register' | 'panels.register' | 'events.emit' | 'scheduler.register' | 'chat.message.write';
|
|
18
|
+
/** System permissions */
|
|
19
|
+
type SystemPermission = 'files.read' | 'files.write' | 'clipboard.read' | 'clipboard.write';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Manifest Types
|
|
23
|
+
*
|
|
24
|
+
* Types for extension manifest files (manifest.json).
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Extension manifest format (manifest.json)
|
|
29
|
+
*/
|
|
30
|
+
interface ExtensionManifest {
|
|
31
|
+
/** Unique identifier (e.g., "ollama-provider") */
|
|
32
|
+
id: string;
|
|
33
|
+
/** Human-readable name */
|
|
34
|
+
name: string;
|
|
35
|
+
/** Version string (semver) */
|
|
36
|
+
version: string;
|
|
37
|
+
/** Short description */
|
|
38
|
+
description: string;
|
|
39
|
+
/** Author information */
|
|
40
|
+
author: {
|
|
41
|
+
name: string;
|
|
42
|
+
url?: string;
|
|
43
|
+
};
|
|
44
|
+
/** Repository URL */
|
|
45
|
+
repository?: string;
|
|
46
|
+
/** License identifier */
|
|
47
|
+
license?: string;
|
|
48
|
+
/** Minimum Stina version required */
|
|
49
|
+
engines?: {
|
|
50
|
+
stina: string;
|
|
51
|
+
};
|
|
52
|
+
/** Supported platforms */
|
|
53
|
+
platforms?: Platform[];
|
|
54
|
+
/** Entry point file (relative to extension root) */
|
|
55
|
+
main: string;
|
|
56
|
+
/** Required permissions */
|
|
57
|
+
permissions: Permission[];
|
|
58
|
+
/** What the extension contributes */
|
|
59
|
+
contributes?: ExtensionContributions;
|
|
60
|
+
}
|
|
61
|
+
type Platform = 'web' | 'electron' | 'tui';
|
|
3
62
|
|
|
4
63
|
/**
|
|
5
64
|
* Message protocol between Extension Host and Extension Workers
|
|
@@ -187,4 +246,4 @@ interface PendingRequest<T = unknown> {
|
|
|
187
246
|
*/
|
|
188
247
|
declare function generateMessageId(): string;
|
|
189
248
|
|
|
190
|
-
export { type ActionExecuteRequestMessage, type ActionExecuteResponseMessage, type ActionRegisteredMessage, ActionResult, type ActivateMessage, ChatMessage, ChatOptions, type DeactivateMessage, GetModelsOptions, type HostToWorkerMessage, type LogMessage, ModelInfo, type PendingRequest, type ProviderChatRequestMessage, type ProviderModelsRequestMessage, type ProviderRegisteredMessage, type ReadyMessage, type RequestMessage, type RequestMethod, type ResponseMessage, SchedulerFirePayload, type SettingsChangedMessage, StreamEvent, type StreamEventMessage, type ToolExecuteRequestMessage, type ToolExecuteResponseMessage, type ToolRegisteredMessage, ToolResult, type WorkerToHostMessage, generateMessageId };
|
|
249
|
+
export { type ActionExecuteRequestMessage, type ActionExecuteResponseMessage, type ActionRegisteredMessage, ActionResult, type ActivateMessage, type CapabilityPermission, ChatMessage, ChatOptions, type DeactivateMessage, ExtensionContributions, type ExtensionManifest, GetModelsOptions, type HostToWorkerMessage, type LogMessage, ModelInfo, type NetworkPermission, type PendingRequest, type Permission, type Platform, type ProviderChatRequestMessage, type ProviderModelsRequestMessage, type ProviderRegisteredMessage, type ReadyMessage, type RequestMessage, type RequestMethod, type ResponseMessage, SchedulerFirePayload, type SettingsChangedMessage, type StoragePermission, StreamEvent, type StreamEventMessage, type SystemPermission, type ToolExecuteRequestMessage, type ToolExecuteResponseMessage, type ToolRegisteredMessage, ToolResult, type UserDataPermission, type WorkerToHostMessage, generateMessageId };
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["/**\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/**\n * Extension manifest format (manifest.json)\n */\nexport interface ExtensionManifest {\n /** Unique identifier (e.g., \"ollama-provider\") */\n id: string\n /** Human-readable name */\n name: string\n /** Version string (semver) */\n version: string\n /** Short description */\n description: string\n /** Author information */\n author: {\n name: string\n url?: string\n }\n /** Repository URL */\n repository?: string\n /** License identifier */\n license?: string\n /** Minimum Stina version required */\n engines?: {\n stina: string\n }\n /** Supported platforms */\n platforms?: Platform[]\n /** Entry point file (relative to extension root) */\n main: string\n /** Required permissions */\n permissions: Permission[]\n /** What the extension contributes */\n contributes?: ExtensionContributions\n}\n\nexport type Platform = 'web' | 'electron' | 'tui'\n\n/**\n * What an extension can contribute to Stina\n */\nexport interface ExtensionContributions {\n /** User-configurable settings */\n settings?: SettingDefinition[]\n /** Tool settings views for UI */\n toolSettings?: ToolSettingsViewDefinition[]\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}\n\n/**\n * Setting definition for the UI\n */\nexport interface SettingDefinition {\n /** Setting ID (namespaced automatically) */\n id: string\n /** Display title */\n title: string\n /** Help text */\n description?: string\n /** Setting type */\n type: 'string' | 'number' | 'boolean' | 'select'\n /** Default value */\n default?: unknown\n /** For select type: available options */\n options?: { value: string; label: string }[]\n /** For select type: load options from tool */\n optionsToolId?: string\n /** Params for options tool */\n optionsParams?: Record<string, unknown>\n /** Mapping for options tool response */\n optionsMapping?: SettingOptionsMapping\n /** Tool ID for creating a new option */\n createToolId?: string\n /** Label for create action */\n createLabel?: string\n /** Fields for create form */\n createFields?: SettingDefinition[]\n /** Static params always sent to create tool */\n createParams?: Record<string, unknown>\n /** Mapping for create tool response */\n createMapping?: SettingCreateMapping\n /** Validation rules */\n validation?: {\n required?: boolean\n min?: number\n max?: number\n pattern?: string\n }\n}\n\n/**\n * Mapping for select field options from tool response\n */\nexport interface SettingOptionsMapping {\n /** Key for items array in tool result data */\n itemsKey: string\n /** Key for option value */\n valueKey: string\n /** Key for option label */\n labelKey: string\n /** Optional key for description */\n descriptionKey?: string\n}\n\n/**\n * Mapping for create tool response\n */\nexport interface SettingCreateMapping {\n /** Key for result data object */\n resultKey?: string\n /** Key for option value (defaults to \"id\") */\n valueKey: string\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 /** View configuration */\n view: ToolSettingsView\n /** Fields for create/edit forms (uses SettingDefinition) */\n fields?: SettingDefinition[]\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\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: import('./types.components.js').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 * 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 * 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: import('./types.components.js').ExtensionComponentData\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 /** Schema for provider-specific configuration UI */\n configSchema?: ProviderConfigSchema\n}\n\n// ============================================================================\n// Prompt Contributions\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// ============================================================================\n// Provider Configuration Schema\n// ============================================================================\n\n/**\n * Schema for provider-specific configuration.\n * Used to generate UI forms for configuring provider settings.\n */\nexport interface ProviderConfigSchema {\n /** Property definitions */\n properties: Record<string, ProviderConfigProperty>\n /** Display order of properties in UI (optional, defaults to object key order) */\n order?: string[]\n}\n\n/**\n * Property types for provider configuration\n */\nexport type ProviderConfigPropertyType =\n | 'string'\n | 'number'\n | 'boolean'\n | 'select'\n | 'password'\n | 'url'\n\n/**\n * Single property in a provider configuration schema.\n * Defines how a setting should be rendered and validated in the UI.\n */\nexport interface ProviderConfigProperty {\n /** Property type - determines UI control */\n type: ProviderConfigPropertyType\n /** Display label */\n title: string\n /** Help text shown below the input */\n description?: string\n /** Default value */\n default?: unknown\n /** Whether the field is required */\n required?: boolean\n /** Placeholder text for input fields */\n placeholder?: string\n /** For 'select' type: static options */\n options?: ProviderConfigSelectOption[]\n /** Validation rules */\n validation?: ProviderConfigValidation\n}\n\n/**\n * Option for select-type properties\n */\nexport interface ProviderConfigSelectOption {\n /** Value stored in settings */\n value: string\n /** Display label */\n label: string\n}\n\n/**\n * Validation rules for a property\n */\nexport interface ProviderConfigValidation {\n /** Regex pattern the value must match */\n pattern?: string\n /** Minimum string length */\n minLength?: number\n /** Maximum string length */\n maxLength?: number\n /** Minimum number value */\n min?: number\n /** Maximum number value */\n max?: number\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\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// Permissions\n// ============================================================================\n\nexport type Permission =\n | NetworkPermission\n | StoragePermission\n | UserDataPermission\n | CapabilityPermission\n | SystemPermission\n\n/** Network access permissions */\nexport type NetworkPermission =\n | 'network:*'\n | `network:localhost`\n | `network:localhost:${number}`\n | `network:${string}`\n\n/** Storage permissions */\nexport type StoragePermission = 'database.own' | 'storage.local'\n\n/** User data permissions */\nexport type UserDataPermission =\n | 'user.profile.read'\n | 'user.location.read'\n | 'chat.history.read'\n | 'chat.current.read'\n\n/** Capability permissions */\nexport type CapabilityPermission =\n | 'provider.register'\n | 'tools.register'\n | 'actions.register'\n | 'settings.register'\n | 'commands.register'\n | 'panels.register'\n | 'events.emit'\n | 'scheduler.register'\n | 'chat.message.write'\n\n/** System permissions */\nexport type SystemPermission =\n | 'files.read'\n | 'files.write'\n | 'clipboard.read'\n | 'clipboard.write'\n\n// ============================================================================\n// Extension Context (API available to extensions)\n// ============================================================================\n\n/**\n * Disposable resource that can be cleaned up\n */\nexport interface Disposable {\n dispose(): void\n}\n\n/**\n * Context provided to extension's activate function.\n *\n * ## User ID Context\n *\n * The `userId` field provides the current user context for extensions. It is set when:\n * - A tool is executed by a user\n * - An action is executed by a user\n * - A scheduled job fires (if the job was created with a userId)\n *\n * For extension activation, `userId` is undefined since activation happens at system level.\n * Extensions should check for `userId` in their tool/action handlers to access user-specific data.\n *\n * @example\n * ```typescript\n * // In a tool execute handler:\n * execute: async (params, context) => {\n * if (context.userId) {\n * // User-specific logic\n * const userData = await storage.getForUser(context.userId, 'preferences')\n * }\n * }\n * ```\n */\nexport interface ExtensionContext {\n /** Extension metadata */\n readonly extension: {\n readonly id: string\n readonly version: string\n readonly storagePath: string\n }\n\n /**\n * Current user ID if in a user context, undefined for global/system operations.\n * Set when tools or actions are executed by a user, or when a user-scoped job fires.\n */\n readonly userId?: string\n\n /** Network access (if permitted) */\n readonly network?: NetworkAPI\n\n /** Settings access (if permitted) */\n readonly settings?: SettingsAPI\n\n /** Provider registration (if permitted) */\n readonly providers?: ProvidersAPI\n\n /** Tool registration (if permitted) */\n readonly tools?: ToolsAPI\n\n /** Action registration (if permitted) */\n readonly actions?: ActionsAPI\n\n /** Event emission (if permitted) */\n readonly events?: EventsAPI\n\n /** Scheduler access (if permitted) */\n readonly scheduler?: SchedulerAPI\n\n /** User data access (if permitted) */\n readonly user?: UserAPI\n\n /** Chat access (if permitted) */\n readonly chat?: ChatAPI\n\n /** Database access (if permitted) */\n readonly database?: DatabaseAPI\n\n /** Local storage (if permitted) */\n readonly storage?: StorageAPI\n\n /** Logging (always available) */\n readonly log: LogAPI\n}\n\n/**\n * Network API for making HTTP requests\n */\nexport interface NetworkAPI {\n /**\n * Fetch a URL (permissions are enforced by host)\n */\n fetch(url: string, options?: RequestInit): Promise<Response>\n\n /**\n * Streaming fetch for responses like NDJSON or SSE.\n * Yields text chunks as they arrive from the server.\n *\n * @throws {Error} If the request fails or encounters a network error.\n * The error message will contain details about the failure.\n *\n * @example\n * ```typescript\n * try {\n * for await (const chunk of context.network.fetchStream(url, options)) {\n * // Process each chunk (may contain partial lines)\n * buffer += chunk\n * }\n * } catch (error) {\n * console.error('Streaming fetch failed:', error.message)\n * }\n * ```\n */\n fetchStream(url: string, options?: RequestInit): AsyncGenerator<string, void, unknown>\n}\n\n/**\n * Settings API for reading/writing extension settings\n */\nexport interface SettingsAPI {\n /**\n * Get all settings for this extension\n */\n getAll<T extends Record<string, unknown>>(): Promise<T>\n\n /**\n * Get a specific setting value\n */\n get<T>(key: string): Promise<T | undefined>\n\n /**\n * Set a setting value\n */\n set(key: string, value: unknown): Promise<void>\n\n /**\n * Listen for setting changes\n */\n onChange(callback: (key: string, value: unknown) => void): Disposable\n}\n\n/**\n * Providers API for registering AI providers\n */\nexport interface ProvidersAPI {\n /**\n * Register an AI provider\n */\n register(provider: AIProvider): Disposable\n}\n\n/**\n * Tools API for registering tools\n */\nexport interface ToolsAPI {\n /**\n * Register a tool that Stina can use\n */\n register(tool: Tool): Disposable\n}\n\n/**\n * Actions API for registering UI actions\n */\nexport interface ActionsAPI {\n /**\n * Register an action that UI components can invoke\n */\n register(action: Action): Disposable\n}\n\n/**\n * Events API for notifying the host\n */\nexport interface EventsAPI {\n /**\n * Emit a named event with optional payload\n */\n emit(name: string, payload?: Record<string, unknown>): Promise<void>\n}\n\n/**\n * Scheduler schedule types\n */\nexport type SchedulerSchedule =\n | { type: 'at'; at: string }\n | { type: 'cron'; cron: string; timezone?: string }\n | { type: 'interval'; everyMs: number }\n\n/**\n * Scheduler job request\n */\nexport interface SchedulerJobRequest {\n id: string\n schedule: SchedulerSchedule\n payload?: Record<string, unknown>\n misfire?: 'run_once' | 'skip'\n /**\n * Optional user ID for user-scoped jobs.\n * If set, the job is associated with a specific user and the userId\n * will be passed to the extension when the job fires.\n */\n userId?: string\n}\n\n/**\n * Scheduler fire payload\n */\nexport interface SchedulerFirePayload {\n id: string\n payload?: Record<string, unknown>\n scheduledFor: string\n firedAt: string\n delayMs: number\n /** User ID if this is a user-scoped job, undefined if global */\n userId?: string\n}\n\n/**\n * Scheduler API for registering jobs\n */\nexport interface SchedulerAPI {\n schedule(job: SchedulerJobRequest): Promise<void>\n cancel(jobId: string): Promise<void>\n onFire(callback: (payload: SchedulerFirePayload) => void): Disposable\n}\n\n/**\n * User profile data\n */\nexport interface UserProfile {\n firstName?: string\n nickname?: string\n language?: string\n timezone?: string\n}\n\n/**\n * User API for profile access\n */\nexport interface UserAPI {\n getProfile(): Promise<UserProfile>\n}\n\n/**\n * Chat instruction message\n */\nexport interface ChatInstructionMessage {\n text: string\n conversationId?: string\n}\n\n/**\n * Chat API for appending instructions\n */\nexport interface ChatAPI {\n appendInstruction(message: ChatInstructionMessage): Promise<void>\n}\n\n/**\n * Database API for extension-specific tables\n */\nexport interface DatabaseAPI {\n /**\n * Execute a SQL query (only extension's prefixed tables allowed)\n */\n execute<T = unknown>(sql: string, params?: unknown[]): Promise<T[]>\n}\n\n/**\n * Simple key-value storage API with support for user-scoped storage.\n *\n * ## Global vs User-Scoped Storage\n *\n * Extensions have access to two types of storage:\n * - **Global storage**: Shared across all users, accessed via `get()`, `set()`, etc.\n * - **User-scoped storage**: Isolated per user, accessed via `getForUser()`, `setForUser()`, etc.\n *\n * Use global storage for extension-wide settings and user-scoped storage for\n * user preferences, session data, or any data that should be private to a user.\n *\n * @example\n * ```typescript\n * // Global storage (extension-wide)\n * await storage.set('apiEndpoint', 'https://api.example.com')\n * const endpoint = await storage.get<string>('apiEndpoint')\n *\n * // User-scoped storage (per-user)\n * if (context.userId) {\n * await storage.setForUser(context.userId, 'preferences', { theme: 'dark' })\n * const prefs = await storage.getForUser<Preferences>(context.userId, 'preferences')\n * }\n * ```\n */\nexport interface StorageAPI {\n /**\n * Get a value by key (global/extension-scoped)\n */\n get<T>(key: string): Promise<T | undefined>\n\n /**\n * Set a value (global/extension-scoped)\n */\n set(key: string, value: unknown): Promise<void>\n\n /**\n * Delete a key (global/extension-scoped)\n */\n delete(key: string): Promise<void>\n\n /**\n * Get all keys (global/extension-scoped)\n */\n keys(): Promise<string[]>\n\n /**\n * Get a value by key for a specific user (user-scoped)\n * @param userId The user ID\n * @param key The storage key\n */\n getForUser<T>(userId: string, key: string): Promise<T | undefined>\n\n /**\n * Set a value for a specific user (user-scoped)\n * @param userId The user ID\n * @param key The storage key\n * @param value The value to store\n */\n setForUser(userId: string, key: string, value: unknown): Promise<void>\n\n /**\n * Delete a key for a specific user (user-scoped)\n * @param userId The user ID\n * @param key The storage key\n */\n deleteForUser(userId: string, key: string): Promise<void>\n\n /**\n * Get all keys for a specific user (user-scoped)\n * @param userId The user ID\n */\n keysForUser(userId: string): Promise<string[]>\n}\n\n/**\n * Logging API\n */\nexport interface LogAPI {\n debug(message: string, data?: Record<string, unknown>): void\n info(message: string, data?: Record<string, unknown>): void\n warn(message: string, data?: Record<string, unknown>): void\n error(message: string, data?: Record<string, unknown>): void\n}\n\n// ============================================================================\n// AI Provider Types\n// ============================================================================\n\n/**\n * AI provider implementation\n */\nexport interface AIProvider {\n /** Provider ID (must match manifest) */\n id: string\n /** Display name */\n name: string\n\n /**\n * Get available models from this provider\n * @param options Optional settings for the provider (e.g., URL)\n */\n getModels(options?: GetModelsOptions): Promise<ModelInfo[]>\n\n /**\n * Chat completion with streaming\n */\n chat(\n messages: ChatMessage[],\n options: ChatOptions\n ): AsyncGenerator<StreamEvent, void, unknown>\n\n /**\n * Optional: Generate embeddings\n */\n embed?(texts: string[]): Promise<number[][]>\n}\n\n/**\n * Model information\n */\nexport interface ModelInfo {\n /** Model ID */\n id: string\n /** Display name */\n name: string\n /** Description */\n description?: string\n /** Context window size */\n contextLength?: number\n}\n\n/**\n * Chat message\n */\nexport interface ChatMessage {\n role: 'user' | 'assistant' | 'system' | 'tool'\n content: string\n /** For assistant messages: tool calls made by the model */\n tool_calls?: ToolCall[]\n /** For tool messages: the ID of the tool call this is a response to */\n tool_call_id?: string\n}\n\n/**\n * A tool call made by the model\n */\nexport interface ToolCall {\n /** Unique ID for this tool call */\n id: string\n /** Tool name/ID to invoke */\n name: string\n /** Arguments for the tool (as parsed object) */\n arguments: Record<string, unknown>\n}\n\n/**\n * Options for chat completion\n */\nexport interface ChatOptions {\n /** Model to use */\n model?: string\n /** Temperature (0-1) */\n temperature?: number\n /** Maximum tokens to generate */\n maxTokens?: number\n /** Abort signal for cancellation */\n signal?: AbortSignal\n /** Provider-specific settings from model configuration */\n settings?: Record<string, unknown>\n /** Available tools for this request */\n tools?: ToolDefinition[]\n}\n\n/**\n * Options for getModels\n */\nexport interface GetModelsOptions {\n /** Provider-specific settings (e.g., URL for Ollama) */\n settings?: Record<string, unknown>\n}\n\n/**\n * Streaming events from chat\n */\nexport type StreamEvent =\n | { type: 'content'; text: string }\n | { type: 'thinking'; text: string }\n | { type: 'tool_start'; name: string; input: unknown; toolCallId: string }\n | { type: 'tool_end'; name: string; output: unknown; toolCallId: string }\n | { type: 'done'; usage?: { inputTokens: number; outputTokens: number } }\n | { type: 'error'; message: string }\n\n// ============================================================================\n// Tool Types\n// ============================================================================\n\n/**\n * Tool implementation\n */\nexport interface Tool {\n /** Tool ID (must match manifest) */\n id: string\n /** Display name */\n name: string\n /** Description for Stina */\n description: string\n /** Parameter schema (JSON Schema) */\n parameters?: Record<string, unknown>\n\n /**\n * Execute the tool\n */\n execute(params: Record<string, unknown>): Promise<ToolResult>\n}\n\n/**\n * Tool execution result\n */\nexport interface ToolResult {\n /** Whether the tool succeeded */\n success: boolean\n /** Result data (for Stina to use) */\n data?: unknown\n /** Human-readable message */\n message?: string\n /** Error message if failed */\n error?: string\n}\n\n// ============================================================================\n// Action Types (for UI interactions, separate from Tools)\n// ============================================================================\n\n/**\n * Action implementation for UI interactions.\n * Actions are invoked by UI components, not by Stina (AI).\n */\nexport interface Action {\n /** Action ID (unique within the extension) */\n id: string\n\n /**\n * Execute the action\n * @param params Parameters from the UI component (with $-values already resolved)\n */\n execute(params: Record<string, unknown>): Promise<ActionResult>\n}\n\n/**\n * Action execution result\n */\nexport interface ActionResult {\n /** Whether the action succeeded */\n success: boolean\n /** Result data (returned to UI) */\n data?: unknown\n /** Error message if failed */\n error?: string\n}\n\n// ============================================================================\n// Extension Entry Point\n// ============================================================================\n\n/**\n * Extension entry point interface\n */\nexport interface ExtensionModule {\n /**\n * Called when extension is activated\n */\n activate(context: ExtensionContext): void | Disposable | Promise<void | Disposable>\n\n /**\n * Called when extension is deactivated\n */\n deactivate?(): void | Promise<void>\n}\n"],"mappings":";;;;;AAsBO,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;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/types.localization.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"],"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;","names":[]}
|
package/dist/runtime.cjs
CHANGED
|
@@ -90,7 +90,7 @@ async function handleHostMessage(message) {
|
|
|
90
90
|
handleSettingsChanged(message.payload.key, message.payload.value);
|
|
91
91
|
break;
|
|
92
92
|
case "scheduler-fire":
|
|
93
|
-
handleSchedulerFire(message.payload);
|
|
93
|
+
await handleSchedulerFire(message.payload);
|
|
94
94
|
break;
|
|
95
95
|
case "provider-chat-request":
|
|
96
96
|
await handleProviderChatRequest(message.id, message.payload);
|
|
@@ -192,22 +192,23 @@ function handleSettingsChanged(key, value) {
|
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
}
|
|
195
|
-
function handleSchedulerFire(payload) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
callback(payload);
|
|
203
|
-
} catch (error) {
|
|
204
|
-
console.error("Error in scheduler callback:", error);
|
|
195
|
+
async function handleSchedulerFire(payload) {
|
|
196
|
+
const execContext = {
|
|
197
|
+
userId: payload.userId,
|
|
198
|
+
extension: {
|
|
199
|
+
id: extensionContext.extension.id,
|
|
200
|
+
version: extensionContext.extension.version,
|
|
201
|
+
storagePath: extensionContext.extension.storagePath
|
|
205
202
|
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
203
|
+
};
|
|
204
|
+
const results = await Promise.allSettled(
|
|
205
|
+
schedulerCallbacks.map((callback) => callback(payload, execContext))
|
|
206
|
+
);
|
|
207
|
+
results.forEach((result, index) => {
|
|
208
|
+
if (result.status === "rejected") {
|
|
209
|
+
console.error(`Error in scheduler callback ${index}:`, result.reason);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
211
212
|
}
|
|
212
213
|
async function handleProviderChatRequest(requestId, payload) {
|
|
213
214
|
const provider = registeredProviders.get(payload.providerId);
|
|
@@ -305,15 +306,15 @@ async function handleToolExecuteRequest(requestId, payload) {
|
|
|
305
306
|
return;
|
|
306
307
|
}
|
|
307
308
|
try {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
309
|
+
const execContext = {
|
|
310
|
+
userId: payload.userId,
|
|
311
|
+
extension: {
|
|
312
|
+
id: extensionContext.extension.id,
|
|
313
|
+
version: extensionContext.extension.version,
|
|
314
|
+
storagePath: extensionContext.extension.storagePath
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
const result = await tool.execute(payload.params, execContext);
|
|
317
318
|
postMessage({
|
|
318
319
|
type: "tool-execute-response",
|
|
319
320
|
payload: {
|
|
@@ -322,10 +323,6 @@ async function handleToolExecuteRequest(requestId, payload) {
|
|
|
322
323
|
}
|
|
323
324
|
});
|
|
324
325
|
} catch (error) {
|
|
325
|
-
if (extensionContext) {
|
|
326
|
-
;
|
|
327
|
-
extensionContext.userId = void 0;
|
|
328
|
-
}
|
|
329
326
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
330
327
|
postMessage({
|
|
331
328
|
type: "tool-execute-response",
|
|
@@ -351,15 +348,15 @@ async function handleActionExecuteRequest(requestId, payload) {
|
|
|
351
348
|
return;
|
|
352
349
|
}
|
|
353
350
|
try {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
351
|
+
const execContext = {
|
|
352
|
+
userId: payload.userId,
|
|
353
|
+
extension: {
|
|
354
|
+
id: extensionContext.extension.id,
|
|
355
|
+
version: extensionContext.extension.version,
|
|
356
|
+
storagePath: extensionContext.extension.storagePath
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
const result = await action.execute(payload.params, execContext);
|
|
363
360
|
postMessage({
|
|
364
361
|
type: "action-execute-response",
|
|
365
362
|
payload: {
|
|
@@ -368,10 +365,6 @@ async function handleActionExecuteRequest(requestId, payload) {
|
|
|
368
365
|
}
|
|
369
366
|
});
|
|
370
367
|
} catch (error) {
|
|
371
|
-
if (extensionContext) {
|
|
372
|
-
;
|
|
373
|
-
extensionContext.userId = void 0;
|
|
374
|
-
}
|
|
375
368
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
376
369
|
postMessage({
|
|
377
370
|
type: "action-execute-response",
|