@nyte-ai/host 0.0.0-stage → 0.0.19

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 (250) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +6 -2
  3. package/THIRD-PARTY-NOTICES.md +866 -0
  4. package/dist/chunks/canvas-preview-0cmbkp2j.js +65 -0
  5. package/dist/chunks/canvas-preview-0nq75h9k.js +7 -0
  6. package/dist/chunks/canvas-preview-11nadadc.js +241 -0
  7. package/dist/chunks/canvas-preview-1sq7z9jq.js +17 -0
  8. package/dist/chunks/canvas-preview-2jwbe14k.js +130 -0
  9. package/dist/chunks/canvas-preview-2zdyh9ny.js +26 -0
  10. package/dist/chunks/canvas-preview-31w7xm8z.js +34 -0
  11. package/dist/chunks/canvas-preview-4b6sayhg.js +295 -0
  12. package/dist/chunks/canvas-preview-4e0pxa32.js +63 -0
  13. package/dist/chunks/canvas-preview-518dh8by.js +169 -0
  14. package/dist/chunks/canvas-preview-55s0y68g.js +387 -0
  15. package/dist/chunks/canvas-preview-5ekjx6sw.js +613 -0
  16. package/dist/chunks/canvas-preview-5mex725c.js +14 -0
  17. package/dist/chunks/canvas-preview-5z63am63.js +295 -0
  18. package/dist/chunks/canvas-preview-65xqjw7f.js +20 -0
  19. package/dist/chunks/canvas-preview-69fkk9yn.js +95 -0
  20. package/dist/chunks/canvas-preview-8xc0vn7v.js +458 -0
  21. package/dist/chunks/canvas-preview-9aqczacs.js +73 -0
  22. package/dist/chunks/canvas-preview-af86jz8t.js +141 -0
  23. package/dist/chunks/canvas-preview-aq5j4p25.js +240 -0
  24. package/dist/chunks/canvas-preview-b2v8wfnz.js +36 -0
  25. package/dist/chunks/canvas-preview-befkjea2.js +60 -0
  26. package/dist/chunks/canvas-preview-bxnqt8cd.js +103 -0
  27. package/dist/chunks/canvas-preview-cawy6vbz.js +352 -0
  28. package/dist/chunks/canvas-preview-crmzxxt8.js +518 -0
  29. package/dist/chunks/canvas-preview-drctegz4.js +591 -0
  30. package/dist/chunks/canvas-preview-e3vnkkc5.js +134 -0
  31. package/dist/chunks/canvas-preview-ec2mt7es.js +108 -0
  32. package/dist/chunks/canvas-preview-fxa0rfb0.js +61 -0
  33. package/dist/chunks/canvas-preview-g5fkjs34.js +598 -0
  34. package/dist/chunks/canvas-preview-jeddjex8.js +166 -0
  35. package/dist/chunks/canvas-preview-k1yg4fgp.js +571 -0
  36. package/dist/chunks/canvas-preview-kdqgrstc.js +194 -0
  37. package/dist/chunks/canvas-preview-kn7kvbfj.js +12 -0
  38. package/dist/chunks/canvas-preview-kp75gb63.js +141 -0
  39. package/dist/chunks/canvas-preview-mgcx2b2p.js +271 -0
  40. package/dist/chunks/canvas-preview-n2a35zv5.js +81 -0
  41. package/dist/chunks/canvas-preview-pkzqg96v.js +63 -0
  42. package/dist/chunks/canvas-preview-rp4x6y1h.js +144 -0
  43. package/dist/chunks/canvas-preview-s94ebwf5.js +112 -0
  44. package/dist/chunks/canvas-preview-skzwvw4d.js +23 -0
  45. package/dist/chunks/canvas-preview-srgfpdmf.js +60 -0
  46. package/dist/chunks/canvas-preview-tjhabynd.js +252 -0
  47. package/dist/chunks/canvas-preview-tnqe7k0b.js +374 -0
  48. package/dist/chunks/canvas-preview-vaatfznm.js +189 -0
  49. package/dist/chunks/canvas-preview-vm9zdp2t.js +398 -0
  50. package/dist/chunks/canvas-preview-w54ymtb3.js +272 -0
  51. package/dist/chunks/canvas-preview-wg80rbc2.js +46 -0
  52. package/dist/chunks/canvas-preview-y5y6ghaw.js +125 -0
  53. package/dist/chunks/canvas-preview-ycepb05s.js +176 -0
  54. package/dist/chunks/canvas-preview-yjz0f7n4.js +50 -0
  55. package/dist/chunks/canvas-preview-zaaj99wd.js +244 -0
  56. package/dist/src/canvas-preview.d.ts +29 -0
  57. package/dist/src/canvas-preview.js +271 -0
  58. package/dist/src/credentials.d.ts +44 -0
  59. package/dist/src/credentials.js +10 -0
  60. package/dist/src/deploy/cloudflare/worker.d.ts +50 -0
  61. package/dist/src/deploy/cloudflare/worker.js +196 -0
  62. package/dist/src/deploy/vercel/nitro.config.d.ts +2 -0
  63. package/dist/src/deploy/vercel/nitro.config.js +30 -0
  64. package/dist/src/deploy/vercel/server/routes/[...].d.ts +2 -0
  65. package/dist/src/deploy/vercel/server/routes/[...].js +18 -0
  66. package/dist/src/deploy/vercel/server/utils/host.d.ts +13 -0
  67. package/dist/src/deploy/vercel/server/utils/host.js +7 -0
  68. package/dist/src/deploy/vercel/server/utils/repair.d.ts +1 -0
  69. package/dist/src/deploy/vercel/server/utils/repair.js +6 -0
  70. package/dist/src/deploy/vercel/server/utils/step.d.ts +10 -0
  71. package/dist/src/deploy/vercel/server/utils/step.js +6 -0
  72. package/dist/src/deploy/vercel/server/workflows/drive.d.ts +14 -0
  73. package/dist/src/deploy/vercel/server/workflows/drive.js +13 -0
  74. package/dist/src/durable-object.d.ts +14 -0
  75. package/dist/src/durable-object.js +231 -0
  76. package/dist/src/hash.d.ts +1 -0
  77. package/dist/src/hash.js +6 -0
  78. package/dist/src/identity-key.d.ts +11 -0
  79. package/dist/src/identity-key.js +9 -0
  80. package/dist/src/identity.d.ts +12 -0
  81. package/dist/src/identity.js +6 -0
  82. package/dist/src/images/exif.d.ts +1 -0
  83. package/dist/src/images/exif.js +6 -0
  84. package/dist/src/images/node.d.ts +37 -0
  85. package/dist/src/images/node.js +12 -0
  86. package/dist/src/images/photon.d.ts +3 -0
  87. package/dist/src/images/photon.js +7 -0
  88. package/dist/src/images/worker.d.ts +1 -0
  89. package/dist/src/images/worker.js +23 -0
  90. package/dist/src/index.d.ts +20 -0
  91. package/dist/src/index.js +121 -0
  92. package/dist/src/key-file.d.ts +1 -0
  93. package/dist/src/key-file.js +7 -0
  94. package/dist/src/listen-fetch.d.ts +8 -0
  95. package/dist/src/listen-fetch.js +9 -0
  96. package/dist/src/listen.d.ts +4 -0
  97. package/dist/src/listen.js +10 -0
  98. package/dist/src/local/command.d.ts +20 -0
  99. package/dist/src/local/command.js +12 -0
  100. package/dist/src/local/feed.d.ts +7 -0
  101. package/dist/src/local/feed.js +6 -0
  102. package/dist/src/local/files.d.ts +18 -0
  103. package/dist/src/local/files.js +13 -0
  104. package/dist/src/local/git-watch.d.ts +15 -0
  105. package/dist/src/local/git-watch.js +7 -0
  106. package/dist/src/local/git.d.ts +5 -0
  107. package/dist/src/local/git.js +13 -0
  108. package/dist/src/local/github.d.ts +30 -0
  109. package/dist/src/local/github.js +9 -0
  110. package/dist/src/local/identity.d.ts +3 -0
  111. package/dist/src/local/identity.js +7 -0
  112. package/dist/src/local/jobs.d.ts +7 -0
  113. package/dist/src/local/jobs.js +7 -0
  114. package/dist/src/local/legacy-trust.d.ts +10 -0
  115. package/dist/src/local/legacy-trust.js +6 -0
  116. package/dist/src/local/patch.d.ts +16 -0
  117. package/dist/src/local/patch.js +17 -0
  118. package/dist/src/local/provider.d.ts +11 -0
  119. package/dist/src/local/provider.js +20 -0
  120. package/dist/src/local/snapshots.d.ts +7 -0
  121. package/dist/src/local/snapshots.js +11 -0
  122. package/dist/src/local/text.d.ts +1 -0
  123. package/dist/src/local/text.js +6 -0
  124. package/dist/src/local/tree.d.ts +50 -0
  125. package/dist/src/local/tree.js +16 -0
  126. package/dist/src/local/workspace-migration.d.ts +2 -0
  127. package/dist/src/local/workspace-migration.js +7 -0
  128. package/dist/src/local/worktrees.d.ts +46 -0
  129. package/dist/src/local/worktrees.js +14 -0
  130. package/dist/src/mcp/config.d.ts +75 -0
  131. package/dist/src/mcp/config.js +12 -0
  132. package/dist/src/mcp/connect.d.ts +15 -0
  133. package/dist/src/mcp/connect.js +9 -0
  134. package/dist/src/mcp/hub.d.ts +19 -0
  135. package/dist/src/mcp/hub.js +11 -0
  136. package/dist/src/mcp/oauth.d.ts +46 -0
  137. package/dist/src/mcp/oauth.js +12 -0
  138. package/dist/src/mcp/tools.d.ts +29 -0
  139. package/dist/src/mcp/tools.js +12 -0
  140. package/dist/src/open.d.ts +14 -0
  141. package/dist/src/open.js +46 -0
  142. package/dist/src/plugins/loader.d.ts +21 -0
  143. package/dist/src/plugins/loader.js +11 -0
  144. package/dist/src/postgres.d.ts +19 -0
  145. package/dist/src/postgres.js +8 -0
  146. package/dist/src/providers.d.ts +16 -0
  147. package/dist/src/providers.js +112 -0
  148. package/dist/src/secrets.d.ts +12 -0
  149. package/dist/src/secrets.js +8 -0
  150. package/dist/src/serve/binding.d.ts +39 -0
  151. package/dist/src/serve/binding.js +6 -0
  152. package/dist/src/serve/handler.d.ts +15 -0
  153. package/dist/src/serve/handler.js +8 -0
  154. package/dist/src/serve/stream-server.d.ts +6 -0
  155. package/dist/src/serve/stream-server.js +6 -0
  156. package/dist/src/session-index.d.ts +11 -0
  157. package/dist/src/session-index.js +11 -0
  158. package/dist/src/shell-env.d.ts +14 -0
  159. package/dist/src/shell-env.js +108 -0
  160. package/dist/src/sqlite-workers.d.ts +6 -0
  161. package/dist/src/sqlite-workers.js +6 -0
  162. package/dist/src/sqlite.d.ts +8 -0
  163. package/dist/src/sqlite.js +11 -0
  164. package/dist/src/store-rows.d.ts +13 -0
  165. package/dist/src/store-rows.js +26 -0
  166. package/dist/src/store-usage.d.ts +25 -0
  167. package/dist/src/store-usage.js +19 -0
  168. package/dist/src/usage-history.d.ts +54 -0
  169. package/dist/src/usage-history.js +14 -0
  170. package/dist/src/usage-scan.d.ts +24 -0
  171. package/dist/src/usage-scan.js +65 -0
  172. package/dist/src/usage-service.d.ts +23 -0
  173. package/dist/src/usage-service.js +16 -0
  174. package/dist/src/usage-summary.d.ts +9 -0
  175. package/dist/src/usage-summary.js +16 -0
  176. package/dist/src/usage-types.d.ts +86 -0
  177. package/dist/src/usage-types.js +0 -0
  178. package/dist/src/usage-worker.d.ts +1 -0
  179. package/dist/src/usage-worker.js +29 -0
  180. package/dist/src/usage.d.ts +195 -0
  181. package/dist/src/usage.js +23 -0
  182. package/package.json +140 -3
  183. package/src/canvas-preview.ts +403 -0
  184. package/src/credentials.ts +294 -0
  185. package/src/deploy/cloudflare/README.md +3 -0
  186. package/src/deploy/cloudflare/worker.ts +306 -0
  187. package/src/deploy/cloudflare/wrangler.jsonc +12 -0
  188. package/src/deploy/vercel/README.md +3 -0
  189. package/src/deploy/vercel/nitro.config.ts +29 -0
  190. package/src/deploy/vercel/server/routes/[...].ts +10 -0
  191. package/src/deploy/vercel/server/utils/host.ts +104 -0
  192. package/src/deploy/vercel/server/utils/repair.ts +35 -0
  193. package/src/deploy/vercel/server/utils/step.ts +25 -0
  194. package/src/deploy/vercel/server/workflows/drive.ts +46 -0
  195. package/src/deploy/vercel/tsconfig.json +9 -0
  196. package/src/deploy/vercel/types/bun.d.ts +2 -0
  197. package/src/durable-object.ts +386 -0
  198. package/src/hash.ts +5 -0
  199. package/src/identity-key.ts +20 -0
  200. package/src/identity.ts +66 -0
  201. package/src/images/exif.ts +69 -0
  202. package/src/images/node.ts +163 -0
  203. package/src/images/photon.ts +141 -0
  204. package/src/images/worker.ts +29 -0
  205. package/src/index.ts +39 -0
  206. package/src/key-file.ts +53 -0
  207. package/src/listen-fetch.ts +409 -0
  208. package/src/listen.ts +228 -0
  209. package/src/local/command.ts +161 -0
  210. package/src/local/feed.ts +70 -0
  211. package/src/local/files.ts +817 -0
  212. package/src/local/git-watch.ts +199 -0
  213. package/src/local/git.ts +919 -0
  214. package/src/local/github.ts +691 -0
  215. package/src/local/identity.ts +21 -0
  216. package/src/local/jobs.ts +573 -0
  217. package/src/local/legacy-trust.ts +105 -0
  218. package/src/local/patch.ts +334 -0
  219. package/src/local/provider.ts +184 -0
  220. package/src/local/snapshots.ts +778 -0
  221. package/src/local/text.ts +9 -0
  222. package/src/local/tree.ts +398 -0
  223. package/src/local/workspace-migration.ts +95 -0
  224. package/src/local/worktrees.ts +239 -0
  225. package/src/mcp/config.ts +330 -0
  226. package/src/mcp/connect.ts +92 -0
  227. package/src/mcp/hub.ts +836 -0
  228. package/src/mcp/oauth.ts +436 -0
  229. package/src/mcp/tools.ts +333 -0
  230. package/src/open.ts +449 -0
  231. package/src/plugins/loader.ts +186 -0
  232. package/src/postgres.ts +492 -0
  233. package/src/providers.ts +135 -0
  234. package/src/secrets.ts +31 -0
  235. package/src/serve/binding.ts +629 -0
  236. package/src/serve/handler.ts +362 -0
  237. package/src/serve/stream-server.ts +176 -0
  238. package/src/session-index.ts +99 -0
  239. package/src/shell-env.ts +153 -0
  240. package/src/sqlite-workers.ts +283 -0
  241. package/src/sqlite.ts +553 -0
  242. package/src/store-rows.ts +110 -0
  243. package/src/store-usage.ts +347 -0
  244. package/src/usage-history.ts +219 -0
  245. package/src/usage-scan.ts +81 -0
  246. package/src/usage-service.ts +82 -0
  247. package/src/usage-summary.ts +79 -0
  248. package/src/usage-types.ts +87 -0
  249. package/src/usage-worker.ts +24 -0
  250. package/src/usage.ts +776 -0
