jinzd-ai-cli 0.4.277 → 0.4.278
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-7Y4NAA6N.js} +2 -2
- package/dist/{chunk-OCOGYIRY.js → chunk-2BYQP6JX.js} +1 -1
- package/dist/{chunk-I3PYD2YN.js → chunk-4Z6GAYB5.js} +3 -3
- package/dist/{chunk-HCF442WL.js → chunk-H7QC5VMQ.js} +1 -1
- package/dist/{chunk-HJVKCOAG.js → chunk-JJCNNQTU.js} +183 -3
- package/dist/{chunk-UWQCTTP4.js → chunk-L3CPM472.js} +1 -1
- package/dist/{chunk-BYNNKJUC.js → chunk-LOXEYWC3.js} +1 -1
- package/dist/{chunk-7IPMONKZ.js → chunk-LTZFUYBT.js} +3 -3
- package/dist/{chunk-7YYUITED.js → chunk-LXXQTWT2.js} +1 -1
- package/dist/{chunk-7BO5H2QI.js → chunk-RFSKPCYC.js} +1 -1
- package/dist/{chunk-3VFOXEIL.js → chunk-SB4XONS4.js} +1 -1
- package/dist/{chunk-Z752LDYF.js → chunk-SJCOE4C7.js} +1 -1
- package/dist/{chunk-KIGKL3PZ.js → chunk-WOXIKQRI.js} +4 -4
- package/dist/{chunk-ZP3RCZKM.js → chunk-X3722RFA.js} +1 -1
- package/dist/{ci-JFC45LIS.js → ci-WDF2CYR4.js} +4 -4
- package/dist/{ci-format-P3LIZHUR.js → ci-format-7B5VAZGA.js} +2 -2
- package/dist/{constants-N3CHKZJY.js → constants-DC3TNLTL.js} +1 -1
- package/dist/{doctor-cli-Z3TGHTSX.js → doctor-cli-CDDG5XOY.js} +4 -4
- package/dist/electron-server.js +307 -49
- package/dist/{hub-NEWIFMQ3.js → hub-TO7ODOIA.js} +1 -1
- package/dist/index.js +150 -162
- package/dist/{persistent-memory-6Q5FDFJ7.js → persistent-memory-BU63CSGK.js} +2 -2
- package/dist/{persistent-memory-ZFR5GI7D.js → persistent-memory-JCENBMCJ.js} +2 -2
- package/dist/{pr-ZUGSWQ5R.js → pr-GVSZYX6I.js} +4 -4
- package/dist/{run-tests-USV7IJ7X.js → run-tests-2Q5MJHXB.js} +2 -2
- package/dist/{run-tests-76M6AC3G.js → run-tests-R4IQS6IF.js} +2 -2
- package/dist/{server-C523CIGN.js → server-KAURBKFI.js} +148 -54
- package/dist/{server-R7D5RR36.js → server-WXLE53HG.js} +5 -5
- package/dist/{task-orchestrator-G2MQDNGQ.js → task-orchestrator-RJ6FXYY5.js} +5 -5
- package/dist/{usage-EFHXXMYX.js → usage-V3R7DA7M.js} +2 -2
- package/dist/web/client/app.js +4 -1
- package/dist/web/client/app.js.br +0 -0
- package/dist/web/client/app.js.gz +0 -0
- package/package.json +1 -1
package/dist/electron-server.js
CHANGED
|
@@ -40,14 +40,14 @@ import {
|
|
|
40
40
|
touchMemoryReferences,
|
|
41
41
|
updateMemoryApproval,
|
|
42
42
|
updateMemoryEntry
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-LXXQTWT2.js";
|
|
44
44
|
import {
|
|
45
45
|
redactJson,
|
|
46
46
|
scanString
|
|
47
47
|
} from "./chunk-FSC6KEWU.js";
|
|
48
48
|
import {
|
|
49
49
|
runTestsTool
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-LOXEYWC3.js";
|
|
51
51
|
import {
|
|
52
52
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
53
53
|
APP_NAME,
|
|
@@ -80,7 +80,7 @@ import {
|
|
|
80
80
|
SUBAGENT_MAX_ROUNDS_LIMIT,
|
|
81
81
|
VERSION,
|
|
82
82
|
buildUserIdentityPrompt
|
|
83
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-SJCOE4C7.js";
|
|
84
84
|
import {
|
|
85
85
|
hasSemanticIndex,
|
|
86
86
|
semanticSearch
|
|
@@ -15543,48 +15543,259 @@ function applyThinkCommand(sub, state2) {
|
|
|
15543
15543
|
return stay(`Unknown /think option "${sub}" \u2014 expected on | off | low | high | max | status`);
|
|
15544
15544
|
}
|
|
15545
15545
|
|
|
15546
|
+
// src/core/provider-command.ts
|
|
15547
|
+
function preservedSuffix(messageCount) {
|
|
15548
|
+
return messageCount > 0 ? ` (conversation preserved: ${messageCount} messages)` : "";
|
|
15549
|
+
}
|
|
15550
|
+
function resolveProviderSwitch(input) {
|
|
15551
|
+
const id = input.targetId;
|
|
15552
|
+
if (!input.configured) {
|
|
15553
|
+
return {
|
|
15554
|
+
status: "not-configured",
|
|
15555
|
+
message: `Provider '${id}' is not configured. Run: aicli config`
|
|
15556
|
+
};
|
|
15557
|
+
}
|
|
15558
|
+
if (input.availableModels.length === 0) {
|
|
15559
|
+
return {
|
|
15560
|
+
status: "no-models",
|
|
15561
|
+
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.")
|
|
15562
|
+
};
|
|
15563
|
+
}
|
|
15564
|
+
if (id === input.currentProvider) {
|
|
15565
|
+
return { status: "unchanged", message: `Already using provider: ${id}` };
|
|
15566
|
+
}
|
|
15567
|
+
const model = input.configuredDefaultModel || input.providerDefaultModel;
|
|
15568
|
+
return {
|
|
15569
|
+
status: "switched",
|
|
15570
|
+
providerId: id,
|
|
15571
|
+
model,
|
|
15572
|
+
message: `Switched to provider: ${id} (${model})` + preservedSuffix(input.messageCount)
|
|
15573
|
+
};
|
|
15574
|
+
}
|
|
15575
|
+
function parseModelCommand(args, currentProvider) {
|
|
15576
|
+
const raw = args[0];
|
|
15577
|
+
if (!raw) return { kind: "select" };
|
|
15578
|
+
const sub = raw.toLowerCase();
|
|
15579
|
+
if (sub === "refresh") return { kind: "refresh", providerId: args[1] ?? currentProvider };
|
|
15580
|
+
if (sub === "cache") {
|
|
15581
|
+
if ((args[1] ?? "").toLowerCase() === "clear") return { kind: "cache-clear", providerId: args[2] };
|
|
15582
|
+
return { kind: "cache-show" };
|
|
15583
|
+
}
|
|
15584
|
+
return { kind: "set", modelId: raw };
|
|
15585
|
+
}
|
|
15586
|
+
function resolveModelSwitch(input) {
|
|
15587
|
+
if (input.targetModel === input.currentModel) {
|
|
15588
|
+
return { status: "unchanged", message: `Already using model: ${input.targetModel}` };
|
|
15589
|
+
}
|
|
15590
|
+
const known = input.knownModels.includes(input.targetModel);
|
|
15591
|
+
return {
|
|
15592
|
+
status: "switched",
|
|
15593
|
+
model: input.targetModel,
|
|
15594
|
+
message: `Switched to model: ${input.targetModel}` + preservedSuffix(input.messageCount),
|
|
15595
|
+
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}.`
|
|
15596
|
+
};
|
|
15597
|
+
}
|
|
15598
|
+
var PLAN_MODE_TOOL_HINT = [
|
|
15599
|
+
"read_file \xB7 list_dir \xB7 grep_files \xB7 glob_files",
|
|
15600
|
+
"web_fetch \xB7 google_search \xB7 ask_user \xB7 write_todos"
|
|
15601
|
+
];
|
|
15602
|
+
function applyPlanCommand(sub, active) {
|
|
15603
|
+
const key = (sub ?? "enter").toLowerCase() === "toggle" ? active ? "exit" : "enter" : (sub ?? "enter").toLowerCase();
|
|
15604
|
+
if (key === "enter") {
|
|
15605
|
+
if (active) {
|
|
15606
|
+
return {
|
|
15607
|
+
planMode: true,
|
|
15608
|
+
changed: false,
|
|
15609
|
+
status: "already-active",
|
|
15610
|
+
summary: "Already in Plan Mode. Use /plan execute to start executing, or /plan exit to leave.",
|
|
15611
|
+
details: []
|
|
15612
|
+
};
|
|
15613
|
+
}
|
|
15614
|
+
return {
|
|
15615
|
+
planMode: true,
|
|
15616
|
+
changed: true,
|
|
15617
|
+
status: "entered",
|
|
15618
|
+
summary: "\u{1F4CB} Plan Mode activated",
|
|
15619
|
+
details: [
|
|
15620
|
+
"AI can now ONLY use read-only tools:",
|
|
15621
|
+
...PLAN_MODE_TOOL_HINT,
|
|
15622
|
+
"Describe your task and the AI will analyze the codebase and create a detailed implementation plan.",
|
|
15623
|
+
"When ready: /plan execute | To cancel: /plan exit"
|
|
15624
|
+
]
|
|
15625
|
+
};
|
|
15626
|
+
}
|
|
15627
|
+
if (key === "execute") {
|
|
15628
|
+
if (!active) {
|
|
15629
|
+
return { planMode: false, changed: false, status: "not-active", summary: "Not in Plan Mode. Enter first with /plan", details: [] };
|
|
15630
|
+
}
|
|
15631
|
+
return {
|
|
15632
|
+
planMode: false,
|
|
15633
|
+
changed: true,
|
|
15634
|
+
status: "executing",
|
|
15635
|
+
summary: "Plan Mode ended \u2014 switching to execute mode. AI now has full tool access.",
|
|
15636
|
+
details: []
|
|
15637
|
+
};
|
|
15638
|
+
}
|
|
15639
|
+
if (key === "exit" || key === "cancel") {
|
|
15640
|
+
if (!active) {
|
|
15641
|
+
return { planMode: false, changed: false, status: "not-active", summary: "Not in Plan Mode.", details: [] };
|
|
15642
|
+
}
|
|
15643
|
+
return { planMode: false, changed: true, status: "cancelled", summary: "Plan Mode cancelled. Returning to normal mode.", details: [] };
|
|
15644
|
+
}
|
|
15645
|
+
if (key === "status" || key === "show") {
|
|
15646
|
+
return {
|
|
15647
|
+
planMode: active,
|
|
15648
|
+
changed: false,
|
|
15649
|
+
status: "status",
|
|
15650
|
+
summary: `Plan Mode: ${active ? "ACTIVE \u{1F4CB}" : "inactive"}`,
|
|
15651
|
+
details: active ? ["Tools restricted to read-only set.", "Use /plan execute to start executing, or /plan exit to cancel."] : []
|
|
15652
|
+
};
|
|
15653
|
+
}
|
|
15654
|
+
return {
|
|
15655
|
+
planMode: active,
|
|
15656
|
+
changed: false,
|
|
15657
|
+
status: "unknown",
|
|
15658
|
+
summary: `Unknown /plan option "${sub}" \u2014 expected execute | exit | status`,
|
|
15659
|
+
details: []
|
|
15660
|
+
};
|
|
15661
|
+
}
|
|
15662
|
+
function parseRouteCommand(args) {
|
|
15663
|
+
const sub = (args[0] ?? "show").toLowerCase();
|
|
15664
|
+
if (sub === "on" || sub === "enable") return { kind: "enable" };
|
|
15665
|
+
if (sub === "off" || sub === "disable") return { kind: "disable" };
|
|
15666
|
+
if (sub === "test") {
|
|
15667
|
+
const message = args.slice(1).join(" ").trim();
|
|
15668
|
+
return message ? { kind: "test", message } : { kind: "usage", message: "Usage: /route test <message>" };
|
|
15669
|
+
}
|
|
15670
|
+
if (sub === "show" || sub === "status") return { kind: "show" };
|
|
15671
|
+
return { kind: "unknown", message: `Unknown subcommand: ${sub}. Usage: /route [on|off|show|test <message>]` };
|
|
15672
|
+
}
|
|
15673
|
+
function routingEmptyRulesNote(routing) {
|
|
15674
|
+
if (routing && routing.rules.length > 0) return null;
|
|
15675
|
+
return 'No rules configured yet. Add rules under `routing.rules` in ~/.aicli/config.json.\nExample: { match: { tag: "fast" }, model: "claude-haiku-4-5" }';
|
|
15676
|
+
}
|
|
15677
|
+
function describeRoutingRule(rule, index) {
|
|
15678
|
+
const parts = [];
|
|
15679
|
+
if (rule.match.tag) parts.push(`tag=#${rule.match.tag}`);
|
|
15680
|
+
if (rule.match.contains && rule.match.contains.length > 0) {
|
|
15681
|
+
const shown = rule.match.contains.slice(0, 3).join(", ");
|
|
15682
|
+
parts.push(`contains=[${shown}${rule.match.contains.length > 3 ? ", \u2026" : ""}]`);
|
|
15683
|
+
}
|
|
15684
|
+
if (typeof rule.match.maxLength === "number") parts.push(`maxLen=${rule.match.maxLength}`);
|
|
15685
|
+
if (typeof rule.match.minLength === "number") parts.push(`minLen=${rule.match.minLength}`);
|
|
15686
|
+
const empty = parts.length === 0;
|
|
15687
|
+
return {
|
|
15688
|
+
index,
|
|
15689
|
+
name: rule.name,
|
|
15690
|
+
condition: empty ? "(empty \u2014 never matches)" : parts.join(" & "),
|
|
15691
|
+
model: rule.model,
|
|
15692
|
+
empty
|
|
15693
|
+
};
|
|
15694
|
+
}
|
|
15695
|
+
function describeRouting(input) {
|
|
15696
|
+
const rules = input.routing?.rules ?? [];
|
|
15697
|
+
return {
|
|
15698
|
+
enabled: input.routing?.enabled === true,
|
|
15699
|
+
provider: input.provider,
|
|
15700
|
+
currentModel: input.currentModel,
|
|
15701
|
+
fallback: input.routing?.fallback,
|
|
15702
|
+
rules: rules.map((r, i) => describeRoutingRule(r, i)),
|
|
15703
|
+
noRulesNote: rules.length === 0 ? "(no rules configured \u2014 edit ~/.aicli/config.json `routing.rules`)" : null,
|
|
15704
|
+
hint: "Commands: /route on | off | test <msg> | show"
|
|
15705
|
+
};
|
|
15706
|
+
}
|
|
15707
|
+
function routeDecisionRows(message, currentModel, decision) {
|
|
15708
|
+
const rows = [
|
|
15709
|
+
{ label: "Input", value: message },
|
|
15710
|
+
{ label: "Current", value: currentModel },
|
|
15711
|
+
{ label: "Decision", value: `${decision.model} ${decision.overridden ? "\u2192 ROUTED" : "(unchanged)"}` },
|
|
15712
|
+
{ label: "Reason", value: decision.reason }
|
|
15713
|
+
];
|
|
15714
|
+
if (typeof decision.ruleIdx === "number") rows.push({ label: "Rule", value: `#${decision.ruleIdx}` });
|
|
15715
|
+
return rows;
|
|
15716
|
+
}
|
|
15717
|
+
|
|
15546
15718
|
// src/web/commands/provider-commands.ts
|
|
15719
|
+
function syncSessionProvider(ctx) {
|
|
15720
|
+
const session = ctx.sessions.current;
|
|
15721
|
+
if (!session) return;
|
|
15722
|
+
session.updateProvider(ctx.currentProvider, ctx.currentModel);
|
|
15723
|
+
ctx.saveIfNeeded();
|
|
15724
|
+
}
|
|
15547
15725
|
async function handleProvider(args, ctx) {
|
|
15548
15726
|
const id = args[0];
|
|
15549
15727
|
if (!id) {
|
|
15550
15728
|
ctx.send({ type: "error", message: "Usage: /provider <id>" });
|
|
15551
15729
|
return;
|
|
15552
15730
|
}
|
|
15553
|
-
const
|
|
15554
|
-
|
|
15555
|
-
|
|
15731
|
+
const configured = ctx.providers.has(id);
|
|
15732
|
+
let availableModels = [];
|
|
15733
|
+
let providerDefaultModel = "";
|
|
15734
|
+
if (configured) {
|
|
15735
|
+
const target = ctx.providers.get(id);
|
|
15736
|
+
providerDefaultModel = target.info.defaultModel;
|
|
15737
|
+
availableModels = target.info.models.map((m) => m.id);
|
|
15738
|
+
if (availableModels.length === 0) {
|
|
15739
|
+
try {
|
|
15740
|
+
availableModels = (await target.listModels()).map((m) => m.id);
|
|
15741
|
+
} catch {
|
|
15742
|
+
availableModels = [];
|
|
15743
|
+
}
|
|
15744
|
+
}
|
|
15745
|
+
}
|
|
15746
|
+
const outcome = resolveProviderSwitch({
|
|
15747
|
+
targetId: id,
|
|
15748
|
+
currentProvider: ctx.currentProvider,
|
|
15749
|
+
configured,
|
|
15750
|
+
availableModels,
|
|
15751
|
+
configuredDefaultModel: ctx.config.get("defaultModels")[id],
|
|
15752
|
+
providerDefaultModel,
|
|
15753
|
+
messageCount: ctx.sessions.current?.messages.length ?? 0
|
|
15754
|
+
});
|
|
15755
|
+
if (outcome.status === "not-configured" || outcome.status === "no-models") {
|
|
15756
|
+
ctx.send({ type: "error", message: outcome.message });
|
|
15556
15757
|
return;
|
|
15557
15758
|
}
|
|
15558
|
-
|
|
15559
|
-
|
|
15759
|
+
if (outcome.status === "unchanged") {
|
|
15760
|
+
ctx.send({ type: "info", message: outcome.message });
|
|
15761
|
+
return;
|
|
15762
|
+
}
|
|
15763
|
+
ctx.currentProvider = outcome.providerId;
|
|
15764
|
+
ctx.currentModel = outcome.model;
|
|
15560
15765
|
ctx.updateContextWindow();
|
|
15561
|
-
|
|
15766
|
+
syncSessionProvider(ctx);
|
|
15767
|
+
ctx.send({ type: "info", message: outcome.message });
|
|
15562
15768
|
ctx.sendStatus();
|
|
15563
15769
|
}
|
|
15564
15770
|
async function handleModel(args, ctx) {
|
|
15565
|
-
const
|
|
15566
|
-
if (
|
|
15771
|
+
const intent = parseModelCommand(args, ctx.currentProvider);
|
|
15772
|
+
if (intent.kind === "select") {
|
|
15567
15773
|
ctx.send({ type: "error", message: "Usage: /model <id>|refresh [provider]|cache [clear [provider]]" });
|
|
15568
15774
|
return;
|
|
15569
15775
|
}
|
|
15570
|
-
if (
|
|
15571
|
-
|
|
15776
|
+
if (intent.kind === "refresh") {
|
|
15777
|
+
if (!ctx.providers.has(intent.providerId)) {
|
|
15778
|
+
ctx.send({ type: "error", message: `Provider is not configured: ${intent.providerId}` });
|
|
15779
|
+
return;
|
|
15780
|
+
}
|
|
15572
15781
|
try {
|
|
15573
|
-
const models2 = await ctx.providers.refreshModels(providerId);
|
|
15574
|
-
ctx.send({ type: "info", message: `Refreshed ${models2.length} model(s) for ${providerId}.` });
|
|
15782
|
+
const models2 = await ctx.providers.refreshModels(intent.providerId);
|
|
15783
|
+
ctx.send({ type: "info", message: `Refreshed ${models2.length} model(s) for ${intent.providerId}.` });
|
|
15575
15784
|
ctx.sendStatus();
|
|
15576
15785
|
} catch (err) {
|
|
15577
15786
|
ctx.send({ type: "error", message: `Model refresh failed: ${err instanceof Error ? err.message : String(err)}` });
|
|
15578
15787
|
}
|
|
15579
15788
|
return;
|
|
15580
15789
|
}
|
|
15581
|
-
if (
|
|
15582
|
-
|
|
15583
|
-
|
|
15584
|
-
|
|
15585
|
-
|
|
15586
|
-
|
|
15587
|
-
|
|
15790
|
+
if (intent.kind === "cache-clear") {
|
|
15791
|
+
ctx.providers.clearModelCache(intent.providerId);
|
|
15792
|
+
ctx.send({
|
|
15793
|
+
type: "info",
|
|
15794
|
+
message: intent.providerId ? `Cleared model cache for ${intent.providerId}.` : "Cleared model cache."
|
|
15795
|
+
});
|
|
15796
|
+
return;
|
|
15797
|
+
}
|
|
15798
|
+
if (intent.kind === "cache-show") {
|
|
15588
15799
|
const rows = ctx.providers.getModelCacheStatus();
|
|
15589
15800
|
ctx.send({
|
|
15590
15801
|
type: "info",
|
|
@@ -15592,16 +15803,25 @@ async function handleModel(args, ctx) {
|
|
|
15592
15803
|
});
|
|
15593
15804
|
return;
|
|
15594
15805
|
}
|
|
15595
|
-
const modelId = sub;
|
|
15596
15806
|
const models = await ctx.providers.listModels(ctx.currentProvider);
|
|
15597
|
-
const
|
|
15598
|
-
|
|
15599
|
-
ctx.
|
|
15807
|
+
const outcome = resolveModelSwitch({
|
|
15808
|
+
targetModel: intent.modelId,
|
|
15809
|
+
currentModel: ctx.currentModel,
|
|
15810
|
+
provider: ctx.currentProvider,
|
|
15811
|
+
knownModels: models.map((m) => m.id),
|
|
15812
|
+
messageCount: ctx.sessions.current?.messages.length ?? 0
|
|
15813
|
+
});
|
|
15814
|
+
if (outcome.status === "unchanged") {
|
|
15815
|
+
ctx.send({ type: "info", message: outcome.message });
|
|
15600
15816
|
return;
|
|
15601
15817
|
}
|
|
15602
|
-
ctx.currentModel =
|
|
15818
|
+
ctx.currentModel = outcome.model;
|
|
15603
15819
|
ctx.updateContextWindow();
|
|
15604
|
-
ctx
|
|
15820
|
+
syncSessionProvider(ctx);
|
|
15821
|
+
ctx.send({
|
|
15822
|
+
type: "info",
|
|
15823
|
+
message: outcome.warning ? `${outcome.message} \u2014 ${outcome.warning}` : outcome.message
|
|
15824
|
+
});
|
|
15605
15825
|
ctx.sendStatus();
|
|
15606
15826
|
}
|
|
15607
15827
|
async function handleThink(args, ctx) {
|
|
@@ -15611,7 +15831,7 @@ async function handleThink(args, ctx) {
|
|
|
15611
15831
|
runtimeEffort: ctx.runtimeThinkingEffort,
|
|
15612
15832
|
configuredThinking: modelParams?.thinking,
|
|
15613
15833
|
configuredEffort: modelParams?.thinkingEffort,
|
|
15614
|
-
supportsEffort: ctx.providers.get(ctx.currentProvider)
|
|
15834
|
+
supportsEffort: ctx.providers.has(ctx.currentProvider) ? ctx.providers.get(ctx.currentProvider).supportsReasoningEffort : false,
|
|
15615
15835
|
provider: ctx.currentProvider
|
|
15616
15836
|
});
|
|
15617
15837
|
if (outcome.changed) {
|
|
@@ -15625,24 +15845,59 @@ async function handleThink(args, ctx) {
|
|
|
15625
15845
|
if (outcome.changed) ctx.sendStatus();
|
|
15626
15846
|
}
|
|
15627
15847
|
async function handlePlan(args, ctx) {
|
|
15628
|
-
const
|
|
15629
|
-
if (
|
|
15630
|
-
|
|
15631
|
-
|
|
15632
|
-
|
|
15633
|
-
|
|
15634
|
-
|
|
15635
|
-
|
|
15636
|
-
|
|
15848
|
+
const outcome = applyPlanCommand(args[0], ctx.planMode);
|
|
15849
|
+
if (outcome.changed) ctx.planMode = outcome.planMode;
|
|
15850
|
+
ctx.send({
|
|
15851
|
+
type: outcome.status === "unknown" ? "error" : "info",
|
|
15852
|
+
message: [outcome.summary, ...outcome.details].join(" \u2014 ")
|
|
15853
|
+
});
|
|
15854
|
+
if (outcome.changed) ctx.sendStatus();
|
|
15855
|
+
}
|
|
15856
|
+
async function handleRoute(args, ctx) {
|
|
15857
|
+
const intent = parseRouteCommand(args);
|
|
15858
|
+
const routing = ctx.config.get("routing");
|
|
15859
|
+
if (intent.kind === "enable" || intent.kind === "disable") {
|
|
15860
|
+
const on = intent.kind === "enable";
|
|
15861
|
+
ctx.config.setByPath("routing.enabled", on ? "true" : "false");
|
|
15862
|
+
const note = on ? routingEmptyRulesNote(routing) : null;
|
|
15863
|
+
ctx.send({
|
|
15864
|
+
type: "info",
|
|
15865
|
+
message: `Smart model routing ${on ? "enabled" : "disabled"}.` + (note ? `
|
|
15866
|
+
${note}` : "")
|
|
15867
|
+
});
|
|
15868
|
+
ctx.sendStatus();
|
|
15869
|
+
return;
|
|
15870
|
+
}
|
|
15871
|
+
if (intent.kind === "usage" || intent.kind === "unknown") {
|
|
15872
|
+
ctx.send({ type: "error", message: intent.message });
|
|
15637
15873
|
return;
|
|
15638
|
-
}
|
|
15639
|
-
|
|
15874
|
+
}
|
|
15875
|
+
if (intent.kind === "test") {
|
|
15876
|
+
const decision = ctx.computeRoutingDecision(intent.message);
|
|
15877
|
+
ctx.send({
|
|
15878
|
+
type: "info",
|
|
15879
|
+
message: routeDecisionRows(intent.message, ctx.currentModel, decision).map((row) => `${row.label}: ${row.value}`).join("\n")
|
|
15880
|
+
});
|
|
15640
15881
|
return;
|
|
15882
|
+
}
|
|
15883
|
+
const view = describeRouting({ routing, provider: ctx.currentProvider, currentModel: ctx.currentModel });
|
|
15884
|
+
const lines = [
|
|
15885
|
+
"Smart Model Routing",
|
|
15886
|
+
`Status: ${view.enabled ? "enabled" : "disabled"}`,
|
|
15887
|
+
`Provider: ${view.provider}`,
|
|
15888
|
+
`Current: ${view.currentModel}`
|
|
15889
|
+
];
|
|
15890
|
+
if (view.fallback) lines.push(`Fallback: ${view.fallback}`);
|
|
15891
|
+
if (view.noRulesNote) {
|
|
15892
|
+
lines.push(view.noRulesNote);
|
|
15641
15893
|
} else {
|
|
15642
|
-
|
|
15643
|
-
|
|
15894
|
+
lines.push("Rules (evaluated top-to-bottom):");
|
|
15895
|
+
for (const rule of view.rules) {
|
|
15896
|
+
lines.push(` #${rule.index} ${rule.name ? `${rule.name} ` : ""}${rule.condition} \u2192 ${rule.model}`);
|
|
15897
|
+
}
|
|
15644
15898
|
}
|
|
15645
|
-
|
|
15899
|
+
lines.push(view.hint);
|
|
15900
|
+
ctx.send({ type: "info", message: lines.join("\n") });
|
|
15646
15901
|
}
|
|
15647
15902
|
|
|
15648
15903
|
// src/core/session-cost.ts
|
|
@@ -16175,7 +16430,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
|
|
|
16175
16430
|
Cost: ${formatCost(cost)}` : "";
|
|
16176
16431
|
let memoryLine = "";
|
|
16177
16432
|
try {
|
|
16178
|
-
const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-
|
|
16433
|
+
const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-JCENBMCJ.js");
|
|
16179
16434
|
const pending = countPendingMemories2(ctx.config.getConfigDir());
|
|
16180
16435
|
if (pending > 0) memoryLine = `
|
|
16181
16436
|
Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
|
|
@@ -16988,7 +17243,7 @@ async function handleTest(args, ctx) {
|
|
|
16988
17243
|
const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
|
|
16989
17244
|
testArgs = isCommand ? { command: argStr } : { filter: argStr };
|
|
16990
17245
|
}
|
|
16991
|
-
const runTests = ctx.runTests ?? (await import("./run-tests-
|
|
17246
|
+
const runTests = ctx.runTests ?? (await import("./run-tests-2Q5MJHXB.js")).executeTests;
|
|
16992
17247
|
const report = await runTests(testArgs);
|
|
16993
17248
|
ctx.send({ type: "info", message: report });
|
|
16994
17249
|
} catch (err) {
|
|
@@ -17324,7 +17579,7 @@ async function handleMemory(args, ctx) {
|
|
|
17324
17579
|
ctx.handleMemoryManage(sub, args[1], sub === "expire" ? args[2] : void 0);
|
|
17325
17580
|
} else if (sub === "export") {
|
|
17326
17581
|
if (args[1] === "md") {
|
|
17327
|
-
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-
|
|
17582
|
+
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-JCENBMCJ.js");
|
|
17328
17583
|
ctx.send({
|
|
17329
17584
|
type: "export_data",
|
|
17330
17585
|
format: "md",
|
|
@@ -17766,7 +18021,8 @@ async function handleHelp(_args, ctx) {
|
|
|
17766
18021
|
" /clear \u2014 Clear conversation & start new session",
|
|
17767
18022
|
" /compact [hint] \u2014 Compress conversation history",
|
|
17768
18023
|
" /think [on|off] \u2014 Toggle extended thinking mode",
|
|
17769
|
-
" /plan [
|
|
18024
|
+
" /plan [execute|exit|status] \u2014 Read-only planning mode (bare /plan enters it)",
|
|
18025
|
+
" /route [on|off|show|test <msg>] \u2014 Smart model routing",
|
|
17770
18026
|
" /session new|list|load|delete <id> \u2014 Session management",
|
|
17771
18027
|
" /system [prompt|clear] \u2014 Set/view/reset system prompt",
|
|
17772
18028
|
" /context [status|reload] \u2014 Show/reload context layers",
|
|
@@ -17903,8 +18159,9 @@ var CLI_ONLY_WEB_COMMANDS = /* @__PURE__ */ new Map([
|
|
|
17903
18159
|
["snapshot", "Dev-state snapshots are written when the terminal REPL exits."],
|
|
17904
18160
|
["hooks", "Hook trust is granted per machine from the terminal."],
|
|
17905
18161
|
["hook", "Hook trust is granted per machine from the terminal."],
|
|
17906
|
-
//
|
|
17907
|
-
|
|
18162
|
+
// 以下一条并非「终端才有意义」,而是 Web 侧尚未实现——如实说明,别假装是设计。
|
|
18163
|
+
// (`route` 曾在这里,理由写的是「Web 尚未应用智能路由」;v0.4.269 让 routing 在 Web
|
|
18164
|
+
// 上真正生效之后那句话就不再成立,命令已在 Web 实现,见 commands/provider-commands.ts。)
|
|
17908
18165
|
["security", "Redaction status and toggles are terminal-only for now; /status shows the current profile."]
|
|
17909
18166
|
]);
|
|
17910
18167
|
var webCommandHandlers = {
|
|
@@ -17912,6 +18169,7 @@ var webCommandHandlers = {
|
|
|
17912
18169
|
model: handleModel,
|
|
17913
18170
|
think: handleThink,
|
|
17914
18171
|
plan: handlePlan,
|
|
18172
|
+
route: handleRoute,
|
|
17915
18173
|
clear: handleClear,
|
|
17916
18174
|
compact: handleCompact,
|
|
17917
18175
|
status: handleStatus,
|
|
@@ -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-
|
|
161
|
+
const { TaskOrchestrator } = await import("./task-orchestrator-RJ6FXYY5.js");
|
|
162
162
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
163
163
|
let interrupted = false;
|
|
164
164
|
const onSigint = () => {
|