@vetta-org/plugin-sdk 0.1.1 → 0.3.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/activity-tab.d.ts +2 -0
- package/dist/activity-tab.d.ts.map +1 -1
- package/dist/activity-tab.js +1 -1
- package/dist/activity-tab.js.map +1 -1
- package/dist/agent.d.ts +148 -4
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +14 -1
- package/dist/agent.js.map +1 -1
- package/dist/ai.d.ts +106 -0
- package/dist/ai.d.ts.map +1 -0
- package/dist/ai.js +2 -0
- package/dist/ai.js.map +1 -0
- package/dist/app-actions.d.ts +9 -1
- package/dist/app-actions.d.ts.map +1 -1
- package/dist/app-actions.js.map +1 -1
- package/dist/artifacts.d.ts +31 -0
- package/dist/artifacts.d.ts.map +1 -0
- package/dist/artifacts.js +2 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/browser.d.ts +119 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +2 -0
- package/dist/browser.js.map +1 -0
- package/dist/capture.d.ts +64 -0
- package/dist/capture.d.ts.map +1 -0
- package/dist/capture.js +2 -0
- package/dist/capture.js.map +1 -0
- package/dist/cli-provider.d.ts +18 -0
- package/dist/cli-provider.d.ts.map +1 -0
- package/dist/cli-provider.js +2 -0
- package/dist/cli-provider.js.map +1 -0
- package/dist/context.d.ts +59 -7
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js.map +1 -1
- package/dist/conversation.d.ts +66 -2
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js.map +1 -1
- package/dist/gateway.d.ts +37 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +14 -0
- package/dist/gateway.js.map +1 -0
- package/dist/index.d.ts +26 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/jobs.d.ts +34 -0
- package/dist/jobs.d.ts.map +1 -0
- package/dist/jobs.js +2 -0
- package/dist/jobs.js.map +1 -0
- package/dist/manifest-schema.d.ts +637 -0
- package/dist/manifest-schema.d.ts.map +1 -0
- package/dist/manifest-schema.js +251 -0
- package/dist/manifest-schema.js.map +1 -0
- package/dist/manifest.d.ts +21 -55
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +468 -1
- package/dist/manifest.js.map +1 -1
- package/dist/media.d.ts +193 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +11 -0
- package/dist/media.js.map +1 -0
- package/dist/models.d.ts +35 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +2 -0
- package/dist/models.js.map +1 -0
- package/dist/network.d.ts +2 -1
- package/dist/network.d.ts.map +1 -1
- package/dist/network.js.map +1 -1
- package/dist/npm-package.d.ts +17 -0
- package/dist/npm-package.d.ts.map +1 -0
- package/dist/npm-package.js +38 -0
- package/dist/npm-package.js.map +1 -0
- package/dist/ocr.d.ts +78 -0
- package/dist/ocr.d.ts.map +1 -0
- package/dist/ocr.js +2 -0
- package/dist/ocr.js.map +1 -0
- package/dist/official.d.ts +219 -10
- package/dist/official.d.ts.map +1 -1
- package/dist/official.js.map +1 -1
- package/dist/permissions.d.ts +2 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +62 -1
- package/dist/permissions.js.map +1 -1
- package/dist/prompt-attachment.d.ts +30 -6
- package/dist/prompt-attachment.d.ts.map +1 -1
- package/dist/prompt-attachment.js +35 -1
- package/dist/prompt-attachment.js.map +1 -1
- package/dist/quickjs.d.ts +147 -0
- package/dist/quickjs.d.ts.map +1 -0
- package/dist/quickjs.js +2 -0
- package/dist/quickjs.js.map +1 -0
- package/dist/secrets.d.ts +27 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +2 -0
- package/dist/secrets.js.map +1 -0
- package/dist/service-provider.d.ts +62 -0
- package/dist/service-provider.d.ts.map +1 -0
- package/dist/service-provider.js +2 -0
- package/dist/service-provider.js.map +1 -0
- package/dist/storage.d.ts +46 -6
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +8 -1
- package/dist/storage.js.map +1 -1
- package/dist/ui.d.ts +341 -22
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js.map +1 -1
- package/package.json +22 -2
- package/src/tailwind-theme.css +30 -0
- package/dist/settings.d.ts +0 -13
- package/dist/settings.d.ts.map +0 -1
- package/dist/settings.js +0 -2
- package/dist/settings.js.map +0 -1
package/dist/storage.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IAClC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IAClC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,0BAA0B;IAC1C,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEtD,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,qBAAqB,CAAC;CAChC;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,kBAAkB,CAAC,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9G,MAAM,WAAW,0BAA0B;IAC1C,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,yBAAyB;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;CACrC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAChF,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,qBAAqB,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAC3G,8FAA8F;IAC9F,MAAM,CACL,OAAO,EAAE,SAAS,mBAAmB,EAAE,EACvC,OAAO,CAAC,EAAE,0BAA0B,GAClC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACtC,8DAA8D;IAC9D,YAAY,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACxG,OAAO,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACjE,uGAAuG;IACvG,eAAe,CAAC,KAAK,EAAE,0BAA0B,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACjF,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACvD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IAC5D,kEAAkE;IAClE,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAED,+FAA+F;AAC/F,wBAAsB,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAGhG;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAEzH","sourcesContent":["export interface PluginStoredBlobRef {\n\tid: string;\n\turl: string;\n\tmimeType: string;\n}\n\nexport interface PluginStoredBlob {\n\tdata: string;\n\tmimeType: string;\n}\n\nexport interface PluginPutBlobInput {\n\tid?: string;\n\tdata: string;\n\tmimeType: string;\n}\n\nexport interface PluginPutBlobFromFileInput {\n\tid?: string;\n\tfile: File;\n\tmimeType: string;\n}\n\nexport type PluginStorageEncoding = \"utf8\" | \"base64\";\n\nexport interface PluginStorageWrite {\n\tpath: string;\n\tdata: string;\n\tencoding: PluginStorageEncoding;\n}\n\nexport type PluginStorageChange = ({ type: \"write\" } & PluginStorageWrite) | { type: \"remove\"; path: string };\n\nexport interface PluginStorageCommitOptions {\n\texpectedRevision?: string;\n}\n\nexport interface PluginStorageCommitResult {\n\trevision: string;\n\tchangedPaths: string[];\n}\n\nexport interface PluginStorageSnapshot {\n\trevision: string;\n\tfiles: Record<string, string | null>;\n}\n\n/**\n * Private persistent storage scoped to the current plugin.\n *\n * Paths are relative to the plugin namespace and are never given an implicit\n * extension. Text and bytes use an explicit encoding at the bridge boundary;\n * JSON is a plugin-level serialization choice. `commit()` publishes all file\n * changes as one revision, and `readSnapshot()` reads several paths from the\n * same revision. Blob bytes remain a separate media resource API.\n */\nexport interface PluginStorageApi {\n\tlist(prefix?: string): Promise<string[]>;\n\treadFile(path: string, encoding: PluginStorageEncoding): Promise<string | null>;\n\twriteFile(path: string, data: string, encoding: PluginStorageEncoding): Promise<PluginStorageCommitResult>;\n\t/** Atomically publish multiple private-file writes/removals as one plugin-scoped revision. */\n\tcommit(\n\t\tchanges: readonly PluginStorageChange[],\n\t\toptions?: PluginStorageCommitOptions,\n\t): Promise<PluginStorageCommitResult>;\n\t/** Read several private files from one committed revision. */\n\treadSnapshot(paths: readonly string[], encoding: PluginStorageEncoding): Promise<PluginStorageSnapshot>;\n\tputBlob(input: PluginPutBlobInput): Promise<PluginStoredBlobRef>;\n\t/** Copy a user-selected or dropped filesystem file without carrying its bytes through the renderer. */\n\tputBlobFromFile(input: PluginPutBlobFromFileInput): Promise<PluginStoredBlobRef>;\n\treadBlob(id: string): Promise<PluginStoredBlob | null>;\n\tgetBlobRef(id: string): Promise<PluginStoredBlobRef | null>;\n\t/** Permanently delete one blob owned by this plugin namespace. */\n\tdeleteBlob(id: string): Promise<void>;\n}\n\n/** Optional JSON convenience helpers. The storage contract itself remains file/bytes based. */\nexport async function readJsonFile<T>(storage: PluginStorageApi, path: string): Promise<T | null> {\n\tconst data = await storage.readFile(path, \"utf8\");\n\treturn data === null ? null : (JSON.parse(data) as T);\n}\n\nexport function writeJsonFile(storage: PluginStorageApi, path: string, value: unknown): Promise<PluginStorageCommitResult> {\n\treturn storage.writeFile(path, JSON.stringify(value, null, 2), \"utf8\");\n}\n"]}
|
package/dist/storage.js
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
/** Optional JSON convenience helpers. The storage contract itself remains file/bytes based. */
|
|
2
|
+
export async function readJsonFile(storage, path) {
|
|
3
|
+
const data = await storage.readFile(path, "utf8");
|
|
4
|
+
return data === null ? null : JSON.parse(data);
|
|
5
|
+
}
|
|
6
|
+
export function writeJsonFile(storage, path, value) {
|
|
7
|
+
return storage.writeFile(path, JSON.stringify(value, null, 2), "utf8");
|
|
8
|
+
}
|
|
2
9
|
//# sourceMappingURL=storage.js.map
|
package/dist/storage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"","sourcesContent":["export interface PluginStoredBlobRef {\n\tid: string;\n\turl: string;\n\tmimeType: string;\n}\n\nexport interface PluginStoredBlob {\n\tdata: string;\n\tmimeType: string;\n}\n\nexport interface PluginPutBlobInput {\n\tid?: string;\n\tdata: string;\n\tmimeType: string;\n}\n\n/**\n * Private persistent storage scoped to the current plugin.\n *\n *
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AA4EA,+FAA+F;AAC/F,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,OAAyB,EAAE,IAAY,EAAqB;IACjG,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAClD,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAO,CAAC;AAAA,CACtD;AAED,MAAM,UAAU,aAAa,CAAC,OAAyB,EAAE,IAAY,EAAE,KAAc,EAAsC;IAC1H,OAAO,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAAA,CACvE","sourcesContent":["export interface PluginStoredBlobRef {\n\tid: string;\n\turl: string;\n\tmimeType: string;\n}\n\nexport interface PluginStoredBlob {\n\tdata: string;\n\tmimeType: string;\n}\n\nexport interface PluginPutBlobInput {\n\tid?: string;\n\tdata: string;\n\tmimeType: string;\n}\n\nexport interface PluginPutBlobFromFileInput {\n\tid?: string;\n\tfile: File;\n\tmimeType: string;\n}\n\nexport type PluginStorageEncoding = \"utf8\" | \"base64\";\n\nexport interface PluginStorageWrite {\n\tpath: string;\n\tdata: string;\n\tencoding: PluginStorageEncoding;\n}\n\nexport type PluginStorageChange = ({ type: \"write\" } & PluginStorageWrite) | { type: \"remove\"; path: string };\n\nexport interface PluginStorageCommitOptions {\n\texpectedRevision?: string;\n}\n\nexport interface PluginStorageCommitResult {\n\trevision: string;\n\tchangedPaths: string[];\n}\n\nexport interface PluginStorageSnapshot {\n\trevision: string;\n\tfiles: Record<string, string | null>;\n}\n\n/**\n * Private persistent storage scoped to the current plugin.\n *\n * Paths are relative to the plugin namespace and are never given an implicit\n * extension. Text and bytes use an explicit encoding at the bridge boundary;\n * JSON is a plugin-level serialization choice. `commit()` publishes all file\n * changes as one revision, and `readSnapshot()` reads several paths from the\n * same revision. Blob bytes remain a separate media resource API.\n */\nexport interface PluginStorageApi {\n\tlist(prefix?: string): Promise<string[]>;\n\treadFile(path: string, encoding: PluginStorageEncoding): Promise<string | null>;\n\twriteFile(path: string, data: string, encoding: PluginStorageEncoding): Promise<PluginStorageCommitResult>;\n\t/** Atomically publish multiple private-file writes/removals as one plugin-scoped revision. */\n\tcommit(\n\t\tchanges: readonly PluginStorageChange[],\n\t\toptions?: PluginStorageCommitOptions,\n\t): Promise<PluginStorageCommitResult>;\n\t/** Read several private files from one committed revision. */\n\treadSnapshot(paths: readonly string[], encoding: PluginStorageEncoding): Promise<PluginStorageSnapshot>;\n\tputBlob(input: PluginPutBlobInput): Promise<PluginStoredBlobRef>;\n\t/** Copy a user-selected or dropped filesystem file without carrying its bytes through the renderer. */\n\tputBlobFromFile(input: PluginPutBlobFromFileInput): Promise<PluginStoredBlobRef>;\n\treadBlob(id: string): Promise<PluginStoredBlob | null>;\n\tgetBlobRef(id: string): Promise<PluginStoredBlobRef | null>;\n\t/** Permanently delete one blob owned by this plugin namespace. */\n\tdeleteBlob(id: string): Promise<void>;\n}\n\n/** Optional JSON convenience helpers. The storage contract itself remains file/bytes based. */\nexport async function readJsonFile<T>(storage: PluginStorageApi, path: string): Promise<T | null> {\n\tconst data = await storage.readFile(path, \"utf8\");\n\treturn data === null ? null : (JSON.parse(data) as T);\n}\n\nexport function writeJsonFile(storage: PluginStorageApi, path: string, value: unknown): Promise<PluginStorageCommitResult> {\n\treturn storage.writeFile(path, JSON.stringify(value, null, 2), \"utf8\");\n}\n"]}
|
package/dist/ui.d.ts
CHANGED
|
@@ -9,6 +9,156 @@ export interface PluginGlobalSlotContribution {
|
|
|
9
9
|
id: string;
|
|
10
10
|
component: ComponentType;
|
|
11
11
|
}
|
|
12
|
+
export interface PluginAbilityDetailSlotProps {
|
|
13
|
+
abilityId: string;
|
|
14
|
+
installed: boolean;
|
|
15
|
+
enabled: boolean;
|
|
16
|
+
}
|
|
17
|
+
/** Inline setup/status surface rendered near the top of one ability detail page. */
|
|
18
|
+
export interface PluginAbilityDetailSlotContribution {
|
|
19
|
+
id: string;
|
|
20
|
+
abilityId: string;
|
|
21
|
+
component: ComponentType<PluginAbilityDetailSlotProps>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Props handed to a workspace-view component. A workspace view owns the whole
|
|
25
|
+
* content area, so unlike panel slots it is addressed by its own route and can
|
|
26
|
+
* be deep-linked; the host passes back its identity so one component can serve
|
|
27
|
+
* several registered views.
|
|
28
|
+
*/
|
|
29
|
+
export interface PluginWorkspaceViewProps {
|
|
30
|
+
/** The contribution id as registered (NOT namespaced). */
|
|
31
|
+
viewId: string;
|
|
32
|
+
/** The owning plugin id. */
|
|
33
|
+
pluginId: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Badge tone. The host maps it to its own theme colors — a plugin cannot pick a
|
|
37
|
+
* raw color, so badges stay consistent with the built-in navigation entries.
|
|
38
|
+
*/
|
|
39
|
+
export type PluginNavBadgeTone = "accent" | "danger" | "default" | "warning";
|
|
40
|
+
/**
|
|
41
|
+
* A badge on the plugin's sidebar navigation entry.
|
|
42
|
+
*
|
|
43
|
+
* `beta` is the host's own preset — it renders exactly like the built-in
|
|
44
|
+
* 知识库 Beta 标识, wording included (and localized by the host), so plugins do
|
|
45
|
+
* not have to spell "Beta" themselves in every locale.
|
|
46
|
+
*
|
|
47
|
+
* `count` renders `99+` past 99 and disappears at 0 — an unread badge showing
|
|
48
|
+
* "0" is worse than no badge.
|
|
49
|
+
*/
|
|
50
|
+
export type PluginNavBadge = {
|
|
51
|
+
kind: "beta";
|
|
52
|
+
} | {
|
|
53
|
+
kind: "text";
|
|
54
|
+
text: string;
|
|
55
|
+
tone?: PluginNavBadgeTone;
|
|
56
|
+
} | {
|
|
57
|
+
kind: "count";
|
|
58
|
+
count: number;
|
|
59
|
+
tone?: PluginNavBadgeTone;
|
|
60
|
+
} | {
|
|
61
|
+
kind: "dot";
|
|
62
|
+
tone?: PluginNavBadgeTone;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* A **workspace view**(工作区视图): a full-page surface a plugin contributes to
|
|
66
|
+
* the host's primary navigation. It is the plugin counterpart of a built-in page
|
|
67
|
+
* such as 自动化 / 知识库 — the host gives it its own route
|
|
68
|
+
* (`/workspace/<pluginId>/<viewId>`) and a sidebar entry, and the plugin owns the
|
|
69
|
+
* entire content area while it is open.
|
|
70
|
+
*
|
|
71
|
+
* Use it for standalone workbenches that are NOT bound to one conversation
|
|
72
|
+
* (dashboards, boards, consoles). Conversation-scoped UI belongs in an
|
|
73
|
+
* {@link PluginActivityTabContribution activity tab}; floating UI belongs in a
|
|
74
|
+
* {@link PluginGlobalSlotContribution global slot}.
|
|
75
|
+
*/
|
|
76
|
+
export interface PluginWorkspaceViewContribution {
|
|
77
|
+
/** Unique within the plugin; the host namespaces it as `${pluginId}:${id}`. */
|
|
78
|
+
id: string;
|
|
79
|
+
/** Sidebar entry label. Supports `%catalogKey%` i18n lookup. */
|
|
80
|
+
label: string;
|
|
81
|
+
/**
|
|
82
|
+
* Sidebar entry icon as an **iconify class string** (e.g.
|
|
83
|
+
* `"icon-[solar--widget-5-linear]"`) — NOT a React node, because the host
|
|
84
|
+
* renders it inside its own nav button and persists nav layout by key.
|
|
85
|
+
*
|
|
86
|
+
* Omit it to inherit the plugin's own `plugin.json` icon: a packaged image
|
|
87
|
+
* (svg / png / webp …) is masked with the theme's foreground color, so a plugin
|
|
88
|
+
* that ships artwork does not have to find a lookalike in an icon set. Set
|
|
89
|
+
* {@link PluginWorkspaceViewContribution.iconTint} to `false` to keep its colors.
|
|
90
|
+
*/
|
|
91
|
+
icon?: string;
|
|
92
|
+
/**
|
|
93
|
+
* Whether an image icon is tinted with the theme's foreground color. Defaults to
|
|
94
|
+
* `true`, which keeps the entry consistent with the built-in navigation and legible
|
|
95
|
+
* in every theme.
|
|
96
|
+
*
|
|
97
|
+
* Pass `false` for a full-color logo. Weigh it first: the entry renders at 16px
|
|
98
|
+
* beside monochrome built-ins, and a fixed-color image cannot follow the active
|
|
99
|
+
* theme — a dark logo can disappear on a dark sidebar. Has no effect on Iconify
|
|
100
|
+
* class icons, which are always tinted.
|
|
101
|
+
*/
|
|
102
|
+
iconTint?: boolean;
|
|
103
|
+
/** Optional one-line description; shown as the nav entry tooltip. */
|
|
104
|
+
description?: string;
|
|
105
|
+
/**
|
|
106
|
+
* Initial badge on the sidebar entry. `{ kind: "text" }` supports the same
|
|
107
|
+
* `%catalogKey%` i18n lookup as {@link label}. Update it at runtime with
|
|
108
|
+
* {@link PluginUiApi.setWorkspaceViewBadge}.
|
|
109
|
+
*/
|
|
110
|
+
badge?: PluginNavBadge;
|
|
111
|
+
/** Zero-props aside from {@link PluginWorkspaceViewProps}. */
|
|
112
|
+
component: ComponentType<PluginWorkspaceViewProps>;
|
|
113
|
+
/** Sort hint among this plugin's own views (ascending). Defaults to 0. */
|
|
114
|
+
navOrder?: number;
|
|
115
|
+
/**
|
|
116
|
+
* Whether this view takes a sidebar entry. Defaults to `true`.
|
|
117
|
+
*
|
|
118
|
+
* Pass `false` for a surface users open occasionally — a setup page, a
|
|
119
|
+
* diagnostics console. It then lives only under Settings → More options,
|
|
120
|
+
* where the host lists every off-sidebar view and opens it inside the
|
|
121
|
+
* settings shell, so switching between such pages stays one click.
|
|
122
|
+
*
|
|
123
|
+
* The sidebar is a scarce, user-curated space: a plugin that always claims a
|
|
124
|
+
* slot pushes the entries someone actually uses into the overflow menu.
|
|
125
|
+
*/
|
|
126
|
+
sidebar?: boolean;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* What a workspace view puts into the **host page header** — the window's top
|
|
130
|
+
* bar that also carries the drag region, the macOS traffic-light gutter and the
|
|
131
|
+
* sidebar trigger.
|
|
132
|
+
*
|
|
133
|
+
* Without this the header still renders, showing the app name above the
|
|
134
|
+
* plugin's own toolbar — two stacked bars. Set `hideTitle` and move the view's
|
|
135
|
+
* toolbar in here and the surface gets a single, host-consistent header.
|
|
136
|
+
*
|
|
137
|
+
* `left` / `right` are ReactNodes rendered by the host inside that bar (left:
|
|
138
|
+
* right after the sidebar trigger; right: before the window controls). They are
|
|
139
|
+
* rendered in the plugin's i18n + CSS scope, so `useTranslation()` and the
|
|
140
|
+
* plugin's own classes work as usual. Pass fresh nodes whenever the view's
|
|
141
|
+
* state changes — this is a live setter, not a one-time registration.
|
|
142
|
+
*/
|
|
143
|
+
export interface PluginWorkspaceViewHeader {
|
|
144
|
+
/** Replaces the host title text. Supports `%catalogKey%` i18n lookup. */
|
|
145
|
+
title?: string;
|
|
146
|
+
/** Drop the host title entirely (use when {@link left} carries its own). */
|
|
147
|
+
hideTitle?: boolean;
|
|
148
|
+
/** Rendered in the header's left cluster, after the sidebar trigger. */
|
|
149
|
+
left?: ReactNode;
|
|
150
|
+
/** Rendered in the header's action cluster, before the window controls. */
|
|
151
|
+
right?: ReactNode;
|
|
152
|
+
/**
|
|
153
|
+
* Float the host header OVER the view instead of stacking above it. The view
|
|
154
|
+
* then owns the full content height, and its top `~44px` sit under the
|
|
155
|
+
* transparent header strip (window drag region / traffic lights / sidebar
|
|
156
|
+
* trigger all keep working on top). Use for immersive full-page surfaces
|
|
157
|
+
* whose own hero starts at the very top; leave unset for toolbar-style
|
|
158
|
+
* headers that need their own opaque row.
|
|
159
|
+
*/
|
|
160
|
+
immersive?: boolean;
|
|
161
|
+
}
|
|
12
162
|
export interface PluginAudioMetadata {
|
|
13
163
|
/** Embedded title; preview renderers should fall back to file.name. */
|
|
14
164
|
title?: string;
|
|
@@ -63,10 +213,17 @@ export interface PluginFilePreviewContribution {
|
|
|
63
213
|
* tab to the "addable pool" — it renders only after the user attaches it in
|
|
64
214
|
* the activity panel (scoped by session cwd).
|
|
65
215
|
*/
|
|
216
|
+
/** Host residency policy for an activity-panel tab. */
|
|
217
|
+
export type PluginActivityTabRetention = "active-only" | "warm" | "pinned";
|
|
66
218
|
export interface PluginActivityTabContribution {
|
|
67
219
|
id: string;
|
|
68
220
|
label: string;
|
|
69
|
-
/**
|
|
221
|
+
/**
|
|
222
|
+
* Tab icon as a React node (not an iconify class string).
|
|
223
|
+
* Omit to inherit the host-resolved brand icon from `plugin.json#icon`
|
|
224
|
+
* (`ctx.plugin.iconUrl`). Prefer omitting for package brand icons so the
|
|
225
|
+
* plugin never loads assets via absolute `/…` paths or host protocols.
|
|
226
|
+
*/
|
|
70
227
|
icon?: ReactNode;
|
|
71
228
|
component: ComponentType;
|
|
72
229
|
/**
|
|
@@ -82,13 +239,36 @@ export interface PluginActivityTabContribution {
|
|
|
82
239
|
* 工作台跟随输入栏 toggle)。无论哪种,用户仍可用减号手动隐藏。
|
|
83
240
|
*/
|
|
84
241
|
initiallyVisible?: boolean;
|
|
242
|
+
/**
|
|
243
|
+
* Component residency while the tab is inactive. Defaults to `"warm"`:
|
|
244
|
+
* visited tabs stay mounted in the host's bounded LRU cache. Use
|
|
245
|
+
* `"active-only"` for cheap, stateless content and `"pinned"` for runtimes
|
|
246
|
+
* that must never be evicted while available.
|
|
247
|
+
*/
|
|
248
|
+
retention?: PluginActivityTabRetention;
|
|
249
|
+
/**
|
|
250
|
+
* @deprecated Use {@link PluginActivityTabContribution.retention}. `true`
|
|
251
|
+
* maps to `"pinned"`; `false` maps to `"active-only"`.
|
|
252
|
+
*/
|
|
253
|
+
keepAliveWhenAvailable?: boolean;
|
|
254
|
+
}
|
|
255
|
+
/** Explicit conversation scope for an activity-tab command. */
|
|
256
|
+
export interface PluginActivityTabTargetOptions {
|
|
257
|
+
/**
|
|
258
|
+
* Absolute cwd whose activity-tab state should be changed. Omit to target
|
|
259
|
+
* the conversation currently displayed by the host. Tool handlers and
|
|
260
|
+
* background work should pass the triggering session's cwd so a foreground
|
|
261
|
+
* navigation change cannot redirect the command to another conversation.
|
|
262
|
+
*/
|
|
263
|
+
cwd?: string;
|
|
85
264
|
}
|
|
86
265
|
/** Options for {@link PluginUiApi.openActivityTab}. */
|
|
87
|
-
export interface PluginOpenActivityTabOptions {
|
|
266
|
+
export interface PluginOpenActivityTabOptions extends PluginActivityTabTargetOptions {
|
|
88
267
|
/**
|
|
89
|
-
* Desired panel width as it opens: a pixel number, or `"max"`
|
|
90
|
-
* the
|
|
91
|
-
*
|
|
268
|
+
* Desired panel width as it opens: a pixel number, or `"max"` to track the
|
|
269
|
+
* widest the window allows — `"max"` keeps following window resizes until the
|
|
270
|
+
* user drags the divider. The host clamps to its min/max bounds. Omit to keep
|
|
271
|
+
* the user's current width.
|
|
92
272
|
*/
|
|
93
273
|
width?: number | "max";
|
|
94
274
|
}
|
|
@@ -206,7 +386,7 @@ export interface PluginToolCallSlotToolCall {
|
|
|
206
386
|
toolCallId: string;
|
|
207
387
|
toolName: string;
|
|
208
388
|
args: Record<string, unknown>;
|
|
209
|
-
status: "pending" | "success" | "error";
|
|
389
|
+
status: "pending" | "success" | "error" | "cancelled";
|
|
210
390
|
result?: string;
|
|
211
391
|
isError?: boolean;
|
|
212
392
|
}
|
|
@@ -266,8 +446,138 @@ export interface PluginNotifyOptions {
|
|
|
266
446
|
*/
|
|
267
447
|
durationMs?: number;
|
|
268
448
|
}
|
|
449
|
+
/**
|
|
450
|
+
* 新会话上下文区的激活条件。**只能写本插件自己的东西**——填别人的 id 一律不生效。
|
|
451
|
+
*
|
|
452
|
+
* 这条限制是故意的:否则插件 A 可以声明「只要用户选了 B 的智能体我就上屏」,把别人的
|
|
453
|
+
* 使用场景劫持过来。
|
|
454
|
+
*
|
|
455
|
+
* 各字段取并集:任意一条命中即激活。至少要声明一条——全空等于「任何新会话都上屏」,宿主拒掉。
|
|
456
|
+
*/
|
|
457
|
+
export interface PluginNewSessionContextActivation {
|
|
458
|
+
/** 本插件在 manifest 里声明的智能体 id(不带 `plugin:` 前缀)。 */
|
|
459
|
+
agents?: readonly string[];
|
|
460
|
+
/** 本插件在 manifest 里声明的团队 id。省略则任意「含本插件成员的团队」都算命中。 */
|
|
461
|
+
teams?: readonly string[];
|
|
462
|
+
/** 本插件提供的 skill 名;用户在输入框里提到时命中。 */
|
|
463
|
+
skills?: readonly string[];
|
|
464
|
+
/** 本插件提供的 MCP server 名。 */
|
|
465
|
+
mcpServers?: readonly string[];
|
|
466
|
+
}
|
|
467
|
+
/** 用户在新会话页当前选中的对话目标。 */
|
|
468
|
+
export interface PluginNewSessionTarget {
|
|
469
|
+
readonly kind: "agent" | "team";
|
|
470
|
+
/** Agent 档案 id 或团队 id。 */
|
|
471
|
+
readonly id: string;
|
|
472
|
+
/** 目标若由本插件贡献,这里给出 manifest 里的那个 id。 */
|
|
473
|
+
readonly contributedId?: string;
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* 渲染上下文。这是一个**会继续生长的对象**:后续新增字段不会破坏既有插件,所以按需
|
|
477
|
+
* 解构、不要假定它只有这些键。
|
|
478
|
+
*/
|
|
479
|
+
export interface PluginNewSessionContext {
|
|
480
|
+
readonly target: PluginNewSessionTarget | null;
|
|
481
|
+
/** 输入框里提到的、属于本插件的能力。 */
|
|
482
|
+
readonly mentionedAbilities: {
|
|
483
|
+
readonly skills: readonly string[];
|
|
484
|
+
readonly mcpServers: readonly string[];
|
|
485
|
+
};
|
|
486
|
+
/**
|
|
487
|
+
* 输入框中尚未发送的文本。需要 `conversation.draft.read` 权限,未授予时恒为空串。
|
|
488
|
+
*
|
|
489
|
+
* 只在本贡献处于激活状态时提供——插件拿不到「用户随便打点什么」的全程流水。
|
|
490
|
+
*/
|
|
491
|
+
readonly draft: string;
|
|
492
|
+
/** 当前工作区目录;未选择项目时为 null。 */
|
|
493
|
+
readonly cwd: string | null;
|
|
494
|
+
/** 回写输入栏。刻意不提供「直接发送」:越过发送前这道关不属于本区职责。 */
|
|
495
|
+
readonly composer: {
|
|
496
|
+
/** 把资源挂成附件,随下一次发送带走。 */
|
|
497
|
+
attach(attachment: PluginPromptAttachment): void;
|
|
498
|
+
/**
|
|
499
|
+
* 往草稿里插一段文本。始终是插入而非替换,免得抹掉用户已经打的内容。
|
|
500
|
+
*
|
|
501
|
+
* `position` 缺省为 `"end"`(光标处)。`"start"` 插到最前面,适合「先定题、细节
|
|
502
|
+
* 由用户补」这类写法——用户点完多半光标并不在开头,位置只能由调用方定死。
|
|
503
|
+
*/
|
|
504
|
+
insertText(text: string, options?: {
|
|
505
|
+
position?: "start" | "end";
|
|
506
|
+
}): void;
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* 新会话页输入框下方的一块内容(`ui.slot.new-session-context`)。
|
|
511
|
+
*
|
|
512
|
+
* 与 input-action 的分工:那是发送前的开关,这是发送前的**上下文**——把用户接下来多半
|
|
513
|
+
* 要用到的素材摆出来。激活与否由宿主按 {@link PluginNewSessionContextActivation} 裁决,
|
|
514
|
+
* 插件只负责在被激活后渲染,因此拿不到用户逐键输入的全程内容。
|
|
515
|
+
*
|
|
516
|
+
* 同时有多个贡献上屏时,宿主会在该区域顶部出 tabbar;只有一个时直接渲染内容。
|
|
517
|
+
*/
|
|
518
|
+
export interface PluginNewSessionContextContribution {
|
|
519
|
+
id: string;
|
|
520
|
+
/** tabbar 上的标题;只有一个贡献上屏时不展示。 */
|
|
521
|
+
label: string;
|
|
522
|
+
/** tab 图标;省略时用插件自己的图标。 */
|
|
523
|
+
icon?: ReactNode;
|
|
524
|
+
activateWhen: PluginNewSessionContextActivation;
|
|
525
|
+
/**
|
|
526
|
+
* 横向占位。`"input"`(默认)与输入框同宽,适合补充说明一类的窄内容;`"wide"` 铺满
|
|
527
|
+
* 页面可用宽度,留给画廊、素材墙这类「内容本身就是主角」的东西——把它们压在输入框
|
|
528
|
+
* 宽度里,每一项都会小到看不清。
|
|
529
|
+
*/
|
|
530
|
+
width?: "input" | "wide";
|
|
531
|
+
render(context: PluginNewSessionContext): ReactNode;
|
|
532
|
+
}
|
|
269
533
|
export interface PluginUiApi {
|
|
270
534
|
registerGlobalSlot(contribution: PluginGlobalSlotContribution): Disposable;
|
|
535
|
+
registerAbilityDetailSlot(contribution: PluginAbilityDetailSlotContribution): Disposable;
|
|
536
|
+
/** Render an opaque setup URL as a host-themed PNG data URL. */
|
|
537
|
+
createQrCode(text: string): Promise<string>;
|
|
538
|
+
/**
|
|
539
|
+
* Register a **workspace view**(工作区视图)— a full-page surface with its own
|
|
540
|
+
* route and sidebar entry, on par with the host's built-in pages. Needs the
|
|
541
|
+
* `ui.slot.workspace-view` permission (missing permission = **warn+noop**).
|
|
542
|
+
*
|
|
543
|
+
* The entry lands in the sidebar's「更多」收纳 by default; the user can pin it
|
|
544
|
+
* to the top region or reorder it, and that layout is remembered.
|
|
545
|
+
*/
|
|
546
|
+
registerWorkspaceView(contribution: PluginWorkspaceViewContribution): Disposable;
|
|
547
|
+
/**
|
|
548
|
+
* Register a **new-session context block** — content shown beneath the input
|
|
549
|
+
* on the new-session page, surfaced only when the user's current selection or
|
|
550
|
+
* draft matches {@link PluginNewSessionContextActivation}. Needs the
|
|
551
|
+
* `ui.slot.new-session-context` permission (missing permission = **warn+noop**).
|
|
552
|
+
*/
|
|
553
|
+
registerNewSessionContext(contribution: PluginNewSessionContextContribution): Disposable;
|
|
554
|
+
/**
|
|
555
|
+
* Navigate to one of this plugin's own workspace views. `viewId` is the
|
|
556
|
+
* contribution id passed to {@link PluginUiApi.registerWorkspaceView}. No-op
|
|
557
|
+
* when the view is not registered (e.g. permission missing).
|
|
558
|
+
*/
|
|
559
|
+
openWorkspaceView(viewId: string): void;
|
|
560
|
+
/**
|
|
561
|
+
* Update (or clear, with `null`) the badge on one of this plugin's workspace
|
|
562
|
+
* view entries. Re-registering the view is NOT a way to do this — it would
|
|
563
|
+
* remount the whole surface — so live badges (unread counts, status dots)
|
|
564
|
+
* must come through here.
|
|
565
|
+
*
|
|
566
|
+
* No-op when the view is not registered (e.g. permission missing).
|
|
567
|
+
*/
|
|
568
|
+
setWorkspaceViewBadge(viewId: string, badge: PluginNavBadge | null): void;
|
|
569
|
+
/**
|
|
570
|
+
* Fill (or clear, with `null`) the host page header while one of this
|
|
571
|
+
* plugin's workspace views is open. Call it from the view component (an
|
|
572
|
+
* effect that re-runs on state change) and clear it on unmount — the host
|
|
573
|
+
* keeps the entry keyed by view, and only applies it on that view's route.
|
|
574
|
+
*
|
|
575
|
+
* The header itself is never removed: it owns the window drag region and the
|
|
576
|
+
* macOS traffic-light gutter. This is how a view takes it over instead.
|
|
577
|
+
*
|
|
578
|
+
* No-op when the view is not registered (e.g. permission missing).
|
|
579
|
+
*/
|
|
580
|
+
setWorkspaceViewHeader(viewId: string, header: PluginWorkspaceViewHeader | null): void;
|
|
271
581
|
/**
|
|
272
582
|
* Register a preview component keyed by file extension. The host dispatches
|
|
273
583
|
* registered extensions before its built-in fallback renderers; first
|
|
@@ -317,7 +627,7 @@ export interface PluginUiApi {
|
|
|
317
627
|
registerShortcutScope(contribution: PluginShortcutScopeContribution): Disposable;
|
|
318
628
|
/**
|
|
319
629
|
* Programmatically attach (if needed) and activate one of this plugin's
|
|
320
|
-
* own activity tabs in
|
|
630
|
+
* own activity tabs in a conversation's activity panel. `tabId`
|
|
321
631
|
* is the contribution id passed to registerActivityTab. Any payload (e.g.
|
|
322
632
|
* which image to edit) is passed via the plugin's own in-memory state.
|
|
323
633
|
*
|
|
@@ -325,22 +635,29 @@ export interface PluginUiApi {
|
|
|
325
635
|
* `"max"` to expand it to the widest the current window allows (the host
|
|
326
636
|
* still clamps to its min/max and auto-hides the sidebar when needed). Omit
|
|
327
637
|
* to leave the user's current width untouched.
|
|
638
|
+
*
|
|
639
|
+
* Omit `options.cwd` for the conversation currently displayed by the host.
|
|
640
|
+
* Tool handlers and background work should pass their session cwd explicitly.
|
|
328
641
|
*/
|
|
329
642
|
openActivityTab(tabId: string, options?: PluginOpenActivityTabOptions): void;
|
|
330
643
|
/**
|
|
331
|
-
*
|
|
644
|
+
* 把本插件的某个活动面板标签卡在目标会话里上栏 / 下栏,**不激活也不展开
|
|
332
645
|
* 面板**——`openActivityTab` 是「用户此刻要看它」,这个是「它现在该不该在
|
|
333
646
|
* 栏里」。配合 `initiallyVisible: false` 使用,插件即可完全掌握自己标签卡的
|
|
334
647
|
* 出现条件(如 git 只在仓库目录里上栏、工作台跟随输入栏 toggle)。
|
|
335
648
|
*
|
|
336
649
|
* 上栏记录按会话 cwd 持久化(ADR-0026),所以只需在条件变化时调用一次;
|
|
337
|
-
*
|
|
338
|
-
*
|
|
650
|
+
* 用户随后用减号手动隐藏的结果不会被重复调用覆盖。缺省作用于宿主当前显示的
|
|
651
|
+
* 会话;工具 handler 与后台任务应通过 `options.cwd` 传入自己的会话 cwd。既没有
|
|
652
|
+
* 显式 cwd、也没有活动会话时为 no-op(无处记录)。
|
|
339
653
|
*/
|
|
340
|
-
setActivityTabVisible(tabId: string, visible: boolean): void;
|
|
654
|
+
setActivityTabVisible(tabId: string, visible: boolean, options?: PluginActivityTabTargetOptions): void;
|
|
341
655
|
/**
|
|
342
|
-
* 直接设置活动面板宽度:像素值,或 `"max"`
|
|
343
|
-
*
|
|
656
|
+
* 直接设置活动面板宽度:像素值,或 `"max"` 表示「跟随窗口拉满」(宿主仍会夹到
|
|
657
|
+
* 自己的 min/max 内,必要时自动收起侧边栏)。
|
|
658
|
+
*
|
|
659
|
+
* `"max"` 是一种持续状态而非一次性求值:窗口尺寸变化时面板跟着变宽变窄,直到
|
|
660
|
+
* 用户拖动分隔条或有人写入具体像素为止。传数字则是一次性的固定宽度。
|
|
344
661
|
*
|
|
345
662
|
* 与 `openActivityTab(id, { width })` 的区别:那里的宽度只在标签卡首次 attach
|
|
346
663
|
* 时生效(避免 activate 重放覆盖用户手拖的宽度);这个是命令式的,每次调用都
|
|
@@ -348,9 +665,10 @@ export interface PluginUiApi {
|
|
|
348
665
|
*/
|
|
349
666
|
setActivityPanelWidth(width: number | "max"): void;
|
|
350
667
|
/**
|
|
351
|
-
* Bind or clear plugin-owned
|
|
352
|
-
*
|
|
353
|
-
*
|
|
668
|
+
* Bind or clear plugin-owned context for outgoing prompts. The host renders
|
|
669
|
+
* its label/icon and carries a structured `context` as a versioned snapshot.
|
|
670
|
+
* Attachments default to one-shot; `lifecycle: "sticky"` remains until the
|
|
671
|
+
* plugin or user clears the capsule.
|
|
354
672
|
*/
|
|
355
673
|
setPromptAttachment(attachment: PluginPromptAttachment | null): void;
|
|
356
674
|
/**
|
|
@@ -361,12 +679,6 @@ export interface PluginUiApi {
|
|
|
361
679
|
* the previewer shows a thumbnail strip + arrows and starts at `ref`.
|
|
362
680
|
*/
|
|
363
681
|
previewImage(ref: PluginImageRef, group?: PluginImageRef[]): void;
|
|
364
|
-
/**
|
|
365
|
-
* Open the app settings, scrolled to and highlighting THIS plugin's own
|
|
366
|
-
* settings section (e.g. so the user can fill in a required API key/model).
|
|
367
|
-
* The host owns the navigation; the plugin only asks to jump there.
|
|
368
|
-
*/
|
|
369
|
-
openPluginSettings(): void;
|
|
370
682
|
/**
|
|
371
683
|
* Capture a rectangle in the current Vetta window and open the host save
|
|
372
684
|
* dialog. Coordinates use renderer DIP values such as getBoundingClientRect().
|
|
@@ -380,6 +692,13 @@ export interface PluginUiApi {
|
|
|
380
692
|
* can only write what it already rendered.
|
|
381
693
|
*/
|
|
382
694
|
copyImage(dataUrl: string): Promise<void>;
|
|
695
|
+
/**
|
|
696
|
+
* Hand a URL to the OS default browser (Electron `shell.openExternal`) —
|
|
697
|
+
* NOT the in-app browser panel. Only `http:`/`https:` are accepted; the host
|
|
698
|
+
* rejects every other protocol, so this cannot be used to launch arbitrary
|
|
699
|
+
* schemes. Needs `shell.openExternal`.
|
|
700
|
+
*/
|
|
701
|
+
openExternal(url: string): Promise<void>;
|
|
383
702
|
/**
|
|
384
703
|
* Show a global toast in the host UI (bottom-right). No permission required.
|
|
385
704
|
* Prefer this over swallowing errors into opaque UI copy: pass `error` so
|