jinzd-ai-cli 0.4.278 → 0.4.280

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.
Files changed (34) hide show
  1. package/dist/{batch-7Y4NAA6N.js → batch-F27NOTWC.js} +2 -2
  2. package/dist/{chunk-LTZFUYBT.js → chunk-B3FHA6IN.js} +3 -3
  3. package/dist/{chunk-WOXIKQRI.js → chunk-CP5LAA52.js} +4 -4
  4. package/dist/{chunk-2BYQP6JX.js → chunk-EOP775JU.js} +1 -1
  5. package/dist/{chunk-JJCNNQTU.js → chunk-IIO2SMEJ.js} +354 -3
  6. package/dist/{chunk-H7QC5VMQ.js → chunk-LPZNOYRJ.js} +1 -1
  7. package/dist/{chunk-LOXEYWC3.js → chunk-NHJ4GHL4.js} +1 -1
  8. package/dist/{chunk-SJCOE4C7.js → chunk-PN42JO74.js} +1 -1
  9. package/dist/{chunk-LXXQTWT2.js → chunk-PUC277TH.js} +1 -1
  10. package/dist/{chunk-4Z6GAYB5.js → chunk-TAIZZY3N.js} +3 -3
  11. package/dist/{chunk-X3722RFA.js → chunk-UBPRUSAF.js} +1 -1
  12. package/dist/{chunk-L3CPM472.js → chunk-UMWDNNPS.js} +1 -1
  13. package/dist/{chunk-RFSKPCYC.js → chunk-V7EZ4SDC.js} +1 -1
  14. package/dist/{chunk-SB4XONS4.js → chunk-VQCFEA4Z.js} +1 -1
  15. package/dist/{ci-WDF2CYR4.js → ci-HJ4OVHCM.js} +4 -4
  16. package/dist/{ci-format-7B5VAZGA.js → ci-format-NKJRZ3QI.js} +2 -2
  17. package/dist/{constants-DC3TNLTL.js → constants-6LCZOBJC.js} +1 -1
  18. package/dist/{doctor-cli-CDDG5XOY.js → doctor-cli-7JGPC5G4.js} +4 -4
  19. package/dist/electron-server.js +525 -140
  20. package/dist/{hub-TO7ODOIA.js → hub-NX7HYN7V.js} +1 -1
  21. package/dist/index.js +151 -429
  22. package/dist/{persistent-memory-JCENBMCJ.js → persistent-memory-E6WECUTW.js} +2 -2
  23. package/dist/{persistent-memory-BU63CSGK.js → persistent-memory-MHHX7F25.js} +2 -2
  24. package/dist/{pr-GVSZYX6I.js → pr-GLUFBQLI.js} +4 -4
  25. package/dist/{run-tests-2Q5MJHXB.js → run-tests-LWAFPVS3.js} +2 -2
  26. package/dist/{run-tests-R4IQS6IF.js → run-tests-YPJDOEJA.js} +2 -2
  27. package/dist/{server-KAURBKFI.js → server-CXXYIPMU.js} +226 -145
  28. package/dist/{server-WXLE53HG.js → server-P6DI27CY.js} +5 -5
  29. package/dist/{task-orchestrator-RJ6FXYY5.js → task-orchestrator-FW4LBPTS.js} +5 -5
  30. package/dist/{usage-V3R7DA7M.js → usage-CJUHQDT2.js} +2 -2
  31. package/dist/web/client/app.js +14 -2
  32. package/dist/web/client/app.js.br +0 -0
  33. package/dist/web/client/app.js.gz +0 -0
  34. package/package.json +1 -1
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ConfigManager
4
- } from "./chunk-2BYQP6JX.js";
4
+ } from "./chunk-EOP775JU.js";
5
5
  import "./chunk-TU3L3PW7.js";
6
6
  import {
7
7
  atomicWriteFileSync
8
8
  } from "./chunk-IW3Q7AE5.js";
9
- import "./chunk-X3722RFA.js";
9
+ import "./chunk-UBPRUSAF.js";
10
10
 
11
11
  // src/cli/batch.ts
12
12
  import Anthropic from "@anthropic-ai/sdk";
