@evident-ai/cli 3.4.1-dev.b1bf8c5 → 3.4.1-dev.bcdc457
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 +205 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1127,7 +1127,7 @@ async function claudeUsage() {
|
|
|
1127
1127
|
|
|
1128
1128
|
// src/commands/run.ts
|
|
1129
1129
|
import { homedir as homedir4 } from "os";
|
|
1130
|
-
import { isAbsolute as isAbsolute2, join as
|
|
1130
|
+
import { isAbsolute as isAbsolute2, join as join7, parse, resolve as resolvePath } from "path";
|
|
1131
1131
|
import chalk6 from "chalk";
|
|
1132
1132
|
|
|
1133
1133
|
// ../../packages/types/src/agents/index.ts
|
|
@@ -1360,6 +1360,8 @@ var SEVERITY_BY_LEVEL = {
|
|
|
1360
1360
|
error: "error"
|
|
1361
1361
|
};
|
|
1362
1362
|
var MAX_MESSAGE_LENGTH = 500;
|
|
1363
|
+
var MAX_METADATA_VALUE_LENGTH = 200;
|
|
1364
|
+
var MAX_METADATA_ENTRIES = 20;
|
|
1363
1365
|
var TRUNCATION_MARKER = "\u2026";
|
|
1364
1366
|
function redact(message) {
|
|
1365
1367
|
return message.replace(/esk_[A-Za-z0-9_-]+/g, "esk_***").replace(/ct_[A-Za-z0-9_-]+/g, "ct_***").replace(/https?:\/\/\S+/g, "<url>");
|
|
@@ -1368,6 +1370,24 @@ function truncate(message) {
|
|
|
1368
1370
|
if (message.length <= MAX_MESSAGE_LENGTH) return message;
|
|
1369
1371
|
return message.slice(0, MAX_MESSAGE_LENGTH - TRUNCATION_MARKER.length) + TRUNCATION_MARKER;
|
|
1370
1372
|
}
|
|
1373
|
+
function sanitiseMetadata(metadata) {
|
|
1374
|
+
if (!metadata) return {};
|
|
1375
|
+
const entries = Object.entries(metadata).slice(0, MAX_METADATA_ENTRIES);
|
|
1376
|
+
if (Object.keys(metadata).length > entries.length) {
|
|
1377
|
+
console.error(
|
|
1378
|
+
`[runner-activity-telemetry] dropped ${Object.keys(metadata).length - entries.length} metadata entries`
|
|
1379
|
+
);
|
|
1380
|
+
}
|
|
1381
|
+
const sanitised = [];
|
|
1382
|
+
for (const [key, value] of entries) {
|
|
1383
|
+
if (typeof value === "string") {
|
|
1384
|
+
sanitised.push([key, truncate(redact(value).slice(0, MAX_METADATA_VALUE_LENGTH))]);
|
|
1385
|
+
} else if (value === null || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)) {
|
|
1386
|
+
sanitised.push([key, value]);
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
return Object.fromEntries(sanitised);
|
|
1390
|
+
}
|
|
1371
1391
|
var RATE_LIMIT_WINDOW_MS = 6e4;
|
|
1372
1392
|
var RATE_LIMIT_MAX_EVENTS = 30;
|
|
1373
1393
|
var windowStartedAt = 0;
|
|
@@ -1406,7 +1426,7 @@ function forwardRunnerActivity(entry, context) {
|
|
|
1406
1426
|
logEvent(TelemetryEventTypes.RUNNER_ACTIVITY, {
|
|
1407
1427
|
severity: SEVERITY_BY_LEVEL[entry.level],
|
|
1408
1428
|
message,
|
|
1409
|
-
metadata: { source: "cli.run" },
|
|
1429
|
+
metadata: { ...sanitiseMetadata(entry.metadata), source: "cli.run" },
|
|
1410
1430
|
agentId: context.agentId
|
|
1411
1431
|
});
|
|
1412
1432
|
} catch (err) {
|
|
@@ -1416,6 +1436,150 @@ function forwardRunnerActivity(entry, context) {
|
|
|
1416
1436
|
}
|
|
1417
1437
|
}
|
|
1418
1438
|
|
|
1439
|
+
// src/lib/opencode/session-db-recovery-report.ts
|
|
1440
|
+
import { readFileSync as readFileSync2, unlinkSync } from "fs";
|
|
1441
|
+
import { join as join2 } from "path";
|
|
1442
|
+
function sessionDbRecoveryReportPath(homeDir, env) {
|
|
1443
|
+
const override = env.EVIDENT_SESSION_DB_RECOVERY_REPORT?.trim();
|
|
1444
|
+
return override || join2(homeDir, ".local", "state", "evident", "session-db-recovery.jsonl");
|
|
1445
|
+
}
|
|
1446
|
+
function drainSessionDbRecoveryReport({
|
|
1447
|
+
homeDir,
|
|
1448
|
+
env
|
|
1449
|
+
}) {
|
|
1450
|
+
const path = sessionDbRecoveryReportPath(homeDir, env);
|
|
1451
|
+
let content;
|
|
1452
|
+
try {
|
|
1453
|
+
content = readFileSync2(path, "utf8");
|
|
1454
|
+
} catch (error2) {
|
|
1455
|
+
if (error2 instanceof Error && "code" in error2 && error2.code === "ENOENT")
|
|
1456
|
+
return { path, records: [], skippedLines: 0, readError: null };
|
|
1457
|
+
const readError = error2 instanceof Error ? error2.message : String(error2);
|
|
1458
|
+
console.error(`[session-db-recovery-report] could not read ${path}: ${readError}`);
|
|
1459
|
+
return { path, records: [], skippedLines: 0, readError };
|
|
1460
|
+
}
|
|
1461
|
+
let skippedLines = 0;
|
|
1462
|
+
const records = content.split("\n").flatMap((line) => {
|
|
1463
|
+
if (!line.trim()) return [];
|
|
1464
|
+
try {
|
|
1465
|
+
const value = JSON.parse(line);
|
|
1466
|
+
if (!isSessionDbRecoveryRecord(value)) {
|
|
1467
|
+
skippedLines++;
|
|
1468
|
+
return [];
|
|
1469
|
+
}
|
|
1470
|
+
return [value];
|
|
1471
|
+
} catch (error2) {
|
|
1472
|
+
skippedLines++;
|
|
1473
|
+
console.error(
|
|
1474
|
+
`[session-db-recovery-report] skipped malformed record in ${path}: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
1475
|
+
);
|
|
1476
|
+
return [];
|
|
1477
|
+
}
|
|
1478
|
+
});
|
|
1479
|
+
return { path, records, skippedLines, readError: null };
|
|
1480
|
+
}
|
|
1481
|
+
function acknowledgeSessionDbRecoveryReport(path) {
|
|
1482
|
+
try {
|
|
1483
|
+
unlinkSync(path);
|
|
1484
|
+
} catch (error2) {
|
|
1485
|
+
if (error2 instanceof Error && "code" in error2 && error2.code === "ENOENT") return;
|
|
1486
|
+
console.error(
|
|
1487
|
+
`[session-db-recovery-report] could not remove ${path}: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
1488
|
+
);
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
function buildSessionDbRecoveryActivity(record) {
|
|
1492
|
+
const level = record.severity === "warning" ? "warn" : record.severity === "error" ? "error" : null;
|
|
1493
|
+
if (!level) return null;
|
|
1494
|
+
const noVerifiedPoint = record.verified_restore_point ? ` The verified restore point is ${record.verified_restore_point}.` : " No verified restore point is known.";
|
|
1495
|
+
switch (record.outcome) {
|
|
1496
|
+
case "fresh_session_db":
|
|
1497
|
+
return {
|
|
1498
|
+
level,
|
|
1499
|
+
metadata: withoutContractFields(record),
|
|
1500
|
+
message: `This runner started with a fresh session database. Earlier sessions are unavailable, and queued conversation or session references from before this start may no longer resolve.${noVerifiedPoint} Review the runner's backup configuration before relying on restored session history.`
|
|
1501
|
+
};
|
|
1502
|
+
case "restore_retried":
|
|
1503
|
+
return {
|
|
1504
|
+
level,
|
|
1505
|
+
metadata: withoutContractFields(record),
|
|
1506
|
+
message: "The initial session database restore failed; the runner will retry it. Monitor the runner backup for another restore failure."
|
|
1507
|
+
};
|
|
1508
|
+
case "replica_recovered":
|
|
1509
|
+
if (record.reason === "quarantine")
|
|
1510
|
+
return {
|
|
1511
|
+
level,
|
|
1512
|
+
metadata: withoutContractFields(record),
|
|
1513
|
+
message: `Session database recovery quarantined ${record.quarantined_objects ?? "unknown"} objects (${record.quarantined_bytes ?? "unknown"} bytes); ${record.quarantine_failed_objects ?? "unknown"} moves failed. Review the preserved backup at ${record.quarantine_destination ?? "an unknown destination"} before deleting it.`
|
|
1514
|
+
};
|
|
1515
|
+
if (record.reason === "prune")
|
|
1516
|
+
return {
|
|
1517
|
+
level,
|
|
1518
|
+
metadata: withoutContractFields(record),
|
|
1519
|
+
message: "Session database recovery discarded a damaged newest backup and retried. Sessions recorded after the previous backup point may be unavailable. Review the runner backup for another restore failure."
|
|
1520
|
+
};
|
|
1521
|
+
if (record.reason === "clear")
|
|
1522
|
+
return {
|
|
1523
|
+
level,
|
|
1524
|
+
metadata: withoutContractFields(record),
|
|
1525
|
+
message: "Session database recovery deleted the damaged backup and prior session history is unavailable. Review the runner backup configuration before relying on restored session history."
|
|
1526
|
+
};
|
|
1527
|
+
return null;
|
|
1528
|
+
case "history_rolled_back":
|
|
1529
|
+
return {
|
|
1530
|
+
level,
|
|
1531
|
+
metadata: withoutContractFields(record),
|
|
1532
|
+
message: `Session history was rolled back to verified restore point ${record.verified_restore_point ?? "unknown"}; everything after it is unavailable. Review the runner backup for another restore failure.`
|
|
1533
|
+
};
|
|
1534
|
+
case "restore_misconfigured":
|
|
1535
|
+
return {
|
|
1536
|
+
level,
|
|
1537
|
+
metadata: withoutContractFields(record),
|
|
1538
|
+
message: "This runner started with a fresh session database because it could not verify where its session history is backed up. Nothing in the backup was changed; check the runner backup configuration and permissions."
|
|
1539
|
+
};
|
|
1540
|
+
case "session_db_boot_refused":
|
|
1541
|
+
return {
|
|
1542
|
+
level,
|
|
1543
|
+
metadata: withoutContractFields(record),
|
|
1544
|
+
message: `This runner did not come online because its damaged session database could not be safely separated from its active backup or proven removed. Backed-up session history remains readable at ${record.quarantine_destination ?? "its original location or the quarantine destination named in the boot logs"}; any local session-database files that remain were left in place and nothing opened or wrote them. See the runner boot logs for SESSION-DB-LOCAL-DISCARD-FAILED details.`
|
|
1545
|
+
};
|
|
1546
|
+
default:
|
|
1547
|
+
return null;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
function withoutContractFields(record) {
|
|
1551
|
+
const { v: _v, event: _event, ...metadata } = record;
|
|
1552
|
+
return metadata;
|
|
1553
|
+
}
|
|
1554
|
+
var OUTCOMES = /* @__PURE__ */ new Set([
|
|
1555
|
+
"replica_recovered",
|
|
1556
|
+
"restore_retried",
|
|
1557
|
+
"fresh_session_db",
|
|
1558
|
+
"history_rolled_back",
|
|
1559
|
+
"restore_misconfigured",
|
|
1560
|
+
"session_db_boot_refused"
|
|
1561
|
+
]);
|
|
1562
|
+
var STAGES = /* @__PURE__ */ new Set(["restore", "verify"]);
|
|
1563
|
+
var SEVERITIES = /* @__PURE__ */ new Set(["warning", "error"]);
|
|
1564
|
+
var NUMBER_FIELDS = [
|
|
1565
|
+
"litestream_exit_code",
|
|
1566
|
+
"attempt",
|
|
1567
|
+
"replica_objects",
|
|
1568
|
+
"replica_bytes",
|
|
1569
|
+
"quarantined_objects",
|
|
1570
|
+
"quarantine_failed_objects",
|
|
1571
|
+
"quarantined_bytes",
|
|
1572
|
+
"restore_points_tried"
|
|
1573
|
+
];
|
|
1574
|
+
var STRING_OR_NULL_FIELDS = ["quarantine_destination", "verified_restore_point"];
|
|
1575
|
+
function isSessionDbRecoveryRecord(value) {
|
|
1576
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1577
|
+
const record = value;
|
|
1578
|
+
return record.v === 1 && record.event === "session_db_recovery" && typeof record.at === "string" && STAGES.has(record.stage) && OUTCOMES.has(record.outcome) && SEVERITIES.has(record.severity) && typeof record.reason === "string" && NUMBER_FIELDS.every((field) => record[field] === null || Number.isInteger(record[field])) && STRING_OR_NULL_FIELDS.every(
|
|
1579
|
+
(field) => record[field] === null || typeof record[field] === "string"
|
|
1580
|
+
);
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1419
1583
|
// src/lib/opencode/health.ts
|
|
1420
1584
|
async function checkOpenCodeHealth(port) {
|
|
1421
1585
|
try {
|
|
@@ -2453,10 +2617,10 @@ function resolveSessionCleanupConfig(flags, env = process.env) {
|
|
|
2453
2617
|
|
|
2454
2618
|
// src/lib/opencode/session-db-size.ts
|
|
2455
2619
|
import { statSync as statSync2 } from "fs";
|
|
2456
|
-
import { join as
|
|
2620
|
+
import { join as join3 } from "path";
|
|
2457
2621
|
var LARGE_DB_THRESHOLD_BYTES = 268435456;
|
|
2458
2622
|
function statSessionDbBytes(homeDir) {
|
|
2459
|
-
const dbPath =
|
|
2623
|
+
const dbPath = join3(homeDir, ".local", "share", "opencode", "opencode.db");
|
|
2460
2624
|
try {
|
|
2461
2625
|
return statSync2(dbPath).size;
|
|
2462
2626
|
} catch (err) {
|
|
@@ -3026,9 +3190,9 @@ function writeTunnelReadyMarker(path, agentId) {
|
|
|
3026
3190
|
}
|
|
3027
3191
|
|
|
3028
3192
|
// src/lib/openai-usage.ts
|
|
3029
|
-
import { readFileSync as
|
|
3193
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
3030
3194
|
import { homedir as homedir2 } from "os";
|
|
3031
|
-
import { join as
|
|
3195
|
+
import { join as join4 } from "path";
|
|
3032
3196
|
var CODEX_RESPONSES_URL = "https://chatgpt.com/backend-api/codex/responses";
|
|
3033
3197
|
var OPENCODE_AUTH_SEGMENTS = [".local", "share", "opencode", "auth.json"];
|
|
3034
3198
|
var OpenAiUsageError = class extends Error {
|
|
@@ -3042,7 +3206,7 @@ function isLocalCredentialProblem2(err) {
|
|
|
3042
3206
|
}
|
|
3043
3207
|
function readOpenCodeChatGptCredentials() {
|
|
3044
3208
|
try {
|
|
3045
|
-
const raw =
|
|
3209
|
+
const raw = readFileSync3(join4(homedir2(), ...OPENCODE_AUTH_SEGMENTS), "utf-8");
|
|
3046
3210
|
let parsed;
|
|
3047
3211
|
try {
|
|
3048
3212
|
parsed = JSON.parse(raw);
|
|
@@ -3418,12 +3582,12 @@ function createResourceUsageCollector(homeDir) {
|
|
|
3418
3582
|
import { homedir as homedir3 } from "os";
|
|
3419
3583
|
|
|
3420
3584
|
// src/lib/runner-file-sync.ts
|
|
3421
|
-
import { join as
|
|
3585
|
+
import { join as join6 } from "path";
|
|
3422
3586
|
|
|
3423
3587
|
// src/lib/file-push.ts
|
|
3424
3588
|
import { randomUUID } from "crypto";
|
|
3425
3589
|
import { chmod, mkdir, open as open2, realpath, rename, unlink } from "fs/promises";
|
|
3426
|
-
import { basename, dirname as dirname3, isAbsolute, join as
|
|
3590
|
+
import { basename, dirname as dirname3, isAbsolute, join as join5, relative, resolve as resolve2, sep } from "path";
|
|
3427
3591
|
var FILE_MODE = 384;
|
|
3428
3592
|
var DIRECTORY_MODE = 448;
|
|
3429
3593
|
async function writePushedFile(request) {
|
|
@@ -3456,7 +3620,7 @@ async function writePushedFile(request) {
|
|
|
3456
3620
|
const { existingAncestor, missingSegments } = await resolveNearestExistingAncestor(
|
|
3457
3621
|
dirname3(candidate)
|
|
3458
3622
|
);
|
|
3459
|
-
const realTarget =
|
|
3623
|
+
const realTarget = join5(existingAncestor, ...missingSegments, basename(candidate));
|
|
3460
3624
|
const allowedDirectory = await findContainingAllowedDirectory(allowedDirectories, realTarget);
|
|
3461
3625
|
if (allowedDirectory === null) {
|
|
3462
3626
|
return refuse("path_not_allowed", "The runner does not allow writing to that location.", {
|
|
@@ -3492,7 +3656,7 @@ function expandAndValidate(requestedPath, homeDir) {
|
|
|
3492
3656
|
if (requestedPath.trim() === "" || requestedPath.includes("\0")) {
|
|
3493
3657
|
return null;
|
|
3494
3658
|
}
|
|
3495
|
-
const expanded = requestedPath === "~" ? homeDir : requestedPath.startsWith("~/") ?
|
|
3659
|
+
const expanded = requestedPath === "~" ? homeDir : requestedPath.startsWith("~/") ? join5(homeDir, requestedPath.slice(2)) : requestedPath;
|
|
3496
3660
|
if (expanded.split(/[/\\]/).includes("..")) {
|
|
3497
3661
|
return null;
|
|
3498
3662
|
}
|
|
@@ -3565,13 +3729,13 @@ function contains(realDirectory, realTarget) {
|
|
|
3565
3729
|
async function createMissingDirectories(existingAncestor, missingSegments) {
|
|
3566
3730
|
let current = existingAncestor;
|
|
3567
3731
|
for (const segment of missingSegments) {
|
|
3568
|
-
current =
|
|
3732
|
+
current = join5(current, segment);
|
|
3569
3733
|
await mkdir(current, { recursive: true, mode: DIRECTORY_MODE });
|
|
3570
3734
|
await chmod(current, DIRECTORY_MODE);
|
|
3571
3735
|
}
|
|
3572
3736
|
}
|
|
3573
3737
|
async function writeAtomically(realTarget, content) {
|
|
3574
|
-
const temporaryPath =
|
|
3738
|
+
const temporaryPath = join5(dirname3(realTarget), `.evident-push-${randomUUID()}.tmp`);
|
|
3575
3739
|
let handle;
|
|
3576
3740
|
try {
|
|
3577
3741
|
handle = await open2(temporaryPath, "wx", FILE_MODE);
|
|
@@ -3701,12 +3865,12 @@ var NOT_APPLIED = {
|
|
|
3701
3865
|
opencodeAuthApplied: false
|
|
3702
3866
|
};
|
|
3703
3867
|
function isClaudeCredentialPath(requestedPath, homeDir) {
|
|
3704
|
-
const expanded = requestedPath === "~" ? homeDir : requestedPath.startsWith("~/") ?
|
|
3705
|
-
return expanded ===
|
|
3868
|
+
const expanded = requestedPath === "~" ? homeDir : requestedPath.startsWith("~/") ? join6(homeDir, requestedPath.slice(2)) : requestedPath;
|
|
3869
|
+
return expanded === join6(homeDir, ...CLAUDE_CREDENTIALS_SEGMENTS);
|
|
3706
3870
|
}
|
|
3707
3871
|
function isOpenCodeAuthPath(requestedPath, homeDir) {
|
|
3708
|
-
const expanded = requestedPath === "~" ? homeDir : requestedPath.startsWith("~/") ?
|
|
3709
|
-
return expanded ===
|
|
3872
|
+
const expanded = requestedPath === "~" ? homeDir : requestedPath.startsWith("~/") ? join6(homeDir, requestedPath.slice(2)) : requestedPath;
|
|
3873
|
+
return expanded === join6(homeDir, ...OPENCODE_AUTH_SEGMENTS);
|
|
3710
3874
|
}
|
|
3711
3875
|
async function applyOne(options, file) {
|
|
3712
3876
|
const label = `${file.id.slice(0, 8)} (${file.path})`;
|
|
@@ -7768,7 +7932,7 @@ function resolveFileSyncDirectories(raw, homeDir) {
|
|
|
7768
7932
|
if (trimmed === "") {
|
|
7769
7933
|
throw new Error("--enable-file-sync-to requires a directory path (got an empty value)");
|
|
7770
7934
|
}
|
|
7771
|
-
const expanded = trimmed === "~" ? homeDir : trimmed.startsWith("~/") ?
|
|
7935
|
+
const expanded = trimmed === "~" ? homeDir : trimmed.startsWith("~/") ? join7(homeDir, trimmed.slice(2)) : trimmed;
|
|
7772
7936
|
if (!isAbsolute2(expanded)) {
|
|
7773
7937
|
throw new Error(`--enable-file-sync-to requires an absolute directory path; got "${entry}"`);
|
|
7774
7938
|
}
|
|
@@ -7866,7 +8030,7 @@ function logActivity(state, entry) {
|
|
|
7866
8030
|
const level = entry.level ?? (entry.type === "error" ? "error" : "info");
|
|
7867
8031
|
if (!meetsThreshold(state, level)) return;
|
|
7868
8032
|
forwardRunnerActivity(
|
|
7869
|
-
{ level, message: entry.message, error: entry.error },
|
|
8033
|
+
{ level, message: entry.message, error: entry.error, metadata: entry.metadata },
|
|
7870
8034
|
{ agentId: state.agentId, authHeader: state.authHeader }
|
|
7871
8035
|
);
|
|
7872
8036
|
const fullEntry = {
|
|
@@ -7886,6 +8050,26 @@ function logActivity(state, entry) {
|
|
|
7886
8050
|
}
|
|
7887
8051
|
}
|
|
7888
8052
|
}
|
|
8053
|
+
function reportSessionDbRecovery(state) {
|
|
8054
|
+
try {
|
|
8055
|
+
const report = drainSessionDbRecoveryReport({ homeDir: homedir4(), env: process.env });
|
|
8056
|
+
for (const record of report.records) {
|
|
8057
|
+
const activity = buildSessionDbRecoveryActivity(record);
|
|
8058
|
+
if (!activity) throw new Error("could not map session-DB recovery record");
|
|
8059
|
+
logActivity(state, {
|
|
8060
|
+
type: activity.level === "error" ? "error" : "info",
|
|
8061
|
+
level: activity.level,
|
|
8062
|
+
...activity.level === "error" ? { error: activity.message } : { message: activity.message },
|
|
8063
|
+
metadata: activity.metadata
|
|
8064
|
+
});
|
|
8065
|
+
}
|
|
8066
|
+
acknowledgeSessionDbRecoveryReport(report.path);
|
|
8067
|
+
} catch (error2) {
|
|
8068
|
+
console.error(
|
|
8069
|
+
`[run] could not report session-DB recovery activity: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
8070
|
+
);
|
|
8071
|
+
}
|
|
8072
|
+
}
|
|
7889
8073
|
function displayStatus(state) {
|
|
7890
8074
|
if (!state.interactive) return;
|
|
7891
8075
|
const attempt = state.connection?.reconnectAttempt ?? 0;
|
|
@@ -8081,7 +8265,7 @@ async function driveChannels(state, driver) {
|
|
|
8081
8265
|
var SESSION_CLEANUP_FIRST_SWEEP_MS = 1e4;
|
|
8082
8266
|
var SESSION_DB_RECLAIM_MAX_PAGES = 2e3;
|
|
8083
8267
|
function sessionDbPath() {
|
|
8084
|
-
return
|
|
8268
|
+
return join7(homedir4(), ".local", "share", "opencode", "opencode.db");
|
|
8085
8269
|
}
|
|
8086
8270
|
async function runSweep(state, driver, config) {
|
|
8087
8271
|
const mode = `age=${config.maxAgeMs ?? "\u2014"} count=${config.maxCount ?? "\u2014"}`;
|
|
@@ -8744,6 +8928,7 @@ async function run(options) {
|
|
|
8744
8928
|
} else {
|
|
8745
8929
|
log2(state, "Not running in a MicroVM (MICROVM_ID unset) \u2014 nothing to report", "debug");
|
|
8746
8930
|
}
|
|
8931
|
+
reportSessionDbRecovery(state);
|
|
8747
8932
|
const { timeoutMs: opencodeStartTimeoutMs, warnings: opencodeStartTimeoutWarnings } = resolveOpenCodeStartTimeoutMs(options, process.env);
|
|
8748
8933
|
for (const warning2 of opencodeStartTimeoutWarnings) {
|
|
8749
8934
|
logActivity(state, { type: "info", level: "warn", message: warning2 });
|