@evident-ai/cli 3.5.2-dev.8b315dd → 3.5.2-dev.8c3e0f7

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/README.md CHANGED
@@ -117,9 +117,11 @@ Options:
117
117
  starting OpenCode. Requires `--litestream-config` for the replica location and
118
118
  `--session-db-no-replicate-marker` for give-up records. Omit it for a normal local
119
119
  run.
120
- - `--restore-runner-credentials` — Restore the hosted runner secret and persisted
121
- credential stores before starting OpenCode. Intended for runner images; omit it
122
- for a normal local run.
120
+ - `--restore-runner-credentials` — Restore the persisted credential stores (Claude/OpenCode
121
+ model auth) before starting OpenCode. Intended for runner images; omit it for a normal
122
+ local run. The hosted runner secret's env vars (`GH_TOKEN` and the MCP tokens) are
123
+ fetched on every `evident run` boot regardless of this flag — it's in-memory,
124
+ per-process state, never persisted, so there's no store to restore over.
123
125
  - `--opencode-config-overlay <path>` — Apply a runner-provided OpenCode config
124
126
  before starting OpenCode. Relative paths are resolved from the working directory;
125
127
  an existing `opencode.jsonc` is replaced before `opencode.json`.
package/dist/index.js CHANGED
@@ -1322,7 +1322,7 @@ import ora4 from "ora";
1322
1322
  import { select as select4 } from "@inquirer/prompts";
1323
1323
 
1324
1324
  // src/lib/telemetry.ts
1325
- var CLI_VERSION = (true ? "3.5.2-dev.8b315dd" : void 0) ?? process.env.npm_package_version ?? "unknown";
1325
+ var CLI_VERSION = (true ? "3.5.2-dev.8c3e0f7" : void 0) ?? process.env.npm_package_version ?? "unknown";
1326
1326
  function getCliVersion() {
1327
1327
  return CLI_VERSION;
1328
1328
  }
@@ -1515,9 +1515,10 @@ function redactDiagnosticText(message) {
1515
1515
  }
1516
1516
 
1517
1517
  // src/lib/opencode/session-db-reclaim.ts
1518
- var SESSION_DB_RECLAIM_CHUNK_PAGES = 2e3;
1518
+ var SESSION_DB_RECLAIM_CHUNK_PAGES = 100;
1519
1519
  var SESSION_DB_RECLAIM_TIME_BUDGET_MS = 500;
1520
1520
  var SESSION_DB_RECLAIM_PAGE_CEILING = 4e4;