@@ -0,0 +1,398 @@
1
+ import {
2
+ run2,
3
+ spawnCommand2,
4
+ killTree2,
5
+ findExecutable2
6
+ } from "./canvas-preview-bxnqt8cd.js";
7
+
8
+ // src/local/jobs.ts
9
+ import { spawn } from "node:child_process";
10
+ import { createRequire } from "node:module";
11
+ import { basename, resolve } from "node:path";
12
+ import { asId, SdkError } from "@nyte-ai/schema";
13
+ import {
14
+ processEnvironment,
15
+ closable,
16
+ dev,
17
+ readTraceparent,
18
+ startSpan,
19
+ tracing
20
+ } from "@nyte-ai/core";
21
+ var OUTPUT_LIMIT = 1024 * 1024;
22
+ var PAUSE_BYTES = 256 * 1024;
23
+ var RESUME_BYTES = 64 * 1024;
24
+ var STOP_GRACE_MS = 2000;
25
+ var CLOSE_GRACE_MS = 2000;
26
+ var DONE = { done: true, value: undefined };
27
+ var loaded;
28
+ function localExec2(root, options) {
29
+ const readers = new Set;
30
+ const custom = options?.loadPty;
31
+ const load = custom === undefined ? loadPty : () => ptyFrom(custom);
32
+ options?.signal?.addEventListener("abort", () => {
33
+ for (const close of readers)
34
+ close();
35
+ }, { once: true });
36
+ return async (command, input) => {
37
+ if (input?.signal?.aborted === true)
38
+ throw new SdkError("unavailable", "aborted");
39
+ if (typeof command !== "string" && command.length === 0 && input?.pty === undefined)
40
+ throw new SdkError("invalid", "An empty command runs only in a pty, as the login shell.");
41
+ const cwd = input?.cwd === undefined ? root : resolve(root, input.cwd);
42
+ await processEnvironment();
43
+ const env = { ...process.env, ...input?.env };
44
+ const trace = readTraceparent(input?.env?.TRACEPARENT);
45
+ const spawned = startSpan("pty.spawn", trace, { pty: input?.pty !== undefined });
46
+ const log = tracedOutput(createOutputLog(OUTPUT_LIMIT), trace);
47
+ let settle = () => {
48
+ return;
49
+ };
50
+ const ended = new Promise((done) => {
51
+ settle = done;
52
+ });
53
+ let stopping = false;
54
+ let finished = null;
55
+ const finish = (code) => {
56
+ if (finished !== null)
57
+ return;
58
+ finished = { kind: "exited", code, reason: stopping ? "terminated" : "exited" };
59
+ dev("jobs", "exit", { code, reason: finished.reason });
60
+ log.end(code);
61
+ settle(finished);
62
+ };
63
+ const driver = input?.pty === undefined ? await pipe(command, { cwd, env, protocol: input?.stdio === "protocol" }, log, finish) : await terminal(command, { cwd, env, size: input.pty, shell: options?.shell?.() ?? undefined, load }, log, finish);
64
+ spawned();
65
+ dev("jobs", "start", {
66
+ program: typeof command === "string" ? command.split(/\s/, 1)[0] : command[0] ?? null,
67
+ args: typeof command === "string" ? null : command.length - 1,
68
+ pty: driver.pty
69
+ });
70
+ let stopped = null;
71
+ const stop = () => {
72
+ stopped ??= (async () => {
73
+ if (finished !== null)
74
+ return finished;
75
+ stopping = true;
76
+ driver.kill(driver.pty ? "SIGHUP" : "SIGTERM");
77
+ const timer = setTimeout(() => driver.kill("SIGKILL"), STOP_GRACE_MS);
78
+ try {
79
+ return await ended;
80
+ } finally {
81
+ clearTimeout(timer);
82
+ }
83
+ })();
84
+ return stopped;
85
+ };
86
+ input?.signal?.addEventListener("abort", () => void stop(), { once: true });
87
+ const own = new Set;
88
+ const close = async () => {
89
+ for (const detach of own)
90
+ detach();
91
+ };
92
+ const job = {
93
+ id: asId(crypto.randomUUID()),
94
+ key: null,
95
+ write: (bytes) => driver.write(bytes),
96
+ output: () => closable(() => {
97
+ const reader = log.reader();
98
+ const detach = () => {
99
+ own.delete(detach);
100
+ readers.delete(detach);
101
+ reader.close();
102
+ };
103
+ own.add(detach);
104
+ readers.add(detach);
105
+ return { pull: () => reader.next(), close: detach };
106
+ }),
107
+ async resize(size) {
108
+ if (!driver.pty)
109
+ return { kind: "not-pty" };
110
+ return finished === null && driver.resize(size) ? { kind: "resized" } : { kind: "missing" };
111
+ },
112
+ idle: async () => driver.pty && (finished !== null || driver.idle()),
113
+ stop: async () => ({ kind: "settled", outcome: await stop() }),
114
+ settled: (request) => waitEnd(ended, request),
115
+ close,
116
+ [Symbol.asyncDispose]: close
117
+ };
118
+ return job;
119
+ };
120
+ }
121
+ async function pipe(command, options, log, finish) {
122
+ const windows = process.platform === "win32";
123
+ const [file, ...args] = typeof command === "string" ? [command] : command;
124
+ const settings = {
125
+ cwd: options.cwd,
126
+ env: options.env,
127
+ detached: !windows,
128
+ stdio: "pipe",
129
+ windowsHide: true
130
+ };
131
+ const child = typeof command === "string" ? spawn(command, { ...settings, shell: true }) : spawnCommand2(windows ? await findExecutable2(file ?? "") ?? file ?? "" : file ?? "", args, settings);
132
+ await new Promise((started, failed) => {
133
+ child.once("spawn", started);
134
+ child.once("error", (error) => failed(new SdkError("unavailable", `Cannot start ${file ?? ""}: ${error.message}`)));
135
+ });
136
+ child.stdout?.on("data", (chunk) => log.push(chunk));
137
+ child.stderr?.on("data", (chunk) => log.push(chunk, options.protocol ? "stderr" : undefined));
138
+ if (options.protocol)
139
+ log.throttle({
140
+ pause: () => {
141
+ child.stdout?.pause();
142
+ child.stderr?.pause();
143
+ },
144
+ resume: () => {
145
+ child.stdout?.resume();
146
+ child.stderr?.resume();
147
+ }
148
+ });
149
+ child.stdin?.on("error", () => {
150
+ return;
151
+ });
152
+ let killed = false;
153
+ child.on("close", (code) => finish(killed ? null : code));
154
+ child.on("exit", (code) => {
155
+ setTimeout(() => {
156
+ child.stdout?.destroy();
157
+ child.stderr?.destroy();
158
+ finish(killed ? null : code);
159
+ }, CLOSE_GRACE_MS).unref();
160
+ });
161
+ return {
162
+ pty: false,
163
+ async write(bytes) {
164
+ const stdin = child.stdin;
165
+ if (stdin === null || !stdin.writable)
166
+ throw new SdkError("unavailable", "The process no longer reads its input.");
167
+ await new Promise((written) => stdin.write(bytes, () => written()));
168
+ },
169
+ resize: () => false,
170
+ idle: () => false,
171
+ kill(signal) {
172
+ if (windows) {
173
+ killed = true;
174
+ killTree2(child, signal);
175
+ return;
176
+ }
177
+ try {
178
+ if (child.pid !== undefined)
179
+ process.kill(-child.pid, signal);
180
+ else
181
+ child.kill(signal);
182
+ } catch {
183
+ child.kill(signal);
184
+ }
185
+ }
186
+ };
187
+ }
188
+ function terminalEnv(env) {
189
+ const { ELECTRON_RUN_AS_NODE: _electron, NODE_OPTIONS: _node, ...rest } = env;
190
+ return { ...rest, TERM: "xterm-256color", COLORTERM: "truecolor", TERM_PROGRAM: "Nyte" };
191
+ }
192
+ async function terminal(command, options, log, finish) {
193
+ const pty = options.load();
194
+ if (pty === null)
195
+ throw new SdkError("unavailable", "Terminals need @lydell/node-pty, which does not load on this platform.");
196
+ const windows = process.platform === "win32";
197
+ const shell = options.shell ?? (windows ? process.env.COMSPEC ?? "cmd.exe" : process.env.SHELL ?? "/bin/sh");
198
+ const [file, ...args] = typeof command === "string" ? windows ? [shell, "/d", "/s", "/c", command] : ["/bin/sh", "-c", command] : command.length === 0 ? windows ? [shell] : [shell, "-l"] : command;
199
+ let term;
200
+ try {
201
+ term = pty.spawn(file ?? shell, args, {
202
+ name: "xterm-256color",
203
+ cols: options.size.columns,
204
+ rows: options.size.rows,
205
+ cwd: options.cwd,
206
+ env: terminalEnv(options.env)
207
+ });
208
+ } catch (error) {
209
+ throw new SdkError("unavailable", `Cannot start ${file ?? shell} in a pty: ${error instanceof Error ? error.message : String(error)}`);
210
+ }
211
+ const encoder = new TextEncoder;
212
+ term.onData((text) => log.push(encoder.encode(text)));
213
+ term.onExit(({ exitCode, signal }) => finish(signal ? null : exitCode));
214
+ log.throttle({ pause: () => term.pause(), resume: () => term.resume() });
215
+ return {
216
+ pty: true,
217
+ async write(bytes) {
218
+ term.write(Buffer.from(bytes));
219
+ },
220
+ resize(size) {
221
+ term.resize(size.columns, size.rows);
222
+ return true;
223
+ },
224
+ async idle() {
225
+ if (typeof command === "string" || command.length !== 0)
226
+ return false;
227
+ const result = await run2(windows ? "powershell.exe" : "ps", windows ? [
228
+ "-NoProfile",
229
+ "-NonInteractive",
230
+ "-Command",
231
+ `Get-CimInstance Win32_Process -Filter "ParentProcessId = ${term.pid} AND Name != 'conhost.exe' AND Name != 'OpenConsole.exe'" | Select-Object -ExpandProperty ProcessId`
232
+ ] : ["-A", "-o", "pid=,ppid=,stat=,comm="], { cwd: options.cwd, timeoutMs: 1500 });
233
+ if (result.code !== 0)
234
+ throw new SdkError("unavailable", "Cannot inspect terminal processes");
235
+ const processes = result.stdout.toString("utf8").trim();
236
+ if (windows)
237
+ return processes === "";
238
+ return !processes.split(`
239
+ `).some((line) => {
240
+ const [pid, parent, state, ...name] = line.trim().split(/\s+/);
241
+ if (state?.startsWith("Z"))
242
+ return false;
243
+ if (Number(parent) === term.pid)
244
+ return true;
245
+ return Number(pid) === term.pid && basename(name.join(" ")).replace(/^-/, "") !== basename(shell);
246
+ });
247
+ },
248
+ kill(signal) {
249
+ try {
250
+ term.kill(windows ? undefined : signal);
251
+ } catch {}
252
+ }
253
+ };
254
+ }
255
+ function loadPty() {
256
+ if (loaded === undefined)
257
+ loaded = ptyFrom(() => createRequire(import.meta.url)("@lydell/node-pty"));
258
+ return loaded;
259
+ }
260
+ function ptyFrom(load) {
261
+ try {
262
+ const required = load();
263
+ return fitsPtyModule(required) ? required : null;
264
+ } catch {
265
+ return null;
266
+ }
267
+ }
268
+ function fitsPtyModule(value) {
269
+ return typeof value === "object" && value !== null && "spawn" in value && typeof value.spawn === "function";
270
+ }
271
+ function waitEnd(ended, request) {
272
+ const signal = request?.signal;
273
+ if (signal === undefined)
274
+ return ended;
275
+ if (signal.aborted)
276
+ return Promise.reject(new SdkError("unavailable", "aborted"));
277
+ return new Promise((settled, failed) => {
278
+ const abort = () => failed(new SdkError("unavailable", "aborted"));
279
+ signal.addEventListener("abort", abort, { once: true });
280
+ ended.then((end) => {
281
+ signal.removeEventListener("abort", abort);
282
+ settled(end);
283
+ }, failed);
284
+ });
285
+ }
286
+ function tracedOutput(log, trace) {
287
+ if (!tracing.enabled)
288
+ return log;
289
+ let ended = null;
290
+ let bytes = 0;
291
+ return {
292
+ ...log,
293
+ push(chunk, stream) {
294
+ ended ??= startSpan("pty.output", trace);
295
+ bytes += chunk.byteLength;
296
+ log.push(chunk, stream);
297
+ },
298
+ end(code) {
299
+ ended?.({ bytes, code });
300
+ log.end(code);
301
+ }
302
+ };
303
+ }
304
+ function createOutputLog(limit) {
305
+ const state = { chunks: [], first: 0, size: 0, pushed: 0, exit: null };
306
+ const waiters = new Set;
307
+ const positions = new Set;
308
+ let source = null;
309
+ let paused = false;
310
+ const behind = () => Math.max(0, ...[...positions].map((position) => state.pushed - position.read));
311
+ const pace = () => {
312
+ if (source === null)
313
+ return;
314
+ const lag = behind();
315
+ if (!paused && lag > PAUSE_BYTES) {
316
+ paused = true;
317
+ source.pause();
318
+ } else if (paused && lag < RESUME_BYTES) {
319
+ paused = false;
320
+ source.resume();
321
+ }
322
+ };
323
+ const wake = () => {
324
+ const pending = [...waiters];
325
+ waiters.clear();
326
+ for (const resolve of pending)
327
+ resolve();
328
+ };
329
+ return {
330
+ throttle(next) {
331
+ source = next;
332
+ },
333
+ push(bytes, stream) {
334
+ state.chunks.push(stream === undefined ? { kind: "bytes", data: bytes } : { kind: "bytes", data: bytes, stream });
335
+ state.size += bytes.byteLength;
336
+ state.pushed += bytes.byteLength;
337
+ while (state.size > limit && state.chunks.length > 1) {
338
+ state.size -= state.chunks.shift()?.data.byteLength ?? 0;
339
+ state.first += 1;
340
+ }
341
+ pace();
342
+ wake();
343
+ },
344
+ end(code) {
345
+ state.exit ??= { code };
346
+ wake();
347
+ },
348
+ reader() {
349
+ let cursor = 0;
350
+ let done = false;
351
+ let waiting = null;
352
+ const position = { read: 0 };
353
+ positions.add(position);
354
+ return {
355
+ async next() {
356
+ for (;; ) {
357
+ if (done)
358
+ return DONE;
359
+ if (cursor < state.first) {
360
+ cursor = state.first;
361
+ position.read = state.pushed - state.size;
362
+ return { done: false, value: { kind: "gap" } };
363
+ }
364
+ const chunk = state.chunks[cursor - state.first];
365
+ if (chunk !== undefined) {
366
+ cursor += 1;
367
+ position.read += chunk.data.byteLength;
368
+ pace();
369
+ return { done: false, value: chunk };
370
+ }
371
+ if (state.exit !== null) {
372
+ done = true;
373
+ return { done: false, value: { kind: "exit", code: state.exit.code } };
374
+ }
375
+ await new Promise((woken) => {
376
+ waiting = woken;
377
+ waiters.add(woken);
378
+ });
379
+ waiting = null;
380
+ }
381
+ },
382
+ close() {
383
+ done = true;
384
+ positions.delete(position);
385
+ pace();
386
+ const resolve = waiting;
387
+ waiting = null;
388
+ if (resolve !== null) {
389
+ waiters.delete(resolve);
390
+ resolve();
391
+ }
392
+ }
393
+ };
394
+ }
395
+ };
396
+ }
397
+
398
+ export { localExec2 };
@@ -0,0 +1,272 @@
1
+ import {
2
+ createHandler2
3
+ } from "./canvas-preview-aq5j4p25.js";
4
+
5
+ // src/listen-fetch.ts
6
+ import { SdkError } from "@nyte-ai/schema";
7
+ import { serial } from "@nyte-ai/schema/serial";
8
+ import { dev } from "@nyte-ai/core";
9
+ import { TOKEN, TOKEN_AUTHORITY } from "@nyte-ai/core/server";
10
+ import {
11
+ HOST_HEADER,
12
+ OPERATIONS_HEADER,
13
+ asSdkError,
14
+ encodeError,
15
+ errorStatus,
16
+ operationsDigest
17
+ } from "@nyte-ai/protocol";
18
+ var encoder = new TextEncoder;
19
+ async function listenFetch2(host, options) {
20
+ const { auth } = options;
21
+ if (auth.kind === "token" && auth.token.length < 16)
22
+ throw new SdkError("invalid", "A listener token needs at least 16 characters.");
23
+ const { server } = host;
24
+ const operations = await operationsDigest();
25
+ const cache = new Map;
26
+ const devices = new Map;
27
+ const streams = new Map;
28
+ const flights = new WeakMap;
29
+ let generation = new AbortController;
30
+ let closing = null;
31
+ let principalsRevision = null;
32
+ const rechecks = serial();
33
+ const drop = (key, entry, reason) => {
34
+ if (cache.get(key) === entry)
35
+ cache.delete(key);
36
+ entry.dispose();
37
+ for (const [digest, device] of devices)
38
+ if (device.principal === entry.principal)
39
+ devices.delete(digest);
40
+ const open = streams.get(entry.principal);
41
+ streams.delete(entry.principal);
42
+ for (const flight of open ?? [])
43
+ flight.controller.abort(reason);
44
+ entry.connection.close();
45
+ };
46
+ const land = (flight) => {
47
+ for (const [principal, open] of streams)
48
+ if (open.delete(flight) && open.size === 0)
49
+ streams.delete(principal);
50
+ };
51
+ const connectionFor = (flight, principal, authority, token) => {
52
+ const key = JSON.stringify([principal, [...authority].sort()]);
53
+ const entry = cache.get(key) ?? admit(key, principal, authority, token);
54
+ flight.principal = principal;
55
+ const open = streams.get(principal) ?? new Set;
56
+ open.add(flight);
57
+ streams.set(principal, open);
58
+ return entry.connection;
59
+ };
60
+ const admit = (key, principal, authority, token) => {
61
+ const connection = server.connect({
62
+ principal,
63
+ authority,
64
+ credential: { kind: "token", token },
65
+ origin: null
66
+ });
67
+ const entry = { connection, principal, dispose: () => {
68
+ return;
69
+ } };
70
+ const admitted = server.connections.register(principal, () => drop(key, entry, new SdkError("unauthenticated", "The principal was revoked.")));
71
+ if (admitted.kind === "revoked")
72
+ throw new SdkError("unauthenticated", "The principal was revoked.");
73
+ entry.dispose = admitted.dispose;
74
+ cache.set(key, entry);
75
+ return entry;
76
+ };
77
+ const reread = async (token, digest) => {
78
+ const found = await server.authenticate(token);
79
+ if (found === null) {
80
+ const known = devices.get(digest);
81
+ devices.delete(digest);
82
+ if (known !== undefined)
83
+ server.connections.revoke(known.principal);
84
+ return null;
85
+ }
86
+ return { ...found, token };
87
+ };
88
+ const findDevice = async (token) => {
89
+ const digest = hex(await sha256(token));
90
+ const device = devices.get(digest) ?? await reread(token, digest);
91
+ return device === null ? null : { digest, device };
92
+ };
93
+ const recheck = async () => {
94
+ if (devices.size === 0)
95
+ return;
96
+ const revision = await server.principalsRevision();
97
+ if (revision === principalsRevision)
98
+ return;
99
+ principalsRevision = revision;
100
+ await Promise.all([...devices].map(([digest, known]) => reread(known.token, digest)));
101
+ };
102
+ const externalCommit = () => {
103
+ rechecks.run(recheck).catch((error) => dev("listen", "device re-check failed", { error: String(error) }));
104
+ };
105
+ const unwatchCommits = server.onExternalCommit(externalCommit);
106
+ const isListenerToken = auth.kind === "token" ? (token) => sameSecret(token, auth.token) : async () => false;
107
+ const fallback = auth.kind === "custom" ? async (request) => {
108
+ const verdict = await auth.authorize(request);
109
+ if ("deny" in verdict)
110
+ throw verdict.deny === "forbidden" ? new SdkError("denied", "This principal may not call the host.") : new SdkError("unauthenticated", "The request is not authorized.");
111
+ return verdict;
112
+ } : async (_request, token) => {
113
+ throw new SdkError("unauthenticated", token === undefined ? "Send Authorization: Bearer <token>." : "The token is not accepted.");
114
+ };
115
+ const authenticate = async (request, flight) => {
116
+ const header = request.headers.get("Authorization") ?? "";
117
+ const pairing = /^Pairing\s+(\S+)\s*$/i.exec(header)?.[1];
118
+ if (pairing !== undefined) {
119
+ const redeemed = await server.redeem(pairing);
120
+ if (redeemed === null)
121
+ throw new SdkError("unauthenticated", "The pairing code is unknown or has expired.");
122
+ const digest = hex(await sha256(redeemed.token));
123
+ const { principal, authority, token } = redeemed;
124
+ const connection = connectionFor(flight, principal, authority, token);
125
+ devices.set(digest, { principal, authority, token });
126
+ return { connection, authority, headers: { "X-Nyte-Credential": token } };
127
+ }
128
+ const token = /^Bearer\s+(\S+)\s*$/i.exec(header)?.[1];
129
+ if (token !== undefined) {
130
+ if (await isListenerToken(token))
131
+ return {
132
+ connection: connectionFor(flight, TOKEN, TOKEN_AUTHORITY, token),
133
+ authority: TOKEN_AUTHORITY
134
+ };
135
+ const remembered = await findDevice(token);
136
+ if (remembered !== null) {
137
+ const { digest, device } = remembered;
138
+ const connection = connectionFor(flight, device.principal, device.authority, token);
139
+ devices.set(digest, device);
140
+ return { connection, authority: device.authority };
141
+ }
142
+ }
143
+ const verdict = await fallback(request, token);
144
+ return {
145
+ connection: connectionFor(flight, verdict.principal, verdict.authority, ""),
146
+ authority: verdict.authority
147
+ };
148
+ };
149
+ const handler = createHandler2({
150
+ server,
151
+ origins: options.origins,
152
+ maxBodyBytes: options.maxBodyBytes,
153
+ connection: (request) => {
154
+ const flight = flights.get(request);
155
+ if (flight === undefined)
156
+ throw new Error("The listener did not register this request.");
157
+ return authenticate(request, flight);
158
+ }
159
+ });
160
+ const cors = (request) => {
161
+ const origin = request.headers.get("Origin");
162
+ return origin !== null && (options.origins ?? []).includes(origin) ? {
163
+ "Access-Control-Allow-Origin": origin,
164
+ "Access-Control-Expose-Headers": `${HOST_HEADER}, ${OPERATIONS_HEADER}`,
165
+ Vary: "Origin"
166
+ } : {};
167
+ };
168
+ const serve = async (request, trace) => {
169
+ if (closing !== null)
170
+ return failure(new SdkError("unavailable", "This listener is closed."), {});
171
+ const early = await options.before?.(request);
172
+ if (early !== undefined)
173
+ return early;
174
+ const url = new URL(request.url);
175
+ if (request.method === "GET" && url.pathname === "/.nyte/identity") {
176
+ const nonce = url.searchParams.get("nonce");
177
+ if (options.identity === undefined || nonce === null || nonce === "")
178
+ return failure(new SdkError("unknown", "This host answers no identity challenge."), cors(request));
179
+ return json({ ...await options.identity.sign(nonce), hostId: server.hostId }, cors(request));
180
+ }
181
+ if (request.method === "GET" && url.pathname === "/.nyte/describe") {
182
+ if (options.describe === undefined)
183
+ return failure(new SdkError("unknown", "This host describes nothing."), cors(request));
184
+ return json(await options.describe(), cors(request));
185
+ }
186
+ const controller = new AbortController;
187
+ const forwarded = new Request(request, {
188
+ signal: AbortSignal.any([request.signal, generation.signal, controller.signal])
189
+ });
190
+ const flight = { request: forwarded, controller, principal: null };
191
+ flights.set(forwarded, flight);
192
+ const response = await handler(forwarded);
193
+ trace.principal = flight.principal;
194
+ return landing(response, () => land(flight));
195
+ };
196
+ const fetch = async (request) => {
197
+ const started = Date.now();
198
+ const trace = { principal: null };
199
+ const response = await serve(request, trace).catch((error) => failure(asSdkError(error), cors(request)));
200
+ dev("listen", "request", {
201
+ method: request.method,
202
+ path: new URL(request.url).pathname,
203
+ status: response.status,
204
+ principal: trace.principal === null ? "none" : trace.principal === TOKEN ? "token" : "principal",
205
+ ms: Date.now() - started
206
+ });
207
+ return withHost(response, server.hostId, operations);
208
+ };
209
+ const execution = options.execution ?? { kind: "run", coverage: { kind: "all" } };
210
+ const coverage = execution.kind === "admit-only" || server.execution.kind === "dispatch" ? null : server.execution.kind === "admit-only" ? server.drive(execution.coverage) : await host.execution.cover(execution.coverage);
211
+ const disconnectClients = () => {
212
+ for (const [key, entry] of cache)
213
+ drop(key, entry, new SdkError("unavailable", "The host disconnected its clients."));
214
+ devices.clear();
215
+ generation.abort(new SdkError("unavailable", "The host disconnected its clients."));
216
+ generation = new AbortController;
217
+ };
218
+ const close = () => {
219
+ closing ??= (async () => {
220
+ unwatchCommits();
221
+ disconnectClients();
222
+ await coverage?.close();
223
+ })();
224
+ return closing;
225
+ };
226
+ return { address: null, fetch, disconnectClients, close, [Symbol.asyncDispose]: close };
227
+ }
228
+ function landing(response, done) {
229
+ if (response.body === null) {
230
+ done();
231
+ return response;
232
+ }
233
+ const settles = { flush: done, cancel: done };
234
+ return new Response(response.body.pipeThrough(new TransformStream(settles)), { status: response.status, statusText: response.statusText, headers: response.headers });
235
+ }
236
+ function withHost(response, hostId, operations) {
237
+ const headers = new Headers(response.headers);
238
+ headers.set(HOST_HEADER, hostId);
239
+ headers.set(OPERATIONS_HEADER, operations);
240
+ return new Response(response.body, {
241
+ status: response.status,
242
+ statusText: response.statusText,
243
+ headers
244
+ });
245
+ }
246
+ function json(value, headers) {
247
+ return new Response(JSON.stringify(value), {
248
+ status: 200,
249
+ headers: { ...headers, "Content-Type": "application/json" }
250
+ });
251
+ }
252
+ function failure(error, headers) {
253
+ return new Response(JSON.stringify(encodeError(error)), {
254
+ status: errorStatus[error.code],
255
+ headers: { ...headers, "Content-Type": "application/json" }
256
+ });
257
+ }
258
+ async function sha256(text) {
259
+ return new Uint8Array(await crypto.subtle.digest("SHA-256", encoder.encode(text)));
260
+ }
261
+ function hex(bytes) {
262
+ return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
263
+ }
264
+ async function sameSecret(given, expected) {
265
+ const [left, right] = await Promise.all([sha256(given), sha256(expected)]);
266
+ let difference = left.length ^ right.length;
267
+ for (let index = 0;index < left.length; index += 1)
268
+ difference |= (left[index] ?? 0) ^ (right[index] ?? 0);
269
+ return difference === 0;
270
+ }
271
+
272
+ export { listenFetch2 };