@@ -8,13 +8,13 @@ import {
8
8
  listHooks,
9
9
  listInstalledPlugins,
10
10
  resetStats
11
- } from "./chunk-L3CPM472.js";
11
+ } from "./chunk-UMWDNNPS.js";
12
12
  import {
13
13
  ProviderRegistry
14
14
  } from "./chunk-UGY5SVNX.js";
15
15
  import {
16
16
  ConfigManager
17
- } from "./chunk-2BYQP6JX.js";
17
+ } from "./chunk-EOP775JU.js";
18
18
  import {
19
19
  getGitRoot
20
20
  } from "./chunk-HOSJZMQS.js";
@@ -26,7 +26,7 @@ import {
26
26
  MCP_PROJECT_CONFIG_NAME,
27
27
  MEMORY_FILE_NAME,
28
28
  VERSION
29
- } from "./chunk-X3722RFA.js";
29
+ } from "./chunk-UBPRUSAF.js";
30
30
 
31
31
  // src/diagnostics/doctor-report.ts
32
32
  import { existsSync as existsSync3, statSync as statSync2 } from "fs";
@@ -11,7 +11,7 @@ import {
11
11
  searchPersistentMemories,
12
12
  touchMemoryReferences,
13
13
  updateMemoryEntry
14
- } from "./chunk-RFSKPCYC.js";
14
+ } from "./chunk-V7EZ4SDC.js";
15
15
  import {
16
16
  indexProject
17
17
  } from "./chunk-4DEMGCK4.js";
@@ -30,7 +30,7 @@ import {
30
30
  runHook,
31
31
  runLifecycleHooks,
32
32
  runTool
33
- } from "./chunk-L3CPM472.js";
33
+ } from "./chunk-UMWDNNPS.js";
34
34
  import {
35
35
  buildTruncatedArgumentsError,
36
36
  getDangerLevel,
@@ -50,14 +50,14 @@ import {
50
50
  } from "./chunk-4BKXL7SM.js";
51
51
  import {
52
52
  runTestsTool
53
- } from "./chunk-SB4XONS4.js";
53
+ } from "./chunk-VQCFEA4Z.js";
54
54
  import {
55
55
  CONFIG_DIR_NAME,
56
56
  DEFAULT_MAX_TOOL_OUTPUT_CHARS_CAP,
57
57
  SUBAGENT_ALLOWED_TOOLS,
58
58
  SUBAGENT_DEFAULT_MAX_ROUNDS,
59
59
  SUBAGENT_MAX_ROUNDS_LIMIT
60
- } from "./chunk-X3722RFA.js";
60
+ } from "./chunk-UBPRUSAF.js";
61
61
 
62
62
  // src/tools/shell-pool.ts
63
63
  import { spawn as spawn2 } from "child_process";
@@ -11,7 +11,7 @@ import {
11
11
  CONFIG_FILE_NAME,
12
12
  HISTORY_DIR_NAME,
13
13
  PLUGINS_DIR_NAME
14
- } from "./chunk-X3722RFA.js";
14
+ } from "./chunk-UBPRUSAF.js";
15
15
 
16
16
  // src/config/config-manager.ts
17
17
  import { readFileSync, existsSync, mkdirSync } from "fs";
@@ -5,11 +5,14 @@ import {
5
5
  import {
6
6
  estimateTokens,
7
7
  truncateForPersist
8
- } from "./chunk-WOXIKQRI.js";
8
+ } from "./chunk-CP5LAA52.js";
9
9
  import {
10
10
  isMemoryExpired,
11
11
  isMemoryStale
12
- } from "./chunk-RFSKPCYC.js";
12
+ } from "./chunk-V7EZ4SDC.js";
13
+ import {
14
+ getContentText
15
+ } from "./chunk-CGDYO52A.js";
13
16
  import {
14
17
  isCleanDocumentBody,
15
18
  stripOuterCodeFence
@@ -27,7 +30,7 @@ import {
27
30
  MCP_PROTOCOL_VERSION,
28
31
  MCP_TOOL_PREFIX,
29
32
  VERSION
30
- } from "./chunk-X3722RFA.js";
33
+ } from "./chunk-UBPRUSAF.js";
31
34
 
32
35
  // src/mcp/client.ts
33
36
  import { spawn } from "child_process";
