@multiplayer-app/agent 0.1.19 → 0.1.21

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 (308) hide show
  1. package/README.md +14 -7
  2. package/dist/agent/definition.d.ts +13 -0
  3. package/dist/agent/definition.d.ts.map +1 -1
  4. package/dist/agent/definition.test.js +8 -3
  5. package/dist/agent/definition.test.js.map +1 -1
  6. package/dist/agent/profiles/coding.d.ts +1 -1
  7. package/dist/agent/profiles/coding.d.ts.map +1 -1
  8. package/dist/agent/profiles/coding.js +21 -4
  9. package/dist/agent/profiles/coding.js.map +1 -1
  10. package/dist/agent/profiles/index.js +1 -1
  11. package/dist/agent/profiles/index.js.map +1 -1
  12. package/dist/agent/profiles/research.d.ts.map +1 -1
  13. package/dist/agent/profiles/research.js +23 -1
  14. package/dist/agent/profiles/research.js.map +1 -1
  15. package/dist/agent/turn-history.d.ts +40 -0
  16. package/dist/agent/turn-history.d.ts.map +1 -0
  17. package/dist/agent/turn-history.js +167 -0
  18. package/dist/agent/turn-history.js.map +1 -0
  19. package/dist/agent/turn-runner.d.ts +22 -1
  20. package/dist/agent/turn-runner.d.ts.map +1 -1
  21. package/dist/agent/turn-runner.js +162 -79
  22. package/dist/agent/turn-runner.js.map +1 -1
  23. package/dist/app/app-host.d.ts +57 -0
  24. package/dist/app/app-host.d.ts.map +1 -0
  25. package/dist/app/app-host.js +252 -0
  26. package/dist/app/app-host.js.map +1 -0
  27. package/dist/app/app-host.test.d.ts +2 -0
  28. package/dist/app/app-host.test.d.ts.map +1 -0
  29. package/dist/app/app-host.test.js +639 -0
  30. package/dist/app/app-host.test.js.map +1 -0
  31. package/dist/app/config.d.ts +196 -0
  32. package/dist/app/config.d.ts.map +1 -0
  33. package/dist/app/config.js +362 -0
  34. package/dist/app/config.js.map +1 -0
  35. package/dist/app/config.test.d.ts +2 -0
  36. package/dist/app/config.test.d.ts.map +1 -0
  37. package/dist/app/config.test.js +224 -0
  38. package/dist/app/config.test.js.map +1 -0
  39. package/dist/app/detect.d.ts +68 -0
  40. package/dist/app/detect.d.ts.map +1 -0
  41. package/dist/app/detect.js +449 -0
  42. package/dist/app/detect.js.map +1 -0
  43. package/dist/app/detect.test.d.ts +2 -0
  44. package/dist/app/detect.test.d.ts.map +1 -0
  45. package/dist/app/detect.test.js +267 -0
  46. package/dist/app/detect.test.js.map +1 -0
  47. package/dist/app/env.d.ts +5 -0
  48. package/dist/app/env.d.ts.map +1 -0
  49. package/dist/app/env.js +22 -0
  50. package/dist/app/env.js.map +1 -0
  51. package/dist/app/functions-cli.d.ts +3 -0
  52. package/dist/app/functions-cli.d.ts.map +1 -0
  53. package/dist/app/functions-cli.js +27 -0
  54. package/dist/app/functions-cli.js.map +1 -0
  55. package/dist/app/functions-host.d.ts +15 -0
  56. package/dist/app/functions-host.d.ts.map +1 -0
  57. package/dist/app/functions-host.js +276 -0
  58. package/dist/app/functions-host.js.map +1 -0
  59. package/dist/app/functions-host.test.d.ts +2 -0
  60. package/dist/app/functions-host.test.d.ts.map +1 -0
  61. package/dist/app/functions-host.test.js +117 -0
  62. package/dist/app/functions-host.test.js.map +1 -0
  63. package/dist/app/functions-routes.d.ts +23 -0
  64. package/dist/app/functions-routes.d.ts.map +1 -0
  65. package/dist/app/functions-routes.js +85 -0
  66. package/dist/app/functions-routes.js.map +1 -0
  67. package/dist/app/functions-routes.test.d.ts +2 -0
  68. package/dist/app/functions-routes.test.d.ts.map +1 -0
  69. package/dist/app/functions-routes.test.js +40 -0
  70. package/dist/app/functions-routes.test.js.map +1 -0
  71. package/dist/app/manifest.d.ts +17 -0
  72. package/dist/app/manifest.d.ts.map +1 -0
  73. package/dist/app/manifest.js +64 -0
  74. package/dist/app/manifest.js.map +1 -0
  75. package/dist/app/manifest.test.d.ts +2 -0
  76. package/dist/app/manifest.test.d.ts.map +1 -0
  77. package/dist/app/manifest.test.js +173 -0
  78. package/dist/app/manifest.test.js.map +1 -0
  79. package/dist/app/release-artifacts.d.ts +39 -0
  80. package/dist/app/release-artifacts.d.ts.map +1 -0
  81. package/dist/app/release-artifacts.js +229 -0
  82. package/dist/app/release-artifacts.js.map +1 -0
  83. package/dist/app/release-artifacts.test.d.ts +2 -0
  84. package/dist/app/release-artifacts.test.d.ts.map +1 -0
  85. package/dist/app/release-artifacts.test.js +295 -0
  86. package/dist/app/release-artifacts.test.js.map +1 -0
  87. package/dist/app/route-pattern.d.ts +23 -0
  88. package/dist/app/route-pattern.d.ts.map +1 -0
  89. package/dist/app/route-pattern.js +339 -0
  90. package/dist/app/route-pattern.js.map +1 -0
  91. package/dist/app/route-pattern.test.d.ts +2 -0
  92. package/dist/app/route-pattern.test.d.ts.map +1 -0
  93. package/dist/app/route-pattern.test.js +187 -0
  94. package/dist/app/route-pattern.test.js.map +1 -0
  95. package/dist/app/rules.d.ts +61 -0
  96. package/dist/app/rules.d.ts.map +1 -0
  97. package/dist/app/rules.js +90 -0
  98. package/dist/app/rules.js.map +1 -0
  99. package/dist/app/rules.test.d.ts +2 -0
  100. package/dist/app/rules.test.d.ts.map +1 -0
  101. package/dist/app/rules.test.js +69 -0
  102. package/dist/app/rules.test.js.map +1 -0
  103. package/dist/app/runner.d.ts +109 -0
  104. package/dist/app/runner.d.ts.map +1 -0
  105. package/dist/app/runner.js +429 -0
  106. package/dist/app/runner.js.map +1 -0
  107. package/dist/app/site.d.ts +73 -0
  108. package/dist/app/site.d.ts.map +1 -0
  109. package/dist/app/site.js +161 -0
  110. package/dist/app/site.js.map +1 -0
  111. package/dist/app/site.test.d.ts +2 -0
  112. package/dist/app/site.test.d.ts.map +1 -0
  113. package/dist/app/site.test.js +291 -0
  114. package/dist/app/site.test.js.map +1 -0
  115. package/dist/app/static-server.d.ts +20 -0
  116. package/dist/app/static-server.d.ts.map +1 -0
  117. package/dist/app/static-server.js +145 -0
  118. package/dist/app/static-server.js.map +1 -0
  119. package/dist/context-pruning.d.ts +2 -0
  120. package/dist/context-pruning.d.ts.map +1 -1
  121. package/dist/context-pruning.js +3 -2
  122. package/dist/context-pruning.js.map +1 -1
  123. package/dist/models/usage.d.ts +6 -0
  124. package/dist/models/usage.d.ts.map +1 -1
  125. package/dist/models/usage.js +13 -0
  126. package/dist/models/usage.js.map +1 -1
  127. package/dist/persistence/conversation-store.d.ts +21 -0
  128. package/dist/persistence/conversation-store.d.ts.map +1 -0
  129. package/dist/persistence/conversation-store.js +59 -0
  130. package/dist/persistence/conversation-store.js.map +1 -0
  131. package/dist/persistence/conversation-store.test.d.ts +2 -0
  132. package/dist/persistence/conversation-store.test.d.ts.map +1 -0
  133. package/dist/persistence/conversation-store.test.js +98 -0
  134. package/dist/persistence/conversation-store.test.js.map +1 -0
  135. package/dist/persistence/git-sync.d.ts +14 -1
  136. package/dist/persistence/git-sync.d.ts.map +1 -1
  137. package/dist/persistence/git-sync.js +73 -17
  138. package/dist/persistence/git-sync.js.map +1 -1
  139. package/dist/persistence/git-sync.test.js +155 -6
  140. package/dist/persistence/git-sync.test.js.map +1 -1
  141. package/dist/persistence/snapshot-sync.d.ts +19 -2
  142. package/dist/persistence/snapshot-sync.d.ts.map +1 -1
  143. package/dist/persistence/snapshot-sync.js +194 -83
  144. package/dist/persistence/snapshot-sync.js.map +1 -1
  145. package/dist/persistence/snapshot-sync.test.js +145 -27
  146. package/dist/persistence/snapshot-sync.test.js.map +1 -1
  147. package/dist/persistence/workspace.d.ts +3 -0
  148. package/dist/persistence/workspace.d.ts.map +1 -1
  149. package/dist/persistence/workspace.js +1 -0
  150. package/dist/persistence/workspace.js.map +1 -1
  151. package/dist/research/extract-texts.d.ts.map +1 -1
  152. package/dist/research/extract-texts.js +34 -16
  153. package/dist/research/extract-texts.js.map +1 -1
  154. package/dist/research/filingramp/attachment-tools.d.ts.map +1 -1
  155. package/dist/research/filingramp/attachment-tools.js +7 -4
  156. package/dist/research/filingramp/attachment-tools.js.map +1 -1
  157. package/dist/research/filingramp/shared.d.ts.map +1 -1
  158. package/dist/research/filingramp/shared.js +5 -5
  159. package/dist/research/filingramp/shared.js.map +1 -1
  160. package/dist/research/prompt.d.ts.map +1 -1
  161. package/dist/research/prompt.js +2 -1
  162. package/dist/research/prompt.js.map +1 -1
  163. package/dist/runtime/app-mode.d.ts +10 -0
  164. package/dist/runtime/app-mode.d.ts.map +1 -0
  165. package/dist/runtime/app-mode.js +172 -0
  166. package/dist/runtime/app-mode.js.map +1 -0
  167. package/dist/runtime/app-mode.test.d.ts +2 -0
  168. package/dist/runtime/app-mode.test.d.ts.map +1 -0
  169. package/dist/runtime/app-mode.test.js +130 -0
  170. package/dist/runtime/app-mode.test.js.map +1 -0
  171. package/dist/runtime/app-rehearsal.d.ts +2 -0
  172. package/dist/runtime/app-rehearsal.d.ts.map +1 -0
  173. package/dist/runtime/app-rehearsal.js +56 -0
  174. package/dist/runtime/app-rehearsal.js.map +1 -0
  175. package/dist/runtime/build-mode.d.ts +12 -0
  176. package/dist/runtime/build-mode.d.ts.map +1 -0
  177. package/dist/runtime/build-mode.js +116 -0
  178. package/dist/runtime/build-mode.js.map +1 -0
  179. package/dist/runtime/build-mode.test.d.ts +2 -0
  180. package/dist/runtime/build-mode.test.d.ts.map +1 -0
  181. package/dist/runtime/build-mode.test.js +121 -0
  182. package/dist/runtime/build-mode.test.js.map +1 -0
  183. package/dist/runtime/cli.js +7 -2
  184. package/dist/runtime/cli.js.map +1 -1
  185. package/dist/runtime/config.d.ts +4 -0
  186. package/dist/runtime/config.d.ts.map +1 -1
  187. package/dist/runtime/config.js +13 -2
  188. package/dist/runtime/config.js.map +1 -1
  189. package/dist/runtime/guest-server.d.ts +3 -0
  190. package/dist/runtime/guest-server.d.ts.map +1 -0
  191. package/dist/runtime/{lambda-microvm.js → guest-server.js} +49 -18
  192. package/dist/runtime/guest-server.js.map +1 -0
  193. package/dist/runtime/image-hooks.d.ts +5 -0
  194. package/dist/runtime/image-hooks.d.ts.map +1 -0
  195. package/dist/runtime/image-hooks.js +68 -0
  196. package/dist/runtime/image-hooks.js.map +1 -0
  197. package/dist/runtime/image-hooks.test.d.ts +2 -0
  198. package/dist/runtime/image-hooks.test.d.ts.map +1 -0
  199. package/dist/runtime/image-hooks.test.js +74 -0
  200. package/dist/runtime/image-hooks.test.js.map +1 -0
  201. package/dist/runtime/index.d.ts +8 -3
  202. package/dist/runtime/index.d.ts.map +1 -1
  203. package/dist/runtime/index.js +53 -35
  204. package/dist/runtime/index.js.map +1 -1
  205. package/dist/runtime/listening-ports.d.ts +13 -0
  206. package/dist/runtime/listening-ports.d.ts.map +1 -0
  207. package/dist/runtime/listening-ports.js +78 -0
  208. package/dist/runtime/listening-ports.js.map +1 -0
  209. package/dist/runtime/listening-ports.test.d.ts +2 -0
  210. package/dist/runtime/listening-ports.test.d.ts.map +1 -0
  211. package/dist/runtime/listening-ports.test.js +39 -0
  212. package/dist/runtime/listening-ports.test.js.map +1 -0
  213. package/dist/runtime/preview-proxy.d.ts +56 -0
  214. package/dist/runtime/preview-proxy.d.ts.map +1 -0
  215. package/dist/runtime/preview-proxy.js +302 -0
  216. package/dist/runtime/preview-proxy.js.map +1 -0
  217. package/dist/runtime/preview-proxy.test.d.ts +2 -0
  218. package/dist/runtime/preview-proxy.test.d.ts.map +1 -0
  219. package/dist/runtime/preview-proxy.test.js +122 -0
  220. package/dist/runtime/preview-proxy.test.js.map +1 -0
  221. package/dist/runtime/session-mode.d.ts +3 -0
  222. package/dist/runtime/session-mode.d.ts.map +1 -0
  223. package/dist/runtime/session-mode.js +60 -0
  224. package/dist/runtime/session-mode.js.map +1 -0
  225. package/dist/runtime/workload.d.ts +44 -0
  226. package/dist/runtime/workload.d.ts.map +1 -0
  227. package/dist/runtime/workload.js +222 -0
  228. package/dist/runtime/workload.js.map +1 -0
  229. package/dist/runtime/workload.test.d.ts +2 -0
  230. package/dist/runtime/workload.test.d.ts.map +1 -0
  231. package/dist/runtime/workload.test.js +235 -0
  232. package/dist/runtime/workload.test.js.map +1 -0
  233. package/dist/session/conversation.d.ts +10 -2
  234. package/dist/session/conversation.d.ts.map +1 -1
  235. package/dist/session/conversation.js +40 -12
  236. package/dist/session/conversation.js.map +1 -1
  237. package/dist/session/conversation.test.js +2 -3
  238. package/dist/session/conversation.test.js.map +1 -1
  239. package/dist/session/index.d.ts +1 -1
  240. package/dist/session/index.d.ts.map +1 -1
  241. package/dist/session/index.js +2 -1
  242. package/dist/session/index.js.map +1 -1
  243. package/dist/session/runtime.d.ts +20 -3
  244. package/dist/session/runtime.d.ts.map +1 -1
  245. package/dist/session/runtime.js +97 -16
  246. package/dist/session/runtime.js.map +1 -1
  247. package/dist/session/runtime.test.js +18 -7
  248. package/dist/session/runtime.test.js.map +1 -1
  249. package/dist/session/tools.d.ts.map +1 -1
  250. package/dist/session/tools.js +5 -4
  251. package/dist/session/tools.js.map +1 -1
  252. package/dist/task/loop.d.ts.map +1 -1
  253. package/dist/task/loop.js +6 -4
  254. package/dist/task/loop.js.map +1 -1
  255. package/dist/tools/exec-tools.d.ts +12 -0
  256. package/dist/tools/exec-tools.d.ts.map +1 -1
  257. package/dist/tools/exec-tools.js +46 -3
  258. package/dist/tools/exec-tools.js.map +1 -1
  259. package/dist/tools/exec-tools.test.d.ts +2 -0
  260. package/dist/tools/exec-tools.test.d.ts.map +1 -0
  261. package/dist/tools/exec-tools.test.js +48 -0
  262. package/dist/tools/exec-tools.test.js.map +1 -0
  263. package/dist/tools/fs-tools.d.ts.map +1 -1
  264. package/dist/tools/fs-tools.js +5 -5
  265. package/dist/tools/fs-tools.js.map +1 -1
  266. package/dist/transport/link.d.ts.map +1 -1
  267. package/dist/transport/link.js +16 -5
  268. package/dist/transport/link.js.map +1 -1
  269. package/dist/transport/link.test.js +24 -0
  270. package/dist/transport/link.test.js.map +1 -1
  271. package/dist/transport/protocol.d.ts +190 -3
  272. package/dist/transport/protocol.d.ts.map +1 -1
  273. package/dist/transport/protocol.js +147 -7
  274. package/dist/transport/protocol.js.map +1 -1
  275. package/dist/transport/protocol.test.js +41 -0
  276. package/dist/transport/protocol.test.js.map +1 -1
  277. package/dist/workspace-sync/eligibility.d.ts +14 -0
  278. package/dist/workspace-sync/eligibility.d.ts.map +1 -0
  279. package/dist/workspace-sync/eligibility.js +53 -0
  280. package/dist/workspace-sync/eligibility.js.map +1 -0
  281. package/dist/workspace-sync/merge.d.ts +15 -0
  282. package/dist/workspace-sync/merge.d.ts.map +1 -0
  283. package/dist/workspace-sync/merge.js +66 -0
  284. package/dist/workspace-sync/merge.js.map +1 -0
  285. package/dist/workspace-sync/merge.test.d.ts +2 -0
  286. package/dist/workspace-sync/merge.test.d.ts.map +1 -0
  287. package/dist/workspace-sync/merge.test.js +28 -0
  288. package/dist/workspace-sync/merge.test.js.map +1 -0
  289. package/dist/workspace-sync/workspace-sync.d.ts +48 -0
  290. package/dist/workspace-sync/workspace-sync.d.ts.map +1 -0
  291. package/dist/workspace-sync/workspace-sync.js +308 -0
  292. package/dist/workspace-sync/workspace-sync.js.map +1 -0
  293. package/dist/workspace-sync/workspace-sync.test.d.ts +2 -0
  294. package/dist/workspace-sync/workspace-sync.test.d.ts.map +1 -0
  295. package/dist/workspace-sync/workspace-sync.test.js +111 -0
  296. package/dist/workspace-sync/workspace-sync.test.js.map +1 -0
  297. package/dist/workspace-sync/write-drafts.d.ts +24 -0
  298. package/dist/workspace-sync/write-drafts.d.ts.map +1 -0
  299. package/dist/workspace-sync/write-drafts.js +87 -0
  300. package/dist/workspace-sync/write-drafts.js.map +1 -0
  301. package/dist/workspace-sync/write-drafts.test.d.ts +2 -0
  302. package/dist/workspace-sync/write-drafts.test.d.ts.map +1 -0
  303. package/dist/workspace-sync/write-drafts.test.js +36 -0
  304. package/dist/workspace-sync/write-drafts.test.js.map +1 -0
  305. package/package.json +12 -2
  306. package/dist/runtime/lambda-microvm.d.ts +0 -3
  307. package/dist/runtime/lambda-microvm.d.ts.map +0 -1
  308. package/dist/runtime/lambda-microvm.js.map +0 -1
