jinzd-ai-cli 0.1.93 → 0.1.94

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.
@@ -16,7 +16,7 @@ import {
16
16
  SUBAGENT_MAX_ROUNDS_LIMIT,
17
17
  VERSION,
18
18
  runTestsTool
19
- } from "./chunk-BZVXXYAB.js";
19
+ } from "./chunk-PYJJOWBD.js";
20
20
 
21
21
  // src/config/config-manager.ts
22
22
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
@@ -8,7 +8,7 @@ import { platform } from "os";
8
8
  import chalk from "chalk";
9
9
 
10
10
  // src/core/constants.ts
11
- var VERSION = "0.1.93";
11
+ var VERSION = "0.1.94";
12
12
  var APP_NAME = "ai-cli";
13
13
  var CONFIG_DIR_NAME = ".aicli";
14
14
  var CONFIG_FILE_NAME = "config.json";
package/dist/index.js CHANGED
@@ -35,7 +35,7 @@ import {
35
35
  theme,
36
36
  truncateOutput,
37
37
  undoStack
38
- } from "./chunk-HLMYGNCU.js";
38
+ } from "./chunk-A56ZRY2B.js";
39
39
  import {
40
40
  AGENTIC_BEHAVIOR_GUIDELINE,
41
41
  AUTHOR,
@@ -55,7 +55,7 @@ import {
55
55
  REPO_URL,
56
56
  SKILLS_DIR_NAME,
57
57
  VERSION
58
- } from "./chunk-BZVXXYAB.js";
58
+ } from "./chunk-PYJJOWBD.js";
59
59
 
60
60
  // src/index.ts
61
61
  import { program } from "commander";
@@ -1904,7 +1904,7 @@ ${hint}` : "")
1904
1904
  description: "Run project tests and show structured report",
1905
1905
  usage: "/test [command|filter]",
1906
1906
  async execute(args, _ctx) {
1907
- const { executeTests } = await import("./run-tests-X5ZA6FTL.js");
1907
+ const { executeTests } = await import("./run-tests-56DD3KFS.js");
1908
1908
  const argStr = args.join(" ").trim();
1909
1909
  let testArgs = {};
1910
1910
  if (argStr) {
@@ -5292,7 +5292,7 @@ program.command("web").description("Start Web UI server with browser-based chat
5292
5292
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
5293
5293
  process.exit(1);
5294
5294
  }
5295
- const { startWebServer } = await import("./server-G4DGAXKU.js");
5295
+ const { startWebServer } = await import("./server-4YKTZGGC.js");
5296
5296
  await startWebServer({ port, host: options.host });
5297
5297
  });
5298
5298
  program.command("sessions").description("List recent conversation sessions").action(async () => {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  executeTests,
4
4
  runTestsTool
5
- } from "./chunk-BZVXXYAB.js";
5
+ } from "./chunk-PYJJOWBD.js";
6
6
  export {
7
7
  executeTests,
8
8
  runTestsTool
@@ -23,7 +23,7 @@ import {
23
23
  setupProxy,
24
24
  spawnAgentContext,
25
25
  truncateOutput
26
- } from "./chunk-HLMYGNCU.js";
26
+ } from "./chunk-A56ZRY2B.js";
27
27
  import {
28
28
  AGENTIC_BEHAVIOR_GUIDELINE,
29
29
  CONTEXT_FILE_CANDIDATES,
@@ -35,7 +35,7 @@ import {
35
35
  PLAN_MODE_SYSTEM_ADDON,
36
36
  SKILLS_DIR_NAME,
37
37
  VERSION
38
- } from "./chunk-BZVXXYAB.js";
38
+ } from "./chunk-PYJJOWBD.js";
39
39
 
40
40
  // src/web/server.ts
41
41
  import express from "express";
@@ -524,6 +524,10 @@ var SessionHandler = class {
524
524
  if (this.abortController) this.abortController.abort();
525
525
  for (const resolve3 of this.pendingAskUser.values()) resolve3(null);
526
526
  this.pendingAskUser.clear();
527
+ this.saveIfNeeded();
528
+ }
529
+ /** Save session only if it exists and has messages (never persist empty "Untitled" sessions). */
530
+ saveIfNeeded() {
527
531
  if (this.sessions.current && this.sessions.current.messages.length > 0) {
528
532
  this.sessions.save();
529
533
  }
@@ -580,7 +584,9 @@ var SessionHandler = class {
580
584
  this.send({ type: "error", message });
581
585
  } finally {
582
586
  this.processing = false;
587
+ this.saveIfNeeded();
583
588
  this.sendStatus();
589
+ this.sendSessionList();
584
590
  }
585
591
  }
586
592
  async handleChatSimple(provider, messages) {
@@ -873,10 +879,12 @@ ${summaryResult.content}`,
873
879
  break;
