@dev.fast/whiteboard 0.0.0-stage → 0.2.1-preview.20261005.98

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 (247) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +146 -2
  3. package/THIRD_PARTY_NOTICES.md +93 -0
  4. package/dist/account-alias-DOHN1RSH.js +973 -0
  5. package/dist/agent-cli-ChOq0ZuO.js +117 -0
  6. package/dist/agent-cli-DzWfZr6G.js +2 -0
  7. package/dist/agent-client-CPQo7iTI.js +305 -0
  8. package/dist/authoring-tools-Cr6Kpjsx.js +234 -0
  9. package/dist/build-info.json +1 -0
  10. package/dist/cli-hVgHcdsv.js +47 -0
  11. package/dist/cli-runner-D8y2_luU.js +5095 -0
  12. package/dist/cli.d.ts +1 -0
  13. package/dist/cli.js +128 -0
  14. package/dist/client-DFoh50W3.js +950 -0
  15. package/dist/desktop-discovery-DBO-PM2V.js +164 -0
  16. package/dist/error-message-OtiDonty.js +6 -0
  17. package/dist/fs-utils-BMPLt0cr.js +22 -0
  18. package/dist/fuzzy-match-BoAmcyak.js +30 -0
  19. package/dist/headless-host-BJxf4dUU.js +94 -0
  20. package/dist/input-error-OLgB_h31.js +11 -0
  21. package/dist/local-data-CxLk75rx.js +4491 -0
  22. package/dist/mcp-QeF8vkdf.js +140 -0
  23. package/dist/package-paths-B6-zxvIO.js +47 -0
  24. package/dist/process-error-telemetry-v9e5h6D7.js +3952 -0
  25. package/dist/profile-4ry2f3AM.js +76 -0
  26. package/dist/profile-Bh5FIrmf.js +2 -0
  27. package/dist/request-origin-D_4QIdoN.js +811 -0
  28. package/dist/review-agent-traces-DNJFYzc8.js +3866 -0
  29. package/dist/review-home-paths-6zZH-1c9.js +2560 -0
  30. package/dist/review-telemetry-DEFnQsQ2.js +1195 -0
  31. package/dist/runtime-CKiWhGrf.js +52 -0
  32. package/dist/runtime.d.ts +9 -0
  33. package/dist/runtime.js +2 -0
  34. package/dist/s3-SzLpeCG6.js +345 -0
  35. package/dist/s3-config-BgxkSoOy.js +2 -0
  36. package/dist/s3-config-CAxhO9u_.js +676 -0
  37. package/dist/server/desktop-host.d.ts +4 -0
  38. package/dist/server/desktop-host.js +1702 -0
  39. package/dist/server-discovery-Dbzn3w6Z.js +66 -0
  40. package/dist/sharing/index.d.ts +1977 -0
  41. package/dist/sharing/index.js +2 -0
  42. package/dist/src-CGP5ytbV.js +283 -0
  43. package/dist/src-CmdiBL20.js +3676 -0
  44. package/dist/src-DnwdaQ2r.js +865 -0
  45. package/dist/src-X9phtB2j.js +68 -0
  46. package/dist/stored-document-migration-DHeMpLMb.js +2671 -0
  47. package/dist/tool-failure-C8zB73HV.js +98 -0
  48. package/dist/tutorial-trace-DrBvkaeL.js +43 -0
  49. package/instructions/authoring.md +36 -0
  50. package/instructions/file-lenses.md +13 -0
  51. package/instructions/scratchpad.md +23 -0
  52. package/instructions/trace-archaeology.md +113 -0
  53. package/onboarding.md +8 -0
  54. package/package.json +106 -3
  55. package/src/agent-selection.ts +100 -0
  56. package/src/agent-session-ref.ts +80 -0
  57. package/src/ask/agents.ts +351 -0
  58. package/src/ask/checkout-files.ts +47 -0
  59. package/src/ask/file-refs.ts +111 -0
  60. package/src/ask/pi-mcp.ts +154 -0
  61. package/src/ask/protocol.ts +244 -0
  62. package/src/ask/thread-state.ts +350 -0
  63. package/src/ask/thread.ts +1400 -0
  64. package/src/ask/threads.ts +219 -0
  65. package/src/ask/watch.ts +79 -0
  66. package/src/cli-install.ts +1041 -0
  67. package/src/cli-runner.ts +1461 -0
  68. package/src/cli-runtime-info.ts +35 -0
  69. package/src/cli.ts +222 -0
  70. package/src/connect-prompts.ts +248 -0
  71. package/src/cursor-deeplink.ts +11 -0
  72. package/src/desktop-discovery.ts +355 -0
  73. package/src/diff-selection-migration.ts +63 -0
  74. package/src/embedded-posthog-key.ts +6 -0
  75. package/src/error-telemetry.ts +247 -0
  76. package/src/evidence.ts +14 -0
  77. package/src/exception-telemetry.ts +126 -0
  78. package/src/fixtures/blocks/call_stack_diff.json +27 -0
  79. package/src/fixtures/blocks/callout.json +11 -0
  80. package/src/fixtures/blocks/code.json +9 -0
  81. package/src/fixtures/blocks/code_peek.json +8 -0
  82. package/src/fixtures/blocks/database_lens.json +51 -0
  83. package/src/fixtures/blocks/divider.json +1 -0
  84. package/src/fixtures/blocks/fixtures.ts +33 -0
  85. package/src/fixtures/blocks/flow_diagram.json +36 -0
  86. package/src/fixtures/blocks/ids.ts +8 -0
  87. package/src/fixtures/blocks/image.json +9 -0
  88. package/src/fixtures/blocks/markdown.json +7 -0
  89. package/src/fixtures/blocks/section.json +11 -0
  90. package/src/fixtures/blocks/sequence.json +31 -0
  91. package/src/fixtures/blocks/software_map.json +7 -0
  92. package/src/fixtures/blocks/trace_quote.json +9 -0
  93. package/src/fixtures/blocks/tutorial.json +51 -0
  94. package/src/fs-utils.ts +32 -0
  95. package/src/fuzzy-match.ts +94 -0
  96. package/src/install.ts +29 -0
  97. package/src/legacy-skills.ts +133 -0
  98. package/src/lens-selection.ts +230 -0
  99. package/src/markdown-latex-math.ts +230 -0
  100. package/src/markdown.ts +81 -0
  101. package/src/package-paths.ts +53 -0
  102. package/src/posthog-capture-client.ts +610 -0
  103. package/src/review-api/README.md +295 -0
  104. package/src/review-api/activity.ts +340 -0
  105. package/src/review-api/agent-cli.ts +219 -0
  106. package/src/review-api/agent-client.ts +188 -0
  107. package/src/review-api/anchor-quotes.ts +88 -0
  108. package/src/review-api/ask-history.ts +242 -0
  109. package/src/review-api/authoring-tools.ts +211 -0
  110. package/src/review-api/blocks/call_stack_diff.ts +75 -0
  111. package/src/review-api/blocks/callout.ts +24 -0
  112. package/src/review-api/blocks/code.ts +9 -0
  113. package/src/review-api/blocks/code_peek.ts +13 -0
  114. package/src/review-api/blocks/database_lens.ts +150 -0
  115. package/src/review-api/blocks/definition.ts +40 -0
  116. package/src/review-api/blocks/divider.ts +6 -0
  117. package/src/review-api/blocks/flow_diagram.ts +111 -0
  118. package/src/review-api/blocks/image.ts +10 -0
  119. package/src/review-api/blocks/index.ts +90 -0
  120. package/src/review-api/blocks/markdown.ts +17 -0
  121. package/src/review-api/blocks/section.ts +24 -0
  122. package/src/review-api/blocks/sequence.ts +56 -0
  123. package/src/review-api/blocks/software_map.ts +9 -0
  124. package/src/review-api/blocks/trace_quote.ts +10 -0
  125. package/src/review-api/blocks/tutorial.ts +39 -0
  126. package/src/review-api/checkout-fs.ts +14 -0
  127. package/src/review-api/client.ts +1 -0
  128. package/src/review-api/comparison-coverage.ts +304 -0
  129. package/src/review-api/component-reference.ts +30 -0
  130. package/src/review-api/diff-lenses.ts +175 -0
  131. package/src/review-api/document-headings.ts +51 -0
  132. package/src/review-api/document-text.ts +200 -0
  133. package/src/review-api/document.ts +906 -0
  134. package/src/review-api/file-lenses.ts +100 -0
  135. package/src/review-api/http.ts +1877 -0
  136. package/src/review-api/image-decode.ts +29 -0
  137. package/src/review-api/input-error.ts +9 -0
  138. package/src/review-api/instructions.ts +89 -0
  139. package/src/review-api/lens-alignment.ts +52 -0
  140. package/src/review-api/local-data.ts +1837 -0
  141. package/src/review-api/map-input.ts +154 -0
  142. package/src/review-api/mcp-client-agent.ts +32 -0
  143. package/src/review-api/mcp.ts +240 -0
  144. package/src/review-api/origin.ts +43 -0
  145. package/src/review-api/profile.ts +146 -0
  146. package/src/review-api/public-tools.ts +102 -0
  147. package/src/review-api/pull-request.ts +389 -0
  148. package/src/review-api/read-schemas.ts +85 -0
  149. package/src/review-api/recovery.ts +2 -0
  150. package/src/review-api/request-origin.ts +33 -0
  151. package/src/review-api/review-progress.ts +382 -0
  152. package/src/review-api/status-tool.ts +10 -0
  153. package/src/review-api/store-schema.ts +22 -0
  154. package/src/review-api/store.ts +1647 -0
  155. package/src/review-api/tool-failure.ts +64 -0
  156. package/src/review-api/trace-schema.ts +13 -0
  157. package/src/review-api/traces.ts +119 -0
  158. package/src/review-api/unsupported-files.integration.ts +91 -0
  159. package/src/review-api/workspaces.ts +692 -0
  160. package/src/review-api/worktree-source.ts +170 -0
  161. package/src/review-api/worktree-structural.integration.ts +320 -0
  162. package/src/review-app-launcher.ts +432 -0
  163. package/src/review-app-picker.ts +168 -0
  164. package/src/review-app.ts +134 -0
  165. package/src/review-bundled-tools.ts +249 -0
  166. package/src/review-checkout-paths.ts +37 -0
  167. package/src/review-diff-files.ts +89 -0
  168. package/src/review-head-checkout.ts +300 -0
  169. package/src/review-home-paths.ts +73 -0
  170. package/src/review-info.ts +59 -0
  171. package/src/review-instances.ts +113 -0
  172. package/src/review-logger.ts +183 -0
  173. package/src/review-preferences.ts +88 -0
  174. package/src/review-prepare.ts +291 -0
  175. package/src/review-stack.ts +112 -0
  176. package/src/review-telemetry.ts +1066 -0
  177. package/src/runtime.ts +74 -0
  178. package/src/server/account-alias.ts +30 -0
  179. package/src/server/bounded-stream.ts +34 -0
  180. package/src/server/bug-report.ts +301 -0
  181. package/src/server/client-error-budget.ts +45 -0
  182. package/src/server/crash-report.ts +273 -0
  183. package/src/server/desktop-host-shutdown.ts +64 -0
  184. package/src/server/desktop-host.ts +190 -0
  185. package/src/server/desktop-server.ts +703 -0
  186. package/src/server/diffr-config.ts +509 -0
  187. package/src/server/diffr-languages.ts +97 -0
  188. package/src/server/global-verb-relay.ts +190 -0
  189. package/src/server/headless-host.ts +149 -0
  190. package/src/server/hono-http.ts +162 -0
  191. package/src/server/http-json.ts +24 -0
  192. package/src/server/json-review-reporting.ts +174 -0
  193. package/src/server/process-error-telemetry.ts +174 -0
  194. package/src/server/review-api-parsers.ts +90 -0
  195. package/src/server/review-lifecycle-telemetry.ts +73 -0
  196. package/src/server/review-open-watchdog.ts +46 -0
  197. package/src/server/review-server-core.ts +290 -0
  198. package/src/server/structural-comparisons.ts +153 -0
  199. package/src/server/structural-diff.ts +186 -0
  200. package/src/server/tutorial-service.ts +241 -0
  201. package/src/server/ui-telemetry.ts +198 -0
  202. package/src/server-discovery.ts +95 -0
  203. package/src/session-markers.ts +132 -0
  204. package/src/sharing/auth.ts +41 -0
  205. package/src/sharing/cli.ts +83 -0
  206. package/src/sharing/client.ts +334 -0
  207. package/src/sharing/export.ts +195 -0
  208. package/src/sharing/host.ts +316 -0
  209. package/src/sharing/import.ts +787 -0
  210. package/src/sharing/index.ts +16 -0
  211. package/src/sharing/repository.ts +145 -0
  212. package/src/sharing/routes.ts +34 -0
  213. package/src/slug.ts +23 -0
  214. package/src/software-map-diff-counts.ts +517 -0
  215. package/src/software-map-model.ts +1147 -0
  216. package/src/software-map-topology-diff.ts +260 -0
  217. package/src/source.ts +92 -0
  218. package/src/startup-trace.ts +232 -0
  219. package/src/stored-document-migration.ts +151 -0
  220. package/src/telemetry-clean-text.ts +257 -0
  221. package/src/telemetry-config.ts +298 -0
  222. package/src/telemetry-debug-sink.ts +38 -0
  223. package/src/telemetry.ts +13 -0
  224. package/src/trace-cli.ts +156 -0
  225. package/src/trace-storage-cli.ts +509 -0
  226. package/src/tutorial-conversation.ts +18 -0
  227. package/src/ui-telemetry-events.ts +765 -0
  228. package/src/unified-diff.ts +71 -0
  229. package/src/viewed-coverage.ts +259 -0
  230. package/src/windows-cli.ts +125 -0
  231. package/tutorial/document.json +275 -0
  232. package/tutorial/runtime-manifest.json +12 -0
  233. package/tutorial/sample-service/package.json +9 -0
  234. package/tutorial/sample-service/src/api/checkout-api.ts +17 -0
  235. package/tutorial/sample-service/src/app.ts +26 -0
  236. package/tutorial/sample-service/src/database/schema.ts +10 -0
  237. package/tutorial/sample-service/src/fulfillment/fulfillment-queue.ts +15 -0
  238. package/tutorial/sample-service/src/fulfillment/fulfillment-worker.ts +24 -0
  239. package/tutorial/sample-service/src/inventory/inventory-service.ts +11 -0
  240. package/tutorial/sample-service/src/orders/order-service.ts +34 -0
  241. package/tutorial/sample-service/src/orders/order.ts +21 -0
  242. package/tutorial/sample-service/src/orders/orders-repository.ts +24 -0
  243. package/tutorial/sample-service/src/payments/payment-gateway.ts +12 -0
  244. package/tutorial/sample-service/src/shipping/shipping-gateway.ts +15 -0
  245. package/tutorial/sample-service/tsconfig.json +12 -0
  246. package/tutorial/software-map.json +139 -0
  247. package/tutorial/trace.json +20 -0