1521
+ var SESSION_DB_RECLAIM_BUSY_TIMEOUT_MS = 5e3;
1521
1522
  function errorMessage(error2) {
1522
1523
  if (!(error2 instanceof Error)) return String(error2);
1523
1524
  return error2.cause instanceof Error ? error2.cause.message : error2.message;
@@ -1642,6 +1643,7 @@ function readFreelistCount(db) {
1642
1643
  return db.prepare("PRAGMA freelist_count").get().freelist_count;
1643
1644
  }
1644
1645
  function readCheckpointResult(db) {
1646
+ db.exec("PRAGMA busy_timeout=0");
1645
1647
  const row = db.prepare("PRAGMA wal_checkpoint(TRUNCATE)").get();
1646
1648
  return { busy: row.busy !== 0, log: row.log, checkpointed: row.checkpointed };
1647
1649
  }
@@ -1659,7 +1661,7 @@ async function probeReclaimAvailability(input) {
1659
1661
  try {
1660
1662
  const db = new sqlite.DatabaseSync(dbPath, { readOnly: true });
1661
1663
  try {
1662
- db.exec("PRAGMA busy_timeout=5000");
1664
+ db.exec(`PRAGMA busy_timeout=${SESSION_DB_RECLAIM_BUSY_TIMEOUT_MS}`);
1663
1665
  autoVacuum = db.prepare("PRAGMA auto_vacuum").get().auto_vacuum;
1664
1666
  } finally {
1665
1667
  db.close();
@@ -1679,7 +1681,8 @@ async function reclaimSessionDbSpace(input) {
1679
1681
  timeBudgetMs = SESSION_DB_RECLAIM_TIME_BUDGET_MS,
1680
1682
  chunkPages = SESSION_DB_RECLAIM_CHUNK_PAGES,
1681
1683
  now = () => performance.now(),
1682
- allowFullVacuum = true
1684
+ hasLiveTurn = false,
1685
+ hasProvenanceAnomaly = false
1683
1686
  } = input;
1684
1687
  let sqlite;
1685
1688
  try {
@@ -1695,17 +1698,19 @@ async function reclaimSessionDbSpace(input) {
1695
1698
  let db;
1696
1699
  try {
1697
1700
  db = new DatabaseSync(dbPath);
1698
- db.exec("PRAGMA busy_timeout=5000");
1701
+ db.exec(`PRAGMA busy_timeout=${SESSION_DB_RECLAIM_BUSY_TIMEOUT_MS}`);
1699
1702
  const autoVacuum = db.prepare("PRAGMA auto_vacuum").get().auto_vacuum;
1700
1703
  if (autoVacuum === 0) {
1701
- if (!allowFullVacuum) {
1702
- console.warn(
1703
- `[reclaimSessionDbSpace] skipping VACUUM conversion of ${dbPath}: a session turn is live`
1704
- );
1704
+ if (hasLiveTurn || hasProvenanceAnomaly) {
1705
+ const detail = [
1706
+ ...hasLiveTurn ? ["a session turn is live"] : [],
1707
+ ...hasProvenanceAnomaly ? ["session-DB provenance is anomalous"] : []
1708
+ ].join(" and ");
1709
+ console.warn(`[reclaimSessionDbSpace] skipping VACUUM conversion of ${dbPath}: ${detail}`);
1705
1710
  return {
1706
1711
  ok: false,
1707
1712
  skipped: "full-vacuum-blocked",
1708
- detail: "a session turn is live"
1713
+ detail
1709
1714
  };
1710
1715
  }
1711
1716
  const fileBytesForGuard = statSync2(dbPath).size;
@@ -1723,7 +1728,9 @@ async function reclaimSessionDbSpace(input) {
1723
1728
  db.exec("VACUUM");
1724
1729
  const afterBytes = readLogicalBytes(db);
1725
1730
  const freelistAfter = readFreelistCount(db);
1731
+ const checkpointStartedAt = now();
1726
1732
  const checkpoint = readCheckpointResult(db);
1733
+ const checkpointElapsedMs = Math.max(0, now() - checkpointStartedAt);
1727
1734
  return {
1728
1735
  ok: true,
1729
1736
  mode: "convert",
@@ -1734,10 +1741,18 @@ async function reclaimSessionDbSpace(input) {
1734
1741
  pagesReclaimed: Math.max(0, freelistBefore - freelistAfter),
1735
1742
  stoppedBy: "freelist-drained",
1736
1743
  elapsedMs: Math.max(0, now() - startedAt),
1744
+ checkpointElapsedMs,
1737
1745
  checkpoint
1738
1746
  };
1739
1747
  }
1740
1748
  if (autoVacuum === 2) {
1749
+ if (hasLiveTurn) {
1750
+ const detail = "a session turn is live";
1751
+ console.warn(
1752
+ `[reclaimSessionDbSpace] skipping incremental reclaim of ${dbPath}: ${detail}`
1753
+ );
1754
+ return { ok: false, skipped: "live-turn", detail };
1755
+ }
1741
1756
  const beforeBytes = readLogicalBytes(db);
1742
1757
  const freelistBefore = readFreelistCount(db);
1743
1758
  const startedAt = now();
@@ -1762,7 +1777,9 @@ async function reclaimSessionDbSpace(input) {
1762
1777
  freelistAfter = readFreelistCount(db);
1763
1778
  }
1764
1779
  const afterBytes = readLogicalBytes(db);
1780
+ const checkpointStartedAt = now();
1765
1781
  const checkpoint = readCheckpointResult(db);
1782
+ const checkpointElapsedMs = Math.max(0, now() - checkpointStartedAt);
1766
1783
  return {
1767
1784
  ok: true,
1768
1785
  mode: "incremental",
@@ -1773,6 +1790,7 @@ async function reclaimSessionDbSpace(input) {
1773
1790
  pagesReclaimed: Math.max(0, freelistBefore - freelistAfter),
1774
1791
  stoppedBy,
1775
1792
  elapsedMs: Math.max(0, now() - startedAt),
1793
+ checkpointElapsedMs,
1776
1794
  checkpoint
1777
1795
  };
1778
1796
  }
@@ -3058,9 +3076,11 @@ function sumAssistantUsage(messages) {
3058
3076
  let cacheWriteSum = 0;
3059
3077
  let costSum = 0;
3060
3078
  let sawCost = false;
3079
+ let toolCallCount = 0;
3061
3080
  let modelId = null;
3062
3081
  let providerId = null;
3063
3082
  for (const m of selected) {
3083
+ toolCallCount += m.parts?.filter((part) => part.type === "tool").length ?? 0;
3064
3084
  const info = m.info;
3065
3085
  if (!info) continue;
3066
3086
  const tokens = info.tokens;
@@ -3097,7 +3117,8 @@ function sumAssistantUsage(messages) {
3097
3117
  usage_tokens_cache_write: cacheWriteSum,
3098
3118
  // NULL means OpenCode never reported a cost; it is distinct from a genuine
3099
3119
  // zero-cost message, which sets `sawCost` with `costSum === 0`.
3100
- usage_cost_usd: sawCost ? costSum : null
3120
+ usage_cost_usd: sawCost ? costSum : null,
3121
+ turn_tool_calls: toolCallCount
3101
3122
  };
3102
3123
  }
3103
3124
  function messageUsage(messages, userMessageId) {
@@ -12858,7 +12879,9 @@ async function installRunnerSecret({
12858
12879
  }) {
12859
12880
  const arn = env.RUNNER_SECRET_ARN?.trim();
12860
12881
  if (!arn) {
12861
- log3("runner secret is not configured; continuing without GitHub and MCP credentials");
12882
+ if (!env.GH_TOKEN) {
12883
+ log3("runner secret is not configured; continuing without GitHub and MCP credentials");
12884
+ }
12862
12885
  return false;
12863
12886
  }
12864
12887
  const result = await (commandRunner ?? runCommand2)(
@@ -13978,21 +14001,31 @@ async function runSweep(state, driver, config) {
13978
14001
  sessions_remaining: remaining,
13979
14002
  ...enumerationReason !== null ? { session_enumeration_reason: enumerationReason } : {}
13980
14003
  };
14004
+ const protectedForReclaim = driver.protectedSessionIds();
13981
14005
  const reclaimResult = await reclaimSessionDbSpace({
13982
14006
  dbPath: sessionDbPath(),
13983
14007
  chunkPages: SESSION_DB_RECLAIM_CHUNK_PAGES,
13984
14008
  pageCeiling: SESSION_DB_RECLAIM_PAGE_CEILING,
13985
14009
  timeBudgetMs: SESSION_DB_RECLAIM_TIME_BUDGET_MS,
13986
- allowFullVacuum: protectedNow.size === 0 && !state.sessionDbProvenanceAnomaly
14010
+ hasLiveTurn: protectedForReclaim.size > 0,
14011
+ hasProvenanceAnomaly: state.sessionDbProvenanceAnomaly
13987
14012
  });
13988
14013
  if (reclaimResult.ok) {
13989
14014
  state.sessionStoreHealth.observeWritable();
13990
14015
  const beforeMib = (reclaimResult.beforeBytes / 1024 / 1024).toFixed(1);
13991
14016
  const afterMib = (reclaimResult.afterBytes / 1024 / 1024).toFixed(1);
13992
14017
  const checkpointNote = reclaimResult.checkpoint.busy ? ` (on-disk file truncation deferred: checkpoint busy, ${reclaimResult.checkpoint.log} WAL frames pending)` : "";
14018
+ const loopElapsedMs = Math.max(
14019
+ 0,
14020
+ reclaimResult.elapsedMs - reclaimResult.checkpointElapsedMs
14021
+ );
14022
+ const reclaimIsSlow = reclaimResult.elapsedMs >= 4 * SESSION_DB_RECLAIM_TIME_BUDGET_MS;
14023
+ const perPageNote = reclaimResult.pagesReclaimed > 0 ? `, per-page ${(loopElapsedMs / reclaimResult.pagesReclaimed).toFixed(2)} ms/page` : "";
14024
+ const slowReclaimNote = reclaimIsSlow ? ` (slow reclaim: total elapsed ${reclaimResult.elapsedMs} ms, checkpoint ${reclaimResult.checkpointElapsedMs} ms, loop ${loopElapsedMs} ms, budget ${SESSION_DB_RECLAIM_TIME_BUDGET_MS} ms${perPageNote})` : "";
13993
14025
  logSessionCleanupActivity(state, "sweep", {
13994
14026
  type: "info",
13995
- message: `Session cleanup: reclaimed session-db space (${reclaimResult.mode}): ${beforeMib} MiB -> ${afterMib} MiB (stopped by ${reclaimResult.stoppedBy}; freelist ${reclaimResult.freelistBefore} -> ${reclaimResult.freelistAfter} pages)` + checkpointNote,
14027
+ level: reclaimIsSlow ? "warn" : "info",
14028
+ message: `Session cleanup: reclaimed session-db space (${reclaimResult.mode}): ${beforeMib} MiB -> ${afterMib} MiB (stopped by ${reclaimResult.stoppedBy}; freelist ${reclaimResult.freelistBefore} -> ${reclaimResult.freelistAfter} pages)` + checkpointNote + slowReclaimNote,
13996
14029
  metadata: {
13997
14030
  outcome: "reclaimed",
13998
14031
  mode: reclaimResult.mode,
@@ -14005,6 +14038,7 @@ async function runSweep(state, driver, config) {
14005
14038
  freelist_after: reclaimResult.freelistAfter,
14006
14039
  pages_reclaimed: reclaimResult.pagesReclaimed,
14007
14040
  reclaim_elapsed_ms: reclaimResult.elapsedMs,
14041
+ checkpoint_elapsed_ms: reclaimResult.checkpointElapsedMs,
14008
14042
  ...sessionMetadata
14009
14043
  }
14010
14044
  });
@@ -14757,22 +14791,21 @@ async function run(options) {
14757
14791
  );
14758
14792
  }
14759
14793
  }
14760
- if (options.restoreRunnerCredentials) {
14761
- log2(state, "Restoring runner credentials before starting OpenCode");
14762
- const credentialContext = {
14763
- env: process.env,
14764
- log: (message, level = "info") => {
14765
- if (level === "error") {
14766
- logActivity(state, { type: "error", error: message });
14767
- } else {
14768
- logActivity(state, { type: "info", level, message });
14769
- }
14794
+ const credentialContext = {
14795
+ env: process.env,
14796
+ log: (message, level = "info") => {
14797
+ if (level === "error") {
14798
+ logActivity(state, { type: "error", error: message });
14799
+ } else {
14800
+ logActivity(state, { type: "info", level, message });
14770
14801
  }
14771
- };
14772
- const githubTokenPopulated = await installRunnerSecret(credentialContext);
14802
+ }
14803
+ };
14804
+ const githubTokenPopulated = await installRunnerSecret(credentialContext);
14805
+ if (options.restoreRunnerCredentials) {
14773
14806
  await restoreCredentialStores(credentialContext);
14774
- if (githubTokenPopulated) await configureGitHubAccess(credentialContext);
14775
14807
  }
14808
+ if (githubTokenPopulated) await configureGitHubAccess(credentialContext);
14776
14809
  state.credentialSync?.arm();
14777
14810
  const openCodeActivityForwarder = createOpenCodeActivityForwarder(
14778
14811
  () => ({