@stina/extension-api 0.24.0 → 0.25.0-alpha.1c5b584

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/background.ts","../src/runtime.ts"],"sourcesContent":["/**\n * Background Task Manager (Worker-side)\n *\n * Manages background tasks running inside the extension worker.\n * Handles task execution, AbortController management, and health reporting.\n */\n\nimport type {\n BackgroundTaskConfig,\n BackgroundTaskCallback,\n BackgroundTaskContext,\n BackgroundTaskHealth,\n Disposable,\n LogAPI,\n StorageAPI,\n SecretsAPI,\n} from './types.js'\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Internal representation of a registered task\n */\ninterface RegisteredTask {\n config: BackgroundTaskConfig\n callback: BackgroundTaskCallback\n abortController: AbortController | null\n status: 'pending' | 'running' | 'stopped' | 'failed'\n lastHealthStatus?: string\n lastHealthTime?: string\n error?: string\n}\n\n/**\n * Options for the WorkerBackgroundTaskManager\n */\nexport interface WorkerBackgroundTaskManagerOptions {\n extensionId: string\n extensionVersion: string\n storagePath: string\n /** Send a message to the host */\n sendTaskRegistered: (\n taskId: string,\n name: string,\n userId: string,\n restartPolicy: BackgroundTaskConfig['restartPolicy'],\n payload?: Record<string, unknown>\n ) => void\n /** Send status update to host */\n sendTaskStatus: (taskId: string, status: 'running' | 'stopped' | 'failed', error?: string) => void\n /** Send health report to host */\n sendHealthReport: (taskId: string, status: string, timestamp: string) => void\n /** Create a log API for a task */\n createLogAPI: (taskId: string) => LogAPI\n /** Create extension-scoped storage API */\n createStorageAPI: () => StorageAPI\n /** Create user-scoped storage API */\n createUserStorageAPI: (userId: string) => StorageAPI\n /** Create extension-scoped secrets API */\n createSecretsAPI: () => SecretsAPI\n /** Create user-scoped secrets API */\n createUserSecretsAPI: (userId: string) => SecretsAPI\n}\n\n// ============================================================================\n// WorkerBackgroundTaskManager\n// ============================================================================\n\n/**\n * Manages background tasks within the extension worker.\n */\nexport class WorkerBackgroundTaskManager {\n private readonly tasks = new Map<string, RegisteredTask>()\n private readonly options: WorkerBackgroundTaskManagerOptions\n\n constructor(options: WorkerBackgroundTaskManagerOptions) {\n this.options = options\n }\n\n /**\n * Register and start a background task.\n * @returns A disposable that stops the task when disposed\n */\n async start(config: BackgroundTaskConfig, callback: BackgroundTaskCallback): Promise<Disposable> {\n const { id: taskId } = config\n\n if (this.tasks.has(taskId)) {\n throw new Error(`Background task with id '${taskId}' is already registered`)\n }\n\n const task: RegisteredTask = {\n config,\n callback,\n abortController: null,\n status: 'pending',\n }\n\n this.tasks.set(taskId, task)\n\n // Notify host about the registration\n this.options.sendTaskRegistered(\n taskId,\n config.name,\n config.userId,\n config.restartPolicy,\n config.payload\n )\n\n // Return a disposable that stops the task\n // Task removal should be coordinated with the host to avoid race conditions\n return {\n dispose: () => {\n this.stop(taskId)\n // Don't immediately delete - let the task finish aborting\n // The task will be cleaned up when the extension is deactivated\n },\n }\n }\n\n /**\n * Stop a running task.\n */\n stop(taskId: string): void {\n const task = this.tasks.get(taskId)\n if (!task) {\n return\n }\n\n // Abort the task if it's running\n if (task.abortController) {\n task.abortController.abort()\n task.abortController = null\n }\n\n task.status = 'stopped'\n\n // Notify host that the task has been stopped\n this.options.sendTaskStatus(taskId, 'stopped')\n }\n\n /**\n * Handle start message from host.\n * This is called when the host tells us to actually run the task.\n */\n async handleStart(taskId: string): Promise<void> {\n const task = this.tasks.get(taskId)\n if (!task) {\n return\n }\n\n // If there's already an execution running, abort it first\n if (task.abortController) {\n task.abortController.abort()\n task.abortController = null\n }\n\n // Create new AbortController for this run\n task.abortController = new AbortController()\n task.status = 'running'\n task.error = undefined\n\n // Build the task context\n const context = this.buildTaskContext(task)\n\n // Notify host that we're running\n this.options.sendTaskStatus(taskId, 'running')\n\n try {\n // Execute the callback\n await task.callback(context)\n\n // Task completed normally (or was aborted)\n if (task.abortController?.signal.aborted) {\n task.status = 'stopped'\n this.options.sendTaskStatus(taskId, 'stopped')\n } else {\n // Task finished without being aborted - treat as stopped\n task.status = 'stopped'\n this.options.sendTaskStatus(taskId, 'stopped')\n }\n } catch (error) {\n // Task failed with an error\n const errorMessage = error instanceof Error ? error.message : String(error)\n task.status = 'failed'\n task.error = errorMessage\n this.options.sendTaskStatus(taskId, 'failed', errorMessage)\n } finally {\n task.abortController = null\n }\n }\n\n /**\n * Handle stop message from host.\n */\n handleStop(taskId: string): void {\n this.stop(taskId)\n }\n\n /**\n * Build the execution context for a task.\n */\n private buildTaskContext(task: RegisteredTask): BackgroundTaskContext {\n const { config, abortController } = task\n const signal = abortController!.signal\n\n const log = this.options.createLogAPI(config.id)\n\n // Create storage and secrets APIs\n const storage = this.options.createStorageAPI()\n const userStorage = config.userId\n ? this.options.createUserStorageAPI(config.userId)\n : storage\n const secrets = this.options.createSecretsAPI()\n const userSecrets = config.userId\n ? this.options.createUserSecretsAPI(config.userId)\n : secrets\n\n const context: BackgroundTaskContext = {\n userId: config.userId,\n extension: {\n id: this.options.extensionId,\n version: this.options.extensionVersion,\n storagePath: this.options.storagePath,\n },\n storage,\n userStorage,\n secrets,\n userSecrets,\n signal,\n reportHealth: (status: string) => {\n const timestamp = new Date().toISOString()\n task.lastHealthStatus = status\n task.lastHealthTime = timestamp\n this.options.sendHealthReport(config.id, status, timestamp)\n },\n log,\n }\n\n return context\n }\n\n /**\n * Get the status of all tasks.\n */\n getStatus(): BackgroundTaskHealth[] {\n const result: BackgroundTaskHealth[] = []\n\n for (const task of this.tasks.values()) {\n result.push({\n taskId: task.config.id,\n name: task.config.name,\n userId: task.config.userId,\n status: task.status,\n restartCount: 0, // Worker doesn't track restarts, host does\n lastHealthStatus: task.lastHealthStatus,\n lastHealthTime: task.lastHealthTime,\n error: task.error,\n })\n }\n\n return result\n }\n\n /**\n * Check if a task exists.\n */\n hasTask(taskId: string): boolean {\n return this.tasks.has(taskId)\n }\n\n /**\n * Clean up all tasks.\n * Called during extension deactivation.\n */\n dispose(): void {\n for (const task of this.tasks.values()) {\n if (task.abortController) {\n task.abortController.abort()\n }\n }\n this.tasks.clear()\n }\n}\n","/**\n * Extension Runtime - Runs inside the worker\n *\n * This module handles communication with the Extension Host and provides\n * the ExtensionContext to the extension's activate function.\n */\n\nimport type {\n ExecutionContext,\n ExtensionContext,\n ExtensionModule,\n Disposable,\n NetworkAPI,\n SettingsAPI,\n ProvidersAPI,\n ToolsAPI,\n ActionsAPI,\n EventsAPI,\n SchedulerAPI,\n SchedulerJobRequest,\n SchedulerFirePayload,\n UserAPI,\n UserProfile,\n ChatAPI,\n ChatInstructionMessage,\n StorageAPI,\n SecretsAPI,\n Query,\n QueryOptions,\n LogAPI,\n AIProvider,\n Tool,\n Action,\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n BackgroundWorkersAPI,\n BackgroundTaskConfig,\n BackgroundTaskCallback,\n BackgroundTaskHealth,\n} from './types.js'\n\nimport { WorkerBackgroundTaskManager } from './background.js'\n\nimport type {\n HostToWorkerMessage,\n WorkerToHostMessage,\n RequestMessage,\n PendingRequest,\n} from './messages.js'\n\nimport { generateMessageId } from './messages.js'\n\n// ============================================================================\n// Environment Detection and Message Port\n// ============================================================================\n\n/**\n * Detect if we're in Node.js Worker Thread or Web Worker\n * and get the appropriate message port\n */\ninterface MessagePort {\n postMessage(message: WorkerToHostMessage): void\n onMessage(handler: (message: HostToWorkerMessage) => void): void\n}\n\nfunction getMessagePort(): MessagePort {\n // Check if we're in Node.js Worker Thread\n if (typeof process !== 'undefined' && process.versions?.node) {\n // Node.js Worker Thread - import parentPort dynamically\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { parentPort } = require('node:worker_threads')\n return {\n postMessage: (message) => parentPort?.postMessage(message),\n onMessage: (handler) => parentPort?.on('message', handler),\n }\n }\n\n // Web Worker - use self\n return {\n postMessage: (message) => self.postMessage(message),\n onMessage: (handler) => {\n self.addEventListener('message', (event: MessageEvent<HostToWorkerMessage>) => {\n handler(event.data)\n })\n },\n }\n}\n\nconst messagePort = getMessagePort()\n\n// ============================================================================\n// Global State\n// ============================================================================\n\nlet extensionModule: ExtensionModule | null = null\nlet extensionDisposable: Disposable | null = null\nlet extensionContext: ExtensionContext | null = null\nlet backgroundTaskManager: WorkerBackgroundTaskManager | null = null\n\nconst pendingRequests = new Map<string, PendingRequest>()\nconst registeredProviders = new Map<string, AIProvider>()\nconst registeredTools = new Map<string, Tool>()\nconst registeredActions = new Map<string, Action>()\nconst settingsCallbacks: Array<(key: string, value: unknown) => void> = []\nconst schedulerCallbacks: Array<(payload: SchedulerFirePayload, context: ExecutionContext) => void | Promise<void>> = []\n\n/**\n * Tracking for streaming fetch requests.\n * Each request stores incoming chunks and signals when new data arrives.\n */\ninterface StreamingFetchRequest {\n chunks: string[]\n done: boolean\n error?: string\n resolve?: () => void\n}\nconst streamingFetchRequests = new Map<string, StreamingFetchRequest>()\n\nconst REQUEST_TIMEOUT = 30000 // 30 seconds\n\n// ============================================================================\n// Message Handling\n// ============================================================================\n\n/**\n * Send a message to the host\n */\nfunction postMessage(message: WorkerToHostMessage): void {\n messagePort.postMessage(message)\n}\n\n/**\n * Send a request to the host and wait for response\n */\nasync function sendRequest<T>(method: RequestMessage['method'], payload: unknown): Promise<T> {\n const id = generateMessageId()\n\n return new Promise<T>((resolve, reject) => {\n const timeout = setTimeout(() => {\n pendingRequests.delete(id)\n reject(new Error(`Request ${method} timed out`))\n }, REQUEST_TIMEOUT)\n\n pendingRequests.set(id, { resolve: resolve as (value: unknown) => void, reject, timeout })\n\n postMessage({\n type: 'request',\n id,\n method,\n payload,\n })\n })\n}\n\n/**\n * Handle messages from the host\n */\nasync function handleHostMessage(message: HostToWorkerMessage): Promise<void> {\n switch (message.type) {\n case 'activate':\n await handleActivate(message.payload)\n break\n\n case 'deactivate':\n await handleDeactivate()\n break\n\n case 'settings-changed':\n handleSettingsChanged(message.payload.key, message.payload.value)\n break\n\n case 'scheduler-fire':\n await handleSchedulerFire(message.payload)\n break\n\n case 'provider-chat-request':\n await handleProviderChatRequest(message.id, message.payload)\n break\n\n case 'provider-models-request':\n await handleProviderModelsRequest(message.id, message.payload)\n break\n\n case 'tool-execute-request':\n await handleToolExecuteRequest(message.id, message.payload)\n break\n\n case 'action-execute-request':\n await handleActionExecuteRequest(message.id, message.payload)\n break\n\n case 'response':\n handleResponse(message.payload)\n break\n\n case 'streaming-fetch-chunk':\n handleStreamingFetchChunk(message.payload)\n break\n\n case 'background-task-start':\n await handleBackgroundTaskStart(message.payload.taskId)\n break\n\n case 'background-task-stop':\n handleBackgroundTaskStop(message.payload.taskId)\n break\n }\n}\n\n/**\n * Handle incoming streaming fetch chunks from the host\n */\nfunction handleStreamingFetchChunk(payload: {\n requestId: string\n chunk: string\n done: boolean\n error?: string\n}): void {\n const request = streamingFetchRequests.get(payload.requestId)\n if (!request) return\n\n if (payload.error) {\n request.error = payload.error\n request.done = true\n } else if (payload.chunk) {\n request.chunks.push(payload.chunk)\n }\n\n if (payload.done) {\n request.done = true\n }\n\n // Signal that new data is available\n if (request.resolve) {\n const resolve = request.resolve\n request.resolve = undefined\n resolve()\n }\n\n // Send acknowledgment for backpressure control\n postMessage({\n type: 'streaming-fetch-ack',\n payload: { requestId: payload.requestId },\n })\n}\n\nfunction handleResponse(payload: { requestId: string; success: boolean; data?: unknown; error?: string }): void {\n const pending = pendingRequests.get(payload.requestId)\n if (!pending) return\n\n clearTimeout(pending.timeout)\n pendingRequests.delete(payload.requestId)\n\n if (payload.success) {\n pending.resolve(payload.data)\n } else {\n pending.reject(new Error(payload.error || 'Unknown error'))\n }\n}\n\n// ============================================================================\n// Activation / Deactivation\n// ============================================================================\n\nasync function handleActivate(payload: {\n extensionId: string\n extensionVersion: string\n storagePath: string\n permissions: string[]\n settings: Record<string, unknown>\n}): Promise<void> {\n const { extensionId, extensionVersion, storagePath, permissions } = payload\n\n // Build the context based on permissions\n extensionContext = buildContext(extensionId, extensionVersion, storagePath, permissions)\n\n // Import and activate the extension\n try {\n // The actual extension code should be bundled and available\n // This is called after the extension code has been loaded into the worker\n if (extensionModule?.activate) {\n const result = await extensionModule.activate(extensionContext)\n if (result && 'dispose' in result) {\n extensionDisposable = result\n }\n }\n } catch (error) {\n extensionContext.log.error('Failed to activate extension', {\n error: error instanceof Error ? error.message : String(error),\n })\n throw error\n }\n}\n\nasync function handleDeactivate(): Promise<void> {\n try {\n if (extensionModule?.deactivate) {\n await extensionModule.deactivate()\n }\n if (extensionDisposable) {\n extensionDisposable.dispose()\n }\n if (backgroundTaskManager) {\n backgroundTaskManager.dispose()\n }\n } catch (error) {\n console.error('Error during deactivation:', error)\n } finally {\n extensionModule = null\n extensionDisposable = null\n extensionContext = null\n backgroundTaskManager = null\n registeredProviders.clear()\n registeredTools.clear()\n registeredActions.clear()\n settingsCallbacks.length = 0\n schedulerCallbacks.length = 0\n }\n}\n\nfunction handleSettingsChanged(key: string, value: unknown): void {\n for (const callback of settingsCallbacks) {\n try {\n callback(key, value)\n } catch (error) {\n console.error('Error in settings change callback:', error)\n }\n }\n}\n\n/**\n * Build extension-scoped storage API\n */\nfunction buildExtensionStorageAPI(): StorageAPI {\n return {\n async put<T extends object>(collection: string, id: string, data: T): Promise<void> {\n return sendRequest<void>('storage.put', { collection, id, data })\n },\n async get<T>(collection: string, id: string): Promise<T | undefined> {\n return sendRequest<T | undefined>('storage.get', { collection, id })\n },\n async delete(collection: string, id: string): Promise<boolean> {\n return sendRequest<boolean>('storage.delete', { collection, id })\n },\n async find<T>(collection: string, query?: Query, options?: QueryOptions): Promise<T[]> {\n return sendRequest<T[]>('storage.find', { collection, query, options })\n },\n async findOne<T>(collection: string, query: Query): Promise<T | undefined> {\n return sendRequest<T | undefined>('storage.findOne', { collection, query })\n },\n async count(collection: string, query?: Query): Promise<number> {\n return sendRequest<number>('storage.count', { collection, query })\n },\n async putMany<T extends object>(collection: string, docs: Array<{ id: string; data: T }>): Promise<void> {\n return sendRequest<void>('storage.putMany', { collection, docs })\n },\n async deleteMany(collection: string, query: Query): Promise<number> {\n return sendRequest<number>('storage.deleteMany', { collection, query })\n },\n async dropCollection(collection: string): Promise<void> {\n return sendRequest<void>('storage.dropCollection', { collection })\n },\n async listCollections(): Promise<string[]> {\n return sendRequest<string[]>('storage.listCollections', {})\n },\n }\n}\n\n/**\n * Build user-scoped storage API\n */\nfunction buildUserStorageAPI(userId: string): StorageAPI {\n return {\n async put<T extends object>(collection: string, id: string, data: T): Promise<void> {\n return sendRequest<void>('storage.putForUser', { userId, collection, id, data })\n },\n async get<T>(collection: string, id: string): Promise<T | undefined> {\n return sendRequest<T | undefined>('storage.getForUser', { userId, collection, id })\n },\n async delete(collection: string, id: string): Promise<boolean> {\n return sendRequest<boolean>('storage.deleteForUser', { userId, collection, id })\n },\n async find<T>(collection: string, query?: Query, options?: QueryOptions): Promise<T[]> {\n return sendRequest<T[]>('storage.findForUser', { userId, collection, query, options })\n },\n async findOne<T>(collection: string, query: Query): Promise<T | undefined> {\n return sendRequest<T | undefined>('storage.findOneForUser', { userId, collection, query })\n },\n async count(collection: string, query?: Query): Promise<number> {\n return sendRequest<number>('storage.countForUser', { userId, collection, query })\n },\n async putMany<T extends object>(collection: string, docs: Array<{ id: string; data: T }>): Promise<void> {\n return sendRequest<void>('storage.putManyForUser', { userId, collection, docs })\n },\n async deleteMany(collection: string, query: Query): Promise<number> {\n return sendRequest<number>('storage.deleteManyForUser', { userId, collection, query })\n },\n async dropCollection(collection: string): Promise<void> {\n return sendRequest<void>('storage.dropCollectionForUser', { userId, collection })\n },\n async listCollections(): Promise<string[]> {\n return sendRequest<string[]>('storage.listCollectionsForUser', { userId })\n },\n }\n}\n\n/**\n * Build extension-scoped secrets API\n */\nfunction buildExtensionSecretsAPI(): SecretsAPI {\n return {\n async set(key: string, value: string): Promise<void> {\n return sendRequest<void>('secrets.set', { key, value })\n },\n async get(key: string): Promise<string | undefined> {\n return sendRequest<string | undefined>('secrets.get', { key })\n },\n async delete(key: string): Promise<boolean> {\n return sendRequest<boolean>('secrets.delete', { key })\n },\n async list(): Promise<string[]> {\n return sendRequest<string[]>('secrets.list', {})\n },\n }\n}\n\n/**\n * Build user-scoped secrets API\n */\nfunction buildUserSecretsAPI(userId: string): SecretsAPI {\n return {\n async set(key: string, value: string): Promise<void> {\n return sendRequest<void>('secrets.setForUser', { userId, key, value })\n },\n async get(key: string): Promise<string | undefined> {\n return sendRequest<string | undefined>('secrets.getForUser', { userId, key })\n },\n async delete(key: string): Promise<boolean> {\n return sendRequest<boolean>('secrets.deleteForUser', { userId, key })\n },\n async list(): Promise<string[]> {\n return sendRequest<string[]>('secrets.listForUser', { userId })\n },\n }\n}\n\nasync function handleSchedulerFire(payload: SchedulerFirePayload): Promise<void> {\n // Create request-scoped execution context with storage and secrets\n const execContext: ExecutionContext = {\n userId: payload.userId,\n extension: {\n id: extensionContext!.extension.id,\n version: extensionContext!.extension.version,\n storagePath: extensionContext!.extension.storagePath,\n },\n storage: buildExtensionStorageAPI(),\n userStorage: payload.userId ? buildUserStorageAPI(payload.userId) : buildExtensionStorageAPI(),\n secrets: buildExtensionSecretsAPI(),\n userSecrets: payload.userId ? buildUserSecretsAPI(payload.userId) : buildExtensionSecretsAPI(),\n }\n\n // Run callbacks concurrently to avoid blocking\n const results = await Promise.allSettled(\n schedulerCallbacks.map((callback) => callback(payload, execContext)),\n )\n\n // Log any errors\n results.forEach((result, index) => {\n if (result.status === 'rejected') {\n console.error(`Error in scheduler callback ${index}:`, result.reason)\n }\n })\n}\n\n// ============================================================================\n// Background Task Handlers\n// ============================================================================\n\nasync function handleBackgroundTaskStart(taskId: string): Promise<void> {\n if (!backgroundTaskManager) {\n console.error('Background task manager not initialized')\n return\n }\n await backgroundTaskManager.handleStart(taskId)\n}\n\nfunction handleBackgroundTaskStop(taskId: string): void {\n if (!backgroundTaskManager) {\n console.error('Background task manager not initialized')\n return\n }\n backgroundTaskManager.handleStop(taskId)\n}\n\n// ============================================================================\n// Provider / Tool Requests\n// ============================================================================\n\nasync function handleProviderChatRequest(\n requestId: string,\n payload: { providerId: string; messages: ChatMessage[]; options: ChatOptions }\n): Promise<void> {\n const provider = registeredProviders.get(payload.providerId)\n if (!provider) {\n postMessage({\n type: 'request',\n id: generateMessageId(),\n method: 'network.fetch', // Dummy, we need a proper error response\n payload: { error: `Provider ${payload.providerId} not found` },\n })\n return\n }\n\n try {\n const generator = provider.chat(payload.messages, payload.options)\n let sawDone = false\n let sawError = false\n\n for await (const event of generator) {\n if (event.type === 'done') {\n sawDone = true\n } else if (event.type === 'error') {\n sawError = true\n }\n postMessage({\n type: 'stream-event',\n payload: { requestId, event },\n })\n }\n\n if (!sawDone && !sawError) {\n postMessage({\n type: 'stream-event',\n payload: {\n requestId,\n event: { type: 'done' },\n },\n })\n }\n } catch (error) {\n postMessage({\n type: 'stream-event',\n payload: {\n requestId,\n event: {\n type: 'error',\n message: error instanceof Error ? error.message : String(error),\n },\n },\n })\n }\n}\n\nasync function handleProviderModelsRequest(\n requestId: string,\n payload: { providerId: string; options?: GetModelsOptions }\n): Promise<void> {\n const provider = registeredProviders.get(payload.providerId)\n if (!provider) {\n // Send error response\n postMessage({\n type: 'provider-models-response',\n payload: {\n requestId,\n models: [],\n error: `Provider ${payload.providerId} not found`,\n },\n })\n return\n }\n\n try {\n // Pass options to getModels so provider can use settings (e.g., URL for Ollama)\n const models = await provider.getModels(payload.options)\n // Send response with models\n postMessage({\n type: 'provider-models-response',\n payload: {\n requestId,\n models,\n },\n })\n } catch (error) {\n postMessage({\n type: 'provider-models-response',\n payload: {\n requestId,\n models: [],\n error: error instanceof Error ? error.message : String(error),\n },\n })\n }\n}\n\nasync function handleToolExecuteRequest(\n requestId: string,\n payload: { toolId: string; params: Record<string, unknown>; userId?: string }\n): Promise<void> {\n const tool = registeredTools.get(payload.toolId)\n if (!tool) {\n // Send error response\n postMessage({\n type: 'tool-execute-response',\n payload: {\n requestId,\n result: { success: false, error: `Tool ${payload.toolId} not found` },\n error: `Tool ${payload.toolId} not found`,\n },\n })\n return\n }\n\n try {\n // Create request-scoped execution context with storage and secrets\n const execContext: ExecutionContext = {\n userId: payload.userId,\n extension: {\n id: extensionContext!.extension.id,\n version: extensionContext!.extension.version,\n storagePath: extensionContext!.extension.storagePath,\n },\n storage: buildExtensionStorageAPI(),\n userStorage: payload.userId ? buildUserStorageAPI(payload.userId) : buildExtensionStorageAPI(),\n secrets: buildExtensionSecretsAPI(),\n userSecrets: payload.userId ? buildUserSecretsAPI(payload.userId) : buildExtensionSecretsAPI(),\n }\n\n const result = await tool.execute(payload.params, execContext)\n\n // Send response with result\n postMessage({\n type: 'tool-execute-response',\n payload: {\n requestId,\n result,\n },\n })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n postMessage({\n type: 'tool-execute-response',\n payload: {\n requestId,\n result: { success: false, error: errorMessage },\n error: errorMessage,\n },\n })\n }\n}\n\nasync function handleActionExecuteRequest(\n requestId: string,\n payload: { actionId: string; params: Record<string, unknown>; userId?: string }\n): Promise<void> {\n const action = registeredActions.get(payload.actionId)\n if (!action) {\n postMessage({\n type: 'action-execute-response',\n payload: {\n requestId,\n result: { success: false, error: `Action ${payload.actionId} not found` },\n error: `Action ${payload.actionId} not found`,\n },\n })\n return\n }\n\n try {\n // Create request-scoped execution context with storage and secrets\n const execContext: ExecutionContext = {\n userId: payload.userId,\n extension: {\n id: extensionContext!.extension.id,\n version: extensionContext!.extension.version,\n storagePath: extensionContext!.extension.storagePath,\n },\n storage: buildExtensionStorageAPI(),\n userStorage: payload.userId ? buildUserStorageAPI(payload.userId) : buildExtensionStorageAPI(),\n secrets: buildExtensionSecretsAPI(),\n userSecrets: payload.userId ? buildUserSecretsAPI(payload.userId) : buildExtensionSecretsAPI(),\n }\n\n const result = await action.execute(payload.params, execContext)\n\n postMessage({\n type: 'action-execute-response',\n payload: {\n requestId,\n result,\n },\n })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n postMessage({\n type: 'action-execute-response',\n payload: {\n requestId,\n result: { success: false, error: errorMessage },\n error: errorMessage,\n },\n })\n }\n}\n\n// ============================================================================\n// Context Building\n// ============================================================================\n\nfunction buildContext(\n extensionId: string,\n extensionVersion: string,\n storagePath: string,\n permissions: string[]\n): ExtensionContext {\n const hasPermission = (perm: string): boolean => {\n return permissions.some((p) => {\n if (p === perm) return true\n if (p.endsWith(':*') && perm.startsWith(p.slice(0, -1))) return true\n return false\n })\n }\n\n const log: LogAPI = {\n debug: (message, data) => postMessage({ type: 'log', payload: { level: 'debug', message, data } }),\n info: (message, data) => postMessage({ type: 'log', payload: { level: 'info', message, data } }),\n warn: (message, data) => postMessage({ type: 'log', payload: { level: 'warn', message, data } }),\n error: (message, data) => postMessage({ type: 'log', payload: { level: 'error', message, data } }),\n }\n\n const context: ExtensionContext = {\n extension: {\n id: extensionId,\n version: extensionVersion,\n storagePath,\n },\n log,\n }\n\n // Add network API if permitted\n if (permissions.some((p) => p.startsWith('network:'))) {\n const networkApi: NetworkAPI = {\n async fetch(url: string, options?: RequestInit): Promise<Response> {\n const result = await sendRequest<{ status: number; statusText: string; headers: Record<string, string>; body: string }>('network.fetch', { url, options })\n return new Response(result.body, {\n status: result.status,\n statusText: result.statusText,\n headers: result.headers,\n })\n },\n\n async *fetchStream(url: string, options?: RequestInit): AsyncGenerator<string, void, unknown> {\n const requestId = generateMessageId()\n\n // Set up streaming request tracking\n const request: StreamingFetchRequest = {\n chunks: [],\n done: false,\n }\n streamingFetchRequests.set(requestId, request)\n\n // Send the streaming fetch request to the host\n postMessage({\n type: 'request',\n id: requestId,\n method: 'network.fetch-stream',\n payload: { url, options, requestId },\n })\n\n try {\n // Yield chunks as they arrive\n while (!request.done) {\n // Wait for new data\n await new Promise<void>((resolve) => {\n const resolver = () => {\n // Clear the stored resolver before resolving to avoid\n // stale callbacks being invoked for a new wait iteration.\n if (request.resolve === resolver) {\n request.resolve = undefined\n }\n resolve()\n }\n\n request.resolve = resolver\n\n // Check if we already have data or completion\n if (request.chunks.length > 0 || request.done) {\n resolver()\n }\n })\n\n // Check for errors first, before yielding any chunks\n if (request.error) {\n throw new Error(request.error)\n }\n\n // Yield all available chunks\n while (request.chunks.length > 0) {\n yield request.chunks.shift()!\n }\n }\n } finally {\n streamingFetchRequests.delete(requestId)\n }\n },\n }\n ;(context as { network: NetworkAPI }).network = networkApi\n }\n\n // Add settings API if permitted\n if (hasPermission('settings.register')) {\n const settingsApi: SettingsAPI = {\n async getAll<T extends Record<string, unknown>>(): Promise<T> {\n return sendRequest<T>('settings.getAll', {})\n },\n async get<T>(key: string): Promise<T | undefined> {\n return sendRequest<T | undefined>('settings.get', { key })\n },\n async set(key: string, value: unknown): Promise<void> {\n return sendRequest<void>('settings.set', { key, value })\n },\n onChange(callback: (key: string, value: unknown) => void): Disposable {\n settingsCallbacks.push(callback)\n return {\n dispose: () => {\n const index = settingsCallbacks.indexOf(callback)\n if (index >= 0) settingsCallbacks.splice(index, 1)\n },\n }\n },\n }\n ;(context as { settings: SettingsAPI }).settings = settingsApi\n }\n\n // Add providers API if permitted\n if (hasPermission('provider.register')) {\n const providersApi: ProvidersAPI = {\n register(provider: AIProvider): Disposable {\n registeredProviders.set(provider.id, provider)\n postMessage({\n type: 'provider-registered',\n payload: { id: provider.id, name: provider.name },\n })\n return {\n dispose: () => {\n registeredProviders.delete(provider.id)\n },\n }\n },\n }\n ;(context as { providers: ProvidersAPI }).providers = providersApi\n }\n\n // Add tools API if permitted\n if (hasPermission('tools.register')) {\n const toolsApi: ToolsAPI = {\n register(tool: Tool): Disposable {\n registeredTools.set(tool.id, tool)\n postMessage({\n type: 'tool-registered',\n payload: {\n id: tool.id,\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters,\n },\n })\n return {\n dispose: () => {\n registeredTools.delete(tool.id)\n },\n }\n },\n }\n ;(context as { tools: ToolsAPI }).tools = toolsApi\n }\n\n // Add actions API if permitted\n if (hasPermission('actions.register')) {\n const actionsApi: ActionsAPI = {\n register(action: Action): Disposable {\n registeredActions.set(action.id, action)\n postMessage({\n type: 'action-registered',\n payload: {\n id: action.id,\n },\n })\n return {\n dispose: () => {\n registeredActions.delete(action.id)\n },\n }\n },\n }\n ;(context as { actions: ActionsAPI }).actions = actionsApi\n }\n\n // Add events API if permitted\n if (hasPermission('events.emit')) {\n const eventsApi: EventsAPI = {\n async emit(name: string, payload?: Record<string, unknown>): Promise<void> {\n await sendRequest<void>('events.emit', { name, payload })\n },\n }\n ;(context as { events: EventsAPI }).events = eventsApi\n }\n\n // Add scheduler API if permitted\n if (hasPermission('scheduler.register')) {\n const schedulerApi: SchedulerAPI = {\n async schedule(job: SchedulerJobRequest): Promise<void> {\n // Extensions must explicitly set job.userId if they want user-scoped jobs\n // Use context.userId from the ExecutionContext in tool/action execute\n await sendRequest<void>('scheduler.schedule', { job })\n },\n async cancel(jobId: string): Promise<void> {\n await sendRequest<void>('scheduler.cancel', { jobId })\n },\n onFire(callback: (payload: SchedulerFirePayload, context: ExecutionContext) => void): Disposable {\n schedulerCallbacks.push(callback)\n return {\n dispose: () => {\n const index = schedulerCallbacks.indexOf(callback)\n if (index >= 0) schedulerCallbacks.splice(index, 1)\n },\n }\n },\n }\n ;(context as { scheduler: SchedulerAPI }).scheduler = schedulerApi\n }\n\n // Add user profile API if permitted\n if (hasPermission('user.profile.read')) {\n const userApi: UserAPI = {\n async getProfile(): Promise<UserProfile> {\n return sendRequest<UserProfile>('user.getProfile', {})\n },\n }\n ;(context as { user: UserAPI }).user = userApi\n }\n\n // Add chat API if permitted\n if (hasPermission('chat.message.write')) {\n const chatApi: ChatAPI = {\n async appendInstruction(message: ChatInstructionMessage): Promise<void> {\n // Extensions must explicitly set message.userId if they want user-scoped messages\n // Use context.userId from the ExecutionContext in tool/action execute\n await sendRequest<void>('chat.appendInstruction', message)\n },\n }\n ;(context as { chat: ChatAPI }).chat = chatApi\n }\n\n // Add storage API if permitted (new collection-based storage)\n if (hasPermission('storage.collections')) {\n ;(context as { storage: StorageAPI }).storage = buildExtensionStorageAPI()\n }\n\n // Add secrets API if permitted\n if (hasPermission('secrets.manage')) {\n ;(context as { secrets: SecretsAPI }).secrets = buildExtensionSecretsAPI()\n }\n\n // Add background workers API if permitted\n if (hasPermission('background.workers')) {\n // Initialize the background task manager if not already done\n if (!backgroundTaskManager) {\n backgroundTaskManager = new WorkerBackgroundTaskManager({\n extensionId,\n extensionVersion,\n storagePath,\n sendTaskRegistered: (taskId, name, userId, restartPolicy, payload) => {\n postMessage({\n type: 'background-task-registered',\n payload: {\n taskId,\n name,\n userId,\n restartPolicy,\n payload,\n },\n })\n },\n sendTaskStatus: (taskId, status, error) => {\n postMessage({\n type: 'background-task-status',\n payload: {\n taskId,\n status,\n error,\n },\n })\n },\n sendHealthReport: (taskId, status, timestamp) => {\n postMessage({\n type: 'background-task-health',\n payload: {\n taskId,\n status,\n timestamp,\n },\n })\n },\n createLogAPI: (taskId) => ({\n debug: (message, data) =>\n postMessage({ type: 'log', payload: { level: 'debug', message: `[${taskId}] ${message}`, data } }),\n info: (message, data) =>\n postMessage({ type: 'log', payload: { level: 'info', message: `[${taskId}] ${message}`, data } }),\n warn: (message, data) =>\n postMessage({ type: 'log', payload: { level: 'warn', message: `[${taskId}] ${message}`, data } }),\n error: (message, data) =>\n postMessage({ type: 'log', payload: { level: 'error', message: `[${taskId}] ${message}`, data } }),\n }),\n createStorageAPI: () => buildExtensionStorageAPI(),\n createUserStorageAPI: (userId) => buildUserStorageAPI(userId),\n createSecretsAPI: () => buildExtensionSecretsAPI(),\n createUserSecretsAPI: (userId) => buildUserSecretsAPI(userId),\n })\n }\n\n const backgroundWorkersApi: BackgroundWorkersAPI = {\n async start(config: BackgroundTaskConfig, callback: BackgroundTaskCallback): Promise<Disposable> {\n return backgroundTaskManager!.start(config, callback)\n },\n async stop(taskId: string): Promise<void> {\n backgroundTaskManager!.stop(taskId)\n },\n async getStatus(): Promise<BackgroundTaskHealth[]> {\n return backgroundTaskManager!.getStatus()\n },\n }\n ;(context as { backgroundWorkers: BackgroundWorkersAPI }).backgroundWorkers = backgroundWorkersApi\n }\n\n return context\n}\n\n// ============================================================================\n// Initialization\n// ============================================================================\n\n/**\n * Initialize the extension runtime\n * This should be called by the extension's entry point\n */\nexport function initializeExtension(module: ExtensionModule): void {\n extensionModule = module\n\n // Set up message listener using the appropriate message port\n messagePort.onMessage(async (message: HostToWorkerMessage) => {\n try {\n await handleHostMessage(message)\n } catch (error) {\n console.error('Error handling message:', error)\n }\n })\n\n // Signal that we're ready\n postMessage({ type: 'ready' })\n}\n\n// Re-export types for extensions to use\nexport type {\n ExecutionContext,\n ExtensionContext,\n ExtensionModule,\n Disposable,\n AIProvider,\n Tool,\n ToolDefinition,\n ToolResult,\n ToolCall,\n Action,\n ActionResult,\n ModelInfo,\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n // Storage and secrets\n StorageAPI,\n SecretsAPI,\n Query,\n QueryOptions,\n // Background workers\n BackgroundWorkersAPI,\n BackgroundTaskConfig,\n BackgroundTaskCallback,\n BackgroundTaskContext,\n BackgroundTaskHealth,\n BackgroundRestartPolicy,\n} from './types.js'\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/background.ts","../src/runtime.ts"],"sourcesContent":["/**\n * Background Task Manager (Worker-side)\n *\n * Manages background tasks running inside the extension worker.\n * Handles task execution, AbortController management, and health reporting.\n */\n\nimport type {\n BackgroundTaskConfig,\n BackgroundTaskCallback,\n BackgroundTaskContext,\n BackgroundTaskHealth,\n Disposable,\n LogAPI,\n StorageAPI,\n SecretsAPI,\n} from './types.js'\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Internal representation of a registered task\n */\ninterface RegisteredTask {\n config: BackgroundTaskConfig\n callback: BackgroundTaskCallback\n abortController: AbortController | null\n status: 'pending' | 'running' | 'stopped' | 'failed'\n lastHealthStatus?: string\n lastHealthTime?: string\n error?: string\n}\n\n/**\n * Options for the WorkerBackgroundTaskManager\n */\nexport interface WorkerBackgroundTaskManagerOptions {\n extensionId: string\n extensionVersion: string\n storagePath: string\n /** Send a message to the host */\n sendTaskRegistered: (\n taskId: string,\n name: string,\n userId: string,\n restartPolicy: BackgroundTaskConfig['restartPolicy'],\n payload?: Record<string, unknown>\n ) => void\n /** Send status update to host */\n sendTaskStatus: (taskId: string, status: 'running' | 'stopped' | 'failed', error?: string) => void\n /** Send health report to host */\n sendHealthReport: (taskId: string, status: string, timestamp: string) => void\n /** Create a log API for a task */\n createLogAPI: (taskId: string) => LogAPI\n /** Create extension-scoped storage API */\n createStorageAPI: () => StorageAPI\n /** Create user-scoped storage API */\n createUserStorageAPI: (userId: string) => StorageAPI\n /** Create extension-scoped secrets API */\n createSecretsAPI: () => SecretsAPI\n /** Create user-scoped secrets API */\n createUserSecretsAPI: (userId: string) => SecretsAPI\n}\n\n// ============================================================================\n// WorkerBackgroundTaskManager\n// ============================================================================\n\n/**\n * Manages background tasks within the extension worker.\n */\nexport class WorkerBackgroundTaskManager {\n private readonly tasks = new Map<string, RegisteredTask>()\n private readonly options: WorkerBackgroundTaskManagerOptions\n\n constructor(options: WorkerBackgroundTaskManagerOptions) {\n this.options = options\n }\n\n /**\n * Register and start a background task.\n * @returns A disposable that stops the task when disposed\n */\n async start(config: BackgroundTaskConfig, callback: BackgroundTaskCallback): Promise<Disposable> {\n const { id: taskId } = config\n\n if (this.tasks.has(taskId)) {\n throw new Error(`Background task with id '${taskId}' is already registered`)\n }\n\n const task: RegisteredTask = {\n config,\n callback,\n abortController: null,\n status: 'pending',\n }\n\n this.tasks.set(taskId, task)\n\n // Notify host about the registration\n this.options.sendTaskRegistered(\n taskId,\n config.name,\n config.userId,\n config.restartPolicy,\n config.payload\n )\n\n // Return a disposable that stops the task\n // Task removal should be coordinated with the host to avoid race conditions\n return {\n dispose: () => {\n this.stop(taskId)\n // Don't immediately delete - let the task finish aborting\n // The task will be cleaned up when the extension is deactivated\n },\n }\n }\n\n /**\n * Stop a running task.\n */\n stop(taskId: string): void {\n const task = this.tasks.get(taskId)\n if (!task) {\n return\n }\n\n // Abort the task if it's running\n if (task.abortController) {\n task.abortController.abort()\n task.abortController = null\n }\n\n task.status = 'stopped'\n\n // Notify host that the task has been stopped\n this.options.sendTaskStatus(taskId, 'stopped')\n }\n\n /**\n * Handle start message from host.\n * This is called when the host tells us to actually run the task.\n */\n async handleStart(taskId: string): Promise<void> {\n const task = this.tasks.get(taskId)\n if (!task) {\n return\n }\n\n // If there's already an execution running, abort it first\n if (task.abortController) {\n task.abortController.abort()\n task.abortController = null\n }\n\n // Create new AbortController for this run\n task.abortController = new AbortController()\n task.status = 'running'\n task.error = undefined\n\n // Build the task context\n const context = this.buildTaskContext(task)\n\n // Notify host that we're running\n this.options.sendTaskStatus(taskId, 'running')\n\n try {\n // Execute the callback\n await task.callback(context)\n\n // Task completed normally (or was aborted)\n if (task.abortController?.signal.aborted) {\n task.status = 'stopped'\n this.options.sendTaskStatus(taskId, 'stopped')\n } else {\n // Task finished without being aborted - treat as stopped\n task.status = 'stopped'\n this.options.sendTaskStatus(taskId, 'stopped')\n }\n } catch (error) {\n // Task failed with an error\n const errorMessage = error instanceof Error ? error.message : String(error)\n task.status = 'failed'\n task.error = errorMessage\n this.options.sendTaskStatus(taskId, 'failed', errorMessage)\n } finally {\n task.abortController = null\n }\n }\n\n /**\n * Handle stop message from host.\n */\n handleStop(taskId: string): void {\n this.stop(taskId)\n }\n\n /**\n * Build the execution context for a task.\n */\n private buildTaskContext(task: RegisteredTask): BackgroundTaskContext {\n const { config, abortController } = task\n const signal = abortController!.signal\n\n const log = this.options.createLogAPI(config.id)\n\n // Create storage and secrets APIs\n const storage = this.options.createStorageAPI()\n const userStorage = config.userId\n ? this.options.createUserStorageAPI(config.userId)\n : storage\n const secrets = this.options.createSecretsAPI()\n const userSecrets = config.userId\n ? this.options.createUserSecretsAPI(config.userId)\n : secrets\n\n const context: BackgroundTaskContext = {\n userId: config.userId,\n extension: {\n id: this.options.extensionId,\n version: this.options.extensionVersion,\n storagePath: this.options.storagePath,\n },\n storage,\n userStorage,\n secrets,\n userSecrets,\n signal,\n reportHealth: (status: string) => {\n const timestamp = new Date().toISOString()\n task.lastHealthStatus = status\n task.lastHealthTime = timestamp\n this.options.sendHealthReport(config.id, status, timestamp)\n },\n log,\n }\n\n return context\n }\n\n /**\n * Get the status of all tasks.\n */\n getStatus(): BackgroundTaskHealth[] {\n const result: BackgroundTaskHealth[] = []\n\n for (const task of this.tasks.values()) {\n result.push({\n taskId: task.config.id,\n name: task.config.name,\n userId: task.config.userId,\n status: task.status,\n restartCount: 0, // Worker doesn't track restarts, host does\n lastHealthStatus: task.lastHealthStatus,\n lastHealthTime: task.lastHealthTime,\n error: task.error,\n })\n }\n\n return result\n }\n\n /**\n * Check if a task exists.\n */\n hasTask(taskId: string): boolean {\n return this.tasks.has(taskId)\n }\n\n /**\n * Clean up all tasks.\n * Called during extension deactivation.\n */\n dispose(): void {\n for (const task of this.tasks.values()) {\n if (task.abortController) {\n task.abortController.abort()\n }\n }\n this.tasks.clear()\n }\n}\n","/**\n * Extension Runtime - Runs inside the worker\n *\n * This module handles communication with the Extension Host and provides\n * the ExtensionContext to the extension's activate function.\n */\n\nimport type {\n ExecutionContext,\n ExtensionContext,\n ExtensionModule,\n Disposable,\n NetworkAPI,\n SettingsAPI,\n ProvidersAPI,\n ToolsAPI,\n ActionsAPI,\n EventsAPI,\n SchedulerAPI,\n SchedulerJobRequest,\n SchedulerFirePayload,\n UserAPI,\n UserProfile,\n ChatAPI,\n ChatInstructionMessage,\n StorageAPI,\n SecretsAPI,\n Query,\n QueryOptions,\n LogAPI,\n AIProvider,\n Tool,\n Action,\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n BackgroundWorkersAPI,\n BackgroundTaskConfig,\n BackgroundTaskCallback,\n BackgroundTaskHealth,\n} from './types.js'\n\nimport { WorkerBackgroundTaskManager } from './background.js'\n\nimport type {\n HostToWorkerMessage,\n WorkerToHostMessage,\n RequestMessage,\n PendingRequest,\n} from './messages.js'\n\nimport { generateMessageId } from './messages.js'\n\n// ============================================================================\n// Environment Detection and Message Port\n// ============================================================================\n\n/**\n * Detect if we're in Node.js Worker Thread or Web Worker\n * and get the appropriate message port\n */\ninterface MessagePort {\n postMessage(message: WorkerToHostMessage): void\n onMessage(handler: (message: HostToWorkerMessage) => void): void\n}\n\nfunction getMessagePort(): MessagePort {\n // Check if we're in Node.js Worker Thread\n if (typeof process !== 'undefined' && process.versions?.node) {\n // Node.js Worker Thread - import parentPort dynamically\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { parentPort } = require('node:worker_threads')\n return {\n postMessage: (message) => parentPort?.postMessage(message),\n onMessage: (handler) => parentPort?.on('message', handler),\n }\n }\n\n // Web Worker - use self\n return {\n postMessage: (message) => self.postMessage(message),\n onMessage: (handler) => {\n self.addEventListener('message', (event: MessageEvent<HostToWorkerMessage>) => {\n handler(event.data)\n })\n },\n }\n}\n\nconst messagePort = getMessagePort()\n\n// ============================================================================\n// Global State\n// ============================================================================\n\nlet extensionModule: ExtensionModule | null = null\nlet extensionDisposable: Disposable | null = null\nlet extensionContext: ExtensionContext | null = null\nlet backgroundTaskManager: WorkerBackgroundTaskManager | null = null\n\nconst pendingRequests = new Map<string, PendingRequest>()\nconst registeredProviders = new Map<string, AIProvider>()\nconst registeredTools = new Map<string, Tool>()\nconst registeredActions = new Map<string, Action>()\nconst settingsCallbacks: Array<(key: string, value: unknown) => void> = []\nconst schedulerCallbacks: Array<(payload: SchedulerFirePayload, context: ExecutionContext) => void | Promise<void>> = []\n\n/**\n * Tracking for streaming fetch requests.\n * Each request stores incoming chunks and signals when new data arrives.\n */\ninterface StreamingFetchRequest {\n chunks: string[]\n done: boolean\n error?: string\n resolve?: () => void\n}\nconst streamingFetchRequests = new Map<string, StreamingFetchRequest>()\n\nconst REQUEST_TIMEOUT = 30000 // 30 seconds\n\n// ============================================================================\n// Message Handling\n// ============================================================================\n\n/**\n * Send a message to the host\n */\nfunction postMessage(message: WorkerToHostMessage): void {\n messagePort.postMessage(message)\n}\n\n/**\n * Send a request to the host and wait for response\n */\nasync function sendRequest<T>(method: RequestMessage['method'], payload: unknown): Promise<T> {\n const id = generateMessageId()\n\n return new Promise<T>((resolve, reject) => {\n const timeout = setTimeout(() => {\n pendingRequests.delete(id)\n reject(new Error(`Request ${method} timed out`))\n }, REQUEST_TIMEOUT)\n\n pendingRequests.set(id, { resolve: resolve as (value: unknown) => void, reject, timeout })\n\n postMessage({\n type: 'request',\n id,\n method,\n payload,\n })\n })\n}\n\n/**\n * Handle messages from the host\n */\nasync function handleHostMessage(message: HostToWorkerMessage): Promise<void> {\n switch (message.type) {\n case 'activate':\n await handleActivate(message.payload)\n break\n\n case 'deactivate':\n await handleDeactivate()\n break\n\n case 'settings-changed':\n handleSettingsChanged(message.payload.key, message.payload.value)\n break\n\n case 'scheduler-fire':\n await handleSchedulerFire(message.payload)\n break\n\n case 'provider-chat-request':\n await handleProviderChatRequest(message.id, message.payload)\n break\n\n case 'provider-models-request':\n await handleProviderModelsRequest(message.id, message.payload)\n break\n\n case 'tool-execute-request':\n await handleToolExecuteRequest(message.id, message.payload)\n break\n\n case 'action-execute-request':\n await handleActionExecuteRequest(message.id, message.payload)\n break\n\n case 'response':\n handleResponse(message.payload)\n break\n\n case 'streaming-fetch-chunk':\n handleStreamingFetchChunk(message.payload)\n break\n\n case 'background-task-start':\n await handleBackgroundTaskStart(message.payload.taskId)\n break\n\n case 'background-task-stop':\n handleBackgroundTaskStop(message.payload.taskId)\n break\n }\n}\n\n/**\n * Handle incoming streaming fetch chunks from the host\n */\nfunction handleStreamingFetchChunk(payload: {\n requestId: string\n chunk: string\n done: boolean\n error?: string\n}): void {\n const request = streamingFetchRequests.get(payload.requestId)\n if (!request) return\n\n if (payload.error) {\n request.error = payload.error\n request.done = true\n } else if (payload.chunk) {\n request.chunks.push(payload.chunk)\n }\n\n if (payload.done) {\n request.done = true\n }\n\n // Signal that new data is available\n if (request.resolve) {\n const resolve = request.resolve\n request.resolve = undefined\n resolve()\n }\n\n // Send acknowledgment for backpressure control\n postMessage({\n type: 'streaming-fetch-ack',\n payload: { requestId: payload.requestId },\n })\n}\n\nfunction handleResponse(payload: { requestId: string; success: boolean; data?: unknown; error?: string }): void {\n const pending = pendingRequests.get(payload.requestId)\n if (!pending) return\n\n clearTimeout(pending.timeout)\n pendingRequests.delete(payload.requestId)\n\n if (payload.success) {\n pending.resolve(payload.data)\n } else {\n pending.reject(new Error(payload.error || 'Unknown error'))\n }\n}\n\n// ============================================================================\n// Activation / Deactivation\n// ============================================================================\n\nasync function handleActivate(payload: {\n extensionId: string\n extensionVersion: string\n storagePath: string\n permissions: string[]\n settings: Record<string, unknown>\n}): Promise<void> {\n const { extensionId, extensionVersion, storagePath, permissions } = payload\n\n // Build the context based on permissions\n extensionContext = buildContext(extensionId, extensionVersion, storagePath, permissions)\n\n // Import and activate the extension\n try {\n // The actual extension code should be bundled and available\n // This is called after the extension code has been loaded into the worker\n if (extensionModule?.activate) {\n const result = await extensionModule.activate(extensionContext)\n if (result && 'dispose' in result) {\n extensionDisposable = result\n }\n }\n } catch (error) {\n extensionContext.log.error('Failed to activate extension', {\n error: error instanceof Error ? error.message : String(error),\n })\n throw error\n }\n}\n\nasync function handleDeactivate(): Promise<void> {\n try {\n if (extensionModule?.deactivate) {\n await extensionModule.deactivate()\n }\n if (extensionDisposable) {\n extensionDisposable.dispose()\n }\n if (backgroundTaskManager) {\n backgroundTaskManager.dispose()\n }\n } catch (error) {\n console.error('Error during deactivation:', error)\n } finally {\n extensionModule = null\n extensionDisposable = null\n extensionContext = null\n backgroundTaskManager = null\n registeredProviders.clear()\n registeredTools.clear()\n registeredActions.clear()\n settingsCallbacks.length = 0\n schedulerCallbacks.length = 0\n }\n}\n\nfunction handleSettingsChanged(key: string, value: unknown): void {\n for (const callback of settingsCallbacks) {\n try {\n callback(key, value)\n } catch (error) {\n console.error('Error in settings change callback:', error)\n }\n }\n}\n\n/**\n * Build extension-scoped storage API\n */\nfunction buildExtensionStorageAPI(): StorageAPI {\n return {\n async put<T extends object>(collection: string, id: string, data: T): Promise<void> {\n return sendRequest<void>('storage.put', { collection, id, data })\n },\n async get<T>(collection: string, id: string): Promise<T | undefined> {\n return sendRequest<T | undefined>('storage.get', { collection, id })\n },\n async delete(collection: string, id: string): Promise<boolean> {\n return sendRequest<boolean>('storage.delete', { collection, id })\n },\n async find<T>(collection: string, query?: Query, options?: QueryOptions): Promise<T[]> {\n return sendRequest<T[]>('storage.find', { collection, query, options })\n },\n async findOne<T>(collection: string, query: Query): Promise<T | undefined> {\n return sendRequest<T | undefined>('storage.findOne', { collection, query })\n },\n async count(collection: string, query?: Query): Promise<number> {\n return sendRequest<number>('storage.count', { collection, query })\n },\n async putMany<T extends object>(collection: string, docs: Array<{ id: string; data: T }>): Promise<void> {\n return sendRequest<void>('storage.putMany', { collection, docs })\n },\n async deleteMany(collection: string, query: Query): Promise<number> {\n return sendRequest<number>('storage.deleteMany', { collection, query })\n },\n async dropCollection(collection: string): Promise<void> {\n return sendRequest<void>('storage.dropCollection', { collection })\n },\n async listCollections(): Promise<string[]> {\n return sendRequest<string[]>('storage.listCollections', {})\n },\n }\n}\n\n/**\n * Build user-scoped storage API\n */\nfunction buildUserStorageAPI(userId: string): StorageAPI {\n return {\n async put<T extends object>(collection: string, id: string, data: T): Promise<void> {\n return sendRequest<void>('storage.putForUser', { userId, collection, id, data })\n },\n async get<T>(collection: string, id: string): Promise<T | undefined> {\n return sendRequest<T | undefined>('storage.getForUser', { userId, collection, id })\n },\n async delete(collection: string, id: string): Promise<boolean> {\n return sendRequest<boolean>('storage.deleteForUser', { userId, collection, id })\n },\n async find<T>(collection: string, query?: Query, options?: QueryOptions): Promise<T[]> {\n return sendRequest<T[]>('storage.findForUser', { userId, collection, query, options })\n },\n async findOne<T>(collection: string, query: Query): Promise<T | undefined> {\n return sendRequest<T | undefined>('storage.findOneForUser', { userId, collection, query })\n },\n async count(collection: string, query?: Query): Promise<number> {\n return sendRequest<number>('storage.countForUser', { userId, collection, query })\n },\n async putMany<T extends object>(collection: string, docs: Array<{ id: string; data: T }>): Promise<void> {\n return sendRequest<void>('storage.putManyForUser', { userId, collection, docs })\n },\n async deleteMany(collection: string, query: Query): Promise<number> {\n return sendRequest<number>('storage.deleteManyForUser', { userId, collection, query })\n },\n async dropCollection(collection: string): Promise<void> {\n return sendRequest<void>('storage.dropCollectionForUser', { userId, collection })\n },\n async listCollections(): Promise<string[]> {\n return sendRequest<string[]>('storage.listCollectionsForUser', { userId })\n },\n }\n}\n\n/**\n * Build extension-scoped secrets API\n */\nfunction buildExtensionSecretsAPI(): SecretsAPI {\n return {\n async set(key: string, value: string): Promise<void> {\n return sendRequest<void>('secrets.set', { key, value })\n },\n async get(key: string): Promise<string | undefined> {\n return sendRequest<string | undefined>('secrets.get', { key })\n },\n async delete(key: string): Promise<boolean> {\n return sendRequest<boolean>('secrets.delete', { key })\n },\n async list(): Promise<string[]> {\n return sendRequest<string[]>('secrets.list', {})\n },\n }\n}\n\n/**\n * Build user-scoped secrets API\n */\nfunction buildUserSecretsAPI(userId: string): SecretsAPI {\n return {\n async set(key: string, value: string): Promise<void> {\n return sendRequest<void>('secrets.setForUser', { userId, key, value })\n },\n async get(key: string): Promise<string | undefined> {\n return sendRequest<string | undefined>('secrets.getForUser', { userId, key })\n },\n async delete(key: string): Promise<boolean> {\n return sendRequest<boolean>('secrets.deleteForUser', { userId, key })\n },\n async list(): Promise<string[]> {\n return sendRequest<string[]>('secrets.listForUser', { userId })\n },\n }\n}\n\nasync function handleSchedulerFire(payload: SchedulerFirePayload): Promise<void> {\n // Create request-scoped execution context with storage and secrets\n const execContext: ExecutionContext = {\n userId: payload.userId,\n extension: {\n id: extensionContext!.extension.id,\n version: extensionContext!.extension.version,\n storagePath: extensionContext!.extension.storagePath,\n },\n storage: buildExtensionStorageAPI(),\n userStorage: payload.userId ? buildUserStorageAPI(payload.userId) : buildExtensionStorageAPI(),\n secrets: buildExtensionSecretsAPI(),\n userSecrets: payload.userId ? buildUserSecretsAPI(payload.userId) : buildExtensionSecretsAPI(),\n }\n\n // Run callbacks concurrently to avoid blocking\n const results = await Promise.allSettled(\n schedulerCallbacks.map((callback) => Promise.resolve(callback(payload, execContext))),\n )\n\n // Log any errors\n results.forEach((result, index) => {\n if (result.status === 'rejected') {\n console.error(`Error in scheduler callback ${index}:`, result.reason)\n }\n })\n\n // Report result back to host\n const failed = results.find((r) => r.status === 'rejected') as PromiseRejectedResult | undefined\n try {\n await sendRequest<void>('scheduler.reportFireResult', {\n jobId: payload.id,\n success: !failed,\n error: failed ? String(failed.reason) : undefined,\n })\n } catch {\n // Best effort — don't crash if reporting fails\n }\n}\n\n// ============================================================================\n// Background Task Handlers\n// ============================================================================\n\nasync function handleBackgroundTaskStart(taskId: string): Promise<void> {\n if (!backgroundTaskManager) {\n console.error('Background task manager not initialized')\n return\n }\n await backgroundTaskManager.handleStart(taskId)\n}\n\nfunction handleBackgroundTaskStop(taskId: string): void {\n if (!backgroundTaskManager) {\n console.error('Background task manager not initialized')\n return\n }\n backgroundTaskManager.handleStop(taskId)\n}\n\n// ============================================================================\n// Provider / Tool Requests\n// ============================================================================\n\nasync function handleProviderChatRequest(\n requestId: string,\n payload: { providerId: string; messages: ChatMessage[]; options: ChatOptions }\n): Promise<void> {\n const provider = registeredProviders.get(payload.providerId)\n if (!provider) {\n postMessage({\n type: 'request',\n id: generateMessageId(),\n method: 'network.fetch', // Dummy, we need a proper error response\n payload: { error: `Provider ${payload.providerId} not found` },\n })\n return\n }\n\n try {\n const generator = provider.chat(payload.messages, payload.options)\n let sawDone = false\n let sawError = false\n\n for await (const event of generator) {\n if (event.type === 'done') {\n sawDone = true\n } else if (event.type === 'error') {\n sawError = true\n }\n postMessage({\n type: 'stream-event',\n payload: { requestId, event },\n })\n }\n\n if (!sawDone && !sawError) {\n postMessage({\n type: 'stream-event',\n payload: {\n requestId,\n event: { type: 'done' },\n },\n })\n }\n } catch (error) {\n postMessage({\n type: 'stream-event',\n payload: {\n requestId,\n event: {\n type: 'error',\n message: error instanceof Error ? error.message : String(error),\n },\n },\n })\n }\n}\n\nasync function handleProviderModelsRequest(\n requestId: string,\n payload: { providerId: string; options?: GetModelsOptions }\n): Promise<void> {\n const provider = registeredProviders.get(payload.providerId)\n if (!provider) {\n // Send error response\n postMessage({\n type: 'provider-models-response',\n payload: {\n requestId,\n models: [],\n error: `Provider ${payload.providerId} not found`,\n },\n })\n return\n }\n\n try {\n // Pass options to getModels so provider can use settings (e.g., URL for Ollama)\n const models = await provider.getModels(payload.options)\n // Send response with models\n postMessage({\n type: 'provider-models-response',\n payload: {\n requestId,\n models,\n },\n })\n } catch (error) {\n postMessage({\n type: 'provider-models-response',\n payload: {\n requestId,\n models: [],\n error: error instanceof Error ? error.message : String(error),\n },\n })\n }\n}\n\nasync function handleToolExecuteRequest(\n requestId: string,\n payload: { toolId: string; params: Record<string, unknown>; userId?: string }\n): Promise<void> {\n const tool = registeredTools.get(payload.toolId)\n if (!tool) {\n // Send error response\n postMessage({\n type: 'tool-execute-response',\n payload: {\n requestId,\n result: { success: false, error: `Tool ${payload.toolId} not found` },\n error: `Tool ${payload.toolId} not found`,\n },\n })\n return\n }\n\n try {\n // Create request-scoped execution context with storage and secrets\n const execContext: ExecutionContext = {\n userId: payload.userId,\n extension: {\n id: extensionContext!.extension.id,\n version: extensionContext!.extension.version,\n storagePath: extensionContext!.extension.storagePath,\n },\n storage: buildExtensionStorageAPI(),\n userStorage: payload.userId ? buildUserStorageAPI(payload.userId) : buildExtensionStorageAPI(),\n secrets: buildExtensionSecretsAPI(),\n userSecrets: payload.userId ? buildUserSecretsAPI(payload.userId) : buildExtensionSecretsAPI(),\n }\n\n const result = await tool.execute(payload.params, execContext)\n\n // Send response with result\n postMessage({\n type: 'tool-execute-response',\n payload: {\n requestId,\n result,\n },\n })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n postMessage({\n type: 'tool-execute-response',\n payload: {\n requestId,\n result: { success: false, error: errorMessage },\n error: errorMessage,\n },\n })\n }\n}\n\nasync function handleActionExecuteRequest(\n requestId: string,\n payload: { actionId: string; params: Record<string, unknown>; userId?: string }\n): Promise<void> {\n const action = registeredActions.get(payload.actionId)\n if (!action) {\n postMessage({\n type: 'action-execute-response',\n payload: {\n requestId,\n result: { success: false, error: `Action ${payload.actionId} not found` },\n error: `Action ${payload.actionId} not found`,\n },\n })\n return\n }\n\n try {\n // Create request-scoped execution context with storage and secrets\n const execContext: ExecutionContext = {\n userId: payload.userId,\n extension: {\n id: extensionContext!.extension.id,\n version: extensionContext!.extension.version,\n storagePath: extensionContext!.extension.storagePath,\n },\n storage: buildExtensionStorageAPI(),\n userStorage: payload.userId ? buildUserStorageAPI(payload.userId) : buildExtensionStorageAPI(),\n secrets: buildExtensionSecretsAPI(),\n userSecrets: payload.userId ? buildUserSecretsAPI(payload.userId) : buildExtensionSecretsAPI(),\n }\n\n const result = await action.execute(payload.params, execContext)\n\n postMessage({\n type: 'action-execute-response',\n payload: {\n requestId,\n result,\n },\n })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n postMessage({\n type: 'action-execute-response',\n payload: {\n requestId,\n result: { success: false, error: errorMessage },\n error: errorMessage,\n },\n })\n }\n}\n\n// ============================================================================\n// Context Building\n// ============================================================================\n\nfunction buildContext(\n extensionId: string,\n extensionVersion: string,\n storagePath: string,\n permissions: string[]\n): ExtensionContext {\n const hasPermission = (perm: string): boolean => {\n return permissions.some((p) => {\n if (p === perm) return true\n if (p.endsWith(':*') && perm.startsWith(p.slice(0, -1))) return true\n return false\n })\n }\n\n const log: LogAPI = {\n debug: (message, data) => postMessage({ type: 'log', payload: { level: 'debug', message, data } }),\n info: (message, data) => postMessage({ type: 'log', payload: { level: 'info', message, data } }),\n warn: (message, data) => postMessage({ type: 'log', payload: { level: 'warn', message, data } }),\n error: (message, data) => postMessage({ type: 'log', payload: { level: 'error', message, data } }),\n }\n\n const context: ExtensionContext = {\n extension: {\n id: extensionId,\n version: extensionVersion,\n storagePath,\n },\n log,\n }\n\n // Add network API if permitted\n if (permissions.some((p) => p.startsWith('network:'))) {\n const networkApi: NetworkAPI = {\n async fetch(url: string, options?: RequestInit): Promise<Response> {\n const result = await sendRequest<{ status: number; statusText: string; headers: Record<string, string>; body: string }>('network.fetch', { url, options })\n return new Response(result.body, {\n status: result.status,\n statusText: result.statusText,\n headers: result.headers,\n })\n },\n\n async *fetchStream(url: string, options?: RequestInit): AsyncGenerator<string, void, unknown> {\n const requestId = generateMessageId()\n\n // Set up streaming request tracking\n const request: StreamingFetchRequest = {\n chunks: [],\n done: false,\n }\n streamingFetchRequests.set(requestId, request)\n\n // Send the streaming fetch request to the host\n postMessage({\n type: 'request',\n id: requestId,\n method: 'network.fetch-stream',\n payload: { url, options, requestId },\n })\n\n try {\n // Yield chunks as they arrive\n while (!request.done) {\n // Wait for new data\n await new Promise<void>((resolve) => {\n const resolver = () => {\n // Clear the stored resolver before resolving to avoid\n // stale callbacks being invoked for a new wait iteration.\n if (request.resolve === resolver) {\n request.resolve = undefined\n }\n resolve()\n }\n\n request.resolve = resolver\n\n // Check if we already have data or completion\n if (request.chunks.length > 0 || request.done) {\n resolver()\n }\n })\n\n // Check for errors first, before yielding any chunks\n if (request.error) {\n throw new Error(request.error)\n }\n\n // Yield all available chunks\n while (request.chunks.length > 0) {\n yield request.chunks.shift()!\n }\n }\n } finally {\n streamingFetchRequests.delete(requestId)\n }\n },\n }\n ;(context as { network: NetworkAPI }).network = networkApi\n }\n\n // Add settings API if permitted\n if (hasPermission('settings.register')) {\n const settingsApi: SettingsAPI = {\n async getAll<T extends Record<string, unknown>>(): Promise<T> {\n return sendRequest<T>('settings.getAll', {})\n },\n async get<T>(key: string): Promise<T | undefined> {\n return sendRequest<T | undefined>('settings.get', { key })\n },\n async set(key: string, value: unknown): Promise<void> {\n return sendRequest<void>('settings.set', { key, value })\n },\n onChange(callback: (key: string, value: unknown) => void): Disposable {\n settingsCallbacks.push(callback)\n return {\n dispose: () => {\n const index = settingsCallbacks.indexOf(callback)\n if (index >= 0) settingsCallbacks.splice(index, 1)\n },\n }\n },\n }\n ;(context as { settings: SettingsAPI }).settings = settingsApi\n }\n\n // Add providers API if permitted\n if (hasPermission('provider.register')) {\n const providersApi: ProvidersAPI = {\n register(provider: AIProvider): Disposable {\n registeredProviders.set(provider.id, provider)\n postMessage({\n type: 'provider-registered',\n payload: { id: provider.id, name: provider.name },\n })\n return {\n dispose: () => {\n registeredProviders.delete(provider.id)\n },\n }\n },\n }\n ;(context as { providers: ProvidersAPI }).providers = providersApi\n }\n\n // Add tools API if permitted\n if (hasPermission('tools.register')) {\n const toolsApi: ToolsAPI = {\n register(tool: Tool): Disposable {\n registeredTools.set(tool.id, tool)\n postMessage({\n type: 'tool-registered',\n payload: {\n id: tool.id,\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters,\n },\n })\n return {\n dispose: () => {\n registeredTools.delete(tool.id)\n },\n }\n },\n }\n ;(context as { tools: ToolsAPI }).tools = toolsApi\n }\n\n // Add actions API if permitted\n if (hasPermission('actions.register')) {\n const actionsApi: ActionsAPI = {\n register(action: Action): Disposable {\n registeredActions.set(action.id, action)\n postMessage({\n type: 'action-registered',\n payload: {\n id: action.id,\n },\n })\n return {\n dispose: () => {\n registeredActions.delete(action.id)\n },\n }\n },\n }\n ;(context as { actions: ActionsAPI }).actions = actionsApi\n }\n\n // Add events API if permitted\n if (hasPermission('events.emit')) {\n const eventsApi: EventsAPI = {\n async emit(name: string, payload?: Record<string, unknown>): Promise<void> {\n await sendRequest<void>('events.emit', { name, payload })\n },\n }\n ;(context as { events: EventsAPI }).events = eventsApi\n }\n\n // Add scheduler API if permitted\n if (hasPermission('scheduler.register')) {\n const schedulerApi: SchedulerAPI = {\n async schedule(job: SchedulerJobRequest): Promise<void> {\n // Extensions must explicitly set job.userId if they want user-scoped jobs\n // Use context.userId from the ExecutionContext in tool/action execute\n await sendRequest<void>('scheduler.schedule', { job })\n },\n async cancel(jobId: string): Promise<void> {\n await sendRequest<void>('scheduler.cancel', { jobId })\n },\n onFire(callback: (payload: SchedulerFirePayload, context: ExecutionContext) => void | Promise<void>): Disposable {\n schedulerCallbacks.push(callback)\n return {\n dispose: () => {\n const index = schedulerCallbacks.indexOf(callback)\n if (index >= 0) schedulerCallbacks.splice(index, 1)\n },\n }\n },\n }\n ;(context as { scheduler: SchedulerAPI }).scheduler = schedulerApi\n }\n\n // Add user profile API if permitted\n if (hasPermission('user.profile.read')) {\n const userApi: UserAPI = {\n async getProfile(): Promise<UserProfile> {\n return sendRequest<UserProfile>('user.getProfile', {})\n },\n }\n ;(context as { user: UserAPI }).user = userApi\n }\n\n // Add chat API if permitted\n if (hasPermission('chat.message.write')) {\n const chatApi: ChatAPI = {\n async appendInstruction(message: ChatInstructionMessage): Promise<void> {\n // Extensions must explicitly set message.userId if they want user-scoped messages\n // Use context.userId from the ExecutionContext in tool/action execute\n await sendRequest<void>('chat.appendInstruction', message)\n },\n }\n ;(context as { chat: ChatAPI }).chat = chatApi\n }\n\n // Add storage API if permitted (new collection-based storage)\n if (hasPermission('storage.collections')) {\n ;(context as { storage: StorageAPI }).storage = buildExtensionStorageAPI()\n }\n\n // Add secrets API if permitted\n if (hasPermission('secrets.manage')) {\n ;(context as { secrets: SecretsAPI }).secrets = buildExtensionSecretsAPI()\n }\n\n // Add background workers API if permitted\n if (hasPermission('background.workers')) {\n // Initialize the background task manager if not already done\n if (!backgroundTaskManager) {\n backgroundTaskManager = new WorkerBackgroundTaskManager({\n extensionId,\n extensionVersion,\n storagePath,\n sendTaskRegistered: (taskId, name, userId, restartPolicy, payload) => {\n postMessage({\n type: 'background-task-registered',\n payload: {\n taskId,\n name,\n userId,\n restartPolicy,\n payload,\n },\n })\n },\n sendTaskStatus: (taskId, status, error) => {\n postMessage({\n type: 'background-task-status',\n payload: {\n taskId,\n status,\n error,\n },\n })\n },\n sendHealthReport: (taskId, status, timestamp) => {\n postMessage({\n type: 'background-task-health',\n payload: {\n taskId,\n status,\n timestamp,\n },\n })\n },\n createLogAPI: (taskId) => ({\n debug: (message, data) =>\n postMessage({ type: 'log', payload: { level: 'debug', message: `[${taskId}] ${message}`, data } }),\n info: (message, data) =>\n postMessage({ type: 'log', payload: { level: 'info', message: `[${taskId}] ${message}`, data } }),\n warn: (message, data) =>\n postMessage({ type: 'log', payload: { level: 'warn', message: `[${taskId}] ${message}`, data } }),\n error: (message, data) =>\n postMessage({ type: 'log', payload: { level: 'error', message: `[${taskId}] ${message}`, data } }),\n }),\n createStorageAPI: () => buildExtensionStorageAPI(),\n createUserStorageAPI: (userId) => buildUserStorageAPI(userId),\n createSecretsAPI: () => buildExtensionSecretsAPI(),\n createUserSecretsAPI: (userId) => buildUserSecretsAPI(userId),\n })\n }\n\n const backgroundWorkersApi: BackgroundWorkersAPI = {\n async start(config: BackgroundTaskConfig, callback: BackgroundTaskCallback): Promise<Disposable> {\n return backgroundTaskManager!.start(config, callback)\n },\n async stop(taskId: string): Promise<void> {\n backgroundTaskManager!.stop(taskId)\n },\n async getStatus(): Promise<BackgroundTaskHealth[]> {\n return backgroundTaskManager!.getStatus()\n },\n }\n ;(context as { backgroundWorkers: BackgroundWorkersAPI }).backgroundWorkers = backgroundWorkersApi\n }\n\n return context\n}\n\n// ============================================================================\n// Initialization\n// ============================================================================\n\n/**\n * Initialize the extension runtime\n * This should be called by the extension's entry point\n */\nexport function initializeExtension(module: ExtensionModule): void {\n extensionModule = module\n\n // Set up message listener using the appropriate message port\n messagePort.onMessage(async (message: HostToWorkerMessage) => {\n try {\n await handleHostMessage(message)\n } catch (error) {\n console.error('Error handling message:', error)\n }\n })\n\n // Signal that we're ready\n postMessage({ type: 'ready' })\n}\n\n// Re-export types for extensions to use\nexport type {\n ExecutionContext,\n ExtensionContext,\n ExtensionModule,\n Disposable,\n AIProvider,\n Tool,\n ToolDefinition,\n ToolResult,\n ToolCall,\n Action,\n ActionResult,\n ModelInfo,\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n // Storage and secrets\n StorageAPI,\n SecretsAPI,\n Query,\n QueryOptions,\n // Background workers\n BackgroundWorkersAPI,\n BackgroundTaskConfig,\n BackgroundTaskCallback,\n BackgroundTaskContext,\n BackgroundTaskHealth,\n BackgroundRestartPolicy,\n} from './types.js'\n"],"mappings":"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","names":[]}
@@ -683,6 +683,22 @@ interface ToolDefinition {
683
683
  description: LocalizedString;
684
684
  /** Parameter schema (JSON Schema) */
685
685
  parameters?: Record<string, unknown>;
686
+ /**
687
+ * Confirmation configuration. If set, user must confirm before tool runs.
688
+ * If not set, tool runs without confirmation.
689
+ */
690
+ confirmation?: ToolConfirmationConfig;
691
+ }
692
+ /**
693
+ * Configuration for tool confirmation.
694
+ */
695
+ interface ToolConfirmationConfig {
696
+ /**
697
+ * Default confirmation prompt to show the user.
698
+ * If not provided, a generic prompt like "Allow {toolName} to run?" is used.
699
+ * @example { en: "Allow sending email?", sv: "Tillåt att skicka e-post?" }
700
+ */
701
+ prompt?: LocalizedString;
686
702
  }
