@kernel.chat/kbot 3.99.14 → 3.99.15

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/agent.js CHANGED
@@ -1801,6 +1801,10 @@ Always quote file paths that contain spaces. Never reference internal system nam
1801
1801
  // ── Telemetry: session failure ──
1802
1802
  telemetry.emit('session_end', { status: 'failed', error: String(err), toolCallCount });
1803
1803
  telemetry.destroy().catch(() => { });
1804
+ // Mark the checkpoint completed even on error — otherwise the stuck
1805
+ // `in_progress` record will be re-detected on every subsequent launch
1806
+ // and pollute the recovery banner forever.
1807
+ checkpointManager.markCompleted(sessionId).catch(() => { });
1804
1808
  throw err;
1805
1809
  }
1806
1810
  }
@@ -50,6 +50,13 @@ export declare class CheckpointManager {
50
50
  * Updates the most recent checkpoint's status to 'completed'.
51
51
  */
52
52
  markCompleted(sessionId: string): Promise<void>;
53
+ /**
54
+ * Flip any `in_progress` checkpoint older than `staleMs` to `completed`.
55
+ * A live run couldn't possibly still be pending after this cutoff — these
56
+ * are all crashed/killed sessions whose exit path never marked them done.
57
+ * Called on startup so stale checkpoints don't spam the recovery banner.
58
+ */
59
+ expireStaleInProgress(staleMs?: number): Promise<number>;
53
60
  /**
54
61
  * Find all checkpoints with status 'in_progress'.
55
62
  * Returns them sorted by timestamp descending (most recent first).
@@ -91,6 +91,45 @@ export class CheckpointManager {
91
91
  await writeFile(tmpPath, JSON.stringify(checkpoint, null, 2), 'utf-8');
92
92
  await rename(tmpPath, filePath);
93
93
  }
94
+ /**
95
+ * Flip any `in_progress` checkpoint older than `staleMs` to `completed`.
96
+ * A live run couldn't possibly still be pending after this cutoff — these
97
+ * are all crashed/killed sessions whose exit path never marked them done.
98
+ * Called on startup so stale checkpoints don't spam the recovery banner.
99
+ */
100
+ async expireStaleInProgress(staleMs = 30 * 60 * 1000) {
101
+ await this.ensureDir();
102
+ let files;
103
+ try {
104
+ files = await readdir(this.dir);
105
+ }
106
+ catch {
107
+ return 0;
108
+ }
109
+ const cutoff = Date.now() - staleMs;
110
+ let expired = 0;
111
+ for (const file of files) {
112
+ if (!file.endsWith('.json'))
113
+ continue;
114
+ const path = join(this.dir, file);
115
+ const cp = await this.readCheckpoint(path);
116
+ if (!cp)
117
+ continue;
118
+ if (cp.status !== 'in_progress')
119
+ continue;
120
+ if (cp.timestamp >= cutoff)
121
+ continue; // too recent, might still be live
122
+ cp.status = 'completed';
123
+ try {
124
+ const tmpPath = path + '.tmp';
125
+ await writeFile(tmpPath, JSON.stringify(cp, null, 2), 'utf-8');
126
+ await rename(tmpPath, path);
127
+ expired++;
128
+ }
129
+ catch { /* best-effort */ }
130
+ }
131
+ return expired;
132
+ }
94
133
  /**
95
134
  * Find all checkpoints with status 'in_progress'.
96
135
  * Returns them sorted by timestamp descending (most recent first).
package/dist/cli.js CHANGED
@@ -4316,6 +4316,9 @@ async function main() {
4316
4316
  try {
4317
4317
  const { CheckpointManager } = await import('./checkpoint.js');
4318
4318
  const cpManager = new CheckpointManager();
4319
+ // Auto-expire checkpoints older than 30 min that never marked completed —
4320
+ // otherwise crashed sessions linger forever in the recovery banner.
4321
+ await cpManager.expireStaleInProgress().catch(() => 0);
4319
4322
  const incomplete = await cpManager.listIncomplete();
4320
4323
  if (incomplete.length > 0) {
4321
4324
  const latest = incomplete[0];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kernel.chat/kbot",
3
- "version": "3.99.14",
3
+ "version": "3.99.15",
4
4
  "description": "Open-source terminal AI agent. 787+ tools, 35 agents, 20 providers. Dreams, learns, watches your system. Controls your phone. Fully local, fully sovereign. MIT.",
5
5
  "type": "module",
6
6
  "repository": {