@nyte-ai/host 0.0.0-stage → 0.0.18

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 (235) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +6 -2
  3. package/THIRD-PARTY-NOTICES.md +800 -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-0nrnbt76.js +497 -0
  7. package/dist/chunks/canvas-preview-1sq7z9jq.js +17 -0
  8. package/dist/chunks/canvas-preview-1ta3avah.js +56 -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-5hxat7hh.js +239 -0
  15. package/dist/chunks/canvas-preview-5mex725c.js +14 -0
  16. package/dist/chunks/canvas-preview-5z63am63.js +295 -0
  17. package/dist/chunks/canvas-preview-65xqjw7f.js +20 -0
  18. package/dist/chunks/canvas-preview-69fkk9yn.js +95 -0
  19. package/dist/chunks/canvas-preview-75db60xy.js +457 -0
  20. package/dist/chunks/canvas-preview-76fwvd6e.js +272 -0
  21. package/dist/chunks/canvas-preview-8xgt67ka.js +598 -0
  22. package/dist/chunks/canvas-preview-98aj5p34.js +176 -0
  23. package/dist/chunks/canvas-preview-9aqczacs.js +73 -0
  24. package/dist/chunks/canvas-preview-a3yw0j70.js +72 -0
  25. package/dist/chunks/canvas-preview-azg56359.js +68 -0
  26. package/dist/chunks/canvas-preview-d9wwhbtz.js +240 -0
  27. package/dist/chunks/canvas-preview-ehf3vp31.js +411 -0
  28. package/dist/chunks/canvas-preview-evh92ywd.js +369 -0
  29. package/dist/chunks/canvas-preview-ewgspmsd.js +81 -0
  30. package/dist/chunks/canvas-preview-g3qj3y3k.js +156 -0
  31. package/dist/chunks/canvas-preview-h8hshnff.js +63 -0
  32. package/dist/chunks/canvas-preview-j1tnf51w.js +36 -0
  33. package/dist/chunks/canvas-preview-kdqgrstc.js +194 -0
  34. package/dist/chunks/canvas-preview-kn7kvbfj.js +12 -0
  35. package/dist/chunks/canvas-preview-m02v4yy6.js +386 -0
  36. package/dist/chunks/canvas-preview-mgcx2b2p.js +271 -0
  37. package/dist/chunks/canvas-preview-rp4x6y1h.js +144 -0
  38. package/dist/chunks/canvas-preview-rp6fz0w5.js +130 -0
  39. package/dist/chunks/canvas-preview-s94ebwf5.js +112 -0
  40. package/dist/chunks/canvas-preview-senpjwep.js +518 -0
  41. package/dist/chunks/canvas-preview-skzwvw4d.js +23 -0
  42. package/dist/chunks/canvas-preview-srgfpdmf.js +60 -0
  43. package/dist/chunks/canvas-preview-tjhabynd.js +252 -0
  44. package/dist/chunks/canvas-preview-vaatfznm.js +189 -0
  45. package/dist/chunks/canvas-preview-vax9ne4e.js +341 -0
  46. package/dist/chunks/canvas-preview-wg80rbc2.js +46 -0
  47. package/dist/chunks/canvas-preview-xn10d4f8.js +608 -0
  48. package/dist/chunks/canvas-preview-yjz0f7n4.js +50 -0
  49. package/dist/chunks/canvas-preview-ymgz0937.js +587 -0
  50. package/dist/chunks/canvas-preview-yrfz2ak6.js +134 -0
  51. package/dist/chunks/canvas-preview-zaaj99wd.js +244 -0
  52. package/dist/chunks/canvas-preview-zn2d0k9d.js +133 -0
  53. package/dist/src/canvas-preview.d.ts +29 -0
  54. package/dist/src/canvas-preview.js +267 -0
  55. package/dist/src/credentials.d.ts +44 -0
  56. package/dist/src/credentials.js +10 -0
  57. package/dist/src/deploy/cloudflare/worker.d.ts +50 -0
  58. package/dist/src/deploy/cloudflare/worker.js +196 -0
  59. package/dist/src/deploy/vercel/nitro.config.d.ts +2 -0
  60. package/dist/src/deploy/vercel/nitro.config.js +30 -0
  61. package/dist/src/deploy/vercel/server/routes/[...].d.ts +2 -0
  62. package/dist/src/deploy/vercel/server/routes/[...].js +18 -0
  63. package/dist/src/deploy/vercel/server/utils/host.d.ts +13 -0
  64. package/dist/src/deploy/vercel/server/utils/host.js +7 -0
  65. package/dist/src/deploy/vercel/server/utils/repair.d.ts +1 -0
  66. package/dist/src/deploy/vercel/server/utils/repair.js +6 -0
  67. package/dist/src/deploy/vercel/server/utils/step.d.ts +10 -0
  68. package/dist/src/deploy/vercel/server/utils/step.js +6 -0
  69. package/dist/src/deploy/vercel/server/workflows/drive.d.ts +14 -0
  70. package/dist/src/deploy/vercel/server/workflows/drive.js +13 -0
  71. package/dist/src/durable-object.d.ts +14 -0
  72. package/dist/src/durable-object.js +231 -0
  73. package/dist/src/hash.d.ts +1 -0
  74. package/dist/src/hash.js +6 -0
  75. package/dist/src/identity-key.d.ts +11 -0
  76. package/dist/src/identity-key.js +9 -0
  77. package/dist/src/identity.d.ts +12 -0
  78. package/dist/src/identity.js +6 -0
  79. package/dist/src/index.d.ts +21 -0
  80. package/dist/src/index.js +120 -0
  81. package/dist/src/key-file.d.ts +1 -0
  82. package/dist/src/key-file.js +7 -0
  83. package/dist/src/listen-fetch.d.ts +8 -0
  84. package/dist/src/listen-fetch.js +9 -0
  85. package/dist/src/listen.d.ts +4 -0
  86. package/dist/src/listen.js +10 -0
  87. package/dist/src/local/command.d.ts +15 -0
  88. package/dist/src/local/command.js +8 -0
  89. package/dist/src/local/feed.d.ts +7 -0
  90. package/dist/src/local/feed.js +6 -0
  91. package/dist/src/local/files.d.ts +18 -0
  92. package/dist/src/local/files.js +13 -0
  93. package/dist/src/local/git-watch.d.ts +15 -0
  94. package/dist/src/local/git-watch.js +7 -0
  95. package/dist/src/local/git.d.ts +5 -0
  96. package/dist/src/local/git.js +13 -0
  97. package/dist/src/local/github.d.ts +30 -0
  98. package/dist/src/local/github.js +9 -0
  99. package/dist/src/local/identity.d.ts +3 -0
  100. package/dist/src/local/identity.js +7 -0
  101. package/dist/src/local/jobs.d.ts +7 -0
  102. package/dist/src/local/jobs.js +6 -0
  103. package/dist/src/local/legacy-trust.d.ts +10 -0
  104. package/dist/src/local/legacy-trust.js +6 -0
  105. package/dist/src/local/patch.d.ts +16 -0
  106. package/dist/src/local/patch.js +17 -0
  107. package/dist/src/local/provider.d.ts +11 -0
  108. package/dist/src/local/provider.js +20 -0
  109. package/dist/src/local/snapshots.d.ts +7 -0
  110. package/dist/src/local/snapshots.js +11 -0
  111. package/dist/src/local/text.d.ts +1 -0
  112. package/dist/src/local/text.js +6 -0
  113. package/dist/src/local/tree.d.ts +50 -0
  114. package/dist/src/local/tree.js +16 -0
  115. package/dist/src/local/workspace-migration.d.ts +2 -0
  116. package/dist/src/local/workspace-migration.js +7 -0
  117. package/dist/src/local/worktrees.d.ts +46 -0
  118. package/dist/src/local/worktrees.js +14 -0
  119. package/dist/src/mcp/config.d.ts +75 -0
  120. package/dist/src/mcp/config.js +12 -0
  121. package/dist/src/mcp/connect.d.ts +28 -0
  122. package/dist/src/mcp/connect.js +9 -0
  123. package/dist/src/mcp/hub.d.ts +19 -0
  124. package/dist/src/mcp/hub.js +11 -0
  125. package/dist/src/mcp/oauth.d.ts +46 -0
  126. package/dist/src/mcp/oauth.js +12 -0
  127. package/dist/src/mcp/tools.d.ts +29 -0
  128. package/dist/src/mcp/tools.js +12 -0
  129. package/dist/src/open.d.ts +42 -0
  130. package/dist/src/open.js +44 -0
  131. package/dist/src/plugins/loader.d.ts +21 -0
  132. package/dist/src/plugins/loader.js +11 -0
  133. package/dist/src/postgres.d.ts +19 -0
  134. package/dist/src/postgres.js +8 -0
  135. package/dist/src/providers.d.ts +16 -0
  136. package/dist/src/providers.js +112 -0
  137. package/dist/src/secrets.d.ts +12 -0
  138. package/dist/src/secrets.js +8 -0
  139. package/dist/src/serve/binding.d.ts +39 -0
  140. package/dist/src/serve/binding.js +6 -0
  141. package/dist/src/serve/handler.d.ts +15 -0
  142. package/dist/src/serve/handler.js +8 -0
  143. package/dist/src/serve/stream-server.d.ts +6 -0
  144. package/dist/src/serve/stream-server.js +6 -0
  145. package/dist/src/session-index.d.ts +11 -0
  146. package/dist/src/session-index.js +11 -0
  147. package/dist/src/shell-env.d.ts +14 -0
  148. package/dist/src/shell-env.js +108 -0
  149. package/dist/src/sqlite-workers.d.ts +6 -0
  150. package/dist/src/sqlite-workers.js +6 -0
  151. package/dist/src/sqlite.d.ts +7 -0
  152. package/dist/src/sqlite.js +10 -0
  153. package/dist/src/store-owner.d.ts +15 -0
  154. package/dist/src/store-owner.js +9 -0
  155. package/dist/src/store-rows.d.ts +13 -0
  156. package/dist/src/store-rows.js +26 -0
  157. package/dist/src/store-usage.d.ts +25 -0
  158. package/dist/src/store-usage.js +16 -0
  159. package/dist/src/usage-scan.d.ts +24 -0
  160. package/dist/src/usage-scan.js +65 -0
  161. package/dist/src/usage-service.d.ts +22 -0
  162. package/dist/src/usage-service.js +12 -0
  163. package/dist/src/usage-summary.d.ts +9 -0
  164. package/dist/src/usage-summary.js +16 -0
  165. package/dist/src/usage-types.d.ts +86 -0
  166. package/dist/src/usage-types.js +0 -0
  167. package/dist/src/usage-worker.d.ts +1 -0
  168. package/dist/src/usage-worker.js +25 -0
  169. package/dist/src/usage.d.ts +72 -0
  170. package/dist/src/usage.js +13 -0
  171. package/package.json +132 -3
  172. package/src/canvas-preview.ts +402 -0
  173. package/src/credentials.ts +294 -0
  174. package/src/deploy/cloudflare/README.md +3 -0
  175. package/src/deploy/cloudflare/worker.ts +306 -0
  176. package/src/deploy/cloudflare/wrangler.jsonc +12 -0
  177. package/src/deploy/vercel/README.md +3 -0
  178. package/src/deploy/vercel/nitro.config.ts +29 -0
  179. package/src/deploy/vercel/server/routes/[...].ts +10 -0
  180. package/src/deploy/vercel/server/utils/host.ts +104 -0
  181. package/src/deploy/vercel/server/utils/repair.ts +35 -0
  182. package/src/deploy/vercel/server/utils/step.ts +25 -0
  183. package/src/deploy/vercel/server/workflows/drive.ts +46 -0
  184. package/src/deploy/vercel/tsconfig.json +9 -0
  185. package/src/deploy/vercel/types/bun.d.ts +2 -0
  186. package/src/durable-object.ts +386 -0
  187. package/src/hash.ts +5 -0
  188. package/src/identity-key.ts +20 -0
  189. package/src/identity.ts +66 -0
  190. package/src/index.ts +21 -0
  191. package/src/key-file.ts +53 -0
  192. package/src/listen-fetch.ts +409 -0
  193. package/src/listen.ts +228 -0
  194. package/src/local/command.ts +109 -0
  195. package/src/local/feed.ts +70 -0
  196. package/src/local/files.ts +812 -0
  197. package/src/local/git-watch.ts +189 -0
  198. package/src/local/git.ts +914 -0
  199. package/src/local/github.ts +692 -0
  200. package/src/local/identity.ts +21 -0
  201. package/src/local/jobs.ts +587 -0
  202. package/src/local/legacy-trust.ts +105 -0
  203. package/src/local/patch.ts +334 -0
  204. package/src/local/provider.ts +184 -0
  205. package/src/local/snapshots.ts +776 -0
  206. package/src/local/text.ts +9 -0
  207. package/src/local/tree.ts +398 -0
  208. package/src/local/workspace-migration.ts +95 -0
  209. package/src/local/worktrees.ts +239 -0
  210. package/src/mcp/config.ts +330 -0
  211. package/src/mcp/connect.ts +105 -0
  212. package/src/mcp/hub.ts +836 -0
  213. package/src/mcp/oauth.ts +436 -0
  214. package/src/mcp/tools.ts +333 -0
  215. package/src/open.ts +469 -0
  216. package/src/plugins/loader.ts +186 -0
  217. package/src/postgres.ts +492 -0
  218. package/src/providers.ts +135 -0
  219. package/src/secrets.ts +31 -0
  220. package/src/serve/binding.ts +628 -0
  221. package/src/serve/handler.ts +362 -0
  222. package/src/serve/stream-server.ts +176 -0
  223. package/src/session-index.ts +99 -0
  224. package/src/shell-env.ts +153 -0
  225. package/src/sqlite-workers.ts +283 -0
  226. package/src/sqlite.ts +528 -0
  227. package/src/store-owner.ts +98 -0
  228. package/src/store-rows.ts +110 -0
  229. package/src/store-usage.ts +344 -0
  230. package/src/usage-scan.ts +81 -0
  231. package/src/usage-service.ts +73 -0
  232. package/src/usage-summary.ts +79 -0
  233. package/src/usage-types.ts +87 -0
  234. package/src/usage-worker.ts +24 -0
  235. package/src/usage.ts +701 -0
