virlen-remote 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/CHANGELOG.md +373 -169
  2. package/README.md +389 -201
  3. package/dist/index.d.ts +10 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +10 -0
  6. package/dist/index.js.map +1 -1
  7. package/dist/protocol/agents.d.ts +14 -0
  8. package/dist/protocol/agents.d.ts.map +1 -0
  9. package/dist/protocol/agents.js +14 -0
  10. package/dist/protocol/agents.js.map +1 -0
  11. package/dist/protocol/api.d.ts +370 -1
  12. package/dist/protocol/api.d.ts.map +1 -1
  13. package/dist/protocol/api.js.map +1 -1
  14. package/dist/protocol/compress.d.ts +55 -0
  15. package/dist/protocol/compress.d.ts.map +1 -0
  16. package/dist/protocol/compress.js +60 -0
  17. package/dist/protocol/compress.js.map +1 -0
  18. package/dist/protocol/files.d.ts +261 -0
  19. package/dist/protocol/files.d.ts.map +1 -0
  20. package/dist/protocol/files.js +506 -0
  21. package/dist/protocol/files.js.map +1 -0
  22. package/dist/protocol/host.d.ts +24 -1
  23. package/dist/protocol/host.d.ts.map +1 -1
  24. package/dist/protocol/host.js +9 -1
  25. package/dist/protocol/host.js.map +1 -1
  26. package/dist/protocol/message-files.d.ts +79 -0
  27. package/dist/protocol/message-files.d.ts.map +1 -0
  28. package/dist/protocol/message-files.js +118 -0
  29. package/dist/protocol/message-files.js.map +1 -0
  30. package/dist/protocol/tool-args.d.ts +95 -0
  31. package/dist/protocol/tool-args.d.ts.map +1 -0
  32. package/dist/protocol/tool-args.js +439 -0
  33. package/dist/protocol/tool-args.js.map +1 -0
  34. package/dist/testing/mock-host.d.ts +44 -1
  35. package/dist/testing/mock-host.d.ts.map +1 -1
  36. package/dist/testing/mock-host.js +439 -10
  37. package/dist/testing/mock-host.js.map +1 -1
  38. package/dist/transport/rtc.d.ts +17 -0
  39. package/dist/transport/rtc.d.ts.map +1 -1
  40. package/dist/transport/rtc.js +49 -12
  41. package/dist/transport/rtc.js.map +1 -1
  42. package/dist/transport/signaling.d.ts +12 -1
  43. package/dist/transport/signaling.d.ts.map +1 -1
  44. package/dist/transport/signaling.js +17 -3
  45. package/dist/transport/signaling.js.map +1 -1
  46. package/package.json +69 -69
  47. package/src/index.ts +270 -184
  48. package/src/protocol/agents.ts +13 -0
  49. package/src/protocol/api.ts +974 -615
  50. package/src/protocol/compress.ts +65 -0
  51. package/src/protocol/files.ts +544 -0
  52. package/src/protocol/host.ts +205 -165
  53. package/src/protocol/message-actions.ts +60 -60
  54. package/src/protocol/message-files.ts +161 -0
  55. package/src/protocol/pairing.ts +254 -254
  56. package/src/protocol/tool-args.ts +478 -0
  57. package/src/testing/mock-host.ts +1285 -740
  58. package/src/transport/link-kind.ts +222 -222
  59. package/src/transport/rtc.ts +381 -344
  60. package/src/transport/signaling.ts +331 -317
  61. package/src/transport/transfer-tier.ts +64 -64