@@ -979,6 +982,110 @@ function filterMemoryEntries(entries, filters) {
979
982
  return { entries: out, applied };
980
983
  }
981
984
 
985
+ // src/core/session-export.ts
986
+ function parseExportArgs(args) {
987
+ let format = "md";
988
+ let outFile = null;
989
+ for (const arg of args) {
990
+ if (arg === "md" || arg === "json") format = arg;
991
+ else if (arg) outFile = arg;
992
+ }
993
+ return { format, outFile };
994
+ }
995
+ function defaultExportFilename(session, format) {
996
+ const dateTag = session.created.toISOString().slice(0, 10);
997
+ return `session-${dateTag}-${session.id.slice(0, 8)}.${format === "json" ? "json" : "md"}`;
998
+ }
999
+ function markdownHeading(msg) {
1000
+ switch (msg.role) {
1001
+ case "user":
1002
+ return "## \u{1F464} You";
1003
+ case "assistant":
1004
+ return "## \u{1F916} Assistant";
1005
+ case "tool":
1006
+ return `### \u{1F527} Tool result: ${msg.toolName ?? "tool"}${msg.isError ? " (error)" : ""}`;
1007
+ default:
1008
+ return `## \u2699 ${msg.role}`;
1009
+ }
1010
+ }
1011
+ function buildSessionExport(session, format, outFile) {
1012
+ const filename = outFile || defaultExportFilename(session, format);
1013
+ if (format === "json") {
1014
+ const payload = session.toJSON ? session.toJSON() : {
1015
+ id: session.id,
1016
+ title: session.title ?? null,
1017
+ provider: session.provider,
1018
+ model: session.model,
1019
+ created: session.created.toISOString(),
1020
+ messages: session.messages
1021
+ };
1022
+ return { filename, content: JSON.stringify(payload, null, 2), messageCount: session.messages.length };
1023
+ }
1024
+ const dateStr = session.created.toISOString().replace("T", " ").slice(0, 19);
1025
+ let md = `# ${session.title ?? "Conversation Export"}
1026
+
1027
+ `;
1028
+ md += `| Field | Value |
1029
+ |----------|-------|
1030
+ `;
1031
+ md += `| Provider | ${session.provider} |
1032
+ `;
1033
+ md += `| Model | ${session.model} |
1034
+ `;
1035
+ md += `| Date | ${dateStr} |
1036
+ `;
1037
+ md += `| Session | ${session.id.slice(0, 8)} |
1038
+
1039
+ ---
1040
+
1041
+ `;
1042
+ for (const msg of session.messages) {
1043
+ const text = getContentText(msg.content);
1044
+ md += `${markdownHeading(msg)}
1045
+
1046
+ `;
1047
+ if (text.trim()) md += `${text}
1048
+
1049
+ `;
1050
+ if (msg.toolCalls && msg.toolCalls.length > 0) {
1051
+ for (const tc of msg.toolCalls) {
1052
+ md += `\`\`\`json
1053
+ ${JSON.stringify({ tool: tc.name, arguments: tc.arguments ?? {} }, null, 2)}
1054
+ \`\`\`
1055
+
1056
+ `;
1057
+ }
1058
+ }
1059
+ md += `---
1060
+
1061
+ `;
1062
+ }
1063
+ return { filename, content: md, messageCount: session.messages.length };
1064
+ }
1065
+ function parseCheckpointCommand(args) {
1066
+ const sub = args[0]?.toLowerCase();
1067
+ if (!sub || sub === "list") return { kind: "list" };
1068
+ const name = args.slice(1).join(" ").trim();
1069
+ if (sub === "save" || sub === "restore" || sub === "delete") {
1070
+ if (!name) return { kind: "usage", message: `Usage: /checkpoint ${sub} <name>` };
1071
+ return { kind: sub, name };
1072
+ }
1073
+ return { kind: "unknown", message: `Unknown subcommand: ${sub}. Use save/restore/list/delete.` };
1074
+ }
1075
+ function formatCheckpointList(checkpoints) {
1076
+ if (checkpoints.length === 0) {
1077
+ return ["No checkpoints. Use /checkpoint save <name> to create one."];
1078
+ }
1079
+ return [
1080
+ `Checkpoints (${checkpoints.length}):`,
1081
+ ...checkpoints.map((cp) => ` ${cp.name.padEnd(20)} msg #${cp.messageIndex} ${cp.timestamp.toLocaleString()}`)
1082
+ ];
1083
+ }
1084
+ var checkpointSavedMessage = (name, messageCount) => `\u2713 Checkpoint "${name}" saved at message #${messageCount}`;
1085
+ var checkpointRestoredMessage = (name, messageCount) => `\u2713 Restored to checkpoint "${name}" (${messageCount} messages, token usage reset)`;
1086
+ var checkpointDeletedMessage = (name) => `\u2713 Deleted checkpoint "${name}"`;
1087
+ var checkpointNotFoundMessage = (name) => `Checkpoint "${name}" not found.`;
1088
+
982
1089
  // src/session/tool-history.ts
