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.
- package/dist/{batch-7Y4NAA6N.js → batch-F27NOTWC.js} +2 -2
- package/dist/{chunk-LTZFUYBT.js → chunk-B3FHA6IN.js} +3 -3
- package/dist/{chunk-WOXIKQRI.js → chunk-CP5LAA52.js} +4 -4
- package/dist/{chunk-2BYQP6JX.js → chunk-EOP775JU.js} +1 -1
- package/dist/{chunk-JJCNNQTU.js → chunk-IIO2SMEJ.js} +354 -3
- package/dist/{chunk-H7QC5VMQ.js → chunk-LPZNOYRJ.js} +1 -1
- package/dist/{chunk-LOXEYWC3.js → chunk-NHJ4GHL4.js} +1 -1
- package/dist/{chunk-SJCOE4C7.js → chunk-PN42JO74.js} +1 -1
- package/dist/{chunk-LXXQTWT2.js → chunk-PUC277TH.js} +1 -1
- package/dist/{chunk-4Z6GAYB5.js → chunk-TAIZZY3N.js} +3 -3
- package/dist/{chunk-X3722RFA.js → chunk-UBPRUSAF.js} +1 -1
- package/dist/{chunk-L3CPM472.js → chunk-UMWDNNPS.js} +1 -1
- package/dist/{chunk-RFSKPCYC.js → chunk-V7EZ4SDC.js} +1 -1
- package/dist/{chunk-SB4XONS4.js → chunk-VQCFEA4Z.js} +1 -1
- package/dist/{ci-WDF2CYR4.js → ci-HJ4OVHCM.js} +4 -4
- package/dist/{ci-format-7B5VAZGA.js → ci-format-NKJRZ3QI.js} +2 -2
- package/dist/{constants-DC3TNLTL.js → constants-6LCZOBJC.js} +1 -1
- package/dist/{doctor-cli-CDDG5XOY.js → doctor-cli-7JGPC5G4.js} +4 -4
- package/dist/electron-server.js +525 -140
- package/dist/{hub-TO7ODOIA.js → hub-NX7HYN7V.js} +1 -1
- package/dist/index.js +151 -429
- package/dist/{persistent-memory-JCENBMCJ.js → persistent-memory-E6WECUTW.js} +2 -2
- package/dist/{persistent-memory-BU63CSGK.js → persistent-memory-MHHX7F25.js} +2 -2
- package/dist/{pr-GVSZYX6I.js → pr-GLUFBQLI.js} +4 -4
- package/dist/{run-tests-2Q5MJHXB.js → run-tests-LWAFPVS3.js} +2 -2
- package/dist/{run-tests-R4IQS6IF.js → run-tests-YPJDOEJA.js} +2 -2
- package/dist/{server-KAURBKFI.js → server-CXXYIPMU.js} +226 -145
- package/dist/{server-WXLE53HG.js → server-P6DI27CY.js} +5 -5
- package/dist/{task-orchestrator-RJ6FXYY5.js → task-orchestrator-FW4LBPTS.js} +5 -5
- package/dist/{usage-V3R7DA7M.js → usage-CJUHQDT2.js} +2 -2
- package/dist/web/client/app.js +14 -2
- package/dist/web/client/app.js.br +0 -0
- package/dist/web/client/app.js.gz +0 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11,6 +11,11 @@ import {
|
|
|
11
11
|
autoTrimSessionIfNeeded,
|
|
12
12
|
buildInitPrompt,
|
|
13
13
|
buildSessionCostReport,
|
|
14
|
+
buildSessionExport,
|
|
15
|
+
checkpointDeletedMessage,
|
|
16
|
+
checkpointNotFoundMessage,
|
|
17
|
+
checkpointRestoredMessage,
|
|
18
|
+
checkpointSavedMessage,
|
|
14
19
|
clearDevState,
|
|
15
20
|
costSourceNote,
|
|
16
21
|
decideDeferredSave,
|
|
@@ -19,24 +24,36 @@ import {
|
|
|
19
24
|
estimateConversationTokens,
|
|
20
25
|
evaluateContextPressure,
|
|
21
26
|
filterMemoryEntries,
|
|
27
|
+
formatCheckpointList,
|
|
28
|
+
formatSessionSummaryLine,
|
|
22
29
|
loadDevState,
|
|
30
|
+
parseBatchDeleteArgs,
|
|
31
|
+
parseCheckpointCommand,
|
|
32
|
+
parseCleanArgs,
|
|
33
|
+
parseExportArgs,
|
|
23
34
|
parseMemoryShowFilters,
|
|
24
35
|
parseModelCommand,
|
|
25
36
|
parseRouteCommand,
|
|
37
|
+
parseSessionListArgs,
|
|
26
38
|
parseSimpleYaml,
|
|
27
39
|
persistToolRound,
|
|
28
40
|
readGitDiff,
|
|
29
41
|
resolveModelSwitch,
|
|
30
42
|
resolveProviderSwitch,
|
|
43
|
+
resolveSessionRef,
|
|
31
44
|
routeDecisionRows,
|
|
32
45
|
routingEmptyRulesNote,
|
|
33
46
|
saveDevState,
|
|
34
47
|
scanProject,
|
|
48
|
+
selectSessions,
|
|
49
|
+
selectStaleSessions,
|
|
35
50
|
sessionHasMeaningfulContent,
|
|
51
|
+
sessionListJsonRow,
|
|
52
|
+
sessionListSummary,
|
|
36
53
|
setupProxy,
|
|
37
54
|
snapshotFile,
|
|
38
55
|
stripRoutingTags
|
|
39
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-IIO2SMEJ.js";
|
|
40
57
|
import {
|
|
41
58
|
CostTracker,
|
|
42
59
|
computeCost,
|
|
@@ -66,7 +83,7 @@ import {
|
|
|
66
83
|
setMaxOutputCap,
|
|
67
84
|
spawnAgentContext,
|
|
68
85
|
undoStack
|
|
69
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-CP5LAA52.js";
|
|
70
87
|
import {
|
|
71
88
|
buildReviewPrompt,
|
|
72
89
|
buildSecurityReviewPrompt
|
|
@@ -107,7 +124,7 @@ import {
|
|
|
107
124
|
touchMemoryReferences,
|
|
108
125
|
updateMemoryApproval,
|
|
109
126
|
updateMemoryEntry
|
|
110
|
-
} from "./chunk-
|
|
127
|
+
} from "./chunk-V7EZ4SDC.js";
|
|
111
128
|
import "./chunk-4DEMGCK4.js";
|
|
112
129
|
import "./chunk-UUSRWSSX.js";
|
|
113
130
|
import "./chunk-CKH4KQ4E.js";
|
|
@@ -131,7 +148,7 @@ import {
|
|
|
131
148
|
formatDoctorReport,
|
|
132
149
|
loadContextFiles,
|
|
133
150
|
writeCrashLog
|
|
134
|
-
} from "./chunk-
|
|
151
|
+
} from "./chunk-B3FHA6IN.js";
|
|
135
152
|
import {
|
|
136
153
|
describePlugin,
|
|
137
154
|
getActivePluginAssets,
|
|
@@ -148,14 +165,14 @@ import {
|
|
|
148
165
|
trustHook,
|
|
149
166
|
trustPlugin,
|
|
150
167
|
untrustHook
|
|
151
|
-
} from "./chunk-
|
|
168
|
+
} from "./chunk-UMWDNNPS.js";
|
|
152
169
|
import {
|
|
153
170
|
ProviderRegistry,
|
|
154
171
|
listBuiltInProviderMetadata
|
|
155
172
|
} from "./chunk-UGY5SVNX.js";
|
|
156
173
|
import {
|
|
157
174
|
ConfigManager
|
|
158
|
-
} from "./chunk-
|
|
175
|
+
} from "./chunk-EOP775JU.js";
|
|
159
176
|
import {
|
|
160
177
|
CONTENT_ONLY_STREAM_REMINDER,
|
|
161
178
|
TEE_FINAL_USER_NUDGE,
|
|
@@ -193,7 +210,7 @@ import {
|
|
|
193
210
|
import {
|
|
194
211
|
fileCheckpoints
|
|
195
212
|
} from "./chunk-4BKXL7SM.js";
|
|
196
|
-
import "./chunk-
|
|
213
|
+
import "./chunk-VQCFEA4Z.js";
|
|
197
214
|
import {
|
|
198
215
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
199
216
|
AUTHOR,
|
|
@@ -211,7 +228,7 @@ import {
|
|
|
211
228
|
SKILLS_DIR_NAME,
|
|
212
229
|
VERSION,
|
|
213
230
|
buildUserIdentityPrompt
|
|
214
|
-
} from "./chunk-
|
|
231
|
+
} from "./chunk-UBPRUSAF.js";
|
|
215
232
|
|
|
216
233
|
// src/index.ts
|
|
217
234
|
import { program } from "commander";
|
|
@@ -730,7 +747,6 @@ import { platform } from "os";
|
|
|
730
747
|
|
|
731
748
|
// src/repl/commands/constants.ts
|
|
732
749
|
var SESSION_PAGE_SIZE = 20;
|
|
733
|
-
var DEFAULT_SESSION_LIST_LIMIT = 50;
|
|
734
750
|
var MAX_TITLE_WIDTH = 40;
|
|
735
751
|
|
|
736
752
|
// src/repl/commands/utils.ts
|
|
@@ -809,73 +825,6 @@ function formatSessionDate(date) {
|
|
|
809
825
|
if (diffDays < 7) return `${abs} (${diffDays} days ago)`;
|
|
810
826
|
return abs;
|
|
811
827
|
}
|
|
812
|
-
function parseSessionListArgs(args) {
|
|
813
|
-
let limit = DEFAULT_SESSION_LIST_LIMIT;
|
|
814
|
-
let all = false;
|
|
815
|
-
const filter = {};
|
|
816
|
-
const warnings = [];
|
|
817
|
-
let search = null;
|
|
818
|
-
let days = null;
|
|
819
|
-
let since = null;
|
|
820
|
-
let sort = { field: "updated", order: "desc" };
|
|
821
|
-
let json = false;
|
|
822
|
-
let stale = null;
|
|
823
|
-
let verbose = false;
|
|
824
|
-
for (let i = 1; i < args.length; i++) {
|
|
825
|
-
const a = args[i];
|
|
826
|
-
if (a === "--all" || a === "-a") {
|
|
827
|
-
all = true;
|
|
828
|
-
} else if ((a === "--limit" || a === "-n") && i + 1 < args.length) {
|
|
829
|
-
const n = Number(args[i + 1]);
|
|
830
|
-
if (Number.isFinite(n) && n > 0) {
|
|
831
|
-
limit = n;
|
|
832
|
-
i++;
|
|
833
|
-
}
|
|
834
|
-
} else if (a === "--filter" && i + 1 < args.length) {
|
|
835
|
-
const val = args[++i];
|
|
836
|
-
const eq = val.indexOf("=");
|
|
837
|
-
if (eq > 0) {
|
|
838
|
-
const key = val.slice(0, eq);
|
|
839
|
-
const vals = val.slice(eq + 1).split(",").map((s) => s.trim().toLowerCase());
|
|
840
|
-
if (key === "provider") filter.provider = vals;
|
|
841
|
-
else if (key === "model") filter.model = vals;
|
|
842
|
-
else if (key === "messages") {
|
|
843
|
-
const n = Number(vals[0]);
|
|
844
|
-
if (Number.isFinite(n) && n >= 0) filter.messages = n;
|
|
845
|
-
else warnings.push(`Invalid filter value for "messages": expected a non-negative integer, got "${vals[0]}"`);
|
|
846
|
-
} else {
|
|
847
|
-
warnings.push(`Unknown filter key: "${key}". Supported keys: provider, model, messages`);
|
|
848
|
-
}
|
|
849
|
-
} else {
|
|
850
|
-
warnings.push(`Invalid --filter syntax: "${val}". Expected key=value`);
|
|
851
|
-
}
|
|
852
|
-
} else if ((a === "--search" || a === "-s") && i + 1 < args.length) {
|
|
853
|
-
search = args[++i];
|
|
854
|
-
} else if (a === "--days" && i + 1 < args.length) {
|
|
855
|
-
const n = Number(args[++i]);
|
|
856
|
-
if (Number.isFinite(n) && n > 0) days = n;
|
|
857
|
-
} else if (a === "--since" && i + 1 < args.length) {
|
|
858
|
-
since = args[++i];
|
|
859
|
-
} else if (a === "--sort" && i + 1 < args.length) {
|
|
860
|
-
const sv = args[++i];
|
|
861
|
-
const colon = sv.indexOf(":");
|
|
862
|
-
const field = colon > 0 ? sv.slice(0, colon) : sv;
|
|
863
|
-
const order = colon > 0 ? sv.slice(colon + 1) : "desc";
|
|
864
|
-
if (field === "updated" || field === "created" || field === "messages" || field === "size") {
|
|
865
|
-
sort = { field, order: order === "asc" ? "asc" : "desc" };
|
|
866
|
-
}
|
|
867
|
-
} else if (a === "--json") {
|
|
868
|
-
json = true;
|
|
869
|
-
} else if (a === "--verbose" || a === "-v") {
|
|
870
|
-
verbose = true;
|
|
871
|
-
} else if (a === "--stale" && i + 1 < args.length) {
|
|
872
|
-
const n = Number(args[++i]);
|
|
873
|
-
if (Number.isFinite(n) && n > 0) stale = n;
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
if (all) limit = -1;
|
|
877
|
-
return { limit, all, filter, search, days, since, sort, json, stale, verbose, warnings };
|
|
878
|
-
}
|
|
879
828
|
function renderTranscriptMessage(msg, renderer) {
|
|
880
829
|
if (msg.role === "user") {
|
|
881
830
|
const text = getContentText(msg.content);
|
|
@@ -1397,7 +1346,7 @@ No tools match "${filter}".
|
|
|
1397
1346
|
const { join: join6 } = await import("path");
|
|
1398
1347
|
const { existsSync: existsSync6 } = await import("fs");
|
|
1399
1348
|
const { getGitRoot: getGitRoot2 } = await import("./git-context-EXOEHQSF.js");
|
|
1400
|
-
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-
|
|
1349
|
+
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-6LCZOBJC.js");
|
|
1401
1350
|
const { approveProject, hashMcpFile } = await import("./project-trust-NKYHL3VZ.js");
|
|
1402
1351
|
const cwd = process.cwd();
|
|
1403
1352
|
const projectRoot = getGitRoot2(cwd) ?? cwd;
|
|
@@ -2317,7 +2266,7 @@ function createReviewCommands() {
|
|
|
2317
2266
|
usage: "/test [command|filter]",
|
|
2318
2267
|
async execute(args, ctx) {
|
|
2319
2268
|
try {
|
|
2320
|
-
const { executeTests } = await import("./run-tests-
|
|
2269
|
+
const { executeTests } = await import("./run-tests-YPJDOEJA.js");
|
|
2321
2270
|
const argStr = args.join(" ").trim();
|
|
2322
2271
|
let testArgs = {};
|
|
2323
2272
|
if (argStr) {
|
|
@@ -3081,7 +3030,7 @@ function createSessionCommands() {
|
|
|
3081
3030
|
{
|
|
3082
3031
|
name: "session",
|
|
3083
3032
|
description: "Session management",
|
|
3084
|
-
usage: "/session new|list [--limit N|--all] [--filter provider=|model=|messages=N] [--search kw] [--days N|--stale N] [--sort f[:o]] [--json] [--verbose]|load <id>|show <id> [page]|page <n>|remove <id>|clean --stale N [--dry-run]",
|
|
3033
|
+
usage: "/session new|list [--limit N|--all] [--filter provider=|model=|messages=N] [--search kw] [--days N|--stale N] [--sort f[:o]] [--json] [--verbose]|load <id>|show <id> [page]|page <n>|rename <id> <title>|remove <id>|clean --stale N [--dry-run]",
|
|
3085
3034
|
async execute(args, ctx) {
|
|
3086
3035
|
const sub = args[0];
|
|
3087
3036
|
if (sub === "new") {
|
|
@@ -3093,139 +3042,44 @@ function createSessionCommands() {
|
|
|
3093
3042
|
ctx.renderer.printSuccess("New session started.");
|
|
3094
3043
|
} else if (sub === "list") {
|
|
3095
3044
|
const opts = parseSessionListArgs(args);
|
|
3096
|
-
for (const w of opts.warnings) {
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
const needFileSize = opts.verbose || opts.sort.field === "size";
|
|
3100
|
-
let allSessions = ctx.sessions.listSessions({ includeFileSize: needFileSize });
|
|
3101
|
-
if (allSessions.length === 0) {
|
|
3045
|
+
for (const w of opts.warnings) ctx.renderer.printInfo(`\u26A0 ${w}`);
|
|
3046
|
+
const all = ctx.sessions.listSessions({ includeFileSize: opts.verbose || opts.sort.field === "size" });
|
|
3047
|
+
if (all.length === 0) {
|
|
3102
3048
|
ctx.renderer.printInfo("No saved sessions.");
|
|
3103
3049
|
return;
|
|
3104
3050
|
}
|
|
3105
|
-
const
|
|
3106
|
-
|
|
3107
|
-
const hasTimeFilter = opts.days !== null || opts.since !== null;
|
|
3108
|
-
const hasStale = opts.stale !== null;
|
|
3109
|
-
if (hasFilters) {
|
|
3110
|
-
const p = opts.filter.provider;
|
|
3111
|
-
const m = opts.filter.model;
|
|
3112
|
-
const msg = opts.filter.messages;
|
|
3113
|
-
allSessions = allSessions.filter((s) => {
|
|
3114
|
-
if (p && !p.includes(s.provider.toLowerCase())) return false;
|
|
3115
|
-
if (m && !m.some((kw) => s.model.toLowerCase().includes(kw))) return false;
|
|
3116
|
-
if (msg !== void 0 && s.messageCount !== msg) return false;
|
|
3117
|
-
return true;
|
|
3118
|
-
});
|
|
3119
|
-
}
|
|
3120
|
-
if (hasSearch) {
|
|
3121
|
-
const q = opts.search.toLowerCase();
|
|
3122
|
-
allSessions = allSessions.filter(
|
|
3123
|
-
(s) => (s.title ?? "").toLowerCase().includes(q) || s.id.toLowerCase().includes(q)
|
|
3124
|
-
);
|
|
3125
|
-
}
|
|
3126
|
-
if (hasTimeFilter) {
|
|
3127
|
-
const now = Date.now();
|
|
3128
|
-
let cutoff = 0;
|
|
3129
|
-
if (opts.since) {
|
|
3130
|
-
cutoff = new Date(opts.since).getTime();
|
|
3131
|
-
} else if (opts.days !== null) {
|
|
3132
|
-
cutoff = now - opts.days * 24 * 60 * 60 * 1e3;
|
|
3133
|
-
}
|
|
3134
|
-
if (!isNaN(cutoff)) {
|
|
3135
|
-
allSessions = allSessions.filter((s) => s.updated.getTime() >= cutoff);
|
|
3136
|
-
}
|
|
3137
|
-
}
|
|
3138
|
-
const staleCutoff = hasStale ? Date.now() - opts.stale * 24 * 60 * 60 * 1e3 : 0;
|
|
3139
|
-
if (hasStale) {
|
|
3140
|
-
allSessions = allSessions.filter((s) => s.updated.getTime() < staleCutoff);
|
|
3141
|
-
}
|
|
3142
|
-
const defaultSort = opts.sort.field === "updated" && opts.sort.order === "desc";
|
|
3143
|
-
if (!defaultSort) {
|
|
3144
|
-
const mul = opts.sort.order === "asc" ? 1 : -1;
|
|
3145
|
-
allSessions = [...allSessions].sort((a, b) => {
|
|
3146
|
-
switch (opts.sort.field) {
|
|
3147
|
-
case "created":
|
|
3148
|
-
return (a.created.getTime() - b.created.getTime()) * mul;
|
|
3149
|
-
case "messages":
|
|
3150
|
-
return (a.messageCount - b.messageCount) * mul;
|
|
3151
|
-
case "size":
|
|
3152
|
-
return ((a.fileSize ?? 0) - (b.fileSize ?? 0)) * mul;
|
|
3153
|
-
default:
|
|
3154
|
-
return (a.updated.getTime() - b.updated.getTime()) * mul;
|
|
3155
|
-
}
|
|
3156
|
-
});
|
|
3157
|
-
}
|
|
3158
|
-
const totalCount = allSessions.length;
|
|
3159
|
-
if (totalCount === 0) {
|
|
3051
|
+
const view = selectSessions(all, opts);
|
|
3052
|
+
if (view.totalCount === 0) {
|
|
3160
3053
|
ctx.renderer.printInfo("No sessions match the filter criteria.");
|
|
3161
3054
|
return;
|
|
3162
3055
|
}
|
|
3163
3056
|
if (opts.json) {
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
id: s.id,
|
|
3167
|
-
title: s.title ?? null,
|
|
3168
|
-
provider: s.provider,
|
|
3169
|
-
model: s.model,
|
|
3170
|
-
messageCount: s.messageCount,
|
|
3171
|
-
created: s.created.toISOString(),
|
|
3172
|
-
updated: s.updated.toISOString(),
|
|
3173
|
-
...needFileSize ? { fileSize: s.fileSize } : {},
|
|
3174
|
-
...s.branchCount !== void 0 ? { branchCount: s.branchCount, activeBranch: s.activeBranch } : {}
|
|
3175
|
-
}));
|
|
3176
|
-
console.log(JSON.stringify(payload, null, 2));
|
|
3177
|
-
if (opts.limit > 0 && totalCount > opts.limit) {
|
|
3057
|
+
console.log(JSON.stringify(view.shown.map((s) => sessionListJsonRow(s, view.needsFileSize)), null, 2));
|
|
3058
|
+
if (view.shown.length < view.totalCount) {
|
|
3178
3059
|
console.error(
|
|
3179
3060
|
`
|
|
3180
|
-
(truncated: ${
|
|
3061
|
+
(truncated: ${view.shown.length} of ${view.totalCount} sessions shown; use --all for full list)`
|
|
3181
3062
|
);
|
|
3182
3063
|
}
|
|
3183
3064
|
return;
|
|
3184
3065
|
}
|
|
3185
|
-
const sliced = opts.limit > 0 ? allSessions.slice(0, opts.limit) : allSessions;
|
|
3186
3066
|
const headers = ["ID (short)", "Provider", "Model", "Messages"];
|
|
3187
|
-
if (opts.verbose)
|
|
3188
|
-
headers.push("Size");
|
|
3189
|
-
headers.push("Br");
|
|
3190
|
-
}
|
|
3067
|
+
if (opts.verbose) headers.push("Size", "Br");
|
|
3191
3068
|
headers.push("Date", "Title");
|
|
3192
|
-
const rows =
|
|
3193
|
-
const isStale =
|
|
3069
|
+
const rows = view.shown.map((s) => {
|
|
3070
|
+
const isStale = view.staleCutoff !== null && s.updated.getTime() < view.staleCutoff;
|
|
3194
3071
|
const dim = isStale ? theme.dim : (x) => String(x);
|
|
3195
|
-
const row = [
|
|
3196
|
-
dim(s.id.slice(0, 8)),
|
|
3197
|
-
dim(s.provider),
|
|
3198
|
-
dim(s.model),
|
|
3199
|
-
s.messageCount
|
|
3200
|
-
];
|
|
3072
|
+
const row = [dim(s.id.slice(0, 8)), dim(s.provider), dim(s.model), s.messageCount];
|
|
3201
3073
|
if (opts.verbose) {
|
|
3202
|
-
row.push(
|
|
3203
|
-
s.fileSize !== void 0 ? formatFileSize(s.fileSize) : "\u2014",
|
|
3204
|
-
s.branchCount ?? 1
|
|
3205
|
-
);
|
|
3074
|
+
row.push(s.fileSize !== void 0 ? formatFileSize(s.fileSize) : "\u2014", s.branchCount ?? 1);
|
|
3206
3075
|
}
|
|
3207
|
-
row.push(
|
|
3208
|
-
formatSessionDate(s.updated),
|
|
3209
|
-
dim(truncateTitle(s.title ?? "(untitled)", MAX_TITLE_WIDTH))
|
|
3210
|
-
);
|
|
3076
|
+
row.push(formatSessionDate(s.updated), dim(truncateTitle(s.title ?? "(untitled)", MAX_TITLE_WIDTH)));
|
|
3211
3077
|
return row;
|
|
3212
3078
|
});
|
|
3213
3079
|
console.log();
|
|
3214
3080
|
ctx.renderer.printTable(headers, rows);
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
const filterHints = [];
|
|
3218
|
-
if (hasFilters) filterHints.push("filtered");
|
|
3219
|
-
if (hasSearch) filterHints.push("searched");
|
|
3220
|
-
if (hasTimeFilter) filterHints.push("time-limited");
|
|
3221
|
-
if (hasStale) filterHints.push(`stale >${opts.stale}d`);
|
|
3222
|
-
const filterTag = filterHints.length > 0 ? ` (${filterHints.join(", ")})` : "";
|
|
3223
|
-
console.log(
|
|
3224
|
-
theme.dim(
|
|
3225
|
-
` \u2500\u2500 ${shown} of ${totalCount} sessions${filterTag} \xB7 ${totalMessages} messages total`
|
|
3226
|
-
)
|
|
3227
|
-
);
|
|
3228
|
-
if (shown < totalCount) {
|
|
3081
|
+
console.log(theme.dim(` \u2500\u2500 ${sessionListSummary(view)}`));
|
|
3082
|
+
if (view.shown.length < view.totalCount) {
|
|
3229
3083
|
console.log(theme.dim(` Use --all to show all, or --limit N to change count.`));
|
|
3230
3084
|
}
|
|
3231
3085
|
} else if (sub === "load" || sub === "show") {
|
|
@@ -3234,19 +3088,18 @@ function createSessionCommands() {
|
|
|
3234
3088
|
ctx.renderer.renderError(`Usage: /session ${sub} <id>${sub === "show" ? " [page]" : ""}`);
|
|
3235
3089
|
return;
|
|
3236
3090
|
}
|
|
3237
|
-
const
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
ctx.renderer.renderError(`Session '${id}' not found.`);
|
|
3091
|
+
const ref = resolveSessionRef(ctx.sessions.listSessions(), id, "most-recent");
|
|
3092
|
+
if (ref.status !== "ok") {
|
|
3093
|
+
ctx.renderer.renderError(ref.message);
|
|
3241
3094
|
return;
|
|
3242
3095
|
}
|
|
3243
|
-
if (
|
|
3244
|
-
console.log(theme.warning(`
|
|
3245
|
-
for (const m of
|
|
3096
|
+
if (ref.message) {
|
|
3097
|
+
console.log(theme.warning(` ${ref.message}`));
|
|
3098
|
+
for (const m of ref.ambiguousWith.slice(0, 5)) {
|
|
3246
3099
|
console.log(theme.dim(` ${m.id.slice(0, 12)} ${m.title ?? "(untitled)"}`));
|
|
3247
3100
|
}
|
|
3248
3101
|
}
|
|
3249
|
-
const match =
|
|
3102
|
+
const match = ref.match;
|
|
3250
3103
|
ctx.sessions.loadSession(match.id);
|
|
3251
3104
|
ctx.setProvider(match.provider, match.model);
|
|
3252
3105
|
ctx.resetSessionTokenUsage();
|
|
@@ -3270,70 +3123,54 @@ function createSessionCommands() {
|
|
|
3270
3123
|
return;
|
|
3271
3124
|
}
|
|
3272
3125
|
renderTranscriptPage(cur.messages, ctx.renderer, n);
|
|
3126
|
+
} else if (sub === "rename") {
|
|
3127
|
+
const id = args[1];
|
|
3128
|
+
const newTitle = args.slice(2).join(" ").trim();
|
|
3129
|
+
if (!id || !newTitle) {
|
|
3130
|
+
ctx.renderer.renderError("Usage: /session rename <id> <new title>");
|
|
3131
|
+
return;
|
|
3132
|
+
}
|
|
3133
|
+
const ref = resolveSessionRef(ctx.sessions.listSessions(), id, "strict");
|
|
3134
|
+
if (ref.status !== "ok") {
|
|
3135
|
+
ctx.renderer.renderError(ref.message);
|
|
3136
|
+
if (ref.status === "ambiguous") {
|
|
3137
|
+
for (const m of ref.matches.slice(0, 10)) console.log(theme.dim(` ${formatSessionSummaryLine(m)}`));
|
|
3138
|
+
}
|
|
3139
|
+
return;
|
|
3140
|
+
}
|
|
3141
|
+
const priorId = ctx.sessions.current?.id ?? null;
|
|
3142
|
+
const isCurrent = priorId === ref.match.id;
|
|
3143
|
+
const session = isCurrent ? ctx.sessions.current : ctx.sessions.loadSession(ref.match.id);
|
|
3144
|
+
session.title = newTitle;
|
|
3145
|
+
await ctx.sessions.save();
|
|
3146
|
+
if (!isCurrent && priorId) {
|
|
3147
|
+
ctx.sessions.loadSession(priorId);
|
|
3148
|
+
}
|
|
3149
|
+
ctx.renderer.printSuccess(`Renamed session ${ref.match.id.slice(0, 8)}: "${newTitle}"`);
|
|
3273
3150
|
} else if (sub === "remove" || sub === "delete") {
|
|
3274
3151
|
if (args[1] === "--filter") {
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
if (args[i] === "--filter" && i + 1 < args.length) {
|
|
3279
|
-
const val = args[++i];
|
|
3280
|
-
const eq = val.indexOf("=");
|
|
3281
|
-
if (eq > 0) {
|
|
3282
|
-
const key = val.slice(0, eq);
|
|
3283
|
-
const vals = val.slice(eq + 1).split(",").map((s) => s.trim().toLowerCase());
|
|
3284
|
-
if (key === "messages") {
|
|
3285
|
-
const n = Number(vals[0]);
|
|
3286
|
-
if (Number.isFinite(n) && n >= 0) filterMessages = n;
|
|
3287
|
-
else {
|
|
3288
|
-
ctx.renderer.renderError(`Invalid filter value for "messages": expected a non-negative integer, got "${vals[0]}"`);
|
|
3289
|
-
return;
|
|
3290
|
-
}
|
|
3291
|
-
} else {
|
|
3292
|
-
ctx.renderer.renderError(`Unsupported filter key for remove: "${key}". Only "messages" is supported.`);
|
|
3293
|
-
return;
|
|
3294
|
-
}
|
|
3295
|
-
} else {
|
|
3296
|
-
ctx.renderer.renderError(`Invalid --filter syntax: "${val}". Expected key=value (e.g., messages=0)`);
|
|
3297
|
-
return;
|
|
3298
|
-
}
|
|
3299
|
-
} else if (args[i] === "--dry-run") {
|
|
3300
|
-
dryRun = true;
|
|
3301
|
-
}
|
|
3302
|
-
}
|
|
3303
|
-
if (filterMessages === void 0) {
|
|
3304
|
-
ctx.renderer.renderError("Usage: /session remove --filter messages=N [--dry-run]");
|
|
3152
|
+
const opts = parseBatchDeleteArgs(args);
|
|
3153
|
+
if (opts.error) {
|
|
3154
|
+
ctx.renderer.renderError(opts.error);
|
|
3305
3155
|
return;
|
|
3306
3156
|
}
|
|
3307
|
-
const
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
ctx.renderer.printInfo(`No sessions with ${filterMessages} message(s) found.`);
|
|
3157
|
+
const matches = ctx.sessions.listSessions().filter((s) => s.messageCount === opts.messages);
|
|
3158
|
+
if (matches.length === 0) {
|
|
3159
|
+
ctx.renderer.printInfo(`No sessions with ${opts.messages} message(s) found.`);
|
|
3311
3160
|
return;
|
|
3312
3161
|
}
|
|
3313
3162
|
console.log();
|
|
3314
|
-
console.log(
|
|
3315
|
-
|
|
3316
|
-
);
|
|
3317
|
-
|
|
3318
|
-
console.log(
|
|
3319
|
-
|
|
3320
|
-
` ${s.id.slice(0, 12)} ${s.provider}/${s.model} ${String(s.messageCount).padStart(4)} msgs ${s.updated.toISOString().slice(0, 10)} ${truncateTitle(s.title ?? "(untitled)", 60)}`
|
|
3321
|
-
)
|
|
3322
|
-
);
|
|
3323
|
-
}
|
|
3324
|
-
if (matches2.length > 20) {
|
|
3325
|
-
console.log(theme.dim(` ... and ${matches2.length - 20} more`));
|
|
3326
|
-
}
|
|
3327
|
-
if (dryRun) {
|
|
3328
|
-
console.log(
|
|
3329
|
-
theme.info(`
|
|
3330
|
-
--dry-run: no sessions were deleted. Remove --dry-run to actually delete.`)
|
|
3331
|
-
);
|
|
3163
|
+
console.log(theme.warning(` Found ${matches.length} session(s) with ${opts.messages} message(s):`));
|
|
3164
|
+
for (const s of matches.slice(0, 20)) console.log(theme.dim(` ${formatSessionSummaryLine(s)}`));
|
|
3165
|
+
if (matches.length > 20) console.log(theme.dim(` ... and ${matches.length - 20} more`));
|
|
3166
|
+
if (opts.dryRun) {
|
|
3167
|
+
console.log(theme.info(`
|
|
3168
|
+
--dry-run: no sessions were deleted. Remove --dry-run to actually delete.`));
|
|
3332
3169
|
return;
|
|
3333
3170
|
}
|
|
3334
3171
|
console.log();
|
|
3335
3172
|
const choice2 = await ctx.select(
|
|
3336
|
-
`Delete all ${
|
|
3173
|
+
`Delete all ${matches.length} matching sessions?`,
|
|
3337
3174
|
[
|
|
3338
3175
|
{ label: "No \u2014 keep them", value: "no" },
|
|
3339
3176
|
{ label: "Yes \u2014 delete permanently", value: "yes", hint: "unlinks all matching history files" }
|
|
@@ -3345,17 +3182,12 @@ function createSessionCommands() {
|
|
|
3345
3182
|
}
|
|
3346
3183
|
let deleted = 0;
|
|
3347
3184
|
let failed = 0;
|
|
3348
|
-
for (const s of
|
|
3349
|
-
if (ctx.sessions.deleteSession(s.id))
|
|
3350
|
-
|
|
3351
|
-
} else {
|
|
3352
|
-
failed++;
|
|
3353
|
-
}
|
|
3185
|
+
for (const s of matches) {
|
|
3186
|
+
if (ctx.sessions.deleteSession(s.id)) deleted++;
|
|
3187
|
+
else failed++;
|
|
3354
3188
|
}
|
|
3355
3189
|
const currentStillExists = ctx.sessions.current !== null;
|
|
3356
|
-
ctx.renderer.printSuccess(
|
|
3357
|
-
`Removed: ${deleted} deleted${failed > 0 ? `, ${failed} failed` : ""}.`
|
|
3358
|
-
);
|
|
3190
|
+
ctx.renderer.printSuccess(`Removed: ${deleted} deleted${failed > 0 ? `, ${failed} failed` : ""}.`);
|
|
3359
3191
|
if (!currentStillExists) {
|
|
3360
3192
|
ctx.sessions.createSession(ctx.getCurrentProvider(), ctx.getCurrentModel());
|
|
3361
3193
|
ctx.resetSessionTokenUsage();
|
|
@@ -3369,20 +3201,15 @@ function createSessionCommands() {
|
|
|
3369
3201
|
ctx.renderer.renderError("Usage: /session remove <id> | /session remove --filter messages=N [--dry-run]");
|
|
3370
3202
|
return;
|
|
3371
3203
|
}
|
|
3372
|
-
const
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
}
|
|
3378
|
-
if (matches.length > 1) {
|
|
3379
|
-
ctx.renderer.renderError(`Ambiguous prefix '${id}' matches ${matches.length} sessions \u2014 be more specific:`);
|
|
3380
|
-
for (const m of matches.slice(0, 10)) {
|
|
3381
|
-
console.log(theme.dim(` ${m.id.slice(0, 12)} ${String(m.messageCount).padStart(4)} msgs ${m.updated.toLocaleDateString()} ${m.title ?? "(untitled)"}`));
|
|
3204
|
+
const ref = resolveSessionRef(ctx.sessions.listSessions(), id, "strict");
|
|
3205
|
+
if (ref.status !== "ok") {
|
|
3206
|
+
ctx.renderer.renderError(ref.message);
|
|
3207
|
+
if (ref.status === "ambiguous") {
|
|
3208
|
+
for (const m of ref.matches.slice(0, 10)) console.log(theme.dim(` ${formatSessionSummaryLine(m)}`));
|
|
3382
3209
|
}
|
|
3383
3210
|
return;
|
|
3384
3211
|
}
|
|
3385
|
-
const match =
|
|
3212
|
+
const match = ref.match;
|
|
3386
3213
|
const isCurrent = ctx.sessions.current?.id === match.id;
|
|
3387
3214
|
console.log();
|
|
3388
3215
|
console.log(theme.warning(" About to permanently delete session (no undo):"));
|
|
@@ -3409,44 +3236,19 @@ function createSessionCommands() {
|
|
|
3409
3236
|
ctx.renderer.printInfo("Current session was deleted \u2014 started a fresh session.");
|
|
3410
3237
|
}
|
|
3411
3238
|
} else if (sub === "clean") {
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
for (let i = 1; i < args.length; i++) {
|
|
3415
|
-
if (args[i] === "--stale" && i + 1 < args.length) {
|
|
3416
|
-
const n = Number(args[++i]);
|
|
3417
|
-
if (Number.isFinite(n) && n > 0) staleDays = n;
|
|
3418
|
-
} else if (args[i] === "--dry-run") {
|
|
3419
|
-
dryRun = true;
|
|
3420
|
-
}
|
|
3421
|
-
}
|
|
3422
|
-
const cutoff = Date.now() - staleDays * 24 * 60 * 60 * 1e3;
|
|
3423
|
-
const allSessions = ctx.sessions.listSessions();
|
|
3424
|
-
const stale = allSessions.filter((s) => s.updated.getTime() < cutoff);
|
|
3239
|
+
const opts = parseCleanArgs(args);
|
|
3240
|
+
const stale = selectStaleSessions(ctx.sessions.listSessions(), opts.staleDays);
|
|
3425
3241
|
if (stale.length === 0) {
|
|
3426
|
-
ctx.renderer.printInfo(`No sessions older than ${staleDays} days found.`);
|
|
3242
|
+
ctx.renderer.printInfo(`No sessions older than ${opts.staleDays} days found.`);
|
|
3427
3243
|
return;
|
|
3428
3244
|
}
|
|
3429
3245
|
console.log();
|
|
3430
|
-
console.log(
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
console.log(
|
|
3437
|
-
theme.dim(
|
|
3438
|
-
` ${s.id.slice(0, 12)} ${String(s.messageCount).padStart(4)} msgs ${s.updated.toISOString().slice(0, 10)} ${truncateTitle(s.title ?? "(untitled)", 60)}`
|
|
3439
|
-
)
|
|
3440
|
-
);
|
|
3441
|
-
}
|
|
3442
|
-
if (stale.length > 20) {
|
|
3443
|
-
console.log(theme.dim(` ... and ${stale.length - 20} more`));
|
|
3444
|
-
}
|
|
3445
|
-
if (dryRun) {
|
|
3446
|
-
console.log(
|
|
3447
|
-
theme.info(`
|
|
3448
|
-
--dry-run: no sessions were deleted. Remove --dry-run to actually delete.`)
|
|
3449
|
-
);
|
|
3246
|
+
console.log(theme.warning(` Found ${stale.length} session(s) not updated in ${opts.staleDays}+ days:`));
|
|
3247
|
+
for (const s of stale.slice(0, 20)) console.log(theme.dim(` ${formatSessionSummaryLine(s)}`));
|
|
3248
|
+
if (stale.length > 20) console.log(theme.dim(` ... and ${stale.length - 20} more`));
|
|
3249
|
+
if (opts.dryRun) {
|
|
3250
|
+
console.log(theme.info(`
|
|
3251
|
+
--dry-run: no sessions were deleted. Remove --dry-run to actually delete.`));
|
|
3450
3252
|
return;
|
|
3451
3253
|
}
|
|
3452
3254
|
console.log();
|
|
@@ -3464,17 +3266,12 @@ function createSessionCommands() {
|
|
|
3464
3266
|
let deleted = 0;
|
|
3465
3267
|
let failed = 0;
|
|
3466
3268
|
for (const s of stale) {
|
|
3467
|
-
if (ctx.sessions.deleteSession(s.id))
|
|
3468
|
-
|
|
3469
|
-
} else {
|
|
3470
|
-
failed++;
|
|
3471
|
-
}
|
|
3269
|
+
if (ctx.sessions.deleteSession(s.id)) deleted++;
|
|
3270
|
+
else failed++;
|
|
3472
3271
|
}
|
|
3473
|
-
ctx.renderer.printSuccess(
|
|
3474
|
-
`Cleaned up: ${deleted} deleted${failed > 0 ? `, ${failed} failed` : ""}.`
|
|
3475
|
-
);
|
|
3272
|
+
ctx.renderer.printSuccess(`Cleaned up: ${deleted} deleted${failed > 0 ? `, ${failed} failed` : ""}.`);
|
|
3476
3273
|
} else {
|
|
3477
|
-
ctx.renderer.renderError("Usage: /session new|list|load <id>|show <id> [page]|page <n>|remove <id>|remove --filter messages=N [--dry-run]|clean --stale N [--dry-run]");
|
|
3274
|
+
ctx.renderer.renderError("Usage: /session new|list|load <id>|show <id> [page]|page <n>|rename <id> <title>|remove <id>|remove --filter messages=N [--dry-run]|clean --stale N [--dry-run]");
|
|
3478
3275
|
}
|
|
3479
3276
|
}
|
|
3480
3277
|
},
|
|
@@ -3492,76 +3289,20 @@ function createSessionCommands() {
|
|
|
3492
3289
|
description: "Export current session to file or stdout",
|
|
3493
3290
|
usage: "/export [md|json] [filename]",
|
|
3494
3291
|
execute(args, ctx) {
|
|
3495
|
-
|
|
3496
|
-
let outFile = null;
|
|
3497
|
-
for (const arg of args) {
|
|
3498
|
-
if (arg === "md" || arg === "json") {
|
|
3499
|
-
format = arg;
|
|
3500
|
-
} else if (arg) {
|
|
3501
|
-
outFile = arg;
|
|
3502
|
-
}
|
|
3503
|
-
}
|
|
3292
|
+
const { format, outFile } = parseExportArgs(args);
|
|
3504
3293
|
const session = ctx.sessions.current;
|
|
3505
3294
|
if (!session || session.messages.length === 0) {
|
|
3506
3295
|
ctx.renderer.printInfo("No messages to export.");
|
|
3507
3296
|
return;
|
|
3508
3297
|
}
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
md += `| Field | Value |
|
|
3518
|
-
|----------|-------|
|
|
3519
|
-
`;
|
|
3520
|
-
md += `| Provider | ${session.provider} |
|
|
3521
|
-
`;
|
|
3522
|
-
md += `| Model | ${session.model} |
|
|
3523
|
-
`;
|
|
3524
|
-
md += `| Date | ${dateStr} |
|
|
3525
|
-
`;
|
|
3526
|
-
md += `| Session | ${session.id.slice(0, 8)} |
|
|
3527
|
-
|
|
3528
|
-
---
|
|
3529
|
-
|
|
3530
|
-
`;
|
|
3531
|
-
for (const msg of session.messages) {
|
|
3532
|
-
const role = msg.role === "user" ? "## \u{1F464} You" : "## \u{1F916} Assistant";
|
|
3533
|
-
const text = getContentText(msg.content);
|
|
3534
|
-
md += `${role}
|
|
3535
|
-
|
|
3536
|
-
${text}
|
|
3537
|
-
|
|
3538
|
-
---
|
|
3539
|
-
|
|
3540
|
-
`;
|
|
3541
|
-
}
|
|
3542
|
-
output = md;
|
|
3543
|
-
}
|
|
3544
|
-
if (outFile) {
|
|
3545
|
-
const absPath = resolve(process.cwd(), outFile);
|
|
3546
|
-
try {
|
|
3547
|
-
mkdirSync2(dirname2(absPath), { recursive: true });
|
|
3548
|
-
writeFileSync2(absPath, output, "utf-8");
|
|
3549
|
-
ctx.renderer.printSuccess(`Exported ${session.messages.length} messages \u2192 ${absPath}`);
|
|
3550
|
-
} catch (err) {
|
|
3551
|
-
ctx.renderer.renderError(`Failed to write file: ${err instanceof Error ? err.message : String(err)}`);
|
|
3552
|
-
}
|
|
3553
|
-
} else {
|
|
3554
|
-
const shortId = session.id.slice(0, 8);
|
|
3555
|
-
const dateTag = session.created.toISOString().slice(0, 10);
|
|
3556
|
-
const ext = format === "json" ? "json" : "md";
|
|
3557
|
-
const autoName = `session-${dateTag}-${shortId}.${ext}`;
|
|
3558
|
-
const absPath = resolve(process.cwd(), autoName);
|
|
3559
|
-
try {
|
|
3560
|
-
writeFileSync2(absPath, output, "utf-8");
|
|
3561
|
-
ctx.renderer.printSuccess(`Exported ${session.messages.length} messages \u2192 ${absPath}`);
|
|
3562
|
-
} catch (err) {
|
|
3563
|
-
ctx.renderer.renderError(`Failed to write file: ${err instanceof Error ? err.message : String(err)}`);
|
|
3564
|
-
}
|
|
3298
|
+
const exported = buildSessionExport(session, format, outFile);
|
|
3299
|
+
const absPath = resolve(process.cwd(), exported.filename);
|
|
3300
|
+
try {
|
|
3301
|
+
mkdirSync2(dirname2(absPath), { recursive: true });
|
|
3302
|
+
writeFileSync2(absPath, exported.content, "utf-8");
|
|
3303
|
+
ctx.renderer.printSuccess(`Exported ${exported.messageCount} messages \u2192 ${absPath}`);
|
|
3304
|
+
} catch (err) {
|
|
3305
|
+
ctx.renderer.renderError(`Failed to write file: ${err instanceof Error ? err.message : String(err)}`);
|
|
3565
3306
|
}
|
|
3566
3307
|
}
|
|
3567
3308
|
},
|
|
@@ -3575,59 +3316,40 @@ ${text}
|
|
|
3575
3316
|
ctx.renderer.renderError("No active session.");
|
|
3576
3317
|
return;
|
|
3577
3318
|
}
|
|
3578
|
-
const
|
|
3579
|
-
if (
|
|
3580
|
-
const
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
console.log(theme.dim(` Checkpoints (${cps.length}):`));
|
|
3586
|
-
for (const cp of cps) {
|
|
3587
|
-
const ts = cp.timestamp.toLocaleString();
|
|
3588
|
-
console.log(theme.accent(` ${cp.name.padEnd(20)} `) + theme.dim(`msg #${cp.messageIndex} ${ts}`));
|
|
3319
|
+
const intent = parseCheckpointCommand(args);
|
|
3320
|
+
if (intent.kind === "list") {
|
|
3321
|
+
const lines = formatCheckpointList(ctx.listCheckpoints());
|
|
3322
|
+
console.log(theme.dim(` ${lines[0]}`));
|
|
3323
|
+
for (const line of lines.slice(1)) {
|
|
3324
|
+
const [name, rest] = [line.slice(0, 24), line.slice(24)];
|
|
3325
|
+
console.log(theme.accent(` ${name}`) + theme.dim(rest));
|
|
3589
3326
|
}
|
|
3590
3327
|
console.log();
|
|
3591
3328
|
return;
|
|
3592
3329
|
}
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
if (!name) {
|
|
3596
|
-
ctx.renderer.renderError("Usage: /checkpoint save <name>");
|
|
3597
|
-
return;
|
|
3598
|
-
}
|
|
3599
|
-
ctx.createCheckpoint(name);
|
|
3600
|
-
console.log(theme.success(` \u2713 Checkpoint "${name}" saved at message #${session.messages.length}`));
|
|
3330
|
+
if (intent.kind === "usage" || intent.kind === "unknown") {
|
|
3331
|
+
ctx.renderer.renderError(intent.message);
|
|
3601
3332
|
return;
|
|
3602
3333
|
}
|
|
3603
|
-
if (
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
return;
|
|
3607
|
-
}
|
|
3608
|
-
const ok = ctx.restoreCheckpoint(name);
|
|
3609
|
-
if (ok) {
|
|
3610
|
-
ctx.resetSessionTokenUsage();
|
|
3611
|
-
console.log(theme.success(` \u2713 Restored to checkpoint "${name}" (${session.messages.length} messages, token usage reset)`));
|
|
3612
|
-
} else {
|
|
3613
|
-
ctx.renderer.renderError(`Checkpoint "${name}" not found.`);
|
|
3614
|
-
}
|
|
3334
|
+
if (intent.kind === "save") {
|
|
3335
|
+
ctx.createCheckpoint(intent.name);
|
|
3336
|
+
console.log(theme.success(` ${checkpointSavedMessage(intent.name, session.messages.length)}`));
|
|
3615
3337
|
return;
|
|
3616
3338
|
}
|
|
3617
|
-
if (
|
|
3618
|
-
if (!name) {
|
|
3619
|
-
ctx.renderer.renderError(
|
|
3339
|
+
if (intent.kind === "restore") {
|
|
3340
|
+
if (!ctx.restoreCheckpoint(intent.name)) {
|
|
3341
|
+
ctx.renderer.renderError(checkpointNotFoundMessage(intent.name));
|
|
3620
3342
|
return;
|
|
3621
3343
|
}
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3344
|
+
ctx.resetSessionTokenUsage();
|
|
3345
|
+
console.log(theme.success(` ${checkpointRestoredMessage(intent.name, session.messages.length)}`));
|
|
3346
|
+
return;
|
|
3347
|
+
}
|
|
3348
|
+
if (!ctx.deleteCheckpoint(intent.name)) {
|
|
3349
|
+
ctx.renderer.renderError(checkpointNotFoundMessage(intent.name));
|
|
3628
3350
|
return;
|
|
3629
3351
|
}
|
|
3630
|
-
|
|
3352
|
+
console.log(theme.success(` ${checkpointDeletedMessage(intent.name)}`));
|
|
3631
3353
|
}
|
|
3632
3354
|
},
|
|
3633
3355
|
// ── /review ──────────────────────────────────────────────────
|
|
@@ -7547,7 +7269,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
7547
7269
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
7548
7270
|
process.exit(1);
|
|
7549
7271
|
}
|
|
7550
|
-
const { startWebServer } = await import("./server-
|
|
7272
|
+
const { startWebServer } = await import("./server-CXXYIPMU.js");
|
|
7551
7273
|
await startWebServer({ port, host: options.host });
|
|
7552
7274
|
});
|
|
7553
7275
|
program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | logout-all <name> | migrate <name>)").action(async (action, username) => {
|
|
@@ -7714,11 +7436,11 @@ program.command("sessions").description("List recent conversation sessions").opt
|
|
|
7714
7436
|
console.log(footer + "\n");
|
|
7715
7437
|
});
|
|
7716
7438
|
program.command("usage").description("Show token + cost usage grouped by provider/model (cross-session)").option("--days <n>", "Only the last N days (inclusive of today)").option("--month <ym>", "Only a specific month, format YYYY-MM (e.g. 2026-06)").option("--json", "Output as JSON (for scripting)").action(async (options) => {
|
|
7717
|
-
const { runUsageCli } = await import("./usage-
|
|
7439
|
+
const { runUsageCli } = await import("./usage-CJUHQDT2.js");
|
|
7718
7440
|
await runUsageCli(options);
|
|
7719
7441
|
});
|
|
7720
7442
|
program.command("doctor").description("Health check: API keys, config, MCP, recent crashes, tool usage, disk usage").option("--json", "Output as JSON (for scripting)").option("--reset-stats", "Reset accumulated tool usage statistics").action(async (options) => {
|
|
7721
|
-
const { runDoctorCli } = await import("./doctor-cli-
|
|
7443
|
+
const { runDoctorCli } = await import("./doctor-cli-7JGPC5G4.js");
|
|
7722
7444
|
const argv = process.argv.slice(2);
|
|
7723
7445
|
await runDoctorCli({
|
|
7724
7446
|
json: !!options.json || argv.includes("--json"),
|
|
@@ -7727,7 +7449,7 @@ program.command("doctor").description("Health check: API keys, config, MCP, rece
|
|
|
7727
7449
|
});
|
|
7728
7450
|
program.command("batch <action> [arg] [arg2]").description("Anthropic Message Batches: submit | list | status <id> | results <id> [out] | cancel <id>").option("--dry-run", "Parse and validate input without submitting (submit only)").action(async (action, arg, arg2, options) => {
|
|
7729
7451
|
try {
|
|
7730
|
-
const batch = await import("./batch-
|
|
7452
|
+
const batch = await import("./batch-F27NOTWC.js");
|
|
7731
7453
|
switch (action) {
|
|
7732
7454
|
case "submit":
|
|
7733
7455
|
if (!arg) {
|
|
@@ -7770,7 +7492,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
|
|
|
7770
7492
|
}
|
|
7771
7493
|
});
|
|
7772
7494
|
program.command("mcp-serve").description("Start an MCP server over STDIO, exposing aicli's built-in tools to Claude Desktop / Cursor / other MCP clients").option("--allow-destructive", "Allow bash / run_interactive / task_create (always destructive in MCP mode)").option("--allow-outside-cwd", "Allow tool path arguments to escape the sandbox root \u2014 disabled by default").option("--tools <list>", "Comma-separated whitelist of tools to expose (default: all eligible tools)").option("--cwd <path>", "Working directory AND sandbox root (default: current directory)").action(async (options) => {
|
|
7773
|
-
const { startMcpServer } = await import("./server-
|
|
7495
|
+
const { startMcpServer } = await import("./server-P6DI27CY.js");
|
|
7774
7496
|
await startMcpServer({
|
|
7775
7497
|
allowDestructive: !!options.allowDestructive,
|
|
7776
7498
|
allowOutsideCwd: !!options.allowOutsideCwd,
|
|
@@ -7783,7 +7505,7 @@ program.command("pr <action> [target]").description("PR review helpers: review |
|
|
|
7783
7505
|
console.error(`Unknown pr action: ${action}. Use review | security-review | summarize.`);
|
|
7784
7506
|
process.exit(1);
|
|
7785
7507
|
}
|
|
7786
|
-
const { runPrCli } = await import("./pr-
|
|
7508
|
+
const { runPrCli } = await import("./pr-GLUFBQLI.js");
|
|
7787
7509
|
const result = await runPrCli({
|
|
7788
7510
|
action,
|
|
7789
7511
|
target,
|
|
@@ -7803,8 +7525,8 @@ program.command("pr <action> [target]").description("PR review helpers: review |
|
|
|
7803
7525
|
process.exit(result.exitCode);
|
|
7804
7526
|
});
|
|
7805
7527
|
program.command("ci").description("Headless PR review (code + security) \u2014 reads git/gh diff, optionally posts to PR. Designed for GitHub Actions.").option("--pr <num>", "PR number or URL; diff fetched via gh pr diff <value>", (v) => /^#?\d+$/.test(v) ? parseInt(v.replace(/^#/, ""), 10) : v).option("--base <ref>", "Base ref for git diff <ref>...HEAD (ignored when --pr set)").option("--post", "Post review as a PR comment (requires gh CLI + GH_TOKEN, needs --pr)").option("--no-update", "Always create a new comment instead of updating the previous aicli review").option("--skip-code", "Skip the code review section").option("--skip-security", "Skip the security review section").option("--detailed", "Use the detailed code-review prompt").option("--max-diff <n>", "Max diff chars sent to the model (default 30000)", (v) => parseInt(v, 10)).option("--provider <id>", "Override provider (default: config.defaultProvider)").option("--model <id>", "Override model").option("--dry-run", "Print result to stdout instead of posting (overrides --post)").option("--json", "Output a structured JSON report").option("--markdown", "Output Markdown report (default)").option("--sarif", "Output SARIF 2.1.0 for code scanning artifacts").option("--fail-on-security-high", "Fail when the security review contains HIGH/CRITICAL findings (default)").option("--no-fail-on-security-high", "Do not fail on security HIGH/CRITICAL findings").option("--fail-on-test-failure", "Fail when the report mentions test failures (default)").option("--no-fail-on-test-failure", "Do not fail on test failure findings").option("--fail-on-lint-failure", "Fail when the report mentions lint/typecheck failures (default)").option("--no-fail-on-lint-failure", "Do not fail on lint/typecheck failure findings").action(async (options) => {
|
|
7806
|
-
const { runCi } = await import("./ci-
|
|
7807
|
-
const { formatCiResult } = await import("./ci-format-
|
|
7528
|
+
const { runCi } = await import("./ci-HJ4OVHCM.js");
|
|
7529
|
+
const { formatCiResult } = await import("./ci-format-NKJRZ3QI.js");
|
|
7808
7530
|
const formats = [options.json, options.markdown, options.sarif].filter(Boolean).length;
|
|
7809
7531
|
if (formats > 1) {
|
|
7810
7532
|
console.error("Choose only one output format: --json, --markdown, or --sarif.");
|
|
@@ -7962,7 +7684,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
|
|
|
7962
7684
|
config.get("customProviders"),
|
|
7963
7685
|
config.getConfigDir()
|
|
7964
7686
|
);
|
|
7965
|
-
const { startHub } = await import("./hub-
|
|
7687
|
+
const { startHub } = await import("./hub-NX7HYN7V.js");
|
|
7966
7688
|
await startHub(
|
|
7967
7689
|
{
|
|
7968
7690
|
topic: topic ?? "",
|