package/src/index.ts CHANGED
@@ -1,184 +1,270 @@
1
- /**
2
- * virlen-remote —— 手机控制协议栈共享包
3
- *
4
- * 电脑端(virlen-app)与手机端(virlen-mobile)共用同一份实现
5
- * (见 docs/phone-control-bridge.md §1「越往下越同构」、§6「共享包」)。
6
- *
7
- * 分层:
8
- * protocol/ 与传输无关的逻辑(帧 / RPC / 错误 / 能力协商 / 方法表)
9
- * transport/ 字节通道抽象 + 内存实现(RTC 实现属 M3)
10
- *
11
- * **零运行时依赖**:WebRTC 用浏览器原生 `RTCPeerConnection`;Node 侧只用 memory transport 做测试。
12
- */
13
-
14
- // ── protocol ──
15
- export { PROTOCOL_VERSION, HEADER_SIZE, DEFAULT_MAX_FRAME_PAYLOAD, FrameKind } from './protocol/frame'
16
- export { encodeHeader, decodeHeader, frameBody, encodeFrames, Reassembler } from './protocol/frame'
17
- export type { FrameHeader, DecodedMessage } from './protocol/frame'
18
-
19
- export { BridgeError, toBridgeError } from './protocol/errors'
20
- export type { ErrorCode, WireError, BridgeErrorOptions } from './protocol/errors'
21
-
22
- export { newRequestId } from './protocol/ids'
23
-
24
- // ── 设备身份与授权凭证(M6,§30)──
25
- export {
26
- HOST_KEY_PREFIX,
27
- MOBILE_KEY_PREFIX,
28
- GRANT_PREFIX,
29
- ROOM_PREFIX,
30
- GRANT_TTL_MS,
31
- GRANT_MAX_LIFETIME_MS,
32
- randomKey,
33
- newDeviceKey,
34
- newGrantToken,
35
- isDeviceKey,
36
- roomFor,
37
- hostKeyFromRoom,
38
- issueGrant,
39
- isGrantExpired,
40
- renewGrant,
41
- checkGrant,
42
- describeGrantRemaining,
43
- } from './protocol/identity'
44
- export type { DeviceKind, GrantRecord, CredentialRejectReason, RoomStatus } from './protocol/identity'
45
-
46
- // ── 配对载荷(二维码内容,两端同一份)──
47
- export {
48
- PAIRING_PAYLOAD_VERSION,
49
- PAIRING_TICKET_TTL_MS,
50
- PAIRING_OBFUSCATION_PREFIX,
51
- PAIRING_URL_BASE,
52
- PAIRING_URL_PARAM,
53
- buildPairingPayload,
54
- encodePairingPayload,
55
- buildPairingUrl,
56
- parsePairingPayload,
57
- roomOfPayload,
58
- } from './protocol/pairing'
59
- export type { PairingPayload } from './protocol/pairing'
60
-
61
- export { normalizeChoiceAnswer, answerActionError, CHOICE_JOINER } from './protocol/answer'
62
- export type { ChoiceAnswer } from './protocol/answer'
63
-
64
- export { negotiate, intersectCapabilities } from './protocol/hello'
65
-
66
- // ── 消息级操作(引用 / 删除)的共用契约:能力名 + 引用快照体 ──
67
- export { MESSAGE_QUOTE_CAPABILITY, MESSAGE_DELETE_CAPABILITY } from './protocol/message-actions'
68
- export type { MessageQuote } from './protocol/message-actions'
69
-
70
- export { Endpoint } from './protocol/endpoint'
71
- export type {
72
- CallContext,
73
- EventContext,
74
- RpcHandler,
75
- EventSubscriber,
76
- CallOptions,
77
- EndpointOptions,
78
- } from './protocol/endpoint'
79
-
80
- export { createCaller, createSubscriber, registerHandlers } from './protocol/api'
81
- export { DEFAULT_CONTEXT_WINDOW_TOKENS, COMPRESS_MIN_RATIO } from './protocol/api'
82
- export type {
83
- ParamsOf,
84
- ResultOf,
85
- TypedCaller,
86
- TypedSubscriber,
87
- HandlerImpl,
88
- HostApi,
89
- MobileApi,
90
- HostEvents,
91
- MobileEvents,
92
- SessionSummaryDTO,
93
- MessageDTO,
94
- RuntimeDTO,
95
- InteractionDTO,
96
- InteractionOutcome,
97
- StreamMode,
98
- ApprovalTier,
99
- SendParams,
100
- MsgPageParams,
101
- MsgPageDTO,
102
- AnswerParams,
103
- AnswerAction,
104
- AnswerResult,
105
- AnswerRejectReason,
106
- CreateSessionParams,
107
- RenameSessionParams,
108
- PinSessionParams,
109
- DeleteSessionParams,
110
- DeleteMessageParams,
111
- ModelProviderDTO,
112
- WorkspaceOptionDTO,
113
- ContextInfoDTO,
114
- SetModelParams,
115
- ContextParams,
116
- CompressParams,
117
- } from './protocol/api'
118
- export type { HelloParams, HelloResult, ClientInfo, NegotiationInput, Negotiated } from './protocol/hello'
119
-
120
- export { registerHostHandlers } from './protocol/host'
121
- export type { HostDataSource, HostEmit, HostRegistration, RegisterHostOptions } from './protocol/host'
122
- // ── transport ──
123
- export type { Transport, TransportState } from './transport/types'
124
- export { MemoryTransport, createMemoryPair } from './transport/memory'
125
- export type { MemoryTransportMetrics } from './transport/memory'
126
- export { BroadcastTransport, createBroadcastPair } from './transport/broadcast'
127
- export { SseSignalingClient, fetchRoomStatus, fetchHostOnlineMap } from './transport/signaling'
128
- export type {
129
- SignalingChannel,
130
- SignalingRole,
131
- SseSignalingOptions,
132
- EventSourceLike,
133
- KickedInfo,
134
- FetchRoomStatusOptions,
135
- } from './transport/signaling'
136
- export { RtcTransport } from './transport/rtc'
137
- export type { RtcTransportOptions } from './transport/rtc'
138
-
139
- // ── RTC 链路类型判定(直连 / 中继,两端同一份口径)──
140
- export {
141
- LINK_KIND_POLL_MS,
142
- classifyLinkKind,
143
- probeLinkKind,
144
- pickCandidatePair,
145
- findCandidate,
146
- LinkKindWatcher,
147
- } from './transport/link-kind'
148
- export type {
149
- LinkKind,
150
- LinkStatsEntry,
151
- StatsReportLike,
152
- StatsProvider,
153
- } from './transport/link-kind'
154
-
155
- // ── 传输档位(链路类型 → 发不发详细内容,两端同一份口径)──
156
- export { MESSAGE_DETAIL_CAPABILITY, transferTierOf } from './transport/transfer-tier'
157
- export type { TransferTier } from './transport/transfer-tier'
158
-
159
- // ── ICE 配置(M7,§31):客户端不再内置任何 TURN 凭证 ──
160
- export {
161
- ICE_CONFIG_VERSION,
162
- ICE_API_PATH,
163
- ICE_CUSTOM_STORAGE_KEY,
164
- ICE_REMOTE_STORAGE_KEY,
165
- ICE_CACHE_TTL_MS,
166
- ICE_FETCH_TIMEOUT_MS,
167
- sanitizeIceServers,
168
- parseIceText,
169
- formatIceServers,
170
- describeIceSource,
171
- fetchIceServers,
172
- resolveIceServers,
173
- readCustomIceText,
174
- writeCustomIceText,
175
- } from './transport/ice'
176
- export type {
177
- IceServerInit,
178
- IceSource,
179
- IceStoragePort,
180
- ResolvedIceServers,
181
- ParseIceResult,
182
- FetchIceOptions,
183
- ResolveIceOptions,
184
- } from './transport/ice'
1
+ /**
2
+ * virlen-remote —— 手机控制协议栈共享包
3
+ *
4
+ * 电脑端(virlen-app)与手机端(virlen-mobile)共用同一份实现
5
+ * (见 docs/phone-control-bridge.md §1「越往下越同构」、§6「共享包」)。
6
+ *
7
+ * 分层:
8
+ * protocol/ 与传输无关的逻辑(帧 / RPC / 错误 / 能力协商 / 方法表)
9
+ * transport/ 字节通道抽象 + 内存实现(RTC 实现属 M3)
10
+ *
11
+ * **零运行时依赖**:WebRTC 用浏览器原生 `RTCPeerConnection`;Node 侧只用 memory transport 做测试。
12
+ */
13
+
14
+ // ── protocol ──
15
+ export { PROTOCOL_VERSION, HEADER_SIZE, DEFAULT_MAX_FRAME_PAYLOAD, FrameKind } from './protocol/frame'
16
+ export { encodeHeader, decodeHeader, frameBody, encodeFrames, Reassembler } from './protocol/frame'
17
+ export type { FrameHeader, DecodedMessage } from './protocol/frame'
18
+
19
+ export { BridgeError, toBridgeError } from './protocol/errors'
20
+ export type { ErrorCode, WireError, BridgeErrorOptions } from './protocol/errors'
21
+
22
+ export { newRequestId } from './protocol/ids'
23
+
24
+ // ── 设备身份与授权凭证(M6,§30)──
25
+ export {
26
+ HOST_KEY_PREFIX,
27
+ MOBILE_KEY_PREFIX,
28
+ GRANT_PREFIX,
29
+ ROOM_PREFIX,
30
+ GRANT_TTL_MS,
31
+ GRANT_MAX_LIFETIME_MS,
32
+ randomKey,
33
+ newDeviceKey,
34
+ newGrantToken,
35
+ isDeviceKey,
36
+ roomFor,
37
+ hostKeyFromRoom,
38
+ issueGrant,
39
+ isGrantExpired,
40
+ renewGrant,
41
+ checkGrant,
42
+ describeGrantRemaining,
43
+ } from './protocol/identity'
44
+ export type { DeviceKind, GrantRecord, CredentialRejectReason, RoomStatus } from './protocol/identity'
45
+
46
+ // ── 配对载荷(二维码内容,两端同一份)──
47
+ export {
48
+ PAIRING_PAYLOAD_VERSION,
49
+ PAIRING_TICKET_TTL_MS,
50
+ PAIRING_OBFUSCATION_PREFIX,
51
+ PAIRING_URL_BASE,
52
+ PAIRING_URL_PARAM,
53
+ buildPairingPayload,
54
+ encodePairingPayload,
55
+ buildPairingUrl,
56
+ parsePairingPayload,
57
+ roomOfPayload,
58
+ } from './protocol/pairing'
59
+ export type { PairingPayload } from './protocol/pairing'
60
+
61
+ export { normalizeChoiceAnswer, answerActionError, CHOICE_JOINER } from './protocol/answer'
62
+ export type { ChoiceAnswer } from './protocol/answer'
63
+
64
+ export { negotiate, intersectCapabilities } from './protocol/hello'
65
+
66
+ // ── 消息级操作(引用 / 删除)的共用契约:能力名 + 引用快照体 ──
67
+ export { MESSAGE_QUOTE_CAPABILITY, MESSAGE_DELETE_CAPABILITY } from './protocol/message-actions'
68
+ export type { MessageQuote } from './protocol/message-actions'
69
+
70
+ // ── 消息里的文件引用(§37 的延伸):能力名 + 引用体 + 两端同一份校验口径 ──
71
+ export {
72
+ MESSAGE_FILE_CAPABILITY,
73
+ MESSAGE_FILE_MAX,
74
+ MESSAGE_FILE_PATH_MAX,
75
+ sanitizeFileRefs,
76
+ } from './protocol/message-files'
77
+ export type { MessageFileRef, FileRefSanitizeResult } from './protocol/message-files'
78
+
79
+ // ── Agent 相关能力名(新建会话时选定 Agent 的授权口径)──
80
+ export { SESSION_AGENT_CAPABILITY } from './protocol/agents'
81
+
82
+ // ── §22:上下文压缩方式的取值域 + 能力名(手机端选、电脑端执行)──
83
+ export {
84
+ COMPRESS_MODES,
85
+ DEFAULT_COMPRESS_MODE,
86
+ COMPRESS_MODE_CAPABILITY,
87
+ compressModeOf,
88
+ } from './protocol/compress'
89
+ export type { CompressMode } from './protocol/compress'
90
+
91
+ // ── 工具入参的两种呈现(折叠态一行摘要 / 展开态完整入参)的唯一格式化口径 ──
92
+ export {
93
+ summarizeToolArgs,
94
+ formatToolArgs,
95
+ elideMiddle,
96
+ TOOL_ARGS_MAX,
97
+ TOOL_DETAIL_MAX,
98
+ } from './protocol/tool-args'
99
+ export type { ToolArgsSummaryOptions, ToolArgsFormatOptions } from './protocol/tool-args'
100
+
101
+ // ── §37:工作目录文件(能力名 / 限额 / base64 / 预览分类 / 路径工具,两端同一份)──
102
+ export {
103
+ FILE_BROWSE_CAPABILITY,
104
+ FILE_DOWNLOAD_CAPABILITY,
105
+ FILE_UPLOAD_CAPABILITY,
106
+ FILE_EDIT_CAPABILITY,
107
+ FILE_CHUNK_BYTES,
108
+ FILE_UPLOAD_MAX_BYTES,
109
+ FILE_EDIT_MAX_BYTES,
110
+ FILE_TEXT_PREVIEW_MAX_BYTES,
111
+ FILE_IMAGE_PREVIEW_MAX_BYTES,
112
+ FILE_LIST_MAX_ENTRIES,
113
+ FILE_NAME_MAX_LEN,
114
+ UPLOAD_PART_SUFFIX,
115
+ FILE_DIRECT_ONLY_MESSAGE,
116
+ fileTransferDeniedReason,
117
+ splitNameExt,
118
+ previewKindOf,
119
+ previewLimitOf,
120
+ mimeTypeOf,
121
+ isEditableKind,
122
+ isEditableFileName,
123
+ detectEolStyle,
124
+ applyEolStyle,
125
+ hasUtf8Bom,
126
+ decodeUtf8Strict,
127
+ encodeEditedText,
128
+ bytesToBase64,
129
+ base64ToBytes,
130
+ formatFileSize,
131
+ normalizeRelPath,
132
+ joinRelPath,
133
+ parentOfRelPath,
134
+ baseNameOfPath,
135
+ isSafeEntryName,
136
+ duplicateNameCandidate,
137
+ compareFileEntries,
138
+ } from './protocol/files'
139
+ export type { FilePreviewKind, EolStyle } from './protocol/files'
140
+
141
+ export { Endpoint } from './protocol/endpoint'
142
+ export type {
143
+ CallContext,
144
+ EventContext,
145
+ RpcHandler,
146
+ EventSubscriber,
147
+ CallOptions,
148
+ EndpointOptions,
149
+ } from './protocol/endpoint'
150
+
151
+ export { createCaller, createSubscriber, registerHandlers } from './protocol/api'
152
+ export { DEFAULT_CONTEXT_WINDOW_TOKENS, COMPRESS_MIN_RATIO } from './protocol/api'
153
+ export type {
154
+ ParamsOf,
155
+ ResultOf,
156
+ TypedCaller,
157
+ TypedSubscriber,
158
+ HandlerImpl,
159
+ HostApi,
160
+ MobileApi,
161
+ HostEvents,
162
+ MobileEvents,
163
+ SessionSummaryDTO,
164
+ MessageDTO,
165
+ RuntimeDTO,
166
+ RunningToolDTO,
167
+ InteractionDTO,
168
+ InteractionOutcome,
169
+ StreamMode,
170
+ ApprovalTier,
171
+ SendParams,
172
+ MsgPageParams,
173
+ MsgPageDTO,
174
+ AnswerParams,
175
+ AnswerAction,
176
+ AnswerResult,
177
+ AnswerRejectReason,
178
+ CreateSessionParams,
179
+ RenameSessionParams,
180
+ PinSessionParams,
181
+ DeleteSessionParams,
182
+ DeleteMessageParams,
183
+ AgentOptionDTO,
184
+ ModelProviderDTO,
185
+ WorkspaceOptionDTO,
186
+ ContextInfoDTO,
187
+ SetModelParams,
188
+ ContextParams,
189
+ CompressParams,
190
+ FileEntryDTO,
191
+ FileListParams,
192
+ FileListResult,
193
+ FileReadParams,
194
+ FileReadResult,
195
+ FileWriteBeginParams,
196
+ FileWriteBeginResult,
197
+ FileWriteChunkParams,
198
+ FileWriteChunkResult,
199
+ FileWriteFinishParams,
200
+ FileWriteFinishResult,
201
+ FileWriteAbortParams,
202
+ FileConflictPolicy,
203
+ } from './protocol/api'
204
+ export type { HelloParams, HelloResult, ClientInfo, NegotiationInput, Negotiated } from './protocol/hello'
205
+
206
+ export { registerHostHandlers } from './protocol/host'
207
+ export type { HostDataSource, HostEmit, HostRegistration, RegisterHostOptions } from './protocol/host'
208
+ // ── transport ──
209
+ export type { Transport, TransportState } from './transport/types'
210
+ export { MemoryTransport, createMemoryPair } from './transport/memory'
211
+ export type { MemoryTransportMetrics } from './transport/memory'
212
+ export { BroadcastTransport, createBroadcastPair } from './transport/broadcast'
213
+ export { SseSignalingClient, fetchRoomStatus, fetchHostOnlineMap } from './transport/signaling'
214
+ export type {
215
+ SignalingChannel,
216
+ SignalingRole,
217
+ SseSignalingOptions,
218
+ EventSourceLike,
219
+ KickedInfo,
220
+ FetchRoomStatusOptions,
221
+ } from './transport/signaling'
222
+ export { RtcTransport } from './transport/rtc'
223
+ export type { RtcTransportOptions } from './transport/rtc'
224
+
225
+ // ── RTC 链路类型判定(直连 / 中继,两端同一份口径)──
226
+ export {
227
+ LINK_KIND_POLL_MS,
228
+ classifyLinkKind,
229
+ probeLinkKind,
230
+ pickCandidatePair,
231
+ findCandidate,
232
+ LinkKindWatcher,
233
+ } from './transport/link-kind'
234
+ export type {
235
+ LinkKind,
236
+ LinkStatsEntry,
237
+ StatsReportLike,
238
+ StatsProvider,
239
+ } from './transport/link-kind'
240
+
241
+ // ── 传输档位(链路类型 → 发不发详细内容,两端同一份口径)──
242
+ export { MESSAGE_DETAIL_CAPABILITY, transferTierOf } from './transport/transfer-tier'
243
+ export type { TransferTier } from './transport/transfer-tier'
244
+
245
+ // ── ICE 配置(M7,§31):客户端不再内置任何 TURN 凭证 ──
246
+ export {
247
+ ICE_CONFIG_VERSION,
248
+ ICE_API_PATH,
249
+ ICE_CUSTOM_STORAGE_KEY,
250
+ ICE_REMOTE_STORAGE_KEY,
251
+ ICE_CACHE_TTL_MS,
252
+ ICE_FETCH_TIMEOUT_MS,
253
+ sanitizeIceServers,
254
+ parseIceText,
255
+ formatIceServers,
256
+ describeIceSource,
257
+ fetchIceServers,
258
+ resolveIceServers,
259
+ readCustomIceText,
260
+ writeCustomIceText,
261
+ } from './transport/ice'
262
+ export type {
263
+ IceServerInit,
264
+ IceSource,
265
+ IceStoragePort,
266
+ ResolvedIceServers,
267
+ ParseIceResult,
268
+ FetchIceOptions,
269
+ ResolveIceOptions,
270
+ } from './transport/ice'
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Agent 相关的能力名(两端共用的唯一一份口径)。
3
+ *
4
+ * 为什么单列一个模块:`session.agent` 是**权限**而不是功能标记 ——
5
+ * 新建会话时选定 Agent 决定这条会话的 systemPrompt / 工具白名单 / skills / 默认参数
6
+ * (电脑侧落点是 `chat-service.createSession(…, agent, …)`),是实实在在的授权范围变化。
7
+ * 所以电脑侧的 handler 必须独立 `assert`(手机端隐藏入口只是 UI 收敛,§7-⑪ 的教训)。
8
+ *
9
+ * 与 `message-actions.ts` 里的两个常量同族:常量写在共享包里、两端 import 同一个字面量,
10
+ * 免得一边写成 `session.agents`、另一边写 `session.agent` 却没人发现(能力名不匹配时
11
+ * 不会报错,只会「UI 不显示」这种最费解的症状)。
12
+ */
13
+ export const SESSION_AGENT_CAPABILITY = 'session.agent'