kimiflare 0.39.1 → 0.41.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 +393 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1861,6 +1861,9 @@ var init_code_mode = __esm({
|
|
|
1861
1861
|
});
|
|
1862
1862
|
|
|
1863
1863
|
// src/agent/loop.ts
|
|
1864
|
+
function isHighSignalMemory(memory) {
|
|
1865
|
+
return memory.topicKey === "project_dependencies" || memory.topicKey === "project_tsconfig" || memory.topicKey === "project_entry_point" || memory.category === "instruction" || memory.category === "preference" || memory.category === "event" && memory.importance >= 3;
|
|
1866
|
+
}
|
|
1864
1867
|
async function runAgentTurn(opts2) {
|
|
1865
1868
|
const turnStart = performance.now();
|
|
1866
1869
|
const max = opts2.maxToolIterations ?? 50;
|
|
@@ -2260,6 +2263,15 @@ ${sandboxResult.output}` : `${warningPrefix}${sandboxResult.output}`;
|
|
|
2260
2263
|
void 0,
|
|
2261
2264
|
memory.topicKey
|
|
2262
2265
|
);
|
|
2266
|
+
if (isHighSignalMemory(memory)) {
|
|
2267
|
+
const sid = opts2.sessionId ?? "default";
|
|
2268
|
+
const current = (driftAccumulator.get(sid) ?? 0) + 1;
|
|
2269
|
+
driftAccumulator.set(sid, current);
|
|
2270
|
+
if (current >= DRIFT_THRESHOLD) {
|
|
2271
|
+
opts2.callbacks.onKimiMdStale?.();
|
|
2272
|
+
driftAccumulator.set(sid, 0);
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2263
2275
|
}
|
|
2264
2276
|
} catch {
|
|
2265
2277
|
}
|
|
@@ -2271,6 +2283,12 @@ ${sandboxResult.output}` : `${warningPrefix}${sandboxResult.output}`;
|
|
|
2271
2283
|
if (recentToolCalls.length > LOOP_WINDOW) recentToolCalls.shift();
|
|
2272
2284
|
}
|
|
2273
2285
|
}
|
|
2286
|
+
if (opts2.sessionId) {
|
|
2287
|
+
const current = driftAccumulator.get(opts2.sessionId) ?? 0;
|
|
2288
|
+
if (current > 0) {
|
|
2289
|
+
driftAccumulator.set(opts2.sessionId, Math.max(0, current - 1));
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2274
2292
|
if (opts2.onIterationEnd) {
|
|
2275
2293
|
opts2.messages = await opts2.onIterationEnd(opts2.messages, opts2.signal);
|
|
2276
2294
|
if (opts2.signal.aborted) throw new DOMException("aborted", "AbortError");
|
|
@@ -2303,7 +2321,7 @@ function validateToolArguments(raw) {
|
|
|
2303
2321
|
return "{}";
|
|
2304
2322
|
}
|
|
2305
2323
|
}
|
|
2306
|
-
var BudgetExhaustedError, codeModeApiCache;
|
|
2324
|
+
var BudgetExhaustedError, codeModeApiCache, driftAccumulator, DRIFT_THRESHOLD;
|
|
2307
2325
|
var init_loop = __esm({
|
|
2308
2326
|
"src/agent/loop.ts"() {
|
|
2309
2327
|
"use strict";
|
|
@@ -2321,6 +2339,8 @@ var init_loop = __esm({
|
|
|
2321
2339
|
}
|
|
2322
2340
|
};
|
|
2323
2341
|
codeModeApiCache = /* @__PURE__ */ new Map();
|
|
2342
|
+
driftAccumulator = /* @__PURE__ */ new Map();
|
|
2343
|
+
DRIFT_THRESHOLD = 5;
|
|
2324
2344
|
}
|
|
2325
2345
|
});
|
|
2326
2346
|
|
|
@@ -2654,9 +2674,6 @@ function collapsePath(input, cwd, maxLen = 40) {
|
|
|
2654
2674
|
if (parts.length <= 2) return input;
|
|
2655
2675
|
return `\u2026/${parts.slice(-2).join(sep)}`;
|
|
2656
2676
|
}
|
|
2657
|
-
function collapsePathsInText(s, cwd, maxLen = 40) {
|
|
2658
|
-
return s.replace(/([~/][^\s"',)}\]]+)/g, (match) => collapsePath(match, cwd, maxLen));
|
|
2659
|
-
}
|
|
2660
2677
|
var init_paths = __esm({
|
|
2661
2678
|
"src/util/paths.ts"() {
|
|
2662
2679
|
"use strict";
|
|
@@ -6719,16 +6736,191 @@ var init_diff_view = __esm({
|
|
|
6719
6736
|
}
|
|
6720
6737
|
});
|
|
6721
6738
|
|
|
6739
|
+
// src/ui/narrative.ts
|
|
6740
|
+
function countByCategory(items) {
|
|
6741
|
+
let reads = 0;
|
|
6742
|
+
let writes = 0;
|
|
6743
|
+
let shells = 0;
|
|
6744
|
+
let webs = 0;
|
|
6745
|
+
let memories = 0;
|
|
6746
|
+
let others = 0;
|
|
6747
|
+
for (const t of items) {
|
|
6748
|
+
if (READING_TOOLS.has(t.name)) reads++;
|
|
6749
|
+
else if (WRITING_TOOLS.has(t.name)) writes++;
|
|
6750
|
+
else if (SHELL_TOOLS.has(t.name)) shells++;
|
|
6751
|
+
else if (WEB_TOOLS.has(t.name)) webs++;
|
|
6752
|
+
else if (MEMORY_TOOLS.has(t.name)) memories++;
|
|
6753
|
+
else others++;
|
|
6754
|
+
}
|
|
6755
|
+
return { reads, writes, shells, webs, memories, others };
|
|
6756
|
+
}
|
|
6757
|
+
function pickOne(arr) {
|
|
6758
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
6759
|
+
}
|
|
6760
|
+
function generateActivityText(items, _ctx) {
|
|
6761
|
+
if (items.length === 0) return null;
|
|
6762
|
+
const { reads, writes, shells, webs, memories } = countByCategory(items);
|
|
6763
|
+
const total = items.length;
|
|
6764
|
+
if (total === 1) {
|
|
6765
|
+
const t = items[0];
|
|
6766
|
+
if (t.name === "read") {
|
|
6767
|
+
const path = typeof t.args?.path === "string" ? t.args.path : "a file";
|
|
6768
|
+
return pickOne([`Reading ${path}\u2026`, `Opening ${path}\u2026`, `Taking a look at ${path}\u2026`]);
|
|
6769
|
+
}
|
|
6770
|
+
if (t.name === "grep") {
|
|
6771
|
+
const pattern = typeof t.args?.pattern === "string" ? `"${t.args.pattern}"` : "for patterns";
|
|
6772
|
+
return pickOne([`Searching for ${pattern}\u2026`, `Hunting for ${pattern}\u2026`]);
|
|
6773
|
+
}
|
|
6774
|
+
if (t.name === "glob") {
|
|
6775
|
+
const pattern = typeof t.args?.pattern === "string" ? t.args.pattern : "files";
|
|
6776
|
+
return pickOne([`Finding ${pattern}\u2026`, `Gathering ${pattern}\u2026`]);
|
|
6777
|
+
}
|
|
6778
|
+
if (t.name === "write") {
|
|
6779
|
+
const path = typeof t.args?.path === "string" ? t.args.path : "a file";
|
|
6780
|
+
return pickOne([`Creating ${path}\u2026`, `Writing ${path}\u2026`]);
|
|
6781
|
+
}
|
|
6782
|
+
if (t.name === "edit") {
|
|
6783
|
+
const path = typeof t.args?.path === "string" ? t.args.path : "a file";
|
|
6784
|
+
return pickOne([`Patching ${path}\u2026`, `Editing ${path}\u2026`]);
|
|
6785
|
+
}
|
|
6786
|
+
if (t.name === "bash") {
|
|
6787
|
+
return pickOne([`Running a shell command\u2026`, `Executing something in the terminal\u2026`]);
|
|
6788
|
+
}
|
|
6789
|
+
if (t.name === "web_fetch") {
|
|
6790
|
+
return pickOne([`Fetching docs\u2026`, `Checking a reference\u2026`, `Looking something up\u2026`]);
|
|
6791
|
+
}
|
|
6792
|
+
if (t.name === "memory_remember") {
|
|
6793
|
+
return pickOne([`Taking notes for next time\u2026`, `Committing that to memory\u2026`]);
|
|
6794
|
+
}
|
|
6795
|
+
if (t.name === "memory_recall") {
|
|
6796
|
+
return pickOne([`Recalling what we know\u2026`, `Searching past notes\u2026`]);
|
|
6797
|
+
}
|
|
6798
|
+
return null;
|
|
6799
|
+
}
|
|
6800
|
+
if (webs >= 2) {
|
|
6801
|
+
return pickOne([`Digging through documentation\u2026`, `Cross-referencing sources\u2026`, `Reading up on this\u2026`]);
|
|
6802
|
+
}
|
|
6803
|
+
if (reads >= 2 && writes === 0 && shells === 0) {
|
|
6804
|
+
return pickOne([`Surveying the landscape\u2026`, `Getting the lay of the land\u2026`, `Mapping out the files\u2026`]);
|
|
6805
|
+
}
|
|
6806
|
+
if (reads >= 1 && (writes >= 1 || shells >= 1)) {
|
|
6807
|
+
return pickOne([`Reading, then making changes\u2026`, `Exploring and editing\u2026`, `Survey and patch\u2026`]);
|
|
6808
|
+
}
|
|
6809
|
+
if (writes >= 1 && shells >= 1) {
|
|
6810
|
+
return pickOne([`Committing the changes\u2026`, `Writing and verifying\u2026`, `Editing and checking\u2026`]);
|
|
6811
|
+
}
|
|
6812
|
+
if (reads >= 1 && webs >= 1) {
|
|
6813
|
+
return pickOne([`Exploring the codebase and docs\u2026`, `Cross-referencing code with references\u2026`]);
|
|
6814
|
+
}
|
|
6815
|
+
if (memories >= 1) {
|
|
6816
|
+
return pickOne([`Jogging the memory\u2026`, `Checking past notes\u2026`]);
|
|
6817
|
+
}
|
|
6818
|
+
if (shells >= 1) {
|
|
6819
|
+
return pickOne([`Running some commands\u2026`, `Working in the shell\u2026`]);
|
|
6820
|
+
}
|
|
6821
|
+
return null;
|
|
6822
|
+
}
|
|
6823
|
+
function narrativizeInfo(text, ctx) {
|
|
6824
|
+
if (ctx?.tier === "heavy") {
|
|
6825
|
+
return { kind: "activity", text: "Sizing this up\u2026 feels like a deep one.", feature: "triage" };
|
|
6826
|
+
}
|
|
6827
|
+
if (ctx?.tier === "light") {
|
|
6828
|
+
return { kind: "activity", text: "Quick check \u2014 this looks light.", feature: "triage" };
|
|
6829
|
+
}
|
|
6830
|
+
if (ctx?.tier === "medium") {
|
|
6831
|
+
return { kind: "activity", text: "This one feels medium weight.", feature: "triage" };
|
|
6832
|
+
}
|
|
6833
|
+
if (ctx?.codeMode) {
|
|
6834
|
+
return { kind: "activity", text: "The toolbox feels right for this. Switching to code mode\u2026", feature: "code" };
|
|
6835
|
+
}
|
|
6836
|
+
if (text.includes("auto-compacted") || text.includes("compacted")) {
|
|
6837
|
+
return { kind: "activity", text: "Making room by summarizing older turns\u2026", feature: "compact" };
|
|
6838
|
+
}
|
|
6839
|
+
if (text.includes("recalled") && text.includes("memory")) {
|
|
6840
|
+
return { kind: "activity", text: "Remembering what we learned before\u2026", feature: "memory" };
|
|
6841
|
+
}
|
|
6842
|
+
if (text.includes("memory cleanup") || text.includes("memory backfill")) {
|
|
6843
|
+
return null;
|
|
6844
|
+
}
|
|
6845
|
+
if (text.startsWith("LSP ready")) {
|
|
6846
|
+
return { kind: "activity", text: "Waking up the language servers\u2026" };
|
|
6847
|
+
}
|
|
6848
|
+
if (text.startsWith("LSP reload complete")) {
|
|
6849
|
+
return null;
|
|
6850
|
+
}
|
|
6851
|
+
if (text.startsWith("MCP connected")) {
|
|
6852
|
+
return { kind: "activity", text: "Plugging in external tools\u2026" };
|
|
6853
|
+
}
|
|
6854
|
+
if (text.includes("research budget") || text.includes("web request")) {
|
|
6855
|
+
return { kind: "activity", text: "Researching\u2026 gathering what we can from the web.", feature: "explore" };
|
|
6856
|
+
}
|
|
6857
|
+
return null;
|
|
6858
|
+
}
|
|
6859
|
+
function humanizeToolTitle(name, args) {
|
|
6860
|
+
const path = typeof args?.path === "string" ? args.path : void 0;
|
|
6861
|
+
const pattern = typeof args?.pattern === "string" ? args.pattern : void 0;
|
|
6862
|
+
const command = typeof args?.command === "string" ? args.command : void 0;
|
|
6863
|
+
const url = typeof args?.url === "string" ? args.url : void 0;
|
|
6864
|
+
switch (name) {
|
|
6865
|
+
case "read":
|
|
6866
|
+
return path ? `Reading ${path}` : "Reading a file\u2026";
|
|
6867
|
+
case "grep":
|
|
6868
|
+
return pattern ? `Searching for "${pattern}"` : "Searching\u2026";
|
|
6869
|
+
case "glob":
|
|
6870
|
+
return pattern ? `Finding ${pattern}` : "Finding files\u2026";
|
|
6871
|
+
case "write":
|
|
6872
|
+
return path ? `Creating ${path}` : "Creating a file\u2026";
|
|
6873
|
+
case "edit":
|
|
6874
|
+
return path ? `Patching ${path}` : "Patching a file\u2026";
|
|
6875
|
+
case "bash":
|
|
6876
|
+
return command ? `Running: ${command.split(/\s+/).slice(0, 4).join(" ")}${command.split(/\s+/).length > 4 ? "\u2026" : ""}` : "Running shell command\u2026";
|
|
6877
|
+
case "web_fetch":
|
|
6878
|
+
return url ? `Fetching ${url.replace(/^https?:\/\//, "").split("/")[0]}` : "Fetching docs\u2026";
|
|
6879
|
+
case "memory_remember":
|
|
6880
|
+
return "Committing to memory\u2026";
|
|
6881
|
+
case "memory_recall":
|
|
6882
|
+
return "Recalling memories\u2026";
|
|
6883
|
+
case "memory_forget":
|
|
6884
|
+
return "Forgetting a memory\u2026";
|
|
6885
|
+
case "lsp_hover":
|
|
6886
|
+
return "Inspecting symbol\u2026";
|
|
6887
|
+
case "lsp_definition":
|
|
6888
|
+
return "Jumping to definition\u2026";
|
|
6889
|
+
case "lsp_references":
|
|
6890
|
+
return "Finding references\u2026";
|
|
6891
|
+
case "lsp_implementation":
|
|
6892
|
+
return "Finding implementations\u2026";
|
|
6893
|
+
case "lsp_typeDefinition":
|
|
6894
|
+
return "Finding type definition\u2026";
|
|
6895
|
+
case "lsp_documentSymbols":
|
|
6896
|
+
return "Listing symbols\u2026";
|
|
6897
|
+
case "lsp_workspaceSymbol":
|
|
6898
|
+
return "Searching workspace symbols\u2026";
|
|
6899
|
+
case "lsp_rename":
|
|
6900
|
+
return "Renaming symbol\u2026";
|
|
6901
|
+
case "lsp_codeAction":
|
|
6902
|
+
return "Applying quick fix\u2026";
|
|
6903
|
+
default:
|
|
6904
|
+
return name;
|
|
6905
|
+
}
|
|
6906
|
+
}
|
|
6907
|
+
var READING_TOOLS, WRITING_TOOLS, SHELL_TOOLS, WEB_TOOLS, MEMORY_TOOLS;
|
|
6908
|
+
var init_narrative = __esm({
|
|
6909
|
+
"src/ui/narrative.ts"() {
|
|
6910
|
+
"use strict";
|
|
6911
|
+
READING_TOOLS = /* @__PURE__ */ new Set(["read", "glob", "grep", "lsp_hover", "lsp_definition", "lsp_references", "lsp_implementation", "lsp_typeDefinition", "lsp_documentSymbols", "lsp_workspaceSymbol"]);
|
|
6912
|
+
WRITING_TOOLS = /* @__PURE__ */ new Set(["write", "edit", "lsp_rename", "lsp_codeAction"]);
|
|
6913
|
+
SHELL_TOOLS = /* @__PURE__ */ new Set(["bash"]);
|
|
6914
|
+
WEB_TOOLS = /* @__PURE__ */ new Set(["web_fetch"]);
|
|
6915
|
+
MEMORY_TOOLS = /* @__PURE__ */ new Set(["memory_remember", "memory_recall", "memory_forget"]);
|
|
6916
|
+
}
|
|
6917
|
+
});
|
|
6918
|
+
|
|
6722
6919
|
// src/ui/tool-view.tsx
|
|
6723
6920
|
import React2 from "react";
|
|
6724
6921
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
6725
6922
|
import Spinner from "ink-spinner";
|
|
6726
6923
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
6727
|
-
function compactArgs(raw) {
|
|
6728
|
-
const collapsed = collapsePathsInText(raw, process.cwd());
|
|
6729
|
-
const s = collapsed.replace(/\s+/g, " ");
|
|
6730
|
-
return s.length <= 80 ? s : s.slice(0, 80) + "\u2026";
|
|
6731
|
-
}
|
|
6732
6924
|
function firstLine(s) {
|
|
6733
6925
|
const line = s.split("\n").find((l) => l.trim().length > 0) ?? "";
|
|
6734
6926
|
return line.length <= 120 ? line : line.slice(0, 120) + "\u2026";
|
|
@@ -6740,10 +6932,18 @@ var init_tool_view = __esm({
|
|
|
6740
6932
|
init_diff_view();
|
|
6741
6933
|
init_paths();
|
|
6742
6934
|
init_theme_context();
|
|
6935
|
+
init_narrative();
|
|
6743
6936
|
ToolView = React2.memo(function ToolView2({ evt, verbose }) {
|
|
6744
6937
|
const theme = useTheme();
|
|
6745
6938
|
const statusIcon = evt.status === "running" ? /* @__PURE__ */ jsx3(Text2, { color: theme.info.color, children: /* @__PURE__ */ jsx3(Spinner, { type: "dots" }) }) : evt.status === "error" ? /* @__PURE__ */ jsx3(Text2, { color: theme.palette.error, children: "\u2717" }) : /* @__PURE__ */ jsx3(Text2, { color: theme.palette.success, children: "\u2713" });
|
|
6746
|
-
const title = evt.render?.title ??
|
|
6939
|
+
const title = evt.render?.title ?? (() => {
|
|
6940
|
+
try {
|
|
6941
|
+
const args = evt.args ? JSON.parse(evt.args) : {};
|
|
6942
|
+
return humanizeToolTitle(evt.name, args);
|
|
6943
|
+
} catch {
|
|
6944
|
+
return humanizeToolTitle(evt.name);
|
|
6945
|
+
}
|
|
6946
|
+
})();
|
|
6747
6947
|
const expand = Boolean(evt.expanded || verbose);
|
|
6748
6948
|
const lines = evt.result ? evt.result.split("\n") : [];
|
|
6749
6949
|
const showLimit = verbose ? 200 : 20;
|
|
@@ -6958,12 +7158,13 @@ var init_chat = __esm({
|
|
|
6958
7158
|
init_tool_view();
|
|
6959
7159
|
init_markdown();
|
|
6960
7160
|
init_theme_context();
|
|
6961
|
-
ChatView = React4.memo(function ChatView2({ events, showReasoning, verbose }) {
|
|
7161
|
+
ChatView = React4.memo(function ChatView2({ events, showReasoning, verbose, suppressTools }) {
|
|
6962
7162
|
const theme = useTheme();
|
|
6963
7163
|
const finalized = [];
|
|
6964
7164
|
const active = [];
|
|
6965
7165
|
for (let i = 0; i < events.length; i++) {
|
|
6966
7166
|
const e = events[i];
|
|
7167
|
+
if (suppressTools && e.kind === "tool") continue;
|
|
6967
7168
|
const isStreaming = e.kind === "assistant" && e.streaming;
|
|
6968
7169
|
if (isStreaming) {
|
|
6969
7170
|
active.push(e);
|
|
@@ -7035,6 +7236,12 @@ var init_chat = __esm({
|
|
|
7035
7236
|
evt.text
|
|
7036
7237
|
] });
|
|
7037
7238
|
}
|
|
7239
|
+
if (evt.kind === "activity") {
|
|
7240
|
+
return /* @__PURE__ */ jsxs4(Text4, { italic: true, color: theme.info.dim ? theme.info.color : theme.palette.secondary, children: [
|
|
7241
|
+
"~ ",
|
|
7242
|
+
evt.text
|
|
7243
|
+
] });
|
|
7244
|
+
}
|
|
7038
7245
|
return /* @__PURE__ */ jsxs4(Text4, { color: theme.error, children: [
|
|
7039
7246
|
"! ",
|
|
7040
7247
|
evt.text
|
|
@@ -7066,7 +7273,7 @@ import { useEffect, useState } from "react";
|
|
|
7066
7273
|
import { Box as Box5, Text as Text5 } from "ink";
|
|
7067
7274
|
import Spinner3 from "ink-spinner";
|
|
7068
7275
|
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
7069
|
-
function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode, effort, contextLimit, hasUpdate, latestVersion, gatewayMeta, codeMode, cloudMode, cloudBudget }) {
|
|
7276
|
+
function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode, effort, contextLimit, hasUpdate, latestVersion, gatewayMeta, codeMode, cloudMode, cloudBudget, kimiMdStale }) {
|
|
7070
7277
|
const theme = useTheme();
|
|
7071
7278
|
const [now2, setNow] = useState(Date.now());
|
|
7072
7279
|
const modeColor = mode === "plan" ? theme.modeBadge.plan : mode === "auto" ? theme.modeBadge.auto : theme.modeBadge.edit;
|
|
@@ -7109,6 +7316,10 @@ function StatusBar({ model, usage, sessionUsage, thinking, turnStartedAt, mode,
|
|
|
7109
7316
|
"update available",
|
|
7110
7317
|
latestVersion ? ` \u2192 ${latestVersion}` : "",
|
|
7111
7318
|
" \xB7 run /update"
|
|
7319
|
+
] }) : null,
|
|
7320
|
+
kimiMdStale ? /* @__PURE__ */ jsxs5(Text5, { color: theme.warn, bold: true, children: [
|
|
7321
|
+
" \xB7 ",
|
|
7322
|
+
"\u26A0 KIMI.md stale \xB7 run /init"
|
|
7112
7323
|
] }) : null
|
|
7113
7324
|
] })
|
|
7114
7325
|
] });
|
|
@@ -9525,11 +9736,21 @@ var init_usage_tracker = __esm({
|
|
|
9525
9736
|
}
|
|
9526
9737
|
});
|
|
9527
9738
|
|
|
9739
|
+
// src/memory/schema.ts
|
|
9740
|
+
var DEFAULT_EMBEDDING_DIM;
|
|
9741
|
+
var init_schema = __esm({
|
|
9742
|
+
"src/memory/schema.ts"() {
|
|
9743
|
+
"use strict";
|
|
9744
|
+
DEFAULT_EMBEDDING_DIM = 768;
|
|
9745
|
+
}
|
|
9746
|
+
});
|
|
9747
|
+
|
|
9528
9748
|
// src/memory/db.ts
|
|
9529
9749
|
var db_exports = {};
|
|
9530
9750
|
__export(db_exports, {
|
|
9531
9751
|
clearMemoriesForRepo: () => clearMemoriesForRepo,
|
|
9532
9752
|
closeMemoryDb: () => closeMemoryDb,
|
|
9753
|
+
countHighSignalMemoriesSince: () => countHighSignalMemoriesSince,
|
|
9533
9754
|
deleteExcessMemories: () => deleteExcessMemories,
|
|
9534
9755
|
deleteMemoriesByIds: () => deleteMemoriesByIds,
|
|
9535
9756
|
deleteOldMemories: () => deleteOldMemories,
|
|
@@ -9916,6 +10137,19 @@ function getMemoryById(db, id) {
|
|
|
9916
10137
|
const row = db.prepare("SELECT * FROM memories WHERE id = ?").get(id);
|
|
9917
10138
|
return row ? rowToMemory(row) : null;
|
|
9918
10139
|
}
|
|
10140
|
+
function countHighSignalMemoriesSince(db, repoPath, since) {
|
|
10141
|
+
const row = db.prepare(
|
|
10142
|
+
`SELECT COUNT(*) as count FROM memories
|
|
10143
|
+
WHERE repo_path = ? AND created_at > ?
|
|
10144
|
+
AND forgotten = 0 AND superseded_by IS NULL
|
|
10145
|
+
AND (
|
|
10146
|
+
topic_key IN ('project_dependencies', 'project_tsconfig', 'project_entry_point')
|
|
10147
|
+
OR category IN ('instruction', 'preference')
|
|
10148
|
+
OR (category = 'event' AND importance >= 3)
|
|
10149
|
+
)`
|
|
10150
|
+
).get(repoPath, since);
|
|
10151
|
+
return row?.count ?? 0;
|
|
10152
|
+
}
|
|
9919
10153
|
var dbInstance, dbPathInstance;
|
|
9920
10154
|
var init_db = __esm({
|
|
9921
10155
|
"src/memory/db.ts"() {
|
|
@@ -10277,6 +10511,7 @@ var init_manager3 = __esm({
|
|
|
10277
10511
|
"src/memory/manager.ts"() {
|
|
10278
10512
|
"use strict";
|
|
10279
10513
|
init_client();
|
|
10514
|
+
init_schema();
|
|
10280
10515
|
init_db();
|
|
10281
10516
|
init_embeddings();
|
|
10282
10517
|
init_retrieval();
|
|
@@ -10406,6 +10641,48 @@ Return a JSON array of strings. Example:
|
|
|
10406
10641
|
}
|
|
10407
10642
|
return { id: memory.id, superseded: supersededIds.length > 0 ? supersededIds : void 0 };
|
|
10408
10643
|
}
|
|
10644
|
+
/**
|
|
10645
|
+
* Count high-signal memories created since the given timestamp.
|
|
10646
|
+
* Used for KIMI.md drift detection (Trigger A: session-start check).
|
|
10647
|
+
*/
|
|
10648
|
+
countHighSignalMemoriesSince(repoPath, since) {
|
|
10649
|
+
if (!this.db) return 0;
|
|
10650
|
+
return countHighSignalMemoriesSince(this.db, repoPath, since);
|
|
10651
|
+
}
|
|
10652
|
+
/**
|
|
10653
|
+
* Get the timestamp of the most recent KIMI.md refresh memory.
|
|
10654
|
+
* Returns 0 if none exists.
|
|
10655
|
+
*/
|
|
10656
|
+
getLastKimiMdRefreshTime(repoPath) {
|
|
10657
|
+
if (!this.db) return 0;
|
|
10658
|
+
const rows = this.db.prepare(
|
|
10659
|
+
`SELECT created_at FROM memories
|
|
10660
|
+
WHERE repo_path = ? AND topic_key = 'kimi_md_refresh'
|
|
10661
|
+
AND forgotten = 0 AND superseded_by IS NULL
|
|
10662
|
+
ORDER BY created_at DESC LIMIT 1`
|
|
10663
|
+
).all(repoPath);
|
|
10664
|
+
return rows[0]?.created_at ?? 0;
|
|
10665
|
+
}
|
|
10666
|
+
/**
|
|
10667
|
+
* Record that KIMI.md was refreshed. Creates a lightweight memory
|
|
10668
|
+
* so drift detection knows when the snapshot was last updated.
|
|
10669
|
+
*/
|
|
10670
|
+
async recordKimiMdRefresh(repoPath, sessionId) {
|
|
10671
|
+
if (!this.db) return;
|
|
10672
|
+
const embedding = new Float32Array(DEFAULT_EMBEDDING_DIM);
|
|
10673
|
+
insertMemory(
|
|
10674
|
+
this.db,
|
|
10675
|
+
{
|
|
10676
|
+
content: `KIMI.md refreshed for ${repoPath}`,
|
|
10677
|
+
category: "event",
|
|
10678
|
+
sourceSessionId: sessionId,
|
|
10679
|
+
repoPath,
|
|
10680
|
+
importance: 2,
|
|
10681
|
+
topicKey: "kimi_md_refresh"
|
|
10682
|
+
},
|
|
10683
|
+
embedding
|
|
10684
|
+
);
|
|
10685
|
+
}
|
|
10409
10686
|
/**
|
|
10410
10687
|
* Recall memories using the full hybrid retrieval pipeline.
|
|
10411
10688
|
*/
|
|
@@ -13289,6 +13566,7 @@ function App({
|
|
|
13289
13566
|
const [latestVersion, setLatestVersion] = useState10(initialUpdateResult?.latestVersion ?? null);
|
|
13290
13567
|
const [theme, setTheme] = useState10(resolveTheme(initialCfg?.theme));
|
|
13291
13568
|
const [showThemePicker, setShowThemePicker] = useState10(false);
|
|
13569
|
+
const [kimiMdStale, setKimiMdStale] = useState10(false);
|
|
13292
13570
|
useEffect6(() => {
|
|
13293
13571
|
if (!cfg?.cloudMode || !initialCloudToken) return;
|
|
13294
13572
|
let cancelled = false;
|
|
@@ -13319,6 +13597,8 @@ function App({
|
|
|
13319
13597
|
const permResolveRef = useRef3(null);
|
|
13320
13598
|
const limitResolveRef = useRef3(null);
|
|
13321
13599
|
const pendingToolCallsRef = useRef3(/* @__PURE__ */ new Map());
|
|
13600
|
+
const toolBatchRef = useRef3([]);
|
|
13601
|
+
const toolBatchTimerRef = useRef3(null);
|
|
13322
13602
|
const sessionIdRef = useRef3(null);
|
|
13323
13603
|
const modeRef = useRef3(mode);
|
|
13324
13604
|
const effortRef = useRef3(effort);
|
|
@@ -13342,6 +13622,8 @@ function App({
|
|
|
13342
13622
|
const busyRef = useRef3(busy);
|
|
13343
13623
|
const memoryManagerRef = useRef3(null);
|
|
13344
13624
|
const sessionStartRecallRef = useRef3(null);
|
|
13625
|
+
const kimiMdStaleNudgedRef = useRef3(false);
|
|
13626
|
+
const turnCounterRef = useRef3(0);
|
|
13345
13627
|
const pendingTextRef = useRef3(/* @__PURE__ */ new Map());
|
|
13346
13628
|
const flushTimeoutRef = useRef3(null);
|
|
13347
13629
|
const customCommandsRef = useRef3([]);
|
|
@@ -13565,12 +13847,19 @@ function App({
|
|
|
13565
13847
|
messagesRef.current.splice(insertIdx, 0, { role: "system", content: text });
|
|
13566
13848
|
setEvents((e) => [
|
|
13567
13849
|
...e,
|
|
13568
|
-
{ kind: "
|
|
13850
|
+
{ kind: "activity", key: mkKey(), text: "Remembering what we know about this repo\u2026", feature: "memory" }
|
|
13569
13851
|
]);
|
|
13570
13852
|
}
|
|
13571
13853
|
} catch {
|
|
13572
13854
|
}
|
|
13573
13855
|
})();
|
|
13856
|
+
if (existsSync3(join22(cwd, "KIMI.md"))) {
|
|
13857
|
+
const lastRefresh = manager.getLastKimiMdRefreshTime(cwd);
|
|
13858
|
+
const driftCount = manager.countHighSignalMemoriesSince(cwd, lastRefresh);
|
|
13859
|
+
if (driftCount >= 5) {
|
|
13860
|
+
setKimiMdStale(true);
|
|
13861
|
+
}
|
|
13862
|
+
}
|
|
13574
13863
|
} else {
|
|
13575
13864
|
memoryManagerRef.current?.close();
|
|
13576
13865
|
memoryManagerRef.current = null;
|
|
@@ -13784,7 +14073,7 @@ function App({
|
|
|
13784
14073
|
}
|
|
13785
14074
|
setEvents((e) => [
|
|
13786
14075
|
...e,
|
|
13787
|
-
{ kind: "
|
|
14076
|
+
{ kind: "activity", key: mkKey(), text: "Plugging in external tools\u2026" }
|
|
13788
14077
|
]);
|
|
13789
14078
|
}
|
|
13790
14079
|
}, [cfg]);
|
|
@@ -13842,7 +14131,7 @@ function App({
|
|
|
13842
14131
|
}
|
|
13843
14132
|
setEvents((e) => [
|
|
13844
14133
|
...e,
|
|
13845
|
-
{ kind: "
|
|
14134
|
+
{ kind: "activity", key: mkKey(), text: "Waking up the language servers\u2026" }
|
|
13846
14135
|
]);
|
|
13847
14136
|
} else {
|
|
13848
14137
|
setEvents((e) => [
|
|
@@ -14079,6 +14368,16 @@ function App({
|
|
|
14079
14368
|
},
|
|
14080
14369
|
[]
|
|
14081
14370
|
);
|
|
14371
|
+
const flushToolBatch = useCallback2(() => {
|
|
14372
|
+
toolBatchTimerRef.current = null;
|
|
14373
|
+
const batch = toolBatchRef.current;
|
|
14374
|
+
toolBatchRef.current = [];
|
|
14375
|
+
if (batch.length === 0) return;
|
|
14376
|
+
const text = generateActivityText(batch, { mode: modeRef.current });
|
|
14377
|
+
if (text) {
|
|
14378
|
+
setEvents((e) => [...e, { kind: "activity", key: mkKey(), text, feature: "explore" }]);
|
|
14379
|
+
}
|
|
14380
|
+
}, []);
|
|
14082
14381
|
const updateGatewayMeta = useCallback2((meta) => {
|
|
14083
14382
|
gatewayMetaRef.current = meta;
|
|
14084
14383
|
setGatewayMeta(meta);
|
|
@@ -14255,11 +14554,16 @@ function App({
|
|
|
14255
14554
|
pendingToolCallsRef.current.set(call.id, call.function.name);
|
|
14256
14555
|
const spec = executorRef.current.list().find((t) => t.name === call.function.name);
|
|
14257
14556
|
let renderMeta;
|
|
14557
|
+
let argsParsed = {};
|
|
14258
14558
|
try {
|
|
14259
|
-
|
|
14260
|
-
renderMeta = spec?.render?.(
|
|
14559
|
+
argsParsed = call.function.arguments ? JSON.parse(call.function.arguments) : {};
|
|
14560
|
+
renderMeta = spec?.render?.(argsParsed);
|
|
14261
14561
|
} catch {
|
|
14262
14562
|
}
|
|
14563
|
+
toolBatchRef.current.push({ name: call.function.name, args: argsParsed });
|
|
14564
|
+
if (toolBatchTimerRef.current) clearTimeout(toolBatchTimerRef.current);
|
|
14565
|
+
toolBatchTimerRef.current = setTimeout(flushToolBatch, 120);
|
|
14566
|
+
if (modeRef.current === "plan") return;
|
|
14263
14567
|
setEvents((e) => [
|
|
14264
14568
|
...e,
|
|
14265
14569
|
{
|
|
@@ -14327,7 +14631,17 @@ function App({
|
|
|
14327
14631
|
}
|
|
14328
14632
|
permResolveRef.current = resolve2;
|
|
14329
14633
|
setPerm({ tool: req.tool, args: req.args, resolve: resolve2 });
|
|
14330
|
-
})
|
|
14634
|
+
}),
|
|
14635
|
+
onKimiMdStale: () => {
|
|
14636
|
+
if (!kimiMdStaleNudgedRef.current) {
|
|
14637
|
+
kimiMdStaleNudgedRef.current = true;
|
|
14638
|
+
setKimiMdStale(true);
|
|
14639
|
+
setEvents((e) => [
|
|
14640
|
+
...e,
|
|
14641
|
+
{ kind: "info", key: mkKey(), text: "Project context may be stale. Run /init to refresh KIMI.md based on recent changes." }
|
|
14642
|
+
]);
|
|
14643
|
+
}
|
|
14644
|
+
}
|
|
14331
14645
|
}
|
|
14332
14646
|
});
|
|
14333
14647
|
if (existsSync3(join22(cwd, "KIMI.md"))) {
|
|
@@ -14356,6 +14670,9 @@ function App({
|
|
|
14356
14670
|
...e,
|
|
14357
14671
|
{ kind: "info", key: mkKey(), text: "KIMI.md generated; context loaded for future turns" }
|
|
14358
14672
|
]);
|
|
14673
|
+
void memoryManagerRef.current?.recordKimiMdRefresh(cwd, ensureSessionId());
|
|
14674
|
+
setKimiMdStale(false);
|
|
14675
|
+
kimiMdStaleNudgedRef.current = false;
|
|
14359
14676
|
}
|
|
14360
14677
|
} catch (e) {
|
|
14361
14678
|
if (e.name === "AbortError") {
|
|
@@ -14387,8 +14704,15 @@ function App({
|
|
|
14387
14704
|
permResolveRef.current = null;
|
|
14388
14705
|
limitResolveRef.current = null;
|
|
14389
14706
|
pendingToolCallsRef.current.clear();
|
|
14707
|
+
tasksRef.current = [];
|
|
14708
|
+
setTasks([]);
|
|
14709
|
+
setTasksStartedAt(null);
|
|
14710
|
+
setTasksStartTokens(0);
|
|
14711
|
+
setEvents(
|
|
14712
|
+
(evts) => evts.map((e) => e.kind === "tool" && e.status === "running" ? { ...e, status: "error", result: "(interrupted)" } : e)
|
|
14713
|
+
);
|
|
14390
14714
|
}
|
|
14391
|
-
}, [cfg, busy, updateAssistant, updateTool, updateGatewayMeta]);
|
|
14715
|
+
}, [cfg, busy, updateAssistant, updateTool, updateGatewayMeta, flushToolBatch]);
|
|
14392
14716
|
const handleThemePick = useCallback2(
|
|
14393
14717
|
(picked) => {
|
|
14394
14718
|
setShowThemePicker(false);
|
|
@@ -15295,6 +15619,13 @@ ${lines.join("\n")}` }]);
|
|
|
15295
15619
|
};
|
|
15296
15620
|
}
|
|
15297
15621
|
}
|
|
15622
|
+
turnCounterRef.current += 1;
|
|
15623
|
+
if (turnCounterRef.current % 15 === 0 && existsSync3(join22(process.cwd(), "KIMI.md")) && !kimiMdStale) {
|
|
15624
|
+
setEvents((e) => [
|
|
15625
|
+
...e,
|
|
15626
|
+
{ kind: "info", key: mkKey(), text: "Tip: Rerunning /init occasionally helps KimiFlare stay accurate as your project evolves." }
|
|
15627
|
+
]);
|
|
15628
|
+
}
|
|
15298
15629
|
setBusy(true);
|
|
15299
15630
|
gatewayMetaRef.current = null;
|
|
15300
15631
|
setGatewayMeta(null);
|
|
@@ -15308,6 +15639,10 @@ ${lines.join("\n")}` }]);
|
|
|
15308
15639
|
const turnReasoningEffort = overrideEffort ?? effortForTier[classification.tier] ?? effortRef.current;
|
|
15309
15640
|
const effectiveCodeMode = classification.tier === "heavy";
|
|
15310
15641
|
setCodeMode(effectiveCodeMode);
|
|
15642
|
+
const triageActivity = narrativizeInfo("", { tier: classification.tier, codeMode: effectiveCodeMode });
|
|
15643
|
+
if (triageActivity) {
|
|
15644
|
+
setEvents((e) => [...e, { kind: "activity", key: mkKey(), text: triageActivity.text, feature: triageActivity.feature }]);
|
|
15645
|
+
}
|
|
15311
15646
|
const controller = new AbortController();
|
|
15312
15647
|
activeControllerRef.current = controller;
|
|
15313
15648
|
const sharedCallbacks = {
|
|
@@ -15335,11 +15670,16 @@ ${lines.join("\n")}` }]);
|
|
|
15335
15670
|
pendingToolCallsRef.current.set(call.id, call.function.name);
|
|
15336
15671
|
const spec = executorRef.current.list().find((t) => t.name === call.function.name);
|
|
15337
15672
|
let renderMeta;
|
|
15673
|
+
let argsParsed = {};
|
|
15338
15674
|
try {
|
|
15339
|
-
|
|
15340
|
-
renderMeta = spec?.render?.(
|
|
15675
|
+
argsParsed = call.function.arguments ? JSON.parse(call.function.arguments) : {};
|
|
15676
|
+
renderMeta = spec?.render?.(argsParsed);
|
|
15341
15677
|
} catch {
|
|
15342
15678
|
}
|
|
15679
|
+
toolBatchRef.current.push({ name: call.function.name, args: argsParsed });
|
|
15680
|
+
if (toolBatchTimerRef.current) clearTimeout(toolBatchTimerRef.current);
|
|
15681
|
+
toolBatchTimerRef.current = setTimeout(flushToolBatch, 120);
|
|
15682
|
+
if (modeRef.current === "plan") return;
|
|
15343
15683
|
setEvents((e) => [
|
|
15344
15684
|
...e,
|
|
15345
15685
|
{
|
|
@@ -15423,7 +15763,17 @@ ${lines.join("\n")}` }]);
|
|
|
15423
15763
|
onToolLimitReached: () => new Promise((resolve2) => {
|
|
15424
15764
|
limitResolveRef.current = resolve2;
|
|
15425
15765
|
setLimitModal({ limit: 50, resolve: resolve2 });
|
|
15426
|
-
})
|
|
15766
|
+
}),
|
|
15767
|
+
onKimiMdStale: () => {
|
|
15768
|
+
if (!kimiMdStaleNudgedRef.current) {
|
|
15769
|
+
kimiMdStaleNudgedRef.current = true;
|
|
15770
|
+
setKimiMdStale(true);
|
|
15771
|
+
setEvents((e) => [
|
|
15772
|
+
...e,
|
|
15773
|
+
{ kind: "info", key: mkKey(), text: "Project context may be stale. Run /init to refresh KIMI.md based on recent changes." }
|
|
15774
|
+
]);
|
|
15775
|
+
}
|
|
15776
|
+
}
|
|
15427
15777
|
};
|
|
15428
15778
|
try {
|
|
15429
15779
|
await runAgentTurn({
|
|
@@ -15474,9 +15824,10 @@ ${lines.join("\n")}` }]);
|
|
|
15474
15824
|
setEvents((e) => [
|
|
15475
15825
|
...e,
|
|
15476
15826
|
{
|
|
15477
|
-
kind: "
|
|
15827
|
+
kind: "activity",
|
|
15478
15828
|
key: mkKey(),
|
|
15479
|
-
text:
|
|
15829
|
+
text: "Making room by summarizing older turns\u2026",
|
|
15830
|
+
feature: "compact"
|
|
15480
15831
|
}
|
|
15481
15832
|
]);
|
|
15482
15833
|
await saveSessionSafe();
|
|
@@ -15496,9 +15847,10 @@ ${lines.join("\n")}` }]);
|
|
|
15496
15847
|
setEvents((e) => [
|
|
15497
15848
|
...e,
|
|
15498
15849
|
{
|
|
15499
|
-
kind: "
|
|
15850
|
+
kind: "activity",
|
|
15500
15851
|
key: mkKey(),
|
|
15501
|
-
text:
|
|
15852
|
+
text: "Making room by summarizing older turns\u2026",
|
|
15853
|
+
feature: "compact"
|
|
15502
15854
|
}
|
|
15503
15855
|
]);
|
|
15504
15856
|
await saveSessionSafe();
|
|
@@ -15533,9 +15885,10 @@ ${lines.join("\n")}` }]);
|
|
|
15533
15885
|
setEvents((e) => [
|
|
15534
15886
|
...e,
|
|
15535
15887
|
{
|
|
15536
|
-
kind: "
|
|
15888
|
+
kind: "activity",
|
|
15537
15889
|
key: mkKey(),
|
|
15538
|
-
text:
|
|
15890
|
+
text: "Remembering what we learned before\u2026",
|
|
15891
|
+
feature: "memory"
|
|
15539
15892
|
}
|
|
15540
15893
|
]);
|
|
15541
15894
|
await saveSessionSafe();
|
|
@@ -15586,9 +15939,16 @@ ${lines.join("\n")}` }]);
|
|
|
15586
15939
|
permResolveRef.current = null;
|
|
15587
15940
|
limitResolveRef.current = null;
|
|
15588
15941
|
pendingToolCallsRef.current.clear();
|
|
15942
|
+
tasksRef.current = [];
|
|
15943
|
+
setTasks([]);
|
|
15944
|
+
setTasksStartedAt(null);
|
|
15945
|
+
setTasksStartTokens(0);
|
|
15946
|
+
setEvents(
|
|
15947
|
+
(evts) => evts.map((e) => e.kind === "tool" && e.status === "running" ? { ...e, status: "error", result: "(interrupted)" } : e)
|
|
15948
|
+
);
|
|
15589
15949
|
}
|
|
15590
15950
|
},
|
|
15591
|
-
[cfg, handleSlash, updateAssistant, updateTool, saveSessionSafe, updateGatewayMeta]
|
|
15951
|
+
[cfg, handleSlash, updateAssistant, updateTool, saveSessionSafe, updateGatewayMeta, flushToolBatch]
|
|
15592
15952
|
);
|
|
15593
15953
|
useEffect6(() => {
|
|
15594
15954
|
if (!busy && queue.length > 0) {
|
|
@@ -15819,7 +16179,7 @@ ${lines.join("\n")}` }]);
|
|
|
15819
16179
|
}
|
|
15820
16180
|
const hasConversation = events.some((e) => e.kind === "user" || e.kind === "assistant");
|
|
15821
16181
|
return /* @__PURE__ */ jsx23(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
|
|
15822
|
-
!hasConversation && events.length === 0 ? /* @__PURE__ */ jsx23(Welcome, { accountId: cfg.accountId }) : /* @__PURE__ */ jsx23(ChatView, { events, showReasoning, verbose }),
|
|
16182
|
+
!hasConversation && events.length === 0 ? /* @__PURE__ */ jsx23(Welcome, { accountId: cfg.accountId }) : /* @__PURE__ */ jsx23(ChatView, { events, showReasoning, verbose, suppressTools: mode === "plan" }),
|
|
15823
16183
|
perm ? /* @__PURE__ */ jsx23(
|
|
15824
16184
|
PermissionModal,
|
|
15825
16185
|
{
|
|
@@ -15870,7 +16230,8 @@ ${lines.join("\n")}` }]);
|
|
|
15870
16230
|
gatewayMeta,
|
|
15871
16231
|
codeMode,
|
|
15872
16232
|
cloudMode: cfg.cloudMode,
|
|
15873
|
-
cloudBudget
|
|
16233
|
+
cloudBudget,
|
|
16234
|
+
kimiMdStale
|
|
15874
16235
|
}
|
|
15875
16236
|
),
|
|
15876
16237
|
activePicker?.kind === "file" && /* @__PURE__ */ jsx23(
|
|
@@ -15982,6 +16343,7 @@ var init_app = __esm({
|
|
|
15982
16343
|
init_errors();
|
|
15983
16344
|
init_chat();
|
|
15984
16345
|
init_status();
|
|
16346
|
+
init_narrative();
|
|
15985
16347
|
init_permission();
|
|
15986
16348
|
init_limit_modal();
|
|
15987
16349
|
init_resume_picker();
|