@stina/extension-api 1.6.0 → 1.7.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.
Files changed (39) hide show
  1. package/dist/{chunk-3Q3YXWOH.js → chunk-S3YP4QPF.js} +1 -1
  2. package/dist/{chunk-3Q3YXWOH.js.map → chunk-S3YP4QPF.js.map} +1 -1
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +12 -4
  5. package/dist/index.d.ts +12 -4
  6. package/dist/index.js +1 -1
  7. package/dist/runtime.cjs +24 -6
  8. package/dist/runtime.cjs.map +1 -1
  9. package/dist/runtime.d.cts +2 -2
  10. package/dist/runtime.d.ts +2 -2
  11. package/dist/runtime.js +25 -7
  12. package/dist/runtime.js.map +1 -1
  13. package/dist/schemas/index.cjs +26 -2
  14. package/dist/schemas/index.cjs.map +1 -1
  15. package/dist/schemas/index.d.cts +91 -5
  16. package/dist/schemas/index.d.ts +91 -5
  17. package/dist/schemas/index.js +22 -2
  18. package/dist/schemas/index.js.map +1 -1
  19. package/dist/{types.tools-R0xGhiBa.d.cts → types.tools-DcFBsfRV.d.cts} +105 -1
  20. package/dist/{types.tools-R0xGhiBa.d.ts → types.tools-DcFBsfRV.d.ts} +105 -1
  21. package/package.json +1 -1
  22. package/schema/extension-manifest.schema.json +39 -0
  23. package/src/background.test.ts +33 -0
  24. package/src/background.ts +9 -0
  25. package/src/index.ts +5 -0
  26. package/src/messages.ts +3 -0
  27. package/src/runtime/accountsApi.ts +26 -0
  28. package/src/runtime/executionContext.test.ts +46 -4
  29. package/src/runtime/executionContext.ts +10 -4
  30. package/src/runtime/index.ts +1 -0
  31. package/src/runtime.ts +15 -3
  32. package/src/schemas/accounts.schema.test.ts +58 -0
  33. package/src/schemas/contributions.schema.ts +48 -0
  34. package/src/schemas/index.ts +6 -0
  35. package/src/schemas/permissions.schema.ts +2 -0
  36. package/src/types.context.ts +68 -0
  37. package/src/types.contributions.ts +47 -0
  38. package/src/types.permissions.ts +8 -0
  39. package/src/types.ts +6 -0
