hillclimb 0.8.3 → 0.8.4
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/dist/main.js +58 -16
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2349,7 +2349,11 @@ var VOLATILE_KEYS = /* @__PURE__ */ new Set([
|
|
|
2349
2349
|
"wall_time_ms"
|
|
2350
2350
|
]);
|
|
2351
2351
|
function sessionsDir() {
|
|
2352
|
-
|
|
2352
|
+
if (process.env.HILLCLIMB_CODEX_SESSIONS_DIR) {
|
|
2353
|
+
return process.env.HILLCLIMB_CODEX_SESSIONS_DIR;
|
|
2354
|
+
}
|
|
2355
|
+
const codexHome = process.env.CODEX_HOME || path9.join(os3.homedir(), ".codex");
|
|
2356
|
+
return path9.join(codexHome, "sessions");
|
|
2353
2357
|
}
|
|
2354
2358
|
function asRecord(value) {
|
|
2355
2359
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -2519,6 +2523,10 @@ async function findCodexRolloutPath(sessionId) {
|
|
|
2519
2523
|
}
|
|
2520
2524
|
return void 0;
|
|
2521
2525
|
}
|
|
2526
|
+
async function isCodexInternalThread(payload, sessionId) {
|
|
2527
|
+
if (!sessionId || payload.transcript_path) return false;
|
|
2528
|
+
return await findCodexRolloutPath(sessionId) === void 0;
|
|
2529
|
+
}
|
|
2522
2530
|
function commonPrefixLength(a, b) {
|
|
2523
2531
|
const limit = Math.min(a.length, b.length);
|
|
2524
2532
|
let count = 0;
|
|
@@ -11762,14 +11770,20 @@ function getSourceBaseDir(sourceName) {
|
|
|
11762
11770
|
}
|
|
11763
11771
|
}
|
|
11764
11772
|
function archivePathFor(file) {
|
|
11773
|
+
return path11.posix.join(file.sourceName, path11.basename(file.absolutePath));
|
|
11774
|
+
}
|
|
11775
|
+
function legacyArchivePathFor(file) {
|
|
11765
11776
|
const baseDir = getSourceBaseDir(file.sourceName);
|
|
11766
11777
|
const relativePath = file.absolutePath.startsWith(baseDir) ? path11.relative(baseDir, file.absolutePath) : path11.basename(file.absolutePath);
|
|
11767
11778
|
return path11.join(file.sourceName, relativePath);
|
|
11768
11779
|
}
|
|
11769
11780
|
function addGroupToArchive(archive, group, selectedSources) {
|
|
11781
|
+
const used = /* @__PURE__ */ new Set();
|
|
11770
11782
|
for (const file of group.files) {
|
|
11771
11783
|
if (!selectedSources.has(file.sourceName)) continue;
|
|
11772
|
-
|
|
11784
|
+
let archivePath = archivePathFor(file);
|
|
11785
|
+
if (used.has(archivePath)) archivePath = legacyArchivePathFor(file);
|
|
11786
|
+
used.add(archivePath);
|
|
11773
11787
|
if (file.content) {
|
|
11774
11788
|
archive.append(file.content, { name: archivePath });
|
|
11775
11789
|
} else {
|
|
@@ -13065,7 +13079,7 @@ async function runUploadInner(payload) {
|
|
|
13065
13079
|
"warn",
|
|
13066
13080
|
`Skipping upload: missing required hook fields (session_id=${!!sessionId}, transcript_path=${!!payload.transcript_path}, cwd=${!!cwd})`
|
|
13067
13081
|
);
|
|
13068
|
-
return
|
|
13082
|
+
return "skipped";
|
|
13069
13083
|
}
|
|
13070
13084
|
const match = await findProjectForCwd(cwd);
|
|
13071
13085
|
if (!match) {
|
|
@@ -13073,13 +13087,13 @@ async function runUploadInner(payload) {
|
|
|
13073
13087
|
"warn",
|
|
13074
13088
|
`Skipping session ${sessionId}: no hillclimb config for cwd ${cwd}. Run \`npx hillclimb\` in the repo.`
|
|
13075
13089
|
);
|
|
13076
|
-
return
|
|
13090
|
+
return "skipped";
|
|
13077
13091
|
}
|
|
13078
13092
|
const { repoRoot, config } = match;
|
|
13079
13093
|
const sourceTool = await resolveSourceTool(payload, repoRoot);
|
|
13080
13094
|
if (!sourceTool) {
|
|
13081
13095
|
payload.tool = "unknown";
|
|
13082
|
-
return
|
|
13096
|
+
return "skipped";
|
|
13083
13097
|
}
|
|
13084
13098
|
payload.tool = sourceTool;
|
|
13085
13099
|
appendLog(
|
|
@@ -13093,11 +13107,18 @@ async function runUploadInner(payload) {
|
|
|
13093
13107
|
sessionId
|
|
13094
13108
|
);
|
|
13095
13109
|
if (!transcriptPath) {
|
|
13110
|
+
if (sourceTool === "codex") {
|
|
13111
|
+
appendLog(
|
|
13112
|
+
"info",
|
|
13113
|
+
`Skipping session ${sessionId}: Codex internal thread (no transcript_path and no rollout under ~/.codex/sessions); not a user session`
|
|
13114
|
+
);
|
|
13115
|
+
return "internal-thread";
|
|
13116
|
+
}
|
|
13096
13117
|
appendLog(
|
|
13097
13118
|
"warn",
|
|
13098
13119
|
`Skipping upload: missing required hook fields (session_id=true, transcript_path=false, cwd=true)`
|
|
13099
13120
|
);
|
|
13100
|
-
return
|
|
13121
|
+
return "skipped";
|
|
13101
13122
|
}
|
|
13102
13123
|
const transcriptResolved = path15.resolve(transcriptPath);
|
|
13103
13124
|
try {
|
|
@@ -13107,23 +13128,32 @@ async function runUploadInner(payload) {
|
|
|
13107
13128
|
"warn",
|
|
13108
13129
|
`Skipping session ${sessionId}: transcript_path is not a file: ${transcriptResolved}`
|
|
13109
13130
|
);
|
|
13110
|
-
return
|
|
13131
|
+
return "skipped";
|
|
13111
13132
|
}
|
|
13112
13133
|
} catch (err) {
|
|
13134
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
13135
|
+
const missing = err?.code === "ENOENT";
|
|
13136
|
+
if (missing && eventKind2 === "sessionEnd") {
|
|
13137
|
+
appendLog(
|
|
13138
|
+
"info",
|
|
13139
|
+
`Skipping session ${sessionId}: session ended without any turns; transcript was never written (${transcriptResolved})`
|
|
13140
|
+
);
|
|
13141
|
+
return "skipped";
|
|
13142
|
+
}
|
|
13113
13143
|
appendLog(
|
|
13114
13144
|
"warn",
|
|
13115
|
-
`Skipping session ${sessionId}: transcript_path not readable (${transcriptResolved}): ${
|
|
13145
|
+
`Skipping session ${sessionId}: transcript_path not readable (${transcriptResolved}): ${detail}`
|
|
13116
13146
|
);
|
|
13117
|
-
return
|
|
13147
|
+
return "skipped";
|
|
13118
13148
|
}
|
|
13119
13149
|
if (!await hasAssistantMessage(transcriptResolved)) {
|
|
13120
13150
|
appendLog(
|
|
13121
13151
|
"info",
|
|
13122
13152
|
`Skipping session ${sessionId}: transcript contains no assistant messages (nothing to upload).`
|
|
13123
13153
|
);
|
|
13124
|
-
return
|
|
13154
|
+
return "skipped";
|
|
13125
13155
|
}
|
|
13126
|
-
|
|
13156
|
+
const uploaded = await uploadSession({
|
|
13127
13157
|
sessionId,
|
|
13128
13158
|
transcriptPath: transcriptResolved,
|
|
13129
13159
|
repoRoot,
|
|
@@ -13132,6 +13162,7 @@ async function runUploadInner(payload) {
|
|
|
13132
13162
|
eventKind: eventKind2,
|
|
13133
13163
|
recordedAt
|
|
13134
13164
|
});
|
|
13165
|
+
return uploaded ? "uploaded" : "skipped";
|
|
13135
13166
|
}
|
|
13136
13167
|
var AGENT_MAX_UPLOAD_BYTES = 1024 * 1024 * 1024;
|
|
13137
13168
|
var CLI_VERSION = "0.8.0";
|
|
@@ -13351,6 +13382,10 @@ async function uploadSession(args) {
|
|
|
13351
13382
|
sourceName: sourceTool,
|
|
13352
13383
|
absolutePath: transcriptPath
|
|
13353
13384
|
});
|
|
13385
|
+
const legacyTranscriptArchivePath = legacyArchivePathFor({
|
|
13386
|
+
sourceName: sourceTool,
|
|
13387
|
+
absolutePath: transcriptPath
|
|
13388
|
+
});
|
|
13354
13389
|
const alreadySubmitted = prior?.submitted ?? false;
|
|
13355
13390
|
const submitThisUpload = config.autoSubmit && !alreadySubmitted;
|
|
13356
13391
|
if (mode === "meta-refresh" && prior?.contributionId && prior.epochMeta && cursor) {
|
|
@@ -13428,7 +13463,7 @@ async function uploadSession(args) {
|
|
|
13428
13463
|
epochMeta2 = {
|
|
13429
13464
|
transitionKind: "legacy-adopted",
|
|
13430
13465
|
baseline: "legacy-latest-zip",
|
|
13431
|
-
transcriptArchivePath,
|
|
13466
|
+
transcriptArchivePath: legacyTranscriptArchivePath,
|
|
13432
13467
|
rawByteOffset: baseCursor.rawByteOffset,
|
|
13433
13468
|
rawPrefixSha256: baseCursor.rawPrefixSha256
|
|
13434
13469
|
};
|
|
@@ -13444,7 +13479,7 @@ async function uploadSession(args) {
|
|
|
13444
13479
|
epoch: epoch2,
|
|
13445
13480
|
transitionKind: "legacy-adopted",
|
|
13446
13481
|
baseline: "legacy-latest-zip",
|
|
13447
|
-
transcriptArchivePath,
|
|
13482
|
+
transcriptArchivePath: legacyTranscriptArchivePath,
|
|
13448
13483
|
cursor: baseCursor,
|
|
13449
13484
|
recordedAt,
|
|
13450
13485
|
lineage: codexLineage
|
|
@@ -13885,16 +13920,16 @@ async function runUploadWorker() {
|
|
|
13885
13920
|
const toolOverride = process.env[TOOL_ENV_FLAG];
|
|
13886
13921
|
if (toolOverride) payload.tool = toolOverride;
|
|
13887
13922
|
appendLog("info", `worker: payload summary: ${summarizePayload(payload)}`);
|
|
13888
|
-
let
|
|
13923
|
+
let outcome = "skipped";
|
|
13889
13924
|
try {
|
|
13890
|
-
|
|
13925
|
+
outcome = await runUploadInner(payload);
|
|
13891
13926
|
} catch (err) {
|
|
13892
13927
|
appendLog(
|
|
13893
13928
|
"error",
|
|
13894
13929
|
`worker: unexpected error: ${err instanceof Error ? err.stack ?? err.message : String(err)}`
|
|
13895
13930
|
);
|
|
13896
13931
|
} finally {
|
|
13897
|
-
if (
|
|
13932
|
+
if (outcome !== "internal-thread") {
|
|
13898
13933
|
await recordDebugLogCompletion({
|
|
13899
13934
|
kind: "agent",
|
|
13900
13935
|
tool: fallbackSourceTool(payload),
|
|
@@ -16693,6 +16728,13 @@ async function runGitTracesWorker() {
|
|
|
16693
16728
|
);
|
|
16694
16729
|
return;
|
|
16695
16730
|
}
|
|
16731
|
+
if (tool === "codex" && await isCodexInternalThread(payload, resolveHookSessionId(payload))) {
|
|
16732
|
+
appendLog(
|
|
16733
|
+
"info",
|
|
16734
|
+
`git-traces: skipping Codex internal thread ${resolveHookSessionId(payload)} on ${event} (no transcript_path and no rollout on disk; not a user session)`
|
|
16735
|
+
);
|
|
16736
|
+
return;
|
|
16737
|
+
}
|
|
16696
16738
|
try {
|
|
16697
16739
|
await selfHealHook2(payload, tool);
|
|
16698
16740
|
switch (eventKind2) {
|