@motrix/mdxp 0.2.0 → 0.4.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/README.md +28 -23
- package/README.zh-CN.md +26 -23
- package/dist/browser.d.ts +4 -0
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +3 -0
- package/dist/browser.js.map +1 -1
- package/dist/node.d.ts +4 -0
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +3 -0
- package/dist/node.js.map +1 -1
- package/dist/schemas/download-add.d.ts +1 -0
- package/dist/schemas/download-add.d.ts.map +1 -1
- package/dist/schemas/task.d.ts +3 -0
- package/dist/schemas/task.d.ts.map +1 -1
- package/dist/schemas/task.js +4 -0
- package/dist/schemas/task.js.map +1 -1
- package/dist/transports/stdio.d.ts +19 -0
- package/dist/transports/stdio.d.ts.map +1 -0
- package/dist/transports/stdio.js +17 -0
- package/dist/transports/stdio.js.map +1 -0
- package/dist/transports/worker.d.ts +27 -0
- package/dist/transports/worker.d.ts.map +1 -0
- package/dist/transports/worker.js +22 -0
- package/dist/transports/worker.js.map +1 -0
- package/dist/transports/ws.d.ts +35 -0
- package/dist/transports/ws.d.ts.map +1 -0
- package/dist/transports/ws.js +144 -0
- package/dist/transports/ws.js.map +1 -0
- package/package.json +1 -1
- package/src/browser.ts +5 -0
- package/src/node.ts +5 -0
- package/src/schemas/task.ts +4 -0
- package/src/transports/stdio.ts +27 -0
- package/src/transports/worker.ts +49 -0
- package/src/transports/ws.ts +188 -0
package/README.md
CHANGED
|
@@ -35,6 +35,9 @@ top of it.
|
|
|
35
35
|
- **Platform RAL entry points.** `./node` and `./browser` install the matching
|
|
36
36
|
`vscode-jsonrpc` runtime abstraction layer and re-export its transport classes,
|
|
37
37
|
so you import everything — connection helper and reader/writer — from one place.
|
|
38
|
+
- **One-call constructors.** `fromWebSocket`, `fromStdio`, and `fromWorker` build
|
|
39
|
+
a connection over a common transport in a single call; `createMdxpConnection`
|
|
40
|
+
stays the generic escape hatch.
|
|
38
41
|
- **Agent-ready.** A built-in tool registry emits a JSON-Schema tool catalog you
|
|
39
42
|
can feed straight into an LLM function-calling API.
|
|
40
43
|
- **Forward-compatible.** Unknown methods and fields are ignored, not rejected.
|
|
@@ -75,16 +78,10 @@ including its reader/writer, from a single place.
|
|
|
75
78
|
### Node host (over stdio)
|
|
76
79
|
|
|
77
80
|
```ts
|
|
78
|
-
import {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
} from '@motrix/mdxp/node'
|
|
83
|
-
|
|
84
|
-
const conn = createMdxpConnection(
|
|
85
|
-
new StreamMessageReader(process.stdin),
|
|
86
|
-
new StreamMessageWriter(process.stdout),
|
|
87
|
-
)
|
|
81
|
+
import { fromStdio } from '@motrix/mdxp/node'
|
|
82
|
+
|
|
83
|
+
// Over process.stdin / process.stdout (the native-messaging / CLI case).
|
|
84
|
+
const conn = fromStdio()
|
|
88
85
|
|
|
89
86
|
// Register handlers BEFORE listen().
|
|
90
87
|
conn.onNotification('$/task/progress', (p) => {
|
|
@@ -95,24 +92,31 @@ conn.onNotification('$/task/progress', (p) => {
|
|
|
95
92
|
conn.listen()
|
|
96
93
|
```
|
|
97
94
|
|
|
98
|
-
### Browser host
|
|
95
|
+
### Browser host (over WebSocket)
|
|
99
96
|
|
|
100
97
|
```ts
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
BrowserMessageWriter,
|
|
106
|
-
} from '@motrix/mdxp/browser'
|
|
107
|
-
|
|
108
|
-
// e.g. a MessagePort / Worker; adapt your WebSocket to reader/writer as needed.
|
|
109
|
-
const conn = createMdxpConnection(
|
|
110
|
-
new BrowserMessageReader(worker),
|
|
111
|
-
new BrowserMessageWriter(worker),
|
|
112
|
-
)
|
|
98
|
+
import { fromWebSocket } from '@motrix/mdxp/browser'
|
|
99
|
+
|
|
100
|
+
const conn = fromWebSocket(new WebSocket('ws://127.0.0.1:16650/v1'))
|
|
101
|
+
conn.onNotification('$/task/progress', (p) => {})
|
|
113
102
|
conn.listen()
|
|
114
103
|
```
|
|
115
104
|
|
|
105
|
+
### Convenience constructors
|
|
106
|
+
|
|
107
|
+
`createMdxpConnection(reader, writer)` is the generic entry point — bring any
|
|
108
|
+
`vscode-jsonrpc` reader/writer. For the common transports, skip the boilerplate:
|
|
109
|
+
|
|
110
|
+
| Constructor | Entry | Transport |
|
|
111
|
+
| --- | --- | --- |
|
|
112
|
+
| `fromWebSocket(ws)` | `./node` · `./browser` | A browser `WebSocket` or a Node `ws` socket |
|
|
113
|
+
| `fromStdio(opts?)` | `./node` | `process.stdin` / `process.stdout`, or given streams |
|
|
114
|
+
| `fromWorker(port)` | `./browser` | A `Worker` or `MessagePort` |
|
|
115
|
+
|
|
116
|
+
Each returns a ready `MdxpConnection` — you still register handlers and call
|
|
117
|
+
`listen()`. For any other transport, build the reader/writer and call
|
|
118
|
+
`createMdxpConnection` directly.
|
|
119
|
+
|
|
116
120
|
## Core concepts
|
|
117
121
|
|
|
118
122
|
**Server vs. client.** The Motrix desktop app is the **server** — it owns the
|
|
@@ -321,6 +325,7 @@ const tools = toAgentToolCatalog()
|
|
|
321
325
|
| Export | Kind | Purpose |
|
|
322
326
|
| --- | --- | --- |
|
|
323
327
|
| `createMdxpConnection(reader, writer)` | function | Wrap a reader/writer pair in a typed `MdxpConnection`. |
|
|
328
|
+
| `fromWebSocket` · `fromStdio` · `fromWorker` | function | One-call constructors over a WebSocket / stdio / Worker (from `./node` · `./browser`). |
|
|
324
329
|
| `MdxpConnection` | type | The connection interface (`sendRequest`, `onRequest`, `sendNotification`, `onNotification`, `dispose`, `raw`). |
|
|
325
330
|
| `MdxpRequestMap` / `MdxpNotificationMap` | type | Method/notification name → params/result type maps. |
|
|
326
331
|
| `Methods` / `Notifications` | const | Wire-name constants (`Methods.DownloadAdd === 'download/add'`). |
|
package/README.zh-CN.md
CHANGED
|
@@ -30,6 +30,8 @@
|
|
|
30
30
|
- **平台 RAL 入口**:`./node` 与 `./browser` 会替你装好对应的 `vscode-jsonrpc`
|
|
31
31
|
runtime abstraction layer,并 re-export 它的 transport class —— 连接封装与
|
|
32
32
|
reader/writer 都从同一处 import。
|
|
33
|
+
- **一步构造**:`fromWebSocket`、`fromStdio`、`fromWorker` 一行即可在常见 transport
|
|
34
|
+
上建好连接;`createMdxpConnection` 仍是通用的底层入口。
|
|
33
35
|
- **面向 agent**:内置的 tool registry 可产出一份 JSON-Schema tool catalog,
|
|
34
36
|
能直接对接 LLM 的 function-calling API。
|
|
35
37
|
- **forward-compatible**:遇到未知的 method 或字段选择忽略,而非 reject。
|
|
@@ -67,16 +69,10 @@ transport class**(Node 的 `StreamMessageReader`/`Writer`、浏览器的
|
|
|
67
69
|
### Node host(走 stdio)
|
|
68
70
|
|
|
69
71
|
```ts
|
|
70
|
-
import {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
} from '@motrix/mdxp/node'
|
|
75
|
-
|
|
76
|
-
const conn = createMdxpConnection(
|
|
77
|
-
new StreamMessageReader(process.stdin),
|
|
78
|
-
new StreamMessageWriter(process.stdout),
|
|
79
|
-
)
|
|
72
|
+
import { fromStdio } from '@motrix/mdxp/node'
|
|
73
|
+
|
|
74
|
+
// 走 process.stdin / process.stdout(native-messaging / CLI 场景)。
|
|
75
|
+
const conn = fromStdio()
|
|
80
76
|
|
|
81
77
|
// 务必在 listen() 之前注册 handler。
|
|
82
78
|
conn.onNotification('$/task/progress', (p) => {
|
|
@@ -87,24 +83,30 @@ conn.onNotification('$/task/progress', (p) => {
|
|
|
87
83
|
conn.listen()
|
|
88
84
|
```
|
|
89
85
|
|
|
90
|
-
### 浏览器 host
|
|
86
|
+
### 浏览器 host(走 WebSocket)
|
|
91
87
|
|
|
92
88
|
```ts
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
BrowserMessageWriter,
|
|
98
|
-
} from '@motrix/mdxp/browser'
|
|
99
|
-
|
|
100
|
-
// 例如一个 MessagePort / Worker;若用 WebSocket,需自行适配成 reader/writer。
|
|
101
|
-
const conn = createMdxpConnection(
|
|
102
|
-
new BrowserMessageReader(worker),
|
|
103
|
-
new BrowserMessageWriter(worker),
|
|
104
|
-
)
|
|
89
|
+
import { fromWebSocket } from '@motrix/mdxp/browser'
|
|
90
|
+
|
|
91
|
+
const conn = fromWebSocket(new WebSocket('ws://127.0.0.1:16650/v1'))
|
|
92
|
+
conn.onNotification('$/task/progress', (p) => {})
|
|
105
93
|
conn.listen()
|
|
106
94
|
```
|
|
107
95
|
|
|
96
|
+
### 便捷构造器
|
|
97
|
+
|
|
98
|
+
`createMdxpConnection(reader, writer)` 是通用入口 —— 传入任意 `vscode-jsonrpc` 的
|
|
99
|
+
reader/writer。常见 transport 则可直接省去样板:
|
|
100
|
+
|
|
101
|
+
| 构造器 | 入口 | Transport |
|
|
102
|
+
| --- | --- | --- |
|
|
103
|
+
| `fromWebSocket(ws)` | `./node` · `./browser` | 浏览器 `WebSocket` 或 Node 的 `ws` socket |
|
|
104
|
+
| `fromStdio(opts?)` | `./node` | `process.stdin` / `process.stdout`,或指定的流 |
|
|
105
|
+
| `fromWorker(port)` | `./browser` | 一个 `Worker` 或 `MessagePort` |
|
|
106
|
+
|
|
107
|
+
每个都返回开箱即用的 `MdxpConnection` —— 你仍需注册 handler 并调用 `listen()`。
|
|
108
|
+
其它 transport 则自行构造 reader/writer,再直接调用 `createMdxpConnection`。
|
|
109
|
+
|
|
108
110
|
## 核心概念
|
|
109
111
|
|
|
110
112
|
**server 与 client**:Motrix 桌面端是 **server** —— 下载引擎由它持有。**client**
|
|
@@ -305,6 +307,7 @@ const tools = toAgentToolCatalog()
|
|
|
305
307
|
| 导出 | 类型 | 作用 |
|
|
306
308
|
| --- | --- | --- |
|
|
307
309
|
| `createMdxpConnection(reader, writer)` | function | 把一对 reader/writer 封装成类型化的 `MdxpConnection`。 |
|
|
310
|
+
| `fromWebSocket` · `fromStdio` · `fromWorker` | function | 在 WebSocket / stdio / Worker 上的一步构造器(来自 `./node` · `./browser`)。 |
|
|
308
311
|
| `MdxpConnection` | type | 连接接口(`sendRequest`、`onRequest`、`sendNotification`、`onNotification`、`dispose`、`raw`)。 |
|
|
309
312
|
| `MdxpRequestMap` / `MdxpNotificationMap` | type | method / notification 名 → params/result 类型的映射表。 |
|
|
310
313
|
| `Methods` / `Notifications` | const | wire 名常量(`Methods.DownloadAdd === 'download/add'`)。 |
|
package/dist/browser.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import 'vscode-jsonrpc/browser';
|
|
2
2
|
export { BrowserMessageReader, BrowserMessageWriter, } from 'vscode-jsonrpc/browser';
|
|
3
3
|
export * from './index.js';
|
|
4
|
+
export type { WorkerLike } from './transports/worker.js';
|
|
5
|
+
export { fromWorker } from './transports/worker.js';
|
|
6
|
+
export type { WebSocketLike } from './transports/ws.js';
|
|
7
|
+
export { fromWebSocket } from './transports/ws.js';
|
|
4
8
|
//# sourceMappingURL=browser.d.ts.map
|
package/dist/browser.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAWA,OAAO,wBAAwB,CAAA;AAM/B,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,wBAAwB,CAAA;AAC/B,cAAc,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAWA,OAAO,wBAAwB,CAAA;AAM/B,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,wBAAwB,CAAA;AAC/B,cAAc,YAAY,CAAA;AAC1B,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnD,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAEvD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA"}
|
package/dist/browser.js
CHANGED
|
@@ -16,4 +16,7 @@ import 'vscode-jsonrpc/browser';
|
|
|
16
16
|
// installed the RAL into.
|
|
17
17
|
export { BrowserMessageReader, BrowserMessageWriter, } from 'vscode-jsonrpc/browser';
|
|
18
18
|
export * from './index.js';
|
|
19
|
+
export { fromWorker } from './transports/worker.js';
|
|
20
|
+
// High-level convenience constructors for browser transports.
|
|
21
|
+
export { fromWebSocket } from './transports/ws.js';
|
|
19
22
|
//# sourceMappingURL=browser.js.map
|
package/dist/browser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,EAAE;AACF,8EAA8E;AAC9E,0EAA0E;AAC1E,gFAAgF;AAChF,8EAA8E;AAC9E,mCAAmC;AACnC,EAAE;AACF,uEAAuE;AACvE,iFAAiF;AACjF,4EAA4E;AAC5E,OAAO,wBAAwB,CAAA;AAE/B,uEAAuE;AACvE,4EAA4E;AAC5E,0EAA0E;AAC1E,0BAA0B;AAC1B,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,wBAAwB,CAAA;AAC/B,cAAc,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,EAAE;AACF,8EAA8E;AAC9E,0EAA0E;AAC1E,gFAAgF;AAChF,8EAA8E;AAC9E,mCAAmC;AACnC,EAAE;AACF,uEAAuE;AACvE,iFAAiF;AACjF,4EAA4E;AAC5E,OAAO,wBAAwB,CAAA;AAE/B,uEAAuE;AACvE,4EAA4E;AAC5E,0EAA0E;AAC1E,0BAA0B;AAC1B,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,wBAAwB,CAAA;AAC/B,cAAc,YAAY,CAAA;AAE1B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAEnD,8DAA8D;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA"}
|
package/dist/node.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import 'vscode-jsonrpc/node';
|
|
2
2
|
export { IPCMessageReader, IPCMessageWriter, PortMessageReader, PortMessageWriter, SocketMessageReader, SocketMessageWriter, StreamMessageReader, StreamMessageWriter, } from 'vscode-jsonrpc/node';
|
|
3
3
|
export * from './index.js';
|
|
4
|
+
export type { StdioOptions } from './transports/stdio.js';
|
|
5
|
+
export { fromStdio } from './transports/stdio.js';
|
|
6
|
+
export type { WebSocketLike } from './transports/ws.js';
|
|
7
|
+
export { fromWebSocket } from './transports/ws.js';
|
|
4
8
|
//# sourceMappingURL=node.d.ts.map
|
package/dist/node.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAYA,OAAO,qBAAqB,CAAA;AAK5B,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,qBAAqB,CAAA;AAC5B,cAAc,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAYA,OAAO,qBAAqB,CAAA;AAK5B,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,qBAAqB,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,YAAY,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAEzD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACjD,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA"}
|
package/dist/node.js
CHANGED
|
@@ -16,4 +16,7 @@ import 'vscode-jsonrpc/node';
|
|
|
16
16
|
// import, and guaranteed to be the instance this package installed the RAL into.
|
|
17
17
|
export { IPCMessageReader, IPCMessageWriter, PortMessageReader, PortMessageWriter, SocketMessageReader, SocketMessageWriter, StreamMessageReader, StreamMessageWriter, } from 'vscode-jsonrpc/node';
|
|
18
18
|
export * from './index.js';
|
|
19
|
+
// High-level convenience constructors for Node transports.
|
|
20
|
+
export { fromStdio } from './transports/stdio.js';
|
|
21
|
+
export { fromWebSocket } from './transports/ws.js';
|
|
19
22
|
//# sourceMappingURL=node.js.map
|
package/dist/node.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,EAAE;AACF,8EAA8E;AAC9E,0EAA0E;AAC1E,gFAAgF;AAChF,2EAA2E;AAC3E,gFAAgF;AAChF,4BAA4B;AAC5B,EAAE;AACF,mFAAmF;AACnF,4EAA4E;AAC5E,yEAAyE;AACzE,OAAO,qBAAqB,CAAA;AAE5B,+EAA+E;AAC/E,+EAA+E;AAC/E,iFAAiF;AACjF,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,qBAAqB,CAAA;AAC5B,cAAc,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,EAAE;AACF,8EAA8E;AAC9E,0EAA0E;AAC1E,gFAAgF;AAChF,2EAA2E;AAC3E,gFAAgF;AAChF,4BAA4B;AAC5B,EAAE;AACF,mFAAmF;AACnF,4EAA4E;AAC5E,yEAAyE;AACzE,OAAO,qBAAqB,CAAA;AAE5B,+EAA+E;AAC/E,+EAA+E;AAC/E,iFAAiF;AACjF,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,qBAAqB,CAAA;AAC5B,cAAc,YAAY,CAAA;AAE1B,2DAA2D;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA"}
|
|
@@ -66,6 +66,7 @@ export declare const DownloadAddResultSchema: z.ZodObject<{
|
|
|
66
66
|
ratio: z.ZodNumber;
|
|
67
67
|
trackers: z.ZodArray<z.ZodString>;
|
|
68
68
|
}, z.core.$strip>>;
|
|
69
|
+
errorCode: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
69
70
|
}, z.core.$strip>;
|
|
70
71
|
export type DownloadAddParams = z.infer<typeof DownloadAddParamsSchema>;
|
|
71
72
|
export type DownloadAddResult = z.infer<typeof DownloadAddResultSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"download-add.d.ts","sourceRoot":"","sources":["../../src/schemas/download-add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAmBvB;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;4BAuBlC,CAAA;AAEF,6EAA6E;AAC7E,eAAO,MAAM,uBAAuB
|
|
1
|
+
{"version":3,"file":"download-add.d.ts","sourceRoot":"","sources":["../../src/schemas/download-add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAmBvB;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;4BAuBlC,CAAA;AAEF,6EAA6E;AAC7E,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAiB,CAAA;AAErD,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AACvE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA"}
|
package/dist/schemas/task.d.ts
CHANGED
|
@@ -72,6 +72,7 @@ export declare const MdxpTaskSchema: z.ZodObject<{
|
|
|
72
72
|
ratio: z.ZodNumber;
|
|
73
73
|
trackers: z.ZodArray<z.ZodString>;
|
|
74
74
|
}, z.core.$strip>>;
|
|
75
|
+
errorCode: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
75
76
|
}, z.core.$strip>;
|
|
76
77
|
/** Shared result for write methods that only need to ack. */
|
|
77
78
|
export declare const OkResultSchema: z.ZodObject<{
|
|
@@ -129,6 +130,7 @@ export declare const TaskListResultSchema: z.ZodObject<{
|
|
|
129
130
|
ratio: z.ZodNumber;
|
|
130
131
|
trackers: z.ZodArray<z.ZodString>;
|
|
131
132
|
}, z.core.$strip>>;
|
|
133
|
+
errorCode: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
132
134
|
}, z.core.$strip>>;
|
|
133
135
|
total: z.ZodNumber;
|
|
134
136
|
}, z.core.$strip>;
|
|
@@ -173,6 +175,7 @@ export declare const TaskGetResultSchema: z.ZodObject<{
|
|
|
173
175
|
ratio: z.ZodNumber;
|
|
174
176
|
trackers: z.ZodArray<z.ZodString>;
|
|
175
177
|
}, z.core.$strip>>;
|
|
178
|
+
errorCode: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
176
179
|
}, z.core.$strip>>;
|
|
177
180
|
}, z.core.$strip>;
|
|
178
181
|
export declare const TaskPauseParamsSchema: z.ZodObject<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/schemas/task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;EAS/B,CAAA;AAEF,eAAO,MAAM,kBAAkB;;;;;;EAM7B,CAAA;AAEF,4EAA4E;AAC5E,eAAO,MAAM,YAAY;;;;;iBAKvB,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc
|
|
1
|
+
{"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/schemas/task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;EAS/B,CAAA;AAEF,eAAO,MAAM,kBAAkB;;;;;;EAM7B,CAAA;AAEF,4EAA4E;AAC5E,eAAO,MAAM,YAAY;;;;;iBAKvB,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwBzB,CAAA;AAEF,6DAA6D;AAC7D,eAAO,MAAM,cAAc;;iBAAoC,CAAA;AAG/D,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;kBAI/B,CAAA;AACF,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAG/B,CAAA;AAGF,eAAO,MAAM,mBAAmB;;kBAE9B,CAAA;AACF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAE9B,CAAA;AAGF,eAAO,MAAM,qBAAqB;;kBAEhC,CAAA;AACF,eAAO,MAAM,sBAAsB;;kBAEjC,CAAA;AAGF,eAAO,MAAM,sBAAsB;;;kBAGjC,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACjE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAC7D,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA;AACrD,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA;AACrD,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACjE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACjE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AACnE,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAA;AACtC,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AACrE,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAA;AACvC,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AACrE,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAA"}
|
package/dist/schemas/task.js
CHANGED
|
@@ -55,6 +55,10 @@ export const MdxpTaskSchema = z.object({
|
|
|
55
55
|
finalPath: z.string().nullable(),
|
|
56
56
|
infoHash: z.string().nullable().optional(),
|
|
57
57
|
bt: MdxpBtSchema.optional(),
|
|
58
|
+
/** Open set of `DL_*` values (host's `DownloadErrorCode`); the host may add
|
|
59
|
+
* new codes over time, so consumers MUST tolerate an unrecognized string
|
|
60
|
+
* here rather than reject it — adding a value is not a breaking change. */
|
|
61
|
+
errorCode: z.string().nullish(),
|
|
58
62
|
});
|
|
59
63
|
/** Shared result for write methods that only need to ack. */
|
|
60
64
|
export const OkResultSchema = z.object({ ok: z.literal(true) });
|
package/dist/schemas/task.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task.js","sourceRoot":"","sources":["../../src/schemas/task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,IAAI,CAAC;IACzC,QAAQ;IACR,mBAAmB;IACnB,aAAa;IACb,QAAQ;IACR,SAAS;IACT,YAAY;IACZ,WAAW;IACX,OAAO;CACR,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,CAAC;IACvC,MAAM;IACN,KAAK;IACL,IAAI;IACJ,QAAQ;IACR,UAAU;CACX,CAAC,CAAA;AAEF,4EAA4E;AAC5E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;CAC9B,CAAC,CAAA;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,kBAAkB;IACxB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,MAAM,EAAE,oBAAoB;IAC5B;;uEAEmE;IACnE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC1C,EAAE,EAAE,YAAY,CAAC,QAAQ,EAAE;
|
|
1
|
+
{"version":3,"file":"task.js","sourceRoot":"","sources":["../../src/schemas/task.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { MdxpConnection } from '../connection.js';
|
|
2
|
+
/** Streams for {@link fromStdio}; defaults to the process's stdio. */
|
|
3
|
+
export interface StdioOptions {
|
|
4
|
+
input?: NodeJS.ReadableStream;
|
|
5
|
+
output?: NodeJS.WritableStream;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Create an {@link MdxpConnection} over Node streams — `process.stdin` /
|
|
9
|
+
* `process.stdout` by default. This is the native-messaging-host / CLI case:
|
|
10
|
+
* the parent process pipes JSON-RPC over the child's stdio.
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* const conn = fromStdio()
|
|
14
|
+
* conn.onRequest('url/resolve', async (params) => {})
|
|
15
|
+
* conn.listen()
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function fromStdio(options?: StdioOptions): MdxpConnection;
|
|
19
|
+
//# sourceMappingURL=stdio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/transports/stdio.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAGtD,sEAAsE;AACtE,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC,cAAc,CAAA;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAA;CAC/B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,YAAiB,GAAG,cAAc,CAKpE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { StreamMessageReader, StreamMessageWriter } from 'vscode-jsonrpc/node';
|
|
2
|
+
import { createMdxpConnection } from '../connection.js';
|
|
3
|
+
/**
|
|
4
|
+
* Create an {@link MdxpConnection} over Node streams — `process.stdin` /
|
|
5
|
+
* `process.stdout` by default. This is the native-messaging-host / CLI case:
|
|
6
|
+
* the parent process pipes JSON-RPC over the child's stdio.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* const conn = fromStdio()
|
|
10
|
+
* conn.onRequest('url/resolve', async (params) => {})
|
|
11
|
+
* conn.listen()
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export function fromStdio(options = {}) {
|
|
15
|
+
return createMdxpConnection(new StreamMessageReader(options.input ?? process.stdin), new StreamMessageWriter(options.output ?? process.stdout));
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=stdio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/transports/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAE9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAQvD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,SAAS,CAAC,UAAwB,EAAE;IAClD,OAAO,oBAAoB,CACzB,IAAI,mBAAmB,CAAC,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,EACvD,IAAI,mBAAmB,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAC1D,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { MdxpConnection } from '../connection.js';
|
|
2
|
+
/**
|
|
3
|
+
* Minimal structural subset of a `MessagePort` / `Worker` /
|
|
4
|
+
* `DedicatedWorkerGlobalScope` — anything the browser RAL's reader/writer
|
|
5
|
+
* accept. Consumers pass their worker or port as-is.
|
|
6
|
+
*/
|
|
7
|
+
export interface WorkerLike {
|
|
8
|
+
postMessage(message: unknown): void;
|
|
9
|
+
addEventListener(type: 'message', listener: (event: {
|
|
10
|
+
readonly data: unknown;
|
|
11
|
+
}) => void): void;
|
|
12
|
+
removeEventListener(type: 'message', listener: (event: {
|
|
13
|
+
readonly data: unknown;
|
|
14
|
+
}) => void): void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Create an {@link MdxpConnection} over a Worker or `MessagePort` (the browser
|
|
18
|
+
* `postMessage` transport).
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* const conn = fromWorker(self) // inside a Web Worker
|
|
22
|
+
* conn.onNotification('$/task/progress', (p) => {})
|
|
23
|
+
* conn.listen()
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function fromWorker(port: WorkerLike): MdxpConnection;
|
|
27
|
+
//# sourceMappingURL=worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/transports/worker.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAGtD;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IACnC,gBAAgB,CACd,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,GACpD,IAAI,CAAA;IACP,mBAAmB,CACjB,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,GACpD,IAAI,CAAA;CACR;AAaD;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,cAAc,CAE3D"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { BrowserMessageReader, BrowserMessageWriter, } from 'vscode-jsonrpc/browser';
|
|
2
|
+
import { createMdxpConnection } from '../connection.js';
|
|
3
|
+
// vscode-jsonrpc types the port as `MessagePort | Worker | DedicatedWorkerGlobalScope`,
|
|
4
|
+
// which are DOM / WebWorker globals. This package targets `lib: ES2022` (no DOM),
|
|
5
|
+
// so re-type the constructors against the structural `WorkerLike` instead of
|
|
6
|
+
// pulling the DOM libs into every consumer.
|
|
7
|
+
const Reader = BrowserMessageReader;
|
|
8
|
+
const Writer = BrowserMessageWriter;
|
|
9
|
+
/**
|
|
10
|
+
* Create an {@link MdxpConnection} over a Worker or `MessagePort` (the browser
|
|
11
|
+
* `postMessage` transport).
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* const conn = fromWorker(self) // inside a Web Worker
|
|
15
|
+
* conn.onNotification('$/task/progress', (p) => {})
|
|
16
|
+
* conn.listen()
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export function fromWorker(port) {
|
|
20
|
+
return createMdxpConnection(new Reader(port), new Writer(port));
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/transports/worker.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAmBvD,wFAAwF;AACxF,kFAAkF;AAClF,6EAA6E;AAC7E,4CAA4C;AAC5C,MAAM,MAAM,GAAG,oBAEG,CAAA;AAClB,MAAM,MAAM,GAAG,oBAEG,CAAA;AAElB;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CAAC,IAAgB;IACzC,OAAO,oBAAoB,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;AACjE,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { MdxpConnection } from '../connection.js';
|
|
2
|
+
/**
|
|
3
|
+
* Minimal structural subset of a WebSocket shared by the browser `WebSocket`
|
|
4
|
+
* and the Node [`ws`](https://www.npmjs.com/package/ws) package. Consumers pass
|
|
5
|
+
* their socket as-is — no wrapping required.
|
|
6
|
+
*/
|
|
7
|
+
export interface WebSocketLike {
|
|
8
|
+
readonly readyState: number;
|
|
9
|
+
send(data: string): void;
|
|
10
|
+
close(code?: number, reason?: string): void;
|
|
11
|
+
addEventListener(type: 'message' | 'close' | 'error', listener: (event: {
|
|
12
|
+
readonly data?: unknown;
|
|
13
|
+
}) => void): void;
|
|
14
|
+
removeEventListener(type: 'message' | 'close' | 'error', listener: (event: {
|
|
15
|
+
readonly data?: unknown;
|
|
16
|
+
}) => void): void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Create an {@link MdxpConnection} over a WebSocket.
|
|
20
|
+
*
|
|
21
|
+
* Each WebSocket message carries exactly one complete JSON-RPC 2.0 message —
|
|
22
|
+
* the WebSocket protocol already frames messages, so there is no Content-Length
|
|
23
|
+
* framing. Works with the browser `WebSocket` and the Node `ws` package alike
|
|
24
|
+
* (both satisfy {@link WebSocketLike}).
|
|
25
|
+
*
|
|
26
|
+
* Register handlers first, then call `listen()`:
|
|
27
|
+
*
|
|
28
|
+
* ```ts
|
|
29
|
+
* const conn = fromWebSocket(ws)
|
|
30
|
+
* conn.onNotification('$/task/progress', (p) => {})
|
|
31
|
+
* conn.listen()
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function fromWebSocket(ws: WebSocketLike): MdxpConnection;
|
|
35
|
+
//# sourceMappingURL=ws.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws.d.ts","sourceRoot":"","sources":["../../src/transports/ws.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAMtD;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3C,gBAAgB,CACd,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,EACnC,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,GACrD,IAAI,CAAA;IACP,mBAAmB,CACjB,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,EACnC,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,GACrD,IAAI,CAAA;CACR;AAsID;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,aAAa,GAAG,cAAc,CAK/D"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { Emitter } from 'vscode-jsonrpc';
|
|
2
|
+
import { createMdxpConnection } from '../connection.js';
|
|
3
|
+
/** `WebSocket.readyState` value for an open socket (browser and `ws` agree). */
|
|
4
|
+
const OPEN = 1;
|
|
5
|
+
function toText(data) {
|
|
6
|
+
if (typeof data === 'string')
|
|
7
|
+
return data;
|
|
8
|
+
if (data instanceof ArrayBuffer)
|
|
9
|
+
return new TextDecoder().decode(data);
|
|
10
|
+
// A typed array / DataView / Node Buffer. TS 6's generic `ArrayBufferView`
|
|
11
|
+
// typing is stricter than `TextDecoder.decode`'s runtime contract (which
|
|
12
|
+
// accepts any view), so widen to satisfy the compiler.
|
|
13
|
+
if (ArrayBuffer.isView(data)) {
|
|
14
|
+
return new TextDecoder().decode(data);
|
|
15
|
+
}
|
|
16
|
+
throw new Error('unsupported WebSocket message data type');
|
|
17
|
+
}
|
|
18
|
+
class WebSocketMessageReader {
|
|
19
|
+
ws;
|
|
20
|
+
errorEmitter = new Emitter();
|
|
21
|
+
closeEmitter = new Emitter();
|
|
22
|
+
partialEmitter = new Emitter();
|
|
23
|
+
callback = null;
|
|
24
|
+
attached = false;
|
|
25
|
+
constructor(ws) {
|
|
26
|
+
this.ws = ws;
|
|
27
|
+
}
|
|
28
|
+
get onError() {
|
|
29
|
+
return this.errorEmitter.event;
|
|
30
|
+
}
|
|
31
|
+
get onClose() {
|
|
32
|
+
return this.closeEmitter.event;
|
|
33
|
+
}
|
|
34
|
+
get onPartialMessage() {
|
|
35
|
+
return this.partialEmitter.event;
|
|
36
|
+
}
|
|
37
|
+
onMessage = (event) => {
|
|
38
|
+
if (!this.callback)
|
|
39
|
+
return;
|
|
40
|
+
let message;
|
|
41
|
+
try {
|
|
42
|
+
message = JSON.parse(toText(event.data));
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
this.errorEmitter.fire(error instanceof Error ? error : new Error(String(error)));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
this.callback(message);
|
|
49
|
+
};
|
|
50
|
+
onCloseEvent = () => {
|
|
51
|
+
this.closeEmitter.fire(undefined);
|
|
52
|
+
};
|
|
53
|
+
onErrorEvent = () => {
|
|
54
|
+
this.errorEmitter.fire(new Error('WebSocket error'));
|
|
55
|
+
};
|
|
56
|
+
listen(callback) {
|
|
57
|
+
if (this.attached) {
|
|
58
|
+
throw new Error('WebSocketMessageReader is already listening');
|
|
59
|
+
}
|
|
60
|
+
this.callback = callback;
|
|
61
|
+
this.ws.addEventListener('message', this.onMessage);
|
|
62
|
+
this.ws.addEventListener('close', this.onCloseEvent);
|
|
63
|
+
this.ws.addEventListener('error', this.onErrorEvent);
|
|
64
|
+
this.attached = true;
|
|
65
|
+
return { dispose: () => this.dispose() };
|
|
66
|
+
}
|
|
67
|
+
dispose() {
|
|
68
|
+
if (!this.attached)
|
|
69
|
+
return;
|
|
70
|
+
this.ws.removeEventListener('message', this.onMessage);
|
|
71
|
+
this.ws.removeEventListener('close', this.onCloseEvent);
|
|
72
|
+
this.ws.removeEventListener('error', this.onErrorEvent);
|
|
73
|
+
this.attached = false;
|
|
74
|
+
this.callback = null;
|
|
75
|
+
this.errorEmitter.dispose();
|
|
76
|
+
this.closeEmitter.dispose();
|
|
77
|
+
this.partialEmitter.dispose();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
class WebSocketMessageWriter {
|
|
81
|
+
ws;
|
|
82
|
+
errorEmitter = new Emitter();
|
|
83
|
+
closeEmitter = new Emitter();
|
|
84
|
+
attached = false;
|
|
85
|
+
onCloseEvent = () => {
|
|
86
|
+
this.closeEmitter.fire(undefined);
|
|
87
|
+
};
|
|
88
|
+
constructor(ws) {
|
|
89
|
+
this.ws = ws;
|
|
90
|
+
this.ws.addEventListener('close', this.onCloseEvent);
|
|
91
|
+
this.attached = true;
|
|
92
|
+
}
|
|
93
|
+
get onError() {
|
|
94
|
+
return this.errorEmitter.event;
|
|
95
|
+
}
|
|
96
|
+
get onClose() {
|
|
97
|
+
return this.closeEmitter.event;
|
|
98
|
+
}
|
|
99
|
+
async write(message) {
|
|
100
|
+
if (this.ws.readyState !== OPEN) {
|
|
101
|
+
throw new Error(`WebSocket is not open (readyState=${this.ws.readyState})`);
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
this.ws.send(JSON.stringify(message));
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
108
|
+
this.errorEmitter.fire([err, message, undefined]);
|
|
109
|
+
throw err;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
end() {
|
|
113
|
+
if (this.ws.readyState === OPEN)
|
|
114
|
+
this.ws.close();
|
|
115
|
+
}
|
|
116
|
+
dispose() {
|
|
117
|
+
if (!this.attached)
|
|
118
|
+
return;
|
|
119
|
+
this.ws.removeEventListener('close', this.onCloseEvent);
|
|
120
|
+
this.attached = false;
|
|
121
|
+
this.errorEmitter.dispose();
|
|
122
|
+
this.closeEmitter.dispose();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Create an {@link MdxpConnection} over a WebSocket.
|
|
127
|
+
*
|
|
128
|
+
* Each WebSocket message carries exactly one complete JSON-RPC 2.0 message —
|
|
129
|
+
* the WebSocket protocol already frames messages, so there is no Content-Length
|
|
130
|
+
* framing. Works with the browser `WebSocket` and the Node `ws` package alike
|
|
131
|
+
* (both satisfy {@link WebSocketLike}).
|
|
132
|
+
*
|
|
133
|
+
* Register handlers first, then call `listen()`:
|
|
134
|
+
*
|
|
135
|
+
* ```ts
|
|
136
|
+
* const conn = fromWebSocket(ws)
|
|
137
|
+
* conn.onNotification('$/task/progress', (p) => {})
|
|
138
|
+
* conn.listen()
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
export function fromWebSocket(ws) {
|
|
142
|
+
return createMdxpConnection(new WebSocketMessageReader(ws), new WebSocketMessageWriter(ws));
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=ws.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws.js","sourceRoot":"","sources":["../../src/transports/ws.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/browser.ts
CHANGED
|
@@ -20,3 +20,8 @@ export {
|
|
|
20
20
|
BrowserMessageWriter,
|
|
21
21
|
} from 'vscode-jsonrpc/browser'
|
|
22
22
|
export * from './index.js'
|
|
23
|
+
export type { WorkerLike } from './transports/worker.js'
|
|
24
|
+
export { fromWorker } from './transports/worker.js'
|
|
25
|
+
export type { WebSocketLike } from './transports/ws.js'
|
|
26
|
+
// High-level convenience constructors for browser transports.
|
|
27
|
+
export { fromWebSocket } from './transports/ws.js'
|
package/src/node.ts
CHANGED
|
@@ -26,3 +26,8 @@ export {
|
|
|
26
26
|
StreamMessageWriter,
|
|
27
27
|
} from 'vscode-jsonrpc/node'
|
|
28
28
|
export * from './index.js'
|
|
29
|
+
export type { StdioOptions } from './transports/stdio.js'
|
|
30
|
+
// High-level convenience constructors for Node transports.
|
|
31
|
+
export { fromStdio } from './transports/stdio.js'
|
|
32
|
+
export type { WebSocketLike } from './transports/ws.js'
|
|
33
|
+
export { fromWebSocket } from './transports/ws.js'
|
package/src/schemas/task.ts
CHANGED
|
@@ -59,6 +59,10 @@ export const MdxpTaskSchema = z.object({
|
|
|
59
59
|
finalPath: z.string().nullable(),
|
|
60
60
|
infoHash: z.string().nullable().optional(),
|
|
61
61
|
bt: MdxpBtSchema.optional(),
|
|
62
|
+
/** Open set of `DL_*` values (host's `DownloadErrorCode`); the host may add
|
|
63
|
+
* new codes over time, so consumers MUST tolerate an unrecognized string
|
|
64
|
+
* here rather than reject it — adding a value is not a breaking change. */
|
|
65
|
+
errorCode: z.string().nullish(),
|
|
62
66
|
})
|
|
63
67
|
|
|
64
68
|
/** Shared result for write methods that only need to ack. */
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { StreamMessageReader, StreamMessageWriter } from 'vscode-jsonrpc/node'
|
|
2
|
+
import type { MdxpConnection } from '../connection.js'
|
|
3
|
+
import { createMdxpConnection } from '../connection.js'
|
|
4
|
+
|
|
5
|
+
/** Streams for {@link fromStdio}; defaults to the process's stdio. */
|
|
6
|
+
export interface StdioOptions {
|
|
7
|
+
input?: NodeJS.ReadableStream
|
|
8
|
+
output?: NodeJS.WritableStream
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Create an {@link MdxpConnection} over Node streams — `process.stdin` /
|
|
13
|
+
* `process.stdout` by default. This is the native-messaging-host / CLI case:
|
|
14
|
+
* the parent process pipes JSON-RPC over the child's stdio.
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* const conn = fromStdio()
|
|
18
|
+
* conn.onRequest('url/resolve', async (params) => {})
|
|
19
|
+
* conn.listen()
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function fromStdio(options: StdioOptions = {}): MdxpConnection {
|
|
23
|
+
return createMdxpConnection(
|
|
24
|
+
new StreamMessageReader(options.input ?? process.stdin),
|
|
25
|
+
new StreamMessageWriter(options.output ?? process.stdout)
|
|
26
|
+
)
|
|
27
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { MessageReader, MessageWriter } from 'vscode-jsonrpc'
|
|
2
|
+
import {
|
|
3
|
+
BrowserMessageReader,
|
|
4
|
+
BrowserMessageWriter,
|
|
5
|
+
} from 'vscode-jsonrpc/browser'
|
|
6
|
+
import type { MdxpConnection } from '../connection.js'
|
|
7
|
+
import { createMdxpConnection } from '../connection.js'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Minimal structural subset of a `MessagePort` / `Worker` /
|
|
11
|
+
* `DedicatedWorkerGlobalScope` — anything the browser RAL's reader/writer
|
|
12
|
+
* accept. Consumers pass their worker or port as-is.
|
|
13
|
+
*/
|
|
14
|
+
export interface WorkerLike {
|
|
15
|
+
postMessage(message: unknown): void
|
|
16
|
+
addEventListener(
|
|
17
|
+
type: 'message',
|
|
18
|
+
listener: (event: { readonly data: unknown }) => void
|
|
19
|
+
): void
|
|
20
|
+
removeEventListener(
|
|
21
|
+
type: 'message',
|
|
22
|
+
listener: (event: { readonly data: unknown }) => void
|
|
23
|
+
): void
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// vscode-jsonrpc types the port as `MessagePort | Worker | DedicatedWorkerGlobalScope`,
|
|
27
|
+
// which are DOM / WebWorker globals. This package targets `lib: ES2022` (no DOM),
|
|
28
|
+
// so re-type the constructors against the structural `WorkerLike` instead of
|
|
29
|
+
// pulling the DOM libs into every consumer.
|
|
30
|
+
const Reader = BrowserMessageReader as unknown as new (
|
|
31
|
+
port: WorkerLike
|
|
32
|
+
) => MessageReader
|
|
33
|
+
const Writer = BrowserMessageWriter as unknown as new (
|
|
34
|
+
port: WorkerLike
|
|
35
|
+
) => MessageWriter
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Create an {@link MdxpConnection} over a Worker or `MessagePort` (the browser
|
|
39
|
+
* `postMessage` transport).
|
|
40
|
+
*
|
|
41
|
+
* ```ts
|
|
42
|
+
* const conn = fromWorker(self) // inside a Web Worker
|
|
43
|
+
* conn.onNotification('$/task/progress', (p) => {})
|
|
44
|
+
* conn.listen()
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export function fromWorker(port: WorkerLike): MdxpConnection {
|
|
48
|
+
return createMdxpConnection(new Reader(port), new Writer(port))
|
|
49
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DataCallback,
|
|
3
|
+
Disposable,
|
|
4
|
+
Message,
|
|
5
|
+
MessageReader,
|
|
6
|
+
MessageWriter,
|
|
7
|
+
PartialMessageInfo,
|
|
8
|
+
} from 'vscode-jsonrpc'
|
|
9
|
+
import { Emitter } from 'vscode-jsonrpc'
|
|
10
|
+
import type { MdxpConnection } from '../connection.js'
|
|
11
|
+
import { createMdxpConnection } from '../connection.js'
|
|
12
|
+
|
|
13
|
+
/** `WebSocket.readyState` value for an open socket (browser and `ws` agree). */
|
|
14
|
+
const OPEN = 1
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Minimal structural subset of a WebSocket shared by the browser `WebSocket`
|
|
18
|
+
* and the Node [`ws`](https://www.npmjs.com/package/ws) package. Consumers pass
|
|
19
|
+
* their socket as-is — no wrapping required.
|
|
20
|
+
*/
|
|
21
|
+
export interface WebSocketLike {
|
|
22
|
+
readonly readyState: number
|
|
23
|
+
send(data: string): void
|
|
24
|
+
close(code?: number, reason?: string): void
|
|
25
|
+
addEventListener(
|
|
26
|
+
type: 'message' | 'close' | 'error',
|
|
27
|
+
listener: (event: { readonly data?: unknown }) => void
|
|
28
|
+
): void
|
|
29
|
+
removeEventListener(
|
|
30
|
+
type: 'message' | 'close' | 'error',
|
|
31
|
+
listener: (event: { readonly data?: unknown }) => void
|
|
32
|
+
): void
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function toText(data: unknown): string {
|
|
36
|
+
if (typeof data === 'string') return data
|
|
37
|
+
if (data instanceof ArrayBuffer) return new TextDecoder().decode(data)
|
|
38
|
+
// A typed array / DataView / Node Buffer. TS 6's generic `ArrayBufferView`
|
|
39
|
+
// typing is stricter than `TextDecoder.decode`'s runtime contract (which
|
|
40
|
+
// accepts any view), so widen to satisfy the compiler.
|
|
41
|
+
if (ArrayBuffer.isView(data)) {
|
|
42
|
+
return new TextDecoder().decode(data as unknown as Uint8Array)
|
|
43
|
+
}
|
|
44
|
+
throw new Error('unsupported WebSocket message data type')
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
class WebSocketMessageReader implements MessageReader {
|
|
48
|
+
private readonly errorEmitter = new Emitter<Error>()
|
|
49
|
+
private readonly closeEmitter = new Emitter<void>()
|
|
50
|
+
private readonly partialEmitter = new Emitter<PartialMessageInfo>()
|
|
51
|
+
private callback: DataCallback | null = null
|
|
52
|
+
private attached = false
|
|
53
|
+
|
|
54
|
+
constructor(private readonly ws: WebSocketLike) {}
|
|
55
|
+
|
|
56
|
+
get onError() {
|
|
57
|
+
return this.errorEmitter.event
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
get onClose() {
|
|
61
|
+
return this.closeEmitter.event
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
get onPartialMessage() {
|
|
65
|
+
return this.partialEmitter.event
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private readonly onMessage = (event: { readonly data?: unknown }): void => {
|
|
69
|
+
if (!this.callback) return
|
|
70
|
+
let message: Message
|
|
71
|
+
try {
|
|
72
|
+
message = JSON.parse(toText(event.data)) as Message
|
|
73
|
+
} catch (error) {
|
|
74
|
+
this.errorEmitter.fire(
|
|
75
|
+
error instanceof Error ? error : new Error(String(error))
|
|
76
|
+
)
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
this.callback(message)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private readonly onCloseEvent = (): void => {
|
|
83
|
+
this.closeEmitter.fire(undefined)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private readonly onErrorEvent = (): void => {
|
|
87
|
+
this.errorEmitter.fire(new Error('WebSocket error'))
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
listen(callback: DataCallback): Disposable {
|
|
91
|
+
if (this.attached) {
|
|
92
|
+
throw new Error('WebSocketMessageReader is already listening')
|
|
93
|
+
}
|
|
94
|
+
this.callback = callback
|
|
95
|
+
this.ws.addEventListener('message', this.onMessage)
|
|
96
|
+
this.ws.addEventListener('close', this.onCloseEvent)
|
|
97
|
+
this.ws.addEventListener('error', this.onErrorEvent)
|
|
98
|
+
this.attached = true
|
|
99
|
+
return { dispose: () => this.dispose() }
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
dispose(): void {
|
|
103
|
+
if (!this.attached) return
|
|
104
|
+
this.ws.removeEventListener('message', this.onMessage)
|
|
105
|
+
this.ws.removeEventListener('close', this.onCloseEvent)
|
|
106
|
+
this.ws.removeEventListener('error', this.onErrorEvent)
|
|
107
|
+
this.attached = false
|
|
108
|
+
this.callback = null
|
|
109
|
+
this.errorEmitter.dispose()
|
|
110
|
+
this.closeEmitter.dispose()
|
|
111
|
+
this.partialEmitter.dispose()
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
class WebSocketMessageWriter implements MessageWriter {
|
|
116
|
+
private readonly errorEmitter = new Emitter<
|
|
117
|
+
[Error, Message | undefined, number | undefined]
|
|
118
|
+
>()
|
|
119
|
+
private readonly closeEmitter = new Emitter<void>()
|
|
120
|
+
private attached = false
|
|
121
|
+
|
|
122
|
+
private readonly onCloseEvent = (): void => {
|
|
123
|
+
this.closeEmitter.fire(undefined)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
constructor(private readonly ws: WebSocketLike) {
|
|
127
|
+
this.ws.addEventListener('close', this.onCloseEvent)
|
|
128
|
+
this.attached = true
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
get onError() {
|
|
132
|
+
return this.errorEmitter.event
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
get onClose() {
|
|
136
|
+
return this.closeEmitter.event
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async write(message: Message): Promise<void> {
|
|
140
|
+
if (this.ws.readyState !== OPEN) {
|
|
141
|
+
throw new Error(
|
|
142
|
+
`WebSocket is not open (readyState=${this.ws.readyState})`
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
this.ws.send(JSON.stringify(message))
|
|
147
|
+
} catch (error) {
|
|
148
|
+
const err = error instanceof Error ? error : new Error(String(error))
|
|
149
|
+
this.errorEmitter.fire([err, message, undefined])
|
|
150
|
+
throw err
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
end(): void {
|
|
155
|
+
if (this.ws.readyState === OPEN) this.ws.close()
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
dispose(): void {
|
|
159
|
+
if (!this.attached) return
|
|
160
|
+
this.ws.removeEventListener('close', this.onCloseEvent)
|
|
161
|
+
this.attached = false
|
|
162
|
+
this.errorEmitter.dispose()
|
|
163
|
+
this.closeEmitter.dispose()
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Create an {@link MdxpConnection} over a WebSocket.
|
|
169
|
+
*
|
|
170
|
+
* Each WebSocket message carries exactly one complete JSON-RPC 2.0 message —
|
|
171
|
+
* the WebSocket protocol already frames messages, so there is no Content-Length
|
|
172
|
+
* framing. Works with the browser `WebSocket` and the Node `ws` package alike
|
|
173
|
+
* (both satisfy {@link WebSocketLike}).
|
|
174
|
+
*
|
|
175
|
+
* Register handlers first, then call `listen()`:
|
|
176
|
+
*
|
|
177
|
+
* ```ts
|
|
178
|
+
* const conn = fromWebSocket(ws)
|
|
179
|
+
* conn.onNotification('$/task/progress', (p) => {})
|
|
180
|
+
* conn.listen()
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export function fromWebSocket(ws: WebSocketLike): MdxpConnection {
|
|
184
|
+
return createMdxpConnection(
|
|
185
|
+
new WebSocketMessageReader(ws),
|
|
186
|
+
new WebSocketMessageWriter(ws)
|
|
187
|
+
)
|
|
188
|
+
}
|