jinzd-ai-cli 0.4.267 → 0.4.268

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-GY5MAN5F.js → batch-2N2YMRX2.js} +2 -2
  2. package/dist/{chunk-WPN7LDLM.js → chunk-2FQGMR34.js} +1 -1
  3. package/dist/{chunk-5AEOIETL.js → chunk-74BK22BM.js} +4 -4
  4. package/dist/{chunk-6C6FLDGH.js → chunk-7US7K3CD.js} +1 -1
  5. package/dist/{chunk-7HECI3U5.js → chunk-EPVJS4F6.js} +3 -1
  6. package/dist/{chunk-FI6IWUXW.js → chunk-RRQZRSXW.js} +1 -1
  7. package/dist/{chunk-THHPKZJ3.js → chunk-UT2WAJJG.js} +1 -1
  8. package/dist/{chunk-EWRZMIQE.js → chunk-VGVKJTHF.js} +1 -1
  9. package/dist/{chunk-JH343BDI.js → chunk-VNCBY4KY.js} +153 -2
  10. package/dist/{chunk-RVNL7MQG.js → chunk-WNG3YVZX.js} +1 -1
  11. package/dist/{chunk-XLLUQEGO.js → chunk-WWLXW4SY.js} +1 -1
  12. package/dist/{chunk-ARYCWJN6.js → chunk-XDITAGE5.js} +1 -1
  13. package/dist/{chunk-QN7WD2SM.js → chunk-YLSM7RF6.js} +3 -3
  14. package/dist/{chunk-5CU72V6P.js → chunk-Z7CZ72RP.js} +3 -3
  15. package/dist/{ci-MUEQSNKU.js → ci-3RWVJSZ3.js} +4 -4
  16. package/dist/{ci-format-2ZGGSOFK.js → ci-format-M6HVCXCG.js} +2 -2
  17. package/dist/{constants-SZTJESDF.js → constants-G6VN7SJL.js} +1 -1
  18. package/dist/{doctor-cli-Z272364P.js → doctor-cli-Y3SVVJBO.js} +4 -4
  19. package/dist/electron-server.js +216 -16
  20. package/dist/{hub-MRLGKMRI.js → hub-5T5HKOAR.js} +1 -1
  21. package/dist/index.js +72 -111
  22. package/dist/{persistent-memory-HZASMDJQ.js → persistent-memory-XVSSR277.js} +2 -2
  23. package/dist/{persistent-memory-3FTOC7QT.js → persistent-memory-YBWIZWQP.js} +2 -2
  24. package/dist/{pr-VLLIALRK.js → pr-NF5IWLH3.js} +4 -4
  25. package/dist/{run-tests-NTDZ6DDU.js → run-tests-33X3D7PV.js} +2 -2
  26. package/dist/{run-tests-6MWE6D5S.js → run-tests-Y44SCLIO.js} +2 -2
  27. package/dist/{server-SP3AEHRQ.js → server-3LERX42X.js} +5 -5
  28. package/dist/{server-IALCWKSU.js → server-NJ3ZNPQW.js} +79 -21
  29. package/dist/{task-orchestrator-Q6WFFI4J.js → task-orchestrator-JN2WFZSF.js} +5 -5
  30. package/dist/{usage-DJDLHICZ.js → usage-IFTNXTWC.js} +2 -2
  31. package/package.json +1 -1
@@ -34,14 +34,14 @@ import {
34
34
  touchMemoryReferences,
35
35
  updateMemoryApproval,
36
36
  updateMemoryEntry
37
- } from "./chunk-FI6IWUXW.js";
37
+ } from "./chunk-RRQZRSXW.js";
38
38
  import {
39
39
  redactJson,
40
40
  scanString
41
41
  } from "./chunk-YVTASHS5.js";
