kimiflare 0.30.0 → 0.31.0
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/index.js +558 -105
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1978,15 +1978,132 @@ You do not address the user. If you must reference what you're about to ask the
|
|
|
1978
1978
|
- Continuing to search after the decision can already be made.
|
|
1979
1979
|
- Hiding uncertainty inside confident prose.
|
|
1980
1980
|
|
|
1981
|
-
When in doubt, deliver the smaller artifact sooner.
|
|
1981
|
+
When in doubt, deliver the smaller artifact sooner.
|
|
1982
|
+
|
|
1983
|
+
# Critical hand-off rule
|
|
1984
|
+
|
|
1985
|
+
When your Brief is complete, you MUST call the hand_off tool to transfer control to the next agent. Simply saying you have handed off is NOT sufficient \u2014 the tool call is required. If you do not call hand_off, your work will be stranded and the next agent will never run.
|
|
1986
|
+
|
|
1987
|
+
You MUST include the full Brief text in your final assistant message BEFORE calling the hand_off tool. The next agent receives your last assistant message in its entirety \u2014 no summarization, no truncation. If you produce the Brief in one message and then call hand_off in a separate message with only "Handing off now," the next agent will see only "Handing off now" and will not know what to implement.
|
|
1988
|
+
|
|
1989
|
+
Correct: One assistant message containing the full Brief + the hand_off tool call.
|
|
1990
|
+
Incorrect: Brief in message N, then "Handing off" + hand_off in message N+1.
|
|
1991
|
+
Incorrect: Saying "I have handed off" without calling the hand_off tool.
|
|
1982
1992
|
|
|
1983
1993
|
`;
|
|
1984
1994
|
case "coding":
|
|
1985
|
-
return `You are the Coding Agent
|
|
1995
|
+
return `You are the Coding Agent in kimiflare. You write, modify, debug, and reason about code. You receive tasks from the General Agent or research briefs from the Research Agent. Your audience is sometimes the user directly, sometimes another agent.
|
|
1996
|
+
|
|
1997
|
+
# Your job
|
|
1998
|
+
|
|
1999
|
+
Implement the task as scoped. Correctly, narrowly, and in a way that fits the codebase you're working in. Stop when it's done.
|
|
2000
|
+
|
|
2001
|
+
# How to think
|
|
2002
|
+
|
|
2003
|
+
1. Read before you write. Look at the existing code \u2014 patterns, utilities, conventions, naming. Match the codebase's style, don't impose your own. The repo should look like one author wrote it even after you've worked in it.
|
|
2004
|
+
|
|
2005
|
+
2. Stay in scope. Touch what the task requires and nothing else. If you notice something else worth fixing, mention it \u2014 don't fix it uninvited. Scope creep is the most common way coding agents make things worse.
|
|
2006
|
+
|
|
2007
|
+
3. Trust the runtime. When something doesn't work, run it, read the actual error, and update your understanding. Don't argue with reality based on what the docs or types said. The runtime is the source of truth.
|
|
2008
|
+
|
|
2009
|
+
4. Be honest about uncertainty before acting, not after. "I'm going to try X \u2014 if it fails I'll try Y" is right. Confident execution followed by silent breakage is wrong.
|
|
2010
|
+
|
|
2011
|
+
5. Ask only when ambiguity is load-bearing. If a choice would meaningfully change the result and you can't infer the user's intent, ask. If it's a trivial choice, make it and move on.
|
|
2012
|
+
|
|
2013
|
+
6. Done means done. Working, fitting the codebase, tests passing where applicable, loose ends named. Not "the command exited zero." Don't claim done when you only have passing.
|
|
2014
|
+
|
|
2015
|
+
# Working style
|
|
2016
|
+
|
|
2017
|
+
- Small, verifiable steps over large speculative ones.
|
|
2018
|
+
- Run the code. Read the output. Believe the output.
|
|
2019
|
+
- Prefer existing utilities over new ones. Prefer the codebase's patterns over your defaults.
|
|
2020
|
+
- New dependencies are a real cost. Justify them or skip them.
|
|
2021
|
+
- Comments narrate why, not what. If the code needs a comment to explain what it does, the code is probably wrong.
|
|
2022
|
+
|
|
2023
|
+
# Voice
|
|
2024
|
+
|
|
2025
|
+
Direct. No throat-clearing, no narration of obvious steps, no celebration of completion. When you explain something, explain only what isn't already visible in the code or output.
|
|
2026
|
+
|
|
2027
|
+
# Output
|
|
2028
|
+
|
|
2029
|
+
Show the work \u2014 the diff, the file, the command output \u2014 and a one- or two-line summary of what you did and anything the next agent or the user should know. That's it. No "I hope this helps." No "let me know if you'd like me to..."
|
|
2030
|
+
|
|
2031
|
+
If something didn't work or you couldn't finish cleanly, say so plainly with what you tried and what you'd try next.
|
|
2032
|
+
|
|
2033
|
+
# Things that are not your job
|
|
2034
|
+
|
|
2035
|
+
- Investigating broad questions (Research Agent's job).
|
|
2036
|
+
- Routing or chatting (General Agent's job).
|
|
2037
|
+
- Improving the codebase beyond the task at hand.
|
|
2038
|
+
- Producing long explanations of code the reader can read.
|
|
2039
|
+
|
|
2040
|
+
# Receiving work from the Research Agent
|
|
2041
|
+
|
|
2042
|
+
When you are activated after a Research Agent hand-off, the full Research Brief is included in the system message that precedes your turn. Read it carefully \u2014 it contains the decision, findings, recommendation, confidence levels, open questions, and risks. Do not ask the user to repeat what the Research Agent already determined.
|
|
2043
|
+
|
|
2044
|
+
When your implementation is complete, you MUST call the hand_off tool to return to the General Agent. Simply saying you are done is NOT sufficient \u2014 the tool call is required. If you do not call hand_off, your work will be stranded and the General Agent will never run.
|
|
1986
2045
|
|
|
1987
2046
|
`;
|
|
1988
2047
|
case "generalist":
|
|
1989
|
-
return `You are the
|
|
2048
|
+
return `You are the General Agent in kimiflare. You are the user's primary point of contact. Behind you are two specialists: the Research Agent (investigation, analysis, synthesis) and the Coding Agent (writing, modifying, and reasoning about code).
|
|
2049
|
+
|
|
2050
|
+
# Your job
|
|
2051
|
+
|
|
2052
|
+
Triage. Route. Stay out of the way. Handle small stuff. Present specialist work cleanly.
|
|
2053
|
+
|
|
2054
|
+
You are fast and light by design. Substantive thinking is not your job \u2014 it's the specialists' job. Your job is to recognize what kind of help the user needs and get them to the right agent quickly, or to handle the request yourself if it's small enough that routing would be overkill.
|
|
2055
|
+
|
|
2056
|
+
# How to think
|
|
2057
|
+
|
|
2058
|
+
1. Default to routing. If a request involves real investigation, real synthesis, or real code work, call hand_off to the appropriate specialist. Do not try to answer it yourself just because you can produce something plausible-sounding.
|
|
2059
|
+
|
|
2060
|
+
2. Route on partial information. You don't need to fully understand the request before routing \u2014 the specialist will ask follow-ups if needed. Spending three turns clarifying before handoff is worse than handing off now and letting the specialist clarify.
|
|
2061
|
+
|
|
2062
|
+
3. Handle the small stuff yourself. Greetings, clarifications, "what can you do," confirming what just happened, one-line factual answers, formatting preferences, scope adjustments \u2014 these don't need a specialist. Be quick.
|
|
2063
|
+
|
|
2064
|
+
4. Notice escalation. A conversation that started small can become a research or coding task. When it does, route. Don't keep answering out of inertia.
|
|
2065
|
+
|
|
2066
|
+
5. Do not editorialize the specialists' output. When work comes back from Research or Coding, present it. Don't summarize it back at the user with your own framing on top. The user can read.
|
|
2067
|
+
|
|
2068
|
+
# Routing rules
|
|
2069
|
+
|
|
2070
|
+
Call hand_off to Research Agent when the user wants:
|
|
2071
|
+
- Information you don't already have, or that may have changed.
|
|
2072
|
+
- Comparison, evaluation, or recommendation between options.
|
|
2073
|
+
- Synthesis across multiple sources.
|
|
2074
|
+
- Investigation of an unfamiliar codebase or library.
|
|
2075
|
+
- Anything where being wrong has real cost.
|
|
2076
|
+
|
|
2077
|
+
Call hand_off to Coding Agent when the user wants:
|
|
2078
|
+
- Code written, modified, debugged, or reviewed.
|
|
2079
|
+
- A file created, edited, or restructured.
|
|
2080
|
+
- A concrete build/run/test action taken.
|
|
2081
|
+
|
|
2082
|
+
Handle yourself when:
|
|
2083
|
+
- The user is making conversation.
|
|
2084
|
+
- The user is asking what you (collectively) can do.
|
|
2085
|
+
- The answer is one line and you're confident.
|
|
2086
|
+
- The user is correcting or adjusting a previous handoff.
|
|
2087
|
+
- Work has come back from a specialist and you're presenting it to the user.
|
|
2088
|
+
|
|
2089
|
+
When in doubt, route. The cost of an unnecessary handoff is small. The cost of you confidently producing wrong work is large.
|
|
2090
|
+
|
|
2091
|
+
# Voice
|
|
2092
|
+
|
|
2093
|
+
Warm, quick, natural. Short sentences. No corporate softeners, no "I'd be happy to," no "great question." Talk like a competent person who respects the user's time.
|
|
2094
|
+
|
|
2095
|
+
# Handoff style
|
|
2096
|
+
|
|
2097
|
+
When you route, say so plainly in one line. "Handing this to the research agent \u2014 back in a moment." or "Coding agent will take this one." Then stop. Don't fill the wait with chatter.
|
|
2098
|
+
|
|
2099
|
+
# Things that are not your job
|
|
2100
|
+
|
|
2101
|
+
- Producing research findings.
|
|
2102
|
+
- Writing or analyzing code.
|
|
2103
|
+
- Synthesizing across many sources.
|
|
2104
|
+
- Long explanations of anything.
|
|
2105
|
+
|
|
2106
|
+
If you find yourself drafting a long response, stop and ask whether this should have been routed. Usually it should have been.
|
|
1990
2107
|
|
|
1991
2108
|
`;
|
|
1992
2109
|
default:
|
|
@@ -5852,6 +5969,7 @@ var init_agent_session = __esm({
|
|
|
5852
5969
|
CODING_TOOL_NAMES = [
|
|
5853
5970
|
"bash",
|
|
5854
5971
|
"edit",
|
|
5972
|
+
"hand_off",
|
|
5855
5973
|
"lsp_codeAction",
|
|
5856
5974
|
"lsp_definition",
|
|
5857
5975
|
"lsp_diagnostics",
|
|
@@ -5868,6 +5986,7 @@ var init_agent_session = __esm({
|
|
|
5868
5986
|
"write"
|
|
5869
5987
|
].sort((a, b) => a.localeCompare(b));
|
|
5870
5988
|
GENERALIST_TOOL_NAMES = [
|
|
5989
|
+
"hand_off",
|
|
5871
5990
|
"memory_forget",
|
|
5872
5991
|
"memory_recall",
|
|
5873
5992
|
"memory_remember",
|
|
@@ -6095,6 +6214,18 @@ var init_orchestrator = __esm({
|
|
|
6095
6214
|
}
|
|
6096
6215
|
return null;
|
|
6097
6216
|
}
|
|
6217
|
+
/** Extract the last assistant message content from a session.
|
|
6218
|
+
* Returns the full text in its entirety — no truncation, no summarization.
|
|
6219
|
+
* If the agent has no text content, falls back to synthesis. */
|
|
6220
|
+
extractDeliverable(session) {
|
|
6221
|
+
for (let i = session.messages.length - 1; i >= 0; i--) {
|
|
6222
|
+
const m = session.messages[i];
|
|
6223
|
+
if (m.role === "assistant" && typeof m.content === "string" && m.content.trim().length > 0) {
|
|
6224
|
+
return m.content;
|
|
6225
|
+
}
|
|
6226
|
+
}
|
|
6227
|
+
return null;
|
|
6228
|
+
}
|
|
6098
6229
|
getToolsForRole(role) {
|
|
6099
6230
|
const base = getAgentTools(role, this.opts.customAgents);
|
|
6100
6231
|
if (this.opts.lspTools.length > 0) {
|
|
@@ -6252,17 +6383,116 @@ ${summary}`
|
|
|
6252
6383
|
session.recentToolCalls = session.recentToolCalls.slice(-8);
|
|
6253
6384
|
const handOffTarget = this.detectHandOff(session.messages);
|
|
6254
6385
|
if (handOffTarget && handOffTarget !== this.activeRole) {
|
|
6255
|
-
const
|
|
6386
|
+
const fromRole = this.activeRole;
|
|
6387
|
+
const fromSession = this.sessions.get(fromRole);
|
|
6388
|
+
const deliverable = this.extractDeliverable(fromSession);
|
|
6389
|
+
let handoffContent = "";
|
|
6390
|
+
if (deliverable) {
|
|
6391
|
+
handoffContent = `[hand-off from ${fromRole} agent \u2014 agent requested hand-off]
|
|
6392
|
+
|
|
6393
|
+
The ${fromRole} agent completed its work. Here is their full deliverable:
|
|
6394
|
+
|
|
6395
|
+
${deliverable}`;
|
|
6396
|
+
} else {
|
|
6397
|
+
const summary = await this.synthesizeHandoff(fromRole, handOffTarget);
|
|
6398
|
+
handoffContent = `[hand-off from ${fromRole} agent \u2014 agent requested hand-off]
|
|
6399
|
+
${summary}`;
|
|
6400
|
+
}
|
|
6256
6401
|
this.activeRole = handOffTarget;
|
|
6257
6402
|
const newSession = this.getActiveSession();
|
|
6258
|
-
if (
|
|
6403
|
+
if (handoffContent) {
|
|
6259
6404
|
newSession.messages.push({
|
|
6260
6405
|
role: "system",
|
|
6261
|
-
content:
|
|
6262
|
-
${summary}`
|
|
6406
|
+
content: handoffContent
|
|
6263
6407
|
});
|
|
6264
6408
|
}
|
|
6409
|
+
newSession.messages.push(userMessage);
|
|
6265
6410
|
this.turnCounts.set(handOffTarget, 0);
|
|
6411
|
+
const targetTools = this.getToolsForRole(this.activeRole);
|
|
6412
|
+
const targetCustomAgent = this.opts.customAgents?.find((a) => a.name === this.activeRole);
|
|
6413
|
+
const targetConfig = this.resolveAgentConfig(this.activeRole);
|
|
6414
|
+
const targetModel = targetCustomAgent?.model ?? targetConfig.model ?? this.opts.model;
|
|
6415
|
+
const targetReasoning = targetCustomAgent?.reasoningEffort ?? targetConfig.reasoningEffort ?? this.opts.reasoningEffort;
|
|
6416
|
+
if (targetCustomAgent?.systemPrompt && !newSession.messages.some((m) => m.role === "system" && m.content === targetCustomAgent.systemPrompt)) {
|
|
6417
|
+
newSession.messages.unshift({
|
|
6418
|
+
role: "system",
|
|
6419
|
+
content: targetCustomAgent.systemPrompt
|
|
6420
|
+
});
|
|
6421
|
+
}
|
|
6422
|
+
await runAgentTurn({
|
|
6423
|
+
accountId: this.opts.accountId,
|
|
6424
|
+
apiToken: this.opts.apiToken,
|
|
6425
|
+
model: targetModel,
|
|
6426
|
+
gateway: this.opts.gateway,
|
|
6427
|
+
messages: newSession.messages,
|
|
6428
|
+
tools: [...targetTools, ...this.opts.mcpTools],
|
|
6429
|
+
executor: this.opts.executor,
|
|
6430
|
+
cwd: this.opts.cwd,
|
|
6431
|
+
signal: this.opts.signal,
|
|
6432
|
+
reasoningEffort: targetReasoning,
|
|
6433
|
+
coauthor: this.opts.coauthor,
|
|
6434
|
+
sessionId: this.opts.sessionId,
|
|
6435
|
+
memoryManager: this.opts.memoryManager,
|
|
6436
|
+
keepLastImageTurns: this.opts.keepLastImageTurns,
|
|
6437
|
+
codeMode: this.opts.codeMode,
|
|
6438
|
+
onFileChange: this.opts.onFileChange,
|
|
6439
|
+
callbacks: this.opts.callbacks,
|
|
6440
|
+
recentToolCalls: newSession.recentToolCalls,
|
|
6441
|
+
agentRole: this.activeRole
|
|
6442
|
+
});
|
|
6443
|
+
newSession.recentToolCalls = newSession.recentToolCalls.slice(-8);
|
|
6444
|
+
}
|
|
6445
|
+
if (!handOffTarget && this.activeRole !== "generalist") {
|
|
6446
|
+
const deliverable = this.extractDeliverable(session);
|
|
6447
|
+
if (deliverable && deliverable.length >= 300) {
|
|
6448
|
+
const fromRole = this.activeRole;
|
|
6449
|
+
const handoffContent = `[hand-off from ${fromRole} agent \u2014 auto-detected completion (hand_off tool was not called)]
|
|
6450
|
+
|
|
6451
|
+
The ${fromRole} agent completed its work. Here is their full deliverable:
|
|
6452
|
+
|
|
6453
|
+
${deliverable}`;
|
|
6454
|
+
this.activeRole = "generalist";
|
|
6455
|
+
const newSession = this.getActiveSession();
|
|
6456
|
+
newSession.messages.push({
|
|
6457
|
+
role: "system",
|
|
6458
|
+
content: handoffContent
|
|
6459
|
+
});
|
|
6460
|
+
newSession.messages.push(userMessage);
|
|
6461
|
+
this.turnCounts.set("generalist", 0);
|
|
6462
|
+
const targetTools = this.getToolsForRole(this.activeRole);
|
|
6463
|
+
const targetCustomAgent = this.opts.customAgents?.find((a) => a.name === this.activeRole);
|
|
6464
|
+
const targetConfig = this.resolveAgentConfig(this.activeRole);
|
|
6465
|
+
const targetModel = targetCustomAgent?.model ?? targetConfig.model ?? this.opts.model;
|
|
6466
|
+
const targetReasoning = targetCustomAgent?.reasoningEffort ?? targetConfig.reasoningEffort ?? this.opts.reasoningEffort;
|
|
6467
|
+
if (targetCustomAgent?.systemPrompt && !newSession.messages.some((m) => m.role === "system" && m.content === targetCustomAgent.systemPrompt)) {
|
|
6468
|
+
newSession.messages.unshift({
|
|
6469
|
+
role: "system",
|
|
6470
|
+
content: targetCustomAgent.systemPrompt
|
|
6471
|
+
});
|
|
6472
|
+
}
|
|
6473
|
+
await runAgentTurn({
|
|
6474
|
+
accountId: this.opts.accountId,
|
|
6475
|
+
apiToken: this.opts.apiToken,
|
|
6476
|
+
model: targetModel,
|
|
6477
|
+
gateway: this.opts.gateway,
|
|
6478
|
+
messages: newSession.messages,
|
|
6479
|
+
tools: [...targetTools, ...this.opts.mcpTools],
|
|
6480
|
+
executor: this.opts.executor,
|
|
6481
|
+
cwd: this.opts.cwd,
|
|
6482
|
+
signal: this.opts.signal,
|
|
6483
|
+
reasoningEffort: targetReasoning,
|
|
6484
|
+
coauthor: this.opts.coauthor,
|
|
6485
|
+
sessionId: this.opts.sessionId,
|
|
6486
|
+
memoryManager: this.opts.memoryManager,
|
|
6487
|
+
keepLastImageTurns: this.opts.keepLastImageTurns,
|
|
6488
|
+
codeMode: this.opts.codeMode,
|
|
6489
|
+
onFileChange: this.opts.onFileChange,
|
|
6490
|
+
callbacks: this.opts.callbacks,
|
|
6491
|
+
recentToolCalls: newSession.recentToolCalls,
|
|
6492
|
+
agentRole: this.activeRole
|
|
6493
|
+
});
|
|
6494
|
+
newSession.recentToolCalls = newSession.recentToolCalls.slice(-8);
|
|
6495
|
+
}
|
|
6266
6496
|
}
|
|
6267
6497
|
this.turnCounts.set(this.activeRole, (this.turnCounts.get(this.activeRole) ?? 0) + 1);
|
|
6268
6498
|
}
|
|
@@ -10404,6 +10634,45 @@ var init_renderer2 = __esm({
|
|
|
10404
10634
|
}
|
|
10405
10635
|
});
|
|
10406
10636
|
|
|
10637
|
+
// src/commands/builtins.ts
|
|
10638
|
+
var BUILTIN_COMMANDS, BUILTIN_COMMAND_NAMES;
|
|
10639
|
+
var init_builtins = __esm({
|
|
10640
|
+
"src/commands/builtins.ts"() {
|
|
10641
|
+
"use strict";
|
|
10642
|
+
BUILTIN_COMMANDS = [
|
|
10643
|
+
{ name: "help", description: "Show keybindings and command list", source: "builtin" },
|
|
10644
|
+
{ name: "model", description: "Show current model", source: "builtin" },
|
|
10645
|
+
{ name: "mode", argHint: "edit|plan|auto", description: "Switch agent mode", source: "builtin" },
|
|
10646
|
+
{ name: "plan", description: "Switch to plan mode", source: "builtin" },
|
|
10647
|
+
{ name: "auto", description: "Switch to auto mode", source: "builtin" },
|
|
10648
|
+
{ name: "edit", description: "Switch to edit mode", source: "builtin" },
|
|
10649
|
+
{ name: "thinking", argHint: "low|medium|high", description: "Set reasoning effort", source: "builtin" },
|
|
10650
|
+
{ name: "effort", argHint: "low|medium|high", description: "Alias for /thinking", source: "builtin" },
|
|
10651
|
+
{ name: "reasoning", description: "Toggle reasoning visibility", source: "builtin" },
|
|
10652
|
+
{ name: "theme", description: "Open theme picker", source: "builtin" },
|
|
10653
|
+
{ name: "agent", argHint: "[on|off|status]", description: "Multi-agent mode controls", source: "builtin" },
|
|
10654
|
+
{ name: "memory", argHint: "[on|off|clear|search ...]", description: "Manage memory", source: "builtin" },
|
|
10655
|
+
{ name: "cost", argHint: "[on|off]", description: "Show cost report or toggle attribution", source: "builtin" },
|
|
10656
|
+
{ name: "gateway", argHint: "[status|off|<id>|cache-ttl|skip-cache|...]", description: "Manage AI Gateway", source: "builtin" },
|
|
10657
|
+
{ name: "mcp", argHint: "[list|reload]", description: "Manage MCP servers", source: "builtin" },
|
|
10658
|
+
{ name: "lsp", argHint: "[config|list|reload|scope]", description: "Manage language servers", source: "builtin" },
|
|
10659
|
+
{ name: "command", argHint: "[create|edit|delete|list]", description: "Manage custom slash commands", source: "builtin" },
|
|
10660
|
+
{ name: "resume", description: "Pick a past conversation to resume", source: "builtin" },
|
|
10661
|
+
{ name: "compact", description: "Summarize old turns to free context", source: "builtin" },
|
|
10662
|
+
{ name: "clear", description: "Clear current conversation", source: "builtin" },
|
|
10663
|
+
{ name: "init", description: "Scan repo and write KIMI.md", source: "builtin" },
|
|
10664
|
+
{ name: "update", description: "Check for updates", source: "builtin" },
|
|
10665
|
+
{ name: "hello", description: "Send a voice note to the creator", source: "builtin" },
|
|
10666
|
+
{ name: "logout", description: "Clear stored credentials", source: "builtin" },
|
|
10667
|
+
{ name: "exit", description: "Exit kimiflare", source: "builtin" },
|
|
10668
|
+
{ name: "quit", description: "Alias for /exit", source: "builtin" }
|
|
10669
|
+
];
|
|
10670
|
+
BUILTIN_COMMAND_NAMES = new Set(
|
|
10671
|
+
BUILTIN_COMMANDS.map((c) => c.name.toLowerCase())
|
|
10672
|
+
);
|
|
10673
|
+
}
|
|
10674
|
+
});
|
|
10675
|
+
|
|
10407
10676
|
// src/commands/save.ts
|
|
10408
10677
|
import { mkdir as mkdir9, writeFile as writeFile9, unlink as unlink2 } from "fs/promises";
|
|
10409
10678
|
import { dirname as dirname6 } from "path";
|
|
@@ -11565,6 +11834,125 @@ var init_file_picker = __esm({
|
|
|
11565
11834
|
}
|
|
11566
11835
|
});
|
|
11567
11836
|
|
|
11837
|
+
// src/ui/slash-picker.tsx
|
|
11838
|
+
import { Box as Box18, Text as Text19 } from "ink";
|
|
11839
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
11840
|
+
function sourceBadge(source) {
|
|
11841
|
+
if (source === "builtin") return "";
|
|
11842
|
+
if (source === "project") return "project";
|
|
11843
|
+
return "global";
|
|
11844
|
+
}
|
|
11845
|
+
function commandLabel(item) {
|
|
11846
|
+
return `/${item.name}${item.argHint ? ` ${item.argHint}` : ""}`;
|
|
11847
|
+
}
|
|
11848
|
+
function SlashPicker({ items, selectedIndex, theme, query }) {
|
|
11849
|
+
let startIndex = 0;
|
|
11850
|
+
if (selectedIndex >= VISIBLE_LIMIT2) {
|
|
11851
|
+
startIndex = selectedIndex - VISIBLE_LIMIT2 + 1;
|
|
11852
|
+
}
|
|
11853
|
+
const visible = items.slice(startIndex, startIndex + VISIBLE_LIMIT2);
|
|
11854
|
+
const hasMoreAbove = startIndex > 0;
|
|
11855
|
+
const hasMoreBelow = items.length > startIndex + VISIBLE_LIMIT2;
|
|
11856
|
+
const longestLabel = visible.reduce((m, it) => Math.max(m, commandLabel(it).length), 0);
|
|
11857
|
+
const nameColWidth = Math.max(NAME_COL_MIN_WIDTH, longestLabel + NAME_DESC_GAP);
|
|
11858
|
+
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
11859
|
+
/* @__PURE__ */ jsx19(Text19, { color: theme.accent, bold: true, children: query ? `Commands matching "/${query}"` : "Slash commands" }),
|
|
11860
|
+
/* @__PURE__ */ jsx19(Text19, { color: theme.info.color, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
|
|
11861
|
+
/* @__PURE__ */ jsxs18(Box18, { marginTop: 1, flexDirection: "column", children: [
|
|
11862
|
+
visible.length === 0 && /* @__PURE__ */ jsx19(Text19, { color: theme.info.color, dimColor: true, children: "No matches" }),
|
|
11863
|
+
hasMoreAbove && /* @__PURE__ */ jsxs18(Text19, { color: theme.info.color, dimColor: true, children: [
|
|
11864
|
+
"\u2026 ",
|
|
11865
|
+
startIndex,
|
|
11866
|
+
" more above"
|
|
11867
|
+
] }),
|
|
11868
|
+
visible.map((item, i) => {
|
|
11869
|
+
const actualIndex = startIndex + i;
|
|
11870
|
+
const isSelected = actualIndex === selectedIndex;
|
|
11871
|
+
const nameCol = commandLabel(item).padEnd(nameColWidth);
|
|
11872
|
+
const badge = sourceBadge(item.source);
|
|
11873
|
+
return /* @__PURE__ */ jsxs18(Text19, { color: isSelected ? theme.accent : void 0, bold: isSelected, children: [
|
|
11874
|
+
isSelected ? "\u203A " : " ",
|
|
11875
|
+
nameCol,
|
|
11876
|
+
/* @__PURE__ */ jsxs18(Text19, { color: theme.info.color, dimColor: true, children: [
|
|
11877
|
+
item.description,
|
|
11878
|
+
badge && ` [${badge}]`
|
|
11879
|
+
] })
|
|
11880
|
+
] }, item.name);
|
|
11881
|
+
}),
|
|
11882
|
+
hasMoreBelow && /* @__PURE__ */ jsxs18(Text19, { color: theme.info.color, dimColor: true, children: [
|
|
11883
|
+
"\u2026 ",
|
|
11884
|
+
items.length - (startIndex + VISIBLE_LIMIT2),
|
|
11885
|
+
" more below"
|
|
11886
|
+
] })
|
|
11887
|
+
] })
|
|
11888
|
+
] });
|
|
11889
|
+
}
|
|
11890
|
+
var VISIBLE_LIMIT2, NAME_COL_MIN_WIDTH, NAME_DESC_GAP;
|
|
11891
|
+
var init_slash_picker = __esm({
|
|
11892
|
+
"src/ui/slash-picker.tsx"() {
|
|
11893
|
+
"use strict";
|
|
11894
|
+
VISIBLE_LIMIT2 = 7;
|
|
11895
|
+
NAME_COL_MIN_WIDTH = 18;
|
|
11896
|
+
NAME_DESC_GAP = 2;
|
|
11897
|
+
}
|
|
11898
|
+
});
|
|
11899
|
+
|
|
11900
|
+
// src/util/fuzzy.ts
|
|
11901
|
+
function fuzzyMatch(query, text) {
|
|
11902
|
+
const q = query.toLowerCase();
|
|
11903
|
+
const t = text.toLowerCase();
|
|
11904
|
+
if (q.length === 0) return { matches: true, score: 0 };
|
|
11905
|
+
if (q.length > t.length) return { matches: false, score: 0 };
|
|
11906
|
+
let qi = 0;
|
|
11907
|
+
let score = 0;
|
|
11908
|
+
let lastMatch = -1;
|
|
11909
|
+
let consecutive = 0;
|
|
11910
|
+
for (let i = 0; i < t.length && qi < q.length; i++) {
|
|
11911
|
+
if (t[i] !== q[qi]) continue;
|
|
11912
|
+
const isWordBoundary = i === 0 || /[\s\-_./:]/.test(t[i - 1]);
|
|
11913
|
+
if (lastMatch === i - 1) {
|
|
11914
|
+
consecutive++;
|
|
11915
|
+
score -= consecutive * 5;
|
|
11916
|
+
} else {
|
|
11917
|
+
consecutive = 0;
|
|
11918
|
+
if (lastMatch >= 0) score += (i - lastMatch - 1) * 2;
|
|
11919
|
+
}
|
|
11920
|
+
if (isWordBoundary) score -= 10;
|
|
11921
|
+
score += i * 0.1;
|
|
11922
|
+
lastMatch = i;
|
|
11923
|
+
qi++;
|
|
11924
|
+
}
|
|
11925
|
+
if (qi < q.length) return { matches: false, score: 0 };
|
|
11926
|
+
return { matches: true, score };
|
|
11927
|
+
}
|
|
11928
|
+
function fuzzyFilter(items, query, getText) {
|
|
11929
|
+
const trimmed = query.trim();
|
|
11930
|
+
if (trimmed.length === 0) return items;
|
|
11931
|
+
const tokens = trimmed.split(/\s+/);
|
|
11932
|
+
const scored = [];
|
|
11933
|
+
for (const item of items) {
|
|
11934
|
+
const text = getText(item);
|
|
11935
|
+
let total = 0;
|
|
11936
|
+
let allMatch = true;
|
|
11937
|
+
for (const token of tokens) {
|
|
11938
|
+
const m = fuzzyMatch(token, text);
|
|
11939
|
+
if (!m.matches) {
|
|
11940
|
+
allMatch = false;
|
|
11941
|
+
break;
|
|
11942
|
+
}
|
|
11943
|
+
total += m.score;
|
|
11944
|
+
}
|
|
11945
|
+
if (allMatch) scored.push({ item, score: total });
|
|
11946
|
+
}
|
|
11947
|
+
scored.sort((a, b) => a.score - b.score);
|
|
11948
|
+
return scored.map((s) => s.item);
|
|
11949
|
+
}
|
|
11950
|
+
var init_fuzzy = __esm({
|
|
11951
|
+
"src/util/fuzzy.ts"() {
|
|
11952
|
+
"use strict";
|
|
11953
|
+
}
|
|
11954
|
+
});
|
|
11955
|
+
|
|
11568
11956
|
// src/cost-attribution/tui-report.ts
|
|
11569
11957
|
var tui_report_exports = {};
|
|
11570
11958
|
__export(tui_report_exports, {
|
|
@@ -11657,11 +12045,13 @@ var app_exports = {};
|
|
|
11657
12045
|
__export(app_exports, {
|
|
11658
12046
|
buildFilePickerIgnoreList: () => buildFilePickerIgnoreList,
|
|
11659
12047
|
filterPickerItems: () => filterPickerItems,
|
|
12048
|
+
insertSlashCommand: () => insertSlashCommand,
|
|
11660
12049
|
renderApp: () => renderApp,
|
|
11661
|
-
shouldOpenMentionPicker: () => shouldOpenMentionPicker
|
|
12050
|
+
shouldOpenMentionPicker: () => shouldOpenMentionPicker,
|
|
12051
|
+
shouldOpenSlashPicker: () => shouldOpenSlashPicker
|
|
11662
12052
|
});
|
|
11663
12053
|
import React12, { useState as useState9, useRef as useRef3, useEffect as useEffect4, useCallback } from "react";
|
|
11664
|
-
import { Box as
|
|
12054
|
+
import { Box as Box19, Text as Text20, useApp, useInput as useInput5, render } from "ink";
|
|
11665
12055
|
import SelectInput8 from "ink-select-input";
|
|
11666
12056
|
import { existsSync as existsSync2, statSync as statSync3 } from "fs";
|
|
11667
12057
|
import { join as join17 } from "path";
|
|
@@ -11670,7 +12060,7 @@ import { spawn as spawn4 } from "child_process";
|
|
|
11670
12060
|
import { platform as platform2 } from "os";
|
|
11671
12061
|
import fg4 from "fast-glob";
|
|
11672
12062
|
import { readFileSync as readFileSync3 } from "fs";
|
|
11673
|
-
import { jsx as
|
|
12063
|
+
import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
11674
12064
|
function buildFilePickerIgnoreList(cwd) {
|
|
11675
12065
|
const hardcoded = [
|
|
11676
12066
|
// Dependencies
|
|
@@ -11779,6 +12169,18 @@ function shouldOpenMentionPicker(input, cursorOffset, pickerCancelOffset) {
|
|
|
11779
12169
|
}
|
|
11780
12170
|
return false;
|
|
11781
12171
|
}
|
|
12172
|
+
function shouldOpenSlashPicker(input, cursorOffset, cancelOffset) {
|
|
12173
|
+
if (cancelOffset === cursorOffset) return false;
|
|
12174
|
+
if (cursorOffset === 0 || input[cursorOffset - 1] !== "/") return false;
|
|
12175
|
+
return /^\s*$/.test(input.slice(0, cursorOffset - 1));
|
|
12176
|
+
}
|
|
12177
|
+
function insertSlashCommand(input, anchor, name) {
|
|
12178
|
+
let tokenEnd = anchor + 1;
|
|
12179
|
+
while (tokenEnd < input.length && !/\s/.test(input[tokenEnd])) tokenEnd++;
|
|
12180
|
+
const head = input.slice(0, anchor + 1) + name;
|
|
12181
|
+
const tail = " " + input.slice(tokenEnd).replace(/^\s+/, "");
|
|
12182
|
+
return { value: head + tail, cursor: head.length + 1 };
|
|
12183
|
+
}
|
|
11782
12184
|
function gatewayFromConfig(cfg) {
|
|
11783
12185
|
if (!cfg.aiGatewayId) return void 0;
|
|
11784
12186
|
return {
|
|
@@ -11913,9 +12315,10 @@ function App({
|
|
|
11913
12315
|
const [hasUpdate, setHasUpdate] = useState9(initialUpdateResult?.hasUpdate ?? false);
|
|
11914
12316
|
const [latestVersion, setLatestVersion] = useState9(initialUpdateResult?.latestVersion ?? null);
|
|
11915
12317
|
const [cursorOffset, setCursorOffset] = useState9(0);
|
|
11916
|
-
const [
|
|
11917
|
-
const [
|
|
11918
|
-
const
|
|
12318
|
+
const [activePicker, setActivePicker] = useState9(null);
|
|
12319
|
+
const [filePickerItems, setFilePickerItems] = useState9([]);
|
|
12320
|
+
const filePickerLoadedRef = useRef3(false);
|
|
12321
|
+
const [customCommandsVersion, setCustomCommandsVersion] = useState9(0);
|
|
11919
12322
|
const cacheStableRef = useRef3(initialCfg?.cacheStablePrompts !== false);
|
|
11920
12323
|
const messagesRef = useRef3(
|
|
11921
12324
|
makePrefixMessages(cacheStableRef.current, cfg?.model ?? DEFAULT_MODEL, "edit", ALL_TOOLS)
|
|
@@ -11951,28 +12354,42 @@ function App({
|
|
|
11951
12354
|
const flushTimeoutRef = useRef3(null);
|
|
11952
12355
|
const customCommandsRef = useRef3([]);
|
|
11953
12356
|
const pickerCancelRef = useRef3(null);
|
|
11954
|
-
const
|
|
12357
|
+
const pickerAnchor = activePicker?.anchor ?? null;
|
|
12358
|
+
const pickerKind = activePicker?.kind ?? null;
|
|
12359
|
+
const pickerQuery = React12.useMemo(() => {
|
|
11955
12360
|
if (pickerAnchor === null) return null;
|
|
11956
|
-
|
|
11957
|
-
return { query, anchor: pickerAnchor };
|
|
12361
|
+
return input.slice(pickerAnchor + 1, cursorOffset);
|
|
11958
12362
|
}, [input, cursorOffset, pickerAnchor]);
|
|
11959
|
-
const
|
|
11960
|
-
if (
|
|
11961
|
-
return filterPickerItems(
|
|
11962
|
-
}, [
|
|
12363
|
+
const filteredFileItems = React12.useMemo(() => {
|
|
12364
|
+
if (pickerKind !== "file" || pickerQuery === null) return [];
|
|
12365
|
+
return filterPickerItems(filePickerItems, pickerQuery);
|
|
12366
|
+
}, [pickerKind, filePickerItems, pickerQuery]);
|
|
12367
|
+
const allSlashCommands = React12.useMemo(() => {
|
|
12368
|
+
const customs = customCommandsRef.current.filter((c) => !BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase())).map((c) => ({
|
|
12369
|
+
name: c.name,
|
|
12370
|
+
description: c.description ?? "",
|
|
12371
|
+
source: c.source
|
|
12372
|
+
}));
|
|
12373
|
+
return [...BUILTIN_COMMANDS, ...customs];
|
|
12374
|
+
}, [customCommandsVersion]);
|
|
12375
|
+
const filteredSlashItems = React12.useMemo(() => {
|
|
12376
|
+
if (pickerKind !== "slash" || pickerQuery === null) return [];
|
|
12377
|
+
return fuzzyFilter(allSlashCommands, pickerQuery, (c) => c.name).slice(0, 50);
|
|
12378
|
+
}, [pickerKind, allSlashCommands, pickerQuery]);
|
|
11963
12379
|
useEffect4(() => {
|
|
11964
|
-
if (
|
|
11965
|
-
|
|
11966
|
-
|
|
12380
|
+
if (activePicker !== null) {
|
|
12381
|
+
const trigger = activePicker.kind === "file" ? "@" : "/";
|
|
12382
|
+
if (cursorOffset < activePicker.anchor) {
|
|
12383
|
+
setActivePicker(null);
|
|
11967
12384
|
return;
|
|
11968
12385
|
}
|
|
11969
|
-
if (input[
|
|
11970
|
-
|
|
12386
|
+
if (input[activePicker.anchor] !== trigger) {
|
|
12387
|
+
setActivePicker(null);
|
|
11971
12388
|
return;
|
|
11972
12389
|
}
|
|
11973
|
-
const query = input.slice(
|
|
11974
|
-
if (query
|
|
11975
|
-
|
|
12390
|
+
const query = input.slice(activePicker.anchor + 1, cursorOffset);
|
|
12391
|
+
if (/\s/.test(query)) {
|
|
12392
|
+
setActivePicker(null);
|
|
11976
12393
|
return;
|
|
11977
12394
|
}
|
|
11978
12395
|
return;
|
|
@@ -11982,9 +12399,9 @@ function App({
|
|
|
11982
12399
|
return;
|
|
11983
12400
|
}
|
|
11984
12401
|
if (filePickerEnabled && shouldOpenMentionPicker(input, cursorOffset, pickerCancelRef.current)) {
|
|
11985
|
-
|
|
11986
|
-
|
|
11987
|
-
|
|
12402
|
+
setActivePicker({ kind: "file", anchor: cursorOffset - 1, selected: 0 });
|
|
12403
|
+
if (!filePickerLoadedRef.current) {
|
|
12404
|
+
filePickerLoadedRef.current = true;
|
|
11988
12405
|
const cwd = process.cwd();
|
|
11989
12406
|
void fg4("**/*", {
|
|
11990
12407
|
cwd,
|
|
@@ -12004,38 +12421,87 @@ function App({
|
|
|
12004
12421
|
if (!a.isDirectory && b.isDirectory) return 1;
|
|
12005
12422
|
return a.name.localeCompare(b.name);
|
|
12006
12423
|
});
|
|
12007
|
-
|
|
12424
|
+
setFilePickerItems(items);
|
|
12008
12425
|
}).catch(() => {
|
|
12009
|
-
|
|
12426
|
+
setFilePickerItems([]);
|
|
12010
12427
|
});
|
|
12011
12428
|
}
|
|
12429
|
+
return;
|
|
12430
|
+
}
|
|
12431
|
+
if (shouldOpenSlashPicker(input, cursorOffset, pickerCancelRef.current)) {
|
|
12432
|
+
setActivePicker({ kind: "slash", anchor: cursorOffset - 1, selected: 0 });
|
|
12433
|
+
return;
|
|
12012
12434
|
}
|
|
12013
|
-
}, [input, cursorOffset,
|
|
12435
|
+
}, [input, cursorOffset, activePicker, filePickerEnabled]);
|
|
12014
12436
|
useEffect4(() => {
|
|
12015
|
-
if (
|
|
12016
|
-
|
|
12437
|
+
if (activePicker?.kind !== "file") return;
|
|
12438
|
+
const max = Math.max(0, filteredFileItems.length - 1);
|
|
12439
|
+
if (activePicker.selected > max) {
|
|
12440
|
+
setActivePicker({ ...activePicker, selected: max });
|
|
12017
12441
|
}
|
|
12018
|
-
}, [
|
|
12442
|
+
}, [filteredFileItems.length, activePicker]);
|
|
12443
|
+
useEffect4(() => {
|
|
12444
|
+
if (activePicker?.kind !== "slash") return;
|
|
12445
|
+
const max = Math.max(0, filteredSlashItems.length - 1);
|
|
12446
|
+
if (activePicker.selected > max) {
|
|
12447
|
+
setActivePicker({ ...activePicker, selected: max });
|
|
12448
|
+
}
|
|
12449
|
+
}, [filteredSlashItems.length, activePicker]);
|
|
12019
12450
|
const handlePickerUp = useCallback(() => {
|
|
12020
|
-
|
|
12451
|
+
setActivePicker((p) => {
|
|
12452
|
+
if (!p) return null;
|
|
12453
|
+
const next = Math.max(0, p.selected - 1);
|
|
12454
|
+
return next === p.selected ? p : { ...p, selected: next };
|
|
12455
|
+
});
|
|
12021
12456
|
}, []);
|
|
12022
12457
|
const handlePickerDown = useCallback(() => {
|
|
12023
|
-
|
|
12024
|
-
|
|
12458
|
+
setActivePicker((p) => {
|
|
12459
|
+
if (!p) return null;
|
|
12460
|
+
const max = p.kind === "file" ? Math.max(0, filteredFileItems.length - 1) : Math.max(0, filteredSlashItems.length - 1);
|
|
12461
|
+
const next = Math.min(max, p.selected + 1);
|
|
12462
|
+
return next === p.selected ? p : { ...p, selected: next };
|
|
12463
|
+
});
|
|
12464
|
+
}, [filteredFileItems.length, filteredSlashItems.length]);
|
|
12025
12465
|
const handlePickerSelect = useCallback(() => {
|
|
12026
|
-
if (!
|
|
12027
|
-
|
|
12466
|
+
if (!activePicker) return;
|
|
12467
|
+
if (activePicker.kind === "file") {
|
|
12468
|
+
const item2 = filteredFileItems[activePicker.selected];
|
|
12469
|
+
if (!item2) return;
|
|
12470
|
+
const insert = item2.name + (item2.isDirectory ? "/" : " ");
|
|
12471
|
+
const newInput = input.slice(0, activePicker.anchor) + insert + input.slice(cursorOffset);
|
|
12472
|
+
setInput(newInput);
|
|
12473
|
+
setCursorOffset(activePicker.anchor + insert.length);
|
|
12474
|
+
setActivePicker(null);
|
|
12475
|
+
return;
|
|
12476
|
+
}
|
|
12477
|
+
const item = filteredSlashItems[activePicker.selected];
|
|
12028
12478
|
if (!item) return;
|
|
12029
|
-
const
|
|
12030
|
-
|
|
12031
|
-
|
|
12032
|
-
|
|
12033
|
-
|
|
12034
|
-
}, [mentionState, filteredPickerItems, pickerSelected, input, cursorOffset]);
|
|
12479
|
+
const { value, cursor } = insertSlashCommand(input, activePicker.anchor, item.name);
|
|
12480
|
+
setInput(value);
|
|
12481
|
+
setCursorOffset(cursor);
|
|
12482
|
+
setActivePicker(null);
|
|
12483
|
+
}, [activePicker, filteredFileItems, filteredSlashItems, input, cursorOffset]);
|
|
12035
12484
|
const handlePickerCancel = useCallback(() => {
|
|
12036
12485
|
pickerCancelRef.current = cursorOffset;
|
|
12037
|
-
|
|
12486
|
+
setActivePicker(null);
|
|
12038
12487
|
}, [cursorOffset]);
|
|
12488
|
+
useEffect4(() => {
|
|
12489
|
+
const modalActive = showThemePicker || showHelpMenu || commandWizard !== null || commandPicker !== null || commandToDelete !== null || showCommandList || showLspWizard || resumeSessions !== null || perm !== null;
|
|
12490
|
+
if (modalActive && activePicker !== null) {
|
|
12491
|
+
setActivePicker(null);
|
|
12492
|
+
}
|
|
12493
|
+
}, [
|
|
12494
|
+
showThemePicker,
|
|
12495
|
+
showHelpMenu,
|
|
12496
|
+
commandWizard,
|
|
12497
|
+
commandPicker,
|
|
12498
|
+
commandToDelete,
|
|
12499
|
+
showCommandList,
|
|
12500
|
+
showLspWizard,
|
|
12501
|
+
resumeSessions,
|
|
12502
|
+
perm,
|
|
12503
|
+
activePicker
|
|
12504
|
+
]);
|
|
12039
12505
|
useEffect4(() => {
|
|
12040
12506
|
if (!cfg) return;
|
|
12041
12507
|
void Promise.resolve().then(() => (init_sessions(), sessions_exports)).then(
|
|
@@ -12116,6 +12582,7 @@ function App({
|
|
|
12116
12582
|
}
|
|
12117
12583
|
void loadCustomCommands(process.cwd()).then(({ commands, warnings }) => {
|
|
12118
12584
|
customCommandsRef.current = commands;
|
|
12585
|
+
setCustomCommandsVersion((v) => v + 1);
|
|
12119
12586
|
for (const w of warnings) {
|
|
12120
12587
|
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: `commands: ${w}` }]);
|
|
12121
12588
|
}
|
|
@@ -12141,6 +12608,7 @@ function App({
|
|
|
12141
12608
|
const reloadCustomCommands = useCallback(async () => {
|
|
12142
12609
|
const { commands, warnings } = await loadCustomCommands(process.cwd());
|
|
12143
12610
|
customCommandsRef.current = commands;
|
|
12611
|
+
setCustomCommandsVersion((v) => v + 1);
|
|
12144
12612
|
for (const w of warnings) {
|
|
12145
12613
|
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: `commands: ${w}` }]);
|
|
12146
12614
|
}
|
|
@@ -14077,7 +14545,7 @@ ${lines.join("\n")}` }]);
|
|
|
14077
14545
|
}
|
|
14078
14546
|
}, [usage]);
|
|
14079
14547
|
if (!cfg) {
|
|
14080
|
-
return /* @__PURE__ */
|
|
14548
|
+
return /* @__PURE__ */ jsx20(
|
|
14081
14549
|
Onboarding,
|
|
14082
14550
|
{
|
|
14083
14551
|
onDone: (newCfg) => {
|
|
@@ -14091,13 +14559,13 @@ ${lines.join("\n")}` }]);
|
|
|
14091
14559
|
);
|
|
14092
14560
|
}
|
|
14093
14561
|
if (resumeSessions !== null) {
|
|
14094
|
-
return /* @__PURE__ */
|
|
14562
|
+
return /* @__PURE__ */ jsx20(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsx20(ResumePicker, { sessions: resumeSessions, onPick: handleResumePick, theme }) });
|
|
14095
14563
|
}
|
|
14096
14564
|
if (showThemePicker) {
|
|
14097
|
-
return /* @__PURE__ */
|
|
14565
|
+
return /* @__PURE__ */ jsx20(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsx20(ThemePicker, { themes: themeList(), current: theme, onPick: handleThemePick, onPreview: (t) => setTheme(t) }) });
|
|
14098
14566
|
}
|
|
14099
14567
|
if (showHelpMenu) {
|
|
14100
|
-
return /* @__PURE__ */
|
|
14568
|
+
return /* @__PURE__ */ jsx20(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsx20(
|
|
14101
14569
|
HelpMenu,
|
|
14102
14570
|
{
|
|
14103
14571
|
theme,
|
|
@@ -14112,7 +14580,7 @@ ${lines.join("\n")}` }]);
|
|
|
14112
14580
|
) });
|
|
14113
14581
|
}
|
|
14114
14582
|
if (showLspWizard) {
|
|
14115
|
-
return /* @__PURE__ */
|
|
14583
|
+
return /* @__PURE__ */ jsx20(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsx20(
|
|
14116
14584
|
LspWizard,
|
|
14117
14585
|
{
|
|
14118
14586
|
theme,
|
|
@@ -14150,7 +14618,7 @@ ${lines.join("\n")}` }]);
|
|
|
14150
14618
|
) });
|
|
14151
14619
|
}
|
|
14152
14620
|
if (commandWizard) {
|
|
14153
|
-
return /* @__PURE__ */
|
|
14621
|
+
return /* @__PURE__ */ jsx20(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsx20(
|
|
14154
14622
|
CommandWizard,
|
|
14155
14623
|
{
|
|
14156
14624
|
theme,
|
|
@@ -14164,7 +14632,7 @@ ${lines.join("\n")}` }]);
|
|
|
14164
14632
|
) });
|
|
14165
14633
|
}
|
|
14166
14634
|
if (commandPicker) {
|
|
14167
|
-
return /* @__PURE__ */
|
|
14635
|
+
return /* @__PURE__ */ jsx20(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsx20(
|
|
14168
14636
|
CommandPicker,
|
|
14169
14637
|
{
|
|
14170
14638
|
theme,
|
|
@@ -14183,14 +14651,14 @@ ${lines.join("\n")}` }]);
|
|
|
14183
14651
|
) });
|
|
14184
14652
|
}
|
|
14185
14653
|
if (commandToDelete) {
|
|
14186
|
-
return /* @__PURE__ */
|
|
14187
|
-
/* @__PURE__ */
|
|
14654
|
+
return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
14655
|
+
/* @__PURE__ */ jsxs19(Text20, { color: theme.accent, bold: true, children: [
|
|
14188
14656
|
"Delete /",
|
|
14189
14657
|
commandToDelete.name,
|
|
14190
14658
|
"?"
|
|
14191
14659
|
] }),
|
|
14192
|
-
/* @__PURE__ */
|
|
14193
|
-
/* @__PURE__ */
|
|
14660
|
+
/* @__PURE__ */ jsx20(Text20, { color: theme.info.color, dimColor: true, children: commandToDelete.filepath }),
|
|
14661
|
+
/* @__PURE__ */ jsx20(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx20(
|
|
14194
14662
|
SelectInput8,
|
|
14195
14663
|
{
|
|
14196
14664
|
items: [
|
|
@@ -14209,7 +14677,7 @@ ${lines.join("\n")}` }]);
|
|
|
14209
14677
|
] });
|
|
14210
14678
|
}
|
|
14211
14679
|
if (showCommandList) {
|
|
14212
|
-
return /* @__PURE__ */
|
|
14680
|
+
return /* @__PURE__ */ jsx20(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsx20(
|
|
14213
14681
|
CommandList,
|
|
14214
14682
|
{
|
|
14215
14683
|
theme,
|
|
@@ -14219,9 +14687,9 @@ ${lines.join("\n")}` }]);
|
|
|
14219
14687
|
) });
|
|
14220
14688
|
}
|
|
14221
14689
|
const hasConversation = events.some((e) => e.kind === "user" || e.kind === "assistant");
|
|
14222
|
-
return /* @__PURE__ */
|
|
14223
|
-
!hasConversation && events.length === 0 ? /* @__PURE__ */
|
|
14224
|
-
perm ? /* @__PURE__ */
|
|
14690
|
+
return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
|
|
14691
|
+
!hasConversation && events.length === 0 ? /* @__PURE__ */ jsx20(Welcome, { theme, accountId: cfg.accountId }) : /* @__PURE__ */ jsx20(ChatView, { events, showReasoning, theme, verbose }),
|
|
14692
|
+
perm ? /* @__PURE__ */ jsx20(
|
|
14225
14693
|
PermissionModal,
|
|
14226
14694
|
{
|
|
14227
14695
|
tool: perm.tool,
|
|
@@ -14233,8 +14701,8 @@ ${lines.join("\n")}` }]);
|
|
|
14233
14701
|
setPerm(null);
|
|
14234
14702
|
}
|
|
14235
14703
|
}
|
|
14236
|
-
) : /* @__PURE__ */
|
|
14237
|
-
tasks.length > 0 && /* @__PURE__ */
|
|
14704
|
+
) : /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, children: [
|
|
14705
|
+
tasks.length > 0 && /* @__PURE__ */ jsx20(
|
|
14238
14706
|
TaskList,
|
|
14239
14707
|
{
|
|
14240
14708
|
tasks,
|
|
@@ -14243,11 +14711,11 @@ ${lines.join("\n")}` }]);
|
|
|
14243
14711
|
tokensDelta: Math.max(0, (usage?.prompt_tokens ?? 0) - tasksStartTokens)
|
|
14244
14712
|
}
|
|
14245
14713
|
),
|
|
14246
|
-
queue.length > 0 && /* @__PURE__ */
|
|
14714
|
+
queue.length > 0 && /* @__PURE__ */ jsx20(Box19, { flexDirection: "column", marginBottom: 1, children: queue.map((q, i) => /* @__PURE__ */ jsxs19(Text20, { color: theme.queue.color, dimColor: theme.queue.dim, children: [
|
|
14247
14715
|
"\u23F3 ",
|
|
14248
14716
|
q.display
|
|
14249
14717
|
] }, `queue_${i}`)) }),
|
|
14250
|
-
/* @__PURE__ */
|
|
14718
|
+
/* @__PURE__ */ jsx20(
|
|
14251
14719
|
StatusBar,
|
|
14252
14720
|
{
|
|
14253
14721
|
model: cfg.model,
|
|
@@ -14265,18 +14733,27 @@ ${lines.join("\n")}` }]);
|
|
|
14265
14733
|
codeMode
|
|
14266
14734
|
}
|
|
14267
14735
|
),
|
|
14268
|
-
|
|
14736
|
+
activePicker?.kind === "file" && /* @__PURE__ */ jsx20(
|
|
14269
14737
|
FilePicker,
|
|
14270
14738
|
{
|
|
14271
|
-
items:
|
|
14272
|
-
selectedIndex:
|
|
14739
|
+
items: filteredFileItems,
|
|
14740
|
+
selectedIndex: activePicker.selected,
|
|
14273
14741
|
theme,
|
|
14274
|
-
query:
|
|
14742
|
+
query: pickerQuery ?? ""
|
|
14275
14743
|
}
|
|
14276
14744
|
),
|
|
14277
|
-
/* @__PURE__ */
|
|
14278
|
-
|
|
14279
|
-
|
|
14745
|
+
activePicker?.kind === "slash" && /* @__PURE__ */ jsx20(
|
|
14746
|
+
SlashPicker,
|
|
14747
|
+
{
|
|
14748
|
+
items: filteredSlashItems,
|
|
14749
|
+
selectedIndex: activePicker.selected,
|
|
14750
|
+
theme,
|
|
14751
|
+
query: pickerQuery ?? ""
|
|
14752
|
+
}
|
|
14753
|
+
),
|
|
14754
|
+
/* @__PURE__ */ jsxs19(Box19, { marginTop: 1, children: [
|
|
14755
|
+
/* @__PURE__ */ jsx20(Text20, { color: theme.accent, children: "\u203A " }),
|
|
14756
|
+
/* @__PURE__ */ jsx20(
|
|
14280
14757
|
CustomTextInput,
|
|
14281
14758
|
{
|
|
14282
14759
|
value: input,
|
|
@@ -14285,7 +14762,7 @@ ${lines.join("\n")}` }]);
|
|
|
14285
14762
|
enablePaste: true,
|
|
14286
14763
|
cursorOffset,
|
|
14287
14764
|
onCursorChange: setCursorOffset,
|
|
14288
|
-
pickerActive:
|
|
14765
|
+
pickerActive: activePicker !== null,
|
|
14289
14766
|
onPickerUp: handlePickerUp,
|
|
14290
14767
|
onPickerDown: handlePickerDown,
|
|
14291
14768
|
onPickerSelect: handlePickerSelect,
|
|
@@ -14333,7 +14810,7 @@ ${lines.join("\n")}` }]);
|
|
|
14333
14810
|
}
|
|
14334
14811
|
async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath = null) {
|
|
14335
14812
|
const instance = render(
|
|
14336
|
-
/* @__PURE__ */
|
|
14813
|
+
/* @__PURE__ */ jsx20(
|
|
14337
14814
|
App,
|
|
14338
14815
|
{
|
|
14339
14816
|
initialCfg: cfg,
|
|
@@ -14348,7 +14825,7 @@ async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath
|
|
|
14348
14825
|
);
|
|
14349
14826
|
await instance.waitUntilExit();
|
|
14350
14827
|
}
|
|
14351
|
-
var MAX_GITIGNORE_SIZE, FEEDBACK_WORKER_URL, CONTEXT_LIMIT, AUTO_COMPACT_SUGGEST_PCT, MAX_EVENTS, nextAssistantId, nextKey, mkKey, MAX_IMAGES_PER_MESSAGE,
|
|
14828
|
+
var MAX_GITIGNORE_SIZE, FEEDBACK_WORKER_URL, CONTEXT_LIMIT, AUTO_COMPACT_SUGGEST_PCT, MAX_EVENTS, nextAssistantId, nextKey, mkKey, MAX_IMAGES_PER_MESSAGE, EFFORT_DESCRIPTIONS;
|
|
14352
14829
|
var init_app = __esm({
|
|
14353
14830
|
"src/app.tsx"() {
|
|
14354
14831
|
"use strict";
|
|
@@ -14387,6 +14864,7 @@ var init_app = __esm({
|
|
|
14387
14864
|
init_version();
|
|
14388
14865
|
init_loader();
|
|
14389
14866
|
init_renderer2();
|
|
14867
|
+
init_builtins();
|
|
14390
14868
|
init_save();
|
|
14391
14869
|
init_command_wizard();
|
|
14392
14870
|
init_command_picker();
|
|
@@ -14395,6 +14873,8 @@ var init_app = __esm({
|
|
|
14395
14873
|
init_lsp_config();
|
|
14396
14874
|
init_lsp_nudge();
|
|
14397
14875
|
init_file_picker();
|
|
14876
|
+
init_slash_picker();
|
|
14877
|
+
init_fuzzy();
|
|
14398
14878
|
MAX_GITIGNORE_SIZE = 1 * 1024 * 1024;
|
|
14399
14879
|
FEEDBACK_WORKER_URL = "https://kimiflare-feedback.sina-b35.workers.dev";
|
|
14400
14880
|
CONTEXT_LIMIT = 262e3;
|
|
@@ -14404,33 +14884,6 @@ var init_app = __esm({
|
|
|
14404
14884
|
nextKey = 1;
|
|
14405
14885
|
mkKey = () => `evt_${nextKey++}`;
|
|
14406
14886
|
MAX_IMAGES_PER_MESSAGE = 10;
|
|
14407
|
-
BUILTIN_COMMAND_NAMES = /* @__PURE__ */ new Set([
|
|
14408
|
-
"exit",
|
|
14409
|
-
"quit",
|
|
14410
|
-
"clear",
|
|
14411
|
-
"reasoning",
|
|
14412
|
-
"cost",
|
|
14413
|
-
"model",
|
|
14414
|
-
"thinking",
|
|
14415
|
-
"effort",
|
|
14416
|
-
"theme",
|
|
14417
|
-
"mode",
|
|
14418
|
-
"plan",
|
|
14419
|
-
"auto",
|
|
14420
|
-
"edit",
|
|
14421
|
-
"resume",
|
|
14422
|
-
"compact",
|
|
14423
|
-
"init",
|
|
14424
|
-
"update",
|
|
14425
|
-
"mcp",
|
|
14426
|
-
"logout",
|
|
14427
|
-
"help",
|
|
14428
|
-
"memory",
|
|
14429
|
-
"gateway",
|
|
14430
|
-
"hello",
|
|
14431
|
-
"community",
|
|
14432
|
-
"agent"
|
|
14433
|
-
]);
|
|
14434
14887
|
EFFORT_DESCRIPTIONS = {
|
|
14435
14888
|
low: "low \u2014 fastest; lightest reasoning. Best for simple Q&A, small edits, quick coordination.",
|
|
14436
14889
|
medium: "medium \u2014 balanced (default). Solid quality on most edits, fast on trivial prompts.",
|