@stina/extension-api 0.58.0 → 1.3.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.
@@ -176,6 +176,27 @@ export const PanelDefinitionSchema = z
176
176
  })
177
177
  .describe('Panel definition')
178
178
 
179
+ /**
180
+ * A card for the strip above the conversation list.
181
+ *
182
+ * Deliberately the panel's component view rather than a profile of its own: a
183
+ * card and a panel are the same declarative idea at two sizes, and a second
184
+ * vocabulary would be a second thing to keep in step. `size` is what makes it a
185
+ * card, and it is checked rather than suggested because the sidebar is a few
186
+ * hundred pixels wide.
187
+ */
188
+ export const StatusCardDefinitionSchema = z
189
+ .object({
190
+ id: z.string().describe('Unique card ID within the extension'),
191
+ title: z.string().describe('What it is called where the user picks it'),
192
+ icon: z.string().optional().describe('Icon name (from huge-icons)'),
193
+ size: z
194
+ .enum(['line', 'block'])
195
+ .describe('How much room it may take: one row, or up to three'),
196
+ view: PanelComponentViewSchema.describe('What it draws, and where the data comes from'),
197
+ })
198
+ .describe('Status card definition')
199
+
179
200
  // =============================================================================
180
201
  // Providers
181
202
  // =============================================================================