874
880
  }
875
881
  case "clear":
882
+ this.saveIfNeeded();
876
883
  this.sessions.createSession(this.currentProvider, this.currentModel);
877
884
  this.sessionTokenUsage = { inputTokens: 0, outputTokens: 0 };
878
885
  this.send({ type: "info", message: "Conversation cleared." });
879
886
  this.sendStatus();
887
+ this.sendSessionList();
880
888
  break;
881
889
  case "compact":
882
890
  await this.compactSession(args.join(" ") || void 0);
@@ -919,7 +927,7 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
919
927
  case "session": {
920
928
  const sub = args[0];
921
929
  if (sub === "new") {
922
- this.sessions.save();
930
+ this.saveIfNeeded();
923
931
  this.sessions.createSession(this.currentProvider, this.currentModel);
924
932
  this.sessionTokenUsage = { inputTokens: 0, outputTokens: 0 };
925
933
  this.send({ type: "info", message: "New session created." });
@@ -927,7 +935,7 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
927
935
  this.sendSessionList();
928
936
  } else if (sub === "load" && args[1]) {
929
937
  const targetId = args[1];
930
- this.sessions.save();
938
+ this.saveIfNeeded();
931
939
  const list = this.sessions.listSessions();
932
940
  const found = list.find((s) => s.id.startsWith(targetId));
933
941
  if (found) {
@@ -997,6 +1005,9 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
997
1005
  " /cost \u2014 Show cumulative token usage",
998
1006
  " /tools \u2014 Show tools, MCP servers & skills in sidebar",
999
1007
  " /export [md|json] \u2014 Export conversation as Markdown or JSON",
1008
+ " /skill \u2014 List available skills",
1009
+ " /skill <name> \u2014 Activate a skill",
1010
+ " /skill off \u2014 Deactivate current skill",
1000
1011
  " /memory \u2014 Show persistent memory contents",
1001
1012
  " /memory add <text> \u2014 Add entry to persistent memory",
1002
1013
  " /memory clear \u2014 Clear persistent memory",
@@ -1045,6 +1056,49 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
1045
1056
  }
1046
1057
  break;
1047
1058
  }
1059
+ case "skill": {
1060
+ const sub = args[0];
1061
+ if (!this.skillManager) {
1062
+ this.send({ type: "error", message: "Skill system not available." });
1063
+ break;
1064
+ }
1065
+ if (!sub || sub === "list") {
1066
+ const skills = this.skillManager.listSkills();
1067
+ const active = this.skillManager.getActive();
1068
+ if (skills.length === 0) {
1069
+ this.send({ type: "info", message: "No skills available. Add .md files to ~/.aicli/skills/" });
1070
+ } else {
1071
+ const lines = skills.map((s) => {
1072
+ const isActive = active?.meta.name === s.meta.name;
1073
+ const marker = isActive ? " \u2705 (active)" : "";
1074
+ return ` ${s.meta.name}${marker} \u2014 ${s.meta.description || "(no description)"}`;
1075
+ });
1076
+ this.send({ type: "info", message: `\u{1F4DA} Skills:
1077
+ ${lines.join("\n")}` });
1078
+ }
1079
+ } else if (sub === "off") {
1080
+ this.skillManager.deactivate();
1081
+ this.send({ type: "info", message: "\u{1F50C} Skill deactivated." });
1082
+ this.sendToolsList();
1083
+ this.sendStatus();
1084
+ } else if (sub === "reload") {
1085
+ this.skillManager.loadSkills();
1086
+ this.send({ type: "info", message: `\u{1F504} Reloaded ${this.skillManager.listSkills().length} skill(s).` });
1087
+ this.sendToolsList();
1088
+ } else {
1089
+ const activated = this.skillManager.activate(sub);
1090
+ if (activated) {
1091
+ this.send({ type: "info", message: `\u2705 Skill activated: ${activated.meta.name}
1092
+ ${activated.meta.description || ""}` });
1093
+ this.sendToolsList();
1094
+ this.sendStatus();
1095
+ } else {
1096
+ const available = this.skillManager.listSkills().map((s) => s.meta.name).join(", ");
1097
+ this.send({ type: "error", message: `Skill "${sub}" not found. Available: ${available}` });
1098
+ }
1099
+ }
1100
+ break;
1101
+ }
1048
1102
  default:
1049
1103
  this.send({ type: "error", message: `Unknown command: /${name}. Type /help for available commands.` });
1050
1104
  }
