@finalai/agent-provider 0.1.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.

Potentially problematic release.


This version of @finalai/agent-provider might be problematic. Click here for more details.

Files changed (176) hide show
  1. package/README.md +12 -0
  2. package/dist/modules/channel-context.d.mts +102 -0
  3. package/dist/modules/channel-context.mjs +52 -0
  4. package/dist/modules/channel-context.mjs.map +7 -0
  5. package/dist/modules/channel-socket.d.mts +65 -0
  6. package/dist/modules/channel-socket.mjs +188 -0
  7. package/dist/modules/channel-socket.mjs.map +7 -0
  8. package/dist/modules/channel.d.mts +382 -0
  9. package/dist/modules/channel.mjs +146 -0
  10. package/dist/modules/channel.mjs.map +7 -0
  11. package/dist/modules/conformance/agent.d.mts +20 -0
  12. package/dist/modules/conformance/agent.mjs +623 -0
  13. package/dist/modules/conformance/agent.mjs.map +7 -0
  14. package/dist/modules/conformance/fixtures.d.mts +41 -0
  15. package/dist/modules/conformance/fixtures.mjs +190 -0
  16. package/dist/modules/conformance/fixtures.mjs.map +7 -0
  17. package/dist/modules/conformance/harness-kit.d.mts +82 -0
  18. package/dist/modules/conformance/harness-kit.mjs +1303 -0
  19. package/dist/modules/conformance/harness-kit.mjs.map +7 -0
  20. package/dist/modules/conformance/image.d.mts +2 -0
  21. package/dist/modules/conformance/image.mjs +79 -0
  22. package/dist/modules/conformance/image.mjs.map +7 -0
  23. package/dist/modules/conformance/index.d.mts +8 -0
  24. package/dist/modules/conformance/index.mjs +12 -0
  25. package/dist/modules/conformance/index.mjs.map +7 -0
  26. package/dist/modules/conformance/local-harness.d.mts +25 -0
  27. package/dist/modules/conformance/local-harness.mjs +108 -0
  28. package/dist/modules/conformance/local-harness.mjs.map +7 -0
  29. package/dist/modules/conformance/protocol.d.mts +30 -0
  30. package/dist/modules/conformance/protocol.mjs +56 -0
  31. package/dist/modules/conformance/protocol.mjs.map +7 -0
  32. package/dist/modules/conformance/sandbox-kit.d.mts +19 -0
  33. package/dist/modules/conformance/sandbox-kit.mjs +320 -0
  34. package/dist/modules/conformance/sandbox-kit.mjs.map +7 -0
  35. package/dist/modules/conformance/scripted-model/chat-completions.d.mts +30 -0
  36. package/dist/modules/conformance/scripted-model/chat-completions.mjs +125 -0
  37. package/dist/modules/conformance/scripted-model/chat-completions.mjs.map +7 -0
  38. package/dist/modules/conformance/scripted-model/directives.d.mts +84 -0
  39. package/dist/modules/conformance/scripted-model/directives.mjs +304 -0
  40. package/dist/modules/conformance/scripted-model/directives.mjs.map +7 -0
  41. package/dist/modules/conformance/scripted-model/handler.d.mts +14 -0
  42. package/dist/modules/conformance/scripted-model/handler.mjs +133 -0
  43. package/dist/modules/conformance/scripted-model/handler.mjs.map +7 -0
  44. package/dist/modules/conformance/scripted-model/index.d.mts +6 -0
  45. package/dist/modules/conformance/scripted-model/index.mjs +7 -0
  46. package/dist/modules/conformance/scripted-model/index.mjs.map +7 -0
  47. package/dist/modules/conformance/scripted-model/messages.d.mts +39 -0
  48. package/dist/modules/conformance/scripted-model/messages.mjs +139 -0
  49. package/dist/modules/conformance/scripted-model/messages.mjs.map +7 -0
  50. package/dist/modules/conformance/scripted-model/responses.d.mts +62 -0
  51. package/dist/modules/conformance/scripted-model/responses.mjs +273 -0
  52. package/dist/modules/conformance/scripted-model/responses.mjs.map +7 -0
  53. package/dist/modules/conformance/scripted-model/sse.d.mts +15 -0
  54. package/dist/modules/conformance/scripted-model/sse.mjs +75 -0
  55. package/dist/modules/conformance/scripted-model/sse.mjs.map +7 -0
  56. package/dist/modules/conformance/v1-agent.d.mts +24 -0
  57. package/dist/modules/conformance/v1-agent.mjs +40 -0
  58. package/dist/modules/conformance/v1-agent.mjs.map +7 -0
  59. package/dist/modules/credential-routes.d.mts +24 -0
  60. package/dist/modules/credential-routes.mjs +25 -0
  61. package/dist/modules/credential-routes.mjs.map +7 -0
  62. package/dist/modules/credentials.d.mts +206 -0
  63. package/dist/modules/credentials.mjs +207 -0
  64. package/dist/modules/credentials.mjs.map +7 -0
  65. package/dist/modules/dynamic.d.mts +32 -0
  66. package/dist/modules/dynamic.mjs +77 -0
  67. package/dist/modules/dynamic.mjs.map +7 -0
  68. package/dist/modules/harness.d.mts +397 -0
  69. package/dist/modules/harness.mjs +213 -0
  70. package/dist/modules/harness.mjs.map +7 -0
  71. package/dist/modules/index.d.mts +15 -0
  72. package/dist/modules/index.mjs +40 -0
  73. package/dist/modules/index.mjs.map +7 -0
  74. package/dist/modules/json.d.mts +12 -0
  75. package/dist/modules/json.mjs +19 -0
  76. package/dist/modules/json.mjs.map +7 -0
  77. package/dist/modules/local-channel-socket.d.mts +23 -0
  78. package/dist/modules/local-channel-socket.mjs +141 -0
  79. package/dist/modules/local-channel-socket.mjs.map +7 -0
  80. package/dist/modules/manifest.d.mts +558 -0
  81. package/dist/modules/manifest.mjs +266 -0
  82. package/dist/modules/manifest.mjs.map +7 -0
  83. package/dist/modules/mcp-content.d.mts +21 -0
  84. package/dist/modules/mcp-content.mjs +86 -0
  85. package/dist/modules/mcp-content.mjs.map +7 -0
  86. package/dist/modules/provider-ref.d.mts +29 -0
  87. package/dist/modules/provider-ref.mjs +55 -0
  88. package/dist/modules/provider-ref.mjs.map +7 -0
  89. package/dist/modules/sandbox/bytes.d.mts +9 -0
  90. package/dist/modules/sandbox/bytes.mjs +154 -0
  91. package/dist/modules/sandbox/bytes.mjs.map +7 -0
  92. package/dist/modules/sandbox/client.d.mts +51 -0
  93. package/dist/modules/sandbox/client.mjs +500 -0
  94. package/dist/modules/sandbox/client.mjs.map +7 -0
  95. package/dist/modules/sandbox/confined-files.d.mts +22 -0
  96. package/dist/modules/sandbox/confined-files.mjs +142 -0
  97. package/dist/modules/sandbox/confined-files.mjs.map +7 -0
  98. package/dist/modules/sandbox/convenience.d.mts +10 -0
  99. package/dist/modules/sandbox/convenience.mjs +116 -0
  100. package/dist/modules/sandbox/convenience.mjs.map +7 -0
  101. package/dist/modules/sandbox/editor.d.mts +49 -0
  102. package/dist/modules/sandbox/editor.mjs +43 -0
  103. package/dist/modules/sandbox/editor.mjs.map +7 -0
  104. package/dist/modules/sandbox/frame-channel.d.mts +47 -0
  105. package/dist/modules/sandbox/frame-channel.mjs +153 -0
  106. package/dist/modules/sandbox/frame-channel.mjs.map +7 -0
  107. package/dist/modules/sandbox/index.d.mts +18 -0
  108. package/dist/modules/sandbox/index.mjs +70 -0
  109. package/dist/modules/sandbox/index.mjs.map +7 -0
  110. package/dist/modules/sandbox/mcp-channel.d.mts +9 -0
  111. package/dist/modules/sandbox/mcp-channel.mjs +77 -0
  112. package/dist/modules/sandbox/mcp-channel.mjs.map +7 -0
  113. package/dist/modules/sandbox/mcp-hosted.d.mts +46 -0
  114. package/dist/modules/sandbox/mcp-hosted.mjs +221 -0
  115. package/dist/modules/sandbox/mcp-hosted.mjs.map +7 -0
  116. package/dist/modules/sandbox/mcp-search.d.mts +51 -0
  117. package/dist/modules/sandbox/mcp-search.mjs +129 -0
  118. package/dist/modules/sandbox/mcp-search.mjs.map +7 -0
  119. package/dist/modules/sandbox/mcp-shell.d.mts +21 -0
  120. package/dist/modules/sandbox/mcp-shell.mjs +205 -0
  121. package/dist/modules/sandbox/mcp-shell.mjs.map +7 -0
  122. package/dist/modules/sandbox/mcp-testing.d.mts +11 -0
  123. package/dist/modules/sandbox/mcp-testing.mjs +33 -0
  124. package/dist/modules/sandbox/mcp-testing.mjs.map +7 -0
  125. package/dist/modules/sandbox/mcp.d.mts +83 -0
  126. package/dist/modules/sandbox/mcp.mjs +971 -0
  127. package/dist/modules/sandbox/mcp.mjs.map +7 -0
  128. package/dist/modules/sandbox/memory-sandbox.d.mts +32 -0
  129. package/dist/modules/sandbox/memory-sandbox.mjs +416 -0
  130. package/dist/modules/sandbox/memory-sandbox.mjs.map +7 -0
  131. package/dist/modules/sandbox/memory-shell.d.mts +29 -0
  132. package/dist/modules/sandbox/memory-shell.mjs +278 -0
  133. package/dist/modules/sandbox/memory-shell.mjs.map +7 -0
  134. package/dist/modules/sandbox/open-scope-node.d.mts +4 -0
  135. package/dist/modules/sandbox/open-scope-node.mjs +19 -0
  136. package/dist/modules/sandbox/open-scope-node.mjs.map +7 -0
  137. package/dist/modules/sandbox/open-scope.d.mts +16 -0
  138. package/dist/modules/sandbox/open-scope.mjs +66 -0
  139. package/dist/modules/sandbox/open-scope.mjs.map +7 -0
  140. package/dist/modules/sandbox/paths.d.mts +7 -0
  141. package/dist/modules/sandbox/paths.mjs +50 -0
  142. package/dist/modules/sandbox/paths.mjs.map +7 -0
  143. package/dist/modules/sandbox/rpc-peer.d.mts +35 -0
  144. package/dist/modules/sandbox/rpc-peer.mjs +224 -0
  145. package/dist/modules/sandbox/rpc-peer.mjs.map +7 -0
  146. package/dist/modules/sandbox/seeds.d.mts +26 -0
  147. package/dist/modules/sandbox/seeds.mjs +228 -0
  148. package/dist/modules/sandbox/seeds.mjs.map +7 -0
  149. package/dist/modules/sandbox/server.d.mts +66 -0
  150. package/dist/modules/sandbox/server.mjs +567 -0
  151. package/dist/modules/sandbox/server.mjs.map +7 -0
  152. package/dist/modules/sandbox/snapshots.d.mts +49 -0
  153. package/dist/modules/sandbox/snapshots.mjs +55 -0
  154. package/dist/modules/sandbox/snapshots.mjs.map +7 -0
  155. package/dist/modules/sandbox/stream-mux.d.mts +18 -0
  156. package/dist/modules/sandbox/stream-mux.mjs +285 -0
  157. package/dist/modules/sandbox/stream-mux.mjs.map +7 -0
  158. package/dist/modules/sandbox/testing.d.mts +25 -0
  159. package/dist/modules/sandbox/testing.mjs +64 -0
  160. package/dist/modules/sandbox/testing.mjs.map +7 -0
  161. package/dist/modules/sandbox/types.d.mts +352 -0
  162. package/dist/modules/sandbox/types.mjs +86 -0
  163. package/dist/modules/sandbox/types.mjs.map +7 -0
  164. package/dist/modules/sandbox/wire.d.mts +671 -0
  165. package/dist/modules/sandbox/wire.mjs +537 -0
  166. package/dist/modules/sandbox/wire.mjs.map +7 -0
  167. package/dist/modules/sandbox/workspace-root.d.mts +8 -0
  168. package/dist/modules/sandbox/workspace-root.mjs +79 -0
  169. package/dist/modules/sandbox/workspace-root.mjs.map +7 -0
  170. package/dist/modules/schemas.d.mts +121 -0
  171. package/dist/modules/schemas.mjs +146 -0
  172. package/dist/modules/schemas.mjs.map +7 -0
  173. package/dist/modules/semantic-events.d.mts +31 -0
  174. package/dist/modules/semantic-events.mjs +23 -0
  175. package/dist/modules/semantic-events.mjs.map +7 -0
  176. package/package.json +199 -0