983
1090
  var SESSION_SIZE_LIMIT = 2 * 1024 * 1024;
984
1091
  function persistToolRound(session, toolCalls, toolResults, opts) {
@@ -1554,6 +1661,232 @@ function routeDecisionRows(message, currentModel, decision) {
1554
1661
  return rows;
1555
1662
  }
1556
1663
 
1664
+ // src/core/session-command.ts
1665
+ var DEFAULT_SESSION_LIST_LIMIT = 50;
1666
+ function parseSessionListArgs(args) {
1667
+ let limit = DEFAULT_SESSION_LIST_LIMIT;
1668
+ let all = false;
1669
+ const filter = {};
1670
+ const warnings = [];
1671
+ let search = null;
1672
+ let days = null;
1673
+ let since = null;
1674
+ let sort = { field: "updated", order: "desc" };
1675
+ let json = false;
1676
+ let stale = null;
1677
+ let verbose = false;
1678
+ for (let i = 1; i < args.length; i++) {
1679
+ const a = args[i];
1680
+ if (a === "--all" || a === "-a") {
1681
+ all = true;
1682
+ } else if ((a === "--limit" || a === "-n") && i + 1 < args.length) {
1683
+ const n = Number(args[i + 1]);
1684
+ if (Number.isFinite(n) && n > 0) {
1685
+ limit = n;
1686
+ i++;
1687
+ }
1688
+ } else if (a === "--filter" && i + 1 < args.length) {
1689
+ const val = args[++i];
1690
+ const eq = val.indexOf("=");
1691
+ if (eq > 0) {
1692
+ const key = val.slice(0, eq);
1693
+ const vals = val.slice(eq + 1).split(",").map((s) => s.trim().toLowerCase());
1694
+ if (key === "provider") filter.provider = vals;
1695
+ else if (key === "model") filter.model = vals;
1696
+ else if (key === "messages") {
1697
+ const n = Number(vals[0]);
1698
+ if (Number.isFinite(n) && n >= 0) filter.messages = n;
1699
+ else warnings.push(`Invalid filter value for "messages": expected a non-negative integer, got "${vals[0]}"`);
1700
+ } else {
1701
+ warnings.push(`Unknown filter key: "${key}". Supported keys: provider, model, messages`);
1702
+ }
1703
+ } else {
1704
+ warnings.push(`Invalid --filter syntax: "${val}". Expected key=value`);
1705
+ }
1706
+ } else if ((a === "--search" || a === "-s") && i + 1 < args.length) {
1707
+ search = args[++i];
1708
+ } else if (a === "--days" && i + 1 < args.length) {
1709
+ const n = Number(args[++i]);
1710
+ if (Number.isFinite(n) && n > 0) days = n;
1711
+ } else if (a === "--since" && i + 1 < args.length) {
1712
+ since = args[++i];
1713
+ } else if (a === "--sort" && i + 1 < args.length) {
1714
+ const sv = args[++i];
1715
+ const colon = sv.indexOf(":");
1716
+ const field = colon > 0 ? sv.slice(0, colon) : sv;
1717
+ const order = colon > 0 ? sv.slice(colon + 1) : "desc";
1718
+ if (field === "updated" || field === "created" || field === "messages" || field === "size") {
1719
+ sort = { field, order: order === "asc" ? "asc" : "desc" };
1720
+ }
1721
+ } else if (a === "--json") {
1722
+ json = true;
1723
+ } else if (a === "--verbose" || a === "-v") {
1724
+ verbose = true;
1725
+ } else if (a === "--stale" && i + 1 < args.length) {
1726
+ const n = Number(args[++i]);
1727
+ if (Number.isFinite(n) && n > 0) stale = n;
1728
+ }
1729
+ }
1730
+ if (all) limit = -1;
1731
+ return { limit, all, filter, search, days, since, sort, json, stale, verbose, warnings };
1732
+ }
1733
+ function sessionListNeedsFileSize(opts) {
1734
+ return opts.verbose || opts.sort.field === "size";
1735
+ }
1736
+ function selectSessions(sessions, opts, now = Date.now()) {
1737
+ let matched = sessions;
1738
+ const hasFilters = !!opts.filter.provider || !!opts.filter.model || opts.filter.messages !== void 0;
1739
+ const hasSearch = !!opts.search;
1740
+ const hasTimeFilter = opts.days !== null || opts.since !== null;
1741
+ const hasStale = opts.stale !== null;
1742
+ if (hasFilters) {
1743
+ const p = opts.filter.provider;
1744
+ const m = opts.filter.model;
1745
+ const msg = opts.filter.messages;
1746
+ matched = matched.filter((s) => {
1747
+ if (p && !p.includes(s.provider.toLowerCase())) return false;
1748
+ if (m && !m.some((kw) => s.model.toLowerCase().includes(kw))) return false;
1749
+ if (msg !== void 0 && s.messageCount !== msg) return false;
1750
+ return true;
1751
+ });
1752
+ }
1753
+ if (hasSearch) {
1754
+ const q = opts.search.toLowerCase();
1755
+ matched = matched.filter(
1756
+ (s) => (s.title ?? "").toLowerCase().includes(q) || s.id.toLowerCase().includes(q)
1757
+ );
1758
+ }
1759
+ if (hasTimeFilter) {
1760
+ let cutoff = 0;
1761
+ if (opts.since) cutoff = new Date(opts.since).getTime();
1762
+ else if (opts.days !== null) cutoff = now - opts.days * 24 * 60 * 60 * 1e3;
1763
+ if (!Number.isNaN(cutoff)) {
1764
+ matched = matched.filter((s) => s.updated.getTime() >= cutoff);
1765
+ }
1766
+ }
1767
+ const staleCutoff = hasStale ? now - opts.stale * 24 * 60 * 60 * 1e3 : null;
1768
+ if (staleCutoff !== null) {
1769
+ matched = matched.filter((s) => s.updated.getTime() < staleCutoff);
1770
+ }
1771
+ const defaultSort = opts.sort.field === "updated" && opts.sort.order === "desc";
1772
+ if (!defaultSort) {
1773
+ const mul = opts.sort.order === "asc" ? 1 : -1;
1774
+ matched = [...matched].sort((a, b) => {
1775
+ switch (opts.sort.field) {
1776
+ case "created":
1777
+ return (a.created.getTime() - b.created.getTime()) * mul;
1778
+ case "messages":
1779
+ return (a.messageCount - b.messageCount) * mul;
1780
+ case "size":
1781
+ return ((a.fileSize ?? 0) - (b.fileSize ?? 0)) * mul;
1782
+ default:
1783
+ return (a.updated.getTime() - b.updated.getTime()) * mul;
1784
+ }
1785
+ });
1786
+ }
1787
+ const filterTags = [];
1788
+ if (hasFilters) filterTags.push("filtered");
1789
+ if (hasSearch) filterTags.push("searched");
1790
+ if (hasTimeFilter) filterTags.push("time-limited");
1791
+ if (hasStale) filterTags.push(`stale >${opts.stale}d`);
1792
+ return {
1793
+ matched,
1794
+ shown: opts.limit > 0 ? matched.slice(0, opts.limit) : matched,
1795
+ totalCount: matched.length,
1796
+ totalMessages: matched.reduce((sum, s) => sum + s.messageCount, 0),
1797
+ staleCutoff,
1798
+ filterTags,
1799
+ needsFileSize: sessionListNeedsFileSize(opts)
1800
+ };
1801
+ }
1802
+ function sessionListSummary(view) {
1803
+ const tag = view.filterTags.length > 0 ? ` (${view.filterTags.join(", ")})` : "";
1804
+ return `${view.shown.length} of ${view.totalCount} sessions${tag} \xB7 ${view.totalMessages} messages total`;
1805
+ }
1806
+ function sessionListJsonRow(s, includeFileSize) {
1807
+ return {
1808
+ id: s.id,
1809
+ title: s.title ?? null,
1810
+ provider: s.provider,
1811
+ model: s.model,
1812
+ messageCount: s.messageCount,
1813
+ created: s.created.toISOString(),
1814
+ updated: s.updated.toISOString(),
1815
+ ...includeFileSize ? { fileSize: s.fileSize } : {},
1816
+ ...s.branchCount !== void 0 ? { branchCount: s.branchCount, activeBranch: s.activeBranch } : {}
1817
+ };
1818
+ }
1819
+ function resolveSessionRef(sessions, prefix, policy) {
1820
+ const matches2 = sessions.filter((s) => s.id.startsWith(prefix));
1821
+ if (matches2.length === 0) {
1822
+ return { status: "not-found", message: `Session '${prefix}' not found.` };
1823
+ }
1824
+ if (matches2.length > 1 && policy === "strict") {
1825
+ return {
1826
+ status: "ambiguous",
1827
+ matches: matches2,
1828
+ message: `Ambiguous prefix '${prefix}' matches ${matches2.length} sessions \u2014 be more specific:`
1829
+ };
1830
+ }
1831
+ return {
1832
+ status: "ok",
1833
+ match: matches2[0],
1834
+ ambiguousWith: matches2.length > 1 ? matches2 : [],
1835
+ message: matches2.length > 1 ? `\u26A0 Ambiguous prefix '${prefix}' matches ${matches2.length} sessions \u2014 loading most recent:` : void 0
1836
+ };
1837
+ }
1838
+ function formatSessionSummaryLine(s, titleWidth = 60) {
1839
+ const title = s.title ?? "(untitled)";
1840
+ const shown = title.length > titleWidth ? `${title.slice(0, titleWidth - 1)}\u2026` : title;
1841
+ return `${s.id.slice(0, 12)} ${s.provider}/${s.model} ${String(s.messageCount).padStart(4)} msgs ${s.updated.toISOString().slice(0, 10)} ${shown}`;
1842
+ }
1843
+ function parseBatchDeleteArgs(args) {
1844
+ let messages;
1845
+ let dryRun = false;
1846
+ for (let i = 1; i < args.length; i++) {
1847
+ if (args[i] === "--filter" && i + 1 < args.length) {
1848
+ const val = args[++i];
1849
+ const eq = val.indexOf("=");
1850
+ if (eq <= 0) {
1851
+ return { dryRun, error: `Invalid --filter syntax: "${val}". Expected key=value (e.g., messages=0)` };
1852
+ }
1853
+ const key = val.slice(0, eq);
1854
+ const vals = val.slice(eq + 1).split(",").map((s) => s.trim().toLowerCase());
1855
+ if (key !== "messages") {
1856
+ return { dryRun, error: `Unsupported filter key for delete: "${key}". Only "messages" is supported.` };
1857
+ }
1858
+ const n = Number(vals[0]);
1859
+ if (!Number.isFinite(n) || n < 0) {
1860
+ return { dryRun, error: `Invalid filter value for "messages": expected a non-negative integer, got "${vals[0]}"` };
1861
+ }
1862
+ messages = n;
1863
+ } else if (args[i] === "--dry-run") {
1864
+ dryRun = true;
1865
+ }
1866
+ }
1867
+ if (messages === void 0) {
1868
+ return { dryRun, error: "Usage: /session delete --filter messages=N [--dry-run]" };
1869
+ }
1870
+ return { messages, dryRun };
1871
+ }
1872
+ function parseCleanArgs(args) {
1873
+ let staleDays = 90;
1874
+ let dryRun = false;
1875
+ for (let i = 1; i < args.length; i++) {
1876
+ if (args[i] === "--stale" && i + 1 < args.length) {
1877
+ const n = Number(args[++i]);
1878
+ if (Number.isFinite(n) && n > 0) staleDays = n;
1879
+ } else if (args[i] === "--dry-run") {
1880
+ dryRun = true;
1881
+ }
1882
+ }
1883
+ return { staleDays, dryRun };
1884
+ }
1885
+ function selectStaleSessions(sessions, staleDays, now = Date.now()) {
1886
+ const cutoff = now - staleDays * 24 * 60 * 60 * 1e3;
1887
+ return sessions.filter((s) => s.updated.getTime() < cutoff);
1888
+ }
1889
+
1557
1890
  // src/core/profile-command.ts
1558
1891
  var PROFILE_FIELDS = ["name", "nickname", "role", "bio", "interests", "locale", "extra"];
1559
1892
  function stripSurroundingQuotes(value) {
@@ -1723,6 +2056,16 @@ export {
1723
2056
  routingEmptyRulesNote,
1724
2057
  describeRouting,
1725
2058
  routeDecisionRows,
2059
+ parseSessionListArgs,
2060
+ sessionListNeedsFileSize,
2061
+ selectSessions,
2062
+ sessionListSummary,
2063
+ sessionListJsonRow,
2064
+ resolveSessionRef,
2065
+ formatSessionSummaryLine,
2066
+ parseBatchDeleteArgs,
2067
+ parseCleanArgs,
2068
+ selectStaleSessions,
1726
2069
  applyProfileCommand,
1727
2070
  readGitDiff,
1728
2071
  scanDirTree,
@@ -1730,6 +2073,14 @@ export {
1730
2073
  buildInitPrompt,
1731
2074
  parseMemoryShowFilters,
1732
2075
  filterMemoryEntries,
2076
+ parseExportArgs,
2077
+ buildSessionExport,
2078
+ parseCheckpointCommand,
2079
+ formatCheckpointList,
2080
+ checkpointSavedMessage,
2081
+ checkpointRestoredMessage,
2082
+ checkpointDeletedMessage,
2083
+ checkpointNotFoundMessage,
1733
2084
  buildSessionCostReport,
1734
2085
  costSourceNote,
1735
2086
  parseSimpleYaml,
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  VERSION
4
- } from "./chunk-X3722RFA.js";
4
+ } from "./chunk-UBPRUSAF.js";
5
5
 
6
6
  // src/cli/ci-format.ts
7
7
  var DEFAULT_CI_THRESHOLDS = {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  TEST_TIMEOUT
3
- } from "./chunk-SJCOE4C7.js";
3
+ } from "./chunk-PN42JO74.js";
4
4
 
5
5
  // src/tools/builtin/run-tests.ts
6
6
  import { execSync, spawnSync } from "child_process";
@@ -1,5 +1,5 @@
1
1
  // src/core/constants.ts
2
- var VERSION = "0.4.278";
2
+ var VERSION = "0.4.280";
3
3
  var APP_NAME = "ai-cli";
4
4
  var CONFIG_DIR_NAME = ".aicli";
5
5
  var CONFIG_FILE_NAME = "config.json";
@@ -6,7 +6,7 @@ import {
6
6
  MEMORY_FILE_NAME,
7
7
  MEMORY_MAX_CHARS,
8
8
  MEMORY_STORE_FILE_NAME
9
- } from "./chunk-SJCOE4C7.js";
9
+ } from "./chunk-PN42JO74.js";
10
10
  import {
11
11
  atomicWriteFileSync
12
12
  } from "./chunk-6BUTA5VW.js";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  evaluateCiGate,