687
703
  /**
688
704
  * Command definition
@@ -1655,4 +1671,4 @@ interface ActionResult {
1655
1671
  error?: string;
1656
1672
  }
1657
1673
 
1658
- export { type BackgroundTaskCallback as $, type ActionResult as A, type ExtensionContext as B, type ChatMessage as C, type Disposable as D, type ExtensionContributions as E, type SettingsAPI as F, type GetModelsOptions as G, type ProvidersAPI as H, type ToolsAPI as I, type ActionsAPI as J, type EventsAPI as K, type LocalizedString as L, type ModelInfo as M, type NetworkAPI as N, type SchedulerAPI as O, type PanelDefinition as P, type SchedulerJobRequest as Q, type SchedulerSchedule as R, type SchedulerFirePayload as S, type ToolResult as T, type UserAPI as U, type UserProfile as V, type ChatAPI as W, type ChatInstructionMessage as X, type LogAPI as Y, type BackgroundWorkersAPI as Z, type BackgroundTaskConfig as _, type ChatOptions as a, type BackgroundTaskContext as a0, type BackgroundTaskHealth as a1, type BackgroundRestartPolicy as a2, type Query as a3, type QueryOptions as a4, type StorageAPI as a5, type SecretsAPI as a6, type StorageCollectionConfig as a7, type StorageContributions as a8, type AIProvider as a9, type IconButtonProps as aA, type PanelAction as aB, type PanelProps as aC, type ToggleProps as aD, type CollapsibleProps as aE, type PillVariant as aF, type PillProps as aG, type CheckboxProps as aH, type MarkdownProps as aI, type ModalProps as aJ, type ConditionalGroupProps as aK, type ExecutionContext as aL, type ToolCall as aa, type Tool as ab, type Action as ac, type ExtensionModule as ad, type AllowedCSSProperty as ae, type ExtensionComponentStyle as af, type ExtensionComponentData as ag, type ExtensionComponentIterator as ah, type ExtensionComponentChildren as ai, type ExtensionActionCall as aj, type ExtensionActionRef as ak, type ExtensionDataSource as al, type ExtensionPanelDefinition as am, type HeaderProps as an, type LabelProps as ao, type ParagraphProps as ap, type ButtonProps as aq, type TextInputProps as ar, type DateTimeInputProps as as, type SelectProps as at, type VerticalStackProps as au, type HorizontalStackProps as av, type GridProps as aw, type DividerProps as ax, type IconProps as ay, type IconButtonType as az, type StreamEvent as b, type SettingDefinition as c, type SettingOptionsMapping as d, type SettingCreateMapping as e, type ToolSettingsViewDefinition as f, type ToolSettingsView as g, type ToolSettingsListView as h, type ToolSettingsListMapping as i, type ToolSettingsComponentView as j, type ToolSettingsActionDataSource as k, type PanelView as l, type PanelComponentView as m, type PanelActionDataSource as n, type PanelUnknownView as o, type ProviderDefinition as p, type PromptContribution as q, resolveLocalizedString as r, type PromptSection as s, type ToolDefinition as t, type CommandDefinition as u, type ProviderConfigSchema as v, type ProviderConfigProperty as w, type ProviderConfigPropertyType as x, type ProviderConfigSelectOption as y, type ProviderConfigValidation as z };
1674
+ export { type BackgroundTaskConfig as $, type ActionResult as A, type ProviderConfigValidation as B, type ChatMessage as C, type ExtensionContext as D, type ExtensionContributions as E, type Disposable as F, type GetModelsOptions as G, type SettingsAPI as H, type ProvidersAPI as I, type ToolsAPI as J, type ActionsAPI as K, type LocalizedString as L, type ModelInfo as M, type NetworkAPI as N, type EventsAPI as O, type PanelDefinition as P, type SchedulerAPI as Q, type SchedulerJobRequest as R, type SchedulerFirePayload as S, type ToolResult as T, type SchedulerSchedule as U, type UserAPI as V, type UserProfile as W, type ChatAPI as X, type ChatInstructionMessage as Y, type LogAPI as Z, type BackgroundWorkersAPI as _, type ChatOptions as a, type BackgroundTaskCallback as a0, type BackgroundTaskContext as a1, type BackgroundTaskHealth as a2, type BackgroundRestartPolicy as a3, type Query as a4, type QueryOptions as a5, type StorageAPI as a6, type SecretsAPI as a7, type StorageCollectionConfig as a8, type StorageContributions as a9, type IconButtonType as aA, type IconButtonProps as aB, type PanelAction as aC, type PanelProps as aD, type ToggleProps as aE, type CollapsibleProps as aF, type PillVariant as aG, type PillProps as aH, type CheckboxProps as aI, type MarkdownProps as aJ, type ModalProps as aK, type ConditionalGroupProps as aL, type ExecutionContext as aM, type AIProvider as aa, type ToolCall as ab, type Tool as ac, type Action as ad, type ExtensionModule as ae, type AllowedCSSProperty as af, type ExtensionComponentStyle as ag, type ExtensionComponentData as ah, type ExtensionComponentIterator as ai, type ExtensionComponentChildren as aj, type ExtensionActionCall as ak, type ExtensionActionRef as al, type ExtensionDataSource as am, type ExtensionPanelDefinition as an, type HeaderProps as ao, type LabelProps as ap, type ParagraphProps as aq, type ButtonProps as ar, type TextInputProps as as, type DateTimeInputProps as at, type SelectProps as au, type VerticalStackProps as av, type HorizontalStackProps as aw, type GridProps as ax, type DividerProps as ay, type IconProps as az, type StreamEvent as b, type SettingDefinition as c, type SettingOptionsMapping as d, type SettingCreateMapping as e, type ToolSettingsViewDefinition as f, type ToolSettingsView as g, type ToolSettingsListView as h, type ToolSettingsListMapping as i, type ToolSettingsComponentView as j, type ToolSettingsActionDataSource as k, type PanelView as l, type PanelComponentView as m, type PanelActionDataSource as n, type PanelUnknownView as o, type ProviderDefinition as p, type PromptContribution as q, resolveLocalizedString as r, type PromptSection as s, type ToolDefinition as t, type ToolConfirmationConfig as u, type CommandDefinition as v, type ProviderConfigSchema as w, type ProviderConfigProperty as x, type ProviderConfigPropertyType as y, type ProviderConfigSelectOption as z };
@@ -683,6 +683,22 @@ interface ToolDefinition {
683
683
  description: LocalizedString;
684
684
  /** Parameter schema (JSON Schema) */