42
42
  import {
43
43
  runTestsTool
44
- } from "./chunk-ARYCWJN6.js";
44
+ } from "./chunk-XDITAGE5.js";
45
45
  import {
46
46
  AGENTIC_BEHAVIOR_GUIDELINE,
47
47
  APP_NAME,
@@ -51,6 +51,7 @@ import {
51
51
  CONFIG_FILE_NAME,
52
52
  CONTEXT_FILE_CANDIDATES,
53
53
  CONTEXT_FILE_MAX_BYTES,
54
+ CONTEXT_PRESSURE_THRESHOLD,
54
55
  CUSTOM_COMMANDS_DIR_NAME,
55
56
  DEFAULT_MAX_TOKENS,
56
57
  DEFAULT_MAX_TOOL_OUTPUT_CHARS_CAP,
@@ -73,7 +74,7 @@ import {
73
74
  SUBAGENT_MAX_ROUNDS_LIMIT,
74
75
  VERSION,
75
76
  buildUserIdentityPrompt
76
- } from "./chunk-7HECI3U5.js";
77
+ } from "./chunk-EPVJS4F6.js";
77
78
  import {
78
79
  hasSemanticIndex,
79
80
  semanticSearch
@@ -14161,6 +14162,38 @@ function autoTrimSessionIfNeeded(session, sizeLimit = SESSION_SIZE_LIMIT) {
14161
14162
  return committedSize < originalSize;
14162
14163
  }
14163
14164
 
14165
+ // src/core/context-pressure.ts
14166
+ function estimateConversationTokens(input) {
14167
+ let total = 0;
14168
+ if (input.systemPrompt) total += estimateTokens(input.systemPrompt);
14169
+ for (const msg of input.messages) {
14170
+ if (typeof msg.content === "string") {
14171
+ total += estimateTokens(msg.content);
14172
+ } else if (Array.isArray(msg.content)) {
14173
+ for (const part of msg.content) {
14174
+ if (part.type === "text" && part.text) total += estimateTokens(part.text);
14175
+ }
14176
+ }
14177
+ if (msg.toolCalls) {
14178
+ for (const tc of msg.toolCalls) {
14179
+ total += estimateTokens(JSON.stringify(tc.arguments));
14180
+ }
14181
+ }
14182
+ }
14183
+ return total;
14184
+ }
14185
+ function evaluateContextPressure(input) {
14186
+ if (input.contextWindow <= 0) return { shouldCompact: false, ratio: null, percent: null };
14187
+ const ratio = input.estimatedTokens / input.contextWindow;
14188
+ const threshold = input.threshold ?? CONTEXT_PRESSURE_THRESHOLD;
14189
+ return {
14190
+ shouldCompact: input.autoCompactEnabled && ratio >= threshold,
14191
+ ratio,
14192
+ percent: Math.round(ratio * 100)
14193
+ };
14194
+ }
14195
+ var AUTO_COMPACT_INSTRUCTION = "Preserve key context, compress old content, ensure seamless continuation";
14196
+
14164
14197
  // src/core/context-files.ts
14165
14198
  import { existsSync as existsSync25, readFileSync as readFileSync20 } from "fs";
14166
14199
  import { join as join19, relative as relative4, resolve as resolve8 } from "path";
@@ -15287,6 +15320,12 @@ async function handlePlan(args, ctx) {
15287
15320
  } else if (sub === "execute") {
15288
15321
  ctx.planMode = false;
15289
15322
  ctx.send({ type: "info", message: "Plan mode OFF. Executing with all tools enabled." });
15323
+ } else if (sub === "status" || sub === "show") {
15324
+ ctx.send({ type: "info", message: `Plan mode: ${ctx.planMode ? "ON (read-only tools only)" : "OFF"}` });
15325
+ return;
15326
+ } else if (sub !== void 0) {
15327
+ ctx.send({ type: "error", message: `Unknown /plan option "${sub}" \u2014 expected execute | exit | status` });
15328
+ return;
15290
15329
  } else {
15291
15330
  ctx.planMode = !ctx.planMode;
15292
15331
  ctx.send({ type: "info", message: `Plan mode: ${ctx.planMode ? "ON (read-only tools only)" : "OFF"}` });
@@ -15824,7 +15863,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
15824
15863
  Cost: ${formatCost(cost)}` : "";
15825
15864
  let memoryLine = "";
15826
15865
  try {
15827
- const { countPendingMemories } = await import("./persistent-memory-3FTOC7QT.js");
15866
+ const { countPendingMemories } = await import("./persistent-memory-YBWIZWQP.js");
15828
15867
  const pending = countPendingMemories(ctx.config.getConfigDir());
15829
15868
  if (pending > 0) memoryLine = `
15830
15869
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -16637,7 +16676,7 @@ async function handleTest(args, ctx) {
16637
16676
  const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
16638
16677
  testArgs = isCommand ? { command: argStr } : { filter: argStr };
16639
16678
  }
16640
- const runTests = ctx.runTests ?? (await import("./run-tests-6MWE6D5S.js")).executeTests;
16679
+ const runTests = ctx.runTests ?? (await import("./run-tests-Y44SCLIO.js")).executeTests;
16641
16680
  const report = await runTests(testArgs);
16642
16681
  ctx.send({ type: "info", message: report });
16643
16682
  } catch (err) {
@@ -16895,7 +16934,7 @@ async function handleMemory(args, ctx) {
16895
16934
  ctx.handleMemoryManage(sub, args[1], sub === "expire" ? args[2] : void 0);
16896
16935
  } else if (sub === "export") {
16897
16936
  if (args[1] === "md") {
16898
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-3FTOC7QT.js");
16937
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-YBWIZWQP.js");
16899
16938
  ctx.send({
16900
16939
  type: "export_data",
16901
16940
  format: "md",
@@ -16946,6 +16985,119 @@ Use /add-dir remove to clear.` : "No directories added.\nUsage: /add-dir <path>
16946
16985
  It will be included in AI context for subsequent messages.` });
16947
16986
  }
16948
16987
 
16988
+ // src/core/profile-command.ts
16989
+ var PROFILE_FIELDS = ["name", "nickname", "role", "bio", "interests", "locale", "extra"];
16990
+ function stripSurroundingQuotes(value) {
16991
+ const pairs = [['"', '"'], ["'", "'"], ["\u201C", "\u201D"], ["\u2018", "\u2019"], ["\u300C", "\u300D"]];
16992
+ for (const [open, close] of pairs) {
16993
+ if (value.length >= 2 && value.startsWith(open) && value.endsWith(close)) {
16994
+ return value.slice(open.length, value.length - close.length).trim();
16995
+ }
16996
+ }
16997
+ return value;
16998
+ }
16999
+ function showRows(profile) {
17000
+ const rows = [];
17001
+ if (profile.name) rows.push(["Name", profile.name]);
17002
+ if (profile.nickname) rows.push(["Nickname", profile.nickname]);
17003
+ if (profile.role) rows.push(["Role", profile.role]);
17004
+ if (profile.bio) rows.push(["Bio", profile.bio]);
17005
+ if (profile.interests?.length) rows.push(["Interests", profile.interests.join(", ")]);
17006
+ if (profile.locale) rows.push(["Locale", profile.locale]);
17007
+ if (profile.extra) {
17008
+ rows.push(["Extra", profile.extra.length > 80 ? `${profile.extra.slice(0, 80)}\u2026` : profile.extra]);
17009
+ }
17010
+ return rows;
17011
+ }
17012
+ function applyProfileCommand(args, profile) {
17013
+ const sub = (args[0] ?? "show").toLowerCase();
17014
+ if (sub === "show" || sub === "view") {
17015
+ const rows = showRows(profile);
17016
+ if (rows.length === 0) {
17017
+ return {
17018
+ summary: "No profile configured yet.",
17019
+ rows: [],
17020
+ details: ["Set one with /profile set <field> <value> \u2014 it is injected into every conversation."],
17021
+ changed: false,
17022
+ isError: false
17023
+ };
17024
+ }
17025
+ return {
17026
+ summary: "\u{1F464} Your Profile",
17027
+ rows,
17028
+ details: ["This identity is injected into every AI conversation."],
17029
+ changed: false,
17030
+ isError: false
17031
+ };
17032
+ }
17033
+ if (sub === "clear") {
17034
+ return {
17035
+ profile: {},
17036
+ summary: "Profile cleared. The AI will no longer know who you are.",
17037
+ rows: [],
17038
+ details: [],
17039
+ changed: true,
17040
+ isError: false
17041
+ };
17042
+ }
17043
+ if (sub === "set") {
17044
+ const field = args[1];
17045
+ const value = args.slice(2).join(" ").trim();
17046
+ if (!field || !PROFILE_FIELDS.includes(field)) {
17047
+ return {
17048
+ summary: "Usage: /profile set <field> <value>",
17049
+ rows: [],
17050
+ details: [`Fields: ${PROFILE_FIELDS.join(", ")}`],
17051
+ changed: false,
17052
+ isError: true
17053
+ };
17054
+ }
17055
+ if (!value) {
17056
+ return {
17057
+ summary: `Usage: /profile set ${field} <value>`,
17058
+ rows: [],
17059
+ details: [],
17060
+ changed: false,
17061
+ isError: true
17062
+ };
17063
+ }
17064
+ const updated = { ...profile };
17065
+ if (field === "interests") {
17066
+ updated.interests = value.split(",").map((s) => stripSurroundingQuotes(s.trim())).filter(Boolean);
17067
+ } else {
17068
+ updated[field] = stripSurroundingQuotes(value);
17069
+ }
17070
+ const shown = field === "interests" ? (updated.interests ?? []).join(", ") : stripSurroundingQuotes(value);
17071
+ return {
17072
+ profile: updated,
17073
+ summary: `Profile updated: ${field} = ${shown}`,
17074
+ rows: [],
17075
+ details: [],
17076
+ changed: true,
17077
+ isError: false
17078
+ };
17079
+ }
17080
+ if (sub === "edit") {
17081
+ return {
17082
+ summary: "Interactive editing lives in the setup wizard.",
17083
+ rows: [],
17084
+ details: [
17085
+ "Run `aicli config` in a terminal, or use /profile set <field> <value> here.",
17086
+ `Fields: ${PROFILE_FIELDS.join(", ")}`
17087
+ ],
17088
+ changed: false,
17089
+ isError: false
17090
+ };
17091
+ }
17092
+ return {
17093
+ summary: `Unknown /profile option "${args[0]}" \u2014 expected show | set | clear | edit`,
17094
+ rows: [],
17095
+ details: [],
17096
+ changed: false,
17097
+ isError: true
17098
+ };
17099
+ }
17100
+
16949
17101
  // src/web/commands/security-commands.ts
16950
17102
  async function handleConfig(args, ctx) {
16951
17103
  const sub = args[0];
@@ -17007,6 +17159,18 @@ async function handleBug(_args, ctx) {
17007
17159
  ];
17008
17160
  ctx.send({ type: "info", message: lines.join("\n") });
17009
17161
  }
17162
+ async function handleProfile(args, ctx) {
17163
+ const outcome = applyProfileCommand(args, ctx.config.get("userProfile") ?? {});
17164
+ if (outcome.profile) {
17165
+ ctx.config.set("userProfile", outcome.profile);
17166
+ ctx.config.save();
17167
+ }
17168
+ const lines = [outcome.summary];
17169
+ for (const [label, value] of outcome.rows) lines.push(` ${label}: ${value}`);
17170
+ for (const line of outcome.details) lines.push(line);
17171
+ ctx.send({ type: outcome.isError ? "error" : "info", message: lines.join("\n") });
17172
+ if (outcome.changed) ctx.sendStatus();
17173
+ }
17010
17174
 
17011
17175
  // src/web/commands/agent-commands.ts
17012
17176
  async function handleAuto(args, ctx) {
@@ -17050,6 +17214,17 @@ async function handlePermissions(args, ctx) {
17050
17214
  }
17051
17215
  async function handleYolo(args, ctx) {
17052
17216
  const sub = args[0]?.toLowerCase();
17217
+ if (sub === "status") {
17218
+ ctx.send({
17219
+ type: "info",
17220
+ message: `YOLO mode: ${ctx.toolExecutor.sessionAutoApprove ? "ON (write tools auto-approved)" : "OFF"}`
17221
+ });
17222
+ return;
17223
+ }
17224
+ if (sub !== void 0 && sub !== "on" && sub !== "off") {
17225
+ ctx.send({ type: "error", message: `Unknown /yolo option "${sub}" \u2014 expected on | off | status` });
17226
+ return;
17227
+ }
17053
17228
  if (sub === "off") {
17054
17229
  ctx.toolExecutor.sessionAutoApprove = false;
17055
17230
  ctx.send({ type: "info", message: "\u{1F512} Auto-approve disabled \u2014 confirmations restored for this session." });
@@ -17261,14 +17436,17 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
17261
17436
  }
17262
17437
 
17263
17438
  // src/web/session-handler.ts
17264
- var CLI_ONLY_WEB_COMMANDS = /* @__PURE__ */ new Set([
17265
- "copy",
17266
- "paste",
17267
- "exit",
17268
- "quit",
17269
- "snapshot",
17270
- "hooks",
17271
- "hook"
17439
+ var CLI_ONLY_WEB_COMMANDS = /* @__PURE__ */ new Map([
17440
+ ["copy", "It copies to the terminal clipboard; use your browser/OS copy instead."],
17441
+ ["paste", "It reads the terminal clipboard; paste directly into the composer instead."],
17442
+ ["exit", "Close the browser tab to end this Web session."],
17443
+ ["quit", "Close the browser tab to end this Web session."],
17444
+ ["snapshot", "Dev-state snapshots are written when the terminal REPL exits."],
17445
+ ["hooks", "Hook trust is granted per machine from the terminal."],
17446
+ ["hook", "Hook trust is granted per machine from the terminal."],
17447
+ // 以下两条并非「终端才有意义」,而是 Web 侧尚未实现——如实说明,别假装是设计。
17448
+ ["route", "Smart model routing is not applied to Web sessions yet (config.routing is REPL-only)."],
17449
+ ["security", "Redaction status and toggles are terminal-only for now; /status shows the current profile."]
17272
17450
  ]);
17273
17451
  var webCommandHandlers = {
17274
17452
  provider: handleProvider,
@@ -17304,6 +17482,7 @@ var webCommandHandlers = {
17304
17482
  config: handleConfig,
17305
17483
  doctor: handleDoctor,
17306
17484
  bug: handleBug,
17485
+ profile: handleProfile,
17307
17486
  auto: handleAuto,
17308
17487
  permissions: handlePermissions,
17309
17488
  yolo: handleYolo,
@@ -17811,6 +17990,7 @@ var SessionHandler = class {
17811
17990
  } else {
17812
17991
  await this.handleChatSimple(provider, session.messages);
17813
17992
  }
17993
+ await this.checkContextPressure();
17814
17994
  } catch (err) {
17815
17995
  const parts = [];
17816
17996
  let current = err;
@@ -18329,10 +18509,11 @@ ${summaryContent}`,
18329
18509
  }
18330
18510
  // ── Commands ─────────────────────────────────────────────────────
18331
18511
  async handleCommand(name, args) {
18332
- if (CLI_ONLY_WEB_COMMANDS.has(name)) {
18512
+ const cliOnlyReason = CLI_ONLY_WEB_COMMANDS.get(name);
18513
+ if (cliOnlyReason) {
18333
18514
  this.send({
18334
18515
  type: "error",
18335
- message: `/${name} is only available in the terminal REPL. Run \`aicli\` in a terminal and use /${name} there.`
18516
+ message: `/${name} is not available in the Web UI. ${cliOnlyReason}`
18336
18517
  });
18337
18518
  return;
18338
18519
  }
@@ -18343,6 +18524,25 @@ ${summaryContent}`,
18343
18524
  this.send({ type: "error", message: `Unknown command: /${name}. Type /help for available commands.` });
18344
18525
  }
18345
18526
  }
18527
+ /**
18528
+ * 到达上下文压力阈值时自动压缩(与 REPL 同一判据,见 core/context-pressure.ts)。
18529
+ * 上下文窗口未知时不动——不基于猜测改用户的对话历史。
18530
+ */
18531
+ async checkContextPressure() {
18532
+ const contextWindow = this.getContextWindowSize();
18533
+ const session = this.sessions.current;
18534
+ const pressure = evaluateContextPressure({
18535
+ autoCompactEnabled: this.config.get("autoCompact") === true,
18536
+ estimatedTokens: contextWindow > 0 && session ? estimateConversationTokens({ systemPrompt: this.activeSystemPrompt, messages: session.messages }) : 0,
18537
+ contextWindow
18538
+ });
18539
+ if (!pressure.shouldCompact) return;
18540
+ this.send({
18541
+ type: "info",
18542
+ message: `\u26A0 Context pressure: ~${pressure.percent}% of the ${contextWindow.toLocaleString()}-token window used. Auto-compacting\u2026`
18543
+ });
18544
+ await this.compactSession(AUTO_COMPACT_INSTRUCTION);
18545
+ }
18346
18546
  async compactSession(instruction) {
18347
18547
  const session = this.sessions.current;
18348
18548
  if (!session || session.messages.length < 6) {
@@ -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-Q6WFFI4J.js");
161
+ const { TaskOrchestrator } = await import("./task-orchestrator-JN2WFZSF.js");
162
162
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
163
163
  let interrupted = false;
164
164
  const onSigint = () => {