4
4
  normalizeCiThresholds
5
- } from "./chunk-H7QC5VMQ.js";
5
+ } from "./chunk-LPZNOYRJ.js";
6
6
  import {
7
7
  buildReviewPrompt,
8
8
  buildSecurityReviewPrompt,
@@ -16,10 +16,10 @@ import {
16
16
  } from "./chunk-UGY5SVNX.js";
17
17
  import {
18
18
  ConfigManager
19
- } from "./chunk-2BYQP6JX.js";
19
+ } from "./chunk-EOP775JU.js";
20
20
  import {
21
21
  VERSION
22
- } from "./chunk-X3722RFA.js";
22
+ } from "./chunk-UBPRUSAF.js";
23
23
 
24
24
  // src/cli/ci.ts
25
25
  import { execFileSync } from "child_process";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/core/constants.ts
4
- var VERSION = "0.4.278";
4
+ var VERSION = "0.4.280";
5
5
  var APP_NAME = "ai-cli";
6
6
  var CONFIG_DIR_NAME = ".aicli";
7
7
  var CONFIG_FILE_NAME = "config.json";
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  CONFIG_DIR_NAME,
7
7
  PLUGINS_DIR_NAME
8
- } from "./chunk-X3722RFA.js";
8
+ } from "./chunk-UBPRUSAF.js";
9
9
 
