jinzd-ai-cli 0.1.91 → 0.1.93
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-KYHUMNQO.js → chunk-BZVXXYAB.js} +1 -1
- package/dist/{chunk-CXWWAWE7.js → chunk-HLMYGNCU.js} +1 -1
- package/dist/index.js +4 -4
- package/dist/{run-tests-TLJ53CV5.js → run-tests-X5ZA6FTL.js} +1 -1
- package/dist/{server-QG62ZDQI.js → server-G4DGAXKU.js} +51 -10
- package/dist/web/client/app.js +70 -13
- package/dist/web/client/index.html +11 -2
- 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-HLMYGNCU.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-BZVXXYAB.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-X5ZA6FTL.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-G4DGAXKU.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-HLMYGNCU.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-BZVXXYAB.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,15 @@ 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.sessions.
|
|
527
|
+
if (this.sessions.current && this.sessions.current.messages.length > 0) {
|
|
528
|
+
this.sessions.save();
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
/** Lazily create a session if none exists yet (deferred from constructor). */
|
|
532
|
+
ensureSession() {
|
|
533
|
+
if (!this.sessions.current) {
|
|
534
|
+
this.sessions.createSession(this.currentProvider, this.currentModel);
|
|
535
|
+
}
|
|
529
536
|
}
|
|
530
537
|
// ── Chat handling ────────────────────────────────────────────────
|
|
531
538
|
async handleChat(content, images) {
|
|
@@ -535,6 +542,7 @@ var SessionHandler = class {
|
|
|
535
542
|
}
|
|
536
543
|
this.processing = true;
|
|
537
544
|
try {
|
|
545
|
+
this.ensureSession();
|
|
538
546
|
const session = this.sessions.current;
|
|
539
547
|
let msgContent;
|
|
540
548
|
if (images && images.length > 0) {
|
|
@@ -947,6 +955,23 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
|
|
|
947
955
|
} else {
|
|
948
956
|
this.send({ type: "error", message: `Session not found: ${targetId}` });
|
|
949
957
|
}
|
|
958
|
+
} else if (sub === "batch-delete") {
|
|
959
|
+
const ids = args.slice(1).filter(Boolean);
|
|
960
|
+
if (ids.length === 0) {
|
|
961
|
+
this.send({ type: "error", message: "No session IDs provided." });
|
|
962
|
+
break;
|
|
963
|
+
}
|
|
964
|
+
const list = this.sessions.listSessions();
|
|
965
|
+
let deleted = 0;
|
|
966
|
+
for (const targetId of ids) {
|
|
967
|
+
const found = list.find((s) => s.id.startsWith(targetId));
|
|
968
|
+
if (found) {
|
|
969
|
+
this.sessions.deleteSession(found.id);
|
|
970
|
+
deleted++;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
this.send({ type: "info", message: `Deleted ${deleted} session(s).` });
|
|
974
|
+
this.sendSessionList();
|
|
950
975
|
} else {
|
|
951
976
|
this.send({ type: "info", message: "Usage: /session new | list | load <id> | delete <id>" });
|
|
952
977
|
}
|
|
@@ -1477,14 +1502,30 @@ async function startWebServer(options = {}) {
|
|
|
1477
1502
|
console.error(` WebSocket error: ${err.message}`);
|
|
1478
1503
|
});
|
|
1479
1504
|
});
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1505
|
+
const MAX_PORT_ATTEMPTS = 10;
|
|
1506
|
+
let actualPort = port;
|
|
1507
|
+
const tryListen = (attempt) => {
|
|
1508
|
+
server.listen(actualPort, host, () => {
|
|
1509
|
+
const url = `http://${host}:${actualPort}`;
|
|
1510
|
+
console.log(`
|
|
1483
1511
|
\u{1F310} Web UI ready: ${url}`);
|
|
1484
|
-
|
|
1512
|
+
if (actualPort !== port) console.log(` (port ${port} was in use, using ${actualPort})`);
|
|
1513
|
+
console.log(` Press Ctrl+C to stop
|
|
1485
1514
|
`);
|
|
1486
|
-
|
|
1487
|
-
|
|
1515
|
+
openBrowser(url);
|
|
1516
|
+
});
|
|
1517
|
+
server.once("error", (err) => {
|
|
1518
|
+
if (err.code === "EADDRINUSE" && attempt < MAX_PORT_ATTEMPTS) {
|
|
1519
|
+
actualPort++;
|
|
1520
|
+
console.log(` \u26A0 Port ${actualPort - 1} in use, trying ${actualPort}...`);
|
|
1521
|
+
tryListen(attempt + 1);
|
|
1522
|
+
} else {
|
|
1523
|
+
console.error(` \u274C Failed to start server: ${err.message}`);
|
|
1524
|
+
process.exit(1);
|
|
1525
|
+
}
|
|
1526
|
+
});
|
|
1527
|
+
};
|
|
1528
|
+
tryListen(1);
|
|
1488
1529
|
process.on("SIGINT", () => {
|
|
1489
1530
|
console.log("\n Shutting down...");
|
|
1490
1531
|
for (const handler of handlers.values()) handler.onDisconnect();
|
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) {
|
|
@@ -58,10 +58,19 @@
|
|
|
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
|
|
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...">
|
|
63
|
+
<button id="btn-batch-select" class="btn btn-xs btn-ghost flex-shrink-0" title="Select multiple" onclick="toggleBatchSelect()">☑</button>
|
|
63
64
|
<button id="btn-new-session" class="btn btn-xs btn-primary btn-outline flex-shrink-0" title="New session">+ New</button>
|
|
64
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>
|
|
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>
|
|
67
76
|
</div>
|