@stina/extension-api 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-Q7KN57DE.js → chunk-WIDGIYRV.js} +1 -1
- package/dist/chunk-WIDGIYRV.js.map +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -5
- package/dist/index.d.ts +29 -5
- package/dist/index.js +1 -1
- package/dist/runtime.cjs +64 -0
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.cts +2 -2
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.js +65 -1
- package/dist/runtime.js.map +1 -1
- package/dist/{types-D9nElTai.d.cts → types-DjRF9BP3.d.cts} +20 -0
- package/dist/{types-D9nElTai.d.ts → types-DjRF9BP3.d.ts} +20 -0
- package/package.json +1 -1
- package/src/messages.ts +29 -0
- package/src/runtime.ts +108 -0
- package/src/types.ts +21 -0
- package/dist/chunk-Q7KN57DE.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/messages.ts"],"sourcesContent":["/**\n * Message protocol between Extension Host and Extension Workers\n */\n\nimport type {\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolResult,\n ActionResult,\n ModelInfo,\n SchedulerFirePayload,\n} from './types.js'\n\n// ============================================================================\n// Host → Worker Messages\n// ============================================================================\n\nexport type HostToWorkerMessage =\n | ActivateMessage\n | DeactivateMessage\n | SettingsChangedMessage\n | SchedulerFireMessage\n | ProviderChatRequestMessage\n | ProviderModelsRequestMessage\n | ToolExecuteRequestMessage\n | ActionExecuteRequestMessage\n | ResponseMessage\n | StreamingFetchChunkMessage\n\nexport interface ActivateMessage {\n type: 'activate'\n id: string\n payload: {\n extensionId: string\n extensionVersion: string\n storagePath: string\n permissions: string[]\n settings: Record<string, unknown>\n }\n}\n\nexport interface DeactivateMessage {\n type: 'deactivate'\n id: string\n}\n\nexport interface SettingsChangedMessage {\n type: 'settings-changed'\n id: string\n payload: {\n key: string\n value: unknown\n }\n}\n\nexport interface SchedulerFireMessage {\n type: 'scheduler-fire'\n id: string\n payload: SchedulerFirePayload\n}\n\nexport interface ProviderChatRequestMessage {\n type: 'provider-chat-request'\n id: string\n payload: {\n providerId: string\n messages: ChatMessage[]\n options: ChatOptions\n }\n}\n\nexport interface ProviderModelsRequestMessage {\n type: 'provider-models-request'\n id: string\n payload: {\n providerId: string\n options?: GetModelsOptions\n }\n}\n\nexport interface ToolExecuteRequestMessage {\n type: 'tool-execute-request'\n id: string\n payload: {\n toolId: string\n params: Record<string, unknown>\n /** User ID if the tool is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ActionExecuteRequestMessage {\n type: 'action-execute-request'\n id: string\n payload: {\n actionId: string\n params: Record<string, unknown>\n /** User ID if the action is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ResponseMessage {\n type: 'response'\n id: string\n payload: {\n requestId: string\n success: boolean\n data?: unknown\n error?: string\n }\n}\n\n/**\n * Message sent from host to worker with streaming fetch data chunks.\n * Used for streaming network responses (e.g., NDJSON streams from Ollama).\n */\nexport interface StreamingFetchChunkMessage {\n type: 'streaming-fetch-chunk'\n id: string\n payload: {\n requestId: string\n chunk: string\n done: boolean\n error?: string\n }\n}\n\n// ============================================================================\n// Worker → Host Messages\n// ============================================================================\n\nexport type WorkerToHostMessage =\n | ReadyMessage\n | RequestMessage\n | ProviderRegisteredMessage\n | ToolRegisteredMessage\n | ActionRegisteredMessage\n | StreamEventMessage\n | LogMessage\n | ProviderModelsResponseMessage\n | ToolExecuteResponseMessage\n | ActionExecuteResponseMessage\n | StreamingFetchAckMessage\n\nexport interface ReadyMessage {\n type: 'ready'\n}\n\n/**\n * Message sent from worker to host to acknowledge receipt of a streaming fetch chunk.\n * This enables backpressure control to prevent unbounded memory growth.\n */\nexport interface StreamingFetchAckMessage {\n type: 'streaming-fetch-ack'\n payload: {\n requestId: string\n }\n}\n\nexport interface RequestMessage {\n type: 'request'\n id: string\n method: RequestMethod\n payload: unknown\n}\n\nexport type RequestMethod =\n | 'network.fetch'\n | 'network.fetch-stream'\n | 'settings.getAll'\n | 'settings.get'\n | 'settings.set'\n | 'user.getProfile'\n | 'events.emit'\n | 'scheduler.schedule'\n | 'scheduler.cancel'\n | 'chat.appendInstruction'\n | 'database.execute'\n | 'storage.get'\n | 'storage.set'\n | 'storage.delete'\n | 'storage.keys'\n | 'storage.getForUser'\n | 'storage.setForUser'\n | 'storage.deleteForUser'\n | 'storage.keysForUser'\n\nexport interface ProviderRegisteredMessage {\n type: 'provider-registered'\n payload: {\n id: string\n name: string\n }\n}\n\nexport interface ToolRegisteredMessage {\n type: 'tool-registered'\n payload: {\n id: string\n name: string\n description: string\n parameters?: Record<string, unknown>\n }\n}\n\nexport interface ActionRegisteredMessage {\n type: 'action-registered'\n payload: {\n id: string\n }\n}\n\nexport interface StreamEventMessage {\n type: 'stream-event'\n payload: {\n requestId: string\n event: StreamEvent\n }\n}\n\nexport interface ProviderModelsResponseMessage {\n type: 'provider-models-response'\n payload: {\n requestId: string\n models: ModelInfo[]\n error?: string\n }\n}\n\nexport interface ToolExecuteResponseMessage {\n type: 'tool-execute-response'\n payload: {\n requestId: string\n result: ToolResult\n error?: string\n }\n}\n\nexport interface ActionExecuteResponseMessage {\n type: 'action-execute-response'\n payload: {\n requestId: string\n result: ActionResult\n error?: string\n }\n}\n\nexport interface LogMessage {\n type: 'log'\n payload: {\n level: 'debug' | 'info' | 'warn' | 'error'\n message: string\n data?: Record<string, unknown>\n }\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\nexport interface PendingRequest<T = unknown> {\n resolve: (value: T) => void\n reject: (error: Error) => void\n timeout: ReturnType<typeof setTimeout>\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n}\n"],"mappings":";;;;;;;;AAgRO,SAAS,oBAA4B;AAC1C,SAAO,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACjE;","names":[]}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/messages.ts"],"sourcesContent":["/**\n * @stina/extension-api\n *\n * Types and utilities for building Stina extensions.\n *\n * Extensions should import from this package for type definitions.\n * The runtime (worker-side code) should import from '@stina/extension-api/runtime'.\n */\n\n// Types\nexport type {\n // Manifest\n ExtensionManifest,\n Platform,\n ExtensionContributions,\n SettingDefinition,\n SettingOptionsMapping,\n SettingCreateMapping,\n ToolSettingsViewDefinition,\n ToolSettingsView,\n ToolSettingsListView,\n ToolSettingsListMapping,\n PanelDefinition,\n PanelView,\n PanelComponentView,\n PanelActionDataSource,\n PanelUnknownView,\n ProviderDefinition,\n PromptContribution,\n PromptSection,\n ToolDefinition,\n CommandDefinition,\n\n // Provider Configuration Schema\n ProviderConfigSchema,\n ProviderConfigProperty,\n ProviderConfigPropertyType,\n ProviderConfigSelectOption,\n ProviderConfigValidation,\n\n // Permissions\n Permission,\n NetworkPermission,\n StoragePermission,\n UserDataPermission,\n CapabilityPermission,\n SystemPermission,\n\n // Context\n ExtensionContext,\n Disposable,\n NetworkAPI,\n SettingsAPI,\n ProvidersAPI,\n ToolsAPI,\n ActionsAPI,\n EventsAPI,\n SchedulerAPI,\n SchedulerJobRequest,\n SchedulerSchedule,\n SchedulerFirePayload,\n UserAPI,\n UserProfile,\n ChatAPI,\n ChatInstructionMessage,\n DatabaseAPI,\n StorageAPI,\n LogAPI,\n\n // AI Provider\n AIProvider,\n ModelInfo,\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolCall,\n\n // Tools\n Tool,\n ToolResult,\n\n // Actions\n Action,\n ActionResult,\n\n // Entry point\n ExtensionModule,\n} from './types.js'\n\n// Messages (for host implementation)\nexport type {\n HostToWorkerMessage,\n WorkerToHostMessage,\n ActivateMessage,\n DeactivateMessage,\n SettingsChangedMessage,\n ProviderChatRequestMessage,\n ProviderModelsRequestMessage,\n ToolExecuteRequestMessage,\n ToolExecuteResponseMessage,\n ActionExecuteRequestMessage,\n ActionExecuteResponseMessage,\n ResponseMessage,\n ReadyMessage,\n RequestMessage,\n RequestMethod,\n ProviderRegisteredMessage,\n ToolRegisteredMessage,\n ActionRegisteredMessage,\n StreamEventMessage,\n LogMessage,\n PendingRequest,\n} from './messages.js'\n\nexport { generateMessageId } from './messages.js'\n\n// Component types (for extension UI components)\nexport type {\n // Styling\n AllowedCSSProperty,\n ExtensionComponentStyle,\n // Base types\n ExtensionComponentData,\n // Iteration & Children\n ExtensionComponentIterator,\n ExtensionComponentChildren,\n // Actions\n ExtensionActionCall,\n ExtensionActionRef,\n // Data Sources & Panel Definition\n ExtensionDataSource,\n ExtensionPanelDefinition,\n // Component Props\n HeaderProps,\n LabelProps,\n ParagraphProps,\n ButtonProps,\n TextInputProps,\n DateTimeInputProps,\n SelectProps,\n VerticalStackProps,\n HorizontalStackProps,\n GridProps,\n DividerProps,\n IconProps,\n IconButtonType,\n IconButtonProps,\n PanelAction,\n PanelProps,\n ToggleProps,\n CollapsibleProps,\n PillVariant,\n PillProps,\n CheckboxProps,\n MarkdownProps,\n ModalProps,\n} from './types.components.js'\n","/**\n * Message protocol between Extension Host and Extension Workers\n */\n\nimport type {\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolResult,\n ActionResult,\n ModelInfo,\n SchedulerFirePayload,\n} from './types.js'\n\n// ============================================================================\n// Host → Worker Messages\n// ============================================================================\n\nexport type HostToWorkerMessage =\n | ActivateMessage\n | DeactivateMessage\n | SettingsChangedMessage\n | SchedulerFireMessage\n | ProviderChatRequestMessage\n | ProviderModelsRequestMessage\n | ToolExecuteRequestMessage\n | ActionExecuteRequestMessage\n | ResponseMessage\n\nexport interface ActivateMessage {\n type: 'activate'\n id: string\n payload: {\n extensionId: string\n extensionVersion: string\n storagePath: string\n permissions: string[]\n settings: Record<string, unknown>\n }\n}\n\nexport interface DeactivateMessage {\n type: 'deactivate'\n id: string\n}\n\nexport interface SettingsChangedMessage {\n type: 'settings-changed'\n id: string\n payload: {\n key: string\n value: unknown\n }\n}\n\nexport interface SchedulerFireMessage {\n type: 'scheduler-fire'\n id: string\n payload: SchedulerFirePayload\n}\n\nexport interface ProviderChatRequestMessage {\n type: 'provider-chat-request'\n id: string\n payload: {\n providerId: string\n messages: ChatMessage[]\n options: ChatOptions\n }\n}\n\nexport interface ProviderModelsRequestMessage {\n type: 'provider-models-request'\n id: string\n payload: {\n providerId: string\n options?: GetModelsOptions\n }\n}\n\nexport interface ToolExecuteRequestMessage {\n type: 'tool-execute-request'\n id: string\n payload: {\n toolId: string\n params: Record<string, unknown>\n /** User ID if the tool is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ActionExecuteRequestMessage {\n type: 'action-execute-request'\n id: string\n payload: {\n actionId: string\n params: Record<string, unknown>\n /** User ID if the action is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ResponseMessage {\n type: 'response'\n id: string\n payload: {\n requestId: string\n success: boolean\n data?: unknown\n error?: string\n }\n}\n\n// ============================================================================\n// Worker → Host Messages\n// ============================================================================\n\nexport type WorkerToHostMessage =\n | ReadyMessage\n | RequestMessage\n | ProviderRegisteredMessage\n | ToolRegisteredMessage\n | ActionRegisteredMessage\n | StreamEventMessage\n | LogMessage\n | ProviderModelsResponseMessage\n | ToolExecuteResponseMessage\n | ActionExecuteResponseMessage\n\nexport interface ReadyMessage {\n type: 'ready'\n}\n\nexport interface RequestMessage {\n type: 'request'\n id: string\n method: RequestMethod\n payload: unknown\n}\n\nexport type RequestMethod =\n | 'network.fetch'\n | 'settings.getAll'\n | 'settings.get'\n | 'settings.set'\n | 'user.getProfile'\n | 'events.emit'\n | 'scheduler.schedule'\n | 'scheduler.cancel'\n | 'chat.appendInstruction'\n | 'database.execute'\n | 'storage.get'\n | 'storage.set'\n | 'storage.delete'\n | 'storage.keys'\n | 'storage.getForUser'\n | 'storage.setForUser'\n | 'storage.deleteForUser'\n | 'storage.keysForUser'\n\nexport interface ProviderRegisteredMessage {\n type: 'provider-registered'\n payload: {\n id: string\n name: string\n }\n}\n\nexport interface ToolRegisteredMessage {\n type: 'tool-registered'\n payload: {\n id: string\n name: string\n description: string\n parameters?: Record<string, unknown>\n }\n}\n\nexport interface ActionRegisteredMessage {\n type: 'action-registered'\n payload: {\n id: string\n }\n}\n\nexport interface StreamEventMessage {\n type: 'stream-event'\n payload: {\n requestId: string\n event: StreamEvent\n }\n}\n\nexport interface ProviderModelsResponseMessage {\n type: 'provider-models-response'\n payload: {\n requestId: string\n models: ModelInfo[]\n error?: string\n }\n}\n\nexport interface ToolExecuteResponseMessage {\n type: 'tool-execute-response'\n payload: {\n requestId: string\n result: ToolResult\n error?: string\n }\n}\n\nexport interface ActionExecuteResponseMessage {\n type: 'action-execute-response'\n payload: {\n requestId: string\n result: ActionResult\n error?: string\n }\n}\n\nexport interface LogMessage {\n type: 'log'\n payload: {\n level: 'debug' | 'info' | 'warn' | 'error'\n message: string\n data?: Record<string, unknown>\n }\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\nexport interface PendingRequest<T = unknown> {\n resolve: (value: T) => void\n reject: (error: Error) => void\n timeout: ReturnType<typeof setTimeout>\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/messages.ts"],"sourcesContent":["/**\n * @stina/extension-api\n *\n * Types and utilities for building Stina extensions.\n *\n * Extensions should import from this package for type definitions.\n * The runtime (worker-side code) should import from '@stina/extension-api/runtime'.\n */\n\n// Types\nexport type {\n // Manifest\n ExtensionManifest,\n Platform,\n ExtensionContributions,\n SettingDefinition,\n SettingOptionsMapping,\n SettingCreateMapping,\n ToolSettingsViewDefinition,\n ToolSettingsView,\n ToolSettingsListView,\n ToolSettingsListMapping,\n PanelDefinition,\n PanelView,\n PanelComponentView,\n PanelActionDataSource,\n PanelUnknownView,\n ProviderDefinition,\n PromptContribution,\n PromptSection,\n ToolDefinition,\n CommandDefinition,\n\n // Provider Configuration Schema\n ProviderConfigSchema,\n ProviderConfigProperty,\n ProviderConfigPropertyType,\n ProviderConfigSelectOption,\n ProviderConfigValidation,\n\n // Permissions\n Permission,\n NetworkPermission,\n StoragePermission,\n UserDataPermission,\n CapabilityPermission,\n SystemPermission,\n\n // Context\n ExtensionContext,\n Disposable,\n NetworkAPI,\n SettingsAPI,\n ProvidersAPI,\n ToolsAPI,\n ActionsAPI,\n EventsAPI,\n SchedulerAPI,\n SchedulerJobRequest,\n SchedulerSchedule,\n SchedulerFirePayload,\n UserAPI,\n UserProfile,\n ChatAPI,\n ChatInstructionMessage,\n DatabaseAPI,\n StorageAPI,\n LogAPI,\n\n // AI Provider\n AIProvider,\n ModelInfo,\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolCall,\n\n // Tools\n Tool,\n ToolResult,\n\n // Actions\n Action,\n ActionResult,\n\n // Entry point\n ExtensionModule,\n} from './types.js'\n\n// Messages (for host implementation)\nexport type {\n HostToWorkerMessage,\n WorkerToHostMessage,\n ActivateMessage,\n DeactivateMessage,\n SettingsChangedMessage,\n ProviderChatRequestMessage,\n ProviderModelsRequestMessage,\n ToolExecuteRequestMessage,\n ToolExecuteResponseMessage,\n ActionExecuteRequestMessage,\n ActionExecuteResponseMessage,\n ResponseMessage,\n ReadyMessage,\n RequestMessage,\n RequestMethod,\n ProviderRegisteredMessage,\n ToolRegisteredMessage,\n ActionRegisteredMessage,\n StreamEventMessage,\n LogMessage,\n PendingRequest,\n} from './messages.js'\n\nexport { generateMessageId } from './messages.js'\n\n// Component types (for extension UI components)\nexport type {\n // Styling\n AllowedCSSProperty,\n ExtensionComponentStyle,\n // Base types\n ExtensionComponentData,\n // Iteration & Children\n ExtensionComponentIterator,\n ExtensionComponentChildren,\n // Actions\n ExtensionActionCall,\n ExtensionActionRef,\n // Data Sources & Panel Definition\n ExtensionDataSource,\n ExtensionPanelDefinition,\n // Component Props\n HeaderProps,\n LabelProps,\n ParagraphProps,\n ButtonProps,\n TextInputProps,\n DateTimeInputProps,\n SelectProps,\n VerticalStackProps,\n HorizontalStackProps,\n GridProps,\n DividerProps,\n IconProps,\n IconButtonType,\n IconButtonProps,\n PanelAction,\n PanelProps,\n ToggleProps,\n CollapsibleProps,\n PillVariant,\n PillProps,\n CheckboxProps,\n MarkdownProps,\n ModalProps,\n} from './types.components.js'\n","/**\n * Message protocol between Extension Host and Extension Workers\n */\n\nimport type {\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolResult,\n ActionResult,\n ModelInfo,\n SchedulerFirePayload,\n} from './types.js'\n\n// ============================================================================\n// Host → Worker Messages\n// ============================================================================\n\nexport type HostToWorkerMessage =\n | ActivateMessage\n | DeactivateMessage\n | SettingsChangedMessage\n | SchedulerFireMessage\n | ProviderChatRequestMessage\n | ProviderModelsRequestMessage\n | ToolExecuteRequestMessage\n | ActionExecuteRequestMessage\n | ResponseMessage\n | StreamingFetchChunkMessage\n\nexport interface ActivateMessage {\n type: 'activate'\n id: string\n payload: {\n extensionId: string\n extensionVersion: string\n storagePath: string\n permissions: string[]\n settings: Record<string, unknown>\n }\n}\n\nexport interface DeactivateMessage {\n type: 'deactivate'\n id: string\n}\n\nexport interface SettingsChangedMessage {\n type: 'settings-changed'\n id: string\n payload: {\n key: string\n value: unknown\n }\n}\n\nexport interface SchedulerFireMessage {\n type: 'scheduler-fire'\n id: string\n payload: SchedulerFirePayload\n}\n\nexport interface ProviderChatRequestMessage {\n type: 'provider-chat-request'\n id: string\n payload: {\n providerId: string\n messages: ChatMessage[]\n options: ChatOptions\n }\n}\n\nexport interface ProviderModelsRequestMessage {\n type: 'provider-models-request'\n id: string\n payload: {\n providerId: string\n options?: GetModelsOptions\n }\n}\n\nexport interface ToolExecuteRequestMessage {\n type: 'tool-execute-request'\n id: string\n payload: {\n toolId: string\n params: Record<string, unknown>\n /** User ID if the tool is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ActionExecuteRequestMessage {\n type: 'action-execute-request'\n id: string\n payload: {\n actionId: string\n params: Record<string, unknown>\n /** User ID if the action is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ResponseMessage {\n type: 'response'\n id: string\n payload: {\n requestId: string\n success: boolean\n data?: unknown\n error?: string\n }\n}\n\n/**\n * Message sent from host to worker with streaming fetch data chunks.\n * Used for streaming network responses (e.g., NDJSON streams from Ollama).\n */\nexport interface StreamingFetchChunkMessage {\n type: 'streaming-fetch-chunk'\n id: string\n payload: {\n requestId: string\n chunk: string\n done: boolean\n error?: string\n }\n}\n\n// ============================================================================\n// Worker → Host Messages\n// ============================================================================\n\nexport type WorkerToHostMessage =\n | ReadyMessage\n | RequestMessage\n | ProviderRegisteredMessage\n | ToolRegisteredMessage\n | ActionRegisteredMessage\n | StreamEventMessage\n | LogMessage\n | ProviderModelsResponseMessage\n | ToolExecuteResponseMessage\n | ActionExecuteResponseMessage\n | StreamingFetchAckMessage\n\nexport interface ReadyMessage {\n type: 'ready'\n}\n\n/**\n * Message sent from worker to host to acknowledge receipt of a streaming fetch chunk.\n * This enables backpressure control to prevent unbounded memory growth.\n */\nexport interface StreamingFetchAckMessage {\n type: 'streaming-fetch-ack'\n payload: {\n requestId: string\n }\n}\n\nexport interface RequestMessage {\n type: 'request'\n id: string\n method: RequestMethod\n payload: unknown\n}\n\nexport type RequestMethod =\n | 'network.fetch'\n | 'network.fetch-stream'\n | 'settings.getAll'\n | 'settings.get'\n | 'settings.set'\n | 'user.getProfile'\n | 'events.emit'\n | 'scheduler.schedule'\n | 'scheduler.cancel'\n | 'chat.appendInstruction'\n | 'database.execute'\n | 'storage.get'\n | 'storage.set'\n | 'storage.delete'\n | 'storage.keys'\n | 'storage.getForUser'\n | 'storage.setForUser'\n | 'storage.deleteForUser'\n | 'storage.keysForUser'\n\nexport interface ProviderRegisteredMessage {\n type: 'provider-registered'\n payload: {\n id: string\n name: string\n }\n}\n\nexport interface ToolRegisteredMessage {\n type: 'tool-registered'\n payload: {\n id: string\n name: string\n description: string\n parameters?: Record<string, unknown>\n }\n}\n\nexport interface ActionRegisteredMessage {\n type: 'action-registered'\n payload: {\n id: string\n }\n}\n\nexport interface StreamEventMessage {\n type: 'stream-event'\n payload: {\n requestId: string\n event: StreamEvent\n }\n}\n\nexport interface ProviderModelsResponseMessage {\n type: 'provider-models-response'\n payload: {\n requestId: string\n models: ModelInfo[]\n error?: string\n }\n}\n\nexport interface ToolExecuteResponseMessage {\n type: 'tool-execute-response'\n payload: {\n requestId: string\n result: ToolResult\n error?: string\n }\n}\n\nexport interface ActionExecuteResponseMessage {\n type: 'action-execute-response'\n payload: {\n requestId: string\n result: ActionResult\n error?: string\n }\n}\n\nexport interface LogMessage {\n type: 'log'\n payload: {\n level: 'debug' | 'info' | 'warn' | 'error'\n message: string\n data?: Record<string, unknown>\n }\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\nexport interface PendingRequest<T = unknown> {\n resolve: (value: T) => void\n reject: (error: Error) => void\n timeout: ReturnType<typeof setTimeout>\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACgRO,SAAS,oBAA4B;AAC1C,SAAO,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACjE;","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { S as SchedulerFirePayload, C as ChatMessage, a as ChatOptions, G as GetModelsOptions, b as StreamEvent, M as ModelInfo, T as ToolResult, A as ActionResult } from './types-
|
|
2
|
-
export { a3 as AIProvider, a6 as Action, Q as ActionsAPI, a8 as AllowedCSSProperty, ak as ButtonProps, D as CapabilityPermission, _ as ChatAPI, $ as ChatInstructionMessage, aB as CheckboxProps, ay as CollapsibleProps, t as CommandDefinition, a0 as DatabaseAPI, am as DateTimeInputProps, I as Disposable, ar as DividerProps, R as EventsAPI, ad as ExtensionActionCall, ae as ExtensionActionRef, ac as ExtensionComponentChildren, aa as ExtensionComponentData, ab as ExtensionComponentIterator, a9 as ExtensionComponentStyle, H as ExtensionContext, c as ExtensionContributions, af as ExtensionDataSource, E as ExtensionManifest, a7 as ExtensionModule, ag as ExtensionPanelDefinition, aq as GridProps, ah as HeaderProps, ap as HorizontalStackProps, au as IconButtonProps, at as IconButtonType, as as IconProps, ai as LabelProps, a2 as LogAPI, aC as MarkdownProps, aD as ModalProps, J as NetworkAPI, N as NetworkPermission, av as PanelAction, n as PanelActionDataSource, m as PanelComponentView, k as PanelDefinition, aw as PanelProps, o as PanelUnknownView, l as PanelView, aj as ParagraphProps, z as Permission, aA as PillProps, az as PillVariant, P as Platform, q as PromptContribution, r as PromptSection, v as ProviderConfigProperty, w as ProviderConfigPropertyType, u as ProviderConfigSchema, x as ProviderConfigSelectOption, y as ProviderConfigValidation, p as ProviderDefinition, L as ProvidersAPI, V as SchedulerAPI, W as SchedulerJobRequest, X as SchedulerSchedule, an as SelectProps, f as SettingCreateMapping, d as SettingDefinition, e as SettingOptionsMapping, K as SettingsAPI, a1 as StorageAPI, B as StoragePermission, F as SystemPermission, al as TextInputProps, ax as ToggleProps, a5 as Tool, a4 as ToolCall, s as ToolDefinition, j as ToolSettingsListMapping, i as ToolSettingsListView, h as ToolSettingsView, g as ToolSettingsViewDefinition, O as ToolsAPI, Y as UserAPI, U as UserDataPermission, Z as UserProfile, ao as VerticalStackProps } from './types-
|
|
1
|
+
import { S as SchedulerFirePayload, C as ChatMessage, a as ChatOptions, G as GetModelsOptions, b as StreamEvent, M as ModelInfo, T as ToolResult, A as ActionResult } from './types-DjRF9BP3.cjs';
|
|
2
|
+
export { a3 as AIProvider, a6 as Action, Q as ActionsAPI, a8 as AllowedCSSProperty, ak as ButtonProps, D as CapabilityPermission, _ as ChatAPI, $ as ChatInstructionMessage, aB as CheckboxProps, ay as CollapsibleProps, t as CommandDefinition, a0 as DatabaseAPI, am as DateTimeInputProps, I as Disposable, ar as DividerProps, R as EventsAPI, ad as ExtensionActionCall, ae as ExtensionActionRef, ac as ExtensionComponentChildren, aa as ExtensionComponentData, ab as ExtensionComponentIterator, a9 as ExtensionComponentStyle, H as ExtensionContext, c as ExtensionContributions, af as ExtensionDataSource, E as ExtensionManifest, a7 as ExtensionModule, ag as ExtensionPanelDefinition, aq as GridProps, ah as HeaderProps, ap as HorizontalStackProps, au as IconButtonProps, at as IconButtonType, as as IconProps, ai as LabelProps, a2 as LogAPI, aC as MarkdownProps, aD as ModalProps, J as NetworkAPI, N as NetworkPermission, av as PanelAction, n as PanelActionDataSource, m as PanelComponentView, k as PanelDefinition, aw as PanelProps, o as PanelUnknownView, l as PanelView, aj as ParagraphProps, z as Permission, aA as PillProps, az as PillVariant, P as Platform, q as PromptContribution, r as PromptSection, v as ProviderConfigProperty, w as ProviderConfigPropertyType, u as ProviderConfigSchema, x as ProviderConfigSelectOption, y as ProviderConfigValidation, p as ProviderDefinition, L as ProvidersAPI, V as SchedulerAPI, W as SchedulerJobRequest, X as SchedulerSchedule, an as SelectProps, f as SettingCreateMapping, d as SettingDefinition, e as SettingOptionsMapping, K as SettingsAPI, a1 as StorageAPI, B as StoragePermission, F as SystemPermission, al as TextInputProps, ax as ToggleProps, a5 as Tool, a4 as ToolCall, s as ToolDefinition, j as ToolSettingsListMapping, i as ToolSettingsListView, h as ToolSettingsView, g as ToolSettingsViewDefinition, O as ToolsAPI, Y as UserAPI, U as UserDataPermission, Z as UserProfile, ao as VerticalStackProps } from './types-DjRF9BP3.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Message protocol between Extension Host and Extension Workers
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
type HostToWorkerMessage = ActivateMessage | DeactivateMessage | SettingsChangedMessage | SchedulerFireMessage | ProviderChatRequestMessage | ProviderModelsRequestMessage | ToolExecuteRequestMessage | ActionExecuteRequestMessage | ResponseMessage;
|
|
8
|
+
type HostToWorkerMessage = ActivateMessage | DeactivateMessage | SettingsChangedMessage | SchedulerFireMessage | ProviderChatRequestMessage | ProviderModelsRequestMessage | ToolExecuteRequestMessage | ActionExecuteRequestMessage | ResponseMessage | StreamingFetchChunkMessage;
|
|
9
9
|
interface ActivateMessage {
|
|
10
10
|
type: 'activate';
|
|
11
11
|
id: string;
|
|
@@ -81,17 +81,41 @@ interface ResponseMessage {
|
|
|
81
81
|
error?: string;
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Message sent from host to worker with streaming fetch data chunks.
|
|
86
|
+
* Used for streaming network responses (e.g., NDJSON streams from Ollama).
|
|
87
|
+
*/
|
|
88
|
+
interface StreamingFetchChunkMessage {
|
|
89
|
+
type: 'streaming-fetch-chunk';
|
|
90
|
+
id: string;
|
|
91
|
+
payload: {
|
|
92
|
+
requestId: string;
|
|
93
|
+
chunk: string;
|
|
94
|
+
done: boolean;
|
|
95
|
+
error?: string;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
type WorkerToHostMessage = ReadyMessage | RequestMessage | ProviderRegisteredMessage | ToolRegisteredMessage | ActionRegisteredMessage | StreamEventMessage | LogMessage | ProviderModelsResponseMessage | ToolExecuteResponseMessage | ActionExecuteResponseMessage | StreamingFetchAckMessage;
|
|
85
99
|
interface ReadyMessage {
|
|
86
100
|
type: 'ready';
|
|
87
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Message sent from worker to host to acknowledge receipt of a streaming fetch chunk.
|
|
104
|
+
* This enables backpressure control to prevent unbounded memory growth.
|
|
105
|
+
*/
|
|
106
|
+
interface StreamingFetchAckMessage {
|
|
107
|
+
type: 'streaming-fetch-ack';
|
|
108
|
+
payload: {
|
|
109
|
+
requestId: string;
|
|
110
|
+
};
|
|
111
|
+
}
|
|
88
112
|
interface RequestMessage {
|
|
89
113
|
type: 'request';
|
|
90
114
|
id: string;
|
|
91
115
|
method: RequestMethod;
|
|
92
116
|
payload: unknown;
|
|
93
117
|
}
|
|
94
|
-
type RequestMethod = 'network.fetch' | 'settings.getAll' | 'settings.get' | 'settings.set' | 'user.getProfile' | 'events.emit' | 'scheduler.schedule' | 'scheduler.cancel' | 'chat.appendInstruction' | 'database.execute' | 'storage.get' | 'storage.set' | 'storage.delete' | 'storage.keys' | 'storage.getForUser' | 'storage.setForUser' | 'storage.deleteForUser' | 'storage.keysForUser';
|
|
118
|
+
type RequestMethod = 'network.fetch' | 'network.fetch-stream' | 'settings.getAll' | 'settings.get' | 'settings.set' | 'user.getProfile' | 'events.emit' | 'scheduler.schedule' | 'scheduler.cancel' | 'chat.appendInstruction' | 'database.execute' | 'storage.get' | 'storage.set' | 'storage.delete' | 'storage.keys' | 'storage.getForUser' | 'storage.setForUser' | 'storage.deleteForUser' | 'storage.keysForUser';
|
|
95
119
|
interface ProviderRegisteredMessage {
|
|
96
120
|
type: 'provider-registered';
|
|
97
121
|
payload: {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { S as SchedulerFirePayload, C as ChatMessage, a as ChatOptions, G as GetModelsOptions, b as StreamEvent, M as ModelInfo, T as ToolResult, A as ActionResult } from './types-
|
|
2
|
-
export { a3 as AIProvider, a6 as Action, Q as ActionsAPI, a8 as AllowedCSSProperty, ak as ButtonProps, D as CapabilityPermission, _ as ChatAPI, $ as ChatInstructionMessage, aB as CheckboxProps, ay as CollapsibleProps, t as CommandDefinition, a0 as DatabaseAPI, am as DateTimeInputProps, I as Disposable, ar as DividerProps, R as EventsAPI, ad as ExtensionActionCall, ae as ExtensionActionRef, ac as ExtensionComponentChildren, aa as ExtensionComponentData, ab as ExtensionComponentIterator, a9 as ExtensionComponentStyle, H as ExtensionContext, c as ExtensionContributions, af as ExtensionDataSource, E as ExtensionManifest, a7 as ExtensionModule, ag as ExtensionPanelDefinition, aq as GridProps, ah as HeaderProps, ap as HorizontalStackProps, au as IconButtonProps, at as IconButtonType, as as IconProps, ai as LabelProps, a2 as LogAPI, aC as MarkdownProps, aD as ModalProps, J as NetworkAPI, N as NetworkPermission, av as PanelAction, n as PanelActionDataSource, m as PanelComponentView, k as PanelDefinition, aw as PanelProps, o as PanelUnknownView, l as PanelView, aj as ParagraphProps, z as Permission, aA as PillProps, az as PillVariant, P as Platform, q as PromptContribution, r as PromptSection, v as ProviderConfigProperty, w as ProviderConfigPropertyType, u as ProviderConfigSchema, x as ProviderConfigSelectOption, y as ProviderConfigValidation, p as ProviderDefinition, L as ProvidersAPI, V as SchedulerAPI, W as SchedulerJobRequest, X as SchedulerSchedule, an as SelectProps, f as SettingCreateMapping, d as SettingDefinition, e as SettingOptionsMapping, K as SettingsAPI, a1 as StorageAPI, B as StoragePermission, F as SystemPermission, al as TextInputProps, ax as ToggleProps, a5 as Tool, a4 as ToolCall, s as ToolDefinition, j as ToolSettingsListMapping, i as ToolSettingsListView, h as ToolSettingsView, g as ToolSettingsViewDefinition, O as ToolsAPI, Y as UserAPI, U as UserDataPermission, Z as UserProfile, ao as VerticalStackProps } from './types-
|
|
1
|
+
import { S as SchedulerFirePayload, C as ChatMessage, a as ChatOptions, G as GetModelsOptions, b as StreamEvent, M as ModelInfo, T as ToolResult, A as ActionResult } from './types-DjRF9BP3.js';
|
|
2
|
+
export { a3 as AIProvider, a6 as Action, Q as ActionsAPI, a8 as AllowedCSSProperty, ak as ButtonProps, D as CapabilityPermission, _ as ChatAPI, $ as ChatInstructionMessage, aB as CheckboxProps, ay as CollapsibleProps, t as CommandDefinition, a0 as DatabaseAPI, am as DateTimeInputProps, I as Disposable, ar as DividerProps, R as EventsAPI, ad as ExtensionActionCall, ae as ExtensionActionRef, ac as ExtensionComponentChildren, aa as ExtensionComponentData, ab as ExtensionComponentIterator, a9 as ExtensionComponentStyle, H as ExtensionContext, c as ExtensionContributions, af as ExtensionDataSource, E as ExtensionManifest, a7 as ExtensionModule, ag as ExtensionPanelDefinition, aq as GridProps, ah as HeaderProps, ap as HorizontalStackProps, au as IconButtonProps, at as IconButtonType, as as IconProps, ai as LabelProps, a2 as LogAPI, aC as MarkdownProps, aD as ModalProps, J as NetworkAPI, N as NetworkPermission, av as PanelAction, n as PanelActionDataSource, m as PanelComponentView, k as PanelDefinition, aw as PanelProps, o as PanelUnknownView, l as PanelView, aj as ParagraphProps, z as Permission, aA as PillProps, az as PillVariant, P as Platform, q as PromptContribution, r as PromptSection, v as ProviderConfigProperty, w as ProviderConfigPropertyType, u as ProviderConfigSchema, x as ProviderConfigSelectOption, y as ProviderConfigValidation, p as ProviderDefinition, L as ProvidersAPI, V as SchedulerAPI, W as SchedulerJobRequest, X as SchedulerSchedule, an as SelectProps, f as SettingCreateMapping, d as SettingDefinition, e as SettingOptionsMapping, K as SettingsAPI, a1 as StorageAPI, B as StoragePermission, F as SystemPermission, al as TextInputProps, ax as ToggleProps, a5 as Tool, a4 as ToolCall, s as ToolDefinition, j as ToolSettingsListMapping, i as ToolSettingsListView, h as ToolSettingsView, g as ToolSettingsViewDefinition, O as ToolsAPI, Y as UserAPI, U as UserDataPermission, Z as UserProfile, ao as VerticalStackProps } from './types-DjRF9BP3.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Message protocol between Extension Host and Extension Workers
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
type HostToWorkerMessage = ActivateMessage | DeactivateMessage | SettingsChangedMessage | SchedulerFireMessage | ProviderChatRequestMessage | ProviderModelsRequestMessage | ToolExecuteRequestMessage | ActionExecuteRequestMessage | ResponseMessage;
|
|
8
|
+
type HostToWorkerMessage = ActivateMessage | DeactivateMessage | SettingsChangedMessage | SchedulerFireMessage | ProviderChatRequestMessage | ProviderModelsRequestMessage | ToolExecuteRequestMessage | ActionExecuteRequestMessage | ResponseMessage | StreamingFetchChunkMessage;
|
|
9
9
|
interface ActivateMessage {
|
|
10
10
|
type: 'activate';
|
|
11
11
|
id: string;
|
|
@@ -81,17 +81,41 @@ interface ResponseMessage {
|
|
|
81
81
|
error?: string;
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Message sent from host to worker with streaming fetch data chunks.
|
|
86
|
+
* Used for streaming network responses (e.g., NDJSON streams from Ollama).
|
|
87
|
+
*/
|
|
88
|
+
interface StreamingFetchChunkMessage {
|
|
89
|
+
type: 'streaming-fetch-chunk';
|
|
90
|
+
id: string;
|
|
91
|
+
payload: {
|
|
92
|
+
requestId: string;
|
|
93
|
+
chunk: string;
|
|
94
|
+
done: boolean;
|
|
95
|
+
error?: string;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
type WorkerToHostMessage = ReadyMessage | RequestMessage | ProviderRegisteredMessage | ToolRegisteredMessage | ActionRegisteredMessage | StreamEventMessage | LogMessage | ProviderModelsResponseMessage | ToolExecuteResponseMessage | ActionExecuteResponseMessage | StreamingFetchAckMessage;
|
|
85
99
|
interface ReadyMessage {
|
|
86
100
|
type: 'ready';
|
|
87
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Message sent from worker to host to acknowledge receipt of a streaming fetch chunk.
|
|
104
|
+
* This enables backpressure control to prevent unbounded memory growth.
|
|
105
|
+
*/
|
|
106
|
+
interface StreamingFetchAckMessage {
|
|
107
|
+
type: 'streaming-fetch-ack';
|
|
108
|
+
payload: {
|
|
109
|
+
requestId: string;
|
|
110
|
+
};
|
|
111
|
+
}
|
|
88
112
|
interface RequestMessage {
|
|
89
113
|
type: 'request';
|
|
90
114
|
id: string;
|
|
91
115
|
method: RequestMethod;
|
|
92
116
|
payload: unknown;
|
|
93
117
|
}
|
|
94
|
-
type RequestMethod = 'network.fetch' | 'settings.getAll' | 'settings.get' | 'settings.set' | 'user.getProfile' | 'events.emit' | 'scheduler.schedule' | 'scheduler.cancel' | 'chat.appendInstruction' | 'database.execute' | 'storage.get' | 'storage.set' | 'storage.delete' | 'storage.keys' | 'storage.getForUser' | 'storage.setForUser' | 'storage.deleteForUser' | 'storage.keysForUser';
|
|
118
|
+
type RequestMethod = 'network.fetch' | 'network.fetch-stream' | 'settings.getAll' | 'settings.get' | 'settings.set' | 'user.getProfile' | 'events.emit' | 'scheduler.schedule' | 'scheduler.cancel' | 'chat.appendInstruction' | 'database.execute' | 'storage.get' | 'storage.set' | 'storage.delete' | 'storage.keys' | 'storage.getForUser' | 'storage.setForUser' | 'storage.deleteForUser' | 'storage.keysForUser';
|
|
95
119
|
interface ProviderRegisteredMessage {
|
|
96
120
|
type: 'provider-registered';
|
|
97
121
|
payload: {
|
package/dist/index.js
CHANGED
package/dist/runtime.cjs
CHANGED
|
@@ -57,6 +57,7 @@ var registeredTools = /* @__PURE__ */ new Map();
|
|
|
57
57
|
var registeredActions = /* @__PURE__ */ new Map();
|
|
58
58
|
var settingsCallbacks = [];
|
|
59
59
|
var schedulerCallbacks = [];
|
|
60
|
+
var streamingFetchRequests = /* @__PURE__ */ new Map();
|
|
60
61
|
var REQUEST_TIMEOUT = 3e4;
|
|
61
62
|
function postMessage(message) {
|
|
62
63
|
messagePort.postMessage(message);
|
|
@@ -106,7 +107,32 @@ async function handleHostMessage(message) {
|
|
|
106
107
|
case "response":
|
|
107
108
|
handleResponse(message.payload);
|
|
108
109
|
break;
|
|
110
|
+
case "streaming-fetch-chunk":
|
|
111
|
+
handleStreamingFetchChunk(message.payload);
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function handleStreamingFetchChunk(payload) {
|
|
116
|
+
const request = streamingFetchRequests.get(payload.requestId);
|
|
117
|
+
if (!request) return;
|
|
118
|
+
if (payload.error) {
|
|
119
|
+
request.error = payload.error;
|
|
120
|
+
request.done = true;
|
|
121
|
+
} else if (payload.chunk) {
|
|
122
|
+
request.chunks.push(payload.chunk);
|
|
109
123
|
}
|
|
124
|
+
if (payload.done) {
|
|
125
|
+
request.done = true;
|
|
126
|
+
}
|
|
127
|
+
if (request.resolve) {
|
|
128
|
+
const resolve = request.resolve;
|
|
129
|
+
request.resolve = void 0;
|
|
130
|
+
resolve();
|
|
131
|
+
}
|
|
132
|
+
postMessage({
|
|
133
|
+
type: "streaming-fetch-ack",
|
|
134
|
+
payload: { requestId: payload.requestId }
|
|
135
|
+
});
|
|
110
136
|
}
|
|
111
137
|
function handleResponse(payload) {
|
|
112
138
|
const pending = pendingRequests.get(payload.requestId);
|
|
@@ -388,6 +414,44 @@ function buildContext(extensionId, extensionVersion, storagePath, permissions) {
|
|
|
388
414
|
statusText: result.statusText,
|
|
389
415
|
headers: result.headers
|
|
390
416
|
});
|
|
417
|
+
},
|
|
418
|
+
async *fetchStream(url, options) {
|
|
419
|
+
const requestId = generateMessageId();
|
|
420
|
+
const request = {
|
|
421
|
+
chunks: [],
|
|
422
|
+
done: false
|
|
423
|
+
};
|
|
424
|
+
streamingFetchRequests.set(requestId, request);
|
|
425
|
+
postMessage({
|
|
426
|
+
type: "request",
|
|
427
|
+
id: requestId,
|
|
428
|
+
method: "network.fetch-stream",
|
|
429
|
+
payload: { url, options, requestId }
|
|
430
|
+
});
|
|
431
|
+
try {
|
|
432
|
+
while (!request.done) {
|
|
433
|
+
await new Promise((resolve) => {
|
|
434
|
+
const resolver = () => {
|
|
435
|
+
if (request.resolve === resolver) {
|
|
436
|
+
request.resolve = void 0;
|
|
437
|
+
}
|
|
438
|
+
resolve();
|
|
439
|
+
};
|
|
440
|
+
request.resolve = resolver;
|
|
441
|
+
if (request.chunks.length > 0 || request.done) {
|
|
442
|
+
resolver();
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
if (request.error) {
|
|
446
|
+
throw new Error(request.error);
|
|
447
|
+
}
|
|
448
|
+
while (request.chunks.length > 0) {
|
|
449
|
+
yield request.chunks.shift();
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
} finally {
|
|
453
|
+
streamingFetchRequests.delete(requestId);
|
|
454
|
+
}
|
|
391
455
|
}
|
|
392
456
|
};
|
|
393
457
|
context.network = networkApi;
|
package/dist/runtime.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runtime.ts","../src/messages.ts"],"sourcesContent":["/**\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 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 DatabaseAPI,\n StorageAPI,\n LogAPI,\n AIProvider,\n Tool,\n Action,\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n} from './types.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\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) => void> = []\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 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}\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 } catch (error) {\n console.error('Error during deactivation:', error)\n } finally {\n extensionModule = null\n extensionDisposable = null\n extensionContext = 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\nfunction handleSchedulerFire(payload: SchedulerFirePayload): void {\n // Set the userId in context if this is a user-scoped job\n if (extensionContext && payload.userId) {\n ;(extensionContext as { userId?: string }).userId = payload.userId\n }\n\n for (const callback of schedulerCallbacks) {\n try {\n callback(payload)\n } catch (error) {\n console.error('Error in scheduler callback:', error)\n }\n }\n\n // Reset userId after all callbacks\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\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 // Update the extension context with the userId if provided\n if (extensionContext && payload.userId) {\n // Create a new context with the userId for this execution\n ;(extensionContext as { userId?: string }).userId = payload.userId\n }\n\n const result = await tool.execute(payload.params)\n\n // Reset userId after execution\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\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 // Reset userId on error\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\n\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 // Update the extension context with the userId if provided\n if (extensionContext && payload.userId) {\n ;(extensionContext as { userId?: string }).userId = payload.userId\n }\n\n const result = await action.execute(payload.params)\n\n // Reset userId after execution\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\n\n postMessage({\n type: 'action-execute-response',\n payload: {\n requestId,\n result,\n },\n })\n } catch (error) {\n // Reset userId on error\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\n\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 ;(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 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) => 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 await sendRequest<void>('chat.appendInstruction', message)\n },\n }\n ;(context as { chat: ChatAPI }).chat = chatApi\n }\n\n // Add database API if permitted\n if (hasPermission('database.own')) {\n const databaseApi: DatabaseAPI = {\n async execute<T = unknown>(sql: string, params?: unknown[]): Promise<T[]> {\n return sendRequest<T[]>('database.execute', { sql, params })\n },\n }\n ;(context as { database: DatabaseAPI }).database = databaseApi\n }\n\n // Add storage API if permitted\n if (hasPermission('storage.local')) {\n const storageApi: StorageAPI = {\n // Global/extension-scoped storage\n async get<T>(key: string): Promise<T | undefined> {\n return sendRequest<T | undefined>('storage.get', { key })\n },\n async set(key: string, value: unknown): Promise<void> {\n return sendRequest<void>('storage.set', { key, value })\n },\n async delete(key: string): Promise<void> {\n return sendRequest<void>('storage.delete', { key })\n },\n async keys(): Promise<string[]> {\n return sendRequest<string[]>('storage.keys', {})\n },\n // User-scoped storage\n async getForUser<T>(userId: string, key: string): Promise<T | undefined> {\n return sendRequest<T | undefined>('storage.getForUser', { userId, key })\n },\n async setForUser(userId: string, key: string, value: unknown): Promise<void> {\n return sendRequest<void>('storage.setForUser', { userId, key, value })\n },\n async deleteForUser(userId: string, key: string): Promise<void> {\n return sendRequest<void>('storage.deleteForUser', { userId, key })\n },\n async keysForUser(userId: string): Promise<string[]> {\n return sendRequest<string[]>('storage.keysForUser', { userId })\n },\n }\n ;(context as { storage: StorageAPI }).storage = storageApi\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 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} from './types.js'\n","/**\n * Message protocol between Extension Host and Extension Workers\n */\n\nimport type {\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolResult,\n ActionResult,\n ModelInfo,\n SchedulerFirePayload,\n} from './types.js'\n\n// ============================================================================\n// Host → Worker Messages\n// ============================================================================\n\nexport type HostToWorkerMessage =\n | ActivateMessage\n | DeactivateMessage\n | SettingsChangedMessage\n | SchedulerFireMessage\n | ProviderChatRequestMessage\n | ProviderModelsRequestMessage\n | ToolExecuteRequestMessage\n | ActionExecuteRequestMessage\n | ResponseMessage\n\nexport interface ActivateMessage {\n type: 'activate'\n id: string\n payload: {\n extensionId: string\n extensionVersion: string\n storagePath: string\n permissions: string[]\n settings: Record<string, unknown>\n }\n}\n\nexport interface DeactivateMessage {\n type: 'deactivate'\n id: string\n}\n\nexport interface SettingsChangedMessage {\n type: 'settings-changed'\n id: string\n payload: {\n key: string\n value: unknown\n }\n}\n\nexport interface SchedulerFireMessage {\n type: 'scheduler-fire'\n id: string\n payload: SchedulerFirePayload\n}\n\nexport interface ProviderChatRequestMessage {\n type: 'provider-chat-request'\n id: string\n payload: {\n providerId: string\n messages: ChatMessage[]\n options: ChatOptions\n }\n}\n\nexport interface ProviderModelsRequestMessage {\n type: 'provider-models-request'\n id: string\n payload: {\n providerId: string\n options?: GetModelsOptions\n }\n}\n\nexport interface ToolExecuteRequestMessage {\n type: 'tool-execute-request'\n id: string\n payload: {\n toolId: string\n params: Record<string, unknown>\n /** User ID if the tool is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ActionExecuteRequestMessage {\n type: 'action-execute-request'\n id: string\n payload: {\n actionId: string\n params: Record<string, unknown>\n /** User ID if the action is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ResponseMessage {\n type: 'response'\n id: string\n payload: {\n requestId: string\n success: boolean\n data?: unknown\n error?: string\n }\n}\n\n// ============================================================================\n// Worker → Host Messages\n// ============================================================================\n\nexport type WorkerToHostMessage =\n | ReadyMessage\n | RequestMessage\n | ProviderRegisteredMessage\n | ToolRegisteredMessage\n | ActionRegisteredMessage\n | StreamEventMessage\n | LogMessage\n | ProviderModelsResponseMessage\n | ToolExecuteResponseMessage\n | ActionExecuteResponseMessage\n\nexport interface ReadyMessage {\n type: 'ready'\n}\n\nexport interface RequestMessage {\n type: 'request'\n id: string\n method: RequestMethod\n payload: unknown\n}\n\nexport type RequestMethod =\n | 'network.fetch'\n | 'settings.getAll'\n | 'settings.get'\n | 'settings.set'\n | 'user.getProfile'\n | 'events.emit'\n | 'scheduler.schedule'\n | 'scheduler.cancel'\n | 'chat.appendInstruction'\n | 'database.execute'\n | 'storage.get'\n | 'storage.set'\n | 'storage.delete'\n | 'storage.keys'\n | 'storage.getForUser'\n | 'storage.setForUser'\n | 'storage.deleteForUser'\n | 'storage.keysForUser'\n\nexport interface ProviderRegisteredMessage {\n type: 'provider-registered'\n payload: {\n id: string\n name: string\n }\n}\n\nexport interface ToolRegisteredMessage {\n type: 'tool-registered'\n payload: {\n id: string\n name: string\n description: string\n parameters?: Record<string, unknown>\n }\n}\n\nexport interface ActionRegisteredMessage {\n type: 'action-registered'\n payload: {\n id: string\n }\n}\n\nexport interface StreamEventMessage {\n type: 'stream-event'\n payload: {\n requestId: string\n event: StreamEvent\n }\n}\n\nexport interface ProviderModelsResponseMessage {\n type: 'provider-models-response'\n payload: {\n requestId: string\n models: ModelInfo[]\n error?: string\n }\n}\n\nexport interface ToolExecuteResponseMessage {\n type: 'tool-execute-response'\n payload: {\n requestId: string\n result: ToolResult\n error?: string\n }\n}\n\nexport interface ActionExecuteResponseMessage {\n type: 'action-execute-response'\n payload: {\n requestId: string\n result: ActionResult\n error?: string\n }\n}\n\nexport interface LogMessage {\n type: 'log'\n payload: {\n level: 'debug' | 'info' | 'warn' | 'error'\n message: string\n data?: Record<string, unknown>\n }\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\nexport interface PendingRequest<T = unknown> {\n resolve: (value: T) => void\n reject: (error: Error) => void\n timeout: ReturnType<typeof setTimeout>\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n}\n"],"mappings":"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","names":["module"]}
|
|
1
|
+
{"version":3,"sources":["../src/runtime.ts","../src/messages.ts"],"sourcesContent":["/**\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 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 DatabaseAPI,\n StorageAPI,\n LogAPI,\n AIProvider,\n Tool,\n Action,\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n} from './types.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\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) => 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 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}\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 } catch (error) {\n console.error('Error during deactivation:', error)\n } finally {\n extensionModule = null\n extensionDisposable = null\n extensionContext = 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\nfunction handleSchedulerFire(payload: SchedulerFirePayload): void {\n // Set the userId in context if this is a user-scoped job\n if (extensionContext && payload.userId) {\n ;(extensionContext as { userId?: string }).userId = payload.userId\n }\n\n for (const callback of schedulerCallbacks) {\n try {\n callback(payload)\n } catch (error) {\n console.error('Error in scheduler callback:', error)\n }\n }\n\n // Reset userId after all callbacks\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\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 // Update the extension context with the userId if provided\n if (extensionContext && payload.userId) {\n // Create a new context with the userId for this execution\n ;(extensionContext as { userId?: string }).userId = payload.userId\n }\n\n const result = await tool.execute(payload.params)\n\n // Reset userId after execution\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\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 // Reset userId on error\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\n\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 // Update the extension context with the userId if provided\n if (extensionContext && payload.userId) {\n ;(extensionContext as { userId?: string }).userId = payload.userId\n }\n\n const result = await action.execute(payload.params)\n\n // Reset userId after execution\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\n\n postMessage({\n type: 'action-execute-response',\n payload: {\n requestId,\n result,\n },\n })\n } catch (error) {\n // Reset userId on error\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\n\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 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) => 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 await sendRequest<void>('chat.appendInstruction', message)\n },\n }\n ;(context as { chat: ChatAPI }).chat = chatApi\n }\n\n // Add database API if permitted\n if (hasPermission('database.own')) {\n const databaseApi: DatabaseAPI = {\n async execute<T = unknown>(sql: string, params?: unknown[]): Promise<T[]> {\n return sendRequest<T[]>('database.execute', { sql, params })\n },\n }\n ;(context as { database: DatabaseAPI }).database = databaseApi\n }\n\n // Add storage API if permitted\n if (hasPermission('storage.local')) {\n const storageApi: StorageAPI = {\n // Global/extension-scoped storage\n async get<T>(key: string): Promise<T | undefined> {\n return sendRequest<T | undefined>('storage.get', { key })\n },\n async set(key: string, value: unknown): Promise<void> {\n return sendRequest<void>('storage.set', { key, value })\n },\n async delete(key: string): Promise<void> {\n return sendRequest<void>('storage.delete', { key })\n },\n async keys(): Promise<string[]> {\n return sendRequest<string[]>('storage.keys', {})\n },\n // User-scoped storage\n async getForUser<T>(userId: string, key: string): Promise<T | undefined> {\n return sendRequest<T | undefined>('storage.getForUser', { userId, key })\n },\n async setForUser(userId: string, key: string, value: unknown): Promise<void> {\n return sendRequest<void>('storage.setForUser', { userId, key, value })\n },\n async deleteForUser(userId: string, key: string): Promise<void> {\n return sendRequest<void>('storage.deleteForUser', { userId, key })\n },\n async keysForUser(userId: string): Promise<string[]> {\n return sendRequest<string[]>('storage.keysForUser', { userId })\n },\n }\n ;(context as { storage: StorageAPI }).storage = storageApi\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 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} from './types.js'\n","/**\n * Message protocol between Extension Host and Extension Workers\n */\n\nimport type {\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolResult,\n ActionResult,\n ModelInfo,\n SchedulerFirePayload,\n} from './types.js'\n\n// ============================================================================\n// Host → Worker Messages\n// ============================================================================\n\nexport type HostToWorkerMessage =\n | ActivateMessage\n | DeactivateMessage\n | SettingsChangedMessage\n | SchedulerFireMessage\n | ProviderChatRequestMessage\n | ProviderModelsRequestMessage\n | ToolExecuteRequestMessage\n | ActionExecuteRequestMessage\n | ResponseMessage\n | StreamingFetchChunkMessage\n\nexport interface ActivateMessage {\n type: 'activate'\n id: string\n payload: {\n extensionId: string\n extensionVersion: string\n storagePath: string\n permissions: string[]\n settings: Record<string, unknown>\n }\n}\n\nexport interface DeactivateMessage {\n type: 'deactivate'\n id: string\n}\n\nexport interface SettingsChangedMessage {\n type: 'settings-changed'\n id: string\n payload: {\n key: string\n value: unknown\n }\n}\n\nexport interface SchedulerFireMessage {\n type: 'scheduler-fire'\n id: string\n payload: SchedulerFirePayload\n}\n\nexport interface ProviderChatRequestMessage {\n type: 'provider-chat-request'\n id: string\n payload: {\n providerId: string\n messages: ChatMessage[]\n options: ChatOptions\n }\n}\n\nexport interface ProviderModelsRequestMessage {\n type: 'provider-models-request'\n id: string\n payload: {\n providerId: string\n options?: GetModelsOptions\n }\n}\n\nexport interface ToolExecuteRequestMessage {\n type: 'tool-execute-request'\n id: string\n payload: {\n toolId: string\n params: Record<string, unknown>\n /** User ID if the tool is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ActionExecuteRequestMessage {\n type: 'action-execute-request'\n id: string\n payload: {\n actionId: string\n params: Record<string, unknown>\n /** User ID if the action is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ResponseMessage {\n type: 'response'\n id: string\n payload: {\n requestId: string\n success: boolean\n data?: unknown\n error?: string\n }\n}\n\n/**\n * Message sent from host to worker with streaming fetch data chunks.\n * Used for streaming network responses (e.g., NDJSON streams from Ollama).\n */\nexport interface StreamingFetchChunkMessage {\n type: 'streaming-fetch-chunk'\n id: string\n payload: {\n requestId: string\n chunk: string\n done: boolean\n error?: string\n }\n}\n\n// ============================================================================\n// Worker → Host Messages\n// ============================================================================\n\nexport type WorkerToHostMessage =\n | ReadyMessage\n | RequestMessage\n | ProviderRegisteredMessage\n | ToolRegisteredMessage\n | ActionRegisteredMessage\n | StreamEventMessage\n | LogMessage\n | ProviderModelsResponseMessage\n | ToolExecuteResponseMessage\n | ActionExecuteResponseMessage\n | StreamingFetchAckMessage\n\nexport interface ReadyMessage {\n type: 'ready'\n}\n\n/**\n * Message sent from worker to host to acknowledge receipt of a streaming fetch chunk.\n * This enables backpressure control to prevent unbounded memory growth.\n */\nexport interface StreamingFetchAckMessage {\n type: 'streaming-fetch-ack'\n payload: {\n requestId: string\n }\n}\n\nexport interface RequestMessage {\n type: 'request'\n id: string\n method: RequestMethod\n payload: unknown\n}\n\nexport type RequestMethod =\n | 'network.fetch'\n | 'network.fetch-stream'\n | 'settings.getAll'\n | 'settings.get'\n | 'settings.set'\n | 'user.getProfile'\n | 'events.emit'\n | 'scheduler.schedule'\n | 'scheduler.cancel'\n | 'chat.appendInstruction'\n | 'database.execute'\n | 'storage.get'\n | 'storage.set'\n | 'storage.delete'\n | 'storage.keys'\n | 'storage.getForUser'\n | 'storage.setForUser'\n | 'storage.deleteForUser'\n | 'storage.keysForUser'\n\nexport interface ProviderRegisteredMessage {\n type: 'provider-registered'\n payload: {\n id: string\n name: string\n }\n}\n\nexport interface ToolRegisteredMessage {\n type: 'tool-registered'\n payload: {\n id: string\n name: string\n description: string\n parameters?: Record<string, unknown>\n }\n}\n\nexport interface ActionRegisteredMessage {\n type: 'action-registered'\n payload: {\n id: string\n }\n}\n\nexport interface StreamEventMessage {\n type: 'stream-event'\n payload: {\n requestId: string\n event: StreamEvent\n }\n}\n\nexport interface ProviderModelsResponseMessage {\n type: 'provider-models-response'\n payload: {\n requestId: string\n models: ModelInfo[]\n error?: string\n }\n}\n\nexport interface ToolExecuteResponseMessage {\n type: 'tool-execute-response'\n payload: {\n requestId: string\n result: ToolResult\n error?: string\n }\n}\n\nexport interface ActionExecuteResponseMessage {\n type: 'action-execute-response'\n payload: {\n requestId: string\n result: ActionResult\n error?: string\n }\n}\n\nexport interface LogMessage {\n type: 'log'\n payload: {\n level: 'debug' | 'info' | 'warn' | 'error'\n message: string\n data?: Record<string, unknown>\n }\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\nexport interface PendingRequest<T = unknown> {\n resolve: (value: T) => void\n reject: (error: Error) => void\n timeout: ReturnType<typeof setTimeout>\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n}\n"],"mappings":"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","names":["module"]}
|
package/dist/runtime.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a7 as ExtensionModule } from './types-
|
|
2
|
-
export { a3 as AIProvider, a6 as Action, A as ActionResult, C as ChatMessage, a as ChatOptions, I as Disposable, H as ExtensionContext, G as GetModelsOptions, M as ModelInfo, b as StreamEvent, a5 as Tool, a4 as ToolCall, s as ToolDefinition, T as ToolResult } from './types-
|
|
1
|
+
import { a7 as ExtensionModule } from './types-DjRF9BP3.cjs';
|
|
2
|
+
export { a3 as AIProvider, a6 as Action, A as ActionResult, C as ChatMessage, a as ChatOptions, I as Disposable, H as ExtensionContext, G as GetModelsOptions, M as ModelInfo, b as StreamEvent, a5 as Tool, a4 as ToolCall, s as ToolDefinition, T as ToolResult } from './types-DjRF9BP3.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Extension Runtime - Runs inside the worker
|
package/dist/runtime.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a7 as ExtensionModule } from './types-
|
|
2
|
-
export { a3 as AIProvider, a6 as Action, A as ActionResult, C as ChatMessage, a as ChatOptions, I as Disposable, H as ExtensionContext, G as GetModelsOptions, M as ModelInfo, b as StreamEvent, a5 as Tool, a4 as ToolCall, s as ToolDefinition, T as ToolResult } from './types-
|
|
1
|
+
import { a7 as ExtensionModule } from './types-DjRF9BP3.js';
|
|
2
|
+
export { a3 as AIProvider, a6 as Action, A as ActionResult, C as ChatMessage, a as ChatOptions, I as Disposable, H as ExtensionContext, G as GetModelsOptions, M as ModelInfo, b as StreamEvent, a5 as Tool, a4 as ToolCall, s as ToolDefinition, T as ToolResult } from './types-DjRF9BP3.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Extension Runtime - Runs inside the worker
|
package/dist/runtime.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
__require,
|
|
3
3
|
generateMessageId
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WIDGIYRV.js";
|
|
5
5
|
|
|
6
6
|
// src/runtime.ts
|
|
7
7
|
function getMessagePort() {
|
|
@@ -31,6 +31,7 @@ var registeredTools = /* @__PURE__ */ new Map();
|
|
|
31
31
|
var registeredActions = /* @__PURE__ */ new Map();
|
|
32
32
|
var settingsCallbacks = [];
|
|
33
33
|
var schedulerCallbacks = [];
|
|
34
|
+
var streamingFetchRequests = /* @__PURE__ */ new Map();
|
|
34
35
|
var REQUEST_TIMEOUT = 3e4;
|
|
35
36
|
function postMessage(message) {
|
|
36
37
|
messagePort.postMessage(message);
|
|
@@ -80,7 +81,32 @@ async function handleHostMessage(message) {
|
|
|
80
81
|
case "response":
|
|
81
82
|
handleResponse(message.payload);
|
|
82
83
|
break;
|
|
84
|
+
case "streaming-fetch-chunk":
|
|
85
|
+
handleStreamingFetchChunk(message.payload);
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function handleStreamingFetchChunk(payload) {
|
|
90
|
+
const request = streamingFetchRequests.get(payload.requestId);
|
|
91
|
+
if (!request) return;
|
|
92
|
+
if (payload.error) {
|
|
93
|
+
request.error = payload.error;
|
|
94
|
+
request.done = true;
|
|
95
|
+
} else if (payload.chunk) {
|
|
96
|
+
request.chunks.push(payload.chunk);
|
|
83
97
|
}
|
|
98
|
+
if (payload.done) {
|
|
99
|
+
request.done = true;
|
|
100
|
+
}
|
|
101
|
+
if (request.resolve) {
|
|
102
|
+
const resolve = request.resolve;
|
|
103
|
+
request.resolve = void 0;
|
|
104
|
+
resolve();
|
|
105
|
+
}
|
|
106
|
+
postMessage({
|
|
107
|
+
type: "streaming-fetch-ack",
|
|
108
|
+
payload: { requestId: payload.requestId }
|
|
109
|
+
});
|
|
84
110
|
}
|
|
85
111
|
function handleResponse(payload) {
|
|
86
112
|
const pending = pendingRequests.get(payload.requestId);
|
|
@@ -362,6 +388,44 @@ function buildContext(extensionId, extensionVersion, storagePath, permissions) {
|
|
|
362
388
|
statusText: result.statusText,
|
|
363
389
|
headers: result.headers
|
|
364
390
|
});
|
|
391
|
+
},
|
|
392
|
+
async *fetchStream(url, options) {
|
|
393
|
+
const requestId = generateMessageId();
|
|
394
|
+
const request = {
|
|
395
|
+
chunks: [],
|
|
396
|
+
done: false
|
|
397
|
+
};
|
|
398
|
+
streamingFetchRequests.set(requestId, request);
|
|
399
|
+
postMessage({
|
|
400
|
+
type: "request",
|
|
401
|
+
id: requestId,
|
|
402
|
+
method: "network.fetch-stream",
|
|
403
|
+
payload: { url, options, requestId }
|
|
404
|
+
});
|
|
405
|
+
try {
|
|
406
|
+
while (!request.done) {
|
|
407
|
+
await new Promise((resolve) => {
|
|
408
|
+
const resolver = () => {
|
|
409
|
+
if (request.resolve === resolver) {
|
|
410
|
+
request.resolve = void 0;
|
|
411
|
+
}
|
|
412
|
+
resolve();
|
|
413
|
+
};
|
|
414
|
+
request.resolve = resolver;
|
|
415
|
+
if (request.chunks.length > 0 || request.done) {
|
|
416
|
+
resolver();
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
if (request.error) {
|
|
420
|
+
throw new Error(request.error);
|
|
421
|
+
}
|
|
422
|
+
while (request.chunks.length > 0) {
|
|
423
|
+
yield request.chunks.shift();
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
} finally {
|
|
427
|
+
streamingFetchRequests.delete(requestId);
|
|
428
|
+
}
|
|
365
429
|
}
|
|
366
430
|
};
|
|
367
431
|
context.network = networkApi;
|
package/dist/runtime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runtime.ts"],"sourcesContent":["/**\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 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 DatabaseAPI,\n StorageAPI,\n LogAPI,\n AIProvider,\n Tool,\n Action,\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n} from './types.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\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) => void> = []\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 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}\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 } catch (error) {\n console.error('Error during deactivation:', error)\n } finally {\n extensionModule = null\n extensionDisposable = null\n extensionContext = 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\nfunction handleSchedulerFire(payload: SchedulerFirePayload): void {\n // Set the userId in context if this is a user-scoped job\n if (extensionContext && payload.userId) {\n ;(extensionContext as { userId?: string }).userId = payload.userId\n }\n\n for (const callback of schedulerCallbacks) {\n try {\n callback(payload)\n } catch (error) {\n console.error('Error in scheduler callback:', error)\n }\n }\n\n // Reset userId after all callbacks\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\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 // Update the extension context with the userId if provided\n if (extensionContext && payload.userId) {\n // Create a new context with the userId for this execution\n ;(extensionContext as { userId?: string }).userId = payload.userId\n }\n\n const result = await tool.execute(payload.params)\n\n // Reset userId after execution\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\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 // Reset userId on error\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\n\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 // Update the extension context with the userId if provided\n if (extensionContext && payload.userId) {\n ;(extensionContext as { userId?: string }).userId = payload.userId\n }\n\n const result = await action.execute(payload.params)\n\n // Reset userId after execution\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\n\n postMessage({\n type: 'action-execute-response',\n payload: {\n requestId,\n result,\n },\n })\n } catch (error) {\n // Reset userId on error\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\n\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 ;(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 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) => 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 await sendRequest<void>('chat.appendInstruction', message)\n },\n }\n ;(context as { chat: ChatAPI }).chat = chatApi\n }\n\n // Add database API if permitted\n if (hasPermission('database.own')) {\n const databaseApi: DatabaseAPI = {\n async execute<T = unknown>(sql: string, params?: unknown[]): Promise<T[]> {\n return sendRequest<T[]>('database.execute', { sql, params })\n },\n }\n ;(context as { database: DatabaseAPI }).database = databaseApi\n }\n\n // Add storage API if permitted\n if (hasPermission('storage.local')) {\n const storageApi: StorageAPI = {\n // Global/extension-scoped storage\n async get<T>(key: string): Promise<T | undefined> {\n return sendRequest<T | undefined>('storage.get', { key })\n },\n async set(key: string, value: unknown): Promise<void> {\n return sendRequest<void>('storage.set', { key, value })\n },\n async delete(key: string): Promise<void> {\n return sendRequest<void>('storage.delete', { key })\n },\n async keys(): Promise<string[]> {\n return sendRequest<string[]>('storage.keys', {})\n },\n // User-scoped storage\n async getForUser<T>(userId: string, key: string): Promise<T | undefined> {\n return sendRequest<T | undefined>('storage.getForUser', { userId, key })\n },\n async setForUser(userId: string, key: string, value: unknown): Promise<void> {\n return sendRequest<void>('storage.setForUser', { userId, key, value })\n },\n async deleteForUser(userId: string, key: string): Promise<void> {\n return sendRequest<void>('storage.deleteForUser', { userId, key })\n },\n async keysForUser(userId: string): Promise<string[]> {\n return sendRequest<string[]>('storage.keysForUser', { userId })\n },\n }\n ;(context as { storage: StorageAPI }).storage = storageApi\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 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} from './types.js'\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/runtime.ts"],"sourcesContent":["/**\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 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 DatabaseAPI,\n StorageAPI,\n LogAPI,\n AIProvider,\n Tool,\n Action,\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n} from './types.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\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) => 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 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}\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 } catch (error) {\n console.error('Error during deactivation:', error)\n } finally {\n extensionModule = null\n extensionDisposable = null\n extensionContext = 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\nfunction handleSchedulerFire(payload: SchedulerFirePayload): void {\n // Set the userId in context if this is a user-scoped job\n if (extensionContext && payload.userId) {\n ;(extensionContext as { userId?: string }).userId = payload.userId\n }\n\n for (const callback of schedulerCallbacks) {\n try {\n callback(payload)\n } catch (error) {\n console.error('Error in scheduler callback:', error)\n }\n }\n\n // Reset userId after all callbacks\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\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 // Update the extension context with the userId if provided\n if (extensionContext && payload.userId) {\n // Create a new context with the userId for this execution\n ;(extensionContext as { userId?: string }).userId = payload.userId\n }\n\n const result = await tool.execute(payload.params)\n\n // Reset userId after execution\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\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 // Reset userId on error\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\n\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 // Update the extension context with the userId if provided\n if (extensionContext && payload.userId) {\n ;(extensionContext as { userId?: string }).userId = payload.userId\n }\n\n const result = await action.execute(payload.params)\n\n // Reset userId after execution\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\n\n postMessage({\n type: 'action-execute-response',\n payload: {\n requestId,\n result,\n },\n })\n } catch (error) {\n // Reset userId on error\n if (extensionContext) {\n ;(extensionContext as { userId?: string }).userId = undefined\n }\n\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 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) => 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 await sendRequest<void>('chat.appendInstruction', message)\n },\n }\n ;(context as { chat: ChatAPI }).chat = chatApi\n }\n\n // Add database API if permitted\n if (hasPermission('database.own')) {\n const databaseApi: DatabaseAPI = {\n async execute<T = unknown>(sql: string, params?: unknown[]): Promise<T[]> {\n return sendRequest<T[]>('database.execute', { sql, params })\n },\n }\n ;(context as { database: DatabaseAPI }).database = databaseApi\n }\n\n // Add storage API if permitted\n if (hasPermission('storage.local')) {\n const storageApi: StorageAPI = {\n // Global/extension-scoped storage\n async get<T>(key: string): Promise<T | undefined> {\n return sendRequest<T | undefined>('storage.get', { key })\n },\n async set(key: string, value: unknown): Promise<void> {\n return sendRequest<void>('storage.set', { key, value })\n },\n async delete(key: string): Promise<void> {\n return sendRequest<void>('storage.delete', { key })\n },\n async keys(): Promise<string[]> {\n return sendRequest<string[]>('storage.keys', {})\n },\n // User-scoped storage\n async getForUser<T>(userId: string, key: string): Promise<T | undefined> {\n return sendRequest<T | undefined>('storage.getForUser', { userId, key })\n },\n async setForUser(userId: string, key: string, value: unknown): Promise<void> {\n return sendRequest<void>('storage.setForUser', { userId, key, value })\n },\n async deleteForUser(userId: string, key: string): Promise<void> {\n return sendRequest<void>('storage.deleteForUser', { userId, key })\n },\n async keysForUser(userId: string): Promise<string[]> {\n return sendRequest<string[]>('storage.keysForUser', { userId })\n },\n }\n ;(context as { storage: StorageAPI }).storage = storageApi\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 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} from './types.js'\n"],"mappings":"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","names":[]}
|
|
@@ -735,6 +735,26 @@ interface NetworkAPI {
|
|
|
735
735
|
* Fetch a URL (permissions are enforced by host)
|
|
736
736
|
*/
|
|
737
737
|
fetch(url: string, options?: RequestInit): Promise<Response>;
|
|
738
|
+
/**
|
|
739
|
+
* Streaming fetch for responses like NDJSON or SSE.
|
|
740
|
+
* Yields text chunks as they arrive from the server.
|
|
741
|
+
*
|
|
742
|
+
* @throws {Error} If the request fails or encounters a network error.
|
|
743
|
+
* The error message will contain details about the failure.
|
|
744
|
+
*
|
|
745
|
+
* @example
|
|
746
|
+
* ```typescript
|
|
747
|
+
* try {
|
|
748
|
+
* for await (const chunk of context.network.fetchStream(url, options)) {
|
|
749
|
+
* // Process each chunk (may contain partial lines)
|
|
750
|
+
* buffer += chunk
|
|
751
|
+
* }
|
|
752
|
+
* } catch (error) {
|
|
753
|
+
* console.error('Streaming fetch failed:', error.message)
|
|
754
|
+
* }
|
|
755
|
+
* ```
|
|
756
|
+
*/
|
|
757
|
+
fetchStream(url: string, options?: RequestInit): AsyncGenerator<string, void, unknown>;
|
|
738
758
|
}
|
|
739
759
|
/**
|
|
740
760
|
* Settings API for reading/writing extension settings
|
|
@@ -735,6 +735,26 @@ interface NetworkAPI {
|
|
|
735
735
|
* Fetch a URL (permissions are enforced by host)
|
|
736
736
|
*/
|
|
737
737
|
fetch(url: string, options?: RequestInit): Promise<Response>;
|
|
738
|
+
/**
|
|
739
|
+
* Streaming fetch for responses like NDJSON or SSE.
|
|
740
|
+
* Yields text chunks as they arrive from the server.
|
|
741
|
+
*
|
|
742
|
+
* @throws {Error} If the request fails or encounters a network error.
|
|
743
|
+
* The error message will contain details about the failure.
|
|
744
|
+
*
|
|
745
|
+
* @example
|
|
746
|
+
* ```typescript
|
|
747
|
+
* try {
|
|
748
|
+
* for await (const chunk of context.network.fetchStream(url, options)) {
|
|
749
|
+
* // Process each chunk (may contain partial lines)
|
|
750
|
+
* buffer += chunk
|
|
751
|
+
* }
|
|
752
|
+
* } catch (error) {
|
|
753
|
+
* console.error('Streaming fetch failed:', error.message)
|
|
754
|
+
* }
|
|
755
|
+
* ```
|
|
756
|
+
*/
|
|
757
|
+
fetchStream(url: string, options?: RequestInit): AsyncGenerator<string, void, unknown>;
|
|
738
758
|
}
|
|
739
759
|
/**
|
|
740
760
|
* Settings API for reading/writing extension settings
|
package/package.json
CHANGED
package/src/messages.ts
CHANGED
|
@@ -27,6 +27,7 @@ export type HostToWorkerMessage =
|
|
|
27
27
|
| ToolExecuteRequestMessage
|
|
28
28
|
| ActionExecuteRequestMessage
|
|
29
29
|
| ResponseMessage
|
|
30
|
+
| StreamingFetchChunkMessage
|
|
30
31
|
|
|
31
32
|
export interface ActivateMessage {
|
|
32
33
|
type: 'activate'
|
|
@@ -112,6 +113,21 @@ export interface ResponseMessage {
|
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Message sent from host to worker with streaming fetch data chunks.
|
|
118
|
+
* Used for streaming network responses (e.g., NDJSON streams from Ollama).
|
|
119
|
+
*/
|
|
120
|
+
export interface StreamingFetchChunkMessage {
|
|
121
|
+
type: 'streaming-fetch-chunk'
|
|
122
|
+
id: string
|
|
123
|
+
payload: {
|
|
124
|
+
requestId: string
|
|
125
|
+
chunk: string
|
|
126
|
+
done: boolean
|
|
127
|
+
error?: string
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
115
131
|
// ============================================================================
|
|
116
132
|
// Worker → Host Messages
|
|
117
133
|
// ============================================================================
|
|
@@ -127,11 +143,23 @@ export type WorkerToHostMessage =
|
|
|
127
143
|
| ProviderModelsResponseMessage
|
|
128
144
|
| ToolExecuteResponseMessage
|
|
129
145
|
| ActionExecuteResponseMessage
|
|
146
|
+
| StreamingFetchAckMessage
|
|
130
147
|
|
|
131
148
|
export interface ReadyMessage {
|
|
132
149
|
type: 'ready'
|
|
133
150
|
}
|
|
134
151
|
|
|
152
|
+
/**
|
|
153
|
+
* Message sent from worker to host to acknowledge receipt of a streaming fetch chunk.
|
|
154
|
+
* This enables backpressure control to prevent unbounded memory growth.
|
|
155
|
+
*/
|
|
156
|
+
export interface StreamingFetchAckMessage {
|
|
157
|
+
type: 'streaming-fetch-ack'
|
|
158
|
+
payload: {
|
|
159
|
+
requestId: string
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
135
163
|
export interface RequestMessage {
|
|
136
164
|
type: 'request'
|
|
137
165
|
id: string
|
|
@@ -141,6 +169,7 @@ export interface RequestMessage {
|
|
|
141
169
|
|
|
142
170
|
export type RequestMethod =
|
|
143
171
|
| 'network.fetch'
|
|
172
|
+
| 'network.fetch-stream'
|
|
144
173
|
| 'settings.getAll'
|
|
145
174
|
| 'settings.get'
|
|
146
175
|
| 'settings.set'
|
package/src/runtime.ts
CHANGED
|
@@ -95,6 +95,18 @@ const registeredActions = new Map<string, Action>()
|
|
|
95
95
|
const settingsCallbacks: Array<(key: string, value: unknown) => void> = []
|
|
96
96
|
const schedulerCallbacks: Array<(payload: SchedulerFirePayload) => void> = []
|
|
97
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Tracking for streaming fetch requests.
|
|
100
|
+
* Each request stores incoming chunks and signals when new data arrives.
|
|
101
|
+
*/
|
|
102
|
+
interface StreamingFetchRequest {
|
|
103
|
+
chunks: string[]
|
|
104
|
+
done: boolean
|
|
105
|
+
error?: string
|
|
106
|
+
resolve?: () => void
|
|
107
|
+
}
|
|
108
|
+
const streamingFetchRequests = new Map<string, StreamingFetchRequest>()
|
|
109
|
+
|
|
98
110
|
const REQUEST_TIMEOUT = 30000 // 30 seconds
|
|
99
111
|
|
|
100
112
|
// ============================================================================
|
|
@@ -171,9 +183,50 @@ async function handleHostMessage(message: HostToWorkerMessage): Promise<void> {
|
|
|
171
183
|
case 'response':
|
|
172
184
|
handleResponse(message.payload)
|
|
173
185
|
break
|
|
186
|
+
|
|
187
|
+
case 'streaming-fetch-chunk':
|
|
188
|
+
handleStreamingFetchChunk(message.payload)
|
|
189
|
+
break
|
|
174
190
|
}
|
|
175
191
|
}
|
|
176
192
|
|
|
193
|
+
/**
|
|
194
|
+
* Handle incoming streaming fetch chunks from the host
|
|
195
|
+
*/
|
|
196
|
+
function handleStreamingFetchChunk(payload: {
|
|
197
|
+
requestId: string
|
|
198
|
+
chunk: string
|
|
199
|
+
done: boolean
|
|
200
|
+
error?: string
|
|
201
|
+
}): void {
|
|
202
|
+
const request = streamingFetchRequests.get(payload.requestId)
|
|
203
|
+
if (!request) return
|
|
204
|
+
|
|
205
|
+
if (payload.error) {
|
|
206
|
+
request.error = payload.error
|
|
207
|
+
request.done = true
|
|
208
|
+
} else if (payload.chunk) {
|
|
209
|
+
request.chunks.push(payload.chunk)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (payload.done) {
|
|
213
|
+
request.done = true
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Signal that new data is available
|
|
217
|
+
if (request.resolve) {
|
|
218
|
+
const resolve = request.resolve
|
|
219
|
+
request.resolve = undefined
|
|
220
|
+
resolve()
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Send acknowledgment for backpressure control
|
|
224
|
+
postMessage({
|
|
225
|
+
type: 'streaming-fetch-ack',
|
|
226
|
+
payload: { requestId: payload.requestId },
|
|
227
|
+
})
|
|
228
|
+
}
|
|
229
|
+
|
|
177
230
|
function handleResponse(payload: { requestId: string; success: boolean; data?: unknown; error?: string }): void {
|
|
178
231
|
const pending = pendingRequests.get(payload.requestId)
|
|
179
232
|
if (!pending) return
|
|
@@ -532,6 +585,61 @@ function buildContext(
|
|
|
532
585
|
headers: result.headers,
|
|
533
586
|
})
|
|
534
587
|
},
|
|
588
|
+
|
|
589
|
+
async *fetchStream(url: string, options?: RequestInit): AsyncGenerator<string, void, unknown> {
|
|
590
|
+
const requestId = generateMessageId()
|
|
591
|
+
|
|
592
|
+
// Set up streaming request tracking
|
|
593
|
+
const request: StreamingFetchRequest = {
|
|
594
|
+
chunks: [],
|
|
595
|
+
done: false,
|
|
596
|
+
}
|
|
597
|
+
streamingFetchRequests.set(requestId, request)
|
|
598
|
+
|
|
599
|
+
// Send the streaming fetch request to the host
|
|
600
|
+
postMessage({
|
|
601
|
+
type: 'request',
|
|
602
|
+
id: requestId,
|
|
603
|
+
method: 'network.fetch-stream',
|
|
604
|
+
payload: { url, options, requestId },
|
|
605
|
+
})
|
|
606
|
+
|
|
607
|
+
try {
|
|
608
|
+
// Yield chunks as they arrive
|
|
609
|
+
while (!request.done) {
|
|
610
|
+
// Wait for new data
|
|
611
|
+
await new Promise<void>((resolve) => {
|
|
612
|
+
const resolver = () => {
|
|
613
|
+
// Clear the stored resolver before resolving to avoid
|
|
614
|
+
// stale callbacks being invoked for a new wait iteration.
|
|
615
|
+
if (request.resolve === resolver) {
|
|
616
|
+
request.resolve = undefined
|
|
617
|
+
}
|
|
618
|
+
resolve()
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
request.resolve = resolver
|
|
622
|
+
|
|
623
|
+
// Check if we already have data or completion
|
|
624
|
+
if (request.chunks.length > 0 || request.done) {
|
|
625
|
+
resolver()
|
|
626
|
+
}
|
|
627
|
+
})
|
|
628
|
+
|
|
629
|
+
// Check for errors first, before yielding any chunks
|
|
630
|
+
if (request.error) {
|
|
631
|
+
throw new Error(request.error)
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// Yield all available chunks
|
|
635
|
+
while (request.chunks.length > 0) {
|
|
636
|
+
yield request.chunks.shift()!
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
} finally {
|
|
640
|
+
streamingFetchRequests.delete(requestId)
|
|
641
|
+
}
|
|
642
|
+
},
|
|
535
643
|
}
|
|
536
644
|
;(context as { network: NetworkAPI }).network = networkApi
|
|
537
645
|
}
|
package/src/types.ts
CHANGED
|
@@ -517,6 +517,27 @@ export interface NetworkAPI {
|
|
|
517
517
|
* Fetch a URL (permissions are enforced by host)
|
|
518
518
|
*/
|
|
519
519
|
fetch(url: string, options?: RequestInit): Promise<Response>
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* Streaming fetch for responses like NDJSON or SSE.
|
|
523
|
+
* Yields text chunks as they arrive from the server.
|
|
524
|
+
*
|
|
525
|
+
* @throws {Error} If the request fails or encounters a network error.
|
|
526
|
+
* The error message will contain details about the failure.
|
|
527
|
+
*
|
|
528
|
+
* @example
|
|
529
|
+
* ```typescript
|
|
530
|
+
* try {
|
|
531
|
+
* for await (const chunk of context.network.fetchStream(url, options)) {
|
|
532
|
+
* // Process each chunk (may contain partial lines)
|
|
533
|
+
* buffer += chunk
|
|
534
|
+
* }
|
|
535
|
+
* } catch (error) {
|
|
536
|
+
* console.error('Streaming fetch failed:', error.message)
|
|
537
|
+
* }
|
|
538
|
+
* ```
|
|
539
|
+
*/
|
|
540
|
+
fetchStream(url: string, options?: RequestInit): AsyncGenerator<string, void, unknown>
|
|
520
541
|
}
|
|
521
542
|
|
|
522
543
|
/**
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/messages.ts"],"sourcesContent":["/**\n * Message protocol between Extension Host and Extension Workers\n */\n\nimport type {\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolResult,\n ActionResult,\n ModelInfo,\n SchedulerFirePayload,\n} from './types.js'\n\n// ============================================================================\n// Host → Worker Messages\n// ============================================================================\n\nexport type HostToWorkerMessage =\n | ActivateMessage\n | DeactivateMessage\n | SettingsChangedMessage\n | SchedulerFireMessage\n | ProviderChatRequestMessage\n | ProviderModelsRequestMessage\n | ToolExecuteRequestMessage\n | ActionExecuteRequestMessage\n | ResponseMessage\n\nexport interface ActivateMessage {\n type: 'activate'\n id: string\n payload: {\n extensionId: string\n extensionVersion: string\n storagePath: string\n permissions: string[]\n settings: Record<string, unknown>\n }\n}\n\nexport interface DeactivateMessage {\n type: 'deactivate'\n id: string\n}\n\nexport interface SettingsChangedMessage {\n type: 'settings-changed'\n id: string\n payload: {\n key: string\n value: unknown\n }\n}\n\nexport interface SchedulerFireMessage {\n type: 'scheduler-fire'\n id: string\n payload: SchedulerFirePayload\n}\n\nexport interface ProviderChatRequestMessage {\n type: 'provider-chat-request'\n id: string\n payload: {\n providerId: string\n messages: ChatMessage[]\n options: ChatOptions\n }\n}\n\nexport interface ProviderModelsRequestMessage {\n type: 'provider-models-request'\n id: string\n payload: {\n providerId: string\n options?: GetModelsOptions\n }\n}\n\nexport interface ToolExecuteRequestMessage {\n type: 'tool-execute-request'\n id: string\n payload: {\n toolId: string\n params: Record<string, unknown>\n /** User ID if the tool is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ActionExecuteRequestMessage {\n type: 'action-execute-request'\n id: string\n payload: {\n actionId: string\n params: Record<string, unknown>\n /** User ID if the action is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ResponseMessage {\n type: 'response'\n id: string\n payload: {\n requestId: string\n success: boolean\n data?: unknown\n error?: string\n }\n}\n\n// ============================================================================\n// Worker → Host Messages\n// ============================================================================\n\nexport type WorkerToHostMessage =\n | ReadyMessage\n | RequestMessage\n | ProviderRegisteredMessage\n | ToolRegisteredMessage\n | ActionRegisteredMessage\n | StreamEventMessage\n | LogMessage\n | ProviderModelsResponseMessage\n | ToolExecuteResponseMessage\n | ActionExecuteResponseMessage\n\nexport interface ReadyMessage {\n type: 'ready'\n}\n\nexport interface RequestMessage {\n type: 'request'\n id: string\n method: RequestMethod\n payload: unknown\n}\n\nexport type RequestMethod =\n | 'network.fetch'\n | 'settings.getAll'\n | 'settings.get'\n | 'settings.set'\n | 'user.getProfile'\n | 'events.emit'\n | 'scheduler.schedule'\n | 'scheduler.cancel'\n | 'chat.appendInstruction'\n | 'database.execute'\n | 'storage.get'\n | 'storage.set'\n | 'storage.delete'\n | 'storage.keys'\n | 'storage.getForUser'\n | 'storage.setForUser'\n | 'storage.deleteForUser'\n | 'storage.keysForUser'\n\nexport interface ProviderRegisteredMessage {\n type: 'provider-registered'\n payload: {\n id: string\n name: string\n }\n}\n\nexport interface ToolRegisteredMessage {\n type: 'tool-registered'\n payload: {\n id: string\n name: string\n description: string\n parameters?: Record<string, unknown>\n }\n}\n\nexport interface ActionRegisteredMessage {\n type: 'action-registered'\n payload: {\n id: string\n }\n}\n\nexport interface StreamEventMessage {\n type: 'stream-event'\n payload: {\n requestId: string\n event: StreamEvent\n }\n}\n\nexport interface ProviderModelsResponseMessage {\n type: 'provider-models-response'\n payload: {\n requestId: string\n models: ModelInfo[]\n error?: string\n }\n}\n\nexport interface ToolExecuteResponseMessage {\n type: 'tool-execute-response'\n payload: {\n requestId: string\n result: ToolResult\n error?: string\n }\n}\n\nexport interface ActionExecuteResponseMessage {\n type: 'action-execute-response'\n payload: {\n requestId: string\n result: ActionResult\n error?: string\n }\n}\n\nexport interface LogMessage {\n type: 'log'\n payload: {\n level: 'debug' | 'info' | 'warn' | 'error'\n message: string\n data?: Record<string, unknown>\n }\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\nexport interface PendingRequest<T = unknown> {\n resolve: (value: T) => void\n reject: (error: Error) => void\n timeout: ReturnType<typeof setTimeout>\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n}\n"],"mappings":";;;;;;;;AAmPO,SAAS,oBAA4B;AAC1C,SAAO,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACjE;","names":[]}
|