685
685
  parameters?: Record<string, unknown>;
686
+ /**
687
+ * Confirmation configuration. If set, user must confirm before tool runs.
688
+ * If not set, tool runs without confirmation.
689
+ */
690
+ confirmation?: ToolConfirmationConfig;
691
+ }
692
+ /**
693
+ * Configuration for tool confirmation.
694
+ */
695
+ interface ToolConfirmationConfig {
696
+ /**
697
+ * Default confirmation prompt to show the user.
698
+ * If not provided, a generic prompt like "Allow {toolName} to run?" is used.
699
+ * @example { en: "Allow sending email?", sv: "Tillåt att skicka e-post?" }
700
+ */
701
+ prompt?: LocalizedString;
686
702
  }
687
703
  /**
688
704
  * Command definition
@@ -1655,4 +1671,4 @@ interface ActionResult {
1655
1671
  error?: string;
1656
1672
  }
1657
1673
 
1658
- export { type BackgroundTaskCallback as $, type ActionResult as A, type ExtensionContext as B, type ChatMessage as C, type Disposable as D, type ExtensionContributions as E, type SettingsAPI as F, type GetModelsOptions as G, type ProvidersAPI as H, type ToolsAPI as I, type ActionsAPI as J, type EventsAPI as K, type LocalizedString as L, type ModelInfo as M, type NetworkAPI as N, type SchedulerAPI as O, type PanelDefinition as P, type SchedulerJobRequest as Q, type SchedulerSchedule as R, type SchedulerFirePayload as S, type ToolResult as T, type UserAPI as U, type UserProfile as V, type ChatAPI as W, type ChatInstructionMessage as X, type LogAPI as Y, type BackgroundWorkersAPI as Z, type BackgroundTaskConfig as _, type ChatOptions as a, type BackgroundTaskContext as a0, type BackgroundTaskHealth as a1, type BackgroundRestartPolicy as a2, type Query as a3, type QueryOptions as a4, type StorageAPI as a5, type SecretsAPI as a6, type StorageCollectionConfig as a7, type StorageContributions as a8, type AIProvider as a9, type IconButtonProps as aA, type PanelAction as aB, type PanelProps as aC, type ToggleProps as aD, type CollapsibleProps as aE, type PillVariant as aF, type PillProps as aG, type CheckboxProps as aH, type MarkdownProps as aI, type ModalProps as aJ, type ConditionalGroupProps as aK, type ExecutionContext as aL, type ToolCall as aa, type Tool as ab, type Action as ac, type ExtensionModule as ad, type AllowedCSSProperty as ae, type ExtensionComponentStyle as af, type ExtensionComponentData as ag, type ExtensionComponentIterator as ah, type ExtensionComponentChildren as ai, type ExtensionActionCall as aj, type ExtensionActionRef as ak, type ExtensionDataSource as al, type ExtensionPanelDefinition as am, type HeaderProps as an, type LabelProps as ao, type ParagraphProps as ap, type ButtonProps as aq, type TextInputProps as ar, type DateTimeInputProps as as, type SelectProps as at, type VerticalStackProps as au, type HorizontalStackProps as av, type GridProps as aw, type DividerProps as ax, type IconProps as ay, type IconButtonType as az, type StreamEvent as b, type SettingDefinition as c, type SettingOptionsMapping as d, type SettingCreateMapping as e, type ToolSettingsViewDefinition as f, type ToolSettingsView as g, type ToolSettingsListView as h, type ToolSettingsListMapping as i, type ToolSettingsComponentView as j, type ToolSettingsActionDataSource as k, type PanelView as l, type PanelComponentView as m, type PanelActionDataSource as n, type PanelUnknownView as o, type ProviderDefinition as p, type PromptContribution as q, resolveLocalizedString as r, type PromptSection as s, type ToolDefinition as t, type CommandDefinition as u, type ProviderConfigSchema as v, type ProviderConfigProperty as w, type ProviderConfigPropertyType as x, type ProviderConfigSelectOption as y, type ProviderConfigValidation as z };
1674
+ export { type BackgroundTaskConfig as $, type ActionResult as A, type ProviderConfigValidation as B, type ChatMessage as C, type ExtensionContext as D, type ExtensionContributions as E, type Disposable as F, type GetModelsOptions as G, type SettingsAPI as H, type ProvidersAPI as I, type ToolsAPI as J, type ActionsAPI as K, type LocalizedString as L, type ModelInfo as M, type NetworkAPI as N, type EventsAPI as O, type PanelDefinition as P, type SchedulerAPI as Q, type SchedulerJobRequest as R, type SchedulerFirePayload as S, type ToolResult as T, type SchedulerSchedule as U, type UserAPI as V, type UserProfile as W, type ChatAPI as X, type ChatInstructionMessage as Y, type LogAPI as Z, type BackgroundWorkersAPI as _, type ChatOptions as a, type BackgroundTaskCallback as a0, type BackgroundTaskContext as a1, type BackgroundTaskHealth as a2, type BackgroundRestartPolicy as a3, type Query as a4, type QueryOptions as a5, type StorageAPI as a6, type SecretsAPI as a7, type StorageCollectionConfig as a8, type StorageContributions as a9, type IconButtonType as aA, type IconButtonProps as aB, type PanelAction as aC, type PanelProps as aD, type ToggleProps as aE, type CollapsibleProps as aF, type PillVariant as aG, type PillProps as aH, type CheckboxProps as aI, type MarkdownProps as aJ, type ModalProps as aK, type ConditionalGroupProps as aL, type ExecutionContext as aM, type AIProvider as aa, type ToolCall as ab, type Tool as ac, type Action as ad, type ExtensionModule as ae, type AllowedCSSProperty as af, type ExtensionComponentStyle as ag, type ExtensionComponentData as ah, type ExtensionComponentIterator as ai, type ExtensionComponentChildren as aj, type ExtensionActionCall as ak, type ExtensionActionRef as al, type ExtensionDataSource as am, type ExtensionPanelDefinition as an, type HeaderProps as ao, type LabelProps as ap, type ParagraphProps as aq, type ButtonProps as ar, type TextInputProps as as, type DateTimeInputProps as at, type SelectProps as au, type VerticalStackProps as av, type HorizontalStackProps as aw, type GridProps as ax, type DividerProps as ay, type IconProps as az, type StreamEvent as b, type SettingDefinition as c, type SettingOptionsMapping as d, type SettingCreateMapping as e, type ToolSettingsViewDefinition as f, type ToolSettingsView as g, type ToolSettingsListView as h, type ToolSettingsListMapping as i, type ToolSettingsComponentView as j, type ToolSettingsActionDataSource as k, type PanelView as l, type PanelComponentView as m, type PanelActionDataSource as n, type PanelUnknownView as o, type ProviderDefinition as p, type PromptContribution as q, resolveLocalizedString as r, type PromptSection as s, type ToolDefinition as t, type ToolConfirmationConfig as u, type CommandDefinition as v, type ProviderConfigSchema as w, type ProviderConfigProperty as x, type ProviderConfigPropertyType as y, type ProviderConfigSelectOption as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stina/extension-api",
3
- "version": "0.24.0",
3
+ "version": "0.25.0-alpha.1c5b584",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
package/src/index.ts CHANGED
@@ -35,6 +35,7 @@ export type {
35
35
  PromptContribution,
36
36
  PromptSection,
37
37
  ToolDefinition,
38
+ ToolConfirmationConfig,
38
39
  CommandDefinition,
39
40
 
40
41
  // Provider Configuration Schema
package/src/messages.ts CHANGED
@@ -204,6 +204,7 @@ export type RequestMethod =
204
204
  | 'events.emit'
205
205
  | 'scheduler.schedule'
206
206
  | 'scheduler.cancel'
207
+ | 'scheduler.reportFireResult'
207
208
  | 'chat.appendInstruction'
208
209
  | 'database.execute'
209
210
  // Simple key-value storage methods
package/src/runtime.ts CHANGED
@@ -462,7 +462,7 @@ async function handleSchedulerFire(payload: SchedulerFirePayload): Promise<void>
462
462
 
463
463
  // Run callbacks concurrently to avoid blocking
464
464
  const results = await Promise.allSettled(
465
- schedulerCallbacks.map((callback) => callback(payload, execContext)),
465
+ schedulerCallbacks.map((callback) => Promise.resolve(callback(payload, execContext))),
466
466
  )
467
467
 
468
468
  // Log any errors
@@ -471,6 +471,18 @@ async function handleSchedulerFire(payload: SchedulerFirePayload): Promise<void>
471
471
  console.error(`Error in scheduler callback ${index}:`, result.reason)
472
472
  }
473
473
  })
474
+
475
+ // Report result back to host
476
+ const failed = results.find((r) => r.status === 'rejected') as PromiseRejectedResult | undefined
477
+ try {
478
+ await sendRequest<void>('scheduler.reportFireResult', {
479
+ jobId: payload.id,
480
+ success: !failed,
481
+ error: failed ? String(failed.reason) : undefined,
482
+ })
483
+ } catch {
484
+ // Best effort — don't crash if reporting fails
485
+ }
474
486
  }
475
487
 
476
488
  // ============================================================================
@@ -917,7 +929,7 @@ function buildContext(
917
929
  async cancel(jobId: string): Promise<void> {
918
930
  await sendRequest<void>('scheduler.cancel', { jobId })
919
931
  },
920
- onFire(callback: (payload: SchedulerFirePayload, context: ExecutionContext) => void): Disposable {
932
+ onFire(callback: (payload: SchedulerFirePayload, context: ExecutionContext) => void | Promise<void>): Disposable {
921
933
  schedulerCallbacks.push(callback)
922
934
  return {
923
935
  dispose: () => {
@@ -373,6 +373,23 @@ export interface ToolDefinition {
373
373
  description: LocalizedString
374
374
  /** Parameter schema (JSON Schema) */
375
375
  parameters?: Record<string, unknown>
376
+ /**
377
+ * Confirmation configuration. If set, user must confirm before tool runs.
378
+ * If not set, tool runs without confirmation.
379
+ */
380
+ confirmation?: ToolConfirmationConfig
381
+ }
382
+
383
+ /**
384
+ * Configuration for tool confirmation.
385
+ */
386
+ export interface ToolConfirmationConfig {
387
+ /**
388
+ * Default confirmation prompt to show the user.
389
+ * If not provided, a generic prompt like "Allow {toolName} to run?" is used.
390
+ * @example { en: "Allow sending email?", sv: "Tillåt att skicka e-post?" }
391
+ */
392
+ prompt?: LocalizedString
376
393
  }
377
394
 
378
395
  // ============================================================================
package/src/types.ts CHANGED
@@ -48,6 +48,7 @@ export type {
48
48
  ProviderConfigValidation,
49
49
  // Tools
50
50
  ToolDefinition,
51
+ ToolConfirmationConfig,
51
52
  // Commands
52
53
  CommandDefinition,
53
54
  // Prompts