@evident-ai/cli 3.6.1-dev.98128d1 → 3.6.1-dev.a11d5f5
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/index.js +282 -78
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -723,6 +723,9 @@ async function reportResourceUsage(agentId, authHeader, usage) {
|
|
|
723
723
|
opencode_db_bytes: usage.opencodeDbBytes
|
|
724
724
|
});
|
|
725
725
|
}
|
|
726
|
+
async function reportSessionDeletions(agentId, authHeader, deletions) {
|
|
727
|
+
return postBestEffort(`/runners/${agentId}/session-deletions`, authHeader, { deletions });
|
|
728
|
+
}
|
|
726
729
|
async function getRunnerCredentialVault(agentId, authHeader) {
|
|
727
730
|
const empty = { prefix: null, vaultId: null, source: null };
|
|
728
731
|
try {
|
|
@@ -1176,9 +1179,9 @@ async function claudeUsage() {
|
|
|
1176
1179
|
}
|
|
1177
1180
|
|
|
1178
1181
|
// src/commands/run.ts
|
|
1179
|
-
import { chmodSync as chmodSync3, existsSync as existsSync3, readFileSync as
|
|
1182
|
+
import { chmodSync as chmodSync3, existsSync as existsSync3, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "node:fs";
|
|
1180
1183
|
import { homedir as homedir8 } from "node:os";
|
|
1181
|
-
import { isAbsolute as isAbsolute4, join as
|
|
1184
|
+
import { isAbsolute as isAbsolute4, join as join14, parse, resolve as resolvePath2 } from "node:path";
|
|
1182
1185
|
import chalk7 from "chalk";
|
|
1183
1186
|
|
|
1184
1187
|
// ../../packages/types/src/agents/index.ts
|
|
@@ -1442,7 +1445,7 @@ import ora4 from "ora";
|
|
|
1442
1445
|
import { select as select4 } from "@inquirer/prompts";
|
|
1443
1446
|
|
|
1444
1447
|
// src/lib/telemetry.ts
|
|
1445
|
-
var CLI_VERSION = (true ? "3.6.1-dev.
|
|
1448
|
+
var CLI_VERSION = (true ? "3.6.1-dev.a11d5f5" : void 0) ?? process.env.npm_package_version ?? "unknown";
|
|
1446
1449
|
function getCliVersion() {
|
|
1447
1450
|
return CLI_VERSION;
|
|
1448
1451
|
}
|
|
@@ -2638,6 +2641,122 @@ function isSessionDbRecoveryRecord(value) {
|
|
|
2638
2641
|
);
|
|
2639
2642
|
}
|
|
2640
2643
|
|
|
2644
|
+
// src/lib/opencode/session-deletion-report.ts
|
|
2645
|
+
import { appendFileSync, mkdirSync, readFileSync as readFileSync3, unlinkSync as unlinkSync2, writeFileSync } from "node:fs";
|
|
2646
|
+
import { dirname as dirname4, join as join4 } from "node:path";
|
|
2647
|
+
var SESSION_DELETION_SPOOL_MAX_RECORDS = 1e3;
|
|
2648
|
+
var MAX_DIAGNOSTIC_LENGTH = 200;
|
|
2649
|
+
function sessionDeletionReportPath(homeDir, env) {
|
|
2650
|
+
const override = env.EVIDENT_SESSION_DELETION_REPORT?.trim();
|
|
2651
|
+
return override || join4(homeDir, ".local", "state", "evident", "session-deletions.jsonl");
|
|
2652
|
+
}
|
|
2653
|
+
function appendSessionDeletionRecords(path, records) {
|
|
2654
|
+
if (records.length === 0) return 0;
|
|
2655
|
+
mkdirSync(dirname4(path), { recursive: true });
|
|
2656
|
+
const current = readSessionDeletionRecords(path);
|
|
2657
|
+
if (current.readError !== null) {
|
|
2658
|
+
throw new Error(`cannot enforce the spool limit after reading ${path}: ${current.readError}`);
|
|
2659
|
+
}
|
|
2660
|
+
const combined = [...current.records, ...records];
|
|
2661
|
+
const kept = combined.slice(-SESSION_DELETION_SPOOL_MAX_RECORDS);
|
|
2662
|
+
const dropped = combined.length - kept.length;
|
|
2663
|
+
if (dropped > 0) {
|
|
2664
|
+
writeFileSync(path, `${kept.map((record) => JSON.stringify(record)).join("\n")}
|
|
2665
|
+
`, "utf8");
|
|
2666
|
+
} else {
|
|
2667
|
+
appendFileSync(path, `${records.map((record) => JSON.stringify(record)).join("\n")}
|
|
2668
|
+
`, "utf8");
|
|
2669
|
+
}
|
|
2670
|
+
return dropped;
|
|
2671
|
+
}
|
|
2672
|
+
function readSessionDeletionRecords(path) {
|
|
2673
|
+
let content;
|
|
2674
|
+
try {
|
|
2675
|
+
content = readFileSync3(path, "utf8");
|
|
2676
|
+
} catch (error2) {
|
|
2677
|
+
if (isMissingFile(error2)) return { records: [], skippedLines: 0, readError: null };
|
|
2678
|
+
const readError = boundedError(error2);
|
|
2679
|
+
console.error(`[session-deletion-report] could not read ${path}: ${readError}`);
|
|
2680
|
+
return { records: [], skippedLines: 0, readError };
|
|
2681
|
+
}
|
|
2682
|
+
let skippedLines = 0;
|
|
2683
|
+
const records = content.split("\n").flatMap((line) => {
|
|
2684
|
+
if (!line.trim()) return [];
|
|
2685
|
+
const record = parseRecord(line, path);
|
|
2686
|
+
if (record) return [record];
|
|
2687
|
+
skippedLines++;
|
|
2688
|
+
return [];
|
|
2689
|
+
});
|
|
2690
|
+
return { records, skippedLines, readError: null };
|
|
2691
|
+
}
|
|
2692
|
+
function removeDeliveredSessionDeletionRecords(path, delivered) {
|
|
2693
|
+
let content;
|
|
2694
|
+
try {
|
|
2695
|
+
content = readFileSync3(path, "utf8");
|
|
2696
|
+
} catch (error2) {
|
|
2697
|
+
if (isMissingFile(error2)) return;
|
|
2698
|
+
console.error(
|
|
2699
|
+
`[session-deletion-report] could not read ${path} before removing delivered records: ${boundedError(error2)}`
|
|
2700
|
+
);
|
|
2701
|
+
throw error2;
|
|
2702
|
+
}
|
|
2703
|
+
const toRemove = /* @__PURE__ */ new Map();
|
|
2704
|
+
for (const record of delivered) {
|
|
2705
|
+
toRemove.set(record.opencode_session_id, (toRemove.get(record.opencode_session_id) ?? 0) + 1);
|
|
2706
|
+
}
|
|
2707
|
+
const remaining = [];
|
|
2708
|
+
for (const line of content.split("\n")) {
|
|
2709
|
+
if (!line.trim()) continue;
|
|
2710
|
+
const record = parseRecord(line, path);
|
|
2711
|
+
const count = record ? toRemove.get(record.opencode_session_id) ?? 0 : 0;
|
|
2712
|
+
if (record && count > 0) {
|
|
2713
|
+
if (count === 1) toRemove.delete(record.opencode_session_id);
|
|
2714
|
+
else toRemove.set(record.opencode_session_id, count - 1);
|
|
2715
|
+
} else {
|
|
2716
|
+
remaining.push(line);
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2719
|
+
try {
|
|
2720
|
+
if (remaining.length === 0) unlinkSync2(path);
|
|
2721
|
+
else writeFileSync(path, `${remaining.join("\n")}
|
|
2722
|
+
`, "utf8");
|
|
2723
|
+
} catch (error2) {
|
|
2724
|
+
if (isMissingFile(error2)) return;
|
|
2725
|
+
console.error(
|
|
2726
|
+
`[session-deletion-report] could not write ${path} after removing delivered records: ${boundedError(error2)}`
|
|
2727
|
+
);
|
|
2728
|
+
throw error2;
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
function parseRecord(line, path) {
|
|
2732
|
+
try {
|
|
2733
|
+
const value = JSON.parse(line);
|
|
2734
|
+
if (isSessionDeletionRecord(value)) return value;
|
|
2735
|
+
console.error(`[session-deletion-report] skipped malformed record in ${path}: invalid shape`);
|
|
2736
|
+
return null;
|
|
2737
|
+
} catch (error2) {
|
|
2738
|
+
console.error(
|
|
2739
|
+
`[session-deletion-report] skipped malformed record in ${path}: ${boundedError(error2)}`
|
|
2740
|
+
);
|
|
2741
|
+
return null;
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
function isSessionDeletionRecord(value) {
|
|
2745
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
2746
|
+
const record = value;
|
|
2747
|
+
const policy = record.policy;
|
|
2748
|
+
if (!policy || typeof policy !== "object" || Array.isArray(policy)) return false;
|
|
2749
|
+
const fields = policy;
|
|
2750
|
+
return typeof record.opencode_session_id === "string" && record.opencode_session_id.length > 0 && typeof record.deleted_at === "string" && record.reason === "auto_cleanup" && (fields.max_age_ms === null || typeof fields.max_age_ms === "number") && (fields.max_count === null || typeof fields.max_count === "number") && (fields.last_activity_at === null || typeof fields.last_activity_at === "string");
|
|
2751
|
+
}
|
|
2752
|
+
function isMissingFile(error2) {
|
|
2753
|
+
return error2 instanceof Error && "code" in error2 && error2.code === "ENOENT";
|
|
2754
|
+
}
|
|
2755
|
+
function boundedError(error2) {
|
|
2756
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
2757
|
+
return message.slice(0, MAX_DIAGNOSTIC_LENGTH);
|
|
2758
|
+
}
|
|
2759
|
+
|
|
2641
2760
|
// src/lib/opencode/auth.ts
|
|
2642
2761
|
function buildOpenCodeBasicAuthHeader(password) {
|
|
2643
2762
|
return `Basic ${Buffer.from(["opencode", password].join(":")).toString("base64")}`;
|
|
@@ -4537,13 +4656,13 @@ async function readV2SessionErrorStream(client, options) {
|
|
|
4537
4656
|
}
|
|
4538
4657
|
|
|
4539
4658
|
// src/lib/opencode/credential-import-v2.ts
|
|
4540
|
-
import { readFileSync as
|
|
4541
|
-
import { join as
|
|
4659
|
+
import { readFileSync as readFileSync5 } from "node:fs";
|
|
4660
|
+
import { join as join6 } from "node:path";
|
|
4542
4661
|
|
|
4543
4662
|
// src/lib/openai-usage.ts
|
|
4544
|
-
import { readFileSync as
|
|
4663
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
4545
4664
|
import { homedir as homedir3 } from "node:os";
|
|
4546
|
-
import { join as
|
|
4665
|
+
import { join as join5 } from "node:path";
|
|
4547
4666
|
var CODEX_RESPONSES_URL = "https://chatgpt.com/backend-api/codex/responses";
|
|
4548
4667
|
var OPENCODE_AUTH_SEGMENTS = [".local", "share", "opencode", "auth.json"];
|
|
4549
4668
|
var OpenAiUsageError = class extends Error {
|
|
@@ -4557,7 +4676,7 @@ function isLocalCredentialProblem2(err) {
|
|
|
4557
4676
|
}
|
|
4558
4677
|
function readOpenCodeChatGptCredentials() {
|
|
4559
4678
|
try {
|
|
4560
|
-
const raw =
|
|
4679
|
+
const raw = readFileSync4(join5(homedir3(), ...OPENCODE_AUTH_SEGMENTS), "utf-8");
|
|
4561
4680
|
let parsed;
|
|
4562
4681
|
try {
|
|
4563
4682
|
parsed = JSON.parse(raw);
|
|
@@ -4789,7 +4908,7 @@ function emptyResult(unsupported = [], outcome = "completed") {
|
|
|
4789
4908
|
}
|
|
4790
4909
|
function readOpenCodeCredentials(homeDir, log3) {
|
|
4791
4910
|
try {
|
|
4792
|
-
const raw =
|
|
4911
|
+
const raw = readFileSync5(join6(homeDir, ...OPENCODE_AUTH_SEGMENTS), "utf8");
|
|
4793
4912
|
let parsed;
|
|
4794
4913
|
try {
|
|
4795
4914
|
parsed = JSON.parse(raw);
|
|
@@ -4989,9 +5108,9 @@ async function importOpenCodeV2Credentials({
|
|
|
4989
5108
|
|
|
4990
5109
|
// src/lib/opencode/session-db-boot.ts
|
|
4991
5110
|
import { spawn as spawn2 } from "node:child_process";
|
|
4992
|
-
import { mkdirSync, statSync as statSync3, unlinkSync as
|
|
5111
|
+
import { mkdirSync as mkdirSync2, statSync as statSync3, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
|
4993
5112
|
import { homedir as homedir4 } from "node:os";
|
|
4994
|
-
import { dirname as
|
|
5113
|
+
import { dirname as dirname5, resolve as resolvePath } from "node:path";
|
|
4995
5114
|
|
|
4996
5115
|
// src/lib/runner-synchroniser.ts
|
|
4997
5116
|
import { spawn } from "node:child_process";
|
|
@@ -5107,7 +5226,7 @@ function reportRecord(stage, outcome, reason, litestreamExitCode, options) {
|
|
|
5107
5226
|
function clearMarker(options) {
|
|
5108
5227
|
if (!options.noReplicateMarker) return;
|
|
5109
5228
|
try {
|
|
5110
|
-
|
|
5229
|
+
unlinkSync3(options.noReplicateMarker);
|
|
5111
5230
|
} catch (error2) {
|
|
5112
5231
|
if (error2 instanceof Error && "code" in error2 && error2.code === "ENOENT") return;
|
|
5113
5232
|
options.log(
|
|
@@ -5119,8 +5238,8 @@ function clearMarker(options) {
|
|
|
5119
5238
|
function markNoReplicate(options, message) {
|
|
5120
5239
|
if (options.noReplicateMarker) {
|
|
5121
5240
|
try {
|
|
5122
|
-
|
|
5123
|
-
|
|
5241
|
+
mkdirSync2(dirname5(options.noReplicateMarker), { recursive: true });
|
|
5242
|
+
writeFileSync2(options.noReplicateMarker, "");
|
|
5124
5243
|
} catch (error2) {
|
|
5125
5244
|
options.log(
|
|
5126
5245
|
`Could not write session-DB no-replicate marker ${options.noReplicateMarker}: ${error2 instanceof Error ? error2.message : String(error2)}`,
|
|
@@ -5133,7 +5252,7 @@ function markNoReplicate(options, message) {
|
|
|
5133
5252
|
function discardSessionDbDebris(options) {
|
|
5134
5253
|
for (const path of [options.dbPath, `${options.dbPath}-wal`, `${options.dbPath}-shm`]) {
|
|
5135
5254
|
try {
|
|
5136
|
-
|
|
5255
|
+
unlinkSync3(path);
|
|
5137
5256
|
} catch (error2) {
|
|
5138
5257
|
if (error2 instanceof Error && "code" in error2 && error2.code === "ENOENT") continue;
|
|
5139
5258
|
options.log(
|
|
@@ -5274,8 +5393,8 @@ async function ensureLitestreamConfig(options, env) {
|
|
|
5274
5393
|
return null;
|
|
5275
5394
|
}
|
|
5276
5395
|
try {
|
|
5277
|
-
|
|
5278
|
-
|
|
5396
|
+
mkdirSync2(dirname5(configPath), { recursive: true });
|
|
5397
|
+
writeFileSync2(configPath, rendered.stdout);
|
|
5279
5398
|
} catch (error2) {
|
|
5280
5399
|
options.log(
|
|
5281
5400
|
`Could not write ${configPath}: ${error2 instanceof Error ? error2.message : String(error2)}`,
|
|
@@ -5540,8 +5659,8 @@ async function restoreAndVerifySessionDb(options) {
|
|
|
5540
5659
|
|
|
5541
5660
|
// src/lib/opencode/session-db-provenance.ts
|
|
5542
5661
|
import { createRequire } from "node:module";
|
|
5543
|
-
import { mkdirSync as
|
|
5544
|
-
import { dirname as
|
|
5662
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync3 } from "node:fs";
|
|
5663
|
+
import { dirname as dirname6, join as join7 } from "node:path";
|
|
5545
5664
|
var require2 = createRequire(import.meta.url);
|
|
5546
5665
|
function readSessionDbMigrationIds(dbPath) {
|
|
5547
5666
|
let db;
|
|
@@ -5578,12 +5697,12 @@ function readSessionDbMigrationIds(dbPath) {
|
|
|
5578
5697
|
}
|
|
5579
5698
|
function sessionDbProvenanceStatePath(homeDir, env) {
|
|
5580
5699
|
const override = env.EVIDENT_SESSION_DB_PROVENANCE_STATE?.trim();
|
|
5581
|
-
return override ||
|
|
5700
|
+
return override || join7(homeDir, ".local", "state", "evident", "session-db-provenance.json");
|
|
5582
5701
|
}
|
|
5583
5702
|
function loadSessionDbProvenanceState(path) {
|
|
5584
5703
|
let value;
|
|
5585
5704
|
try {
|
|
5586
|
-
value = JSON.parse(
|
|
5705
|
+
value = JSON.parse(readFileSync6(path, "utf8"));
|
|
5587
5706
|
} catch (error2) {
|
|
5588
5707
|
if (error2 instanceof Error && "code" in error2 && error2.code === "ENOENT") return {};
|
|
5589
5708
|
console.error(
|
|
@@ -5607,8 +5726,8 @@ function loadSessionDbProvenanceState(path) {
|
|
|
5607
5726
|
}
|
|
5608
5727
|
function saveSessionDbProvenanceState(path, state) {
|
|
5609
5728
|
try {
|
|
5610
|
-
|
|
5611
|
-
|
|
5729
|
+
mkdirSync3(dirname6(path), { recursive: true });
|
|
5730
|
+
writeFileSync3(path, `${JSON.stringify(state, null, 2)}
|
|
5612
5731
|
`, "utf8");
|
|
5613
5732
|
} catch (error2) {
|
|
5614
5733
|
console.error(
|
|
@@ -6256,15 +6375,15 @@ function resolveSessionCleanupConfig(flags, env = process.env) {
|
|
|
6256
6375
|
|
|
6257
6376
|
// src/lib/opencode/session-db-size.ts
|
|
6258
6377
|
import { statSync as statSync4 } from "node:fs";
|
|
6259
|
-
import { join as
|
|
6378
|
+
import { join as join8 } from "node:path";
|
|
6260
6379
|
var LARGE_DB_THRESHOLD_BYTES = 268435456;
|
|
6261
6380
|
function statSessionDbBytes(homeDir) {
|
|
6262
|
-
const dbPath =
|
|
6381
|
+
const dbPath = join8(homeDir, ".local", "share", "opencode", "opencode.db");
|
|
6263
6382
|
try {
|
|
6264
6383
|
return statSync4(dbPath).size;
|
|
6265
6384
|
} catch (err) {
|
|
6266
|
-
const
|
|
6267
|
-
if (!
|
|
6385
|
+
const isMissingFile2 = err instanceof Error && "code" in err && err.code === "ENOENT";
|
|
6386
|
+
if (!isMissingFile2) {
|
|
6268
6387
|
console.error(
|
|
6269
6388
|
`[statSessionDbBytes] could not stat ${dbPath}: ${err instanceof Error ? err.message : String(err)}`
|
|
6270
6389
|
);
|
|
@@ -6289,12 +6408,12 @@ function buildSessionStoreSizeWarning(input) {
|
|
|
6289
6408
|
// src/lib/opencode/log-tail.ts
|
|
6290
6409
|
import { statSync as statSync5 } from "node:fs";
|
|
6291
6410
|
import { homedir as homedir5 } from "node:os";
|
|
6292
|
-
import { join as
|
|
6411
|
+
import { join as join9 } from "node:path";
|
|
6293
6412
|
import { open as open2, stat } from "node:fs/promises";
|
|
6294
6413
|
var DEFAULT_POLL_INTERVAL_MS = 1e3;
|
|
6295
6414
|
function resolveOpenCodeLogPath(homeDir = homedir5(), env = process.env) {
|
|
6296
|
-
const dataDir = env.XDG_DATA_HOME ||
|
|
6297
|
-
return
|
|
6415
|
+
const dataDir = env.XDG_DATA_HOME || join9(homeDir, ".local", "share");
|
|
6416
|
+
return join9(dataDir, "opencode", "log", "opencode.log");
|
|
6298
6417
|
}
|
|
6299
6418
|
function isEnoent(error2) {
|
|
6300
6419
|
return error2?.code === "ENOENT";
|
|
@@ -6961,10 +7080,10 @@ var RunnerConnection = class _RunnerConnection {
|
|
|
6961
7080
|
};
|
|
6962
7081
|
|
|
6963
7082
|
// src/lib/tunnel/ready-marker.ts
|
|
6964
|
-
import { writeFileSync as
|
|
7083
|
+
import { writeFileSync as writeFileSync4 } from "node:fs";
|
|
6965
7084
|
function writeTunnelReadyMarker(path, agentId) {
|
|
6966
7085
|
try {
|
|
6967
|
-
|
|
7086
|
+
writeFileSync4(path, `${agentId}
|
|
6968
7087
|
`);
|
|
6969
7088
|
return { ok: true };
|
|
6970
7089
|
} catch (error2) {
|
|
@@ -6989,7 +7108,7 @@ async function stopSessionDbReplication(child, timeoutMs) {
|
|
|
6989
7108
|
}
|
|
6990
7109
|
|
|
6991
7110
|
// src/lib/process-liveness.ts
|
|
6992
|
-
import { readFileSync as
|
|
7111
|
+
import { readFileSync as readFileSync7 } from "node:fs";
|
|
6993
7112
|
function isProcessAlive(pid) {
|
|
6994
7113
|
try {
|
|
6995
7114
|
process.kill(pid, 0);
|
|
@@ -7004,7 +7123,7 @@ function isProcessAlive(pid) {
|
|
|
7004
7123
|
}
|
|
7005
7124
|
if (process.platform !== "linux") return true;
|
|
7006
7125
|
try {
|
|
7007
|
-
const status2 =
|
|
7126
|
+
const status2 = readFileSync7(`/proc/${pid}/status`, "utf8");
|
|
7008
7127
|
return !/^State:\s+Z(?:\s|$)/m.test(status2);
|
|
7009
7128
|
} catch (error2) {
|
|
7010
7129
|
console.error(
|
|
@@ -7363,12 +7482,12 @@ function createSessionStoreHealth(options = {}) {
|
|
|
7363
7482
|
import { homedir as homedir6 } from "node:os";
|
|
7364
7483
|
|
|
7365
7484
|
// src/lib/runner-file-sync.ts
|
|
7366
|
-
import { join as
|
|
7485
|
+
import { join as join11 } from "node:path";
|
|
7367
7486
|
|
|
7368
7487
|
// src/lib/file-push.ts
|
|
7369
7488
|
import { randomUUID } from "node:crypto";
|
|
7370
7489
|
import { chmod, mkdir, open as open3, realpath, rename, unlink } from "node:fs/promises";
|
|
7371
|
-
import { basename as basename2, dirname as
|
|
7490
|
+
import { basename as basename2, dirname as dirname7, isAbsolute as isAbsolute2, join as join10, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
|
|
7372
7491
|
var FILE_MODE = 384;
|
|
7373
7492
|
var DIRECTORY_MODE = 448;
|
|
7374
7493
|
async function writePushedFile(request3) {
|
|
@@ -7399,9 +7518,9 @@ async function writePushedFile(request3) {
|
|
|
7399
7518
|
}
|
|
7400
7519
|
try {
|
|
7401
7520
|
const { existingAncestor, missingSegments } = await resolveNearestExistingAncestor(
|
|
7402
|
-
|
|
7521
|
+
dirname7(candidate)
|
|
7403
7522
|
);
|
|
7404
|
-
const realTarget =
|
|
7523
|
+
const realTarget = join10(existingAncestor, ...missingSegments, basename2(candidate));
|
|
7405
7524
|
const allowedDirectory = await findContainingAllowedDirectory(allowedDirectories, realTarget);
|
|
7406
7525
|
if (allowedDirectory === null) {
|
|
7407
7526
|
return refuse("path_not_allowed", "The runner does not allow writing to that location.", {
|
|
@@ -7411,8 +7530,8 @@ async function writePushedFile(request3) {
|
|
|
7411
7530
|
}
|
|
7412
7531
|
if (missingSegments.length > 0) {
|
|
7413
7532
|
await createMissingDirectories(existingAncestor, missingSegments);
|
|
7414
|
-
const realParent = await realpath(
|
|
7415
|
-
if (realParent !==
|
|
7533
|
+
const realParent = await realpath(dirname7(realTarget));
|
|
7534
|
+
if (realParent !== dirname7(realTarget) || !contains(allowedDirectory, realTarget)) {
|
|
7416
7535
|
return refuse("path_not_allowed", "The runner does not allow writing to that location.", {
|
|
7417
7536
|
path: realTarget,
|
|
7418
7537
|
bytes,
|
|
@@ -7437,7 +7556,7 @@ function expandAndValidate(requestedPath, homeDir) {
|
|
|
7437
7556
|
if (requestedPath.trim() === "" || requestedPath.includes("\0")) {
|
|
7438
7557
|
return null;
|
|
7439
7558
|
}
|
|
7440
|
-
const expanded = requestedPath === "~" ? homeDir : requestedPath.startsWith("~/") ?
|
|
7559
|
+
const expanded = requestedPath === "~" ? homeDir : requestedPath.startsWith("~/") ? join10(homeDir, requestedPath.slice(2)) : requestedPath;
|
|
7441
7560
|
if (expanded.split(/[/\\]/).includes("..")) {
|
|
7442
7561
|
return null;
|
|
7443
7562
|
}
|
|
@@ -7455,7 +7574,7 @@ async function resolveNearestExistingAncestor(directory) {
|
|
|
7455
7574
|
try {
|
|
7456
7575
|
return { existingAncestor: await realpath(current), missingSegments };
|
|
7457
7576
|
} catch (err) {
|
|
7458
|
-
const parent =
|
|
7577
|
+
const parent = dirname7(current);
|
|
7459
7578
|
if (err.code !== "ENOENT" || parent === current) {
|
|
7460
7579
|
throw err;
|
|
7461
7580
|
}
|
|
@@ -7510,13 +7629,13 @@ function contains(realDirectory, realTarget) {
|
|
|
7510
7629
|
async function createMissingDirectories(existingAncestor, missingSegments) {
|
|
7511
7630
|
let current = existingAncestor;
|
|
7512
7631
|
for (const segment of missingSegments) {
|
|
7513
|
-
current =
|
|
7632
|
+
current = join10(current, segment);
|
|
7514
7633
|
await mkdir(current, { recursive: true, mode: DIRECTORY_MODE });
|
|
7515
7634
|
await chmod(current, DIRECTORY_MODE);
|
|
7516
7635
|
}
|
|
7517
7636
|
}
|
|
7518
7637
|
async function writeAtomically(realTarget, content) {
|
|
7519
|
-
const temporaryPath =
|
|
7638
|
+
const temporaryPath = join10(dirname7(realTarget), `.evident-push-${randomUUID()}.tmp`);
|
|
7520
7639
|
let handle;
|
|
7521
7640
|
try {
|
|
7522
7641
|
handle = await open3(temporaryPath, "wx", FILE_MODE);
|
|
@@ -7646,12 +7765,12 @@ var NOT_APPLIED = {
|
|
|
7646
7765
|
opencodeAuthApplied: false
|
|
7647
7766
|
};
|
|
7648
7767
|
function isClaudeCredentialPath(requestedPath, homeDir) {
|
|
7649
|
-
const expanded = requestedPath === "~" ? homeDir : requestedPath.startsWith("~/") ?
|
|
7650
|
-
return expanded ===
|
|
7768
|
+
const expanded = requestedPath === "~" ? homeDir : requestedPath.startsWith("~/") ? join11(homeDir, requestedPath.slice(2)) : requestedPath;
|
|
7769
|
+
return expanded === join11(homeDir, ...CLAUDE_CREDENTIALS_SEGMENTS);
|
|
7651
7770
|
}
|
|
7652
7771
|
function isOpenCodeAuthPath(requestedPath, homeDir) {
|
|
7653
|
-
const expanded = requestedPath === "~" ? homeDir : requestedPath.startsWith("~/") ?
|
|
7654
|
-
return expanded ===
|
|
7772
|
+
const expanded = requestedPath === "~" ? homeDir : requestedPath.startsWith("~/") ? join11(homeDir, requestedPath.slice(2)) : requestedPath;
|
|
7773
|
+
return expanded === join11(homeDir, ...OPENCODE_AUTH_SEGMENTS);
|
|
7655
7774
|
}
|
|
7656
7775
|
async function applyOne(options, file) {
|
|
7657
7776
|
const label = `${file.id.slice(0, 8)} (${file.path})`;
|
|
@@ -13930,7 +14049,7 @@ Port ${port} is already in use.`));
|
|
|
13930
14049
|
}
|
|
13931
14050
|
|
|
13932
14051
|
// src/lib/runner-credentials.ts
|
|
13933
|
-
import { chmodSync as chmodSync2, writeFileSync as
|
|
14052
|
+
import { chmodSync as chmodSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
13934
14053
|
import { spawn as spawn5 } from "node:child_process";
|
|
13935
14054
|
var RUNNER_SECRET_FETCH_TIMEOUT_MS = 6e4;
|
|
13936
14055
|
var CREDENTIAL_RESTORE_TIMEOUT_MS = 6e4;
|
|
@@ -14173,8 +14292,8 @@ async function configureGitHubAccess({ env, log: log3 }) {
|
|
|
14173
14292
|
}
|
|
14174
14293
|
try {
|
|
14175
14294
|
env.GIT_CONFIG_GLOBAL = GIT_CONFIG_GLOBAL;
|
|
14176
|
-
|
|
14177
|
-
|
|
14295
|
+
writeFileSync5(GIT_CONFIG_GLOBAL, "");
|
|
14296
|
+
writeFileSync5(GIT_CREDENTIAL_HELPER, GIT_CREDENTIAL_HELPER_CONTENT, { mode: 448 });
|
|
14178
14297
|
chmodSync2(GIT_CREDENTIAL_HELPER, 448);
|
|
14179
14298
|
const config = [
|
|
14180
14299
|
["user.name", env.GIT_USER_NAME ?? "evident-bot"],
|
|
@@ -14207,7 +14326,7 @@ async function configureGitHubAccess({ env, log: log3 }) {
|
|
|
14207
14326
|
// src/lib/opencode/config-overlay.ts
|
|
14208
14327
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
14209
14328
|
import { copyFileSync, existsSync as existsSync2, statSync as statSync6 } from "node:fs";
|
|
14210
|
-
import { isAbsolute as isAbsolute3, join as
|
|
14329
|
+
import { isAbsolute as isAbsolute3, join as join12, resolve as resolve4 } from "node:path";
|
|
14211
14330
|
function parseConfigContent(content) {
|
|
14212
14331
|
if (!content?.trim()) return {};
|
|
14213
14332
|
const parsed = JSON.parse(content);
|
|
@@ -14237,7 +14356,7 @@ function applyRunnerOpenCodeConfig({
|
|
|
14237
14356
|
return;
|
|
14238
14357
|
}
|
|
14239
14358
|
const source = isAbsolute3(overlayPath) ? overlayPath : resolve4(cwd, overlayPath);
|
|
14240
|
-
const target = isFile(
|
|
14359
|
+
const target = isFile(join12(cwd, "opencode.jsonc")) ? "opencode.jsonc" : "opencode.json";
|
|
14241
14360
|
if (!isFile(source)) {
|
|
14242
14361
|
log3(
|
|
14243
14362
|
`RUNNER-OPENCODE-CONFIG-MISSING: ${source} is not a file; headless turns will wedge on the first external-directory permission prompt (#563)`,
|
|
@@ -14245,7 +14364,7 @@ function applyRunnerOpenCodeConfig({
|
|
|
14245
14364
|
);
|
|
14246
14365
|
return;
|
|
14247
14366
|
}
|
|
14248
|
-
copyFileSync(source,
|
|
14367
|
+
copyFileSync(source, join12(cwd, target));
|
|
14249
14368
|
try {
|
|
14250
14369
|
execFileSync2("git", ["-C", cwd, "update-index", "--skip-worktree", target], {
|
|
14251
14370
|
stdio: "ignore"
|
|
@@ -14254,13 +14373,13 @@ function applyRunnerOpenCodeConfig({
|
|
|
14254
14373
|
const detail = error2 instanceof Error ? error2.message : String(error2);
|
|
14255
14374
|
log3(`could not mark ${target} skip-worktree: ${detail}; it may show as a local change`, "warn");
|
|
14256
14375
|
}
|
|
14257
|
-
log3(`Applied runner OpenCode config ${source} to ${
|
|
14376
|
+
log3(`Applied runner OpenCode config ${source} to ${join12(cwd, target)}`);
|
|
14258
14377
|
}
|
|
14259
14378
|
|
|
14260
14379
|
// src/lib/opencode/runtime-provenance.ts
|
|
14261
|
-
import { readFileSync as
|
|
14380
|
+
import { readFileSync as readFileSync8, readdirSync } from "node:fs";
|
|
14262
14381
|
import { homedir as homedir7 } from "node:os";
|
|
14263
|
-
import { join as
|
|
14382
|
+
import { join as join13 } from "node:path";
|
|
14264
14383
|
var PACKAGE_NAME = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/i;
|
|
14265
14384
|
var REGISTRY_SPEC = /^[a-z0-9.*+^~<>=|-]+$/i;
|
|
14266
14385
|
function errorKind(error2) {
|
|
@@ -14328,7 +14447,7 @@ function parseJsonc(value) {
|
|
|
14328
14447
|
return JSON.parse(output);
|
|
14329
14448
|
}
|
|
14330
14449
|
function openCodeCacheRoot(env = process.env, homeDir = homedir7()) {
|
|
14331
|
-
return
|
|
14450
|
+
return join13(env.XDG_CACHE_HOME ?? join13(homeDir, ".cache"), "opencode");
|
|
14332
14451
|
}
|
|
14333
14452
|
function readConfiguredPluginSpecs({
|
|
14334
14453
|
cwd = process.cwd(),
|
|
@@ -14337,10 +14456,10 @@ function readConfiguredPluginSpecs({
|
|
|
14337
14456
|
let config;
|
|
14338
14457
|
try {
|
|
14339
14458
|
try {
|
|
14340
|
-
config = parseJsonc(
|
|
14459
|
+
config = parseJsonc(readFileSync8(join13(cwd, "opencode.jsonc"), "utf8"));
|
|
14341
14460
|
} catch (error2) {
|
|
14342
14461
|
if (!("code" in Object(error2)) || Object(error2).code !== "ENOENT") throw error2;
|
|
14343
|
-
config = parseJsonc(
|
|
14462
|
+
config = parseJsonc(readFileSync8(join13(cwd, "opencode.json"), "utf8"));
|
|
14344
14463
|
}
|
|
14345
14464
|
} catch (error2) {
|
|
14346
14465
|
log3(`Could not read OpenCode plugin configuration: ${errorKind(error2)}`);
|
|
@@ -14368,7 +14487,7 @@ function resolveInstalledPluginVersions({
|
|
|
14368
14487
|
homeDir = homedir7(),
|
|
14369
14488
|
log: log3
|
|
14370
14489
|
}) {
|
|
14371
|
-
const packagesRoot =
|
|
14490
|
+
const packagesRoot = join13(cacheRoot ?? openCodeCacheRoot(env, homeDir), "packages");
|
|
14372
14491
|
let directories;
|
|
14373
14492
|
try {
|
|
14374
14493
|
directories = readdirSync(packagesRoot, { withFileTypes: true });
|
|
@@ -14389,8 +14508,8 @@ function resolveInstalledPluginVersions({
|
|
|
14389
14508
|
let resolvedVersion = null;
|
|
14390
14509
|
try {
|
|
14391
14510
|
const packageJson = JSON.parse(
|
|
14392
|
-
|
|
14393
|
-
|
|
14511
|
+
readFileSync8(
|
|
14512
|
+
join13(packagesRoot, directory.name, "node_modules", parsed.name, "package.json"),
|
|
14394
14513
|
"utf8"
|
|
14395
14514
|
)
|
|
14396
14515
|
);
|
|
@@ -14411,7 +14530,7 @@ function resolveInstalledPluginVersions({
|
|
|
14411
14530
|
}
|
|
14412
14531
|
|
|
14413
14532
|
// src/lib/credential-sync.ts
|
|
14414
|
-
import { renameSync, writeFileSync as
|
|
14533
|
+
import { renameSync, writeFileSync as writeFileSync6 } from "node:fs";
|
|
14415
14534
|
var CREDENTIAL_SYNC_TICK_TIMEOUT_MS = 3e4;
|
|
14416
14535
|
var CREDENTIAL_FLUSH_DEADLINE_MS = 8e3;
|
|
14417
14536
|
var CREDENTIAL_FLUSH_ABORT_GRACE_MS = 500;
|
|
@@ -14445,7 +14564,7 @@ function writeMarker(markerPath, outcomes, log3) {
|
|
|
14445
14564
|
`;
|
|
14446
14565
|
const temporaryPath = `${markerPath}.tmp`;
|
|
14447
14566
|
try {
|
|
14448
|
-
|
|
14567
|
+
writeFileSync6(temporaryPath, body, { mode: 384 });
|
|
14449
14568
|
renameSync(temporaryPath, markerPath);
|
|
14450
14569
|
} catch (error2) {
|
|
14451
14570
|
log3(`CREDENTIAL-FLUSH-MARKER-UNWRITABLE: ${markerPath}: ${errorMessage2(error2)}`, "warn");
|
|
@@ -14934,7 +15053,7 @@ function resolveFileSyncDirectories(raw, homeDir) {
|
|
|
14934
15053
|
if (trimmed === "") {
|
|
14935
15054
|
throw new Error("--enable-file-sync-to requires a directory path (got an empty value)");
|
|
14936
15055
|
}
|
|
14937
|
-
const expanded = trimmed === "~" ? homeDir : trimmed.startsWith("~/") ?
|
|
15056
|
+
const expanded = trimmed === "~" ? homeDir : trimmed.startsWith("~/") ? join14(homeDir, trimmed.slice(2)) : trimmed;
|
|
14938
15057
|
if (!isAbsolute4(expanded)) {
|
|
14939
15058
|
throw new Error(`--enable-file-sync-to requires an absolute directory path; got "${entry}"`);
|
|
14940
15059
|
}
|
|
@@ -15590,7 +15709,7 @@ function shouldWarnForReclaimSkip(reason) {
|
|
|
15590
15709
|
return major > 22 || major === 22 && (minor > 13 || minor === 13 && patch >= 0);
|
|
15591
15710
|
}
|
|
15592
15711
|
function sessionDbPath() {
|
|
15593
|
-
return
|
|
15712
|
+
return join14(homedir8(), ".local", "share", "opencode", "opencode.db");
|
|
15594
15713
|
}
|
|
15595
15714
|
function logSessionCleanupActivity(state, phase, entry) {
|
|
15596
15715
|
logActivity(state, {
|
|
@@ -15599,6 +15718,47 @@ function logSessionCleanupActivity(state, phase, entry) {
|
|
|
15599
15718
|
metadata: { ...entry.metadata, phase }
|
|
15600
15719
|
});
|
|
15601
15720
|
}
|
|
15721
|
+
async function drainSessionDeletionReports(state) {
|
|
15722
|
+
const path = sessionDeletionReportPath(homedir8(), process.env);
|
|
15723
|
+
let delivered = 0;
|
|
15724
|
+
let failure = null;
|
|
15725
|
+
try {
|
|
15726
|
+
const spool = readSessionDeletionRecords(path);
|
|
15727
|
+
if (spool.readError !== null) {
|
|
15728
|
+
failure = `could not read spool: ${spool.readError}`;
|
|
15729
|
+
} else if (spool.records.length === 0) {
|
|
15730
|
+
return;
|
|
15731
|
+
} else if (!state.agentId || !state.authHeader) {
|
|
15732
|
+
failure = "runner authentication is not available";
|
|
15733
|
+
} else {
|
|
15734
|
+
for (let offset = 0; offset < spool.records.length; offset += 200) {
|
|
15735
|
+
const batch = spool.records.slice(offset, offset + 200);
|
|
15736
|
+
const result = await reportSessionDeletions(state.agentId, state.authHeader, batch);
|
|
15737
|
+
if (!result.ok) {
|
|
15738
|
+
failure = result.error ?? "unknown API error";
|
|
15739
|
+
break;
|
|
15740
|
+
}
|
|
15741
|
+
removeDeliveredSessionDeletionRecords(path, batch);
|
|
15742
|
+
delivered += batch.length;
|
|
15743
|
+
}
|
|
15744
|
+
}
|
|
15745
|
+
} catch (error2) {
|
|
15746
|
+
failure = error2 instanceof Error ? error2.message : String(error2);
|
|
15747
|
+
}
|
|
15748
|
+
const pending = readSessionDeletionRecords(path);
|
|
15749
|
+
const pendingCount = pending.readError === null ? pending.records.length : null;
|
|
15750
|
+
const message = `Session deletion reports: delivered ${delivered}, ${pendingCount === null ? "pending count unavailable" : `${pendingCount} pending`}` + (failure === null ? "." : `; delivery failed: ${failure}.`);
|
|
15751
|
+
logActivity(state, {
|
|
15752
|
+
type: "info",
|
|
15753
|
+
level: failure === null ? "info" : "warn",
|
|
15754
|
+
message,
|
|
15755
|
+
metadata: {
|
|
15756
|
+
outcome: failure === null ? "session-deletion-reports-drained" : "session-deletion-reports-pending",
|
|
15757
|
+
delivered,
|
|
15758
|
+
pending: pendingCount
|
|
15759
|
+
}
|
|
15760
|
+
});
|
|
15761
|
+
}
|
|
15602
15762
|
function logSessionDbProvenanceMismatch(state, provenance, currentVersion, preBootMigrationCount) {
|
|
15603
15763
|
const record = {
|
|
15604
15764
|
v: 1,
|
|
@@ -15656,17 +15816,22 @@ async function runSweep(state, driver, config) {
|
|
|
15656
15816
|
let failedThrew = 0;
|
|
15657
15817
|
let skippedNewlyActive = 0;
|
|
15658
15818
|
let remaining = 0;
|
|
15819
|
+
const deletionRecords = [];
|
|
15659
15820
|
let protectedNow = driver.protectedSessionIds();
|
|
15660
15821
|
if (sessions !== null) {
|
|
15661
|
-
const
|
|
15662
|
-
|
|
15663
|
-
|
|
15664
|
-
|
|
15665
|
-
|
|
15666
|
-
|
|
15667
|
-
protectedIds: protectedNow
|
|
15668
|
-
}
|
|
15822
|
+
const snapshots = sessions.map((session) => ({
|
|
15823
|
+
id: session.id,
|
|
15824
|
+
lastActivityMs: sessionLastActivityMs(session)
|
|
15825
|
+
}));
|
|
15826
|
+
const lastActivityById = new Map(
|
|
15827
|
+
snapshots.map(({ id, lastActivityMs }) => [id, lastActivityMs])
|
|
15669
15828
|
);
|
|
15829
|
+
const toDelete = selectSessionsToDelete(snapshots, {
|
|
15830
|
+
maxAgeMs: config.maxAgeMs,
|
|
15831
|
+
maxCount: config.maxCount,
|
|
15832
|
+
nowMs: Date.now(),
|
|
15833
|
+
protectedIds: protectedNow
|
|
15834
|
+
});
|
|
15670
15835
|
const eligibleToDelete = toDelete.filter(
|
|
15671
15836
|
(id) => (state.sessionDeleteFailures.get(id)?.isolatedFailures ?? 0) < SESSION_CLEANUP_GIVE_UP_AFTER_FAILURES
|
|
15672
15837
|
);
|
|
@@ -15686,6 +15851,17 @@ async function runSweep(state, driver, config) {
|
|
|
15686
15851
|
const outcome = await deleteSession(state.port, id, state.opencodeClient ?? void 0);
|
|
15687
15852
|
if (outcome.ok) {
|
|
15688
15853
|
deleted++;
|
|
15854
|
+
const lastActivityMs = lastActivityById.get(id) ?? null;
|
|
15855
|
+
deletionRecords.push({
|
|
15856
|
+
opencode_session_id: id,
|
|
15857
|
+
deleted_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15858
|
+
reason: "auto_cleanup",
|
|
15859
|
+
policy: {
|
|
15860
|
+
max_age_ms: config.maxAgeMs ?? null,
|
|
15861
|
+
max_count: config.maxCount ?? null,
|
|
15862
|
+
last_activity_at: lastActivityMs === null ? null : new Date(lastActivityMs).toISOString()
|
|
15863
|
+
}
|
|
15864
|
+
});
|
|
15689
15865
|
} else if (outcome.status === "threw") {
|
|
15690
15866
|
failed++;
|
|
15691
15867
|
failedThrew++;
|
|
@@ -15741,6 +15917,32 @@ async function runSweep(state, driver, config) {
|
|
|
15741
15917
|
message: `Session cleanup: inspected ${sessions.length}, deleted ${deleted}${failedNote}${skippedNote}${remainingNote} (${mode})`
|
|
15742
15918
|
});
|
|
15743
15919
|
}
|
|
15920
|
+
if (deletionRecords.length > 0) {
|
|
15921
|
+
try {
|
|
15922
|
+
const dropped = appendSessionDeletionRecords(
|
|
15923
|
+
sessionDeletionReportPath(homedir8(), process.env),
|
|
15924
|
+
deletionRecords
|
|
15925
|
+
);
|
|
15926
|
+
if (dropped > 0) {
|
|
15927
|
+
logSessionCleanupActivity(state, "sweep", {
|
|
15928
|
+
type: "info",
|
|
15929
|
+
level: "warn",
|
|
15930
|
+
message: `Session cleanup: dropped ${dropped} oldest pending deletion report(s) after reaching the spool limit`,
|
|
15931
|
+
metadata: { outcome: "deletion-reports-dropped", dropped_count: dropped }
|
|
15932
|
+
});
|
|
15933
|
+
}
|
|
15934
|
+
} catch (error2) {
|
|
15935
|
+
logSessionCleanupActivity(state, "sweep", {
|
|
15936
|
+
type: "info",
|
|
15937
|
+
level: "warn",
|
|
15938
|
+
message: `Session cleanup: could not persist ${deletionRecords.length} confirmed deletion report(s): ${error2 instanceof Error ? error2.message : String(error2)}`,
|
|
15939
|
+
metadata: {
|
|
15940
|
+
outcome: "deletion-report-spool-write-failed",
|
|
15941
|
+
records: deletionRecords.length
|
|
15942
|
+
}
|
|
15943
|
+
});
|
|
15944
|
+
}
|
|
15945
|
+
}
|
|
15744
15946
|
const sessionMetadata = {
|
|
15745
15947
|
sessions_inspected: sessions?.length ?? null,
|
|
15746
15948
|
sessions_deleted: deleted,
|
|
@@ -15810,6 +16012,7 @@ async function runSweep(state, driver, config) {
|
|
|
15810
16012
|
}
|
|
15811
16013
|
});
|
|
15812
16014
|
}
|
|
16015
|
+
await drainSessionDeletionReports(state);
|
|
15813
16016
|
} catch (error2) {
|
|
15814
16017
|
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
15815
16018
|
logSessionCleanupActivity(state, "sweep", {
|
|
@@ -16652,6 +16855,7 @@ async function run(options) {
|
|
|
16652
16855
|
}
|
|
16653
16856
|
}
|
|
16654
16857
|
reportSessionDbRecovery(state);
|
|
16858
|
+
await drainSessionDeletionReports(state);
|
|
16655
16859
|
if (sessionDbVerifyFatal) {
|
|
16656
16860
|
throw new Error(
|
|
16657
16861
|
sessionDbVerifyFatalReason === void 0 ? "SESSION-DB-INTEGRITY-EXHAUSTED: the corrupt session DB could not be proven separated from the active backup prefix or removed from disk" : `SESSION-DB-VERIFY-TIMEOUT: session DB verification timed out (${sessionDbVerifyFatalReason}); refusing to start`
|
|
@@ -16782,7 +16986,7 @@ async function run(options) {
|
|
|
16782
16986
|
state.opencodeClient = openCodeClient;
|
|
16783
16987
|
if (options.opencodePidFile && oc.process?.pid !== void 0) {
|
|
16784
16988
|
try {
|
|
16785
|
-
|
|
16989
|
+
writeFileSync7(options.opencodePidFile, `${oc.process.pid}
|
|
16786
16990
|
`, { mode: 384 });
|
|
16787
16991
|
chmodSync3(options.opencodePidFile, 384);
|
|
16788
16992
|
} catch (error2) {
|
|
@@ -16892,7 +17096,7 @@ async function run(options) {
|
|
|
16892
17096
|
let existingPid;
|
|
16893
17097
|
if (existsSync3(options.litestreamPidFile)) {
|
|
16894
17098
|
try {
|
|
16895
|
-
const rawPid =
|
|
17099
|
+
const rawPid = readFileSync9(options.litestreamPidFile, "utf8").trim();
|
|
16896
17100
|
const parsedPid = Number(rawPid);
|
|
16897
17101
|
if (/^\d+$/.test(rawPid) && Number.isSafeInteger(parsedPid) && parsedPid > 0) {
|
|
16898
17102
|
existingPid = parsedPid;
|
|
@@ -16929,7 +17133,7 @@ async function run(options) {
|
|
|
16929
17133
|
});
|
|
16930
17134
|
try {
|
|
16931
17135
|
if (litestreamProcess.pid !== void 0) {
|
|
16932
|
-
|
|
17136
|
+
writeFileSync7(options.litestreamPidFile, `${litestreamProcess.pid}
|
|
16933
17137
|
`, {
|
|
16934
17138
|
mode: 384
|
|
16935
17139
|
});
|