kimiflare 0.50.0 → 0.51.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 -113
- package/dist/index.js.map +1 -1
- package/dist/sdk/index.js +99 -92
- package/dist/sdk/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2467,6 +2467,7 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
2467
2467
|
let cumulativePromptTokens = 0;
|
|
2468
2468
|
let iter = 0;
|
|
2469
2469
|
let budgetExhausted = false;
|
|
2470
|
+
let loopExhausted = false;
|
|
2470
2471
|
while (true) {
|
|
2471
2472
|
if (budgetExhausted) {
|
|
2472
2473
|
opts2.messages.push({
|
|
@@ -2474,6 +2475,12 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
2474
2475
|
content: "You have reached the cumulative input token budget for this session. Please synthesize your findings and provide a final summary of what was accomplished."
|
|
2475
2476
|
});
|
|
2476
2477
|
}
|
|
2478
|
+
if (loopExhausted) {
|
|
2479
|
+
opts2.messages.push({
|
|
2480
|
+
role: "system",
|
|
2481
|
+
content: "You have repeatedly called the same tools with identical arguments and are stuck in a loop. Please synthesize what you know from the conversation history and provide a final answer."
|
|
2482
|
+
});
|
|
2483
|
+
}
|
|
2477
2484
|
if (iter >= max) {
|
|
2478
2485
|
if (opts2.callbacks.onToolLimitReached) {
|
|
2479
2486
|
const decision = await opts2.callbacks.onToolLimitReached();
|
|
@@ -2651,6 +2658,7 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
2651
2658
|
logger.info("turn:complete", { sessionId: opts2.sessionId, durationMs: Math.round(performance.now() - turnStart) });
|
|
2652
2659
|
return;
|
|
2653
2660
|
}
|
|
2661
|
+
let blockedCount = 0;
|
|
2654
2662
|
for (const tc of toolCalls) {
|
|
2655
2663
|
if (opts2.signal.aborted) throw new DOMException("aborted", "AbortError");
|
|
2656
2664
|
const loopSignature = `${tc.function.name}:${stableStringify(tc.function.arguments)}`;
|
|
@@ -2673,6 +2681,7 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
2673
2681
|
opts2.callbacks.onToolResult?.(loopResult);
|
|
2674
2682
|
recentToolCalls.push(loopSignature);
|
|
2675
2683
|
if (recentToolCalls.length > LOOP_WINDOW) recentToolCalls.shift();
|
|
2684
|
+
blockedCount++;
|
|
2676
2685
|
continue;
|
|
2677
2686
|
}
|
|
2678
2687
|
if (tc.function.name === "web_fetch") {
|
|
@@ -2700,6 +2709,7 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
2700
2709
|
opts2.callbacks.onToolResult?.(budgetResult);
|
|
2701
2710
|
recentToolCalls.push(loopSignature);
|
|
2702
2711
|
if (recentToolCalls.length > LOOP_WINDOW) recentToolCalls.shift();
|
|
2712
|
+
blockedCount++;
|
|
2703
2713
|
continue;
|
|
2704
2714
|
}
|
|
2705
2715
|
if (domainCount >= WEB_FETCH_DOMAIN_THRESHOLD) {
|
|
@@ -2720,6 +2730,7 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
2720
2730
|
opts2.callbacks.onToolResult?.(loopResult);
|
|
2721
2731
|
recentToolCalls.push(loopSignature);
|
|
2722
2732
|
if (recentToolCalls.length > LOOP_WINDOW) recentToolCalls.shift();
|
|
2733
|
+
blockedCount++;
|
|
2723
2734
|
continue;
|
|
2724
2735
|
}
|
|
2725
2736
|
webFetchHistory.push({ url, domain });
|
|
@@ -2855,6 +2866,9 @@ ${sandboxResult.output}` : `${warningPrefix}${sandboxResult.output}`;
|
|
|
2855
2866
|
if (recentToolCalls.length > LOOP_WINDOW) recentToolCalls.shift();
|
|
2856
2867
|
}
|
|
2857
2868
|
}
|
|
2869
|
+
if (blockedCount === toolCalls.length && toolCalls.length > 0) {
|
|
2870
|
+
loopExhausted = true;
|
|
2871
|
+
}
|
|
2858
2872
|
if (opts2.sessionId) {
|
|
2859
2873
|
const current = driftAccumulator.get(opts2.sessionId) ?? 0;
|
|
2860
2874
|
if (current > 0) {
|
|
@@ -2883,6 +2897,9 @@ ${sandboxResult.output}` : `${warningPrefix}${sandboxResult.output}`;
|
|
|
2883
2897
|
if (budgetExhausted) {
|
|
2884
2898
|
throw new BudgetExhaustedError();
|
|
2885
2899
|
}
|
|
2900
|
+
if (loopExhausted) {
|
|
2901
|
+
throw new AgentLoopError();
|
|
2902
|
+
}
|
|
2886
2903
|
}
|
|
2887
2904
|
}
|
|
2888
2905
|
function validateToolArguments(raw) {
|
|
@@ -2894,7 +2911,7 @@ function validateToolArguments(raw) {
|
|
|
2894
2911
|
return "{}";
|
|
2895
2912
|
}
|
|
2896
2913
|
}
|
|
2897
|
-
var BudgetExhaustedError, codeModeApiCache, driftAccumulator, DRIFT_THRESHOLD, MAX_PROMPT_TOKENS, MAX_TOOL_CONTENT_CHARS;
|
|
2914
|
+
var BudgetExhaustedError, AgentLoopError, codeModeApiCache, driftAccumulator, DRIFT_THRESHOLD, MAX_PROMPT_TOKENS, MAX_TOOL_CONTENT_CHARS;
|
|
2898
2915
|
var init_loop = __esm({
|
|
2899
2916
|
"src/agent/loop.ts"() {
|
|
2900
2917
|
"use strict";
|
|
@@ -2913,6 +2930,12 @@ var init_loop = __esm({
|
|
|
2913
2930
|
this.name = "BudgetExhaustedError";
|
|
2914
2931
|
}
|
|
2915
2932
|
};
|
|
2933
|
+
AgentLoopError = class extends Error {
|
|
2934
|
+
constructor(message2 = "Agent got stuck repeating the same tool calls") {
|
|
2935
|
+
super(message2);
|
|
2936
|
+
this.name = "AgentLoopError";
|
|
2937
|
+
}
|
|
2938
|
+
};
|
|
2916
2939
|
codeModeApiCache = /* @__PURE__ */ new Map();
|
|
2917
2940
|
driftAccumulator = /* @__PURE__ */ new Map();
|
|
2918
2941
|
DRIFT_THRESHOLD = 5;
|
|
@@ -2953,88 +2976,47 @@ function isBlockedInPlanMode(toolName) {
|
|
|
2953
2976
|
if (toolName === "browser_fetch") return true;
|
|
2954
2977
|
return false;
|
|
2955
2978
|
}
|
|
2956
|
-
function
|
|
2957
|
-
const
|
|
2958
|
-
let
|
|
2959
|
-
let
|
|
2960
|
-
for (const ch of
|
|
2961
|
-
if (
|
|
2962
|
-
if (ch ===
|
|
2963
|
-
|
|
2964
|
-
} else {
|
|
2965
|
-
current += ch;
|
|
2966
|
-
}
|
|
2979
|
+
function getTokens(s) {
|
|
2980
|
+
const toks = [];
|
|
2981
|
+
let cur = "";
|
|
2982
|
+
let q = null;
|
|
2983
|
+
for (const ch of s) {
|
|
2984
|
+
if (q) {
|
|
2985
|
+
if (ch === q) q = null;
|
|
2986
|
+
else cur += ch;
|
|
2967
2987
|
} else if (ch === '"' || ch === "'") {
|
|
2968
|
-
|
|
2988
|
+
q = ch;
|
|
2969
2989
|
} else if (/\s/.test(ch)) {
|
|
2970
|
-
if (
|
|
2971
|
-
|
|
2972
|
-
|
|
2990
|
+
if (cur) {
|
|
2991
|
+
toks.push(cur);
|
|
2992
|
+
cur = "";
|
|
2973
2993
|
}
|
|
2974
2994
|
} else {
|
|
2975
|
-
|
|
2995
|
+
cur += ch;
|
|
2976
2996
|
}
|
|
2977
2997
|
}
|
|
2978
|
-
if (
|
|
2979
|
-
return
|
|
2998
|
+
if (cur) toks.push(cur);
|
|
2999
|
+
return toks;
|
|
2980
3000
|
}
|
|
2981
|
-
function
|
|
2982
|
-
const
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
for (let i = 0; i < command.length; i++) {
|
|
2986
|
-
const ch = command[i];
|
|
2987
|
-
if (inQuote) {
|
|
2988
|
-
if (ch === inQuote) {
|
|
2989
|
-
inQuote = null;
|
|
2990
|
-
}
|
|
2991
|
-
current += ch;
|
|
2992
|
-
continue;
|
|
2993
|
-
}
|
|
2994
|
-
if (ch === '"' || ch === "'") {
|
|
2995
|
-
inQuote = ch;
|
|
2996
|
-
current += ch;
|
|
2997
|
-
continue;
|
|
2998
|
-
}
|
|
2999
|
-
let matchedOp = false;
|
|
3000
|
-
for (const op of operators) {
|
|
3001
|
-
if (command.slice(i, i + op.length) === op) {
|
|
3002
|
-
segments.push(current.trim());
|
|
3003
|
-
current = "";
|
|
3004
|
-
i += op.length - 1;
|
|
3005
|
-
matchedOp = true;
|
|
3006
|
-
break;
|
|
3007
|
-
}
|
|
3008
|
-
}
|
|
3009
|
-
if (matchedOp) continue;
|
|
3010
|
-
current += ch;
|
|
3011
|
-
}
|
|
3012
|
-
if (current.trim()) segments.push(current.trim());
|
|
3013
|
-
return segments;
|
|
3014
|
-
}
|
|
3015
|
-
function isReadOnlyBashSegment(command) {
|
|
3016
|
-
const trimmed = command.trim();
|
|
3017
|
-
if (!trimmed) return false;
|
|
3018
|
-
const tokens = tokenizeCommand(trimmed);
|
|
3019
|
-
if (tokens.length === 0) return false;
|
|
3020
|
-
const cmd = tokens[0];
|
|
3021
|
-
const args = tokens.slice(1);
|
|
3001
|
+
function isReadOnlySegment(seg) {
|
|
3002
|
+
const toks = getTokens(seg.trim());
|
|
3003
|
+
if (toks.length === 0) return false;
|
|
3004
|
+
const [cmd, sub, ...rest] = toks;
|
|
3022
3005
|
if (cmd === "git") {
|
|
3023
|
-
const
|
|
3024
|
-
const allowed = GIT_READONLY_SUBCOMMANDS[sub];
|
|
3006
|
+
const allowed = GIT_READONLY_SUBCOMMANDS[sub ?? ""];
|
|
3025
3007
|
if (allowed === void 0) return false;
|
|
3026
3008
|
if (allowed === true) return true;
|
|
3027
3009
|
switch (sub) {
|
|
3028
3010
|
case "branch":
|
|
3029
|
-
return !
|
|
3011
|
+
return !rest.some((a) => /^-[dDmMcC]/.test(a));
|
|
3030
3012
|
case "stash":
|
|
3031
|
-
return
|
|
3013
|
+
return rest[0] === "list";
|
|
3032
3014
|
case "remote":
|
|
3033
|
-
return
|
|
3015
|
+
return rest[0] === "-v" || rest[0] === "--verbose" || rest.length === 0;
|
|
3034
3016
|
case "tag":
|
|
3035
|
-
return
|
|
3017
|
+
return rest[0] === "-l" || rest[0] === "--list" || rest.length === 0;
|
|
3036
3018
|
case "config":
|
|
3037
|
-
return
|
|
3019
|
+
return rest[0] === "--list" || rest[0]?.startsWith("--get") === true || rest.length === 0;
|
|
3038
3020
|
default:
|
|
3039
3021
|
return false;
|
|
3040
3022
|
}
|
|
@@ -3045,10 +3027,32 @@ function isReadOnlyBash(command) {
|
|
|
3045
3027
|
const trimmed = command.trim();
|
|
3046
3028
|
if (!trimmed) return false;
|
|
3047
3029
|
if (DANGEROUS_PATTERNS.test(trimmed)) return false;
|
|
3048
|
-
const
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3030
|
+
const segs = [];
|
|
3031
|
+
let cur = "";
|
|
3032
|
+
let q = null;
|
|
3033
|
+
for (let i = 0; i < trimmed.length; i++) {
|
|
3034
|
+
const ch = trimmed[i];
|
|
3035
|
+
if (q) {
|
|
3036
|
+
if (ch === q) q = null;
|
|
3037
|
+
cur += ch;
|
|
3038
|
+
} else if (ch === '"' || ch === "'") {
|
|
3039
|
+
q = ch;
|
|
3040
|
+
cur += ch;
|
|
3041
|
+
} else if (trimmed.slice(i, i + 2) === "&&") {
|
|
3042
|
+
segs.push(cur);
|
|
3043
|
+
cur = "";
|
|
3044
|
+
i++;
|
|
3045
|
+
} else if (ch === "|") {
|
|
3046
|
+
segs.push(cur);
|
|
3047
|
+
cur = "";
|
|
3048
|
+
} else {
|
|
3049
|
+
cur += ch;
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3052
|
+
if (cur.trim()) segs.push(cur);
|
|
3053
|
+
if (segs.length === 0) return false;
|
|
3054
|
+
for (const seg of segs) {
|
|
3055
|
+
if (!isReadOnlySegment(seg.trim())) return false;
|
|
3052
3056
|
}
|
|
3053
3057
|
return true;
|
|
3054
3058
|
}
|
|
@@ -3349,8 +3353,8 @@ var init_write = __esm({
|
|
|
3349
3353
|
},
|
|
3350
3354
|
needsPermission: true,
|
|
3351
3355
|
render: (args) => ({
|
|
3352
|
-
title: `write ${collapsePath(args.path, process.cwd())} (${args.content.length} chars)`,
|
|
3353
|
-
diff: { path: args.path, before: "", after: args.content }
|
|
3356
|
+
title: `write ${collapsePath(String(args.path ?? ""), process.cwd())} (${String(args.content ?? "").length} chars)`,
|
|
3357
|
+
diff: { path: String(args.path ?? ""), before: "", after: String(args.content ?? "") }
|
|
3354
3358
|
}),
|
|
3355
3359
|
async run(args, ctx) {
|
|
3356
3360
|
const abs = resolvePath(ctx.cwd, args.path);
|
|
@@ -3402,8 +3406,8 @@ var init_edit = __esm({
|
|
|
3402
3406
|
},
|
|
3403
3407
|
needsPermission: true,
|
|
3404
3408
|
render: (args) => ({
|
|
3405
|
-
title: `edit ${collapsePath(args.path, process.cwd())}${args.replace_all ? " (replace_all)" : ""}`,
|
|
3406
|
-
diff: { path: args.path, before: args.old_string, after: args.new_string }
|
|
3409
|
+
title: `edit ${collapsePath(String(args.path ?? ""), process.cwd())}${args.replace_all ? " (replace_all)" : ""}`,
|
|
3410
|
+
diff: { path: String(args.path ?? ""), before: String(args.old_string ?? ""), after: String(args.new_string ?? "") }
|
|
3407
3411
|
}),
|
|
3408
3412
|
async run(args, ctx) {
|
|
3409
3413
|
const abs = resolvePath(ctx.cwd, args.path);
|
|
@@ -3551,7 +3555,7 @@ var init_bash = __esm({
|
|
|
3551
3555
|
additionalProperties: false
|
|
3552
3556
|
},
|
|
3553
3557
|
needsPermission: true,
|
|
3554
|
-
render: (args) => ({ title: formatBashTitle(args.command) }),
|
|
3558
|
+
render: (args) => ({ title: formatBashTitle(String(args.command ?? "")) }),
|
|
3555
3559
|
run: (args, ctx) => runBash(args, ctx)
|
|
3556
3560
|
};
|
|
3557
3561
|
}
|
|
@@ -3577,7 +3581,7 @@ var init_glob = __esm({
|
|
|
3577
3581
|
additionalProperties: false
|
|
3578
3582
|
},
|
|
3579
3583
|
needsPermission: false,
|
|
3580
|
-
render: (args) => ({ title: `glob ${args.pattern}${args.path ? ` in ${collapsePath(args.path, process.cwd())}` : ""}` }),
|
|
3584
|
+
render: (args) => ({ title: `glob ${args.pattern ?? ""}${args.path ? ` in ${collapsePath(String(args.path), process.cwd())}` : ""}` }),
|
|
3581
3585
|
async run(args, ctx) {
|
|
3582
3586
|
const root = args.path ? resolvePath(ctx.cwd, args.path) : ctx.cwd;
|
|
3583
3587
|
const entries = await fg(args.pattern, {
|
|
@@ -3695,7 +3699,7 @@ var init_grep = __esm({
|
|
|
3695
3699
|
additionalProperties: false
|
|
3696
3700
|
},
|
|
3697
3701
|
needsPermission: false,
|
|
3698
|
-
render: (args) => ({ title: `grep ${args.pattern}${args.glob ? ` (${args.glob})` : ""}` }),
|
|
3702
|
+
render: (args) => ({ title: `grep ${args.pattern ?? ""}${args.glob ? ` (${args.glob})` : ""}` }),
|
|
3699
3703
|
async run(args, ctx) {
|
|
3700
3704
|
const root = args.path ? resolvePath(ctx.cwd, args.path) : ctx.cwd;
|
|
3701
3705
|
const mode = args.output_mode ?? "content";
|
|
@@ -3727,7 +3731,7 @@ var init_web_fetch = __esm({
|
|
|
3727
3731
|
additionalProperties: false
|
|
3728
3732
|
},
|
|
3729
3733
|
needsPermission: false,
|
|
3730
|
-
render: (args) => ({ title: `GET ${args.url}` }),
|
|
3734
|
+
render: (args) => ({ title: `GET ${args.url ?? ""}` }),
|
|
3731
3735
|
async run(args) {
|
|
3732
3736
|
const controller = new AbortController();
|
|
3733
3737
|
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
@@ -3862,7 +3866,7 @@ var init_web_search = __esm({
|
|
|
3862
3866
|
additionalProperties: false
|
|
3863
3867
|
},
|
|
3864
3868
|
needsPermission: false,
|
|
3865
|
-
render: (args) => ({ title: `search web: ${args.query}` }),
|
|
3869
|
+
render: (args) => ({ title: `search web: ${args.query ?? ""}` }),
|
|
3866
3870
|
async run(args) {
|
|
3867
3871
|
const count = Math.min(Math.max(args.count ?? DEFAULT_RESULTS, 1), MAX_RESULTS);
|
|
3868
3872
|
try {
|
|
@@ -3948,7 +3952,7 @@ var init_github = __esm({
|
|
|
3948
3952
|
additionalProperties: false
|
|
3949
3953
|
},
|
|
3950
3954
|
needsPermission: false,
|
|
3951
|
-
render: (args) => ({ title: `GitHub PR ${args.owner}/${args.repo}#${args.number}` }),
|
|
3955
|
+
render: (args) => ({ title: `GitHub PR ${args.owner ?? ""}/${args.repo ?? ""}#${args.number ?? ""}` }),
|
|
3952
3956
|
async run(args, ctx) {
|
|
3953
3957
|
const token = getToken(ctx);
|
|
3954
3958
|
const pr = await githubFetch(`/repos/${args.owner}/${args.repo}/pulls/${args.number}`, token);
|
|
@@ -3990,7 +3994,7 @@ var init_github = __esm({
|
|
|
3990
3994
|
additionalProperties: false
|
|
3991
3995
|
},
|
|
3992
3996
|
needsPermission: false,
|
|
3993
|
-
render: (args) => ({ title: `GitHub issue ${args.owner}/${args.repo}#${args.number}` }),
|
|
3997
|
+
render: (args) => ({ title: `GitHub issue ${args.owner ?? ""}/${args.repo ?? ""}#${args.number ?? ""}` }),
|
|
3994
3998
|
async run(args, ctx) {
|
|
3995
3999
|
const token = getToken(ctx);
|
|
3996
4000
|
const issue = await githubFetch(`/repos/${args.owner}/${args.repo}/issues/${args.number}`, token);
|
|
@@ -4037,7 +4041,7 @@ var init_github = __esm({
|
|
|
4037
4041
|
},
|
|
4038
4042
|
needsPermission: false,
|
|
4039
4043
|
render: (args) => ({
|
|
4040
|
-
title: `GitHub code ${args.owner}/${args.repo}/${args.path}${args.ref ? `@${args.ref}` : ""}`
|
|
4044
|
+
title: `GitHub code ${args.owner ?? ""}/${args.repo ?? ""}/${args.path ?? ""}${args.ref ? `@${args.ref}` : ""}`
|
|
4041
4045
|
}),
|
|
4042
4046
|
async run(args, ctx) {
|
|
4043
4047
|
const token = getToken(ctx);
|
|
@@ -4115,7 +4119,7 @@ var init_browser = __esm({
|
|
|
4115
4119
|
},
|
|
4116
4120
|
needsPermission: false,
|
|
4117
4121
|
render: (args) => ({
|
|
4118
|
-
title: `browser ${args.url}${args.screenshot ? " (screenshot)" : ""}`
|
|
4122
|
+
title: `browser ${args.url ?? ""}${args.screenshot ? " (screenshot)" : ""}`
|
|
4119
4123
|
}),
|
|
4120
4124
|
async run(args, ctx) {
|
|
4121
4125
|
let playwright;
|
|
@@ -4241,10 +4245,13 @@ var init_tasks = __esm({
|
|
|
4241
4245
|
required: ["tasks"]
|
|
4242
4246
|
},
|
|
4243
4247
|
needsPermission: false,
|
|
4244
|
-
render: (args) =>
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
+
render: (args) => {
|
|
4249
|
+
const tasks = Array.isArray(args.tasks) ? args.tasks : [];
|
|
4250
|
+
return {
|
|
4251
|
+
title: `tasks (${tasks.length} items)`,
|
|
4252
|
+
body: tasks.map((t) => `${t.status === "completed" ? "\u2713" : t.status === "in_progress" ? "\u25B8" : "\xB7"} ${t.title}`).join("\n")
|
|
4253
|
+
};
|
|
4254
|
+
},
|
|
4248
4255
|
run: async (args, ctx) => {
|
|
4249
4256
|
let tasks;
|
|
4250
4257
|
try {
|
|
@@ -4295,7 +4302,7 @@ var init_memory = __esm({
|
|
|
4295
4302
|
needsPermission: false,
|
|
4296
4303
|
render: (args) => ({
|
|
4297
4304
|
title: "memory_remember",
|
|
4298
|
-
body: `[${args.category}] ${args.content} (importance: ${args.importance})`
|
|
4305
|
+
body: `[${args.category ?? "unknown"}] ${args.content ?? ""} (importance: ${args.importance ?? 1})`
|
|
4299
4306
|
}),
|
|
4300
4307
|
run: async (args, ctx) => {
|
|
4301
4308
|
if (!isMemoryCtx(ctx) || !ctx.memoryManager) {
|
|
@@ -4350,7 +4357,7 @@ var init_memory = __esm({
|
|
|
4350
4357
|
needsPermission: false,
|
|
4351
4358
|
render: (args) => ({
|
|
4352
4359
|
title: "memory_recall",
|
|
4353
|
-
body: `Query: "${args.query}"`
|
|
4360
|
+
body: `Query: "${args.query ?? ""}"`
|
|
4354
4361
|
}),
|
|
4355
4362
|
run: async (args, ctx) => {
|
|
4356
4363
|
if (!isMemoryCtx(ctx) || !ctx.memoryManager) {
|
|
@@ -4395,7 +4402,7 @@ var init_memory = __esm({
|
|
|
4395
4402
|
needsPermission: false,
|
|
4396
4403
|
render: (args) => ({
|
|
4397
4404
|
title: "memory_forget",
|
|
4398
|
-
body: `Forgetting memory ${args.memory_id}`
|
|
4405
|
+
body: `Forgetting memory ${args.memory_id ?? ""}`
|
|
4399
4406
|
}),
|
|
4400
4407
|
run: async (args, ctx) => {
|
|
4401
4408
|
if (!isMemoryCtx(ctx) || !ctx.memoryManager) {
|
|
@@ -4955,7 +4962,7 @@ function makeExpandArtifactTool(store) {
|
|
|
4955
4962
|
additionalProperties: false
|
|
4956
4963
|
},
|
|
4957
4964
|
needsPermission: false,
|
|
4958
|
-
render: (args) => ({ title: `expand ${args.artifact_id}` }),
|
|
4965
|
+
render: (args) => ({ title: `expand ${args.artifact_id ?? ""}` }),
|
|
4959
4966
|
run: async (args) => {
|
|
4960
4967
|
const raw = store.retrieve(args.artifact_id);
|
|
4961
4968
|
if (!raw) {
|
|
@@ -6075,13 +6082,18 @@ __export(auth_exports, {
|
|
|
6075
6082
|
registerDevice: () => registerDevice,
|
|
6076
6083
|
saveCloudCredentials: () => saveCloudCredentials
|
|
6077
6084
|
});
|
|
6078
|
-
import { readFile as readFile11, writeFile as writeFile8 } from "fs/promises";
|
|
6079
|
-
import {
|
|
6085
|
+
import { readFile as readFile11, writeFile as writeFile8, mkdir as mkdir8 } from "fs/promises";
|
|
6086
|
+
import { createHash } from "crypto";
|
|
6087
|
+
import { homedir as homedir9, hostname, userInfo } from "os";
|
|
6080
6088
|
import { join as join15 } from "path";
|
|
6081
6089
|
function cloudCredPath() {
|
|
6082
6090
|
const xdg = process.env.XDG_CONFIG_HOME || join15(homedir9(), ".config");
|
|
6083
6091
|
return join15(xdg, "kimiflare", "cloud.json");
|
|
6084
6092
|
}
|
|
6093
|
+
function deviceIdPath() {
|
|
6094
|
+
const xdg = process.env.XDG_DATA_HOME || join15(homedir9(), ".local", "share");
|
|
6095
|
+
return join15(xdg, "kimiflare", "device_id");
|
|
6096
|
+
}
|
|
6085
6097
|
function generateCode() {
|
|
6086
6098
|
const chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
6087
6099
|
let out = "";
|
|
@@ -6090,16 +6102,51 @@ function generateCode() {
|
|
|
6090
6102
|
}
|
|
6091
6103
|
return out;
|
|
6092
6104
|
}
|
|
6093
|
-
function
|
|
6105
|
+
function deriveStableDeviceId() {
|
|
6106
|
+
const seed = `${hostname()}:${userInfo().username}:${homedir9()}`;
|
|
6107
|
+
const hash = createHash("sha256").update(seed).digest();
|
|
6108
|
+
return hash.subarray(0, 16).toString("hex");
|
|
6109
|
+
}
|
|
6110
|
+
function generateRandomDeviceId() {
|
|
6094
6111
|
const arr = new Uint8Array(16);
|
|
6095
6112
|
crypto.getRandomValues(arr);
|
|
6096
6113
|
return Array.from(arr, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
6097
6114
|
}
|
|
6098
|
-
function
|
|
6115
|
+
async function getOrCreateDeviceId() {
|
|
6116
|
+
try {
|
|
6117
|
+
const raw = await readFile11(deviceIdPath(), "utf8");
|
|
6118
|
+
const id = raw.trim();
|
|
6119
|
+
if (/^[0-9a-f]{32}$/i.test(id)) return id;
|
|
6120
|
+
} catch {
|
|
6121
|
+
}
|
|
6122
|
+
try {
|
|
6123
|
+
const raw = await readFile11(cloudCredPath(), "utf8");
|
|
6124
|
+
const parsed = JSON.parse(raw);
|
|
6125
|
+
if (parsed.deviceId && /^[0-9a-f]{32}$/i.test(parsed.deviceId)) {
|
|
6126
|
+
await persistDeviceId(parsed.deviceId);
|
|
6127
|
+
return parsed.deviceId;
|
|
6128
|
+
}
|
|
6129
|
+
} catch {
|
|
6130
|
+
}
|
|
6131
|
+
let deviceId;
|
|
6132
|
+
try {
|
|
6133
|
+
deviceId = deriveStableDeviceId();
|
|
6134
|
+
} catch {
|
|
6135
|
+
deviceId = generateRandomDeviceId();
|
|
6136
|
+
}
|
|
6137
|
+
await persistDeviceId(deviceId);
|
|
6138
|
+
return deviceId;
|
|
6139
|
+
}
|
|
6140
|
+
async function persistDeviceId(deviceId) {
|
|
6141
|
+
const p = deviceIdPath();
|
|
6142
|
+
await mkdir8(join15(p, ".."), { recursive: true });
|
|
6143
|
+
await writeFile8(p, deviceId, { mode: 384 });
|
|
6144
|
+
}
|
|
6145
|
+
async function generateDeviceCodes() {
|
|
6099
6146
|
const deviceCode = `device-${generateCode()}-${Date.now()}`;
|
|
6100
6147
|
const userCode = `${generateCode()}-${generateCode()}`;
|
|
6101
6148
|
const authUrl = `${CLOUD_API_URL}/auth?code=${encodeURIComponent(userCode)}`;
|
|
6102
|
-
const deviceId =
|
|
6149
|
+
const deviceId = await getOrCreateDeviceId();
|
|
6103
6150
|
return { deviceCode, userCode, authUrl, deviceId };
|
|
6104
6151
|
}
|
|
6105
6152
|
async function registerDevice(codes) {
|
|
@@ -6154,6 +6201,10 @@ async function loadCloudCredentials() {
|
|
|
6154
6201
|
const raw = await readFile11(cloudCredPath(), "utf8");
|
|
6155
6202
|
const parsed = JSON.parse(raw);
|
|
6156
6203
|
if (parsed.expiresAt && parsed.expiresAt > Date.now() / 1e3 && parsed.accessToken) {
|
|
6204
|
+
if (parsed.deviceId) {
|
|
6205
|
+
await persistDeviceId(parsed.deviceId).catch(() => {
|
|
6206
|
+
});
|
|
6207
|
+
}
|
|
6157
6208
|
return parsed;
|
|
6158
6209
|
}
|
|
6159
6210
|
} catch {
|
|
@@ -6163,6 +6214,10 @@ async function loadCloudCredentials() {
|
|
|
6163
6214
|
async function saveCloudCredentials(creds) {
|
|
6164
6215
|
const p = cloudCredPath();
|
|
6165
6216
|
await writeFile8(p, JSON.stringify(creds, null, 2), "utf8");
|
|
6217
|
+
if (creds.deviceId) {
|
|
6218
|
+
await persistDeviceId(creds.deviceId).catch(() => {
|
|
6219
|
+
});
|
|
6220
|
+
}
|
|
6166
6221
|
}
|
|
6167
6222
|
async function clearCloudCredentials() {
|
|
6168
6223
|
try {
|
|
@@ -6170,9 +6225,14 @@ async function clearCloudCredentials() {
|
|
|
6170
6225
|
await unlink5(cloudCredPath());
|
|
6171
6226
|
} catch {
|
|
6172
6227
|
}
|
|
6228
|
+
try {
|
|
6229
|
+
const { unlink: unlink5 } = await import("fs/promises");
|
|
6230
|
+
await unlink5(deviceIdPath());
|
|
6231
|
+
} catch {
|
|
6232
|
+
}
|
|
6173
6233
|
}
|
|
6174
6234
|
async function authenticateDevice(onStatus) {
|
|
6175
|
-
const codes = generateDeviceCodes();
|
|
6235
|
+
const codes = await generateDeviceCodes();
|
|
6176
6236
|
await registerDevice(codes);
|
|
6177
6237
|
onStatus({ url: codes.authUrl, userCode: codes.userCode, polling: false });
|
|
6178
6238
|
const startTime = Date.now();
|
|
@@ -8306,7 +8366,7 @@ __export(sessions_exports, {
|
|
|
8306
8366
|
saveSession: () => saveSession,
|
|
8307
8367
|
sessionsDir: () => sessionsDir2
|
|
8308
8368
|
});
|
|
8309
|
-
import { readFile as readFile12, writeFile as writeFile9, mkdir as
|
|
8369
|
+
import { readFile as readFile12, writeFile as writeFile9, mkdir as mkdir9, readdir as readdir3, stat as stat4 } from "fs/promises";
|
|
8310
8370
|
import { homedir as homedir10 } from "os";
|
|
8311
8371
|
import { join as join17 } from "path";
|
|
8312
8372
|
function sessionsDir2() {
|
|
@@ -8330,7 +8390,7 @@ function makeSessionId(firstPrompt) {
|
|
|
8330
8390
|
}
|
|
8331
8391
|
async function saveSession(file) {
|
|
8332
8392
|
const dir = sessionsDir2();
|
|
8333
|
-
await
|
|
8393
|
+
await mkdir9(dir, { recursive: true });
|
|
8334
8394
|
const path = join17(dir, `${file.id}.json`);
|
|
8335
8395
|
await writeFile9(path, JSON.stringify(file, null, 2), "utf8");
|
|
8336
8396
|
return path;
|
|
@@ -8440,7 +8500,7 @@ var init_pricing = __esm({
|
|
|
8440
8500
|
});
|
|
8441
8501
|
|
|
8442
8502
|
// src/usage-tracker.ts
|
|
8443
|
-
import { readFile as readFile13, writeFile as writeFile10, mkdir as
|
|
8503
|
+
import { readFile as readFile13, writeFile as writeFile10, mkdir as mkdir10 } from "fs/promises";
|
|
8444
8504
|
import { homedir as homedir11 } from "os";
|
|
8445
8505
|
import { join as join18 } from "path";
|
|
8446
8506
|
function usageDir2() {
|
|
@@ -8470,7 +8530,7 @@ async function loadLog2() {
|
|
|
8470
8530
|
return { version: LOG_VERSION2, days: [], sessions: [] };
|
|
8471
8531
|
}
|
|
8472
8532
|
async function saveLog(log2) {
|
|
8473
|
-
await
|
|
8533
|
+
await mkdir10(usageDir2(), { recursive: true });
|
|
8474
8534
|
await writeFile10(usagePath2(), JSON.stringify(log2, null, 2), "utf8");
|
|
8475
8535
|
}
|
|
8476
8536
|
async function loadHistory() {
|
|
@@ -8499,7 +8559,7 @@ async function upsertHistoryDay(day) {
|
|
|
8499
8559
|
entries.push(day);
|
|
8500
8560
|
}
|
|
8501
8561
|
const lines = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
8502
|
-
await
|
|
8562
|
+
await mkdir10(usageDir2(), { recursive: true });
|
|
8503
8563
|
await writeFile10(historyPath(), lines, "utf8");
|
|
8504
8564
|
}
|
|
8505
8565
|
function getOrCreateDay(log2, date) {
|
|
@@ -8970,7 +9030,7 @@ var init_session = __esm({
|
|
|
8970
9030
|
if (err.name === "AbortError") {
|
|
8971
9031
|
this.emit({ type: "session.end", reason: "aborted" });
|
|
8972
9032
|
this.emit({ type: "status", status: "idle" });
|
|
8973
|
-
} else if (err instanceof BudgetExhaustedError) {
|
|
9033
|
+
} else if (err instanceof BudgetExhaustedError || err instanceof AgentLoopError) {
|
|
8974
9034
|
this.emit({ type: "session.end", reason: "error", error: err.message });
|
|
8975
9035
|
this.emit({ type: "status", status: "error" });
|
|
8976
9036
|
throw err;
|
|
@@ -9730,7 +9790,9 @@ import { createTwoFilesPatch } from "diff";
|
|
|
9730
9790
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
9731
9791
|
function DiffView({ path, before, after, maxLines = 40 }) {
|
|
9732
9792
|
const theme = useTheme();
|
|
9733
|
-
const
|
|
9793
|
+
const safeBefore = before ?? "";
|
|
9794
|
+
const safeAfter = after ?? "";
|
|
9795
|
+
const patch = createTwoFilesPatch(path, path, safeBefore, safeAfter, "", "", { context: 2 });
|
|
9734
9796
|
const raw = patch.split("\n").slice(4);
|
|
9735
9797
|
const lines = raw.filter((l) => {
|
|
9736
9798
|
if (l.startsWith("--- ") || l.startsWith("+++ ")) return false;
|
|
@@ -10745,7 +10807,11 @@ import SelectInput from "ink-select-input";
|
|
|
10745
10807
|
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
10746
10808
|
function PermissionModal({ tool, args, onDecide }) {
|
|
10747
10809
|
const theme = useTheme();
|
|
10748
|
-
|
|
10810
|
+
let render2;
|
|
10811
|
+
try {
|
|
10812
|
+
render2 = tool.render?.(args);
|
|
10813
|
+
} catch {
|
|
10814
|
+
}
|
|
10749
10815
|
const items = [
|
|
10750
10816
|
{ label: "Allow once", value: "allow" },
|
|
10751
10817
|
{ label: "Allow for this session", value: "allow_session" },
|
|
@@ -12018,7 +12084,7 @@ function Onboarding({ onDone, onCancel }) {
|
|
|
12018
12084
|
);
|
|
12019
12085
|
const startCloudAuth = useCallback(async () => {
|
|
12020
12086
|
try {
|
|
12021
|
-
const codes = generateDeviceCodes();
|
|
12087
|
+
const codes = await generateDeviceCodes();
|
|
12022
12088
|
await registerDevice(codes);
|
|
12023
12089
|
setCloudAuth({ phase: "ready", codes });
|
|
12024
12090
|
setStep("cloudAuth");
|
|
@@ -12883,7 +12949,7 @@ var init_skills = __esm({
|
|
|
12883
12949
|
});
|
|
12884
12950
|
|
|
12885
12951
|
// src/skills/manager.ts
|
|
12886
|
-
import { mkdir as
|
|
12952
|
+
import { mkdir as mkdir11, writeFile as writeFile11, unlink as unlink2, readFile as readFile15 } from "fs/promises";
|
|
12887
12953
|
import { join as join21 } from "path";
|
|
12888
12954
|
import matter2 from "gray-matter";
|
|
12889
12955
|
function getSkillDirs(cwd) {
|
|
@@ -12924,7 +12990,7 @@ ${yaml}
|
|
|
12924
12990
|
|
|
12925
12991
|
Add your instructions here.
|
|
12926
12992
|
`;
|
|
12927
|
-
await
|
|
12993
|
+
await mkdir11(dir, { recursive: true });
|
|
12928
12994
|
await writeFile11(filepath, content, "utf8");
|
|
12929
12995
|
return { filepath };
|
|
12930
12996
|
}
|
|
@@ -13006,7 +13072,7 @@ var init_image = __esm({
|
|
|
13006
13072
|
});
|
|
13007
13073
|
|
|
13008
13074
|
// src/util/state.ts
|
|
13009
|
-
import { readFile as readFile17, writeFile as writeFile12, mkdir as
|
|
13075
|
+
import { readFile as readFile17, writeFile as writeFile12, mkdir as mkdir12 } from "fs/promises";
|
|
13010
13076
|
import { homedir as homedir13 } from "os";
|
|
13011
13077
|
import { join as join22 } from "path";
|
|
13012
13078
|
function statePath() {
|
|
@@ -13023,7 +13089,7 @@ async function readState() {
|
|
|
13023
13089
|
}
|
|
13024
13090
|
async function writeState(state) {
|
|
13025
13091
|
const path = statePath();
|
|
13026
|
-
await
|
|
13092
|
+
await mkdir12(join22(path, ".."), { recursive: true });
|
|
13027
13093
|
await writeFile12(path, JSON.stringify(state, null, 2) + "\n", "utf8");
|
|
13028
13094
|
}
|
|
13029
13095
|
async function markCreatorMessageSeen(version) {
|
|
@@ -13481,7 +13547,7 @@ var init_builtins = __esm({
|
|
|
13481
13547
|
});
|
|
13482
13548
|
|
|
13483
13549
|
// src/commands/save.ts
|
|
13484
|
-
import { mkdir as
|
|
13550
|
+
import { mkdir as mkdir13, writeFile as writeFile13, unlink as unlink3 } from "fs/promises";
|
|
13485
13551
|
import { dirname as dirname10 } from "path";
|
|
13486
13552
|
async function saveCustomCommand(opts2) {
|
|
13487
13553
|
const dir = opts2.source === "project" ? projectCommandsDir(opts2.cwd) : globalCommandsDir();
|
|
@@ -13493,7 +13559,7 @@ async function saveCustomCommand(opts2) {
|
|
|
13493
13559
|
if (opts2.effort) data.effort = opts2.effort;
|
|
13494
13560
|
const frontmatter = serializeFrontmatter(data);
|
|
13495
13561
|
const content = frontmatter + opts2.template;
|
|
13496
|
-
await
|
|
13562
|
+
await mkdir13(dirname10(filepath), { recursive: true });
|
|
13497
13563
|
await writeFile13(filepath, content, "utf8");
|
|
13498
13564
|
return { filepath };
|
|
13499
13565
|
}
|
|
@@ -18035,6 +18101,11 @@ ${wcagWarnings.join("\n")}` }
|
|
|
18035
18101
|
...es,
|
|
18036
18102
|
{ kind: "cloud_quota_exhausted", key: mkKey(), used, limit, expiresAt }
|
|
18037
18103
|
]);
|
|
18104
|
+
} else if (e instanceof AgentLoopError) {
|
|
18105
|
+
setEvents((es) => [
|
|
18106
|
+
...es,
|
|
18107
|
+
{ kind: "error", key: mkKey(), text: "The agent got stuck repeating the same actions. Here's what we know so far." }
|
|
18108
|
+
]);
|
|
18038
18109
|
} else {
|
|
18039
18110
|
const displayText = e instanceof KimiApiError ? humanizeCloudflareError(e) : `init failed: ${e.message}`;
|
|
18040
18111
|
setEvents((es) => [
|
|
@@ -20425,6 +20496,11 @@ async function runPrintMode(opts2) {
|
|
|
20425
20496
|
process.exitCode = 42;
|
|
20426
20497
|
return;
|
|
20427
20498
|
}
|
|
20499
|
+
if (err instanceof AgentLoopError) {
|
|
20500
|
+
process.stderr.write("\n\x1B[33m[Agent loop detected \u2014 exiting with code 43]\x1B[0m\n");
|
|
20501
|
+
process.exitCode = 43;
|
|
20502
|
+
return;
|
|
20503
|
+
}
|
|
20428
20504
|
if (err instanceof KimiApiError) {
|
|
20429
20505
|
process.stderr.write(`
|
|
20430
20506
|
\x1B[31mError: ${humanizeCloudflareError(err)}\x1B[0m
|