@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,65 @@
1
+ import {
2
+ parseText2,
3
+ parseRef2
4
+ } from "./canvas-preview-69fkk9yn.js";
5
+
6
+ // src/session-index.ts
7
+ import { projectSessionIndex, sessionIndexRef } from "@nyte-ai/core/store";
8
+ import { asId } from "@nyte-ai/schema";
9
+ function sessionIndexChanges2(name, object, revision) {
10
+ const ref = sessionIndexRef(name);
11
+ if (ref === null)
12
+ return [];
13
+ const entry = projectSessionIndex(name, object);
14
+ if (ref.kind === "session") {
15
+ return entry?.kind === "session" ? [
16
+ {
17
+ text: "INSERT INTO session_index (name, session, parent, sort_at, version) VALUES (?, ?, ?, ?, ?) ON CONFLICT (name) DO UPDATE SET session = excluded.session, parent = excluded.parent, sort_at = excluded.sort_at, version = excluded.version",
18
+ values: [name, entry.session, entry.parent, -entry.at, revision]
19
+ }
20
+ ] : [{ text: "DELETE FROM session_index WHERE name = ?", values: [name] }];
21
+ }
22
+ return entry !== null && entry.kind !== "session" ? [
23
+ {
24
+ text: "INSERT INTO pending_work (name, session, kind) VALUES (?, ?, ?) ON CONFLICT (name) DO UPDATE SET session = excluded.session, kind = excluded.kind",
25
+ values: [name, entry.session, entry.kind]
26
+ }
27
+ ] : [{ text: "DELETE FROM pending_work WHERE name = ?", values: [name] }];
28
+ }
29
+ function sqlSessionIndex2(read) {
30
+ return {
31
+ async list({ parents, after, limit }) {
32
+ const conditions = [];
33
+ const values = [];
34
+ if (parents.kind === "roots")
35
+ conditions.push("s.parent IS NULL");
36
+ if (parents.kind === "children") {
37
+ conditions.push("s.parent = ?");
38
+ values.push(parents.session);
39
+ }
40
+ if (after !== undefined) {
41
+ conditions.push("(s.sort_at, s.session) > (?, ?)");
42
+ values.push(-after.at, after.id);
43
+ }
44
+ values.push(limit);
45
+ return (await read(`SELECT r.name, r.target, r.revision, s.version FROM session_index s JOIN refs r ON r.name = s.name${conditions.length === 0 ? "" : ` WHERE ${conditions.join(" AND ")}`} ORDER BY s.sort_at, s.session LIMIT ?`, values)).map((row) => ({
46
+ ref: parseRef2(row),
47
+ version: asId(parseText2(row.version) ?? "")
48
+ }));
49
+ },
50
+ async work({ after, limit }) {
51
+ return (await read(`SELECT r.name, r.target, r.revision FROM (SELECT DISTINCT session FROM pending_work${after === undefined ? "" : " WHERE session > ?"}) p JOIN session_index s ON s.session = p.session JOIN refs r ON r.name = s.name ORDER BY p.session LIMIT ?`, after === undefined ? [limit] : [after, limit])).map(parseRef2);
52
+ },
53
+ async pending({ kind, sessions }) {
54
+ if (sessions?.length === 0)
55
+ return [];
56
+ return (await read(`SELECT r.name, r.target, r.revision FROM pending_work p JOIN refs r ON r.name = p.name WHERE p.kind = ?${sessions === undefined ? "" : ` AND p.session IN (${sessions.map(() => "?").join(", ")})`} ORDER BY p.name`, [kind, ...sessions ?? []])).map(parseRef2);
57
+ }
58
+ };
59
+ }
60
+ function postgresSessionIndexQuery2(text) {
61
+ let parameter = 0;
62
+ return text.replaceAll("?", () => `$${++parameter}`);
63
+ }
64
+
65
+ export { sessionIndexChanges2, sqlSessionIndex2, postgresSessionIndexQuery2 };
@@ -0,0 +1,7 @@
1
+ // src/hash.ts
2
+ import { createHash } from "node:crypto";
3
+ function sha2562(data) {
4
+ return createHash("sha256").update(data).digest("hex");
5
+ }
6
+
7
+ export { sha2562 };
@@ -0,0 +1,497 @@
1
+ import {
2
+ emptyModelUsage2,
3
+ recordedUsage2,
4
+ summarizeModels2
5
+ } from "./canvas-preview-srgfpdmf.js";
6
+
7
+ // src/usage.ts
8
+ import { Buffer } from "node:buffer";
9
+ import { constants, existsSync } from "node:fs";
10
+ import { lstat, open, opendir, stat } from "node:fs/promises";
11
+ import { homedir } from "node:os";
12
+ import { join, resolve } from "node:path";
13
+ import process from "node:process";
14
+ import { StringDecoder } from "node:string_decoder";
15
+ import { Type } from "typebox";
16
+ import { Value } from "typebox/value";
17
+ import { calculateCost } from "@nyte-ai/ai";
18
+ var tokens = Type.Integer({ minimum: 0, maximum: Number.MAX_SAFE_INTEGER });
19
+ var envelope = Type.Object({ type: Type.String() });
20
+ var assistantRecord = Type.Object({
21
+ type: Type.Literal("assistant"),
22
+ requestId: Type.Optional(Type.String()),
23
+ costUSD: Type.Optional(Type.Unknown()),
24
+ message: Type.Object({
25
+ id: Type.Optional(Type.String()),
26
+ model: Type.String({ minLength: 1, pattern: "\\S" }),
27
+ usage: Type.Object({
28
+ input_tokens: tokens,
29
+ output_tokens: tokens,
30
+ cache_read_input_tokens: Type.Optional(tokens),
31
+ cache_creation_input_tokens: Type.Optional(tokens),
32
+ cache_creation: Type.Optional(Type.Object({
33
+ ephemeral_5m_input_tokens: Type.Optional(tokens),
34
+ ephemeral_1h_input_tokens: Type.Optional(tokens)
35
+ }))
36
+ })
37
+ })
38
+ });
39
+ var reportedCost = Type.Number({ minimum: 0, maximum: Number.MAX_VALUE });
40
+ function betterSnapshot(previous, next) {
41
+ if (previous === undefined)
42
+ return true;
43
+ const usage = next.usage;
44
+ return usage.totalTokens > previous.usage.totalTokens || usage.totalTokens === previous.usage.totalTokens && (usage.output > previous.usage.output || usage.output === previous.usage.output && previous.costUSD === undefined && next.costUSD !== undefined);
45
+ }
46
+ async function scanClaudeCodeFile(path, signal) {
47
+ const keyed = new Map;
48
+ const anonymous = [];
49
+ let malformedRecords = 0;
50
+ for await (const line of historyLines(path, signal)) {
51
+ signal?.throwIfAborted();
52
+ if (!line.text.trim())
53
+ continue;
54
+ let value;
55
+ try {
56
+ value = JSON.parse(line.text);
57
+ } catch {
58
+ if (line.terminated)
59
+ malformedRecords++;
60
+ continue;
61
+ }
62
+ if (!Value.Check(envelope, value)) {
63
+ malformedRecords++;
64
+ continue;
65
+ }
66
+ if (value.type !== "assistant")
67
+ continue;
68
+ if (!Value.Check(assistantRecord, value)) {
69
+ malformedRecords++;
70
+ continue;
71
+ }
72
+ const raw = value.message.usage;
73
+ const cacheWrite = raw.cache_creation_input_tokens ?? 0;
74
+ const cacheWrite1h = raw.cache_creation?.ephemeral_1h_input_tokens;
75
+ if ((cacheWrite1h ?? 0) + (raw.cache_creation?.ephemeral_5m_input_tokens ?? 0) > cacheWrite) {
76
+ malformedRecords++;
77
+ continue;
78
+ }
79
+ const usage = {
80
+ ...emptyModelUsage2(),
81
+ input: raw.input_tokens,
82
+ output: raw.output_tokens,
83
+ cacheRead: raw.cache_read_input_tokens ?? 0,
84
+ cacheWrite,
85
+ totalTokens: raw.input_tokens + raw.output_tokens + (raw.cache_read_input_tokens ?? 0) + cacheWrite
86
+ };
87
+ if (cacheWrite1h !== undefined)
88
+ usage.cacheWrite1h = cacheWrite1h;
89
+ const snapshot = {
90
+ model: value.message.model,
91
+ usage,
92
+ costUSD: Value.Check(reportedCost, value.costUSD) ? value.costUSD : undefined
93
+ };
94
+ const messageId = value.message.id?.trim() || null;
95
+ const requestId = value.requestId?.trim() || null;
96
+ if (messageId === null && requestId === null) {
97
+ anonymous.push(snapshot);
98
+ continue;
99
+ }
100
+ const identity = JSON.stringify([messageId, requestId]);
101
+ if (betterSnapshot(keyed.get(identity), snapshot))
102
+ keyed.set(identity, snapshot);
103
+ }
104
+ return { keyed: [...keyed], anonymous, malformedRecords };
105
+ }
106
+ async function scanCached(path, cache, seen, parse) {
107
+ seen.add(path);
108
+ if (cache === undefined)
109
+ return parse();
110
+ const info = await lstat(path);
111
+ if (!info.isFile())
112
+ throw new Error("History is not a regular file.");
113
+ const hit = cache.get(path);
114
+ if (hit !== undefined && hit.size === info.size && hit.mtimeMs === info.mtimeMs)
115
+ return hit.scan;
116
+ const scan = await parse();
117
+ cache.set(path, { size: info.size, mtimeMs: info.mtimeMs, scan });
118
+ return scan;
119
+ }
120
+ function pruneCache(cache, seen) {
121
+ if (cache === undefined)
122
+ return;
123
+ for (const path of cache.keys())
124
+ if (!seen.has(path))
125
+ cache.delete(path);
126
+ }
127
+ async function readClaudeCodeUsage2(options) {
128
+ options.signal?.throwIfAborted();
129
+ const projects = join(resolve(options.configDir ?? (process.env.CLAUDE_CONFIG_DIR?.trim() || join(homedir(), ".claude"))), "projects");
130
+ if (!existsSync(projects))
131
+ return { kind: "missing" };
132
+ try {
133
+ const root = await stat(projects);
134
+ options.signal?.throwIfAborted();
135
+ if (!root.isDirectory())
136
+ return { kind: "failed", message: "Claude Code history path is not a directory." };
137
+ } catch {
138
+ options.signal?.throwIfAborted();
139
+ return { kind: "failed", message: "Could not open Claude Code local history." };
140
+ }
141
+ const keyed = new Map;
142
+ const anonymous = [];
143
+ const seen = new Set;
144
+ let malformedRecords = 0;
145
+ let unreadableFiles = 0;
146
+ try {
147
+ const directories = [projects];
148
+ for (const directory of directories) {
149
+ options.signal?.throwIfAborted();
150
+ try {
151
+ if (directory !== projects && (await lstat(directory)).isSymbolicLink())
152
+ continue;
153
+ const entries = await opendir(directory);
154
+ for await (const entry of entries) {
155
+ options.signal?.throwIfAborted();
156
+ const path = join(directory, entry.name);
157
+ if (entry.isDirectory()) {
158
+ directories.push(path);
159
+ continue;
160
+ }
161
+ if (!entry.isFile() || !entry.name.endsWith(".jsonl"))
162
+ continue;
163
+ try {
164
+ const scan = await scanCached(path, options.cache, seen, () => scanClaudeCodeFile(path, options.signal));
165
+ malformedRecords += scan.malformedRecords;
166
+ anonymous.push(...scan.anonymous);
167
+ for (const [identity, snapshot] of scan.keyed) {
168
+ if (betterSnapshot(keyed.get(identity), snapshot))
169
+ keyed.set(identity, snapshot);
170
+ }
171
+ } catch {
172
+ options.signal?.throwIfAborted();
173
+ unreadableFiles++;
174
+ }
175
+ }
176
+ } catch (error) {
177
+ options.signal?.throwIfAborted();
178
+ if (directory === projects)
179
+ throw error;
180
+ unreadableFiles++;
181
+ }
182
+ }
183
+ options.signal?.throwIfAborted();
184
+ pruneCache(options.cache, seen);
185
+ const catalog = options.models.getModels("anthropic").filter((model) => model.provider === "anthropic");
186
+ const rows = [];
187
+ let unpricedRecords = 0;
188
+ for (const snapshot of [...keyed.values(), ...anonymous]) {
189
+ options.signal?.throwIfAborted();
190
+ const usage = { ...snapshot.usage, cost: { ...snapshot.usage.cost } };
191
+ if (snapshot.costUSD !== undefined) {
192
+ usage.cost.total = snapshot.costUSD;
193
+ } else {
194
+ const matches = catalog.filter((model) => model.id === snapshot.model);
195
+ const model = matches.length === 1 ? matches[0] : undefined;
196
+ if (model)
197
+ calculateCost(model, usage);
198
+ else
199
+ unpricedRecords++;
200
+ }
201
+ rows.push({
202
+ provider: "anthropic",
203
+ model: snapshot.model,
204
+ turns: 1,
205
+ usage: recordedUsage2(usage)
206
+ });
207
+ }
208
+ options.signal?.throwIfAborted();
209
+ return {
210
+ kind: "ready",
211
+ summary: summarizeModels2(rows),
212
+ unpricedRecords,
213
+ malformedRecords,
214
+ unreadableFiles
215
+ };
216
+ } catch {
217
+ options.signal?.throwIfAborted();
218
+ return { kind: "failed", message: "Could not read Claude Code local history." };
219
+ }
220
+ }
221
+ var codexTokens = Type.Object({
222
+ input_tokens: Type.Optional(tokens),
223
+ cached_input_tokens: Type.Optional(tokens),
224
+ cache_write_input_tokens: Type.Optional(tokens),
225
+ output_tokens: Type.Optional(tokens),
226
+ reasoning_output_tokens: Type.Optional(tokens)
227
+ });
228
+ var usageRecord = Type.Object({
229
+ type: Type.Literal("token_usage_record"),
230
+ payload: Type.Object({
231
+ response_id: Type.Optional(Type.String()),
232
+ usage: codexTokens
233
+ })
234
+ });
235
+ var turnContext = Type.Object({
236
+ type: Type.Literal("turn_context"),
237
+ payload: Type.Object({ model: Type.Optional(Type.String({ minLength: 1 })) })
238
+ });
239
+ var sessionMeta = Type.Object({
240
+ type: Type.Literal("session_meta"),
241
+ timestamp: Type.Optional(Type.String()),
242
+ payload: Type.Object({
243
+ forked_from_id: Type.Optional(Type.String()),
244
+ parent_thread_id: Type.Optional(Type.String())
245
+ })
246
+ });
247
+ var tokenCount = Type.Object({
248
+ type: Type.Literal("event_msg"),
249
+ timestamp: Type.Optional(Type.String()),
250
+ payload: Type.Object({
251
+ type: Type.Literal("token_count"),
252
+ info: Type.Object({ last_token_usage: Type.Optional(codexTokens) })
253
+ })
254
+ });
255
+ function codexUsage(raw) {
256
+ const input = raw.input_tokens ?? 0;
257
+ const cacheRead = raw.cached_input_tokens ?? 0;
258
+ const cacheWrite = raw.cache_write_input_tokens ?? 0;
259
+ const output = raw.output_tokens ?? 0;
260
+ const uncached = Math.max(0, input - cacheRead - cacheWrite);
261
+ return {
262
+ ...emptyModelUsage2(),
263
+ input: uncached,
264
+ output,
265
+ cacheRead,
266
+ cacheWrite,
267
+ reasoning: Math.min(output, raw.reasoning_output_tokens ?? 0),
268
+ totalTokens: uncached + output + cacheRead + cacheWrite
269
+ };
270
+ }
271
+ var FORK_COPY_MAX_GAP_MS = 1000;
272
+ function parseMs(value) {
273
+ if (value === undefined)
274
+ return;
275
+ const parsed = Date.parse(value);
276
+ return Number.isNaN(parsed) ? undefined : parsed;
277
+ }
278
+ async function readCodexUsage2(options) {
279
+ options.signal?.throwIfAborted();
280
+ const home = resolve(options.homeDir ?? (process.env.CODEX_HOME?.trim() || join(homedir(), ".codex")));
281
+ const roots = [join(home, "sessions"), join(home, "archived_sessions")];
282
+ const present = [];
283
+ for (const root of roots) {
284
+ if (!existsSync(root))
285
+ continue;
286
+ try {
287
+ if ((await stat(root)).isDirectory())
288
+ present.push(root);
289
+ } catch {
290
+ options.signal?.throwIfAborted();
291
+ return { kind: "failed", message: "Could not open Codex local history." };
292
+ }
293
+ }
294
+ if (present.length === 0)
295
+ return { kind: "missing" };
296
+ const responses = new Map;
297
+ const legacy = [];
298
+ const seen = new Set;
299
+ let malformedRecords = 0;
300
+ let unreadableFiles = 0;
301
+ try {
302
+ for (const root of present) {
303
+ for await (const path of jsonlFiles(root, options.signal)) {
304
+ try {
305
+ const scan = await scanCached(path, options.cache, seen, () => scanCodexRollout(path, options.signal));
306
+ malformedRecords += scan.malformedRecords;
307
+ if (scan.modern.length > 0) {
308
+ for (const [id, row] of scan.modern)
309
+ if (!responses.has(id))
310
+ responses.set(id, row);
311
+ } else {
312
+ legacy.push(...scan.legacy);
313
+ }
314
+ } catch {
315
+ options.signal?.throwIfAborted();
316
+ unreadableFiles++;
317
+ }
318
+ }
319
+ }
320
+ options.signal?.throwIfAborted();
321
+ pruneCache(options.cache, seen);
322
+ const catalog = options.models.getModels("openai-codex").filter((model) => model.provider === "openai-codex");
323
+ const rows = [];
324
+ let unpricedRecords = 0;
325
+ for (const row of [...responses.values(), ...legacy]) {
326
+ options.signal?.throwIfAborted();
327
+ const usage = { ...row.usage, cost: { ...row.usage.cost } };
328
+ const matches = catalog.filter((model) => model.id === row.model);
329
+ const model = matches.length === 1 ? matches[0] : undefined;
330
+ if (model)
331
+ calculateCost(model, usage);
332
+ else
333
+ unpricedRecords++;
334
+ rows.push({
335
+ provider: "openai-codex",
336
+ model: row.model,
337
+ turns: 1,
338
+ usage: recordedUsage2(usage)
339
+ });
340
+ }
341
+ return {
342
+ kind: "ready",
343
+ summary: summarizeModels2(rows),
344
+ unpricedRecords,
345
+ malformedRecords,
346
+ unreadableFiles
347
+ };
348
+ } catch {
349
+ options.signal?.throwIfAborted();
350
+ return { kind: "failed", message: "Could not read Codex local history." };
351
+ }
352
+ }
353
+ async function scanCodexRollout(path, signal) {
354
+ const modern = new Map;
355
+ const legacy = [];
356
+ let malformedRecords = 0;
357
+ let model = "";
358
+ let sawMeta = false;
359
+ let signature;
360
+ let forkAnchorMs;
361
+ for await (const line of historyLines(path, signal)) {
362
+ signal?.throwIfAborted();
363
+ if (!line.text.trim())
364
+ continue;
365
+ let value;
366
+ try {
367
+ value = JSON.parse(line.text);
368
+ } catch {
369
+ if (line.terminated)
370
+ malformedRecords++;
371
+ continue;
372
+ }
373
+ if (!Value.Check(envelope, value)) {
374
+ malformedRecords++;
375
+ continue;
376
+ }
377
+ if (Value.Check(turnContext, value)) {
378
+ if (value.payload.model !== undefined)
379
+ model = value.payload.model;
380
+ continue;
381
+ }
382
+ if (Value.Check(sessionMeta, value)) {
383
+ if (sawMeta)
384
+ continue;
385
+ sawMeta = true;
386
+ const forked = value.payload.forked_from_id !== undefined || value.payload.parent_thread_id !== undefined;
387
+ if (forked)
388
+ forkAnchorMs = parseMs(value.timestamp);
389
+ continue;
390
+ }
391
+ if (Value.Check(usageRecord, value)) {
392
+ const id = value.payload.response_id;
393
+ if (id === undefined || model === "")
394
+ continue;
395
+ const usage = codexUsage(value.payload.usage);
396
+ if (usage.totalTokens > 0 && !modern.has(id))
397
+ modern.set(id, { model, usage });
398
+ continue;
399
+ }
400
+ if (!Value.Check(tokenCount, value))
401
+ continue;
402
+ const last = value.payload.info.last_token_usage;
403
+ if (last === undefined || model === "")
404
+ continue;
405
+ const next = JSON.stringify(last);
406
+ if (next === signature)
407
+ continue;
408
+ signature = next;
409
+ if (forkAnchorMs !== undefined) {
410
+ const at = parseMs(value.timestamp);
411
+ if (at !== undefined && at - forkAnchorMs < FORK_COPY_MAX_GAP_MS) {
412
+ forkAnchorMs = at;
413
+ continue;
414
+ }
415
+ forkAnchorMs = undefined;
416
+ }
417
+ const usage = codexUsage(last);
418
+ if (usage.totalTokens > 0)
419
+ legacy.push({ model, usage });
420
+ }
421
+ return { modern: [...modern], legacy, malformedRecords };
422
+ }
423
+ async function* jsonlFiles(root, signal) {
424
+ const directories = [root];
425
+ for (const directory of directories) {
426
+ signal?.throwIfAborted();
427
+ try {
428
+ if (directory !== root && (await lstat(directory)).isSymbolicLink())
429
+ continue;
430
+ for await (const entry of await opendir(directory)) {
431
+ signal?.throwIfAborted();
432
+ const path = join(directory, entry.name);
433
+ if (entry.isDirectory())
434
+ directories.push(path);
435
+ else if (entry.isFile() && entry.name.endsWith(".jsonl"))
436
+ yield path;
437
+ }
438
+ } catch (error) {
439
+ if (directory === root)
440
+ throw error;
441
+ }
442
+ }
443
+ }
444
+ async function* historyLines(path, signal) {
445
+ const file = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
446
+ try {
447
+ const stat = await file.stat();
448
+ if (!stat.isFile())
449
+ throw new Error("History is not a regular file.");
450
+ const buffer = Buffer.alloc(64 * 1024);
451
+ const decoder = new StringDecoder("utf8");
452
+ let pending = "";
453
+ let position = 0;
454
+ while (position < stat.size) {
455
+ signal?.throwIfAborted();
456
+ const { bytesRead } = await file.read(buffer, 0, Math.min(buffer.length, stat.size - position), position);
457
+ if (bytesRead === 0)
458
+ break;
459
+ position += bytesRead;
460
+ const lines = `${pending}${decoder.write(buffer.subarray(0, bytesRead))}`.split(`
461
+ `);
462
+ pending = lines.pop() ?? "";
463
+ for (const text of lines)
464
+ yield { text, terminated: true };
465
+ }
466
+ pending += decoder.end();
467
+ if (pending)
468
+ yield { text: pending, terminated: false };
469
+ } finally {
470
+ await file.close();
471
+ }
472
+ }
473
+ function createUsageScanCaches2() {
474
+ return { claudeCode: new Map, codex: new Map };
475
+ }
476
+ async function readLocalUsage2(options) {
477
+ const failed = (message) => {
478
+ options.signal?.throwIfAborted();
479
+ return { kind: "failed", message };
480
+ };
481
+ const [claudeCode, codex] = await Promise.all([
482
+ readClaudeCodeUsage2({
483
+ models: options.models,
484
+ signal: options.signal,
485
+ cache: options.caches?.claudeCode
486
+ }).catch(() => failed("Could not read Claude Code history.")),
487
+ readCodexUsage2({
488
+ models: options.models,
489
+ signal: options.signal,
490
+ cache: options.caches?.codex
491
+ }).catch(() => failed("Could not read Codex history."))
492
+ ]);
493
+ options.signal?.throwIfAborted();
494
+ return { claudeCode, codex };
495
+ }
496
+
497
+ export { readClaudeCodeUsage2, readCodexUsage2, createUsageScanCaches2, readLocalUsage2 };
@@ -0,0 +1,17 @@
1
+ import {
2
+ sha2562
3
+ } from "./canvas-preview-0nq75h9k.js";
4
+
5
+ // src/local/identity.ts
6
+ import { realpath, stat } from "node:fs/promises";
7
+ import { resolve } from "node:path";
8
+ import { asId } from "@nyte-ai/schema";
9
+ async function folderIdentity2(path) {
10
+ const real = await realpath(path).catch(() => null);
11
+ if (real === null)
12
+ return asId(sha2562(resolve(path)));
13
+ const stats = await stat(real, { bigint: true }).catch(() => null);
14
+ return asId(sha2562(stats === null || stats.ino === 0n || stats.birthtimeNs === 0n ? real : `${stats.birthtimeNs}:${stats.ino}`));
15
+ }
16
+
17
+ export { folderIdentity2 };
@@ -0,0 +1,56 @@
1
+ import {
2
+ readNyteUsage2
3
+ } from "./canvas-preview-5hxat7hh.js";
4
+ import {
5
+ createUsageScanCaches2,
6
+ readLocalUsage2
7
+ } from "./canvas-preview-0nrnbt76.js";
8
+
9
+ // src/usage-service.ts
10
+ import { join } from "node:path";
11
+ import { FileModelsStore, nyteProviders } from "@nyte-ai/ai";
12
+ import { createModels } from "@nyte-ai/ai/models";
13
+ import { serial } from "@nyte-ai/schema/serial";
14
+ function catalogForUsage2(models) {
15
+ return [...models.getModels("anthropic"), ...models.getModels("openai-codex")];
16
+ }
17
+
18
+ class UsageScanner2 {
19
+ home;
20
+ caches = createUsageScanCaches2();
21
+ models;
22
+ scans = serial();
23
+ constructor(home) {
24
+ this.home = home;
25
+ this.models = createModels({
26
+ modelsStore: new FileModelsStore(join(home, ".nyte", "models-store.json"))
27
+ });
28
+ for (const provider of nyteProviders())
29
+ this.models.setProvider(provider);
30
+ }
31
+ scan(request) {
32
+ return this.scans.run(async () => {
33
+ if (request.catalog === undefined)
34
+ await this.models.refresh({
35
+ providers: ["anthropic", "openai-codex"],
36
+ allowNetwork: false
37
+ });
38
+ const catalog = request.catalog;
39
+ const models = catalog === undefined ? this.models : {
40
+ getModels: (provider) => catalog.filter((model) => provider === undefined || model.provider === provider)
41
+ };
42
+ const local = await readLocalUsage2({ models, caches: this.caches });
43
+ const report = readNyteUsage2(this.home, request.window);
44
+ return {
45
+ ...report,
46
+ ...local,
47
+ nyteError: report.sources.find((source) => source.status === "failed")?.message ?? null
48
+ };
49
+ });
50
+ }
51
+ close() {
52
+ return this.scans.settled();
53
+ }
54
+ }
55
+
56
+ export { catalogForUsage2, UsageScanner2 };
@@ -0,0 +1,26 @@
1
+ // src/deploy/vercel/server/utils/repair.ts
2
+ import { createHash, timingSafeEqual } from "node:crypto";
3
+ import { SdkError } from "@nyte-ai/schema";
4
+ import { encodeError, errorStatus } from "@nyte-ai/protocol";
5
+ async function answerRepair2(request, secret, repair) {
6
+ if (request.method !== "GET" || new URL(request.url).pathname !== "/.nyte/repair")
7
+ return;
8
+ if (secret === undefined || secret === "")
9
+ return failure(new SdkError("unknown", "This deployment sets no CRON_SECRET."));
10
+ const given = /^Bearer\s+(\S+)\s*$/i.exec(request.headers.get("Authorization") ?? "")?.[1] ?? "";
11
+ if (!timingSafeEqual(digest(given), digest(secret)))
12
+ return failure(new SdkError("unauthenticated", "Send Authorization: Bearer <CRON_SECRET>."));
13
+ await repair();
14
+ return new Response(null, { status: 204 });
15
+ }
16
+ function digest(text) {
17
+ return createHash("sha256").update(text).digest();
18
+ }
19
+ function failure(error) {
20
+ return new Response(JSON.stringify(encodeError(error)), {
21
+ status: errorStatus[error.code],
22
+ headers: { "Content-Type": "application/json" }
23
+ });
24
+ }
25
+
26
+ export { answerRepair2 };