@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,374 @@
1
+ import {
2
+ prefixEnd2,
3
+ mintRevision2,
4
+ decodeEvent2,
5
+ parseNumber2,
6
+ parseText2,
7
+ parseRef2,
8
+ parseStoredRecord2,
9
+ parseStoredObject2,
10
+ loggedRow2,
11
+ collect2,
12
+ memoryReader2
13
+ } from "./canvas-preview-69fkk9yn.js";
14
+ import {
15
+ sqliteWorkers2
16
+ } from "./canvas-preview-zaaj99wd.js";
17
+ import {
18
+ sessionIndexChanges2,
19
+ sqlSessionIndex2
20
+ } from "./canvas-preview-0cmbkp2j.js";
21
+
22
+ // src/sqlite.ts
23
+ import { mkdirSync, readdirSync, rmSync, writeFileSync } from "node:fs";
24
+ import { dirname, join } from "node:path";
25
+ import process from "node:process";
26
+ import { DatabaseSync } from "node:sqlite";
27
+ import { asSeq } from "@nyte-ai/schema";
28
+ import { dev } from "@nyte-ai/core";
29
+ import {
30
+ admits,
31
+ fenceNames,
32
+ assertStoreVersion,
33
+ blobId,
34
+ decodeObject,
35
+ collectSessionEvents,
36
+ migrateStore,
37
+ objectId,
38
+ sessionIndexRef,
39
+ parseSessionRef
40
+ } from "@nyte-ai/core/store";
41
+ var BUSY_TIMEOUT_MS = 5000;
42
+ var BACKUPS_KEPT = 3;
43
+ var PUT_BODY = "INSERT INTO objects (id, body) VALUES (?, ?) ON CONFLICT (id) DO UPDATE SET body = excluded.body WHERE objects.body IS NULL";
44
+ function storePath2(home) {
45
+ return process.env["NYTE_DB"] ?? join(home, ".nyte", "nyte.db");
46
+ }
47
+ function sqliteStore2(input) {
48
+ let database = null;
49
+ let opening = null;
50
+ let closing = null;
51
+ let workers = null;
52
+ const open = async () => {
53
+ let created;
54
+ try {
55
+ created = new DatabaseSync("path" in input ? input.path : ":memory:", {
56
+ timeout: BUSY_TIMEOUT_MS
57
+ });
58
+ if ("path" in input)
59
+ created.exec("PRAGMA journal_mode = WAL");
60
+ created.exec("PRAGMA synchronous = NORMAL");
61
+ created.exec("PRAGMA checkpoint_fullfsync = ON");
62
+ created.exec("PRAGMA journal_size_limit = 33554432");
63
+ await migrateStore(sqliteTarget(created, "path" in input ? input.path : null));
64
+ created.exec("PRAGMA optimize = 0x10012");
65
+ } catch (error) {
66
+ created?.close();
67
+ throw error;
68
+ }
69
+ database = created;
70
+ workers = "path" in input ? sqliteWorkers2(created, input.path) : null;
71
+ return connect(created, workers);
72
+ };
73
+ const connection = () => {
74
+ if (closing !== null)
75
+ return closing.then(connection);
76
+ opening ??= open().catch((error) => {
77
+ opening = null;
78
+ throw error;
79
+ });
80
+ return opening;
81
+ };
82
+ return {
83
+ open: connection,
84
+ close() {
85
+ closing ??= (async () => {
86
+ await opening?.catch(() => {
87
+ return;
88
+ });
89
+ await workers?.close();
90
+ database?.close();
91
+ workers = null;
92
+ database = null;
93
+ opening = null;
94
+ })().finally(() => {
95
+ closing = null;
96
+ });
97
+ return closing;
98
+ }
99
+ };
100
+ }
101
+ function hasTable(database, name) {
102
+ return database.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(name) !== undefined;
103
+ }
104
+ function storedVersion(database) {
105
+ if (!hasTable(database, "store_meta"))
106
+ return 0;
107
+ const row = database.prepare("SELECT version FROM store_meta WHERE id = 1").get();
108
+ return row === undefined ? 0 : parseNumber2(row.version);
109
+ }
110
+ function sqliteTarget(database, path) {
111
+ const target = {
112
+ dialect: "sqlite",
113
+ async stamp() {
114
+ return {
115
+ version: storedVersion(database),
116
+ empty: !hasTable(database, "refs") || database.prepare("SELECT 1 FROM refs LIMIT 1").get() === undefined
117
+ };
118
+ },
119
+ async records() {
120
+ return database.prepare("SELECT refs.name, refs.target, refs.revision, objects.body FROM refs JOIN objects ON objects.id = refs.target WHERE objects.body IS NOT NULL").all().map(parseStoredRecord2);
121
+ },
122
+ async* objects(kind) {
123
+ yield* database.prepare("SELECT id, body FROM objects WHERE body IS NOT NULL AND instr(body, ?) > 0").all(`"kind":${JSON.stringify(kind)}`).map(parseStoredObject2);
124
+ },
125
+ async* logs() {
126
+ if (!hasTable(database, "log"))
127
+ return;
128
+ const read = database.prepare("SELECT seq, event FROM log WHERE session = ? ORDER BY seq");
129
+ for (const row of database.prepare("SELECT DISTINCT session FROM log").all()) {
130
+ const session = parseText2(row.session);
131
+ if (session !== null)
132
+ yield { session, events: read.all(session).map(loggedRow2) };
133
+ }
134
+ },
135
+ async commit(change) {
136
+ database.exec("BEGIN IMMEDIATE");
137
+ try {
138
+ if (storedVersion(database) !== change.from) {
139
+ database.exec("ROLLBACK");
140
+ return "moved";
141
+ }
142
+ for (const statement of change.sql)
143
+ database.exec(statement);
144
+ const putBody = database.prepare(PUT_BODY);
145
+ const repoint = database.prepare("UPDATE refs SET target = ?, revision = ? WHERE name = ? AND revision = ?");
146
+ for (const moved of change.repoints) {
147
+ write(database, putBody, moved.id, moved.body);
148
+ if (Number(repoint.run(moved.id, mintRevision2(), moved.name, moved.expect).changes) === 0) {
149
+ database.exec("ROLLBACK");
150
+ return "conflict";
151
+ }
152
+ updateSessionIndex(database, moved.name, moved.id, mintRevision2());
153
+ }
154
+ const create = database.prepare("INSERT INTO refs (name, target, revision) VALUES (?, ?, ?) ON CONFLICT (name) DO NOTHING");
155
+ for (const created of change.creates) {
156
+ write(database, putBody, created.target, created.body);
157
+ const revision = mintRevision2();
158
+ if (Number(create.run(created.name, created.target, revision).changes) > 0)
159
+ updateSessionIndex(database, created.name, created.target, revision);
160
+ }
161
+ const relog = database.prepare("UPDATE log SET event = ? WHERE session = ? AND seq = ? AND event = ?");
162
+ for (const row of change.relogs) {
163
+ if (Number(relog.run(row.event, row.session, row.seq, row.expect).changes) === 0) {
164
+ database.exec("ROLLBACK");
165
+ return "conflict";
166
+ }
167
+ }
168
+ if (change.reindexSessions)
169
+ for (const row of database.prepare("SELECT name, target, revision FROM refs").all()) {
170
+ const ref = parseRef2(row);
171
+ updateSessionIndex(database, ref.name, ref.target, ref.revision);
172
+ }
173
+ database.prepare("INSERT INTO store_meta (id, version) VALUES (1, ?) ON CONFLICT (id) DO UPDATE SET version = excluded.version").run(change.to);
174
+ database.exec("COMMIT");
175
+ return "committed";
176
+ } catch (error) {
177
+ if (database.isTransaction)
178
+ database.exec("ROLLBACK");
179
+ throw error;
180
+ }
181
+ }
182
+ };
183
+ if (path === null)
184
+ return target;
185
+ return {
186
+ ...target,
187
+ backup: async (from, to, names, log) => backup(database, path, from, to, names, log)
188
+ };
189
+ }
190
+ function backup(database, path, from, to, names, log) {
191
+ const folder = join(dirname(path), "backups");
192
+ mkdirSync(folder, { recursive: true, mode: 448 });
193
+ const at = new Date().toISOString().replaceAll(":", "-");
194
+ const read = database.prepare("SELECT name, target, revision FROM refs WHERE name = ?");
195
+ const rows = names.flatMap((name) => {
196
+ const row = read.get(name);
197
+ return row === undefined ? [] : [parseRef2(row)];
198
+ });
199
+ writeFileSync(join(folder, `store-${at}-${process.pid}-${crypto.randomUUID()}-v${from}-v${to}.json`), JSON.stringify({
200
+ refs: rows,
201
+ log: log.map((row) => ({ session: row.session, seq: row.seq, event: row.expect }))
202
+ }), { mode: 384 });
203
+ const copies = readdirSync(folder).filter((file) => /^store-.+-v\d+-v\d+\.(?:db|json)$/u.test(file)).sort();
204
+ for (const file of copies.slice(0, -BACKUPS_KEPT))
205
+ rmSync(join(folder, file), { force: true });
206
+ }
207
+ function connect(database, workers) {
208
+ const putBody = database.prepare(PUT_BODY);
209
+ const putBytes = database.prepare("INSERT INTO objects (id, bytes) VALUES (?, ?) ON CONFLICT (id) DO UPDATE SET bytes = excluded.bytes WHERE objects.bytes IS NULL");
210
+ const getBody = database.prepare("SELECT body FROM objects WHERE id = ?");
211
+ const getBytes = database.prepare("SELECT bytes FROM objects WHERE id = ?");
212
+ const getRef = database.prepare("SELECT name, target, revision FROM refs WHERE name = ?");
213
+ const listFrom = database.prepare("SELECT name, target, revision FROM refs WHERE name >= ? ORDER BY name");
214
+ const listRange = database.prepare("SELECT name, target, revision FROM refs WHERE name >= ? AND name < ? ORDER BY name");
215
+ const putRef = database.prepare("INSERT INTO refs (name, target, revision) VALUES (?, ?, ?) ON CONFLICT (name) DO UPDATE SET target = excluded.target, revision = excluded.revision");
216
+ const deleteRef = database.prepare("DELETE FROM refs WHERE name = ?");
217
+ const audit = auditing(database);
218
+ const append = database.prepare("INSERT INTO log (session, seq, at, event) VALUES (?, ?, ?, ?)");
219
+ const readLog = database.prepare("SELECT seq, at, event FROM log WHERE session = ? AND seq > ? ORDER BY seq LIMIT ?");
220
+ const readTail = database.prepare("SELECT MAX(seq) AS tail FROM log WHERE session = ?");
221
+ const readCheckpoint = database.prepare("SELECT seq, body FROM fold_checkpoints WHERE session = ?");
222
+ const writeCheckpoint = database.prepare("INSERT INTO fold_checkpoints (session, seq, body) VALUES (?, ?, ?) ON CONFLICT (session) DO UPDATE SET seq = excluded.seq, body = excluded.body WHERE excluded.seq >= fold_checkpoints.seq");
223
+ const readGap = database.prepare("SELECT COUNT(*) AS events, COALESCE(SUM(LENGTH(CAST(event AS BLOB))), 0) AS bytes FROM log WHERE session = ? AND seq > ?");
224
+ const readVersion = database.prepare("SELECT version FROM store_meta WHERE id = 1");
225
+ const readDataVersion = database.prepare("PRAGMA data_version");
226
+ const read = async (statement, ...params) => await workers?.read(statement.sourceSQL, params) ?? statement.all(...params);
227
+ const tail = (session) => {
228
+ const row = readTail.get(session);
229
+ return asSeq(row?.tail === null || row?.tail === undefined ? 0 : parseNumber2(row.tail));
230
+ };
231
+ const ref = (name) => {
232
+ const row = getRef.get(name);
233
+ return row === undefined ? null : parseRef2(row);
234
+ };
235
+ return {
236
+ commitMark: async () => parseNumber2(readDataVersion.get()?.data_version),
237
+ sessions: sqlSessionIndex2(async (text, values) => await workers?.read(text, values) ?? database.prepare(text).all(...values)),
238
+ objects: {
239
+ async put(object) {
240
+ const id = await objectId(object);
241
+ write(database, putBody, id, JSON.stringify(object));
242
+ workers?.check();
243
+ return id;
244
+ },
245
+ async get(id) {
246
+ const body = parseText2(getBody.get(id)?.body);
247
+ return body === null ? null : decodeObject(body);
248
+ },
249
+ async putBlob(bytes) {
250
+ const joined = await collect2(bytes);
251
+ const id = await blobId(joined);
252
+ write(database, putBytes, id, joined);
253
+ workers?.check();
254
+ return id;
255
+ },
256
+ async blob(id) {
257
+ const bytes = getBytes.get(id)?.bytes;
258
+ return bytes instanceof Uint8Array ? memoryReader2(bytes) : null;
259
+ }
260
+ },
261
+ refs: {
262
+ get: async (name) => ref(name),
263
+ async list(prefix) {
264
+ const end = prefixEnd2(prefix);
265
+ const rows = end === null ? await read(listFrom, prefix) : await read(listRange, prefix, end);
266
+ return rows.map(parseRef2);
267
+ },
268
+ async set(updates) {
269
+ const logged = collectSessionEvents(updates);
270
+ const waiting = performance.now();
271
+ database.exec("BEGIN IMMEDIATE");
272
+ const acquired = performance.now();
273
+ try {
274
+ assertStoreVersion(parseNumber2(readVersion.get()?.version ?? 0));
275
+ const before = new Map;
276
+ for (const update of updates)
277
+ if (!before.has(update.name))
278
+ before.set(update.name, ref(update.name) ?? undefined);
279
+ const fenced = fenceNames(updates).find((name) => ref(name) === null);
280
+ if (fenced !== undefined) {
281
+ database.exec("ROLLBACK");
282
+ return { kind: "fenced", name: fenced };
283
+ }
284
+ const stale = updates.find((update) => !admits(update, before.get(update.name)));
285
+ if (stale !== undefined) {
286
+ database.exec("ROLLBACK");
287
+ return {
288
+ kind: "stale",
289
+ name: stale.name,
290
+ revision: before.get(stale.name)?.revision ?? null
291
+ };
292
+ }
293
+ const touched = new Map;
294
+ const current = new Map([...before].map(([name, row]) => [name, row?.revision ?? null]));
295
+ const revisions = updates.map((update) => {
296
+ const revision = mintRevision2();
297
+ if (update.target === null)
298
+ deleteRef.run(update.name);
299
+ else
300
+ putRef.run(update.name, update.target, revision);
301
+ audit?.run(Date.now(), process.pid, fenceNames([update]).find((name) => name.startsWith("processes/")) ?? null, update.name, current.get(update.name) ?? null, update.target === null ? null : revision, update.target);
302
+ current.set(update.name, update.target === null ? null : revision);
303
+ updateSessionIndex(database, update.name, update.target, revision);
304
+ const session = parseSessionRef(update.name);
305
+ if (session !== null)
306
+ touched.set(session, revision);
307
+ return revision;
308
+ });
309
+ for (const [session, version] of touched)
310
+ database.prepare("UPDATE session_index SET version = ? WHERE session = ?").run(version, session);
311
+ const at = Date.now();
312
+ const tails = new Map;
313
+ const appended = logged.map(({ session, event }) => {
314
+ const seq = (tails.get(session) ?? tail(session)) + 1;
315
+ tails.set(session, seq);
316
+ write(database, append, session, seq, at, JSON.stringify(event));
317
+ return asSeq(seq);
318
+ });
319
+ database.exec("COMMIT");
320
+ workers?.check();
321
+ return { kind: "set", logged: appended, at, revisions };
322
+ } catch (error) {
323
+ if (database.isTransaction)
324
+ database.exec("ROLLBACK");
325
+ throw error;
326
+ } finally {
327
+ dev("sqlite", "transaction", {
328
+ connection: "writer",
329
+ lockWaitMs: acquired - waiting,
330
+ executionMs: performance.now() - acquired
331
+ });
332
+ }
333
+ },
334
+ async log(session, after, limit) {
335
+ return (await read(readLog, session, after, limit)).map((row) => decodeEvent2(parseNumber2(row.seq), parseNumber2(row.at), parseText2(row.event) ?? ""));
336
+ },
337
+ tail: async (session) => tail(session)
338
+ },
339
+ checkpoints: {
340
+ async read(session) {
341
+ const [row] = await read(readCheckpoint, session);
342
+ const body = parseText2(row?.body);
343
+ return row === undefined || body === null ? null : { seq: asSeq(parseNumber2(row.seq)), body };
344
+ },
345
+ async write(session, checkpoint) {
346
+ write(database, writeCheckpoint, session, checkpoint.seq, checkpoint.body);
347
+ workers?.check();
348
+ },
349
+ async gap(session, after) {
350
+ const [row] = await read(readGap, session, after);
351
+ return { events: parseNumber2(row?.events ?? 0), bytes: parseNumber2(row?.bytes ?? 0) };
352
+ }
353
+ }
354
+ };
355
+ }
356
+ function auditing(database) {
357
+ if (process.env.NYTE_STORE_AUDIT !== "1")
358
+ return null;
359
+ database.exec("CREATE TABLE IF NOT EXISTS store_audit (id INTEGER PRIMARY KEY, at INTEGER NOT NULL, pid INTEGER NOT NULL, writer TEXT, name TEXT NOT NULL, before TEXT, after TEXT, target TEXT)");
360
+ return database.prepare("INSERT INTO store_audit (at, pid, writer, name, before, after, target) VALUES (?, ?, ?, ?, ?, ?, ?)");
361
+ }
362
+ function updateSessionIndex(database, name, target, revision) {
363
+ if (sessionIndexRef(name) === null)
364
+ return;
365
+ const body = target === null ? null : parseText2(database.prepare("SELECT body FROM objects WHERE id = ?").get(target)?.body);
366
+ for (const change of sessionIndexChanges2(name, body === null ? null : decodeObject(body), revision))
367
+ database.prepare(change.text).run(...change.values);
368
+ }
369
+ function write(database, statement, ...params) {
370
+ const size = params.reduce((total, value) => total + (typeof value === "string" ? value.length : ArrayBuffer.isView(value) ? value.byteLength : 0), 0);
371
+ return (size > 64 * 1024 ? database.prepare(statement.sourceSQL) : statement).run(...params);
372
+ }
373
+
374
+ export { storePath2, sqliteStore2 };
@@ -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 };