@dev.fast/whiteboard 0.0.0-stage → 0.2.0
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.
- package/LICENSE +21 -0
- package/README.md +146 -2
- package/THIRD_PARTY_NOTICES.md +93 -0
- package/dist/account-alias-DOHN1RSH.js +973 -0
- package/dist/agent-cli-ChOq0ZuO.js +117 -0
- package/dist/agent-cli-DzWfZr6G.js +2 -0
- package/dist/agent-client-CPQo7iTI.js +305 -0
- package/dist/authoring-tools-Cr6Kpjsx.js +234 -0
- package/dist/build-info.json +1 -0
- package/dist/cli-hVgHcdsv.js +47 -0
- package/dist/cli-runner-D8y2_luU.js +5095 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +128 -0
- package/dist/client-DFoh50W3.js +950 -0
- package/dist/desktop-discovery-DBO-PM2V.js +164 -0
- package/dist/error-message-OtiDonty.js +6 -0
- package/dist/fs-utils-BMPLt0cr.js +22 -0
- package/dist/fuzzy-match-BoAmcyak.js +30 -0
- package/dist/headless-host-BJxf4dUU.js +94 -0
- package/dist/input-error-OLgB_h31.js +11 -0
- package/dist/local-data-CxLk75rx.js +4491 -0
- package/dist/mcp-QeF8vkdf.js +140 -0
- package/dist/package-paths-B6-zxvIO.js +47 -0
- package/dist/process-error-telemetry-v9e5h6D7.js +3952 -0
- package/dist/profile-4ry2f3AM.js +76 -0
- package/dist/profile-Bh5FIrmf.js +2 -0
- package/dist/request-origin-D_4QIdoN.js +811 -0
- package/dist/review-agent-traces-DNJFYzc8.js +3866 -0
- package/dist/review-home-paths-6zZH-1c9.js +2560 -0
- package/dist/review-telemetry-DEFnQsQ2.js +1195 -0
- package/dist/runtime-CKiWhGrf.js +52 -0
- package/dist/runtime.d.ts +9 -0
- package/dist/runtime.js +2 -0
- package/dist/s3-SzLpeCG6.js +345 -0
- package/dist/s3-config-BgxkSoOy.js +2 -0
- package/dist/s3-config-CAxhO9u_.js +676 -0
- package/dist/server/desktop-host.d.ts +4 -0
- package/dist/server/desktop-host.js +1702 -0
- package/dist/server-discovery-Dbzn3w6Z.js +66 -0
- package/dist/sharing/index.d.ts +1977 -0
- package/dist/sharing/index.js +2 -0
- package/dist/src-CGP5ytbV.js +283 -0
- package/dist/src-CmdiBL20.js +3676 -0
- package/dist/src-DnwdaQ2r.js +865 -0
- package/dist/src-X9phtB2j.js +68 -0
- package/dist/stored-document-migration-DHeMpLMb.js +2671 -0
- package/dist/tool-failure-C8zB73HV.js +98 -0
- package/dist/tutorial-trace-DrBvkaeL.js +43 -0
- package/instructions/authoring.md +36 -0
- package/instructions/file-lenses.md +13 -0
- package/instructions/scratchpad.md +23 -0
- package/instructions/trace-archaeology.md +113 -0
- package/onboarding.md +8 -0
- package/package.json +106 -3
- package/src/agent-selection.ts +100 -0
- package/src/agent-session-ref.ts +80 -0
- package/src/ask/agents.ts +351 -0
- package/src/ask/checkout-files.ts +47 -0
- package/src/ask/file-refs.ts +111 -0
- package/src/ask/pi-mcp.ts +154 -0
- package/src/ask/protocol.ts +244 -0
- package/src/ask/thread-state.ts +350 -0
- package/src/ask/thread.ts +1400 -0
- package/src/ask/threads.ts +219 -0
- package/src/ask/watch.ts +79 -0
- package/src/cli-install.ts +1041 -0
- package/src/cli-runner.ts +1461 -0
- package/src/cli-runtime-info.ts +35 -0
- package/src/cli.ts +222 -0
- package/src/connect-prompts.ts +248 -0
- package/src/cursor-deeplink.ts +11 -0
- package/src/desktop-discovery.ts +355 -0
- package/src/diff-selection-migration.ts +63 -0
- package/src/embedded-posthog-key.ts +6 -0
- package/src/error-telemetry.ts +247 -0
- package/src/evidence.ts +14 -0
- package/src/exception-telemetry.ts +126 -0
- package/src/fixtures/blocks/call_stack_diff.json +27 -0
- package/src/fixtures/blocks/callout.json +11 -0
- package/src/fixtures/blocks/code.json +9 -0
- package/src/fixtures/blocks/code_peek.json +8 -0
- package/src/fixtures/blocks/database_lens.json +51 -0
- package/src/fixtures/blocks/divider.json +1 -0
- package/src/fixtures/blocks/fixtures.ts +33 -0
- package/src/fixtures/blocks/flow_diagram.json +36 -0
- package/src/fixtures/blocks/ids.ts +8 -0
- package/src/fixtures/blocks/image.json +9 -0
- package/src/fixtures/blocks/markdown.json +7 -0
- package/src/fixtures/blocks/section.json +11 -0
- package/src/fixtures/blocks/sequence.json +31 -0
- package/src/fixtures/blocks/software_map.json +7 -0
- package/src/fixtures/blocks/trace_quote.json +9 -0
- package/src/fixtures/blocks/tutorial.json +51 -0
- package/src/fs-utils.ts +32 -0
- package/src/fuzzy-match.ts +94 -0
- package/src/install.ts +29 -0
- package/src/legacy-skills.ts +133 -0
- package/src/lens-selection.ts +230 -0
- package/src/markdown-latex-math.ts +230 -0
- package/src/markdown.ts +81 -0
- package/src/package-paths.ts +53 -0
- package/src/posthog-capture-client.ts +610 -0
- package/src/review-api/README.md +295 -0
- package/src/review-api/activity.ts +340 -0
- package/src/review-api/agent-cli.ts +219 -0
- package/src/review-api/agent-client.ts +188 -0
- package/src/review-api/anchor-quotes.ts +88 -0
- package/src/review-api/ask-history.ts +242 -0
- package/src/review-api/authoring-tools.ts +211 -0
- package/src/review-api/blocks/call_stack_diff.ts +75 -0
- package/src/review-api/blocks/callout.ts +24 -0
- package/src/review-api/blocks/code.ts +9 -0
- package/src/review-api/blocks/code_peek.ts +13 -0
- package/src/review-api/blocks/database_lens.ts +150 -0
- package/src/review-api/blocks/definition.ts +40 -0
- package/src/review-api/blocks/divider.ts +6 -0
- package/src/review-api/blocks/flow_diagram.ts +111 -0
- package/src/review-api/blocks/image.ts +10 -0
- package/src/review-api/blocks/index.ts +90 -0
- package/src/review-api/blocks/markdown.ts +17 -0
- package/src/review-api/blocks/section.ts +24 -0
- package/src/review-api/blocks/sequence.ts +56 -0
- package/src/review-api/blocks/software_map.ts +9 -0
- package/src/review-api/blocks/trace_quote.ts +10 -0
- package/src/review-api/blocks/tutorial.ts +39 -0
- package/src/review-api/checkout-fs.ts +14 -0
- package/src/review-api/client.ts +1 -0
- package/src/review-api/comparison-coverage.ts +304 -0
- package/src/review-api/component-reference.ts +30 -0
- package/src/review-api/diff-lenses.ts +175 -0
- package/src/review-api/document-headings.ts +51 -0
- package/src/review-api/document-text.ts +200 -0
- package/src/review-api/document.ts +906 -0
- package/src/review-api/file-lenses.ts +100 -0
- package/src/review-api/http.ts +1877 -0
- package/src/review-api/image-decode.ts +29 -0
- package/src/review-api/input-error.ts +9 -0
- package/src/review-api/instructions.ts +89 -0
- package/src/review-api/lens-alignment.ts +52 -0
- package/src/review-api/local-data.ts +1837 -0
- package/src/review-api/map-input.ts +154 -0
- package/src/review-api/mcp-client-agent.ts +32 -0
- package/src/review-api/mcp.ts +240 -0
- package/src/review-api/origin.ts +43 -0
- package/src/review-api/profile.ts +146 -0
- package/src/review-api/public-tools.ts +102 -0
- package/src/review-api/pull-request.ts +389 -0
- package/src/review-api/read-schemas.ts +85 -0
- package/src/review-api/recovery.ts +2 -0
- package/src/review-api/request-origin.ts +33 -0
- package/src/review-api/review-progress.ts +382 -0
- package/src/review-api/status-tool.ts +10 -0
- package/src/review-api/store-schema.ts +22 -0
- package/src/review-api/store.ts +1647 -0
- package/src/review-api/tool-failure.ts +64 -0
- package/src/review-api/trace-schema.ts +13 -0
- package/src/review-api/traces.ts +119 -0
- package/src/review-api/unsupported-files.integration.ts +91 -0
- package/src/review-api/workspaces.ts +692 -0
- package/src/review-api/worktree-source.ts +170 -0
- package/src/review-api/worktree-structural.integration.ts +320 -0
- package/src/review-app-launcher.ts +432 -0
- package/src/review-app-picker.ts +168 -0
- package/src/review-app.ts +134 -0
- package/src/review-bundled-tools.ts +249 -0
- package/src/review-checkout-paths.ts +37 -0
- package/src/review-diff-files.ts +89 -0
- package/src/review-head-checkout.ts +300 -0
- package/src/review-home-paths.ts +73 -0
- package/src/review-info.ts +59 -0
- package/src/review-instances.ts +113 -0
- package/src/review-logger.ts +183 -0
- package/src/review-preferences.ts +88 -0
- package/src/review-prepare.ts +291 -0
- package/src/review-stack.ts +112 -0
- package/src/review-telemetry.ts +1066 -0
- package/src/runtime.ts +74 -0
- package/src/server/account-alias.ts +30 -0
- package/src/server/bounded-stream.ts +34 -0
- package/src/server/bug-report.ts +301 -0
- package/src/server/client-error-budget.ts +45 -0
- package/src/server/crash-report.ts +273 -0
- package/src/server/desktop-host-shutdown.ts +64 -0
- package/src/server/desktop-host.ts +190 -0
- package/src/server/desktop-server.ts +703 -0
- package/src/server/diffr-config.ts +509 -0
- package/src/server/diffr-languages.ts +97 -0
- package/src/server/global-verb-relay.ts +190 -0
- package/src/server/headless-host.ts +149 -0
- package/src/server/hono-http.ts +162 -0
- package/src/server/http-json.ts +24 -0
- package/src/server/json-review-reporting.ts +174 -0
- package/src/server/process-error-telemetry.ts +174 -0
- package/src/server/review-api-parsers.ts +90 -0
- package/src/server/review-lifecycle-telemetry.ts +73 -0
- package/src/server/review-open-watchdog.ts +46 -0
- package/src/server/review-server-core.ts +290 -0
- package/src/server/structural-comparisons.ts +153 -0
- package/src/server/structural-diff.ts +186 -0
- package/src/server/tutorial-service.ts +241 -0
- package/src/server/ui-telemetry.ts +198 -0
- package/src/server-discovery.ts +95 -0
- package/src/session-markers.ts +132 -0
- package/src/sharing/auth.ts +41 -0
- package/src/sharing/cli.ts +83 -0
- package/src/sharing/client.ts +334 -0
- package/src/sharing/export.ts +195 -0
- package/src/sharing/host.ts +316 -0
- package/src/sharing/import.ts +787 -0
- package/src/sharing/index.ts +16 -0
- package/src/sharing/repository.ts +145 -0
- package/src/sharing/routes.ts +34 -0
- package/src/slug.ts +23 -0
- package/src/software-map-diff-counts.ts +517 -0
- package/src/software-map-model.ts +1147 -0
- package/src/software-map-topology-diff.ts +260 -0
- package/src/source.ts +92 -0
- package/src/startup-trace.ts +232 -0
- package/src/stored-document-migration.ts +151 -0
- package/src/telemetry-clean-text.ts +257 -0
- package/src/telemetry-config.ts +298 -0
- package/src/telemetry-debug-sink.ts +38 -0
- package/src/telemetry.ts +13 -0
- package/src/trace-cli.ts +156 -0
- package/src/trace-storage-cli.ts +509 -0
- package/src/tutorial-conversation.ts +18 -0
- package/src/ui-telemetry-events.ts +765 -0
- package/src/unified-diff.ts +71 -0
- package/src/viewed-coverage.ts +259 -0
- package/src/windows-cli.ts +125 -0
- package/tutorial/document.json +275 -0
- package/tutorial/runtime-manifest.json +12 -0
- package/tutorial/sample-service/package.json +9 -0
- package/tutorial/sample-service/src/api/checkout-api.ts +17 -0
- package/tutorial/sample-service/src/app.ts +26 -0
- package/tutorial/sample-service/src/database/schema.ts +10 -0
- package/tutorial/sample-service/src/fulfillment/fulfillment-queue.ts +15 -0
- package/tutorial/sample-service/src/fulfillment/fulfillment-worker.ts +24 -0
- package/tutorial/sample-service/src/inventory/inventory-service.ts +11 -0
- package/tutorial/sample-service/src/orders/order-service.ts +34 -0
- package/tutorial/sample-service/src/orders/order.ts +21 -0
- package/tutorial/sample-service/src/orders/orders-repository.ts +24 -0
- package/tutorial/sample-service/src/payments/payment-gateway.ts +12 -0
- package/tutorial/sample-service/src/shipping/shipping-gateway.ts +15 -0
- package/tutorial/sample-service/tsconfig.json +12 -0
- package/tutorial/software-map.json +139 -0
- 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 };
|
package/dist/runtime.js
ADDED
|
@@ -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 };
|