@@ -294,6 +315,10 @@ export const ExtensionContributionsSchema = z
294
315
  .object({
295
316
  toolSettings: z.array(ToolSettingsViewDefinitionSchema).optional().describe('Tool settings views'),
296
317
  panels: z.array(PanelDefinitionSchema).optional().describe('Right panel contributions'),
318
+ statusCards: z
319
+ .array(StatusCardDefinitionSchema)
320
+ .optional()
321
+ .describe('Cards for the strip above the conversation list'),
297
322
  providers: z.array(ProviderDefinitionSchema).optional().describe('AI providers'),
298
323
  tools: z.array(ToolDefinitionSchema).optional().describe('Tools for Stina to use'),
299
324
  commands: z.array(CommandDefinitionSchema).optional().describe('Slash commands'),
@@ -306,6 +331,7 @@ export const ExtensionContributionsSchema = z
306
331
  // Type Exports
307
332
  // =============================================================================
308
333
 
334
+ export type StatusCardDefinition = z.infer<typeof StatusCardDefinitionSchema>
309
335
  export type LocalizedString = z.infer<typeof LocalizedStringSchema>
310
336
  export type ToolSettingsListMapping = z.infer<typeof ToolSettingsListMappingSchema>
311
337
  export type ToolSettingsActionDataSource = z.infer<typeof ToolSettingsActionDataSourceSchema>
@@ -47,6 +47,7 @@ export {
47
47
  ToolSettingsListMappingSchema,
48
48
  ToolSettingsActionDataSourceSchema,
49
49
  PanelDefinitionSchema,
50
+ StatusCardDefinitionSchema,
50
51
  PanelViewSchema,
51
52
  PanelComponentViewSchema,
52
53
  PanelUnknownViewSchema,
@@ -67,6 +68,7 @@ export {
67
68
  type ToolSettingsListMapping,
68
69
  type ToolSettingsActionDataSource,
69
70
  type PanelDefinition,
71
+ type StatusCardDefinition,
70
72
  type PanelView,
71
73
  type PanelComponentView,
72
74
  type PanelUnknownView,
@@ -94,6 +96,7 @@ export {
94
96
  PanelActionSchema,
95
97
  HeaderPropsSchema,
96
98
  LabelPropsSchema,
99
+ ClockPropsSchema,
97
100
  ParagraphPropsSchema,
98
101
  ButtonPropsSchema,
99
102
  TextInputPropsSchema,
@@ -128,6 +131,9 @@ export {
128
131
  ChartPropsSchema,
129
132
  StatTrendSchema,
130
133
  StatTilePropsSchema,
134
+ ProgressShapeSchema,
135
+ ProgressColorSchema,
136
+ ProgressBarPropsSchema,
131
137
  KeyValueRowSchema,
132
138
  KeyValueListPropsSchema,
133
139
  TimelineVariantSchema,
@@ -150,6 +156,7 @@ export {
150
156
  type PanelAction,
151
157
  type HeaderProps,
152
158
  type LabelProps,
159
+ type ClockProps,
153
160
  type ParagraphProps,
154
161
  type ButtonProps,
155
162
  type TextInputProps,
@@ -181,8 +188,10 @@ export {
181
188
  ChatCardSchema,
182
189
  ChatCardComponentSchema,
183
190
  CHAT_CARD_COMPONENTS,
191
+ CHAT_CARD_PROPS,
184
192
  validateChatCard,
185
193
  describeChatCardProfile,
186
194
  type ChatCardComponent,
187
195
  type ChatCardValidation,
188
196
  } from './card.schema.js'
197
+
@@ -29,6 +29,7 @@ export const VALID_PERMISSIONS = [
29
29
  'settings.register',
30
30
  'commands.register',
31
31
  'panels.register',
32
+ 'statusCards.register',
32
33
  'events.emit',
33
34
  'scheduler.register',
34
35
  'background.workers',
@@ -90,6 +91,7 @@ const CapabilityPermissionSchema = z
90
91
  'settings.register',
91
92
  'commands.register',
92
93
  'panels.register',
94
+ 'statusCards.register',
93
95
  'events.emit',
94
96
  'scheduler.register',
95
97
  'chat.message.write',
@@ -251,6 +251,19 @@ export interface LabelProps extends ExtensionComponentData {
251
251
  text: string
252
252
  }
253
253
 
254
+ /**
255
+ * The extension API properties for the Clock component.
256
+ *
257
+ * The odd one out among the display components: it takes no facts, because the
258
+ * fact it shows is what time it is, and that is not something an action can
259
+ * hand over once. It reads the clock and the timezone from the host and keeps
260
+ * itself current, so a card carrying one stays right while the window is left
261
+ * open.
262
+ */
263
+ export interface ClockProps extends ExtensionComponentData {
264
+ component: 'Clock'
265
+ }
266
+
254
267
  /** The extension API properties for the paragraph component. */
255
268
  export interface ParagraphProps extends ExtensionComponentData {
256
269
  component: 'Paragraph'
@@ -731,6 +744,53 @@ export interface StatTileProps extends ExtensionComponentData {
731
744
  trendIsGood?: boolean
732
745
  }
733
746
 
747
+ /** Whether a progress reading is drawn as a rail or as a ring. */
748
+ export type ProgressShape = 'bar' | 'circle'
749
+
750
+ /**
751
+ * The colours a progress reading may take.
752
+ *
753
+ * A closed list rather than a colour string: the caller is usually a language
754
+ * model, and the six names here are the six the themes actually define, so a
755
+ * reading cannot end up in a hue the current theme has no contrast for.
756
+ */
757
+ export type ProgressColor = 'accent' | 'success' | 'warning' | 'danger' | 'info' | 'neutral'
758
+
759
+ /**
760
+ * The extension API properties for the ProgressBar component.
761
+ *
762
+ * One value seen against the range it lives in — how far along something is,
763
+ * how loaded a day looks, how high a level sits. A StatTile says what the
764
+ * number *is*; this says where it *sits*, which is the thing a number alone
765
+ * cannot show.
766
+ *
767
+ * `min` and `max` are the range, not decoration: a value is drawn as its
768
+ * position between them, so "3 of 5" and "60 of 100" fill the same amount.
769
+ * Values outside the range are clamped rather than refused — a reading that
770
+ * ran past its ceiling should still draw as full.
771
+ */
772
+ export interface ProgressBarProps extends ExtensionComponentData {
773
+ component: 'ProgressBar'
774
+ /** What is being measured, e.g. "Stressnivå". Shown beside the reading. */
775
+ label: string
776
+ value: number
777
+ /** Bottom of the range. Defaults to 0. */
778
+ min?: number
779
+ /** Top of the range. Defaults to 100. */
780
+ max?: number
781
+ /** Defaults to `bar`. */
782
+ shape?: ProgressShape
783
+ /** Defaults to `accent`. */
784
+ color?: ProgressColor
785
+ /** Written after the value, e.g. `%` or ` av 5`. */
786
+ unit?: string
787
+ /** The readout in words, when the bare number does not say it. Replaces value and unit. */
788
+ valueLabel?: string
789
+ /** One quiet line under the reading. */
790
+ caption?: string
791
+ icon?: HugeIconName
792
+ }
793
+
734
794
  /** One row of a KeyValueList. */
735
795
  export interface KeyValueRow {
736
796
  label: string
@@ -13,6 +13,8 @@ import type { ExtensionComponentData } from './types.components.js'
13
13
  export interface ExtensionContributions {
14
14
  /** Tool settings views for UI */
15
15
  toolSettings?: ToolSettingsViewDefinition[]
16
+ /** Cards for the strip above the conversation list */
17
+ statusCards?: StatusCardDefinition[]
16
18
  /** Right panel contributions */
17
19
  panels?: PanelDefinition[]
18
20
  /** AI providers */
@@ -170,6 +172,39 @@ export interface PanelDefinition {
170
172
  view: PanelView
171
173
  }
172
174
 
175
+ /**
176
+ * A card for the strip above the conversation list.
177
+ *
178
+ * The same declarative machinery as a panel, in a much smaller space and with
179
+ * one rule that is not a style guide: a card says what is true right now. It
180
+ * has no controls, because a sidebar is read in passing and anything the user
181
+ * wants to do about what it says, they say in words.
182
+ *
183
+ * The user chooses which cards they want and in what order, so an extension
184
+ * offering three is offering three, not imposing them.
185
+ */
186
+ export interface StatusCardDefinition {
187
+ /** Unique card ID within the extension */
188
+ id: string
189
+ /** What it is called where the user picks it */
190
+ title: string
191
+ /** Icon name (from huge-icons) */
192
+ icon?: string
193
+ /**
194
+ * How much room it may take.
195
+ *
196
+ * Part of the contract rather than a guideline, because the sidebar is a few
197
+ * hundred pixels wide and the first card written without a limit will be
198
+ * written against a screen.
199
+ *
200
+ * - `line`: one row. A figure, a label, a pill.
201
+ * - `block`: up to three rows.
202
+ */
203
+ size: 'line' | 'block'
204
+ /** What it draws, and where the data comes from */
205
+ view: PanelComponentView
206
+ }
207
+
173
208
  /**
174
209
  * Panel view schema (declarative)
175
210
  */
@@ -39,6 +39,7 @@ export type CapabilityPermission =
39
39
  | 'settings.register'
40
40
  | 'commands.register'
41
41
  | 'panels.register'
42
+ | 'statusCards.register'
42
43
  | 'events.emit'
43
44
  | 'scheduler.register'
44
45
  | 'chat.message.write'
@@ -73,6 +73,34 @@ export interface ToolResult {
73
73
  * would send her after a component that does not exist.
74
74
  */
75
75
  cardSuggestion?: string
76
+
77
+ /**
78
+ * Pictures to show the user, rendered in the conversation where the tool ran.
79
+ *
80
+ * For what a card cannot hold and the model cannot reproduce: a generated
81
+ * image, a rendered document, a photo fetched on the user's behalf. Like
82
+ * {@link ToolResult.display}, this is for the user only — it is lifted out
83
+ * before the result reaches the model, which would have nothing to do with
84
+ * the bytes but spend tokens on them. Say in `data` that a picture was shown,
85
+ * so she can talk about it without describing it back.
86
+ *
87
+ * The host stores each one as an attachment of the conversation, the same way
88
+ * a picture the user sends is stored, so it is served to every client and can
89
+ * be saved or shared from there. JPEG and PNG only, and 20 MB at most, since
90
+ * those are the limits the attachment store already holds users to. One that
91
+ * fails them is dropped with a warning rather than half-shown.
92
+ */
93
+ attachments?: ToolAttachment[]
94
+ }
95
+
96
+ /**
97
+ * One picture a tool wants shown. See {@link ToolResult.attachments}.
98
+ */
99
+ export interface ToolAttachment {
100
+ /** The image bytes, base64 encoded. The format is read from the bytes. */
101
+ data: string
102
+ /** A file name to offer when the user saves it, e.g. `friday.png`. */
103
+ name?: string
76
104
  }
77
105
 
78
106
  /**
package/src/types.ts CHANGED
@@ -31,6 +31,7 @@ export type {
31
31
  ToolSettingsActionDataSource,
32
32
  // Panels
33
33
  PanelDefinition,
34
+ StatusCardDefinition,
34
35
  PanelView,
35
36
  PanelUnknownView,
36
37
  PanelActionDataSource,
@@ -68,7 +69,7 @@ export type {
68
69
  } from './types.provider.js'
69
70
 
70
71
  // Tools and Actions
71
- export type { Tool, ToolResult, Action, ActionResult } from './types.tools.js'
72
+ export type { Tool, ToolResult, ToolAttachment, Action, ActionResult } from './types.tools.js'
72
73
 
73
74
  // Context and APIs
74
75
  export type {