10
10
  // src/diagnostics/tool-stats.ts
11
11
  import { existsSync, readFileSync, mkdirSync } from "fs";
@@ -13,7 +13,7 @@ import {
13
13
  MEMORY_FILE_NAME,
14
14
  MEMORY_MAX_CHARS,
15
15
  MEMORY_STORE_FILE_NAME
16
- } from "./chunk-X3722RFA.js";
16
+ } from "./chunk-UBPRUSAF.js";
17
17
 
18
18
  // src/memory/persistent-memory.ts
19
19
  import { copyFileSync, existsSync, mkdirSync, readFileSync, statSync } from "fs";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  TEST_TIMEOUT
4
- } from "./chunk-X3722RFA.js";
4
+ } from "./chunk-UBPRUSAF.js";
5
5
 
6
6
  // src/tools/builtin/run-tests.ts
7
7
  import { execSync, spawnSync } from "child_process";
@@ -3,16 +3,16 @@ import {
3
3
  CI_COMMENT_MARKER,
4
4
  countSeverity,
5
5
  runCi
6
- } from "./chunk-4Z6GAYB5.js";
7
- import "./chunk-H7QC5VMQ.js";
6
+ } from "./chunk-TAIZZY3N.js";
7
+ import "./chunk-LPZNOYRJ.js";
8
8
  import "./chunk-HLWUDRBO.js";
