kimiflare 0.55.0 → 0.56.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/README.md +18 -10
- package/dist/index.js +127 -22
- package/dist/index.js.map +1 -1
- package/dist/sdk/index.js +12 -5
- package/dist/sdk/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,7 +33,12 @@
|
|
|
33
33
|
|
|
34
34
|
- **262k context window** — Read entire modules, large configs, and full stack traces without the model losing track.
|
|
35
35
|
- **Image understanding** — Drop image paths (PNG, JPG, WebP, GIF, BMP up to 5 MB) into any prompt. Great for UI reviews, diagrams, and screenshots.
|
|
36
|
-
- **Plan / Edit / Auto modes** — `plan`
|
|
36
|
+
- **Plan / Edit / Auto modes** — `plan` is a whitelist-only research mode: only read-only tools (read, glob, grep, web search, GitHub read-only, browser fetch) are allowed. Writes, edits, mutating bash, MCP tools, and LSP renames are all blocked. `edit` (default) prompts per mutating call. `auto` approves everything for trusted tasks.
|
|
37
|
+
- **Windows support** — OS-aware shell auto-detects `cmd.exe` / PowerShell on Windows, `bash` on Unix. The `bash` tool works out of the box on all platforms.
|
|
38
|
+
- **Message queuing** — Submit multiple messages while the agent is busy; they queue and auto-drain. Escape interrupts the current turn but preserves the queue.
|
|
39
|
+
- **Smart permission modal** — Denying a tool opens inline feedback so you can tell the agent what to do instead. Keyboard-native navigation (`↑/↓`, `j/k`, `Alt+1/2/3`).
|
|
40
|
+
- **Loop guardrails** — Agent hard-stops when all tools in a turn are blocked, preventing infinite token-burning cycles.
|
|
41
|
+
- **Persistent all-time cost history** — Append-only `history.jsonl` tracks daily usage forever, so `/cost` shows true all-time and monthly totals that survive across sessions and version updates.
|
|
37
42
|
- **Live cost tracking** — Status bar shows real-time spend based on Cloudflare pricing. Know exactly what each turn costs.
|
|
38
43
|
- **LSP + MCP** — Semantic code intelligence (hover, go-to-definition, references, diagnostics) via Language Server Protocol. Extend with external tools via Model Context Protocol.
|
|
39
44
|
- **Local structured memory** — SQLite + embeddings cross-session memory. The agent recalls facts, instructions, and preferences across sessions via `remember`, `recall`, and `forget` tools.
|
|
@@ -41,14 +46,16 @@
|
|
|
41
46
|
|
|
42
47
|
## Recently shipped
|
|
43
48
|
|
|
44
|
-
- **
|
|
45
|
-
- **
|
|
46
|
-
- **
|
|
47
|
-
- **
|
|
48
|
-
- **
|
|
49
|
-
- **
|
|
50
|
-
- **
|
|
51
|
-
- **
|
|
49
|
+
- **OS-aware shell with Windows support** — Auto-detects `cmd.exe`, PowerShell, or bash based on platform. Override with `KIMIFLARE_SHELL` or `/shell`.
|
|
50
|
+
- **Smart permission modal with inline feedback** — Deny a tool and immediately tell the agent what to do instead. Keyboard-native navigation with `↑/↓`, `j/k`, `Alt+1/2/3`.
|
|
51
|
+
- **True message queuing** — Enter queues messages while the agent is busy; Escape interrupts and auto-drains the queue.
|
|
52
|
+
- **Hard-stop loop guardrail** — Stops token-burning cycles when all tools in a turn are blocked.
|
|
53
|
+
- **Persistent all-time usage history** — `history.jsonl` tracks daily usage forever; `/cost` shows true all-time and monthly totals.
|
|
54
|
+
- **Humanized Cloudflare API errors** — Actionable error codes and structured error display instead of raw JSON dumps.
|
|
55
|
+
- **429 rate limit retry** — Automatic backoff and retry when Cloudflare rate-limits requests.
|
|
56
|
+
- **Tool state visualization** — Queued, rejected, and cancelled tools are clearly labeled in the TUI.
|
|
57
|
+
- **Paste preview placeholders** — Pasted content shows a snippet preview with sequential IDs instead of random hashes.
|
|
58
|
+
- **Headless SDK** — Programmatic `createAgentSession` API and JSONL-over-stdio RPC mode for building on top of KimiFlare.
|
|
52
59
|
|
|
53
60
|
See the full changelog at [github.com/sinameraji/kimiflare/releases](https://github.com/sinameraji/kimiflare/releases).
|
|
54
61
|
|
|
@@ -112,7 +119,7 @@ session.dispose();
|
|
|
112
119
|
```
|
|
113
120
|
|
|
114
121
|
**Key features:**
|
|
115
|
-
- `subscribe()` — receive typed events (`text_delta`, `tool_call`, `tool_result`, `task_update`, `usage`, `error`, `done`, etc.)
|
|
122
|
+
- `subscribe()` — receive typed events (`text_delta`, `tool_call`, `tool_result`, `task_update`, `usage`, `warning`, `error`, `done`, etc.)
|
|
116
123
|
- `prompt()` / `steer()` / `followUp()` — full conversation lifecycle
|
|
117
124
|
- `pause()` / `resume()` — graceful preemption
|
|
118
125
|
- `getStatus()` / `getUsage()` — inspect session state
|
|
@@ -191,6 +198,7 @@ kimiflare
|
|
|
191
198
|
| Command | Effect |
|
|
192
199
|
|---------|--------|
|
|
193
200
|
| `/mode edit\|plan\|auto` | Switch permission mode |
|
|
201
|
+
| `/shell auto\|bash\|cmd\|powershell` | Show or set the shell for the bash tool |
|
|
194
202
|
| `/thinking low\|medium\|high` | Reasoning effort (persists) |
|
|
195
203
|
| `/theme` | Interactive theme picker (`Ctrl+T`) |
|
|
196
204
|
| `/resume` | Pick a past conversation to restore |
|
package/dist/index.js
CHANGED
|
@@ -140,7 +140,7 @@ async function loadConfig() {
|
|
|
140
140
|
cacheStablePrompts,
|
|
141
141
|
compiledContext,
|
|
142
142
|
imageHistoryTurns: Number.isNaN(imageHistoryTurns) ? void 0 : imageHistoryTurns,
|
|
143
|
-
memoryEnabled: envMemoryEnabled,
|
|
143
|
+
memoryEnabled: envMemoryEnabled ?? true,
|
|
144
144
|
memoryDbPath: envMemoryDbPath,
|
|
145
145
|
memoryMaxAgeDays: envMemoryMaxAgeDays,
|
|
146
146
|
memoryMaxEntries: envMemoryMaxEntries,
|
|
@@ -199,7 +199,7 @@ async function loadConfig() {
|
|
|
199
199
|
cacheStablePrompts: parsed.cacheStablePrompts ?? cacheStablePrompts,
|
|
200
200
|
compiledContext: parsed.compiledContext ?? compiledContext,
|
|
201
201
|
imageHistoryTurns: Number.isNaN(imageHistoryTurns) ? parsed.imageHistoryTurns : imageHistoryTurns,
|
|
202
|
-
memoryEnabled: envMemoryEnabled ?? parsed.memoryEnabled,
|
|
202
|
+
memoryEnabled: envMemoryEnabled ?? parsed.memoryEnabled ?? true,
|
|
203
203
|
memoryDbPath: envMemoryDbPath ?? parsed.memoryDbPath,
|
|
204
204
|
memoryMaxAgeDays: envMemoryMaxAgeDays ?? parsed.memoryMaxAgeDays,
|
|
205
205
|
memoryMaxEntries: envMemoryMaxEntries ?? parsed.memoryMaxEntries,
|
|
@@ -353,16 +353,21 @@ var init_lsp_config = __esm({
|
|
|
353
353
|
|
|
354
354
|
// src/util/logger.ts
|
|
355
355
|
function log(level, event, data) {
|
|
356
|
-
if (LEVEL_ORDER[level] < LEVEL_ORDER[globalMinLevel]) return;
|
|
357
356
|
const entry = {
|
|
358
357
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
359
358
|
level,
|
|
360
359
|
event,
|
|
361
360
|
data
|
|
362
361
|
};
|
|
363
|
-
|
|
362
|
+
recentLogs.push(entry);
|
|
363
|
+
if (recentLogs.length > RECENT_LOGS_MAX) {
|
|
364
|
+
recentLogs.shift();
|
|
365
|
+
}
|
|
366
|
+
if (LEVEL_ORDER[level] >= LEVEL_ORDER[globalMinLevel]) {
|
|
367
|
+
console.error(JSON.stringify(entry));
|
|
368
|
+
}
|
|
364
369
|
}
|
|
365
|
-
var globalMinLevel, LEVEL_ORDER, logger;
|
|
370
|
+
var globalMinLevel, LEVEL_ORDER, RECENT_LOGS_MAX, recentLogs, logger;
|
|
366
371
|
var init_logger = __esm({
|
|
367
372
|
"src/util/logger.ts"() {
|
|
368
373
|
"use strict";
|
|
@@ -374,6 +379,8 @@ var init_logger = __esm({
|
|
|
374
379
|
error: 3,
|
|
375
380
|
off: 4
|
|
376
381
|
};
|
|
382
|
+
RECENT_LOGS_MAX = 100;
|
|
383
|
+
recentLogs = [];
|
|
377
384
|
logger = {
|
|
378
385
|
debug: (event, data) => log("debug", event, data),
|
|
379
386
|
info: (event, data) => log("info", event, data),
|
|
@@ -8866,7 +8873,7 @@ async function createAgentSession(opts2) {
|
|
|
8866
8873
|
const tools = opts2.tools ?? ALL_TOOLS;
|
|
8867
8874
|
const executor = new ToolExecutor(tools);
|
|
8868
8875
|
let memoryManager = null;
|
|
8869
|
-
const memoryEnabled = opts2.memoryEnabled ?? config.memoryEnabled ??
|
|
8876
|
+
const memoryEnabled = opts2.memoryEnabled ?? config.memoryEnabled ?? true;
|
|
8870
8877
|
if (memoryEnabled) {
|
|
8871
8878
|
const dbPath = config.memoryDbPath ?? join19(homedir12(), ".local", "share", "kimiflare", "memory.db");
|
|
8872
8879
|
memoryManager = new MemoryManager({
|
|
@@ -9821,6 +9828,59 @@ var init_abort_scope = __esm({
|
|
|
9821
9828
|
}
|
|
9822
9829
|
});
|
|
9823
9830
|
|
|
9831
|
+
// src/cloud/report.ts
|
|
9832
|
+
function buildReport2(opts2) {
|
|
9833
|
+
return {
|
|
9834
|
+
error: {
|
|
9835
|
+
message: opts2.errorMessage,
|
|
9836
|
+
code: opts2.errorCode,
|
|
9837
|
+
http_status: opts2.httpStatus
|
|
9838
|
+
},
|
|
9839
|
+
context: {
|
|
9840
|
+
command: "/report",
|
|
9841
|
+
model: opts2.model,
|
|
9842
|
+
session_id: opts2.sessionId,
|
|
9843
|
+
request_id: opts2.requestId
|
|
9844
|
+
},
|
|
9845
|
+
user_message: opts2.userNote,
|
|
9846
|
+
metadata: {
|
|
9847
|
+
version: getAppVersion(),
|
|
9848
|
+
platform: `${process.platform} ${process.arch}`,
|
|
9849
|
+
node_version: process.version,
|
|
9850
|
+
cloud_mode: opts2.cloudMode ?? false
|
|
9851
|
+
}
|
|
9852
|
+
};
|
|
9853
|
+
}
|
|
9854
|
+
async function sendReport(payload, token) {
|
|
9855
|
+
try {
|
|
9856
|
+
const headers = { "Content-Type": "application/json" };
|
|
9857
|
+
if (token) {
|
|
9858
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
9859
|
+
}
|
|
9860
|
+
const res = await fetch(REPORT_URL, {
|
|
9861
|
+
method: "POST",
|
|
9862
|
+
headers,
|
|
9863
|
+
body: JSON.stringify(payload)
|
|
9864
|
+
});
|
|
9865
|
+
if (res.ok) {
|
|
9866
|
+
return { ok: true, message: "Report sent. Thanks for helping improve KimiFlare!" };
|
|
9867
|
+
}
|
|
9868
|
+
const body = await res.text().catch(() => "unknown error");
|
|
9869
|
+
return { ok: false, message: `Failed to send report (${res.status}): ${body}` };
|
|
9870
|
+
} catch (e) {
|
|
9871
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
9872
|
+
return { ok: false, message: `Failed to send report: ${msg}` };
|
|
9873
|
+
}
|
|
9874
|
+
}
|
|
9875
|
+
var REPORT_URL;
|
|
9876
|
+
var init_report2 = __esm({
|
|
9877
|
+
"src/cloud/report.ts"() {
|
|
9878
|
+
"use strict";
|
|
9879
|
+
init_version();
|
|
9880
|
+
REPORT_URL = "https://api.kimiflare.com/v1/report";
|
|
9881
|
+
}
|
|
9882
|
+
});
|
|
9883
|
+
|
|
9824
9884
|
// src/ui/theme-context.tsx
|
|
9825
9885
|
import { createContext, useContext } from "react";
|
|
9826
9886
|
import { jsx } from "react/jsx-runtime";
|
|
@@ -10629,7 +10689,8 @@ function ApiErrorMessage({ httpStatus, code, message: message2 }) {
|
|
|
10629
10689
|
"\u26A0 ",
|
|
10630
10690
|
message2
|
|
10631
10691
|
] }),
|
|
10632
|
-
meta && /* @__PURE__ */ jsx6(Text5, { color: theme.muted?.color ?? theme.info.color, dimColor: theme.muted?.dim ?? true, children: meta })
|
|
10692
|
+
meta && /* @__PURE__ */ jsx6(Text5, { color: theme.muted?.color ?? theme.info.color, dimColor: theme.muted?.dim ?? true, children: meta }),
|
|
10693
|
+
/* @__PURE__ */ jsx6(Text5, { color: theme.muted?.color ?? theme.info.color, dimColor: theme.muted?.dim ?? true, children: "Type /report to send diagnostic info" })
|
|
10633
10694
|
] });
|
|
10634
10695
|
}
|
|
10635
10696
|
var init_api_error_message = __esm({
|
|
@@ -13766,6 +13827,7 @@ var init_builtins = __esm({
|
|
|
13766
13827
|
{ name: "remote", argHint: "<prompt>", description: "Run a remote session on Cloudflare", source: "builtin" },
|
|
13767
13828
|
{ name: "update", description: "Check for updates", source: "builtin" },
|
|
13768
13829
|
{ name: "hello", description: "Send a voice note to the creator", source: "builtin" },
|
|
13830
|
+
{ name: "report", argHint: "[send] [note]", description: "Report the last API error with diagnostic logs", source: "builtin" },
|
|
13769
13831
|
{ name: "shell", argHint: "[auto|bash|cmd|powershell|<path>]", description: "Show or set shell for bash tool", source: "builtin" },
|
|
13770
13832
|
{ name: "logout", description: "Clear stored credentials", source: "builtin" },
|
|
13771
13833
|
{ name: "exit", description: "Exit kimiflare", source: "builtin" },
|
|
@@ -17147,6 +17209,7 @@ ${wcagWarnings.join("\n")}` }
|
|
|
17147
17209
|
const tasksRef = useRef3([]);
|
|
17148
17210
|
const usageRef = useRef3(null);
|
|
17149
17211
|
const gatewayMetaRef = useRef3(null);
|
|
17212
|
+
const lastApiErrorRef = useRef3(null);
|
|
17150
17213
|
const updateCheckedRef = useRef3(false);
|
|
17151
17214
|
const sessionStateRef = useRef3(emptySessionState());
|
|
17152
17215
|
const artifactStoreRef = useRef3(new ArtifactStore());
|
|
@@ -18368,15 +18431,11 @@ ${wcagWarnings.join("\n")}` }
|
|
|
18368
18431
|
{ kind: "error", key: mkKey(), text: "The agent got stuck repeating the same actions. Here's what we know so far." }
|
|
18369
18432
|
]);
|
|
18370
18433
|
} else if (e instanceof KimiApiError && (e.httpStatus === 429 || e.code === 3040 || e.httpStatus !== void 0 && e.httpStatus >= 500)) {
|
|
18434
|
+
const err = { httpStatus: e.httpStatus, code: e.code, message: humanizeCloudflareError(e) };
|
|
18435
|
+
lastApiErrorRef.current = err;
|
|
18371
18436
|
setEvents((es) => [
|
|
18372
18437
|
...es,
|
|
18373
|
-
{
|
|
18374
|
-
kind: "api_error",
|
|
18375
|
-
key: mkKey(),
|
|
18376
|
-
httpStatus: e.httpStatus,
|
|
18377
|
-
code: e.code,
|
|
18378
|
-
message: humanizeCloudflareError(e)
|
|
18379
|
-
}
|
|
18438
|
+
{ kind: "api_error", key: mkKey(), ...err }
|
|
18380
18439
|
]);
|
|
18381
18440
|
} else {
|
|
18382
18441
|
const displayText = e instanceof KimiApiError ? humanizeCloudflareError(e) : `init failed: ${e.message}`;
|
|
@@ -19191,6 +19250,55 @@ ${lines.join("\n")}` }]);
|
|
|
19191
19250
|
]);
|
|
19192
19251
|
return true;
|
|
19193
19252
|
}
|
|
19253
|
+
if (c === "/report") {
|
|
19254
|
+
const err = lastApiErrorRef.current;
|
|
19255
|
+
if (!err) {
|
|
19256
|
+
setEvents((e) => [
|
|
19257
|
+
...e,
|
|
19258
|
+
{ kind: "info", key: mkKey(), text: "No recent API error to report." }
|
|
19259
|
+
]);
|
|
19260
|
+
return true;
|
|
19261
|
+
}
|
|
19262
|
+
const note = rest.join(" ").trim();
|
|
19263
|
+
const isSend = note.toLowerCase() === "send" || note.toLowerCase().startsWith("send ");
|
|
19264
|
+
if (!isSend) {
|
|
19265
|
+
const preview = [
|
|
19266
|
+
"Report preview:",
|
|
19267
|
+
` Error: ${err.message}`,
|
|
19268
|
+
err.httpStatus !== void 0 ? ` HTTP ${err.httpStatus}` : "",
|
|
19269
|
+
err.code !== void 0 ? ` Code: ${err.code}` : "",
|
|
19270
|
+
note ? ` Note: ${note}` : "",
|
|
19271
|
+
"",
|
|
19272
|
+
"Type `/report send` to submit or `/report send <note>` to add context."
|
|
19273
|
+
].filter(Boolean).join("\n");
|
|
19274
|
+
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: preview }]);
|
|
19275
|
+
return true;
|
|
19276
|
+
}
|
|
19277
|
+
const userNote = note.slice(4).trim() || void 0;
|
|
19278
|
+
const payload = buildReport2({
|
|
19279
|
+
errorMessage: err.message,
|
|
19280
|
+
httpStatus: err.httpStatus,
|
|
19281
|
+
errorCode: err.code,
|
|
19282
|
+
sessionId: sessionIdRef.current ?? void 0,
|
|
19283
|
+
userNote,
|
|
19284
|
+
model: cfg?.model,
|
|
19285
|
+
cloudMode: cfg?.cloudMode
|
|
19286
|
+
});
|
|
19287
|
+
void sendReport(payload, cfg?.cloudToken).then((result) => {
|
|
19288
|
+
setEvents((e) => [
|
|
19289
|
+
...e,
|
|
19290
|
+
{ kind: result.ok ? "info" : "error", key: mkKey(), text: result.message }
|
|
19291
|
+
]);
|
|
19292
|
+
if (result.ok) {
|
|
19293
|
+
lastApiErrorRef.current = null;
|
|
19294
|
+
}
|
|
19295
|
+
});
|
|
19296
|
+
setEvents((e) => [
|
|
19297
|
+
...e,
|
|
19298
|
+
{ kind: "info", key: mkKey(), text: "Sending report\u2026" }
|
|
19299
|
+
]);
|
|
19300
|
+
return true;
|
|
19301
|
+
}
|
|
19194
19302
|
if (c === "/logout") {
|
|
19195
19303
|
unlink4(configPath()).catch(() => {
|
|
19196
19304
|
});
|
|
@@ -19967,15 +20075,11 @@ ${lines.join("\n")}` }]);
|
|
|
19967
20075
|
{ kind: "cloud_quota_exhausted", key: mkKey(), used, limit, expiresAt }
|
|
19968
20076
|
]);
|
|
19969
20077
|
} else if (e instanceof KimiApiError && (e.httpStatus === 429 || e.code === 3040 || e.httpStatus !== void 0 && e.httpStatus >= 500)) {
|
|
20078
|
+
const err = { httpStatus: e.httpStatus, code: e.code, message: humanizeCloudflareError(e) };
|
|
20079
|
+
lastApiErrorRef.current = err;
|
|
19970
20080
|
setEvents((es) => [
|
|
19971
20081
|
...es,
|
|
19972
|
-
{
|
|
19973
|
-
kind: "api_error",
|
|
19974
|
-
key: mkKey(),
|
|
19975
|
-
httpStatus: e.httpStatus,
|
|
19976
|
-
code: e.code,
|
|
19977
|
-
message: humanizeCloudflareError(e)
|
|
19978
|
-
}
|
|
20082
|
+
{ kind: "api_error", key: mkKey(), ...err }
|
|
19979
20083
|
]);
|
|
19980
20084
|
} else {
|
|
19981
20085
|
const displayText2 = e instanceof KimiApiError ? humanizeCloudflareError(e) : e.message ?? String(e);
|
|
@@ -20393,6 +20497,7 @@ var init_app = __esm({
|
|
|
20393
20497
|
init_errors();
|
|
20394
20498
|
init_abort_scope();
|
|
20395
20499
|
init_logger();
|
|
20500
|
+
init_report2();
|
|
20396
20501
|
init_chat();
|
|
20397
20502
|
init_status();
|
|
20398
20503
|
init_permission();
|
|
@@ -20671,7 +20776,7 @@ async function main() {
|
|
|
20671
20776
|
cloudToken = cloudCreds.accessToken;
|
|
20672
20777
|
cloudDeviceId = cloudCreds.deviceId;
|
|
20673
20778
|
cfg = {
|
|
20674
|
-
...cfg ?? { accountId: "", apiToken: "", model: DEFAULT_MODEL },
|
|
20779
|
+
...cfg ?? { accountId: "", apiToken: "", model: DEFAULT_MODEL, memoryEnabled: true },
|
|
20675
20780
|
cloudMode: true
|
|
20676
20781
|
};
|
|
20677
20782
|
}
|