@secure-exec/core 0.2.1 → 0.3.0-rc.1

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 (248) hide show
  1. package/README.md +5 -5
  2. package/dist/binary.d.ts +4 -0
  3. package/dist/binary.js +25 -0
  4. package/dist/bytes.d.ts +2 -0
  5. package/dist/bytes.js +6 -0
  6. package/dist/callbacks.d.ts +41 -0
  7. package/dist/callbacks.js +94 -0
  8. package/dist/cargo.d.ts +2 -0
  9. package/dist/cargo.js +142 -0
  10. package/dist/correlation.d.ts +10 -0
  11. package/dist/correlation.js +49 -0
  12. package/dist/descriptors.d.ts +34 -0
  13. package/dist/descriptors.js +37 -0
  14. package/dist/event-buffer.d.ts +90 -0
  15. package/dist/event-buffer.js +313 -0
  16. package/dist/ext.d.ts +7 -0
  17. package/dist/ext.js +13 -0
  18. package/dist/filesystem.d.ts +41 -0
  19. package/dist/filesystem.js +70 -0
  20. package/dist/frame-payload-codec.d.ts +8 -0
  21. package/dist/frame-payload-codec.js +14 -0
  22. package/dist/frame-rpc.d.ts +38 -0
  23. package/dist/frame-rpc.js +73 -0
  24. package/dist/frame-stream.d.ts +27 -0
  25. package/dist/frame-stream.js +99 -0
  26. package/dist/framing.d.ts +7 -0
  27. package/dist/framing.js +22 -0
  28. package/dist/generated/AcpLimitsConfig.d.ts +4 -0
  29. package/dist/generated/AcpLimitsConfig.js +2 -0
  30. package/dist/generated/CreateVmConfig.d.ts +19 -0
  31. package/dist/generated/FsPermissionRule.d.ts +6 -0
  32. package/dist/generated/FsPermissionRuleSet.d.ts +6 -0
  33. package/dist/generated/FsPermissionRuleSet.js +1 -0
  34. package/dist/generated/FsPermissionScope.d.ts +3 -0
  35. package/dist/generated/FsPermissionScope.js +1 -0
  36. package/dist/generated/HttpLimitsConfig.d.ts +3 -0
  37. package/dist/generated/HttpLimitsConfig.js +2 -0
  38. package/dist/generated/JsModuleResolution.d.ts +1 -0
  39. package/dist/generated/JsModuleResolution.js +2 -0
  40. package/dist/generated/JsRuntimeConfig.d.ts +26 -0
  41. package/dist/generated/JsRuntimeConfig.js +1 -0
  42. package/dist/generated/JsRuntimeLimitsConfig.d.ts +7 -0
  43. package/dist/generated/JsRuntimeLimitsConfig.js +2 -0
  44. package/dist/generated/JsRuntimePlatform.d.ts +1 -0
  45. package/dist/generated/JsRuntimePlatform.js +2 -0
  46. package/dist/generated/MountPluginDescriptor.d.ts +4 -0
  47. package/dist/generated/MountPluginDescriptor.js +2 -0
  48. package/dist/generated/NativeRootFilesystemConfig.d.ts +5 -0
  49. package/dist/generated/NativeRootFilesystemConfig.js +1 -0
  50. package/dist/generated/PatternPermissionRule.d.ts +6 -0
  51. package/dist/generated/PatternPermissionRule.js +1 -0
  52. package/dist/generated/PatternPermissionRuleSet.d.ts +6 -0
  53. package/dist/generated/PatternPermissionRuleSet.js +1 -0
  54. package/dist/generated/PatternPermissionScope.d.ts +3 -0
  55. package/dist/generated/PatternPermissionScope.js +1 -0
  56. package/dist/generated/PermissionMode.d.ts +1 -0
  57. package/dist/generated/PermissionMode.js +2 -0
  58. package/dist/generated/PermissionsPolicy.d.ts +10 -0
  59. package/dist/generated/PermissionsPolicy.js +1 -0
  60. package/dist/generated/PluginLimitsConfig.d.ts +4 -0
  61. package/dist/generated/PluginLimitsConfig.js +2 -0
  62. package/dist/generated/PythonLimitsConfig.d.ts +5 -0
  63. package/dist/generated/PythonLimitsConfig.js +2 -0
  64. package/dist/generated/ResourceLimitsConfig.d.ts +22 -0
  65. package/dist/generated/ResourceLimitsConfig.js +2 -0
  66. package/dist/generated/RootFilesystemConfig.d.ts +9 -0
  67. package/dist/generated/RootFilesystemConfig.js +1 -0
  68. package/dist/generated/RootFilesystemEntry.d.ts +13 -0
  69. package/dist/generated/RootFilesystemEntry.js +1 -0
  70. package/dist/generated/RootFilesystemEntryEncoding.d.ts +1 -0
  71. package/dist/generated/RootFilesystemEntryEncoding.js +2 -0
  72. package/dist/generated/RootFilesystemEntryKind.d.ts +1 -0
  73. package/dist/generated/RootFilesystemEntryKind.js +2 -0
  74. package/dist/generated/RootFilesystemLowerDescriptor.d.ts +7 -0
  75. package/dist/generated/RootFilesystemLowerDescriptor.js +1 -0
  76. package/dist/generated/RootFilesystemMode.d.ts +1 -0
  77. package/dist/generated/RootFilesystemMode.js +2 -0
  78. package/dist/generated/ToolLimitsConfig.d.ts +10 -0
  79. package/dist/generated/ToolLimitsConfig.js +2 -0
  80. package/dist/generated/VmDnsConfig.d.ts +6 -0
  81. package/dist/generated/VmDnsConfig.js +2 -0
  82. package/dist/generated/VmLimitsConfig.d.ts +18 -0
  83. package/dist/generated/VmLimitsConfig.js +1 -0
  84. package/dist/generated/VmListenPolicyConfig.d.ts +5 -0
  85. package/dist/generated/VmListenPolicyConfig.js +2 -0
  86. package/dist/generated/WasmLimitsConfig.d.ts +5 -0
  87. package/dist/generated/WasmLimitsConfig.js +2 -0
  88. package/dist/generated-protocol.d.ts +1037 -0
  89. package/dist/generated-protocol.js +2887 -0
  90. package/dist/index.d.ts +24 -62
  91. package/dist/index.js +24 -53
  92. package/dist/json.d.ts +2 -0
  93. package/dist/json.js +20 -0
  94. package/dist/kernel-proxy.d.ts +149 -0
  95. package/dist/kernel-proxy.js +1733 -0
  96. package/dist/native-client.d.ts +41 -0
  97. package/dist/native-client.js +124 -0
  98. package/dist/node-runtime.d.ts +443 -0
  99. package/dist/node-runtime.js +569 -0
  100. package/dist/numbers.d.ts +1 -0
  101. package/dist/numbers.js +8 -0
  102. package/dist/ownership.d.ts +18 -0
  103. package/dist/ownership.js +77 -0
  104. package/dist/permissions.d.ts +29 -0
  105. package/dist/permissions.js +68 -0
  106. package/dist/process.d.ts +35 -0
  107. package/dist/process.js +125 -0
  108. package/dist/protocol-client.d.ts +46 -0
  109. package/dist/protocol-client.js +180 -0
  110. package/dist/protocol-frames.d.ts +68 -0
  111. package/dist/protocol-frames.js +139 -0
  112. package/dist/protocol-maps.d.ts +28 -0
  113. package/dist/protocol-maps.js +217 -0
  114. package/dist/protocol-schema.d.ts +10 -0
  115. package/dist/protocol-schema.js +11 -0
  116. package/dist/request-payloads.d.ts +137 -0
  117. package/dist/request-payloads.js +210 -0
  118. package/dist/response-payloads.d.ts +107 -0
  119. package/dist/response-payloads.js +161 -0
  120. package/dist/sidecar-client.d.ts +242 -0
  121. package/dist/sidecar-client.js +797 -0
  122. package/dist/state.d.ts +40 -0
  123. package/dist/state.js +44 -0
  124. package/dist/test-runtime.d.ts +526 -0
  125. package/dist/test-runtime.js +2119 -0
  126. package/dist/vm-config.d.ts +31 -0
  127. package/dist/vm-config.js +1 -0
  128. package/fixtures/alpine-defaults.json +520 -0
  129. package/fixtures/base-filesystem.json +528 -0
  130. package/package.json +193 -115
  131. package/LICENSE +0 -191
  132. package/dist/bridge-setup.d.ts +0 -6
  133. package/dist/bridge-setup.js +0 -9
  134. package/dist/esm-compiler.d.ts +0 -18
  135. package/dist/esm-compiler.js +0 -72
  136. package/dist/fs-helpers.d.ts +0 -23
  137. package/dist/fs-helpers.js +0 -41
  138. package/dist/generated/isolate-runtime.d.ts +0 -19
  139. package/dist/generated/isolate-runtime.js +0 -21
  140. package/dist/generated/polyfills.d.ts +0 -82
  141. package/dist/generated/polyfills.js +0 -82
  142. package/dist/isolate-runtime/apply-custom-global-policy.js +0 -53
  143. package/dist/isolate-runtime/apply-timing-mitigation-freeze.js +0 -130
  144. package/dist/isolate-runtime/apply-timing-mitigation-off.js +0 -14
  145. package/dist/isolate-runtime/bridge-attach.js +0 -29
  146. package/dist/isolate-runtime/bridge-initial-globals.js +0 -385
  147. package/dist/isolate-runtime/eval-script-result.js +0 -8
  148. package/dist/isolate-runtime/global-exposure-helpers.js +0 -36
  149. package/dist/isolate-runtime/init-commonjs-module-globals.js +0 -28
  150. package/dist/isolate-runtime/override-process-cwd.js +0 -8
  151. package/dist/isolate-runtime/override-process-env.js +0 -8
  152. package/dist/isolate-runtime/require-setup.js +0 -4153
  153. package/dist/isolate-runtime/set-commonjs-file-globals.js +0 -36
  154. package/dist/isolate-runtime/set-stdin-data.js +0 -10
  155. package/dist/isolate-runtime/setup-dynamic-import.js +0 -123
  156. package/dist/isolate-runtime/setup-fs-facade.js +0 -87
  157. package/dist/kernel/command-registry.d.ts +0 -44
  158. package/dist/kernel/command-registry.js +0 -114
  159. package/dist/kernel/device-backend.d.ts +0 -14
  160. package/dist/kernel/device-backend.js +0 -251
  161. package/dist/kernel/device-layer.d.ts +0 -12
  162. package/dist/kernel/device-layer.js +0 -271
  163. package/dist/kernel/dns-cache.d.ts +0 -29
  164. package/dist/kernel/dns-cache.js +0 -52
  165. package/dist/kernel/fd-table.d.ts +0 -84
  166. package/dist/kernel/fd-table.js +0 -278
  167. package/dist/kernel/file-lock.d.ts +0 -34
  168. package/dist/kernel/file-lock.js +0 -122
  169. package/dist/kernel/host-adapter.d.ts +0 -50
  170. package/dist/kernel/host-adapter.js +0 -8
  171. package/dist/kernel/index.d.ts +0 -36
  172. package/dist/kernel/index.js +0 -34
  173. package/dist/kernel/kernel.d.ts +0 -9
  174. package/dist/kernel/kernel.js +0 -1415
  175. package/dist/kernel/mount-table.d.ts +0 -75
  176. package/dist/kernel/mount-table.js +0 -353
  177. package/dist/kernel/permissions.d.ts +0 -36
  178. package/dist/kernel/permissions.js +0 -150
  179. package/dist/kernel/pipe-manager.d.ts +0 -64
  180. package/dist/kernel/pipe-manager.js +0 -267
  181. package/dist/kernel/proc-backend.d.ts +0 -30
  182. package/dist/kernel/proc-backend.js +0 -428
  183. package/dist/kernel/proc-layer.d.ts +0 -11
  184. package/dist/kernel/proc-layer.js +0 -507
  185. package/dist/kernel/process-table.d.ts +0 -126
  186. package/dist/kernel/process-table.js +0 -651
  187. package/dist/kernel/pty.d.ts +0 -109
  188. package/dist/kernel/pty.js +0 -552
  189. package/dist/kernel/socket-table.d.ts +0 -312
  190. package/dist/kernel/socket-table.js +0 -1188
  191. package/dist/kernel/timer-table.d.ts +0 -54
  192. package/dist/kernel/timer-table.js +0 -108
  193. package/dist/kernel/types.d.ts +0 -541
  194. package/dist/kernel/types.js +0 -98
  195. package/dist/kernel/user.d.ts +0 -29
  196. package/dist/kernel/user.js +0 -35
  197. package/dist/kernel/vfs.d.ts +0 -82
  198. package/dist/kernel/vfs.js +0 -25
  199. package/dist/kernel/wait.d.ts +0 -45
  200. package/dist/kernel/wait.js +0 -112
  201. package/dist/kernel/wstatus.d.ts +0 -21
  202. package/dist/kernel/wstatus.js +0 -33
  203. package/dist/module-resolver.d.ts +0 -29
  204. package/dist/module-resolver.js +0 -314
  205. package/dist/package-bundler.d.ts +0 -41
  206. package/dist/package-bundler.js +0 -497
  207. package/dist/runtime-driver.d.ts +0 -66
  208. package/dist/shared/api-types.d.ts +0 -83
  209. package/dist/shared/bridge-contract.d.ts +0 -772
  210. package/dist/shared/bridge-contract.js +0 -169
  211. package/dist/shared/console-formatter.d.ts +0 -22
  212. package/dist/shared/console-formatter.js +0 -161
  213. package/dist/shared/constants.d.ts +0 -3
  214. package/dist/shared/constants.js +0 -3
  215. package/dist/shared/errors.d.ts +0 -16
  216. package/dist/shared/errors.js +0 -21
  217. package/dist/shared/esm-utils.d.ts +0 -28
  218. package/dist/shared/esm-utils.js +0 -97
  219. package/dist/shared/global-exposure.d.ts +0 -38
  220. package/dist/shared/global-exposure.js +0 -876
  221. package/dist/shared/in-memory-fs.d.ts +0 -16
  222. package/dist/shared/in-memory-fs.js +0 -115
  223. package/dist/shared/permissions.d.ts +0 -36
  224. package/dist/shared/permissions.js +0 -314
  225. package/dist/shared/require-setup.d.ts +0 -6
  226. package/dist/shared/require-setup.js +0 -9
  227. package/dist/test/block-store-conformance.d.ts +0 -34
  228. package/dist/test/block-store-conformance.js +0 -251
  229. package/dist/test/metadata-store-conformance.d.ts +0 -37
  230. package/dist/test/metadata-store-conformance.js +0 -646
  231. package/dist/test/vfs-conformance.d.ts +0 -65
  232. package/dist/test/vfs-conformance.js +0 -842
  233. package/dist/types.d.ts +0 -98
  234. package/dist/types.js +0 -6
  235. package/dist/vfs/chunked-vfs.d.ts +0 -66
  236. package/dist/vfs/chunked-vfs.js +0 -1290
  237. package/dist/vfs/host-block-store.d.ts +0 -19
  238. package/dist/vfs/host-block-store.js +0 -97
  239. package/dist/vfs/memory-block-store.d.ts +0 -16
  240. package/dist/vfs/memory-block-store.js +0 -45
  241. package/dist/vfs/memory-metadata.d.ts +0 -75
  242. package/dist/vfs/memory-metadata.js +0 -528
  243. package/dist/vfs/sqlite-metadata.d.ts +0 -91
  244. package/dist/vfs/sqlite-metadata.js +0 -582
  245. package/dist/vfs/types.d.ts +0 -210
  246. package/dist/vfs/types.js +0 -8
  247. /package/dist/{runtime-driver.js → generated/CreateVmConfig.js} +0 -0
  248. /package/dist/{shared/api-types.js → generated/FsPermissionRule.js} +0 -0
