jinzd-ai-cli 0.4.279 → 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 (31) hide show
  1. package/dist/{batch-6QZSWCBL.js → batch-F27NOTWC.js} +2 -2
  2. package/dist/{chunk-JLOQBYU4.js → chunk-B3FHA6IN.js} +3 -3
  3. package/dist/{chunk-FQJFGGKN.js → chunk-CP5LAA52.js} +4 -4
  4. package/dist/{chunk-UD3BVNC5.js → chunk-EOP775JU.js} +1 -1
  5. package/dist/{chunk-7L4TEK7Q.js → chunk-IIO2SMEJ.js} +118 -3
  6. package/dist/{chunk-RJY3HJS4.js → chunk-LPZNOYRJ.js} +1 -1
  7. package/dist/{chunk-SIVM2YQQ.js → chunk-NHJ4GHL4.js} +1 -1
  8. package/dist/{chunk-5XHEXRMN.js → chunk-PN42JO74.js} +1 -1
  9. package/dist/{chunk-CMNXAJLH.js → chunk-PUC277TH.js} +1 -1
  10. package/dist/{chunk-JS6VAPWM.js → chunk-TAIZZY3N.js} +3 -3
  11. package/dist/{chunk-2BKRWTEQ.js → chunk-UBPRUSAF.js} +1 -1
  12. package/dist/{chunk-IIXZ7IPN.js → chunk-UMWDNNPS.js} +1 -1
  13. package/dist/{chunk-6WMT7OQG.js → chunk-V7EZ4SDC.js} +1 -1
  14. package/dist/{chunk-NZPHEUJM.js → chunk-VQCFEA4Z.js} +1 -1
  15. package/dist/{ci-F4ESOYI5.js → ci-HJ4OVHCM.js} +4 -4
  16. package/dist/{ci-format-AIRW3TVQ.js → ci-format-NKJRZ3QI.js} +2 -2
  17. package/dist/{constants-3VMMZJDS.js → constants-6LCZOBJC.js} +1 -1
  18. package/dist/{doctor-cli-WVMEWMYE.js → doctor-cli-7JGPC5G4.js} +4 -4
  19. package/dist/electron-server.js +133 -88
  20. package/dist/{hub-JJCCCU3O.js → hub-NX7HYN7V.js} +1 -1
  21. package/dist/index.js +58 -125
  22. package/dist/{persistent-memory-QZN4Q3W4.js → persistent-memory-E6WECUTW.js} +2 -2
  23. package/dist/{persistent-memory-KSZKM4JG.js → persistent-memory-MHHX7F25.js} +2 -2
  24. package/dist/{pr-GFB5JC26.js → pr-GLUFBQLI.js} +4 -4
  25. package/dist/{run-tests-HMHHIG7Y.js → run-tests-LWAFPVS3.js} +2 -2
  26. package/dist/{run-tests-EL54INOI.js → run-tests-YPJDOEJA.js} +2 -2
  27. package/dist/{server-WUSJWC3A.js → server-CXXYIPMU.js} +50 -93
  28. package/dist/{server-6C7GITHY.js → server-P6DI27CY.js} +5 -5
  29. package/dist/{task-orchestrator-C7RUUA2Q.js → task-orchestrator-FW4LBPTS.js} +5 -5
  30. package/dist/{usage-CW6BT2UV.js → usage-CJUHQDT2.js} +2 -2
  31. package/package.json +1 -1
@@ -40,14 +40,14 @@ import {
40
40
  touchMemoryReferences,
41
41
  updateMemoryApproval,
42
42
  updateMemoryEntry
43
- } from "./chunk-CMNXAJLH.js";
43
+ } from "./chunk-PUC277TH.js";
44
44
  import {
45
45
  redactJson,
46
46
  scanString
47
47
  } from "./chunk-FSC6KEWU.js";