@@ -0,0 +1,302 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.GUEST_HTTP_PORT = void 0;
7
+ exports.connectLocal = connectLocal;
8
+ exports.localRequestHeaders = localRequestHeaders;
9
+ exports.publicLocation = publicLocation;
10
+ exports.setAppHandler = setAppHandler;
11
+ exports.serveAppUnaddressed = serveAppUnaddressed;
12
+ exports.proxyToPort = proxyToPort;
13
+ exports.guardRequests = guardRequests;
14
+ exports.guardUpgrades = guardUpgrades;
15
+ exports.proxyPreviewRequest = proxyPreviewRequest;
16
+ exports.proxyAppRequest = proxyAppRequest;
17
+ exports.proxyPreviewUpgrade = proxyPreviewUpgrade;
18
+ exports.upgradeToPort = upgradeToPort;
19
+ exports.startPreviewServer = startPreviewServer;
20
+ // The guest end of the live preview. Every engine reaches only the guest's port 8080; a request
21
+ // the gateway addressed to <vmId>-<port>.apps.<domain> arrives there carrying PREVIEW_PORT_HEADER
22
+ // and goes on to whatever listens on localhost:<port>, WebSocket upgrades (hot reload) included.
23
+ // A session's own URL carries APP_PREVIEW_TARGET instead: the workspace's app (src/app) routes it
24
+ // (src/app), else it goes to the default port.
25
+ // Dev servers bind localhost and check Host and Origin by default, so the request is made to look
26
+ // local: Host becomes localhost:<port>, an Origin or Referer naming the public preview names the
27
+ // local one instead, and a redirect to localhost points back at the public preview.
28
+ const http_1 = __importDefault(require("http"));
29
+ const net_1 = __importDefault(require("net"));
30
+ const protocol_1 = require("../transport/protocol");
31
+ const listening_ports_1 = require("./listening-ports");
32
+ /** Where the guest serves its lifecycle hooks and this proxy. */
33
+ exports.GUEST_HTTP_PORT = 8080;
34
+ // IPv4 first; Vite on `localhost` can end up bound to ::1 only.
35
+ const LOOPBACK_HOSTS = ['127.0.0.1', '::1'];
36
+ // Per connection, never forwarded: the proxy has its own connection to each side.
37
+ const HOP_BY_HOP_HEADERS = ['connection', 'keep-alive', 'proxy-connection', 'transfer-encoding', 'upgrade'];
38
+ /** A connected socket to whatever listens on loopback `port`. */
39
+ function connectLocal(port) {
40
+ return new Promise((resolve, reject) => {
41
+ const attempt = (index) => {
42
+ const socket = net_1.default.connect({ host: LOOPBACK_HOSTS[index], port });
43
+ const onError = (error) => {
44
+ socket.destroy();
45
+ if (index + 1 < LOOPBACK_HOSTS.length)
46
+ attempt(index + 1);
47
+ else
48
+ reject(error);
49
+ };
50
+ socket.once('error', onError);
51
+ socket.once('connect', () => {
52
+ socket.off('error', onError);
53
+ resolve(socket);
54
+ });
55
+ };
56
+ attempt(0);
57
+ });
58
+ }
59
+ function first(value) {
60
+ return Array.isArray(value) ? value[0] : value;
61
+ }
62
+ /** The preview's public origin, from the X-Forwarded-* headers the gateway sets. */
63
+ function publicOrigin(headers) {
64
+ const host = first(headers['x-forwarded-host']);
65
+ if (!host)
66
+ return undefined;
67
+ return `${first(headers['x-forwarded-proto']) === 'https' ? 'https' : 'http'}://${host}`;
68
+ }
69
+ /** `value` with the origin `from` swapped for `to`, or undefined when `value` isn't on `from`. */
70
+ function replacePrefix(value, from, to) {
71
+ if (!value.startsWith(from))
72
+ return undefined;
73
+ const rest = value.slice(from.length);
74
+ return rest === '' || /^[/?#]/.test(rest) ? to + rest : undefined;
75
+ }
76
+ /** The request headers as the app expects them from a browser on the guest itself. */
77
+ function localRequestHeaders(headers, port) {
78
+ const local = `http://localhost:${port}`;
79
+ const out = { ...headers, host: `localhost:${port}` };
80
+ delete out[protocol_1.PREVIEW_PORT_HEADER];
81
+ const origin = publicOrigin(headers);
82
+ if (origin) {
83
+ if (headers.origin === origin)
84
+ out.origin = local;
85
+ const referer = typeof headers.referer === 'string' ? replacePrefix(headers.referer, origin, local) : undefined;
86
+ if (referer)
87
+ out.referer = referer;
88
+ }
89
+ return out;
90
+ }
91
+ /** A redirect to the app's own local address, pointed at the public preview instead. */
92
+ function publicLocation(location, port, origin) {
93
+ for (const host of [`localhost:${port}`, `127.0.0.1:${port}`]) {
94
+ const replaced = replacePrefix(location, `http://${host}`, origin);
95
+ if (replaced)
96
+ return replaced;
97
+ }
98
+ return location;
99
+ }
100
+ function withoutHopByHop(headers) {
101
+ const out = { ...headers };
102
+ for (const name of HOP_BY_HOP_HEADERS)
103
+ delete out[name];
104
+ return out;
105
+ }
106
+ function htmlPage(res, status, title, text) {
107
+ const body = `<!doctype html><title>${title}</title><p>${text}</p>`;
108
+ res.writeHead(status, { 'Content-Type': 'text/html; charset=utf-8', 'Content-Length': Buffer.byteLength(body) });
109
+ res.end(body);
110
+ }
111
+ function nothingListening(res, port) {
112
+ htmlPage(res, 502, `Nothing on port ${port}`, `Nothing is listening on port ${port} in the session VM yet. Start the app, then reload.`);
113
+ }
114
+ let appHandler;
115
+ let appUnaddressed = false;
116
+ function setAppHandler(handler) {
117
+ appHandler = handler;
118
+ }
119
+ /**
120
+ * A deployment (AGENT_MODE=app) is its app: requests without PREVIEW_PORT_HEADER go to it too
121
+ * (proxyAppRequest), not only a session URL's.
122
+ */
123
+ function serveAppUnaddressed() {
124
+ appUnaddressed = true;
125
+ }
126
+ /**
127
+ * Forwards a request to whatever listens on loopback `port`, as from a browser on the guest.
128
+ * `extraHeaders` go on the answer, over any of the same name (the app's builder.json `headers`).
129
+ */
130
+ function proxyToPort(req, res, port, extraHeaders = []) {
131
+ const origin = publicOrigin(req.headers);
132
+ connectLocal(port).then((socket) => {
133
+ const upstream = http_1.default.request({
134
+ method: req.method,
135
+ path: req.url,
136
+ headers: withoutHopByHop(localRequestHeaders(req.headers, port)),
137
+ createConnection: () => socket,
138
+ }, (response) => {
139
+ var _a;
140
+ const headers = withoutHopByHop(response.headers);
141
+ if (origin && typeof headers.location === 'string')
142
+ headers.location = publicLocation(headers.location, port, origin);
143
+ for (const { key, value } of extraHeaders)
144
+ headers[key.toLowerCase()] = value;
145
+ res.writeHead((_a = response.statusCode) !== null && _a !== void 0 ? _a : 502, headers);
146
+ response.pipe(res);
147
+ });
148
+ upstream.on('error', () => {
149
+ if (res.headersSent)
150
+ res.destroy();
151
+ else
152
+ nothingListening(res, port);
153
+ });
154
+ res.on('close', () => upstream.destroy());
155
+ req.pipe(upstream);
156
+ }, () => nothingListening(res, port));
157
+ }
158
+ /** A session URL with no app: the default port (DEFAULT_APP_PORT when it listens, else the lowest). */
159
+ function proxyToDefaultPort(req, res) {
160
+ (0, listening_ports_1.listListeningPorts)().then((ports) => {
161
+ const port = (0, protocol_1.defaultAppPort)(ports);
162
+ if (port === undefined)
163
+ htmlPage(res, 502, 'Nothing running', 'Nothing is listening in the session VM yet. Start the app, then reload.');
164
+ else
165
+ proxyToPort(req, res, port);
166
+ }, () => htmlPage(res, 502, 'Nothing running', 'The session VM could not list its listening ports.'));
167
+ }
168
+ /**
169
+ * The guest's request handler, made safe: it runs the agent and serves the app, so a throw from one
170
+ * request, which nothing above would catch, must fail that request and not take all of it down.
171
+ */
172
+ function guardRequests(handler) {
173
+ return (req, res) => {
174
+ try {
175
+ handler(req, res);
176
+ }
177
+ catch (error) {
178
+ console.error('[guest] request failed:', error instanceof Error ? error.message : error);
179
+ if (!res.headersSent)
180
+ res.writeHead(500);
181
+ res.end();
182
+ }
183
+ };
184
+ }
185
+ /** The same for an upgrade request. */
186
+ function guardUpgrades(handler) {
187
+ return (req, socket, head) => {
188
+ try {
189
+ handler(req, socket, head);
190
+ }
191
+ catch (error) {
192
+ console.error('[guest] upgrade failed:', error instanceof Error ? error.message : error);
193
+ socket.destroy();
194
+ }
195
+ };
196
+ }
197
+ /** Handles a preview request; false when the request isn't one (no PREVIEW_PORT_HEADER). */
198
+ function proxyPreviewRequest(req, res) {
199
+ if (!(protocol_1.PREVIEW_PORT_HEADER in req.headers))
200
+ return false;
201
+ const target = (0, protocol_1.parsePreviewTarget)(req.headers[protocol_1.PREVIEW_PORT_HEADER]);
202
+ if (target === undefined) {
203
+ res.writeHead(400);
204
+ res.end();
205
+ }
206
+ else if (target !== protocol_1.APP_PREVIEW_TARGET) {
207
+ proxyToPort(req, res, target);
208
+ }
209
+ else if (!(appHandler === null || appHandler === void 0 ? void 0 : appHandler.handleRequest(req, res))) {
210
+ proxyToDefaultPort(req, res);
211
+ }
212
+ return true;
213
+ }
214
+ /** In a deployment, any other request is the app's; false elsewhere (or until serveAppUnaddressed). */
215
+ function proxyAppRequest(req, res) {
216
+ if (!appUnaddressed)
217
+ return false;
218
+ if (!(appHandler === null || appHandler === void 0 ? void 0 : appHandler.handleRequest(req, res))) {
219
+ res.setHeader('Retry-After', '2');
220
+ htmlPage(res, 503, 'Starting', 'The app is starting. Reload in a moment.');
221
+ }
222
+ return true;
223
+ }
224
+ function requestHead(req, headers) {
225
+ let head = `${req.method} ${req.url} HTTP/1.1\r\n`;
226
+ for (const [name, value] of Object.entries(headers)) {
227
+ if (value === undefined)
228
+ continue;
229
+ for (const item of Array.isArray(value) ? value : [value])
230
+ head += `${name}: ${item}\r\n`;
231
+ }
232
+ return `${head}\r\n`;
233
+ }
234
+ /**
235
+ * Handles a preview WebSocket upgrade by splicing the two connections together once the
236
+ * request reaches the app; false when the request isn't one. The app answers the handshake.
237
+ */
238
+ function proxyPreviewUpgrade(req, socket, head) {
239
+ const addressed = protocol_1.PREVIEW_PORT_HEADER in req.headers;
240
+ if (!addressed && !appUnaddressed)
241
+ return false;
242
+ socket.on('error', () => socket.destroy());
243
+ // The HTTP server's sockets stay half-open after the client's FIN; a WebSocket never needs
244
+ // that, and an app that ignores the FIN must not keep the client's connection alive.
245
+ if (socket instanceof net_1.default.Socket)
246
+ socket.allowHalfOpen = false;
247
+ const target = addressed ? (0, protocol_1.parsePreviewTarget)(req.headers[protocol_1.PREVIEW_PORT_HEADER]) : protocol_1.APP_PREVIEW_TARGET;
248
+ if (target === undefined) {
249
+ socket.end('HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n');
250
+ }
251
+ else if (target !== protocol_1.APP_PREVIEW_TARGET) {
252
+ upgradeToPort(req, socket, head, target);
253
+ }
254
+ else if (!(appHandler === null || appHandler === void 0 ? void 0 : appHandler.handleUpgrade(req, socket, head))) {
255
+ if (!addressed)
256
+ socket.end('HTTP/1.1 503 Service Unavailable\r\nConnection: close\r\n\r\n');
257
+ else
258
+ (0, listening_ports_1.listListeningPorts)().then((ports) => {
259
+ const port = (0, protocol_1.defaultAppPort)(ports);
260
+ if (port === undefined)
261
+ socket.end('HTTP/1.1 502 Bad Gateway\r\nConnection: close\r\n\r\n');
262
+ else
263
+ upgradeToPort(req, socket, head, port);
264
+ }, () => socket.destroy());
265
+ }
266
+ return true;
267
+ }
268
+ /** Splices an upgrade request through to whatever listens on loopback `port`. */
269
+ function upgradeToPort(req, socket, head, port) {
270
+ connectLocal(port).then((upstream) => {
271
+ upstream.on('error', () => socket.destroy());
272
+ upstream.on('close', () => socket.destroy());
273
+ socket.on('close', () => upstream.destroy());
274
+ upstream.write(requestHead(req, localRequestHeaders(req.headers, port)));
275
+ if (head.length)
276
+ upstream.write(head);
277
+ upstream.pipe(socket);
278
+ socket.pipe(upstream);
279
+ }, () => socket.end('HTTP/1.1 502 Bad Gateway\r\nConnection: close\r\n\r\n'));
280
+ }
281
+ /**
282
+ * The preview proxy on its own, for entrypoints with no lifecycle hook server holding
283
+ * GUEST_HTTP_PORT (cli.ts: QEMU, Firecracker). Anything but a preview (or, in a deployment, the
284
+ * app) gets a 404.
285
+ */
286
+ function startPreviewServer(port = exports.GUEST_HTTP_PORT) {
287
+ const server = http_1.default.createServer(guardRequests((req, res) => {
288
+ if (proxyPreviewRequest(req, res) || proxyAppRequest(req, res))
289
+ return;
290
+ res.writeHead(404);
291
+ res.end();
292
+ }));
293
+ server.on('upgrade', guardUpgrades((req, socket, head) => {
294
+ if (!proxyPreviewUpgrade(req, socket, head))
295
+ socket.destroy();
296
+ }));
297
+ // An app the user started on this port first keeps it; the agent runs without previews then.
298
+ server.on('error', (error) => console.error(`[preview] cannot serve on ${port}:`, error.message));
299
+ server.listen(port);
300
+ return server;
301
+ }
302
+ //# sourceMappingURL=preview-proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview-proxy.js","sourceRoot":"","sources":["../../src/runtime/preview-proxy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=preview-proxy.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview-proxy.test.d.ts","sourceRoot":"","sources":["../../src/runtime/preview-proxy.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const strict_1 = __importDefault(require("node:assert/strict"));
7
+ const node_http_1 = __importDefault(require("node:http"));
8
+ const node_net_1 = __importDefault(require("node:net"));
9
+ const node_test_1 = require("node:test");
10
+ const protocol_1 = require("../transport/protocol");
11
+ const preview_proxy_1 = require("./preview-proxy");
12
+ const PUBLIC_HOST = '64b7f0c2e4b0a1a2b3c4d5e6-3000.vm.example.com';
13
+ const PUBLIC_ORIGIN = `https://${PUBLIC_HOST}`;
14
+ function listen(server) {
15
+ return new Promise((resolve) => server.listen(0, '127.0.0.1', () => resolve(server.address().port)));
16
+ }
17
+ function get(proxyPort, headers) {
18
+ return new Promise((resolve, reject) => {
19
+ node_http_1.default.get({ host: '127.0.0.1', port: proxyPort, path: '/page?x=1', headers }, (res) => {
20
+ let body = '';
21
+ res.on('data', (chunk) => (body += chunk));
22
+ res.on('end', () => { var _a; return resolve({ status: (_a = res.statusCode) !== null && _a !== void 0 ? _a : 0, headers: res.headers, body }); });
23
+ }).on('error', reject);
24
+ });
25
+ }
26
+ (0, node_test_1.describe)('preview proxy', () => {
27
+ let app;
28
+ let appPort;
29
+ let proxy;
30
+ let proxyPort;
31
+ (0, node_test_1.before)(async () => {
32
+ app = node_http_1.default.createServer((req, res) => {
33
+ if (req.url === '/old') {
34
+ res.writeHead(302, { Location: `http://localhost:${appPort}/new?y=2` });
35
+ res.end();
36
+ return;
37
+ }
38
+ res.writeHead(200, { 'Content-Type': 'application/json' });
39
+ res.end(JSON.stringify({ url: req.url, host: req.headers.host, origin: req.headers.origin, port: req.headers[protocol_1.PREVIEW_PORT_HEADER] }));
40
+ });
41
+ // A dev server's hot-reload socket: answers the handshake, then echoes.
42
+ app.on('upgrade', (req, socket) => {
43
+ socket.write(`HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nX-Seen-Host: ${req.headers.host}\r\n\r\n`);
44
+ socket.on('data', (data) => socket.write(data));
45
+ socket.on('end', () => socket.end());
46
+ });
47
+ appPort = await listen(app);
48
+ proxy = (0, preview_proxy_1.startPreviewServer)(0);
49
+ await new Promise((resolve) => proxy.once('listening', resolve));
50
+ proxyPort = proxy.address().port;
51
+ });
52
+ (0, node_test_1.after)(() => {
53
+ // The test client's keep-alive connections would hold both servers open.
54
+ for (const server of [app, proxy]) {
55
+ server.closeAllConnections();
56
+ server.close();
57
+ }
58
+ });
59
+ (0, node_test_1.it)('forwards to the app as a local request', async () => {
60
+ const res = await get(proxyPort, {
61
+ [protocol_1.PREVIEW_PORT_HEADER]: String(appPort),
62
+ 'x-forwarded-host': PUBLIC_HOST,
63
+ 'x-forwarded-proto': 'https',
64
+ origin: PUBLIC_ORIGIN,
65
+ });
66
+ strict_1.default.equal(res.status, 200);
67
+ strict_1.default.deepEqual(JSON.parse(res.body), {
68
+ url: '/page?x=1',
69
+ host: `localhost:${appPort}`,
70
+ origin: `http://localhost:${appPort}`,
71
+ });
72
+ });
73
+ (0, node_test_1.it)('points a redirect to localhost back at the public preview', () => {
74
+ strict_1.default.equal((0, preview_proxy_1.publicLocation)('http://localhost:3000/new?y=2', 3000, PUBLIC_ORIGIN), `${PUBLIC_ORIGIN}/new?y=2`);
75
+ strict_1.default.equal((0, preview_proxy_1.publicLocation)('http://127.0.0.1:3000', 3000, PUBLIC_ORIGIN), PUBLIC_ORIGIN);
76
+ strict_1.default.equal((0, preview_proxy_1.publicLocation)('http://localhost:30001/x', 3000, PUBLIC_ORIGIN), 'http://localhost:30001/x');
77
+ strict_1.default.equal((0, preview_proxy_1.publicLocation)('/relative', 3000, PUBLIC_ORIGIN), '/relative');
78
+ });
79
+ (0, node_test_1.it)('rewrites the app\'s own redirects on the way out', async () => {
80
+ const res = await new Promise((resolve, reject) => {
81
+ node_http_1.default.get({ host: '127.0.0.1', port: proxyPort, path: '/old', headers: {
82
+ [protocol_1.PREVIEW_PORT_HEADER]: String(appPort), 'x-forwarded-host': PUBLIC_HOST, 'x-forwarded-proto': 'https',
83
+ } }, resolve).on('error', reject);
84
+ });
85
+ res.resume();
86
+ strict_1.default.equal(res.statusCode, 302);
87
+ strict_1.default.equal(res.headers.location, `${PUBLIC_ORIGIN}/new?y=2`);
88
+ });
89
+ (0, node_test_1.it)('splices a WebSocket upgrade through to the app', async () => {
90
+ const client = node_net_1.default.connect(proxyPort, '127.0.0.1');
91
+ await new Promise((resolve) => client.once('connect', resolve));
92
+ client.write(`GET /hmr HTTP/1.1\r\nHost: ${PUBLIC_HOST}\r\nUpgrade: websocket\r\nConnection: Upgrade\r\n${protocol_1.PREVIEW_PORT_HEADER}: ${appPort}\r\n\r\n`);
93
+ let received = '';
94
+ const handshake = await new Promise((resolve) => {
95
+ client.on('data', (data) => {
96
+ received += data.toString();
97
+ if (received.includes('\r\n\r\n'))
98
+ resolve(received);
99
+ });
100
+ });
101
+ strict_1.default.match(handshake, /^HTTP\/1\.1 101/);
102
+ strict_1.default.match(handshake, new RegExp(`X-Seen-Host: localhost:${appPort}`));
103
+ received = '';
104
+ const echoed = new Promise((resolve) => client.on('data', () => received === 'frame' && resolve(received)));
105
+ client.write('frame');
106
+ strict_1.default.equal(await echoed, 'frame');
107
+ client.destroy();
108
+ });
109
+ (0, node_test_1.it)('says nothing is listening on a closed port, and rejects the guest\'s own ports', async () => {
110
+ const closed = node_net_1.default.createServer();
111
+ const closedPort = await listen(closed);
112
+ await new Promise((resolve) => closed.close(resolve));
113
+ const res = await get(proxyPort, { [protocol_1.PREVIEW_PORT_HEADER]: String(closedPort) });
114
+ strict_1.default.equal(res.status, 502);
115
+ strict_1.default.match(res.body, new RegExp(`port ${closedPort}`));
116
+ strict_1.default.equal((await get(proxyPort, { [protocol_1.PREVIEW_PORT_HEADER]: '8080' })).status, 400);
117
+ });
118
+ (0, node_test_1.it)('leaves requests without the preview header alone', async () => {
119
+ strict_1.default.equal((await get(proxyPort, {})).status, 404);
120
+ });
121
+ });
122
+ //# sourceMappingURL=preview-proxy.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview-proxy.test.js","sourceRoot":"","sources":["../../src/runtime/preview-proxy.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { RunningAgent } from './index';
2
+ export declare function startSessionOrTask(env: NodeJS.ProcessEnv): Promise<RunningAgent>;
3
+ //# sourceMappingURL=session-mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-mode.d.ts","sourceRoot":"","sources":["../../src/runtime/session-mode.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE3C,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CA2CtF"}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startSessionOrTask = startSessionOrTask;
4
+ // The agent's own modes: task mode runs once and resolves; session mode stays up and resolves with
5
+ // the running agent so lifecycle hooks can reach it.
6
+ const config_1 = require("./config");
7
+ const link_1 = require("../transport/link");
8
+ const loop_1 = require("../task/loop");
9
+ const reporter_1 = require("../transport/reporter");
10
+ const session_1 = require("../session");
11
+ const app_host_1 = require("../app/app-host");
12
+ const env_1 = require("../app/env");
13
+ const protocol_1 = require("../transport/protocol");
14
+ const listening_ports_1 = require("./listening-ports");
15
+ async function startSessionOrTask(env) {
16
+ const config = (0, config_1.loadConfigFromEnv)(env);
17
+ if (config.mode === 'session') {
18
+ const link = (0, link_1.createSessionLink)(config.sessionId, config.socketUrl, config.socketToken);
19
+ const session = await (0, session_1.runSessionAgent)(config, link).catch(async (error) => {
20
+ link.send({ type: 'error', message: `Workspace restore failed: ${error instanceof Error ? error.message : String(error)}` });
21
+ await link.close();
22
+ throw error;
23
+ });
24
+ // The live preview offers whatever listens in the guest, however it was started.
25
+ const stopWatchingPorts = (0, listening_ports_1.watchListeningPorts)((ports) => link.send({ type: 'ports', ports }));
26
+ // The workspace's app (detected, its builder.json written by the guest) runs from every boot,
27
+ // so the session URL works again after a stop, and starts after the turn that built it or
28
+ // changed how it runs; run_app restarts it (tools/exec-tools.ts). Its status routes the
29
+ // session URL to it.
30
+ const app = (0, app_host_1.appHostFor)(session.workspaceDir, () => ({ dir: session.workspaceDir, mode: 'dev', env: (0, env_1.sessionAppEnv)(env), schemaUrl: env[protocol_1.AGENT_ENV.APP_SCHEMA_URL] }));
31
+ const reportFailure = (error) => console.error('[app] failed to start:', error instanceof Error ? error.message : error);
32
+ app.onStatus((status) => link.send({ type: 'app', app: status }));
33
+ void app.start().catch(reportFailure);
34
+ const stopRefreshing = session.onTurnEnd(() => void app.refresh().catch(reportFailure));
35
+ return {
36
+ config,
37
+ session,
38
+ async close() {
39
+ stopWatchingPorts();
40
+ stopRefreshing();
41
+ try {
42
+ await app.stop();
43
+ await session.stop();
44
+ }
45
+ finally {
46
+ await link.close();
47
+ }
48
+ },
49
+ };
50
+ }
51
+ const reporter = (0, reporter_1.createReporter)(config.socketUrl, config.socketToken, config.sessionId);
52
+ try {
53
+ await (0, loop_1.runAgentLoop)(config, reporter);
54
+ }
55
+ finally {
56
+ await reporter.close();
57
+ }
58
+ return { config, async close() { } };
59
+ }
60
+ //# sourceMappingURL=session-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-mode.js","sourceRoot":"","sources":["../../src/runtime/session-mode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import type { FileHandle } from 'node:fs/promises';
2
+ import type { Readable, Writable } from 'node:stream';
3
+ export declare const WORKLOAD_USER = "agent";
4
+ export declare const WORKLOAD_UID = 1001;
5
+ export declare const WORKLOAD_GID = 1001;
6
+ export declare const WORKLOAD_HOME = "/home/agent";
7
+ /** The identity to start a workload process with, for spawn's options. */
8
+ export declare function workloadIdentity(): {
9
+ uid: number;
10
+ gid: number;
11
+ } | undefined;
12
+ /** A workload's env: its own home, since root's isn't readable to it (npm's and pip's caches live there). */
13
+ export declare function workloadEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
14
+ /** Writes a workspace file, and any folder it needs. */
15
+ export declare function writeWorkloadFile(target: string, content: Buffer | string): Promise<void>;
16
+ export declare function appendWorkloadFile(target: string, content: Buffer | string): Promise<void>;
17
+ export declare function removeWorkloadFile(target: string): Promise<void>;
18
+ export declare function makeWorkloadDir(dir: string): Promise<void>;
19
+ /** A file an app's output keeps being appended to, for as long as it runs. */
20
+ export declare function workloadAppendStream(target: string): Writable;
21
+ /**
22
+ * Gives a tree the runtime fetched to the workload. Only before any workload runs: nothing can
23
+ * change it meanwhile, and -h with -R never follows a link left there by an earlier run on this disk.
24
+ */
25
+ export declare function handOverToWorkload(dir: string): Promise<void>;
26
+ /** Writes `folders` of `dir` to `target` as a compressed archive, leaving out what `exclude` names at any depth. */
27
+ export declare function packAsWorkload(dir: string, folders: string[], exclude: string[], target: Writable): Promise<void>;
28
+ /** Unpacks what packAsWorkload wrote into `dir`, which the workload already owns. */
29
+ export declare function unpackAsWorkload(dir: string, source: Readable): Promise<void>;
30
+ /**
31
+ * Whether `target` is `root` or somewhere under it, by path alone: a neighbour that only shares its
32
+ * prefix isn't. Both absolute and normalized, and real paths where a link could lead out.
33
+ */
34
+ export declare function isInsideDir(root: string, target: string): boolean;
35
+ /**
36
+ * Opens a file to read, for the runtime: only if what actually opened is a regular file under
37
+ * `root`. Checking first and opening after would leave a gap to swap a link in, so it asks the
38
+ * kernel what this open reached. Anything else reads as missing, which callers already handle.
39
+ */
40
+ export declare function openInside(root: string, file: string, flags?: number): Promise<FileHandle>;
41
+ export declare function readInside(root: string, file: string, flags?: number): Promise<Buffer>;
42
+ /** A directory's real path, if it's really under `root` (listing one follows links too). */
43
+ export declare function realDirInside(root: string, dir: string): Promise<string>;
44
+ //# sourceMappingURL=workload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workload.d.ts","sourceRoot":"","sources":["../../src/runtime/workload.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAElD,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAIrD,eAAO,MAAM,aAAa,UAAU,CAAA;AACpC,eAAO,MAAM,YAAY,OAAO,CAAA;AAChC,eAAO,MAAM,YAAY,OAAO,CAAA;AAChC,eAAO,MAAM,aAAa,gBAAgB,CAAA;AAE1C,0EAA0E;AAC1E,wBAAgB,gBAAgB,IAAI;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAE3E;AAED,6GAA6G;AAC7G,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAErE;AA6BD,wDAAwD;AACxD,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/F;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIhG;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGtE;AAED,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhE;AAED,8EAA8E;AAC9E,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAU7D;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAanE;AAuBD,oHAAoH;AACpH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAMjH;AAED,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAK7E;AAMD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,OAAO,CAAC,UAAU,CAAC,CAoB3F;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAOvF;AAED,4FAA4F;AAC5F,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAK9E"}