@@ -0,0 +1,797 @@
1
+ import { decodeGuestFilesystemContent, encodeGuestFilesystemContent, } from "./filesystem.js";
2
+ import { DEFAULT_SIDECAR_EVENT_BUFFER_CAPACITY, DEFAULT_SIDECAR_FORCE_EXIT_MS, DEFAULT_SIDECAR_FRAME_TIMEOUT_MS, DEFAULT_SIDECAR_GRACEFUL_EXIT_MS, StdioSidecarProtocolClient, } from "./native-client.js";
3
+ import { SIDECAR_PROTOCOL_SCHEMA } from "./protocol-schema.js";
4
+ export { SidecarProcessError, SidecarProcessExited, } from "./process.js";
5
+ export { SidecarEventBufferOverflow } from "./event-buffer.js";
6
+ const BRIDGE_CONTRACT_VERSION = 1;
7
+ export const NATIVE_SIDECAR_FRAME_TIMEOUT_MS = DEFAULT_SIDECAR_FRAME_TIMEOUT_MS;
8
+ export class NativeSidecarProcessClient {
9
+ protocolClient;
10
+ constructor(protocolClient) {
11
+ this.protocolClient = protocolClient;
12
+ }
13
+ static spawn(options) {
14
+ const protocolClient = StdioSidecarProtocolClient.spawn({
15
+ command: options.command,
16
+ args: options.args ?? [],
17
+ cwd: options.cwd,
18
+ frameTimeoutMs: options.frameTimeoutMs ?? NATIVE_SIDECAR_FRAME_TIMEOUT_MS,
19
+ eventBufferCapacity: options.eventBufferCapacity ?? DEFAULT_SIDECAR_EVENT_BUFFER_CAPACITY,
20
+ gracefulExitMs: DEFAULT_SIDECAR_GRACEFUL_EXIT_MS,
21
+ forceExitMs: DEFAULT_SIDECAR_FORCE_EXIT_MS,
22
+ disposedErrorMessage: "native sidecar disposed",
23
+ payloadCodec: options.payloadCodec ?? "bare",
24
+ });
25
+ return new NativeSidecarProcessClient(protocolClient);
26
+ }
27
+ setSidecarRequestHandler(handler) {
28
+ this.protocolClient.setSidecarRequestHandler(handler);
29
+ }
30
+ onEvent(handler) {
31
+ return this.protocolClient.onEvent(handler);
32
+ }
33
+ async authenticateAndOpenSession(sessionMetadata = {}) {
34
+ const authenticated = await this.sendRequest({
35
+ ownership: {
36
+ scope: "connection",
37
+ connection_id: "client-hint",
38
+ },
39
+ payload: {
40
+ type: "authenticate",
41
+ client_name: "secure-exec-core-client",
42
+ auth_token: "secure-exec-core-client-token",
43
+ protocol_version: SIDECAR_PROTOCOL_SCHEMA.version,
44
+ bridge_version: BRIDGE_CONTRACT_VERSION,
45
+ },
46
+ });
47
+ if (authenticated.payload.type !== "authenticated") {
48
+ throw new Error(`unexpected authenticate response: ${authenticated.payload.type}`);
49
+ }
50
+ const opened = await this.sendRequest({
51
+ ownership: {
52
+ scope: "connection",
53
+ connection_id: authenticated.payload.connection_id,
54
+ },
55
+ payload: {
56
+ type: "open_session",
57
+ placement: {
58
+ kind: "shared",
59
+ pool: null,
60
+ },
61
+ metadata: sessionMetadata,
62
+ },
63
+ });
64
+ if (opened.payload.type !== "session_opened") {
65
+ throw new Error(`unexpected open_session response: ${opened.payload.type}`);
66
+ }
67
+ return {
68
+ connectionId: authenticated.payload.connection_id,
69
+ sessionId: opened.payload.session_id,
70
+ };
71
+ }
72
+ async createVm(session, options) {
73
+ const response = await this.sendRequest({
74
+ ownership: {
75
+ scope: "session",
76
+ connection_id: session.connectionId,
77
+ session_id: session.sessionId,
78
+ },
79
+ payload: {
80
+ type: "create_vm",
81
+ runtime: options.runtime,
82
+ config: options.config,
83
+ },
84
+ });
85
+ if (response.payload.type !== "vm_created") {
86
+ throw new Error(`unexpected create_vm response: ${response.payload.type}`);
87
+ }
88
+ return {
89
+ vmId: response.payload.vm_id,
90
+ };
91
+ }
92
+ async extensionRequest(session, vm, envelope) {
93
+ const response = await this.sendRequest({
94
+ ownership: {
95
+ scope: "vm",
96
+ connection_id: session.connectionId,
97
+ session_id: session.sessionId,
98
+ vm_id: vm.vmId,
99
+ },
100
+ payload: {
101
+ type: "ext",
102
+ envelope,
103
+ },
104
+ });
105
+ if (response.payload.type !== "ext_result") {
106
+ throw new Error(`unexpected ext response: ${response.payload.type}`);
107
+ }
108
+ return response.payload.envelope;
109
+ }
110
+ async configureVm(session, vm, options) {
111
+ const response = await this.sendRequest({
112
+ ownership: {
113
+ scope: "vm",
114
+ connection_id: session.connectionId,
115
+ session_id: session.sessionId,
116
+ vm_id: vm.vmId,
117
+ },
118
+ payload: {
119
+ type: "configure_vm",
120
+ mounts: (options.mounts ?? []).map(toWireMountDescriptor),
121
+ software: (options.software ?? []).map(toWireSoftwareDescriptor),
122
+ permissions: toWirePermissionsPolicy(options.permissions),
123
+ module_access_cwd: options.moduleAccessCwd,
124
+ instructions: options.instructions ?? [],
125
+ projected_modules: (options.projectedModules ?? []).map(toWireProjectedModuleDescriptor),
126
+ command_permissions: options.commandPermissions ?? {},
127
+ ...(options.loopbackExemptPorts
128
+ ? { loopback_exempt_ports: options.loopbackExemptPorts }
129
+ : {}),
130
+ },
131
+ });
132
+ if (response.payload.type !== "vm_configured") {
133
+ throw new Error(`unexpected configure_vm response: ${response.payload.type}`);
134
+ }
135
+ }
136
+ async registerHostCallbacks(session, vm, registration) {
137
+ const response = await this.sendRequest({
138
+ ownership: {
139
+ scope: "vm",
140
+ connection_id: session.connectionId,
141
+ session_id: session.sessionId,
142
+ vm_id: vm.vmId,
143
+ },
144
+ payload: {
145
+ type: "register_host_callbacks",
146
+ name: registration.name,
147
+ description: registration.description,
148
+ command_aliases: registration.commandAliases ?? [],
149
+ registry_command_aliases: registration.registryCommandAliases ?? [],
150
+ callbacks: Object.fromEntries(Object.entries(registration.callbacks).map(([callbackName, callback]) => [
151
+ callbackName,
152
+ {
153
+ description: callback.description,
154
+ input_schema: callback.inputSchema,
155
+ ...(callback.timeoutMs !== undefined
156
+ ? { timeout_ms: callback.timeoutMs }
157
+ : {}),
158
+ ...(callback.examples && callback.examples.length > 0
159
+ ? {
160
+ examples: callback.examples.map((example) => ({
161
+ description: example.description,
162
+ input: example.input,
163
+ })),
164
+ }
165
+ : {}),
166
+ },
167
+ ])),
168
+ },
169
+ });
170
+ if (response.payload.type !== "host_callbacks_registered") {
171
+ throw new Error(`unexpected register_host_callbacks response: ${response.payload.type}`);
172
+ }
173
+ return {
174
+ registration: response.payload.registration,
175
+ commandCount: response.payload.command_count,
176
+ };
177
+ }
178
+ async createLayer(session, vm) {
179
+ const response = await this.sendRequest({
180
+ ownership: {
181
+ scope: "vm",
182
+ connection_id: session.connectionId,
183
+ session_id: session.sessionId,
184
+ vm_id: vm.vmId,
185
+ },
186
+ payload: {
187
+ type: "create_layer",
188
+ },
189
+ });
190
+ if (response.payload.type !== "layer_created") {
191
+ throw new Error(`unexpected create_layer response: ${response.payload.type}`);
192
+ }
193
+ return response.payload.layer_id;
194
+ }
195
+ async sealLayer(session, vm, layerId) {
196
+ const response = await this.sendRequest({
197
+ ownership: {
198
+ scope: "vm",
199
+ connection_id: session.connectionId,
200
+ session_id: session.sessionId,
201
+ vm_id: vm.vmId,
202
+ },
203
+ payload: {
204
+ type: "seal_layer",
205
+ layer_id: layerId,
206
+ },
207
+ });
208
+ if (response.payload.type !== "layer_sealed") {
209
+ throw new Error(`unexpected seal_layer response: ${response.payload.type}`);
210
+ }
211
+ return response.payload.layer_id;
212
+ }
213
+ async importSnapshot(session, vm, entries) {
214
+ const response = await this.sendRequest({
215
+ ownership: {
216
+ scope: "vm",
217
+ connection_id: session.connectionId,
218
+ session_id: session.sessionId,
219
+ vm_id: vm.vmId,
220
+ },
221
+ payload: {
222
+ type: "import_snapshot",
223
+ entries,
224
+ },
225
+ });
226
+ if (response.payload.type !== "snapshot_imported") {
227
+ throw new Error(`unexpected import_snapshot response: ${response.payload.type}`);
228
+ }
229
+ return response.payload.layer_id;
230
+ }
231
+ async exportSnapshot(session, vm, layerId) {
232
+ const response = await this.sendRequest({
233
+ ownership: {
234
+ scope: "vm",
235
+ connection_id: session.connectionId,
236
+ session_id: session.sessionId,
237
+ vm_id: vm.vmId,
238
+ },
239
+ payload: {
240
+ type: "export_snapshot",
241
+ layer_id: layerId,
242
+ },
243
+ });
244
+ if (response.payload.type !== "snapshot_exported") {
245
+ throw new Error(`unexpected export_snapshot response: ${response.payload.type}`);
246
+ }
247
+ return response.payload.entries;
248
+ }
249
+ async createOverlay(session, vm, options) {
250
+ const response = await this.sendRequest({
251
+ ownership: {
252
+ scope: "vm",
253
+ connection_id: session.connectionId,
254
+ session_id: session.sessionId,
255
+ vm_id: vm.vmId,
256
+ },
257
+ payload: {
258
+ type: "create_overlay",
259
+ mode: options.mode,
260
+ upper_layer_id: options.upperLayerId,
261
+ lower_layer_ids: options.lowerLayerIds,
262
+ },
263
+ });
264
+ if (response.payload.type !== "overlay_created") {
265
+ throw new Error(`unexpected create_overlay response: ${response.payload.type}`);
266
+ }
267
+ return response.payload.layer_id;
268
+ }
269
+ async bootstrapRootFilesystem(session, vm, entries) {
270
+ const response = await this.sendRequest({
271
+ ownership: {
272
+ scope: "vm",
273
+ connection_id: session.connectionId,
274
+ session_id: session.sessionId,
275
+ vm_id: vm.vmId,
276
+ },
277
+ payload: {
278
+ type: "bootstrap_root_filesystem",
279
+ entries,
280
+ },
281
+ });
282
+ if (response.payload.type !== "root_filesystem_bootstrapped") {
283
+ throw new Error(`unexpected bootstrap_root_filesystem response: ${response.payload.type}`);
284
+ }
285
+ }
286
+ async snapshotRootFilesystem(session, vm) {
287
+ const response = await this.sendRequest({
288
+ ownership: {
289
+ scope: "vm",
290
+ connection_id: session.connectionId,
291
+ session_id: session.sessionId,
292
+ vm_id: vm.vmId,
293
+ },
294
+ payload: {
295
+ type: "snapshot_root_filesystem",
296
+ },
297
+ });
298
+ if (response.payload.type !== "root_filesystem_snapshot") {
299
+ throw new Error(`unexpected snapshot_root_filesystem response: ${response.payload.type}`);
300
+ }
301
+ return response.payload.entries;
302
+ }
303
+ async readFile(session, vm, path) {
304
+ const response = await this.guestFilesystemCall(session, vm, {
305
+ operation: "read_file",
306
+ path,
307
+ });
308
+ return decodeGuestFilesystemContent(response);
309
+ }
310
+ async pread(session, vm, path, offset, length) {
311
+ const response = await this.guestFilesystemCall(session, vm, {
312
+ operation: "pread",
313
+ path,
314
+ offset,
315
+ len: length,
316
+ });
317
+ return decodeGuestFilesystemContent(response);
318
+ }
319
+ async writeFile(session, vm, path, content) {
320
+ const encoded = encodeGuestFilesystemContent(content);
321
+ await this.guestFilesystemCall(session, vm, {
322
+ operation: "write_file",
323
+ path,
324
+ content: encoded.content,
325
+ encoding: encoded.encoding,
326
+ });
327
+ }
328
+ async mkdir(session, vm, path, options) {
329
+ await this.guestFilesystemCall(session, vm, {
330
+ operation: options?.recursive ? "mkdir" : "create_dir",
331
+ path,
332
+ recursive: options?.recursive ?? false,
333
+ });
334
+ }
335
+ async readdir(session, vm, path) {
336
+ const response = await this.guestFilesystemCall(session, vm, {
337
+ operation: "read_dir",
338
+ path,
339
+ });
340
+ return response.entries ?? [];
341
+ }
342
+ async exists(session, vm, path) {
343
+ const response = await this.guestFilesystemCall(session, vm, {
344
+ operation: "exists",
345
+ path,
346
+ });
347
+ return response.exists ?? false;
348
+ }
349
+ async stat(session, vm, path, options) {
350
+ const response = await this.guestFilesystemCall(session, vm, {
351
+ operation: options?.dereference === false ? "lstat" : "stat",
352
+ path,
353
+ });
354
+ if (!response.stat) {
355
+ throw new Error(`sidecar returned no stat payload for ${path}`);
356
+ }
357
+ return response.stat;
358
+ }
359
+ async lstat(session, vm, path) {
360
+ return this.stat(session, vm, path, { dereference: false });
361
+ }
362
+ async rename(session, vm, fromPath, toPath) {
363
+ await this.guestFilesystemCall(session, vm, {
364
+ operation: "rename",
365
+ path: fromPath,
366
+ destination_path: toPath,
367
+ });
368
+ }
369
+ async realpath(session, vm, path) {
370
+ const response = await this.guestFilesystemCall(session, vm, {
371
+ operation: "realpath",
372
+ path,
373
+ });
374
+ if (response.target === undefined) {
375
+ throw new Error(`sidecar returned no realpath payload for ${path}`);
376
+ }
377
+ return response.target;
378
+ }
379
+ async removeFile(session, vm, path) {
380
+ await this.guestFilesystemCall(session, vm, {
381
+ operation: "remove_file",
382
+ path,
383
+ });
384
+ }
385
+ async removeDir(session, vm, path) {
386
+ await this.guestFilesystemCall(session, vm, {
387
+ operation: "remove_dir",
388
+ path,
389
+ });
390
+ }
391
+ async symlink(session, vm, target, linkPath) {
392
+ await this.guestFilesystemCall(session, vm, {
393
+ operation: "symlink",
394
+ path: linkPath,
395
+ target,
396
+ });
397
+ }
398
+ async readLink(session, vm, path) {
399
+ const response = await this.guestFilesystemCall(session, vm, {
400
+ operation: "read_link",
401
+ path,
402
+ });
403
+ if (response.target === undefined) {
404
+ throw new Error(`sidecar returned no symlink target for ${path}`);
405
+ }
406
+ return response.target;
407
+ }
408
+ async link(session, vm, fromPath, toPath) {
409
+ await this.guestFilesystemCall(session, vm, {
410
+ operation: "link",
411
+ path: fromPath,
412
+ destination_path: toPath,
413
+ });
414
+ }
415
+ async chmod(session, vm, path, mode) {
416
+ await this.guestFilesystemCall(session, vm, {
417
+ operation: "chmod",
418
+ path,
419
+ mode,
420
+ });
421
+ }
422
+ async chown(session, vm, path, uid, gid) {
423
+ await this.guestFilesystemCall(session, vm, {
424
+ operation: "chown",
425
+ path,
426
+ uid,
427
+ gid,
428
+ });
429
+ }
430
+ async utimes(session, vm, path, atimeMs, mtimeMs) {
431
+ await this.guestFilesystemCall(session, vm, {
432
+ operation: "utimes",
433
+ path,
434
+ atime_ms: atimeMs,
435
+ mtime_ms: mtimeMs,
436
+ });
437
+ }
438
+ async truncate(session, vm, path, length) {
439
+ await this.guestFilesystemCall(session, vm, {
440
+ operation: "truncate",
441
+ path,
442
+ len: length,
443
+ });
444
+ }
445
+ async disposeVm(session, vm) {
446
+ const response = await this.sendRequest({
447
+ ownership: {
448
+ scope: "vm",
449
+ connection_id: session.connectionId,
450
+ session_id: session.sessionId,
451
+ vm_id: vm.vmId,
452
+ },
453
+ payload: {
454
+ type: "dispose_vm",
455
+ reason: "requested",
456
+ },
457
+ });
458
+ if (response.payload.type !== "vm_disposed") {
459
+ throw new Error(`unexpected dispose_vm response: ${response.payload.type}`);
460
+ }
461
+ }
462
+ async execute(session, vm, options) {
463
+ const response = await this.sendRequest({
464
+ ownership: {
465
+ scope: "vm",
466
+ connection_id: session.connectionId,
467
+ session_id: session.sessionId,
468
+ vm_id: vm.vmId,
469
+ },
470
+ payload: {
471
+ type: "execute",
472
+ process_id: options.processId,
473
+ args: options.args ?? [],
474
+ ...(options.command ? { command: options.command } : {}),
475
+ ...(options.runtime ? { runtime: options.runtime } : {}),
476
+ ...(options.entrypoint ? { entrypoint: options.entrypoint } : {}),
477
+ ...(options.env ? { env: options.env } : {}),
478
+ ...(options.cwd ? { cwd: options.cwd } : {}),
479
+ ...(options.wasmPermissionTier
480
+ ? { wasm_permission_tier: options.wasmPermissionTier }
481
+ : {}),
482
+ },
483
+ });
484
+ if (response.payload.type !== "process_started") {
485
+ throw new Error(`unexpected execute response: ${response.payload.type}`);
486
+ }
487
+ return {
488
+ pid: response.payload.pid ?? null,
489
+ };
490
+ }
491
+ async writeStdin(session, vm, processId, chunk) {
492
+ const response = await this.sendRequest({
493
+ ownership: {
494
+ scope: "vm",
495
+ connection_id: session.connectionId,
496
+ session_id: session.sessionId,
497
+ vm_id: vm.vmId,
498
+ },
499
+ payload: {
500
+ type: "write_stdin",
501
+ process_id: processId,
502
+ chunk: typeof chunk === "string" ? Buffer.from(chunk, "utf8") : chunk,
503
+ },
504
+ });
505
+ if (response.payload.type !== "stdin_written") {
506
+ throw new Error(`unexpected write_stdin response: ${response.payload.type}`);
507
+ }
508
+ }
509
+ async closeStdin(session, vm, processId) {
510
+ const response = await this.sendRequest({
511
+ ownership: {
512
+ scope: "vm",
513
+ connection_id: session.connectionId,
514
+ session_id: session.sessionId,
515
+ vm_id: vm.vmId,
516
+ },
517
+ payload: {
518
+ type: "close_stdin",
519
+ process_id: processId,
520
+ },
521
+ });
522
+ if (response.payload.type !== "stdin_closed") {
523
+ throw new Error(`unexpected close_stdin response: ${response.payload.type}`);
524
+ }
525
+ }
526
+ async killProcess(session, vm, processId, signal = "SIGTERM") {
527
+ const response = await this.sendRequest({
528
+ ownership: {
529
+ scope: "vm",
530
+ connection_id: session.connectionId,
531
+ session_id: session.sessionId,
532
+ vm_id: vm.vmId,
533
+ },
534
+ payload: {
535
+ type: "kill_process",
536
+ process_id: processId,
537
+ signal,
538
+ },
539
+ });
540
+ if (response.payload.type !== "process_killed") {
541
+ throw new Error(`unexpected kill_process response: ${response.payload.type}`);
542
+ }
543
+ }
544
+ async findListener(session, vm, request) {
545
+ const response = await this.sendRequest({
546
+ ownership: {
547
+ scope: "vm",
548
+ connection_id: session.connectionId,
549
+ session_id: session.sessionId,
550
+ vm_id: vm.vmId,
551
+ },
552
+ payload: {
553
+ type: "find_listener",
554
+ ...(request.host !== undefined ? { host: request.host } : {}),
555
+ ...(request.port !== undefined ? { port: request.port } : {}),
556
+ ...(request.path !== undefined ? { path: request.path } : {}),
557
+ },
558
+ });
559
+ if (response.payload.type !== "listener_snapshot") {
560
+ throw new Error(`unexpected find_listener response: ${response.payload.type}`);
561
+ }
562
+ return response.payload.listener
563
+ ? toSidecarSocketStateEntry(response.payload.listener)
564
+ : null;
565
+ }
566
+ async getProcessSnapshot(session, vm) {
567
+ const response = await this.sendRequest({
568
+ ownership: {
569
+ scope: "vm",
570
+ connection_id: session.connectionId,
571
+ session_id: session.sessionId,
572
+ vm_id: vm.vmId,
573
+ },
574
+ payload: {
575
+ type: "get_process_snapshot",
576
+ },
577
+ });
578
+ if (response.payload.type !== "process_snapshot") {
579
+ throw new Error(`unexpected get_process_snapshot response: ${response.payload.type}`);
580
+ }
581
+ return response.payload.processes.map(toSidecarProcessSnapshotEntry);
582
+ }
583
+ async findBoundUdp(session, vm, request) {
584
+ const response = await this.sendRequest({
585
+ ownership: {
586
+ scope: "vm",
587
+ connection_id: session.connectionId,
588
+ session_id: session.sessionId,
589
+ vm_id: vm.vmId,
590
+ },
591
+ payload: {
592
+ type: "find_bound_udp",
593
+ ...(request.host !== undefined ? { host: request.host } : {}),
594
+ ...(request.port !== undefined ? { port: request.port } : {}),
595
+ },
596
+ });
597
+ if (response.payload.type !== "bound_udp_snapshot") {
598
+ throw new Error(`unexpected find_bound_udp response: ${response.payload.type}`);
599
+ }
600
+ return response.payload.socket
601
+ ? toSidecarSocketStateEntry(response.payload.socket)
602
+ : null;
603
+ }
604
+ async vmFetch(session, vm, request) {
605
+ const response = await this.sendRequest({
606
+ ownership: {
607
+ scope: "vm",
608
+ connection_id: session.connectionId,
609
+ session_id: session.sessionId,
610
+ vm_id: vm.vmId,
611
+ },
612
+ payload: {
613
+ type: "vm_fetch",
614
+ port: request.port,
615
+ method: request.method,
616
+ path: request.path,
617
+ headers_json: request.headersJson,
618
+ ...(request.body !== undefined ? { body: request.body } : {}),
619
+ },
620
+ });
621
+ if (response.payload.type !== "vm_fetch_result") {
622
+ throw new Error(`unexpected vm_fetch response: ${response.payload.type}`);
623
+ }
624
+ return response.payload.response_json;
625
+ }
626
+ async getSignalState(session, vm, processId) {
627
+ const response = await this.sendRequest({
628
+ ownership: {
629
+ scope: "vm",
630
+ connection_id: session.connectionId,
631
+ session_id: session.sessionId,
632
+ vm_id: vm.vmId,
633
+ },
634
+ payload: {
635
+ type: "get_signal_state",
636
+ process_id: processId,
637
+ },
638
+ });
639
+ if (response.payload.type !== "signal_state") {
640
+ throw new Error(`unexpected get_signal_state response: ${response.payload.type}`);
641
+ }
642
+ return {
643
+ processId: response.payload.process_id,
644
+ handlers: new Map(Object.entries(response.payload.handlers).map(([signal, registration]) => [
645
+ Number(signal),
646
+ {
647
+ action: registration.action,
648
+ mask: [...registration.mask],
649
+ flags: registration.flags,
650
+ },
651
+ ])),
652
+ };
653
+ }
654
+ async getZombieTimerCount(session, vm) {
655
+ const response = await this.sendRequest({
656
+ ownership: {
657
+ scope: "vm",
658
+ connection_id: session.connectionId,
659
+ session_id: session.sessionId,
660
+ vm_id: vm.vmId,
661
+ },
662
+ payload: {
663
+ type: "get_zombie_timer_count",
664
+ },
665
+ });
666
+ if (response.payload.type !== "zombie_timer_count") {
667
+ throw new Error(`unexpected get_zombie_timer_count response: ${response.payload.type}`);
668
+ }
669
+ return {
670
+ count: response.payload.count,
671
+ };
672
+ }
673
+ async waitForEvent(matcher, timeoutMs, options) {
674
+ return await this.protocolClient.waitForEvent(matcher, timeoutMs, options);
675
+ }
676
+ async dispose() {
677
+ await this.protocolClient.dispose();
678
+ }
679
+ async sendRequest(input) {
680
+ return await this.protocolClient.sendRequest(input);
681
+ }
682
+ async guestFilesystemCall(session, vm, payload) {
683
+ const response = await this.sendRequest({
684
+ ownership: {
685
+ scope: "vm",
686
+ connection_id: session.connectionId,
687
+ session_id: session.sessionId,
688
+ vm_id: vm.vmId,
689
+ },
690
+ payload: {
691
+ type: "guest_filesystem_call",
692
+ ...payload,
693
+ },
694
+ });
695
+ if (response.payload.type !== "guest_filesystem_result") {
696
+ throw new Error(`unexpected guest_filesystem_call response: ${response.payload.type}`);
697
+ }
698
+ return response.payload;
699
+ }
700
+ }
701
+ function toSidecarSocketStateEntry(entry) {
702
+ return {
703
+ processId: entry.process_id,
704
+ ...(entry.host !== undefined ? { host: entry.host } : {}),
705
+ ...(entry.port !== undefined ? { port: entry.port } : {}),
706
+ ...(entry.path !== undefined ? { path: entry.path } : {}),
707
+ };
708
+ }
709
+ function toSidecarProcessSnapshotEntry(entry) {
710
+ return {
711
+ processId: entry.process_id,
712
+ pid: entry.pid,
713
+ ppid: entry.ppid,
714
+ pgid: entry.pgid,
715
+ sid: entry.sid,
716
+ driver: entry.driver,
717
+ command: entry.command,
718
+ args: [...(entry.args ?? [])],
719
+ cwd: entry.cwd,
720
+ status: entry.status,
721
+ exitCode: entry.exit_code ?? null,
722
+ };
723
+ }
724
+ function toWireRootFilesystemDescriptor(descriptor) {
725
+ if (!descriptor) {
726
+ return {};
727
+ }
728
+ return {
729
+ ...(descriptor.mode ? { mode: descriptor.mode } : {}),
730
+ ...(descriptor.disableDefaultBaseLayer !== undefined
731
+ ? { disable_default_base_layer: descriptor.disableDefaultBaseLayer }
732
+ : {}),
733
+ ...(descriptor.lowers
734
+ ? {
735
+ lowers: descriptor.lowers.map((lower) => lower.kind === "bundled_base_filesystem"
736
+ ? { kind: "bundled_base_filesystem" }
737
+ : {
738
+ kind: "snapshot",
739
+ entries: (lower.entries ?? []).map(toWireRootFilesystemEntry),
740
+ }),
741
+ }
742
+ : {}),
743
+ ...(descriptor.bootstrapEntries
744
+ ? {
745
+ bootstrap_entries: descriptor.bootstrapEntries.map(toWireRootFilesystemEntry),
746
+ }
747
+ : {}),
748
+ };
749
+ }
750
+ function toWireRootFilesystemEntry(entry) {
751
+ return {
752
+ path: entry.path,
753
+ kind: entry.kind,
754
+ ...(entry.mode !== undefined ? { mode: entry.mode } : {}),
755
+ ...(entry.uid !== undefined ? { uid: entry.uid } : {}),
756
+ ...(entry.gid !== undefined ? { gid: entry.gid } : {}),
757
+ ...(entry.content !== undefined ? { content: entry.content } : {}),
758
+ ...(entry.encoding !== undefined ? { encoding: entry.encoding } : {}),
759
+ ...(entry.target !== undefined ? { target: entry.target } : {}),
760
+ ...(entry.executable !== undefined ? { executable: entry.executable } : {}),
761
+ };
762
+ }
763
+ function toWireMountDescriptor(descriptor) {
764
+ return {
765
+ guest_path: descriptor.guestPath,
766
+ read_only: descriptor.readOnly,
767
+ plugin: {
768
+ id: descriptor.plugin.id,
769
+ config: descriptor.plugin.config ?? {},
770
+ },
771
+ };
772
+ }
773
+ function toWireSoftwareDescriptor(descriptor) {
774
+ return {
775
+ package_name: descriptor.packageName,
776
+ root: descriptor.root,
777
+ };
778
+ }
779
+ function toWirePermissionsPolicy(policy) {
780
+ if (!policy) {
781
+ return undefined;
782
+ }
783
+ return {
784
+ fs: policy.fs,
785
+ network: policy.network,
786
+ child_process: policy.childProcess,
787
+ process: policy.process,
788
+ env: policy.env,
789
+ tool: policy.tool,
790
+ };
791
+ }
792
+ function toWireProjectedModuleDescriptor(descriptor) {
793
+ return {
794
+ package_name: descriptor.packageName,
795
+ entrypoint: descriptor.entrypoint,
796
+ };
797
+ }