48
48
  import {
49
49
  runTestsTool
50
- } from "./chunk-SIVM2YQQ.js";
50
+ } from "./chunk-NHJ4GHL4.js";
51
51
  import {
52
52
  AGENTIC_BEHAVIOR_GUIDELINE,
53
53
  APP_NAME,
@@ -80,7 +80,7 @@ import {
80
80
  SUBAGENT_MAX_ROUNDS_LIMIT,
81
81
  VERSION,
82
82
  buildUserIdentityPrompt
83
- } from "./chunk-5XHEXRMN.js";
83
+ } from "./chunk-PN42JO74.js";
84
84
  import {
85
85
  hasSemanticIndex,
86
86
  semanticSearch
@@ -14370,6 +14370,101 @@ function decideModel(input) {
14370
14370
  return pickModel(input.userInput, input.currentModel, input.routingConfig, input.availableModels);
14371
14371
  }
14372
14372
 
14373
+ // src/core/session-export.ts
14374
+ function defaultExportFilename(session, format) {
14375
+ const dateTag = session.created.toISOString().slice(0, 10);
14376
+ return `session-${dateTag}-${session.id.slice(0, 8)}.${format === "json" ? "json" : "md"}`;
14377
+ }
14378
+ function markdownHeading(msg) {
14379
+ switch (msg.role) {
14380
+ case "user":
14381
+ return "## \u{1F464} You";
14382
+ case "assistant":
14383
+ return "## \u{1F916} Assistant";
14384
+ case "tool":
14385
+ return `### \u{1F527} Tool result: ${msg.toolName ?? "tool"}${msg.isError ? " (error)" : ""}`;
14386
+ default:
14387
+ return `## \u2699 ${msg.role}`;
14388
+ }
14389
+ }
14390
+ function buildSessionExport(session, format, outFile) {
14391
+ const filename = outFile || defaultExportFilename(session, format);
14392
+ if (format === "json") {
14393
+ const payload = session.toJSON ? session.toJSON() : {
14394
+ id: session.id,
14395
+ title: session.title ?? null,
14396
+ provider: session.provider,
14397
+ model: session.model,
14398
+ created: session.created.toISOString(),
14399
+ messages: session.messages
14400
+ };
14401
+ return { filename, content: JSON.stringify(payload, null, 2), messageCount: session.messages.length };
14402
+ }
14403
+ const dateStr = session.created.toISOString().replace("T", " ").slice(0, 19);
14404
+ let md = `# ${session.title ?? "Conversation Export"}
14405
+
14406
+ `;
14407
+ md += `| Field | Value |
14408
+ |----------|-------|
14409
+ `;
14410
+ md += `| Provider | ${session.provider} |
14411
+ `;
14412
+ md += `| Model | ${session.model} |
14413
+ `;
14414
+ md += `| Date | ${dateStr} |
14415
+ `;
14416
+ md += `| Session | ${session.id.slice(0, 8)} |
14417
+
14418
+ ---
14419
+
14420
+ `;
14421
+ for (const msg of session.messages) {
14422
+ const text = getContentText(msg.content);
14423
+ md += `${markdownHeading(msg)}
14424
+
14425
+ `;
14426
+ if (text.trim()) md += `${text}
14427
+
14428
+ `;
14429
+ if (msg.toolCalls && msg.toolCalls.length > 0) {
14430
+ for (const tc of msg.toolCalls) {
14431
+ md += `\`\`\`json
14432
+ ${JSON.stringify({ tool: tc.name, arguments: tc.arguments ?? {} }, null, 2)}
14433
+ \`\`\`
14434
+
14435
+ `;
14436
+ }
14437
+ }
14438
+ md += `---
14439
+
14440
+ `;
14441
+ }
14442
+ return { filename, content: md, messageCount: session.messages.length };
14443
+ }
14444
+ function parseCheckpointCommand(args) {
14445
+ const sub = args[0]?.toLowerCase();
14446
+ if (!sub || sub === "list") return { kind: "list" };
14447
+ const name = args.slice(1).join(" ").trim();
14448
+ if (sub === "save" || sub === "restore" || sub === "delete") {
14449
+ if (!name) return { kind: "usage", message: `Usage: /checkpoint ${sub} <name>` };
14450
+ return { kind: sub, name };
14451
+ }
14452
+ return { kind: "unknown", message: `Unknown subcommand: ${sub}. Use save/restore/list/delete.` };
14453
+ }
14454
+ function formatCheckpointList(checkpoints) {
14455
+ if (checkpoints.length === 0) {
14456
+ return ["No checkpoints. Use /checkpoint save <name> to create one."];
14457
+ }
14458
+ return [
14459
+ `Checkpoints (${checkpoints.length}):`,
14460
+ ...checkpoints.map((cp) => ` ${cp.name.padEnd(20)} msg #${cp.messageIndex} ${cp.timestamp.toLocaleString()}`)
14461
+ ];
14462
+ }
14463
+ var checkpointSavedMessage = (name, messageCount) => `\u2713 Checkpoint "${name}" saved at message #${messageCount}`;
14464
+ var checkpointRestoredMessage = (name, messageCount) => `\u2713 Restored to checkpoint "${name}" (${messageCount} messages, token usage reset)`;
14465
+ var checkpointDeletedMessage = (name) => `\u2713 Deleted checkpoint "${name}"`;
14466
+ var checkpointNotFoundMessage = (name) => `Checkpoint "${name}" not found.`;
14467
+
14373
14468
  // src/core/context-files.ts
14374
14469
  import { existsSync as existsSync25, readFileSync as readFileSync20 } from "fs";
14375
14470
  import { join as join19, relative as relative4, resolve as resolve8 } from "path";
@@ -16656,7 +16751,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
16656
16751
  Cost: ${formatCost(cost)}` : "";
16657
16752
  let memoryLine = "";
16658
16753
  try {
16659
- const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-QZN4Q3W4.js");
16754
+ const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-E6WECUTW.js");
16660
16755
  const pending = countPendingMemories2(ctx.config.getConfigDir());
16661
16756
  if (pending > 0) memoryLine = `
16662
16757
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -17017,56 +17112,36 @@ async function handleCheckpoint(args, ctx) {
17017
17112
  ctx.send({ type: "error", message: "No active session." });
17018
17113
  return;
17019
17114
  }
17020
- const sub = args[0]?.toLowerCase();
17021
- if (!sub || sub === "list") {
17022
- const cps = session.checkpoints;
17023
- if (cps.length === 0) {
17024
- ctx.send({ type: "info", message: "No checkpoints. Use /checkpoint save <name> to create one." });
17025
- } else {
17026
- const lines = [`\u{1F4CC} Checkpoints (${cps.length}):`, ""];
17027
- for (const cp of cps) {
17028
- const ts = cp.timestamp.toLocaleString();
17029
- lines.push(` ${cp.name.padEnd(20)} msg #${cp.messageIndex} ${ts}`);
17030
- }
17031
- ctx.send({ type: "info", message: lines.join("\n") });
17032
- }
17115
+ const intent = parseCheckpointCommand(args);
17116
+ if (intent.kind === "list") {
17117
+ ctx.send({ type: "info", message: formatCheckpointList(session.checkpoints).join("\n") });
17033
17118
  return;
17034
17119
  }
17035
- const cpName = args.slice(1).join(" ").trim();
17036
- if (sub === "save") {
17037
- if (!cpName) {
17038
- ctx.send({ type: "error", message: "Usage: /checkpoint save <name>" });
17039
- return;
17040
- }
17041
- session.createCheckpoint(cpName);
17042
- ctx.send({ type: "info", message: `\u2713 Checkpoint "${cpName}" saved at message #${session.messages.length}` });
17043
- } else if (sub === "restore") {
17044
- if (!cpName) {
17045
- ctx.send({ type: "error", message: "Usage: /checkpoint restore <name>" });
17046
- return;
17047
- }
17048
- const ok = session.restoreCheckpoint(cpName);
17049
- if (ok) {
17050
- ctx.send({ type: "info", message: `\u2713 Restored to checkpoint "${cpName}" (${session.messages.length} messages)` });
17051
- ctx.sendSessionMessages();
17052
- ctx.sendStatus();
17053
- } else {
17054
- ctx.send({ type: "error", message: `Checkpoint "${cpName}" not found.` });
17055
- }
17056
- } else if (sub === "delete") {
17057
- if (!cpName) {
17058
- ctx.send({ type: "error", message: "Usage: /checkpoint delete <name>" });
17120
+ if (intent.kind === "usage" || intent.kind === "unknown") {
17121
+ ctx.send({ type: "error", message: intent.message });
17122
+ return;
17123
+ }
17124
+ if (intent.kind === "save") {
17125
+ session.createCheckpoint(intent.name);
17126
+ ctx.send({ type: "info", message: checkpointSavedMessage(intent.name, session.messages.length) });
17127
+ return;
17128
+ }
17129
+ if (intent.kind === "restore") {
17130
+ if (!session.restoreCheckpoint(intent.name)) {
17131
+ ctx.send({ type: "error", message: checkpointNotFoundMessage(intent.name) });
17059
17132
  return;
17060
17133
  }
17061
- const ok = session.deleteCheckpoint(cpName);
17062
- if (ok) {
17063
- ctx.send({ type: "info", message: `\u2713 Deleted checkpoint "${cpName}"` });
17064
- } else {
17065
- ctx.send({ type: "error", message: `Checkpoint "${cpName}" not found.` });
17066
- }
17067
- } else {
17068
- ctx.send({ type: "error", message: `Unknown subcommand: ${sub}. Use save/restore/list/delete.` });
17134
+ ctx.resetWebSessionUsage();
17135
+ ctx.send({ type: "info", message: checkpointRestoredMessage(intent.name, session.messages.length) });
17136
+ ctx.sendSessionMessages();
17137
+ ctx.sendStatus();
17138
+ return;
17069
17139
  }
17140
+ if (!session.deleteCheckpoint(intent.name)) {
17141
+ ctx.send({ type: "error", message: checkpointNotFoundMessage(intent.name) });
17142
+ return;
17143
+ }
17144
+ ctx.send({ type: "info", message: checkpointDeletedMessage(intent.name) });
17070
17145
  }
17071
17146
  async function handleBranch(args, ctx) {
17072
17147
  const session = ctx.sessions.current;
@@ -17583,7 +17658,7 @@ async function handleTest(args, ctx) {
17583
17658
  const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
17584
17659
  testArgs = isCommand ? { command: argStr } : { filter: argStr };
17585
17660
  }
17586
- const runTests = ctx.runTests ?? (await import("./run-tests-HMHHIG7Y.js")).executeTests;
17661
+ const runTests = ctx.runTests ?? (await import("./run-tests-LWAFPVS3.js")).executeTests;
17587
17662
  const report = await runTests(testArgs);
17588
17663
  ctx.send({ type: "info", message: report });
17589
17664
  } catch (err) {
@@ -17919,7 +17994,7 @@ async function handleMemory(args, ctx) {
17919
17994
  ctx.handleMemoryManage(sub, args[1], sub === "expire" ? args[2] : void 0);
17920
17995
  } else if (sub === "export") {
17921
17996
  if (args[1] === "md") {
17922
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-QZN4Q3W4.js");
17997
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-E6WECUTW.js");
17923
17998
  ctx.send({
17924
17999
  type: "export_data",
17925
18000
  format: "md",
@@ -19764,43 +19839,13 @@ ${summaryContent}`,
19764
19839
  this.send({ type: "info", message: "No messages to export." });
19765
19840
  return;
19766
19841
  }
19767
- const title = session.title ?? "Untitled";
19768
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
19769
- if (format === "json") {
19770
- const data = {
19771
- title,
19772
- provider: this.currentProvider,
19773
- model: this.currentModel,
19774
- exported: (/* @__PURE__ */ new Date()).toISOString(),
19775
- messages: session.messages.map((m) => ({
19776
- role: m.role,
19777
- content: getContentText(m.content),
19778
- timestamp: m.timestamp?.toISOString()
19779
- }))
19780
- };
19781
- this.send({
19782
- type: "export_data",
19783
- format: "json",
19784
- filename: `aicli-${timestamp}.json`,
19785
- content: JSON.stringify(data, null, 2)
19786
- });
19787
- } else {
19788
- const lines = [`# ${title}`, "", `> Exported: ${(/* @__PURE__ */ new Date()).toLocaleString()} | Provider: ${this.currentProvider} | Model: ${this.currentModel}`, ""];
19789
- for (const m of session.messages) {
19790
- const text = getContentText(m.content);
19791
- if (m.role === "user") {
19792
- lines.push(`## \u{1F9D1} User`, "", text, "");
19793
- } else if (m.role === "assistant") {
19794
- lines.push(`## \u{1F916} Assistant`, "", text, "");
19795
- }
19796
- }
19797
- this.send({
19798
- type: "export_data",
19799
- format: "md",
19800
- filename: `aicli-${timestamp}.md`,
19801
- content: lines.join("\n")
19802
- });
19803
- }
19842
+ const exported = buildSessionExport(session, format);
19843
+ this.send({
19844
+ type: "export_data",
19845
+ format,
19846
+ filename: exported.filename,
19847
+ content: exported.content
19848
+ });
19804
19849
  }
19805
19850
  memoryShow(args = []) {
19806
19851
  const configDir = this.config.getConfigDir();
@@ -158,7 +158,7 @@ ${content}`);
158
158
  }
159
159
  }
160
160
  async function runTaskMode(config, providers, configManager, topic) {
161
- const { TaskOrchestrator } = await import("./task-orchestrator-C7RUUA2Q.js");
161
+ const { TaskOrchestrator } = await import("./task-orchestrator-FW4LBPTS.js");
162
162
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
163
163
  let interrupted = false;
164
164
  const onSigint = () => {
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,10 +24,13 @@ import {
19
24
  estimateConversationTokens,
20
25
  evaluateContextPressure,
21
26
  filterMemoryEntries,
27
+ formatCheckpointList,
22
28
  formatSessionSummaryLine,
23
29
  loadDevState,
24
30
  parseBatchDeleteArgs,
31
+ parseCheckpointCommand,
25
32
  parseCleanArgs,
33
+ parseExportArgs,
26
34
  parseMemoryShowFilters,
27
35
  parseModelCommand,
28
36
  parseRouteCommand,
@@ -45,7 +53,7 @@ import {
45
53
  setupProxy,
46
54
  snapshotFile,
47
55
  stripRoutingTags
48
- } from "./chunk-7L4TEK7Q.js";
56
+ } from "./chunk-IIO2SMEJ.js";
49
57
  import {
50
58
  CostTracker,
51
59
  computeCost,
@@ -75,7 +83,7 @@ import {
75
83
  setMaxOutputCap,
76
84
  spawnAgentContext,
77
85
  undoStack
78
- } from "./chunk-FQJFGGKN.js";
86
+ } from "./chunk-CP5LAA52.js";
79
87
  import {
80
88
  buildReviewPrompt,
81
89
  buildSecurityReviewPrompt
@@ -116,7 +124,7 @@ import {
116
124
  touchMemoryReferences,
117
125
  updateMemoryApproval,
118
126
  updateMemoryEntry
119
- } from "./chunk-6WMT7OQG.js";
127
+ } from "./chunk-V7EZ4SDC.js";
120
128
  import "./chunk-4DEMGCK4.js";
121
129
  import "./chunk-UUSRWSSX.js";
122
130
  import "./chunk-CKH4KQ4E.js";
@@ -140,7 +148,7 @@ import {
140
148
  formatDoctorReport,
141
149
  loadContextFiles,
142
150
  writeCrashLog
143
- } from "./chunk-JLOQBYU4.js";
151
+ } from "./chunk-B3FHA6IN.js";
144
152
  import {
145
153
  describePlugin,
146
154
  getActivePluginAssets,
@@ -157,14 +165,14 @@ import {
157
165
  trustHook,
158
166
  trustPlugin,
159
167
  untrustHook
160
- } from "./chunk-IIXZ7IPN.js";
168
+ } from "./chunk-UMWDNNPS.js";
161
169
  import {
162
170
  ProviderRegistry,
163
171
  listBuiltInProviderMetadata
164
172
  } from "./chunk-UGY5SVNX.js";
165
173
  import {
166
174
  ConfigManager
167
- } from "./chunk-UD3BVNC5.js";
175
+ } from "./chunk-EOP775JU.js";
168
176
  import {
169
177
  CONTENT_ONLY_STREAM_REMINDER,
170
178
  TEE_FINAL_USER_NUDGE,
@@ -202,7 +210,7 @@ import {
202
210
  import {
203
211
  fileCheckpoints
204
212
  } from "./chunk-4BKXL7SM.js";
205
- import "./chunk-NZPHEUJM.js";
213
+ import "./chunk-VQCFEA4Z.js";
206
214
  import {
207
215
  AGENTIC_BEHAVIOR_GUIDELINE,
208
216
  AUTHOR,
@@ -220,7 +228,7 @@ import {
220
228
  SKILLS_DIR_NAME,
221
229
  VERSION,
222
230
  buildUserIdentityPrompt
223
- } from "./chunk-2BKRWTEQ.js";
231
+ } from "./chunk-UBPRUSAF.js";
224
232
 
225
233
  // src/index.ts
226
234
  import { program } from "commander";
@@ -1338,7 +1346,7 @@ No tools match "${filter}".
1338
1346
  const { join: join6 } = await import("path");
1339
1347
  const { existsSync: existsSync6 } = await import("fs");
1340
1348
  const { getGitRoot: getGitRoot2 } = await import("./git-context-EXOEHQSF.js");
1341
- const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-3VMMZJDS.js");
1349
+ const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-6LCZOBJC.js");
1342
1350
  const { approveProject, hashMcpFile } = await import("./project-trust-NKYHL3VZ.js");
1343
1351
  const cwd = process.cwd();
1344
1352
  const projectRoot = getGitRoot2(cwd) ?? cwd;
@@ -2258,7 +2266,7 @@ function createReviewCommands() {
2258
2266
  usage: "/test [command|filter]",
2259
2267
  async execute(args, ctx) {
2260
2268
  try {
2261
- const { executeTests } = await import("./run-tests-EL54INOI.js");
2269
+ const { executeTests } = await import("./run-tests-YPJDOEJA.js");
2262
2270
  const argStr = args.join(" ").trim();
2263
2271
  let testArgs = {};
2264
2272
  if (argStr) {
@@ -3281,76 +3289,20 @@ function createSessionCommands() {
3281
3289
  description: "Export current session to file or stdout",
3282
3290
  usage: "/export [md|json] [filename]",
3283
3291
  execute(args, ctx) {
3284
- let format = "md";
3285
- let outFile = null;
3286
- for (const arg of args) {
3287
- if (arg === "md" || arg === "json") {
3288
- format = arg;
3289
- } else if (arg) {
3290
- outFile = arg;
3291
- }
3292
- }
3292
+ const { format, outFile } = parseExportArgs(args);
3293
3293
  const session = ctx.sessions.current;
3294
3294
  if (!session || session.messages.length === 0) {
3295
3295
  ctx.renderer.printInfo("No messages to export.");
3296
3296
  return;
3297
3297
  }
3298
- let output;
3299
- if (format === "json") {
3300
- output = JSON.stringify(session.toJSON(), null, 2);
3301
- } else {
3302
- const dateStr = session.created.toISOString().replace("T", " ").slice(0, 19);
3303
- let md = `# Conversation Export
3304
-
3305
- `;
3306
- md += `| Field | Value |
3307
- |----------|-------|
3308
- `;
3309
- md += `| Provider | ${session.provider} |
3310
- `;
3311
- md += `| Model | ${session.model} |
3312
- `;
3313
- md += `| Date | ${dateStr} |
3314
- `;
3315
- md += `| Session | ${session.id.slice(0, 8)} |
3316
-
3317
- ---
3318
-
3319
- `;
3320
- for (const msg of session.messages) {
3321
- const role = msg.role === "user" ? "## \u{1F464} You" : "## \u{1F916} Assistant";
3322
- const text = getContentText(msg.content);
3323
- md += `${role}
3324
-
3325
- ${text}
3326
-
3327
- ---
3328
-
3329
- `;
3330
- }
3331
- output = md;
3332
- }
3333
- if (outFile) {
3334
- const absPath = resolve(process.cwd(), outFile);
3335
- try {
3336
- mkdirSync2(dirname2(absPath), { recursive: true });
3337
- writeFileSync2(absPath, output, "utf-8");
3338
- ctx.renderer.printSuccess(`Exported ${session.messages.length} messages \u2192 ${absPath}`);
3339
- } catch (err) {
3340
- ctx.renderer.renderError(`Failed to write file: ${err instanceof Error ? err.message : String(err)}`);
3341
- }
3342
- } else {
3343
- const shortId = session.id.slice(0, 8);
3344
- const dateTag = session.created.toISOString().slice(0, 10);
3345
- const ext = format === "json" ? "json" : "md";
3346
- const autoName = `session-${dateTag}-${shortId}.${ext}`;
3347
- const absPath = resolve(process.cwd(), autoName);
3348
- try {
3349
- writeFileSync2(absPath, output, "utf-8");
3350
- ctx.renderer.printSuccess(`Exported ${session.messages.length} messages \u2192 ${absPath}`);
3351
- } catch (err) {
3352
- ctx.renderer.renderError(`Failed to write file: ${err instanceof Error ? err.message : String(err)}`);
3353
- }
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)}`);
3354
3306
  }
3355
3307
  }
3356
3308
  },
@@ -3364,59 +3316,40 @@ ${text}
3364
3316
  ctx.renderer.renderError("No active session.");
3365
3317
  return;
3366
3318
  }
3367
- const sub = args[0]?.toLowerCase();
3368
- if (!sub || sub === "list") {
3369
- const cps = ctx.listCheckpoints();
3370
- if (cps.length === 0) {
3371
- console.log(theme.dim(" No checkpoints. Use /checkpoint save <name> to create one."));
3372
- return;
3373
- }
3374
- console.log(theme.dim(` Checkpoints (${cps.length}):`));
3375
- for (const cp of cps) {
3376
- const ts = cp.timestamp.toLocaleString();
3377
- 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));
3378
3326
  }
3379
3327
  console.log();
3380
3328
  return;
3381
3329
  }
3382
- const name = args.slice(1).join(" ").trim();
3383
- if (sub === "save") {
3384
- if (!name) {
3385
- ctx.renderer.renderError("Usage: /checkpoint save <name>");
3386
- return;
3387
- }
3388
- ctx.createCheckpoint(name);
3389
- 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);
3390
3332
  return;
3391
3333
  }
3392
- if (sub === "restore") {
3393
- if (!name) {
3394
- ctx.renderer.renderError("Usage: /checkpoint restore <name>");
3395
- return;
3396
- }
3397
- const ok = ctx.restoreCheckpoint(name);
3398
- if (ok) {
3399
- ctx.resetSessionTokenUsage();
3400
- console.log(theme.success(` \u2713 Restored to checkpoint "${name}" (${session.messages.length} messages, token usage reset)`));
3401
- } else {
3402
- ctx.renderer.renderError(`Checkpoint "${name}" not found.`);
3403
- }
3334
+ if (intent.kind === "save") {
3335
+ ctx.createCheckpoint(intent.name);
3336
+ console.log(theme.success(` ${checkpointSavedMessage(intent.name, session.messages.length)}`));
3404
3337
  return;
3405
3338
  }
3406
- if (sub === "delete") {
3407
- if (!name) {
3408
- ctx.renderer.renderError("Usage: /checkpoint delete <name>");
3339
+ if (intent.kind === "restore") {
3340
+ if (!ctx.restoreCheckpoint(intent.name)) {
3341
+ ctx.renderer.renderError(checkpointNotFoundMessage(intent.name));
3409
3342
  return;
3410
3343
  }
3411
- const ok = ctx.deleteCheckpoint(name);
3412
- if (ok) {
3413
- console.log(theme.success(` \u2713 Deleted checkpoint "${name}"`));
3414
- } else {
3415
- ctx.renderer.renderError(`Checkpoint "${name}" not found.`);
3416
- }
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));
3417
3350
  return;
3418
3351
  }
3419
- ctx.renderer.renderError(`Unknown subcommand: ${sub}. Use save/restore/list/delete.`);
3352
+ console.log(theme.success(` ${checkpointDeletedMessage(intent.name)}`));
3420
3353
  }
3421
3354
  },
3422
3355
  // ── /review ──────────────────────────────────────────────────
@@ -7336,7 +7269,7 @@ program.command("web").description("Start Web UI server with browser-based chat
7336
7269
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
7337
7270
  process.exit(1);
7338
7271
  }
7339
- const { startWebServer } = await import("./server-WUSJWC3A.js");
7272
+ const { startWebServer } = await import("./server-CXXYIPMU.js");
7340
7273
  await startWebServer({ port, host: options.host });
7341
7274
  });
7342
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) => {
@@ -7503,11 +7436,11 @@ program.command("sessions").description("List recent conversation sessions").opt
7503
7436
  console.log(footer + "\n");
7504
7437
  });
7505
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) => {
7506
- const { runUsageCli } = await import("./usage-CW6BT2UV.js");
7439
+ const { runUsageCli } = await import("./usage-CJUHQDT2.js");
7507
7440
  await runUsageCli(options);
7508
7441
  });
7509
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) => {
7510
- const { runDoctorCli } = await import("./doctor-cli-WVMEWMYE.js");
7443
+ const { runDoctorCli } = await import("./doctor-cli-7JGPC5G4.js");
7511
7444
  const argv = process.argv.slice(2);
7512
7445
  await runDoctorCli({
7513
7446
  json: !!options.json || argv.includes("--json"),
@@ -7516,7 +7449,7 @@ program.command("doctor").description("Health check: API keys, config, MCP, rece
7516
7449
  });
7517
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) => {
7518
7451
  try {
7519
- const batch = await import("./batch-6QZSWCBL.js");
7452
+ const batch = await import("./batch-F27NOTWC.js");
7520
7453
  switch (action) {
7521
7454
  case "submit":
7522
7455
  if (!arg) {
@@ -7559,7 +7492,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
7559
7492
  }
7560
7493
  });
7561
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) => {
7562
- const { startMcpServer } = await import("./server-6C7GITHY.js");
7495
+ const { startMcpServer } = await import("./server-P6DI27CY.js");
7563
7496
  await startMcpServer({
7564
7497
  allowDestructive: !!options.allowDestructive,
7565
7498
  allowOutsideCwd: !!options.allowOutsideCwd,
@@ -7572,7 +7505,7 @@ program.command("pr <action> [target]").description("PR review helpers: review |
7572
7505
  console.error(`Unknown pr action: ${action}. Use review | security-review | summarize.`);
7573
7506
  process.exit(1);
7574
7507
  }
7575
- const { runPrCli } = await import("./pr-GFB5JC26.js");
7508
+ const { runPrCli } = await import("./pr-GLUFBQLI.js");
7576
7509
  const result = await runPrCli({
7577
7510
  action,
7578
7511
  target,
@@ -7592,8 +7525,8 @@ program.command("pr <action> [target]").description("PR review helpers: review |
7592
7525
  process.exit(result.exitCode);
7593
7526
  });
7594
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) => {
7595
- const { runCi } = await import("./ci-F4ESOYI5.js");
7596
- const { formatCiResult } = await import("./ci-format-AIRW3TVQ.js");
7528
+ const { runCi } = await import("./ci-HJ4OVHCM.js");
7529
+ const { formatCiResult } = await import("./ci-format-NKJRZ3QI.js");
7597
7530
  const formats = [options.json, options.markdown, options.sarif].filter(Boolean).length;
7598
7531
  if (formats > 1) {
7599
7532
  console.error("Choose only one output format: --json, --markdown, or --sarif.");
@@ -7751,7 +7684,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
7751
7684
  config.get("customProviders"),
7752
7685
  config.getConfigDir()
7753
7686
  );
7754
- const { startHub } = await import("./hub-JJCCCU3O.js");
7687
+ const { startHub } = await import("./hub-NX7HYN7V.js");
7755
7688
  await startHub(
7756
7689
  {
7757
7690
  topic: topic ?? "",
@@ -27,9 +27,9 @@ import {
27
27
  touchMemoryReferences,
28
28
  updateMemoryApproval,
29
29
  updateMemoryEntry
30
- } from "./chunk-CMNXAJLH.js";
30
+ } from "./chunk-PUC277TH.js";
31
31
  import "./chunk-FSC6KEWU.js";
32
- import "./chunk-5XHEXRMN.js";
32
+ import "./chunk-PN42JO74.js";
33
33
  import "./chunk-6BUTA5VW.js";
34
34
  export {
35
35
  addMemoryEntry,