kimiflare 0.25.0 → 0.26.1
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 +1013 -102
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -83,6 +83,7 @@ async function loadConfig() {
|
|
|
83
83
|
const envMemoryMaxAgeDays = readNumberEnv("KIMIFLARE_MEMORY_MAX_AGE_DAYS");
|
|
84
84
|
const envMemoryMaxEntries = readNumberEnv("KIMIFLARE_MEMORY_MAX_ENTRIES");
|
|
85
85
|
const envMemoryEmbeddingModel = process.env.KIMIFLARE_MEMORY_EMBEDDING_MODEL;
|
|
86
|
+
const envPlumbingModel = process.env.KIMIFLARE_PLUMBING_MODEL;
|
|
86
87
|
const envCodeMode = readBooleanEnv("KIMIFLARE_CODE_MODE");
|
|
87
88
|
if (envAccount && envToken) {
|
|
88
89
|
return {
|
|
@@ -107,6 +108,7 @@ async function loadConfig() {
|
|
|
107
108
|
memoryMaxAgeDays: envMemoryMaxAgeDays,
|
|
108
109
|
memoryMaxEntries: envMemoryMaxEntries,
|
|
109
110
|
memoryEmbeddingModel: envMemoryEmbeddingModel,
|
|
111
|
+
plumbingModel: envPlumbingModel,
|
|
110
112
|
codeMode: envCodeMode
|
|
111
113
|
};
|
|
112
114
|
}
|
|
@@ -137,6 +139,7 @@ async function loadConfig() {
|
|
|
137
139
|
memoryMaxAgeDays: envMemoryMaxAgeDays ?? parsed.memoryMaxAgeDays,
|
|
138
140
|
memoryMaxEntries: envMemoryMaxEntries ?? parsed.memoryMaxEntries,
|
|
139
141
|
memoryEmbeddingModel: envMemoryEmbeddingModel ?? parsed.memoryEmbeddingModel,
|
|
142
|
+
plumbingModel: envPlumbingModel ?? parsed.plumbingModel,
|
|
140
143
|
codeMode: envCodeMode ?? parsed.codeMode
|
|
141
144
|
};
|
|
142
145
|
}
|
|
@@ -248,7 +251,7 @@ function stableStringify(value, replacer, space) {
|
|
|
248
251
|
function stripOldImages(messages, keepLastTurns) {
|
|
249
252
|
if (keepLastTurns < 0) return messages;
|
|
250
253
|
let userCount = 0;
|
|
251
|
-
let cutoffIndex =
|
|
254
|
+
let cutoffIndex = 0;
|
|
252
255
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
253
256
|
if (messages[i].role === "user") {
|
|
254
257
|
userCount++;
|
|
@@ -880,7 +883,7 @@ function schemaToTsType(prop, required = true) {
|
|
|
880
883
|
types.push(`${itemType}[]`);
|
|
881
884
|
} else if (prop.type === "object") {
|
|
882
885
|
if (prop.properties && Object.keys(prop.properties).length > 0) {
|
|
883
|
-
const entries = Object.entries(prop.properties).map(([key, val]) => {
|
|
886
|
+
const entries = Object.entries(prop.properties).sort(([a], [b]) => a.localeCompare(b)).map(([key, val]) => {
|
|
884
887
|
const isReq = prop.required?.includes(key) ?? false;
|
|
885
888
|
return ` ${key}${isReq ? "" : "?"}: ${schemaToTsType(val, isReq)};`;
|
|
886
889
|
}).join("\n");
|
|
@@ -901,7 +904,7 @@ ${entries}
|
|
|
901
904
|
return required ? result : `${result} | undefined`;
|
|
902
905
|
}
|
|
903
906
|
function generateInterface(name, properties, required = []) {
|
|
904
|
-
const entries = Object.entries(properties).map(([key, val]) => {
|
|
907
|
+
const entries = Object.entries(properties).sort(([a], [b]) => a.localeCompare(b)).map(([key, val]) => {
|
|
905
908
|
const isReq = required.includes(key);
|
|
906
909
|
return ` ${key}${isReq ? "" : "?"}: ${schemaToTsType(val, isReq)};`;
|
|
907
910
|
}).join("\n");
|
|
@@ -921,13 +924,14 @@ function generateTypeScriptApi(tools) {
|
|
|
921
924
|
const inputInterfaces = [];
|
|
922
925
|
const outputInterfaces = [];
|
|
923
926
|
const methodEntries = [];
|
|
924
|
-
for (const tool of tools) {
|
|
927
|
+
for (const tool of [...tools].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
925
928
|
const baseName = sanitizeTypeName(tool.name);
|
|
926
929
|
const inputName = `${baseName}_Input`;
|
|
927
930
|
const outputName = `${baseName}_Output`;
|
|
928
931
|
const params = tool.parameters;
|
|
929
|
-
|
|
930
|
-
|
|
932
|
+
const sortedPropKeys = params.properties ? Object.keys(params.properties).sort((a, b) => a.localeCompare(b)) : [];
|
|
933
|
+
if (sortedPropKeys.length > 0 && params.properties) {
|
|
934
|
+
inputInterfaces.push(generateInterface(inputName, params.properties, [...params.required ?? []].sort((a, b) => a.localeCompare(b))));
|
|
931
935
|
inputInterfaces.push("");
|
|
932
936
|
methodEntries.push(` /**`);
|
|
933
937
|
methodEntries.push(` * ${tool.description.replace(/\n/g, "\n * ")}`);
|
|
@@ -1148,7 +1152,14 @@ async function runAgentTurn(opts2) {
|
|
|
1148
1152
|
let toolDefs;
|
|
1149
1153
|
let codeModeApiString = "";
|
|
1150
1154
|
if (codeMode) {
|
|
1151
|
-
|
|
1155
|
+
const toolsKey = stableStringify(opts2.tools);
|
|
1156
|
+
const cached = codeModeApiCache.get(toolsKey);
|
|
1157
|
+
if (cached) {
|
|
1158
|
+
codeModeApiString = cached;
|
|
1159
|
+
} else {
|
|
1160
|
+
codeModeApiString = generateTypeScriptApi(opts2.tools);
|
|
1161
|
+
codeModeApiCache.set(toolsKey, codeModeApiString);
|
|
1162
|
+
}
|
|
1152
1163
|
toolDefs = [
|
|
1153
1164
|
{
|
|
1154
1165
|
type: "function",
|
|
@@ -1183,6 +1194,9 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
1183
1194
|
}
|
|
1184
1195
|
let turn = 0;
|
|
1185
1196
|
let lastUsage = null;
|
|
1197
|
+
const recentToolCalls = [];
|
|
1198
|
+
const LOOP_WINDOW = 8;
|
|
1199
|
+
const LOOP_THRESHOLD = 2;
|
|
1186
1200
|
for (let iter = 0; iter < max; iter++) {
|
|
1187
1201
|
turn++;
|
|
1188
1202
|
const previousMessages = opts2.messages.slice();
|
|
@@ -1313,6 +1327,28 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
1313
1327
|
}
|
|
1314
1328
|
for (const tc of toolCalls) {
|
|
1315
1329
|
if (opts2.signal.aborted) throw new DOMException("aborted", "AbortError");
|
|
1330
|
+
const loopSignature = `${tc.function.name}:${stableStringify(tc.function.arguments)}`;
|
|
1331
|
+
const loopCount = recentToolCalls.filter((s) => s === loopSignature).length;
|
|
1332
|
+
if (loopCount >= LOOP_THRESHOLD) {
|
|
1333
|
+
const warning = `Loop detected: you have called ${tc.function.name} with the same arguments multiple times in a row. Consider a different approach.`;
|
|
1334
|
+
const loopResult = {
|
|
1335
|
+
tool_call_id: tc.id,
|
|
1336
|
+
name: tc.function.name,
|
|
1337
|
+
content: warning,
|
|
1338
|
+
ok: false
|
|
1339
|
+
};
|
|
1340
|
+
toolResults.push(loopResult);
|
|
1341
|
+
opts2.messages.push({
|
|
1342
|
+
role: "tool",
|
|
1343
|
+
tool_call_id: tc.id,
|
|
1344
|
+
content: sanitizeString(warning),
|
|
1345
|
+
name: tc.function.name
|
|
1346
|
+
});
|
|
1347
|
+
opts2.callbacks.onToolResult?.(loopResult);
|
|
1348
|
+
recentToolCalls.push(loopSignature);
|
|
1349
|
+
if (recentToolCalls.length > LOOP_WINDOW) recentToolCalls.shift();
|
|
1350
|
+
continue;
|
|
1351
|
+
}
|
|
1316
1352
|
if (codeMode && tc.function.name === "execute_code") {
|
|
1317
1353
|
const args = JSON.parse(tc.function.arguments || "{}");
|
|
1318
1354
|
const code = args.code || "";
|
|
@@ -1353,6 +1389,8 @@ ${sandboxResult.output}` : sandboxResult.output;
|
|
|
1353
1389
|
name: "execute_code"
|
|
1354
1390
|
});
|
|
1355
1391
|
opts2.callbacks.onToolResult?.(result);
|
|
1392
|
+
recentToolCalls.push(loopSignature);
|
|
1393
|
+
if (recentToolCalls.length > LOOP_WINDOW) recentToolCalls.shift();
|
|
1356
1394
|
} else {
|
|
1357
1395
|
const result = await opts2.executor.run(
|
|
1358
1396
|
{ id: tc.id, name: tc.function.name, arguments: tc.function.arguments },
|
|
@@ -1367,6 +1405,8 @@ ${sandboxResult.output}` : sandboxResult.output;
|
|
|
1367
1405
|
name: result.name
|
|
1368
1406
|
});
|
|
1369
1407
|
opts2.callbacks.onToolResult?.(result);
|
|
1408
|
+
recentToolCalls.push(loopSignature);
|
|
1409
|
+
if (recentToolCalls.length > LOOP_WINDOW) recentToolCalls.shift();
|
|
1370
1410
|
}
|
|
1371
1411
|
}
|
|
1372
1412
|
if (opts2.sessionId && lastUsage) {
|
|
@@ -1392,6 +1432,7 @@ function validateToolArguments(raw) {
|
|
|
1392
1432
|
return "{}";
|
|
1393
1433
|
}
|
|
1394
1434
|
}
|
|
1435
|
+
var codeModeApiCache;
|
|
1395
1436
|
var init_loop = __esm({
|
|
1396
1437
|
"src/agent/loop.ts"() {
|
|
1397
1438
|
"use strict";
|
|
@@ -1401,6 +1442,7 @@ var init_loop = __esm({
|
|
|
1401
1442
|
init_cost_debug();
|
|
1402
1443
|
init_strip_reasoning();
|
|
1403
1444
|
init_code_mode();
|
|
1445
|
+
codeModeApiCache = /* @__PURE__ */ new Map();
|
|
1404
1446
|
}
|
|
1405
1447
|
});
|
|
1406
1448
|
|
|
@@ -3236,6 +3278,39 @@ function emptySessionState(task = "") {
|
|
|
3236
3278
|
artifact_index: {}
|
|
3237
3279
|
};
|
|
3238
3280
|
}
|
|
3281
|
+
function serializeArtifactStore(store) {
|
|
3282
|
+
const MAX_ARTIFACT_CHARS = 5e4;
|
|
3283
|
+
const out = [];
|
|
3284
|
+
for (const a of store.list()) {
|
|
3285
|
+
out.push({
|
|
3286
|
+
id: a.id,
|
|
3287
|
+
type: a.type,
|
|
3288
|
+
summary: a.summary,
|
|
3289
|
+
raw: a.raw.slice(0, MAX_ARTIFACT_CHARS),
|
|
3290
|
+
source: a.source,
|
|
3291
|
+
path: a.path,
|
|
3292
|
+
lineRange: a.lineRange,
|
|
3293
|
+
ts: a.ts
|
|
3294
|
+
});
|
|
3295
|
+
}
|
|
3296
|
+
return out;
|
|
3297
|
+
}
|
|
3298
|
+
function deserializeArtifactStore(data) {
|
|
3299
|
+
const store = new ArtifactStore();
|
|
3300
|
+
for (const a of data) {
|
|
3301
|
+
store.add({
|
|
3302
|
+
id: a.id,
|
|
3303
|
+
type: a.type,
|
|
3304
|
+
summary: a.summary,
|
|
3305
|
+
raw: a.raw,
|
|
3306
|
+
source: a.source,
|
|
3307
|
+
path: a.path,
|
|
3308
|
+
lineRange: a.lineRange,
|
|
3309
|
+
ts: a.ts
|
|
3310
|
+
});
|
|
3311
|
+
}
|
|
3312
|
+
return store;
|
|
3313
|
+
}
|
|
3239
3314
|
function formatRecalledArtifacts(recalled) {
|
|
3240
3315
|
if (recalled.length === 0) return "";
|
|
3241
3316
|
const lines = ["[recalled artifacts]"];
|
|
@@ -4101,6 +4176,12 @@ var init_chat = __esm({
|
|
|
4101
4176
|
evt.text
|
|
4102
4177
|
] });
|
|
4103
4178
|
}
|
|
4179
|
+
if (evt.kind === "memory") {
|
|
4180
|
+
return /* @__PURE__ */ jsxs4(Text4, { color: theme.info.color, dimColor: theme.info.dim, children: [
|
|
4181
|
+
"\u25C8 ",
|
|
4182
|
+
evt.text
|
|
4183
|
+
] });
|
|
4184
|
+
}
|
|
4104
4185
|
return /* @__PURE__ */ jsxs4(Text4, { color: theme.error, children: [
|
|
4105
4186
|
"! ",
|
|
4106
4187
|
evt.text
|
|
@@ -5427,7 +5508,7 @@ function HelpMenu({ theme, themes, currentThemeName, customCommands, onDone, onC
|
|
|
5427
5508
|
key: cat.key
|
|
5428
5509
|
}));
|
|
5429
5510
|
if (customs.length > 0) {
|
|
5430
|
-
items2.push({ label: "
|
|
5511
|
+
items2.push({ label: "Run custom commands", value: "custom", key: "custom" });
|
|
5431
5512
|
}
|
|
5432
5513
|
items2.push({ label: "(close)", value: "__close__", key: "__close__" });
|
|
5433
5514
|
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
@@ -5611,6 +5692,16 @@ var init_help_menu = __esm({
|
|
|
5611
5692
|
{ command: "/community", description: "join our Discord server" }
|
|
5612
5693
|
]
|
|
5613
5694
|
},
|
|
5695
|
+
{
|
|
5696
|
+
key: "commands",
|
|
5697
|
+
label: "Commands",
|
|
5698
|
+
commands: [
|
|
5699
|
+
{ command: "/command create", description: "create a new custom slash command" },
|
|
5700
|
+
{ command: "/command edit", description: "edit an existing custom command" },
|
|
5701
|
+
{ command: "/command delete", description: "delete a custom command" },
|
|
5702
|
+
{ command: "/command list", description: "list all custom commands" }
|
|
5703
|
+
]
|
|
5704
|
+
},
|
|
5614
5705
|
{
|
|
5615
5706
|
key: "config",
|
|
5616
5707
|
label: "Config",
|
|
@@ -6425,11 +6516,11 @@ function updateAccessedAt(db, ids) {
|
|
|
6425
6516
|
function searchMemoriesFts(db, query, repoPath, limit = 50) {
|
|
6426
6517
|
const sql = repoPath ? `SELECT m.*, rank FROM memories m
|
|
6427
6518
|
JOIN memories_fts fts ON m.rowid = fts.rowid
|
|
6428
|
-
WHERE memories_fts MATCH ? AND m.repo_path = ? AND m.forgotten = 0 AND m.superseded_by IS NULL
|
|
6519
|
+
WHERE memories_fts MATCH ? AND m.repo_path = ? AND m.forgotten = 0 AND m.superseded_by IS NULL AND m.category != 'task'
|
|
6429
6520
|
ORDER BY rank
|
|
6430
6521
|
LIMIT ?` : `SELECT m.*, rank FROM memories m
|
|
6431
6522
|
JOIN memories_fts fts ON m.rowid = fts.rowid
|
|
6432
|
-
WHERE memories_fts MATCH ? AND m.forgotten = 0 AND m.superseded_by IS NULL
|
|
6523
|
+
WHERE memories_fts MATCH ? AND m.forgotten = 0 AND m.superseded_by IS NULL AND m.category != 'task'
|
|
6433
6524
|
ORDER BY rank
|
|
6434
6525
|
LIMIT ?`;
|
|
6435
6526
|
const params = repoPath ? [`${query}*`, repoPath, limit] : [`${query}*`, limit];
|
|
@@ -6442,7 +6533,7 @@ function searchMemoriesFts(db, query, repoPath, limit = 50) {
|
|
|
6442
6533
|
function listMemoriesForVectorSearch(db, repoPath, since, limit = 2e3) {
|
|
6443
6534
|
const rows = db.prepare(
|
|
6444
6535
|
`SELECT * FROM memories
|
|
6445
|
-
WHERE repo_path = ? AND created_at >= ? AND forgotten = 0 AND superseded_by IS NULL
|
|
6536
|
+
WHERE repo_path = ? AND created_at >= ? AND forgotten = 0 AND superseded_by IS NULL AND category != 'task'
|
|
6446
6537
|
ORDER BY accessed_at DESC
|
|
6447
6538
|
LIMIT ?`
|
|
6448
6539
|
).all(repoPath, since, limit);
|
|
@@ -6889,7 +6980,20 @@ function redactSecrets(text) {
|
|
|
6889
6980
|
}
|
|
6890
6981
|
return result;
|
|
6891
6982
|
}
|
|
6892
|
-
|
|
6983
|
+
function deterministicTopicKey(content) {
|
|
6984
|
+
return content.toLowerCase().replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+/g, "_").slice(0, 60);
|
|
6985
|
+
}
|
|
6986
|
+
function pickTopicKey(content, existingKeys) {
|
|
6987
|
+
const normalized = deterministicTopicKey(content);
|
|
6988
|
+
if (!normalized) return null;
|
|
6989
|
+
for (const existing of existingKeys) {
|
|
6990
|
+
if (normalized.includes(existing) || existing.includes(normalized)) {
|
|
6991
|
+
return existing;
|
|
6992
|
+
}
|
|
6993
|
+
}
|
|
6994
|
+
return normalized;
|
|
6995
|
+
}
|
|
6996
|
+
var SECRET_PATTERNS, VERIFY_SYSTEM, HYPOTHETICAL_QUERIES_SYSTEM, MemoryManager;
|
|
6893
6997
|
var init_manager2 = __esm({
|
|
6894
6998
|
"src/memory/manager.ts"() {
|
|
6895
6999
|
"use strict";
|
|
@@ -6917,19 +7021,12 @@ Return a JSON object:
|
|
|
6917
7021
|
"confidence": "high" | "medium" | "low",
|
|
6918
7022
|
"corrected_content": string | null // if minor correction needed, provide it; otherwise null
|
|
6919
7023
|
}`;
|
|
6920
|
-
TOPIC_KEY_SYSTEM = `You are a topic normalization engine. Given a new memory and a list of existing topic keys for this project, decide whether the new memory belongs to an existing topic or needs a new one.
|
|
6921
|
-
|
|
6922
|
-
Rules:
|
|
6923
|
-
- Topic keys are lowercase snake_case, max 3 words.
|
|
6924
|
-
- If the new memory is about the same topic as an existing key, return the existing key.
|
|
6925
|
-
- If it's a genuinely new topic, generate a new normalized key.
|
|
6926
|
-
- Return ONLY the topic key string, nothing else.`;
|
|
6927
7024
|
HYPOTHETICAL_QUERIES_SYSTEM = `Given a memory, generate 3-5 short search queries a user might type to find it.
|
|
6928
7025
|
Cover different phrasings: declarative, interrogative, and keyword-based.
|
|
6929
7026
|
|
|
6930
7027
|
Return a JSON array of strings. Example:
|
|
6931
7028
|
["what package manager does this project use?", "pnpm preference", "user likes pnpm over npm"]`;
|
|
6932
|
-
MemoryManager = class {
|
|
7029
|
+
MemoryManager = class _MemoryManager {
|
|
6933
7030
|
db = null;
|
|
6934
7031
|
opts;
|
|
6935
7032
|
constructor(opts2) {
|
|
@@ -6957,6 +7054,14 @@ Return a JSON array of strings. Example:
|
|
|
6957
7054
|
gateway: this.opts.gateway
|
|
6958
7055
|
};
|
|
6959
7056
|
}
|
|
7057
|
+
get plumbingLlmOpts() {
|
|
7058
|
+
return {
|
|
7059
|
+
accountId: this.opts.accountId,
|
|
7060
|
+
apiToken: this.opts.apiToken,
|
|
7061
|
+
model: this.opts.plumbingModel ?? "@cf/meta/llama-4-scout-17b-16e-instruct",
|
|
7062
|
+
gateway: this.opts.gateway
|
|
7063
|
+
};
|
|
7064
|
+
}
|
|
6960
7065
|
shouldRedact() {
|
|
6961
7066
|
return this.opts.redactSecrets !== false;
|
|
6962
7067
|
}
|
|
@@ -6977,7 +7082,7 @@ Return a JSON array of strings. Example:
|
|
|
6977
7082
|
if (verified.corrected_content) {
|
|
6978
7083
|
safeContent = verified.corrected_content;
|
|
6979
7084
|
}
|
|
6980
|
-
const topicKey =
|
|
7085
|
+
const topicKey = this.normalizeTopicKey(safeContent, repoPath);
|
|
6981
7086
|
const supersededIds = [];
|
|
6982
7087
|
if (topicKey) {
|
|
6983
7088
|
const existing = findMemoriesByTopicKey(this.db, repoPath, topicKey);
|
|
@@ -7029,6 +7134,38 @@ Return a JSON array of strings. Example:
|
|
|
7029
7134
|
}
|
|
7030
7135
|
return retrieveMemories({ db: this.db, query });
|
|
7031
7136
|
}
|
|
7137
|
+
/**
|
|
7138
|
+
* Format recalled memories as a compact context block for injection into messages.
|
|
7139
|
+
*/
|
|
7140
|
+
static formatRecalled(results) {
|
|
7141
|
+
if (results.length === 0) return "";
|
|
7142
|
+
const lines = ["[recalled memories]"];
|
|
7143
|
+
for (const r of results) {
|
|
7144
|
+
const files = r.memory.relatedFiles.length > 0 ? ` [${r.memory.relatedFiles.join(", ")}]` : "";
|
|
7145
|
+
lines.push(`- [${r.memory.category}] ${r.memory.content}${files}`);
|
|
7146
|
+
}
|
|
7147
|
+
return lines.join("\n");
|
|
7148
|
+
}
|
|
7149
|
+
/**
|
|
7150
|
+
* Synthesize recalled memories into a dense prose paragraph.
|
|
7151
|
+
* Uses the lightweight plumbing model (Scout) to keep costs low.
|
|
7152
|
+
*/
|
|
7153
|
+
async synthesizeRecalled(results, signal) {
|
|
7154
|
+
if (results.length === 0) return "";
|
|
7155
|
+
const raw = _MemoryManager.formatRecalled(results);
|
|
7156
|
+
const text = await runKimiText({
|
|
7157
|
+
...this.plumbingLlmOpts,
|
|
7158
|
+
signal,
|
|
7159
|
+
messages: [
|
|
7160
|
+
{
|
|
7161
|
+
role: "system",
|
|
7162
|
+
content: "You are a context-synthesis engine. Given a list of recalled memories about a codebase, produce a single dense paragraph of context for a coding assistant. Preserve all facts, file paths, and decisions. Do not add information not present in the memories. Be terse."
|
|
7163
|
+
},
|
|
7164
|
+
{ role: "user", content: raw }
|
|
7165
|
+
]
|
|
7166
|
+
});
|
|
7167
|
+
return text || raw;
|
|
7168
|
+
}
|
|
7032
7169
|
/**
|
|
7033
7170
|
* Soft-delete a memory by ID.
|
|
7034
7171
|
*/
|
|
@@ -7088,7 +7225,7 @@ Return a JSON array of strings. Example:
|
|
|
7088
7225
|
}
|
|
7089
7226
|
async verifyMemory(content, signal) {
|
|
7090
7227
|
const text = await runKimiText({
|
|
7091
|
-
...this.
|
|
7228
|
+
...this.plumbingLlmOpts,
|
|
7092
7229
|
signal,
|
|
7093
7230
|
messages: [
|
|
7094
7231
|
{ role: "system", content: VERIFY_SYSTEM },
|
|
@@ -7112,31 +7249,13 @@ Context: This memory was explicitly provided by the user during a conversation.`
|
|
|
7112
7249
|
const corrected = typeof rec.corrected_content === "string" ? rec.corrected_content : null;
|
|
7113
7250
|
return { valid, corrected_content: corrected };
|
|
7114
7251
|
}
|
|
7115
|
-
|
|
7252
|
+
normalizeTopicKey(content, repoPath) {
|
|
7116
7253
|
const existingKeys = listTopicKeys(this.db, repoPath);
|
|
7117
|
-
|
|
7118
|
-
const text = await runKimiText({
|
|
7119
|
-
...this.llmOpts,
|
|
7120
|
-
signal,
|
|
7121
|
-
messages: [
|
|
7122
|
-
{ role: "system", content: TOPIC_KEY_SYSTEM },
|
|
7123
|
-
{
|
|
7124
|
-
role: "user",
|
|
7125
|
-
content: `Existing topic keys:
|
|
7126
|
-
${keysBlock}
|
|
7127
|
-
|
|
7128
|
-
New memory: "${content}"
|
|
7129
|
-
|
|
7130
|
-
Return only the topic key string.`
|
|
7131
|
-
}
|
|
7132
|
-
]
|
|
7133
|
-
});
|
|
7134
|
-
const key = text.trim().toLowerCase().replace(/\s+/g, "_").replace(/[^a-z0-9_]/g, "").slice(0, 60);
|
|
7135
|
-
return key || null;
|
|
7254
|
+
return pickTopicKey(content, existingKeys);
|
|
7136
7255
|
}
|
|
7137
7256
|
async generateHypotheticalQueries(content, signal) {
|
|
7138
7257
|
const text = await runKimiText({
|
|
7139
|
-
...this.
|
|
7258
|
+
...this.plumbingLlmOpts,
|
|
7140
7259
|
signal,
|
|
7141
7260
|
messages: [
|
|
7142
7261
|
{ role: "system", content: HYPOTHETICAL_QUERIES_SYSTEM },
|
|
@@ -7194,6 +7313,18 @@ var init_state = __esm({
|
|
|
7194
7313
|
});
|
|
7195
7314
|
|
|
7196
7315
|
// src/commands/frontmatter.ts
|
|
7316
|
+
function serializeFrontmatter(data) {
|
|
7317
|
+
const lines = [];
|
|
7318
|
+
for (const [key, value] of Object.entries(data)) {
|
|
7319
|
+
if (value === void 0 || value === "") continue;
|
|
7320
|
+
lines.push(`${key}: ${value}`);
|
|
7321
|
+
}
|
|
7322
|
+
if (lines.length === 0) return "";
|
|
7323
|
+
return `---
|
|
7324
|
+
${lines.join("\n")}
|
|
7325
|
+
---
|
|
7326
|
+
`;
|
|
7327
|
+
}
|
|
7197
7328
|
function parseFrontmatter(input) {
|
|
7198
7329
|
const errors = [];
|
|
7199
7330
|
if (!FENCE.test(input)) {
|
|
@@ -7532,19 +7663,566 @@ var init_renderer = __esm({
|
|
|
7532
7663
|
}
|
|
7533
7664
|
});
|
|
7534
7665
|
|
|
7666
|
+
// src/commands/save.ts
|
|
7667
|
+
import { mkdir as mkdir8, writeFile as writeFile8, unlink as unlink2 } from "fs/promises";
|
|
7668
|
+
import { dirname as dirname5 } from "path";
|
|
7669
|
+
async function saveCustomCommand(opts2) {
|
|
7670
|
+
const dir = opts2.source === "project" ? projectCommandsDir(opts2.cwd) : globalCommandsDir();
|
|
7671
|
+
const filepath = `${dir}/${opts2.name}.md`;
|
|
7672
|
+
const data = {};
|
|
7673
|
+
if (opts2.description) data.description = opts2.description;
|
|
7674
|
+
if (opts2.mode) data.mode = opts2.mode;
|
|
7675
|
+
if (opts2.model) data.model = opts2.model;
|
|
7676
|
+
if (opts2.effort) data.effort = opts2.effort;
|
|
7677
|
+
const frontmatter = serializeFrontmatter(data);
|
|
7678
|
+
const content = frontmatter + opts2.template;
|
|
7679
|
+
await mkdir8(dirname5(filepath), { recursive: true });
|
|
7680
|
+
await writeFile8(filepath, content, "utf8");
|
|
7681
|
+
return { filepath };
|
|
7682
|
+
}
|
|
7683
|
+
async function deleteCustomCommand(cmd) {
|
|
7684
|
+
await unlink2(cmd.filepath);
|
|
7685
|
+
}
|
|
7686
|
+
var init_save = __esm({
|
|
7687
|
+
"src/commands/save.ts"() {
|
|
7688
|
+
"use strict";
|
|
7689
|
+
init_frontmatter();
|
|
7690
|
+
init_loader();
|
|
7691
|
+
}
|
|
7692
|
+
});
|
|
7693
|
+
|
|
7694
|
+
// src/ui/command-wizard.tsx
|
|
7695
|
+
import { useState as useState7 } from "react";
|
|
7696
|
+
import { Box as Box13, Text as Text14, useInput as useInput3, useWindowSize as useWindowSize2 } from "ink";
|
|
7697
|
+
import SelectInput5 from "ink-select-input";
|
|
7698
|
+
import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
7699
|
+
function CommandWizard({ theme, mode, initial, existingNames, builtinNames, onDone, onSave }) {
|
|
7700
|
+
const [step, setStep] = useState7("name");
|
|
7701
|
+
const [name, setName] = useState7(initial?.name ?? "");
|
|
7702
|
+
const [description, setDescription] = useState7(initial?.description ?? "");
|
|
7703
|
+
const [template, setTemplate] = useState7(initial?.template ?? "");
|
|
7704
|
+
const [cmdMode, setCmdMode] = useState7(initial?.mode);
|
|
7705
|
+
const [cmdEffort, setCmdEffort] = useState7(initial?.effort);
|
|
7706
|
+
const [cmdModel, setCmdModel] = useState7(initial?.model);
|
|
7707
|
+
const [source, setSource] = useState7(initial?.source ?? "project");
|
|
7708
|
+
const [error, setError] = useState7(null);
|
|
7709
|
+
const { columns } = useWindowSize2();
|
|
7710
|
+
const totalSteps = 5;
|
|
7711
|
+
const stepIndex = step === "name" ? 1 : step === "description" ? 2 : step === "template" ? 3 : step === "advanced" || step === "mode" || step === "effort" || step === "model" ? 4 : step === "location" ? 4 : 5;
|
|
7712
|
+
const isEditingSelf = (n) => initial !== void 0 && initial.name === n;
|
|
7713
|
+
const validateName = (n) => {
|
|
7714
|
+
const trimmed = n.trim();
|
|
7715
|
+
if (!trimmed) return "name is required";
|
|
7716
|
+
if (!NAME_RE.test(trimmed)) return "invalid name: use letters, numbers, _ - / only; must start with a letter";
|
|
7717
|
+
if (builtinNames.has(trimmed.toLowerCase())) return `/${trimmed} is a built-in command`;
|
|
7718
|
+
if (existingNames.includes(trimmed) && !isEditingSelf(trimmed)) return `/${trimmed} already exists`;
|
|
7719
|
+
return null;
|
|
7720
|
+
};
|
|
7721
|
+
useInput3((_input, key) => {
|
|
7722
|
+
if (key.escape) {
|
|
7723
|
+
onDone();
|
|
7724
|
+
}
|
|
7725
|
+
});
|
|
7726
|
+
const handleNameSubmit = (value) => {
|
|
7727
|
+
const trimmed = value.trim();
|
|
7728
|
+
const err = validateName(trimmed);
|
|
7729
|
+
if (err) {
|
|
7730
|
+
setError(err);
|
|
7731
|
+
return;
|
|
7732
|
+
}
|
|
7733
|
+
setError(null);
|
|
7734
|
+
setName(trimmed);
|
|
7735
|
+
setStep("description");
|
|
7736
|
+
};
|
|
7737
|
+
const handleDescriptionSubmit = (value) => {
|
|
7738
|
+
setDescription(value.trim());
|
|
7739
|
+
setStep("template");
|
|
7740
|
+
};
|
|
7741
|
+
const handleTemplateSubmit = (value) => {
|
|
7742
|
+
const trimmed = value.trim();
|
|
7743
|
+
if (!trimmed) {
|
|
7744
|
+
setError("template cannot be empty");
|
|
7745
|
+
return;
|
|
7746
|
+
}
|
|
7747
|
+
setError(null);
|
|
7748
|
+
setTemplate(trimmed);
|
|
7749
|
+
setStep("advanced");
|
|
7750
|
+
};
|
|
7751
|
+
const handleAdvancedChoice = (choice) => {
|
|
7752
|
+
if (choice === "skip") {
|
|
7753
|
+
setCmdMode(void 0);
|
|
7754
|
+
setCmdEffort(void 0);
|
|
7755
|
+
setCmdModel("");
|
|
7756
|
+
if (mode === "edit" && initial) {
|
|
7757
|
+
setSource(initial.source);
|
|
7758
|
+
setStep("confirm");
|
|
7759
|
+
} else {
|
|
7760
|
+
setStep("location");
|
|
7761
|
+
}
|
|
7762
|
+
} else {
|
|
7763
|
+
setStep("mode");
|
|
7764
|
+
}
|
|
7765
|
+
};
|
|
7766
|
+
const handleModeChoice = (m) => {
|
|
7767
|
+
setCmdMode(m === "none" ? void 0 : m);
|
|
7768
|
+
setStep("effort");
|
|
7769
|
+
};
|
|
7770
|
+
const handleEffortChoice = (e) => {
|
|
7771
|
+
setCmdEffort(e === "none" ? void 0 : e);
|
|
7772
|
+
setStep("model");
|
|
7773
|
+
};
|
|
7774
|
+
const handleModelSubmit = (value) => {
|
|
7775
|
+
const trimmed = value.trim();
|
|
7776
|
+
setCmdModel(trimmed || void 0);
|
|
7777
|
+
if (mode === "edit" && initial) {
|
|
7778
|
+
setSource(initial.source);
|
|
7779
|
+
setStep("confirm");
|
|
7780
|
+
} else {
|
|
7781
|
+
setStep("location");
|
|
7782
|
+
}
|
|
7783
|
+
};
|
|
7784
|
+
const handleLocationChoice = (s) => {
|
|
7785
|
+
setSource(s);
|
|
7786
|
+
setStep("confirm");
|
|
7787
|
+
};
|
|
7788
|
+
const handleConfirm = (choice) => {
|
|
7789
|
+
if (choice === "cancel") {
|
|
7790
|
+
onDone();
|
|
7791
|
+
return;
|
|
7792
|
+
}
|
|
7793
|
+
onSave({
|
|
7794
|
+
name,
|
|
7795
|
+
description: description || void 0,
|
|
7796
|
+
template,
|
|
7797
|
+
source,
|
|
7798
|
+
mode: cmdMode,
|
|
7799
|
+
model: cmdModel || void 0,
|
|
7800
|
+
effort: cmdEffort
|
|
7801
|
+
});
|
|
7802
|
+
};
|
|
7803
|
+
const previewContent = () => {
|
|
7804
|
+
const data = {};
|
|
7805
|
+
if (description) data.description = description;
|
|
7806
|
+
if (cmdMode) data.mode = cmdMode;
|
|
7807
|
+
if (cmdModel) data.model = cmdModel;
|
|
7808
|
+
if (cmdEffort) data.effort = cmdEffort;
|
|
7809
|
+
const fm = Object.entries(data).map(([k, v]) => `${k}: ${v}`).join("\n");
|
|
7810
|
+
if (fm) {
|
|
7811
|
+
return `---
|
|
7812
|
+
${fm}
|
|
7813
|
+
---
|
|
7814
|
+
${template}`;
|
|
7815
|
+
}
|
|
7816
|
+
return template;
|
|
7817
|
+
};
|
|
7818
|
+
const renderStep = () => {
|
|
7819
|
+
switch (step) {
|
|
7820
|
+
case "name":
|
|
7821
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
7822
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
7823
|
+
mode === "create" ? "Create" : "Edit",
|
|
7824
|
+
" custom command \u2014 Name (",
|
|
7825
|
+
stepIndex,
|
|
7826
|
+
"/",
|
|
7827
|
+
totalSteps,
|
|
7828
|
+
")"
|
|
7829
|
+
] }),
|
|
7830
|
+
error && /* @__PURE__ */ jsx14(Text14, { color: theme.error, children: error }),
|
|
7831
|
+
/* @__PURE__ */ jsx14(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx14(
|
|
7832
|
+
CustomTextInput,
|
|
7833
|
+
{
|
|
7834
|
+
value: name,
|
|
7835
|
+
onChange: setName,
|
|
7836
|
+
onSubmit: handleNameSubmit,
|
|
7837
|
+
focus: true
|
|
7838
|
+
}
|
|
7839
|
+
) }),
|
|
7840
|
+
/* @__PURE__ */ jsx14(Text14, { color: theme.info.color, dimColor: true, children: "letters, numbers, _ - / only; must start with a letter" })
|
|
7841
|
+
] });
|
|
7842
|
+
case "description":
|
|
7843
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
7844
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
7845
|
+
mode === "create" ? "Create" : "Edit",
|
|
7846
|
+
" custom command \u2014 Description (",
|
|
7847
|
+
stepIndex,
|
|
7848
|
+
"/",
|
|
7849
|
+
totalSteps,
|
|
7850
|
+
")"
|
|
7851
|
+
] }),
|
|
7852
|
+
/* @__PURE__ */ jsx14(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx14(
|
|
7853
|
+
CustomTextInput,
|
|
7854
|
+
{
|
|
7855
|
+
value: description,
|
|
7856
|
+
onChange: setDescription,
|
|
7857
|
+
onSubmit: handleDescriptionSubmit,
|
|
7858
|
+
focus: true
|
|
7859
|
+
}
|
|
7860
|
+
) }),
|
|
7861
|
+
/* @__PURE__ */ jsx14(Text14, { color: theme.info.color, dimColor: true, children: "Press Enter to skip" })
|
|
7862
|
+
] });
|
|
7863
|
+
case "template": {
|
|
7864
|
+
const guide = /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", paddingLeft: 1, children: [
|
|
7865
|
+
/* @__PURE__ */ jsx14(Text14, { color: theme.accent, bold: true, children: "What is this?" }),
|
|
7866
|
+
/* @__PURE__ */ jsx14(Text14, { color: theme.info.color, dimColor: true, children: "A prompt template \u2014 instructions to the AI." }),
|
|
7867
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, dimColor: true, children: [
|
|
7868
|
+
"When you type /",
|
|
7869
|
+
name || "yourcommand",
|
|
7870
|
+
" later, this gets sent to the model."
|
|
7871
|
+
] }),
|
|
7872
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
|
|
7873
|
+
/* @__PURE__ */ jsx14(Text14, { color: theme.accent, bold: true, children: "Variables" }),
|
|
7874
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, dimColor: true, children: [
|
|
7875
|
+
" ",
|
|
7876
|
+
"$1, $2 ... \u2192 arguments you type"
|
|
7877
|
+
] }),
|
|
7878
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, dimColor: true, children: [
|
|
7879
|
+
" ",
|
|
7880
|
+
"$ARGUMENTS \u2192 everything after the command"
|
|
7881
|
+
] })
|
|
7882
|
+
] }),
|
|
7883
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
|
|
7884
|
+
/* @__PURE__ */ jsx14(Text14, { color: theme.accent, bold: true, children: "Dynamic inlines" }),
|
|
7885
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, dimColor: true, children: [
|
|
7886
|
+
" ",
|
|
7887
|
+
"!`git diff` \u2192 shell output inlined"
|
|
7888
|
+
] }),
|
|
7889
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, dimColor: true, children: [
|
|
7890
|
+
" ",
|
|
7891
|
+
"@README.md \u2192 file contents inlined"
|
|
7892
|
+
] })
|
|
7893
|
+
] }),
|
|
7894
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
|
|
7895
|
+
/* @__PURE__ */ jsx14(Text14, { color: theme.accent, bold: true, children: "Example" }),
|
|
7896
|
+
/* @__PURE__ */ jsx14(Text14, { color: theme.info.color, dimColor: true, children: "Review this PR diff:" }),
|
|
7897
|
+
/* @__PURE__ */ jsx14(Text14, { color: theme.info.color, dimColor: true, children: "!`git diff main...HEAD`" }),
|
|
7898
|
+
/* @__PURE__ */ jsx14(Text14, { color: theme.info.color, dimColor: true, children: "Focus on: $1" })
|
|
7899
|
+
] })
|
|
7900
|
+
] });
|
|
7901
|
+
const inputArea = /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", flexGrow: 1, children: [
|
|
7902
|
+
error && /* @__PURE__ */ jsx14(Text14, { color: theme.error, children: error }),
|
|
7903
|
+
/* @__PURE__ */ jsx14(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx14(
|
|
7904
|
+
CustomTextInput,
|
|
7905
|
+
{
|
|
7906
|
+
value: template,
|
|
7907
|
+
onChange: setTemplate,
|
|
7908
|
+
onSubmit: handleTemplateSubmit,
|
|
7909
|
+
focus: true,
|
|
7910
|
+
enablePaste: true
|
|
7911
|
+
}
|
|
7912
|
+
) }),
|
|
7913
|
+
columns < 100 && /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
7914
|
+
/* @__PURE__ */ jsx14(Text14, { color: theme.info.color, dimColor: true, children: "Paste multi-line templates with Ctrl+V." }),
|
|
7915
|
+
/* @__PURE__ */ jsx14(Text14, { color: theme.info.color, dimColor: true, children: "Variables: $1 $2 ... $ARGUMENTS Shell: !`cmd` File: @path" })
|
|
7916
|
+
] })
|
|
7917
|
+
] });
|
|
7918
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
7919
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
7920
|
+
mode === "create" ? "Create" : "Edit",
|
|
7921
|
+
" custom command \u2014 Template (",
|
|
7922
|
+
stepIndex,
|
|
7923
|
+
"/",
|
|
7924
|
+
totalSteps,
|
|
7925
|
+
")"
|
|
7926
|
+
] }),
|
|
7927
|
+
columns >= 100 ? /* @__PURE__ */ jsxs13(Box13, { flexDirection: "row", marginTop: 1, children: [
|
|
7928
|
+
/* @__PURE__ */ jsx14(Box13, { flexDirection: "column", width: "50%", children: inputArea }),
|
|
7929
|
+
/* @__PURE__ */ jsx14(Box13, { flexDirection: "column", width: "50%", children: guide })
|
|
7930
|
+
] }) : /* @__PURE__ */ jsx14(Box13, { flexDirection: "column", marginTop: 1, children: inputArea })
|
|
7931
|
+
] });
|
|
7932
|
+
}
|
|
7933
|
+
case "advanced": {
|
|
7934
|
+
const items = [
|
|
7935
|
+
{ label: "Set advanced options", value: "set", key: "set" },
|
|
7936
|
+
{ label: "Skip", value: "skip", key: "skip" },
|
|
7937
|
+
{ label: "\u2190 Cancel", value: "cancel", key: "cancel" }
|
|
7938
|
+
];
|
|
7939
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
7940
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
7941
|
+
mode === "create" ? "Create" : "Edit",
|
|
7942
|
+
" custom command \u2014 Options (",
|
|
7943
|
+
stepIndex,
|
|
7944
|
+
"/",
|
|
7945
|
+
totalSteps,
|
|
7946
|
+
")"
|
|
7947
|
+
] }),
|
|
7948
|
+
/* @__PURE__ */ jsx14(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx14(
|
|
7949
|
+
SelectInput5,
|
|
7950
|
+
{
|
|
7951
|
+
items,
|
|
7952
|
+
onSelect: (item) => {
|
|
7953
|
+
if (item.value === "cancel") onDone();
|
|
7954
|
+
else handleAdvancedChoice(item.value);
|
|
7955
|
+
}
|
|
7956
|
+
}
|
|
7957
|
+
) })
|
|
7958
|
+
] });
|
|
7959
|
+
}
|
|
7960
|
+
case "mode": {
|
|
7961
|
+
const items = [
|
|
7962
|
+
{ label: cmdMode === void 0 ? "none \xB7 current" : "none", value: "none", key: "none" },
|
|
7963
|
+
{ label: cmdMode === "edit" ? "edit \xB7 current" : "edit", value: "edit", key: "edit" },
|
|
7964
|
+
{ label: cmdMode === "plan" ? "plan \xB7 current" : "plan", value: "plan", key: "plan" },
|
|
7965
|
+
{ label: cmdMode === "auto" ? "auto \xB7 current" : "auto", value: "auto", key: "auto" },
|
|
7966
|
+
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
7967
|
+
];
|
|
7968
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
7969
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
7970
|
+
"Mode override (",
|
|
7971
|
+
stepIndex,
|
|
7972
|
+
"/",
|
|
7973
|
+
totalSteps,
|
|
7974
|
+
")"
|
|
7975
|
+
] }),
|
|
7976
|
+
/* @__PURE__ */ jsx14(Text14, { color: theme.info.color, dimColor: true, children: "Saved to file but not yet enforced at runtime" }),
|
|
7977
|
+
/* @__PURE__ */ jsx14(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx14(
|
|
7978
|
+
SelectInput5,
|
|
7979
|
+
{
|
|
7980
|
+
items,
|
|
7981
|
+
onSelect: (item) => {
|
|
7982
|
+
if (item.value === "__back__") setStep("advanced");
|
|
7983
|
+
else handleModeChoice(item.value);
|
|
7984
|
+
}
|
|
7985
|
+
}
|
|
7986
|
+
) })
|
|
7987
|
+
] });
|
|
7988
|
+
}
|
|
7989
|
+
case "effort": {
|
|
7990
|
+
const items = [
|
|
7991
|
+
{ label: cmdEffort === void 0 ? "none \xB7 current" : "none", value: "none", key: "none" },
|
|
7992
|
+
{ label: cmdEffort === "low" ? "low \xB7 current" : "low", value: "low", key: "low" },
|
|
7993
|
+
{ label: cmdEffort === "medium" ? "medium \xB7 current" : "medium", value: "medium", key: "medium" },
|
|
7994
|
+
{ label: cmdEffort === "high" ? "high \xB7 current" : "high", value: "high", key: "high" },
|
|
7995
|
+
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
7996
|
+
];
|
|
7997
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
7998
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
7999
|
+
"Reasoning effort (",
|
|
8000
|
+
stepIndex,
|
|
8001
|
+
"/",
|
|
8002
|
+
totalSteps,
|
|
8003
|
+
")"
|
|
8004
|
+
] }),
|
|
8005
|
+
/* @__PURE__ */ jsx14(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx14(
|
|
8006
|
+
SelectInput5,
|
|
8007
|
+
{
|
|
8008
|
+
items,
|
|
8009
|
+
onSelect: (item) => {
|
|
8010
|
+
if (item.value === "__back__") setStep("mode");
|
|
8011
|
+
else handleEffortChoice(item.value);
|
|
8012
|
+
}
|
|
8013
|
+
}
|
|
8014
|
+
) })
|
|
8015
|
+
] });
|
|
8016
|
+
}
|
|
8017
|
+
case "model":
|
|
8018
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
8019
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
8020
|
+
"Model override (",
|
|
8021
|
+
stepIndex,
|
|
8022
|
+
"/",
|
|
8023
|
+
totalSteps,
|
|
8024
|
+
")"
|
|
8025
|
+
] }),
|
|
8026
|
+
/* @__PURE__ */ jsx14(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx14(
|
|
8027
|
+
CustomTextInput,
|
|
8028
|
+
{
|
|
8029
|
+
value: cmdModel ?? "",
|
|
8030
|
+
onChange: setCmdModel,
|
|
8031
|
+
onSubmit: handleModelSubmit,
|
|
8032
|
+
focus: true
|
|
8033
|
+
}
|
|
8034
|
+
) }),
|
|
8035
|
+
/* @__PURE__ */ jsx14(Text14, { color: theme.info.color, dimColor: true, children: "Press Enter to skip" })
|
|
8036
|
+
] });
|
|
8037
|
+
case "location": {
|
|
8038
|
+
const items = [
|
|
8039
|
+
{ label: source === "project" ? "Project \xB7 current" : "Project", value: "project", key: "project" },
|
|
8040
|
+
{ label: source === "global" ? "Global \xB7 current" : "Global", value: "global", key: "global" },
|
|
8041
|
+
{ label: "\u2190 Back", value: "__back__", key: "__back__" }
|
|
8042
|
+
];
|
|
8043
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
8044
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
8045
|
+
"Save location (",
|
|
8046
|
+
stepIndex,
|
|
8047
|
+
"/",
|
|
8048
|
+
totalSteps,
|
|
8049
|
+
")"
|
|
8050
|
+
] }),
|
|
8051
|
+
/* @__PURE__ */ jsx14(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx14(
|
|
8052
|
+
SelectInput5,
|
|
8053
|
+
{
|
|
8054
|
+
items,
|
|
8055
|
+
onSelect: (item) => {
|
|
8056
|
+
if (item.value === "__back__") setStep("advanced");
|
|
8057
|
+
else handleLocationChoice(item.value);
|
|
8058
|
+
}
|
|
8059
|
+
}
|
|
8060
|
+
) }),
|
|
8061
|
+
/* @__PURE__ */ jsx14(Text14, { color: theme.info.color, dimColor: true, children: "Project: .kimiflare/commands/ Global: ~/.config/kimiflare/commands/" })
|
|
8062
|
+
] });
|
|
8063
|
+
}
|
|
8064
|
+
case "confirm": {
|
|
8065
|
+
const items = [
|
|
8066
|
+
{ label: "Save", value: "save", key: "save" },
|
|
8067
|
+
{ label: "Cancel", value: "cancel", key: "cancel" }
|
|
8068
|
+
];
|
|
8069
|
+
return /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
8070
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.accent, bold: true, children: [
|
|
8071
|
+
mode === "create" ? "Create" : "Edit",
|
|
8072
|
+
" custom command \u2014 Confirm (",
|
|
8073
|
+
stepIndex,
|
|
8074
|
+
"/",
|
|
8075
|
+
totalSteps,
|
|
8076
|
+
")"
|
|
8077
|
+
] }),
|
|
8078
|
+
/* @__PURE__ */ jsxs13(Text14, { color: theme.info.color, dimColor: true, children: [
|
|
8079
|
+
source === "project" ? ".kimiflare/commands/" : "~/.config/kimiflare/commands/",
|
|
8080
|
+
name,
|
|
8081
|
+
".md"
|
|
8082
|
+
] }),
|
|
8083
|
+
/* @__PURE__ */ jsx14(Box13, { marginTop: 1, flexDirection: "column", children: previewContent().split("\n").map((line, i) => /* @__PURE__ */ jsx14(Text14, { color: theme.info.color, dimColor: true, children: line || " " }, i)) }),
|
|
8084
|
+
/* @__PURE__ */ jsx14(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx14(
|
|
8085
|
+
SelectInput5,
|
|
8086
|
+
{
|
|
8087
|
+
items,
|
|
8088
|
+
onSelect: (item) => handleConfirm(item.value)
|
|
8089
|
+
}
|
|
8090
|
+
) })
|
|
8091
|
+
] });
|
|
8092
|
+
}
|
|
8093
|
+
}
|
|
8094
|
+
};
|
|
8095
|
+
return /* @__PURE__ */ jsx14(Box13, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: renderStep() });
|
|
8096
|
+
}
|
|
8097
|
+
var NAME_RE;
|
|
8098
|
+
var init_command_wizard = __esm({
|
|
8099
|
+
"src/ui/command-wizard.tsx"() {
|
|
8100
|
+
"use strict";
|
|
8101
|
+
init_text_input();
|
|
8102
|
+
NAME_RE = /^[a-zA-Z][a-zA-Z0-9_\-/]*$/;
|
|
8103
|
+
}
|
|
8104
|
+
});
|
|
8105
|
+
|
|
8106
|
+
// src/ui/command-picker.tsx
|
|
8107
|
+
import { Box as Box14, Text as Text15 } from "ink";
|
|
8108
|
+
import SelectInput6 from "ink-select-input";
|
|
8109
|
+
import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
8110
|
+
function CommandPicker({ theme, commands, title, onPick }) {
|
|
8111
|
+
const items = commands.map((cmd) => ({
|
|
8112
|
+
label: `/${cmd.name.padEnd(20)} ${cmd.description ?? ""}`,
|
|
8113
|
+
value: cmd,
|
|
8114
|
+
key: cmd.name
|
|
8115
|
+
}));
|
|
8116
|
+
items.push({ label: "\u2190 Cancel", value: null, key: "__cancel__" });
|
|
8117
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
8118
|
+
/* @__PURE__ */ jsx15(Text15, { color: theme.accent, bold: true, children: title }),
|
|
8119
|
+
/* @__PURE__ */ jsx15(Text15, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select." }),
|
|
8120
|
+
/* @__PURE__ */ jsx15(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx15(
|
|
8121
|
+
SelectInput6,
|
|
8122
|
+
{
|
|
8123
|
+
items,
|
|
8124
|
+
onSelect: (item) => {
|
|
8125
|
+
if (item.key === "__cancel__") {
|
|
8126
|
+
onPick(null);
|
|
8127
|
+
} else {
|
|
8128
|
+
onPick(item.value);
|
|
8129
|
+
}
|
|
8130
|
+
}
|
|
8131
|
+
}
|
|
8132
|
+
) })
|
|
8133
|
+
] });
|
|
8134
|
+
}
|
|
8135
|
+
var init_command_picker = __esm({
|
|
8136
|
+
"src/ui/command-picker.tsx"() {
|
|
8137
|
+
"use strict";
|
|
8138
|
+
}
|
|
8139
|
+
});
|
|
8140
|
+
|
|
8141
|
+
// src/ui/command-list.tsx
|
|
8142
|
+
import { Box as Box15, Text as Text16, useInput as useInput4 } from "ink";
|
|
8143
|
+
import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
8144
|
+
function CommandList({ theme, commands, onDone }) {
|
|
8145
|
+
useInput4((_input, key) => {
|
|
8146
|
+
if (key.escape) {
|
|
8147
|
+
onDone();
|
|
8148
|
+
}
|
|
8149
|
+
});
|
|
8150
|
+
return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
8151
|
+
/* @__PURE__ */ jsx16(Text16, { color: theme.accent, bold: true, children: "Custom commands" }),
|
|
8152
|
+
/* @__PURE__ */ jsx16(Text16, { color: theme.info.color, dimColor: false, children: "Esc to close." }),
|
|
8153
|
+
/* @__PURE__ */ jsxs15(Box15, { marginTop: 1, flexDirection: "column", children: [
|
|
8154
|
+
commands.length === 0 && /* @__PURE__ */ jsx16(Text16, { color: theme.info.color, dimColor: true, children: "No custom commands found." }),
|
|
8155
|
+
commands.map((cmd) => /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", marginBottom: 1, children: [
|
|
8156
|
+
/* @__PURE__ */ jsxs15(Text16, { color: theme.accent, bold: true, children: [
|
|
8157
|
+
"/",
|
|
8158
|
+
cmd.name
|
|
8159
|
+
] }),
|
|
8160
|
+
/* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, dimColor: true, children: [
|
|
8161
|
+
" ",
|
|
8162
|
+
"source: ",
|
|
8163
|
+
cmd.source
|
|
8164
|
+
] }),
|
|
8165
|
+
/* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, dimColor: true, children: [
|
|
8166
|
+
" ",
|
|
8167
|
+
"path: ",
|
|
8168
|
+
cmd.filepath
|
|
8169
|
+
] }),
|
|
8170
|
+
cmd.description && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, dimColor: true, children: [
|
|
8171
|
+
" ",
|
|
8172
|
+
"desc: ",
|
|
8173
|
+
cmd.description
|
|
8174
|
+
] }),
|
|
8175
|
+
cmd.mode && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, dimColor: true, children: [
|
|
8176
|
+
" ",
|
|
8177
|
+
"mode: ",
|
|
8178
|
+
cmd.mode
|
|
8179
|
+
] }),
|
|
8180
|
+
cmd.effort && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, dimColor: true, children: [
|
|
8181
|
+
" ",
|
|
8182
|
+
"effort: ",
|
|
8183
|
+
cmd.effort
|
|
8184
|
+
] }),
|
|
8185
|
+
cmd.model && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, dimColor: true, children: [
|
|
8186
|
+
" ",
|
|
8187
|
+
"model: ",
|
|
8188
|
+
cmd.model
|
|
8189
|
+
] }),
|
|
8190
|
+
/* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, dimColor: true, children: [
|
|
8191
|
+
" ",
|
|
8192
|
+
"template:"
|
|
8193
|
+
] }),
|
|
8194
|
+
cmd.template.split("\n").slice(0, 5).map((line, i) => /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, dimColor: true, children: [
|
|
8195
|
+
" ",
|
|
8196
|
+
line || " "
|
|
8197
|
+
] }, i)),
|
|
8198
|
+
cmd.template.split("\n").length > 5 && /* @__PURE__ */ jsxs15(Text16, { color: theme.info.color, dimColor: true, children: [
|
|
8199
|
+
" ",
|
|
8200
|
+
"..."
|
|
8201
|
+
] })
|
|
8202
|
+
] }, cmd.name))
|
|
8203
|
+
] })
|
|
8204
|
+
] });
|
|
8205
|
+
}
|
|
8206
|
+
var init_command_list = __esm({
|
|
8207
|
+
"src/ui/command-list.tsx"() {
|
|
8208
|
+
"use strict";
|
|
8209
|
+
}
|
|
8210
|
+
});
|
|
8211
|
+
|
|
7535
8212
|
// src/app.tsx
|
|
7536
8213
|
var app_exports = {};
|
|
7537
8214
|
__export(app_exports, {
|
|
7538
8215
|
renderApp: () => renderApp
|
|
7539
8216
|
});
|
|
7540
|
-
import { useState as
|
|
7541
|
-
import { Box as
|
|
8217
|
+
import { useState as useState8, useRef as useRef3, useEffect as useEffect4, useCallback } from "react";
|
|
8218
|
+
import { Box as Box16, Text as Text17, useApp, useInput as useInput5, render } from "ink";
|
|
8219
|
+
import SelectInput7 from "ink-select-input";
|
|
7542
8220
|
import { existsSync } from "fs";
|
|
7543
8221
|
import { join as join13 } from "path";
|
|
7544
|
-
import { unlink as
|
|
8222
|
+
import { unlink as unlink3 } from "fs/promises";
|
|
7545
8223
|
import { spawn as spawn2 } from "child_process";
|
|
7546
8224
|
import { platform as platform2 } from "os";
|
|
7547
|
-
import { jsx as
|
|
8225
|
+
import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
7548
8226
|
function gatewayFromConfig(cfg) {
|
|
7549
8227
|
if (!cfg.aiGatewayId) return void 0;
|
|
7550
8228
|
return {
|
|
@@ -7605,18 +8283,29 @@ function makePrefixMessages(cacheStable, model, mode, tools) {
|
|
|
7605
8283
|
}
|
|
7606
8284
|
function findImagePaths(text) {
|
|
7607
8285
|
const paths = [];
|
|
7608
|
-
|
|
7609
|
-
|
|
7610
|
-
|
|
8286
|
+
const quotedRegex = /"([^"]+)"|'([^']+)'/g;
|
|
8287
|
+
let match;
|
|
8288
|
+
while ((match = quotedRegex.exec(text)) !== null) {
|
|
8289
|
+
const path = match[1] ?? match[2];
|
|
8290
|
+
if (path && isImagePath(path) && existsSync(path)) {
|
|
8291
|
+
paths.push(path);
|
|
8292
|
+
}
|
|
8293
|
+
}
|
|
8294
|
+
const remaining = text.replace(/"[^"]+"|'[^']+'/g, "");
|
|
8295
|
+
const ESCAPED_SPACE = "\0";
|
|
8296
|
+
const processed = remaining.replace(/\\ /g, ESCAPED_SPACE);
|
|
8297
|
+
for (const token of processed.split(/\s+/)) {
|
|
8298
|
+
const clean = token.replace(new RegExp(ESCAPED_SPACE, "g"), " ").replace(/^["']|["',;:!?]$/g, "").replace(/[.,;:!?]$/, "");
|
|
8299
|
+
if (clean && isImagePath(clean) && existsSync(clean) && !paths.includes(clean)) {
|
|
7611
8300
|
paths.push(clean);
|
|
7612
8301
|
}
|
|
7613
8302
|
}
|
|
7614
|
-
return
|
|
8303
|
+
return paths;
|
|
7615
8304
|
}
|
|
7616
8305
|
function App({ initialCfg, initialUpdateResult }) {
|
|
7617
8306
|
const { exit } = useApp();
|
|
7618
|
-
const [cfg, setCfg] =
|
|
7619
|
-
const [events, setRawEvents] =
|
|
8307
|
+
const [cfg, setCfg] = useState8(initialCfg);
|
|
8308
|
+
const [events, setRawEvents] = useState8([]);
|
|
7620
8309
|
const setEvents = useCallback(
|
|
7621
8310
|
(updater) => {
|
|
7622
8311
|
setRawEvents((prev) => {
|
|
@@ -7626,34 +8315,38 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7626
8315
|
},
|
|
7627
8316
|
[]
|
|
7628
8317
|
);
|
|
7629
|
-
const [input, setInput] =
|
|
7630
|
-
const [busy, setBusy] =
|
|
7631
|
-
const [usage, setUsage] =
|
|
7632
|
-
const [sessionUsage, setSessionUsage] =
|
|
7633
|
-
const [gatewayMeta, setGatewayMeta] =
|
|
7634
|
-
const [showReasoning, setShowReasoning] =
|
|
7635
|
-
const [perm, setPerm] =
|
|
7636
|
-
const [queue, setQueue] =
|
|
7637
|
-
const [history, setHistory] =
|
|
7638
|
-
const [historyIndex, setHistoryIndex] =
|
|
7639
|
-
const [draftInput, setDraftInput] =
|
|
7640
|
-
const [mode, setMode] =
|
|
7641
|
-
const [codeMode, setCodeMode] =
|
|
7642
|
-
const [effort, setEffort] =
|
|
8318
|
+
const [input, setInput] = useState8("");
|
|
8319
|
+
const [busy, setBusy] = useState8(false);
|
|
8320
|
+
const [usage, setUsage] = useState8(null);
|
|
8321
|
+
const [sessionUsage, setSessionUsage] = useState8(null);
|
|
8322
|
+
const [gatewayMeta, setGatewayMeta] = useState8(null);
|
|
8323
|
+
const [showReasoning, setShowReasoning] = useState8(false);
|
|
8324
|
+
const [perm, setPerm] = useState8(null);
|
|
8325
|
+
const [queue, setQueue] = useState8([]);
|
|
8326
|
+
const [history, setHistory] = useState8([]);
|
|
8327
|
+
const [historyIndex, setHistoryIndex] = useState8(-1);
|
|
8328
|
+
const [draftInput, setDraftInput] = useState8("");
|
|
8329
|
+
const [mode, setMode] = useState8("edit");
|
|
8330
|
+
const [codeMode, setCodeMode] = useState8(initialCfg?.codeMode ?? false);
|
|
8331
|
+
const [effort, setEffort] = useState8(
|
|
7643
8332
|
initialCfg?.reasoningEffort ?? DEFAULT_REASONING_EFFORT
|
|
7644
8333
|
);
|
|
7645
|
-
const [theme, setTheme] =
|
|
7646
|
-
const [resumeSessions, setResumeSessions] =
|
|
7647
|
-
const [showThemePicker, setShowThemePicker] =
|
|
7648
|
-
const [showHelpMenu, setShowHelpMenu] =
|
|
7649
|
-
const [originalTheme, setOriginalTheme] =
|
|
7650
|
-
const [
|
|
7651
|
-
const [
|
|
7652
|
-
const [
|
|
7653
|
-
const [
|
|
7654
|
-
const [
|
|
7655
|
-
const [
|
|
7656
|
-
const [
|
|
8334
|
+
const [theme, setTheme] = useState8(resolveTheme(initialCfg?.theme));
|
|
8335
|
+
const [resumeSessions, setResumeSessions] = useState8(null);
|
|
8336
|
+
const [showThemePicker, setShowThemePicker] = useState8(false);
|
|
8337
|
+
const [showHelpMenu, setShowHelpMenu] = useState8(false);
|
|
8338
|
+
const [originalTheme, setOriginalTheme] = useState8(null);
|
|
8339
|
+
const [commandWizard, setCommandWizard] = useState8(null);
|
|
8340
|
+
const [commandPicker, setCommandPicker] = useState8(null);
|
|
8341
|
+
const [commandToDelete, setCommandToDelete] = useState8(null);
|
|
8342
|
+
const [showCommandList, setShowCommandList] = useState8(false);
|
|
8343
|
+
const [tasks, setTasks] = useState8([]);
|
|
8344
|
+
const [tasksStartedAt, setTasksStartedAt] = useState8(null);
|
|
8345
|
+
const [tasksStartTokens, setTasksStartTokens] = useState8(0);
|
|
8346
|
+
const [turnStartedAt, setTurnStartedAt] = useState8(null);
|
|
8347
|
+
const [verbose, setVerbose] = useState8(false);
|
|
8348
|
+
const [hasUpdate, setHasUpdate] = useState8(initialUpdateResult?.hasUpdate ?? false);
|
|
8349
|
+
const [latestVersion, setLatestVersion] = useState8(initialUpdateResult?.latestVersion ?? null);
|
|
7657
8350
|
const cacheStableRef = useRef3(initialCfg?.cacheStablePrompts !== false);
|
|
7658
8351
|
const messagesRef = useRef3(
|
|
7659
8352
|
makePrefixMessages(cacheStableRef.current, cfg?.model ?? DEFAULT_MODEL, "edit", ALL_TOOLS)
|
|
@@ -7677,6 +8370,7 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7677
8370
|
const mcpToolsRef = useRef3([]);
|
|
7678
8371
|
const mcpInitRef = useRef3(false);
|
|
7679
8372
|
const memoryManagerRef = useRef3(null);
|
|
8373
|
+
const sessionStartRecallRef = useRef3(null);
|
|
7680
8374
|
const pendingTextRef = useRef3(/* @__PURE__ */ new Map());
|
|
7681
8375
|
const flushTimeoutRef = useRef3(null);
|
|
7682
8376
|
const customCommandsRef = useRef3([]);
|
|
@@ -7712,6 +8406,7 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7712
8406
|
accountId: cfg.accountId,
|
|
7713
8407
|
apiToken: cfg.apiToken,
|
|
7714
8408
|
model: cfg.model,
|
|
8409
|
+
plumbingModel: cfg.plumbingModel,
|
|
7715
8410
|
embeddingModel: cfg.memoryEmbeddingModel,
|
|
7716
8411
|
gateway: gatewayFromConfig(cfg),
|
|
7717
8412
|
maxAgeDays: cfg.memoryMaxAgeDays ?? RETENTION.memoryMaxAgeDays,
|
|
@@ -7724,7 +8419,7 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7724
8419
|
if (total > 0) {
|
|
7725
8420
|
setEvents((e) => [
|
|
7726
8421
|
...e,
|
|
7727
|
-
{ kind: "
|
|
8422
|
+
{ kind: "memory", key: mkKey(), text: `memory cleanup: removed ${total} stale entries` }
|
|
7728
8423
|
]);
|
|
7729
8424
|
}
|
|
7730
8425
|
});
|
|
@@ -7732,10 +8427,27 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7732
8427
|
if (fixed > 0) {
|
|
7733
8428
|
setEvents((e) => [
|
|
7734
8429
|
...e,
|
|
7735
|
-
{ kind: "
|
|
8430
|
+
{ kind: "memory", key: mkKey(), text: `memory backfill: embedded ${fixed} un-vectorized entries` }
|
|
7736
8431
|
]);
|
|
7737
8432
|
}
|
|
7738
8433
|
});
|
|
8434
|
+
const cwd = process.cwd();
|
|
8435
|
+
sessionStartRecallRef.current = (async () => {
|
|
8436
|
+
try {
|
|
8437
|
+
const results = await manager.recall({ text: cwd, repoPath: cwd, limit: 5 });
|
|
8438
|
+
if (results.length > 0) {
|
|
8439
|
+
const text = await manager.synthesizeRecalled(results);
|
|
8440
|
+
const lastSystemIdx = messagesRef.current.findLastIndex((m) => m.role === "system");
|
|
8441
|
+
const insertIdx = lastSystemIdx >= 0 ? lastSystemIdx + 1 : messagesRef.current.length;
|
|
8442
|
+
messagesRef.current.splice(insertIdx, 0, { role: "system", content: text });
|
|
8443
|
+
setEvents((e) => [
|
|
8444
|
+
...e,
|
|
8445
|
+
{ kind: "memory", key: mkKey(), text: `recalled ${results.length} memory${results.length === 1 ? "" : "ies"} about this repo` }
|
|
8446
|
+
]);
|
|
8447
|
+
}
|
|
8448
|
+
} catch {
|
|
8449
|
+
}
|
|
8450
|
+
})();
|
|
7739
8451
|
} else {
|
|
7740
8452
|
memoryManagerRef.current?.close();
|
|
7741
8453
|
memoryManagerRef.current = null;
|
|
@@ -7754,6 +8466,20 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7754
8466
|
}
|
|
7755
8467
|
});
|
|
7756
8468
|
}, [cfg, setEvents]);
|
|
8469
|
+
const reloadCustomCommands = useCallback(async () => {
|
|
8470
|
+
const { commands, warnings } = await loadCustomCommands(process.cwd());
|
|
8471
|
+
customCommandsRef.current = commands;
|
|
8472
|
+
for (const w of warnings) {
|
|
8473
|
+
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: `commands: ${w}` }]);
|
|
8474
|
+
}
|
|
8475
|
+
const shadowed = commands.filter((c) => BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase()));
|
|
8476
|
+
for (const c of shadowed) {
|
|
8477
|
+
setEvents((e) => [
|
|
8478
|
+
...e,
|
|
8479
|
+
{ kind: "info", key: mkKey(), text: `commands: /${c.name} (${c.filepath}) shadowed by built-in \u2014 will not run` }
|
|
8480
|
+
]);
|
|
8481
|
+
}
|
|
8482
|
+
}, [setEvents]);
|
|
7757
8483
|
useEffect4(() => {
|
|
7758
8484
|
if (!cfg || updateCheckedRef.current) return;
|
|
7759
8485
|
updateCheckedRef.current = true;
|
|
@@ -7956,12 +8682,13 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7956
8682
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7957
8683
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7958
8684
|
messages: messagesRef.current,
|
|
7959
|
-
sessionState: compiledContextRef.current ? sessionStateRef.current : void 0
|
|
8685
|
+
sessionState: compiledContextRef.current ? sessionStateRef.current : void 0,
|
|
8686
|
+
artifactStore: serializeArtifactStore(artifactStoreRef.current)
|
|
7960
8687
|
});
|
|
7961
8688
|
} catch {
|
|
7962
8689
|
}
|
|
7963
8690
|
}, [cfg, ensureSessionId]);
|
|
7964
|
-
|
|
8691
|
+
useInput5((inputChar, key) => {
|
|
7965
8692
|
if (key.ctrl && inputChar === "c") {
|
|
7966
8693
|
if (busy && activeControllerRef.current) {
|
|
7967
8694
|
activeControllerRef.current.abort();
|
|
@@ -8337,8 +9064,26 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
8337
9064
|
sessionIdRef.current = file.id;
|
|
8338
9065
|
if (file.sessionState && compiledContextRef.current) {
|
|
8339
9066
|
sessionStateRef.current = file.sessionState;
|
|
9067
|
+
}
|
|
9068
|
+
if (file.artifactStore) {
|
|
9069
|
+
artifactStoreRef.current = deserializeArtifactStore(file.artifactStore);
|
|
9070
|
+
} else {
|
|
8340
9071
|
artifactStoreRef.current = new ArtifactStore();
|
|
8341
9072
|
}
|
|
9073
|
+
const manager = memoryManagerRef.current;
|
|
9074
|
+
if (manager) {
|
|
9075
|
+
try {
|
|
9076
|
+
const cwd = process.cwd();
|
|
9077
|
+
const results = await manager.recall({ text: cwd, repoPath: cwd, limit: 5 });
|
|
9078
|
+
if (results.length > 0) {
|
|
9079
|
+
const text = await manager.synthesizeRecalled(results);
|
|
9080
|
+
const lastSystemIdx = messagesRef.current.findLastIndex((m) => m.role === "system");
|
|
9081
|
+
const insertIdx = lastSystemIdx >= 0 ? lastSystemIdx + 1 : messagesRef.current.length;
|
|
9082
|
+
messagesRef.current.splice(insertIdx, 0, { role: "system", content: text });
|
|
9083
|
+
}
|
|
9084
|
+
} catch {
|
|
9085
|
+
}
|
|
9086
|
+
}
|
|
8342
9087
|
setEvents([
|
|
8343
9088
|
{
|
|
8344
9089
|
kind: "info",
|
|
@@ -8656,7 +9401,7 @@ use: /thinking low | medium | high`
|
|
|
8656
9401
|
setCfg(next);
|
|
8657
9402
|
void saveConfig(next).catch(() => {
|
|
8658
9403
|
});
|
|
8659
|
-
setEvents((e) => [...e, { kind: "
|
|
9404
|
+
setEvents((e) => [...e, { kind: "memory", key: mkKey(), text: "memory enabled" }]);
|
|
8660
9405
|
return true;
|
|
8661
9406
|
}
|
|
8662
9407
|
if (arg === "off") {
|
|
@@ -8664,7 +9409,7 @@ use: /thinking low | medium | high`
|
|
|
8664
9409
|
setCfg(next);
|
|
8665
9410
|
void saveConfig(next).catch(() => {
|
|
8666
9411
|
});
|
|
8667
|
-
setEvents((e) => [...e, { kind: "
|
|
9412
|
+
setEvents((e) => [...e, { kind: "memory", key: mkKey(), text: "memory disabled" }]);
|
|
8668
9413
|
return true;
|
|
8669
9414
|
}
|
|
8670
9415
|
if (!cfg.memoryEnabled) {
|
|
@@ -8673,7 +9418,7 @@ use: /thinking low | medium | high`
|
|
|
8673
9418
|
}
|
|
8674
9419
|
if (arg === "clear") {
|
|
8675
9420
|
const cleared = memoryManagerRef.current?.clearRepo(process.cwd()) ?? 0;
|
|
8676
|
-
setEvents((e) => [...e, { kind: "
|
|
9421
|
+
setEvents((e) => [...e, { kind: "memory", key: mkKey(), text: `cleared ${cleared} memories for this repo` }]);
|
|
8677
9422
|
return true;
|
|
8678
9423
|
}
|
|
8679
9424
|
if (arg.startsWith("search ")) {
|
|
@@ -8808,7 +9553,7 @@ ${lines.join("\n")}` }]);
|
|
|
8808
9553
|
return true;
|
|
8809
9554
|
}
|
|
8810
9555
|
if (c === "/logout") {
|
|
8811
|
-
|
|
9556
|
+
unlink3(configPath()).catch(() => {
|
|
8812
9557
|
});
|
|
8813
9558
|
setEvents((e) => [
|
|
8814
9559
|
...e,
|
|
@@ -8817,6 +9562,30 @@ ${lines.join("\n")}` }]);
|
|
|
8817
9562
|
setCfg(null);
|
|
8818
9563
|
return true;
|
|
8819
9564
|
}
|
|
9565
|
+
if (c === "/command") {
|
|
9566
|
+
const sub = rest[0]?.toLowerCase() ?? "";
|
|
9567
|
+
if (sub === "create") {
|
|
9568
|
+
setCommandWizard({ mode: "create" });
|
|
9569
|
+
return true;
|
|
9570
|
+
}
|
|
9571
|
+
if (sub === "edit") {
|
|
9572
|
+
setCommandPicker({ mode: "edit" });
|
|
9573
|
+
return true;
|
|
9574
|
+
}
|
|
9575
|
+
if (sub === "delete") {
|
|
9576
|
+
setCommandPicker({ mode: "delete" });
|
|
9577
|
+
return true;
|
|
9578
|
+
}
|
|
9579
|
+
if (sub === "list") {
|
|
9580
|
+
setShowCommandList(true);
|
|
9581
|
+
return true;
|
|
9582
|
+
}
|
|
9583
|
+
setEvents((e) => [
|
|
9584
|
+
...e,
|
|
9585
|
+
{ kind: "info", key: mkKey(), text: "usage: /command create | edit | delete | list" }
|
|
9586
|
+
]);
|
|
9587
|
+
return true;
|
|
9588
|
+
}
|
|
8820
9589
|
if (c === "/help") {
|
|
8821
9590
|
setShowHelpMenu(true);
|
|
8822
9591
|
return true;
|
|
@@ -8835,6 +9604,47 @@ ${lines.join("\n")}` }]);
|
|
|
8835
9604
|
},
|
|
8836
9605
|
[handleSlash]
|
|
8837
9606
|
);
|
|
9607
|
+
const handleCommandSave = useCallback(
|
|
9608
|
+
async (opts2) => {
|
|
9609
|
+
setCommandWizard(null);
|
|
9610
|
+
try {
|
|
9611
|
+
if (commandWizard?.mode === "edit" && commandWizard.initial && commandWizard.initial.name !== opts2.name) {
|
|
9612
|
+
await deleteCustomCommand(commandWizard.initial);
|
|
9613
|
+
}
|
|
9614
|
+
const result = await saveCustomCommand(opts2);
|
|
9615
|
+
await reloadCustomCommands();
|
|
9616
|
+
setEvents((e) => [
|
|
9617
|
+
...e,
|
|
9618
|
+
{ kind: "info", key: mkKey(), text: `saved /${opts2.name} \u2192 ${result.filepath}` }
|
|
9619
|
+
]);
|
|
9620
|
+
} catch (err) {
|
|
9621
|
+
setEvents((e) => [
|
|
9622
|
+
...e,
|
|
9623
|
+
{ kind: "error", key: mkKey(), text: `failed to save /${opts2.name}: ${err.message}` }
|
|
9624
|
+
]);
|
|
9625
|
+
}
|
|
9626
|
+
},
|
|
9627
|
+
[commandWizard, reloadCustomCommands, setEvents]
|
|
9628
|
+
);
|
|
9629
|
+
const handleCommandDelete = useCallback(
|
|
9630
|
+
async (cmd) => {
|
|
9631
|
+
setCommandToDelete(null);
|
|
9632
|
+
try {
|
|
9633
|
+
await deleteCustomCommand(cmd);
|
|
9634
|
+
await reloadCustomCommands();
|
|
9635
|
+
setEvents((e) => [
|
|
9636
|
+
...e,
|
|
9637
|
+
{ kind: "info", key: mkKey(), text: `deleted /${cmd.name} (${cmd.filepath})` }
|
|
9638
|
+
]);
|
|
9639
|
+
} catch (err) {
|
|
9640
|
+
setEvents((e) => [
|
|
9641
|
+
...e,
|
|
9642
|
+
{ kind: "error", key: mkKey(), text: `failed to delete /${cmd.name}: ${err.message}` }
|
|
9643
|
+
]);
|
|
9644
|
+
}
|
|
9645
|
+
},
|
|
9646
|
+
[reloadCustomCommands, setEvents]
|
|
9647
|
+
);
|
|
8838
9648
|
const processMessage = useCallback(
|
|
8839
9649
|
async (text, displayText) => {
|
|
8840
9650
|
if (!cfg) return;
|
|
@@ -8897,6 +9707,10 @@ ${lines.join("\n")}` }]);
|
|
|
8897
9707
|
content = parts;
|
|
8898
9708
|
}
|
|
8899
9709
|
}
|
|
9710
|
+
if (sessionStartRecallRef.current) {
|
|
9711
|
+
await sessionStartRecallRef.current;
|
|
9712
|
+
sessionStartRecallRef.current = null;
|
|
9713
|
+
}
|
|
8900
9714
|
setEvents((e) => [...e, { kind: "user", key: mkKey(), text: display, images: images.length > 0 ? images : void 0 }]);
|
|
8901
9715
|
messagesRef.current.push({ role: "user", content });
|
|
8902
9716
|
if (compiledContextRef.current) {
|
|
@@ -9088,6 +9902,30 @@ ${lines.join("\n")}` }]);
|
|
|
9088
9902
|
}
|
|
9089
9903
|
}
|
|
9090
9904
|
}
|
|
9905
|
+
const manager = memoryManagerRef.current;
|
|
9906
|
+
if (manager) {
|
|
9907
|
+
try {
|
|
9908
|
+
const cwd = process.cwd();
|
|
9909
|
+
const queryText = sessionStateRef.current.task || cwd;
|
|
9910
|
+
const results = await manager.recall({ text: queryText, repoPath: cwd, limit: 5 });
|
|
9911
|
+
if (results.length > 0) {
|
|
9912
|
+
const text2 = await manager.synthesizeRecalled(results);
|
|
9913
|
+
const lastSystemIdx = messagesRef.current.findLastIndex((m) => m.role === "system");
|
|
9914
|
+
const insertIdx = lastSystemIdx >= 0 ? lastSystemIdx + 1 : messagesRef.current.length;
|
|
9915
|
+
messagesRef.current.splice(insertIdx, 0, { role: "system", content: text2 });
|
|
9916
|
+
setEvents((e) => [
|
|
9917
|
+
...e,
|
|
9918
|
+
{
|
|
9919
|
+
kind: "memory",
|
|
9920
|
+
key: mkKey(),
|
|
9921
|
+
text: `recalled ${results.length} memory${results.length === 1 ? "" : "ies"} after compaction`
|
|
9922
|
+
}
|
|
9923
|
+
]);
|
|
9924
|
+
await saveSessionSafe();
|
|
9925
|
+
}
|
|
9926
|
+
} catch {
|
|
9927
|
+
}
|
|
9928
|
+
}
|
|
9091
9929
|
} catch (e) {
|
|
9092
9930
|
if (e.name === "AbortError") {
|
|
9093
9931
|
setEvents((es) => [...es, { kind: "info", key: mkKey(), text: "(aborted)" }]);
|
|
@@ -9161,7 +9999,7 @@ ${lines.join("\n")}` }]);
|
|
|
9161
9999
|
}
|
|
9162
10000
|
}, [usage]);
|
|
9163
10001
|
if (!cfg) {
|
|
9164
|
-
return /* @__PURE__ */
|
|
10002
|
+
return /* @__PURE__ */ jsx17(
|
|
9165
10003
|
Onboarding,
|
|
9166
10004
|
{
|
|
9167
10005
|
onDone: (newCfg) => {
|
|
@@ -9175,13 +10013,13 @@ ${lines.join("\n")}` }]);
|
|
|
9175
10013
|
);
|
|
9176
10014
|
}
|
|
9177
10015
|
if (resumeSessions !== null) {
|
|
9178
|
-
return /* @__PURE__ */
|
|
10016
|
+
return /* @__PURE__ */ jsx17(Box16, { flexDirection: "column", children: /* @__PURE__ */ jsx17(ResumePicker, { sessions: resumeSessions, onPick: handleResumePick, theme }) });
|
|
9179
10017
|
}
|
|
9180
10018
|
if (showThemePicker) {
|
|
9181
|
-
return /* @__PURE__ */
|
|
10019
|
+
return /* @__PURE__ */ jsx17(Box16, { flexDirection: "column", children: /* @__PURE__ */ jsx17(ThemePicker, { themes: themeList(), current: theme, onPick: handleThemePick, onPreview: (t) => setTheme(t) }) });
|
|
9182
10020
|
}
|
|
9183
10021
|
if (showHelpMenu) {
|
|
9184
|
-
return /* @__PURE__ */
|
|
10022
|
+
return /* @__PURE__ */ jsx17(Box16, { flexDirection: "column", children: /* @__PURE__ */ jsx17(
|
|
9185
10023
|
HelpMenu,
|
|
9186
10024
|
{
|
|
9187
10025
|
theme,
|
|
@@ -9193,10 +10031,79 @@ ${lines.join("\n")}` }]);
|
|
|
9193
10031
|
}
|
|
9194
10032
|
) });
|
|
9195
10033
|
}
|
|
10034
|
+
if (commandWizard) {
|
|
10035
|
+
return /* @__PURE__ */ jsx17(Box16, { flexDirection: "column", children: /* @__PURE__ */ jsx17(
|
|
10036
|
+
CommandWizard,
|
|
10037
|
+
{
|
|
10038
|
+
theme,
|
|
10039
|
+
mode: commandWizard.mode,
|
|
10040
|
+
initial: commandWizard.initial,
|
|
10041
|
+
existingNames: customCommandsRef.current.map((c) => c.name),
|
|
10042
|
+
builtinNames: BUILTIN_COMMAND_NAMES,
|
|
10043
|
+
onDone: () => setCommandWizard(null),
|
|
10044
|
+
onSave: handleCommandSave
|
|
10045
|
+
}
|
|
10046
|
+
) });
|
|
10047
|
+
}
|
|
10048
|
+
if (commandPicker) {
|
|
10049
|
+
return /* @__PURE__ */ jsx17(Box16, { flexDirection: "column", children: /* @__PURE__ */ jsx17(
|
|
10050
|
+
CommandPicker,
|
|
10051
|
+
{
|
|
10052
|
+
theme,
|
|
10053
|
+
commands: customCommandsRef.current,
|
|
10054
|
+
title: commandPicker.mode === "edit" ? "Edit custom command" : "Delete custom command",
|
|
10055
|
+
onPick: (cmd) => {
|
|
10056
|
+
setCommandPicker(null);
|
|
10057
|
+
if (!cmd) return;
|
|
10058
|
+
if (commandPicker.mode === "edit") {
|
|
10059
|
+
setCommandWizard({ mode: "edit", initial: cmd });
|
|
10060
|
+
} else {
|
|
10061
|
+
setCommandToDelete(cmd);
|
|
10062
|
+
}
|
|
10063
|
+
}
|
|
10064
|
+
}
|
|
10065
|
+
) });
|
|
10066
|
+
}
|
|
10067
|
+
if (commandToDelete) {
|
|
10068
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
10069
|
+
/* @__PURE__ */ jsxs16(Text17, { color: theme.accent, bold: true, children: [
|
|
10070
|
+
"Delete /",
|
|
10071
|
+
commandToDelete.name,
|
|
10072
|
+
"?"
|
|
10073
|
+
] }),
|
|
10074
|
+
/* @__PURE__ */ jsx17(Text17, { color: theme.info.color, dimColor: true, children: commandToDelete.filepath }),
|
|
10075
|
+
/* @__PURE__ */ jsx17(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx17(
|
|
10076
|
+
SelectInput7,
|
|
10077
|
+
{
|
|
10078
|
+
items: [
|
|
10079
|
+
{ label: "Yes, delete", value: "yes", key: "yes" },
|
|
10080
|
+
{ label: "Cancel", value: "cancel", key: "cancel" }
|
|
10081
|
+
],
|
|
10082
|
+
onSelect: (item) => {
|
|
10083
|
+
if (item.value === "yes") {
|
|
10084
|
+
void handleCommandDelete(commandToDelete);
|
|
10085
|
+
} else {
|
|
10086
|
+
setCommandToDelete(null);
|
|
10087
|
+
}
|
|
10088
|
+
}
|
|
10089
|
+
}
|
|
10090
|
+
) })
|
|
10091
|
+
] });
|
|
10092
|
+
}
|
|
10093
|
+
if (showCommandList) {
|
|
10094
|
+
return /* @__PURE__ */ jsx17(Box16, { flexDirection: "column", children: /* @__PURE__ */ jsx17(
|
|
10095
|
+
CommandList,
|
|
10096
|
+
{
|
|
10097
|
+
theme,
|
|
10098
|
+
commands: customCommandsRef.current,
|
|
10099
|
+
onDone: () => setShowCommandList(false)
|
|
10100
|
+
}
|
|
10101
|
+
) });
|
|
10102
|
+
}
|
|
9196
10103
|
const hasConversation = events.some((e) => e.kind === "user" || e.kind === "assistant");
|
|
9197
|
-
return /* @__PURE__ */
|
|
9198
|
-
!hasConversation && events.length === 0 ? /* @__PURE__ */
|
|
9199
|
-
perm ? /* @__PURE__ */
|
|
10104
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
|
|
10105
|
+
!hasConversation && events.length === 0 ? /* @__PURE__ */ jsx17(Welcome, { theme, accountId: cfg.accountId }) : /* @__PURE__ */ jsx17(ChatView, { events, showReasoning, theme, verbose }),
|
|
10106
|
+
perm ? /* @__PURE__ */ jsx17(
|
|
9200
10107
|
PermissionModal,
|
|
9201
10108
|
{
|
|
9202
10109
|
tool: perm.tool,
|
|
@@ -9207,8 +10114,8 @@ ${lines.join("\n")}` }]);
|
|
|
9207
10114
|
setPerm(null);
|
|
9208
10115
|
}
|
|
9209
10116
|
}
|
|
9210
|
-
) : /* @__PURE__ */
|
|
9211
|
-
tasks.length > 0 && /* @__PURE__ */
|
|
10117
|
+
) : /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginTop: 1, children: [
|
|
10118
|
+
tasks.length > 0 && /* @__PURE__ */ jsx17(
|
|
9212
10119
|
TaskList,
|
|
9213
10120
|
{
|
|
9214
10121
|
tasks,
|
|
@@ -9217,11 +10124,11 @@ ${lines.join("\n")}` }]);
|
|
|
9217
10124
|
tokensDelta: Math.max(0, (usage?.prompt_tokens ?? 0) - tasksStartTokens)
|
|
9218
10125
|
}
|
|
9219
10126
|
),
|
|
9220
|
-
queue.length > 0 && /* @__PURE__ */
|
|
10127
|
+
queue.length > 0 && /* @__PURE__ */ jsx17(Box16, { flexDirection: "column", marginBottom: 1, children: queue.map((q, i) => /* @__PURE__ */ jsxs16(Text17, { color: theme.queue.color, dimColor: theme.queue.dim, children: [
|
|
9221
10128
|
"\u23F3 ",
|
|
9222
10129
|
q.display
|
|
9223
10130
|
] }, `queue_${i}`)) }),
|
|
9224
|
-
/* @__PURE__ */
|
|
10131
|
+
/* @__PURE__ */ jsx17(
|
|
9225
10132
|
StatusBar,
|
|
9226
10133
|
{
|
|
9227
10134
|
model: cfg.model,
|
|
@@ -9239,9 +10146,9 @@ ${lines.join("\n")}` }]);
|
|
|
9239
10146
|
codeMode
|
|
9240
10147
|
}
|
|
9241
10148
|
),
|
|
9242
|
-
/* @__PURE__ */
|
|
9243
|
-
/* @__PURE__ */
|
|
9244
|
-
/* @__PURE__ */
|
|
10149
|
+
/* @__PURE__ */ jsxs16(Box16, { marginTop: 1, children: [
|
|
10150
|
+
/* @__PURE__ */ jsx17(Text17, { color: theme.accent, children: "\u203A " }),
|
|
10151
|
+
/* @__PURE__ */ jsx17(
|
|
9245
10152
|
CustomTextInput,
|
|
9246
10153
|
{
|
|
9247
10154
|
value: input,
|
|
@@ -9290,7 +10197,7 @@ ${lines.join("\n")}` }]);
|
|
|
9290
10197
|
] });
|
|
9291
10198
|
}
|
|
9292
10199
|
async function renderApp(cfg, updateResult) {
|
|
9293
|
-
const instance = render(/* @__PURE__ */
|
|
10200
|
+
const instance = render(/* @__PURE__ */ jsx17(App, { initialCfg: cfg, initialUpdateResult: updateResult }), {
|
|
9294
10201
|
incrementalRendering: true
|
|
9295
10202
|
});
|
|
9296
10203
|
await instance.waitUntilExit();
|
|
@@ -9331,6 +10238,10 @@ var init_app = __esm({
|
|
|
9331
10238
|
init_version();
|
|
9332
10239
|
init_loader();
|
|
9333
10240
|
init_renderer();
|
|
10241
|
+
init_save();
|
|
10242
|
+
init_command_wizard();
|
|
10243
|
+
init_command_picker();
|
|
10244
|
+
init_command_list();
|
|
9334
10245
|
FEEDBACK_WORKER_URL = "https://kimiflare-feedback.sina-b35.workers.dev";
|
|
9335
10246
|
CONTEXT_LIMIT = 262e3;
|
|
9336
10247
|
AUTO_COMPACT_SUGGEST_PCT = 0.8;
|