@stina/extension-api 1.3.1 → 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.
- package/dist/{chunk-ZB7GJUPS.js → chunk-S3YP4QPF.js} +1 -1
- package/dist/{chunk-ZB7GJUPS.js.map → chunk-S3YP4QPF.js.map} +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -4
- package/dist/index.d.ts +19 -4
- package/dist/index.js +1 -1
- package/dist/runtime.cjs +53 -6
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.cts +2 -2
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.js +54 -7
- package/dist/runtime.js.map +1 -1
- package/dist/schemas/index.cjs +34 -2
- package/dist/schemas/index.cjs.map +1 -1
- package/dist/schemas/index.d.cts +91 -5
- package/dist/schemas/index.d.ts +91 -5
- package/dist/schemas/index.js +30 -2
- package/dist/schemas/index.js.map +1 -1
- package/dist/{types.tools-C0GqXQlu.d.cts → types.tools-DcFBsfRV.d.cts} +223 -17
- package/dist/{types.tools-C0GqXQlu.d.ts → types.tools-DcFBsfRV.d.ts} +223 -17
- package/package.json +1 -1
- package/schema/extension-manifest.schema.json +40 -0
- package/src/background.test.ts +33 -0
- package/src/background.ts +9 -0
- package/src/index.ts +8 -0
- package/src/messages.ts +5 -0
- package/src/runtime/accountsApi.ts +26 -0
- package/src/runtime/executionContext.test.ts +113 -0
- package/src/runtime/executionContext.ts +28 -2
- package/src/runtime/index.ts +1 -0
- package/src/runtime.ts +38 -3
- package/src/schemas/accounts.schema.test.ts +58 -0
- package/src/schemas/contributions.schema.ts +48 -0
- package/src/schemas/index.ts +6 -0
- package/src/schemas/permissions.schema.ts +11 -1
- package/src/types.context.ts +111 -0
- package/src/types.contributions.ts +47 -0
- package/src/types.permissions.ts +15 -0
- package/src/types.provider.ts +51 -1
- package/src/types.tools.ts +29 -15
- package/src/types.ts +9 -0
|
@@ -789,6 +789,8 @@ interface ExtensionContributions {
|
|
|
789
789
|
commands?: CommandDefinition[];
|
|
790
790
|
/** Prompt contributions for the system prompt */
|
|
791
791
|
prompts?: PromptContribution[];
|
|
792
|
+
/** External accounts the extension works through, signed in once in Stina's settings */
|
|
793
|
+
accounts?: AccountContribution[];
|
|
792
794
|
/** Storage collection declarations */
|
|
793
795
|
storage?: {
|
|
794
796
|
collections: {
|
|
@@ -799,6 +801,45 @@ interface ExtensionContributions {
|
|
|
799
801
|
};
|
|
800
802
|
};
|
|
801
803
|
}
|
|
804
|
+
/**
|
|
805
|
+
* An external account provider the host can sign in to on the user's behalf.
|
|
806
|
+
*
|
|
807
|
+
* Only Microsoft for now, and only through Microsoft Graph: mail and calendar
|
|
808
|
+
* then share one sign-in and one token, instead of an IMAP token and a Graph
|
|
809
|
+
* token that an admin has to approve separately.
|
|
810
|
+
*/
|
|
811
|
+
type AccountProvider = 'microsoft';
|
|
812
|
+
/**
|
|
813
|
+
* What an extension needs from an account the user connects to Stina.
|
|
814
|
+
*
|
|
815
|
+
* Stina asks the provider for every scope that the enabled extensions declare,
|
|
816
|
+
* all at once, so that the user - and, at work, their administrator - approves
|
|
817
|
+
* one request instead of one per extension. Declaring a scope here is therefore
|
|
818
|
+
* also what makes it show up in that request, and in the list of what is asked
|
|
819
|
+
* for in the settings.
|
|
820
|
+
*
|
|
821
|
+
* @example
|
|
822
|
+
* ```json
|
|
823
|
+
* "accounts": [
|
|
824
|
+
* {
|
|
825
|
+
* "provider": "microsoft",
|
|
826
|
+
* "scopes": ["Calendars.ReadWrite"],
|
|
827
|
+
* "reason": { "en": "Read and book events in your calendar", "sv": "Läsa och boka i din kalender" }
|
|
828
|
+
* }
|
|
829
|
+
* ]
|
|
830
|
+
* ```
|
|
831
|
+
*/
|
|
832
|
+
interface AccountContribution {
|
|
833
|
+
provider: AccountProvider;
|
|
834
|
+
/**
|
|
835
|
+
* Microsoft Graph delegated permissions, by name: `Mail.Read`,
|
|
836
|
+
* `Calendars.ReadWrite`. The host adds `offline_access` and `User.Read`
|
|
837
|
+
* itself, so they are not declared here.
|
|
838
|
+
*/
|
|
839
|
+
scopes: string[];
|
|
840
|
+
/** Why the extension needs them, shown next to the scopes in the settings. */
|
|
841
|
+
reason?: LocalizedString;
|
|
842
|
+
}
|
|
802
843
|
/**
|
|
803
844
|
* Tool settings view definition (UI schema)
|
|
804
845
|
*/
|
|
@@ -1178,9 +1219,22 @@ interface ModelCapabilities {
|
|
|
1178
1219
|
* Report this per model *and* per auth mode, like `voiceDuplex`: the same
|
|
1179
1220
|
* provider often serves both a vision model and a text-only one, and a picture
|
|
1180
1221
|
* sent to the latter is at best ignored and at worst an error mid-conversation.
|
|
1181
|
-
* Stina uses it to decide whether the paperclip is offered at all.
|
|
1182
1222
|
*/
|
|
1183
1223
|
vision?: boolean;
|
|
1224
|
+
/**
|
|
1225
|
+
* The model can be given files to read alongside the text of a message, and
|
|
1226
|
+
* the provider folds {@link ChatMessage.files} into whatever its API calls them.
|
|
1227
|
+
*
|
|
1228
|
+
* Separate from `vision` because the two come apart in both directions: a model
|
|
1229
|
+
* that reads a PDF natively is not necessarily one that looks at a photograph,
|
|
1230
|
+
* and an OpenAI-compatible server with a vision model behind it may take images
|
|
1231
|
+
* and nothing else. Report it per model and per auth mode for the same reason
|
|
1232
|
+
* `vision` is reported that way.
|
|
1233
|
+
*
|
|
1234
|
+
* A provider that says nothing here keeps behaving exactly as before: it is
|
|
1235
|
+
* handed the text, and `files` is simply a field it does not read.
|
|
1236
|
+
*/
|
|
1237
|
+
documents?: boolean;
|
|
1184
1238
|
}
|
|
1185
1239
|
/**
|
|
1186
1240
|
* How the client wants to connect to the voice session.
|
|
@@ -1280,6 +1334,18 @@ interface ChatMessage {
|
|
|
1280
1334
|
* Only ever `image/jpeg` or `image/png` — see `ChatAttachmentDTO` for why.
|
|
1281
1335
|
*/
|
|
1282
1336
|
images?: ChatImage[];
|
|
1337
|
+
/**
|
|
1338
|
+
* Files the user attached for the model to read: PDFs and plain text.
|
|
1339
|
+
*
|
|
1340
|
+
* Additive in the same way `images` is, and split from it for the same reason
|
|
1341
|
+
* the two capabilities are separate — a provider folds a document into a
|
|
1342
|
+
* different content block than a picture, and many can do one and not the other.
|
|
1343
|
+
* A provider that ignores the field behaves exactly as it did before.
|
|
1344
|
+
*
|
|
1345
|
+
* Only present on user messages, because that is where both hosted providers
|
|
1346
|
+
* require a document to sit.
|
|
1347
|
+
*/
|
|
1348
|
+
files?: ChatFile[];
|
|
1283
1349
|
/** For assistant messages: tool calls made by the model */
|
|
1284
1350
|
tool_calls?: ToolCall[];
|
|
1285
1351
|
/** For tool messages: the ID of the tool call this is a response to */
|
|
@@ -1299,6 +1365,29 @@ interface ChatImage {
|
|
|
1299
1365
|
/** The image itself, base64 with no data-URI prefix. */
|
|
1300
1366
|
data: string;
|
|
1301
1367
|
}
|
|
1368
|
+
/**
|
|
1369
|
+
* One file the user attached for the model to read, rather than to look at.
|
|
1370
|
+
*
|
|
1371
|
+
* `application/pdf` and `text/plain` are what the host stores, so those are what
|
|
1372
|
+
* arrive. Both hosted providers read a PDF natively and want it as its own content
|
|
1373
|
+
* block; plain text needs no such thing and can simply be put in the prompt, which
|
|
1374
|
+
* is why a provider with no document support at all can still do something useful
|
|
1375
|
+
* with a `text/plain` file if it chooses to.
|
|
1376
|
+
*/
|
|
1377
|
+
interface ChatFile {
|
|
1378
|
+
/** `application/pdf` or `text/plain`. */
|
|
1379
|
+
mime: string;
|
|
1380
|
+
/** The file itself, base64 with no data-URI prefix. */
|
|
1381
|
+
data: string;
|
|
1382
|
+
/**
|
|
1383
|
+
* The name the file arrived under, when it had one.
|
|
1384
|
+
*
|
|
1385
|
+
* Worth passing on rather than dropping: `faktura-1042.pdf` is most of what is
|
|
1386
|
+
* known about a file before it is opened, and both providers have somewhere to
|
|
1387
|
+
* put it — a file name on the one, a document title on the other.
|
|
1388
|
+
*/
|
|
1389
|
+
name?: string;
|
|
1390
|
+
}
|
|
1302
1391
|
/**
|
|
1303
1392
|
* A tool call made by the model
|
|
1304
1393
|
*/
|
|
@@ -1714,6 +1803,109 @@ interface ExecutionContext {
|
|
|
1714
1803
|
readonly secrets: SecretsAPI;
|
|
1715
1804
|
/** User-scoped secrets */
|
|
1716
1805
|
readonly userSecrets: SecretsAPI;
|
|
1806
|
+
/**
|
|
1807
|
+
* The files attached to this user's conversations.
|
|
1808
|
+
*
|
|
1809
|
+
* Present only for an extension holding `attachments.read`, and only on a request
|
|
1810
|
+
* that knows whose it is. Absent otherwise, so a tool that wants files has to say
|
|
1811
|
+
* so in its manifest and check before reaching for them.
|
|
1812
|
+
*/
|
|
1813
|
+
readonly attachments?: AttachmentsAPI;
|
|
1814
|
+
/**
|
|
1815
|
+
* The external accounts this user has connected to Stina.
|
|
1816
|
+
*
|
|
1817
|
+
* Present only for an extension holding `accounts.use`, and only on a request
|
|
1818
|
+
* that knows whose it is - an account belongs to somebody, like an attachment.
|
|
1819
|
+
*/
|
|
1820
|
+
readonly accounts?: ConnectedAccountsAPI;
|
|
1821
|
+
}
|
|
1822
|
+
/**
|
|
1823
|
+
* Working through an account the user signed in to in Stina's settings.
|
|
1824
|
+
*
|
|
1825
|
+
* The user connects a Microsoft account once, and every extension that declares
|
|
1826
|
+
* Microsoft under `contributes.accounts` can use it. The extension never sees the
|
|
1827
|
+
* refresh token; it asks for an access token when it needs one and gets a fresh
|
|
1828
|
+
* one back, refreshed by the host when the old one has run out.
|
|
1829
|
+
*
|
|
1830
|
+
* One thing the host cannot narrow: Microsoft issues a Graph token carrying every
|
|
1831
|
+
* permission the user has granted Stina, not only the ones this extension
|
|
1832
|
+
* declared. The declaration decides whether an extension gets a token at all,
|
|
1833
|
+
* and what the user is asked to approve - not what the token can do.
|
|
1834
|
+
*/
|
|
1835
|
+
interface ConnectedAccountsAPI {
|
|
1836
|
+
/**
|
|
1837
|
+
* The accounts this user has connected for a provider, newest first.
|
|
1838
|
+
*
|
|
1839
|
+
* An empty list is the normal answer for a user who has not connected one yet:
|
|
1840
|
+
* the extension should point them at Stina's settings rather than start a
|
|
1841
|
+
* sign-in of its own.
|
|
1842
|
+
*/
|
|
1843
|
+
list(provider: 'microsoft'): Promise<ConnectedAccount[]>;
|
|
1844
|
+
/**
|
|
1845
|
+
* An access token for one of those accounts, for the scopes this extension
|
|
1846
|
+
* declared.
|
|
1847
|
+
*
|
|
1848
|
+
* Rejects when the account is gone, when the user has not granted every
|
|
1849
|
+
* declared scope yet, or when the provider has revoked the sign-in. The
|
|
1850
|
+
* message says which, in words the user can act on - it is fine to show it.
|
|
1851
|
+
*/
|
|
1852
|
+
getAccessToken(accountId: string): Promise<AccountAccessToken>;
|
|
1853
|
+
}
|
|
1854
|
+
/** An account the user has connected, as an extension sees it. */
|
|
1855
|
+
interface ConnectedAccount {
|
|
1856
|
+
/** Stable id, to store alongside whatever the extension keeps for this account. */
|
|
1857
|
+
id: string;
|
|
1858
|
+
provider: 'microsoft';
|
|
1859
|
+
/** The address the user signs in with. */
|
|
1860
|
+
email: string;
|
|
1861
|
+
displayName?: string;
|
|
1862
|
+
/**
|
|
1863
|
+
* Whether the user has granted every scope this extension declared. False when
|
|
1864
|
+
* the extension was installed after the account was connected, and the user has
|
|
1865
|
+
* yet to reconnect it in the settings.
|
|
1866
|
+
*/
|
|
1867
|
+
hasRequiredScopes: boolean;
|
|
1868
|
+
/** Set when the provider has refused the stored sign-in and it has to be redone. */
|
|
1869
|
+
needsReconnect: boolean;
|
|
1870
|
+
}
|
|
1871
|
+
/** An access token, and when it stops working. */
|
|
1872
|
+
interface AccountAccessToken {
|
|
1873
|
+
/** Bearer token for Microsoft Graph. */
|
|
1874
|
+
token: string;
|
|
1875
|
+
/** ISO timestamp. Ask again after this; the host refreshes. */
|
|
1876
|
+
expiresAt: string;
|
|
1877
|
+
}
|
|
1878
|
+
/**
|
|
1879
|
+
* Reading a file that is already in a conversation.
|
|
1880
|
+
*
|
|
1881
|
+
* For handing one on: mailing back the PDF she was just shown, printing it, putting
|
|
1882
|
+
* it somewhere. Not for finding out what it says — `core_read_attachment` does that
|
|
1883
|
+
* without an extension, and getting the text is nearly always what she actually
|
|
1884
|
+
* wants.
|
|
1885
|
+
*/
|
|
1886
|
+
interface AttachmentsAPI {
|
|
1887
|
+
/**
|
|
1888
|
+
* Read one attachment by id.
|
|
1889
|
+
*
|
|
1890
|
+
* The id comes from Stina, which is the whole point: she gets it from the message
|
|
1891
|
+
* a file arrived on, or from the result of the tool that handed it over, and
|
|
1892
|
+
* passes it to a tool as a parameter.
|
|
1893
|
+
*
|
|
1894
|
+
* Resolves `null` when no such attachment belongs to this user — deleted, or
|
|
1895
|
+
* never theirs. The two are the same answer on purpose.
|
|
1896
|
+
*/
|
|
1897
|
+
read(attachmentId: string): Promise<AttachmentContent | null>;
|
|
1898
|
+
}
|
|
1899
|
+
/** One attachment's bytes, with what is known about them. */
|
|
1900
|
+
interface AttachmentContent {
|
|
1901
|
+
id: string;
|
|
1902
|
+
/** `image/jpeg`, `image/png`, `application/pdf` or `text/plain`, read from the bytes. */
|
|
1903
|
+
mime: string;
|
|
1904
|
+
/** base64, no data-URI prefix. */
|
|
1905
|
+
data: string;
|
|
1906
|
+
byteSize: number;
|
|
1907
|
+
/** The name it was stored under, when it had one. */
|
|
1908
|
+
name?: string;
|
|
1717
1909
|
}
|
|
1718
1910
|
/**
|
|
1719
1911
|
* Context provided to extension's activate function.
|
|
@@ -2353,30 +2545,44 @@ interface ToolResult {
|
|
|
2353
2545
|
*/
|
|
2354
2546
|
cardSuggestion?: string;
|
|
2355
2547
|
/**
|
|
2356
|
-
*
|
|
2548
|
+
* Files to put in front of the user, in the conversation where the tool ran.
|
|
2357
2549
|
*
|
|
2358
|
-
* For what a card cannot hold and the model cannot reproduce: a generated
|
|
2359
|
-
*
|
|
2360
|
-
* {@link ToolResult.display}, this is for the user
|
|
2361
|
-
*
|
|
2362
|
-
*
|
|
2363
|
-
*
|
|
2550
|
+
* For what a card cannot hold and the model cannot reproduce: a generated image,
|
|
2551
|
+
* a photo fetched on the user's behalf, the PDF that came attached to a mail.
|
|
2552
|
+
* Like {@link ToolResult.display}, this is for the user — it is lifted out before
|
|
2553
|
+
* the result reaches the model, which would have nothing to do with the bytes but
|
|
2554
|
+
* spend tokens on them. Say in `data` that a file was attached, so she can talk
|
|
2555
|
+
* about it without reciting it.
|
|
2364
2556
|
*
|
|
2365
|
-
* The host stores each one as an attachment of the conversation,
|
|
2366
|
-
*
|
|
2367
|
-
*
|
|
2368
|
-
*
|
|
2369
|
-
*
|
|
2557
|
+
* The host stores each one as an attachment of the conversation, exactly as a
|
|
2558
|
+
* file the user sends is stored, so it is served to every client and can be saved
|
|
2559
|
+
* or shared from there. The store's own rules apply: JPEG and PNG, PDF, and plain
|
|
2560
|
+
* text, up to 20 MB (1 MB for text). What the file *is* is read from the bytes,
|
|
2561
|
+
* not from `name`, so a PDF mislabelled `.png` still lands as a PDF. One that
|
|
2562
|
+
* fails the rules is dropped with a warning rather than half-shown.
|
|
2563
|
+
*
|
|
2564
|
+
* Attaching a file does not read it to the model. What comes back in the result
|
|
2565
|
+
* the model sees is a reference apiece — `{ id, mime, name? }` under this same
|
|
2566
|
+
* key, in place of the bytes — and she reads one with `core_read_attachment` if
|
|
2567
|
+
* she decides to. That is the intended flow for a mail's attachment: hand it over
|
|
2568
|
+
* here, and let her choose whether to open it.
|
|
2370
2569
|
*/
|
|
2371
2570
|
attachments?: ToolAttachment[];
|
|
2372
2571
|
}
|
|
2373
2572
|
/**
|
|
2374
|
-
* One
|
|
2573
|
+
* One file a tool wants to put in the conversation. See {@link ToolResult.attachments}.
|
|
2375
2574
|
*/
|
|
2376
2575
|
interface ToolAttachment {
|
|
2377
|
-
/** The
|
|
2576
|
+
/** The bytes, base64 encoded. What they are is read from them, not from `name`. */
|
|
2378
2577
|
data: string;
|
|
2379
|
-
/**
|
|
2578
|
+
/**
|
|
2579
|
+
* A file name to offer when the user saves it, e.g. `friday.png` or
|
|
2580
|
+
* `faktura-1042.pdf`.
|
|
2581
|
+
*
|
|
2582
|
+
* Worth sending for a picture and close to required for a document: it is the
|
|
2583
|
+
* whole label the user sees in the conversation, and it is what Stina has to go
|
|
2584
|
+
* on when she decides whether to read it.
|
|
2585
|
+
*/
|
|
2380
2586
|
name?: string;
|
|
2381
2587
|
}
|
|
2382
2588
|
/**
|
|
@@ -2405,4 +2611,4 @@ interface ActionResult {
|
|
|
2405
2611
|
error?: string;
|
|
2406
2612
|
}
|
|
2407
2613
|
|
|
2408
|
-
export { type
|
|
2614
|
+
export { type ConnectedAccountsAPI as $, type ActionResult as A, type ProvidersAPI as B, type ChatMessage as C, type Disposable as D, type ExtensionContributions as E, type ToolsAPI as F, type GetModelsOptions as G, type HugeIconName as H, type ActionsAPI as I, type EventsAPI as J, type SchedulerAPI as K, type LocalizedString as L, type ModelInfo as M, type NetworkAPI as N, type SchedulerJobRequest as O, type PanelDefinition as P, type SchedulerSchedule as Q, type UserProfile as R, type SchedulerFirePayload as S, type ToolResult as T, type UserAPI as U, type VoiceSessionOptions as V, type ChatAPI as W, type ChatInstructionMessage as X, type ConversationPresentation as Y, type AttachmentsAPI as Z, type AttachmentContent as _, type ChatOptions as a, type MarkdownProps as a$, type ConnectedAccount as a0, type AccountAccessToken as a1, type LogAPI as a2, type BackgroundWorkersAPI as a3, type BackgroundTaskConfig as a4, type BackgroundTaskCallback as a5, type BackgroundTaskContext as a6, type BackgroundTaskHealth as a7, type BackgroundRestartPolicy as a8, type Query as a9, type ClockProps as aA, type ParagraphProps as aB, type ButtonProps as aC, type TextInputProps as aD, type PasswordInputProps as aE, type NumberInputProps as aF, type TextAreaProps as aG, type DateTimeInputProps as aH, type SelectProps as aI, type IconPickerProps as aJ, type VerticalStackProps as aK, type HorizontalStackProps as aL, type GridProps as aM, type DividerProps as aN, type IconProps as aO, type IconButtonType as aP, type IconButtonProps as aQ, type PanelAction as aR, type PanelProps as aS, type ToggleProps as aT, type CollapsibleProps as aU, type FrameVariant as aV, type FrameProps as aW, type ListProps as aX, type PillVariant as aY, type PillProps as aZ, type CheckboxProps as a_, type QueryOptions as aa, type StorageAPI as ab, type SecretsAPI as ac, type StorageCollectionConfig as ad, type StorageContributions as ae, type AIProvider as af, type ModelCapabilities as ag, type ChatImage as ah, type ChatFile as ai, type ToolCall as aj, type VoiceTransportRequest as ak, type Tool as al, type ToolAttachment as am, type Action as an, type ExtensionModule as ao, type AllowedCSSProperty as ap, type ExtensionComponentStyle as aq, type ExtensionComponentData as ar, type ExtensionComponentIterator as as, type ExtensionComponentChildren as at, type ExtensionActionCall as au, type ExtensionActionRef as av, type ExtensionDataSource as aw, type ExtensionPanelDefinition as ax, type HeaderProps as ay, type LabelProps as az, type StreamEvent as b, type TextPreviewProps as b0, type ModalProps as b1, type ConditionalGroupProps as b2, type WeatherCondition as b3, type WeatherWind as b4, type WeatherNowProps as b5, type WeatherForecastStep as b6, type WeatherForecastProps as b7, type ChartKind as b8, type ChartSeries as b9, type ChartProps as ba, type StatTrend as bb, type StatTileProps as bc, type ProgressShape as bd, type ProgressColor as be, type ProgressBarProps as bf, type KeyValueRow as bg, type KeyValueListProps as bh, type TimelineVariant as bi, type TimelineEntry as bj, type TimelineProps as bk, type NoteVariant as bl, type NoteProps as bm, type CalendarEventStatus as bn, type CalendarEventProps as bo, type ExecutionContext as bp, type VoiceSessionDescriptor as c, type ToolSettingsViewDefinition as d, type ToolSettingsView as e, type ToolSettingsListView as f, type ToolSettingsListMapping as g, type ToolSettingsComponentView as h, type ToolSettingsActionDataSource as i, type StatusCardDefinition as j, type PanelView as k, type PanelComponentView as l, type PanelActionDataSource as m, type PanelUnknownView as n, type ProviderDefinition as o, type ProviderConfigView as p, type PromptContribution as q, resolveLocalizedString as r, type PromptSection as s, type ToolDefinition as t, type ToolConfirmationConfig as u, type CommandDefinition as v, type AccountProvider as w, type AccountContribution as x, type ExtensionContext as y, type SettingsAPI as z };
|
|
@@ -789,6 +789,8 @@ interface ExtensionContributions {
|
|
|
789
789
|
commands?: CommandDefinition[];
|
|
790
790
|
/** Prompt contributions for the system prompt */
|
|
791
791
|
prompts?: PromptContribution[];
|
|
792
|
+
/** External accounts the extension works through, signed in once in Stina's settings */
|
|
793
|
+
accounts?: AccountContribution[];
|
|
792
794
|
/** Storage collection declarations */
|
|
793
795
|
storage?: {
|
|
794
796
|
collections: {
|
|
@@ -799,6 +801,45 @@ interface ExtensionContributions {
|
|
|
799
801
|
};
|
|
800
802
|
};
|
|
801
803
|
}
|
|
804
|
+
/**
|
|
805
|
+
* An external account provider the host can sign in to on the user's behalf.
|
|
806
|
+
*
|
|
807
|
+
* Only Microsoft for now, and only through Microsoft Graph: mail and calendar
|
|
808
|
+
* then share one sign-in and one token, instead of an IMAP token and a Graph
|
|
809
|
+
* token that an admin has to approve separately.
|
|
810
|
+
*/
|
|
811
|
+
type AccountProvider = 'microsoft';
|
|
812
|
+
/**
|
|
813
|
+
* What an extension needs from an account the user connects to Stina.
|
|
814
|
+
*
|
|
815
|
+
* Stina asks the provider for every scope that the enabled extensions declare,
|
|
816
|
+
* all at once, so that the user - and, at work, their administrator - approves
|
|
817
|
+
* one request instead of one per extension. Declaring a scope here is therefore
|
|
818
|
+
* also what makes it show up in that request, and in the list of what is asked
|
|
819
|
+
* for in the settings.
|
|
820
|
+
*
|
|
821
|
+
* @example
|
|
822
|
+
* ```json
|
|
823
|
+
* "accounts": [
|
|
824
|
+
* {
|
|
825
|
+
* "provider": "microsoft",
|
|
826
|
+
* "scopes": ["Calendars.ReadWrite"],
|
|
827
|
+
* "reason": { "en": "Read and book events in your calendar", "sv": "Läsa och boka i din kalender" }
|
|
828
|
+
* }
|
|
829
|
+
* ]
|
|
830
|
+
* ```
|
|
831
|
+
*/
|
|
832
|
+
interface AccountContribution {
|
|
833
|
+
provider: AccountProvider;
|
|
834
|
+
/**
|
|
835
|
+
* Microsoft Graph delegated permissions, by name: `Mail.Read`,
|
|
836
|
+
* `Calendars.ReadWrite`. The host adds `offline_access` and `User.Read`
|
|
837
|
+
* itself, so they are not declared here.
|
|
838
|
+
*/
|
|
839
|
+
scopes: string[];
|
|
840
|
+
/** Why the extension needs them, shown next to the scopes in the settings. */
|
|
841
|
+
reason?: LocalizedString;
|
|
842
|
+
}
|
|
802
843
|
/**
|
|
803
844
|
* Tool settings view definition (UI schema)
|
|
804
845
|
*/
|
|
@@ -1178,9 +1219,22 @@ interface ModelCapabilities {
|
|
|
1178
1219
|
* Report this per model *and* per auth mode, like `voiceDuplex`: the same
|
|
1179
1220
|
* provider often serves both a vision model and a text-only one, and a picture
|
|
1180
1221
|
* sent to the latter is at best ignored and at worst an error mid-conversation.
|
|
1181
|
-
* Stina uses it to decide whether the paperclip is offered at all.
|
|
1182
1222
|
*/
|
|
1183
1223
|
vision?: boolean;
|
|
1224
|
+
/**
|
|
1225
|
+
* The model can be given files to read alongside the text of a message, and
|
|
1226
|
+
* the provider folds {@link ChatMessage.files} into whatever its API calls them.
|
|
1227
|
+
*
|
|
1228
|
+
* Separate from `vision` because the two come apart in both directions: a model
|
|
1229
|
+
* that reads a PDF natively is not necessarily one that looks at a photograph,
|
|
1230
|
+
* and an OpenAI-compatible server with a vision model behind it may take images
|
|
1231
|
+
* and nothing else. Report it per model and per auth mode for the same reason
|
|
1232
|
+
* `vision` is reported that way.
|
|
1233
|
+
*
|
|
1234
|
+
* A provider that says nothing here keeps behaving exactly as before: it is
|
|
1235
|
+
* handed the text, and `files` is simply a field it does not read.
|
|
1236
|
+
*/
|
|
1237
|
+
documents?: boolean;
|
|
1184
1238
|
}
|
|
1185
1239
|
/**
|
|
1186
1240
|
* How the client wants to connect to the voice session.
|
|
@@ -1280,6 +1334,18 @@ interface ChatMessage {
|
|
|
1280
1334
|
* Only ever `image/jpeg` or `image/png` — see `ChatAttachmentDTO` for why.
|
|
1281
1335
|
*/
|
|
1282
1336
|
images?: ChatImage[];
|
|
1337
|
+
/**
|
|
1338
|
+
* Files the user attached for the model to read: PDFs and plain text.
|
|
1339
|
+
*
|
|
1340
|
+
* Additive in the same way `images` is, and split from it for the same reason
|
|
1341
|
+
* the two capabilities are separate — a provider folds a document into a
|
|
1342
|
+
* different content block than a picture, and many can do one and not the other.
|
|
1343
|
+
* A provider that ignores the field behaves exactly as it did before.
|
|
1344
|
+
*
|
|
1345
|
+
* Only present on user messages, because that is where both hosted providers
|
|
1346
|
+
* require a document to sit.
|
|
1347
|
+
*/
|
|
1348
|
+
files?: ChatFile[];
|
|
1283
1349
|
/** For assistant messages: tool calls made by the model */
|
|
1284
1350
|
tool_calls?: ToolCall[];
|
|
1285
1351
|
/** For tool messages: the ID of the tool call this is a response to */
|
|
@@ -1299,6 +1365,29 @@ interface ChatImage {
|
|
|
1299
1365
|
/** The image itself, base64 with no data-URI prefix. */
|
|
1300
1366
|
data: string;
|
|
1301
1367
|
}
|
|
1368
|
+
/**
|
|
1369
|
+
* One file the user attached for the model to read, rather than to look at.
|
|
1370
|
+
*
|
|
1371
|
+
* `application/pdf` and `text/plain` are what the host stores, so those are what
|
|
1372
|
+
* arrive. Both hosted providers read a PDF natively and want it as its own content
|
|
1373
|
+
* block; plain text needs no such thing and can simply be put in the prompt, which
|
|
1374
|
+
* is why a provider with no document support at all can still do something useful
|
|
1375
|
+
* with a `text/plain` file if it chooses to.
|
|
1376
|
+
*/
|
|
1377
|
+
interface ChatFile {
|
|
1378
|
+
/** `application/pdf` or `text/plain`. */
|
|
1379
|
+
mime: string;
|
|
1380
|
+
/** The file itself, base64 with no data-URI prefix. */
|
|
1381
|
+
data: string;
|
|
1382
|
+
/**
|
|
1383
|
+
* The name the file arrived under, when it had one.
|
|
1384
|
+
*
|
|
1385
|
+
* Worth passing on rather than dropping: `faktura-1042.pdf` is most of what is
|
|
1386
|
+
* known about a file before it is opened, and both providers have somewhere to
|
|
1387
|
+
* put it — a file name on the one, a document title on the other.
|
|
1388
|
+
*/
|
|
1389
|
+
name?: string;
|
|
1390
|
+
}
|
|
1302
1391
|
/**
|
|
1303
1392
|
* A tool call made by the model
|
|
1304
1393
|
*/
|
|
@@ -1714,6 +1803,109 @@ interface ExecutionContext {
|
|
|
1714
1803
|
readonly secrets: SecretsAPI;
|
|
1715
1804
|
/** User-scoped secrets */
|
|
1716
1805
|
readonly userSecrets: SecretsAPI;
|
|
1806
|
+
/**
|
|
1807
|
+
* The files attached to this user's conversations.
|
|
1808
|
+
*
|
|
1809
|
+
* Present only for an extension holding `attachments.read`, and only on a request
|
|
1810
|
+
* that knows whose it is. Absent otherwise, so a tool that wants files has to say
|
|
1811
|
+
* so in its manifest and check before reaching for them.
|
|
1812
|
+
*/
|
|
1813
|
+
readonly attachments?: AttachmentsAPI;
|
|
1814
|
+
/**
|
|
1815
|
+
* The external accounts this user has connected to Stina.
|
|
1816
|
+
*
|
|
1817
|
+
* Present only for an extension holding `accounts.use`, and only on a request
|
|
1818
|
+
* that knows whose it is - an account belongs to somebody, like an attachment.
|
|
1819
|
+
*/
|
|
1820
|
+
readonly accounts?: ConnectedAccountsAPI;
|
|
1821
|
+
}
|
|
1822
|
+
/**
|
|
1823
|
+
* Working through an account the user signed in to in Stina's settings.
|
|
1824
|
+
*
|
|
1825
|
+
* The user connects a Microsoft account once, and every extension that declares
|
|
1826
|
+
* Microsoft under `contributes.accounts` can use it. The extension never sees the
|
|
1827
|
+
* refresh token; it asks for an access token when it needs one and gets a fresh
|
|
1828
|
+
* one back, refreshed by the host when the old one has run out.
|
|
1829
|
+
*
|
|
1830
|
+
* One thing the host cannot narrow: Microsoft issues a Graph token carrying every
|
|
1831
|
+
* permission the user has granted Stina, not only the ones this extension
|
|
1832
|
+
* declared. The declaration decides whether an extension gets a token at all,
|
|
1833
|
+
* and what the user is asked to approve - not what the token can do.
|
|
1834
|
+
*/
|
|
1835
|
+
interface ConnectedAccountsAPI {
|
|
1836
|
+
/**
|
|
1837
|
+
* The accounts this user has connected for a provider, newest first.
|
|
1838
|
+
*
|
|
1839
|
+
* An empty list is the normal answer for a user who has not connected one yet:
|
|
1840
|
+
* the extension should point them at Stina's settings rather than start a
|
|
1841
|
+
* sign-in of its own.
|
|
1842
|
+
*/
|
|
1843
|
+
list(provider: 'microsoft'): Promise<ConnectedAccount[]>;
|
|
1844
|
+
/**
|
|
1845
|
+
* An access token for one of those accounts, for the scopes this extension
|
|
1846
|
+
* declared.
|
|
1847
|
+
*
|
|
1848
|
+
* Rejects when the account is gone, when the user has not granted every
|
|
1849
|
+
* declared scope yet, or when the provider has revoked the sign-in. The
|
|
1850
|
+
* message says which, in words the user can act on - it is fine to show it.
|
|
1851
|
+
*/
|
|
1852
|
+
getAccessToken(accountId: string): Promise<AccountAccessToken>;
|
|
1853
|
+
}
|
|
1854
|
+
/** An account the user has connected, as an extension sees it. */
|
|
1855
|
+
interface ConnectedAccount {
|
|
1856
|
+
/** Stable id, to store alongside whatever the extension keeps for this account. */
|
|
1857
|
+
id: string;
|
|
1858
|
+
provider: 'microsoft';
|
|
1859
|
+
/** The address the user signs in with. */
|
|
1860
|
+
email: string;
|
|
1861
|
+
displayName?: string;
|
|
1862
|
+
/**
|
|
1863
|
+
* Whether the user has granted every scope this extension declared. False when
|
|
1864
|
+
* the extension was installed after the account was connected, and the user has
|
|
1865
|
+
* yet to reconnect it in the settings.
|
|
1866
|
+
*/
|
|
1867
|
+
hasRequiredScopes: boolean;
|
|
1868
|
+
/** Set when the provider has refused the stored sign-in and it has to be redone. */
|
|
1869
|
+
needsReconnect: boolean;
|
|
1870
|
+
}
|
|
1871
|
+
/** An access token, and when it stops working. */
|
|
1872
|
+
interface AccountAccessToken {
|
|
1873
|
+
/** Bearer token for Microsoft Graph. */
|
|
1874
|
+
token: string;
|
|
1875
|
+
/** ISO timestamp. Ask again after this; the host refreshes. */
|
|
1876
|
+
expiresAt: string;
|
|
1877
|
+
}
|
|
1878
|
+
/**
|
|
1879
|
+
* Reading a file that is already in a conversation.
|
|
1880
|
+
*
|
|
1881
|
+
* For handing one on: mailing back the PDF she was just shown, printing it, putting
|
|
1882
|
+
* it somewhere. Not for finding out what it says — `core_read_attachment` does that
|
|
1883
|
+
* without an extension, and getting the text is nearly always what she actually
|
|
1884
|
+
* wants.
|
|
1885
|
+
*/
|
|
1886
|
+
interface AttachmentsAPI {
|
|
1887
|
+
/**
|
|
1888
|
+
* Read one attachment by id.
|
|
1889
|
+
*
|
|
1890
|
+
* The id comes from Stina, which is the whole point: she gets it from the message
|
|
1891
|
+
* a file arrived on, or from the result of the tool that handed it over, and
|
|
1892
|
+
* passes it to a tool as a parameter.
|
|
1893
|
+
*
|
|
1894
|
+
* Resolves `null` when no such attachment belongs to this user — deleted, or
|
|
1895
|
+
* never theirs. The two are the same answer on purpose.
|
|
1896
|
+
*/
|
|
1897
|
+
read(attachmentId: string): Promise<AttachmentContent | null>;
|
|
1898
|
+
}
|
|
1899
|
+
/** One attachment's bytes, with what is known about them. */
|
|
1900
|
+
interface AttachmentContent {
|
|
1901
|
+
id: string;
|
|
1902
|
+
/** `image/jpeg`, `image/png`, `application/pdf` or `text/plain`, read from the bytes. */
|
|
1903
|
+
mime: string;
|
|
1904
|
+
/** base64, no data-URI prefix. */
|
|
1905
|
+
data: string;
|
|
1906
|
+
byteSize: number;
|
|
1907
|
+
/** The name it was stored under, when it had one. */
|
|
1908
|
+
name?: string;
|
|
1717
1909
|
}
|
|
1718
1910
|
/**
|
|
1719
1911
|
* Context provided to extension's activate function.
|
|
@@ -2353,30 +2545,44 @@ interface ToolResult {
|
|
|
2353
2545
|
*/
|
|
2354
2546
|
cardSuggestion?: string;
|
|
2355
2547
|
/**
|
|
2356
|
-
*
|
|
2548
|
+
* Files to put in front of the user, in the conversation where the tool ran.
|
|
2357
2549
|
*
|
|
2358
|
-
* For what a card cannot hold and the model cannot reproduce: a generated
|
|
2359
|
-
*
|
|
2360
|
-
* {@link ToolResult.display}, this is for the user
|
|
2361
|
-
*
|
|
2362
|
-
*
|
|
2363
|
-
*
|
|
2550
|
+
* For what a card cannot hold and the model cannot reproduce: a generated image,
|
|
2551
|
+
* a photo fetched on the user's behalf, the PDF that came attached to a mail.
|
|
2552
|
+
* Like {@link ToolResult.display}, this is for the user — it is lifted out before
|
|
2553
|
+
* the result reaches the model, which would have nothing to do with the bytes but
|
|
2554
|
+
* spend tokens on them. Say in `data` that a file was attached, so she can talk
|
|
2555
|
+
* about it without reciting it.
|
|
2364
2556
|
*
|
|
2365
|
-
* The host stores each one as an attachment of the conversation,
|
|
2366
|
-
*
|
|
2367
|
-
*
|
|
2368
|
-
*
|
|
2369
|
-
*
|
|
2557
|
+
* The host stores each one as an attachment of the conversation, exactly as a
|
|
2558
|
+
* file the user sends is stored, so it is served to every client and can be saved
|
|
2559
|
+
* or shared from there. The store's own rules apply: JPEG and PNG, PDF, and plain
|
|
2560
|
+
* text, up to 20 MB (1 MB for text). What the file *is* is read from the bytes,
|
|
2561
|
+
* not from `name`, so a PDF mislabelled `.png` still lands as a PDF. One that
|
|
2562
|
+
* fails the rules is dropped with a warning rather than half-shown.
|
|
2563
|
+
*
|
|
2564
|
+
* Attaching a file does not read it to the model. What comes back in the result
|
|
2565
|
+
* the model sees is a reference apiece — `{ id, mime, name? }` under this same
|
|
2566
|
+
* key, in place of the bytes — and she reads one with `core_read_attachment` if
|
|
2567
|
+
* she decides to. That is the intended flow for a mail's attachment: hand it over
|
|
2568
|
+
* here, and let her choose whether to open it.
|
|
2370
2569
|
*/
|
|
2371
2570
|
attachments?: ToolAttachment[];
|
|
2372
2571
|
}
|
|
2373
2572
|
/**
|
|
2374
|
-
* One
|
|
2573
|
+
* One file a tool wants to put in the conversation. See {@link ToolResult.attachments}.
|
|
2375
2574
|
*/
|
|
2376
2575
|
interface ToolAttachment {
|
|
2377
|
-
/** The
|
|
2576
|
+
/** The bytes, base64 encoded. What they are is read from them, not from `name`. */
|
|
2378
2577
|
data: string;
|
|
2379
|
-
/**
|
|
2578
|
+
/**
|
|
2579
|
+
* A file name to offer when the user saves it, e.g. `friday.png` or
|
|
2580
|
+
* `faktura-1042.pdf`.
|
|
2581
|
+
*
|
|
2582
|
+
* Worth sending for a picture and close to required for a document: it is the
|
|
2583
|
+
* whole label the user sees in the conversation, and it is what Stina has to go
|
|
2584
|
+
* on when she decides whether to read it.
|
|
2585
|
+
*/
|
|
2380
2586
|
name?: string;
|
|
2381
2587
|
}
|
|
2382
2588
|
/**
|
|
@@ -2405,4 +2611,4 @@ interface ActionResult {
|
|
|
2405
2611
|
error?: string;
|
|
2406
2612
|
}
|
|
2407
2613
|
|
|
2408
|
-
export { type
|
|
2614
|
+
export { type ConnectedAccountsAPI as $, type ActionResult as A, type ProvidersAPI as B, type ChatMessage as C, type Disposable as D, type ExtensionContributions as E, type ToolsAPI as F, type GetModelsOptions as G, type HugeIconName as H, type ActionsAPI as I, type EventsAPI as J, type SchedulerAPI as K, type LocalizedString as L, type ModelInfo as M, type NetworkAPI as N, type SchedulerJobRequest as O, type PanelDefinition as P, type SchedulerSchedule as Q, type UserProfile as R, type SchedulerFirePayload as S, type ToolResult as T, type UserAPI as U, type VoiceSessionOptions as V, type ChatAPI as W, type ChatInstructionMessage as X, type ConversationPresentation as Y, type AttachmentsAPI as Z, type AttachmentContent as _, type ChatOptions as a, type MarkdownProps as a$, type ConnectedAccount as a0, type AccountAccessToken as a1, type LogAPI as a2, type BackgroundWorkersAPI as a3, type BackgroundTaskConfig as a4, type BackgroundTaskCallback as a5, type BackgroundTaskContext as a6, type BackgroundTaskHealth as a7, type BackgroundRestartPolicy as a8, type Query as a9, type ClockProps as aA, type ParagraphProps as aB, type ButtonProps as aC, type TextInputProps as aD, type PasswordInputProps as aE, type NumberInputProps as aF, type TextAreaProps as aG, type DateTimeInputProps as aH, type SelectProps as aI, type IconPickerProps as aJ, type VerticalStackProps as aK, type HorizontalStackProps as aL, type GridProps as aM, type DividerProps as aN, type IconProps as aO, type IconButtonType as aP, type IconButtonProps as aQ, type PanelAction as aR, type PanelProps as aS, type ToggleProps as aT, type CollapsibleProps as aU, type FrameVariant as aV, type FrameProps as aW, type ListProps as aX, type PillVariant as aY, type PillProps as aZ, type CheckboxProps as a_, type QueryOptions as aa, type StorageAPI as ab, type SecretsAPI as ac, type StorageCollectionConfig as ad, type StorageContributions as ae, type AIProvider as af, type ModelCapabilities as ag, type ChatImage as ah, type ChatFile as ai, type ToolCall as aj, type VoiceTransportRequest as ak, type Tool as al, type ToolAttachment as am, type Action as an, type ExtensionModule as ao, type AllowedCSSProperty as ap, type ExtensionComponentStyle as aq, type ExtensionComponentData as ar, type ExtensionComponentIterator as as, type ExtensionComponentChildren as at, type ExtensionActionCall as au, type ExtensionActionRef as av, type ExtensionDataSource as aw, type ExtensionPanelDefinition as ax, type HeaderProps as ay, type LabelProps as az, type StreamEvent as b, type TextPreviewProps as b0, type ModalProps as b1, type ConditionalGroupProps as b2, type WeatherCondition as b3, type WeatherWind as b4, type WeatherNowProps as b5, type WeatherForecastStep as b6, type WeatherForecastProps as b7, type ChartKind as b8, type ChartSeries as b9, type ChartProps as ba, type StatTrend as bb, type StatTileProps as bc, type ProgressShape as bd, type ProgressColor as be, type ProgressBarProps as bf, type KeyValueRow as bg, type KeyValueListProps as bh, type TimelineVariant as bi, type TimelineEntry as bj, type TimelineProps as bk, type NoteVariant as bl, type NoteProps as bm, type CalendarEventStatus as bn, type CalendarEventProps as bo, type ExecutionContext as bp, type VoiceSessionDescriptor as c, type ToolSettingsViewDefinition as d, type ToolSettingsView as e, type ToolSettingsListView as f, type ToolSettingsListMapping as g, type ToolSettingsComponentView as h, type ToolSettingsActionDataSource as i, type StatusCardDefinition as j, type PanelView as k, type PanelComponentView as l, type PanelActionDataSource as m, type PanelUnknownView as n, type ProviderDefinition as o, type ProviderConfigView as p, type PromptContribution as q, resolveLocalizedString as r, type PromptSection as s, type ToolDefinition as t, type ToolConfirmationConfig as u, type CommandDefinition as v, type AccountProvider as w, type AccountContribution as x, type ExtensionContext as y, type SettingsAPI as z };
|