@@ -0,0 +1,252 @@
1
+ import {
2
+ sha2562
3
+ } from "./canvas-preview-0nq75h9k.js";
4
+
5
+ // src/local/patch.ts
6
+ import { lineDiff } from "@nyte-ai/core";
7
+ import { writePatch } from "@nyte-ai/schema";
8
+ var PATCH_LIMIT2 = 1024 * 1024;
9
+ var ESCAPES = new Map([
10
+ ["a", 7],
11
+ ["b", 8],
12
+ ["f", 12],
13
+ ["n", 10],
14
+ ["r", 13],
15
+ ["t", 9],
16
+ ["v", 11],
17
+ ['"', 34],
18
+ ["\\", 92]
19
+ ]);
20
+ function splitDiff(output) {
21
+ const lines = output.split(`
22
+ `);
23
+ if (lines.at(-1) === "")
24
+ lines.pop();
25
+ const sections = [];
26
+ let index = 0;
27
+ while (index < lines.length) {
28
+ const header = lines[index] ?? "";
29
+ if (!header.startsWith("diff --git ")) {
30
+ index += 1;
31
+ continue;
32
+ }
33
+ const start = index;
34
+ const named = headerPaths(header.slice("diff --git ".length));
35
+ let oldPath = named?.old ?? null;
36
+ let newPath = named?.new ?? null;
37
+ let binary = false;
38
+ let hunked = false;
39
+ let added = 0;
40
+ let removed = 0;
41
+ index += 1;
42
+ while (index < lines.length && !(lines[index] ?? "").startsWith("diff --git ")) {
43
+ const line = lines[index] ?? "";
44
+ index += 1;
45
+ if (line.startsWith("@@ "))
46
+ hunked = true;
47
+ else if (hunked && line.startsWith("+"))
48
+ added += 1;
49
+ else if (hunked && line.startsWith("-"))
50
+ removed += 1;
51
+ else if (hunked)
52
+ continue;
53
+ else if (line.startsWith("--- "))
54
+ oldPath = sidePath(line.slice(4), "a/");
55
+ else if (line.startsWith("+++ "))
56
+ newPath = sidePath(line.slice(4), "b/");
57
+ else if (/^(?:rename|copy) from /u.test(line))
58
+ oldPath = unquote(line.replace(/^(?:rename|copy) from /u, ""));
59
+ else if (/^(?:rename|copy) to /u.test(line))
60
+ newPath = unquote(line.replace(/^(?:rename|copy) to /u, ""));
61
+ else if (line.startsWith("new file mode "))
62
+ oldPath = null;
63
+ else if (line.startsWith("deleted file mode "))
64
+ newPath = null;
65
+ else if (line.startsWith("Binary files ") || line === "GIT binary patch")
66
+ binary = true;
67
+ }
68
+ sections.push({
69
+ oldPath,
70
+ newPath,
71
+ binary,
72
+ hunked,
73
+ added,
74
+ removed,
75
+ text: `${lines.slice(start, index).join(`
76
+ `)}
77
+ `
78
+ });
79
+ }
80
+ return sections;
81
+ }
82
+ function sectionEntry(path, status, section) {
83
+ const digest = sha2562(section.text);
84
+ if (section.binary)
85
+ return { path, status, digest, kind: "binary" };
86
+ if (section.text.length > PATCH_LIMIT2)
87
+ return { path, status, digest, kind: "too-large", limit: PATCH_LIMIT2 };
88
+ if (!section.hunked)
89
+ return { path, status, digest, kind: "empty" };
90
+ return {
91
+ path,
92
+ status,
93
+ digest,
94
+ kind: "text",
95
+ added: section.added,
96
+ removed: section.removed,
97
+ patch: section.text
98
+ };
99
+ }
100
+ function textEntry2(path, status, before, after, options) {
101
+ const { hunks, added, removed } = lineDiff(before ?? "", after ?? "", options);
102
+ if (hunks.length === 0) {
103
+ const mode = options?.ignoreWhitespace === true ? "ignore-whitespace" : "";
104
+ return {
105
+ path,
106
+ status,
107
+ digest: sha2562(`${mode}\x00${before ?? ""}\x00${after ?? ""}`),
108
+ kind: "empty"
109
+ };
110
+ }
111
+ const patch = writePatch(path, status, hunks);
112
+ return { path, status, digest: sha2562(patch), kind: "text", added, removed, patch };
113
+ }
114
+ async function readPatches2(files, read, emptyDigest) {
115
+ const settle = (batch, ran) => {
116
+ const sections = splitDiff(ran.stdout.toString("utf8"));
117
+ return batch.map((file) => {
118
+ const section = sections.find((candidate) => (candidate.newPath ?? candidate.oldPath) === file.path);
119
+ return section === undefined ? { path: file.path, status: file.status, digest: emptyDigest(file), kind: "empty" } : sectionEntry(file.path, file.status, section);
120
+ });
121
+ };
122
+ const together = await read(files, PATCH_LIMIT2 * files.length + 4096).catch(() => null);
123
+ if (together !== null && !together.truncated && (together.code === 0 || together.code === 1))
124
+ return settle(files, together);
125
+ const entries = [];
126
+ for (const file of files) {
127
+ const failed = (reason) => ({
128
+ path: file.path,
129
+ status: file.status,
130
+ digest: "",
131
+ kind: "failed",
132
+ reason
133
+ });
134
+ const alone = await read([file], PATCH_LIMIT2 + 1).catch((error) => error instanceof Error ? error.message : String(error));
135
+ if (typeof alone === "string")
136
+ entries.push(failed(alone));
137
+ else if (alone.truncated)
138
+ entries.push({
139
+ path: file.path,
140
+ status: file.status,
141
+ digest: sha2562(alone.stdout),
142
+ kind: "too-large",
143
+ limit: PATCH_LIMIT2
144
+ });
145
+ else if (alone.code !== 0 && alone.code !== 1)
146
+ entries.push(failed(alone.stderr.trim() || "git diff failed"));
147
+ else
148
+ entries.push(...settle([file], alone));
149
+ }
150
+ return entries;
151
+ }
152
+ function lineStat2(before, after) {
153
+ const { added, removed } = lineDiff(before, after);
154
+ return { kind: "text", added, removed };
155
+ }
156
+ function headerPaths(rest) {
157
+ if (rest.startsWith('"')) {
158
+ const end = quotedEnd(rest);
159
+ const old = unquote(rest.slice(0, end + 1));
160
+ const next = unquote(rest.slice(end + 2));
161
+ return { old: old.replace(/^a\//, ""), new: next.replace(/^b\//, "") };
162
+ }
163
+ const half = (rest.length - 5) / 2;
164
+ if (Number.isInteger(half) && rest.startsWith("a/") && rest.slice(half + 2, half + 5) === " b/") {
165
+ const path = rest.slice(2, half + 2);
166
+ if (rest.slice(half + 5) === path)
167
+ return { old: path, new: path };
168
+ }
169
+ const split = /^.{2}(.*?) b\/(.*)$/su.exec(rest);
170
+ return split === null ? null : { old: split[1] ?? "", new: unquote(split[2] ?? "") };
171
+ }
172
+ function quotedEnd(text) {
173
+ for (let index = 1;index < text.length; index += 1) {
174
+ if (text[index] === "\\")
175
+ index += 1;
176
+ else if (text[index] === '"')
177
+ return index;
178
+ }
179
+ return text.length - 1;
180
+ }
181
+ function sidePath(text, prefix) {
182
+ const name = unquote(text.replace(/\t$/, ""));
183
+ if (name === "/dev/null")
184
+ return null;
185
+ return name.startsWith(prefix) ? name.slice(prefix.length) : name;
186
+ }
187
+ function unquote(text) {
188
+ if (!text.startsWith('"') || !text.endsWith('"') || text.length < 2)
189
+ return text;
190
+ const bytes = [];
191
+ const encoder = new TextEncoder;
192
+ for (let index = 1;index < text.length - 1; index += 1) {
193
+ const char = text[index] ?? "";
194
+ if (char !== "\\") {
195
+ bytes.push(...encoder.encode(char));
196
+ continue;
197
+ }
198
+ const next = text[index + 1] ?? "";
199
+ const octal = /^[0-7]{3}$/.exec(text.slice(index + 1, index + 4));
200
+ if (octal !== null) {
201
+ bytes.push(Number.parseInt(octal[0], 8));
202
+ index += 3;
203
+ continue;
204
+ }
205
+ bytes.push(ESCAPES.get(next) ?? next.charCodeAt(0));
206
+ index += 1;
207
+ }
208
+ return new TextDecoder().decode(new Uint8Array(bytes));
209
+ }
210
+ function parseNumstat2(output) {
211
+ const tokens = output.split("\x00");
212
+ const stats = new Map;
213
+ for (let index = 0;index < tokens.length; index += 1) {
214
+ const token = tokens[index] ?? "";
215
+ if (token === "")
216
+ continue;
217
+ const [added = "", removed = "", path = ""] = token.split("\t");
218
+ let name = path;
219
+ if (path === "") {
220
+ name = tokens[index + 2] ?? "";
221
+ index += 2;
222
+ }
223
+ stats.set(name, added === "-" || removed === "-" ? { kind: "binary" } : { kind: "text", added: Number(added) || 0, removed: Number(removed) || 0 });
224
+ }
225
+ return stats;
226
+ }
227
+ function parseNameStatus2(output) {
228
+ const tokens = output.split("\x00");
229
+ const changed = [];
230
+ for (let index = 0;index < tokens.length; index += 1) {
231
+ const code = tokens[index] ?? "";
232
+ if (code === "")
233
+ continue;
234
+ const letter = code[0];
235
+ if (letter === "R" || letter === "C") {
236
+ const from = tokens[index + 1] ?? "";
237
+ const path = tokens[index + 2] ?? "";
238
+ index += 2;
239
+ changed.push(letter === "R" ? { path, status: "renamed", from } : { path, status: "added" });
240
+ continue;
241
+ }
242
+ const path = tokens[index + 1] ?? "";
243
+ index += 1;
244
+ changed.push({
245
+ path,
246
+ status: letter === "A" ? "added" : letter === "D" ? "deleted" : letter === "U" ? "conflicted" : "modified"
247
+ });
248
+ }
249
+ return changed;
250
+ }
251
+
252
+ export { PATCH_LIMIT2, textEntry2, readPatches2, lineStat2, parseNumstat2, parseNameStatus2 };
@@ -0,0 +1,189 @@
1
+ // src/mcp/tools.ts
2
+ import { createHash } from "node:crypto";
3
+ import { McpClient } from "@earendil-works/pi-mcp";
4
+ import { followedTrace, startSpan, traceparent } from "@nyte-ai/core";
5
+ import { isJson, isJsonObject } from "@nyte-ai/schema";
6
+ import { Errors, Meta } from "typebox/schema";
7
+ var NAME_LIMIT = 64;
8
+ var RESULT_CHARS = 32000;
9
+ var HEAD_CHARS = 8000;
10
+ var CALL_LIMIT_MS = 10 * 60000;
11
+ var DRAFT_2020_12 = Meta["https://json-schema.org/draft/2020-12/schema"];
12
+ var DRAFTS = new Map(Object.entries(Meta).filter(([uri]) => !uri.includes("draft-03")).map(([uri, meta]) => [draftKey(uri), meta]));
13
+ function toolExposure2(entry, tool) {
14
+ const exact = entry.toolExposure.find(([pattern]) => pattern === tool);
15
+ if (exact !== undefined)
16
+ return exact[1];
17
+ const matched = entry.toolExposure.find(([pattern]) => globMatches(pattern, tool));
18
+ return matched?.[1] ?? entry.exposure;
19
+ }
20
+ function checkToolSchemas2(server, tools) {
21
+ const usable = [];
22
+ const issues = [];
23
+ for (const tool of tools) {
24
+ const problem = findSchemaProblem(tool.inputSchema);
25
+ if (problem === null) {
26
+ usable.push(tool);
27
+ continue;
28
+ }
29
+ issues.push({
30
+ severity: "error",
31
+ path: ["mcpServers", server, "tools", tool.name, "inputSchema"],
32
+ message: `${server} lists ${tool.name} with an input schema that is not valid JSON Schema (${problem}), so sessions do not get the tool.`
33
+ });
34
+ }
35
+ return { usable, issues };
36
+ }
37
+ function findSchemaProblem(schema) {
38
+ if (schema["type"] !== "object")
39
+ return 'its type is not "object"';
40
+ const declared = schema["$schema"];
41
+ const named = typeof declared === "string" ? DRAFTS.get(draftKey(declared)) : undefined;
42
+ const drafts = named === undefined ? [...DRAFTS.values()] : [named];
43
+ if (drafts.some((meta) => Errors(Meta, meta, schema)[0]))
44
+ return null;
45
+ const [, errors] = Errors(Meta, named ?? DRAFT_2020_12, schema);
46
+ const first = new Map;
47
+ for (const error of errors)
48
+ if (!first.has(error.instancePath))
49
+ first.set(error.instancePath, `${error.instancePath || "/"} ${error.message}`);
50
+ return [...first.values()].slice(0, 3).join("; ");
51
+ }
52
+ function draftKey(uri) {
53
+ return uri.replace(/^https?:\/\//, "").replace(/#$/, "");
54
+ }
55
+
56
+ class TracingMcpClient2 extends McpClient {
57
+ request(method, params, options) {
58
+ const traceparent = options !== undefined && "traceparent" in options && typeof options.traceparent === "string" ? options.traceparent : null;
59
+ return super.request(method, traceparent === null || params?._meta !== undefined ? params : { ...params, _meta: { traceparent } }, options);
60
+ }
61
+ }
62
+ function bridgeTools2(entry, tools, call) {
63
+ const names = tools.map((tool) => toolName(entry.name, tool.name));
64
+ const counts = Map.groupBy(names, (name) => name);
65
+ return tools.map((tool, index) => {
66
+ const name = names[index];
67
+ const unique = (counts.get(name)?.length ?? 0) > 1 ? hashed(name, tool.name) : name;
68
+ return bridge(entry, tool, call, unique);
69
+ });
70
+ }
71
+ function toolName(server, tool) {
72
+ const name = `mcp__${server}__${tool}`.replace(/[^A-Za-z0-9_]/g, "_");
73
+ return name.length > NAME_LIMIT ? hashed(name, tool) : name;
74
+ }
75
+ function hashed(name, tool) {
76
+ const suffix = createHash("sha256").update(tool).digest("hex").slice(0, 8);
77
+ return `${name.slice(0, NAME_LIMIT - suffix.length - 1)}_${suffix}`;
78
+ }
79
+ function globMatches(pattern, value) {
80
+ if (!pattern.includes("*"))
81
+ return false;
82
+ const source = pattern.split("*").map((part) => part.replace(/[.+?^${}()|[\]\\]/g, "\\$&")).join(".*");
83
+ return new RegExp(`^${source}$`).test(value);
84
+ }
85
+ function bridge(entry, tool, call, name) {
86
+ const output = tool.outputSchema;
87
+ const definition = {
88
+ name,
89
+ namespace: `mcp/${entry.name}`,
90
+ description: tool.description ?? tool.title ?? tool.name,
91
+ parameters: passthrough(tool.inputSchema),
92
+ exposure: toolExposure2(entry, tool.name),
93
+ class: () => ({ kind: "custom", label: `${entry.name}: ${tool.title ?? tool.name}` }),
94
+ effects: tool.annotations?.readOnlyHint === true ? "none" : "workspace",
95
+ replay: tool.annotations?.readOnlyHint === true || tool.annotations?.idempotentHint === true ? "safe" : "never",
96
+ async execute(args, invocation) {
97
+ const limitMs = Math.max(entry.timeoutMs, CALL_LIMIT_MS);
98
+ const limit = AbortSignal.timeout(limitMs);
99
+ let result;
100
+ const trace = followedTrace(invocation.session.id);
101
+ const ended = startSpan("mcp.call", trace, {
102
+ session: invocation.session.id,
103
+ server: entry.name,
104
+ tool: tool.name
105
+ });
106
+ try {
107
+ result = await call(tool.name, args, {
108
+ signal: AbortSignal.any([invocation.signal, limit]),
109
+ timeoutMs: entry.timeoutMs,
110
+ onProgress: (update) => invocation.progress(toolProgress(update)),
111
+ traceparent: trace === null ? undefined : traceparent(trace)
112
+ });
113
+ } catch (error) {
114
+ ended({ failed: true });
115
+ if (!limit.aborted || invocation.signal.aborted)
116
+ throw error;
117
+ throw new Error(`${tool.name} was still running after ${limitMs / 60000} minutes, so it was cancelled.`, { cause: error });
118
+ }
119
+ ended({ failed: result.isError === true });
120
+ const content = await readToolContent(result, invocation.env, tool.name);
121
+ if (result.isError === true)
122
+ throw new Error(content.flatMap((item) => item.kind === "text" ? [item.text] : []).join(`
123
+ `) || `${tool.name} failed.`);
124
+ const structured = result.structuredContent;
125
+ if (output === undefined || !isJson(structured) || JSON.stringify(structured).length > RESULT_CHARS)
126
+ return { content };
127
+ return { content, output: structured };
128
+ }
129
+ };
130
+ return output === undefined ? definition : { ...definition, output: passthrough(output) };
131
+ }
132
+ function toolProgress(update) {
133
+ const step = update.total === undefined ? `${update.progress}` : `${update.progress} of ${update.total}`;
134
+ const text = update.message ?? step;
135
+ return update.total === undefined || update.total <= 0 ? { text } : { text, fraction: Math.min(1, update.progress / update.total) };
136
+ }
137
+ async function readToolContent(result, env, tool) {
138
+ const content = [];
139
+ for (const block of result.content) {
140
+ if (block.type === "text")
141
+ content.push({ kind: "text", text: block.text });
142
+ else if (block.type === "image")
143
+ content.push({
144
+ kind: "file",
145
+ blob: await env.files.upload(once(Uint8Array.fromBase64(block.data))),
146
+ mime: block.mimeType
147
+ });
148
+ else
149
+ content.push({ kind: "text", text: JSON.stringify(block) });
150
+ }
151
+ const text = content.flatMap((item) => item.kind === "text" ? [item.text] : []).join(`
152
+ `);
153
+ if (text.length <= RESULT_CHARS)
154
+ return content;
155
+ const name = `${tool}.txt`;
156
+ const elided = (text.length - RESULT_CHARS).toLocaleString("en-US");
157
+ return [
158
+ {
159
+ kind: "text",
160
+ text: `${text.slice(0, HEAD_CHARS)}
161
+
162
+ [${elided} characters cut from the middle; the whole result is attached as ${name}.]
163
+
164
+ ${text.slice(HEAD_CHARS - RESULT_CHARS)}`
165
+ },
166
+ {
167
+ kind: "file",
168
+ blob: await env.files.upload(once(new TextEncoder().encode(text))),
169
+ mime: "text/plain",
170
+ name
171
+ },
172
+ ...content.filter((item) => item.kind === "file")
173
+ ];
174
+ }
175
+ function passthrough(json) {
176
+ return {
177
+ "~standard": {
178
+ version: 1,
179
+ vendor: "mcp",
180
+ validate: (value) => isJson(value) && isJsonObject(value) ? { value } : { issues: [{ message: "Expected a JSON object." }] },
181
+ jsonSchema: { input: () => json, output: () => json }
182
+ }
183
+ };
184
+ }
185
+ async function* once(bytes) {
186
+ yield bytes;
187
+ }
188
+
189
+ export { toolExposure2, checkToolSchemas2, TracingMcpClient2, bridgeTools2 };