jinzd-ai-cli 0.1.92 → 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.
- package/dist/{chunk-OZ2VVEBE.js → chunk-A56ZRY2B.js} +1 -1
- package/dist/{chunk-W7ZOYZFR.js → chunk-PYJJOWBD.js} +1 -1
- package/dist/index.js +4 -4
- package/dist/{run-tests-XWNY6FYC.js → run-tests-56DD3KFS.js} +1 -1
- package/dist/{server-Y67I66FG.js → server-4YKTZGGC.js} +85 -6
- package/dist/web/client/app.js +70 -13
- package/dist/web/client/index.html +13 -4
- package/dist/web/client/style.css +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
theme,
|
|
36
36
|
truncateOutput,
|
|
37
37
|
undoStack
|
|
38
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
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 () => {
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
setupProxy,
|
|
24
24
|
spawnAgentContext,
|
|
25
25
|
truncateOutput
|
|
26
|
-
} from "./chunk-
|
|
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-
|
|
38
|
+
} from "./chunk-PYJJOWBD.js";
|
|
39
39
|
|
|
40
40
|
// src/web/server.ts
|
|
41
41
|
import express from "express";
|
|
@@ -448,7 +448,6 @@ var SessionHandler = class {
|
|
|
448
448
|
this.currentModel = "";
|
|
449
449
|
}
|
|
450
450
|
}
|
|
451
|
-
this.sessions.createSession(this.currentProvider, this.currentModel);
|
|
452
451
|
this.activeSystemPrompt = this.loadContextFiles();
|
|
453
452
|
const hooks = this.config.get("hooks");
|
|
454
453
|
const permissionRules = this.config.get("permissionRules");
|
|
@@ -525,7 +524,19 @@ var SessionHandler = class {
|
|
|
525
524
|
if (this.abortController) this.abortController.abort();
|
|
526
525
|
for (const resolve3 of this.pendingAskUser.values()) resolve3(null);
|
|
527
526
|
this.pendingAskUser.clear();
|
|
528
|
-
this.
|
|
527
|
+
this.saveIfNeeded();
|
|
528
|
+
}
|
|
529
|
+
/** Save session only if it exists and has messages (never persist empty "Untitled" sessions). */
|
|
530
|
+
saveIfNeeded() {
|
|
531
|
+
if (this.sessions.current && this.sessions.current.messages.length > 0) {
|
|
532
|
+
this.sessions.save();
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
/** Lazily create a session if none exists yet (deferred from constructor). */
|
|
536
|
+
ensureSession() {
|
|
537
|
+
if (!this.sessions.current) {
|
|
538
|
+
this.sessions.createSession(this.currentProvider, this.currentModel);
|
|
539
|
+
}
|
|
529
540
|
}
|
|
530
541
|
// ── Chat handling ────────────────────────────────────────────────
|
|
531
542
|
async handleChat(content, images) {
|
|
@@ -535,6 +546,7 @@ var SessionHandler = class {
|
|
|
535
546
|
}
|
|
536
547
|
this.processing = true;
|
|
537
548
|
try {
|
|
549
|
+
this.ensureSession();
|
|
538
550
|
const session = this.sessions.current;
|
|
539
551
|
let msgContent;
|
|
540
552
|
if (images && images.length > 0) {
|
|
@@ -572,7 +584,9 @@ var SessionHandler = class {
|
|
|
572
584
|
this.send({ type: "error", message });
|
|
573
585
|
} finally {
|
|
574
586
|
this.processing = false;
|
|
587
|
+
this.saveIfNeeded();
|
|
575
588
|
this.sendStatus();
|
|
589
|
+
this.sendSessionList();
|
|
576
590
|
}
|
|
577
591
|
}
|
|
578
592
|
async handleChatSimple(provider, messages) {
|
|
@@ -865,10 +879,12 @@ ${summaryResult.content}`,
|
|
|
865
879
|
break;
|
|
866
880
|
}
|
|
867
881
|
case "clear":
|
|
882
|
+
this.saveIfNeeded();
|
|
868
883
|
this.sessions.createSession(this.currentProvider, this.currentModel);
|
|
869
884
|
this.sessionTokenUsage = { inputTokens: 0, outputTokens: 0 };
|
|
870
885
|
this.send({ type: "info", message: "Conversation cleared." });
|
|
871
886
|
this.sendStatus();
|
|
887
|
+
this.sendSessionList();
|
|
872
888
|
break;
|
|
873
889
|
case "compact":
|
|
874
890
|
await this.compactSession(args.join(" ") || void 0);
|
|
@@ -911,7 +927,7 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
|
|
|
911
927
|
case "session": {
|
|
912
928
|
const sub = args[0];
|
|
913
929
|
if (sub === "new") {
|
|
914
|
-
this.
|
|
930
|
+
this.saveIfNeeded();
|
|
915
931
|
this.sessions.createSession(this.currentProvider, this.currentModel);
|
|
916
932
|
this.sessionTokenUsage = { inputTokens: 0, outputTokens: 0 };
|
|
917
933
|
this.send({ type: "info", message: "New session created." });
|
|
@@ -919,7 +935,7 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
|
|
|
919
935
|
this.sendSessionList();
|
|
920
936
|
} else if (sub === "load" && args[1]) {
|
|
921
937
|
const targetId = args[1];
|
|
922
|
-
this.
|
|
938
|
+
this.saveIfNeeded();
|
|
923
939
|
const list = this.sessions.listSessions();
|
|
924
940
|
const found = list.find((s) => s.id.startsWith(targetId));
|
|
925
941
|
if (found) {
|
|
@@ -947,6 +963,23 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
|
|
|
947
963
|
} else {
|
|
948
964
|
this.send({ type: "error", message: `Session not found: ${targetId}` });
|
|
949
965
|
}
|
|
966
|
+
} else if (sub === "batch-delete") {
|
|
967
|
+
const ids = args.slice(1).filter(Boolean);
|
|
968
|
+
if (ids.length === 0) {
|
|
969
|
+
this.send({ type: "error", message: "No session IDs provided." });
|
|
970
|
+
break;
|
|
971
|
+
}
|
|
972
|
+
const list = this.sessions.listSessions();
|
|
973
|
+
let deleted = 0;
|
|
974
|
+
for (const targetId of ids) {
|
|
975
|
+
const found = list.find((s) => s.id.startsWith(targetId));
|
|
976
|
+
if (found) {
|
|
977
|
+
this.sessions.deleteSession(found.id);
|
|
978
|
+
deleted++;
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
this.send({ type: "info", message: `Deleted ${deleted} session(s).` });
|
|
982
|
+
this.sendSessionList();
|
|
950
983
|
} else {
|
|
951
984
|
this.send({ type: "info", message: "Usage: /session new | list | load <id> | delete <id>" });
|
|
952
985
|
}
|
|
@@ -972,6 +1005,9 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
|
|
|
972
1005
|
" /cost \u2014 Show cumulative token usage",
|
|
973
1006
|
" /tools \u2014 Show tools, MCP servers & skills in sidebar",
|
|
974
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",
|
|
975
1011
|
" /memory \u2014 Show persistent memory contents",
|
|
976
1012
|
" /memory add <text> \u2014 Add entry to persistent memory",
|
|
977
1013
|
" /memory clear \u2014 Clear persistent memory",
|
|
@@ -1020,6 +1056,49 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
|
|
|
1020
1056
|
}
|
|
1021
1057
|
break;
|
|
1022
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
|
+
}
|
|
1023
1102
|
default:
|
|
1024
1103
|
this.send({ type: "error", message: `Unknown command: /${name}. Type /help for available commands.` });
|
|
1025
1104
|
}
|
package/dist/web/client/app.js
CHANGED
|
@@ -741,6 +741,9 @@ function renderSessionList(sessions) {
|
|
|
741
741
|
renderFilteredSessions(sessionSearchInput?.value || '');
|
|
742
742
|
}
|
|
743
743
|
|
|
744
|
+
let batchSelectMode = false;
|
|
745
|
+
const batchSelectedIds = new Set();
|
|
746
|
+
|
|
744
747
|
function renderFilteredSessions(filter) {
|
|
745
748
|
const sessions = filter
|
|
746
749
|
? cachedSessions.filter(s => (s.title || '').toLowerCase().includes(filter.toLowerCase()))
|
|
@@ -753,37 +756,91 @@ function renderFilteredSessions(filter) {
|
|
|
753
756
|
const title = s.title || 'Untitled';
|
|
754
757
|
const date = new Date(s.updated);
|
|
755
758
|
const timeStr = date.toLocaleDateString() + ' ' + date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
|
759
|
+
const checked = batchSelectedIds.has(s.id) ? 'checked' : '';
|
|
760
|
+
const checkbox = batchSelectMode
|
|
761
|
+
? `<input type="checkbox" class="checkbox checkbox-xs checkbox-error session-batch-cb" data-sid="${s.id}" ${checked}>`
|
|
762
|
+
: '';
|
|
756
763
|
return `<div class="session-item ${s.isCurrent ? 'active' : ''}" data-session-id="${s.id}" title="${escapeHtml(title)}">
|
|
757
764
|
<div class="flex items-center gap-1">
|
|
765
|
+
${checkbox}
|
|
758
766
|
<div class="session-title flex-1">${escapeHtml(title)}</div>
|
|
759
|
-
|
|
767
|
+
${batchSelectMode ? '' : `<button class="session-delete-btn opacity-0 hover:opacity-100 text-error text-xs px-1 flex-shrink-0" data-delete-id="${s.id}" title="Delete session">×</button>`}
|
|
760
768
|
</div>
|
|
761
769
|
<div class="session-meta">${s.messageCount} msgs · ${timeStr}</div>
|
|
762
770
|
</div>`;
|
|
763
771
|
}).join('');
|
|
764
772
|
|
|
765
|
-
// Click to load session
|
|
773
|
+
// Click to load session (only in normal mode)
|
|
766
774
|
sessionListEl.querySelectorAll('.session-item').forEach(el => {
|
|
767
775
|
el.addEventListener('click', (e) => {
|
|
768
|
-
|
|
769
|
-
if (
|
|
776
|
+
if (e.target.closest('.session-delete-btn') || e.target.closest('.session-batch-cb')) return;
|
|
777
|
+
if (batchSelectMode) {
|
|
778
|
+
// In batch mode, clicking the row toggles the checkbox
|
|
779
|
+
const cb = el.querySelector('.session-batch-cb');
|
|
780
|
+
if (cb) { cb.checked = !cb.checked; cb.dispatchEvent(new Event('change')); }
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
770
783
|
const id = el.dataset.sessionId;
|
|
771
784
|
if (!id) return;
|
|
772
785
|
send({ type: 'command', name: 'session', args: ['load', id] });
|
|
773
786
|
});
|
|
774
787
|
});
|
|
775
788
|
|
|
776
|
-
//
|
|
777
|
-
sessionListEl.querySelectorAll('.session-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
if (confirm('Delete this session?')) {
|
|
783
|
-
send({ type: 'command', name: 'session', args: ['delete', id] });
|
|
784
|
-
}
|
|
789
|
+
// Checkbox change in batch mode
|
|
790
|
+
sessionListEl.querySelectorAll('.session-batch-cb').forEach(cb => {
|
|
791
|
+
cb.addEventListener('change', () => {
|
|
792
|
+
const sid = cb.dataset.sid;
|
|
793
|
+
if (cb.checked) batchSelectedIds.add(sid); else batchSelectedIds.delete(sid);
|
|
794
|
+
updateBatchBar();
|
|
785
795
|
});
|
|
786
796
|
});
|
|
797
|
+
|
|
798
|
+
// Click to delete session (normal mode only)
|
|
799
|
+
if (!batchSelectMode) {
|
|
800
|
+
sessionListEl.querySelectorAll('.session-delete-btn').forEach(btn => {
|
|
801
|
+
btn.addEventListener('click', (e) => {
|
|
802
|
+
e.stopPropagation();
|
|
803
|
+
const id = btn.dataset.deleteId;
|
|
804
|
+
if (!id) return;
|
|
805
|
+
if (confirm('Delete this session?')) {
|
|
806
|
+
send({ type: 'command', name: 'session', args: ['delete', id] });
|
|
807
|
+
}
|
|
808
|
+
});
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
function toggleBatchSelect() {
|
|
814
|
+
batchSelectMode = !batchSelectMode;
|
|
815
|
+
batchSelectedIds.clear();
|
|
816
|
+
updateBatchBar();
|
|
817
|
+
renderFilteredSessions(sessionSearchInput?.value || '');
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
function selectAllSessions() {
|
|
821
|
+
cachedSessions.forEach(s => batchSelectedIds.add(s.id));
|
|
822
|
+
renderFilteredSessions(sessionSearchInput?.value || '');
|
|
823
|
+
updateBatchBar();
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
function batchDeleteSelected() {
|
|
827
|
+
if (batchSelectedIds.size === 0) return;
|
|
828
|
+
if (!confirm(`Delete ${batchSelectedIds.size} session(s)?`)) return;
|
|
829
|
+
send({ type: 'command', name: 'session', args: ['batch-delete', ...batchSelectedIds] });
|
|
830
|
+
batchSelectMode = false;
|
|
831
|
+
batchSelectedIds.clear();
|
|
832
|
+
updateBatchBar();
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
function updateBatchBar() {
|
|
836
|
+
const bar = document.getElementById('batch-bar');
|
|
837
|
+
if (!bar) return;
|
|
838
|
+
if (batchSelectMode) {
|
|
839
|
+
bar.classList.remove('hidden');
|
|
840
|
+
bar.querySelector('.batch-count').textContent = `${batchSelectedIds.size} selected`;
|
|
841
|
+
} else {
|
|
842
|
+
bar.classList.add('hidden');
|
|
843
|
+
}
|
|
787
844
|
}
|
|
788
845
|
|
|
789
846
|
function renderSessionMessages(messages) {
|
|
@@ -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-
|
|
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>
|
|
@@ -58,9 +58,18 @@
|
|
|
58
58
|
</div>
|
|
59
59
|
<!-- Sessions tab -->
|
|
60
60
|
<div id="tab-sessions" class="sidebar-tab-content flex flex-col flex-1 overflow-hidden">
|
|
61
|
-
<div class="p-2 border-b border-base-content/10 flex items-center justify-between">
|
|
62
|
-
<input id="session-search" type="text" class="input input-xs input-bordered flex-1
|
|
63
|
-
<button id="btn-
|
|
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 min-w-0" placeholder="Search...">
|
|
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 whitespace-nowrap" title="New session">+ New</button>
|
|
65
|
+
</div>
|
|
66
|
+
<!-- Batch action bar (hidden by default) -->
|
|
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">
|
|
68
|
+
<span class="batch-count opacity-60">0 selected</span>
|
|
69
|
+
<span class="flex-1"></span>
|
|
70
|
+
<button class="btn btn-xs btn-ghost" onclick="selectAllSessions()">All</button>
|
|
71
|
+
<button class="btn btn-xs btn-error btn-outline" onclick="batchDeleteSelected()">🗑 Delete</button>
|
|
72
|
+
<button class="btn btn-xs btn-ghost" onclick="toggleBatchSelect()">Cancel</button>
|
|
64
73
|
</div>
|
|
65
74
|
<div id="session-list" class="flex-1 overflow-y-auto p-2 flex flex-col gap-1 text-sm">
|
|
66
75
|
<div class="text-xs opacity-40 text-center py-4">No sessions yet</div>
|
|
@@ -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:
|
|
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; }
|