@@ -6,4 +6,4 @@ function generateMessageId() {
6
6
  export {
7
7
  generateMessageId
8
8
  };
9
- //# sourceMappingURL=chunk-3Q3YXWOH.js.map
9
+ //# sourceMappingURL=chunk-S3YP4QPF.js.map
@@ -1 +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 VoiceSessionOptions,\n VoiceSessionDescriptor,\n} from './types.js'\n\n// ============================================================================\n// Host → Worker Messages\n// ============================================================================\n\nexport type HostToWorkerMessage =\n | ActivateMessage\n | DeactivateMessage\n | SettingsChangedMessage\n | SchedulerFireMessage\n | ProviderChatRequestMessage\n | ProviderModelsRequestMessage\n | ProviderVoiceSessionRequestMessage\n | ToolExecuteRequestMessage\n | ActionExecuteRequestMessage\n | ResponseMessage\n | StreamingFetchChunkMessage\n | BackgroundTaskStartMessage\n | BackgroundTaskStopMessage\n\nexport interface ActivateMessage {\n type: 'activate'\n id: string\n payload: {\n extensionId: string\n extensionVersion: string\n storagePath: string\n permissions: string[]\n settings: Record<string, unknown>\n }\n}\n\nexport interface DeactivateMessage {\n type: 'deactivate'\n id: string\n}\n\nexport interface SettingsChangedMessage {\n type: 'settings-changed'\n id: string\n payload: {\n key: string\n value: unknown\n }\n}\n\nexport interface SchedulerFireMessage {\n type: 'scheduler-fire'\n id: string\n payload: SchedulerFirePayload\n}\n\nexport interface ProviderChatRequestMessage {\n type: 'provider-chat-request'\n id: string\n payload: {\n providerId: string\n messages: ChatMessage[]\n options: ChatOptions\n }\n}\n\nexport interface ProviderModelsRequestMessage {\n type: 'provider-models-request'\n id: string\n payload: {\n providerId: string\n options?: GetModelsOptions\n }\n}\n\nexport interface ProviderVoiceSessionRequestMessage {\n type: 'provider-voice-session-request'\n id: string\n payload: {\n providerId: string\n /**\n * `signal` is dropped on the way across: an AbortSignal cannot be\n * structured-cloned into a worker. Cancellation is handled by the host\n * rejecting the pending request instead.\n */\n options: Omit<VoiceSessionOptions, 'signal'>\n }\n}\n\nexport interface ToolExecuteRequestMessage {\n type: 'tool-execute-request'\n id: string\n payload: {\n toolId: string\n params: Record<string, unknown>\n /** User ID if the tool is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ActionExecuteRequestMessage {\n type: 'action-execute-request'\n id: string\n payload: {\n actionId: string\n params: Record<string, unknown>\n /** User ID if the action is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ResponseMessage {\n type: 'response'\n id: string\n payload: {\n requestId: string\n success: boolean\n data?: unknown\n error?: string\n }\n}\n\n/**\n * Message sent from host to worker with streaming fetch data chunks.\n * Used for streaming network responses (e.g., NDJSON streams from Ollama).\n */\nexport interface StreamingFetchChunkMessage {\n type: 'streaming-fetch-chunk'\n id: string\n payload: {\n requestId: string\n chunk: string\n done: boolean\n error?: string\n }\n}\n\n/**\n * Message sent from host to worker to start a registered background task.\n */\nexport interface BackgroundTaskStartMessage {\n type: 'background-task-start'\n id: string\n payload: {\n taskId: string\n }\n}\n\n/**\n * Message sent from host to worker to stop a running background task.\n */\nexport interface BackgroundTaskStopMessage {\n type: 'background-task-stop'\n id: string\n payload: {\n taskId: string\n }\n}\n\n// ============================================================================\n// Worker → Host Messages\n// ============================================================================\n\nexport type WorkerToHostMessage =\n | ReadyMessage\n | RequestMessage\n | ProviderRegisteredMessage\n | ToolRegisteredMessage\n | ActionRegisteredMessage\n | StreamEventMessage\n | LogMessage\n | ProviderModelsResponseMessage\n | ProviderVoiceSessionResponseMessage\n | ToolExecuteResponseMessage\n | ActionExecuteResponseMessage\n | StreamingFetchAckMessage\n | BackgroundTaskRegisteredMessage\n | BackgroundTaskStatusMessage\n | BackgroundTaskHealthMessage\n\nexport interface ReadyMessage {\n type: 'ready'\n}\n\n/**\n * Message sent from worker to host to acknowledge receipt of a streaming fetch chunk.\n * This enables backpressure control to prevent unbounded memory growth.\n */\nexport interface StreamingFetchAckMessage {\n type: 'streaming-fetch-ack'\n payload: {\n requestId: string\n }\n}\n\nexport interface RequestMessage {\n type: 'request'\n id: string\n method: RequestMethod\n payload: unknown\n}\n\nexport type RequestMethod =\n | 'network.fetch'\n | 'network.fetch-stream'\n | 'settings.getAll'\n | 'settings.get'\n | 'settings.set'\n | 'user.getProfile'\n | 'user.listIds'\n | 'events.emit'\n | 'scheduler.schedule'\n | 'scheduler.cancel'\n | 'scheduler.reportFireResult'\n | 'chat.appendInstruction'\n | 'database.execute'\n // Simple key-value storage methods\n | 'storage.set'\n | 'storage.keys'\n | 'storage.setForUser'\n | 'storage.keysForUser'\n // Collection-based storage methods\n | 'storage.put'\n | 'storage.get'\n | 'storage.delete'\n | 'storage.find'\n | 'storage.findOne'\n | 'storage.count'\n | 'storage.putMany'\n | 'storage.deleteMany'\n | 'storage.dropCollection'\n | 'storage.listCollections'\n | 'storage.putForUser'\n | 'storage.getForUser'\n | 'storage.deleteForUser'\n | 'storage.findForUser'\n | 'storage.findOneForUser'\n | 'storage.countForUser'\n | 'storage.putManyForUser'\n | 'storage.deleteManyForUser'\n | 'storage.dropCollectionForUser'\n | 'storage.listCollectionsForUser'\n // Secrets methods\n | 'secrets.set'\n | 'secrets.get'\n | 'secrets.delete'\n | 'secrets.list'\n | 'secrets.setForUser'\n | 'secrets.getForUser'\n | 'secrets.deleteForUser'\n | 'secrets.listForUser'\n // Tools cross-extension methods\n | 'tools.list'\n | 'tools.execute'\n // Attachments\n | 'attachments.read'\n\nexport interface ProviderRegisteredMessage {\n type: 'provider-registered'\n payload: {\n id: string\n name: string\n }\n}\n\nexport interface ToolRegisteredMessage {\n type: 'tool-registered'\n payload: {\n id: string\n name: string\n description: string\n parameters?: Record<string, unknown>\n }\n}\n\nexport interface ActionRegisteredMessage {\n type: 'action-registered'\n payload: {\n id: string\n }\n}\n\nexport interface StreamEventMessage {\n type: 'stream-event'\n payload: {\n requestId: string\n event: StreamEvent\n }\n}\n\nexport interface ProviderModelsResponseMessage {\n type: 'provider-models-response'\n payload: {\n requestId: string\n models: ModelInfo[]\n error?: string\n }\n}\n\nexport interface ProviderVoiceSessionResponseMessage {\n type: 'provider-voice-session-response'\n payload: {\n requestId: string\n /** Absent when `error` is set. */\n descriptor?: VoiceSessionDescriptor\n error?: string\n }\n}\n\nexport interface ToolExecuteResponseMessage {\n type: 'tool-execute-response'\n payload: {\n requestId: string\n result: ToolResult\n error?: string\n }\n}\n\nexport interface ActionExecuteResponseMessage {\n type: 'action-execute-response'\n payload: {\n requestId: string\n result: ActionResult\n error?: string\n }\n}\n\nexport interface LogMessage {\n type: 'log'\n payload: {\n level: 'debug' | 'info' | 'warn' | 'error'\n message: string\n data?: Record<string, unknown>\n }\n}\n\n/**\n * Message sent from worker to host when a background task is registered.\n */\nexport interface BackgroundTaskRegisteredMessage {\n type: 'background-task-registered'\n payload: {\n taskId: string\n name: string\n userId: string\n restartPolicy: {\n type: 'always' | 'on-failure' | 'never'\n maxRestarts?: number\n initialDelayMs?: number\n maxDelayMs?: number\n backoffMultiplier?: number\n }\n payload?: Record<string, unknown>\n }\n}\n\n/**\n * Message sent from worker to host with background task status updates.\n */\nexport interface BackgroundTaskStatusMessage {\n type: 'background-task-status'\n payload: {\n taskId: string\n status: 'running' | 'stopped' | 'completed' | 'failed'\n error?: string\n }\n}\n\n/**\n * Message sent from worker to host with background task health reports.\n */\nexport interface BackgroundTaskHealthMessage {\n type: 'background-task-health'\n payload: {\n taskId: string\n status: string\n timestamp: string\n }\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\nexport interface PendingRequest<T = unknown> {\n resolve: (value: T) => void\n reject: (error: Error) => void\n timeout: ReturnType<typeof setTimeout>\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n}\n"],"mappings":";AAqZO,SAAS,oBAA4B;AAC1C,SAAO,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACjE;","names":[]}
1
+ {"version":3,"sources":["../src/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 VoiceSessionOptions,\n VoiceSessionDescriptor,\n} from './types.js'\n\n// ============================================================================\n// Host → Worker Messages\n// ============================================================================\n\nexport type HostToWorkerMessage =\n | ActivateMessage\n | DeactivateMessage\n | SettingsChangedMessage\n | SchedulerFireMessage\n | ProviderChatRequestMessage\n | ProviderModelsRequestMessage\n | ProviderVoiceSessionRequestMessage\n | ToolExecuteRequestMessage\n | ActionExecuteRequestMessage\n | ResponseMessage\n | StreamingFetchChunkMessage\n | BackgroundTaskStartMessage\n | BackgroundTaskStopMessage\n\nexport interface ActivateMessage {\n type: 'activate'\n id: string\n payload: {\n extensionId: string\n extensionVersion: string\n storagePath: string\n permissions: string[]\n settings: Record<string, unknown>\n }\n}\n\nexport interface DeactivateMessage {\n type: 'deactivate'\n id: string\n}\n\nexport interface SettingsChangedMessage {\n type: 'settings-changed'\n id: string\n payload: {\n key: string\n value: unknown\n }\n}\n\nexport interface SchedulerFireMessage {\n type: 'scheduler-fire'\n id: string\n payload: SchedulerFirePayload\n}\n\nexport interface ProviderChatRequestMessage {\n type: 'provider-chat-request'\n id: string\n payload: {\n providerId: string\n messages: ChatMessage[]\n options: ChatOptions\n }\n}\n\nexport interface ProviderModelsRequestMessage {\n type: 'provider-models-request'\n id: string\n payload: {\n providerId: string\n options?: GetModelsOptions\n }\n}\n\nexport interface ProviderVoiceSessionRequestMessage {\n type: 'provider-voice-session-request'\n id: string\n payload: {\n providerId: string\n /**\n * `signal` is dropped on the way across: an AbortSignal cannot be\n * structured-cloned into a worker. Cancellation is handled by the host\n * rejecting the pending request instead.\n */\n options: Omit<VoiceSessionOptions, 'signal'>\n }\n}\n\nexport interface ToolExecuteRequestMessage {\n type: 'tool-execute-request'\n id: string\n payload: {\n toolId: string\n params: Record<string, unknown>\n /** User ID if the tool is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ActionExecuteRequestMessage {\n type: 'action-execute-request'\n id: string\n payload: {\n actionId: string\n params: Record<string, unknown>\n /** User ID if the action is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ResponseMessage {\n type: 'response'\n id: string\n payload: {\n requestId: string\n success: boolean\n data?: unknown\n error?: string\n }\n}\n\n/**\n * Message sent from host to worker with streaming fetch data chunks.\n * Used for streaming network responses (e.g., NDJSON streams from Ollama).\n */\nexport interface StreamingFetchChunkMessage {\n type: 'streaming-fetch-chunk'\n id: string\n payload: {\n requestId: string\n chunk: string\n done: boolean\n error?: string\n }\n}\n\n/**\n * Message sent from host to worker to start a registered background task.\n */\nexport interface BackgroundTaskStartMessage {\n type: 'background-task-start'\n id: string\n payload: {\n taskId: string\n }\n}\n\n/**\n * Message sent from host to worker to stop a running background task.\n */\nexport interface BackgroundTaskStopMessage {\n type: 'background-task-stop'\n id: string\n payload: {\n taskId: string\n }\n}\n\n// ============================================================================\n// Worker → Host Messages\n// ============================================================================\n\nexport type WorkerToHostMessage =\n | ReadyMessage\n | RequestMessage\n | ProviderRegisteredMessage\n | ToolRegisteredMessage\n | ActionRegisteredMessage\n | StreamEventMessage\n | LogMessage\n | ProviderModelsResponseMessage\n | ProviderVoiceSessionResponseMessage\n | ToolExecuteResponseMessage\n | ActionExecuteResponseMessage\n | StreamingFetchAckMessage\n | BackgroundTaskRegisteredMessage\n | BackgroundTaskStatusMessage\n | BackgroundTaskHealthMessage\n\nexport interface ReadyMessage {\n type: 'ready'\n}\n\n/**\n * Message sent from worker to host to acknowledge receipt of a streaming fetch chunk.\n * This enables backpressure control to prevent unbounded memory growth.\n */\nexport interface StreamingFetchAckMessage {\n type: 'streaming-fetch-ack'\n payload: {\n requestId: string\n }\n}\n\nexport interface RequestMessage {\n type: 'request'\n id: string\n method: RequestMethod\n payload: unknown\n}\n\nexport type RequestMethod =\n | 'network.fetch'\n | 'network.fetch-stream'\n | 'settings.getAll'\n | 'settings.get'\n | 'settings.set'\n | 'user.getProfile'\n | 'user.listIds'\n | 'events.emit'\n | 'scheduler.schedule'\n | 'scheduler.cancel'\n | 'scheduler.reportFireResult'\n | 'chat.appendInstruction'\n | 'database.execute'\n // Simple key-value storage methods\n | 'storage.set'\n | 'storage.keys'\n | 'storage.setForUser'\n | 'storage.keysForUser'\n // Collection-based storage methods\n | 'storage.put'\n | 'storage.get'\n | 'storage.delete'\n | 'storage.find'\n | 'storage.findOne'\n | 'storage.count'\n | 'storage.putMany'\n | 'storage.deleteMany'\n | 'storage.dropCollection'\n | 'storage.listCollections'\n | 'storage.putForUser'\n | 'storage.getForUser'\n | 'storage.deleteForUser'\n | 'storage.findForUser'\n | 'storage.findOneForUser'\n | 'storage.countForUser'\n | 'storage.putManyForUser'\n | 'storage.deleteManyForUser'\n | 'storage.dropCollectionForUser'\n | 'storage.listCollectionsForUser'\n // Secrets methods\n | 'secrets.set'\n | 'secrets.get'\n | 'secrets.delete'\n | 'secrets.list'\n | 'secrets.setForUser'\n | 'secrets.getForUser'\n | 'secrets.deleteForUser'\n | 'secrets.listForUser'\n // Tools cross-extension methods\n | 'tools.list'\n | 'tools.execute'\n // Attachments\n | 'attachments.read'\n // Connected accounts\n | 'accounts.list'\n | 'accounts.getAccessToken'\n\nexport interface ProviderRegisteredMessage {\n type: 'provider-registered'\n payload: {\n id: string\n name: string\n }\n}\n\nexport interface ToolRegisteredMessage {\n type: 'tool-registered'\n payload: {\n id: string\n name: string\n description: string\n parameters?: Record<string, unknown>\n }\n}\n\nexport interface ActionRegisteredMessage {\n type: 'action-registered'\n payload: {\n id: string\n }\n}\n\nexport interface StreamEventMessage {\n type: 'stream-event'\n payload: {\n requestId: string\n event: StreamEvent\n }\n}\n\nexport interface ProviderModelsResponseMessage {\n type: 'provider-models-response'\n payload: {\n requestId: string\n models: ModelInfo[]\n error?: string\n }\n}\n\nexport interface ProviderVoiceSessionResponseMessage {\n type: 'provider-voice-session-response'\n payload: {\n requestId: string\n /** Absent when `error` is set. */\n descriptor?: VoiceSessionDescriptor\n error?: string\n }\n}\n\nexport interface ToolExecuteResponseMessage {\n type: 'tool-execute-response'\n payload: {\n requestId: string\n result: ToolResult\n error?: string\n }\n}\n\nexport interface ActionExecuteResponseMessage {\n type: 'action-execute-response'\n payload: {\n requestId: string\n result: ActionResult\n error?: string\n }\n}\n\nexport interface LogMessage {\n type: 'log'\n payload: {\n level: 'debug' | 'info' | 'warn' | 'error'\n message: string\n data?: Record<string, unknown>\n }\n}\n\n/**\n * Message sent from worker to host when a background task is registered.\n */\nexport interface BackgroundTaskRegisteredMessage {\n type: 'background-task-registered'\n payload: {\n taskId: string\n name: string\n userId: string\n restartPolicy: {\n type: 'always' | 'on-failure' | 'never'\n maxRestarts?: number\n initialDelayMs?: number\n maxDelayMs?: number\n backoffMultiplier?: number\n }\n payload?: Record<string, unknown>\n }\n}\n\n/**\n * Message sent from worker to host with background task status updates.\n */\nexport interface BackgroundTaskStatusMessage {\n type: 'background-task-status'\n payload: {\n taskId: string\n status: 'running' | 'stopped' | 'completed' | 'failed'\n error?: string\n }\n}\n\n/**\n * Message sent from worker to host with background task health reports.\n */\nexport interface BackgroundTaskHealthMessage {\n type: 'background-task-health'\n payload: {\n taskId: string\n status: string\n timestamp: string\n }\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\nexport interface PendingRequest<T = unknown> {\n resolve: (value: T) => void\n reject: (error: Error) => void\n timeout: ReturnType<typeof setTimeout>\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n}\n"],"mappings":";AAwZO,SAAS,oBAA4B;AAC1C,SAAO,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACjE;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types.localization.ts","../src/messages.ts"],"sourcesContent":["/**\n * @stina/extension-api\n *\n * Types and utilities for building Stina extensions.\n *\n * Extensions should import from this package for type definitions.\n * The runtime (worker-side code) should import from '@stina/extension-api/runtime'.\n */\n\n// Localization\nexport type { LocalizedString } from './types.js'\nexport { resolveLocalizedString } from './types.js'\n\n// Types\nexport type {\n // Manifest\n ExtensionManifest,\n Platform,\n ExtensionContributions,\n ToolSettingsViewDefinition,\n ToolSettingsView,\n ToolSettingsListView,\n ToolSettingsListMapping,\n ToolSettingsComponentView,\n ToolSettingsActionDataSource,\n PanelDefinition,\n StatusCardDefinition,\n PanelView,\n PanelComponentView,\n PanelActionDataSource,\n PanelUnknownView,\n ProviderDefinition,\n ProviderConfigView,\n PromptContribution,\n PromptSection,\n ToolDefinition,\n ToolConfirmationConfig,\n CommandDefinition,\n\n // Permissions\n Permission,\n NetworkPermission,\n StoragePermission,\n UserDataPermission,\n CapabilityPermission,\n SystemPermission,\n\n // Context\n ExtensionContext,\n Disposable,\n NetworkAPI,\n SettingsAPI,\n ProvidersAPI,\n ToolsAPI,\n ActionsAPI,\n EventsAPI,\n SchedulerAPI,\n SchedulerJobRequest,\n SchedulerSchedule,\n SchedulerFirePayload,\n UserAPI,\n UserProfile,\n ChatAPI,\n ChatInstructionMessage,\n ConversationPresentation,\n AttachmentsAPI,\n AttachmentContent,\n LogAPI,\n\n // Background workers\n BackgroundWorkersAPI,\n BackgroundTaskConfig,\n BackgroundTaskCallback,\n BackgroundTaskContext,\n BackgroundTaskHealth,\n BackgroundRestartPolicy,\n\n // Storage and Secrets\n Query,\n QueryOptions,\n StorageAPI,\n SecretsAPI,\n StorageCollectionConfig,\n StorageContributions,\n\n // AI Provider\n AIProvider,\n ModelInfo,\n ModelCapabilities,\n ChatMessage,\n ChatImage,\n ChatFile,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolCall,\n\n // Duplex voice\n VoiceSessionOptions,\n VoiceSessionDescriptor,\n VoiceTransportRequest,\n\n // Tools\n Tool,\n ToolResult,\n ToolAttachment,\n\n // Actions\n Action,\n ActionResult,\n\n // Entry point\n ExtensionModule,\n} from './types.js'\n\n// Messages (for host implementation)\nexport type {\n HostToWorkerMessage,\n WorkerToHostMessage,\n ActivateMessage,\n DeactivateMessage,\n SettingsChangedMessage,\n ProviderChatRequestMessage,\n ProviderModelsRequestMessage,\n ToolExecuteRequestMessage,\n ToolExecuteResponseMessage,\n ActionExecuteRequestMessage,\n ActionExecuteResponseMessage,\n ResponseMessage,\n ReadyMessage,\n RequestMessage,\n RequestMethod,\n ProviderRegisteredMessage,\n ToolRegisteredMessage,\n ActionRegisteredMessage,\n StreamEventMessage,\n LogMessage,\n PendingRequest,\n // Background task messages\n BackgroundTaskStartMessage,\n BackgroundTaskStopMessage,\n BackgroundTaskRegisteredMessage,\n BackgroundTaskStatusMessage,\n BackgroundTaskHealthMessage,\n} from './messages.js'\n\nexport { generateMessageId } from './messages.js'\n\n// Component types (for extension UI components)\nexport type {\n // Icon Names\n HugeIconName,\n // Styling\n AllowedCSSProperty,\n ExtensionComponentStyle,\n // Base types\n ExtensionComponentData,\n // Iteration & Children\n ExtensionComponentIterator,\n ExtensionComponentChildren,\n // Actions\n ExtensionActionCall,\n ExtensionActionRef,\n // Data Sources & Panel Definition\n ExtensionDataSource,\n ExtensionPanelDefinition,\n // Component Props\n HeaderProps,\n LabelProps,\n ClockProps,\n ParagraphProps,\n ButtonProps,\n TextInputProps,\n PasswordInputProps,\n NumberInputProps,\n TextAreaProps,\n DateTimeInputProps,\n SelectProps,\n IconPickerProps,\n VerticalStackProps,\n HorizontalStackProps,\n GridProps,\n DividerProps,\n IconProps,\n IconButtonType,\n IconButtonProps,\n PanelAction,\n PanelProps,\n ToggleProps,\n CollapsibleProps,\n FrameVariant,\n FrameProps,\n ListProps,\n PillVariant,\n PillProps,\n CheckboxProps,\n MarkdownProps,\n TextPreviewProps,\n ModalProps,\n ConditionalGroupProps,\n // Purpose-built display components\n WeatherCondition,\n WeatherWind,\n WeatherNowProps,\n WeatherForecastStep,\n WeatherForecastProps,\n ChartKind,\n ChartSeries,\n ChartProps,\n StatTrend,\n StatTileProps,\n ProgressShape,\n ProgressColor,\n ProgressBarProps,\n KeyValueRow,\n KeyValueListProps,\n TimelineVariant,\n TimelineEntry,\n TimelineProps,\n NoteVariant,\n NoteProps,\n CalendarEventStatus,\n CalendarEventProps,\n} from './types.components.js'\n","/**\n * Localization Types\n *\n * Types and utilities for localized strings in extensions.\n */\n\n/**\n * A string that can be either a simple string or a map of language codes to localized strings.\n * When a simple string is provided, it's used as the default/fallback value.\n * When a map is provided, the appropriate language is selected at runtime.\n *\n * @example\n * // Simple string (backwards compatible)\n * name: \"Get Weather\"\n *\n * @example\n * // Localized strings\n * name: { en: \"Get Weather\", sv: \"Hämta väder\", de: \"Wetter abrufen\" }\n */\nexport type LocalizedString = string | Record<string, string>\n\n/**\n * Resolves a LocalizedString to an actual string value.\n * @param value The LocalizedString to resolve\n * @param lang The preferred language code (e.g., \"sv\", \"en\")\n * @param fallbackLang The fallback language code (defaults to \"en\")\n * @returns The resolved string value\n */\nexport function resolveLocalizedString(\n value: LocalizedString,\n lang: string,\n fallbackLang = 'en'\n): string {\n if (typeof value === 'string') {\n return value\n }\n // Try preferred language first, then fallback language, then first available, then empty string\n return value[lang] ?? value[fallbackLang] ?? Object.values(value)[0] ?? ''\n}\n","/**\n * Message protocol between Extension Host and Extension Workers\n */\n\nimport type {\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolResult,\n ActionResult,\n ModelInfo,\n SchedulerFirePayload,\n VoiceSessionOptions,\n VoiceSessionDescriptor,\n} from './types.js'\n\n// ============================================================================\n// Host → Worker Messages\n// ============================================================================\n\nexport type HostToWorkerMessage =\n | ActivateMessage\n | DeactivateMessage\n | SettingsChangedMessage\n | SchedulerFireMessage\n | ProviderChatRequestMessage\n | ProviderModelsRequestMessage\n | ProviderVoiceSessionRequestMessage\n | ToolExecuteRequestMessage\n | ActionExecuteRequestMessage\n | ResponseMessage\n | StreamingFetchChunkMessage\n | BackgroundTaskStartMessage\n | BackgroundTaskStopMessage\n\nexport interface ActivateMessage {\n type: 'activate'\n id: string\n payload: {\n extensionId: string\n extensionVersion: string\n storagePath: string\n permissions: string[]\n settings: Record<string, unknown>\n }\n}\n\nexport interface DeactivateMessage {\n type: 'deactivate'\n id: string\n}\n\nexport interface SettingsChangedMessage {\n type: 'settings-changed'\n id: string\n payload: {\n key: string\n value: unknown\n }\n}\n\nexport interface SchedulerFireMessage {\n type: 'scheduler-fire'\n id: string\n payload: SchedulerFirePayload\n}\n\nexport interface ProviderChatRequestMessage {\n type: 'provider-chat-request'\n id: string\n payload: {\n providerId: string\n messages: ChatMessage[]\n options: ChatOptions\n }\n}\n\nexport interface ProviderModelsRequestMessage {\n type: 'provider-models-request'\n id: string\n payload: {\n providerId: string\n options?: GetModelsOptions\n }\n}\n\nexport interface ProviderVoiceSessionRequestMessage {\n type: 'provider-voice-session-request'\n id: string\n payload: {\n providerId: string\n /**\n * `signal` is dropped on the way across: an AbortSignal cannot be\n * structured-cloned into a worker. Cancellation is handled by the host\n * rejecting the pending request instead.\n */\n options: Omit<VoiceSessionOptions, 'signal'>\n }\n}\n\nexport interface ToolExecuteRequestMessage {\n type: 'tool-execute-request'\n id: string\n payload: {\n toolId: string\n params: Record<string, unknown>\n /** User ID if the tool is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ActionExecuteRequestMessage {\n type: 'action-execute-request'\n id: string\n payload: {\n actionId: string\n params: Record<string, unknown>\n /** User ID if the action is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ResponseMessage {\n type: 'response'\n id: string\n payload: {\n requestId: string\n success: boolean\n data?: unknown\n error?: string\n }\n}\n\n/**\n * Message sent from host to worker with streaming fetch data chunks.\n * Used for streaming network responses (e.g., NDJSON streams from Ollama).\n */\nexport interface StreamingFetchChunkMessage {\n type: 'streaming-fetch-chunk'\n id: string\n payload: {\n requestId: string\n chunk: string\n done: boolean\n error?: string\n }\n}\n\n/**\n * Message sent from host to worker to start a registered background task.\n */\nexport interface BackgroundTaskStartMessage {\n type: 'background-task-start'\n id: string\n payload: {\n taskId: string\n }\n}\n\n/**\n * Message sent from host to worker to stop a running background task.\n */\nexport interface BackgroundTaskStopMessage {\n type: 'background-task-stop'\n id: string\n payload: {\n taskId: string\n }\n}\n\n// ============================================================================\n// Worker → Host Messages\n// ============================================================================\n\nexport type WorkerToHostMessage =\n | ReadyMessage\n | RequestMessage\n | ProviderRegisteredMessage\n | ToolRegisteredMessage\n | ActionRegisteredMessage\n | StreamEventMessage\n | LogMessage\n | ProviderModelsResponseMessage\n | ProviderVoiceSessionResponseMessage\n | ToolExecuteResponseMessage\n | ActionExecuteResponseMessage\n | StreamingFetchAckMessage\n | BackgroundTaskRegisteredMessage\n | BackgroundTaskStatusMessage\n | BackgroundTaskHealthMessage\n\nexport interface ReadyMessage {\n type: 'ready'\n}\n\n/**\n * Message sent from worker to host to acknowledge receipt of a streaming fetch chunk.\n * This enables backpressure control to prevent unbounded memory growth.\n */\nexport interface StreamingFetchAckMessage {\n type: 'streaming-fetch-ack'\n payload: {\n requestId: string\n }\n}\n\nexport interface RequestMessage {\n type: 'request'\n id: string\n method: RequestMethod\n payload: unknown\n}\n\nexport type RequestMethod =\n | 'network.fetch'\n | 'network.fetch-stream'\n | 'settings.getAll'\n | 'settings.get'\n | 'settings.set'\n | 'user.getProfile'\n | 'user.listIds'\n | 'events.emit'\n | 'scheduler.schedule'\n | 'scheduler.cancel'\n | 'scheduler.reportFireResult'\n | 'chat.appendInstruction'\n | 'database.execute'\n // Simple key-value storage methods\n | 'storage.set'\n | 'storage.keys'\n | 'storage.setForUser'\n | 'storage.keysForUser'\n // Collection-based storage methods\n | 'storage.put'\n | 'storage.get'\n | 'storage.delete'\n | 'storage.find'\n | 'storage.findOne'\n | 'storage.count'\n | 'storage.putMany'\n | 'storage.deleteMany'\n | 'storage.dropCollection'\n | 'storage.listCollections'\n | 'storage.putForUser'\n | 'storage.getForUser'\n | 'storage.deleteForUser'\n | 'storage.findForUser'\n | 'storage.findOneForUser'\n | 'storage.countForUser'\n | 'storage.putManyForUser'\n | 'storage.deleteManyForUser'\n | 'storage.dropCollectionForUser'\n | 'storage.listCollectionsForUser'\n // Secrets methods\n | 'secrets.set'\n | 'secrets.get'\n | 'secrets.delete'\n | 'secrets.list'\n | 'secrets.setForUser'\n | 'secrets.getForUser'\n | 'secrets.deleteForUser'\n | 'secrets.listForUser'\n // Tools cross-extension methods\n | 'tools.list'\n | 'tools.execute'\n // Attachments\n | 'attachments.read'\n\nexport interface ProviderRegisteredMessage {\n type: 'provider-registered'\n payload: {\n id: string\n name: string\n }\n}\n\nexport interface ToolRegisteredMessage {\n type: 'tool-registered'\n payload: {\n id: string\n name: string\n description: string\n parameters?: Record<string, unknown>\n }\n}\n\nexport interface ActionRegisteredMessage {\n type: 'action-registered'\n payload: {\n id: string\n }\n}\n\nexport interface StreamEventMessage {\n type: 'stream-event'\n payload: {\n requestId: string\n event: StreamEvent\n }\n}\n\nexport interface ProviderModelsResponseMessage {\n type: 'provider-models-response'\n payload: {\n requestId: string\n models: ModelInfo[]\n error?: string\n }\n}\n\nexport interface ProviderVoiceSessionResponseMessage {\n type: 'provider-voice-session-response'\n payload: {\n requestId: string\n /** Absent when `error` is set. */\n descriptor?: VoiceSessionDescriptor\n error?: string\n }\n}\n\nexport interface ToolExecuteResponseMessage {\n type: 'tool-execute-response'\n payload: {\n requestId: string\n result: ToolResult\n error?: string\n }\n}\n\nexport interface ActionExecuteResponseMessage {\n type: 'action-execute-response'\n payload: {\n requestId: string\n result: ActionResult\n error?: string\n }\n}\n\nexport interface LogMessage {\n type: 'log'\n payload: {\n level: 'debug' | 'info' | 'warn' | 'error'\n message: string\n data?: Record<string, unknown>\n }\n}\n\n/**\n * Message sent from worker to host when a background task is registered.\n */\nexport interface BackgroundTaskRegisteredMessage {\n type: 'background-task-registered'\n payload: {\n taskId: string\n name: string\n userId: string\n restartPolicy: {\n type: 'always' | 'on-failure' | 'never'\n maxRestarts?: number\n initialDelayMs?: number\n maxDelayMs?: number\n backoffMultiplier?: number\n }\n payload?: Record<string, unknown>\n }\n}\n\n/**\n * Message sent from worker to host with background task status updates.\n */\nexport interface BackgroundTaskStatusMessage {\n type: 'background-task-status'\n payload: {\n taskId: string\n status: 'running' | 'stopped' | 'completed' | 'failed'\n error?: string\n }\n}\n\n/**\n * Message sent from worker to host with background task health reports.\n */\nexport interface BackgroundTaskHealthMessage {\n type: 'background-task-health'\n payload: {\n taskId: string\n status: string\n timestamp: string\n }\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\nexport interface PendingRequest<T = unknown> {\n resolve: (value: T) => void\n reject: (error: Error) => void\n timeout: ReturnType<typeof setTimeout>\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC4BO,SAAS,uBACd,OACA,MACA,eAAe,MACP;AACR,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AAEA,SAAO,MAAM,IAAI,KAAK,MAAM,YAAY,KAAK,OAAO,OAAO,KAAK,EAAE,CAAC,KAAK;AAC1E;;;AC+WO,SAAS,oBAA4B;AAC1C,SAAO,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACjE;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types.localization.ts","../src/messages.ts"],"sourcesContent":["/**\n * @stina/extension-api\n *\n * Types and utilities for building Stina extensions.\n *\n * Extensions should import from this package for type definitions.\n * The runtime (worker-side code) should import from '@stina/extension-api/runtime'.\n */\n\n// Localization\nexport type { LocalizedString } from './types.js'\nexport { resolveLocalizedString } from './types.js'\n\n// Types\nexport type {\n // Manifest\n ExtensionManifest,\n Platform,\n ExtensionContributions,\n ToolSettingsViewDefinition,\n ToolSettingsView,\n ToolSettingsListView,\n ToolSettingsListMapping,\n ToolSettingsComponentView,\n ToolSettingsActionDataSource,\n PanelDefinition,\n StatusCardDefinition,\n PanelView,\n PanelComponentView,\n PanelActionDataSource,\n PanelUnknownView,\n ProviderDefinition,\n ProviderConfigView,\n PromptContribution,\n PromptSection,\n ToolDefinition,\n ToolConfirmationConfig,\n CommandDefinition,\n AccountProvider,\n AccountContribution,\n\n // Permissions\n Permission,\n NetworkPermission,\n StoragePermission,\n UserDataPermission,\n CapabilityPermission,\n SystemPermission,\n\n // Context\n ExtensionContext,\n Disposable,\n NetworkAPI,\n SettingsAPI,\n ProvidersAPI,\n ToolsAPI,\n ActionsAPI,\n EventsAPI,\n SchedulerAPI,\n SchedulerJobRequest,\n SchedulerSchedule,\n SchedulerFirePayload,\n UserAPI,\n UserProfile,\n ChatAPI,\n ChatInstructionMessage,\n ConversationPresentation,\n AttachmentsAPI,\n AttachmentContent,\n ConnectedAccountsAPI,\n ConnectedAccount,\n AccountAccessToken,\n LogAPI,\n\n // Background workers\n BackgroundWorkersAPI,\n BackgroundTaskConfig,\n BackgroundTaskCallback,\n BackgroundTaskContext,\n BackgroundTaskHealth,\n BackgroundRestartPolicy,\n\n // Storage and Secrets\n Query,\n QueryOptions,\n StorageAPI,\n SecretsAPI,\n StorageCollectionConfig,\n StorageContributions,\n\n // AI Provider\n AIProvider,\n ModelInfo,\n ModelCapabilities,\n ChatMessage,\n ChatImage,\n ChatFile,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolCall,\n\n // Duplex voice\n VoiceSessionOptions,\n VoiceSessionDescriptor,\n VoiceTransportRequest,\n\n // Tools\n Tool,\n ToolResult,\n ToolAttachment,\n\n // Actions\n Action,\n ActionResult,\n\n // Entry point\n ExtensionModule,\n} from './types.js'\n\n// Messages (for host implementation)\nexport type {\n HostToWorkerMessage,\n WorkerToHostMessage,\n ActivateMessage,\n DeactivateMessage,\n SettingsChangedMessage,\n ProviderChatRequestMessage,\n ProviderModelsRequestMessage,\n ToolExecuteRequestMessage,\n ToolExecuteResponseMessage,\n ActionExecuteRequestMessage,\n ActionExecuteResponseMessage,\n ResponseMessage,\n ReadyMessage,\n RequestMessage,\n RequestMethod,\n ProviderRegisteredMessage,\n ToolRegisteredMessage,\n ActionRegisteredMessage,\n StreamEventMessage,\n LogMessage,\n PendingRequest,\n // Background task messages\n BackgroundTaskStartMessage,\n BackgroundTaskStopMessage,\n BackgroundTaskRegisteredMessage,\n BackgroundTaskStatusMessage,\n BackgroundTaskHealthMessage,\n} from './messages.js'\n\nexport { generateMessageId } from './messages.js'\n\n// Component types (for extension UI components)\nexport type {\n // Icon Names\n HugeIconName,\n // Styling\n AllowedCSSProperty,\n ExtensionComponentStyle,\n // Base types\n ExtensionComponentData,\n // Iteration & Children\n ExtensionComponentIterator,\n ExtensionComponentChildren,\n // Actions\n ExtensionActionCall,\n ExtensionActionRef,\n // Data Sources & Panel Definition\n ExtensionDataSource,\n ExtensionPanelDefinition,\n // Component Props\n HeaderProps,\n LabelProps,\n ClockProps,\n ParagraphProps,\n ButtonProps,\n TextInputProps,\n PasswordInputProps,\n NumberInputProps,\n TextAreaProps,\n DateTimeInputProps,\n SelectProps,\n IconPickerProps,\n VerticalStackProps,\n HorizontalStackProps,\n GridProps,\n DividerProps,\n IconProps,\n IconButtonType,\n IconButtonProps,\n PanelAction,\n PanelProps,\n ToggleProps,\n CollapsibleProps,\n FrameVariant,\n FrameProps,\n ListProps,\n PillVariant,\n PillProps,\n CheckboxProps,\n MarkdownProps,\n TextPreviewProps,\n ModalProps,\n ConditionalGroupProps,\n // Purpose-built display components\n WeatherCondition,\n WeatherWind,\n WeatherNowProps,\n WeatherForecastStep,\n WeatherForecastProps,\n ChartKind,\n ChartSeries,\n ChartProps,\n StatTrend,\n StatTileProps,\n ProgressShape,\n ProgressColor,\n ProgressBarProps,\n KeyValueRow,\n KeyValueListProps,\n TimelineVariant,\n TimelineEntry,\n TimelineProps,\n NoteVariant,\n NoteProps,\n CalendarEventStatus,\n CalendarEventProps,\n} from './types.components.js'\n","/**\n * Localization Types\n *\n * Types and utilities for localized strings in extensions.\n */\n\n/**\n * A string that can be either a simple string or a map of language codes to localized strings.\n * When a simple string is provided, it's used as the default/fallback value.\n * When a map is provided, the appropriate language is selected at runtime.\n *\n * @example\n * // Simple string (backwards compatible)\n * name: \"Get Weather\"\n *\n * @example\n * // Localized strings\n * name: { en: \"Get Weather\", sv: \"Hämta väder\", de: \"Wetter abrufen\" }\n */\nexport type LocalizedString = string | Record<string, string>\n\n/**\n * Resolves a LocalizedString to an actual string value.\n * @param value The LocalizedString to resolve\n * @param lang The preferred language code (e.g., \"sv\", \"en\")\n * @param fallbackLang The fallback language code (defaults to \"en\")\n * @returns The resolved string value\n */\nexport function resolveLocalizedString(\n value: LocalizedString,\n lang: string,\n fallbackLang = 'en'\n): string {\n if (typeof value === 'string') {\n return value\n }\n // Try preferred language first, then fallback language, then first available, then empty string\n return value[lang] ?? value[fallbackLang] ?? Object.values(value)[0] ?? ''\n}\n","/**\n * Message protocol between Extension Host and Extension Workers\n */\n\nimport type {\n ChatMessage,\n ChatOptions,\n GetModelsOptions,\n StreamEvent,\n ToolResult,\n ActionResult,\n ModelInfo,\n SchedulerFirePayload,\n VoiceSessionOptions,\n VoiceSessionDescriptor,\n} from './types.js'\n\n// ============================================================================\n// Host → Worker Messages\n// ============================================================================\n\nexport type HostToWorkerMessage =\n | ActivateMessage\n | DeactivateMessage\n | SettingsChangedMessage\n | SchedulerFireMessage\n | ProviderChatRequestMessage\n | ProviderModelsRequestMessage\n | ProviderVoiceSessionRequestMessage\n | ToolExecuteRequestMessage\n | ActionExecuteRequestMessage\n | ResponseMessage\n | StreamingFetchChunkMessage\n | BackgroundTaskStartMessage\n | BackgroundTaskStopMessage\n\nexport interface ActivateMessage {\n type: 'activate'\n id: string\n payload: {\n extensionId: string\n extensionVersion: string\n storagePath: string\n permissions: string[]\n settings: Record<string, unknown>\n }\n}\n\nexport interface DeactivateMessage {\n type: 'deactivate'\n id: string\n}\n\nexport interface SettingsChangedMessage {\n type: 'settings-changed'\n id: string\n payload: {\n key: string\n value: unknown\n }\n}\n\nexport interface SchedulerFireMessage {\n type: 'scheduler-fire'\n id: string\n payload: SchedulerFirePayload\n}\n\nexport interface ProviderChatRequestMessage {\n type: 'provider-chat-request'\n id: string\n payload: {\n providerId: string\n messages: ChatMessage[]\n options: ChatOptions\n }\n}\n\nexport interface ProviderModelsRequestMessage {\n type: 'provider-models-request'\n id: string\n payload: {\n providerId: string\n options?: GetModelsOptions\n }\n}\n\nexport interface ProviderVoiceSessionRequestMessage {\n type: 'provider-voice-session-request'\n id: string\n payload: {\n providerId: string\n /**\n * `signal` is dropped on the way across: an AbortSignal cannot be\n * structured-cloned into a worker. Cancellation is handled by the host\n * rejecting the pending request instead.\n */\n options: Omit<VoiceSessionOptions, 'signal'>\n }\n}\n\nexport interface ToolExecuteRequestMessage {\n type: 'tool-execute-request'\n id: string\n payload: {\n toolId: string\n params: Record<string, unknown>\n /** User ID if the tool is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ActionExecuteRequestMessage {\n type: 'action-execute-request'\n id: string\n payload: {\n actionId: string\n params: Record<string, unknown>\n /** User ID if the action is executed in a user context */\n userId?: string\n }\n}\n\nexport interface ResponseMessage {\n type: 'response'\n id: string\n payload: {\n requestId: string\n success: boolean\n data?: unknown\n error?: string\n }\n}\n\n/**\n * Message sent from host to worker with streaming fetch data chunks.\n * Used for streaming network responses (e.g., NDJSON streams from Ollama).\n */\nexport interface StreamingFetchChunkMessage {\n type: 'streaming-fetch-chunk'\n id: string\n payload: {\n requestId: string\n chunk: string\n done: boolean\n error?: string\n }\n}\n\n/**\n * Message sent from host to worker to start a registered background task.\n */\nexport interface BackgroundTaskStartMessage {\n type: 'background-task-start'\n id: string\n payload: {\n taskId: string\n }\n}\n\n/**\n * Message sent from host to worker to stop a running background task.\n */\nexport interface BackgroundTaskStopMessage {\n type: 'background-task-stop'\n id: string\n payload: {\n taskId: string\n }\n}\n\n// ============================================================================\n// Worker → Host Messages\n// ============================================================================\n\nexport type WorkerToHostMessage =\n | ReadyMessage\n | RequestMessage\n | ProviderRegisteredMessage\n | ToolRegisteredMessage\n | ActionRegisteredMessage\n | StreamEventMessage\n | LogMessage\n | ProviderModelsResponseMessage\n | ProviderVoiceSessionResponseMessage\n | ToolExecuteResponseMessage\n | ActionExecuteResponseMessage\n | StreamingFetchAckMessage\n | BackgroundTaskRegisteredMessage\n | BackgroundTaskStatusMessage\n | BackgroundTaskHealthMessage\n\nexport interface ReadyMessage {\n type: 'ready'\n}\n\n/**\n * Message sent from worker to host to acknowledge receipt of a streaming fetch chunk.\n * This enables backpressure control to prevent unbounded memory growth.\n */\nexport interface StreamingFetchAckMessage {\n type: 'streaming-fetch-ack'\n payload: {\n requestId: string\n }\n}\n\nexport interface RequestMessage {\n type: 'request'\n id: string\n method: RequestMethod\n payload: unknown\n}\n\nexport type RequestMethod =\n | 'network.fetch'\n | 'network.fetch-stream'\n | 'settings.getAll'\n | 'settings.get'\n | 'settings.set'\n | 'user.getProfile'\n | 'user.listIds'\n | 'events.emit'\n | 'scheduler.schedule'\n | 'scheduler.cancel'\n | 'scheduler.reportFireResult'\n | 'chat.appendInstruction'\n | 'database.execute'\n // Simple key-value storage methods\n | 'storage.set'\n | 'storage.keys'\n | 'storage.setForUser'\n | 'storage.keysForUser'\n // Collection-based storage methods\n | 'storage.put'\n | 'storage.get'\n | 'storage.delete'\n | 'storage.find'\n | 'storage.findOne'\n | 'storage.count'\n | 'storage.putMany'\n | 'storage.deleteMany'\n | 'storage.dropCollection'\n | 'storage.listCollections'\n | 'storage.putForUser'\n | 'storage.getForUser'\n | 'storage.deleteForUser'\n | 'storage.findForUser'\n | 'storage.findOneForUser'\n | 'storage.countForUser'\n | 'storage.putManyForUser'\n | 'storage.deleteManyForUser'\n | 'storage.dropCollectionForUser'\n | 'storage.listCollectionsForUser'\n // Secrets methods\n | 'secrets.set'\n | 'secrets.get'\n | 'secrets.delete'\n | 'secrets.list'\n | 'secrets.setForUser'\n | 'secrets.getForUser'\n | 'secrets.deleteForUser'\n | 'secrets.listForUser'\n // Tools cross-extension methods\n | 'tools.list'\n | 'tools.execute'\n // Attachments\n | 'attachments.read'\n // Connected accounts\n | 'accounts.list'\n | 'accounts.getAccessToken'\n\nexport interface ProviderRegisteredMessage {\n type: 'provider-registered'\n payload: {\n id: string\n name: string\n }\n}\n\nexport interface ToolRegisteredMessage {\n type: 'tool-registered'\n payload: {\n id: string\n name: string\n description: string\n parameters?: Record<string, unknown>\n }\n}\n\nexport interface ActionRegisteredMessage {\n type: 'action-registered'\n payload: {\n id: string\n }\n}\n\nexport interface StreamEventMessage {\n type: 'stream-event'\n payload: {\n requestId: string\n event: StreamEvent\n }\n}\n\nexport interface ProviderModelsResponseMessage {\n type: 'provider-models-response'\n payload: {\n requestId: string\n models: ModelInfo[]\n error?: string\n }\n}\n\nexport interface ProviderVoiceSessionResponseMessage {\n type: 'provider-voice-session-response'\n payload: {\n requestId: string\n /** Absent when `error` is set. */\n descriptor?: VoiceSessionDescriptor\n error?: string\n }\n}\n\nexport interface ToolExecuteResponseMessage {\n type: 'tool-execute-response'\n payload: {\n requestId: string\n result: ToolResult\n error?: string\n }\n}\n\nexport interface ActionExecuteResponseMessage {\n type: 'action-execute-response'\n payload: {\n requestId: string\n result: ActionResult\n error?: string\n }\n}\n\nexport interface LogMessage {\n type: 'log'\n payload: {\n level: 'debug' | 'info' | 'warn' | 'error'\n message: string\n data?: Record<string, unknown>\n }\n}\n\n/**\n * Message sent from worker to host when a background task is registered.\n */\nexport interface BackgroundTaskRegisteredMessage {\n type: 'background-task-registered'\n payload: {\n taskId: string\n name: string\n userId: string\n restartPolicy: {\n type: 'always' | 'on-failure' | 'never'\n maxRestarts?: number\n initialDelayMs?: number\n maxDelayMs?: number\n backoffMultiplier?: number\n }\n payload?: Record<string, unknown>\n }\n}\n\n/**\n * Message sent from worker to host with background task status updates.\n */\nexport interface BackgroundTaskStatusMessage {\n type: 'background-task-status'\n payload: {\n taskId: string\n status: 'running' | 'stopped' | 'completed' | 'failed'\n error?: string\n }\n}\n\n/**\n * Message sent from worker to host with background task health reports.\n */\nexport interface BackgroundTaskHealthMessage {\n type: 'background-task-health'\n payload: {\n taskId: string\n status: string\n timestamp: string\n }\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\nexport interface PendingRequest<T = unknown> {\n resolve: (value: T) => void\n reject: (error: Error) => void\n timeout: ReturnType<typeof setTimeout>\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC4BO,SAAS,uBACd,OACA,MACA,eAAe,MACP;AACR,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AAEA,SAAO,MAAM,IAAI,KAAK,MAAM,YAAY,KAAK,OAAO,OAAO,KAAK,EAAE,CAAC,KAAK;AAC1E;;;ACkXO,SAAS,oBAA4B;AAC1C,SAAO,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACjE;","names":[]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { H as HugeIconName, E as ExtensionContributions, S as SchedulerFirePayload, C as ChatMessage, a as ChatOptions, G as GetModelsOptions, V as VoiceSessionOptions, b as StreamEvent, M as ModelInfo, c as VoiceSessionDescriptor, T as ToolResult, A as ActionResult } from './types.tools-R0xGhiBa.cjs';
2
- export { aa as AIProvider, ai as Action, B as ActionsAPI, ak as AllowedCSSProperty, Y as AttachmentContent, X as AttachmentsAPI, a3 as BackgroundRestartPolicy, a0 as BackgroundTaskCallback, $ as BackgroundTaskConfig, a1 as BackgroundTaskContext, a2 as BackgroundTaskHealth, _ as BackgroundWorkersAPI, ax as ButtonProps, bj as CalendarEventProps, bi as CalendarEventStatus, b3 as ChartKind, b5 as ChartProps, b4 as ChartSeries, Q as ChatAPI, ad as ChatFile, ac as ChatImage, R as ChatInstructionMessage, aV as CheckboxProps, av as ClockProps, aP as CollapsibleProps, v as CommandDefinition, aZ as ConditionalGroupProps, W as ConversationPresentation, aC as DateTimeInputProps, D as Disposable, aI as DividerProps, F as EventsAPI, ap as ExtensionActionCall, aq as ExtensionActionRef, ao as ExtensionComponentChildren, am as ExtensionComponentData, an as ExtensionComponentIterator, al as ExtensionComponentStyle, w as ExtensionContext, ar as ExtensionDataSource, aj as ExtensionModule, as as ExtensionPanelDefinition, aR as FrameProps, aQ as FrameVariant, aH as GridProps, at as HeaderProps, aG as HorizontalStackProps, aL as IconButtonProps, aK as IconButtonType, aE as IconPickerProps, aJ as IconProps, bc as KeyValueListProps, bb as KeyValueRow, au as LabelProps, aS as ListProps, L as LocalizedString, Z as LogAPI, aW as MarkdownProps, aY as ModalProps, ab as ModelCapabilities, N as NetworkAPI, bh as NoteProps, bg as NoteVariant, aA as NumberInputProps, aM as PanelAction, m as PanelActionDataSource, l as PanelComponentView, P as PanelDefinition, aN as PanelProps, n as PanelUnknownView, k as PanelView, aw as ParagraphProps, az as PasswordInputProps, aU as PillProps, aT as PillVariant, ba as ProgressBarProps, b9 as ProgressColor, b8 as ProgressShape, q as PromptContribution, s as PromptSection, p as ProviderConfigView, o as ProviderDefinition, y as ProvidersAPI, a4 as Query, a5 as QueryOptions, I as SchedulerAPI, J as SchedulerJobRequest, K as SchedulerSchedule, a7 as SecretsAPI, aD as SelectProps, x as SettingsAPI, b7 as StatTileProps, b6 as StatTrend, j as StatusCardDefinition, a6 as StorageAPI, a8 as StorageCollectionConfig, a9 as StorageContributions, aB as TextAreaProps, ay as TextInputProps, aX as TextPreviewProps, be as TimelineEntry, bf as TimelineProps, bd as TimelineVariant, aO as ToggleProps, ag as Tool, ah as ToolAttachment, ae as ToolCall, u as ToolConfirmationConfig, t as ToolDefinition, i as ToolSettingsActionDataSource, h as ToolSettingsComponentView, g as ToolSettingsListMapping, f as ToolSettingsListView, e as ToolSettingsView, d as ToolSettingsViewDefinition, z as ToolsAPI, U as UserAPI, O as UserProfile, aF as VerticalStackProps, af as VoiceTransportRequest, a_ as WeatherCondition, b2 as WeatherForecastProps, b1 as WeatherForecastStep, b0 as WeatherNowProps, a$ as WeatherWind, r as resolveLocalizedString } from './types.tools-R0xGhiBa.cjs';
1
+ import { H as HugeIconName, E as ExtensionContributions, S as SchedulerFirePayload, C as ChatMessage, a as ChatOptions, G as GetModelsOptions, V as VoiceSessionOptions, b as StreamEvent, M as ModelInfo, c as VoiceSessionDescriptor, T as ToolResult, A as ActionResult } from './types.tools-DcFBsfRV.cjs';
2
+ export { af as AIProvider, a1 as AccountAccessToken, x as AccountContribution, w as AccountProvider, an as Action, I as ActionsAPI, ap as AllowedCSSProperty, _ as AttachmentContent, Z as AttachmentsAPI, a8 as BackgroundRestartPolicy, a5 as BackgroundTaskCallback, a4 as BackgroundTaskConfig, a6 as BackgroundTaskContext, a7 as BackgroundTaskHealth, a3 as BackgroundWorkersAPI, aC as ButtonProps, bo as CalendarEventProps, bn as CalendarEventStatus, b8 as ChartKind, ba as ChartProps, b9 as ChartSeries, W as ChatAPI, ai as ChatFile, ah as ChatImage, X as ChatInstructionMessage, a_ as CheckboxProps, aA as ClockProps, aU as CollapsibleProps, v as CommandDefinition, b2 as ConditionalGroupProps, a0 as ConnectedAccount, $ as ConnectedAccountsAPI, Y as ConversationPresentation, aH as DateTimeInputProps, D as Disposable, aN as DividerProps, J as EventsAPI, au as ExtensionActionCall, av as ExtensionActionRef, at as ExtensionComponentChildren, ar as ExtensionComponentData, as as ExtensionComponentIterator, aq as ExtensionComponentStyle, y as ExtensionContext, aw as ExtensionDataSource, ao as ExtensionModule, ax as ExtensionPanelDefinition, aW as FrameProps, aV as FrameVariant, aM as GridProps, ay as HeaderProps, aL as HorizontalStackProps, aQ as IconButtonProps, aP as IconButtonType, aJ as IconPickerProps, aO as IconProps, bh as KeyValueListProps, bg as KeyValueRow, az as LabelProps, aX as ListProps, L as LocalizedString, a2 as LogAPI, a$ as MarkdownProps, b1 as ModalProps, ag as ModelCapabilities, N as NetworkAPI, bm as NoteProps, bl as NoteVariant, aF as NumberInputProps, aR as PanelAction, m as PanelActionDataSource, l as PanelComponentView, P as PanelDefinition, aS as PanelProps, n as PanelUnknownView, k as PanelView, aB as ParagraphProps, aE as PasswordInputProps, aZ as PillProps, aY as PillVariant, bf as ProgressBarProps, be as ProgressColor, bd as ProgressShape, q as PromptContribution, s as PromptSection, p as ProviderConfigView, o as ProviderDefinition, B as ProvidersAPI, a9 as Query, aa as QueryOptions, K as SchedulerAPI, O as SchedulerJobRequest, Q as SchedulerSchedule, ac as SecretsAPI, aI as SelectProps, z as SettingsAPI, bc as StatTileProps, bb as StatTrend, j as StatusCardDefinition, ab as StorageAPI, ad as StorageCollectionConfig, ae as StorageContributions, aG as TextAreaProps, aD as TextInputProps, b0 as TextPreviewProps, bj as TimelineEntry, bk as TimelineProps, bi as TimelineVariant, aT as ToggleProps, al as Tool, am as ToolAttachment, aj as ToolCall, u as ToolConfirmationConfig, t as ToolDefinition, i as ToolSettingsActionDataSource, h as ToolSettingsComponentView, g as ToolSettingsListMapping, f as ToolSettingsListView, e as ToolSettingsView, d as ToolSettingsViewDefinition, F as ToolsAPI, U as UserAPI, R as UserProfile, aK as VerticalStackProps, ak as VoiceTransportRequest, b3 as WeatherCondition, b7 as WeatherForecastProps, b6 as WeatherForecastStep, b5 as WeatherNowProps, b4 as WeatherWind, r as resolveLocalizedString } from './types.tools-DcFBsfRV.cjs';
3
3
 
4
4
  /**
5
5
  * Permission Types
@@ -19,7 +19,15 @@ type UserDataPermission = 'user.profile.read' | 'user.list' | 'user.location.rea
19
19
  * not for reading what it says, which `core_read_attachment` does without an
20
20
  * extension.
21
21
  */
22
- | 'attachments.read';
22
+ | 'attachments.read'
23
+ /**
24
+ * Get access tokens for the external accounts the user has connected to Stina
25
+ * itself - a Microsoft account, say - for the scopes the extension declares under
26
+ * `contributes.accounts`. The user signs in once, in Stina's settings, and every
27
+ * extension that declares the provider can use that sign-in. Refresh tokens stay
28
+ * with the host.
29
+ */
30
+ | 'accounts.use';
23
31
  /** Capability permissions */
24
32
  type CapabilityPermission = 'provider.register' | 'tools.register' | 'tools.list' | 'tools.execute' | 'actions.register' | 'settings.register' | 'commands.register' | 'panels.register' | 'statusCards.register' | 'events.emit' | 'scheduler.register' | 'chat.message.write' | 'background.workers';
25
33
  /** System permissions */
@@ -220,7 +228,7 @@ interface RequestMessage {
220
228
  method: RequestMethod;
221
229
  payload: unknown;
222
230
  }
223
- type RequestMethod = 'network.fetch' | 'network.fetch-stream' | 'settings.getAll' | 'settings.get' | 'settings.set' | 'user.getProfile' | 'user.listIds' | 'events.emit' | 'scheduler.schedule' | 'scheduler.cancel' | 'scheduler.reportFireResult' | 'chat.appendInstruction' | 'database.execute' | 'storage.set' | 'storage.keys' | 'storage.setForUser' | 'storage.keysForUser' | 'storage.put' | 'storage.get' | 'storage.delete' | 'storage.find' | 'storage.findOne' | 'storage.count' | 'storage.putMany' | 'storage.deleteMany' | 'storage.dropCollection' | 'storage.listCollections' | 'storage.putForUser' | 'storage.getForUser' | 'storage.deleteForUser' | 'storage.findForUser' | 'storage.findOneForUser' | 'storage.countForUser' | 'storage.putManyForUser' | 'storage.deleteManyForUser' | 'storage.dropCollectionForUser' | 'storage.listCollectionsForUser' | 'secrets.set' | 'secrets.get' | 'secrets.delete' | 'secrets.list' | 'secrets.setForUser' | 'secrets.getForUser' | 'secrets.deleteForUser' | 'secrets.listForUser' | 'tools.list' | 'tools.execute' | 'attachments.read';
231
+ type RequestMethod = 'network.fetch' | 'network.fetch-stream' | 'settings.getAll' | 'settings.get' | 'settings.set' | 'user.getProfile' | 'user.listIds' | 'events.emit' | 'scheduler.schedule' | 'scheduler.cancel' | 'scheduler.reportFireResult' | 'chat.appendInstruction' | 'database.execute' | 'storage.set' | 'storage.keys' | 'storage.setForUser' | 'storage.keysForUser' | 'storage.put' | 'storage.get' | 'storage.delete' | 'storage.find' | 'storage.findOne' | 'storage.count' | 'storage.putMany' | 'storage.deleteMany' | 'storage.dropCollection' | 'storage.listCollections' | 'storage.putForUser' | 'storage.getForUser' | 'storage.deleteForUser' | 'storage.findForUser' | 'storage.findOneForUser' | 'storage.countForUser' | 'storage.putManyForUser' | 'storage.deleteManyForUser' | 'storage.dropCollectionForUser' | 'storage.listCollectionsForUser' | 'secrets.set' | 'secrets.get' | 'secrets.delete' | 'secrets.list' | 'secrets.setForUser' | 'secrets.getForUser' | 'secrets.deleteForUser' | 'secrets.listForUser' | 'tools.list' | 'tools.execute' | 'attachments.read' | 'accounts.list' | 'accounts.getAccessToken';
224
232
  interface ProviderRegisteredMessage {
225
233
  type: 'provider-registered';
226
234
  payload: {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { H as HugeIconName, E as ExtensionContributions, S as SchedulerFirePayload, C as ChatMessage, a as ChatOptions, G as GetModelsOptions, V as VoiceSessionOptions, b as StreamEvent, M as ModelInfo, c as VoiceSessionDescriptor, T as ToolResult, A as ActionResult } from './types.tools-R0xGhiBa.js';
2
- export { aa as AIProvider, ai as Action, B as ActionsAPI, ak as AllowedCSSProperty, Y as AttachmentContent, X as AttachmentsAPI, a3 as BackgroundRestartPolicy, a0 as BackgroundTaskCallback, $ as BackgroundTaskConfig, a1 as BackgroundTaskContext, a2 as BackgroundTaskHealth, _ as BackgroundWorkersAPI, ax as ButtonProps, bj as CalendarEventProps, bi as CalendarEventStatus, b3 as ChartKind, b5 as ChartProps, b4 as ChartSeries, Q as ChatAPI, ad as ChatFile, ac as ChatImage, R as ChatInstructionMessage, aV as CheckboxProps, av as ClockProps, aP as CollapsibleProps, v as CommandDefinition, aZ as ConditionalGroupProps, W as ConversationPresentation, aC as DateTimeInputProps, D as Disposable, aI as DividerProps, F as EventsAPI, ap as ExtensionActionCall, aq as ExtensionActionRef, ao as ExtensionComponentChildren, am as ExtensionComponentData, an as ExtensionComponentIterator, al as ExtensionComponentStyle, w as ExtensionContext, ar as ExtensionDataSource, aj as ExtensionModule, as as ExtensionPanelDefinition, aR as FrameProps, aQ as FrameVariant, aH as GridProps, at as HeaderProps, aG as HorizontalStackProps, aL as IconButtonProps, aK as IconButtonType, aE as IconPickerProps, aJ as IconProps, bc as KeyValueListProps, bb as KeyValueRow, au as LabelProps, aS as ListProps, L as LocalizedString, Z as LogAPI, aW as MarkdownProps, aY as ModalProps, ab as ModelCapabilities, N as NetworkAPI, bh as NoteProps, bg as NoteVariant, aA as NumberInputProps, aM as PanelAction, m as PanelActionDataSource, l as PanelComponentView, P as PanelDefinition, aN as PanelProps, n as PanelUnknownView, k as PanelView, aw as ParagraphProps, az as PasswordInputProps, aU as PillProps, aT as PillVariant, ba as ProgressBarProps, b9 as ProgressColor, b8 as ProgressShape, q as PromptContribution, s as PromptSection, p as ProviderConfigView, o as ProviderDefinition, y as ProvidersAPI, a4 as Query, a5 as QueryOptions, I as SchedulerAPI, J as SchedulerJobRequest, K as SchedulerSchedule, a7 as SecretsAPI, aD as SelectProps, x as SettingsAPI, b7 as StatTileProps, b6 as StatTrend, j as StatusCardDefinition, a6 as StorageAPI, a8 as StorageCollectionConfig, a9 as StorageContributions, aB as TextAreaProps, ay as TextInputProps, aX as TextPreviewProps, be as TimelineEntry, bf as TimelineProps, bd as TimelineVariant, aO as ToggleProps, ag as Tool, ah as ToolAttachment, ae as ToolCall, u as ToolConfirmationConfig, t as ToolDefinition, i as ToolSettingsActionDataSource, h as ToolSettingsComponentView, g as ToolSettingsListMapping, f as ToolSettingsListView, e as ToolSettingsView, d as ToolSettingsViewDefinition, z as ToolsAPI, U as UserAPI, O as UserProfile, aF as VerticalStackProps, af as VoiceTransportRequest, a_ as WeatherCondition, b2 as WeatherForecastProps, b1 as WeatherForecastStep, b0 as WeatherNowProps, a$ as WeatherWind, r as resolveLocalizedString } from './types.tools-R0xGhiBa.js';
1
+ import { H as HugeIconName, E as ExtensionContributions, S as SchedulerFirePayload, C as ChatMessage, a as ChatOptions, G as GetModelsOptions, V as VoiceSessionOptions, b as StreamEvent, M as ModelInfo, c as VoiceSessionDescriptor, T as ToolResult, A as ActionResult } from './types.tools-DcFBsfRV.js';
2
+ export { af as AIProvider, a1 as AccountAccessToken, x as AccountContribution, w as AccountProvider, an as Action, I as ActionsAPI, ap as AllowedCSSProperty, _ as AttachmentContent, Z as AttachmentsAPI, a8 as BackgroundRestartPolicy, a5 as BackgroundTaskCallback, a4 as BackgroundTaskConfig, a6 as BackgroundTaskContext, a7 as BackgroundTaskHealth, a3 as BackgroundWorkersAPI, aC as ButtonProps, bo as CalendarEventProps, bn as CalendarEventStatus, b8 as ChartKind, ba as ChartProps, b9 as ChartSeries, W as ChatAPI, ai as ChatFile, ah as ChatImage, X as ChatInstructionMessage, a_ as CheckboxProps, aA as ClockProps, aU as CollapsibleProps, v as CommandDefinition, b2 as ConditionalGroupProps, a0 as ConnectedAccount, $ as ConnectedAccountsAPI, Y as ConversationPresentation, aH as DateTimeInputProps, D as Disposable, aN as DividerProps, J as EventsAPI, au as ExtensionActionCall, av as ExtensionActionRef, at as ExtensionComponentChildren, ar as ExtensionComponentData, as as ExtensionComponentIterator, aq as ExtensionComponentStyle, y as ExtensionContext, aw as ExtensionDataSource, ao as ExtensionModule, ax as ExtensionPanelDefinition, aW as FrameProps, aV as FrameVariant, aM as GridProps, ay as HeaderProps, aL as HorizontalStackProps, aQ as IconButtonProps, aP as IconButtonType, aJ as IconPickerProps, aO as IconProps, bh as KeyValueListProps, bg as KeyValueRow, az as LabelProps, aX as ListProps, L as LocalizedString, a2 as LogAPI, a$ as MarkdownProps, b1 as ModalProps, ag as ModelCapabilities, N as NetworkAPI, bm as NoteProps, bl as NoteVariant, aF as NumberInputProps, aR as PanelAction, m as PanelActionDataSource, l as PanelComponentView, P as PanelDefinition, aS as PanelProps, n as PanelUnknownView, k as PanelView, aB as ParagraphProps, aE as PasswordInputProps, aZ as PillProps, aY as PillVariant, bf as ProgressBarProps, be as ProgressColor, bd as ProgressShape, q as PromptContribution, s as PromptSection, p as ProviderConfigView, o as ProviderDefinition, B as ProvidersAPI, a9 as Query, aa as QueryOptions, K as SchedulerAPI, O as SchedulerJobRequest, Q as SchedulerSchedule, ac as SecretsAPI, aI as SelectProps, z as SettingsAPI, bc as StatTileProps, bb as StatTrend, j as StatusCardDefinition, ab as StorageAPI, ad as StorageCollectionConfig, ae as StorageContributions, aG as TextAreaProps, aD as TextInputProps, b0 as TextPreviewProps, bj as TimelineEntry, bk as TimelineProps, bi as TimelineVariant, aT as ToggleProps, al as Tool, am as ToolAttachment, aj as ToolCall, u as ToolConfirmationConfig, t as ToolDefinition, i as ToolSettingsActionDataSource, h as ToolSettingsComponentView, g as ToolSettingsListMapping, f as ToolSettingsListView, e as ToolSettingsView, d as ToolSettingsViewDefinition, F as ToolsAPI, U as UserAPI, R as UserProfile, aK as VerticalStackProps, ak as VoiceTransportRequest, b3 as WeatherCondition, b7 as WeatherForecastProps, b6 as WeatherForecastStep, b5 as WeatherNowProps, b4 as WeatherWind, r as resolveLocalizedString } from './types.tools-DcFBsfRV.js';
3
3
 
4
4
  /**
5
5
  * Permission Types
@@ -19,7 +19,15 @@ type UserDataPermission = 'user.profile.read' | 'user.list' | 'user.location.rea
19
19
  * not for reading what it says, which `core_read_attachment` does without an
20
20
  * extension.
21
21
  */
22
- | 'attachments.read';
22
+ | 'attachments.read'
23
+ /**
24
+ * Get access tokens for the external accounts the user has connected to Stina
25
+ * itself - a Microsoft account, say - for the scopes the extension declares under
26
+ * `contributes.accounts`. The user signs in once, in Stina's settings, and every
27
+ * extension that declares the provider can use that sign-in. Refresh tokens stay
28
+ * with the host.
29
+ */
30
+ | 'accounts.use';
23
31
  /** Capability permissions */
24
32
  type CapabilityPermission = 'provider.register' | 'tools.register' | 'tools.list' | 'tools.execute' | 'actions.register' | 'settings.register' | 'commands.register' | 'panels.register' | 'statusCards.register' | 'events.emit' | 'scheduler.register' | 'chat.message.write' | 'background.workers';
25
33
  /** System permissions */
@@ -220,7 +228,7 @@ interface RequestMessage {
220
228
  method: RequestMethod;
221
229
  payload: unknown;
222
230
  }
223
- type RequestMethod = 'network.fetch' | 'network.fetch-stream' | 'settings.getAll' | 'settings.get' | 'settings.set' | 'user.getProfile' | 'user.listIds' | 'events.emit' | 'scheduler.schedule' | 'scheduler.cancel' | 'scheduler.reportFireResult' | 'chat.appendInstruction' | 'database.execute' | 'storage.set' | 'storage.keys' | 'storage.setForUser' | 'storage.keysForUser' | 'storage.put' | 'storage.get' | 'storage.delete' | 'storage.find' | 'storage.findOne' | 'storage.count' | 'storage.putMany' | 'storage.deleteMany' | 'storage.dropCollection' | 'storage.listCollections' | 'storage.putForUser' | 'storage.getForUser' | 'storage.deleteForUser' | 'storage.findForUser' | 'storage.findOneForUser' | 'storage.countForUser' | 'storage.putManyForUser' | 'storage.deleteManyForUser' | 'storage.dropCollectionForUser' | 'storage.listCollectionsForUser' | 'secrets.set' | 'secrets.get' | 'secrets.delete' | 'secrets.list' | 'secrets.setForUser' | 'secrets.getForUser' | 'secrets.deleteForUser' | 'secrets.listForUser' | 'tools.list' | 'tools.execute' | 'attachments.read';
231
+ type RequestMethod = 'network.fetch' | 'network.fetch-stream' | 'settings.getAll' | 'settings.get' | 'settings.set' | 'user.getProfile' | 'user.listIds' | 'events.emit' | 'scheduler.schedule' | 'scheduler.cancel' | 'scheduler.reportFireResult' | 'chat.appendInstruction' | 'database.execute' | 'storage.set' | 'storage.keys' | 'storage.setForUser' | 'storage.keysForUser' | 'storage.put' | 'storage.get' | 'storage.delete' | 'storage.find' | 'storage.findOne' | 'storage.count' | 'storage.putMany' | 'storage.deleteMany' | 'storage.dropCollection' | 'storage.listCollections' | 'storage.putForUser' | 'storage.getForUser' | 'storage.deleteForUser' | 'storage.findForUser' | 'storage.findOneForUser' | 'storage.countForUser' | 'storage.putManyForUser' | 'storage.deleteManyForUser' | 'storage.dropCollectionForUser' | 'storage.listCollectionsForUser' | 'secrets.set' | 'secrets.get' | 'secrets.delete' | 'secrets.list' | 'secrets.setForUser' | 'secrets.getForUser' | 'secrets.deleteForUser' | 'secrets.listForUser' | 'tools.list' | 'tools.execute' | 'attachments.read' | 'accounts.list' | 'accounts.getAccessToken';
224
232
  interface ProviderRegisteredMessage {
225
233
  type: 'provider-registered';
226
234
  payload: {
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  generateMessageId
3
- } from "./chunk-3Q3YXWOH.js";
3
+ } from "./chunk-S3YP4QPF.js";
4
4
  import "./chunk-DGUM43GV.js";
5
5
 
6
6
  // src/types.localization.ts
package/dist/runtime.cjs CHANGED
@@ -139,6 +139,7 @@ var WorkerBackgroundTaskManager = class {
139
139
  userStorage,
140
140
  secrets,
141
141
  userSecrets,
142
+ ...config.userId && this.options.createUserAccountsAPI ? { accounts: this.options.createUserAccountsAPI(config.userId) } : {},
142
143
  signal,
143
144
  reportHealth: (status) => {
144
145
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
@@ -272,8 +273,22 @@ function buildUserSecretsAPI(sendRequest2, userId) {
272
273
  };
273
274
  }
274
275
 
276
+ // src/runtime/accountsApi.ts
277
+ function buildUserAccountsAPI(sendRequest2, userId) {
278
+ return {
279
+ async list(provider) {
280
+ return sendRequest2("accounts.list", { provider, userId });
281
+ },
282
+ async getAccessToken(accountId) {
283
+ return sendRequest2("accounts.getAccessToken", { accountId, userId });
284
+ }
285
+ };
286
+ }
287
+
275
288
  // src/runtime/executionContext.ts
276
- function createExecutionContext(sendRequest2, extensionContext2, userId, canReadAttachments = false) {
289
+ function createExecutionContext(sendRequest2, extensionContext2, userId, granted = []) {
290
+ const canReadAttachments = granted.includes("attachments.read");
291
+ const canUseAccounts = granted.includes("accounts.use");
277
292
  return {
278
293
  userId,
279
294
  extension: {
@@ -296,7 +311,9 @@ function createExecutionContext(sendRequest2, extensionContext2, userId, canRead
296
311
  });
297
312
  }
298
313
  }
299
- } : {}
314
+ } : {},
315
+ // Scoped to a user for the same reason: a connected account is somebody's.
316
+ ...canUseAccounts && userId ? { accounts: buildUserAccountsAPI(sendRequest2, userId) } : {}
300
317
  };
301
318
  }
302
319
 
@@ -484,7 +501,7 @@ async function handleSchedulerFire(payload) {
484
501
  sendRequest,
485
502
  extensionContext,
486
503
  payload.userId,
487
- grantedPermissions.includes("attachments.read")
504
+ grantedPermissions
488
505
  );
489
506
  const results = await Promise.allSettled(
490
507
  schedulerCallbacks.map((callback) => Promise.resolve(callback(payload, execContext)))
@@ -636,7 +653,7 @@ async function handleToolExecuteRequest(requestId, payload) {
636
653
  sendRequest,
637
654
  extensionContext,
638
655
  payload.userId,
639
- grantedPermissions.includes("attachments.read")
656
+ grantedPermissions
640
657
  );
641
658
  const result = await tool.execute(payload.params, execContext);
642
659
  postMessage({
@@ -676,7 +693,7 @@ async function handleActionExecuteRequest(requestId, payload) {
676
693
  sendRequest,
677
694
  extensionContext,
678
695
  payload.userId,
679
- grantedPermissions.includes("attachments.read")
696
+ grantedPermissions
680
697
  );
681
698
  const result = await action.execute(payload.params, execContext);
682
699
  postMessage({
@@ -978,7 +995,8 @@ function buildContext(extensionId, extensionVersion, storagePath, permissions) {
978
995
  createStorageAPI: () => buildExtensionStorageAPI(sendRequest),
979
996
  createUserStorageAPI: (userId) => buildUserStorageAPI(sendRequest, userId),
980
997
  createSecretsAPI: () => buildExtensionSecretsAPI(sendRequest),
981
- createUserSecretsAPI: (userId) => buildUserSecretsAPI(sendRequest, userId)
998
+ createUserSecretsAPI: (userId) => buildUserSecretsAPI(sendRequest, userId),
999
+ ...hasPermission("accounts.use") ? { createUserAccountsAPI: (userId) => buildUserAccountsAPI(sendRequest, userId) } : {}
982
1000
  });
983
1001
  }
984
1002
  const backgroundWorkersApi = {