jinzd-ai-cli 0.4.277 → 0.4.279
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/{batch-2I5TPZA2.js → batch-6QZSWCBL.js} +2 -2
- package/dist/{chunk-ZP3RCZKM.js → chunk-2BKRWTEQ.js} +1 -1
- package/dist/{chunk-Z752LDYF.js → chunk-5XHEXRMN.js} +1 -1
- package/dist/{chunk-7BO5H2QI.js → chunk-6WMT7OQG.js} +1 -1
- package/dist/{chunk-HJVKCOAG.js → chunk-7L4TEK7Q.js} +419 -3
- package/dist/{chunk-7YYUITED.js → chunk-CMNXAJLH.js} +1 -1
- package/dist/{chunk-KIGKL3PZ.js → chunk-FQJFGGKN.js} +4 -4
- package/dist/{chunk-UWQCTTP4.js → chunk-IIXZ7IPN.js} +1 -1
- package/dist/{chunk-7IPMONKZ.js → chunk-JLOQBYU4.js} +3 -3
- package/dist/{chunk-I3PYD2YN.js → chunk-JS6VAPWM.js} +3 -3
- package/dist/{chunk-3VFOXEIL.js → chunk-NZPHEUJM.js} +1 -1
- package/dist/{chunk-HCF442WL.js → chunk-RJY3HJS4.js} +1 -1
- package/dist/{chunk-BYNNKJUC.js → chunk-SIVM2YQQ.js} +1 -1
- package/dist/{chunk-OCOGYIRY.js → chunk-UD3BVNC5.js} +1 -1
- package/dist/{ci-JFC45LIS.js → ci-F4ESOYI5.js} +4 -4
- package/dist/{ci-format-P3LIZHUR.js → ci-format-AIRW3TVQ.js} +2 -2
- package/dist/{constants-N3CHKZJY.js → constants-3VMMZJDS.js} +1 -1
- package/dist/{doctor-cli-Z3TGHTSX.js → doctor-cli-WVMEWMYE.js} +4 -4
- package/dist/electron-server.js +699 -101
- package/dist/{hub-NEWIFMQ3.js → hub-JJCCCU3O.js} +1 -1
- package/dist/index.js +243 -466
- package/dist/{persistent-memory-6Q5FDFJ7.js → persistent-memory-KSZKM4JG.js} +2 -2
- package/dist/{persistent-memory-ZFR5GI7D.js → persistent-memory-QZN4Q3W4.js} +2 -2
- package/dist/{pr-ZUGSWQ5R.js → pr-GFB5JC26.js} +4 -4
- package/dist/{run-tests-76M6AC3G.js → run-tests-EL54INOI.js} +2 -2
- package/dist/{run-tests-USV7IJ7X.js → run-tests-HMHHIG7Y.js} +2 -2
- package/dist/{server-R7D5RR36.js → server-6C7GITHY.js} +5 -5
- package/dist/{server-C523CIGN.js → server-WUSJWC3A.js} +324 -106
- package/dist/{task-orchestrator-G2MQDNGQ.js → task-orchestrator-C7RUUA2Q.js} +5 -5
- package/dist/{usage-EFHXXMYX.js → usage-CW6BT2UV.js} +2 -2
- package/dist/web/client/app.js +18 -3
- package/dist/web/client/app.js.br +0 -0
- package/dist/web/client/app.js.gz +0 -0
- package/package.json +1 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ConfigManager
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-UD3BVNC5.js";
|
|
5
5
|
import "./chunk-TU3L3PW7.js";
|
|
6
6
|
import {
|
|
7
7
|
atomicWriteFileSync
|
|
8
8
|
} from "./chunk-IW3Q7AE5.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-2BKRWTEQ.js";
|
|
10
10
|
|
|
11
11
|
// src/cli/batch.ts
|
|
12
12
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
MEMORY_FILE_NAME,
|
|
14
14
|
MEMORY_MAX_CHARS,
|
|
15
15
|
MEMORY_STORE_FILE_NAME
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-2BKRWTEQ.js";
|
|
17
17
|
|
|
18
18
|
// src/memory/persistent-memory.ts
|
|
19
19
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, statSync } from "fs";
|
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
estimateTokens,
|
|
7
7
|
truncateForPersist
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-FQJFGGKN.js";
|
|
9
9
|
import {
|
|
10
10
|
isMemoryExpired,
|
|
11
11
|
isMemoryStale
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-6WMT7OQG.js";
|
|
13
13
|
import {
|
|
14
14
|
isCleanDocumentBody,
|
|
15
15
|
stripOuterCodeFence
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
MCP_PROTOCOL_VERSION,
|
|
28
28
|
MCP_TOOL_PREFIX,
|
|
29
29
|
VERSION
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-2BKRWTEQ.js";
|
|
31
31
|
|
|
32
32
|
// src/mcp/client.ts
|
|
33
33
|
import { spawn } from "child_process";
|
|
@@ -1382,6 +1382,404 @@ function applyThinkCommand(sub, state) {
|
|
|
1382
1382
|
return stay(`Unknown /think option "${sub}" \u2014 expected on | off | low | high | max | status`);
|
|
1383
1383
|
}
|
|
1384
1384
|
|
|
1385
|
+
// src/core/provider-command.ts
|
|
1386
|
+
function preservedSuffix(messageCount) {
|
|
1387
|
+
return messageCount > 0 ? ` (conversation preserved: ${messageCount} messages)` : "";
|
|
1388
|
+
}
|
|
1389
|
+
function resolveProviderSwitch(input) {
|
|
1390
|
+
const id = input.targetId;
|
|
1391
|
+
if (!input.configured) {
|
|
1392
|
+
return {
|
|
1393
|
+
status: "not-configured",
|
|
1394
|
+
message: `Provider '${id}' is not configured. Run: aicli config`
|
|
1395
|
+
};
|
|
1396
|
+
}
|
|
1397
|
+
if (input.availableModels.length === 0) {
|
|
1398
|
+
return {
|
|
1399
|
+
status: "no-models",
|
|
1400
|
+
message: `Provider '${id}' has no available models. ` + (id === "ollama" ? "Make sure Ollama is running (`ollama serve`) and has models (`ollama pull <model>`)." : "Check provider configuration.")
|
|
1401
|
+
};
|
|
1402
|
+
}
|
|
1403
|
+
if (id === input.currentProvider) {
|
|
1404
|
+
return { status: "unchanged", message: `Already using provider: ${id}` };
|
|
1405
|
+
}
|
|
1406
|
+
const model = input.configuredDefaultModel || input.providerDefaultModel;
|
|
1407
|
+
return {
|
|
1408
|
+
status: "switched",
|
|
1409
|
+
providerId: id,
|
|
1410
|
+
model,
|
|
1411
|
+
message: `Switched to provider: ${id} (${model})` + preservedSuffix(input.messageCount)
|
|
1412
|
+
};
|
|
1413
|
+
}
|
|
1414
|
+
function parseModelCommand(args, currentProvider) {
|
|
1415
|
+
const raw = args[0];
|
|
1416
|
+
if (!raw) return { kind: "select" };
|
|
1417
|
+
const sub = raw.toLowerCase();
|
|
1418
|
+
if (sub === "refresh") return { kind: "refresh", providerId: args[1] ?? currentProvider };
|
|
1419
|
+
if (sub === "cache") {
|
|
1420
|
+
if ((args[1] ?? "").toLowerCase() === "clear") return { kind: "cache-clear", providerId: args[2] };
|
|
1421
|
+
return { kind: "cache-show" };
|
|
1422
|
+
}
|
|
1423
|
+
return { kind: "set", modelId: raw };
|
|
1424
|
+
}
|
|
1425
|
+
function resolveModelSwitch(input) {
|
|
1426
|
+
if (input.targetModel === input.currentModel) {
|
|
1427
|
+
return { status: "unchanged", message: `Already using model: ${input.targetModel}` };
|
|
1428
|
+
}
|
|
1429
|
+
const known = input.knownModels.includes(input.targetModel);
|
|
1430
|
+
return {
|
|
1431
|
+
status: "switched",
|
|
1432
|
+
model: input.targetModel,
|
|
1433
|
+
message: `Switched to model: ${input.targetModel}` + preservedSuffix(input.messageCount),
|
|
1434
|
+
warning: known ? void 0 : `'${input.targetModel}' is not in the known model list for ${input.provider}. If the provider rejects it, check the spelling or run /model refresh ${input.provider}.`
|
|
1435
|
+
};
|
|
1436
|
+
}
|
|
1437
|
+
var PLAN_MODE_TOOL_HINT = [
|
|
1438
|
+
"read_file \xB7 list_dir \xB7 grep_files \xB7 glob_files",
|
|
1439
|
+
"web_fetch \xB7 google_search \xB7 ask_user \xB7 write_todos"
|
|
1440
|
+
];
|
|
1441
|
+
function applyPlanCommand(sub, active) {
|
|
1442
|
+
const key = (sub ?? "enter").toLowerCase() === "toggle" ? active ? "exit" : "enter" : (sub ?? "enter").toLowerCase();
|
|
1443
|
+
if (key === "enter") {
|
|
1444
|
+
if (active) {
|
|
1445
|
+
return {
|
|
1446
|
+
planMode: true,
|
|
1447
|
+
changed: false,
|
|
1448
|
+
status: "already-active",
|
|
1449
|
+
summary: "Already in Plan Mode. Use /plan execute to start executing, or /plan exit to leave.",
|
|
1450
|
+
details: []
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
return {
|
|
1454
|
+
planMode: true,
|
|
1455
|
+
changed: true,
|
|
1456
|
+
status: "entered",
|
|
1457
|
+
summary: "\u{1F4CB} Plan Mode activated",
|
|
1458
|
+
details: [
|
|
1459
|
+
"AI can now ONLY use read-only tools:",
|
|
1460
|
+
...PLAN_MODE_TOOL_HINT,
|
|
1461
|
+
"Describe your task and the AI will analyze the codebase and create a detailed implementation plan.",
|
|
1462
|
+
"When ready: /plan execute | To cancel: /plan exit"
|
|
1463
|
+
]
|
|
1464
|
+
};
|
|
1465
|
+
}
|
|
1466
|
+
if (key === "execute") {
|
|
1467
|
+
if (!active) {
|
|
1468
|
+
return { planMode: false, changed: false, status: "not-active", summary: "Not in Plan Mode. Enter first with /plan", details: [] };
|
|
1469
|
+
}
|
|
1470
|
+
return {
|
|
1471
|
+
planMode: false,
|
|
1472
|
+
changed: true,
|
|
1473
|
+
status: "executing",
|
|
1474
|
+
summary: "Plan Mode ended \u2014 switching to execute mode. AI now has full tool access.",
|
|
1475
|
+
details: []
|
|
1476
|
+
};
|
|
1477
|
+
}
|
|
1478
|
+
if (key === "exit" || key === "cancel") {
|
|
1479
|
+
if (!active) {
|
|
1480
|
+
return { planMode: false, changed: false, status: "not-active", summary: "Not in Plan Mode.", details: [] };
|
|
1481
|
+
}
|
|
1482
|
+
return { planMode: false, changed: true, status: "cancelled", summary: "Plan Mode cancelled. Returning to normal mode.", details: [] };
|
|
1483
|
+
}
|
|
1484
|
+
if (key === "status" || key === "show") {
|
|
1485
|
+
return {
|
|
1486
|
+
planMode: active,
|
|
1487
|
+
changed: false,
|
|
1488
|
+
status: "status",
|
|
1489
|
+
summary: `Plan Mode: ${active ? "ACTIVE \u{1F4CB}" : "inactive"}`,
|
|
1490
|
+
details: active ? ["Tools restricted to read-only set.", "Use /plan execute to start executing, or /plan exit to cancel."] : []
|
|
1491
|
+
};
|
|
1492
|
+
}
|
|
1493
|
+
return {
|
|
1494
|
+
planMode: active,
|
|
1495
|
+
changed: false,
|
|
1496
|
+
status: "unknown",
|
|
1497
|
+
summary: `Unknown /plan option "${sub}" \u2014 expected execute | exit | status`,
|
|
1498
|
+
details: []
|
|
1499
|
+
};
|
|
1500
|
+
}
|
|
1501
|
+
function parseRouteCommand(args) {
|
|
1502
|
+
const sub = (args[0] ?? "show").toLowerCase();
|
|
1503
|
+
if (sub === "on" || sub === "enable") return { kind: "enable" };
|
|
1504
|
+
if (sub === "off" || sub === "disable") return { kind: "disable" };
|
|
1505
|
+
if (sub === "test") {
|
|
1506
|
+
const message = args.slice(1).join(" ").trim();
|
|
1507
|
+
return message ? { kind: "test", message } : { kind: "usage", message: "Usage: /route test <message>" };
|
|
1508
|
+
}
|
|
1509
|
+
if (sub === "show" || sub === "status") return { kind: "show" };
|
|
1510
|
+
return { kind: "unknown", message: `Unknown subcommand: ${sub}. Usage: /route [on|off|show|test <message>]` };
|
|
1511
|
+
}
|
|
1512
|
+
function routingEmptyRulesNote(routing) {
|
|
1513
|
+
if (routing && routing.rules.length > 0) return null;
|
|
1514
|
+
return 'No rules configured yet. Add rules under `routing.rules` in ~/.aicli/config.json.\nExample: { match: { tag: "fast" }, model: "claude-haiku-4-5" }';
|
|
1515
|
+
}
|
|
1516
|
+
function describeRoutingRule(rule, index) {
|
|
1517
|
+
const parts = [];
|
|
1518
|
+
if (rule.match.tag) parts.push(`tag=#${rule.match.tag}`);
|
|
1519
|
+
if (rule.match.contains && rule.match.contains.length > 0) {
|
|
1520
|
+
const shown = rule.match.contains.slice(0, 3).join(", ");
|
|
1521
|
+
parts.push(`contains=[${shown}${rule.match.contains.length > 3 ? ", \u2026" : ""}]`);
|
|
1522
|
+
}
|
|
1523
|
+
if (typeof rule.match.maxLength === "number") parts.push(`maxLen=${rule.match.maxLength}`);
|
|
1524
|
+
if (typeof rule.match.minLength === "number") parts.push(`minLen=${rule.match.minLength}`);
|
|
1525
|
+
const empty = parts.length === 0;
|
|
1526
|
+
return {
|
|
1527
|
+
index,
|
|
1528
|
+
name: rule.name,
|
|
1529
|
+
condition: empty ? "(empty \u2014 never matches)" : parts.join(" & "),
|
|
1530
|
+
model: rule.model,
|
|
1531
|
+
empty
|
|
1532
|
+
};
|
|
1533
|
+
}
|
|
1534
|
+
function describeRouting(input) {
|
|
1535
|
+
const rules = input.routing?.rules ?? [];
|
|
1536
|
+
return {
|
|
1537
|
+
enabled: input.routing?.enabled === true,
|
|
1538
|
+
provider: input.provider,
|
|
1539
|
+
currentModel: input.currentModel,
|
|
1540
|
+
fallback: input.routing?.fallback,
|
|
1541
|
+
rules: rules.map((r, i) => describeRoutingRule(r, i)),
|
|
1542
|
+
noRulesNote: rules.length === 0 ? "(no rules configured \u2014 edit ~/.aicli/config.json `routing.rules`)" : null,
|
|
1543
|
+
hint: "Commands: /route on | off | test <msg> | show"
|
|
1544
|
+
};
|
|
1545
|
+
}
|
|
1546
|
+
function routeDecisionRows(message, currentModel, decision) {
|
|
1547
|
+
const rows = [
|
|
1548
|
+
{ label: "Input", value: message },
|
|
1549
|
+
{ label: "Current", value: currentModel },
|
|
1550
|
+
{ label: "Decision", value: `${decision.model} ${decision.overridden ? "\u2192 ROUTED" : "(unchanged)"}` },
|
|
1551
|
+
{ label: "Reason", value: decision.reason }
|
|
1552
|
+
];
|
|
1553
|
+
if (typeof decision.ruleIdx === "number") rows.push({ label: "Rule", value: `#${decision.ruleIdx}` });
|
|
1554
|
+
return rows;
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
// src/core/session-command.ts
|
|
1558
|
+
var DEFAULT_SESSION_LIST_LIMIT = 50;
|
|
1559
|
+
function parseSessionListArgs(args) {
|
|
1560
|
+
let limit = DEFAULT_SESSION_LIST_LIMIT;
|
|
1561
|
+
let all = false;
|
|
1562
|
+
const filter = {};
|
|
1563
|
+
const warnings = [];
|
|
1564
|
+
let search = null;
|
|
1565
|
+
let days = null;
|
|
1566
|
+
let since = null;
|
|
1567
|
+
let sort = { field: "updated", order: "desc" };
|
|
1568
|
+
let json = false;
|
|
1569
|
+
let stale = null;
|
|
1570
|
+
let verbose = false;
|
|
1571
|
+
for (let i = 1; i < args.length; i++) {
|
|
1572
|
+
const a = args[i];
|
|
1573
|
+
if (a === "--all" || a === "-a") {
|
|
1574
|
+
all = true;
|
|
1575
|
+
} else if ((a === "--limit" || a === "-n") && i + 1 < args.length) {
|
|
1576
|
+
const n = Number(args[i + 1]);
|
|
1577
|
+
if (Number.isFinite(n) && n > 0) {
|
|
1578
|
+
limit = n;
|
|
1579
|
+
i++;
|
|
1580
|
+
}
|
|
1581
|
+
} else if (a === "--filter" && i + 1 < args.length) {
|
|
1582
|
+
const val = args[++i];
|
|
1583
|
+
const eq = val.indexOf("=");
|
|
1584
|
+
if (eq > 0) {
|
|
1585
|
+
const key = val.slice(0, eq);
|
|
1586
|
+
const vals = val.slice(eq + 1).split(",").map((s) => s.trim().toLowerCase());
|
|
1587
|
+
if (key === "provider") filter.provider = vals;
|
|
1588
|
+
else if (key === "model") filter.model = vals;
|
|
1589
|
+
else if (key === "messages") {
|
|
1590
|
+
const n = Number(vals[0]);
|
|
1591
|
+
if (Number.isFinite(n) && n >= 0) filter.messages = n;
|
|
1592
|
+
else warnings.push(`Invalid filter value for "messages": expected a non-negative integer, got "${vals[0]}"`);
|
|
1593
|
+
} else {
|
|
1594
|
+
warnings.push(`Unknown filter key: "${key}". Supported keys: provider, model, messages`);
|
|
1595
|
+
}
|
|
1596
|
+
} else {
|
|
1597
|
+
warnings.push(`Invalid --filter syntax: "${val}". Expected key=value`);
|
|
1598
|
+
}
|
|
1599
|
+
} else if ((a === "--search" || a === "-s") && i + 1 < args.length) {
|
|
1600
|
+
search = args[++i];
|
|
1601
|
+
} else if (a === "--days" && i + 1 < args.length) {
|
|
1602
|
+
const n = Number(args[++i]);
|
|
1603
|
+
if (Number.isFinite(n) && n > 0) days = n;
|
|
1604
|
+
} else if (a === "--since" && i + 1 < args.length) {
|
|
1605
|
+
since = args[++i];
|
|
1606
|
+
} else if (a === "--sort" && i + 1 < args.length) {
|
|
1607
|
+
const sv = args[++i];
|
|
1608
|
+
const colon = sv.indexOf(":");
|
|
1609
|
+
const field = colon > 0 ? sv.slice(0, colon) : sv;
|
|
1610
|
+
const order = colon > 0 ? sv.slice(colon + 1) : "desc";
|
|
1611
|
+
if (field === "updated" || field === "created" || field === "messages" || field === "size") {
|
|
1612
|
+
sort = { field, order: order === "asc" ? "asc" : "desc" };
|
|
1613
|
+
}
|
|
1614
|
+
} else if (a === "--json") {
|
|
1615
|
+
json = true;
|
|
1616
|
+
} else if (a === "--verbose" || a === "-v") {
|
|
1617
|
+
verbose = true;
|
|
1618
|
+
} else if (a === "--stale" && i + 1 < args.length) {
|
|
1619
|
+
const n = Number(args[++i]);
|
|
1620
|
+
if (Number.isFinite(n) && n > 0) stale = n;
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
if (all) limit = -1;
|
|
1624
|
+
return { limit, all, filter, search, days, since, sort, json, stale, verbose, warnings };
|
|
1625
|
+
}
|
|
1626
|
+
function sessionListNeedsFileSize(opts) {
|
|
1627
|
+
return opts.verbose || opts.sort.field === "size";
|
|
1628
|
+
}
|
|
1629
|
+
function selectSessions(sessions, opts, now = Date.now()) {
|
|
1630
|
+
let matched = sessions;
|
|
1631
|
+
const hasFilters = !!opts.filter.provider || !!opts.filter.model || opts.filter.messages !== void 0;
|
|
1632
|
+
const hasSearch = !!opts.search;
|
|
1633
|
+
const hasTimeFilter = opts.days !== null || opts.since !== null;
|
|
1634
|
+
const hasStale = opts.stale !== null;
|
|
1635
|
+
if (hasFilters) {
|
|
1636
|
+
const p = opts.filter.provider;
|
|
1637
|
+
const m = opts.filter.model;
|
|
1638
|
+
const msg = opts.filter.messages;
|
|
1639
|
+
matched = matched.filter((s) => {
|
|
1640
|
+
if (p && !p.includes(s.provider.toLowerCase())) return false;
|
|
1641
|
+
if (m && !m.some((kw) => s.model.toLowerCase().includes(kw))) return false;
|
|
1642
|
+
if (msg !== void 0 && s.messageCount !== msg) return false;
|
|
1643
|
+
return true;
|
|
1644
|
+
});
|
|
1645
|
+
}
|
|
1646
|
+
if (hasSearch) {
|
|
1647
|
+
const q = opts.search.toLowerCase();
|
|
1648
|
+
matched = matched.filter(
|
|
1649
|
+
(s) => (s.title ?? "").toLowerCase().includes(q) || s.id.toLowerCase().includes(q)
|
|
1650
|
+
);
|
|
1651
|
+
}
|
|
1652
|
+
if (hasTimeFilter) {
|
|
1653
|
+
let cutoff = 0;
|
|
1654
|
+
if (opts.since) cutoff = new Date(opts.since).getTime();
|
|
1655
|
+
else if (opts.days !== null) cutoff = now - opts.days * 24 * 60 * 60 * 1e3;
|
|
1656
|
+
if (!Number.isNaN(cutoff)) {
|
|
1657
|
+
matched = matched.filter((s) => s.updated.getTime() >= cutoff);
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
const staleCutoff = hasStale ? now - opts.stale * 24 * 60 * 60 * 1e3 : null;
|
|
1661
|
+
if (staleCutoff !== null) {
|
|
1662
|
+
matched = matched.filter((s) => s.updated.getTime() < staleCutoff);
|
|
1663
|
+
}
|
|
1664
|
+
const defaultSort = opts.sort.field === "updated" && opts.sort.order === "desc";
|
|
1665
|
+
if (!defaultSort) {
|
|
1666
|
+
const mul = opts.sort.order === "asc" ? 1 : -1;
|
|
1667
|
+
matched = [...matched].sort((a, b) => {
|
|
1668
|
+
switch (opts.sort.field) {
|
|
1669
|
+
case "created":
|
|
1670
|
+
return (a.created.getTime() - b.created.getTime()) * mul;
|
|
1671
|
+
case "messages":
|
|
1672
|
+
return (a.messageCount - b.messageCount) * mul;
|
|
1673
|
+
case "size":
|
|
1674
|
+
return ((a.fileSize ?? 0) - (b.fileSize ?? 0)) * mul;
|
|
1675
|
+
default:
|
|
1676
|
+
return (a.updated.getTime() - b.updated.getTime()) * mul;
|
|
1677
|
+
}
|
|
1678
|
+
});
|
|
1679
|
+
}
|
|
1680
|
+
const filterTags = [];
|
|
1681
|
+
if (hasFilters) filterTags.push("filtered");
|
|
1682
|
+
if (hasSearch) filterTags.push("searched");
|
|
1683
|
+
if (hasTimeFilter) filterTags.push("time-limited");
|
|
1684
|
+
if (hasStale) filterTags.push(`stale >${opts.stale}d`);
|
|
1685
|
+
return {
|
|
1686
|
+
matched,
|
|
1687
|
+
shown: opts.limit > 0 ? matched.slice(0, opts.limit) : matched,
|
|
1688
|
+
totalCount: matched.length,
|
|
1689
|
+
totalMessages: matched.reduce((sum, s) => sum + s.messageCount, 0),
|
|
1690
|
+
staleCutoff,
|
|
1691
|
+
filterTags,
|
|
1692
|
+
needsFileSize: sessionListNeedsFileSize(opts)
|
|
1693
|
+
};
|
|
1694
|
+
}
|
|
1695
|
+
function sessionListSummary(view) {
|
|
1696
|
+
const tag = view.filterTags.length > 0 ? ` (${view.filterTags.join(", ")})` : "";
|
|
1697
|
+
return `${view.shown.length} of ${view.totalCount} sessions${tag} \xB7 ${view.totalMessages} messages total`;
|
|
1698
|
+
}
|
|
1699
|
+
function sessionListJsonRow(s, includeFileSize) {
|
|
1700
|
+
return {
|
|
1701
|
+
id: s.id,
|
|
1702
|
+
title: s.title ?? null,
|
|
1703
|
+
provider: s.provider,
|
|
1704
|
+
model: s.model,
|
|
1705
|
+
messageCount: s.messageCount,
|
|
1706
|
+
created: s.created.toISOString(),
|
|
1707
|
+
updated: s.updated.toISOString(),
|
|
1708
|
+
...includeFileSize ? { fileSize: s.fileSize } : {},
|
|
1709
|
+
...s.branchCount !== void 0 ? { branchCount: s.branchCount, activeBranch: s.activeBranch } : {}
|
|
1710
|
+
};
|
|
1711
|
+
}
|
|
1712
|
+
function resolveSessionRef(sessions, prefix, policy) {
|
|
1713
|
+
const matches2 = sessions.filter((s) => s.id.startsWith(prefix));
|
|
1714
|
+
if (matches2.length === 0) {
|
|
1715
|
+
return { status: "not-found", message: `Session '${prefix}' not found.` };
|
|
1716
|
+
}
|
|
1717
|
+
if (matches2.length > 1 && policy === "strict") {
|
|
1718
|
+
return {
|
|
1719
|
+
status: "ambiguous",
|
|
1720
|
+
matches: matches2,
|
|
1721
|
+
message: `Ambiguous prefix '${prefix}' matches ${matches2.length} sessions \u2014 be more specific:`
|
|
1722
|
+
};
|
|
1723
|
+
}
|
|
1724
|
+
return {
|
|
1725
|
+
status: "ok",
|
|
1726
|
+
match: matches2[0],
|
|
1727
|
+
ambiguousWith: matches2.length > 1 ? matches2 : [],
|
|
1728
|
+
message: matches2.length > 1 ? `\u26A0 Ambiguous prefix '${prefix}' matches ${matches2.length} sessions \u2014 loading most recent:` : void 0
|
|
1729
|
+
};
|
|
1730
|
+
}
|
|
1731
|
+
function formatSessionSummaryLine(s, titleWidth = 60) {
|
|
1732
|
+
const title = s.title ?? "(untitled)";
|
|
1733
|
+
const shown = title.length > titleWidth ? `${title.slice(0, titleWidth - 1)}\u2026` : title;
|
|
1734
|
+
return `${s.id.slice(0, 12)} ${s.provider}/${s.model} ${String(s.messageCount).padStart(4)} msgs ${s.updated.toISOString().slice(0, 10)} ${shown}`;
|
|
1735
|
+
}
|
|
1736
|
+
function parseBatchDeleteArgs(args) {
|
|
1737
|
+
let messages;
|
|
1738
|
+
let dryRun = false;
|
|
1739
|
+
for (let i = 1; i < args.length; i++) {
|
|
1740
|
+
if (args[i] === "--filter" && i + 1 < args.length) {
|
|
1741
|
+
const val = args[++i];
|
|
1742
|
+
const eq = val.indexOf("=");
|
|
1743
|
+
if (eq <= 0) {
|
|
1744
|
+
return { dryRun, error: `Invalid --filter syntax: "${val}". Expected key=value (e.g., messages=0)` };
|
|
1745
|
+
}
|
|
1746
|
+
const key = val.slice(0, eq);
|
|
1747
|
+
const vals = val.slice(eq + 1).split(",").map((s) => s.trim().toLowerCase());
|
|
1748
|
+
if (key !== "messages") {
|
|
1749
|
+
return { dryRun, error: `Unsupported filter key for delete: "${key}". Only "messages" is supported.` };
|
|
1750
|
+
}
|
|
1751
|
+
const n = Number(vals[0]);
|
|
1752
|
+
if (!Number.isFinite(n) || n < 0) {
|
|
1753
|
+
return { dryRun, error: `Invalid filter value for "messages": expected a non-negative integer, got "${vals[0]}"` };
|
|
1754
|
+
}
|
|
1755
|
+
messages = n;
|
|
1756
|
+
} else if (args[i] === "--dry-run") {
|
|
1757
|
+
dryRun = true;
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
if (messages === void 0) {
|
|
1761
|
+
return { dryRun, error: "Usage: /session delete --filter messages=N [--dry-run]" };
|
|
1762
|
+
}
|
|
1763
|
+
return { messages, dryRun };
|
|
1764
|
+
}
|
|
1765
|
+
function parseCleanArgs(args) {
|
|
1766
|
+
let staleDays = 90;
|
|
1767
|
+
let dryRun = false;
|
|
1768
|
+
for (let i = 1; i < args.length; i++) {
|
|
1769
|
+
if (args[i] === "--stale" && i + 1 < args.length) {
|
|
1770
|
+
const n = Number(args[++i]);
|
|
1771
|
+
if (Number.isFinite(n) && n > 0) staleDays = n;
|
|
1772
|
+
} else if (args[i] === "--dry-run") {
|
|
1773
|
+
dryRun = true;
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
return { staleDays, dryRun };
|
|
1777
|
+
}
|
|
1778
|
+
function selectStaleSessions(sessions, staleDays, now = Date.now()) {
|
|
1779
|
+
const cutoff = now - staleDays * 24 * 60 * 60 * 1e3;
|
|
1780
|
+
return sessions.filter((s) => s.updated.getTime() < cutoff);
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1385
1783
|
// src/core/profile-command.ts
|
|
1386
1784
|
var PROFILE_FIELDS = ["name", "nickname", "role", "bio", "interests", "locale", "extra"];
|
|
1387
1785
|
function stripSurroundingQuotes(value) {
|
|
@@ -1543,6 +1941,24 @@ function costSourceNote(source) {
|
|
|
1543
1941
|
|
|
1544
1942
|
export {
|
|
1545
1943
|
applyThinkCommand,
|
|
1944
|
+
resolveProviderSwitch,
|
|
1945
|
+
parseModelCommand,
|
|
1946
|
+
resolveModelSwitch,
|
|
1947
|
+
applyPlanCommand,
|
|
1948
|
+
parseRouteCommand,
|
|
1949
|
+
routingEmptyRulesNote,
|
|
1950
|
+
describeRouting,
|
|
1951
|
+
routeDecisionRows,
|
|
1952
|
+
parseSessionListArgs,
|
|
1953
|
+
sessionListNeedsFileSize,
|
|
1954
|
+
selectSessions,
|
|
1955
|
+
sessionListSummary,
|
|
1956
|
+
sessionListJsonRow,
|
|
1957
|
+
resolveSessionRef,
|
|
1958
|
+
formatSessionSummaryLine,
|
|
1959
|
+
parseBatchDeleteArgs,
|
|
1960
|
+
parseCleanArgs,
|
|
1961
|
+
selectStaleSessions,
|
|
1546
1962
|
applyProfileCommand,
|
|
1547
1963
|
readGitDiff,
|
|
1548
1964
|
scanDirTree,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
searchPersistentMemories,
|
|
12
12
|
touchMemoryReferences,
|
|
13
13
|
updateMemoryEntry
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-6WMT7OQG.js";
|
|
15
15
|
import {
|
|
16
16
|
indexProject
|
|
17
17
|
} from "./chunk-4DEMGCK4.js";
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
runHook,
|
|
31
31
|
runLifecycleHooks,
|
|
32
32
|
runTool
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-IIXZ7IPN.js";
|
|
34
34
|
import {
|
|
35
35
|
buildTruncatedArgumentsError,
|
|
36
36
|
getDangerLevel,
|
|
@@ -50,14 +50,14 @@ import {
|
|
|
50
50
|
} from "./chunk-4BKXL7SM.js";
|
|
51
51
|
import {
|
|
52
52
|
runTestsTool
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-NZPHEUJM.js";
|
|
54
54
|
import {
|
|
55
55
|
CONFIG_DIR_NAME,
|
|
56
56
|
DEFAULT_MAX_TOOL_OUTPUT_CHARS_CAP,
|
|
57
57
|
SUBAGENT_ALLOWED_TOOLS,
|
|
58
58
|
SUBAGENT_DEFAULT_MAX_ROUNDS,
|
|
59
59
|
SUBAGENT_MAX_ROUNDS_LIMIT
|
|
60
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-2BKRWTEQ.js";
|
|
61
61
|
|
|
62
62
|
// src/tools/shell-pool.ts
|
|
63
63
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -8,13 +8,13 @@ import {
|
|
|
8
8
|
listHooks,
|
|
9
9
|
listInstalledPlugins,
|
|
10
10
|
resetStats
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-IIXZ7IPN.js";
|
|
12
12
|
import {
|
|
13
13
|
ProviderRegistry
|
|
14
14
|
} from "./chunk-UGY5SVNX.js";
|
|
15
15
|
import {
|
|
16
16
|
ConfigManager
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-UD3BVNC5.js";
|
|
18
18
|
import {
|
|
19
19
|
getGitRoot
|
|
20
20
|
} from "./chunk-HOSJZMQS.js";
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
MCP_PROJECT_CONFIG_NAME,
|
|
27
27
|
MEMORY_FILE_NAME,
|
|
28
28
|
VERSION
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-2BKRWTEQ.js";
|
|
30
30
|
|
|
31
31
|
// src/diagnostics/doctor-report.ts
|
|
32
32
|
import { existsSync as existsSync3, statSync as statSync2 } from "fs";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
evaluateCiGate,
|
|
4
4
|
normalizeCiThresholds
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-RJY3HJS4.js";
|
|
6
6
|
import {
|
|
7
7
|
buildReviewPrompt,
|
|
8
8
|
buildSecurityReviewPrompt,
|
|
@@ -16,10 +16,10 @@ import {
|
|
|
16
16
|
} from "./chunk-UGY5SVNX.js";
|
|
17
17
|
import {
|
|
18
18
|
ConfigManager
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-UD3BVNC5.js";
|
|
20
20
|
import {
|
|
21
21
|
VERSION
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-2BKRWTEQ.js";
|
|
23
23
|
|
|
24
24
|
// src/cli/ci.ts
|
|
25
25
|
import { execFileSync } from "child_process";
|
|
@@ -3,16 +3,16 @@ import {
|
|
|
3
3
|
CI_COMMENT_MARKER,
|
|
4
4
|
countSeverity,
|
|
5
5
|
runCi
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-JS6VAPWM.js";
|
|
7
|
+
import "./chunk-RJY3HJS4.js";
|
|
8
8
|
import "./chunk-HLWUDRBO.js";
|
|
9
9
|
import "./chunk-6YZEZFX5.js";
|
|
10
10
|
import "./chunk-UGY5SVNX.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-UD3BVNC5.js";
|
|
12
12
|
import "./chunk-TEXT4DAT.js";
|
|
13
13
|
import "./chunk-TU3L3PW7.js";
|
|
14
14
|
import "./chunk-IW3Q7AE5.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-2BKRWTEQ.js";
|
|
16
16
|
export {
|
|
17
17
|
CI_COMMENT_MARKER,
|
|
18
18
|
countSeverity,
|