blun-king-cli 9.1.278 → 9.1.279

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.
@@ -1,10 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  const { randomUUID } = require('node:crypto');
4
- const { mkdir, writeFile } = require('node:fs/promises');
4
+ const { lstat, mkdir, readdir, unlink, writeFile } = require('node:fs/promises');
5
5
  const path = require('node:path');
6
6
 
7
7
  const COMPACTION_HISTORY_DIR = 'conversation-history';
8
+ const COMPACTION_HISTORY_RETENTION_DAYS = 30;
9
+ const MAX_COMPACTION_HISTORY_RETENTION_DAYS = 3650;
10
+ const DAY_MS = 24 * 60 * 60 * 1000;
8
11
  const INLINE_MEDIA_NOTICE = '[inline media payload omitted; original remains in session wire]';
9
12
 
10
13
  async function archiveCompactionHistory(options = {}) {
@@ -17,6 +20,11 @@ async function archiveCompactionHistory(options = {}) {
17
20
  const outputPath = path.join(dir, `compaction-${timestamp}-${id}.md`);
18
21
 
19
22
  await mkdir(dir, { recursive: true, mode: 0o700 });
23
+ await sweepCompactionHistory({
24
+ homedir,
25
+ now,
26
+ retentionDays: options.retentionDays,
27
+ });
20
28
  await writeFile(outputPath, serializeCompactionHistory(messages, { now }), {
21
29
  encoding: 'utf8',
22
30
  flag: 'wx',
@@ -25,6 +33,49 @@ async function archiveCompactionHistory(options = {}) {
25
33
  return outputPath;
26
34
  }
27
35
 
36
+ async function sweepCompactionHistory(options = {}) {
37
+ const homedir = requiredString(options.homedir, 'homedir');
38
+ const now = finiteNumber(options.now, Date.now());
39
+ const retentionDays = options.retentionDays === undefined
40
+ ? resolveCompactionHistoryRetentionDays(process.env.BLUN_COMPACTION_HISTORY_RETENTION_DAYS)
41
+ : resolveCompactionHistoryRetentionDays(options.retentionDays);
42
+ const result = { deleted: 0, failed: 0 };
43
+ if (retentionDays === 0) return result;
44
+ const dir = path.join(homedir, COMPACTION_HISTORY_DIR);
45
+ let entries;
46
+ try {
47
+ entries = await readdir(dir, { withFileTypes: true });
48
+ } catch (error) {
49
+ if (error?.code !== 'ENOENT') result.failed += 1;
50
+ return result;
51
+ }
52
+ const cutoff = now - retentionDays * DAY_MS;
53
+ for (const entry of entries) {
54
+ if (!entry.isFile() || !/^compaction-.*\.md$/u.test(entry.name)) continue;
55
+ const candidate = path.join(dir, entry.name);
56
+ try {
57
+ const info = await lstat(candidate);
58
+ if (!info.isFile() || info.mtimeMs >= cutoff) continue;
59
+ await unlink(candidate);
60
+ result.deleted += 1;
61
+ } catch (error) {
62
+ if (error?.code !== 'ENOENT') result.failed += 1;
63
+ }
64
+ }
65
+ return result;
66
+ }
67
+
68
+ function resolveCompactionHistoryRetentionDays(value) {
69
+ if (value === undefined || value === null || value === '') {
70
+ return COMPACTION_HISTORY_RETENTION_DAYS;
71
+ }
72
+ const parsed = Number(value);
73
+ if (!Number.isInteger(parsed) || parsed < 0 || parsed > MAX_COMPACTION_HISTORY_RETENTION_DAYS) {
74
+ return COMPACTION_HISTORY_RETENTION_DAYS;
75
+ }
76
+ return parsed;
77
+ }
78
+
28
79
  function serializeCompactionHistory(messages, options = {}) {
29
80
  const now = finiteNumber(options.now, Date.now());
30
81
  const lines = [
@@ -106,7 +157,10 @@ function finiteNumber(value, fallback) {
106
157
 
107
158
  module.exports = {
108
159
  COMPACTION_HISTORY_DIR,
160
+ COMPACTION_HISTORY_RETENTION_DAYS,
109
161
  archiveCompactionHistory,
110
162
  buildCompactionArchiveNotice,
163
+ resolveCompactionHistoryRetentionDays,
111
164
  serializeCompactionHistory,
165
+ sweepCompactionHistory,
112
166
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.278",
3
+ "version": "9.1.279",
4
4
  "description": "BLUN CLI - your own AI agent with a Telegram channel. Get it done. With BLUN.",
5
5
  "license": "MIT",
6
6
  "bin": {