@@ -0,0 +1,35 @@
1
+ import type { JsonValue } from "../json.mjs";
2
+ import { type StreamMuxIface } from "./stream-mux.mjs";
3
+ import { type FrameChannelCloseIface, type FrameChannelIface, type JsonRpcId } from "./wire.mjs";
4
+ export interface RpcRequestContextIface {
5
+ id: JsonRpcId;
6
+ method: string;
7
+ params: JsonValue;
8
+ signal: AbortSignal;
9
+ }
10
+ export interface RpcPeerIface {
11
+ readonly streams: StreamMuxIface;
12
+ readonly closed: Promise<FrameChannelCloseIface>;
13
+ readonly isClosed: () => boolean;
14
+ request(method: string, params: object, options?: {
15
+ signal?: AbortSignal;
16
+ timeoutMs?: number;
17
+ }): Promise<JsonValue>;
18
+ notify(method: string, params: object): void;
19
+ close(code?: number, reason?: string): void;
20
+ pendingCount(): number;
21
+ }
22
+ export interface JsonRpcErrorBodyIface {
23
+ code: number;
24
+ message: string;
25
+ data: JsonValue;
26
+ }
27
+ export declare const toJsonRpcError: (cause: unknown) => JsonRpcErrorBodyIface;
28
+ export declare const createRpcPeer: (args: {
29
+ channel: FrameChannelIface;
30
+ binary: boolean;
31
+ onRequest?: (context: RpcRequestContextIface) => Promise<object>;
32
+ onNotification?: (method: string, params: JsonValue) => void;
33
+ onClose?: (info: FrameChannelCloseIface) => void;
34
+ beforeRequest?: (context: RpcRequestContextIface) => void;
35
+ }) => RpcPeerIface;
@@ -0,0 +1,224 @@
1
+ import { createStreamMux } from "./stream-mux.mjs";
2
+ import {
3
+ cancelRequestParamsSchema,
4
+ errnoOf,
5
+ handleRpcError,
6
+ HandleRpcErrorCode,
7
+ handleRpcErrorDataSchema,
8
+ HandleRpcNotification,
9
+ isHandleRpcError,
10
+ jsonRpcErrorResponseSchema,
11
+ jsonRpcNotificationSchema,
12
+ jsonRpcRequestSchema,
13
+ jsonRpcSuccessSchema
14
+ } from "./wire.mjs";
15
+ const toJsonRpcError = (cause) => {
16
+ if (isHandleRpcError(cause)) {
17
+ return {
18
+ code: cause.code,
19
+ message: cause.message,
20
+ data: { errno: cause.errno, retryable: cause.retryable }
21
+ };
22
+ }
23
+ const errno = errnoOf(cause);
24
+ const message = cause instanceof Error ? cause.message : String(cause);
25
+ const code = errno === "ENOENT" ? HandleRpcErrorCode.NotFound : errno === "EACCES" || errno === "EPERM" ? HandleRpcErrorCode.Forbidden : HandleRpcErrorCode.Internal;
26
+ return { code, message, data: { errno, retryable: false } };
27
+ };
28
+ const createRpcPeer = (args) => {
29
+ let nextId = 1;
30
+ const pending = /* @__PURE__ */ new Map();
31
+ const inbound = /* @__PURE__ */ new Map();
32
+ let closedInfo = null;
33
+ let resolveClosed = () => void 0;
34
+ const closed = new Promise((resolve) => {
35
+ resolveClosed = resolve;
36
+ });
37
+ const send = (frame) => {
38
+ if (closedInfo == null) args.channel.send(frame);
39
+ };
40
+ const streams = createStreamMux({ send, binary: args.binary });
41
+ const sendJson = (message) => send(JSON.stringify({ jsonrpc: "2.0", ...message }));
42
+ const respond = async (context, controller) => {
43
+ try {
44
+ const result = await (args.onRequest?.(context) ?? Promise.reject(
45
+ handleRpcError({ code: HandleRpcErrorCode.MethodNotFound, message: context.method })
46
+ ));
47
+ if (!controller.signal.aborted) sendJson({ id: context.id, result: result ?? {} });
48
+ else
49
+ sendJson({
50
+ id: context.id,
51
+ error: { code: HandleRpcErrorCode.Cancelled, message: "request cancelled" }
52
+ });
53
+ } catch (error) {
54
+ const rpcError = controller.signal.aborted ? { code: HandleRpcErrorCode.Cancelled, message: "request cancelled", data: null } : toJsonRpcError(error);
55
+ sendJson({ id: context.id, error: rpcError });
56
+ } finally {
57
+ inbound.delete(context.id);
58
+ }
59
+ };
60
+ const handleText = (text) => {
61
+ let message;
62
+ try {
63
+ message = JSON.parse(text);
64
+ } catch {
65
+ sendJson({
66
+ id: null,
67
+ error: { code: HandleRpcErrorCode.ParseError, message: "invalid JSON" }
68
+ });
69
+ return;
70
+ }
71
+ const request2 = jsonRpcRequestSchema.safeParse(message);
72
+ if (request2.success) {
73
+ const controller = new AbortController();
74
+ inbound.set(request2.data.id, controller);
75
+ const context = {
76
+ id: request2.data.id,
77
+ method: request2.data.method,
78
+ params: request2.data.params ?? {},
79
+ signal: controller.signal
80
+ };
81
+ try {
82
+ args.beforeRequest?.(context);
83
+ } catch (error) {
84
+ inbound.delete(request2.data.id);
85
+ sendJson({ id: request2.data.id, error: toJsonRpcError(error) });
86
+ return;
87
+ }
88
+ void respond(context, controller);
89
+ return;
90
+ }
91
+ const failure = jsonRpcErrorResponseSchema.safeParse(message);
92
+ if (failure.success) {
93
+ if (failure.data.id == null) return;
94
+ const entry = pending.get(failure.data.id);
95
+ pending.delete(failure.data.id);
96
+ const data = handleRpcErrorDataSchema.safeParse(failure.data.error.data);
97
+ entry?.reject(
98
+ handleRpcError({
99
+ code: failure.data.error.code,
100
+ message: failure.data.error.message,
101
+ errno: data.success ? data.data.errno ?? null : null,
102
+ retryable: data.success ? data.data.retryable ?? false : false
103
+ })
104
+ );
105
+ return;
106
+ }
107
+ const success = jsonRpcSuccessSchema.safeParse(message);
108
+ if (success.success) {
109
+ const entry = pending.get(success.data.id);
110
+ pending.delete(success.data.id);
111
+ entry?.resolve(success.data.result);
112
+ return;
113
+ }
114
+ const notification = jsonRpcNotificationSchema.safeParse(message);
115
+ if (!notification.success) return;
116
+ const params = notification.data.params ?? {};
117
+ if (streams.handleNotification(notification.data.method, params)) return;
118
+ if (notification.data.method === HandleRpcNotification.CancelRequest) {
119
+ const parsed = cancelRequestParamsSchema.safeParse(params);
120
+ if (parsed.success) inbound.get(parsed.data.requestId)?.abort();
121
+ return;
122
+ }
123
+ args.onNotification?.(notification.data.method, params);
124
+ };
125
+ const handleClose = (info) => {
126
+ if (closedInfo != null) return;
127
+ closedInfo = info;
128
+ const error = handleRpcError({
129
+ code: HandleRpcErrorCode.ConnectionClosed,
130
+ message: `connection closed (${info.code}${info.reason === "" ? "" : `: ${info.reason}`})`,
131
+ retryable: true
132
+ });
133
+ for (const entry of pending.values()) entry.reject(error);
134
+ pending.clear();
135
+ for (const controller of inbound.values()) controller.abort();
136
+ inbound.clear();
137
+ streams.failAll(error);
138
+ args.onClose?.(info);
139
+ resolveClosed(info);
140
+ };
141
+ args.channel.listen({
142
+ frame: (frame) => {
143
+ if (frame instanceof Uint8Array) streams.handleBinary(frame);
144
+ else handleText(frame);
145
+ },
146
+ close: handleClose
147
+ });
148
+ const request = (method, params, options) => {
149
+ if (closedInfo != null) {
150
+ return Promise.reject(
151
+ handleRpcError({
152
+ code: HandleRpcErrorCode.ConnectionClosed,
153
+ message: "connection closed",
154
+ retryable: true
155
+ })
156
+ );
157
+ }
158
+ if (options?.signal?.aborted === true) {
159
+ return Promise.reject(
160
+ handleRpcError({ code: HandleRpcErrorCode.Cancelled, message: "request aborted" })
161
+ );
162
+ }
163
+ const id = nextId;
164
+ nextId += 1;
165
+ return new Promise((resolve, reject) => {
166
+ let timer = null;
167
+ const onAbort = () => {
168
+ if (!pending.has(id)) return;
169
+ sendJson({ method: HandleRpcNotification.CancelRequest, params: { requestId: id } });
170
+ pending.delete(id);
171
+ cleanup();
172
+ reject(handleRpcError({ code: HandleRpcErrorCode.Cancelled, message: "request aborted" }));
173
+ };
174
+ const cleanup = () => {
175
+ if (timer != null) clearTimeout(timer);
176
+ options?.signal?.removeEventListener("abort", onAbort);
177
+ };
178
+ pending.set(id, {
179
+ resolve: (value) => {
180
+ cleanup();
181
+ resolve(value);
182
+ },
183
+ reject: (error) => {
184
+ cleanup();
185
+ reject(error);
186
+ }
187
+ });
188
+ options?.signal?.addEventListener("abort", onAbort);
189
+ if (options?.timeoutMs != null) {
190
+ timer = setTimeout(() => {
191
+ if (!pending.has(id)) return;
192
+ sendJson({ method: HandleRpcNotification.CancelRequest, params: { requestId: id } });
193
+ pending.delete(id);
194
+ cleanup();
195
+ reject(
196
+ handleRpcError({
197
+ code: HandleRpcErrorCode.Timeout,
198
+ message: `${method} timed out`,
199
+ retryable: true
200
+ })
201
+ );
202
+ }, options.timeoutMs);
203
+ }
204
+ sendJson({ id, method, params });
205
+ });
206
+ };
207
+ return {
208
+ streams,
209
+ closed,
210
+ isClosed: () => closedInfo != null,
211
+ request,
212
+ notify: (method, params) => sendJson({ method, params }),
213
+ close: (code, reason) => {
214
+ args.channel.close(code, reason);
215
+ handleClose({ code: code ?? 1e3, reason: reason ?? "" });
216
+ },
217
+ pendingCount: () => pending.size
218
+ };
219
+ };
220
+ export {
221
+ createRpcPeer,
222
+ toJsonRpcError
223
+ };
224
+ //# sourceMappingURL=rpc-peer.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/sandbox/rpc-peer.ts"],
4
+ "sourcesContent": ["import type { JsonValue } from \"../json.mjs\";\nimport { createStreamMux, type StreamMuxIface } from \"./stream-mux.mjs\";\nimport {\n cancelRequestParamsSchema,\n errnoOf,\n handleRpcError,\n HandleRpcErrorCode,\n handleRpcErrorDataSchema,\n HandleRpcNotification,\n isHandleRpcError,\n jsonRpcErrorResponseSchema,\n jsonRpcNotificationSchema,\n jsonRpcRequestSchema,\n jsonRpcSuccessSchema,\n type FrameChannelCloseIface,\n type FrameChannelIface,\n type JsonRpcId,\n type WireFrame,\n} from \"./wire.mjs\";\n\n// JSON-RPC 2.0 over a frame channel with the handle RPC's stream mux attached.\n// One peer per connection; both client and server use it.\n\nexport interface RpcRequestContextIface {\n id: JsonRpcId;\n method: string;\n params: JsonValue;\n signal: AbortSignal;\n}\n\nexport interface RpcPeerIface {\n readonly streams: StreamMuxIface;\n readonly closed: Promise<FrameChannelCloseIface>;\n readonly isClosed: () => boolean;\n request(\n method: string,\n // Params are serialized as is; wire.ts schemas own their shape.\n // oxlint-disable-next-line anti-slop/no-object-parameters -- JSON-RPC serialization boundary.\n params: object,\n options?: { signal?: AbortSignal; timeoutMs?: number },\n ): Promise<JsonValue>;\n // oxlint-disable-next-line anti-slop/no-object-parameters -- JSON-RPC serialization boundary.\n notify(method: string, params: object): void;\n close(code?: number, reason?: string): void;\n // Number of requests awaiting a response.\n pendingCount(): number;\n}\n\ninterface PendingIface {\n resolve: (value: JsonValue) => void;\n reject: (error: Error) => void;\n}\n\n// Converts a thrown value into a JSON-RPC error object.\nexport interface JsonRpcErrorBodyIface {\n code: number;\n message: string;\n data: JsonValue;\n}\n\nexport const toJsonRpcError = (cause: unknown): JsonRpcErrorBodyIface => {\n if (isHandleRpcError(cause)) {\n return {\n code: cause.code,\n message: cause.message,\n data: { errno: cause.errno, retryable: cause.retryable },\n };\n }\n const errno = errnoOf(cause);\n const message = cause instanceof Error ? cause.message : String(cause);\n const code =\n errno === 'ENOENT'\n ? HandleRpcErrorCode.NotFound\n : errno === 'EACCES' || errno === 'EPERM'\n ? HandleRpcErrorCode.Forbidden\n : HandleRpcErrorCode.Internal;\n return { code, message, data: { errno, retryable: false } };\n};\n\nexport const createRpcPeer = (args: {\n channel: FrameChannelIface;\n binary: boolean;\n onRequest?: (context: RpcRequestContextIface) => Promise<object>;\n onNotification?: (method: string, params: JsonValue) => void;\n onClose?: (info: FrameChannelCloseIface) => void;\n // Called synchronously before onRequest, in frame order; used by the server\n // to register incoming streams before their chunks can arrive.\n beforeRequest?: (context: RpcRequestContextIface) => void;\n}): RpcPeerIface => {\n let nextId = 1;\n const pending = new Map<JsonRpcId, PendingIface>();\n const inbound = new Map<JsonRpcId, AbortController>();\n let closedInfo: FrameChannelCloseIface | null = null;\n let resolveClosed: (info: FrameChannelCloseIface) => void = () => undefined;\n const closed = new Promise<FrameChannelCloseIface>((resolve) => {\n resolveClosed = resolve;\n });\n\n const send = (frame: WireFrame) => {\n if (closedInfo == null) args.channel.send(frame);\n };\n const streams = createStreamMux({ send, binary: args.binary });\n\n // oxlint-disable-next-line anti-slop/no-object-parameters -- JSON-RPC serialization boundary.\n const sendJson = (message: object) => send(JSON.stringify({ jsonrpc: '2.0', ...message }));\n\n const respond = async (context: RpcRequestContextIface, controller: AbortController) => {\n try {\n const result = await (args.onRequest?.(context) ??\n Promise.reject(\n handleRpcError({ code: HandleRpcErrorCode.MethodNotFound, message: context.method }),\n ));\n if (!controller.signal.aborted) sendJson({ id: context.id, result: result ?? {} });\n else\n sendJson({\n id: context.id,\n error: { code: HandleRpcErrorCode.Cancelled, message: 'request cancelled' },\n });\n } catch (error) {\n const rpcError = controller.signal.aborted\n ? { code: HandleRpcErrorCode.Cancelled, message: 'request cancelled', data: null }\n : toJsonRpcError(error);\n sendJson({ id: context.id, error: rpcError });\n } finally {\n inbound.delete(context.id);\n }\n };\n\n const handleText = (text: string) => {\n let message: unknown;\n try {\n message = JSON.parse(text);\n } catch {\n sendJson({\n id: null,\n error: { code: HandleRpcErrorCode.ParseError, message: 'invalid JSON' },\n });\n return;\n }\n const request = jsonRpcRequestSchema.safeParse(message);\n if (request.success) {\n const controller = new AbortController();\n inbound.set(request.data.id, controller);\n const context: RpcRequestContextIface = {\n id: request.data.id,\n method: request.data.method,\n params: request.data.params ?? {},\n signal: controller.signal,\n };\n try {\n args.beforeRequest?.(context);\n } catch (error) {\n inbound.delete(request.data.id);\n sendJson({ id: request.data.id, error: toJsonRpcError(error) });\n return;\n }\n void respond(context, controller);\n return;\n }\n const failure = jsonRpcErrorResponseSchema.safeParse(message);\n if (failure.success) {\n if (failure.data.id == null) return;\n const entry = pending.get(failure.data.id);\n pending.delete(failure.data.id);\n const data = handleRpcErrorDataSchema.safeParse(failure.data.error.data);\n entry?.reject(\n handleRpcError({\n code: failure.data.error.code,\n message: failure.data.error.message,\n errno: data.success ? (data.data.errno ?? null) : null,\n retryable: data.success ? (data.data.retryable ?? false) : false,\n }),\n );\n return;\n }\n const success = jsonRpcSuccessSchema.safeParse(message);\n if (success.success) {\n const entry = pending.get(success.data.id);\n pending.delete(success.data.id);\n entry?.resolve(success.data.result);\n return;\n }\n const notification = jsonRpcNotificationSchema.safeParse(message);\n if (!notification.success) return;\n const params = notification.data.params ?? {};\n if (streams.handleNotification(notification.data.method, params)) return;\n if (notification.data.method === HandleRpcNotification.CancelRequest) {\n const parsed = cancelRequestParamsSchema.safeParse(params);\n if (parsed.success) inbound.get(parsed.data.requestId)?.abort();\n return;\n }\n args.onNotification?.(notification.data.method, params);\n };\n\n const handleClose = (info: FrameChannelCloseIface) => {\n if (closedInfo != null) return;\n closedInfo = info;\n const error = handleRpcError({\n code: HandleRpcErrorCode.ConnectionClosed,\n message: `connection closed (${info.code}${info.reason === '' ? '' : `: ${info.reason}`})`,\n retryable: true,\n });\n for (const entry of pending.values()) entry.reject(error);\n pending.clear();\n for (const controller of inbound.values()) controller.abort();\n inbound.clear();\n streams.failAll(error);\n args.onClose?.(info);\n resolveClosed(info);\n };\n\n args.channel.listen({\n frame: (frame) => {\n if (frame instanceof Uint8Array) streams.handleBinary(frame);\n else handleText(frame);\n },\n close: handleClose,\n });\n\n const request: RpcPeerIface['request'] = (method, params, options) => {\n if (closedInfo != null) {\n return Promise.reject(\n handleRpcError({\n code: HandleRpcErrorCode.ConnectionClosed,\n message: 'connection closed',\n retryable: true,\n }),\n );\n }\n if (options?.signal?.aborted === true) {\n return Promise.reject(\n handleRpcError({ code: HandleRpcErrorCode.Cancelled, message: 'request aborted' }),\n );\n }\n const id = nextId;\n nextId += 1;\n return new Promise<JsonValue>((resolve, reject) => {\n let timer: ReturnType<typeof setTimeout> | null = null;\n const onAbort = () => {\n if (!pending.has(id)) return;\n sendJson({ method: HandleRpcNotification.CancelRequest, params: { requestId: id } });\n pending.delete(id);\n cleanup();\n reject(handleRpcError({ code: HandleRpcErrorCode.Cancelled, message: 'request aborted' }));\n };\n const cleanup = () => {\n if (timer != null) clearTimeout(timer);\n options?.signal?.removeEventListener('abort', onAbort);\n };\n pending.set(id, {\n resolve: (value) => {\n cleanup();\n resolve(value);\n },\n reject: (error) => {\n cleanup();\n reject(error);\n },\n });\n options?.signal?.addEventListener('abort', onAbort);\n if (options?.timeoutMs != null) {\n timer = setTimeout(() => {\n if (!pending.has(id)) return;\n sendJson({ method: HandleRpcNotification.CancelRequest, params: { requestId: id } });\n pending.delete(id);\n cleanup();\n reject(\n handleRpcError({\n code: HandleRpcErrorCode.Timeout,\n message: `${method} timed out`,\n retryable: true,\n }),\n );\n }, options.timeoutMs);\n }\n sendJson({ id, method, params });\n });\n };\n\n return {\n streams,\n closed,\n isClosed: () => closedInfo != null,\n request,\n notify: (method, params) => sendJson({ method, params }),\n close: (code, reason) => {\n args.channel.close(code, reason);\n handleClose({ code: code ?? 1000, reason: reason ?? '' });\n },\n pendingCount: () => pending.size,\n };\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["request"]
7
+ }
@@ -0,0 +1,26 @@
1
+ import * as z from 'zod';
2
+ import type { SandboxPrepareContextIface, SandboxSessionIface, SandboxStartContextIface } from "./types.mjs";
3
+ export declare const sandboxPreparationInputs: (files: Record<string, string>) => Pick<SandboxPrepareContextIface, "files" | "resources">;
4
+ export declare const MAX_SANDBOX_SEED_BYTES: number;
5
+ export declare const sandboxSeedFilesSchema: z.ZodPreprocess<z.ZodPipe<z.ZodArray<z.ZodTuple<[z.ZodString, z.ZodString], null>>, z.ZodTransform<{
6
+ [k: string]: string;
7
+ }, [string, string][]>>, unknown>;
8
+ export declare const sandboxSeedFiles: (ctx: Pick<SandboxPrepareContextIface, "files" | "resources">) => Record<string, string>;
9
+ export declare const sandboxSeedIdentity: (files: Record<string, string>) => string;
10
+ export declare const SANDBOX_SEED_MARKER = "workspace-seeded";
11
+ export declare const SANDBOX_SEED_PROTOCOL = "workspace-seed-v1";
12
+ export declare const SANDBOX_SEED_SCRIPT = "import json, os, stat, sys, uuid\np = json.load(sys.stdin)\nflags = os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW\nroot = os.open('/', flags)\ntry:\n for part in p['root'].split('/'):\n if not part:\n continue\n if part in ('.', '..'):\n raise ValueError('invalid workspace root')\n next_fd = os.open(part, flags, dir_fd=root)\n os.close(root)\n root = next_fd\n try:\n os.mkdir('.final', dir_fd=root)\n except FileExistsError:\n pass\n state = os.open('.final', flags, dir_fd=root)\n try:\n marker = os.open('workspace-seeded', os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK, dir_fd=state)\n except FileNotFoundError:\n marker = None\n if marker is not None:\n try:\n if not stat.S_ISREG(os.fstat(marker).st_mode) or os.read(marker, 64) != b'workspace-seed-v1':\n raise ValueError('invalid workspace seed marker')\n finally:\n os.close(marker)\n os.close(state)\n sys.exit(0)\n for path, content in p['files'].items():\n parts = path.split('/')\n if parts[0] == '.final' or any(x in ('', '.', '..') or '\\\\' in x or '\\x00' in x for x in parts):\n raise ValueError('invalid seed path')\n parent = os.dup(root)\n temporary = None\n try:\n for part in parts[:-1]:\n try:\n os.mkdir(part, dir_fd=parent)\n except FileExistsError:\n pass\n next_fd = os.open(part, flags, dir_fd=parent)\n os.close(parent)\n parent = next_fd\n name = parts[-1]\n try:\n existing = os.stat(name, dir_fd=parent, follow_symlinks=False)\n except FileNotFoundError:\n existing = None\n if existing is not None:\n if not stat.S_ISREG(existing.st_mode):\n raise ValueError('seed destination is not a regular file: ' + path)\n continue\n temporary = '.final-seed-' + uuid.uuid4().hex\n fd = os.open(temporary, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o644, dir_fd=parent)\n with os.fdopen(fd, 'wb') as output:\n output.write(content.encode('utf-8'))\n output.flush()\n os.fsync(output.fileno())\n try:\n os.link(temporary, name, src_dir_fd=parent, dst_dir_fd=parent, follow_symlinks=False)\n except FileExistsError:\n if not stat.S_ISREG(os.stat(name, dir_fd=parent, follow_symlinks=False).st_mode):\n raise ValueError('seed destination is not a regular file: ' + path)\n finally:\n if temporary is not None:\n os.unlink(temporary, dir_fd=parent)\n os.close(parent)\n temporary = '.seed-marker-' + uuid.uuid4().hex\n marker = os.open(temporary, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600, dir_fd=state)\n try:\n with os.fdopen(marker, 'wb') as output:\n output.write(b'workspace-seed-v1')\n output.flush()\n os.fsync(output.fileno())\n try:\n os.link(temporary, 'workspace-seeded', src_dir_fd=state, dst_dir_fd=state, follow_symlinks=False)\n except FileExistsError:\n pass\n finally:\n os.unlink(temporary, dir_fd=state)\n os.close(state)\nfinally:\n os.close(root)\n";
13
+ export declare const materializeSandboxSeeds: (args: {
14
+ sandbox: Pick<SandboxSessionIface, "run">;
15
+ root: string;
16
+ files: Record<string, string>;
17
+ }) => Promise<void>;
18
+ export declare const sandboxSeedArtifactSchema: z.ZodObject<{
19
+ seedFiles: z.ZodDefault<z.ZodPreprocess<z.ZodPipe<z.ZodArray<z.ZodTuple<[z.ZodString, z.ZodString], null>>, z.ZodTransform<{
20
+ [k: string]: string;
21
+ }, [string, string][]>>, unknown>>;
22
+ seedSourceRevision: z.ZodOptional<z.ZodString>;
23
+ seedHash: z.ZodOptional<z.ZodString>;
24
+ }, z.core.$strip>;
25
+ export declare const sandboxSeedArtifact: (ctx: SandboxPrepareContextIface, files: Record<string, string>) => Promise<z.output<typeof sandboxSeedArtifactSchema>>;
26
+ export declare const sandboxSeedFilesForStart: (ctx: SandboxStartContextIface, artifact: z.output<typeof sandboxSeedArtifactSchema>) => Promise<Record<string, string>>;
@@ -0,0 +1,228 @@
1
+ import * as z from "zod";
2
+ const sandboxPreparationInputs = (files) => {
3
+ const workspace = /* @__PURE__ */ new Map();
4
+ const skills = /* @__PURE__ */ new Map();
5
+ for (const [path, content] of Object.entries(files)) {
6
+ if (path.startsWith("workspace/")) workspace.set(path.slice("workspace/".length), content);
7
+ if (!path.startsWith("skills/")) continue;
8
+ const segments = path.slice("skills/".length).split("/");
9
+ const key = segments.shift();
10
+ if (key == null || segments.length === 0) continue;
11
+ const skill = skills.get(key) ?? /* @__PURE__ */ new Map();
12
+ skill.set(segments.join("/"), content);
13
+ skills.set(key, skill);
14
+ }
15
+ const resources = {
16
+ workspace: { files: Object.fromEntries(workspace) },
17
+ skills: Object.fromEntries(
18
+ [...skills].map(([key, entries]) => [key, Object.fromEntries(entries)])
19
+ )
20
+ };
21
+ return { files: Object.fromEntries(workspace), resources };
22
+ };
23
+ const skillResourcesSchema = z.record(z.string(), z.record(z.string(), z.string()));
24
+ const MAX_SANDBOX_SEED_BYTES = 8 * 1024 * 1024;
25
+ const sandboxSeedFilesSchema = z.preprocess(
26
+ (value) => z.record(z.string(), z.unknown()).safeParse(value).success ? Object.entries(value ?? {}) : null,
27
+ z.array(z.tuple([z.string(), z.string()])).transform((entries) => Object.fromEntries(entries))
28
+ );
29
+ const seedPath = (path) => {
30
+ if (path === ".final" || path.startsWith(".final/") || path.includes("\\") || path.includes("\0") || path.split("/").some((part) => part === "" || part === "." || part === "..")) {
31
+ throw new Error(`invalid workspace seed path: ${path}`);
32
+ }
33
+ return path;
34
+ };
35
+ const sandboxSeedFiles = (ctx) => {
36
+ const entries = Object.entries(ctx.files).map(([path, content]) => [
37
+ seedPath(path),
38
+ content
39
+ ]);
40
+ const skills = ctx.resources.skills ?? {};
41
+ skillResourcesSchema.parse(skills);
42
+ const skillEntries = Object.entries(skills);
43
+ for (const [name, files] of skillEntries) {
44
+ if (seedPath(name).includes("/")) throw new Error(`invalid skill resource name: ${name}`);
45
+ z.record(z.string(), z.string()).parse(files);
46
+ const fileEntries = Object.entries(files ?? {});
47
+ for (const [path, content] of fileEntries)
48
+ entries.push([`.agents/skills/${name}/${seedPath(path)}`, z.string().parse(content)]);
49
+ }
50
+ const paths = /* @__PURE__ */ new Set();
51
+ for (const [path] of entries) {
52
+ if (paths.has(path)) throw new Error(`conflicting workspace seed path: ${path}`);
53
+ paths.add(path);
54
+ }
55
+ for (const path of paths) {
56
+ const parts = path.split("/");
57
+ for (let end = 1; end < parts.length; end += 1) {
58
+ const ancestor = parts.slice(0, end).join("/");
59
+ if (paths.has(ancestor))
60
+ throw new Error(`conflicting workspace seed paths: ${ancestor}, ${path}`);
61
+ }
62
+ }
63
+ const encoder = new TextEncoder();
64
+ let bytes = 0;
65
+ for (const [path, content] of entries) {
66
+ if (!path.isWellFormed() || !content.isWellFormed())
67
+ throw new Error(`workspace seed ${path} must contain valid Unicode text`);
68
+ bytes += encoder.encode(path).byteLength + encoder.encode(content).byteLength;
69
+ if (bytes > MAX_SANDBOX_SEED_BYTES)
70
+ throw new Error("workspace and skill resources exceed the combined 8 MiB limit");
71
+ }
72
+ return Object.fromEntries(entries);
73
+ };
74
+ const sandboxSeedIdentity = (files) => JSON.stringify(
75
+ Object.entries(files).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0)
76
+ );
77
+ const SANDBOX_SEED_MARKER = "workspace-seeded";
78
+ const SANDBOX_SEED_PROTOCOL = "workspace-seed-v1";
79
+ const SANDBOX_SEED_SCRIPT = `import json, os, stat, sys, uuid
80
+ p = json.load(sys.stdin)
81
+ flags = os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW
82
+ root = os.open('/', flags)
83
+ try:
84
+ for part in p['root'].split('/'):
85
+ if not part:
86
+ continue
87
+ if part in ('.', '..'):
88
+ raise ValueError('invalid workspace root')
89
+ next_fd = os.open(part, flags, dir_fd=root)
90
+ os.close(root)
91
+ root = next_fd
92
+ try:
93
+ os.mkdir('.final', dir_fd=root)
94
+ except FileExistsError:
95
+ pass
96
+ state = os.open('.final', flags, dir_fd=root)
97
+ try:
98
+ marker = os.open('${SANDBOX_SEED_MARKER}', os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK, dir_fd=state)
99
+ except FileNotFoundError:
100
+ marker = None
101
+ if marker is not None:
102
+ try:
103
+ if not stat.S_ISREG(os.fstat(marker).st_mode) or os.read(marker, 64) != b'${SANDBOX_SEED_PROTOCOL}':
104
+ raise ValueError('invalid workspace seed marker')
105
+ finally:
106
+ os.close(marker)
107
+ os.close(state)
108
+ sys.exit(0)
109
+ for path, content in p['files'].items():
110
+ parts = path.split('/')
111
+ if parts[0] == '.final' or any(x in ('', '.', '..') or '\\\\' in x or '\\x00' in x for x in parts):
112
+ raise ValueError('invalid seed path')
113
+ parent = os.dup(root)
114
+ temporary = None
115
+ try:
116
+ for part in parts[:-1]:
117
+ try:
118
+ os.mkdir(part, dir_fd=parent)
119
+ except FileExistsError:
120
+ pass
121
+ next_fd = os.open(part, flags, dir_fd=parent)
122
+ os.close(parent)
123
+ parent = next_fd
124
+ name = parts[-1]
125
+ try:
126
+ existing = os.stat(name, dir_fd=parent, follow_symlinks=False)
127
+ except FileNotFoundError:
128
+ existing = None
129
+ if existing is not None:
130
+ if not stat.S_ISREG(existing.st_mode):
131
+ raise ValueError('seed destination is not a regular file: ' + path)
132
+ continue
133
+ temporary = '.final-seed-' + uuid.uuid4().hex
134
+ fd = os.open(temporary, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o644, dir_fd=parent)
135
+ with os.fdopen(fd, 'wb') as output:
136
+ output.write(content.encode('utf-8'))
137
+ output.flush()
138
+ os.fsync(output.fileno())
139
+ try:
140
+ os.link(temporary, name, src_dir_fd=parent, dst_dir_fd=parent, follow_symlinks=False)
141
+ except FileExistsError:
142
+ if not stat.S_ISREG(os.stat(name, dir_fd=parent, follow_symlinks=False).st_mode):
143
+ raise ValueError('seed destination is not a regular file: ' + path)
144
+ finally:
145
+ if temporary is not None:
146
+ os.unlink(temporary, dir_fd=parent)
147
+ os.close(parent)
148
+ temporary = '.seed-marker-' + uuid.uuid4().hex
149
+ marker = os.open(temporary, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600, dir_fd=state)
150
+ try:
151
+ with os.fdopen(marker, 'wb') as output:
152
+ output.write(b'${SANDBOX_SEED_PROTOCOL}')
153
+ output.flush()
154
+ os.fsync(output.fileno())
155
+ try:
156
+ os.link(temporary, '${SANDBOX_SEED_MARKER}', src_dir_fd=state, dst_dir_fd=state, follow_symlinks=False)
157
+ except FileExistsError:
158
+ pass
159
+ finally:
160
+ os.unlink(temporary, dir_fd=state)
161
+ os.close(state)
162
+ finally:
163
+ os.close(root)
164
+ `;
165
+ const materializeSandboxSeeds = async (args) => {
166
+ if (Object.keys(args.files).length === 0) return;
167
+ if (!args.root.startsWith("/")) throw new Error("workspace seed root must be absolute");
168
+ const result = await args.sandbox.run({
169
+ command: "python3",
170
+ args: ["-c", SANDBOX_SEED_SCRIPT],
171
+ cwd: "/",
172
+ stdin: new ReadableStream({
173
+ start: (controller) => {
174
+ const bytes = new TextEncoder().encode(
175
+ JSON.stringify({ root: args.root, files: args.files })
176
+ );
177
+ for (let offset = 0; offset < bytes.byteLength; offset += 64 * 1024)
178
+ controller.enqueue(bytes.subarray(offset, offset + 64 * 1024));
179
+ controller.close();
180
+ }
181
+ }),
182
+ timeoutMs: 6e4
183
+ });
184
+ if (result.exitCode !== 0)
185
+ throw new Error(`workspace seeding failed: ${result.stderr.trim().slice(-2e3)}`);
186
+ };
187
+ const sandboxSeedArtifactSchema = z.object({
188
+ seedFiles: sandboxSeedFilesSchema.default({}),
189
+ seedSourceRevision: z.string().optional(),
190
+ seedHash: z.string().optional()
191
+ });
192
+ const seedHash = async (files) => {
193
+ const digest = await crypto.subtle.digest(
194
+ "SHA-256",
195
+ new TextEncoder().encode(sandboxSeedIdentity(files))
196
+ );
197
+ return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
198
+ };
199
+ const sandboxSeedArtifact = async (ctx, files) => {
200
+ if (ctx.preparation == null || Object.keys(files).length === 0) return { seedFiles: files };
201
+ if (ctx.preparation.sourceRevision !== ctx.sourceRevision)
202
+ throw new Error("preparation resource revision does not match");
203
+ return { seedFiles: {}, seedSourceRevision: ctx.sourceRevision, seedHash: await seedHash(files) };
204
+ };
205
+ const sandboxSeedFilesForStart = async (ctx, artifact) => {
206
+ if (artifact.seedSourceRevision == null) return artifact.seedFiles;
207
+ if (ctx.preparation?.sourceRevision !== artifact.seedSourceRevision)
208
+ throw new Error("pinned sandbox seed resource source is unavailable");
209
+ const files = sandboxSeedFiles(await ctx.preparation.read());
210
+ if (artifact.seedHash == null || await seedHash(files) !== artifact.seedHash)
211
+ throw new Error("pinned sandbox seed resource identity does not match the artifact");
212
+ return files;
213
+ };
214
+ export {
215
+ MAX_SANDBOX_SEED_BYTES,
216
+ SANDBOX_SEED_MARKER,
217
+ SANDBOX_SEED_PROTOCOL,
218
+ SANDBOX_SEED_SCRIPT,
219
+ materializeSandboxSeeds,
220
+ sandboxPreparationInputs,
221
+ sandboxSeedArtifact,
222
+ sandboxSeedArtifactSchema,
223
+ sandboxSeedFiles,
224
+ sandboxSeedFilesForStart,
225
+ sandboxSeedFilesSchema,
226
+ sandboxSeedIdentity
227
+ };
228
+ //# sourceMappingURL=seeds.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/sandbox/seeds.ts"],
4
+ "sourcesContent": ["import * as z from 'zod';\nimport type { JsonValue } from \"../json.mjs\";\nimport type {\n SandboxPrepareContextIface,\n SandboxSessionIface,\n SandboxStartContextIface,\n} from \"./types.mjs\";\n\nexport const sandboxPreparationInputs = (\n files: Record<string, string>,\n): Pick<SandboxPrepareContextIface, 'files' | 'resources'> => {\n const workspace = new Map<string, string>();\n const skills = new Map<string, Map<string, string>>();\n for (const [path, content] of Object.entries(files)) {\n if (path.startsWith('workspace/')) workspace.set(path.slice('workspace/'.length), content);\n if (!path.startsWith('skills/')) continue;\n const segments = path.slice('skills/'.length).split('/');\n const key = segments.shift();\n if (key == null || segments.length === 0) continue;\n const skill = skills.get(key) ?? new Map<string, string>();\n skill.set(segments.join('/'), content);\n skills.set(key, skill);\n }\n const resources = {\n workspace: { files: Object.fromEntries(workspace) },\n skills: Object.fromEntries(\n [...skills].map(([key, entries]) => [key, Object.fromEntries(entries)]),\n ),\n } satisfies Record<string, JsonValue>;\n return { files: Object.fromEntries(workspace), resources };\n};\nconst skillResourcesSchema = z.record(z.string(), z.record(z.string(), z.string()));\nexport const MAX_SANDBOX_SEED_BYTES = 8 * 1024 * 1024;\nexport const sandboxSeedFilesSchema = z.preprocess(\n (value) =>\n z.record(z.string(), z.unknown()).safeParse(value).success ? Object.entries(value ?? {}) : null,\n z.array(z.tuple([z.string(), z.string()])).transform((entries) => Object.fromEntries(entries)),\n);\n\nconst seedPath = (path: string): string => {\n if (\n path === '.final' ||\n path.startsWith('.final/') ||\n path.includes('\\\\') ||\n path.includes('\\0') ||\n path.split('/').some((part) => part === '' || part === '.' || part === '..')\n ) {\n throw new Error(`invalid workspace seed path: ${path}`);\n }\n return path;\n};\n\n// Skills remain harness config; their auxiliary files are also available in the workspace.\nexport const sandboxSeedFiles = (\n ctx: Pick<SandboxPrepareContextIface, 'files' | 'resources'>,\n): Record<string, string> => {\n const entries: [string, string][] = Object.entries(ctx.files).map(([path, content]) => [\n seedPath(path),\n content,\n ]);\n const skills = ctx.resources.skills ?? {};\n skillResourcesSchema.parse(skills);\n // Zod dictionaries omit __proto__; validate values while retaining literal filenames.\n const skillEntries: [string, unknown][] = Object.entries(skills);\n for (const [name, files] of skillEntries) {\n if (seedPath(name).includes('/')) throw new Error(`invalid skill resource name: ${name}`);\n z.record(z.string(), z.string()).parse(files);\n const fileEntries: [string, unknown][] = Object.entries(files ?? {});\n for (const [path, content] of fileEntries)\n entries.push([`.agents/skills/${name}/${seedPath(path)}`, z.string().parse(content)]);\n }\n const paths = new Set<string>();\n for (const [path] of entries) {\n if (paths.has(path)) throw new Error(`conflicting workspace seed path: ${path}`);\n paths.add(path);\n }\n for (const path of paths) {\n const parts = path.split('/');\n for (let end = 1; end < parts.length; end += 1) {\n const ancestor = parts.slice(0, end).join('/');\n if (paths.has(ancestor))\n throw new Error(`conflicting workspace seed paths: ${ancestor}, ${path}`);\n }\n }\n const encoder = new TextEncoder();\n let bytes = 0;\n for (const [path, content] of entries) {\n if (!path.isWellFormed() || !content.isWellFormed())\n throw new Error(`workspace seed ${path} must contain valid Unicode text`);\n bytes += encoder.encode(path).byteLength + encoder.encode(content).byteLength;\n if (bytes > MAX_SANDBOX_SEED_BYTES)\n throw new Error('workspace and skill resources exceed the combined 8 MiB limit');\n }\n return Object.fromEntries(entries);\n};\n\nexport const sandboxSeedIdentity = (files: Record<string, string>): string =>\n JSON.stringify(\n Object.entries(files).sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0)),\n );\n\n// As with confined reads, Python 3 is required. Directory descriptors pin every\n// ancestor; link publishes a complete file without replacing existing content.\nexport const SANDBOX_SEED_MARKER = 'workspace-seeded';\nexport const SANDBOX_SEED_PROTOCOL = 'workspace-seed-v1';\nexport const SANDBOX_SEED_SCRIPT = `import json, os, stat, sys, uuid\np = json.load(sys.stdin)\nflags = os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW\nroot = os.open('/', flags)\ntry:\n for part in p['root'].split('/'):\n if not part:\n continue\n if part in ('.', '..'):\n raise ValueError('invalid workspace root')\n next_fd = os.open(part, flags, dir_fd=root)\n os.close(root)\n root = next_fd\n try:\n os.mkdir('.final', dir_fd=root)\n except FileExistsError:\n pass\n state = os.open('.final', flags, dir_fd=root)\n try:\n marker = os.open('${SANDBOX_SEED_MARKER}', os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK, dir_fd=state)\n except FileNotFoundError:\n marker = None\n if marker is not None:\n try:\n if not stat.S_ISREG(os.fstat(marker).st_mode) or os.read(marker, 64) != b'${SANDBOX_SEED_PROTOCOL}':\n raise ValueError('invalid workspace seed marker')\n finally:\n os.close(marker)\n os.close(state)\n sys.exit(0)\n for path, content in p['files'].items():\n parts = path.split('/')\n if parts[0] == '.final' or any(x in ('', '.', '..') or '\\\\\\\\' in x or '\\\\x00' in x for x in parts):\n raise ValueError('invalid seed path')\n parent = os.dup(root)\n temporary = None\n try:\n for part in parts[:-1]:\n try:\n os.mkdir(part, dir_fd=parent)\n except FileExistsError:\n pass\n next_fd = os.open(part, flags, dir_fd=parent)\n os.close(parent)\n parent = next_fd\n name = parts[-1]\n try:\n existing = os.stat(name, dir_fd=parent, follow_symlinks=False)\n except FileNotFoundError:\n existing = None\n if existing is not None:\n if not stat.S_ISREG(existing.st_mode):\n raise ValueError('seed destination is not a regular file: ' + path)\n continue\n temporary = '.final-seed-' + uuid.uuid4().hex\n fd = os.open(temporary, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o644, dir_fd=parent)\n with os.fdopen(fd, 'wb') as output:\n output.write(content.encode('utf-8'))\n output.flush()\n os.fsync(output.fileno())\n try:\n os.link(temporary, name, src_dir_fd=parent, dst_dir_fd=parent, follow_symlinks=False)\n except FileExistsError:\n if not stat.S_ISREG(os.stat(name, dir_fd=parent, follow_symlinks=False).st_mode):\n raise ValueError('seed destination is not a regular file: ' + path)\n finally:\n if temporary is not None:\n os.unlink(temporary, dir_fd=parent)\n os.close(parent)\n temporary = '.seed-marker-' + uuid.uuid4().hex\n marker = os.open(temporary, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600, dir_fd=state)\n try:\n with os.fdopen(marker, 'wb') as output:\n output.write(b'${SANDBOX_SEED_PROTOCOL}')\n output.flush()\n os.fsync(output.fileno())\n try:\n os.link(temporary, '${SANDBOX_SEED_MARKER}', src_dir_fd=state, dst_dir_fd=state, follow_symlinks=False)\n except FileExistsError:\n pass\n finally:\n os.unlink(temporary, dir_fd=state)\n os.close(state)\nfinally:\n os.close(root)\n`;\n\nexport const materializeSandboxSeeds = async (args: {\n sandbox: Pick<SandboxSessionIface, 'run'>;\n root: string;\n files: Record<string, string>;\n}): Promise<void> => {\n if (Object.keys(args.files).length === 0) return;\n if (!args.root.startsWith('/')) throw new Error('workspace seed root must be absolute');\n const result = await args.sandbox.run({\n command: 'python3',\n args: ['-c', SANDBOX_SEED_SCRIPT],\n cwd: '/',\n stdin: new ReadableStream<Uint8Array>({\n start: (controller) => {\n const bytes = new TextEncoder().encode(\n JSON.stringify({ root: args.root, files: args.files }),\n );\n for (let offset = 0; offset < bytes.byteLength; offset += 64 * 1024)\n controller.enqueue(bytes.subarray(offset, offset + 64 * 1024));\n controller.close();\n },\n }),\n timeoutMs: 60_000,\n });\n if (result.exitCode !== 0)\n throw new Error(`workspace seeding failed: ${result.stderr.trim().slice(-2000)}`);\n};\n\nexport const sandboxSeedArtifactSchema = z.object({\n seedFiles: sandboxSeedFilesSchema.default({}),\n seedSourceRevision: z.string().optional(),\n seedHash: z.string().optional(),\n});\n\nconst seedHash = async (files: Record<string, string>): Promise<string> => {\n const digest = await crypto.subtle.digest(\n 'SHA-256',\n new TextEncoder().encode(sandboxSeedIdentity(files)),\n );\n return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, '0')).join('');\n};\n\nexport const sandboxSeedArtifact = async (\n ctx: SandboxPrepareContextIface,\n files: Record<string, string>,\n): Promise<z.output<typeof sandboxSeedArtifactSchema>> => {\n if (ctx.preparation == null || Object.keys(files).length === 0) return { seedFiles: files };\n if (ctx.preparation.sourceRevision !== ctx.sourceRevision)\n throw new Error('preparation resource revision does not match');\n return { seedFiles: {}, seedSourceRevision: ctx.sourceRevision, seedHash: await seedHash(files) };\n};\n\nexport const sandboxSeedFilesForStart = async (\n ctx: SandboxStartContextIface,\n artifact: z.output<typeof sandboxSeedArtifactSchema>,\n): Promise<Record<string, string>> => {\n if (artifact.seedSourceRevision == null) return artifact.seedFiles;\n if (ctx.preparation?.sourceRevision !== artifact.seedSourceRevision)\n throw new Error('pinned sandbox seed resource source is unavailable');\n const files = sandboxSeedFiles(await ctx.preparation.read());\n if (artifact.seedHash == null || (await seedHash(files)) !== artifact.seedHash)\n throw new Error('pinned sandbox seed resource identity does not match the artifact');\n return files;\n};\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }