jinzd-ai-cli 0.4.279 → 0.4.281

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-6QZSWCBL.js → batch-237ZXBQD.js} +2 -2
  2. package/dist/{chunk-2BKRWTEQ.js → chunk-2FCKZ3OS.js} +1 -1
  3. package/dist/{chunk-UD3BVNC5.js → chunk-4XJVSMZ6.js} +1 -1
  4. package/dist/{chunk-5XHEXRMN.js → chunk-5GYOQ7EF.js} +1 -1
  5. package/dist/{chunk-CGDYO52A.js → chunk-6NO5FZW6.js} +1 -0
  6. package/dist/{chunk-JLOQBYU4.js → chunk-BVGSR3BA.js} +3 -3
  7. package/dist/{chunk-FQJFGGKN.js → chunk-FHRIDE2T.js} +4 -4
  8. package/dist/{chunk-6WMT7OQG.js → chunk-H2VE4TTN.js} +1 -1
  9. package/dist/{chunk-CMNXAJLH.js → chunk-IXEKDAIX.js} +1 -1
  10. package/dist/{chunk-NZPHEUJM.js → chunk-J3RWNQOF.js} +1 -1
  11. package/dist/{chunk-7L4TEK7Q.js → chunk-J5TXHFDO.js} +122 -3
  12. package/dist/{chunk-RJY3HJS4.js → chunk-JT2A2M4F.js} +1 -1
  13. package/dist/{chunk-IIXZ7IPN.js → chunk-L7C34TFI.js} +1 -1
  14. package/dist/{chunk-JS6VAPWM.js → chunk-UTJQXG4P.js} +3 -3
  15. package/dist/{chunk-MX75TNE5.js → chunk-VB54ILH7.js} +1 -1
  16. package/dist/{chunk-SIVM2YQQ.js → chunk-WUIOUJA2.js} +1 -1
  17. package/dist/{ci-F4ESOYI5.js → ci-LXRTYJ6F.js} +4 -4
  18. package/dist/{ci-format-AIRW3TVQ.js → ci-format-II3OT2VU.js} +2 -2
  19. package/dist/{constants-3VMMZJDS.js → constants-X53QCUTP.js} +1 -1
  20. package/dist/{doctor-cli-WVMEWMYE.js → doctor-cli-6JCJEQR4.js} +4 -4
  21. package/dist/electron-server.js +144 -91
  22. package/dist/{hub-JJCCCU3O.js → hub-RXAFF7QI.js} +2 -2
  23. package/dist/index.js +68 -130
  24. package/dist/{persist-PQM4BRI4.js → persist-TBQILDSE.js} +2 -2
  25. package/dist/{persistent-memory-KSZKM4JG.js → persistent-memory-7CKJLS25.js} +2 -2
  26. package/dist/{persistent-memory-QZN4Q3W4.js → persistent-memory-WAKFKH2I.js} +2 -2
  27. package/dist/{pr-GFB5JC26.js → pr-DZTRHAMG.js} +4 -4
  28. package/dist/{run-tests-HMHHIG7Y.js → run-tests-4ESYEROQ.js} +2 -2
  29. package/dist/{run-tests-EL54INOI.js → run-tests-XGCNUT5S.js} +2 -2
  30. package/dist/{server-WUSJWC3A.js → server-6RYXFG3H.js} +60 -98
  31. package/dist/{server-6C7GITHY.js → server-EFA7UP4I.js} +5 -5
  32. package/dist/{task-orchestrator-C7RUUA2Q.js → task-orchestrator-H3AEIHR3.js} +5 -5
  33. package/dist/{usage-CW6BT2UV.js → usage-W7TZWHY7.js} +2 -2
  34. 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-IXEKDAIX.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-WUIOUJA2.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-5GYOQ7EF.js";
84
84
  import {
85
85
  hasSemanticIndex,
86
86
  semanticSearch
@@ -5228,6 +5228,7 @@ var SessionManager = class {
5228
5228
  /** P1-PERF-03: `force` 跳过脏检查(用于进程退出、fork 等必须落盘场景) */
5229
5229
  async save(force = false) {
5230
5230
  if (!this._current) return;
5231
+ if (this._current.messages.length === 0) return;
5231
5232
  if (!force && !this._current.dirty) return;
5232
5233
  mkdirSync3(this.historyDir, { recursive: true });
5233
5234
  const filePath = join4(this.historyDir, `${this._current.id}.json`);
@@ -14370,6 +14371,101 @@ function decideModel(input) {
14370
14371
  return pickModel(input.userInput, input.currentModel, input.routingConfig, input.availableModels);
14371
14372
  }
14372
14373
 
14374
+ // src/core/session-export.ts
14375
+ function defaultExportFilename(session, format) {
14376
+ const dateTag = session.created.toISOString().slice(0, 10);
14377
+ return `session-${dateTag}-${session.id.slice(0, 8)}.${format === "json" ? "json" : "md"}`;
14378
+ }
14379
+ function markdownHeading(msg) {
14380
+ switch (msg.role) {
14381
+ case "user":
14382
+ return "## \u{1F464} You";
14383
+ case "assistant":
14384
+ return "## \u{1F916} Assistant";
14385
+ case "tool":
14386
+ return `### \u{1F527} Tool result: ${msg.toolName ?? "tool"}${msg.isError ? " (error)" : ""}`;
14387
+ default:
14388
+ return `## \u2699 ${msg.role}`;
14389
+ }
14390
+ }
14391
+ function buildSessionExport(session, format, outFile) {
14392
+ const filename = outFile || defaultExportFilename(session, format);
14393
+ if (format === "json") {
14394
+ const payload = session.toJSON ? session.toJSON() : {
14395
+ id: session.id,
14396
+ title: session.title ?? null,
14397
+ provider: session.provider,
14398
+ model: session.model,
14399
+ created: session.created.toISOString(),
14400
+ messages: session.messages
14401
+ };
14402
+ return { filename, content: JSON.stringify(payload, null, 2), messageCount: session.messages.length };
14403
+ }
14404
+ const dateStr = session.created.toISOString().replace("T", " ").slice(0, 19);
14405
+ let md = `# ${session.title ?? "Conversation Export"}
14406
+
14407
+ `;
14408
+ md += `| Field | Value |
14409
+ |----------|-------|
14410
+ `;
14411
+ md += `| Provider | ${session.provider} |
14412
+ `;
14413
+ md += `| Model | ${session.model} |
14414
+ `;
14415
+ md += `| Date | ${dateStr} |
14416
+ `;
14417
+ md += `| Session | ${session.id.slice(0, 8)} |
14418
+
14419
+ ---
14420
+
14421
+ `;
14422
+ for (const msg of session.messages) {
14423
+ const text = getContentText(msg.content);
14424
+ md += `${markdownHeading(msg)}
14425
+
14426
+ `;
14427
+ if (text.trim()) md += `${text}
14428
+
14429
+ `;
14430
+ if (msg.toolCalls && msg.toolCalls.length > 0) {
14431
+ for (const tc of msg.toolCalls) {
14432
+ md += `\`\`\`json
14433
+ ${JSON.stringify({ tool: tc.name, arguments: tc.arguments ?? {} }, null, 2)}
14434
+ \`\`\`
14435
+
14436
+ `;
14437
+ }
14438
+ }
14439
+ md += `---
14440
+
14441
+ `;
14442
+ }
14443
+ return { filename, content: md, messageCount: session.messages.length };
14444
+ }
14445
+ function parseCheckpointCommand(args) {
14446
+ const sub = args[0]?.toLowerCase();
14447
+ if (!sub || sub === "list") return { kind: "list" };
14448
+ const name = args.slice(1).join(" ").trim();
14449
+ if (sub === "save" || sub === "restore" || sub === "delete") {
14450
+ if (!name) return { kind: "usage", message: `Usage: /checkpoint ${sub} <name>` };
14451
+ return { kind: sub, name };
14452
+ }
14453
+ return { kind: "unknown", message: `Unknown subcommand: ${sub}. Use save/restore/list/delete.` };
14454
+ }
14455
+ function formatCheckpointList(checkpoints) {
14456
+ if (checkpoints.length === 0) {
14457
+ return ["No checkpoints. Use /checkpoint save <name> to create one."];
14458
+ }
14459
+ return [
14460
+ `Checkpoints (${checkpoints.length}):`,
14461
+ ...checkpoints.map((cp) => ` ${cp.name.padEnd(20)} msg #${cp.messageIndex} ${cp.timestamp.toLocaleString()}`)
14462
+ ];
14463
+ }
14464
+ var checkpointSavedMessage = (name, messageCount) => `\u2713 Checkpoint "${name}" saved at message #${messageCount}`;
14465
+ var checkpointRestoredMessage = (name, messageCount) => `\u2713 Restored to checkpoint "${name}" (${messageCount} messages, token usage reset)`;
14466
+ var checkpointDeletedMessage = (name) => `\u2713 Deleted checkpoint "${name}"`;
14467
+ var checkpointNotFoundMessage = (name) => `Checkpoint "${name}" not found.`;
14468
+
14373
14469
  // src/core/context-files.ts
14374
14470
  import { existsSync as existsSync25, readFileSync as readFileSync20 } from "fs";
14375
14471
  import { join as join19, relative as relative4, resolve as resolve8 } from "path";
@@ -16632,13 +16728,20 @@ function selectStaleSessions(sessions, staleDays, now = Date.now()) {
16632
16728
  const cutoff = now - staleDays * 24 * 60 * 60 * 1e3;
16633
16729
  return sessions.filter((s) => s.updated.getTime() < cutoff);
16634
16730
  }
16731
+ function clearedSessionMessage(priorSessionId, priorMessageCount = 0) {
16732
+ return priorSessionId && priorMessageCount > 0 ? `Started a new session. Previous conversation saved as ${priorSessionId.slice(0, 8)} (${priorMessageCount} messages) \u2014 reload it with /session load ${priorSessionId.slice(0, 8)}.` : "Started a new session.";
16733
+ }
16635
16734
 
16636
16735
  // src/web/commands/session-commands.ts
16637
16736
  async function handleClear(_args, ctx) {
16737
+ const prior = ctx.sessions.current;
16738
+ const priorId = prior?.id ?? null;
16739
+ const priorCount = prior?.messages.length ?? 0;
16638
16740
  ctx.saveIfNeeded();
16639
- ctx.sessions.createSession(ctx.currentProvider, ctx.currentModel);
16741
+ const created = ctx.sessions.createSession(ctx.currentProvider, ctx.currentModel);
16742
+ ctx.unsavedSessions.set(created.id, created);
16640
16743
  ctx.resetWebSessionUsage();
16641
- ctx.send({ type: "info", message: "Conversation cleared." });
16744
+ ctx.send({ type: "info", message: clearedSessionMessage(priorId, priorCount) });
16642
16745
  ctx.sendStatus();
16643
16746
  ctx.sendSessionList();
16644
16747
  }
@@ -16656,7 +16759,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
16656
16759
  Cost: ${formatCost(cost)}` : "";
16657
16760
  let memoryLine = "";
16658
16761
  try {
16659
- const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-QZN4Q3W4.js");
16762
+ const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-WAKFKH2I.js");
16660
16763
  const pending = countPendingMemories2(ctx.config.getConfigDir());
16661
16764
  if (pending > 0) memoryLine = `
16662
16765
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -17017,56 +17120,36 @@ async function handleCheckpoint(args, ctx) {
17017
17120
  ctx.send({ type: "error", message: "No active session." });
17018
17121
  return;
17019
17122
  }
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
- }
17123
+ const intent = parseCheckpointCommand(args);
17124
+ if (intent.kind === "list") {
17125
+ ctx.send({ type: "info", message: formatCheckpointList(session.checkpoints).join("\n") });
17033
17126
  return;
17034
17127
  }
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>" });
17128
+ if (intent.kind === "usage" || intent.kind === "unknown") {
17129
+ ctx.send({ type: "error", message: intent.message });
17130
+ return;
17131
+ }
17132
+ if (intent.kind === "save") {
17133
+ session.createCheckpoint(intent.name);
17134
+ ctx.send({ type: "info", message: checkpointSavedMessage(intent.name, session.messages.length) });
17135
+ return;
17136
+ }
17137
+ if (intent.kind === "restore") {
17138
+ if (!session.restoreCheckpoint(intent.name)) {
17139
+ ctx.send({ type: "error", message: checkpointNotFoundMessage(intent.name) });
17059
17140
  return;
17060
17141
  }
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.` });
17142
+ ctx.resetWebSessionUsage();
17143
+ ctx.send({ type: "info", message: checkpointRestoredMessage(intent.name, session.messages.length) });
17144
+ ctx.sendSessionMessages();
17145
+ ctx.sendStatus();
17146
+ return;
17069
17147
  }
17148
+ if (!session.deleteCheckpoint(intent.name)) {
17149
+ ctx.send({ type: "error", message: checkpointNotFoundMessage(intent.name) });
17150
+ return;
17151
+ }
17152
+ ctx.send({ type: "info", message: checkpointDeletedMessage(intent.name) });
17070
17153
  }
17071
17154
  async function handleBranch(args, ctx) {
17072
17155
  const session = ctx.sessions.current;
@@ -17583,7 +17666,7 @@ async function handleTest(args, ctx) {
17583
17666
  const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
17584
17667
  testArgs = isCommand ? { command: argStr } : { filter: argStr };
17585
17668
  }
17586
- const runTests = ctx.runTests ?? (await import("./run-tests-HMHHIG7Y.js")).executeTests;
17669
+ const runTests = ctx.runTests ?? (await import("./run-tests-4ESYEROQ.js")).executeTests;
17587
17670
  const report = await runTests(testArgs);
17588
17671
  ctx.send({ type: "info", message: report });
17589
17672
  } catch (err) {
@@ -17919,7 +18002,7 @@ async function handleMemory(args, ctx) {
17919
18002
  ctx.handleMemoryManage(sub, args[1], sub === "expire" ? args[2] : void 0);
17920
18003
  } else if (sub === "export") {
17921
18004
  if (args[1] === "md") {
17922
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-QZN4Q3W4.js");
18005
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-WAKFKH2I.js");
17923
18006
  ctx.send({
17924
18007
  type: "export_data",
17925
18008
  format: "md",
@@ -18358,7 +18441,7 @@ async function handleHelp(_args, ctx) {
18358
18441
  " /about \u2014 Version & author info",
18359
18442
  " /provider <id> \u2014 Switch AI provider",
18360
18443
  " /model <id> \u2014 Switch model",
18361
- " /clear \u2014 Clear conversation & start new session",
18444
+ " /clear \u2014 Start a new session (previous conversation is kept)",
18362
18445
  " /compact [hint] \u2014 Compress conversation history",
18363
18446
  " /think [on|off] \u2014 Toggle extended thinking mode",
18364
18447
  " /plan [execute|exit|status] \u2014 Read-only planning mode (bare /plan enters it)",
@@ -19764,43 +19847,13 @@ ${summaryContent}`,
19764
19847
  this.send({ type: "info", message: "No messages to export." });
19765
19848
  return;
19766
19849
  }
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
- }
19850
+ const exported = buildSessionExport(session, format);
19851
+ this.send({
19852
+ type: "export_data",
19853
+ format,
19854
+ filename: exported.filename,
19855
+ content: exported.content
19856
+ });
19804
19857
  }
19805
19858
  memoryShow(args = []) {
19806
19859
  const configDir = this.config.getConfigDir();
@@ -143,7 +143,7 @@ ${content}`);
143
143
  const state = await runDiscussion(config, providers, options.topic);
144
144
  if (options.save !== false && state.messages.length > 0) {
145
145
  try {
146
- const { persistDiscussion } = await import("./persist-PQM4BRI4.js");
146
+ const { persistDiscussion } = await import("./persist-TBQILDSE.js");
147
147
  const { path } = await persistDiscussion(state, configManager, defaultProvider, defaultModel);
148
148
  console.log(chalk.dim(`
149
149
  \u{1F4BE} Saved to history \u2014 open it in the Web UI and hit \u{1F3AC} to replay.
@@ -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-H3AEIHR3.js");
162
162
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
163
163
  let interrupted = false;
164
164
  const onSigint = () => {