kimiflare 0.23.0 → 0.24.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 +189 -77
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1528,7 +1528,7 @@ var init_mode = __esm({
|
|
|
1528
1528
|
"use strict";
|
|
1529
1529
|
MODES = ["edit", "plan", "auto"];
|
|
1530
1530
|
MUTATING_TOOLS = /* @__PURE__ */ new Set(["write", "edit", "bash"]);
|
|
1531
|
-
DANGEROUS_PATTERNS = /[
|
|
1531
|
+
DANGEROUS_PATTERNS = /[<>;`$]|\$\(|\$\{|\|\||\b&\s*$/;
|
|
1532
1532
|
GIT_READONLY_SUBCOMMANDS = {
|
|
1533
1533
|
log: true,
|
|
1534
1534
|
diff: true,
|
|
@@ -1888,8 +1888,10 @@ function injectCoauthor(command, coauthor) {
|
|
|
1888
1888
|
if (command.includes(trailer)) return command;
|
|
1889
1889
|
const createsCommit = /\bgit\s+(commit|merge|revert|cherry-pick)\b/.test(trimmed);
|
|
1890
1890
|
const isRebaseContinue = /\bgit\s+rebase\b/.test(trimmed) && !/\b--abort\b|\b--skip\b/.test(trimmed);
|
|
1891
|
+
const movesHeadOnly = /\bgit\s+(reset|checkout|switch)\b/.test(trimmed);
|
|
1891
1892
|
const mentionsGit = /\bgit\b/.test(trimmed);
|
|
1892
1893
|
if (!createsCommit && !isRebaseContinue && !mentionsGit) return command;
|
|
1894
|
+
if (movesHeadOnly) return command;
|
|
1893
1895
|
const tmpFile = join5(tmpdir(), `kf-coauthor-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
|
|
1894
1896
|
const amendBlock = `
|
|
1895
1897
|
if ! git log -1 --pretty=%B 2>/dev/null | grep -qF "${trailer}"; then
|
|
@@ -1902,7 +1904,7 @@ function injectCoauthor(command, coauthor) {
|
|
|
1902
1904
|
const beforeHead = `git rev-parse HEAD 2>/dev/null || echo "NO_HEAD"`;
|
|
1903
1905
|
const afterCheck = `
|
|
1904
1906
|
_KF_AFTER_HEAD=$(git rev-parse HEAD 2>/dev/null || echo "NO_HEAD")
|
|
1905
|
-
if [ "$_KF_BEFORE_HEAD" != "$_KF_AFTER_HEAD" ] && [ "$_KF_AFTER_HEAD" != "NO_HEAD" ]; then
|
|
1907
|
+
if [ "$_KF_BEFORE_HEAD" != "$_KF_AFTER_HEAD" ] && [ "$_KF_AFTER_HEAD" != "NO_HEAD" ] && git merge-base --is-ancestor "$_KF_BEFORE_HEAD" "$_KF_AFTER_HEAD" 2>/dev/null; then
|
|
1906
1908
|
${amendBlock}
|
|
1907
1909
|
fi
|
|
1908
1910
|
`.trim();
|
|
@@ -3079,6 +3081,29 @@ var init_update_check = __esm({
|
|
|
3079
3081
|
}
|
|
3080
3082
|
});
|
|
3081
3083
|
|
|
3084
|
+
// src/util/version.ts
|
|
3085
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
3086
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3087
|
+
import { dirname as dirname3, join as join7 } from "path";
|
|
3088
|
+
function getAppVersion() {
|
|
3089
|
+
if (cachedVersion !== null) return cachedVersion;
|
|
3090
|
+
try {
|
|
3091
|
+
const here = dirname3(fileURLToPath2(import.meta.url));
|
|
3092
|
+
const pkg = JSON.parse(readFileSync2(join7(here, "..", "..", "package.json"), "utf8"));
|
|
3093
|
+
cachedVersion = pkg.version ?? "0.0.0";
|
|
3094
|
+
} catch {
|
|
3095
|
+
cachedVersion = "0.0.0";
|
|
3096
|
+
}
|
|
3097
|
+
return cachedVersion;
|
|
3098
|
+
}
|
|
3099
|
+
var cachedVersion;
|
|
3100
|
+
var init_version = __esm({
|
|
3101
|
+
"src/util/version.ts"() {
|
|
3102
|
+
"use strict";
|
|
3103
|
+
cachedVersion = null;
|
|
3104
|
+
}
|
|
3105
|
+
});
|
|
3106
|
+
|
|
3082
3107
|
// src/agent/compact.ts
|
|
3083
3108
|
function indexOfNthUserFromEnd(messages, n) {
|
|
3084
3109
|
let seen = 0;
|
|
@@ -3968,13 +3993,12 @@ import React3 from "react";
|
|
|
3968
3993
|
import { Box as Box4, Text as Text4, Static } from "ink";
|
|
3969
3994
|
import Spinner2 from "ink-spinner";
|
|
3970
3995
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
3971
|
-
var
|
|
3996
|
+
var ChatView, EventView;
|
|
3972
3997
|
var init_chat = __esm({
|
|
3973
3998
|
"src/ui/chat.tsx"() {
|
|
3974
3999
|
"use strict";
|
|
3975
4000
|
init_tool_view();
|
|
3976
4001
|
init_markdown();
|
|
3977
|
-
MAX_FINALIZED_EVENTS = 100;
|
|
3978
4002
|
ChatView = React3.memo(function ChatView2({ events, showReasoning, theme, verbose }) {
|
|
3979
4003
|
const finalized = [];
|
|
3980
4004
|
const active = [];
|
|
@@ -3989,15 +4013,13 @@ var init_chat = __esm({
|
|
|
3989
4013
|
finalized.push({ id: e.key, evt: e, showSeparator });
|
|
3990
4014
|
}
|
|
3991
4015
|
}
|
|
3992
|
-
const droppedCount = Math.max(0, finalized.length - MAX_FINALIZED_EVENTS);
|
|
3993
|
-
const visibleFinalized = droppedCount > 0 ? finalized.slice(droppedCount) : finalized;
|
|
3994
4016
|
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
3995
|
-
/* @__PURE__ */ jsx4(Static, { items:
|
|
4017
|
+
/* @__PURE__ */ jsx4(Static, { items: finalized, children: (item) => /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
3996
4018
|
item.showSeparator && /* @__PURE__ */ jsx4(Box4, { marginY: 1, children: /* @__PURE__ */ jsx4(Text4, { color: theme.info.color, dimColor: theme.info.dim, children: "\u2500".repeat(40) }) }),
|
|
3997
4019
|
/* @__PURE__ */ jsx4(EventView, { evt: item.evt, showReasoning, theme, verbose })
|
|
3998
|
-
] }) }),
|
|
4020
|
+
] }, item.id) }),
|
|
3999
4021
|
active.map((e, i) => {
|
|
4000
|
-
const prevEvt = i > 0 ? active[i - 1] :
|
|
4022
|
+
const prevEvt = i > 0 ? active[i - 1] : finalized[finalized.length - 1]?.evt;
|
|
4001
4023
|
const showSeparator = e.kind === "user" && prevEvt && (prevEvt.kind === "assistant" || prevEvt.kind === "tool");
|
|
4002
4024
|
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
4003
4025
|
showSeparator && /* @__PURE__ */ jsx4(Box4, { marginY: 1, children: /* @__PURE__ */ jsx4(Text4, { color: theme.info.color, dimColor: theme.info.dim, children: "\u2500".repeat(40) }) }),
|
|
@@ -5328,7 +5350,9 @@ function Welcome({ theme, accountId }) {
|
|
|
5328
5350
|
] }),
|
|
5329
5351
|
/* @__PURE__ */ jsx12(Text12, { color: theme.user, children: s })
|
|
5330
5352
|
] }, i)) }),
|
|
5331
|
-
/* @__PURE__ */ jsx12(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx12(Text12, { color: theme.info.color, dimColor: theme.info.dim, children: "Type a message or /help for commands \xB7 ctrl-c to exit \xB7 shift+tab to cycle modes" }) })
|
|
5353
|
+
/* @__PURE__ */ jsx12(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx12(Text12, { color: theme.info.color, dimColor: theme.info.dim, children: "Type a message or /help for commands \xB7 ctrl-c to exit \xB7 shift+tab to cycle modes" }) }),
|
|
5354
|
+
/* @__PURE__ */ jsx12(Box11, { children: /* @__PURE__ */ jsx12(Text12, { color: theme.info.color, dimColor: theme.info.dim, children: "Tip: type /hello to send feedback to the creator" }) }),
|
|
5355
|
+
/* @__PURE__ */ jsx12(Box11, { children: /* @__PURE__ */ jsx12(Text12, { color: theme.info.color, dimColor: theme.info.dim, children: "Join our community: https://discord.gg/aEuAUHNTK5 (type /community to open)" }) })
|
|
5332
5356
|
] });
|
|
5333
5357
|
}
|
|
5334
5358
|
var SUGGESTIONS;
|
|
@@ -5579,10 +5603,10 @@ __export(sessions_exports, {
|
|
|
5579
5603
|
});
|
|
5580
5604
|
import { readFile as readFile7, writeFile as writeFile5, mkdir as mkdir5, readdir as readdir2, stat as stat3 } from "fs/promises";
|
|
5581
5605
|
import { homedir as homedir6 } from "os";
|
|
5582
|
-
import { join as
|
|
5606
|
+
import { join as join8 } from "path";
|
|
5583
5607
|
function sessionsDir() {
|
|
5584
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
5585
|
-
return
|
|
5608
|
+
const xdg = process.env.XDG_DATA_HOME || join8(homedir6(), ".local", "share");
|
|
5609
|
+
return join8(xdg, "kimiflare", "sessions");
|
|
5586
5610
|
}
|
|
5587
5611
|
function sanitize(text) {
|
|
5588
5612
|
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
|
|
@@ -5595,7 +5619,7 @@ function makeSessionId(firstPrompt) {
|
|
|
5595
5619
|
async function saveSession(file) {
|
|
5596
5620
|
const dir = sessionsDir();
|
|
5597
5621
|
await mkdir5(dir, { recursive: true });
|
|
5598
|
-
const path =
|
|
5622
|
+
const path = join8(dir, `${file.id}.json`);
|
|
5599
5623
|
await writeFile5(path, JSON.stringify(file, null, 2), "utf8");
|
|
5600
5624
|
return path;
|
|
5601
5625
|
}
|
|
@@ -5615,7 +5639,7 @@ async function listSessions(limit = 30) {
|
|
|
5615
5639
|
const summaries = [];
|
|
5616
5640
|
for (const name of entries) {
|
|
5617
5641
|
if (!name.endsWith(".json")) continue;
|
|
5618
|
-
const path =
|
|
5642
|
+
const path = join8(dir, name);
|
|
5619
5643
|
try {
|
|
5620
5644
|
const [s, raw] = await Promise.all([stat3(path), readFile7(path, "utf8")]);
|
|
5621
5645
|
const parsed = JSON.parse(raw);
|
|
@@ -5688,13 +5712,13 @@ var init_image = __esm({
|
|
|
5688
5712
|
// src/usage-tracker.ts
|
|
5689
5713
|
import { readFile as readFile9, writeFile as writeFile6, mkdir as mkdir6 } from "fs/promises";
|
|
5690
5714
|
import { homedir as homedir7 } from "os";
|
|
5691
|
-
import { join as
|
|
5715
|
+
import { join as join9 } from "path";
|
|
5692
5716
|
function usageDir() {
|
|
5693
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
5694
|
-
return
|
|
5717
|
+
const xdg = process.env.XDG_DATA_HOME || join9(homedir7(), ".local", "share");
|
|
5718
|
+
return join9(xdg, "kimiflare");
|
|
5695
5719
|
}
|
|
5696
5720
|
function usagePath() {
|
|
5697
|
-
return
|
|
5721
|
+
return join9(usageDir(), "usage.json");
|
|
5698
5722
|
}
|
|
5699
5723
|
function today() {
|
|
5700
5724
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -5820,7 +5844,7 @@ async function getCostReport(sessionId) {
|
|
|
5820
5844
|
const log = pruneUsageLog(await loadLog());
|
|
5821
5845
|
const date = today();
|
|
5822
5846
|
const currentMonth = date.slice(0, 7);
|
|
5823
|
-
const session = log.sessions.find((s) => s.id === sessionId) ?? { date, promptTokens: 0, completionTokens: 0, cachedTokens: 0, cost: 0 };
|
|
5847
|
+
const session = sessionId ? log.sessions.find((s) => s.id === sessionId) ?? { date, promptTokens: 0, completionTokens: 0, cachedTokens: 0, cost: 0 } : { date, promptTokens: 0, completionTokens: 0, cachedTokens: 0, cost: 0 };
|
|
5824
5848
|
const todayUsage = log.days.find((d) => d.date === date) ?? { date, promptTokens: 0, completionTokens: 0, cachedTokens: 0, cost: 0 };
|
|
5825
5849
|
const monthUsage = {
|
|
5826
5850
|
date: currentMonth,
|
|
@@ -5919,7 +5943,7 @@ __export(db_exports, {
|
|
|
5919
5943
|
updateMemoryEmbedding: () => updateMemoryEmbedding
|
|
5920
5944
|
});
|
|
5921
5945
|
import Database from "better-sqlite3";
|
|
5922
|
-
import { dirname as
|
|
5946
|
+
import { dirname as dirname4 } from "path";
|
|
5923
5947
|
import { mkdirSync, statSync as statSync2 } from "fs";
|
|
5924
5948
|
function initSchema(db) {
|
|
5925
5949
|
db.exec(`
|
|
@@ -6000,7 +6024,7 @@ function openMemoryDb(dbPath) {
|
|
|
6000
6024
|
if (dbInstance) {
|
|
6001
6025
|
dbInstance.close();
|
|
6002
6026
|
}
|
|
6003
|
-
mkdirSync(
|
|
6027
|
+
mkdirSync(dirname4(dbPath), { recursive: true });
|
|
6004
6028
|
dbInstance = new Database(dbPath);
|
|
6005
6029
|
dbInstance.pragma("journal_mode = WAL");
|
|
6006
6030
|
dbInstance.pragma("foreign_keys = ON");
|
|
@@ -6872,6 +6896,42 @@ Return only the topic key string.`
|
|
|
6872
6896
|
}
|
|
6873
6897
|
});
|
|
6874
6898
|
|
|
6899
|
+
// src/util/state.ts
|
|
6900
|
+
import { readFile as readFile10, writeFile as writeFile7, mkdir as mkdir7 } from "fs/promises";
|
|
6901
|
+
import { homedir as homedir8 } from "os";
|
|
6902
|
+
import { join as join11 } from "path";
|
|
6903
|
+
function statePath() {
|
|
6904
|
+
const xdg = process.env.XDG_CONFIG_HOME || join11(homedir8(), ".config");
|
|
6905
|
+
return join11(xdg, "kimiflare", "state.json");
|
|
6906
|
+
}
|
|
6907
|
+
async function readState() {
|
|
6908
|
+
try {
|
|
6909
|
+
const raw = await readFile10(statePath(), "utf8");
|
|
6910
|
+
return JSON.parse(raw);
|
|
6911
|
+
} catch {
|
|
6912
|
+
return {};
|
|
6913
|
+
}
|
|
6914
|
+
}
|
|
6915
|
+
async function writeState(state) {
|
|
6916
|
+
const path = statePath();
|
|
6917
|
+
await mkdir7(join11(path, ".."), { recursive: true });
|
|
6918
|
+
await writeFile7(path, JSON.stringify(state, null, 2) + "\n", "utf8");
|
|
6919
|
+
}
|
|
6920
|
+
async function markCreatorMessageSeen(version) {
|
|
6921
|
+
const state = await readState();
|
|
6922
|
+
state.creatorMessageSeenVersion = version;
|
|
6923
|
+
await writeState(state);
|
|
6924
|
+
}
|
|
6925
|
+
async function shouldShowCreatorMessage(version) {
|
|
6926
|
+
const state = await readState();
|
|
6927
|
+
return state.creatorMessageSeenVersion !== version;
|
|
6928
|
+
}
|
|
6929
|
+
var init_state = __esm({
|
|
6930
|
+
"src/util/state.ts"() {
|
|
6931
|
+
"use strict";
|
|
6932
|
+
}
|
|
6933
|
+
});
|
|
6934
|
+
|
|
6875
6935
|
// src/app.tsx
|
|
6876
6936
|
var app_exports = {};
|
|
6877
6937
|
__export(app_exports, {
|
|
@@ -6880,8 +6940,10 @@ __export(app_exports, {
|
|
|
6880
6940
|
import { useState as useState6, useRef as useRef3, useEffect as useEffect4, useCallback } from "react";
|
|
6881
6941
|
import { Box as Box12, Text as Text13, useApp, useInput as useInput2, render } from "ink";
|
|
6882
6942
|
import { existsSync } from "fs";
|
|
6883
|
-
import { join as
|
|
6943
|
+
import { join as join12 } from "path";
|
|
6884
6944
|
import { unlink as unlink2 } from "fs/promises";
|
|
6945
|
+
import { spawn as spawn2 } from "child_process";
|
|
6946
|
+
import { platform as platform2 } from "os";
|
|
6885
6947
|
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
6886
6948
|
function gatewayFromConfig(cfg) {
|
|
6887
6949
|
if (!cfg.aiGatewayId) return void 0;
|
|
@@ -6902,10 +6964,34 @@ function gatewayUsageLookupFromConfig(cfg, meta) {
|
|
|
6902
6964
|
meta
|
|
6903
6965
|
};
|
|
6904
6966
|
}
|
|
6967
|
+
function openBrowser(url) {
|
|
6968
|
+
const cmd = platform2() === "darwin" ? "open" : platform2() === "win32" ? "start" : "xdg-open";
|
|
6969
|
+
const child = spawn2(cmd, [url], { detached: true, stdio: "ignore" });
|
|
6970
|
+
child.unref();
|
|
6971
|
+
}
|
|
6905
6972
|
function capEvents(prev) {
|
|
6906
6973
|
if (prev.length <= MAX_EVENTS) return prev;
|
|
6907
6974
|
return prev.slice(prev.length - MAX_EVENTS);
|
|
6908
6975
|
}
|
|
6976
|
+
function compactEventsVisual(prev, keepLastTurns) {
|
|
6977
|
+
let seen = 0;
|
|
6978
|
+
let cutoff = -1;
|
|
6979
|
+
for (let i = prev.length - 1; i >= 0; i--) {
|
|
6980
|
+
if (prev[i].kind === "user") {
|
|
6981
|
+
seen++;
|
|
6982
|
+
if (seen === keepLastTurns + 1) {
|
|
6983
|
+
cutoff = i;
|
|
6984
|
+
break;
|
|
6985
|
+
}
|
|
6986
|
+
}
|
|
6987
|
+
}
|
|
6988
|
+
if (cutoff <= 0) return prev;
|
|
6989
|
+
const kept = prev.slice(cutoff);
|
|
6990
|
+
return [
|
|
6991
|
+
{ kind: "info", key: mkKey(), text: `\xB7\xB7\xB7 ${cutoff} earlier messages compacted \xB7\xB7\xB7` },
|
|
6992
|
+
...kept
|
|
6993
|
+
];
|
|
6994
|
+
}
|
|
6909
6995
|
function makePrefixMessages(cacheStable, model, mode, tools) {
|
|
6910
6996
|
if (cacheStable) {
|
|
6911
6997
|
return buildSystemMessages({ cwd: process.cwd(), tools, model, mode });
|
|
@@ -7004,8 +7090,21 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7004
7090
|
}
|
|
7005
7091
|
})
|
|
7006
7092
|
);
|
|
7093
|
+
void shouldShowCreatorMessage(getAppVersion()).then((shouldShow) => {
|
|
7094
|
+
if (shouldShow) {
|
|
7095
|
+
setEvents((e) => [
|
|
7096
|
+
...e,
|
|
7097
|
+
{
|
|
7098
|
+
kind: "info",
|
|
7099
|
+
key: mkKey(),
|
|
7100
|
+
text: "Hey, how do you like this version? I'd love to hear from you \u2014 type /hello to send me a voice note. Only I see it, and I may DM you back."
|
|
7101
|
+
}
|
|
7102
|
+
]);
|
|
7103
|
+
void markCreatorMessageSeen(getAppVersion());
|
|
7104
|
+
}
|
|
7105
|
+
});
|
|
7007
7106
|
if (cfg.memoryEnabled) {
|
|
7008
|
-
const dbPath = cfg.memoryDbPath ??
|
|
7107
|
+
const dbPath = cfg.memoryDbPath ?? join12(process.cwd(), ".kimiflare", "memory.db");
|
|
7009
7108
|
const manager = new MemoryManager({
|
|
7010
7109
|
dbPath,
|
|
7011
7110
|
accountId: cfg.accountId,
|
|
@@ -7366,14 +7465,19 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7366
7465
|
} else {
|
|
7367
7466
|
messagesRef.current = result.newMessages;
|
|
7368
7467
|
sessionStateRef.current = result.newState;
|
|
7369
|
-
setEvents(
|
|
7370
|
-
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
|
|
7374
|
-
|
|
7375
|
-
|
|
7376
|
-
|
|
7468
|
+
setEvents(
|
|
7469
|
+
(e) => compactEventsVisual(
|
|
7470
|
+
[
|
|
7471
|
+
...e,
|
|
7472
|
+
{
|
|
7473
|
+
kind: "info",
|
|
7474
|
+
key: mkKey(),
|
|
7475
|
+
text: `compacted ${result.metrics.rawTurnsRemoved} turns \u2192 ${result.metrics.estimatedTokensBefore} \u2192 ${result.metrics.estimatedTokensAfter} tokens, ${result.metrics.archivedArtifacts} artifacts`
|
|
7476
|
+
}
|
|
7477
|
+
],
|
|
7478
|
+
4
|
|
7479
|
+
)
|
|
7480
|
+
);
|
|
7377
7481
|
await saveSessionSafe();
|
|
7378
7482
|
}
|
|
7379
7483
|
} else {
|
|
@@ -7392,14 +7496,19 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7392
7496
|
]);
|
|
7393
7497
|
} else {
|
|
7394
7498
|
messagesRef.current = result.newMessages;
|
|
7395
|
-
setEvents(
|
|
7396
|
-
|
|
7397
|
-
|
|
7398
|
-
|
|
7399
|
-
|
|
7400
|
-
|
|
7401
|
-
|
|
7402
|
-
|
|
7499
|
+
setEvents(
|
|
7500
|
+
(e) => compactEventsVisual(
|
|
7501
|
+
[
|
|
7502
|
+
...e,
|
|
7503
|
+
{
|
|
7504
|
+
kind: "info",
|
|
7505
|
+
key: mkKey(),
|
|
7506
|
+
text: `compacted ${result.replacedCount} messages into a summary`
|
|
7507
|
+
}
|
|
7508
|
+
],
|
|
7509
|
+
4
|
|
7510
|
+
)
|
|
7511
|
+
);
|
|
7403
7512
|
await saveSessionSafe();
|
|
7404
7513
|
}
|
|
7405
7514
|
}
|
|
@@ -7428,13 +7537,13 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7428
7537
|
}
|
|
7429
7538
|
const cwd = process.cwd();
|
|
7430
7539
|
for (const name of ["KIMI.md", "KIMIFLARE.md", "AGENT.md"]) {
|
|
7431
|
-
if (existsSync(
|
|
7540
|
+
if (existsSync(join12(cwd, name))) {
|
|
7432
7541
|
setEvents((e) => [
|
|
7433
7542
|
...e,
|
|
7434
7543
|
{
|
|
7435
7544
|
kind: "info",
|
|
7436
7545
|
key: mkKey(),
|
|
7437
|
-
text: `${name} already exists at ${
|
|
7546
|
+
text: `${name} already exists at ${join12(cwd, name)} \u2014 delete it first if you want to regenerate`
|
|
7438
7547
|
}
|
|
7439
7548
|
]);
|
|
7440
7549
|
return;
|
|
@@ -7543,6 +7652,10 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7543
7652
|
resolve2("allow");
|
|
7544
7653
|
return;
|
|
7545
7654
|
}
|
|
7655
|
+
if (req.tool.name === "bash") {
|
|
7656
|
+
setPerm({ tool: req.tool, args: req.args, resolve: resolve2 });
|
|
7657
|
+
return;
|
|
7658
|
+
}
|
|
7546
7659
|
setEvents((e) => [
|
|
7547
7660
|
...e,
|
|
7548
7661
|
{
|
|
@@ -7558,7 +7671,7 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7558
7671
|
})
|
|
7559
7672
|
}
|
|
7560
7673
|
});
|
|
7561
|
-
if (existsSync(
|
|
7674
|
+
if (existsSync(join12(cwd, "KIMI.md"))) {
|
|
7562
7675
|
if (cacheStableRef.current) {
|
|
7563
7676
|
messagesRef.current[1] = {
|
|
7564
7677
|
role: "system",
|
|
@@ -7704,15 +7817,16 @@ function App({ initialCfg, initialUpdateResult }) {
|
|
|
7704
7817
|
return true;
|
|
7705
7818
|
}
|
|
7706
7819
|
if (c === "/cost") {
|
|
7707
|
-
|
|
7708
|
-
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "no usage recorded yet" }]);
|
|
7709
|
-
return true;
|
|
7710
|
-
}
|
|
7711
|
-
void getCostReport(sessionIdRef.current).then((report) => {
|
|
7820
|
+
void getCostReport(sessionIdRef.current ?? void 0).then((report) => {
|
|
7712
7821
|
setEvents((e) => [
|
|
7713
7822
|
...e,
|
|
7714
7823
|
{ kind: "info", key: mkKey(), text: formatCostReport(report) }
|
|
7715
7824
|
]);
|
|
7825
|
+
}).catch((err) => {
|
|
7826
|
+
setEvents((e) => [
|
|
7827
|
+
...e,
|
|
7828
|
+
{ kind: "error", key: mkKey(), text: `cost report failed: ${err.message}` }
|
|
7829
|
+
]);
|
|
7716
7830
|
});
|
|
7717
7831
|
return true;
|
|
7718
7832
|
}
|
|
@@ -7962,19 +8076,6 @@ ${lines.join("\n")}` }]);
|
|
|
7962
8076
|
}
|
|
7963
8077
|
return true;
|
|
7964
8078
|
}
|
|
7965
|
-
if (c === "/cost") {
|
|
7966
|
-
if (!sessionIdRef.current) {
|
|
7967
|
-
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "no usage recorded yet" }]);
|
|
7968
|
-
return true;
|
|
7969
|
-
}
|
|
7970
|
-
void getCostReport(sessionIdRef.current).then((report) => {
|
|
7971
|
-
setEvents((e) => [
|
|
7972
|
-
...e,
|
|
7973
|
-
{ kind: "info", key: mkKey(), text: formatCostReport(report) }
|
|
7974
|
-
]);
|
|
7975
|
-
});
|
|
7976
|
-
return true;
|
|
7977
|
-
}
|
|
7978
8079
|
if (c === "/resume") {
|
|
7979
8080
|
void openResumePicker();
|
|
7980
8081
|
return true;
|
|
@@ -8056,6 +8157,24 @@ ${lines.join("\n")}` }]);
|
|
|
8056
8157
|
]);
|
|
8057
8158
|
return true;
|
|
8058
8159
|
}
|
|
8160
|
+
if (c === "/hello") {
|
|
8161
|
+
const session = crypto.randomUUID();
|
|
8162
|
+
const url = `${FEEDBACK_WORKER_URL}/?s=${session}&v=${getAppVersion()}`;
|
|
8163
|
+
openBrowser(url);
|
|
8164
|
+
setEvents((e) => [
|
|
8165
|
+
...e,
|
|
8166
|
+
{ kind: "info", key: mkKey(), text: "Opened voice note page in your browser. Record your message there and hit Send when you're done." }
|
|
8167
|
+
]);
|
|
8168
|
+
return true;
|
|
8169
|
+
}
|
|
8170
|
+
if (c === "/community") {
|
|
8171
|
+
openBrowser("https://discord.gg/aEuAUHNTK5");
|
|
8172
|
+
setEvents((e) => [
|
|
8173
|
+
...e,
|
|
8174
|
+
{ kind: "info", key: mkKey(), text: "Opened Discord invite in your browser." }
|
|
8175
|
+
]);
|
|
8176
|
+
return true;
|
|
8177
|
+
}
|
|
8059
8178
|
if (c === "/logout") {
|
|
8060
8179
|
unlink2(configPath()).catch(() => {
|
|
8061
8180
|
});
|
|
@@ -8072,7 +8191,7 @@ ${lines.join("\n")}` }]);
|
|
|
8072
8191
|
{
|
|
8073
8192
|
kind: "info",
|
|
8074
8193
|
key: mkKey(),
|
|
8075
|
-
text: "commands:\n /mode edit|plan|auto switch mode (or shift+tab to cycle)\n /plan /auto /edit shortcuts for /mode\n /thinking low|med|high set reasoning effort (quality vs speed)\n /theme interactive theme picker (or ctrl+t)\n /theme NAME set theme by name\n /resume pick a past conversation\n /compact summarize old turns to free context\n /init scan this repo and write a KIMI.md for future agents\n /memory show memory stats\n /memory search <query> search stored memories\n /memory clear wipe memories for this repo\n /mcp list list connected MCP servers and tools\n /mcp reload reconnect all configured MCP servers\n /reasoning toggle show/hide model reasoning\n /clear clear current conversation\n /gateway show gateway status\n /gateway ID enable AI Gateway\n /gateway off disable AI Gateway (direct Workers AI)\n /gateway cache-ttl N set gateway cache TTL in seconds\n /gateway skip-cache T|F set gateway skip-cache flag\n /gateway collect-logs T|F include payload in gateway logs\n /gateway metadata K=V add metadata key-value pair\n /gateway metadata clear remove all metadata\n /cost /model /update /logout /help /exit\nkeys: ctrl-c interrupt/exit \xB7 ctrl-r toggle reasoning \xB7 ctrl-o verbose \xB7 ctrl+t theme \xB7 shift+tab cycle mode \xB7 \u2191/\u2193 history"
|
|
8194
|
+
text: "commands:\n /mode edit|plan|auto switch mode (or shift+tab to cycle)\n /plan /auto /edit shortcuts for /mode\n /thinking low|med|high set reasoning effort (quality vs speed)\n /theme interactive theme picker (or ctrl+t)\n /theme NAME set theme by name\n /resume pick a past conversation\n /compact summarize old turns to free context\n /init scan this repo and write a KIMI.md for future agents\n /memory show memory stats\n /memory search <query> search stored memories\n /memory clear wipe memories for this repo\n /mcp list list connected MCP servers and tools\n /mcp reload reconnect all configured MCP servers\n /reasoning toggle show/hide model reasoning\n /clear clear current conversation\n /hello send a voice note to the creator\n /community join our Discord server\n /gateway show gateway status\n /gateway ID enable AI Gateway\n /gateway off disable AI Gateway (direct Workers AI)\n /gateway cache-ttl N set gateway cache TTL in seconds\n /gateway skip-cache T|F set gateway skip-cache flag\n /gateway collect-logs T|F include payload in gateway logs\n /gateway metadata K=V add metadata key-value pair\n /gateway metadata clear remove all metadata\n /cost /model /update /logout /help /exit\nkeys: ctrl-c interrupt/exit \xB7 ctrl-r toggle reasoning \xB7 ctrl-o verbose \xB7 ctrl+t theme \xB7 shift+tab cycle mode \xB7 \u2191/\u2193 history"
|
|
8076
8195
|
}
|
|
8077
8196
|
]);
|
|
8078
8197
|
return true;
|
|
@@ -8208,6 +8327,7 @@ ${lines.join("\n")}` }]);
|
|
|
8208
8327
|
onUsageFinal: (u, meta) => {
|
|
8209
8328
|
const sid = ensureSessionId();
|
|
8210
8329
|
void recordUsage(sid, u, gatewayUsageLookupFromConfig(cfg, meta ?? gatewayMetaRef.current));
|
|
8330
|
+
void getCostReport(sid).then((report) => setSessionUsage(report.session));
|
|
8211
8331
|
},
|
|
8212
8332
|
onGatewayMeta: updateGatewayMeta,
|
|
8213
8333
|
onTasks: (nextTasks) => {
|
|
@@ -8464,7 +8584,7 @@ async function renderApp(cfg, updateResult) {
|
|
|
8464
8584
|
});
|
|
8465
8585
|
await instance.waitUntilExit();
|
|
8466
8586
|
}
|
|
8467
|
-
var CONTEXT_LIMIT, AUTO_COMPACT_SUGGEST_PCT, MAX_EVENTS, nextAssistantId, nextKey, mkKey, MAX_IMAGES_PER_MESSAGE, EFFORT_DESCRIPTIONS;
|
|
8587
|
+
var FEEDBACK_WORKER_URL, CONTEXT_LIMIT, AUTO_COMPACT_SUGGEST_PCT, MAX_EVENTS, nextAssistantId, nextKey, mkKey, MAX_IMAGES_PER_MESSAGE, EFFORT_DESCRIPTIONS;
|
|
8468
8588
|
var init_app = __esm({
|
|
8469
8589
|
"src/app.tsx"() {
|
|
8470
8590
|
"use strict";
|
|
@@ -8495,9 +8615,12 @@ var init_app = __esm({
|
|
|
8495
8615
|
init_usage_tracker();
|
|
8496
8616
|
init_manager2();
|
|
8497
8617
|
init_storage_limits();
|
|
8618
|
+
init_state();
|
|
8619
|
+
init_version();
|
|
8620
|
+
FEEDBACK_WORKER_URL = "https://kimiflare-feedback.sina-b35.workers.dev";
|
|
8498
8621
|
CONTEXT_LIMIT = 262e3;
|
|
8499
8622
|
AUTO_COMPACT_SUGGEST_PCT = 0.8;
|
|
8500
|
-
MAX_EVENTS =
|
|
8623
|
+
MAX_EVENTS = 500;
|
|
8501
8624
|
nextAssistantId = 1;
|
|
8502
8625
|
nextKey = 1;
|
|
8503
8626
|
mkKey = () => `evt_${nextKey++}`;
|
|
@@ -8516,21 +8639,10 @@ init_loop();
|
|
|
8516
8639
|
init_system_prompt();
|
|
8517
8640
|
init_executor();
|
|
8518
8641
|
init_update_check();
|
|
8642
|
+
init_version();
|
|
8519
8643
|
import { Command } from "commander";
|
|
8520
|
-
import { readFileSync as readFileSync2 } from "fs";
|
|
8521
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8522
|
-
import { dirname as dirname4, join as join11 } from "path";
|
|
8523
|
-
function readPackageVersion() {
|
|
8524
|
-
try {
|
|
8525
|
-
const here = dirname4(fileURLToPath2(import.meta.url));
|
|
8526
|
-
const pkg = JSON.parse(readFileSync2(join11(here, "..", "package.json"), "utf8"));
|
|
8527
|
-
return pkg.version ?? "0.0.0";
|
|
8528
|
-
} catch {
|
|
8529
|
-
return "0.0.0";
|
|
8530
|
-
}
|
|
8531
|
-
}
|
|
8532
8644
|
var program = new Command();
|
|
8533
|
-
program.name("kimiflare").description("Terminal coding agent powered by Kimi-K2.6 on Cloudflare Workers AI.").version(
|
|
8645
|
+
program.name("kimiflare").description("Terminal coding agent powered by Kimi-K2.6 on Cloudflare Workers AI.").version(getAppVersion()).option("-p, --print <prompt>", "one-shot mode: send prompt, stream reply to stdout, exit").option("-m, --model <id>", "model id (defaults to @cf/moonshotai/kimi-k2.6)").option("--dangerously-allow-all", "auto-approve every permission prompt (print mode only)").option("--reasoning", "include reasoning in stdout (print mode only)").parse();
|
|
8534
8646
|
var opts = program.opts();
|
|
8535
8647
|
async function main() {
|
|
8536
8648
|
const cfg = await loadConfig();
|