@@ -49,7 +49,7 @@
49
49
  <div class="flex flex-1 overflow-hidden">
50
50
 
51
51
  <!-- Sidebar -->
52
- <aside id="sidebar" class="sidebar bg-base-200 border-r border-base-content/10 flex flex-col w-64 flex-shrink-0 overflow-hidden transition-all duration-200">
52
+ <aside id="sidebar" class="sidebar bg-base-200 border-r border-base-content/10 flex flex-col w-72 flex-shrink-0 overflow-hidden transition-all duration-200">
53
53
  <!-- Sidebar tabs -->
54
54
  <div class="flex border-b border-base-content/10 flex-shrink-0">
55
55
  <button class="sidebar-tab active flex-1 text-xs font-semibold py-2 px-1 text-center" data-tab="sessions">📋 Sessions</button>
@@ -59,9 +59,9 @@
59
59
  <!-- Sessions tab -->
60
60
  <div id="tab-sessions" class="sidebar-tab-content flex flex-col flex-1 overflow-hidden">
61
61
  <div class="p-2 border-b border-base-content/10 flex items-center justify-between gap-1">
62
- <input id="session-search" type="text" class="input input-xs input-bordered flex-1" placeholder="Search sessions...">
62
+ <input id="session-search" type="text" class="input input-xs input-bordered flex-1 min-w-0" placeholder="Search...">
63
63
  <button id="btn-batch-select" class="btn btn-xs btn-ghost flex-shrink-0" title="Select multiple" onclick="toggleBatchSelect()">☑</button>
64
- <button id="btn-new-session" class="btn btn-xs btn-primary btn-outline flex-shrink-0" title="New session">+ New</button>
64
+ <button id="btn-new-session" class="btn btn-xs btn-primary btn-outline flex-shrink-0 whitespace-nowrap" title="New session">+ New</button>
65
65
  </div>
66
66
  <!-- Batch action bar (hidden by default) -->
67
67
  <div id="batch-bar" class="hidden px-2 py-1 border-b border-base-content/10 flex items-center gap-1 bg-base-300 text-xs">
@@ -562,7 +562,7 @@
562
562
  /* ── Responsive ─────────────────────────────────────── */
563
563
  @media (max-width: 768px) {
564
564
  .sidebar { width: 0; padding: 0; border: none; }
565
- .sidebar.sidebar-open { width: 16rem; position: absolute; z-index: 20; height: calc(100vh - 3.5rem); top: 3.5rem; }
565
+ .sidebar.sidebar-open { width: 18rem; position: absolute; z-index: 20; height: calc(100vh - 3.5rem); top: 3.5rem; }
566
566
  }
567
567
  @media (max-width: 640px) {
568
568
  .navbar-start .select { width: 6rem; font-size: 0.75rem; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jinzd-ai-cli",
3
- "version": "0.1.93",
3
+ "version": "0.1.94",
4
4
  "description": "Cross-platform REPL-style AI CLI with multi-provider support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",