@clipbus/plugin-sdk 0.9.8 → 0.10.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/API.md +94 -27
- package/CHANGELOG.md +84 -0
- package/README.md +11 -3
- package/SPECIFICATION.md +3 -2
- package/dist/dom/index.cjs +29 -34
- package/dist/dom/index.js +29 -34
- package/dist/dom/topicAdapter.d.ts +1 -1
- package/dist/generated/capabilities.generated.d.ts +355 -0
- package/dist/generated/data.generated.d.ts +33 -0
- package/dist/generated/hostClients.generated.d.ts +8 -5
- package/dist/generated/hostEvents.generated.d.ts +68 -0
- package/dist/generated/nodeIPC.generated.d.ts +106 -0
- package/dist/generated/{runtime.definePlugin.generated.d.ts → runtime.registry.generated.d.ts} +2 -2
- package/dist/generated/ui.clipbus.generated.d.ts +19 -20
- package/dist/generated/wireConstants.generated.d.ts +21 -0
- package/dist/internal/capabilities.d.ts +1 -1
- package/dist/internal/hostEvents.d.ts +15 -0
- package/dist/internal/pluginCall.d.ts +11 -0
- package/dist/internal/pluginContext.d.ts +6 -0
- package/dist/preview/index.cjs +41 -48
- package/dist/preview/index.js +41 -48
- package/dist/preview/wire.d.ts +2 -2
- package/dist/runtime/defineMessage.d.ts +1 -1
- package/dist/runtime/definePlugin.d.ts +2 -0
- package/dist/runtime/index.cjs +10 -82
- package/dist/runtime/index.d.cts +7 -1
- package/dist/runtime/index.d.ts +7 -1
- package/dist/runtime/index.js +9 -80
- package/dist/ui/index.cjs +107 -169
- package/dist/ui/index.d.cts +5 -1
- package/dist/ui/index.d.ts +5 -1
- package/dist/ui/index.js +107 -169
- package/dist/validate/index.d.cts +5 -4
- package/dist/validate/index.d.ts +5 -4
- package/docs/authoring.md +1 -1
- package/docs/capability-detection.md +2 -2
- package/docs/entry.md +4 -3
- package/docs/item-context.md +5 -3
- package/docs/permissions.md +1 -1
- package/package.json +7 -5
- package/dist/generated/INDEX.runtime.generated.d.ts +0 -6
- package/dist/generated/INDEX.ui.generated.d.ts +0 -4
- package/dist/generated/capabilityClients.generated.d.ts +0 -231
- package/dist/generated/hostBootstrap.generated.d.ts +0 -23
- package/dist/generated/runtime.host.generated.d.ts +0 -39
- package/dist/generated/topicSubscribers.generated.d.ts +0 -39
- package/dist/generated/ui.bootstrap.generated.d.ts +0 -17
- package/dist/internal/ipcBus.d.ts +0 -48
- package/dist/internal/runtimeInvokeClient.d.ts +0 -3
package/API.md
CHANGED
|
@@ -9,10 +9,10 @@ Every entry below maps 1:1 to a catalog descriptor — there is no hidden surfac
|
|
|
9
9
|
|
|
10
10
|
## 1. Overview
|
|
11
11
|
|
|
12
|
-
- **Capabilities**:
|
|
12
|
+
- **Capabilities**: 35
|
|
13
13
|
- **Host events**: 11
|
|
14
14
|
- **Node IPC methods**: 6
|
|
15
|
-
- **Named types**:
|
|
15
|
+
- **Named types**: 40
|
|
16
16
|
|
|
17
17
|
## 2. Capabilities
|
|
18
18
|
|
|
@@ -92,6 +92,14 @@ Every entry below maps 1:1 to a catalog descriptor — there is no hidden surfac
|
|
|
92
92
|
- **Payload**: { index: `int` }
|
|
93
93
|
- **Response**: { url?: `string` }
|
|
94
94
|
|
|
95
|
+
#### `asset.allocateImageTempPath`
|
|
96
|
+
|
|
97
|
+
- **Side**: runtime
|
|
98
|
+
- **Context**: any
|
|
99
|
+
- **Path**: `asset.allocateImageTempPath`
|
|
100
|
+
- **Payload**: { formatHint: `string` }
|
|
101
|
+
- **Response**: { path: `string` }
|
|
102
|
+
|
|
95
103
|
#### `asset.registerImage`
|
|
96
104
|
|
|
97
105
|
- **Side**: runtime
|
|
@@ -130,6 +138,14 @@ Every entry below maps 1:1 to a catalog descriptor — there is no hidden surfac
|
|
|
130
138
|
- **Payload**: { level: [`PluginConsoleLogLevel`](#pluginconsoleloglevel), message: `string` }
|
|
131
139
|
- **Response**: { }
|
|
132
140
|
|
|
141
|
+
#### `console.diagnostic`
|
|
142
|
+
|
|
143
|
+
- **Side**: both
|
|
144
|
+
- **Context**: any
|
|
145
|
+
- **Path**: `console.diagnostic`
|
|
146
|
+
- **Payload**: { level: [`PluginConsoleLogLevel`](#pluginconsoleloglevel), event: [`PluginDiagnosticEvent`](#plugindiagnosticevent), reason: [`PluginDiagnosticReason`](#plugindiagnosticreason), count: `int`, durationMs: `int` }
|
|
147
|
+
- **Response**: { }
|
|
148
|
+
|
|
133
149
|
### infoPanel
|
|
134
150
|
|
|
135
151
|
#### `infoPanel.open`
|
|
@@ -311,26 +327,27 @@ Every entry below maps 1:1 to a catalog descriptor — there is no hidden surfac
|
|
|
311
327
|
| Capability | UI path | Runtime path | Context |
|
|
312
328
|
| --- | --- | --- | --- |
|
|
313
329
|
| `runtime.invoke` | `clipbus.runtime.invoke` | — | any |
|
|
314
|
-
| `item.setTags` | — | `host.item.setTags` | any |
|
|
315
|
-
| `item.addTags` | — | `host.item.addTags` | any |
|
|
316
|
-
| `item.removeTags` | — | `host.item.removeTags` | any |
|
|
317
|
-
| `item.setPinned` | — | `host.item.setPinned` | any |
|
|
318
|
-
| `item.setAttachments` | — | `host.item.setAttachments` | any |
|
|
319
|
-
| `item.setSearchExtension` | — | `host.item.setSearchExtension` | any |
|
|
320
|
-
| `item.materializeImagePath` | — | `host.item.materializeImagePath` | any |
|
|
321
|
-
| `item.readAttachment` | `clipbus.item.readAttachment` | `host.item.readAttachment` | any |
|
|
330
|
+
| `item.setTags` | — | `ctx.host.item.setTags` | any |
|
|
331
|
+
| `item.addTags` | — | `ctx.host.item.addTags` | any |
|
|
332
|
+
| `item.removeTags` | — | `ctx.host.item.removeTags` | any |
|
|
333
|
+
| `item.setPinned` | — | `ctx.host.item.setPinned` | any |
|
|
334
|
+
| `item.setAttachments` | — | `ctx.host.item.setAttachments` | any |
|
|
335
|
+
| `item.setSearchExtension` | — | `ctx.host.item.setSearchExtension` | any |
|
|
336
|
+
| `item.materializeImagePath` | — | `ctx.host.item.materializeImagePath` | any |
|
|
337
|
+
| `item.readAttachment` | `clipbus.item.readAttachment` | `ctx.host.item.readAttachment` | any |
|
|
322
338
|
| `asset.currentItemImageUrl` | `clipbus.asset.currentItemImageUrl` | — | any |
|
|
323
339
|
| `asset.pathReferenceImageUrl` | `clipbus.asset.pathReferenceImageUrl` | — | any |
|
|
324
340
|
| `asset.currentActionInputImageUrl` | `clipbus.asset.currentActionInputImageUrl` | — | action |
|
|
325
341
|
| `asset.currentActionInputPathReferenceImageUrl` | `clipbus.asset.currentActionInputPathReferenceImageUrl` | — | action |
|
|
326
|
-
| `asset.
|
|
327
|
-
| `
|
|
328
|
-
| `
|
|
329
|
-
| `navigation.
|
|
330
|
-
| `navigation.
|
|
331
|
-
| `
|
|
332
|
-
| `action.
|
|
333
|
-
| `action.
|
|
342
|
+
| `asset.allocateImageTempPath` | — | `ctx.host.asset.allocateImageTempPath` | any |
|
|
343
|
+
| `asset.registerImage` | — | `ctx.host.asset.registerImage` | any |
|
|
344
|
+
| `clipboard.copyText` | `clipbus.clipboard.copyText` | `ctx.host.clipboard.copyText` | any |
|
|
345
|
+
| `navigation.openUrl` | `clipbus.navigation.openUrl` | `ctx.host.navigation.openUrl` | any |
|
|
346
|
+
| `navigation.revealInFinder` | `clipbus.navigation.revealInFinder` | `ctx.host.navigation.revealInFinder` | any |
|
|
347
|
+
| `navigation.openFilePath` | `clipbus.navigation.openFilePath` | `ctx.host.navigation.openFilePath` | any |
|
|
348
|
+
| `action.allocateImageTempPath` | — | `ctx.host.action.allocateImageTempPath` | action |
|
|
349
|
+
| `action.materializeInputImagePath` | — | `ctx.host.action.materializeInputImagePath` | action |
|
|
350
|
+
| `action.allocateOutputFilePath` | — | `ctx.host.action.allocateOutputFilePath` | action |
|
|
334
351
|
| `action.setButtons` | `clipbus.action.setButtons` | — | action |
|
|
335
352
|
| `action.complete` | `clipbus.action.complete` | — | action |
|
|
336
353
|
| `attachmentRenderer.setButtons` | `clipbus.attachmentRenderer.setButtons` | — | attachmentRenderer |
|
|
@@ -338,11 +355,12 @@ Every entry below maps 1:1 to a catalog descriptor — there is no hidden surfac
|
|
|
338
355
|
| `window.autoFit` | `clipbus.window.autoFit` | — | any |
|
|
339
356
|
| `infoPanel.open` | `clipbus.infoPanel.open` | — | any |
|
|
340
357
|
| `infoPanel.close` | `clipbus.infoPanel.close` | — | any |
|
|
341
|
-
| `settings.get` | `clipbus.settings.get` | `host.settings.get` | any |
|
|
342
|
-
| `settings.getAll` | `clipbus.settings.getAll` | `host.settings.getAll` | any |
|
|
343
|
-
| `console.log` | `clipbus.console.log` | `host.console.log` | any |
|
|
358
|
+
| `settings.get` | `clipbus.settings.get` | `ctx.host.settings.get` | any |
|
|
359
|
+
| `settings.getAll` | `clipbus.settings.getAll` | `ctx.host.settings.getAll` | any |
|
|
360
|
+
| `console.log` | `clipbus.console.log` | `ctx.host.console.log` | any |
|
|
361
|
+
| `console.diagnostic` | `clipbus.console.diagnostic` | `ctx.host.console.diagnostic` | any |
|
|
344
362
|
| `textInput.stateChanged` | `clipbus.textInput.stateChanged` | — | any |
|
|
345
|
-
| `locale.get` | — | `host.locale.get` | any |
|
|
363
|
+
| `locale.get` | — | `ctx.host.locale.get` | any |
|
|
346
364
|
|
|
347
365
|
## 4. Host Events
|
|
348
366
|
|
|
@@ -560,6 +578,14 @@ Discriminated union on `type`: { type: `'label'`, text: `string` } | { type: `'t
|
|
|
560
578
|
|
|
561
579
|
Union: `'debug'` | `'info'` | `'warn'` | `'error'`
|
|
562
580
|
|
|
581
|
+
### `PluginDiagnosticEvent`
|
|
582
|
+
|
|
583
|
+
Union: `'action_started'` | `'action_completed'` | `'action_failed'` | `'renderer_ready'` | `'renderer_failed'` | `'detector_completed'` | `'detector_failed'` | `'runtime_ready'` | `'runtime_failed'`
|
|
584
|
+
|
|
585
|
+
### `PluginDiagnosticReason`
|
|
586
|
+
|
|
587
|
+
Union: `'none'` | `'invalid_input'` | `'unsupported'` | `'timeout'` | `'unavailable'` | `'failed'`
|
|
588
|
+
|
|
563
589
|
### `PluginClipboardItem`
|
|
564
590
|
|
|
565
591
|
- `id`: `string`
|
|
@@ -689,6 +715,46 @@ Discriminated union on `kind`: { kind: `'text'`, text: `string` } | { kind: `'im
|
|
|
689
715
|
- `result`: [`PluginActionResult`](#pluginactionresult)
|
|
690
716
|
- `userMessage?`: `string`
|
|
691
717
|
|
|
718
|
+
### `PluginNodeIPCRequestFrame`
|
|
719
|
+
|
|
720
|
+
- `id`: `string`
|
|
721
|
+
- `method`: `string`
|
|
722
|
+
- `request`: `json`
|
|
723
|
+
|
|
724
|
+
### `PluginNodeIPCResponseFrame`
|
|
725
|
+
|
|
726
|
+
- `id?`: `string`
|
|
727
|
+
- `response?`: `json`
|
|
728
|
+
- `error?`: `json`
|
|
729
|
+
|
|
730
|
+
### `PluginNodeIPCErrorFrame`
|
|
731
|
+
|
|
732
|
+
- `name`: `string`
|
|
733
|
+
- `message`: `string`
|
|
734
|
+
- `data?`: `json`
|
|
735
|
+
|
|
736
|
+
### `PluginRuntimePluginDescriptor`
|
|
737
|
+
|
|
738
|
+
- `id`: `string`
|
|
739
|
+
- `title`: `string`
|
|
740
|
+
- `version`: `string`
|
|
741
|
+
|
|
742
|
+
### `PluginRuntimeHostPlatform`
|
|
743
|
+
|
|
744
|
+
Union: `'macos'` | `'windows'`
|
|
745
|
+
|
|
746
|
+
### `PluginRuntimeHostDescriptor`
|
|
747
|
+
|
|
748
|
+
- `platform`: [`PluginRuntimeHostPlatform`](#pluginruntimehostplatform)
|
|
749
|
+
- `hostVersion`: `string`
|
|
750
|
+
- `devMode`: `bool`
|
|
751
|
+
|
|
752
|
+
### `PluginRuntimeLaunchContext`
|
|
753
|
+
|
|
754
|
+
- `plugin`: [`PluginRuntimePluginDescriptor`](#pluginruntimeplugindescriptor)
|
|
755
|
+
- `host`: [`PluginRuntimeHostDescriptor`](#pluginruntimehostdescriptor)
|
|
756
|
+
- `supportedCapabilities`: `string`[]
|
|
757
|
+
|
|
692
758
|
## 9. Wire Constants
|
|
693
759
|
|
|
694
760
|
- `__clipbus_structured_error__:` — prefix used by the runtime error envelope.
|
|
@@ -709,11 +775,12 @@ Discriminated union on `kind`: { kind: `'text'`, text: `string` } | { kind: `'im
|
|
|
709
775
|
|
|
710
776
|
| Concept | Generated file (TS) | Generated file (Swift) |
|
|
711
777
|
| --- | --- | --- |
|
|
712
|
-
| Capability payload/response types | `
|
|
778
|
+
| Capability payload/response types + method map | `capabilities.generated.ts` | `PluginCapabilityPayloads.generated.swift` |
|
|
713
779
|
| UI capability tree | `ui.clipbus.generated.ts` | — |
|
|
714
|
-
| Runtime host
|
|
715
|
-
| Host
|
|
716
|
-
| Node IPC
|
|
780
|
+
| Runtime host client (`ctx.host`) | `hostClients.generated.ts` | — |
|
|
781
|
+
| Host events (payloads, window globals, bootstrap sets) | `hostEvents.generated.ts` | `PluginHostTopicEmitter.generated.swift` |
|
|
782
|
+
| Node IPC types + handler routes | `nodeIPC.generated.ts` | `PluginNodeIPCClient.generated.swift` |
|
|
717
783
|
| Named types | `data.generated.ts` | `PluginCommonTypes.generated.swift` |
|
|
718
784
|
| Handler interfaces | `runtime.handlers.generated.ts` | `PluginUIHostHandler.generated.swift`, `PluginRuntimeHostHandler.generated.swift` |
|
|
719
|
-
|
|
|
785
|
+
| Registry / setup types | `runtime.registry.generated.ts` | — |
|
|
786
|
+
| Wire constants | `wireConstants.generated.ts` | `PluginWireConstants.generated.swift` |
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Release notes for `@clipbus/plugin-sdk`, newest first. Each version is also published at https://github.com/scubers/clipbus-release/releases?q=%22Clipbus+Plugin+SDK%22&expanded=true
|
|
4
|
+
|
|
5
|
+
## 0.10.0
|
|
6
|
+
|
|
7
|
+
### New
|
|
8
|
+
|
|
9
|
+
- **Session-owned temporary paths for generated images**: `ctx.host.asset.allocateImageTempPath({ formatHint })` allocates an image path owned by the current session in any runtime context. Write the image there, then call `ctx.host.asset.registerImage({ path })` to get a URL the WebView can render. The path expires with its owning session; neither method is callable from the WebView.
|
|
10
|
+
- **Structured diagnostics**: `clipbus.console.diagnostic(...)` (UI) and `ctx.host.console.diagnostic(...)` (runtime) take `{ level, event, reason, count, durationMs }`, where `event` and `reason` come from the closed `PluginDiagnosticEvent` / `PluginDiagnosticReason` vocabularies. Use it for anything you need to see in the Log Console:
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
await clipbus.console.diagnostic({ level: 'info', event: 'action_completed', reason: 'none', count: 1, durationMs: 42 });
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Hosts that support it record only the level and byte count of `console.log`, not the message text. Diagnostic volume is bounded and excess calls may be rejected.
|
|
17
|
+
- **Runtime type exports**: `@clipbus/plugin-sdk/runtime` now exports `PluginRegistry`, `PluginSetup`, `MessageHandler`, `MessageHandlerContext`, `HostClient` (the type of `ctx.host`) and `PluginRuntimeLaunchContext`. The `context` argument of `definePlugin({ setup(context) { ... } })` is now typed and carries `plugin`, `host` and `supportedCapabilities`.
|
|
18
|
+
|
|
19
|
+
### Breaking changes
|
|
20
|
+
|
|
21
|
+
- **The `host` export of `@clipbus/plugin-sdk/runtime` is removed.** It was never connected to the Host and threw on every call. Use `ctx.host` from the handler context instead; in ESM, a remaining `import { host }` makes the module fail to load.
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
// Before
|
|
25
|
+
import { host } from '@clipbus/plugin-sdk/runtime';
|
|
26
|
+
await host.clipboard.copyText({ text });
|
|
27
|
+
|
|
28
|
+
// After
|
|
29
|
+
async runAutoAction(input, ctx) {
|
|
30
|
+
await ctx?.host?.clipboard.copyText({ text });
|
|
31
|
+
// ...
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Compatibility
|
|
36
|
+
|
|
37
|
+
- `asset.allocateImageTempPath` and `console.diagnostic` require Clipbus for macOS 1.6.0 or Clipbus for Windows 0.1.0 or later. Older Hosts reject them with `CapabilityUnsupportedError`; check `clipbus.capabilities.has(...)` or the launch context's `supportedCapabilities` first.
|
|
38
|
+
- Everything else takes effect by upgrading the npm package.
|
|
39
|
+
|
|
40
|
+
### Other
|
|
41
|
+
|
|
42
|
+
- The npm package now ships `CHANGELOG.md`, and every version's notes are published as [Plugin SDK releases](https://github.com/scubers/clipbus-release/releases?q=%22Clipbus+Plugin+SDK%22&expanded=true). The package `homepage` and `repository` now point to that release repository.
|
|
43
|
+
|
|
44
|
+
<details>
|
|
45
|
+
<summary>简体中文</summary>
|
|
46
|
+
|
|
47
|
+
### 新增
|
|
48
|
+
|
|
49
|
+
- **运行时生成图片的会话临时路径**:`ctx.host.asset.allocateImageTempPath({ formatHint })` 在任意运行时上下文中分配一个归属当前会话的图片路径,写入图片后再调用 `ctx.host.asset.registerImage({ path })` 获得 WebView 可渲染的 URL。路径随所属会话一起失效;WebView 侧不能调用这两个方法。
|
|
50
|
+
- **结构化诊断日志**:新增 `clipbus.console.diagnostic(...)`(UI)与 `ctx.host.console.diagnostic(...)`(运行时),参数为 `{ level, event, reason, count, durationMs }`,`event` / `reason` 取自封闭枚举 `PluginDiagnosticEvent` / `PluginDiagnosticReason`。需要在 Log Console 中查看的信息请改用它:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
await clipbus.console.diagnostic({ level: 'info', event: 'action_completed', reason: 'none', count: 1, durationMs: 42 });
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
支持该能力的 Host 只记录 `console.log` 的级别与字节数,不记录消息正文;诊断调用量有上限,超出可能被拒绝。
|
|
57
|
+
- **运行时类型导出**:`@clipbus/plugin-sdk/runtime` 现在导出 `PluginRegistry`、`PluginSetup`、`MessageHandler`、`MessageHandlerContext`、`HostClient`(即 `ctx.host` 的类型)以及 `PluginRuntimeLaunchContext`。`definePlugin({ setup(context) { ... } })` 中的 `context` 有了类型,包含 `plugin`、`host` 与 `supportedCapabilities`。
|
|
58
|
+
|
|
59
|
+
### 不兼容变更
|
|
60
|
+
|
|
61
|
+
- **移除 `@clipbus/plugin-sdk/runtime` 的 `host` 导出**。该对象从未接通 Host,任何调用都会抛错。请改用处理函数上下文中的 `ctx.host`;在 ESM 中保留 `import { host }` 会导致模块加载失败。
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
// 之前
|
|
65
|
+
import { host } from '@clipbus/plugin-sdk/runtime';
|
|
66
|
+
await host.clipboard.copyText({ text });
|
|
67
|
+
|
|
68
|
+
// 之后
|
|
69
|
+
async runAutoAction(input, ctx) {
|
|
70
|
+
await ctx?.host?.clipboard.copyText({ text });
|
|
71
|
+
// ...
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 兼容性
|
|
76
|
+
|
|
77
|
+
- `asset.allocateImageTempPath` 与 `console.diagnostic` 需要 Clipbus macOS 1.6.0 或 Windows 0.1.0 及以上版本。较旧的 Host 会以 `CapabilityUnsupportedError` 拒绝,可先用 `clipbus.capabilities.has(...)` 或启动上下文中的 `supportedCapabilities` 检测。
|
|
78
|
+
- 其余变更只需升级 npm 包即可生效。
|
|
79
|
+
|
|
80
|
+
### 其他
|
|
81
|
+
|
|
82
|
+
- npm 包内新增 `CHANGELOG.md`,各版本说明同时发布在 [Plugin SDK releases](https://github.com/scubers/clipbus-release/releases?q=%22Clipbus+Plugin+SDK%22&expanded=true);包的 `homepage` 与 `repository` 改为指向该发布仓库。
|
|
83
|
+
|
|
84
|
+
</details>
|
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Standalone, publishable SDK for Clipbus plugins. Provides typed helpers for the runtime (Node.js) and UI (WebView) sides of a plugin.
|
|
4
4
|
|
|
5
|
+
Release notes for every version are published as [Plugin SDK releases](https://github.com/scubers/clipbus-release/releases?q=%22Clipbus+Plugin+SDK%22&expanded=true) and ship in this package as `CHANGELOG.md`.
|
|
6
|
+
|
|
5
7
|
## Installation
|
|
6
8
|
|
|
7
9
|
Install from npm:
|
|
@@ -288,7 +290,7 @@ Returns opaque `clipbus-asset://` URLs so a WebView can render local images in `
|
|
|
288
290
|
| `clipbus.asset.currentActionInputImageUrl()` | `Verb → {url?: string}` | Action-context URL for the current image value, independent of `sourceItem.type`. |
|
|
289
291
|
| `clipbus.asset.currentActionInputPathReferenceImageUrl({index})` | `Verb → {url?: string}` | Action-context URL for a current path-reference entry. |
|
|
290
292
|
|
|
291
|
-
|
|
293
|
+
Generated images are minted only on the runtime side: allocate a session-owned path with `ctx.host.asset.allocateImageTempPath({formatHint})`, write the image, then call `ctx.host.asset.registerImage({path})`. The WebView cannot call either method or mint a URL for a local file.
|
|
292
294
|
|
|
293
295
|
```ts
|
|
294
296
|
import { clipbus } from '@clipbus/plugin-sdk/ui';
|
|
@@ -462,18 +464,21 @@ clipbus.infoPanel.onClose.on(({ panelID }) => { /* clean up */ });
|
|
|
462
464
|
|
|
463
465
|
| Member | Shape | Description |
|
|
464
466
|
|---|---|---|
|
|
465
|
-
| `clipbus.console.log({level, message})` | `Verb` |
|
|
467
|
+
| `clipbus.console.log({level, message})` | `Verb` | Send legacy console output; the host records only level and UTF-8 byte count, not the message text |
|
|
468
|
+
| `clipbus.console.diagnostic({level, event, reason, count, durationMs})` | `Verb` | Record a structured, privacy-safe diagnostic using the closed event/reason vocabulary in `API.md` |
|
|
466
469
|
| `clipbus.textInput.stateChanged({isFocused, isComposing})` | `Verb` | Notify host that a text input's focus / IME state changed |
|
|
467
470
|
| `clipbus.pluginContext.current()` | Topic | `{ mode: 'attachmentRenderer' \| 'action', pluginID }` — read which kind of WebView this code is running in |
|
|
468
471
|
| `clipbus.pluginContext.on(fn)` | Topic | Subscribe (rare; context doesn't normally change after bootstrap) |
|
|
469
472
|
|
|
470
473
|
> Strict wire shape: every verb takes a single object parameter (`{text}`, `{url}`, etc.), never a bare value. The single source of truth for every payload / response shape is [API.md](./API.md), generated from `protocol/plugin/src/catalog.ts`.
|
|
471
474
|
|
|
475
|
+
Use `console.diagnostic` for information you need in the Log Console. For example, `await clipbus.console.diagnostic({ level: 'info', event: 'action_completed', reason: 'none', count: 1, durationMs: 42 })`. Do not put clipboard content, paths, identifiers, or secrets into log messages; the structured channel has no field for them. The host bounds diagnostic volume and may reject excess calls.
|
|
476
|
+
|
|
472
477
|
---
|
|
473
478
|
|
|
474
479
|
## Types
|
|
475
480
|
|
|
476
|
-
All public types live in the generated `data.generated.ts` / `
|
|
481
|
+
All public types live in the generated `data.generated.ts` / `capabilities.generated.ts` (plus `hostClients.generated.ts` and `runtime.registry.generated.ts` for the runtime entry) and carry the `Plugin` prefix. The pre-`plugin-api-shrink` aliases without the prefix have been removed.
|
|
477
482
|
|
|
478
483
|
```ts
|
|
479
484
|
// Data types — re-exported from both /runtime and /ui
|
|
@@ -513,8 +518,11 @@ import type {
|
|
|
513
518
|
// definePlugin types — runtime side only
|
|
514
519
|
import type {
|
|
515
520
|
PluginRegistry,
|
|
521
|
+
PluginSetup,
|
|
522
|
+
PluginRuntimeLaunchContext, // setup(context) argument
|
|
516
523
|
MessageHandler,
|
|
517
524
|
MessageHandlerContext,
|
|
525
|
+
HostClient, // the type of ctx.host
|
|
518
526
|
} from '@clipbus/plugin-sdk/runtime';
|
|
519
527
|
```
|
|
520
528
|
|
package/SPECIFICATION.md
CHANGED
|
@@ -179,6 +179,7 @@ Capabilities are split by catalog `surface.side`: runtime capabilities are expos
|
|
|
179
179
|
| Replace action button list | `action.setButtons` | — | `clipbus.action.setButtons({buttons})` | Verb; buttons have `isEnabled?: boolean` field |
|
|
180
180
|
| Submit draft result | `action.complete` | — | `clipbus.action.complete({result, userMessage?})` | Verb; draft lifecycle only; value results can be explicitly advanced by the user, `none` cannot |
|
|
181
181
|
| Allocate image temp path | `action.allocateImageTempPath` | `ctx.host.action.allocateImageTempPath({formatHint?})` | — | Verb; runtime-only via user RPC bridge; removed from UI in plugin-api-shrink |
|
|
182
|
+
| Allocate session image path | `asset.allocateImageTempPath` | `ctx.host.asset.allocateImageTempPath({formatHint})` | — | Runtime-only, any context with a temporary-resource owner; path expires with that owner |
|
|
182
183
|
| Materialize current Action image | `action.materializeInputImagePath` | `ctx.host.action.materializeInputImagePath()` | — | Reads current cascade image, not the original item |
|
|
183
184
|
| Allocate Action output file | `action.allocateOutputFilePath` | `ctx.host.action.allocateOutputFilePath({suggestedName?})` | — | Path may only be returned as an `allocated_file` result entry |
|
|
184
185
|
| Current Action input | action input host event | input param | `clipbus.action.input.current()` | Sanitized Topic; path values omit real paths |
|
|
@@ -273,7 +274,7 @@ The plugin wire is fully codegen-driven. Choosing between `defineCapability` and
|
|
|
273
274
|
|
|
274
275
|
6. **Test** — add host bridge tests for the new method. Do not write pure UI unit tests; codegen snapshot tests cover the surface.
|
|
275
276
|
|
|
276
|
-
7. **Verify locally** — `./scripts/checks/check-plugin-contract.sh` and the host platform test flow must
|
|
277
|
+
7. **Verify locally** — `cd protocol/plugin && npm test`, `./scripts/checks/check-plugin-contract.sh` and the host platform test flow must all exit 0.
|
|
277
278
|
|
|
278
279
|
8. **PR** — see Chapter 5 for the PR checklist.
|
|
279
280
|
|
|
@@ -366,7 +367,7 @@ Before merging any PR that touches `sdk/`:
|
|
|
366
367
|
- [ ] `npm run build` passes in `sdk/`
|
|
367
368
|
- [ ] `npm test` passes in `sdk/` (runtime + ui + surface)
|
|
368
369
|
- [ ] Surface snapshot updated with `SNAPSHOT_UPDATE=1` and golden files committed
|
|
369
|
-
- [ ] No references to host-internal paths, WebKit handler names, or host implementation class names in any `*.md` file under `sdk/` (
|
|
370
|
+
- [ ] No references to host-internal paths, WebKit handler names, or host implementation class names in any `*.md` file under `sdk/` (checked in review)
|
|
370
371
|
- [ ] PR description cites the SPECIFICATION.md chapter number justifying shape choice
|
|
371
372
|
- [ ] `npm test` passes in `plugins/template-plugin/` (template plugin integration tests)
|
|
372
373
|
- [ ] `./scripts/checks/check-plugin-contract.sh` exits 0
|
package/dist/dom/index.cjs
CHANGED
|
@@ -30,6 +30,14 @@ module.exports = __toCommonJS(index_exports);
|
|
|
30
30
|
// src/generated/wireConstants.generated.ts
|
|
31
31
|
var STRUCTURED_ERROR_PREFIX = "__clipbus_structured_error__:";
|
|
32
32
|
var CAPABILITY_UNSUPPORTED_ERROR_NAME = "PluginCapabilityUnsupported";
|
|
33
|
+
var PLUGIN_CALL_HANDLER_NAME = "clipbusPluginCall";
|
|
34
|
+
var WIRE_ERROR_NAMES = {
|
|
35
|
+
methodNotFound: "PluginRuntimeMethodNotFound",
|
|
36
|
+
handlerNotFound: "PluginRuntimeHandlerNotFound",
|
|
37
|
+
invocationExpired: "PluginRuntimeInvocationExpired",
|
|
38
|
+
hostCallLimitExceeded: "PluginRuntimeHostCallLimitExceeded",
|
|
39
|
+
hostBridgeUnavailable: "PluginHostBridgeUnavailable"
|
|
40
|
+
};
|
|
33
41
|
|
|
34
42
|
// src/internal/capabilities.ts
|
|
35
43
|
var CapabilityUnsupportedError = class extends Error {
|
|
@@ -51,20 +59,29 @@ function mapToCapabilityError(err, unsupportedName) {
|
|
|
51
59
|
return err;
|
|
52
60
|
}
|
|
53
61
|
|
|
54
|
-
// src/internal/
|
|
62
|
+
// src/internal/pluginCall.ts
|
|
63
|
+
async function callPluginMethod(method, payload) {
|
|
64
|
+
const handler = globalThis.webkit?.messageHandlers?.[PLUGIN_CALL_HANDLER_NAME];
|
|
65
|
+
if (!handler) {
|
|
66
|
+
const err = new Error("clipbus." + method + " is only available inside a Clipbus plugin WebView");
|
|
67
|
+
err.name = WIRE_ERROR_NAMES.hostBridgeUnavailable;
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
const normalized = JSON.parse(JSON.stringify(payload));
|
|
71
|
+
try {
|
|
72
|
+
return await handler.postMessage({ method, payload: normalized });
|
|
73
|
+
} catch (err) {
|
|
74
|
+
throw parseReplyError(err);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
55
77
|
function parseReplyError(raw) {
|
|
56
78
|
const message = extractMessage(raw);
|
|
57
79
|
if (message.startsWith(STRUCTURED_ERROR_PREFIX)) {
|
|
58
|
-
const json = message.slice(STRUCTURED_ERROR_PREFIX.length);
|
|
59
80
|
try {
|
|
60
|
-
const parsed = JSON.parse(
|
|
81
|
+
const parsed = JSON.parse(message.slice(STRUCTURED_ERROR_PREFIX.length));
|
|
61
82
|
const err = new Error(typeof parsed.message === "string" ? parsed.message : "");
|
|
62
|
-
if (typeof parsed.name === "string" && parsed.name.length > 0)
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
if (parsed.data !== void 0) {
|
|
66
|
-
err.data = parsed.data;
|
|
67
|
-
}
|
|
83
|
+
if (typeof parsed.name === "string" && parsed.name.length > 0) err.name = parsed.name;
|
|
84
|
+
if (parsed.data !== void 0) err.data = parsed.data;
|
|
68
85
|
return mapToCapabilityError(err, CAPABILITY_UNSUPPORTED_ERROR_NAME);
|
|
69
86
|
} catch {
|
|
70
87
|
return new Error(message);
|
|
@@ -82,28 +99,6 @@ function extractMessage(raw) {
|
|
|
82
99
|
return String(raw);
|
|
83
100
|
}
|
|
84
101
|
|
|
85
|
-
// src/generated/capabilityClients.generated.ts
|
|
86
|
-
var HANDLER_NAME = "clipbusPluginCall";
|
|
87
|
-
async function callPluginMethod(method, payload) {
|
|
88
|
-
const handler = globalThis.webkit?.messageHandlers?.[HANDLER_NAME];
|
|
89
|
-
if (!handler) {
|
|
90
|
-
const err = new Error("clipbus." + method + " is only available inside a Clipbus plugin WebView");
|
|
91
|
-
err.name = "PluginHostBridgeUnavailable";
|
|
92
|
-
throw err;
|
|
93
|
-
}
|
|
94
|
-
const normalized = JSON.parse(JSON.stringify(payload));
|
|
95
|
-
let reply;
|
|
96
|
-
try {
|
|
97
|
-
reply = await handler.postMessage({ method, payload: normalized });
|
|
98
|
-
} catch (err) {
|
|
99
|
-
throw parseReplyError(err);
|
|
100
|
-
}
|
|
101
|
-
return reply;
|
|
102
|
-
}
|
|
103
|
-
var callWindowSetHeight = (payload) => callPluginMethod("window.setHeight", payload);
|
|
104
|
-
var callConsoleLog = (payload) => callPluginMethod("console.log", payload);
|
|
105
|
-
var callTextInputStateChanged = (payload) => callPluginMethod("textInput.stateChanged", payload);
|
|
106
|
-
|
|
107
102
|
// src/internal/internalConsole.ts
|
|
108
103
|
function pick(method) {
|
|
109
104
|
if (typeof globalThis === "undefined") return () => {
|
|
@@ -137,7 +132,7 @@ function autoFit(options) {
|
|
|
137
132
|
pending = false;
|
|
138
133
|
const raw = target.scrollHeight;
|
|
139
134
|
const clamped = Math.min(max, Math.max(min, raw));
|
|
140
|
-
|
|
135
|
+
callPluginMethod("window.setHeight", { height: clamped }).catch((err) => {
|
|
141
136
|
internalConsole.warn("[clipbus-sdk] autoFit: window.setHeight failed:", err);
|
|
142
137
|
});
|
|
143
138
|
});
|
|
@@ -163,7 +158,7 @@ function patchConsole() {
|
|
|
163
158
|
original(...args);
|
|
164
159
|
if (_inFlight > 0) return;
|
|
165
160
|
_inFlight++;
|
|
166
|
-
Promise.resolve().then(() =>
|
|
161
|
+
Promise.resolve().then(() => callPluginMethod("console.log", { level, message: args.map(String).join(" ") })).catch((err) => {
|
|
167
162
|
internalConsole.warn("[clipbus-sdk] consolePatch: forward to host failed:", err);
|
|
168
163
|
}).finally(() => {
|
|
169
164
|
_inFlight--;
|
|
@@ -182,7 +177,7 @@ function patchTextInputState() {
|
|
|
182
177
|
let isFocused = false;
|
|
183
178
|
let isComposing = false;
|
|
184
179
|
function post() {
|
|
185
|
-
|
|
180
|
+
callPluginMethod("textInput.stateChanged", { isFocused, isComposing }).catch((err) => {
|
|
186
181
|
internalConsole.warn("[clipbus-sdk] textInputState: dispatch failed:", err);
|
|
187
182
|
});
|
|
188
183
|
}
|
package/dist/dom/index.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
// src/generated/wireConstants.generated.ts
|
|
2
2
|
var STRUCTURED_ERROR_PREFIX = "__clipbus_structured_error__:";
|
|
3
3
|
var CAPABILITY_UNSUPPORTED_ERROR_NAME = "PluginCapabilityUnsupported";
|
|
4
|
+
var PLUGIN_CALL_HANDLER_NAME = "clipbusPluginCall";
|
|
5
|
+
var WIRE_ERROR_NAMES = {
|
|
6
|
+
methodNotFound: "PluginRuntimeMethodNotFound",
|
|
7
|
+
handlerNotFound: "PluginRuntimeHandlerNotFound",
|
|
8
|
+
invocationExpired: "PluginRuntimeInvocationExpired",
|
|
9
|
+
hostCallLimitExceeded: "PluginRuntimeHostCallLimitExceeded",
|
|
10
|
+
hostBridgeUnavailable: "PluginHostBridgeUnavailable"
|
|
11
|
+
};
|
|
4
12
|
|
|
5
13
|
// src/internal/capabilities.ts
|
|
6
14
|
var CapabilityUnsupportedError = class extends Error {
|
|
@@ -22,20 +30,29 @@ function mapToCapabilityError(err, unsupportedName) {
|
|
|
22
30
|
return err;
|
|
23
31
|
}
|
|
24
32
|
|
|
25
|
-
// src/internal/
|
|
33
|
+
// src/internal/pluginCall.ts
|
|
34
|
+
async function callPluginMethod(method, payload) {
|
|
35
|
+
const handler = globalThis.webkit?.messageHandlers?.[PLUGIN_CALL_HANDLER_NAME];
|
|
36
|
+
if (!handler) {
|
|
37
|
+
const err = new Error("clipbus." + method + " is only available inside a Clipbus plugin WebView");
|
|
38
|
+
err.name = WIRE_ERROR_NAMES.hostBridgeUnavailable;
|
|
39
|
+
throw err;
|
|
40
|
+
}
|
|
41
|
+
const normalized = JSON.parse(JSON.stringify(payload));
|
|
42
|
+
try {
|
|
43
|
+
return await handler.postMessage({ method, payload: normalized });
|
|
44
|
+
} catch (err) {
|
|
45
|
+
throw parseReplyError(err);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
26
48
|
function parseReplyError(raw) {
|
|
27
49
|
const message = extractMessage(raw);
|
|
28
50
|
if (message.startsWith(STRUCTURED_ERROR_PREFIX)) {
|
|
29
|
-
const json = message.slice(STRUCTURED_ERROR_PREFIX.length);
|
|
30
51
|
try {
|
|
31
|
-
const parsed = JSON.parse(
|
|
52
|
+
const parsed = JSON.parse(message.slice(STRUCTURED_ERROR_PREFIX.length));
|
|
32
53
|
const err = new Error(typeof parsed.message === "string" ? parsed.message : "");
|
|
33
|
-
if (typeof parsed.name === "string" && parsed.name.length > 0)
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
if (parsed.data !== void 0) {
|
|
37
|
-
err.data = parsed.data;
|
|
38
|
-
}
|
|
54
|
+
if (typeof parsed.name === "string" && parsed.name.length > 0) err.name = parsed.name;
|
|
55
|
+
if (parsed.data !== void 0) err.data = parsed.data;
|
|
39
56
|
return mapToCapabilityError(err, CAPABILITY_UNSUPPORTED_ERROR_NAME);
|
|
40
57
|
} catch {
|
|
41
58
|
return new Error(message);
|
|
@@ -53,28 +70,6 @@ function extractMessage(raw) {
|
|
|
53
70
|
return String(raw);
|
|
54
71
|
}
|
|
55
72
|
|
|
56
|
-
// src/generated/capabilityClients.generated.ts
|
|
57
|
-
var HANDLER_NAME = "clipbusPluginCall";
|
|
58
|
-
async function callPluginMethod(method, payload) {
|
|
59
|
-
const handler = globalThis.webkit?.messageHandlers?.[HANDLER_NAME];
|
|
60
|
-
if (!handler) {
|
|
61
|
-
const err = new Error("clipbus." + method + " is only available inside a Clipbus plugin WebView");
|
|
62
|
-
err.name = "PluginHostBridgeUnavailable";
|
|
63
|
-
throw err;
|
|
64
|
-
}
|
|
65
|
-
const normalized = JSON.parse(JSON.stringify(payload));
|
|
66
|
-
let reply;
|
|
67
|
-
try {
|
|
68
|
-
reply = await handler.postMessage({ method, payload: normalized });
|
|
69
|
-
} catch (err) {
|
|
70
|
-
throw parseReplyError(err);
|
|
71
|
-
}
|
|
72
|
-
return reply;
|
|
73
|
-
}
|
|
74
|
-
var callWindowSetHeight = (payload) => callPluginMethod("window.setHeight", payload);
|
|
75
|
-
var callConsoleLog = (payload) => callPluginMethod("console.log", payload);
|
|
76
|
-
var callTextInputStateChanged = (payload) => callPluginMethod("textInput.stateChanged", payload);
|
|
77
|
-
|
|
78
73
|
// src/internal/internalConsole.ts
|
|
79
74
|
function pick(method) {
|
|
80
75
|
if (typeof globalThis === "undefined") return () => {
|
|
@@ -108,7 +103,7 @@ function autoFit(options) {
|
|
|
108
103
|
pending = false;
|
|
109
104
|
const raw = target.scrollHeight;
|
|
110
105
|
const clamped = Math.min(max, Math.max(min, raw));
|
|
111
|
-
|
|
106
|
+
callPluginMethod("window.setHeight", { height: clamped }).catch((err) => {
|
|
112
107
|
internalConsole.warn("[clipbus-sdk] autoFit: window.setHeight failed:", err);
|
|
113
108
|
});
|
|
114
109
|
});
|
|
@@ -134,7 +129,7 @@ function patchConsole() {
|
|
|
134
129
|
original(...args);
|
|
135
130
|
if (_inFlight > 0) return;
|
|
136
131
|
_inFlight++;
|
|
137
|
-
Promise.resolve().then(() =>
|
|
132
|
+
Promise.resolve().then(() => callPluginMethod("console.log", { level, message: args.map(String).join(" ") })).catch((err) => {
|
|
138
133
|
internalConsole.warn("[clipbus-sdk] consolePatch: forward to host failed:", err);
|
|
139
134
|
}).finally(() => {
|
|
140
135
|
_inFlight--;
|
|
@@ -153,7 +148,7 @@ function patchTextInputState() {
|
|
|
153
148
|
let isFocused = false;
|
|
154
149
|
let isComposing = false;
|
|
155
150
|
function post() {
|
|
156
|
-
|
|
151
|
+
callPluginMethod("textInput.stateChanged", { isFocused, isComposing }).catch((err) => {
|
|
157
152
|
internalConsole.warn("[clipbus-sdk] textInputState: dispatch failed:", err);
|
|
158
153
|
});
|
|
159
154
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Framework-agnostic helper for binding a SDK topic to any reactive state
|
|
3
3
|
* system (Vue, React, Svelte, plain callbacks, …).
|
|
4
4
|
*
|
|
5
|
-
* `Topic<T>` is the interface from
|
|
5
|
+
* `Topic<T>` is the interface from src/internal/topic.ts.
|
|
6
6
|
* We intentionally replicate the minimal shape here (structural typing) so this
|
|
7
7
|
* file has zero runtime imports — it works equally well in Node test runners and
|
|
8
8
|
* browser bundles.
|