@stina/extension-api 0.7.1 → 0.8.1

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/src/types.ts CHANGED
@@ -43,6 +43,8 @@ export interface ExtensionContributions {
43
43
  settings?: SettingDefinition[]
44
44
  /** Tool settings views for UI */
45
45
  toolSettings?: ToolSettingsViewDefinition[]
46
+ /** Right panel contributions */
47
+ panels?: PanelDefinition[]
46
48
  /** AI providers */
47
49
  providers?: ProviderDefinition[]
48
50
  /** Tools for Stina to use */
@@ -69,6 +71,22 @@ export interface SettingDefinition {
69
71
  default?: unknown
70
72
  /** For select type: available options */
71
73
  options?: { value: string; label: string }[]
74
+ /** For select type: load options from tool */
75
+ optionsToolId?: string
76
+ /** Params for options tool */
77
+ optionsParams?: Record<string, unknown>
78
+ /** Mapping for options tool response */
79
+ optionsMapping?: SettingOptionsMapping
80
+ /** Tool ID for creating a new option */
81
+ createToolId?: string
82
+ /** Label for create action */
83
+ createLabel?: string
84
+ /** Fields for create form */
85
+ createFields?: SettingDefinition[]
86
+ /** Static params always sent to create tool */
87
+ createParams?: Record<string, unknown>
88
+ /** Mapping for create tool response */
89
+ createMapping?: SettingCreateMapping
72
90
  /** Validation rules */
73
91
  validation?: {
74
92
  required?: boolean
@@ -78,6 +96,30 @@ export interface SettingDefinition {
78
96
  }
79
97
  }
80
98
 
99
+ /**
100
+ * Mapping for select field options from tool response
101
+ */
102
+ export interface SettingOptionsMapping {
103
+ /** Key for items array in tool result data */
104
+ itemsKey: string
105
+ /** Key for option value */
106
+ valueKey: string
107
+ /** Key for option label */
108
+ labelKey: string
109
+ /** Optional key for description */
110
+ descriptionKey?: string
111
+ }
112
+
113
+ /**
114
+ * Mapping for create tool response
115
+ */
116
+ export interface SettingCreateMapping {
117
+ /** Key for result data object */
118
+ resultKey?: string
119
+ /** Key for option value (defaults to "id") */
120
+ valueKey: string
121
+ }
122
+
81
123
  /**
82
124
  * Tool settings view definition (UI schema)
83
125
  */
@@ -143,6 +185,57 @@ export interface ToolSettingsListMapping {
143
185
  secondaryKey?: string
144
186
  }
145
187
 
188
+ /**
189
+ * Panel definition for right panel views
190
+ */
191
+ export interface PanelDefinition {
192
+ /** Unique panel ID within the extension */
193
+ id: string
194
+ /** Display title */
195
+ title: string
196
+ /** Icon name (from huge-icons) */
197
+ icon?: string
198
+ /** Panel view schema */
199
+ view: PanelView
200
+ }
201
+
202
+ /**
203
+ * Panel view schema (declarative)
204
+ */
205
+ export type PanelView = PanelComponentView | PanelUnknownView
206
+
207
+ export interface PanelUnknownView {
208
+ /** View kind */
209
+ kind: string
210
+ /** Additional view configuration */
211
+ [key: string]: unknown
212
+ }
213
+
214
+ /**
215
+ * Action-based data source for declarative panels.
216
+ * Uses actions (not tools) to fetch data.
217
+ */
218
+ export interface PanelActionDataSource {
219
+ /** Action ID to call for fetching data */
220
+ action: string
221
+ /** Parameters to pass to the action */
222
+ params?: Record<string, unknown>
223
+ /** Event names that should trigger a refresh of this data */
224
+ refreshOn?: string[]
225
+ }
226
+
227
+ /**
228
+ * Component-based panel view using the declarative DSL.
229
+ * Data is fetched via actions, content is rendered via ExtensionComponent.
230
+ */
231
+ export interface PanelComponentView {
232
+ kind: 'component'
233
+ /** Data sources available in the panel. Keys become variable names (e.g., "$projects"). */
234
+ data?: Record<string, PanelActionDataSource>
235
+ /** Root component to render */
236
+ content: import('./types.components.js').ExtensionComponentData
237
+ }
238
+
146
239
  /**
147
240
  * Provider definition (metadata only, implementation in code)
148
241
  */
@@ -315,8 +408,13 @@ export type UserDataPermission =
315
408
  export type CapabilityPermission =
316
409
  | 'provider.register'
317
410
  | 'tools.register'
411
+ | 'actions.register'
318
412
  | 'settings.register'
319
413
  | 'commands.register'
414
+ | 'panels.register'
415
+ | 'events.emit'
416
+ | 'scheduler.register'
417
+ | 'chat.message.write'
320
418
 
321
419
  /** System permissions */
322
420
  export type SystemPermission =
@@ -359,6 +457,21 @@ export interface ExtensionContext {
359
457
  /** Tool registration (if permitted) */
360
458
  readonly tools?: ToolsAPI
361
459
 
460
+ /** Action registration (if permitted) */
461
+ readonly actions?: ActionsAPI
462
+
463
+ /** Event emission (if permitted) */
464
+ readonly events?: EventsAPI
465
+
466
+ /** Scheduler access (if permitted) */
467
+ readonly scheduler?: SchedulerAPI
468
+
469
+ /** User data access (if permitted) */
470
+ readonly user?: UserAPI
471
+
472
+ /** Chat access (if permitted) */
473
+ readonly chat?: ChatAPI
474
+
362
475
  /** Database access (if permitted) */
363
476
  readonly database?: DatabaseAPI
364
477
 
@@ -424,6 +537,96 @@ export interface ToolsAPI {
424
537
  register(tool: Tool): Disposable
425
538
  }
426
539
 
540
+ /**
541
+ * Actions API for registering UI actions
542
+ */
543
+ export interface ActionsAPI {
544
+ /**
545
+ * Register an action that UI components can invoke
546
+ */
547
+ register(action: Action): Disposable
548
+ }
549
+
550
+ /**
551
+ * Events API for notifying the host
552
+ */
553
+ export interface EventsAPI {
554
+ /**
555
+ * Emit a named event with optional payload
556
+ */
557
+ emit(name: string, payload?: Record<string, unknown>): Promise<void>
558
+ }
559
+
560
+ /**
561
+ * Scheduler schedule types
562
+ */
563
+ export type SchedulerSchedule =
564
+ | { type: 'at'; at: string }
565
+ | { type: 'cron'; cron: string; timezone?: string }
566
+ | { type: 'interval'; everyMs: number }
567
+
568
+ /**
569
+ * Scheduler job request
570
+ */
571
+ export interface SchedulerJobRequest {
572
+ id: string
573
+ schedule: SchedulerSchedule
574
+ payload?: Record<string, unknown>
575
+ misfire?: 'run_once' | 'skip'
576
+ }
577
+
578
+ /**
579
+ * Scheduler fire payload
580
+ */
581
+ export interface SchedulerFirePayload {
582
+ id: string
583
+ payload?: Record<string, unknown>
584
+ scheduledFor: string
585
+ firedAt: string
586
+ delayMs: number
587
+ }
588
+
589
+ /**
590
+ * Scheduler API for registering jobs
591
+ */
592
+ export interface SchedulerAPI {
593
+ schedule(job: SchedulerJobRequest): Promise<void>
594
+ cancel(jobId: string): Promise<void>
595
+ onFire(callback: (payload: SchedulerFirePayload) => void): Disposable
596
+ }
597
+
598
+ /**
599
+ * User profile data
600
+ */
601
+ export interface UserProfile {
602
+ firstName?: string
603
+ nickname?: string
604
+ language?: string
605
+ timezone?: string
606
+ }
607
+
608
+ /**
609
+ * User API for profile access
610
+ */
611
+ export interface UserAPI {
612
+ getProfile(): Promise<UserProfile>
613
+ }
614
+
615
+ /**
616
+ * Chat instruction message
617
+ */
618
+ export interface ChatInstructionMessage {
619
+ text: string
620
+ conversationId?: string
621
+ }
622
+
623
+ /**
624
+ * Chat API for appending instructions
625
+ */
626
+ export interface ChatAPI {
627
+ appendInstruction(message: ChatInstructionMessage): Promise<void>
628
+ }
629
+
427
630
  /**
428
631
  * Database API for extension-specific tables
429
632
  */
@@ -614,6 +817,37 @@ export interface ToolResult {
614
817
  error?: string
615
818
  }
616
819
 
820
+ // ============================================================================
821
+ // Action Types (for UI interactions, separate from Tools)
822
+ // ============================================================================
823
+
824
+ /**
825
+ * Action implementation for UI interactions.
826
+ * Actions are invoked by UI components, not by Stina (AI).
827
+ */
828
+ export interface Action {
829
+ /** Action ID (unique within the extension) */
830
+ id: string
831
+
832
+ /**
833
+ * Execute the action
834
+ * @param params Parameters from the UI component (with $-values already resolved)
835
+ */
836
+ execute(params: Record<string, unknown>): Promise<ActionResult>
837
+ }
838
+
839
+ /**
840
+ * Action execution result
841
+ */
842
+ export interface ActionResult {
843
+ /** Whether the action succeeded */
844
+ success: boolean
845
+ /** Result data (returned to UI) */
846
+ data?: unknown
847
+ /** Error message if failed */
848
+ error?: string
849
+ }
850
+
617
851
  // ============================================================================
618
852
  // Extension Entry Point
619
853
  // ============================================================================
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/messages.ts"],"sourcesContent":["/**\n * Message protocol between Extension Host and Extension Workers\n */\n\nimport type { ChatMessage, ChatOptions, GetModelsOptions, StreamEvent, ToolResult, ModelInfo } from './types.js'\n\n// ============================================================================\n// Host → Worker Messages\n// ============================================================================\n\nexport type HostToWorkerMessage =\n | ActivateMessage\n | DeactivateMessage\n | SettingsChangedMessage\n | ProviderChatRequestMessage\n | ProviderModelsRequestMessage\n | ToolExecuteRequestMessage\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 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 }\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 | StreamEventMessage\n | LogMessage\n | ProviderModelsResponseMessage\n | ToolExecuteResponseMessage\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 | 'database.execute'\n | 'storage.get'\n | 'storage.set'\n | 'storage.delete'\n | 'storage.keys'\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 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 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":";;;;;;;;AA0LO,SAAS,oBAA4B;AAC1C,SAAO,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACjE;","names":[]}