kimiflare 0.83.0 → 0.84.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 +422 -360
- package/dist/index.js.map +1 -1
- package/dist/sdk/index.js +1 -1
- package/dist/sdk/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3727,7 +3727,7 @@ function raceWithSignal(promise, signal) {
|
|
|
3727
3727
|
async function runAgentTurn(opts2) {
|
|
3728
3728
|
const turnStart = performance.now();
|
|
3729
3729
|
logger.info("turn:start", { sessionId: opts2.sessionId, codeMode: opts2.codeMode ?? false });
|
|
3730
|
-
const max = opts2.maxToolIterations ??
|
|
3730
|
+
const max = opts2.maxToolIterations ?? 200;
|
|
3731
3731
|
const codeMode = opts2.codeMode ?? false;
|
|
3732
3732
|
const fireStopHook = async () => {
|
|
3733
3733
|
if (opts2.signal.aborted) return;
|
|
@@ -13999,6 +13999,301 @@ var init_deploy_commute = __esm({
|
|
|
13999
13999
|
}
|
|
14000
14000
|
});
|
|
14001
14001
|
|
|
14002
|
+
// src/util/image.ts
|
|
14003
|
+
import { readFile as readFile15 } from "fs/promises";
|
|
14004
|
+
import { basename as basename3 } from "path";
|
|
14005
|
+
async function encodeImageFile(filePath) {
|
|
14006
|
+
const buf = await readFile15(filePath);
|
|
14007
|
+
if (buf.byteLength > MAX_IMAGE_BYTES) {
|
|
14008
|
+
throw new Error(
|
|
14009
|
+
`image too large (${(buf.byteLength / 1024 / 1024).toFixed(1)} MB); max is ${MAX_IMAGE_BYTES / 1024 / 1024} MB`
|
|
14010
|
+
);
|
|
14011
|
+
}
|
|
14012
|
+
const ext = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
|
|
14013
|
+
const mime = EXT_TO_MIME[ext] ?? "image/jpeg";
|
|
14014
|
+
const b64 = buf.toString("base64");
|
|
14015
|
+
return {
|
|
14016
|
+
filename: basename3(filePath),
|
|
14017
|
+
mime,
|
|
14018
|
+
dataUrl: `data:${mime};base64,${b64}`
|
|
14019
|
+
};
|
|
14020
|
+
}
|
|
14021
|
+
function isImagePath(path) {
|
|
14022
|
+
const ext = path.slice(path.lastIndexOf(".")).toLowerCase();
|
|
14023
|
+
return ext in EXT_TO_MIME;
|
|
14024
|
+
}
|
|
14025
|
+
var MAX_IMAGE_BYTES, EXT_TO_MIME;
|
|
14026
|
+
var init_image = __esm({
|
|
14027
|
+
"src/util/image.ts"() {
|
|
14028
|
+
"use strict";
|
|
14029
|
+
MAX_IMAGE_BYTES = 5 * 1024 * 1024;
|
|
14030
|
+
EXT_TO_MIME = {
|
|
14031
|
+
".png": "image/png",
|
|
14032
|
+
".jpg": "image/jpeg",
|
|
14033
|
+
".jpeg": "image/jpeg",
|
|
14034
|
+
".gif": "image/gif",
|
|
14035
|
+
".webp": "image/webp",
|
|
14036
|
+
".bmp": "image/bmp"
|
|
14037
|
+
};
|
|
14038
|
+
}
|
|
14039
|
+
});
|
|
14040
|
+
|
|
14041
|
+
// src/ui/app-helpers.ts
|
|
14042
|
+
import { execSync as execSync3, spawn as spawn5 } from "child_process";
|
|
14043
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, statSync as statSync4 } from "fs";
|
|
14044
|
+
import { join as join24 } from "path";
|
|
14045
|
+
import { platform as platform3 } from "os";
|
|
14046
|
+
function buildFilePickerIgnoreList(cwd) {
|
|
14047
|
+
const hardcoded = [
|
|
14048
|
+
// Dependencies
|
|
14049
|
+
"**/node_modules/**",
|
|
14050
|
+
"**/vendor/**",
|
|
14051
|
+
"**/.bundle/**",
|
|
14052
|
+
"**/bower_components/**",
|
|
14053
|
+
// Version control
|
|
14054
|
+
"**/.git/**",
|
|
14055
|
+
"**/.svn/**",
|
|
14056
|
+
"**/.hg/**",
|
|
14057
|
+
// Build / output directories
|
|
14058
|
+
"**/dist/**",
|
|
14059
|
+
"**/build/**",
|
|
14060
|
+
"**/out/**",
|
|
14061
|
+
"**/public/**",
|
|
14062
|
+
"**/.next/**",
|
|
14063
|
+
"**/.nuxt/**",
|
|
14064
|
+
"**/.svelte-kit/**",
|
|
14065
|
+
"**/.vercel/**",
|
|
14066
|
+
"**/.netlify/**",
|
|
14067
|
+
"**/target/**",
|
|
14068
|
+
"**/bin/**",
|
|
14069
|
+
"**/obj/**",
|
|
14070
|
+
"**/Debug/**",
|
|
14071
|
+
"**/Release/**",
|
|
14072
|
+
"**/.gradle/**",
|
|
14073
|
+
// Caches
|
|
14074
|
+
"**/.cache/**",
|
|
14075
|
+
"**/.parcel-cache/**",
|
|
14076
|
+
"**/.turbo/**",
|
|
14077
|
+
"**/.eslintcache",
|
|
14078
|
+
"**/.stylelintcache",
|
|
14079
|
+
"**/.rpt2_cache/**",
|
|
14080
|
+
"**/.rts2_cache/**",
|
|
14081
|
+
// Temporary
|
|
14082
|
+
"**/tmp/**",
|
|
14083
|
+
"**/temp/**",
|
|
14084
|
+
"**/*.tmp",
|
|
14085
|
+
// Coverage
|
|
14086
|
+
"**/coverage/**",
|
|
14087
|
+
"**/.nyc_output/**",
|
|
14088
|
+
// OS files
|
|
14089
|
+
"**/.DS_Store",
|
|
14090
|
+
"**/Thumbs.db",
|
|
14091
|
+
// Logs
|
|
14092
|
+
"**/*.log",
|
|
14093
|
+
"**/logs/**",
|
|
14094
|
+
// Lock files (auto-generated, usually huge)
|
|
14095
|
+
"**/package-lock.json",
|
|
14096
|
+
"**/yarn.lock",
|
|
14097
|
+
"**/pnpm-lock.yaml",
|
|
14098
|
+
"**/bun.lockb",
|
|
14099
|
+
"**/Cargo.lock",
|
|
14100
|
+
"**/Gemfile.lock",
|
|
14101
|
+
"**/composer.lock",
|
|
14102
|
+
"**/Pipfile.lock",
|
|
14103
|
+
"**/poetry.lock",
|
|
14104
|
+
"**/go.sum",
|
|
14105
|
+
// Minified / source maps
|
|
14106
|
+
"**/*.min.js",
|
|
14107
|
+
"**/*.min.css",
|
|
14108
|
+
"**/*.map",
|
|
14109
|
+
// kimiflare internal
|
|
14110
|
+
"**/.kimiflare/**",
|
|
14111
|
+
// IDE (usually not relevant to mention)
|
|
14112
|
+
"**/.idea/**"
|
|
14113
|
+
];
|
|
14114
|
+
const gitignorePatterns = [];
|
|
14115
|
+
try {
|
|
14116
|
+
const gitignorePath = join24(cwd, ".gitignore");
|
|
14117
|
+
const stats = statSync4(gitignorePath);
|
|
14118
|
+
if (stats.size > MAX_GITIGNORE_SIZE) {
|
|
14119
|
+
return hardcoded;
|
|
14120
|
+
}
|
|
14121
|
+
const content = readFileSync4(gitignorePath, "utf-8");
|
|
14122
|
+
for (const line of content.split(/\r?\n/)) {
|
|
14123
|
+
const trimmed = line.trim();
|
|
14124
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
14125
|
+
if (trimmed.startsWith("!")) continue;
|
|
14126
|
+
let pattern = trimmed;
|
|
14127
|
+
const isAnchored = pattern.startsWith("/");
|
|
14128
|
+
const isDir = pattern.endsWith("/");
|
|
14129
|
+
if (isAnchored) pattern = pattern.slice(1);
|
|
14130
|
+
if (isDir) pattern = pattern.slice(0, -1);
|
|
14131
|
+
if (!pattern) continue;
|
|
14132
|
+
if (isAnchored) {
|
|
14133
|
+
gitignorePatterns.push(isDir ? pattern + "/**" : pattern);
|
|
14134
|
+
} else {
|
|
14135
|
+
gitignorePatterns.push(isDir ? "**/" + pattern + "/**" : "**/" + pattern);
|
|
14136
|
+
}
|
|
14137
|
+
}
|
|
14138
|
+
} catch {
|
|
14139
|
+
}
|
|
14140
|
+
return [...hardcoded, ...gitignorePatterns];
|
|
14141
|
+
}
|
|
14142
|
+
function gatewayFromConfig(cfg) {
|
|
14143
|
+
if (process.env.KIMIFLARE_DISABLE_AI_GATEWAY === "1") return void 0;
|
|
14144
|
+
if (!cfg.aiGatewayId) return void 0;
|
|
14145
|
+
return {
|
|
14146
|
+
id: cfg.aiGatewayId,
|
|
14147
|
+
cacheTtl: cfg.aiGatewayCacheTtl,
|
|
14148
|
+
skipCache: cfg.aiGatewaySkipCache,
|
|
14149
|
+
collectLogPayload: cfg.aiGatewayCollectLogPayload,
|
|
14150
|
+
metadata: cfg.aiGatewayMetadata
|
|
14151
|
+
};
|
|
14152
|
+
}
|
|
14153
|
+
function gatewayUsageLookupFromConfig(cfg, meta) {
|
|
14154
|
+
if (process.env.KIMIFLARE_DISABLE_AI_GATEWAY === "1") return void 0;
|
|
14155
|
+
if (!cfg.aiGatewayId || !meta) return void 0;
|
|
14156
|
+
return {
|
|
14157
|
+
accountId: cfg.accountId,
|
|
14158
|
+
apiToken: cfg.apiToken,
|
|
14159
|
+
gatewayId: cfg.aiGatewayId,
|
|
14160
|
+
meta
|
|
14161
|
+
};
|
|
14162
|
+
}
|
|
14163
|
+
function openBrowser(url) {
|
|
14164
|
+
const cmd = platform3() === "darwin" ? "open" : platform3() === "win32" ? "start" : "xdg-open";
|
|
14165
|
+
const child = spawn5(cmd, [url], { detached: true, stdio: "ignore" });
|
|
14166
|
+
child.unref();
|
|
14167
|
+
}
|
|
14168
|
+
function detectGitHubRepo(cachedRepo) {
|
|
14169
|
+
if (cachedRepo) {
|
|
14170
|
+
const parts = cachedRepo.split("/");
|
|
14171
|
+
if (parts.length === 2) return { owner: parts[0], name: parts[1] };
|
|
14172
|
+
}
|
|
14173
|
+
try {
|
|
14174
|
+
const remoteUrl = execSync3("git remote get-url origin", { cwd: process.cwd(), encoding: "utf8" }).trim();
|
|
14175
|
+
const httpsMatch = remoteUrl.match(/github\.com\/([^\/]+)\/([^\/]+?)(?:\.git)?$/);
|
|
14176
|
+
if (httpsMatch) return { owner: httpsMatch[1], name: httpsMatch[2] };
|
|
14177
|
+
const sshMatch = remoteUrl.match(/github\.com:([^\/]+)\/([^\/]+?)(?:\.git)?$/);
|
|
14178
|
+
if (sshMatch) return { owner: sshMatch[1], name: sshMatch[2] };
|
|
14179
|
+
} catch {
|
|
14180
|
+
}
|
|
14181
|
+
return null;
|
|
14182
|
+
}
|
|
14183
|
+
function detectGitBranch() {
|
|
14184
|
+
try {
|
|
14185
|
+
return execSync3("git branch --show-current", { cwd: process.cwd(), encoding: "utf8" }).trim() || null;
|
|
14186
|
+
} catch {
|
|
14187
|
+
return null;
|
|
14188
|
+
}
|
|
14189
|
+
}
|
|
14190
|
+
function formatTokens(n) {
|
|
14191
|
+
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
14192
|
+
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
|
|
14193
|
+
return String(n);
|
|
14194
|
+
}
|
|
14195
|
+
function trackRecentFile(ref, path, max = 10) {
|
|
14196
|
+
ref.current.set(path, Date.now());
|
|
14197
|
+
if (ref.current.size > max) {
|
|
14198
|
+
let oldest = null;
|
|
14199
|
+
let oldestTime = Infinity;
|
|
14200
|
+
for (const [p, t] of ref.current) {
|
|
14201
|
+
if (t < oldestTime) {
|
|
14202
|
+
oldestTime = t;
|
|
14203
|
+
oldest = p;
|
|
14204
|
+
}
|
|
14205
|
+
}
|
|
14206
|
+
if (oldest) ref.current.delete(oldest);
|
|
14207
|
+
}
|
|
14208
|
+
}
|
|
14209
|
+
function capEvents(prev) {
|
|
14210
|
+
if (prev.length <= MAX_EVENTS) return prev;
|
|
14211
|
+
return prev.slice(prev.length - MAX_EVENTS);
|
|
14212
|
+
}
|
|
14213
|
+
function compactEventsVisual(prev, keepLastTurns) {
|
|
14214
|
+
let seen = 0;
|
|
14215
|
+
let cutoff = -1;
|
|
14216
|
+
for (let i = prev.length - 1; i >= 0; i--) {
|
|
14217
|
+
if (prev[i].kind === "user") {
|
|
14218
|
+
seen++;
|
|
14219
|
+
if (seen === keepLastTurns + 1) {
|
|
14220
|
+
cutoff = i;
|
|
14221
|
+
break;
|
|
14222
|
+
}
|
|
14223
|
+
}
|
|
14224
|
+
}
|
|
14225
|
+
if (cutoff <= 0) return prev;
|
|
14226
|
+
const kept = prev.slice(cutoff);
|
|
14227
|
+
return [
|
|
14228
|
+
{ kind: "info", key: mkKey(), text: `\xB7\xB7\xB7 ${cutoff} earlier messages compacted \xB7\xB7\xB7` },
|
|
14229
|
+
...kept
|
|
14230
|
+
];
|
|
14231
|
+
}
|
|
14232
|
+
function makePrefixMessages(cacheStable, model, mode, tools) {
|
|
14233
|
+
if (cacheStable) {
|
|
14234
|
+
return buildSystemMessages({ cwd: process.cwd(), tools, model, mode });
|
|
14235
|
+
}
|
|
14236
|
+
return [
|
|
14237
|
+
{
|
|
14238
|
+
role: "system",
|
|
14239
|
+
content: buildSystemPrompt({ cwd: process.cwd(), tools, model, mode })
|
|
14240
|
+
}
|
|
14241
|
+
];
|
|
14242
|
+
}
|
|
14243
|
+
function rebuildSystemPromptForMode(messages, cacheStable, model, mode, tools) {
|
|
14244
|
+
if (cacheStable) {
|
|
14245
|
+
const rebuilt = buildSystemMessages({ cwd: process.cwd(), tools, model, mode });
|
|
14246
|
+
messages[0] = rebuilt[0];
|
|
14247
|
+
if (rebuilt[1]) {
|
|
14248
|
+
messages[1] = rebuilt[1];
|
|
14249
|
+
}
|
|
14250
|
+
} else {
|
|
14251
|
+
messages[0] = {
|
|
14252
|
+
role: "system",
|
|
14253
|
+
content: buildSystemPrompt({ cwd: process.cwd(), tools, model, mode })
|
|
14254
|
+
};
|
|
14255
|
+
}
|
|
14256
|
+
}
|
|
14257
|
+
function findImagePaths(text) {
|
|
14258
|
+
const paths = [];
|
|
14259
|
+
const quotedRegex = /"([^"]+)"|'([^']+)'/g;
|
|
14260
|
+
let match;
|
|
14261
|
+
while ((match = quotedRegex.exec(text)) !== null) {
|
|
14262
|
+
const path = match[1] ?? match[2];
|
|
14263
|
+
if (path && isImagePath(path) && existsSync4(path)) {
|
|
14264
|
+
paths.push(path);
|
|
14265
|
+
}
|
|
14266
|
+
}
|
|
14267
|
+
const remaining = text.replace(/"[^"]+"|'[^']+'/g, "");
|
|
14268
|
+
const ESCAPED_SPACE = "\0";
|
|
14269
|
+
const processed = remaining.replace(/\\ /g, ESCAPED_SPACE);
|
|
14270
|
+
for (const token of processed.split(/\s+/)) {
|
|
14271
|
+
const clean = token.replace(new RegExp(ESCAPED_SPACE, "g"), " ").replace(/^["']|["',;:!?]$/g, "").replace(/[.,;:!?]$/, "");
|
|
14272
|
+
if (clean && isImagePath(clean) && existsSync4(clean) && !paths.includes(clean)) {
|
|
14273
|
+
paths.push(clean);
|
|
14274
|
+
}
|
|
14275
|
+
}
|
|
14276
|
+
return paths;
|
|
14277
|
+
}
|
|
14278
|
+
var MAX_GITIGNORE_SIZE, CONTEXT_LIMIT, AUTO_COMPACT_THRESHOLD, MAX_EVENTS, MAX_IMAGES_PER_MESSAGE, FEEDBACK_WORKER_URL, nextKey, mkKey, nextAssistantId, mkAssistantId;
|
|
14279
|
+
var init_app_helpers = __esm({
|
|
14280
|
+
"src/ui/app-helpers.ts"() {
|
|
14281
|
+
"use strict";
|
|
14282
|
+
init_system_prompt();
|
|
14283
|
+
init_image();
|
|
14284
|
+
MAX_GITIGNORE_SIZE = 1 * 1024 * 1024;
|
|
14285
|
+
CONTEXT_LIMIT = 262e3;
|
|
14286
|
+
AUTO_COMPACT_THRESHOLD = 0.8;
|
|
14287
|
+
MAX_EVENTS = 500;
|
|
14288
|
+
MAX_IMAGES_PER_MESSAGE = 10;
|
|
14289
|
+
FEEDBACK_WORKER_URL = "https://hello.kimiflare.com";
|
|
14290
|
+
nextKey = 1;
|
|
14291
|
+
mkKey = () => `evt_${nextKey++}`;
|
|
14292
|
+
nextAssistantId = 1;
|
|
14293
|
+
mkAssistantId = () => nextAssistantId++;
|
|
14294
|
+
}
|
|
14295
|
+
});
|
|
14296
|
+
|
|
14002
14297
|
// src/commands/builtins.ts
|
|
14003
14298
|
var BUILTIN_COMMANDS, BUILTIN_COMMAND_NAMES;
|
|
14004
14299
|
var init_builtins = __esm({
|
|
@@ -15021,24 +15316,24 @@ var init_theme = __esm({
|
|
|
15021
15316
|
});
|
|
15022
15317
|
|
|
15023
15318
|
// src/util/clipboard.ts
|
|
15024
|
-
import { execSync as
|
|
15025
|
-
import { platform as
|
|
15319
|
+
import { execSync as execSync4 } from "child_process";
|
|
15320
|
+
import { platform as platform4 } from "os";
|
|
15026
15321
|
function writeToClipboard(text) {
|
|
15027
|
-
const os2 =
|
|
15322
|
+
const os2 = platform4();
|
|
15028
15323
|
try {
|
|
15029
15324
|
if (os2 === "darwin") {
|
|
15030
|
-
|
|
15325
|
+
execSync4("pbcopy", { input: text, timeout: 5e3 });
|
|
15031
15326
|
return { success: true, message: "Copied to clipboard" };
|
|
15032
15327
|
}
|
|
15033
15328
|
if (os2 === "win32") {
|
|
15034
|
-
|
|
15329
|
+
execSync4("clip", { input: text, timeout: 5e3 });
|
|
15035
15330
|
return { success: true, message: "Copied to clipboard" };
|
|
15036
15331
|
}
|
|
15037
15332
|
try {
|
|
15038
|
-
|
|
15333
|
+
execSync4("xclip -selection clipboard", { input: text, timeout: 5e3 });
|
|
15039
15334
|
return { success: true, message: "Copied to clipboard" };
|
|
15040
15335
|
} catch {
|
|
15041
|
-
|
|
15336
|
+
execSync4("xsel --clipboard --input", { input: text, timeout: 5e3 });
|
|
15042
15337
|
return { success: true, message: "Copied to clipboard" };
|
|
15043
15338
|
}
|
|
15044
15339
|
} catch {
|
|
@@ -15359,8 +15654,8 @@ var init_frontmatter = __esm({
|
|
|
15359
15654
|
});
|
|
15360
15655
|
|
|
15361
15656
|
// src/skills/loader.ts
|
|
15362
|
-
import { readFile as
|
|
15363
|
-
import { join as
|
|
15657
|
+
import { readFile as readFile16, readdir as readdir6, stat as stat6 } from "fs/promises";
|
|
15658
|
+
import { join as join25, extname } from "path";
|
|
15364
15659
|
function normalizeManifest(raw, filePath) {
|
|
15365
15660
|
const name = typeof raw.name === "string" ? raw.name : "";
|
|
15366
15661
|
const description = typeof raw.description === "string" ? raw.description : "";
|
|
@@ -15374,7 +15669,7 @@ function normalizeManifest(raw, filePath) {
|
|
|
15374
15669
|
return { name, description, match, scope, priority, enabled };
|
|
15375
15670
|
}
|
|
15376
15671
|
async function loadSkillFile(filePath) {
|
|
15377
|
-
const raw = await
|
|
15672
|
+
const raw = await readFile16(filePath, "utf-8");
|
|
15378
15673
|
const parsed = parseFrontmatter(raw);
|
|
15379
15674
|
const manifest = normalizeManifest(parsed.data, filePath);
|
|
15380
15675
|
const body = parsed.content.trim();
|
|
@@ -15396,7 +15691,7 @@ async function loadSkillsFromDir(dirPath) {
|
|
|
15396
15691
|
const entries = await readdir6(dirPath);
|
|
15397
15692
|
const files = [];
|
|
15398
15693
|
for (const entry of entries) {
|
|
15399
|
-
const full =
|
|
15694
|
+
const full = join25(dirPath, entry);
|
|
15400
15695
|
const s = await stat6(full);
|
|
15401
15696
|
if (s.isFile() && extname(entry) === ".md") {
|
|
15402
15697
|
files.push(full);
|
|
@@ -15424,12 +15719,12 @@ var init_loader = __esm({
|
|
|
15424
15719
|
});
|
|
15425
15720
|
|
|
15426
15721
|
// src/skills/manager.ts
|
|
15427
|
-
import { mkdir as mkdir10, writeFile as writeFile11, unlink as unlink2, readFile as
|
|
15428
|
-
import { join as
|
|
15722
|
+
import { mkdir as mkdir10, writeFile as writeFile11, unlink as unlink2, readFile as readFile17 } from "fs/promises";
|
|
15723
|
+
import { join as join26 } from "path";
|
|
15429
15724
|
function getSkillDirs(cwd) {
|
|
15430
15725
|
return {
|
|
15431
|
-
projectDir:
|
|
15432
|
-
globalDir:
|
|
15726
|
+
projectDir: join26(cwd, ".kimiflare", "skills"),
|
|
15727
|
+
globalDir: join26(process.env.HOME ?? "", ".config", "kimiflare", "skills")
|
|
15433
15728
|
};
|
|
15434
15729
|
}
|
|
15435
15730
|
async function listAllSkills(cwd) {
|
|
@@ -15443,7 +15738,7 @@ async function listAllSkills(cwd) {
|
|
|
15443
15738
|
async function createSkill(opts2) {
|
|
15444
15739
|
const dirs = getSkillDirs(opts2.cwd);
|
|
15445
15740
|
const dir = opts2.scope === "project" ? dirs.projectDir : dirs.globalDir;
|
|
15446
|
-
const filepath =
|
|
15741
|
+
const filepath = join26(dir, `${opts2.name}.md`);
|
|
15447
15742
|
const frontmatter = {
|
|
15448
15743
|
name: opts2.name,
|
|
15449
15744
|
enabled: true,
|
|
@@ -15479,7 +15774,7 @@ async function setSkillEnabled(name, enabled, cwd) {
|
|
|
15479
15774
|
const all = await listAllSkills(cwd);
|
|
15480
15775
|
const skill = all.project.find((s) => s.name === name) ?? all.global.find((s) => s.name === name);
|
|
15481
15776
|
if (!skill) throw new Error(`skill "${name}" not found`);
|
|
15482
|
-
const raw = await
|
|
15777
|
+
const raw = await readFile17(skill.filePath, "utf-8");
|
|
15483
15778
|
const parsed = parseFrontmatter(raw);
|
|
15484
15779
|
parsed.data.enabled = enabled;
|
|
15485
15780
|
const yaml = Object.entries(parsed.data).map(([k, v]) => {
|
|
@@ -15564,13 +15859,13 @@ var init_frontmatter2 = __esm({
|
|
|
15564
15859
|
// src/commands/loader.ts
|
|
15565
15860
|
import { open, realpath as realpath2 } from "fs/promises";
|
|
15566
15861
|
import { homedir as homedir14 } from "os";
|
|
15567
|
-
import { join as
|
|
15862
|
+
import { join as join27, relative as relative5, sep as sep2 } from "path";
|
|
15568
15863
|
function projectCommandsDir(cwd = process.cwd()) {
|
|
15569
|
-
return
|
|
15864
|
+
return join27(cwd, ".kimiflare", "commands");
|
|
15570
15865
|
}
|
|
15571
15866
|
function globalCommandsDir() {
|
|
15572
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
15573
|
-
return
|
|
15867
|
+
const xdg = process.env.XDG_CONFIG_HOME || join27(homedir14(), ".config");
|
|
15868
|
+
return join27(xdg, "kimiflare", "commands");
|
|
15574
15869
|
}
|
|
15575
15870
|
async function loadCustomCommands(cwd = process.cwd()) {
|
|
15576
15871
|
const warnings = [];
|
|
@@ -15844,13 +16139,13 @@ var init_worker_client = __esm({
|
|
|
15844
16139
|
});
|
|
15845
16140
|
|
|
15846
16141
|
// src/init/context-generator.ts
|
|
15847
|
-
import { existsSync as
|
|
15848
|
-
import { join as
|
|
16142
|
+
import { existsSync as existsSync5, statSync as statSync5 } from "fs";
|
|
16143
|
+
import { join as join28 } from "path";
|
|
15849
16144
|
function detectFlavor(cwd) {
|
|
15850
16145
|
for (const [flavor, signatures] of Object.entries(FLAVOR_SIGNATURES)) {
|
|
15851
16146
|
if (flavor === "generic") continue;
|
|
15852
16147
|
for (const sig of signatures) {
|
|
15853
|
-
const path =
|
|
16148
|
+
const path = join28(cwd, sig);
|
|
15854
16149
|
if (sig.includes("*")) {
|
|
15855
16150
|
try {
|
|
15856
16151
|
const parts = sig.split("*");
|
|
@@ -15862,7 +16157,7 @@ function detectFlavor(cwd) {
|
|
|
15862
16157
|
}
|
|
15863
16158
|
} catch {
|
|
15864
16159
|
}
|
|
15865
|
-
} else if (
|
|
16160
|
+
} else if (existsSync5(path)) {
|
|
15866
16161
|
return flavor;
|
|
15867
16162
|
}
|
|
15868
16163
|
}
|
|
@@ -15871,16 +16166,16 @@ function detectFlavor(cwd) {
|
|
|
15871
16166
|
}
|
|
15872
16167
|
function findFile(cwd, candidates) {
|
|
15873
16168
|
for (const c of candidates) {
|
|
15874
|
-
if (
|
|
16169
|
+
if (existsSync5(join28(cwd, c))) return c;
|
|
15875
16170
|
}
|
|
15876
16171
|
return null;
|
|
15877
16172
|
}
|
|
15878
16173
|
function findSourceRoots(cwd) {
|
|
15879
16174
|
const roots = [];
|
|
15880
16175
|
for (const r of SOURCE_ROOT_CANDIDATES) {
|
|
15881
|
-
const p =
|
|
16176
|
+
const p = join28(cwd, r);
|
|
15882
16177
|
try {
|
|
15883
|
-
const s =
|
|
16178
|
+
const s = statSync5(p);
|
|
15884
16179
|
if (s.isDirectory()) roots.push(r);
|
|
15885
16180
|
} catch {
|
|
15886
16181
|
}
|
|
@@ -15889,9 +16184,9 @@ function findSourceRoots(cwd) {
|
|
|
15889
16184
|
}
|
|
15890
16185
|
function findCiConfig(cwd) {
|
|
15891
16186
|
for (const c of CI_PATHS) {
|
|
15892
|
-
if (
|
|
16187
|
+
if (existsSync5(join28(cwd, c))) {
|
|
15893
16188
|
try {
|
|
15894
|
-
const s =
|
|
16189
|
+
const s = statSync5(join28(cwd, c));
|
|
15895
16190
|
return s.isDirectory() ? c : c;
|
|
15896
16191
|
} catch {
|
|
15897
16192
|
}
|
|
@@ -16028,7 +16323,7 @@ function analyzeProject(cwd) {
|
|
|
16028
16323
|
ciConfig: findCiConfig(cwd),
|
|
16029
16324
|
readme: findFile(cwd, ["README.md", "README.rst", "README.txt", "Readme.md"]),
|
|
16030
16325
|
sourceRoots: findSourceRoots(cwd),
|
|
16031
|
-
hasGit:
|
|
16326
|
+
hasGit: existsSync5(join28(cwd, ".git"))
|
|
16032
16327
|
};
|
|
16033
16328
|
}
|
|
16034
16329
|
function bashDiscoveryCommands(profile) {
|
|
@@ -16193,7 +16488,7 @@ Aim for 100\u2013200 lines total. Use markdown tables where they save space.
|
|
|
16193
16488
|
}
|
|
16194
16489
|
function buildInitPrompt(cwd) {
|
|
16195
16490
|
const existingName = ["KIMI.md", "KIMIFLARE.md", "AGENT.md"].find(
|
|
16196
|
-
(n) =>
|
|
16491
|
+
(n) => existsSync5(join28(cwd, n))
|
|
16197
16492
|
);
|
|
16198
16493
|
const isRefresh = existingName !== void 0;
|
|
16199
16494
|
const targetFilename = existingName ?? "KIMI.md";
|
|
@@ -16281,11 +16576,11 @@ __export(ui_mode_exports, {
|
|
|
16281
16576
|
runCamouflageOnboarding: () => runCamouflageOnboarding,
|
|
16282
16577
|
runUiMode: () => runUiMode
|
|
16283
16578
|
});
|
|
16284
|
-
import { execSync as
|
|
16579
|
+
import { execSync as execSync5, spawn as spawn6 } from "child_process";
|
|
16285
16580
|
import { appendFileSync, openSync } from "fs";
|
|
16286
16581
|
import { readdir as readdir7, unlink as unlink4 } from "fs/promises";
|
|
16287
|
-
import { join as
|
|
16288
|
-
import { platform as
|
|
16582
|
+
import { join as join29, relative as relative6 } from "path";
|
|
16583
|
+
import { platform as platform5 } from "os";
|
|
16289
16584
|
function kimiLog(payload) {
|
|
16290
16585
|
if (!KIMI_LOG_PATH) return;
|
|
16291
16586
|
try {
|
|
@@ -16360,6 +16655,7 @@ ${err instanceof Error ? err.message : err}`);
|
|
|
16360
16655
|
let currentThemeName = "everforest-dark";
|
|
16361
16656
|
const branch = tryGitBranch2();
|
|
16362
16657
|
let currentSessionFilePath = null;
|
|
16658
|
+
let sessionPlan = null;
|
|
16363
16659
|
const startupCfg = await loadConfig().catch(() => null);
|
|
16364
16660
|
let multiAgentEnabled = (startupCfg?.multiAgentEnabled ?? false) || /^(1|true|yes|on)$/i.test(process.env.KIMIFLARE_MULTI_AGENT_ENABLED ?? "");
|
|
16365
16661
|
const multiAgentSupervisor = new TurnSupervisor();
|
|
@@ -16915,7 +17211,7 @@ Executor opened PR: ${prUrl}` : plan });
|
|
|
16915
17211
|
onToolLimitReached: async () => {
|
|
16916
17212
|
const r = await confirm(cam, {
|
|
16917
17213
|
id: `lim-${Date.now()}`,
|
|
16918
|
-
prompt: "Tool-call limit reached (
|
|
17214
|
+
prompt: "Tool-call limit reached (200). Continue running?",
|
|
16919
17215
|
yes_label: "Continue",
|
|
16920
17216
|
no_label: "Stop turn",
|
|
16921
17217
|
default: "no",
|
|
@@ -17028,6 +17324,12 @@ Executor opened PR: ${prUrl}` : plan });
|
|
|
17028
17324
|
setPhase("idle");
|
|
17029
17325
|
cam.send("StatusUpdate", { segments: { elapsed: "" } });
|
|
17030
17326
|
kimiLog({ dir: "turn", phase: "end" });
|
|
17327
|
+
if (currentMode === "plan" && !currentController?.signal.aborted) {
|
|
17328
|
+
const plan = distillSessionPlan(messages);
|
|
17329
|
+
if (plan) {
|
|
17330
|
+
sessionPlan = plan;
|
|
17331
|
+
}
|
|
17332
|
+
}
|
|
17031
17333
|
if (planOptionsRef.current && !currentController?.signal.aborted) {
|
|
17032
17334
|
const options = planOptionsRef.current;
|
|
17033
17335
|
planOptionsRef.current = null;
|
|
@@ -17055,10 +17357,19 @@ Executor opened PR: ${prUrl}` : plan });
|
|
|
17055
17357
|
promptTokens = 0;
|
|
17056
17358
|
cachedTokens = 0;
|
|
17057
17359
|
completionTokens = 0;
|
|
17360
|
+
sessionPlan = null;
|
|
17058
17361
|
cam.send("TranscriptCleared", {});
|
|
17059
17362
|
cam.send("StatusUpdate", {
|
|
17060
17363
|
segments: { tokens: "in 0", cost: "$0.00", elapsed: "" }
|
|
17061
17364
|
});
|
|
17365
|
+
rebuildSystemPromptForMode(
|
|
17366
|
+
messages,
|
|
17367
|
+
false,
|
|
17368
|
+
// Camouflage UI always uses single system message
|
|
17369
|
+
opts2.model,
|
|
17370
|
+
currentMode,
|
|
17371
|
+
ALL_TOOLS
|
|
17372
|
+
);
|
|
17062
17373
|
messages.push({ role: "user", content: selected.plan });
|
|
17063
17374
|
cam.send("UserMessageCreated", { text: selected.plan });
|
|
17064
17375
|
cam.send("ShowToast", {
|
|
@@ -17121,7 +17432,7 @@ Executor opened PR: ${prUrl}` : plan });
|
|
|
17121
17432
|
allow_cancel: true
|
|
17122
17433
|
});
|
|
17123
17434
|
if (pick3.cancelled || !pick3.value) return;
|
|
17124
|
-
|
|
17435
|
+
openBrowser2(
|
|
17125
17436
|
`${URL2}/inbox?u=${encodeURIComponent(handle)}&s=${encodeURIComponent(secret)}&m=${encodeURIComponent(pick3.value)}`
|
|
17126
17437
|
);
|
|
17127
17438
|
cam.send("ShowToast", { text: "opened in browser", kind: "success", ttl_ms: 1500 });
|
|
@@ -17625,6 +17936,7 @@ Executor opened PR: ${prUrl}` : plan });
|
|
|
17625
17936
|
promptTokens = 0;
|
|
17626
17937
|
cachedTokens = 0;
|
|
17627
17938
|
completionTokens = 0;
|
|
17939
|
+
sessionPlan = null;
|
|
17628
17940
|
cam.send("TranscriptCleared", {});
|
|
17629
17941
|
cam.send("StatusUpdate", {
|
|
17630
17942
|
segments: { tokens: "in 0", cost: "$0.00", elapsed: "" }
|
|
@@ -18237,7 +18549,7 @@ Executor opened PR: ${prUrl}` : plan });
|
|
|
18237
18549
|
return true;
|
|
18238
18550
|
}
|
|
18239
18551
|
case "hello":
|
|
18240
|
-
|
|
18552
|
+
openBrowser2("https://hello.kimiflare.com");
|
|
18241
18553
|
cam.send("ShowToast", { text: "opened hello.kimiflare.com \u2014 leave the creator a voice note", kind: "info", ttl_ms: 3500 });
|
|
18242
18554
|
return true;
|
|
18243
18555
|
case "inbox":
|
|
@@ -18255,7 +18567,7 @@ Executor opened PR: ${prUrl}` : plan });
|
|
|
18255
18567
|
cam.send("ShowToast", { text: "can't /fresh while model is running \u2014 press Esc to interrupt first", kind: "warn", ttl_ms: 2500 });
|
|
18256
18568
|
return true;
|
|
18257
18569
|
}
|
|
18258
|
-
const plan = distillSessionPlan(messages);
|
|
18570
|
+
const plan = sessionPlan ?? distillSessionPlan(messages);
|
|
18259
18571
|
if (!plan) {
|
|
18260
18572
|
cam.send("ShowToast", { text: "No plan found to start fresh with.", kind: "error", ttl_ms: 2500 });
|
|
18261
18573
|
return true;
|
|
@@ -18268,10 +18580,19 @@ Executor opened PR: ${prUrl}` : plan });
|
|
|
18268
18580
|
promptTokens = 0;
|
|
18269
18581
|
cachedTokens = 0;
|
|
18270
18582
|
completionTokens = 0;
|
|
18583
|
+
sessionPlan = null;
|
|
18271
18584
|
cam.send("TranscriptCleared", {});
|
|
18272
18585
|
cam.send("StatusUpdate", {
|
|
18273
18586
|
segments: { tokens: "in 0", cost: "$0.00", elapsed: "" }
|
|
18274
18587
|
});
|
|
18588
|
+
rebuildSystemPromptForMode(
|
|
18589
|
+
messages,
|
|
18590
|
+
false,
|
|
18591
|
+
// Camouflage UI always uses single system message
|
|
18592
|
+
opts2.model,
|
|
18593
|
+
currentMode,
|
|
18594
|
+
ALL_TOOLS
|
|
18595
|
+
);
|
|
18275
18596
|
messages.push({ role: "user", content: plan });
|
|
18276
18597
|
cam.send("ShowToast", {
|
|
18277
18598
|
text: clipResult.success ? "Plan copied to clipboard. Starting fresh session with plan only\u2026" : "Clipboard unavailable. Starting fresh session with plan only\u2026",
|
|
@@ -18345,7 +18666,7 @@ async function registerMentions(cam, recents) {
|
|
|
18345
18666
|
for (const e of entries) {
|
|
18346
18667
|
if (collected.length >= 200) return;
|
|
18347
18668
|
if (e.name.startsWith(".") || SKIP.has(e.name)) continue;
|
|
18348
|
-
const full =
|
|
18669
|
+
const full = join29(dir, e.name);
|
|
18349
18670
|
if (e.isDirectory()) {
|
|
18350
18671
|
await walk2(full, depth + 1);
|
|
18351
18672
|
} else if (e.isFile()) {
|
|
@@ -18394,9 +18715,9 @@ function formatShortDate(iso) {
|
|
|
18394
18715
|
return iso;
|
|
18395
18716
|
}
|
|
18396
18717
|
}
|
|
18397
|
-
function
|
|
18398
|
-
const cmd =
|
|
18399
|
-
const child =
|
|
18718
|
+
function openBrowser2(url) {
|
|
18719
|
+
const cmd = platform5() === "darwin" ? "open" : platform5() === "win32" ? "start" : "xdg-open";
|
|
18720
|
+
const child = spawn6(cmd, [url], { detached: true, stdio: "ignore" });
|
|
18400
18721
|
child.unref();
|
|
18401
18722
|
}
|
|
18402
18723
|
function formatUsd(n) {
|
|
@@ -18415,7 +18736,7 @@ function formatElapsed2(secs) {
|
|
|
18415
18736
|
}
|
|
18416
18737
|
function tryGitBranch2() {
|
|
18417
18738
|
try {
|
|
18418
|
-
const out =
|
|
18739
|
+
const out = execSync5("git rev-parse --abbrev-ref HEAD 2>/dev/null", {
|
|
18419
18740
|
encoding: "utf8",
|
|
18420
18741
|
timeout: 200
|
|
18421
18742
|
}).trim();
|
|
@@ -18520,6 +18841,7 @@ var init_ui_mode = __esm({
|
|
|
18520
18841
|
init_classify();
|
|
18521
18842
|
init_deploy_commute();
|
|
18522
18843
|
init_system_prompt();
|
|
18844
|
+
init_app_helpers();
|
|
18523
18845
|
init_executor();
|
|
18524
18846
|
init_errors();
|
|
18525
18847
|
init_builtins();
|
|
@@ -21007,7 +21329,7 @@ var init_text_input = __esm({
|
|
|
21007
21329
|
// src/ui/permission.tsx
|
|
21008
21330
|
import { useState as useState4, useCallback } from "react";
|
|
21009
21331
|
import { Box as Box7, Text as Text8, useInput as useInput2 } from "ink";
|
|
21010
|
-
import { platform as
|
|
21332
|
+
import { platform as platform6 } from "os";
|
|
21011
21333
|
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
21012
21334
|
function formatSelection(label, shortcut) {
|
|
21013
21335
|
return `${label} [${MOD_KEY}+${shortcut}]`;
|
|
@@ -21171,7 +21493,7 @@ var init_permission = __esm({
|
|
|
21171
21493
|
{ value: { decision: "deny", scope: "once" }, label: "Something else", key: 3 }
|
|
21172
21494
|
];
|
|
21173
21495
|
DENY = { decision: "deny", scope: "once" };
|
|
21174
|
-
MOD_KEY =
|
|
21496
|
+
MOD_KEY = platform6() === "darwin" ? "\u2325" : "Alt";
|
|
21175
21497
|
}
|
|
21176
21498
|
});
|
|
21177
21499
|
|
|
@@ -21609,7 +21931,7 @@ function TaskList({ tasks, startedAt, tokensDelta }) {
|
|
|
21609
21931
|
const allDone = done === total;
|
|
21610
21932
|
const header = active ? active.title : allDone ? `${total} tasks done` : `${done}/${total}`;
|
|
21611
21933
|
const elapsed = startedAt ? formatElapsed5(now2 - startedAt) : null;
|
|
21612
|
-
const headerStats = [elapsed, tokensDelta > 0 ? `\u2191 ${
|
|
21934
|
+
const headerStats = [elapsed, tokensDelta > 0 ? `\u2191 ${formatTokens2(tokensDelta)} tokens` : null].filter(Boolean).join(" \xB7 ");
|
|
21613
21935
|
const visibleTasks = tasks.slice(0, MAX_VISIBLE);
|
|
21614
21936
|
const hiddenPending = Math.max(0, tasks.length - visibleTasks.length);
|
|
21615
21937
|
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", marginBottom: 1, children: [
|
|
@@ -21661,7 +21983,7 @@ function formatElapsed5(ms) {
|
|
|
21661
21983
|
if (m === 0) return `${s}s`;
|
|
21662
21984
|
return `${m}m ${s}s`;
|
|
21663
21985
|
}
|
|
21664
|
-
function
|
|
21986
|
+
function formatTokens2(n) {
|
|
21665
21987
|
if (n < 1e3) return String(n);
|
|
21666
21988
|
return `${(n / 1e3).toFixed(1)}k`;
|
|
21667
21989
|
}
|
|
@@ -23201,53 +23523,14 @@ function Welcome() {
|
|
|
23201
23523
|
});
|
|
23202
23524
|
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginBottom: 1, children: [
|
|
23203
23525
|
/* @__PURE__ */ jsx20(Box18, { marginBottom: 1, children: /* @__PURE__ */ jsx20(Text19, { bold: true, color: theme.accent, children: headline }) }),
|
|
23204
|
-
/* @__PURE__ */ jsx20(Box18, { flexDirection: "column", children: /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, dimColor: true, children: "Type / for commands" }) })
|
|
23205
|
-
] });
|
|
23206
|
-
}
|
|
23207
|
-
var init_welcome = __esm({
|
|
23208
|
-
"src/ui/welcome.tsx"() {
|
|
23209
|
-
"use strict";
|
|
23210
|
-
init_theme_context();
|
|
23211
|
-
init_greetings();
|
|
23212
|
-
}
|
|
23213
|
-
});
|
|
23214
|
-
|
|
23215
|
-
// src/util/image.ts
|
|
23216
|
-
import { readFile as readFile17 } from "fs/promises";
|
|
23217
|
-
import { basename as basename4 } from "path";
|
|
23218
|
-
async function encodeImageFile(filePath) {
|
|
23219
|
-
const buf = await readFile17(filePath);
|
|
23220
|
-
if (buf.byteLength > MAX_IMAGE_BYTES) {
|
|
23221
|
-
throw new Error(
|
|
23222
|
-
`image too large (${(buf.byteLength / 1024 / 1024).toFixed(1)} MB); max is ${MAX_IMAGE_BYTES / 1024 / 1024} MB`
|
|
23223
|
-
);
|
|
23224
|
-
}
|
|
23225
|
-
const ext = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
|
|
23226
|
-
const mime = EXT_TO_MIME[ext] ?? "image/jpeg";
|
|
23227
|
-
const b64 = buf.toString("base64");
|
|
23228
|
-
return {
|
|
23229
|
-
filename: basename4(filePath),
|
|
23230
|
-
mime,
|
|
23231
|
-
dataUrl: `data:${mime};base64,${b64}`
|
|
23232
|
-
};
|
|
23233
|
-
}
|
|
23234
|
-
function isImagePath(path) {
|
|
23235
|
-
const ext = path.slice(path.lastIndexOf(".")).toLowerCase();
|
|
23236
|
-
return ext in EXT_TO_MIME;
|
|
23526
|
+
/* @__PURE__ */ jsx20(Box18, { flexDirection: "column", children: /* @__PURE__ */ jsx20(Text19, { color: theme.info.color, dimColor: true, children: "Type / for commands" }) })
|
|
23527
|
+
] });
|
|
23237
23528
|
}
|
|
23238
|
-
var
|
|
23239
|
-
|
|
23240
|
-
"src/util/image.ts"() {
|
|
23529
|
+
var init_welcome = __esm({
|
|
23530
|
+
"src/ui/welcome.tsx"() {
|
|
23241
23531
|
"use strict";
|
|
23242
|
-
|
|
23243
|
-
|
|
23244
|
-
".png": "image/png",
|
|
23245
|
-
".jpg": "image/jpeg",
|
|
23246
|
-
".jpeg": "image/jpeg",
|
|
23247
|
-
".gif": "image/gif",
|
|
23248
|
-
".webp": "image/webp",
|
|
23249
|
-
".bmp": "image/bmp"
|
|
23250
|
-
};
|
|
23532
|
+
init_theme_context();
|
|
23533
|
+
init_greetings();
|
|
23251
23534
|
}
|
|
23252
23535
|
});
|
|
23253
23536
|
|
|
@@ -23484,10 +23767,10 @@ var init_wcag = __esm({
|
|
|
23484
23767
|
|
|
23485
23768
|
// src/ui/theme-loader.ts
|
|
23486
23769
|
import { readFile as readFile18, readdir as readdir8 } from "fs/promises";
|
|
23487
|
-
import { join as
|
|
23770
|
+
import { join as join30 } from "path";
|
|
23488
23771
|
import { homedir as homedir15 } from "os";
|
|
23489
23772
|
function projectThemesDir(cwd = process.cwd()) {
|
|
23490
|
-
return
|
|
23773
|
+
return join30(cwd, ".kimiflare", "themes");
|
|
23491
23774
|
}
|
|
23492
23775
|
function isHexColor(c) {
|
|
23493
23776
|
return /^#[0-9a-fA-F]{6}$/.test(c);
|
|
@@ -23576,7 +23859,7 @@ async function loadThemesFromDir(dir, source) {
|
|
|
23576
23859
|
return { themes, errors };
|
|
23577
23860
|
}
|
|
23578
23861
|
for (const file of files.filter((f) => f.endsWith(".json"))) {
|
|
23579
|
-
const path =
|
|
23862
|
+
const path = join30(dir, file);
|
|
23580
23863
|
let raw;
|
|
23581
23864
|
try {
|
|
23582
23865
|
raw = await readFile18(path, "utf-8");
|
|
@@ -23725,8 +24008,8 @@ var init_theme_loader = __esm({
|
|
|
23725
24008
|
"use strict";
|
|
23726
24009
|
init_wcag();
|
|
23727
24010
|
init_theme();
|
|
23728
|
-
USER_THEMES_DIR =
|
|
23729
|
-
process.env.XDG_CONFIG_HOME ||
|
|
24011
|
+
USER_THEMES_DIR = join30(
|
|
24012
|
+
process.env.XDG_CONFIG_HOME || join30(homedir15(), ".config"),
|
|
23730
24013
|
"kimiflare",
|
|
23731
24014
|
"themes"
|
|
23732
24015
|
);
|
|
@@ -24813,7 +25096,7 @@ var init_command_list = __esm({
|
|
|
24813
25096
|
import { useState as useState18 } from "react";
|
|
24814
25097
|
import { Box as Box25, Text as Text26 } from "ink";
|
|
24815
25098
|
import SelectInput10 from "ink-select-input";
|
|
24816
|
-
import { spawn as
|
|
25099
|
+
import { spawn as spawn7 } from "child_process";
|
|
24817
25100
|
import { jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
24818
25101
|
function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
24819
25102
|
const theme = useTheme();
|
|
@@ -24827,7 +25110,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
|
|
|
24827
25110
|
const runInstall = (command) => {
|
|
24828
25111
|
setInstallState({ status: "running", output: "Installing..." });
|
|
24829
25112
|
const { shell, args } = getShellCommand();
|
|
24830
|
-
const child =
|
|
25113
|
+
const child = spawn7(shell, [...args, command], {
|
|
24831
25114
|
env: process.env
|
|
24832
25115
|
});
|
|
24833
25116
|
let stdout = "";
|
|
@@ -25853,7 +26136,7 @@ function formatSessionLine(s) {
|
|
|
25853
26136
|
const ago = formatAgo(new Date(s.updatedAt));
|
|
25854
26137
|
const prompt = s.prompt.slice(0, 30) + (s.prompt.length > 30 ? "\u2026" : "");
|
|
25855
26138
|
const outcome = s.prUrl ? `PR ${s.prUrl.split("/").pop()}` : s.status;
|
|
25856
|
-
const cost = s.tokensUsed && s.tokensBudget ? ` (${
|
|
26139
|
+
const cost = s.tokensUsed && s.tokensBudget ? ` (${formatTokens3(s.tokensUsed)}/${formatTokens3(s.tokensBudget)})` : s.tokensUsed ? ` (${formatTokens3(s.tokensUsed)})` : "";
|
|
25857
26140
|
return `${icon} ${prompt} \u2192 ${outcome} ${ago}${cost}`;
|
|
25858
26141
|
}
|
|
25859
26142
|
function formatAgo(date) {
|
|
@@ -25866,7 +26149,7 @@ function formatAgo(date) {
|
|
|
25866
26149
|
if (minutes > 0) return `${minutes}m ago`;
|
|
25867
26150
|
return "just now";
|
|
25868
26151
|
}
|
|
25869
|
-
function
|
|
26152
|
+
function formatTokens3(n) {
|
|
25870
26153
|
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
25871
26154
|
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
|
|
25872
26155
|
return String(n);
|
|
@@ -25927,8 +26210,8 @@ function RemoteSessionDetail({
|
|
|
25927
26210
|
] }),
|
|
25928
26211
|
session.tokensUsed !== void 0 && /* @__PURE__ */ jsxs33(Text34, { children: [
|
|
25929
26212
|
"Tokens: ",
|
|
25930
|
-
|
|
25931
|
-
session.tokensBudget ? ` / ${
|
|
26213
|
+
formatTokens3(session.tokensUsed),
|
|
26214
|
+
session.tokensBudget ? ` / ${formatTokens3(session.tokensBudget)}` : ""
|
|
25932
26215
|
] }),
|
|
25933
26216
|
/* @__PURE__ */ jsxs33(Text34, { children: [
|
|
25934
26217
|
"Created: ",
|
|
@@ -25972,7 +26255,7 @@ function InboxModal({ onDone, onOpen }) {
|
|
|
25972
26255
|
setError(null);
|
|
25973
26256
|
try {
|
|
25974
26257
|
const res = await fetch(
|
|
25975
|
-
`${
|
|
26258
|
+
`${FEEDBACK_WORKER_URL2}/inbox/check?u=${encodeURIComponent(u)}&s=${encodeURIComponent(s)}`
|
|
25976
26259
|
);
|
|
25977
26260
|
if (!res.ok) {
|
|
25978
26261
|
throw new Error(`Server returned ${res.status}`);
|
|
@@ -26018,7 +26301,7 @@ function InboxModal({ onDone, onOpen }) {
|
|
|
26018
26301
|
if (messages.length === 0) return;
|
|
26019
26302
|
const msg = messages[selectedIndex];
|
|
26020
26303
|
if (!msg) return;
|
|
26021
|
-
const url = `${
|
|
26304
|
+
const url = `${FEEDBACK_WORKER_URL2}/inbox?u=${encodeURIComponent(twitter)}&s=${encodeURIComponent(secret)}&m=${encodeURIComponent(msg.id)}`;
|
|
26022
26305
|
onOpen(url);
|
|
26023
26306
|
onDone();
|
|
26024
26307
|
}, [messages, selectedIndex, twitter, secret, onOpen, onDone]);
|
|
@@ -26117,255 +26400,13 @@ function InboxModal({ onDone, onOpen }) {
|
|
|
26117
26400
|
] })
|
|
26118
26401
|
] });
|
|
26119
26402
|
}
|
|
26120
|
-
var
|
|
26403
|
+
var FEEDBACK_WORKER_URL2;
|
|
26121
26404
|
var init_inbox_modal = __esm({
|
|
26122
26405
|
"src/ui/inbox-modal.tsx"() {
|
|
26123
26406
|
"use strict";
|
|
26124
26407
|
init_text_input();
|
|
26125
26408
|
init_theme_context();
|
|
26126
|
-
FEEDBACK_WORKER_URL = "https://hello.kimiflare.com";
|
|
26127
|
-
}
|
|
26128
|
-
});
|
|
26129
|
-
|
|
26130
|
-
// src/ui/app-helpers.ts
|
|
26131
|
-
import { execSync as execSync5, spawn as spawn7 } from "child_process";
|
|
26132
|
-
import { existsSync as existsSync5, readFileSync as readFileSync4, statSync as statSync5 } from "fs";
|
|
26133
|
-
import { join as join30 } from "path";
|
|
26134
|
-
import { platform as platform6 } from "os";
|
|
26135
|
-
function buildFilePickerIgnoreList(cwd) {
|
|
26136
|
-
const hardcoded = [
|
|
26137
|
-
// Dependencies
|
|
26138
|
-
"**/node_modules/**",
|
|
26139
|
-
"**/vendor/**",
|
|
26140
|
-
"**/.bundle/**",
|
|
26141
|
-
"**/bower_components/**",
|
|
26142
|
-
// Version control
|
|
26143
|
-
"**/.git/**",
|
|
26144
|
-
"**/.svn/**",
|
|
26145
|
-
"**/.hg/**",
|
|
26146
|
-
// Build / output directories
|
|
26147
|
-
"**/dist/**",
|
|
26148
|
-
"**/build/**",
|
|
26149
|
-
"**/out/**",
|
|
26150
|
-
"**/public/**",
|
|
26151
|
-
"**/.next/**",
|
|
26152
|
-
"**/.nuxt/**",
|
|
26153
|
-
"**/.svelte-kit/**",
|
|
26154
|
-
"**/.vercel/**",
|
|
26155
|
-
"**/.netlify/**",
|
|
26156
|
-
"**/target/**",
|
|
26157
|
-
"**/bin/**",
|
|
26158
|
-
"**/obj/**",
|
|
26159
|
-
"**/Debug/**",
|
|
26160
|
-
"**/Release/**",
|
|
26161
|
-
"**/.gradle/**",
|
|
26162
|
-
// Caches
|
|
26163
|
-
"**/.cache/**",
|
|
26164
|
-
"**/.parcel-cache/**",
|
|
26165
|
-
"**/.turbo/**",
|
|
26166
|
-
"**/.eslintcache",
|
|
26167
|
-
"**/.stylelintcache",
|
|
26168
|
-
"**/.rpt2_cache/**",
|
|
26169
|
-
"**/.rts2_cache/**",
|
|
26170
|
-
// Temporary
|
|
26171
|
-
"**/tmp/**",
|
|
26172
|
-
"**/temp/**",
|
|
26173
|
-
"**/*.tmp",
|
|
26174
|
-
// Coverage
|
|
26175
|
-
"**/coverage/**",
|
|
26176
|
-
"**/.nyc_output/**",
|
|
26177
|
-
// OS files
|
|
26178
|
-
"**/.DS_Store",
|
|
26179
|
-
"**/Thumbs.db",
|
|
26180
|
-
// Logs
|
|
26181
|
-
"**/*.log",
|
|
26182
|
-
"**/logs/**",
|
|
26183
|
-
// Lock files (auto-generated, usually huge)
|
|
26184
|
-
"**/package-lock.json",
|
|
26185
|
-
"**/yarn.lock",
|
|
26186
|
-
"**/pnpm-lock.yaml",
|
|
26187
|
-
"**/bun.lockb",
|
|
26188
|
-
"**/Cargo.lock",
|
|
26189
|
-
"**/Gemfile.lock",
|
|
26190
|
-
"**/composer.lock",
|
|
26191
|
-
"**/Pipfile.lock",
|
|
26192
|
-
"**/poetry.lock",
|
|
26193
|
-
"**/go.sum",
|
|
26194
|
-
// Minified / source maps
|
|
26195
|
-
"**/*.min.js",
|
|
26196
|
-
"**/*.min.css",
|
|
26197
|
-
"**/*.map",
|
|
26198
|
-
// kimiflare internal
|
|
26199
|
-
"**/.kimiflare/**",
|
|
26200
|
-
// IDE (usually not relevant to mention)
|
|
26201
|
-
"**/.idea/**"
|
|
26202
|
-
];
|
|
26203
|
-
const gitignorePatterns = [];
|
|
26204
|
-
try {
|
|
26205
|
-
const gitignorePath = join30(cwd, ".gitignore");
|
|
26206
|
-
const stats = statSync5(gitignorePath);
|
|
26207
|
-
if (stats.size > MAX_GITIGNORE_SIZE) {
|
|
26208
|
-
return hardcoded;
|
|
26209
|
-
}
|
|
26210
|
-
const content = readFileSync4(gitignorePath, "utf-8");
|
|
26211
|
-
for (const line of content.split(/\r?\n/)) {
|
|
26212
|
-
const trimmed = line.trim();
|
|
26213
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
26214
|
-
if (trimmed.startsWith("!")) continue;
|
|
26215
|
-
let pattern = trimmed;
|
|
26216
|
-
const isAnchored = pattern.startsWith("/");
|
|
26217
|
-
const isDir = pattern.endsWith("/");
|
|
26218
|
-
if (isAnchored) pattern = pattern.slice(1);
|
|
26219
|
-
if (isDir) pattern = pattern.slice(0, -1);
|
|
26220
|
-
if (!pattern) continue;
|
|
26221
|
-
if (isAnchored) {
|
|
26222
|
-
gitignorePatterns.push(isDir ? pattern + "/**" : pattern);
|
|
26223
|
-
} else {
|
|
26224
|
-
gitignorePatterns.push(isDir ? "**/" + pattern + "/**" : "**/" + pattern);
|
|
26225
|
-
}
|
|
26226
|
-
}
|
|
26227
|
-
} catch {
|
|
26228
|
-
}
|
|
26229
|
-
return [...hardcoded, ...gitignorePatterns];
|
|
26230
|
-
}
|
|
26231
|
-
function gatewayFromConfig(cfg) {
|
|
26232
|
-
if (process.env.KIMIFLARE_DISABLE_AI_GATEWAY === "1") return void 0;
|
|
26233
|
-
if (!cfg.aiGatewayId) return void 0;
|
|
26234
|
-
return {
|
|
26235
|
-
id: cfg.aiGatewayId,
|
|
26236
|
-
cacheTtl: cfg.aiGatewayCacheTtl,
|
|
26237
|
-
skipCache: cfg.aiGatewaySkipCache,
|
|
26238
|
-
collectLogPayload: cfg.aiGatewayCollectLogPayload,
|
|
26239
|
-
metadata: cfg.aiGatewayMetadata
|
|
26240
|
-
};
|
|
26241
|
-
}
|
|
26242
|
-
function gatewayUsageLookupFromConfig(cfg, meta) {
|
|
26243
|
-
if (process.env.KIMIFLARE_DISABLE_AI_GATEWAY === "1") return void 0;
|
|
26244
|
-
if (!cfg.aiGatewayId || !meta) return void 0;
|
|
26245
|
-
return {
|
|
26246
|
-
accountId: cfg.accountId,
|
|
26247
|
-
apiToken: cfg.apiToken,
|
|
26248
|
-
gatewayId: cfg.aiGatewayId,
|
|
26249
|
-
meta
|
|
26250
|
-
};
|
|
26251
|
-
}
|
|
26252
|
-
function openBrowser2(url) {
|
|
26253
|
-
const cmd = platform6() === "darwin" ? "open" : platform6() === "win32" ? "start" : "xdg-open";
|
|
26254
|
-
const child = spawn7(cmd, [url], { detached: true, stdio: "ignore" });
|
|
26255
|
-
child.unref();
|
|
26256
|
-
}
|
|
26257
|
-
function detectGitHubRepo(cachedRepo) {
|
|
26258
|
-
if (cachedRepo) {
|
|
26259
|
-
const parts = cachedRepo.split("/");
|
|
26260
|
-
if (parts.length === 2) return { owner: parts[0], name: parts[1] };
|
|
26261
|
-
}
|
|
26262
|
-
try {
|
|
26263
|
-
const remoteUrl = execSync5("git remote get-url origin", { cwd: process.cwd(), encoding: "utf8" }).trim();
|
|
26264
|
-
const httpsMatch = remoteUrl.match(/github\.com\/([^\/]+)\/([^\/]+?)(?:\.git)?$/);
|
|
26265
|
-
if (httpsMatch) return { owner: httpsMatch[1], name: httpsMatch[2] };
|
|
26266
|
-
const sshMatch = remoteUrl.match(/github\.com:([^\/]+)\/([^\/]+?)(?:\.git)?$/);
|
|
26267
|
-
if (sshMatch) return { owner: sshMatch[1], name: sshMatch[2] };
|
|
26268
|
-
} catch {
|
|
26269
|
-
}
|
|
26270
|
-
return null;
|
|
26271
|
-
}
|
|
26272
|
-
function detectGitBranch() {
|
|
26273
|
-
try {
|
|
26274
|
-
return execSync5("git branch --show-current", { cwd: process.cwd(), encoding: "utf8" }).trim() || null;
|
|
26275
|
-
} catch {
|
|
26276
|
-
return null;
|
|
26277
|
-
}
|
|
26278
|
-
}
|
|
26279
|
-
function formatTokens3(n) {
|
|
26280
|
-
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
26281
|
-
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
|
|
26282
|
-
return String(n);
|
|
26283
|
-
}
|
|
26284
|
-
function trackRecentFile(ref, path, max = 10) {
|
|
26285
|
-
ref.current.set(path, Date.now());
|
|
26286
|
-
if (ref.current.size > max) {
|
|
26287
|
-
let oldest = null;
|
|
26288
|
-
let oldestTime = Infinity;
|
|
26289
|
-
for (const [p, t] of ref.current) {
|
|
26290
|
-
if (t < oldestTime) {
|
|
26291
|
-
oldestTime = t;
|
|
26292
|
-
oldest = p;
|
|
26293
|
-
}
|
|
26294
|
-
}
|
|
26295
|
-
if (oldest) ref.current.delete(oldest);
|
|
26296
|
-
}
|
|
26297
|
-
}
|
|
26298
|
-
function capEvents(prev) {
|
|
26299
|
-
if (prev.length <= MAX_EVENTS) return prev;
|
|
26300
|
-
return prev.slice(prev.length - MAX_EVENTS);
|
|
26301
|
-
}
|
|
26302
|
-
function compactEventsVisual(prev, keepLastTurns) {
|
|
26303
|
-
let seen = 0;
|
|
26304
|
-
let cutoff = -1;
|
|
26305
|
-
for (let i = prev.length - 1; i >= 0; i--) {
|
|
26306
|
-
if (prev[i].kind === "user") {
|
|
26307
|
-
seen++;
|
|
26308
|
-
if (seen === keepLastTurns + 1) {
|
|
26309
|
-
cutoff = i;
|
|
26310
|
-
break;
|
|
26311
|
-
}
|
|
26312
|
-
}
|
|
26313
|
-
}
|
|
26314
|
-
if (cutoff <= 0) return prev;
|
|
26315
|
-
const kept = prev.slice(cutoff);
|
|
26316
|
-
return [
|
|
26317
|
-
{ kind: "info", key: mkKey(), text: `\xB7\xB7\xB7 ${cutoff} earlier messages compacted \xB7\xB7\xB7` },
|
|
26318
|
-
...kept
|
|
26319
|
-
];
|
|
26320
|
-
}
|
|
26321
|
-
function makePrefixMessages(cacheStable, model, mode, tools) {
|
|
26322
|
-
if (cacheStable) {
|
|
26323
|
-
return buildSystemMessages({ cwd: process.cwd(), tools, model, mode });
|
|
26324
|
-
}
|
|
26325
|
-
return [
|
|
26326
|
-
{
|
|
26327
|
-
role: "system",
|
|
26328
|
-
content: buildSystemPrompt({ cwd: process.cwd(), tools, model, mode })
|
|
26329
|
-
}
|
|
26330
|
-
];
|
|
26331
|
-
}
|
|
26332
|
-
function findImagePaths(text) {
|
|
26333
|
-
const paths = [];
|
|
26334
|
-
const quotedRegex = /"([^"]+)"|'([^']+)'/g;
|
|
26335
|
-
let match;
|
|
26336
|
-
while ((match = quotedRegex.exec(text)) !== null) {
|
|
26337
|
-
const path = match[1] ?? match[2];
|
|
26338
|
-
if (path && isImagePath(path) && existsSync5(path)) {
|
|
26339
|
-
paths.push(path);
|
|
26340
|
-
}
|
|
26341
|
-
}
|
|
26342
|
-
const remaining = text.replace(/"[^"]+"|'[^']+'/g, "");
|
|
26343
|
-
const ESCAPED_SPACE = "\0";
|
|
26344
|
-
const processed = remaining.replace(/\\ /g, ESCAPED_SPACE);
|
|
26345
|
-
for (const token of processed.split(/\s+/)) {
|
|
26346
|
-
const clean = token.replace(new RegExp(ESCAPED_SPACE, "g"), " ").replace(/^["']|["',;:!?]$/g, "").replace(/[.,;:!?]$/, "");
|
|
26347
|
-
if (clean && isImagePath(clean) && existsSync5(clean) && !paths.includes(clean)) {
|
|
26348
|
-
paths.push(clean);
|
|
26349
|
-
}
|
|
26350
|
-
}
|
|
26351
|
-
return paths;
|
|
26352
|
-
}
|
|
26353
|
-
var MAX_GITIGNORE_SIZE, CONTEXT_LIMIT, AUTO_COMPACT_THRESHOLD, MAX_EVENTS, MAX_IMAGES_PER_MESSAGE, FEEDBACK_WORKER_URL2, nextKey, mkKey, nextAssistantId, mkAssistantId;
|
|
26354
|
-
var init_app_helpers = __esm({
|
|
26355
|
-
"src/ui/app-helpers.ts"() {
|
|
26356
|
-
"use strict";
|
|
26357
|
-
init_system_prompt();
|
|
26358
|
-
init_image();
|
|
26359
|
-
MAX_GITIGNORE_SIZE = 1 * 1024 * 1024;
|
|
26360
|
-
CONTEXT_LIMIT = 262e3;
|
|
26361
|
-
AUTO_COMPACT_THRESHOLD = 0.8;
|
|
26362
|
-
MAX_EVENTS = 500;
|
|
26363
|
-
MAX_IMAGES_PER_MESSAGE = 10;
|
|
26364
26409
|
FEEDBACK_WORKER_URL2 = "https://hello.kimiflare.com";
|
|
26365
|
-
nextKey = 1;
|
|
26366
|
-
mkKey = () => `evt_${nextKey++}`;
|
|
26367
|
-
nextAssistantId = 1;
|
|
26368
|
-
mkAssistantId = () => nextAssistantId++;
|
|
26369
26410
|
}
|
|
26370
26411
|
});
|
|
26371
26412
|
|
|
@@ -26546,7 +26587,7 @@ function MultiAgentModal({ initial, onSave, onDone, remoteWorkerUrl, remoteAuthS
|
|
|
26546
26587
|
if (deployFailed) {
|
|
26547
26588
|
if (input === "o" || input === "O") {
|
|
26548
26589
|
const url = deployLog.map((l) => l.match(/https:\/\/dash\.cloudflare\.com\/[^\s)]+/)?.[0]).find((u) => !!u) ?? "https://dash.cloudflare.com/profile/api-tokens";
|
|
26549
|
-
|
|
26590
|
+
openBrowser(url);
|
|
26550
26591
|
return;
|
|
26551
26592
|
}
|
|
26552
26593
|
if (input === "r" || input === "R") {
|
|
@@ -28454,6 +28495,14 @@ function executeFreshStart(ctx, planText) {
|
|
|
28454
28495
|
ctx.clearTaskTracking();
|
|
28455
28496
|
ctx.compactSuggestedRef.current = false;
|
|
28456
28497
|
ctx.updateNudgedRef.current = false;
|
|
28498
|
+
ctx.sessionPlanRef.current = null;
|
|
28499
|
+
rebuildSystemPromptForMode(
|
|
28500
|
+
ctx.messagesRef.current,
|
|
28501
|
+
ctx.cacheStableRef.current,
|
|
28502
|
+
ctx.cfg?.model ?? "@cf/moonshotai/kimi-k2.6",
|
|
28503
|
+
ctx.mode,
|
|
28504
|
+
[...ALL_TOOLS, ...ctx.mcpToolsRef.current, ...ctx.lspToolsRef.current]
|
|
28505
|
+
);
|
|
28457
28506
|
ctx.messagesRef.current.push({ role: "user", content: planText });
|
|
28458
28507
|
const newSessionId = ctx.ensureSessionId();
|
|
28459
28508
|
if (oldSessionId) {
|
|
@@ -28486,6 +28535,7 @@ var init_slash_commands = __esm({
|
|
|
28486
28535
|
init_manager4();
|
|
28487
28536
|
init_sessions();
|
|
28488
28537
|
init_session_state();
|
|
28538
|
+
init_executor();
|
|
28489
28539
|
init_recommended();
|
|
28490
28540
|
init_settings();
|
|
28491
28541
|
init_types2();
|
|
@@ -28535,6 +28585,7 @@ var init_slash_commands = __esm({
|
|
|
28535
28585
|
ctx.clearTaskTracking();
|
|
28536
28586
|
ctx.compactSuggestedRef.current = false;
|
|
28537
28587
|
ctx.updateNudgedRef.current = false;
|
|
28588
|
+
ctx.sessionPlanRef.current = null;
|
|
28538
28589
|
return true;
|
|
28539
28590
|
};
|
|
28540
28591
|
handleFresh = (ctx) => {
|
|
@@ -28546,7 +28597,7 @@ var init_slash_commands = __esm({
|
|
|
28546
28597
|
]);
|
|
28547
28598
|
return true;
|
|
28548
28599
|
}
|
|
28549
|
-
const plan = distillSessionPlan(ctx.messagesRef.current);
|
|
28600
|
+
const plan = ctx.sessionPlanRef.current ?? distillSessionPlan(ctx.messagesRef.current);
|
|
28550
28601
|
if (!plan) {
|
|
28551
28602
|
setEvents((e) => [
|
|
28552
28603
|
...e,
|
|
@@ -29543,8 +29594,8 @@ project: ${projectSettingsPath(cwd)}`
|
|
|
29543
29594
|
handleHello = (ctx) => {
|
|
29544
29595
|
const { setEvents, mkKey: mkKey2 } = ctx;
|
|
29545
29596
|
const session = crypto.randomUUID();
|
|
29546
|
-
const url = `${
|
|
29547
|
-
|
|
29597
|
+
const url = `${FEEDBACK_WORKER_URL}/?s=${session}&v=${getAppVersion()}`;
|
|
29598
|
+
openBrowser(url);
|
|
29548
29599
|
void (async () => {
|
|
29549
29600
|
try {
|
|
29550
29601
|
const qr = await QRCode.toString(url, { type: "terminal", small: true });
|
|
@@ -29697,7 +29748,7 @@ project: ${projectSettingsPath(cwd)}`
|
|
|
29697
29748
|
setEvents((e) => [
|
|
29698
29749
|
...e,
|
|
29699
29750
|
{ kind: "info", key: mkKey2(), text: `Starting remote session for ${repo.owner}/${repo.name}...` },
|
|
29700
|
-
{ kind: "info", key: mkKey2(), text: `Budget: ${
|
|
29751
|
+
{ kind: "info", key: mkKey2(), text: `Budget: ${formatTokens(budget)} tokens. TTL: ${ttl} min.` }
|
|
29701
29752
|
]);
|
|
29702
29753
|
try {
|
|
29703
29754
|
const data = await startRemoteSession({
|
|
@@ -31208,6 +31259,7 @@ ${wcagWarnings.join("\n")}` }
|
|
|
31208
31259
|
}, []);
|
|
31209
31260
|
const sessionStartRecallRef = useRef7(null);
|
|
31210
31261
|
const kimiMdStaleNudgedRef = useRef7(false);
|
|
31262
|
+
const sessionPlanRef = useRef7(null);
|
|
31211
31263
|
const sessionMgr = useSessionManager({
|
|
31212
31264
|
cfg,
|
|
31213
31265
|
messagesRef,
|
|
@@ -31885,7 +31937,7 @@ ${wcagWarnings.join("\n")}` }
|
|
|
31885
31937
|
(picked) => {
|
|
31886
31938
|
setShowPlanCompletePicker(false);
|
|
31887
31939
|
if (!picked || picked === "continue") return;
|
|
31888
|
-
const plan = distillSessionPlan(messagesRef.current);
|
|
31940
|
+
const plan = sessionPlanRef.current ?? distillSessionPlan(messagesRef.current);
|
|
31889
31941
|
if (!plan) {
|
|
31890
31942
|
setEvents((e) => [
|
|
31891
31943
|
...e,
|
|
@@ -31919,6 +31971,7 @@ ${wcagWarnings.join("\n")}` }
|
|
|
31919
31971
|
clearTaskTracking();
|
|
31920
31972
|
compactSuggestedRef.current = false;
|
|
31921
31973
|
updateNudgedRef.current = false;
|
|
31974
|
+
sessionPlanRef.current = null;
|
|
31922
31975
|
setEvents((e) => [
|
|
31923
31976
|
...e,
|
|
31924
31977
|
{
|
|
@@ -31932,6 +31985,13 @@ ${wcagWarnings.join("\n")}` }
|
|
|
31932
31985
|
}
|
|
31933
31986
|
setMode(picked);
|
|
31934
31987
|
modeRef.current = picked;
|
|
31988
|
+
rebuildSystemPromptForMode(
|
|
31989
|
+
messagesRef.current,
|
|
31990
|
+
cacheStableRef.current,
|
|
31991
|
+
cfg?.model ?? DEFAULT_MODEL,
|
|
31992
|
+
picked,
|
|
31993
|
+
[...ALL_TOOLS, ...mcpToolsRef.current, ...lspToolsRef.current]
|
|
31994
|
+
);
|
|
31935
31995
|
submitRef.current(plan);
|
|
31936
31996
|
},
|
|
31937
31997
|
[mkKey, setShowPlanCompletePicker, setMode, setEvents, setUsage, setSessionUsage, setGatewayMeta, clearTaskTracking, resetSession, submitRef]
|
|
@@ -32145,7 +32205,8 @@ ${wcagWarnings.join("\n")}` }
|
|
|
32145
32205
|
sessionStateRef,
|
|
32146
32206
|
compiledContextRef,
|
|
32147
32207
|
lastApiErrorRef,
|
|
32148
|
-
activeScopeRef
|
|
32208
|
+
activeScopeRef,
|
|
32209
|
+
sessionPlanRef
|
|
32149
32210
|
}), [
|
|
32150
32211
|
exit,
|
|
32151
32212
|
busy,
|
|
@@ -32583,7 +32644,7 @@ ${conflicts.join("\n")}` }
|
|
|
32583
32644
|
askPermission: askForPermission,
|
|
32584
32645
|
onToolLimitReached: () => new Promise((resolve5) => {
|
|
32585
32646
|
limitResolveRef.current = resolve5;
|
|
32586
|
-
setLimitModal({ limit:
|
|
32647
|
+
setLimitModal({ limit: 200, resolve: resolve5 });
|
|
32587
32648
|
}),
|
|
32588
32649
|
onLoopDetected: () => new Promise((resolve5) => {
|
|
32589
32650
|
loopResolveRef.current = resolve5;
|
|
@@ -32805,6 +32866,7 @@ ${conflicts.join("\n")}` }
|
|
|
32805
32866
|
if (modeRef.current === "plan") {
|
|
32806
32867
|
const plan = distillSessionPlan(messagesRef.current);
|
|
32807
32868
|
if (plan) {
|
|
32869
|
+
sessionPlanRef.current = plan;
|
|
32808
32870
|
setShowPlanCompletePicker(true);
|
|
32809
32871
|
}
|
|
32810
32872
|
}
|
|
@@ -33002,7 +33064,7 @@ ${conflicts.join("\n")}` }
|
|
|
33002
33064
|
selectedRemoteSession,
|
|
33003
33065
|
onSelectRemoteSession: setSelectedRemoteSession,
|
|
33004
33066
|
onCancelRemoteSession: handleRemoteCancel2,
|
|
33005
|
-
onInboxOpen:
|
|
33067
|
+
onInboxOpen: openBrowser,
|
|
33006
33068
|
multiAgentSettings: cfg ? {
|
|
33007
33069
|
multiAgentEnabled: cfg.multiAgentEnabled,
|
|
33008
33070
|
workerEndpoint: cfg.workerEndpoint,
|
|
@@ -33520,7 +33582,7 @@ function renderLogo(version) {
|
|
|
33520
33582
|
|
|
33521
33583
|
// src/index.tsx
|
|
33522
33584
|
var program = new Command2();
|
|
33523
|
-
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)").option("--continue-on-limit", "reset tool-call counter and continue when the
|
|
33585
|
+
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)").option("--continue-on-limit", "reset tool-call counter and continue when the 200-call limit is hit (print mode only)").option("--max-input-tokens <n>", "cumulative prompt token budget; exits 42 when exhausted (print mode only)", (v) => parseInt(v, 10)).option("--emit-events", "emit Camouflage NDJSON events to stdout; requires -p (for initial prompt)").option("--multi-turn", "with --emit-events: keep reading stdin for UserInputSubmitted follow-ups after the initial turn").option("--ui <name>", "render UI with the given engine: `ink` (default, stable) or `camouflage` (experimental Rust TUI). Can also be set via the KIMIFLARE_UI environment variable.").option("--camouflage-bin <path>", "with --ui camouflage: path to the camouflage-tui binary (defaults to PATH lookup)").option("--mode <mode>", "run mode: interactive (default), print, rpc");
|
|
33524
33586
|
program.command("cost").description("Show cost attribution by task type (requires costAttribution enabled)").option("-w, --week", "last 7 days (default)").option("-m, --month", "last 30 days").option("-d, --day", "today only").option("-s, --session <id>", "single session detail").option("-c, --category <name>", "filter by category").option("--json", "machine-readable output").option("--reclassify", "re-run classification on all sessions").option("--local-only", "skip Cloudflare reconciliation").action(async (cmdOpts) => {
|
|
33525
33587
|
const cfg = await loadConfig();
|
|
33526
33588
|
const enabled = cfg?.costAttribution ?? false;
|