@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,34 @@
1
+ // src/identity.ts
2
+ import { SdkError } from "@nyte-ai/schema";
3
+ var PKCS8_PREFIX = Uint8Array.fromHex("302e020100300506032b657004220420");
4
+ var encoder = new TextEncoder;
5
+ async function seedSigner2(id, seed) {
6
+ const { signing, publicKey } = await identityKeys(seed);
7
+ return {
8
+ id,
9
+ async sign(nonce) {
10
+ const signature = new Uint8Array(await crypto.subtle.sign("Ed25519", signing, encoder.encode(`nyte/identity
11
+ ${id}
12
+ ${nonce}`)));
13
+ return {
14
+ hostId: id,
15
+ nonce,
16
+ signature: signature.toBase64({ alphabet: "base64url", omitPadding: true }),
17
+ publicKey
18
+ };
19
+ }
20
+ };
21
+ }
22
+ async function identityKeys(seed) {
23
+ if (seed.length !== 32)
24
+ throw new SdkError("invalid", `The identity seed is ${seed.length} bytes, not 32.`);
25
+ const pkcs8 = new Uint8Array([...PKCS8_PREFIX, ...seed]);
26
+ const readable = await crypto.subtle.importKey("pkcs8", pkcs8, "Ed25519", true, ["sign"]);
27
+ const { x } = await crypto.subtle.exportKey("jwk", readable);
28
+ if (x === undefined)
29
+ throw new SdkError("internal", "The identity key has no public half.");
30
+ const signing = await crypto.subtle.importKey("pkcs8", pkcs8, "Ed25519", false, ["sign"]);
31
+ return { signing, publicKey: x };
32
+ }
33
+
34
+ export { seedSigner2 };
@@ -0,0 +1,295 @@
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
+ sessionIndexChanges2,
16
+ sqlSessionIndex2,
17
+ postgresSessionIndexQuery2
18
+ } from "./canvas-preview-0cmbkp2j.js";
19
+
20
+ // src/postgres.ts
21
+ import { asSeq } from "@nyte-ai/schema";
22
+ import {
23
+ admits,
24
+ fenceNames,
25
+ assertStoreVersion,
26
+ blobId,
27
+ decodeObject,
28
+ collectSessionEvents,
29
+ migrateStore,
30
+ objectId,
31
+ sessionIndexRef,
32
+ parseSessionRef
33
+ } from "@nyte-ai/core/store";
34
+ import { Pool } from "pg";
35
+ var MIGRATION_LOCK = "SELECT pg_advisory_xact_lock(hashtextextended('nyte:store', 0))";
36
+ var SHARED_MIGRATION_LOCK = "SELECT pg_advisory_xact_lock_shared(hashtextextended('nyte:store', 0))";
37
+ function postgresStore2(input) {
38
+ const pool = "pool" in input ? input.pool : new Pool({ connectionString: input.connectionString });
39
+ let ready = null;
40
+ return {
41
+ open() {
42
+ ready ??= migrateStore(postgresTarget(pool)).then(() => connect(pool), (error) => {
43
+ ready = null;
44
+ throw error;
45
+ });
46
+ return ready;
47
+ },
48
+ async close() {
49
+ ready = null;
50
+ if (!("pool" in input))
51
+ await pool.end();
52
+ }
53
+ };
54
+ }
55
+ async function storedVersion(client) {
56
+ const { rows } = await client.query("SELECT to_regclass('store_meta') IS NOT NULL AS stamped");
57
+ if (rows[0]?.stamped !== true)
58
+ return 0;
59
+ const stamp = await client.query("SELECT version FROM store_meta WHERE id = 1");
60
+ const version = stamp.rows[0]?.version;
61
+ return version === undefined ? 0 : parseNumber2(version);
62
+ }
63
+ function postgresTarget(pool) {
64
+ return {
65
+ dialect: "postgres",
66
+ stamp: () => withClient(pool, async (client) => {
67
+ const version = await storedVersion(client);
68
+ const { rows } = await client.query("SELECT to_regclass('refs') IS NOT NULL AS present");
69
+ const empty = rows[0]?.present !== true || (await client.query("SELECT 1 FROM refs LIMIT 1")).rows.length === 0;
70
+ return { version, empty };
71
+ }),
72
+ records: async () => (await withClient(pool, (client) => client.query("SELECT refs.name, refs.target, refs.revision, objects.body FROM refs JOIN objects ON objects.id = refs.target WHERE objects.body IS NOT NULL"))).rows.map(parseStoredRecord2),
73
+ async* objects(kind) {
74
+ const { rows } = await withClient(pool, (client) => client.query("SELECT id, body FROM objects WHERE body IS NOT NULL AND strpos(body, $1) > 0", [`"kind":${JSON.stringify(kind)}`]));
75
+ yield* rows.map(parseStoredObject2);
76
+ },
77
+ async* logs() {
78
+ const sessions = await withClient(pool, async (client) => {
79
+ const { rows } = await client.query("SELECT to_regclass('log') IS NOT NULL AS present");
80
+ return rows[0]?.present === true ? (await client.query("SELECT DISTINCT session FROM log")).rows : [];
81
+ });
82
+ for (const row of sessions) {
83
+ const session = parseText2(row.session);
84
+ if (session === null)
85
+ continue;
86
+ const { rows } = await withClient(pool, (client) => client.query("SELECT seq, event FROM log WHERE session = $1 ORDER BY seq", [session]));
87
+ yield { session, events: rows.map(loggedRow2) };
88
+ }
89
+ },
90
+ commit: (change) => withClient(pool, async (client) => {
91
+ await client.query("BEGIN");
92
+ try {
93
+ await client.query(MIGRATION_LOCK);
94
+ if (await storedVersion(client) !== change.from) {
95
+ await client.query("ROLLBACK");
96
+ return "moved";
97
+ }
98
+ for (const statement of change.sql)
99
+ await client.query(statement);
100
+ for (const moved of change.repoints) {
101
+ await client.query("INSERT INTO objects (id, body) VALUES ($1, $2) ON CONFLICT (id) DO UPDATE SET body = excluded.body WHERE objects.body IS NULL", [moved.id, moved.body]);
102
+ const { rows } = await client.query("UPDATE refs SET target = $1, revision = $2 WHERE name = $3 AND revision = $4 RETURNING name", [moved.id, mintRevision2(), moved.name, moved.expect]);
103
+ if (rows.length === 0) {
104
+ await client.query("ROLLBACK");
105
+ return "conflict";
106
+ }
107
+ await updateSessionIndex(client, moved.name, moved.id, mintRevision2());
108
+ }
109
+ for (const created of change.creates) {
110
+ await client.query("INSERT INTO objects (id, body) VALUES ($1, $2) ON CONFLICT (id) DO UPDATE SET body = excluded.body WHERE objects.body IS NULL", [created.target, created.body]);
111
+ const revision = mintRevision2();
112
+ const { rows } = await client.query("INSERT INTO refs (name, target, revision) VALUES ($1, $2, $3) ON CONFLICT (name) DO NOTHING RETURNING name", [created.name, created.target, revision]);
113
+ if (rows.length > 0)
114
+ await updateSessionIndex(client, created.name, created.target, revision);
115
+ }
116
+ for (const relog of change.relogs) {
117
+ const { rows } = await client.query("UPDATE log SET event = $1 WHERE session = $2 AND seq = $3 AND event = $4 RETURNING seq", [relog.event, relog.session, relog.seq, relog.expect]);
118
+ if (rows.length === 0) {
119
+ await client.query("ROLLBACK");
120
+ return "conflict";
121
+ }
122
+ }
123
+ if (change.reindexSessions) {
124
+ const { rows } = await client.query("SELECT name, target, revision FROM refs");
125
+ for (const row of rows) {
126
+ const ref = parseRef2(row);
127
+ await updateSessionIndex(client, ref.name, ref.target, ref.revision);
128
+ }
129
+ }
130
+ await client.query("INSERT INTO store_meta (id, version) VALUES (1, $1) ON CONFLICT (id) DO UPDATE SET version = excluded.version", [change.to]);
131
+ await client.query("COMMIT");
132
+ return "committed";
133
+ } catch (error) {
134
+ await client.query("ROLLBACK").catch(() => {
135
+ return;
136
+ });
137
+ throw error;
138
+ }
139
+ })
140
+ };
141
+ }
142
+ async function withClient(pool, work) {
143
+ const client = await pool.connect();
144
+ try {
145
+ return await work(client);
146
+ } finally {
147
+ client.release();
148
+ }
149
+ }
150
+ function connect(pool) {
151
+ const query = (text, values) => withClient(pool, (client) => client.query(text, values));
152
+ const readTail = async (client, session) => {
153
+ const { rows } = await client.query("SELECT MAX(seq) AS tail FROM log WHERE session = $1", [
154
+ session
155
+ ]);
156
+ const value = rows[0]?.tail;
157
+ return asSeq(value === null || value === undefined ? 0 : parseNumber2(value));
158
+ };
159
+ return {
160
+ sessions: sqlSessionIndex2(async (text, values) => (await query(postgresSessionIndexQuery2(text), values)).rows),
161
+ objects: {
162
+ async put(object) {
163
+ const id = await objectId(object);
164
+ await query("INSERT INTO objects (id, body) VALUES ($1, $2) ON CONFLICT (id) DO UPDATE SET body = excluded.body WHERE objects.body IS NULL", [id, JSON.stringify(object)]);
165
+ return id;
166
+ },
167
+ async get(id) {
168
+ const { rows } = await query("SELECT body FROM objects WHERE id = $1", [id]);
169
+ const body = parseText2(rows[0]?.body);
170
+ return body === null ? null : decodeObject(body);
171
+ },
172
+ async putBlob(bytes) {
173
+ const joined = await collect2(bytes);
174
+ const id = await blobId(joined);
175
+ await query("INSERT INTO objects (id, bytes) VALUES ($1, $2) ON CONFLICT (id) DO UPDATE SET bytes = excluded.bytes WHERE objects.bytes IS NULL", [id, joined]);
176
+ return id;
177
+ },
178
+ async blob(id) {
179
+ const { rows } = await query("SELECT bytes FROM objects WHERE id = $1", [id]);
180
+ const bytes = rows[0]?.bytes;
181
+ return bytes instanceof Uint8Array ? memoryReader2(new Uint8Array(bytes)) : null;
182
+ }
183
+ },
184
+ refs: {
185
+ async get(name) {
186
+ const { rows } = await query("SELECT name, target, revision FROM refs WHERE name = $1", [
187
+ name
188
+ ]);
189
+ const row = rows[0];
190
+ return row === undefined ? null : parseRef2(row);
191
+ },
192
+ async list(prefix) {
193
+ const end = prefixEnd2(prefix);
194
+ const { rows } = end === null ? await query("SELECT name, target, revision FROM refs WHERE name >= $1 ORDER BY name", [prefix]) : await query("SELECT name, target, revision FROM refs WHERE name >= $1 AND name < $2 ORDER BY name", [prefix, end]);
195
+ return rows.map(parseRef2);
196
+ },
197
+ set: (updates) => withClient(pool, (client) => publish(client, updates, readTail)),
198
+ async log(session, after, limit) {
199
+ const { rows } = await query("SELECT seq, at, event FROM log WHERE session = $1 AND seq > $2 ORDER BY seq LIMIT $3", [session, after, limit]);
200
+ return rows.map((row) => decodeEvent2(parseNumber2(row.seq), parseNumber2(row.at), parseText2(row.event) ?? ""));
201
+ },
202
+ tail: (session) => withClient(pool, (client) => readTail(client, session))
203
+ }
204
+ };
205
+ }
206
+ async function publish(client, updates, readTail) {
207
+ const logged = collectSessionEvents(updates);
208
+ const fences = fenceNames(updates);
209
+ const names = [...new Set([...updates.map((update) => update.name), ...fences])];
210
+ const sessions = [
211
+ ...new Set(updates.flatMap(({ name }) => {
212
+ const session = parseSessionRef(name);
213
+ return session === null ? [] : [session];
214
+ }))
215
+ ];
216
+ const locks = [
217
+ ...names.map((name) => `ref:${name}`),
218
+ ...sessions.map((id) => `log:${id}`)
219
+ ].sort();
220
+ await client.query("BEGIN");
221
+ try {
222
+ await client.query(SHARED_MIGRATION_LOCK);
223
+ assertStoreVersion(await storedVersion(client));
224
+ for (const key of locks)
225
+ await client.query("SELECT pg_advisory_xact_lock(hashtextextended($1, 0))", [key]);
226
+ const { rows } = names.length === 0 ? { rows: [] } : await client.query(`SELECT name, target, revision FROM refs WHERE name IN (${names.map((_, index) => `$${index + 1}`).join(", ")})`, names);
227
+ const before = new Map(rows.map((row) => {
228
+ const ref = parseRef2(row);
229
+ return [ref.name, ref];
230
+ }));
231
+ const fenced = fences.find((name) => !before.has(name));
232
+ if (fenced !== undefined) {
233
+ await client.query("ROLLBACK");
234
+ return { kind: "fenced", name: fenced };
235
+ }
236
+ const stale = updates.find((update) => !admits(update, before.get(update.name)));
237
+ if (stale !== undefined) {
238
+ await client.query("ROLLBACK");
239
+ return {
240
+ kind: "stale",
241
+ name: stale.name,
242
+ revision: before.get(stale.name)?.revision ?? null
243
+ };
244
+ }
245
+ const revisions = [];
246
+ const touched = new Map;
247
+ for (const update of updates) {
248
+ const revision = mintRevision2();
249
+ revisions.push(revision);
250
+ if (update.target === null)
251
+ await client.query("DELETE FROM refs WHERE name = $1", [update.name]);
252
+ else
253
+ await client.query("INSERT INTO refs (name, target, revision) VALUES ($1, $2, $3) ON CONFLICT (name) DO UPDATE SET target = excluded.target, revision = excluded.revision", [update.name, update.target, revision]);
254
+ await updateSessionIndex(client, update.name, update.target, revision);
255
+ const session = parseSessionRef(update.name);
256
+ if (session !== null)
257
+ touched.set(session, revision);
258
+ }
259
+ for (const [session, version] of touched)
260
+ await client.query("UPDATE session_index SET version = $1 WHERE session = $2", [
261
+ version,
262
+ session
263
+ ]);
264
+ const at = Date.now();
265
+ const tails = new Map;
266
+ const appended = [];
267
+ for (const { session, event } of logged) {
268
+ const seq = (tails.get(session) ?? await readTail(client, session)) + 1;
269
+ tails.set(session, seq);
270
+ await client.query("INSERT INTO log (session, seq, at, event) VALUES ($1, $2, $3, $4)", [
271
+ session,
272
+ seq,
273
+ at,
274
+ JSON.stringify(event)
275
+ ]);
276
+ appended.push(asSeq(seq));
277
+ }
278
+ await client.query("COMMIT");
279
+ return { kind: "set", logged: appended, at, revisions };
280
+ } catch (error) {
281
+ await client.query("ROLLBACK").catch(() => {
282
+ return;
283
+ });
284
+ throw error;
285
+ }
286
+ }
287
+ async function updateSessionIndex(client, name, target, revision) {
288
+ if (sessionIndexRef(name) === null)
289
+ return;
290
+ const body = target === null ? null : parseText2((await client.query("SELECT body FROM objects WHERE id = $1", [target])).rows[0]?.body);
291
+ for (const change of sessionIndexChanges2(name, body === null ? null : decodeObject(body), revision))
292
+ await client.query(postgresSessionIndexQuery2(change.text), change.values);
293
+ }
294
+
295
+ export { postgresStore2 };
@@ -0,0 +1,63 @@
1
+ import {
2
+ sha2562
3
+ } from "./canvas-preview-0nq75h9k.js";
4
+
5
+ // src/local/workspace-migration.ts
6
+ import { realpath, stat } from "node:fs/promises";
7
+ import { decodeWorkspaceRecord, envelope } from "@nyte-ai/core/store";
8
+ import { asId, SdkError } from "@nyte-ai/schema";
9
+ import { Type } from "typebox";
10
+ import { Value } from "typebox/value";
11
+ var MIGRATION = "host/migrations/local-workspace-identity-v2";
12
+ var MigrationState = Type.Object({ pending: Type.Array(Type.String()) });
13
+ async function migrateLocalWorkspaceIdentities2(connection) {
14
+ for (let attempt = 0;attempt < 3; attempt += 1) {
15
+ const marker = await connection.refs.get(MIGRATION);
16
+ const state = marker?.target == null ? null : await connection.objects.get(marker.target);
17
+ const pending = Value.Check(MigrationState, state) ? state.pending : null;
18
+ if (marker !== null && pending === null)
19
+ throw new SdkError("internal", "The workspace identity migration state is malformed.");
20
+ if (pending?.length === 0)
21
+ return;
22
+ const refs = pending === null ? await connection.refs.list("workspaces/") : await Promise.all(pending.map((name) => connection.refs.get(name)));
23
+ const updates = [];
24
+ const remaining = [];
25
+ for (const ref of refs) {
26
+ if (ref === null)
27
+ continue;
28
+ const record = decodeWorkspaceRecord(ref.target === null ? null : await connection.objects.get(ref.target));
29
+ if (record?.target.kind !== "local" || !("path" in record.target))
30
+ continue;
31
+ const real = await realpath(record.target.path).catch(() => null);
32
+ if (real === null) {
33
+ remaining.push(ref.name);
34
+ continue;
35
+ }
36
+ const metadata = await stat(real, { bigint: true }).catch(() => null);
37
+ if (metadata === null) {
38
+ remaining.push(ref.name);
39
+ continue;
40
+ }
41
+ if (!metadata.isDirectory() || metadata.ino === 0n || metadata.birthtimeNs === 0n || metadata.birthtimeNs / 1000000n > BigInt(Math.floor(record.createdAt)) || record.identity !== sha2562(`${metadata.dev}:${metadata.ino}`))
42
+ continue;
43
+ const identity = asId(sha2562(`${metadata.birthtimeNs}:${metadata.ino}`));
44
+ updates.push({
45
+ name: ref.name,
46
+ expect: ref.revision,
47
+ target: await connection.objects.put(envelope("workspace", { ...record, identity }, Date.now()))
48
+ });
49
+ }
50
+ if (updates.length === 0 && pending !== null && pending.length === remaining.length && remaining.every((name, index) => pending[index] === name))
51
+ return;
52
+ updates.push({
53
+ name: MIGRATION,
54
+ expect: marker?.revision ?? "absent",
55
+ target: await connection.objects.put({ pending: remaining })
56
+ });
57
+ if ((await connection.refs.set(updates)).kind === "set")
58
+ return;
59
+ }
60
+ throw new SdkError("unavailable", "Workspace identities changed while Nyte was updating them.");
61
+ }
62
+
63
+ export { migrateLocalWorkspaceIdentities2 };
@@ -0,0 +1,169 @@
1
+ // src/credentials.ts
2
+ import { readCredentialAccounts } from "@nyte-ai/ai/auth/types";
3
+ import { SdkError } from "@nyte-ai/schema";
4
+ import { keyedSerial } from "@nyte-ai/schema/serial";
5
+ import { decodeKvValue, envelope, kvRef } from "@nyte-ai/core/store";
6
+ import { Type } from "typebox";
7
+ import { Value } from "typebox/value";
8
+ var SealedCredentialSchema = Type.Union([
9
+ Type.Object({
10
+ type: Type.Union([Type.Literal("api_key"), Type.Literal("oauth")]),
11
+ iv: Type.String(),
12
+ ciphertext: Type.String()
13
+ }),
14
+ Type.Object({
15
+ active: Type.Union([Type.String(), Type.Null()]),
16
+ accounts: Type.Array(Type.Object({
17
+ id: Type.String({ minLength: 1 }),
18
+ label: Type.String({ minLength: 1 }),
19
+ type: Type.Union([Type.Literal("api_key"), Type.Literal("oauth")])
20
+ })),
21
+ iv: Type.String(),
22
+ ciphertext: Type.String()
23
+ })
24
+ ]);
25
+ var PREFIX = kvRef("secret", "models", "");
26
+ var RETRIES = 5;
27
+ function credentialStore2(store, secrets) {
28
+ let key = null;
29
+ const writes = keyedSerial();
30
+ const readKey = () => {
31
+ const known = key ?? importedKey(secrets);
32
+ key = known;
33
+ known.catch(() => {
34
+ if (key === known)
35
+ key = null;
36
+ });
37
+ return known;
38
+ };
39
+ const serialised = (provider, signal, task) => writes.run(provider, () => {
40
+ signal?.throwIfAborted();
41
+ return task();
42
+ });
43
+ return {
44
+ async read(provider, options) {
45
+ options?.signal?.throwIfAborted();
46
+ const { sealed } = await connected(store, (connection) => recordAt(connection, provider));
47
+ if (sealed === null)
48
+ return;
49
+ const unlocked = await readKey().catch(() => null);
50
+ return unlocked === null ? undefined : unsealCredential(unlocked, sealed);
51
+ },
52
+ async list(options) {
53
+ options?.signal?.throwIfAborted();
54
+ return connected(store, async (connection) => {
55
+ const refs = await connection.refs.list(PREFIX);
56
+ const rows = await Promise.all(refs.map(async (ref) => {
57
+ const sealed = ref.target === null ? null : readSealedCredential(decodeKvValue(await connection.objects.get(ref.target)));
58
+ if (sealed === null)
59
+ return [];
60
+ const providerId = ref.name.slice(PREFIX.length);
61
+ if ("type" in sealed)
62
+ return [
63
+ { providerId, id: "default", label: "Default", type: sealed.type, active: true }
64
+ ];
65
+ return sealed.accounts.map((account) => ({
66
+ providerId,
67
+ ...account,
68
+ active: sealed.active === account.id
69
+ }));
70
+ }));
71
+ return rows.flat();
72
+ });
73
+ },
74
+ modify(provider, fn, options) {
75
+ return serialised(provider, options?.signal, async () => modifyCredential(store, await readKey(), provider, fn, options?.signal));
76
+ },
77
+ delete(provider, options) {
78
+ return serialised(provider, options?.signal, () => connected(store, async (connection) => {
79
+ await connection.refs.set([{ name: kvRef("secret", "models", provider), target: null }]);
80
+ }));
81
+ }
82
+ };
83
+ }
84
+ async function sealSecret2(secrets, plain) {
85
+ const iv = crypto.getRandomValues(new Uint8Array(12));
86
+ const ciphertext = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, await importedKey(secrets), new TextEncoder().encode(plain));
87
+ return `${iv.toBase64()}.${new Uint8Array(ciphertext).toBase64()}`;
88
+ }
89
+ async function openSecret2(secrets, sealed) {
90
+ const [iv = "", ciphertext = ""] = sealed.split(".");
91
+ const plain = await crypto.subtle.decrypt({ name: "AES-GCM", iv: Uint8Array.fromBase64(iv) }, await importedKey(secrets), Uint8Array.fromBase64(ciphertext));
92
+ return new TextDecoder().decode(plain);
93
+ }
94
+ async function importedKey(secrets) {
95
+ const bytes = await secrets.key();
96
+ if (bytes.length !== 32)
97
+ throw new SdkError("invalid", `The secrets key is ${bytes.length} bytes; AES-256 needs 32.`);
98
+ return crypto.subtle.importKey("raw", new Uint8Array(bytes), "AES-GCM", false, [
99
+ "encrypt",
100
+ "decrypt"
101
+ ]);
102
+ }
103
+ async function unsealCredential(key, record) {
104
+ let parsed;
105
+ try {
106
+ const plain = await crypto.subtle.decrypt({ name: "AES-GCM", iv: Uint8Array.fromBase64(record.iv) }, key, Uint8Array.fromBase64(record.ciphertext));
107
+ parsed = JSON.parse(new TextDecoder().decode(plain));
108
+ } catch {
109
+ return;
110
+ }
111
+ return readCredentialAccounts(parsed);
112
+ }
113
+ async function modifyCredential(store, key, provider, fn, signal) {
114
+ const name = kvRef("secret", "models", provider);
115
+ let started = false;
116
+ return connected(store, async (connection) => {
117
+ for (let attempt = 0;attempt <= RETRIES; attempt += 1) {
118
+ const { ref, sealed } = await recordAt(connection, provider);
119
+ const current = sealed === null ? undefined : await unsealCredential(key, sealed);
120
+ if (!started)
121
+ signal?.throwIfAborted();
122
+ started = true;
123
+ const next = await fn(current);
124
+ if (next === undefined)
125
+ return current;
126
+ const target = next.accounts.length === 0 ? null : await connection.objects.put(envelope("kv", await seal(key, next), Date.now()));
127
+ const outcome = await connection.refs.set([
128
+ { name, target, expect: ref === null ? "absent" : ref.revision }
129
+ ]);
130
+ if (outcome.kind === "set")
131
+ return next;
132
+ }
133
+ throw new SdkError("unavailable", `The ${provider} credential kept changing under this write; try again.`);
134
+ });
135
+ }
136
+ async function seal(key, credential) {
137
+ const iv = crypto.getRandomValues(new Uint8Array(12));
138
+ const ciphertext = new Uint8Array(await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, new TextEncoder().encode(JSON.stringify(credential))));
139
+ return {
140
+ active: credential.active,
141
+ accounts: credential.accounts.map((account) => ({
142
+ id: account.id,
143
+ label: account.label,
144
+ type: account.credential.type
145
+ })),
146
+ iv: iv.toBase64(),
147
+ ciphertext: ciphertext.toBase64()
148
+ };
149
+ }
150
+ async function recordAt(connection, provider) {
151
+ const ref = await connection.refs.get(kvRef("secret", "models", provider));
152
+ return {
153
+ ref,
154
+ sealed: ref === null || ref.target === null ? null : readSealedCredential(decodeKvValue(await connection.objects.get(ref.target)))
155
+ };
156
+ }
157
+ function readSealedCredential(body) {
158
+ if (!Value.Check(SealedCredentialSchema, body))
159
+ return null;
160
+ if ("type" in body)
161
+ return body;
162
+ const ids = new Set(body.accounts.map((account) => account.id));
163
+ return ids.size === body.accounts.length && (body.active === null || ids.has(body.active)) ? body : null;
164
+ }
165
+ async function connected(store, task) {
166
+ return task(await store.open());
167
+ }
168
+
169
+ export { credentialStore2, sealSecret2, openSecret2 };