@@ -0,0 +1,52 @@
1
+ import path from "node:path";
2
+ import { spawn } from "node:child_process";
3
+ //#region src/runtime.ts
4
+ async function resolveReviewRoot(cwd, execFile = execFilePromise) {
5
+ const initialCwd = path.resolve(cwd);
6
+ try {
7
+ const { stdout } = await execFile("jj", ["root"], { cwd: initialCwd });
8
+ const root = stdout.trim();
9
+ if (root) return path.resolve(root);
10
+ } catch {}
11
+ try {
12
+ const { stdout } = await execFile("git", [
13
+ "-C",
14
+ initialCwd,
15
+ "rev-parse",
16
+ "--show-toplevel"
17
+ ]);
18
+ const root = stdout.trim();
19
+ if (root) return path.resolve(root);
20
+ } catch {}
21
+ return initialCwd;
22
+ }
23
+ function execFilePromise(file, args, options = {}) {
24
+ return execFileUntraced(file, args, options);
25
+ }
26
+ function execFileUntraced(file, args, options = {}) {
27
+ return new Promise((resolve, reject) => {
28
+ const child = spawn(file, args, {
29
+ cwd: options.cwd,
30
+ stdio: [
31
+ "ignore",
32
+ "pipe",
33
+ "pipe"
34
+ ]
35
+ });
36
+ let stdout = "";
37
+ let stderr = "";
38
+ child.stdout?.on("data", (chunk) => {
39
+ stdout += String(chunk);
40
+ });
41
+ child.stderr?.on("data", (chunk) => {
42
+ stderr += String(chunk);
43
+ });
44
+ child.on("error", reject);
45
+ child.on("exit", (code) => {
46
+ if (code === 0) resolve({ stdout });
47
+ else reject(new Error(stderr.trim() || `${file} exited with ${code}`));
48
+ });
49
+ });
50
+ }
51
+ //#endregion
52
+ export { resolveReviewRoot as t };
@@ -0,0 +1,9 @@
1
+ //#region src/runtime.d.ts
2
+ declare function resolveReviewRoot(cwd: string, execFile?: typeof execFilePromise): Promise<string>;
3
+ declare function execFilePromise(file: string, args: string[], options?: {
4
+ cwd?: string;
5
+ }): Promise<{
6
+ stdout: string;
7
+ }>;
8
+ //#endregion
9
+ export { resolveReviewRoot };
@@ -0,0 +1,2 @@
1
+ import { t as resolveReviewRoot } from "./runtime-CKiWhGrf.js";
2
+ export { resolveReviewRoot };
@@ -0,0 +1,345 @@
1
+ import { a as jsonNumber, c as jsonString, o as jsonObject, r as jsonArray, u as parseJsonText } from "./src-X9phtB2j.js";
2
+ import { S as sessionMetaSchema, b as commitShaSchema, y as byCommitSchema } from "./src-CGP5ytbV.js";
3
+ import { i as isS3MockMode, l as s3CacheIdentity, s as resolveS3Credentials, u as s3MockRoot } from "./s3-config-CAxhO9u_.js";
4
+ import { t as errorMessage } from "./error-message-OtiDonty.js";
5
+ import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
6
+ import path from "node:path";
7
+ import { tmpdir } from "node:os";
8
+ import { execFile } from "node:child_process";
9
+ import { promisify } from "node:util";
10
+ //#region ../trace-core/src/trace-storage/s3.ts
11
+ /**
12
+ * Direct S3/R2 storage through the AWS CLI. Owns the legacy bucket layout:
13
+ *
14
+ * by-session/<session>/trace.jsonl
15
+ * by-session/<session>/subagents/<name>.jsonl
16
+ * by-session/<session>/meta.json
17
+ * by-commit/<sha>.json
18
+ *
19
+ * Objects only grow: a transcript is re-uploaded when the local copy is
20
+ * larger than the stored one, and a by-commit entry is written once.
21
+ */
22
+ const execFileAsync = promisify(execFile);
23
+ var S3TraceStorage = class S3TraceStorage {
24
+ config;
25
+ mockRoot;
26
+ env;
27
+ kind = "s3";
28
+ target;
29
+ constructor(config, mockRoot, env) {
30
+ this.config = config;
31
+ this.mockRoot = mockRoot;
32
+ this.env = env;
33
+ this.target = config ? {
34
+ kind: "s3",
35
+ endpoint: config.endpoint,
36
+ bucket: config.bucket,
37
+ region: config.region
38
+ } : {
39
+ kind: "s3",
40
+ endpoint: "mock://endpoint",
41
+ bucket: "mock-bucket",
42
+ region: "auto",
43
+ mockRoot: mockRoot ?? void 0
44
+ };
45
+ }
46
+ /**
47
+ * The bucket named by the legacy configuration, or null when none is
48
+ * configured. Mock mode yields a storage backed by a directory.
49
+ */
50
+ static fromEnvironment(scope = {}) {
51
+ const env = scope.env ?? process.env;
52
+ if (isS3MockMode(env)) return new S3TraceStorage(null, s3MockRoot(env), env);
53
+ const config = resolveS3Credentials(scope);
54
+ return config ? new S3TraceStorage(config, null, env) : null;
55
+ }
56
+ static fromCredentials(config, env = process.env) {
57
+ return new S3TraceStorage(config, null, env);
58
+ }
59
+ /** Secret-free identity of the destination; the same bucket keys the same cache. */
60
+ cacheIdentity() {
61
+ return s3CacheIdentity(this.config, this.mockRoot);
62
+ }
63
+ cacheScope(repo) {
64
+ return repo;
65
+ }
66
+ /** A non-mutating reachability check of the configured bucket. */
67
+ async readiness() {
68
+ if (!this.config) return { ready: true };
69
+ try {
70
+ await this.aws([
71
+ "s3api",
72
+ "head-bucket",
73
+ "--bucket",
74
+ this.config.bucket
75
+ ], { timeout: 15e3 });
76
+ return { ready: true };
77
+ } catch (error) {
78
+ return {
79
+ ready: false,
80
+ reason: errorMessage(error)
81
+ };
82
+ }
83
+ }
84
+ async describeObject(sessionId, traceName) {
85
+ const size = await this.headObjectSize(objectKey(sessionId, traceName));
86
+ return size === null ? null : {
87
+ size,
88
+ contentId: `size:${size}`
89
+ };
90
+ }
91
+ async downloadObject(sessionId, traceName, destinationPath) {
92
+ if (!await this.getObject(objectKey(sessionId, traceName), destinationPath)) return null;
93
+ const size = statSync(destinationPath).size;
94
+ return {
95
+ size,
96
+ contentId: `size:${size}`
97
+ };
98
+ }
99
+ async listSubagents(sessionId) {
100
+ const prefix = `by-session/${sessionId}/subagents/`;
101
+ const names = /* @__PURE__ */ new Set();
102
+ if (this.mockRoot !== null || !this.config) {
103
+ if (this.mockRoot) {
104
+ const dir = path.join(this.mockRoot, prefix);
105
+ if (existsSync(dir)) try {
106
+ for (const entry of readdirSync(dir)) if (entry.endsWith(".jsonl")) names.add(entry.slice(0, -6));
107
+ } catch {}
108
+ }
109
+ return [...names].sort();
110
+ }
111
+ try {
112
+ const proc = await this.aws([
113
+ "s3api",
114
+ "list-objects-v2",
115
+ "--bucket",
116
+ this.config.bucket,
117
+ "--prefix",
118
+ prefix
119
+ ], { timeout: 1e4 });
120
+ const listing = jsonObject(parseJsonText(proc.stdout));
121
+ for (const item of jsonArray(listing?.Contents) ?? []) {
122
+ const key = jsonString(jsonObject(item)?.Key);
123
+ if (key && key.startsWith(prefix) && key.endsWith(".jsonl")) {
124
+ const name = key.slice(prefix.length, -6);
125
+ if (name) names.add(name);
126
+ }
127
+ }
128
+ } catch {}
129
+ return [...names].sort();
130
+ }
131
+ async sessionMeta(sessionId) {
132
+ try {
133
+ const parsed = sessionMetaSchema.safeParse(await this.getJson(metaKey(sessionId)));
134
+ return parsed.success ? parsed.data : null;
135
+ } catch {
136
+ return null;
137
+ }
138
+ }
139
+ async sessionsForCommit(commit) {
140
+ if (!commitShaSchema.safeParse(commit).success) return null;
141
+ try {
142
+ const parsed = byCommitSchema.safeParse(await this.getJson(commitKey(commit)));
143
+ if (!parsed.success || parsed.data.sessions.length === 0) return null;
144
+ return {
145
+ sessions: parsed.data.sessions,
146
+ pr: parsed.data.pr,
147
+ branch: parsed.data.branch
148
+ };
149
+ } catch {
150
+ return null;
151
+ }
152
+ }
153
+ async publish(input) {
154
+ const uploads = [];
155
+ for (const file of input.files) {
156
+ const key = objectKey(input.sessionId, file.name);
157
+ const grown = await this.putIfGrown(key, file.path);
158
+ uploads.push({
159
+ blob: file.name === "main" ? "trace.jsonl" : `subagents/${file.name}`,
160
+ bytes_stored: statSync(file.path).size,
161
+ status: grown ? "uploaded" : "unchanged"
162
+ });
163
+ }
164
+ const existing = await this.sessionMeta(input.sessionId);
165
+ const meta = {
166
+ session: input.sessionId,
167
+ repo: `${input.repo.owner}/${input.repo.repo}`,
168
+ branch: input.branch ?? existing?.branch ?? null,
169
+ pr: existing?.pr ?? null,
170
+ commits: deduplicateStrings([...existing?.commits ?? [], ...(input.commits ?? []).filter((commit) => commitShaSchema.safeParse(commit).success)]),
171
+ author: input.author ?? existing?.author ?? null,
172
+ ts: (/* @__PURE__ */ new Date()).toISOString()
173
+ };
174
+ if (!await this.putBuffer(metaKey(input.sessionId), Buffer.from(JSON.stringify(meta, null, 2), "utf8"))) throw new Error(`Failed to update session metadata for ${input.sessionId} in S3/R2 storage.`);
175
+ return { uploads };
176
+ }
177
+ async associateCommits(input) {
178
+ const commit = commitShaSchema.parse(input.commit);
179
+ if (await this.getJson(commitKey(commit)) !== null) return false;
180
+ const { repo, pr } = await input.resolve();
181
+ const entry = byCommitSchema.parse({
182
+ commit,
183
+ sessions: deduplicateStrings(input.sessions),
184
+ repo: `${repo.owner}/${repo.repo}`,
185
+ pr,
186
+ branch: input.branch,
187
+ indexed_by: "hook",
188
+ ts: (/* @__PURE__ */ new Date()).toISOString()
189
+ });
190
+ if (!await this.putBuffer(commitKey(commit), Buffer.from(JSON.stringify(entry, null, 2), "utf8"))) throw new Error(`Failed to write by-commit/${commit}.json.`);
191
+ return true;
192
+ }
193
+ async headObjectSize(key) {
194
+ if (!this.config) {
195
+ if (!this.mockRoot) return null;
196
+ try {
197
+ const stats = statSync(path.join(this.mockRoot, key));
198
+ return stats.isFile() ? stats.size : null;
199
+ } catch {
200
+ return null;
201
+ }
202
+ }
203
+ try {
204
+ const proc = await this.aws([
205
+ "s3api",
206
+ "head-object",
207
+ "--bucket",
208
+ this.config.bucket,
209
+ "--key",
210
+ key
211
+ ], { timeout: 1e4 });
212
+ return jsonNumber(jsonObject(parseJsonText(proc.stdout))?.ContentLength) ?? null;
213
+ } catch {
214
+ return null;
215
+ }
216
+ }
217
+ async getObject(key, destPath) {
218
+ mkdirSync(path.dirname(destPath), { recursive: true });
219
+ if (!this.config) {
220
+ if (!this.mockRoot) return false;
221
+ try {
222
+ writeFileSync(destPath, readFileSync(path.join(this.mockRoot, key)));
223
+ return true;
224
+ } catch {
225
+ return false;
226
+ }
227
+ }
228
+ try {
229
+ await this.aws([
230
+ "s3api",
231
+ "get-object",
232
+ "--bucket",
233
+ this.config.bucket,
234
+ "--key",
235
+ key,
236
+ destPath
237
+ ], {
238
+ timeout: 6e4,
239
+ maxBuffer: 16777216
240
+ });
241
+ return existsSync(destPath);
242
+ } catch {
243
+ return false;
244
+ }
245
+ }
246
+ async getJson(key) {
247
+ const tmpPath = path.join(tmpdir(), `r2-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
248
+ try {
249
+ if (!await this.getObject(key, tmpPath)) return null;
250
+ return parseJsonText(readFileSync(tmpPath, "utf8"));
251
+ } catch {
252
+ return null;
253
+ } finally {
254
+ rmSync(tmpPath, { force: true });
255
+ }
256
+ }
257
+ async putFile(key, filePath) {
258
+ if (!this.config) {
259
+ if (!this.mockRoot) return false;
260
+ try {
261
+ const target = path.join(this.mockRoot, key);
262
+ mkdirSync(path.dirname(target), { recursive: true });
263
+ writeFileSync(target, readFileSync(filePath));
264
+ return true;
265
+ } catch {
266
+ return false;
267
+ }
268
+ }
269
+ try {
270
+ await this.aws([
271
+ "s3",
272
+ "cp",
273
+ "--only-show-errors",
274
+ filePath,
275
+ `s3://${this.config.bucket}/${key}`
276
+ ], { timeout: 6e4 });
277
+ return true;
278
+ } catch {
279
+ return false;
280
+ }
281
+ }
282
+ async putBuffer(key, content) {
283
+ if (!this.config) {
284
+ if (!this.mockRoot) return false;
285
+ try {
286
+ const target = path.join(this.mockRoot, key);
287
+ mkdirSync(path.dirname(target), { recursive: true });
288
+ writeFileSync(target, content);
289
+ return true;
290
+ } catch {
291
+ return false;
292
+ }
293
+ }
294
+ const tempFile = path.join(tmpdir(), `put-${process.pid}-${Math.random().toString(36).slice(2)}.tmp`);
295
+ writeFileSync(tempFile, content);
296
+ try {
297
+ return await this.putFile(key, tempFile);
298
+ } finally {
299
+ rmSync(tempFile, { force: true });
300
+ }
301
+ }
302
+ async putIfGrown(key, filePath) {
303
+ const remoteSize = await this.headObjectSize(key);
304
+ const localSize = statSync(filePath).size;
305
+ if (remoteSize !== null && localSize <= remoteSize) return false;
306
+ if (!await this.putFile(key, filePath)) throw new Error(`Failed to upload ${key} to S3/R2 storage.`);
307
+ return true;
308
+ }
309
+ aws(args, options) {
310
+ const config = this.config;
311
+ if (!config) throw new Error("S3 trace storage is not configured.");
312
+ return execFileAsync("aws", [
313
+ "--region",
314
+ config.region,
315
+ "--endpoint-url",
316
+ config.endpoint,
317
+ ...args
318
+ ], {
319
+ ...options,
320
+ env: {
321
+ ...this.env,
322
+ AWS_ACCESS_KEY_ID: config.accessKeyId,
323
+ AWS_SECRET_ACCESS_KEY: config.secretAccessKey
324
+ }
325
+ });
326
+ }
327
+ };
328
+ function objectKey(sessionId, traceName) {
329
+ return traceName === "main" ? `by-session/${sessionId}/trace.jsonl` : `by-session/${sessionId}/subagents/${normalizeSubagentFileName(traceName)}`;
330
+ }
331
+ function metaKey(sessionId) {
332
+ return `by-session/${sessionId}/meta.json`;
333
+ }
334
+ function commitKey(commit) {
335
+ return `by-commit/${commit}.json`;
336
+ }
337
+ function normalizeSubagentFileName(name) {
338
+ const base = path.basename(name);
339
+ return base.endsWith(".jsonl") ? base : `${base}.jsonl`;
340
+ }
341
+ function deduplicateStrings(items) {
342
+ return [...new Set(items)];
343
+ }
344
+ //#endregion
345
+ export { S3TraceStorage, normalizeSubagentFileName };
@@ -0,0 +1,2 @@
1
+ import { a as noTraceConfigurationMessage, c as resolveS3Setup, d as traceEnvPath, f as traceEnvValue, i as isS3MockMode, l as s3CacheIdentity, n as clearTraceEnvCache, o as readTraceEnvFile, p as traceSettingsPath, r as describeS3Setup, s as resolveS3Credentials, t as S3_DEFAULT_REGION, u as s3MockRoot } from "./s3-config-CAxhO9u_.js";
2
+ export { S3_DEFAULT_REGION, clearTraceEnvCache, describeS3Setup, isS3MockMode, noTraceConfigurationMessage, readTraceEnvFile, resolveS3Credentials, resolveS3Setup, s3CacheIdentity, s3MockRoot, traceEnvPath, traceEnvValue, traceSettingsPath };