9
9
  import "./chunk-6YZEZFX5.js";
10
10
  import "./chunk-UGY5SVNX.js";
11
- import "./chunk-2BYQP6JX.js";
11
+ import "./chunk-EOP775JU.js";
12
12
  import "./chunk-TEXT4DAT.js";
13
13
  import "./chunk-TU3L3PW7.js";
14
14
  import "./chunk-IW3Q7AE5.js";
15
- import "./chunk-X3722RFA.js";
15
+ import "./chunk-UBPRUSAF.js";
16
16
  export {
17
17
  CI_COMMENT_MARKER,
18
18
  countSeverity,
@@ -6,8 +6,8 @@ import {
6
6
  formatCiResult,
7
7
  formatCiSarif,
8
8
  normalizeCiThresholds
9
- } from "./chunk-H7QC5VMQ.js";
10
- import "./chunk-X3722RFA.js";
9
+ } from "./chunk-LPZNOYRJ.js";
10
+ import "./chunk-UBPRUSAF.js";
11
11
  export {
12
12
  DEFAULT_CI_THRESHOLDS,
13
13
  detectCiGateSignals,
@@ -38,7 +38,7 @@ import {
38
38
  TEST_TIMEOUT,
39
39
  VERSION,
40
40
  buildUserIdentityPrompt
41
- } from "./chunk-X3722RFA.js";
41
+ } from "./chunk-UBPRUSAF.js";
42
42
  export {
43
43
  AGENTIC_BEHAVIOR_GUIDELINE,
44
44
  APP_NAME,
@@ -2,15 +2,15 @@
2
2
  import {
3
3
  formatDoctorReport,
4
4
  runDoctorCli
5
- } from "./chunk-LTZFUYBT.js";
6
- import "./chunk-L3CPM472.js";
5
+ } from "./chunk-B3FHA6IN.js";
6
+ import "./chunk-UMWDNNPS.js";
7
7
  import "./chunk-UGY5SVNX.js";
8
- import "./chunk-2BYQP6JX.js";
8
+ import "./chunk-EOP775JU.js";
9
9
  import "./chunk-TEXT4DAT.js";
10
10
  import "./chunk-TU3L3PW7.js";
11
11
  import "./chunk-HOSJZMQS.js";
12
12
  import "./chunk-IW3Q7AE5.js";
13
- import "./chunk-X3722RFA.js";
13
+ import "./chunk-UBPRUSAF.js";
14
14
  export {
15
15
  formatDoctorReport,
16
16
  runDoctorCli