autopilot-ai 1.24.1 → 1.25.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 +775 -473
- package/dist/index.js.map +1 -1
- package/dist/sdk/index.js +493 -201
- package/dist/sdk/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -102,8 +102,8 @@ async function flushAndCloseForTesting() {
|
|
|
102
102
|
const s = currentStream;
|
|
103
103
|
currentStream = null;
|
|
104
104
|
currentDate = null;
|
|
105
|
-
await new Promise((
|
|
106
|
-
s.end(() =>
|
|
105
|
+
await new Promise((resolve20) => {
|
|
106
|
+
s.end(() => resolve20());
|
|
107
107
|
});
|
|
108
108
|
}
|
|
109
109
|
function isLogSinkEnabled() {
|
|
@@ -1342,10 +1342,10 @@ async function* readSSE(stream, signal, idleTimeoutMs, postFirstByteIdleTimeoutM
|
|
|
1342
1342
|
gotFirstByte = true;
|
|
1343
1343
|
buffer += decoder.decode(value, { stream: true });
|
|
1344
1344
|
buffer = buffer.replace(/\r\n/g, "\n");
|
|
1345
|
-
let
|
|
1346
|
-
while ((
|
|
1347
|
-
const event = buffer.slice(0,
|
|
1348
|
-
buffer = buffer.slice(
|
|
1345
|
+
let sep8;
|
|
1346
|
+
while ((sep8 = buffer.indexOf("\n\n")) !== -1) {
|
|
1347
|
+
const event = buffer.slice(0, sep8);
|
|
1348
|
+
buffer = buffer.slice(sep8 + 2);
|
|
1349
1349
|
const data = extractData(event);
|
|
1350
1350
|
if (data !== null) yield data;
|
|
1351
1351
|
}
|
|
@@ -2782,7 +2782,8 @@ async function* parseStream(body, signal, idleTimeoutMs = DEFAULT_IDLE_TIMEOUT_M
|
|
|
2782
2782
|
index: idx,
|
|
2783
2783
|
id: buf.id,
|
|
2784
2784
|
name: buf.name,
|
|
2785
|
-
arguments: buf.args
|
|
2785
|
+
arguments: buf.args,
|
|
2786
|
+
finishReason
|
|
2786
2787
|
};
|
|
2787
2788
|
}
|
|
2788
2789
|
yield { type: "done", finishReason, usage: lastUsage };
|
|
@@ -2850,11 +2851,11 @@ function extractApiError(parsed, rawText) {
|
|
|
2850
2851
|
return null;
|
|
2851
2852
|
}
|
|
2852
2853
|
function sleep(ms, signal) {
|
|
2853
|
-
return new Promise((
|
|
2854
|
+
return new Promise((resolve20, reject) => {
|
|
2854
2855
|
if (signal?.aborted) return reject(new DOMException("aborted", "AbortError"));
|
|
2855
2856
|
const t = setTimeout(() => {
|
|
2856
2857
|
signal?.removeEventListener("abort", onAbort);
|
|
2857
|
-
|
|
2858
|
+
resolve20();
|
|
2858
2859
|
}, ms);
|
|
2859
2860
|
const onAbort = () => {
|
|
2860
2861
|
clearTimeout(t);
|
|
@@ -3608,9 +3609,9 @@ var require_node_gyp_build = __commonJS({
|
|
|
3608
3609
|
var debug = getFirst(path.join(dir, "build/Debug"), matchBuild);
|
|
3609
3610
|
if (debug) return debug;
|
|
3610
3611
|
}
|
|
3611
|
-
var prebuild =
|
|
3612
|
+
var prebuild = resolve20(dir);
|
|
3612
3613
|
if (prebuild) return prebuild;
|
|
3613
|
-
var nearby =
|
|
3614
|
+
var nearby = resolve20(path.dirname(process.execPath));
|
|
3614
3615
|
if (nearby) return nearby;
|
|
3615
3616
|
var target = [
|
|
3616
3617
|
"platform=" + platform8,
|
|
@@ -3626,7 +3627,7 @@ var require_node_gyp_build = __commonJS({
|
|
|
3626
3627
|
// eslint-disable-line
|
|
3627
3628
|
].filter(Boolean).join(" ");
|
|
3628
3629
|
throw new Error("No native build was found for " + target + "\n loaded from: " + dir + "\n");
|
|
3629
|
-
function
|
|
3630
|
+
function resolve20(dir2) {
|
|
3630
3631
|
var tuples = readdirSync2(path.join(dir2, "prebuilds")).map(parseTuple);
|
|
3631
3632
|
var tuple = tuples.filter(matchTuple(platform8, arch)).sort(compareTuples)[0];
|
|
3632
3633
|
if (!tuple) return;
|
|
@@ -4047,7 +4048,7 @@ function truncateForEmbedding(text) {
|
|
|
4047
4048
|
return text.slice(0, MAX_EMBED_CHARS);
|
|
4048
4049
|
}
|
|
4049
4050
|
async function sleep2(ms) {
|
|
4050
|
-
return new Promise((
|
|
4051
|
+
return new Promise((resolve20) => setTimeout(resolve20, ms));
|
|
4051
4052
|
}
|
|
4052
4053
|
async function fetchWithRetry(url, init, retries = 3) {
|
|
4053
4054
|
let lastError;
|
|
@@ -4699,6 +4700,8 @@ If the user asks what model you are, answer with exactly: \`${opts2.model}\`. Th
|
|
|
4699
4700
|
- Today: ${date}`;
|
|
4700
4701
|
const hasLsp = opts2.tools.some((t) => t.name.startsWith("lsp_"));
|
|
4701
4702
|
const lspBlock = hasLsp ? "\n\nLSP tools are available for semantic code intelligence. Prefer `lsp_definition` over `grep` when looking for the source of a symbol. Prefer `lsp_references` over `grep` when finding usages. Use `lsp_hover` to confirm types before refactoring." : "";
|
|
4703
|
+
const hasArtifactTool = opts2.tools.some((t) => t.name === "create_artifact");
|
|
4704
|
+
const artifactGuidance = hasArtifactTool ? "\n\n## Choosing when to create an artifact\nUse `create_artifact` when the user would benefit from a visual, interactive, or polished standalone deliverable (for example, a dashboard, chart, diagram, prototype, or long structured report). Prefer a normal terminal response for brief answers, explanations, code snippets, and routine repository changes. For an artifact, first use `write` to save the complete HTML document as a local `.html` file in the workspace; then call `create_artifact` with a concise title and that file's workspace-relative `sourcePath`. Never put the full HTML document in `create_artifact` arguments. After it opens, summarize the result briefly in the terminal." : "";
|
|
4702
4705
|
const tools = `Tools available:
|
|
4703
4706
|
${toolsBlock}`;
|
|
4704
4707
|
const userShellBlock = userShellCommandsEnabled() ? `
|
|
@@ -4740,7 +4743,7 @@ ${opts2.lspContext}` : "";
|
|
|
4740
4743
|
The following MCP server information was pre-computed by the coordinator.
|
|
4741
4744
|
|
|
4742
4745
|
${opts2.mcpContext}` : "";
|
|
4743
|
-
return identity + "\n\n" + env2 + "\n\n" + tools + lspBlock + userShellBlock + contextBlock + modeBlock + skillsBlock + memoryBlock + lspContextBlock + mcpContextBlock;
|
|
4746
|
+
return identity + "\n\n" + env2 + "\n\n" + tools + artifactGuidance + lspBlock + userShellBlock + contextBlock + modeBlock + skillsBlock + memoryBlock + lspContextBlock + mcpContextBlock;
|
|
4744
4747
|
}
|
|
4745
4748
|
function buildSystemPrompt(opts2) {
|
|
4746
4749
|
return buildStaticPrefix(opts2) + "\n\n" + buildSessionPrefix(opts2);
|
|
@@ -5438,15 +5441,15 @@ async function gitNumstat(cwd, opts2 = {}) {
|
|
|
5438
5441
|
if (opts2.includeUntracked) {
|
|
5439
5442
|
try {
|
|
5440
5443
|
const { stdout } = await execFileAsync("git", ["ls-files", "--others", "--exclude-standard"], { cwd, timeout: 5e3 });
|
|
5441
|
-
const { readFile:
|
|
5442
|
-
const { join:
|
|
5444
|
+
const { readFile: readFile37, stat: stat14 } = await import("fs/promises");
|
|
5445
|
+
const { join: join58 } = await import("path");
|
|
5443
5446
|
for (const file of stdout.split("\n").filter(Boolean)) {
|
|
5444
5447
|
let lines = 0;
|
|
5445
5448
|
try {
|
|
5446
|
-
const path =
|
|
5447
|
-
const size = (await
|
|
5449
|
+
const path = join58(cwd, file);
|
|
5450
|
+
const size = (await stat14(path)).size;
|
|
5448
5451
|
if (size > 0 && size <= 1024 * 1024) {
|
|
5449
|
-
const text = await
|
|
5452
|
+
const text = await readFile37(path, "utf8");
|
|
5450
5453
|
lines = text.split("\n").length - (text.endsWith("\n") ? 1 : 0);
|
|
5451
5454
|
}
|
|
5452
5455
|
} catch {
|
|
@@ -6048,11 +6051,11 @@ Not in this API \u2014 call these as separate tools instead: ${directTools.map((
|
|
|
6048
6051
|
opts2.callbacks.onToolCallArgs?.(ev.index, ev.argsDelta);
|
|
6049
6052
|
break;
|
|
6050
6053
|
case "tool_call_complete": {
|
|
6051
|
-
const
|
|
6054
|
+
const callArgs = validateToolArguments(ev.arguments, ev.name, ev.id, ev.finishReason, opts2.sessionId);
|
|
6052
6055
|
const call = {
|
|
6053
6056
|
id: ev.id,
|
|
6054
6057
|
type: "function",
|
|
6055
|
-
function: { name: normalizeToolName(ev.name, opts2.tools), arguments:
|
|
6058
|
+
function: { name: normalizeToolName(ev.name, opts2.tools), arguments: callArgs }
|
|
6056
6059
|
};
|
|
6057
6060
|
toolCalls.push(call);
|
|
6058
6061
|
tr.toolsUsed.push(call.function.name);
|
|
@@ -6901,14 +6904,29 @@ function replaceMessagesInPlace(target, next) {
|
|
|
6901
6904
|
function normalizeToolName(name, tools) {
|
|
6902
6905
|
return name === "spawn_worker" && tools.some((t) => t.name === "subagent") ? "subagent" : name;
|
|
6903
6906
|
}
|
|
6904
|
-
function validateToolArguments(raw) {
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
6907
|
+
function validateToolArguments(raw, name, id, finishReason, sessionId) {
|
|
6908
|
+
let issue = null;
|
|
6909
|
+
if (!raw.trim()) {
|
|
6910
|
+
issue = "empty arguments";
|
|
6911
|
+
} else {
|
|
6912
|
+
try {
|
|
6913
|
+
const parsed = JSON.parse(raw);
|
|
6914
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) issue = "arguments must be a JSON object";
|
|
6915
|
+
} catch (error) {
|
|
6916
|
+
issue = error instanceof Error ? error.message : "invalid JSON";
|
|
6917
|
+
}
|
|
6918
|
+
}
|
|
6919
|
+
if (issue) {
|
|
6920
|
+
logger.warn("turn:tool_arguments_invalid", {
|
|
6921
|
+
sessionId,
|
|
6922
|
+
tool: name,
|
|
6923
|
+
toolCallId: id,
|
|
6924
|
+
argumentBytes: Buffer.byteLength(raw, "utf8"),
|
|
6925
|
+
finishReason,
|
|
6926
|
+
issue
|
|
6927
|
+
});
|
|
6911
6928
|
}
|
|
6929
|
+
return raw;
|
|
6912
6930
|
}
|
|
6913
6931
|
function llmAuthOf(opts2) {
|
|
6914
6932
|
return {
|
|
@@ -7813,15 +7831,15 @@ function makeErrorOutput(message2) {
|
|
|
7813
7831
|
return { content: message2, rawBytes: bytes, reducedBytes: bytes };
|
|
7814
7832
|
}
|
|
7815
7833
|
async function execOnce(command, cwd) {
|
|
7816
|
-
return new Promise((
|
|
7834
|
+
return new Promise((resolve20) => {
|
|
7817
7835
|
const child = spawn("bash", ["-lc", command], { cwd });
|
|
7818
7836
|
let out = "";
|
|
7819
7837
|
child.stdout.on("data", (d) => {
|
|
7820
7838
|
out += d.toString("utf8");
|
|
7821
7839
|
});
|
|
7822
7840
|
child.on("close", (code) => {
|
|
7823
|
-
if (code !== 0) return
|
|
7824
|
-
|
|
7841
|
+
if (code !== 0) return resolve20(void 0);
|
|
7842
|
+
resolve20(out.trim() || void 0);
|
|
7825
7843
|
});
|
|
7826
7844
|
});
|
|
7827
7845
|
}
|
|
@@ -7975,7 +7993,7 @@ async function runBash(args, ctx) {
|
|
|
7975
7993
|
if (pushGuard) return pushGuard;
|
|
7976
7994
|
const { shell, args: shellArgs, isPosix } = getShellCommand(ctx.shell);
|
|
7977
7995
|
const { command, env: coauthorEnv } = isPosix ? injectCoauthor(args.command, ctx.coauthor) : { command: args.command, env: {} };
|
|
7978
|
-
return new Promise((
|
|
7996
|
+
return new Promise((resolve20, reject) => {
|
|
7979
7997
|
logger.debug("bash:spawn", { command: args.command.slice(0, 200), cwd: ctx.cwd, shell });
|
|
7980
7998
|
const child = spawn(shell, [...shellArgs, command], {
|
|
7981
7999
|
cwd: ctx.cwd,
|
|
@@ -8040,7 +8058,7 @@ ${stderr}`
|
|
|
8040
8058
|
if (hint) parts.push(hint);
|
|
8041
8059
|
}
|
|
8042
8060
|
const raw = parts.join("\n");
|
|
8043
|
-
|
|
8061
|
+
resolve20({
|
|
8044
8062
|
content: raw,
|
|
8045
8063
|
rawBytes: Buffer.byteLength(raw, "utf8"),
|
|
8046
8064
|
reducedBytes: Buffer.byteLength(raw, "utf8"),
|
|
@@ -9438,7 +9456,7 @@ import { tmpdir as tmpdir2 } from "os";
|
|
|
9438
9456
|
import { join as join19, dirname as dirname8 } from "path";
|
|
9439
9457
|
async function autoScroll(page) {
|
|
9440
9458
|
await page.evaluate(async () => {
|
|
9441
|
-
await new Promise((
|
|
9459
|
+
await new Promise((resolve20) => {
|
|
9442
9460
|
let totalHeight = 0;
|
|
9443
9461
|
const distance = 300;
|
|
9444
9462
|
const timer3 = setInterval(() => {
|
|
@@ -9447,12 +9465,12 @@ async function autoScroll(page) {
|
|
|
9447
9465
|
totalHeight += distance;
|
|
9448
9466
|
if (totalHeight >= scrollHeight) {
|
|
9449
9467
|
clearInterval(timer3);
|
|
9450
|
-
|
|
9468
|
+
resolve20();
|
|
9451
9469
|
}
|
|
9452
9470
|
}, 100);
|
|
9453
9471
|
setTimeout(() => {
|
|
9454
9472
|
clearInterval(timer3);
|
|
9455
|
-
|
|
9473
|
+
resolve20();
|
|
9456
9474
|
}, 1e4);
|
|
9457
9475
|
});
|
|
9458
9476
|
});
|
|
@@ -9551,6 +9569,288 @@ var init_browser = __esm({
|
|
|
9551
9569
|
}
|
|
9552
9570
|
});
|
|
9553
9571
|
|
|
9572
|
+
// src/util/open-browser.ts
|
|
9573
|
+
import { spawn as spawn2 } from "child_process";
|
|
9574
|
+
import { platform as platform3 } from "os";
|
|
9575
|
+
function openBrowser(url) {
|
|
9576
|
+
if (process.env.KIMIFLARE_NO_BROWSER === "1" || process.env.BROWSER === "none") return false;
|
|
9577
|
+
try {
|
|
9578
|
+
const os2 = platform3();
|
|
9579
|
+
const [cmd, args] = os2 === "darwin" ? ["open", [url]] : os2 === "win32" ? ["cmd", ["/c", "start", "", url]] : ["xdg-open", [url]];
|
|
9580
|
+
const child = spawn2(cmd, args, { detached: true, stdio: "ignore" });
|
|
9581
|
+
child.on("error", () => void 0);
|
|
9582
|
+
child.unref();
|
|
9583
|
+
return true;
|
|
9584
|
+
} catch {
|
|
9585
|
+
return false;
|
|
9586
|
+
}
|
|
9587
|
+
}
|
|
9588
|
+
var init_open_browser = __esm({
|
|
9589
|
+
"src/util/open-browser.ts"() {
|
|
9590
|
+
"use strict";
|
|
9591
|
+
}
|
|
9592
|
+
});
|
|
9593
|
+
|
|
9594
|
+
// src/tools/html-artifact.ts
|
|
9595
|
+
import { chmod as chmod2, lstat as lstat2, mkdir as mkdir9, mkdtemp, readFile as readFile11, readdir as readdir4, realpath as realpath2, rm as rm2, stat as stat5, writeFile as writeFile10 } from "fs/promises";
|
|
9596
|
+
import { execFileSync } from "child_process";
|
|
9597
|
+
import { tmpdir as tmpdir3 } from "os";
|
|
9598
|
+
import { isAbsolute as isAbsolute2, join as join20, relative as relative3, resolve as resolve3, sep as sep2 } from "path";
|
|
9599
|
+
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
9600
|
+
async function createHtmlArtifactFromFile(args, cwd, options = {}) {
|
|
9601
|
+
assertArtifactSourceArgs(args);
|
|
9602
|
+
const workspaceRoot = await getWorkspaceRoot(cwd);
|
|
9603
|
+
const workspaceReal = await realpath2(workspaceRoot);
|
|
9604
|
+
const inputPath = resolvePath(cwd, args.sourcePath);
|
|
9605
|
+
let inputReal;
|
|
9606
|
+
try {
|
|
9607
|
+
inputReal = await realpath2(inputPath);
|
|
9608
|
+
} catch (error) {
|
|
9609
|
+
if (error.code === "ENOENT") {
|
|
9610
|
+
throw new ToolError({
|
|
9611
|
+
code: "not_found",
|
|
9612
|
+
message: `Artifact source file not found: ${args.sourcePath}`,
|
|
9613
|
+
suggestion: "Use the write tool to create the complete HTML file first, then pass its path as sourcePath."
|
|
9614
|
+
});
|
|
9615
|
+
}
|
|
9616
|
+
throw error;
|
|
9617
|
+
}
|
|
9618
|
+
if (!isWithin(workspaceReal, inputReal)) {
|
|
9619
|
+
throw new ToolError({
|
|
9620
|
+
code: "policy_rejection",
|
|
9621
|
+
message: "Artifact sourcePath must resolve to a file inside the current workspace.",
|
|
9622
|
+
suggestion: "Write the HTML file inside the workspace and retry with its workspace-relative path."
|
|
9623
|
+
});
|
|
9624
|
+
}
|
|
9625
|
+
const info = await stat5(inputReal);
|
|
9626
|
+
if (!info.isFile()) {
|
|
9627
|
+
throw new ToolError({ code: "invalid_args", message: "Artifact sourcePath must be a regular HTML file." });
|
|
9628
|
+
}
|
|
9629
|
+
if (info.size > MAX_ARTIFACT_HTML_LENGTH * 4) {
|
|
9630
|
+
throw new ToolError({ code: "invalid_args", message: `Artifact HTML exceeds ${MAX_ARTIFACT_HTML_LENGTH} characters.` });
|
|
9631
|
+
}
|
|
9632
|
+
const html = await readFile11(inputReal, "utf8");
|
|
9633
|
+
return createHtmlArtifact({ title: args.title, html }, cwd, options);
|
|
9634
|
+
}
|
|
9635
|
+
async function createHtmlArtifact(args, cwd, options = {}) {
|
|
9636
|
+
assertArtifactHtmlArgs(args);
|
|
9637
|
+
const rootDir = options.rootDir ?? join20(tmpdir3(), ARTIFACT_ROOT);
|
|
9638
|
+
const workspaceRoot = await getWorkspaceRoot(cwd);
|
|
9639
|
+
const workspaceReal = await realpath2(workspaceRoot);
|
|
9640
|
+
if (isWithin(workspaceReal, resolve3(rootDir))) {
|
|
9641
|
+
throw new Error("Refusing to store an artifact inside the workspace: " + rootDir);
|
|
9642
|
+
}
|
|
9643
|
+
await ensureSecureRoot(rootDir);
|
|
9644
|
+
const rootReal = await realpath2(rootDir);
|
|
9645
|
+
if (isWithin(workspaceReal, rootReal)) {
|
|
9646
|
+
throw new Error("Refusing to store an artifact inside the workspace: " + rootReal);
|
|
9647
|
+
}
|
|
9648
|
+
await cleanupOldArtifacts(rootDir, (options.now ?? Date.now)());
|
|
9649
|
+
const artifactDir = await mkdtemp(join20(rootDir, ARTIFACT_PREFIX));
|
|
9650
|
+
await chmod2(artifactDir, 448);
|
|
9651
|
+
const filePath = join20(artifactDir, "index.html");
|
|
9652
|
+
await writeFile10(filePath, buildArtifactHtml(args.title, args.html), {
|
|
9653
|
+
encoding: "utf8",
|
|
9654
|
+
flag: "wx",
|
|
9655
|
+
mode: 384
|
|
9656
|
+
});
|
|
9657
|
+
const opened = (options.open ?? openBrowser)(pathToFileURL2(filePath).href);
|
|
9658
|
+
const status = opened ? "Opened in your browser." : "Could not open a browser automatically.";
|
|
9659
|
+
return "Artifact: " + args.title + "\n" + status + "\nTemporary file: " + filePath;
|
|
9660
|
+
}
|
|
9661
|
+
async function cleanupOldArtifacts(rootDir, now2 = Date.now()) {
|
|
9662
|
+
let entries;
|
|
9663
|
+
try {
|
|
9664
|
+
entries = await readdir4(rootDir, { withFileTypes: true });
|
|
9665
|
+
} catch {
|
|
9666
|
+
return;
|
|
9667
|
+
}
|
|
9668
|
+
for (const entry of entries) {
|
|
9669
|
+
if (!entry.name.startsWith(ARTIFACT_PREFIX) || !entry.isDirectory() || entry.isSymbolicLink()) continue;
|
|
9670
|
+
const path = join20(rootDir, entry.name);
|
|
9671
|
+
try {
|
|
9672
|
+
const info = await lstat2(path);
|
|
9673
|
+
if (!info.isDirectory() || info.isSymbolicLink() || now2 - info.mtimeMs < ARTIFACT_MAX_AGE_MS) continue;
|
|
9674
|
+
await rm2(path, { recursive: true, force: true });
|
|
9675
|
+
} catch {
|
|
9676
|
+
}
|
|
9677
|
+
}
|
|
9678
|
+
}
|
|
9679
|
+
function buildArtifactHtml(title, html) {
|
|
9680
|
+
assertArtifactHtmlArgs({ title, html });
|
|
9681
|
+
const safeTitle = escapeHtml(title);
|
|
9682
|
+
const safeSrcdoc = escapeAttribute(html);
|
|
9683
|
+
const lines = [
|
|
9684
|
+
"<!doctype html>",
|
|
9685
|
+
'<html lang="en">',
|
|
9686
|
+
"<head>",
|
|
9687
|
+
' <meta charset="utf-8">',
|
|
9688
|
+
' <meta name="viewport" content="width=device-width, initial-scale=1">',
|
|
9689
|
+
' <meta name="theme-color" content="#090909">',
|
|
9690
|
+
" <title>" + safeTitle + " \xB7 Autopilot</title>",
|
|
9691
|
+
" <style>",
|
|
9692
|
+
' :root { color-scheme: dark; font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }',
|
|
9693
|
+
" * { box-sizing: border-box; }",
|
|
9694
|
+
" html, body { width: 100%; height: 100%; margin: 0; }",
|
|
9695
|
+
" body { display: grid; grid-template-rows: auto minmax(0, 1fr); overflow: hidden; background: #090909; color: #f4f4f5; }",
|
|
9696
|
+
" .autopilot-bar { position: sticky; top: 0; z-index: 10; display: flex; min-height: 54px; align-items: center; justify-content: space-between; gap: 16px; padding: 0 22px; border-bottom: 1px solid #262626; background: rgba(9, 9, 9, .96); backdrop-filter: blur(12px); }",
|
|
9697
|
+
" .autopilot-brand { display: inline-flex; align-items: center; gap: 9px; color: #f5f5f5; font-size: 14px; font-weight: 650; letter-spacing: -.025em; text-decoration: none; }",
|
|
9698
|
+
" .autopilot-mark { width: 20px; height: 20px; flex: none; }",
|
|
9699
|
+
" .autopilot-actions { display: flex; align-items: center; gap: 16px; }",
|
|
9700
|
+
" .autopilot-actions a { color: #a3a3a3; font-size: 12px; text-decoration: none; transition: color .15s ease; }",
|
|
9701
|
+
" .autopilot-actions a:hover { color: #fff; }",
|
|
9702
|
+
" .autopilot-actions .star { padding: 7px 11px; border: 1px solid #343434; border-radius: 7px; color: #f0f0f0; }",
|
|
9703
|
+
" .autopilot-actions .star:hover { border-color: #ff9933; color: #ffb15c; }",
|
|
9704
|
+
" main { min-width: 0; min-height: 0; }",
|
|
9705
|
+
" iframe { display: block; width: 100%; height: 100%; border: 0; background: #fff; }",
|
|
9706
|
+
" @media (max-width: 520px) { .autopilot-bar { min-height: 48px; padding: 0 14px; } .autopilot-actions { gap: 10px; } .autopilot-actions a { font-size: 11px; } }",
|
|
9707
|
+
" </style>",
|
|
9708
|
+
"</head>",
|
|
9709
|
+
"<body>",
|
|
9710
|
+
' <header class="autopilot-bar">',
|
|
9711
|
+
' <a class="autopilot-brand" href="' + AUTOPILOT_URL + '" target="_blank" rel="noopener noreferrer" aria-label="Autopilot on GitHub">',
|
|
9712
|
+
' <svg class="autopilot-mark" viewBox="0 0 24 24" role="img" aria-label="Autopilot logo" xmlns="http://www.w3.org/2000/svg">',
|
|
9713
|
+
' <path fill="#ff9933" d="M12 1.8a10.2 10.2 0 1 0 10.2 10.2A10.21 10.21 0 0 0 12 1.8Zm0 2.3a7.9 7.9 0 1 1 0 15.8 7.9 7.9 0 0 1 0-15.8Z"/>',
|
|
9714
|
+
' <path fill="#ff9933" d="m6.9 16.8 4.3-9.6c.3-.7 1.3-.7 1.6 0l4.3 9.6h-2.5l-2.6-6-2.6 6H6.9Z"/>',
|
|
9715
|
+
" </svg>",
|
|
9716
|
+
" <span>autopilot</span>",
|
|
9717
|
+
" </a>",
|
|
9718
|
+
' <nav class="autopilot-actions" aria-label="Autopilot links">',
|
|
9719
|
+
' <a href="' + AUTOPILOT_URL + '" target="_blank" rel="noopener noreferrer">About Autopilot \u2197</a>',
|
|
9720
|
+
' <a class="star" href="' + AUTOPILOT_URL + '" target="_blank" rel="noopener noreferrer" aria-label="Star Autopilot on GitHub">\u2606 Star on GitHub</a>',
|
|
9721
|
+
" </nav>",
|
|
9722
|
+
" </header>",
|
|
9723
|
+
' <main><iframe title="' + escapeAttribute(title) + '" sandbox="allow-scripts" srcdoc="' + safeSrcdoc + '"></iframe></main>',
|
|
9724
|
+
"</body>",
|
|
9725
|
+
"</html>"
|
|
9726
|
+
];
|
|
9727
|
+
return lines.join("\n") + "\n";
|
|
9728
|
+
}
|
|
9729
|
+
function assertArtifactSourceArgs(value) {
|
|
9730
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
9731
|
+
throw new ToolError({
|
|
9732
|
+
code: "invalid_args",
|
|
9733
|
+
recoverable: true,
|
|
9734
|
+
message: "Invalid create_artifact arguments: expected an object with a title and sourcePath.",
|
|
9735
|
+
suggestion: "Use write to save the complete HTML file in the workspace, then pass its path as sourcePath."
|
|
9736
|
+
});
|
|
9737
|
+
}
|
|
9738
|
+
const args = value;
|
|
9739
|
+
const issues = [];
|
|
9740
|
+
if (typeof args.title !== "string" || args.title.trim().length === 0 || args.title.length > MAX_ARTIFACT_TITLE_LENGTH) {
|
|
9741
|
+
issues.push(`title must be a non-empty string of at most ${MAX_ARTIFACT_TITLE_LENGTH} characters`);
|
|
9742
|
+
}
|
|
9743
|
+
if (typeof args.sourcePath !== "string" || args.sourcePath.trim().length === 0) {
|
|
9744
|
+
issues.push("sourcePath must be a non-empty path to an HTML file created with write");
|
|
9745
|
+
}
|
|
9746
|
+
if (issues.length > 0) {
|
|
9747
|
+
throw new ToolError({
|
|
9748
|
+
code: "invalid_args",
|
|
9749
|
+
recoverable: true,
|
|
9750
|
+
message: `Invalid create_artifact arguments: ${issues.join("; ")}.`,
|
|
9751
|
+
suggestion: "Use write to save the complete HTML file in the workspace, then call create_artifact with its title and sourcePath."
|
|
9752
|
+
});
|
|
9753
|
+
}
|
|
9754
|
+
}
|
|
9755
|
+
function assertArtifactHtmlArgs(value) {
|
|
9756
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
9757
|
+
throw new ToolError({
|
|
9758
|
+
code: "invalid_args",
|
|
9759
|
+
recoverable: true,
|
|
9760
|
+
message: "Invalid artifact content: expected an object with a title and HTML document.",
|
|
9761
|
+
suggestion: "Provide a non-empty title and complete HTML content."
|
|
9762
|
+
});
|
|
9763
|
+
}
|
|
9764
|
+
const args = value;
|
|
9765
|
+
const issues = [];
|
|
9766
|
+
if (typeof args.title !== "string" || args.title.trim().length === 0 || args.title.length > MAX_ARTIFACT_TITLE_LENGTH) {
|
|
9767
|
+
issues.push(`title must be a non-empty string of at most ${MAX_ARTIFACT_TITLE_LENGTH} characters`);
|
|
9768
|
+
}
|
|
9769
|
+
if (typeof args.html !== "string" || args.html.trim().length === 0 || args.html.length > MAX_ARTIFACT_HTML_LENGTH) {
|
|
9770
|
+
issues.push(`html must be a non-empty string of at most ${MAX_ARTIFACT_HTML_LENGTH} characters`);
|
|
9771
|
+
}
|
|
9772
|
+
if (issues.length > 0) {
|
|
9773
|
+
throw new ToolError({
|
|
9774
|
+
code: "invalid_args",
|
|
9775
|
+
recoverable: true,
|
|
9776
|
+
message: `Invalid artifact content: ${issues.join("; ")}.`,
|
|
9777
|
+
suggestion: "Supply a non-empty title and complete HTML document."
|
|
9778
|
+
});
|
|
9779
|
+
}
|
|
9780
|
+
}
|
|
9781
|
+
async function ensureSecureRoot(rootDir) {
|
|
9782
|
+
await mkdir9(rootDir, { recursive: true, mode: 448 });
|
|
9783
|
+
const info = await lstat2(rootDir);
|
|
9784
|
+
if (!info.isDirectory() || info.isSymbolicLink()) throw new Error("Artifact storage path is not a real directory: " + rootDir);
|
|
9785
|
+
if (typeof process.getuid === "function" && info.uid !== process.getuid()) {
|
|
9786
|
+
throw new Error("Artifact storage directory is not owned by the current user: " + rootDir);
|
|
9787
|
+
}
|
|
9788
|
+
if ((info.mode & 63) !== 0) await chmod2(rootDir, 448);
|
|
9789
|
+
}
|
|
9790
|
+
async function getWorkspaceRoot(cwd) {
|
|
9791
|
+
try {
|
|
9792
|
+
return execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
|
9793
|
+
cwd,
|
|
9794
|
+
encoding: "utf8",
|
|
9795
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
9796
|
+
}).trim();
|
|
9797
|
+
} catch {
|
|
9798
|
+
return cwd;
|
|
9799
|
+
}
|
|
9800
|
+
}
|
|
9801
|
+
function isWithin(parent, candidate) {
|
|
9802
|
+
const rel = relative3(parent, candidate);
|
|
9803
|
+
return rel === "" || rel !== ".." && !rel.startsWith(".." + sep2) && !isAbsolute2(rel);
|
|
9804
|
+
}
|
|
9805
|
+
function escapeHtml(value) {
|
|
9806
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
9807
|
+
}
|
|
9808
|
+
function escapeAttribute(value) {
|
|
9809
|
+
return escapeHtml(value).replaceAll('"', """).replaceAll("'", "'");
|
|
9810
|
+
}
|
|
9811
|
+
var ARTIFACT_ROOT, ARTIFACT_PREFIX, ARTIFACT_MAX_AGE_MS, AUTOPILOT_URL, MAX_ARTIFACT_TITLE_LENGTH, MAX_ARTIFACT_HTML_LENGTH, htmlArtifactTool;
|
|
9812
|
+
var init_html_artifact = __esm({
|
|
9813
|
+
"src/tools/html-artifact.ts"() {
|
|
9814
|
+
"use strict";
|
|
9815
|
+
init_paths2();
|
|
9816
|
+
init_open_browser();
|
|
9817
|
+
init_tool_error();
|
|
9818
|
+
ARTIFACT_ROOT = "autopilot-artifacts";
|
|
9819
|
+
ARTIFACT_PREFIX = "artifact-";
|
|
9820
|
+
ARTIFACT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
9821
|
+
AUTOPILOT_URL = "https://github.com/sinameraji/autopilot";
|
|
9822
|
+
MAX_ARTIFACT_TITLE_LENGTH = 160;
|
|
9823
|
+
MAX_ARTIFACT_HTML_LENGTH = 1e6;
|
|
9824
|
+
htmlArtifactTool = {
|
|
9825
|
+
name: "create_artifact",
|
|
9826
|
+
description: "Open a polished standalone HTML artifact in the user's browser. First use the normal write tool to save the complete HTML document as a local .html file in the workspace. Then call create_artifact with its title and sourcePath; do not pass the full HTML as a tool argument. The source file is kept in the workspace, and a branded, sandboxed browser copy is stored outside the project. Use for visual or interactive deliverables, dashboards, diagrams, prototypes, and substantial structured reports\u2014not short answers, explanations, code snippets, or routine code changes.",
|
|
9827
|
+
parameters: {
|
|
9828
|
+
type: "object",
|
|
9829
|
+
properties: {
|
|
9830
|
+
title: {
|
|
9831
|
+
type: "string",
|
|
9832
|
+
description: "Non-empty, short human-readable artifact title."
|
|
9833
|
+
},
|
|
9834
|
+
sourcePath: {
|
|
9835
|
+
type: "string",
|
|
9836
|
+
description: "Workspace-relative path to the complete HTML file already created with the write tool."
|
|
9837
|
+
}
|
|
9838
|
+
},
|
|
9839
|
+
required: ["title", "sourcePath"],
|
|
9840
|
+
additionalProperties: false
|
|
9841
|
+
},
|
|
9842
|
+
needsPermission: true,
|
|
9843
|
+
render: (args) => ({
|
|
9844
|
+
title: "create artifact: " + String(args.title ?? "Missing title").slice(0, 80),
|
|
9845
|
+
body: `Read ${String(args.sourcePath ?? "Missing sourcePath")} \xB7 opens in your browser`
|
|
9846
|
+
}),
|
|
9847
|
+
async run(args, ctx) {
|
|
9848
|
+
return createHtmlArtifactFromFile(args, ctx.cwd);
|
|
9849
|
+
}
|
|
9850
|
+
};
|
|
9851
|
+
}
|
|
9852
|
+
});
|
|
9853
|
+
|
|
9554
9854
|
// src/tools/tasks.ts
|
|
9555
9855
|
var tasksSetTool;
|
|
9556
9856
|
var init_tasks = __esm({
|
|
@@ -9766,9 +10066,9 @@ var init_memory = __esm({
|
|
|
9766
10066
|
|
|
9767
10067
|
// src/tools/hotcell-snapshot.ts
|
|
9768
10068
|
import { execFile as execFile4 } from "child_process";
|
|
9769
|
-
import { mkdtemp, rm as
|
|
9770
|
-
import { tmpdir as
|
|
9771
|
-
import { join as
|
|
10069
|
+
import { mkdtemp as mkdtemp2, rm as rm3 } from "fs/promises";
|
|
10070
|
+
import { tmpdir as tmpdir4 } from "os";
|
|
10071
|
+
import { join as join21 } from "path";
|
|
9772
10072
|
import { promisify as promisify4 } from "util";
|
|
9773
10073
|
async function git(args, cwd, env2) {
|
|
9774
10074
|
const { stdout } = await execFileAsync2("git", args, {
|
|
@@ -9816,9 +10116,9 @@ async function getRepositorySnapshot(cwd) {
|
|
|
9816
10116
|
if (!ref) {
|
|
9817
10117
|
throw new Error("Could not find an origin branch containing the base commit. Run git fetch, then retry.");
|
|
9818
10118
|
}
|
|
9819
|
-
const scratch = await
|
|
10119
|
+
const scratch = await mkdtemp2(join21(tmpdir4(), "autopilot-snapshot-"));
|
|
9820
10120
|
try {
|
|
9821
|
-
const env2 = { GIT_INDEX_FILE:
|
|
10121
|
+
const env2 = { GIT_INDEX_FILE: join21(scratch, "index") };
|
|
9822
10122
|
await git(["read-tree", "HEAD"], root, env2);
|
|
9823
10123
|
await git(["add", "-A", "--", ".", ...SECRET_EXCLUDES], root, env2);
|
|
9824
10124
|
const tree = (await git(["write-tree"], root, env2)).trim();
|
|
@@ -9837,15 +10137,15 @@ async function getRepositorySnapshot(cwd) {
|
|
|
9837
10137
|
}
|
|
9838
10138
|
return { url, ref, commit, patch: patch.toString("base64"), changedFiles: names.length };
|
|
9839
10139
|
} finally {
|
|
9840
|
-
await
|
|
10140
|
+
await rm3(scratch, { recursive: true, force: true });
|
|
9841
10141
|
}
|
|
9842
10142
|
}
|
|
9843
10143
|
async function getWorkingTreeArchive(cwd, limitBytes = MAX_ARCHIVE_BYTES) {
|
|
9844
10144
|
const root = (await git(["rev-parse", "--show-toplevel"], cwd).catch(() => "")).trim();
|
|
9845
10145
|
if (!root) throw new Error("Subagents need to run inside a Git repository.");
|
|
9846
|
-
const scratch = await
|
|
10146
|
+
const scratch = await mkdtemp2(join21(tmpdir4(), "autopilot-archive-"));
|
|
9847
10147
|
try {
|
|
9848
|
-
const env2 = { GIT_INDEX_FILE:
|
|
10148
|
+
const env2 = { GIT_INDEX_FILE: join21(scratch, "index") };
|
|
9849
10149
|
const hasHead = await git(["rev-parse", "--verify", "-q", "HEAD"], root).then(() => true, () => false);
|
|
9850
10150
|
await git(hasHead ? ["read-tree", "HEAD"] : ["read-tree", "--empty"], root, env2);
|
|
9851
10151
|
await git(["add", "-A", "--", ".", ...SECRET_EXCLUDES], root, env2);
|
|
@@ -9859,7 +10159,7 @@ async function getWorkingTreeArchive(cwd, limitBytes = MAX_ARCHIVE_BYTES) {
|
|
|
9859
10159
|
bytes: tarball.byteLength
|
|
9860
10160
|
};
|
|
9861
10161
|
} finally {
|
|
9862
|
-
await
|
|
10162
|
+
await rm3(scratch, { recursive: true, force: true });
|
|
9863
10163
|
}
|
|
9864
10164
|
}
|
|
9865
10165
|
function chunkPayload(base64, chunkSize = PAYLOAD_CHUNK_CHARS) {
|
|
@@ -9893,23 +10193,23 @@ var init_hotcell_snapshot = __esm({
|
|
|
9893
10193
|
});
|
|
9894
10194
|
|
|
9895
10195
|
// src/tools/hotcell-worker-cache.ts
|
|
9896
|
-
import { mkdir as
|
|
10196
|
+
import { mkdir as mkdir10, readFile as readFile12, writeFile as writeFile11 } from "fs/promises";
|
|
9897
10197
|
import { homedir as homedir11 } from "os";
|
|
9898
|
-
import { dirname as dirname9, join as
|
|
10198
|
+
import { dirname as dirname9, join as join22 } from "path";
|
|
9899
10199
|
function workerCachePath() {
|
|
9900
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
9901
|
-
return
|
|
10200
|
+
const xdg = process.env.XDG_CONFIG_HOME || join22(homedir11(), ".config");
|
|
10201
|
+
return join22(xdg, "kimiflare", "hotcell-worker-cache.json");
|
|
9902
10202
|
}
|
|
9903
10203
|
async function readCache2() {
|
|
9904
10204
|
try {
|
|
9905
|
-
return JSON.parse(await
|
|
10205
|
+
return JSON.parse(await readFile12(workerCachePath(), "utf8"));
|
|
9906
10206
|
} catch {
|
|
9907
10207
|
return {};
|
|
9908
10208
|
}
|
|
9909
10209
|
}
|
|
9910
10210
|
async function writeCache2(cache) {
|
|
9911
|
-
await
|
|
9912
|
-
await
|
|
10211
|
+
await mkdir10(dirname9(workerCachePath()), { recursive: true });
|
|
10212
|
+
await writeFile11(workerCachePath(), JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
|
|
9913
10213
|
}
|
|
9914
10214
|
function ensureWorkerBackup(opts2) {
|
|
9915
10215
|
const existing = inflight.get(opts2.packageSpec);
|
|
@@ -9969,13 +10269,13 @@ var init_hotcell_worker_cache = __esm({
|
|
|
9969
10269
|
});
|
|
9970
10270
|
|
|
9971
10271
|
// src/tools/hotcell-worker.ts
|
|
9972
|
-
import { spawn as
|
|
10272
|
+
import { spawn as spawn3 } from "child_process";
|
|
9973
10273
|
import { promisify as promisify5 } from "util";
|
|
9974
10274
|
import { execFile as execFile5 } from "child_process";
|
|
9975
|
-
import { resolve as
|
|
10275
|
+
import { resolve as resolve4 } from "path";
|
|
9976
10276
|
async function runHotcellWorker(options) {
|
|
9977
10277
|
const workerId = `hotcell-${crypto.randomUUID().slice(0, 8)}`;
|
|
9978
|
-
const cwd =
|
|
10278
|
+
const cwd = resolve4(options.cwd ?? process.cwd());
|
|
9979
10279
|
const model = options.model.trim();
|
|
9980
10280
|
if (!model) throw new Error("Hotcell workers require the coordinator's explicit model ID.");
|
|
9981
10281
|
validateModelId(model);
|
|
@@ -10283,7 +10583,7 @@ function parsePrintOutput(stdout) {
|
|
|
10283
10583
|
async function runProcess(executable, args, options) {
|
|
10284
10584
|
if (options.signal?.aborted) return { code: 130, stdout: "", stderr: "", aborted: true };
|
|
10285
10585
|
return await new Promise((resolvePromise, reject) => {
|
|
10286
|
-
const child =
|
|
10586
|
+
const child = spawn3(executable, args, { cwd: options.cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
10287
10587
|
const stdout = [];
|
|
10288
10588
|
const stderr = [];
|
|
10289
10589
|
let bytes = 0;
|
|
@@ -10515,17 +10815,17 @@ var init_worker_registry = __esm({
|
|
|
10515
10815
|
});
|
|
10516
10816
|
|
|
10517
10817
|
// src/tools/subagent-stats.ts
|
|
10518
|
-
import { appendFile as appendFile2, mkdir as
|
|
10818
|
+
import { appendFile as appendFile2, mkdir as mkdir11, readFile as readFile13 } from "fs/promises";
|
|
10519
10819
|
import { homedir as homedir12 } from "os";
|
|
10520
|
-
import { dirname as dirname10, join as
|
|
10820
|
+
import { dirname as dirname10, join as join23 } from "path";
|
|
10521
10821
|
function subagentStatsPath() {
|
|
10522
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
10523
|
-
return
|
|
10822
|
+
const xdg = process.env.XDG_DATA_HOME || join23(homedir12(), ".local", "share");
|
|
10823
|
+
return join23(xdg, "kimiflare", "subagents.jsonl");
|
|
10524
10824
|
}
|
|
10525
10825
|
async function recordSubagentEvent(event) {
|
|
10526
10826
|
const path = subagentStatsPath();
|
|
10527
10827
|
try {
|
|
10528
|
-
await
|
|
10828
|
+
await mkdir11(dirname10(path), { recursive: true });
|
|
10529
10829
|
await appendFile2(path, JSON.stringify(event) + "\n");
|
|
10530
10830
|
} catch (error) {
|
|
10531
10831
|
logger.debug("subagents:stats_write_failed", { error: String(error) });
|
|
@@ -10545,7 +10845,7 @@ function failureReason(error) {
|
|
|
10545
10845
|
async function readSubagentStats(days = 7, now2 = Date.now()) {
|
|
10546
10846
|
let raw = "";
|
|
10547
10847
|
try {
|
|
10548
|
-
raw = await
|
|
10848
|
+
raw = await readFile13(subagentStatsPath(), "utf8");
|
|
10549
10849
|
} catch {
|
|
10550
10850
|
}
|
|
10551
10851
|
const since = now2 - days * 24 * 60 * 60 * 1e3;
|
|
@@ -11439,18 +11739,18 @@ var init_expand_artifact = __esm({
|
|
|
11439
11739
|
|
|
11440
11740
|
// src/jobs/manager.ts
|
|
11441
11741
|
import Database from "better-sqlite3";
|
|
11442
|
-
import { spawn as
|
|
11742
|
+
import { spawn as spawn4, execFileSync as execFileSync2 } from "child_process";
|
|
11443
11743
|
import { mkdirSync as mkdirSync5, openSync, readFileSync as readFileSync4, readSync, existsSync as existsSync4, statSync as statSync3, closeSync, rmSync } from "fs";
|
|
11444
11744
|
import { homedir as homedir13 } from "os";
|
|
11445
|
-
import { dirname as dirname11, join as
|
|
11745
|
+
import { dirname as dirname11, join as join24 } from "path";
|
|
11446
11746
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
11447
11747
|
function defaultJobDbPath() {
|
|
11448
|
-
const root = process.env.XDG_STATE_HOME ||
|
|
11449
|
-
return process.env.AUTOPILOT_JOBS_DB ||
|
|
11748
|
+
const root = process.env.XDG_STATE_HOME || join24(homedir13(), ".local", "state");
|
|
11749
|
+
return process.env.AUTOPILOT_JOBS_DB || join24(root, "autopilot", "jobs.db");
|
|
11450
11750
|
}
|
|
11451
11751
|
function isProcessGroupAlive(pgid) {
|
|
11452
11752
|
try {
|
|
11453
|
-
const rows =
|
|
11753
|
+
const rows = execFileSync2("ps", ["-axo", "pgid=,state="], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
|
|
11454
11754
|
return rows.split("\n").some((line) => {
|
|
11455
11755
|
const match = line.trim().match(/^(\d+)\s+(\S+)/);
|
|
11456
11756
|
return match?.[1] === String(pgid) && !match[2].startsWith("Z");
|
|
@@ -11476,22 +11776,22 @@ function waitForProcessStartTime(pid, jobId, exitPath) {
|
|
|
11476
11776
|
function readProcessStartTime(pid) {
|
|
11477
11777
|
if (process.platform === "linux") {
|
|
11478
11778
|
try {
|
|
11479
|
-
const
|
|
11480
|
-
const fieldsAfterCommand =
|
|
11779
|
+
const stat14 = readFileSync4(`/proc/${pid}/stat`, "utf8");
|
|
11780
|
+
const fieldsAfterCommand = stat14.slice(stat14.lastIndexOf(")") + 1).trim().split(/\s+/);
|
|
11481
11781
|
return fieldsAfterCommand[19] ? `linux:${fieldsAfterCommand[19]}` : null;
|
|
11482
11782
|
} catch {
|
|
11483
11783
|
return null;
|
|
11484
11784
|
}
|
|
11485
11785
|
}
|
|
11486
11786
|
try {
|
|
11487
|
-
return
|
|
11787
|
+
return execFileSync2("ps", ["-o", "lstart=", "-o", "command=", "-p", String(pid)], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim() || null;
|
|
11488
11788
|
} catch {
|
|
11489
11789
|
return null;
|
|
11490
11790
|
}
|
|
11491
11791
|
}
|
|
11492
11792
|
function isZombie(pid) {
|
|
11493
11793
|
try {
|
|
11494
|
-
const state =
|
|
11794
|
+
const state = execFileSync2("ps", ["-o", "state=", "-p", String(pid)], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
11495
11795
|
return state.startsWith("Z");
|
|
11496
11796
|
} catch {
|
|
11497
11797
|
return true;
|
|
@@ -11590,7 +11890,7 @@ child.on('close', (code, signal) => {
|
|
|
11590
11890
|
jobsDir;
|
|
11591
11891
|
constructor(dbPath = defaultJobDbPath()) {
|
|
11592
11892
|
mkdirSync5(dirname11(dbPath), { recursive: true, mode: 448 });
|
|
11593
|
-
this.jobsDir =
|
|
11893
|
+
this.jobsDir = join24(dirname11(dbPath), "jobs");
|
|
11594
11894
|
mkdirSync5(this.jobsDir, { recursive: true, mode: 448 });
|
|
11595
11895
|
this.db = new Database(dbPath);
|
|
11596
11896
|
this.db.pragma("journal_mode = WAL");
|
|
@@ -11641,13 +11941,13 @@ child.on('close', (code, signal) => {
|
|
|
11641
11941
|
if (existing) return toJobRecord(existing);
|
|
11642
11942
|
}
|
|
11643
11943
|
const id = randomUUID4();
|
|
11644
|
-
const jobDir =
|
|
11944
|
+
const jobDir = join24(this.jobsDir, id);
|
|
11645
11945
|
mkdirSync5(jobDir, { recursive: true, mode: 448 });
|
|
11646
11946
|
const paths = {
|
|
11647
|
-
stdoutPath:
|
|
11648
|
-
stderrPath:
|
|
11649
|
-
exitPath:
|
|
11650
|
-
pidPath:
|
|
11947
|
+
stdoutPath: join24(jobDir, "stdout.log"),
|
|
11948
|
+
stderrPath: join24(jobDir, "stderr.log"),
|
|
11949
|
+
exitPath: join24(jobDir, "exit.json"),
|
|
11950
|
+
pidPath: join24(jobDir, "pid")
|
|
11651
11951
|
};
|
|
11652
11952
|
const now2 = Date.now();
|
|
11653
11953
|
try {
|
|
@@ -11671,7 +11971,7 @@ child.on('close', (code, signal) => {
|
|
|
11671
11971
|
timeoutMs: options.timeoutMs ?? null,
|
|
11672
11972
|
...paths
|
|
11673
11973
|
});
|
|
11674
|
-
const child =
|
|
11974
|
+
const child = spawn4(process.execPath, ["--input-type=module", "-e", JOB_WRAPPER, spec], {
|
|
11675
11975
|
cwd: options.cwd,
|
|
11676
11976
|
detached: true,
|
|
11677
11977
|
stdio: "ignore",
|
|
@@ -11928,10 +12228,10 @@ import Database2 from "better-sqlite3";
|
|
|
11928
12228
|
import { createHash as createHash2, randomUUID as randomUUID5 } from "crypto";
|
|
11929
12229
|
import { chmodSync, mkdirSync as mkdirSync6 } from "fs";
|
|
11930
12230
|
import { homedir as homedir14 } from "os";
|
|
11931
|
-
import { dirname as dirname12, join as
|
|
12231
|
+
import { dirname as dirname12, join as join25 } from "path";
|
|
11932
12232
|
function defaultRunsDbPath() {
|
|
11933
|
-
const root = process.env.XDG_STATE_HOME ||
|
|
11934
|
-
return process.env.AUTOPILOT_RUNS_DB ||
|
|
12233
|
+
const root = process.env.XDG_STATE_HOME || join25(homedir14(), ".local", "state");
|
|
12234
|
+
return process.env.AUTOPILOT_RUNS_DB || join25(root, "autopilot", "runs.db");
|
|
11935
12235
|
}
|
|
11936
12236
|
function validateOptionalPositiveInteger(name, value, minimum = 1) {
|
|
11937
12237
|
if (value !== null && (!Number.isSafeInteger(value) || value < minimum)) {
|
|
@@ -12541,8 +12841,8 @@ var init_wait_for = __esm({
|
|
|
12541
12841
|
});
|
|
12542
12842
|
|
|
12543
12843
|
// src/tools/executor.ts
|
|
12544
|
-
import { realpath as
|
|
12545
|
-
import { isAbsolute as
|
|
12844
|
+
import { realpath as realpath3 } from "fs/promises";
|
|
12845
|
+
import { isAbsolute as isAbsolute3, relative as relative4, resolve as resolve5, sep as sep3 } from "path";
|
|
12546
12846
|
function getWorkerTools(profile) {
|
|
12547
12847
|
return profile === "research" ? ALL_TOOLS.filter((tool) => RESEARCH_WORKER_TOOL_NAMES.has(tool.name) && tool.isReadOnly === true).map(restrictResearchTool) : ALL_TOOLS;
|
|
12548
12848
|
}
|
|
@@ -12563,28 +12863,28 @@ function restrictResearchTool(tool) {
|
|
|
12563
12863
|
}
|
|
12564
12864
|
async function assertResearchPath(pathValue, cwd) {
|
|
12565
12865
|
if (typeof pathValue !== "string" || !pathValue) throw new Error("Research worker paths must be non-empty strings.");
|
|
12566
|
-
const root = await
|
|
12567
|
-
const candidate =
|
|
12866
|
+
const root = await realpath3(cwd);
|
|
12867
|
+
const candidate = resolve5(root, pathValue);
|
|
12568
12868
|
assertInsideResearchRoot(candidate, root);
|
|
12569
12869
|
assertNoSensitivePath(candidate, root);
|
|
12570
|
-
const actual = await
|
|
12870
|
+
const actual = await realpath3(candidate);
|
|
12571
12871
|
assertInsideResearchRoot(actual, root);
|
|
12572
12872
|
assertNoSensitivePath(actual, root);
|
|
12573
12873
|
}
|
|
12574
12874
|
function assertInsideResearchRoot(path, root) {
|
|
12575
|
-
const rel =
|
|
12576
|
-
if (rel === ".." || rel.startsWith(`..${
|
|
12875
|
+
const rel = relative4(root, path);
|
|
12876
|
+
if (rel === ".." || rel.startsWith(`..${sep3}`) || isAbsolute3(rel)) {
|
|
12577
12877
|
throw new Error("Research workers may only inspect paths inside their cloned repository.");
|
|
12578
12878
|
}
|
|
12579
12879
|
}
|
|
12580
12880
|
function assertNoSensitivePath(path, root) {
|
|
12581
|
-
const parts =
|
|
12881
|
+
const parts = relative4(root, path).split(sep3).filter(Boolean).map((part) => part.toLowerCase());
|
|
12582
12882
|
if (parts.some((part) => part === ".env" || part.startsWith(".env.") || SENSITIVE_RESEARCH_PATHS.has(part))) {
|
|
12583
12883
|
throw new Error("Research worker access to environment, credential, and VCS metadata paths is blocked.");
|
|
12584
12884
|
}
|
|
12585
12885
|
}
|
|
12586
12886
|
function assertSafePattern(value) {
|
|
12587
|
-
if (typeof value !== "string" || !value ||
|
|
12887
|
+
if (typeof value !== "string" || !value || isAbsolute3(value)) {
|
|
12588
12888
|
throw new Error("Research worker glob patterns must be relative to the repository.");
|
|
12589
12889
|
}
|
|
12590
12890
|
const parts = value.replaceAll("\\\\", "/").split("/");
|
|
@@ -12637,9 +12937,6 @@ function normalizeToolOutput(result2) {
|
|
|
12637
12937
|
}
|
|
12638
12938
|
return result2;
|
|
12639
12939
|
}
|
|
12640
|
-
function truncateForError(s) {
|
|
12641
|
-
return s.length <= 200 ? s : `${s.slice(0, 200)}... [${s.length - 200} more chars]`;
|
|
12642
|
-
}
|
|
12643
12940
|
var ALL_TOOLS, RESEARCH_WORKER_TOOL_NAMES, SENSITIVE_RESEARCH_PATHS, HOOK_RESULT_CONTENT_CAP_BYTES, ToolExecutor, TRACE_ARGS_INLINE_MAX, ToolTrace;
|
|
12644
12941
|
var init_executor = __esm({
|
|
12645
12942
|
"src/tools/executor.ts"() {
|
|
@@ -12658,6 +12955,7 @@ var init_executor = __esm({
|
|
|
12658
12955
|
init_github();
|
|
12659
12956
|
init_changelog_image();
|
|
12660
12957
|
init_browser();
|
|
12958
|
+
init_html_artifact();
|
|
12661
12959
|
init_tasks();
|
|
12662
12960
|
init_memory();
|
|
12663
12961
|
init_subagent();
|
|
@@ -12685,6 +12983,7 @@ var init_executor = __esm({
|
|
|
12685
12983
|
githubCreatePrTool,
|
|
12686
12984
|
{ ...changelogImageTool, isReadOnly: true },
|
|
12687
12985
|
{ ...browserFetchTool, isReadOnly: true },
|
|
12986
|
+
htmlArtifactTool,
|
|
12688
12987
|
tasksSetTool,
|
|
12689
12988
|
memoryRememberTool,
|
|
12690
12989
|
{ ...memoryRecallTool, isReadOnly: true },
|
|
@@ -12783,17 +13082,23 @@ var init_executor = __esm({
|
|
|
12783
13082
|
}
|
|
12784
13083
|
let args;
|
|
12785
13084
|
try {
|
|
12786
|
-
|
|
13085
|
+
if (!call.arguments.trim()) throw new SyntaxError("tool arguments were empty");
|
|
13086
|
+
const parsed = JSON.parse(call.arguments);
|
|
13087
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
13088
|
+
throw new SyntaxError("tool arguments must be a JSON object");
|
|
13089
|
+
}
|
|
13090
|
+
args = parsed;
|
|
12787
13091
|
} catch (e) {
|
|
12788
13092
|
tr?.call(null, tool.needsPermission);
|
|
13093
|
+
const artifactSuggestion = call.name === "create_artifact" ? "Use write to save the complete HTML document as a workspace .html file, then call create_artifact with its title and sourcePath." : "Retry with valid JSON object arguments for this tool.";
|
|
12789
13094
|
return {
|
|
12790
13095
|
tool_call_id: call.id,
|
|
12791
13096
|
name: call.name,
|
|
12792
|
-
content: `Error: invalid JSON arguments for ${call.name}: ${e.message}.
|
|
13097
|
+
content: `Error: invalid JSON arguments for ${call.name}: ${e.message}. No tool action was performed (${Buffer.byteLength(call.arguments, "utf8")} argument bytes).`,
|
|
12793
13098
|
ok: false,
|
|
12794
13099
|
errorCode: "invalid_args",
|
|
12795
|
-
recoverable:
|
|
12796
|
-
suggestion:
|
|
13100
|
+
recoverable: true,
|
|
13101
|
+
suggestion: artifactSuggestion
|
|
12797
13102
|
};
|
|
12798
13103
|
}
|
|
12799
13104
|
tr?.call(args, tool.needsPermission);
|
|
@@ -13110,12 +13415,12 @@ __export(sessions_exports, {
|
|
|
13110
13415
|
saveSession: () => saveSession,
|
|
13111
13416
|
sessionsDir: () => sessionsDir
|
|
13112
13417
|
});
|
|
13113
|
-
import { readFile as
|
|
13418
|
+
import { readFile as readFile14, writeFile as writeFile12, mkdir as mkdir12, readdir as readdir5, stat as stat6 } from "fs/promises";
|
|
13114
13419
|
import { homedir as homedir15 } from "os";
|
|
13115
|
-
import { join as
|
|
13420
|
+
import { join as join26 } from "path";
|
|
13116
13421
|
function sessionsDir() {
|
|
13117
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
13118
|
-
return
|
|
13422
|
+
const xdg = process.env.XDG_DATA_HOME || join26(homedir15(), ".local", "share");
|
|
13423
|
+
return join26(xdg, "kimiflare", "sessions");
|
|
13119
13424
|
}
|
|
13120
13425
|
function sanitize(text) {
|
|
13121
13426
|
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
|
|
@@ -13134,9 +13439,9 @@ function makeSessionId(firstPrompt) {
|
|
|
13134
13439
|
}
|
|
13135
13440
|
async function saveSession(file) {
|
|
13136
13441
|
const dir = sessionsDir();
|
|
13137
|
-
await
|
|
13138
|
-
const path =
|
|
13139
|
-
await
|
|
13442
|
+
await mkdir12(dir, { recursive: true });
|
|
13443
|
+
const path = join26(dir, `${file.id}.json`);
|
|
13444
|
+
await writeFile12(path, JSON.stringify(file, null, 2), "utf8");
|
|
13140
13445
|
return path;
|
|
13141
13446
|
}
|
|
13142
13447
|
async function pruneSessions() {
|
|
@@ -13148,16 +13453,16 @@ async function listSessions(limit = 30, cwd) {
|
|
|
13148
13453
|
const dir = sessionsDir();
|
|
13149
13454
|
let entries;
|
|
13150
13455
|
try {
|
|
13151
|
-
entries = await
|
|
13456
|
+
entries = await readdir5(dir);
|
|
13152
13457
|
} catch {
|
|
13153
13458
|
return [];
|
|
13154
13459
|
}
|
|
13155
13460
|
const summaries = [];
|
|
13156
13461
|
for (const name of entries) {
|
|
13157
13462
|
if (!name.endsWith(".json")) continue;
|
|
13158
|
-
const path =
|
|
13463
|
+
const path = join26(dir, name);
|
|
13159
13464
|
try {
|
|
13160
|
-
const [s, raw] = await Promise.all([
|
|
13465
|
+
const [s, raw] = await Promise.all([stat6(path), readFile14(path, "utf8")]);
|
|
13161
13466
|
const parsed = JSON.parse(raw);
|
|
13162
13467
|
if (cwd && parsed.cwd !== cwd) continue;
|
|
13163
13468
|
const firstUser = parsed.messages.find((m) => m.role === "user");
|
|
@@ -13179,7 +13484,7 @@ async function listSessions(limit = 30, cwd) {
|
|
|
13179
13484
|
return summaries.slice(0, limit);
|
|
13180
13485
|
}
|
|
13181
13486
|
async function loadSession(filePath) {
|
|
13182
|
-
const raw = await
|
|
13487
|
+
const raw = await readFile14(filePath, "utf8");
|
|
13183
13488
|
const file = JSON.parse(raw);
|
|
13184
13489
|
if (Array.isArray(file.messages)) repairDanglingToolCalls(file.messages);
|
|
13185
13490
|
return file;
|
|
@@ -13229,10 +13534,10 @@ var init_sessions = __esm({
|
|
|
13229
13534
|
});
|
|
13230
13535
|
|
|
13231
13536
|
// src/util/image.ts
|
|
13232
|
-
import { readFile as
|
|
13537
|
+
import { readFile as readFile15 } from "fs/promises";
|
|
13233
13538
|
import { basename as basename2 } from "path";
|
|
13234
13539
|
async function encodeImageFile(filePath) {
|
|
13235
|
-
const buf = await
|
|
13540
|
+
const buf = await readFile15(filePath);
|
|
13236
13541
|
if (buf.byteLength > MAX_IMAGE_BYTES) {
|
|
13237
13542
|
throw new Error(
|
|
13238
13543
|
`image too large (${(buf.byteLength / 1024 / 1024).toFixed(1)} MB); max is ${MAX_IMAGE_BYTES / 1024 / 1024} MB`
|
|
@@ -13268,7 +13573,7 @@ var init_image = __esm({
|
|
|
13268
13573
|
});
|
|
13269
13574
|
|
|
13270
13575
|
// src/permissions-evaluator.ts
|
|
13271
|
-
import { resolve as
|
|
13576
|
+
import { resolve as resolve6, relative as relative5 } from "path";
|
|
13272
13577
|
import { homedir as homedir16 } from "os";
|
|
13273
13578
|
function evaluatePermissionRules(req, rules) {
|
|
13274
13579
|
const toolRules = rules[req.tool];
|
|
@@ -13285,7 +13590,7 @@ function evaluatePermissionRules(req, rules) {
|
|
|
13285
13590
|
}
|
|
13286
13591
|
function expandHome(path) {
|
|
13287
13592
|
if (path.startsWith("~/")) {
|
|
13288
|
-
return
|
|
13593
|
+
return resolve6(homedir16(), path.slice(2));
|
|
13289
13594
|
}
|
|
13290
13595
|
return path;
|
|
13291
13596
|
}
|
|
@@ -13296,7 +13601,7 @@ function extractTarget(tool, args, cwd) {
|
|
|
13296
13601
|
case "read":
|
|
13297
13602
|
case "glob":
|
|
13298
13603
|
case "grep":
|
|
13299
|
-
return typeof args.path === "string" ?
|
|
13604
|
+
return typeof args.path === "string" ? resolve6(cwd, expandHome(args.path)) : null;
|
|
13300
13605
|
case "bash":
|
|
13301
13606
|
return typeof args.command === "string" ? args.command : null;
|
|
13302
13607
|
case "browser_fetch":
|
|
@@ -13305,13 +13610,13 @@ function extractTarget(tool, args, cwd) {
|
|
|
13305
13610
|
case "search_web":
|
|
13306
13611
|
return typeof args.query === "string" ? args.query : null;
|
|
13307
13612
|
default:
|
|
13308
|
-
return (typeof args.path === "string" ?
|
|
13613
|
+
return (typeof args.path === "string" ? resolve6(cwd, expandHome(args.path)) : null) ?? (typeof args.url === "string" ? args.url : null) ?? (typeof args.command === "string" ? args.command : null);
|
|
13309
13614
|
}
|
|
13310
13615
|
}
|
|
13311
13616
|
function matchPattern(target, pattern, cwd) {
|
|
13312
13617
|
let expandedPattern = pattern;
|
|
13313
13618
|
if (pattern.startsWith("~/")) {
|
|
13314
|
-
expandedPattern =
|
|
13619
|
+
expandedPattern = resolve6(homedir16(), pattern.slice(2));
|
|
13315
13620
|
}
|
|
13316
13621
|
if (target.startsWith(expandedPattern)) {
|
|
13317
13622
|
return true;
|
|
@@ -13321,7 +13626,7 @@ function matchPattern(target, pattern, cwd) {
|
|
|
13321
13626
|
return true;
|
|
13322
13627
|
}
|
|
13323
13628
|
try {
|
|
13324
|
-
const relTarget =
|
|
13629
|
+
const relTarget = relative5(cwd, target);
|
|
13325
13630
|
if (regex.test(relTarget)) {
|
|
13326
13631
|
return true;
|
|
13327
13632
|
}
|
|
@@ -13394,17 +13699,17 @@ __export(retention_exports, {
|
|
|
13394
13699
|
listTraceSessions: () => listTraceSessions,
|
|
13395
13700
|
pruneTraces: () => pruneTraces
|
|
13396
13701
|
});
|
|
13397
|
-
import { readdir as
|
|
13398
|
-
import { join as
|
|
13702
|
+
import { readdir as readdir6, rm as rm4, stat as stat7 } from "fs/promises";
|
|
13703
|
+
import { join as join27 } from "path";
|
|
13399
13704
|
async function dirSize(path) {
|
|
13400
13705
|
let total = 0;
|
|
13401
|
-
const entries = await
|
|
13706
|
+
const entries = await readdir6(path, { withFileTypes: true });
|
|
13402
13707
|
for (const entry of entries) {
|
|
13403
|
-
const p =
|
|
13708
|
+
const p = join27(path, entry.name);
|
|
13404
13709
|
if (entry.isDirectory()) total += await dirSize(p);
|
|
13405
13710
|
else if (entry.isFile()) {
|
|
13406
13711
|
try {
|
|
13407
|
-
total += (await
|
|
13712
|
+
total += (await stat7(p)).size;
|
|
13408
13713
|
} catch {
|
|
13409
13714
|
}
|
|
13410
13715
|
}
|
|
@@ -13415,19 +13720,19 @@ async function listTraceSessions(root) {
|
|
|
13415
13720
|
const base = traceRoot(root);
|
|
13416
13721
|
let names;
|
|
13417
13722
|
try {
|
|
13418
|
-
names = await
|
|
13723
|
+
names = await readdir6(base);
|
|
13419
13724
|
} catch {
|
|
13420
13725
|
return [];
|
|
13421
13726
|
}
|
|
13422
13727
|
const sessions = [];
|
|
13423
13728
|
for (const name of names) {
|
|
13424
|
-
const path =
|
|
13729
|
+
const path = join27(base, name);
|
|
13425
13730
|
try {
|
|
13426
|
-
const s = await
|
|
13731
|
+
const s = await stat7(path);
|
|
13427
13732
|
if (!s.isDirectory()) continue;
|
|
13428
13733
|
let mtime = s.mtime;
|
|
13429
13734
|
try {
|
|
13430
|
-
mtime = (await
|
|
13735
|
+
mtime = (await stat7(join27(path, TRACE_FILE_NAME))).mtime;
|
|
13431
13736
|
} catch {
|
|
13432
13737
|
}
|
|
13433
13738
|
sessions.push({ sessionId: name, path, mtime, bytes: await dirSize(path) });
|
|
@@ -13452,7 +13757,7 @@ async function pruneTraces(opts2 = {}) {
|
|
|
13452
13757
|
}
|
|
13453
13758
|
const remove = async (s) => {
|
|
13454
13759
|
try {
|
|
13455
|
-
await
|
|
13760
|
+
await rm4(s.path, { recursive: true, force: true });
|
|
13456
13761
|
removed.push(s.sessionId);
|
|
13457
13762
|
} catch {
|
|
13458
13763
|
}
|
|
@@ -13481,7 +13786,7 @@ var init_retention = __esm({
|
|
|
13481
13786
|
// src/trace/session-start.ts
|
|
13482
13787
|
import { execFile as execFile6 } from "child_process";
|
|
13483
13788
|
import { existsSync as existsSync5 } from "fs";
|
|
13484
|
-
import { dirname as dirname13, join as
|
|
13789
|
+
import { dirname as dirname13, join as join28 } from "path";
|
|
13485
13790
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
13486
13791
|
import { promisify as promisify6 } from "util";
|
|
13487
13792
|
async function git2(args, cwd) {
|
|
@@ -13495,8 +13800,8 @@ async function git2(args, cwd) {
|
|
|
13495
13800
|
}
|
|
13496
13801
|
function harnessCheckoutDir() {
|
|
13497
13802
|
const here = dirname13(fileURLToPath4(import.meta.url));
|
|
13498
|
-
for (const candidate of [
|
|
13499
|
-
if (existsSync5(
|
|
13803
|
+
for (const candidate of [join28(here, "..", ".."), join28(here, "..")]) {
|
|
13804
|
+
if (existsSync5(join28(candidate, "package.json")) && existsSync5(join28(candidate, ".git"))) return candidate;
|
|
13500
13805
|
}
|
|
13501
13806
|
return null;
|
|
13502
13807
|
}
|
|
@@ -13634,14 +13939,14 @@ var init_types2 = __esm({
|
|
|
13634
13939
|
// src/hooks/settings.ts
|
|
13635
13940
|
import { existsSync as existsSync6, readFileSync as readFileSync5, mkdirSync as mkdirSync7, writeFileSync as writeFileSync4 } from "fs";
|
|
13636
13941
|
import { homedir as homedir17 } from "os";
|
|
13637
|
-
import { join as
|
|
13942
|
+
import { join as join29, dirname as dirname14 } from "path";
|
|
13638
13943
|
import { createHash as createHash3 } from "crypto";
|
|
13639
13944
|
function globalSettingsPath() {
|
|
13640
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
13641
|
-
return
|
|
13945
|
+
const xdg = process.env.XDG_CONFIG_HOME || join29(homedir17(), ".config");
|
|
13946
|
+
return join29(xdg, "kimiflare", "settings.json");
|
|
13642
13947
|
}
|
|
13643
13948
|
function projectSettingsPath(cwd) {
|
|
13644
|
-
return
|
|
13949
|
+
return join29(cwd, ".kimiflare", "settings.json");
|
|
13645
13950
|
}
|
|
13646
13951
|
function readSettingsFile(path) {
|
|
13647
13952
|
if (!existsSync6(path)) return null;
|
|
@@ -13759,7 +14064,7 @@ var init_settings = __esm({
|
|
|
13759
14064
|
});
|
|
13760
14065
|
|
|
13761
14066
|
// src/hooks/runner.ts
|
|
13762
|
-
import { spawn as
|
|
14067
|
+
import { spawn as spawn5 } from "child_process";
|
|
13763
14068
|
function isVetoEvent(event) {
|
|
13764
14069
|
return event === "PreToolUse" || event === "UserPromptSubmit";
|
|
13765
14070
|
}
|
|
@@ -13876,8 +14181,8 @@ var init_runner = __esm({
|
|
|
13876
14181
|
init_logger();
|
|
13877
14182
|
DEFAULT_TIMEOUT_MS = 3e4;
|
|
13878
14183
|
STREAM_CAP_BYTES = 4 * 1024;
|
|
13879
|
-
defaultSpawn = (command, payloadJson, env2, cwd, timeoutMs, signal) => new Promise((
|
|
13880
|
-
const child =
|
|
14184
|
+
defaultSpawn = (command, payloadJson, env2, cwd, timeoutMs, signal) => new Promise((resolve20) => {
|
|
14185
|
+
const child = spawn5(command, {
|
|
13881
14186
|
shell: true,
|
|
13882
14187
|
cwd,
|
|
13883
14188
|
env: env2,
|
|
@@ -13891,7 +14196,7 @@ var init_runner = __esm({
|
|
|
13891
14196
|
settled = true;
|
|
13892
14197
|
clearTimeout(timer3);
|
|
13893
14198
|
signal?.removeEventListener("abort", onAbort);
|
|
13894
|
-
|
|
14199
|
+
resolve20({ exitCode, stdout, stderr, timedOut });
|
|
13895
14200
|
};
|
|
13896
14201
|
const onAbort = () => {
|
|
13897
14202
|
child.kill("SIGTERM");
|
|
@@ -13964,11 +14269,11 @@ var init_manager2 = __esm({
|
|
|
13964
14269
|
});
|
|
13965
14270
|
|
|
13966
14271
|
// src/eval/config.ts
|
|
13967
|
-
import { readFile as
|
|
13968
|
-
import { basename as basename4, resolve as
|
|
14272
|
+
import { readFile as readFile17 } from "fs/promises";
|
|
14273
|
+
import { basename as basename4, resolve as resolve8 } from "path";
|
|
13969
14274
|
async function loadEvalConfig(file) {
|
|
13970
|
-
const path =
|
|
13971
|
-
const raw = JSON.parse(await
|
|
14275
|
+
const path = resolve8(file);
|
|
14276
|
+
const raw = JSON.parse(await readFile17(path, "utf8"));
|
|
13972
14277
|
if (!raw || typeof raw !== "object") throw new Error(`${file}: config must be a JSON object`);
|
|
13973
14278
|
const config2 = raw.config ?? {};
|
|
13974
14279
|
if (typeof config2 !== "object" || Array.isArray(config2)) throw new Error(`${file}: "config" must be an object`);
|
|
@@ -13988,8 +14293,8 @@ var init_config2 = __esm({
|
|
|
13988
14293
|
});
|
|
13989
14294
|
|
|
13990
14295
|
// src/eval/tasks.ts
|
|
13991
|
-
import { readdir as
|
|
13992
|
-
import { basename as basename5, join as
|
|
14296
|
+
import { readdir as readdir7, readFile as readFile18, stat as stat8 } from "fs/promises";
|
|
14297
|
+
import { basename as basename5, join as join30, resolve as resolve9 } from "path";
|
|
13993
14298
|
function isNonEmptyString(v) {
|
|
13994
14299
|
return typeof v === "string" && v.trim().length > 0;
|
|
13995
14300
|
}
|
|
@@ -14017,22 +14322,22 @@ function matchesTaskFilter(id, filter) {
|
|
|
14017
14322
|
return filter.split(",").map((g) => g.trim()).filter(Boolean).some((g) => matchGlob(id, g));
|
|
14018
14323
|
}
|
|
14019
14324
|
async function loadTasks(dir, filter) {
|
|
14020
|
-
const root =
|
|
14021
|
-
const names = (await
|
|
14325
|
+
const root = resolve9(dir);
|
|
14326
|
+
const names = (await readdir7(root)).filter((n) => n.endsWith(".json")).sort();
|
|
14022
14327
|
const tasks = [];
|
|
14023
14328
|
const seen = /* @__PURE__ */ new Set();
|
|
14024
14329
|
for (const name of names) {
|
|
14025
|
-
const file =
|
|
14026
|
-
const task = validateTask(JSON.parse(await
|
|
14330
|
+
const file = join30(root, name);
|
|
14331
|
+
const task = validateTask(JSON.parse(await readFile18(file, "utf8")), name);
|
|
14027
14332
|
if (task.id !== basename5(name, ".json")) throw new Error(`${name}: "id" (${task.id}) must match the file name`);
|
|
14028
14333
|
if (seen.has(task.id)) throw new Error(`duplicate task id ${task.id}`);
|
|
14029
14334
|
seen.add(task.id);
|
|
14030
14335
|
if (!matchesTaskFilter(task.id, filter)) continue;
|
|
14031
14336
|
const resolvedFiles = {};
|
|
14032
14337
|
for (const [dest, src] of Object.entries(task.files ?? {})) {
|
|
14033
|
-
const abs =
|
|
14338
|
+
const abs = resolve9(root, src);
|
|
14034
14339
|
if (!abs.startsWith(root)) throw new Error(`${name}: files["${dest}"] escapes the task directory`);
|
|
14035
|
-
await
|
|
14340
|
+
await stat8(abs).catch(() => {
|
|
14036
14341
|
throw new Error(`${name}: files["${dest}"] -> ${src} does not exist`);
|
|
14037
14342
|
});
|
|
14038
14343
|
resolvedFiles[dest] = abs;
|
|
@@ -14053,15 +14358,15 @@ var init_tasks2 = __esm({
|
|
|
14053
14358
|
// src/eval/workspace.ts
|
|
14054
14359
|
import { execFile as execFile7 } from "child_process";
|
|
14055
14360
|
import { createHash as createHash4 } from "crypto";
|
|
14056
|
-
import { mkdir as
|
|
14057
|
-
import { isAbsolute as
|
|
14361
|
+
import { mkdir as mkdir13, rm as rm5, stat as stat9 } from "fs/promises";
|
|
14362
|
+
import { isAbsolute as isAbsolute4, join as join31, resolve as resolve10 } from "path";
|
|
14058
14363
|
import { promisify as promisify7 } from "util";
|
|
14059
14364
|
async function git3(args, cwd, timeoutMs = 6e5) {
|
|
14060
14365
|
const { stdout } = await execFileAsync5("git", args, { cwd, timeout: timeoutMs, maxBuffer: 64 * 1024 * 1024 });
|
|
14061
14366
|
return stdout.trim();
|
|
14062
14367
|
}
|
|
14063
14368
|
function isLocalRepo(repo) {
|
|
14064
|
-
return
|
|
14369
|
+
return isAbsolute4(repo) || repo.startsWith(".") || repo.startsWith("~");
|
|
14065
14370
|
}
|
|
14066
14371
|
function prepareSourceRepo(repo, cacheDir) {
|
|
14067
14372
|
const key = `${cacheDir}\0${repo}`;
|
|
@@ -14074,14 +14379,14 @@ function prepareSourceRepo(repo, cacheDir) {
|
|
|
14074
14379
|
}
|
|
14075
14380
|
async function prepareSourceRepoUncached(repo, cacheDir) {
|
|
14076
14381
|
if (isLocalRepo(repo)) {
|
|
14077
|
-
const path =
|
|
14382
|
+
const path = resolve10(repo.replace(/^~/, process.env.HOME ?? ""));
|
|
14078
14383
|
await git3(["rev-parse", "--git-dir"], path);
|
|
14079
14384
|
return path;
|
|
14080
14385
|
}
|
|
14081
14386
|
const slug = `${repo.replace(/[^A-Za-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(-60)}-${createHash4("sha1").update(repo).digest("hex").slice(0, 8)}`;
|
|
14082
|
-
const dir =
|
|
14083
|
-
await
|
|
14084
|
-
const exists = await
|
|
14387
|
+
const dir = join31(cacheDir, slug);
|
|
14388
|
+
await mkdir13(cacheDir, { recursive: true });
|
|
14389
|
+
const exists = await stat9(join31(dir, ".git")).then(() => true).catch(() => false);
|
|
14085
14390
|
if (!exists) {
|
|
14086
14391
|
await git3(["clone", "--quiet", "--no-checkout", repo, dir], cacheDir);
|
|
14087
14392
|
} else {
|
|
@@ -14100,13 +14405,13 @@ async function ensureCommit(sourceRepo, commit) {
|
|
|
14100
14405
|
async function createWorktree(sourceRepo, commit, path) {
|
|
14101
14406
|
await ensureCommit(sourceRepo, commit);
|
|
14102
14407
|
await removeWorktree({ sourceRepo, path }).catch(() => void 0);
|
|
14103
|
-
await
|
|
14408
|
+
await mkdir13(join31(path, ".."), { recursive: true });
|
|
14104
14409
|
await git3(["worktree", "add", "--quiet", "--detach", path, commit], sourceRepo);
|
|
14105
14410
|
return { sourceRepo, path };
|
|
14106
14411
|
}
|
|
14107
14412
|
async function removeWorktree(wt) {
|
|
14108
14413
|
await git3(["worktree", "remove", "--force", wt.path], wt.sourceRepo).catch(() => void 0);
|
|
14109
|
-
await
|
|
14414
|
+
await rm5(wt.path, { recursive: true, force: true });
|
|
14110
14415
|
await git3(["worktree", "prune"], wt.sourceRepo).catch(() => void 0);
|
|
14111
14416
|
}
|
|
14112
14417
|
var execFileAsync5, preparing;
|
|
@@ -15201,7 +15506,7 @@ Context: This memory was explicitly provided by the user during a conversation.`
|
|
|
15201
15506
|
});
|
|
15202
15507
|
|
|
15203
15508
|
// src/lsp/connection.ts
|
|
15204
|
-
import { spawn as
|
|
15509
|
+
import { spawn as spawn6 } from "child_process";
|
|
15205
15510
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
15206
15511
|
var LspConnection;
|
|
15207
15512
|
var init_connection = __esm({
|
|
@@ -15223,7 +15528,7 @@ var init_connection = __esm({
|
|
|
15223
15528
|
if (this.child) {
|
|
15224
15529
|
throw new Error("LSP connection already started");
|
|
15225
15530
|
}
|
|
15226
|
-
return new Promise((
|
|
15531
|
+
return new Promise((resolve20, reject) => {
|
|
15227
15532
|
const abortController = new AbortController();
|
|
15228
15533
|
const spawnTimer = setTimeout(() => {
|
|
15229
15534
|
abortController.abort();
|
|
@@ -15231,7 +15536,7 @@ var init_connection = __esm({
|
|
|
15231
15536
|
reject(new Error(`LSP server spawn timed out after ${spawnTimeoutMs}ms`));
|
|
15232
15537
|
}, spawnTimeoutMs);
|
|
15233
15538
|
try {
|
|
15234
|
-
const child =
|
|
15539
|
+
const child = spawn6(command[0], command.slice(1), {
|
|
15235
15540
|
env: { ...process.env, ...env2 },
|
|
15236
15541
|
stdio: ["pipe", "pipe", "pipe"]
|
|
15237
15542
|
});
|
|
@@ -15262,7 +15567,7 @@ var init_connection = __esm({
|
|
|
15262
15567
|
if (child.pid) {
|
|
15263
15568
|
clearTimeout(spawnTimer);
|
|
15264
15569
|
this.child = child;
|
|
15265
|
-
|
|
15570
|
+
resolve20();
|
|
15266
15571
|
}
|
|
15267
15572
|
});
|
|
15268
15573
|
} catch (err) {
|
|
@@ -15277,12 +15582,12 @@ var init_connection = __esm({
|
|
|
15277
15582
|
}
|
|
15278
15583
|
const id = this.nextId++;
|
|
15279
15584
|
const msg = { jsonrpc: "2.0", id, method, params };
|
|
15280
|
-
return new Promise((
|
|
15585
|
+
return new Promise((resolve20, reject) => {
|
|
15281
15586
|
const timer3 = setTimeout(() => {
|
|
15282
15587
|
this.pending.delete(id);
|
|
15283
15588
|
reject(toolTimeoutError(`LSP request '${method}'`, this.requestTimeoutMs));
|
|
15284
15589
|
}, this.requestTimeoutMs);
|
|
15285
|
-
const pending = { resolve:
|
|
15590
|
+
const pending = { resolve: resolve20, reject, signal, timer: timer3 };
|
|
15286
15591
|
this.pending.set(id, pending);
|
|
15287
15592
|
if (signal) {
|
|
15288
15593
|
const onAbort = () => {
|
|
@@ -15375,9 +15680,9 @@ var init_connection = __esm({
|
|
|
15375
15680
|
});
|
|
15376
15681
|
|
|
15377
15682
|
// src/lsp/protocol.ts
|
|
15378
|
-
import { pathToFileURL as
|
|
15683
|
+
import { pathToFileURL as pathToFileURL3, fileURLToPath as fileURLToPath5 } from "url";
|
|
15379
15684
|
function toUri(path) {
|
|
15380
|
-
return
|
|
15685
|
+
return pathToFileURL3(path).href;
|
|
15381
15686
|
}
|
|
15382
15687
|
function fromUri(uri) {
|
|
15383
15688
|
return fileURLToPath5(uri);
|
|
@@ -15846,10 +16151,10 @@ var init_manager4 = __esm({
|
|
|
15846
16151
|
});
|
|
15847
16152
|
|
|
15848
16153
|
// src/lsp/adapter.ts
|
|
15849
|
-
import { relative as
|
|
16154
|
+
import { relative as relative6 } from "path";
|
|
15850
16155
|
function formatLocation(loc, cwd) {
|
|
15851
16156
|
const path = fromUri(loc.uri);
|
|
15852
|
-
const rel =
|
|
16157
|
+
const rel = relative6(cwd, path) || path;
|
|
15853
16158
|
return `${rel}:${loc.range.start.line + 1}:${loc.range.start.character + 1}`;
|
|
15854
16159
|
}
|
|
15855
16160
|
function formatLocations(locs, cwd) {
|
|
@@ -15886,7 +16191,7 @@ function formatWorkspaceSymbols(symbols, cwd) {
|
|
|
15886
16191
|
if (!symbols || symbols.length === 0) return "No symbols found.";
|
|
15887
16192
|
return symbols.map((s) => {
|
|
15888
16193
|
const path = fromUri(s.location.uri);
|
|
15889
|
-
const rel =
|
|
16194
|
+
const rel = relative6(cwd, path) || path;
|
|
15890
16195
|
const container = s.containerName ? ` in ${s.containerName}` : "";
|
|
15891
16196
|
return `${s.name} (${symbolKindName(s.kind)})${container} \u2014 ${rel}:${s.location.range.start.line + 1}:${s.location.range.start.character + 1}`;
|
|
15892
16197
|
}).join("\n");
|
|
@@ -15906,7 +16211,7 @@ function formatWorkspaceEdit(edit, cwd) {
|
|
|
15906
16211
|
if (edit.changes) {
|
|
15907
16212
|
for (const [uri, edits] of Object.entries(edit.changes)) {
|
|
15908
16213
|
const path = fromUri(uri);
|
|
15909
|
-
const rel =
|
|
16214
|
+
const rel = relative6(cwd, path) || path;
|
|
15910
16215
|
lines.push(`File: ${rel}`);
|
|
15911
16216
|
for (const e of edits) {
|
|
15912
16217
|
lines.push(` ${e.range.start.line + 1}:${e.range.start.character + 1}-${e.range.end.line + 1}:${e.range.end.character + 1}: ${e.newText}`);
|
|
@@ -15931,7 +16236,7 @@ var init_adapter = __esm({
|
|
|
15931
16236
|
});
|
|
15932
16237
|
|
|
15933
16238
|
// src/tools/lsp.ts
|
|
15934
|
-
import { relative as
|
|
16239
|
+
import { relative as relative7 } from "path";
|
|
15935
16240
|
function makeOutput2(content) {
|
|
15936
16241
|
const bytes = Buffer.byteLength(content, "utf8");
|
|
15937
16242
|
return { content, rawBytes: bytes, reducedBytes: bytes };
|
|
@@ -15939,7 +16244,7 @@ function makeOutput2(content) {
|
|
|
15939
16244
|
function resolveLspPath(args, ctx) {
|
|
15940
16245
|
const raw = typeof args.path === "string" ? args.path : "";
|
|
15941
16246
|
const resolved = resolvePath(ctx.cwd, raw);
|
|
15942
|
-
const rel =
|
|
16247
|
+
const rel = relative7(ctx.cwd, resolved);
|
|
15943
16248
|
if (isPathOutside(rel)) {
|
|
15944
16249
|
throw new Error(`Path outside workspace: ${raw}`);
|
|
15945
16250
|
}
|
|
@@ -16205,12 +16510,12 @@ __export(openrouter_catalog_exports, {
|
|
|
16205
16510
|
loadOpenRouterCatalog: () => loadOpenRouterCatalog,
|
|
16206
16511
|
mapOpenRouterModel: () => mapOpenRouterModel
|
|
16207
16512
|
});
|
|
16208
|
-
import { readFile as
|
|
16513
|
+
import { readFile as readFile19, writeFile as writeFile13, mkdir as mkdir14 } from "fs/promises";
|
|
16209
16514
|
import { homedir as homedir18 } from "os";
|
|
16210
|
-
import { join as
|
|
16515
|
+
import { join as join33, dirname as dirname16 } from "path";
|
|
16211
16516
|
function catalogCachePath() {
|
|
16212
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
16213
|
-
return
|
|
16517
|
+
const xdg = process.env.XDG_CONFIG_HOME || join33(homedir18(), ".config");
|
|
16518
|
+
return join33(xdg, "kimiflare", "openrouter-models.json");
|
|
16214
16519
|
}
|
|
16215
16520
|
function perMtok(perToken) {
|
|
16216
16521
|
const n = Number(perToken);
|
|
@@ -16261,7 +16566,7 @@ async function fetchOpenRouterCatalog(fetchImpl2 = fetch) {
|
|
|
16261
16566
|
}
|
|
16262
16567
|
async function readCache3() {
|
|
16263
16568
|
try {
|
|
16264
|
-
const raw = await
|
|
16569
|
+
const raw = await readFile19(catalogCachePath(), "utf8");
|
|
16265
16570
|
const parsed = JSON.parse(raw);
|
|
16266
16571
|
return parsed.version === CACHE_VERSION ? parsed : null;
|
|
16267
16572
|
} catch {
|
|
@@ -16271,9 +16576,9 @@ async function readCache3() {
|
|
|
16271
16576
|
async function writeCache3(models) {
|
|
16272
16577
|
const path = catalogCachePath();
|
|
16273
16578
|
try {
|
|
16274
|
-
await
|
|
16579
|
+
await mkdir14(dirname16(path), { recursive: true });
|
|
16275
16580
|
const cache = { version: CACHE_VERSION, fetchedAt: (/* @__PURE__ */ new Date()).toISOString(), models };
|
|
16276
|
-
await
|
|
16581
|
+
await writeFile13(path, JSON.stringify(cache, null, 2), "utf8");
|
|
16277
16582
|
} catch {
|
|
16278
16583
|
}
|
|
16279
16584
|
}
|
|
@@ -16320,12 +16625,12 @@ __export(requesty_catalog_exports, {
|
|
|
16320
16625
|
loadRequestyCatalog: () => loadRequestyCatalog,
|
|
16321
16626
|
mapRequestyModel: () => mapRequestyModel
|
|
16322
16627
|
});
|
|
16323
|
-
import { readFile as
|
|
16628
|
+
import { readFile as readFile20, writeFile as writeFile14, mkdir as mkdir15 } from "fs/promises";
|
|
16324
16629
|
import { homedir as homedir19 } from "os";
|
|
16325
|
-
import { join as
|
|
16630
|
+
import { join as join34, dirname as dirname17 } from "path";
|
|
16326
16631
|
function catalogCachePath2() {
|
|
16327
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
16328
|
-
return
|
|
16632
|
+
const xdg = process.env.XDG_CONFIG_HOME || join34(homedir19(), ".config");
|
|
16633
|
+
return join34(xdg, "kimiflare", "requesty-models.json");
|
|
16329
16634
|
}
|
|
16330
16635
|
function isSafeModelId(id) {
|
|
16331
16636
|
return typeof id === "string" && id.length > 0 && !CONTROL_CHARS.test(id);
|
|
@@ -16381,7 +16686,7 @@ async function fetchRequestyCatalog(fetchImpl2 = fetch) {
|
|
|
16381
16686
|
}
|
|
16382
16687
|
async function readCache4() {
|
|
16383
16688
|
try {
|
|
16384
|
-
const raw = await
|
|
16689
|
+
const raw = await readFile20(catalogCachePath2(), "utf8");
|
|
16385
16690
|
const parsed = JSON.parse(raw);
|
|
16386
16691
|
if (parsed.version !== CACHE_VERSION2) return null;
|
|
16387
16692
|
return {
|
|
@@ -16396,9 +16701,9 @@ async function readCache4() {
|
|
|
16396
16701
|
async function writeCache4(catalog) {
|
|
16397
16702
|
const path = catalogCachePath2();
|
|
16398
16703
|
try {
|
|
16399
|
-
await
|
|
16704
|
+
await mkdir15(dirname17(path), { recursive: true });
|
|
16400
16705
|
const cache = { version: CACHE_VERSION2, fetchedAt: (/* @__PURE__ */ new Date()).toISOString(), ...catalog };
|
|
16401
|
-
await
|
|
16706
|
+
await writeFile14(path, JSON.stringify(cache, null, 2), "utf8");
|
|
16402
16707
|
} catch {
|
|
16403
16708
|
}
|
|
16404
16709
|
}
|
|
@@ -16491,15 +16796,15 @@ var session_exports = {};
|
|
|
16491
16796
|
__export(session_exports, {
|
|
16492
16797
|
createAgentSession: () => createAgentSession
|
|
16493
16798
|
});
|
|
16494
|
-
import { resolve as
|
|
16799
|
+
import { resolve as resolve11 } from "path";
|
|
16495
16800
|
import { homedir as homedir20 } from "os";
|
|
16496
|
-
import { join as
|
|
16801
|
+
import { join as join35 } from "path";
|
|
16497
16802
|
import { existsSync as existsSync7 } from "fs";
|
|
16498
16803
|
async function createAgentSession(opts2) {
|
|
16499
16804
|
const config2 = await resolveSdkConfig(opts2);
|
|
16500
16805
|
if (usesRequesty(llmAuthFromConfig(config2))) await ensureRequestyCatalog();
|
|
16501
16806
|
else if (!resolveCustomEndpoint(config2)) await ensureOpenRouterCatalog();
|
|
16502
|
-
const cwd =
|
|
16807
|
+
const cwd = resolve11(opts2.cwd ?? process.cwd());
|
|
16503
16808
|
const tools = opts2.tools ?? ALL_TOOLS;
|
|
16504
16809
|
let hooks;
|
|
16505
16810
|
if (opts2.enableHooks) {
|
|
@@ -16510,7 +16815,7 @@ async function createAgentSession(opts2) {
|
|
|
16510
16815
|
let memoryManager = null;
|
|
16511
16816
|
const memoryEnabled = opts2.memoryEnabled ?? config2.memoryEnabled ?? false;
|
|
16512
16817
|
if (memoryEnabled) {
|
|
16513
|
-
const dbPath = config2.memoryDbPath ??
|
|
16818
|
+
const dbPath = config2.memoryDbPath ?? join35(homedir20(), ".local", "share", "kimiflare", "memory.db");
|
|
16514
16819
|
memoryManager = new MemoryManager({
|
|
16515
16820
|
dbPath,
|
|
16516
16821
|
...llmAuthFromConfig(config2),
|
|
@@ -16540,7 +16845,7 @@ async function createAgentSession(opts2) {
|
|
|
16540
16845
|
}
|
|
16541
16846
|
let sessionFile;
|
|
16542
16847
|
if (opts2.sessionId) {
|
|
16543
|
-
const filePath =
|
|
16848
|
+
const filePath = join35(sessionsDir(), `${opts2.sessionId}.json`);
|
|
16544
16849
|
try {
|
|
16545
16850
|
sessionFile = await loadSession(filePath);
|
|
16546
16851
|
} catch {
|
|
@@ -16739,8 +17044,8 @@ var init_session = __esm({
|
|
|
16739
17044
|
const parts = [{ type: "text", text }];
|
|
16740
17045
|
for (const img of options.images) {
|
|
16741
17046
|
if ("path" in img) {
|
|
16742
|
-
const { readFile:
|
|
16743
|
-
const data = await
|
|
17047
|
+
const { readFile: readFile37 } = await import("fs/promises");
|
|
17048
|
+
const data = await readFile37(img.path, "base64");
|
|
16744
17049
|
const mimeType = img.path.endsWith(".png") ? "image/png" : img.path.endsWith(".jpg") || img.path.endsWith(".jpeg") ? "image/jpeg" : "image/webp";
|
|
16745
17050
|
parts.push({ type: "image_url", image_url: { url: `data:${mimeType};base64,${data}` } });
|
|
16746
17051
|
} else {
|
|
@@ -16999,12 +17304,12 @@ var init_session = __esm({
|
|
|
16999
17304
|
toolName: req.tool.name,
|
|
17000
17305
|
args: req.args
|
|
17001
17306
|
});
|
|
17002
|
-
const decision = await new Promise((
|
|
17003
|
-
this.permissionResolvers.set(requestId,
|
|
17307
|
+
const decision = await new Promise((resolve20) => {
|
|
17308
|
+
this.permissionResolvers.set(requestId, resolve20);
|
|
17004
17309
|
setTimeout(() => {
|
|
17005
17310
|
if (this.permissionResolvers.has(requestId)) {
|
|
17006
17311
|
this.permissionResolvers.delete(requestId);
|
|
17007
|
-
|
|
17312
|
+
resolve20("deny");
|
|
17008
17313
|
}
|
|
17009
17314
|
}, 3e5);
|
|
17010
17315
|
});
|
|
@@ -17063,14 +17368,14 @@ var init_session = __esm({
|
|
|
17063
17368
|
this.lspManager?.notifyChange(path, content);
|
|
17064
17369
|
} else {
|
|
17065
17370
|
void import("fs/promises").then(
|
|
17066
|
-
({ readFile:
|
|
17371
|
+
({ readFile: readFile37 }) => readFile37(path, "utf8").then((c) => this.lspManager?.notifyChange(path, c)).catch(() => {
|
|
17067
17372
|
})
|
|
17068
17373
|
).catch(() => {
|
|
17069
17374
|
});
|
|
17070
17375
|
}
|
|
17071
17376
|
}
|
|
17072
17377
|
});
|
|
17073
|
-
if (["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].some((name) => existsSync7(
|
|
17378
|
+
if (["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].some((name) => existsSync7(join35(this.cwd, name)))) {
|
|
17074
17379
|
this.messages[0] = {
|
|
17075
17380
|
role: "system",
|
|
17076
17381
|
content: buildSystemPrompt({
|
|
@@ -17094,13 +17399,13 @@ __export(run_exports, {
|
|
|
17094
17399
|
runShell: () => runShell,
|
|
17095
17400
|
summarizeTrace: () => summarizeTrace
|
|
17096
17401
|
});
|
|
17097
|
-
import { spawn as
|
|
17098
|
-
import { appendFile as appendFile3, copyFile, mkdir as
|
|
17099
|
-
import { dirname as dirname18, join as
|
|
17402
|
+
import { spawn as spawn7 } from "child_process";
|
|
17403
|
+
import { appendFile as appendFile3, copyFile, mkdir as mkdir16, readFile as readFile21, writeFile as writeFile15 } from "fs/promises";
|
|
17404
|
+
import { dirname as dirname18, join as join36, resolve as resolve12 } from "path";
|
|
17100
17405
|
import { performance as performance2 } from "perf_hooks";
|
|
17101
17406
|
function runShell(command, cwd, timeoutMs) {
|
|
17102
17407
|
return new Promise((resolveShell) => {
|
|
17103
|
-
const child =
|
|
17408
|
+
const child = spawn7(process.platform === "win32" ? process.env.COMSPEC || "cmd.exe" : "bash", [process.platform === "win32" ? "/c" : "-lc", command], {
|
|
17104
17409
|
cwd,
|
|
17105
17410
|
env: { ...process.env, CI: "1", GIT_EDITOR: "true" }
|
|
17106
17411
|
});
|
|
@@ -17129,8 +17434,8 @@ ${err.message}`, timedOut });
|
|
|
17129
17434
|
}
|
|
17130
17435
|
async function copyTaskFiles(task, worktree) {
|
|
17131
17436
|
for (const [dest, src] of Object.entries(task.resolvedFiles)) {
|
|
17132
|
-
const target =
|
|
17133
|
-
await
|
|
17437
|
+
const target = join36(worktree, dest);
|
|
17438
|
+
await mkdir16(dirname18(target), { recursive: true });
|
|
17134
17439
|
await copyFile(src, target);
|
|
17135
17440
|
}
|
|
17136
17441
|
}
|
|
@@ -17138,7 +17443,7 @@ async function summarizeTrace(traceFile) {
|
|
|
17138
17443
|
const out = { cost_usd: 0, prompt_tokens: 0, completion_tokens: 0, turns: 0, tool_calls: 0, overflow: false };
|
|
17139
17444
|
let raw;
|
|
17140
17445
|
try {
|
|
17141
|
-
raw = await
|
|
17446
|
+
raw = await readFile21(traceFile, "utf8");
|
|
17142
17447
|
} catch {
|
|
17143
17448
|
return out;
|
|
17144
17449
|
}
|
|
@@ -17170,7 +17475,7 @@ function sessionIdFor(runName, task, sample) {
|
|
|
17170
17475
|
async function runOne(task, sample, ctx) {
|
|
17171
17476
|
const startedAt2 = performance2.now();
|
|
17172
17477
|
const sessionId = sessionIdFor(ctx.runName, task, sample);
|
|
17173
|
-
const traceDir =
|
|
17478
|
+
const traceDir = join36(ctx.tracesRoot, sessionId);
|
|
17174
17479
|
const base = {
|
|
17175
17480
|
task_id: task.id,
|
|
17176
17481
|
sample,
|
|
@@ -17195,15 +17500,15 @@ async function runOne(task, sample, ctx) {
|
|
|
17195
17500
|
});
|
|
17196
17501
|
let worktree = null;
|
|
17197
17502
|
try {
|
|
17198
|
-
const sourceRepo = await prepareSourceRepo(task.repo,
|
|
17199
|
-
worktree = await createWorktree(sourceRepo, task.base_commit,
|
|
17503
|
+
const sourceRepo = await prepareSourceRepo(task.repo, join36(ctx.out, "cache"));
|
|
17504
|
+
worktree = await createWorktree(sourceRepo, task.base_commit, join36(ctx.out, "work", task.id, String(sample)));
|
|
17200
17505
|
await copyTaskFiles(task, worktree.path);
|
|
17201
17506
|
const timeoutMs = (task.timeout_s ?? DEFAULT_TASK_TIMEOUT_S) * 1e3;
|
|
17202
17507
|
if (task.setup) {
|
|
17203
17508
|
ctx.log(`[${task.id}#${sample}] setup`);
|
|
17204
17509
|
const setup = await runShell(task.setup, worktree.path, timeoutMs);
|
|
17205
17510
|
if (setup.exitCode !== 0) {
|
|
17206
|
-
await
|
|
17511
|
+
await writeFile15(join36(worktree.path, ".eval-setup.log"), setup.log, "utf8").catch(() => void 0);
|
|
17207
17512
|
return finish({ error: `setup failed (exit ${setup.exitCode}${setup.timedOut ? ", timed out" : ""}): ${setup.log.slice(-500)}` });
|
|
17208
17513
|
}
|
|
17209
17514
|
}
|
|
@@ -17237,8 +17542,8 @@ async function runOne(task, sample, ctx) {
|
|
|
17237
17542
|
const test = await runShell(task.test, worktree.path, timeoutMs);
|
|
17238
17543
|
const testMs = Math.round(performance2.now() - testStartedAt);
|
|
17239
17544
|
const passed = test.exitCode === 0 && !test.timedOut;
|
|
17240
|
-
await
|
|
17241
|
-
await
|
|
17545
|
+
await mkdir16(traceDir, { recursive: true }).catch(() => void 0);
|
|
17546
|
+
await writeFile15(join36(traceDir, "test.log"), test.log, "utf8").catch(() => void 0);
|
|
17242
17547
|
if (session.trace.enabled) {
|
|
17243
17548
|
session.trace.emit(
|
|
17244
17549
|
"outcome",
|
|
@@ -17256,7 +17561,7 @@ async function runOne(task, sample, ctx) {
|
|
|
17256
17561
|
}
|
|
17257
17562
|
session.dispose({ traceEndReason: "eval_done" });
|
|
17258
17563
|
await session.trace.flush();
|
|
17259
|
-
const stats = await summarizeTrace(
|
|
17564
|
+
const stats = await summarizeTrace(join36(traceDir, "trace.jsonl"));
|
|
17260
17565
|
ctx.log(`[${task.id}#${sample}] ${passed ? "PASS" : "FAIL"} in ${agentMs + testMs} ms${agentError ? ` (${agentError.slice(0, 120)})` : ""}`);
|
|
17261
17566
|
return finish({
|
|
17262
17567
|
passed,
|
|
@@ -17274,7 +17579,7 @@ async function runOne(task, sample, ctx) {
|
|
|
17274
17579
|
}
|
|
17275
17580
|
}
|
|
17276
17581
|
async function runEval(opts2) {
|
|
17277
|
-
const out =
|
|
17582
|
+
const out = resolve12(opts2.out);
|
|
17278
17583
|
const log2 = opts2.log ?? ((line) => process.stderr.write(`${line}
|
|
17279
17584
|
`));
|
|
17280
17585
|
const evalConfig = await loadEvalConfig(opts2.configFile);
|
|
@@ -17285,12 +17590,12 @@ async function runEval(opts2) {
|
|
|
17285
17590
|
const samples = Math.max(1, Math.floor(opts2.samples ?? 1));
|
|
17286
17591
|
const concurrency = Math.max(1, Math.floor(opts2.concurrency ?? 1));
|
|
17287
17592
|
const createSession = opts2.createSession ?? (await Promise.resolve().then(() => (init_session(), session_exports))).createAgentSession;
|
|
17288
|
-
await
|
|
17289
|
-
const tracesRoot =
|
|
17593
|
+
await mkdir16(out, { recursive: true });
|
|
17594
|
+
const tracesRoot = join36(out, "traces");
|
|
17290
17595
|
const runName = evalConfig.name;
|
|
17291
|
-
const resultsFile =
|
|
17292
|
-
await
|
|
17293
|
-
|
|
17596
|
+
const resultsFile = join36(out, "results.jsonl");
|
|
17597
|
+
await writeFile15(
|
|
17598
|
+
join36(out, "config.json"),
|
|
17294
17599
|
JSON.stringify({ name: evalConfig.name, model, temperature: evalConfig.temperature ?? null, config: redactConfig(evalConfig.config), tasks: opts2.tasksDir, samples, started_at: (/* @__PURE__ */ new Date()).toISOString() }, null, 2),
|
|
17295
17600
|
"utf8"
|
|
17296
17601
|
);
|
|
@@ -17334,9 +17639,9 @@ __export(compare_exports, {
|
|
|
17334
17639
|
perTask: () => perTask,
|
|
17335
17640
|
summarizeArm: () => summarizeArm
|
|
17336
17641
|
});
|
|
17337
|
-
import { readFile as
|
|
17642
|
+
import { readFile as readFile22 } from "fs/promises";
|
|
17338
17643
|
async function loadResults(file) {
|
|
17339
|
-
const raw = await
|
|
17644
|
+
const raw = await readFile22(file, "utf8");
|
|
17340
17645
|
return raw.split("\n").filter((l) => l.trim()).map((l) => JSON.parse(l));
|
|
17341
17646
|
}
|
|
17342
17647
|
function median(values) {
|
|
@@ -17469,16 +17774,16 @@ __export(cost_verify_exports, {
|
|
|
17469
17774
|
verifySession: () => verifySession,
|
|
17470
17775
|
verifyTurn: () => verifyTurn
|
|
17471
17776
|
});
|
|
17472
|
-
import { readFile as
|
|
17777
|
+
import { readFile as readFile23 } from "fs/promises";
|
|
17473
17778
|
import { homedir as homedir21 } from "os";
|
|
17474
|
-
import { join as
|
|
17779
|
+
import { join as join37 } from "path";
|
|
17475
17780
|
function usagePath2() {
|
|
17476
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
17477
|
-
return
|
|
17781
|
+
const xdg = process.env.XDG_DATA_HOME || join37(homedir21(), ".local", "share");
|
|
17782
|
+
return join37(xdg, "kimiflare", "usage.json");
|
|
17478
17783
|
}
|
|
17479
17784
|
async function loadSessions() {
|
|
17480
17785
|
try {
|
|
17481
|
-
return JSON.parse(await
|
|
17786
|
+
return JSON.parse(await readFile23(usagePath2(), "utf8")).sessions ?? [];
|
|
17482
17787
|
} catch {
|
|
17483
17788
|
return [];
|
|
17484
17789
|
}
|
|
@@ -18009,12 +18314,12 @@ var init_heuristic = __esm({
|
|
|
18009
18314
|
});
|
|
18010
18315
|
|
|
18011
18316
|
// src/cost-attribution/classify-from-session.ts
|
|
18012
|
-
import { readFile as
|
|
18013
|
-
import { join as
|
|
18317
|
+
import { readFile as readFile24 } from "fs/promises";
|
|
18318
|
+
import { join as join38 } from "path";
|
|
18014
18319
|
import { homedir as homedir22 } from "os";
|
|
18015
18320
|
function sessionsDir2() {
|
|
18016
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
18017
|
-
return
|
|
18321
|
+
const xdg = process.env.XDG_DATA_HOME || join38(homedir22(), ".local", "share");
|
|
18322
|
+
return join38(xdg, "kimiflare", "sessions");
|
|
18018
18323
|
}
|
|
18019
18324
|
function parseToolCalls(calls) {
|
|
18020
18325
|
return calls.map((c) => {
|
|
@@ -18028,7 +18333,7 @@ function parseToolCalls(calls) {
|
|
|
18028
18333
|
}
|
|
18029
18334
|
async function classifyFromSessionFile(sessionId) {
|
|
18030
18335
|
try {
|
|
18031
|
-
const raw = await
|
|
18336
|
+
const raw = await readFile24(join38(sessionsDir2(), `${sessionId}.json`), "utf8");
|
|
18032
18337
|
const session = JSON.parse(raw);
|
|
18033
18338
|
const messages = session.messages ?? [];
|
|
18034
18339
|
const turns = [];
|
|
@@ -18061,15 +18366,15 @@ var cli_exports = {};
|
|
|
18061
18366
|
__export(cli_exports, {
|
|
18062
18367
|
runCostCommand: () => runCostCommand
|
|
18063
18368
|
});
|
|
18064
|
-
import { readFile as
|
|
18065
|
-
import { join as
|
|
18369
|
+
import { readFile as readFile25 } from "fs/promises";
|
|
18370
|
+
import { join as join39 } from "path";
|
|
18066
18371
|
import { homedir as homedir23 } from "os";
|
|
18067
18372
|
function usageDir2() {
|
|
18068
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
18069
|
-
return
|
|
18373
|
+
const xdg = process.env.XDG_DATA_HOME || join39(homedir23(), ".local", "share");
|
|
18374
|
+
return join39(xdg, "kimiflare");
|
|
18070
18375
|
}
|
|
18071
18376
|
function usagePath3() {
|
|
18072
|
-
return
|
|
18377
|
+
return join39(usageDir2(), "usage.json");
|
|
18073
18378
|
}
|
|
18074
18379
|
function today2() {
|
|
18075
18380
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -18081,7 +18386,7 @@ function daysAgo(n) {
|
|
|
18081
18386
|
}
|
|
18082
18387
|
async function loadLog2() {
|
|
18083
18388
|
try {
|
|
18084
|
-
const raw = await
|
|
18389
|
+
const raw = await readFile25(usagePath3(), "utf8");
|
|
18085
18390
|
return JSON.parse(raw);
|
|
18086
18391
|
} catch {
|
|
18087
18392
|
return { version: 1, days: [], sessions: [] };
|
|
@@ -18171,12 +18476,12 @@ __export(aster_workspaces_exports, {
|
|
|
18171
18476
|
findAsterWorkspace: () => findAsterWorkspace,
|
|
18172
18477
|
loadAsterServerConfig: () => loadAsterServerConfig
|
|
18173
18478
|
});
|
|
18174
|
-
import { readFile as
|
|
18175
|
-
import { isAbsolute as
|
|
18479
|
+
import { readFile as readFile26, realpath as realpath4, stat as stat10 } from "fs/promises";
|
|
18480
|
+
import { isAbsolute as isAbsolute5, relative as relative8, sep as sep4 } from "path";
|
|
18176
18481
|
async function loadAsterServerConfig(configPath3 = process.env.AUTOPILOT_ASTER_CONFIG || "/etc/autopilot/aster.json") {
|
|
18177
18482
|
let raw;
|
|
18178
18483
|
try {
|
|
18179
|
-
raw = JSON.parse(await
|
|
18484
|
+
raw = JSON.parse(await readFile26(configPath3, "utf8"));
|
|
18180
18485
|
} catch {
|
|
18181
18486
|
throw new AsterConfigError();
|
|
18182
18487
|
}
|
|
@@ -18209,15 +18514,15 @@ async function loadAsterServerConfig(configPath3 = process.env.AUTOPILOT_ASTER_C
|
|
|
18209
18514
|
if (typeof workspace.displayName !== "string" || !workspace.displayName.trim() || workspace.displayName.length > 100) {
|
|
18210
18515
|
throw new AsterConfigError();
|
|
18211
18516
|
}
|
|
18212
|
-
if (typeof workspace.rootPath !== "string" || !
|
|
18517
|
+
if (typeof workspace.rootPath !== "string" || !isAbsolute5(workspace.rootPath)) throw new AsterConfigError();
|
|
18213
18518
|
let rootPath;
|
|
18214
18519
|
try {
|
|
18215
|
-
rootPath = await
|
|
18216
|
-
if (!(await
|
|
18520
|
+
rootPath = await realpath4(workspace.rootPath);
|
|
18521
|
+
if (!(await stat10(rootPath)).isDirectory()) throw new Error("not a directory");
|
|
18217
18522
|
} catch {
|
|
18218
18523
|
throw new AsterConfigError();
|
|
18219
18524
|
}
|
|
18220
|
-
if (roots.some((root) =>
|
|
18525
|
+
if (roots.some((root) => isWithin2(root, rootPath) || isWithin2(rootPath, root))) {
|
|
18221
18526
|
throw new AsterConfigError();
|
|
18222
18527
|
}
|
|
18223
18528
|
ids.add(workspace.id);
|
|
@@ -18229,9 +18534,9 @@ async function loadAsterServerConfig(configPath3 = process.env.AUTOPILOT_ASTER_C
|
|
|
18229
18534
|
function findAsterWorkspace(config2, workspaceId) {
|
|
18230
18535
|
return config2.workspaces.find((workspace) => workspace.id === workspaceId);
|
|
18231
18536
|
}
|
|
18232
|
-
function
|
|
18233
|
-
const rel =
|
|
18234
|
-
return rel === "" || rel !== ".." && !rel.startsWith(`..${
|
|
18537
|
+
function isWithin2(parent, candidate) {
|
|
18538
|
+
const rel = relative8(parent, candidate);
|
|
18539
|
+
return rel === "" || rel !== ".." && !rel.startsWith(`..${sep4}`) && !isAbsolute5(rel);
|
|
18235
18540
|
}
|
|
18236
18541
|
var AsterConfigError;
|
|
18237
18542
|
var init_aster_workspaces = __esm({
|
|
@@ -18255,10 +18560,10 @@ import Database4 from "better-sqlite3";
|
|
|
18255
18560
|
import { createHash as createHash5, randomBytes as randomBytes2, randomUUID as randomUUID6 } from "crypto";
|
|
18256
18561
|
import { chmodSync as chmodSync2, mkdirSync as mkdirSync9 } from "fs";
|
|
18257
18562
|
import { homedir as homedir24 } from "os";
|
|
18258
|
-
import { dirname as dirname19, join as
|
|
18563
|
+
import { dirname as dirname19, join as join40 } from "path";
|
|
18259
18564
|
function defaultAsterDbPath() {
|
|
18260
|
-
const root = process.env.XDG_STATE_HOME ||
|
|
18261
|
-
return process.env.AUTOPILOT_ASTER_DB ||
|
|
18565
|
+
const root = process.env.XDG_STATE_HOME || join40(homedir24(), ".local", "state");
|
|
18566
|
+
return process.env.AUTOPILOT_ASTER_DB || join40(root, "autopilot", "aster.db");
|
|
18262
18567
|
}
|
|
18263
18568
|
function hashToken(token) {
|
|
18264
18569
|
return createHash5("sha256").update(token).digest("hex");
|
|
@@ -18612,7 +18917,7 @@ __export(tui_auth_exports, {
|
|
|
18612
18917
|
authGitHubForTui: () => authGitHubForTui
|
|
18613
18918
|
});
|
|
18614
18919
|
function sleep3(ms) {
|
|
18615
|
-
return new Promise((
|
|
18920
|
+
return new Promise((resolve20) => setTimeout(resolve20, ms));
|
|
18616
18921
|
}
|
|
18617
18922
|
async function* authGitHubForTui() {
|
|
18618
18923
|
yield { message: "Starting GitHub OAuth device flow..." };
|
|
@@ -19183,18 +19488,18 @@ var init_openapi = __esm({
|
|
|
19183
19488
|
|
|
19184
19489
|
// src/runs/worktrees.ts
|
|
19185
19490
|
import { execFile as execFile8 } from "child_process";
|
|
19186
|
-
import { access as access2, chmod as
|
|
19491
|
+
import { access as access2, chmod as chmod3, mkdir as mkdir17, realpath as realpath5 } from "fs/promises";
|
|
19187
19492
|
import { homedir as homedir25 } from "os";
|
|
19188
|
-
import { isAbsolute as
|
|
19493
|
+
import { isAbsolute as isAbsolute6, join as join41, parse, relative as relative9, resolve as resolve13, sep as sep5 } from "path";
|
|
19189
19494
|
function defaultWorktreesDir() {
|
|
19190
|
-
const dataHome = process.env.XDG_DATA_HOME ||
|
|
19191
|
-
return
|
|
19495
|
+
const dataHome = process.env.XDG_DATA_HOME || join41(homedir25(), ".local", "share");
|
|
19496
|
+
return join41(dataHome, "autopilot", "worktrees");
|
|
19192
19497
|
}
|
|
19193
19498
|
function isOutside(path) {
|
|
19194
|
-
return path === ".." || path.startsWith(`..${
|
|
19499
|
+
return path === ".." || path.startsWith(`..${sep5}`) || isAbsolute6(path);
|
|
19195
19500
|
}
|
|
19196
|
-
function
|
|
19197
|
-
const path =
|
|
19501
|
+
function isWithin3(parent, candidate) {
|
|
19502
|
+
const path = relative9(parent, candidate);
|
|
19198
19503
|
return path === "" || !isOutside(path);
|
|
19199
19504
|
}
|
|
19200
19505
|
function runGit(args, cwd) {
|
|
@@ -19222,24 +19527,24 @@ var init_worktrees = __esm({
|
|
|
19222
19527
|
if (runId === "." || runId === ".." || !/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/.test(runId)) {
|
|
19223
19528
|
throw new Error("runId must contain only letters, numbers, dots, underscores, or hyphens");
|
|
19224
19529
|
}
|
|
19225
|
-
const source = await
|
|
19530
|
+
const source = await realpath5(sourceCwd);
|
|
19226
19531
|
const repositoryRoot = (await runGit(["rev-parse", "--show-toplevel"], source)).trim();
|
|
19227
|
-
const repository = await
|
|
19228
|
-
const sourceRelativePath =
|
|
19532
|
+
const repository = await realpath5(repositoryRoot);
|
|
19533
|
+
const sourceRelativePath = relative9(repository, source);
|
|
19229
19534
|
if (isOutside(sourceRelativePath)) {
|
|
19230
19535
|
throw new Error("sourceCwd must be inside the Git repository");
|
|
19231
19536
|
}
|
|
19232
|
-
const configuredRoot =
|
|
19233
|
-
if (configuredRoot === parse(configuredRoot).root ||
|
|
19537
|
+
const configuredRoot = resolve13(this.rootDir);
|
|
19538
|
+
if (configuredRoot === parse(configuredRoot).root || isWithin3(repository, configuredRoot)) {
|
|
19234
19539
|
throw new Error("worktree root must be outside the source repository and not the filesystem root");
|
|
19235
19540
|
}
|
|
19236
|
-
await
|
|
19237
|
-
const worktreesRoot = await
|
|
19238
|
-
if (
|
|
19541
|
+
await mkdir17(configuredRoot, { recursive: true, mode: 448 });
|
|
19542
|
+
const worktreesRoot = await realpath5(configuredRoot);
|
|
19543
|
+
if (isWithin3(repository, worktreesRoot)) {
|
|
19239
19544
|
throw new Error("worktree root must be outside the source repository");
|
|
19240
19545
|
}
|
|
19241
|
-
await
|
|
19242
|
-
const worktreePath =
|
|
19546
|
+
await chmod3(worktreesRoot, 448);
|
|
19547
|
+
const worktreePath = join41(worktreesRoot, runId);
|
|
19243
19548
|
try {
|
|
19244
19549
|
await access2(worktreePath);
|
|
19245
19550
|
throw new Error(`worktree path already exists for run ${runId}`);
|
|
@@ -19253,16 +19558,16 @@ var init_worktrees = __esm({
|
|
|
19253
19558
|
repositoryRoot: repository,
|
|
19254
19559
|
sourceCwd: source,
|
|
19255
19560
|
worktreePath,
|
|
19256
|
-
cwd:
|
|
19561
|
+
cwd: resolve13(worktreePath, sourceRelativePath),
|
|
19257
19562
|
branch
|
|
19258
19563
|
};
|
|
19259
19564
|
}
|
|
19260
19565
|
/** Remove a newly-created, still-clean worktree when run initialization fails. */
|
|
19261
19566
|
async discard(worktree) {
|
|
19262
|
-
const root = await
|
|
19263
|
-
const target = await
|
|
19264
|
-
const repository = await
|
|
19265
|
-
if (target === root || !
|
|
19567
|
+
const root = await realpath5(this.rootDir);
|
|
19568
|
+
const target = await realpath5(worktree.worktreePath);
|
|
19569
|
+
const repository = await realpath5(worktree.repositoryRoot);
|
|
19570
|
+
if (target === root || !isWithin3(root, target)) {
|
|
19266
19571
|
throw new Error("worktree path is outside the configured worktree root");
|
|
19267
19572
|
}
|
|
19268
19573
|
if (worktree.branch !== `autopilot/run/${worktree.runId}`) {
|
|
@@ -19407,8 +19712,8 @@ var init_wake_scheduler = __esm({
|
|
|
19407
19712
|
});
|
|
19408
19713
|
|
|
19409
19714
|
// src/server/aster-tools.ts
|
|
19410
|
-
import { realpath as
|
|
19411
|
-
import { isAbsolute as
|
|
19715
|
+
import { realpath as realpath6 } from "fs/promises";
|
|
19716
|
+
import { isAbsolute as isAbsolute7, relative as relative10, sep as sep6 } from "path";
|
|
19412
19717
|
function createAsterTools(workspaceRoot) {
|
|
19413
19718
|
return ASTR_TOOLS.map((tool) => ({
|
|
19414
19719
|
...tool,
|
|
@@ -19420,25 +19725,25 @@ function createAsterTools(workspaceRoot) {
|
|
|
19420
19725
|
}
|
|
19421
19726
|
async function assertAsterWorkspacePath(workspaceRoot, value, allowMissing = false) {
|
|
19422
19727
|
if (typeof value !== "string" || !value.trim()) throw new Error("workspace_path_invalid");
|
|
19423
|
-
const root = await
|
|
19728
|
+
const root = await realpath6(workspaceRoot);
|
|
19424
19729
|
const candidate = resolvePath(root, value);
|
|
19425
19730
|
assertInside(root, candidate);
|
|
19426
19731
|
assertNotSensitive(root, candidate);
|
|
19427
19732
|
let actual;
|
|
19428
19733
|
try {
|
|
19429
|
-
actual = await
|
|
19734
|
+
actual = await realpath6(candidate);
|
|
19430
19735
|
} catch (error) {
|
|
19431
19736
|
if (!allowMissing || error.code !== "ENOENT") throw new Error("workspace_path_unavailable");
|
|
19432
19737
|
let ancestor = candidate;
|
|
19433
19738
|
while (true) {
|
|
19434
19739
|
try {
|
|
19435
|
-
actual = await
|
|
19740
|
+
actual = await realpath6(ancestor);
|
|
19436
19741
|
break;
|
|
19437
19742
|
} catch (ancestorError) {
|
|
19438
19743
|
if (ancestorError.code !== "ENOENT") throw new Error("workspace_path_unavailable");
|
|
19439
|
-
const parent =
|
|
19744
|
+
const parent = relative10(root, ancestor);
|
|
19440
19745
|
if (!parent || parent === ".") throw new Error("workspace_path_unavailable");
|
|
19441
|
-
ancestor = ancestor.slice(0, ancestor.lastIndexOf(
|
|
19746
|
+
ancestor = ancestor.slice(0, ancestor.lastIndexOf(sep6));
|
|
19442
19747
|
}
|
|
19443
19748
|
}
|
|
19444
19749
|
}
|
|
@@ -19460,11 +19765,11 @@ function redactLikelySecrets(value) {
|
|
|
19460
19765
|
return value.replace(SK_CANDIDATE_RE, (match) => isLikelySkKey(match) ? "[REDACTED_PROVIDER_SECRET]" : match).replace(/\bgh[pousr]_[A-Za-z0-9]{20,}/g, "[REDACTED_PROVIDER_SECRET]").replace(/\bgithub_pat_[A-Za-z0-9_]{20,}/g, "[REDACTED_PROVIDER_SECRET]");
|
|
19461
19766
|
}
|
|
19462
19767
|
function assertInside(root, candidate) {
|
|
19463
|
-
const rel =
|
|
19464
|
-
if (rel === ".." || rel.startsWith(`..${
|
|
19768
|
+
const rel = relative10(root, candidate);
|
|
19769
|
+
if (rel === ".." || rel.startsWith(`..${sep6}`) || isAbsolute7(rel)) throw new Error("workspace_path_forbidden");
|
|
19465
19770
|
}
|
|
19466
19771
|
function assertNotSensitive(root, candidate) {
|
|
19467
|
-
const parts =
|
|
19772
|
+
const parts = relative10(root, candidate).split(sep6).filter(Boolean).map((part) => part.toLowerCase());
|
|
19468
19773
|
if (parts.some((part) => part === ".env" || part.startsWith(".env.") || SENSITIVE_NAMES.has(part))) {
|
|
19469
19774
|
throw new Error("workspace_sensitive_path_forbidden");
|
|
19470
19775
|
}
|
|
@@ -19499,7 +19804,7 @@ var init_aster_tools = __esm({
|
|
|
19499
19804
|
// src/server/aster-api.ts
|
|
19500
19805
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
19501
19806
|
import { unlink as unlink2 } from "fs/promises";
|
|
19502
|
-
import { resolve as
|
|
19807
|
+
import { resolve as resolve14 } from "path";
|
|
19503
19808
|
function parseCursor(header, query) {
|
|
19504
19809
|
const value = (Array.isArray(header) ? header[0] : header) ?? query ?? "0";
|
|
19505
19810
|
if (!/^\d{1,16}$/.test(value)) return void 0;
|
|
@@ -19812,7 +20117,7 @@ var init_aster_api = __esm({
|
|
|
19812
20117
|
store.appendEvent(id, null, "conversation.created", { conversationId: id, workspaceId: workspace.id, model });
|
|
19813
20118
|
json(res, 201, publicConversation(conversation));
|
|
19814
20119
|
} catch {
|
|
19815
|
-
await unlink2(
|
|
20120
|
+
await unlink2(resolve14(sessionsDir(), `${sessionId}.json`)).catch(() => {
|
|
19816
20121
|
});
|
|
19817
20122
|
await worktreeManager.discard(worktree).catch(() => {
|
|
19818
20123
|
});
|
|
@@ -19837,7 +20142,7 @@ var init_aster_api = __esm({
|
|
|
19837
20142
|
sendError(res, 409, "conversation_busy", "A turn is already active for this conversation");
|
|
19838
20143
|
return;
|
|
19839
20144
|
}
|
|
19840
|
-
const sessionPath =
|
|
20145
|
+
const sessionPath = resolve14(sessionsDir(), conversation.sessionId + ".json");
|
|
19841
20146
|
let sessionFile;
|
|
19842
20147
|
try {
|
|
19843
20148
|
sessionFile = await loadSession(sessionPath);
|
|
@@ -20155,7 +20460,7 @@ data: ${JSON.stringify(event.data)}
|
|
|
20155
20460
|
|
|
20156
20461
|
// src/server/aster-cell-runtime.ts
|
|
20157
20462
|
import { execFile as execFile9 } from "child_process";
|
|
20158
|
-
import { readFile as
|
|
20463
|
+
import { readFile as readFile27 } from "fs/promises";
|
|
20159
20464
|
import { promisify as promisify8 } from "util";
|
|
20160
20465
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
20161
20466
|
async function writeCellFileChunked(cell, path, content) {
|
|
@@ -20185,7 +20490,7 @@ async function writeCellFileChunked(cell, path, content) {
|
|
|
20185
20490
|
async function readBundledCellSdkBundle() {
|
|
20186
20491
|
for (const url of [new URL("./sdk/index.js", import.meta.url), new URL("../sdk/index.js", import.meta.url)]) {
|
|
20187
20492
|
try {
|
|
20188
|
-
return await
|
|
20493
|
+
return await readFile27(url, "utf8");
|
|
20189
20494
|
} catch {
|
|
20190
20495
|
}
|
|
20191
20496
|
}
|
|
@@ -20238,7 +20543,7 @@ function boundedToolText(text, limit) {
|
|
|
20238
20543
|
${redacted.slice(-half)}`;
|
|
20239
20544
|
}
|
|
20240
20545
|
function sleep4(ms) {
|
|
20241
|
-
return new Promise((
|
|
20546
|
+
return new Promise((resolve20) => setTimeout(resolve20, ms));
|
|
20242
20547
|
}
|
|
20243
20548
|
var execFileAsync6, CELL_WORKSPACE, CELL_STATE_DIR, CHECKPOINT_MESSAGE_FILE, CELL_RUNTIME_DIR, INSTALLED_RUNTIME_PACKAGE, CELL_RUNTIME_SDK_ENTRY, NOTES_FILE, MEMORY_FILE, MEMORY_EXTRACTION_TIMEOUT_MS, LIVENESS_CHECK_MS, ARTIFACTS_DIR, MAX_ARTIFACTS, MAX_ARTIFACT_BYTES, BRANCH_RE, REPOSITORY_RE, GIT, COMMIT_SHA_RE, MAX_TOOL_OUTPUT_CHARS, MAX_TOOL_INPUT_CHARS, MAX_CHECKPOINTS, CELL_CONTROL_DIR, BRIDGE_MARKER, CONTROL_RUNNER, BRIDGE_RUNNER, HEALTH_TIMEOUT_MS, EVENT_POLL_MS, AsterHotcellRuntime, CELL_FILE_WRITE_CHUNK_CHARS, ARTIFACT_MIME_TYPES;
|
|
20244
20549
|
var init_aster_cell_runtime = __esm({
|
|
@@ -20681,9 +20986,9 @@ ${turn.userText}` : turn.userText;
|
|
|
20681
20986
|
if (!isSafeArtifactPath(path)) throw new Error("invalid_artifact_path");
|
|
20682
20987
|
const cell = await this.provider.getCell(cellId);
|
|
20683
20988
|
const file = shellQuote2(`${ARTIFACTS_DIR}/${path}`);
|
|
20684
|
-
const
|
|
20685
|
-
if (
|
|
20686
|
-
if (Number(
|
|
20989
|
+
const stat14 = await cell.exec(`[ -f ${file} ] && [ ! -L ${file} ] && stat -c %s -- ${file}`);
|
|
20990
|
+
if (stat14.exitCode !== 0) throw new Error("artifact_not_found");
|
|
20991
|
+
if (Number(stat14.stdout.trim()) > MAX_ARTIFACT_BYTES) throw new Error("artifact_too_large");
|
|
20687
20992
|
const encoded = await cell.exec(`base64 -w0 -- ${file}`);
|
|
20688
20993
|
if (encoded.exitCode !== 0) throw new Error("artifact_not_found");
|
|
20689
20994
|
return { data: Buffer.from(encoded.stdout.trim(), "base64"), mimeType: artifactMimeType(path), name: path.split("/").pop() ?? path };
|
|
@@ -20980,8 +21285,8 @@ var init_hotcell_provider = __esm({
|
|
|
20980
21285
|
// src/server/routes.ts
|
|
20981
21286
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
20982
21287
|
import { URL as URL2 } from "url";
|
|
20983
|
-
import { readFile as
|
|
20984
|
-
import { resolve as
|
|
21288
|
+
import { readFile as readFile28, unlink as unlink3 } from "fs/promises";
|
|
21289
|
+
import { resolve as resolve15, basename as basename7 } from "path";
|
|
20985
21290
|
function createHotcellAsterRuntime() {
|
|
20986
21291
|
try {
|
|
20987
21292
|
const idlePauseMs = Number(process.env.AUTOPILOT_ASTER_IDLE_PAUSE_MS ?? 15 * 60 * 1e3);
|
|
@@ -21064,9 +21369,9 @@ async function resolveFiles2(filePatterns, cwd) {
|
|
|
21064
21369
|
const resolved = /* @__PURE__ */ new Set();
|
|
21065
21370
|
for (const pattern of filePatterns) {
|
|
21066
21371
|
try {
|
|
21067
|
-
const
|
|
21068
|
-
if (
|
|
21069
|
-
resolved.add(
|
|
21372
|
+
const stat14 = await import("fs/promises").then((m) => m.stat(resolve15(cwd, pattern)));
|
|
21373
|
+
if (stat14.isFile()) {
|
|
21374
|
+
resolved.add(resolve15(cwd, pattern));
|
|
21070
21375
|
continue;
|
|
21071
21376
|
}
|
|
21072
21377
|
} catch {
|
|
@@ -21094,7 +21399,7 @@ async function buildUserMessage2(prompt, files, cwd) {
|
|
|
21094
21399
|
}
|
|
21095
21400
|
} else {
|
|
21096
21401
|
try {
|
|
21097
|
-
const content = await
|
|
21402
|
+
const content = await readFile28(filePath, "utf8");
|
|
21098
21403
|
const relPath = filePath.startsWith(cwd) ? filePath.slice(cwd.length + 1) : filePath;
|
|
21099
21404
|
fileContents.push(`
|
|
21100
21405
|
--- ${relPath} ---
|
|
@@ -21123,7 +21428,7 @@ function setupRoutes(config2, options = {}) {
|
|
|
21123
21428
|
if (!run.sessionId) throw new Error("Cannot restore run without a session id: " + run.id);
|
|
21124
21429
|
const existing = activeRuns.get(run.id) ?? activeSessions.get(run.sessionId);
|
|
21125
21430
|
if (existing) return existing;
|
|
21126
|
-
const sessionFile = await loadSession(
|
|
21431
|
+
const sessionFile = await loadSession(resolve15(sessionsDir(), run.sessionId + ".json"));
|
|
21127
21432
|
const allowedTools = new Set(run.allowedTools);
|
|
21128
21433
|
allowedTools.add("wait_for");
|
|
21129
21434
|
const tools = ALL_TOOLS.filter((tool) => allowedTools.has(tool.name));
|
|
@@ -21258,7 +21563,7 @@ function setupRoutes(config2, options = {}) {
|
|
|
21258
21563
|
const task = typeof body.task === "string" ? body.task.trim() : "";
|
|
21259
21564
|
let cwd;
|
|
21260
21565
|
try {
|
|
21261
|
-
cwd = typeof body.cwd === "string" ?
|
|
21566
|
+
cwd = typeof body.cwd === "string" ? resolve15(body.cwd) : process.cwd();
|
|
21262
21567
|
} catch {
|
|
21263
21568
|
badRequest(res, "cwd must be a valid path");
|
|
21264
21569
|
return;
|
|
@@ -21371,7 +21676,7 @@ function setupRoutes(config2, options = {}) {
|
|
|
21371
21676
|
store.close();
|
|
21372
21677
|
}
|
|
21373
21678
|
} catch (error) {
|
|
21374
|
-
await unlink3(
|
|
21679
|
+
await unlink3(resolve15(sessionsDir(), `${sessionId}.json`)).catch(() => {
|
|
21375
21680
|
});
|
|
21376
21681
|
if (worktree) {
|
|
21377
21682
|
await worktreeManager.discard(worktree).catch((cleanupError) => {
|
|
@@ -21506,7 +21811,7 @@ function setupRoutes(config2, options = {}) {
|
|
|
21506
21811
|
return;
|
|
21507
21812
|
}
|
|
21508
21813
|
try {
|
|
21509
|
-
const file = await loadSession(
|
|
21814
|
+
const file = await loadSession(resolve15(sessionsDir(), `${sessionId}.json`));
|
|
21510
21815
|
json2(res, 200, {
|
|
21511
21816
|
id: file.id,
|
|
21512
21817
|
cwd: file.cwd,
|
|
@@ -21526,7 +21831,7 @@ function setupRoutes(config2, options = {}) {
|
|
|
21526
21831
|
activeSessions.delete(sessionId);
|
|
21527
21832
|
try {
|
|
21528
21833
|
const { unlink: unlink6 } = await import("fs/promises");
|
|
21529
|
-
await unlink6(
|
|
21834
|
+
await unlink6(resolve15(sessionsDir(), `${sessionId}.json`));
|
|
21530
21835
|
} catch {
|
|
21531
21836
|
}
|
|
21532
21837
|
json2(res, 200, { deleted: sessionId });
|
|
@@ -21977,13 +22282,13 @@ async function startServer(opts2) {
|
|
|
21977
22282
|
};
|
|
21978
22283
|
process.on("SIGINT", shutdown);
|
|
21979
22284
|
process.on("SIGTERM", shutdown);
|
|
21980
|
-
return new Promise((
|
|
22285
|
+
return new Promise((resolve20, reject) => {
|
|
21981
22286
|
server.listen(opts2.port, opts2.hostname, () => {
|
|
21982
22287
|
logger.info("server: listening", { hostname: opts2.hostname, port: opts2.port });
|
|
21983
22288
|
console.log(`kimiflare serve: http://${opts2.hostname}:${opts2.port}`);
|
|
21984
22289
|
console.log(` API docs: http://${opts2.hostname}:${opts2.port}/doc`);
|
|
21985
22290
|
console.log(` SSE stream: http://${opts2.hostname}:${opts2.port}/event`);
|
|
21986
|
-
|
|
22291
|
+
resolve20(server);
|
|
21987
22292
|
});
|
|
21988
22293
|
server.on("error", reject);
|
|
21989
22294
|
});
|
|
@@ -22288,8 +22593,8 @@ async function runEmitMode(opts2) {
|
|
|
22288
22593
|
async function nextFollowUp() {
|
|
22289
22594
|
if (followUpQueue.length > 0) return followUpQueue.shift();
|
|
22290
22595
|
if (stdinClosed) return null;
|
|
22291
|
-
return new Promise((
|
|
22292
|
-
followUpResolver =
|
|
22596
|
+
return new Promise((resolve20) => {
|
|
22597
|
+
followUpResolver = resolve20;
|
|
22293
22598
|
});
|
|
22294
22599
|
}
|
|
22295
22600
|
const cwd = process.cwd();
|
|
@@ -22426,8 +22731,8 @@ async function runEmitMode(opts2) {
|
|
|
22426
22731
|
return "allow";
|
|
22427
22732
|
}
|
|
22428
22733
|
if (opts2.multiTurn) {
|
|
22429
|
-
const choice = await new Promise((
|
|
22430
|
-
pendingPermissions.set(reqId,
|
|
22734
|
+
const choice = await new Promise((resolve20) => {
|
|
22735
|
+
pendingPermissions.set(reqId, resolve20);
|
|
22431
22736
|
});
|
|
22432
22737
|
if (choice === "allow" || choice === "allow_session") {
|
|
22433
22738
|
emit("PermissionGranted", { request_id: reqId });
|
|
@@ -22562,7 +22867,7 @@ async function runAttachMode(opts2) {
|
|
|
22562
22867
|
async function streamSse(url, sessionId, format) {
|
|
22563
22868
|
const eventSource = new EventSource(`${url}/event`);
|
|
22564
22869
|
let done = false;
|
|
22565
|
-
return new Promise((
|
|
22870
|
+
return new Promise((resolve20, reject) => {
|
|
22566
22871
|
eventSource.onmessage = (event) => {
|
|
22567
22872
|
try {
|
|
22568
22873
|
const data = JSON.parse(event.data);
|
|
@@ -22609,7 +22914,7 @@ async function streamSse(url, sessionId, format) {
|
|
|
22609
22914
|
done = true;
|
|
22610
22915
|
eventSource.close();
|
|
22611
22916
|
if (format === "text") process.stdout.write("\n");
|
|
22612
|
-
|
|
22917
|
+
resolve20(void 0);
|
|
22613
22918
|
break;
|
|
22614
22919
|
case "error":
|
|
22615
22920
|
done = true;
|
|
@@ -22622,7 +22927,7 @@ async function streamSse(url, sessionId, format) {
|
|
|
22622
22927
|
process.stdout.write(JSON.stringify({ event: "error", message: data.message }) + "\n");
|
|
22623
22928
|
}
|
|
22624
22929
|
process.exitCode = 1;
|
|
22625
|
-
|
|
22930
|
+
resolve20(void 0);
|
|
22626
22931
|
break;
|
|
22627
22932
|
}
|
|
22628
22933
|
} catch {
|
|
@@ -22648,7 +22953,7 @@ async function streamSseJson(url, sessionId) {
|
|
|
22648
22953
|
const toolResults = [];
|
|
22649
22954
|
let usage;
|
|
22650
22955
|
const eventSource = new EventSource(`${url}/event`);
|
|
22651
|
-
return new Promise((
|
|
22956
|
+
return new Promise((resolve20, reject) => {
|
|
22652
22957
|
eventSource.onmessage = (event) => {
|
|
22653
22958
|
try {
|
|
22654
22959
|
const data = JSON.parse(event.data);
|
|
@@ -22685,7 +22990,7 @@ async function streamSseJson(url, sessionId) {
|
|
|
22685
22990
|
2
|
|
22686
22991
|
) + "\n"
|
|
22687
22992
|
);
|
|
22688
|
-
|
|
22993
|
+
resolve20(void 0);
|
|
22689
22994
|
break;
|
|
22690
22995
|
case "error":
|
|
22691
22996
|
eventSource.close();
|
|
@@ -22693,7 +22998,7 @@ async function streamSseJson(url, sessionId) {
|
|
|
22693
22998
|
JSON.stringify({ error: data.message, sessionId }, null, 2) + "\n"
|
|
22694
22999
|
);
|
|
22695
23000
|
process.exitCode = 1;
|
|
22696
|
-
|
|
23001
|
+
resolve20(void 0);
|
|
22697
23002
|
break;
|
|
22698
23003
|
}
|
|
22699
23004
|
} catch {
|
|
@@ -23361,6 +23666,9 @@ var init_help_menu = __esm({
|
|
|
23361
23666
|
});
|
|
23362
23667
|
|
|
23363
23668
|
// src/agent/queue-batch.ts
|
|
23669
|
+
function canDrainQueue(state) {
|
|
23670
|
+
return !state.busy && !state.queuePlanOpen && state.supervisorIdle && state.hasPendingWork;
|
|
23671
|
+
}
|
|
23364
23672
|
function createQueueBatch(items) {
|
|
23365
23673
|
if (items.length < 2) return null;
|
|
23366
23674
|
if (items.some((item) => isCommand(item.full))) return null;
|
|
@@ -23419,10 +23727,9 @@ __export(app_helpers_exports, {
|
|
|
23419
23727
|
replaceUserPromptEvent: () => replaceUserPromptEvent,
|
|
23420
23728
|
trackRecentFile: () => trackRecentFile
|
|
23421
23729
|
});
|
|
23422
|
-
import { execSync as execSync3
|
|
23730
|
+
import { execSync as execSync3 } from "child_process";
|
|
23423
23731
|
import { existsSync as existsSync8, readFileSync as readFileSync6, statSync as statSync5 } from "fs";
|
|
23424
|
-
import { join as
|
|
23425
|
-
import { platform as platform3 } from "os";
|
|
23732
|
+
import { join as join42 } from "path";
|
|
23426
23733
|
function replaceQueuedPrompt(queue2, key, full, display) {
|
|
23427
23734
|
const index = queue2.findIndex((item) => item.key === key);
|
|
23428
23735
|
if (index >= 0) {
|
|
@@ -23529,7 +23836,7 @@ function buildFilePickerIgnoreList(cwd) {
|
|
|
23529
23836
|
];
|
|
23530
23837
|
const gitignorePatterns = [];
|
|
23531
23838
|
try {
|
|
23532
|
-
const gitignorePath =
|
|
23839
|
+
const gitignorePath = join42(cwd, ".gitignore");
|
|
23533
23840
|
const stats = statSync5(gitignorePath);
|
|
23534
23841
|
if (stats.size > MAX_GITIGNORE_SIZE) {
|
|
23535
23842
|
return hardcoded;
|
|
@@ -23560,19 +23867,6 @@ function costLookupFromConfig(cfg, meta) {
|
|
|
23560
23867
|
if (resolveCustomEndpoint(cfg)) return void 0;
|
|
23561
23868
|
return { apiKey: cfg.openrouterApiKey, meta };
|
|
23562
23869
|
}
|
|
23563
|
-
function openBrowser(url) {
|
|
23564
|
-
if (process.env.KIMIFLARE_NO_BROWSER === "1" || process.env.BROWSER === "none") return false;
|
|
23565
|
-
try {
|
|
23566
|
-
const os2 = platform3();
|
|
23567
|
-
const [cmd, args] = os2 === "darwin" ? ["open", [url]] : os2 === "win32" ? ["cmd", ["/c", "start", "", url]] : ["xdg-open", [url]];
|
|
23568
|
-
const child = spawn7(cmd, args, { detached: true, stdio: "ignore" });
|
|
23569
|
-
child.on("error", () => void 0);
|
|
23570
|
-
child.unref();
|
|
23571
|
-
return true;
|
|
23572
|
-
} catch {
|
|
23573
|
-
return false;
|
|
23574
|
-
}
|
|
23575
|
-
}
|
|
23576
23870
|
function detectGitHubRepo(cachedRepo) {
|
|
23577
23871
|
if (cachedRepo) {
|
|
23578
23872
|
const parts = cachedRepo.split("/");
|
|
@@ -23691,6 +23985,7 @@ var init_app_helpers = __esm({
|
|
|
23691
23985
|
init_system_prompt();
|
|
23692
23986
|
init_image();
|
|
23693
23987
|
init_queue_batch();
|
|
23988
|
+
init_open_browser();
|
|
23694
23989
|
MAX_GITIGNORE_SIZE = 1 * 1024 * 1024;
|
|
23695
23990
|
CONTEXT_LIMIT = 262e3;
|
|
23696
23991
|
AUTO_COMPACT_THRESHOLD = 0.8;
|
|
@@ -23707,9 +24002,9 @@ var init_app_helpers = __esm({
|
|
|
23707
24002
|
|
|
23708
24003
|
// src/ui/bang-command.ts
|
|
23709
24004
|
import { spawn as spawn8 } from "child_process";
|
|
23710
|
-
import { mkdtemp as
|
|
23711
|
-
import { tmpdir as
|
|
23712
|
-
import { join as
|
|
24005
|
+
import { mkdtemp as mkdtemp3, readFile as readFile29, rm as rm6 } from "fs/promises";
|
|
24006
|
+
import { tmpdir as tmpdir5, platform as platform4 } from "os";
|
|
24007
|
+
import { join as join43 } from "path";
|
|
23713
24008
|
function registerInkInstance(instance) {
|
|
23714
24009
|
inkInstance = instance;
|
|
23715
24010
|
}
|
|
@@ -23717,13 +24012,13 @@ function registerTerminalHandoff(h) {
|
|
|
23717
24012
|
terminalHandoff = h;
|
|
23718
24013
|
}
|
|
23719
24014
|
function runCaptured(inv, cwd) {
|
|
23720
|
-
return new Promise((
|
|
24015
|
+
return new Promise((resolve20) => {
|
|
23721
24016
|
const child = spawn8(inv.file, inv.args, { cwd, stdio: ["ignore", "pipe", "pipe"], env: inv.env ?? process.env });
|
|
23722
24017
|
let output = "";
|
|
23723
24018
|
child.stdout?.on("data", (c) => output += c.toString("utf8"));
|
|
23724
24019
|
child.stderr?.on("data", (c) => output += c.toString("utf8"));
|
|
23725
|
-
child.once("error", (e) =>
|
|
23726
|
-
child.once("exit", (code, signal) =>
|
|
24020
|
+
child.once("error", (e) => resolve20({ code: 127, signal: null, output: `failed to start: ${e.message}` }));
|
|
24021
|
+
child.once("exit", (code, signal) => resolve20({ code, signal, output }));
|
|
23727
24022
|
});
|
|
23728
24023
|
}
|
|
23729
24024
|
function isTerminalHandedOff() {
|
|
@@ -23791,10 +24086,10 @@ function swallow() {
|
|
|
23791
24086
|
});
|
|
23792
24087
|
}
|
|
23793
24088
|
function spawnInherit(inv, cwd) {
|
|
23794
|
-
return new Promise((
|
|
24089
|
+
return new Promise((resolve20, reject) => {
|
|
23795
24090
|
const child = spawn8(inv.file, inv.args, { cwd, stdio: "inherit", env: inv.env ?? process.env });
|
|
23796
24091
|
child.once("error", reject);
|
|
23797
|
-
child.once("exit", (code, signal) =>
|
|
24092
|
+
child.once("exit", (code, signal) => resolve20({ code, signal }));
|
|
23798
24093
|
});
|
|
23799
24094
|
}
|
|
23800
24095
|
async function runBangCommand(command, cwd) {
|
|
@@ -23812,8 +24107,8 @@ async function runBangCommand(command, cwd) {
|
|
|
23812
24107
|
const origErr = stderr.write;
|
|
23813
24108
|
const readable = stdin.listeners("readable");
|
|
23814
24109
|
const wasRaw = stdin.isTTY ? stdin.isRaw : false;
|
|
23815
|
-
const logDir2 = isWindows ? null : await
|
|
23816
|
-
const logPath = logDir2 ?
|
|
24110
|
+
const logDir2 = isWindows ? null : await mkdtemp3(join43(tmpdir5(), "autopilot-bang-"));
|
|
24111
|
+
const logPath = logDir2 ? join43(logDir2, "out.log") : null;
|
|
23817
24112
|
const viaScript = logPath ? scriptInvocation(command, shell, logPath) : null;
|
|
23818
24113
|
inkInstance?.clear();
|
|
23819
24114
|
origOut.call(stdout, `
|
|
@@ -23855,9 +24150,9 @@ $ ${command}
|
|
|
23855
24150
|
}
|
|
23856
24151
|
let output = spawnError ? `failed to start: ${spawnError}` : null;
|
|
23857
24152
|
if (captured && logPath) {
|
|
23858
|
-
output = cleanTerminalOutput(await
|
|
24153
|
+
output = cleanTerminalOutput(await readFile29(logPath, "utf8").catch(() => ""));
|
|
23859
24154
|
}
|
|
23860
|
-
if (logDir2) await
|
|
24155
|
+
if (logDir2) await rm6(logDir2, { recursive: true, force: true }).catch(() => {
|
|
23861
24156
|
});
|
|
23862
24157
|
return { command, exitCode: result2.code, signal: result2.signal, output };
|
|
23863
24158
|
}
|
|
@@ -26047,10 +26342,10 @@ __export(camouflage_view_exports, {
|
|
|
26047
26342
|
toolSummary: () => toolSummary,
|
|
26048
26343
|
validateCommandName: () => validateCommandName
|
|
26049
26344
|
});
|
|
26050
|
-
import { execFileSync as
|
|
26051
|
-
import { readdir as
|
|
26345
|
+
import { execFileSync as execFileSync3, spawn as spawn10 } from "child_process";
|
|
26346
|
+
import { readdir as readdir8 } from "fs/promises";
|
|
26052
26347
|
import { homedir as homedir26 } from "os";
|
|
26053
|
-
import { join as
|
|
26348
|
+
import { join as join44, resolve as resolve16 } from "path";
|
|
26054
26349
|
async function loadSdk() {
|
|
26055
26350
|
const sdk = await import("camouflage-tui").catch((err) => {
|
|
26056
26351
|
throw new CamouflageUnavailable(`camouflage-tui is not installed (${err.message})`);
|
|
@@ -26139,14 +26434,14 @@ async function runCamouflageView(opts2) {
|
|
|
26139
26434
|
}
|
|
26140
26435
|
}
|
|
26141
26436
|
function runShell2(command) {
|
|
26142
|
-
return new Promise((
|
|
26437
|
+
return new Promise((resolve20) => {
|
|
26143
26438
|
const { shell, args } = getShellCommand();
|
|
26144
26439
|
const child = spawn10(shell, [...args, command], { env: process.env });
|
|
26145
26440
|
let out = "";
|
|
26146
26441
|
child.stdout?.on("data", (c) => out += c.toString("utf8"));
|
|
26147
26442
|
child.stderr?.on("data", (c) => out += c.toString("utf8"));
|
|
26148
|
-
child.on("close", (code) =>
|
|
26149
|
-
child.on("error", (err) =>
|
|
26443
|
+
child.on("close", (code) => resolve20({ ok: code === 0, output: out || (code === 0 ? "" : `Exit code: ${code}`) }));
|
|
26444
|
+
child.on("error", (err) => resolve20({ ok: false, output: err.message }));
|
|
26150
26445
|
});
|
|
26151
26446
|
}
|
|
26152
26447
|
function syncSlashCommands(custom, lastKey, send) {
|
|
@@ -26229,10 +26524,10 @@ function truncateText(s, max) {
|
|
|
26229
26524
|
async function listMentionDir(cwd, query) {
|
|
26230
26525
|
const exact = query === "~" || query === "." || query === ".." || query.endsWith("/..");
|
|
26231
26526
|
const dir = exact ? `${query}/` : query.slice(0, query.lastIndexOf("/") + 1);
|
|
26232
|
-
const expanded = dir.startsWith("~") ?
|
|
26233
|
-
const target =
|
|
26527
|
+
const expanded = dir.startsWith("~") ? join44(homedir26(), dir.slice(1)) : dir;
|
|
26528
|
+
const target = resolve16(cwd, expanded || ".");
|
|
26234
26529
|
try {
|
|
26235
|
-
const items = await
|
|
26530
|
+
const items = await readdir8(target, { withFileTypes: true });
|
|
26236
26531
|
const entries = items.filter((d) => !d.name.startsWith(".")).map((d) => ({ name: d.name, isDir: d.isDirectory() })).sort((a, b) => a.isDir !== b.isDir ? a.isDir ? -1 : 1 : a.name.localeCompare(b.name)).slice(0, 300).map((d) => `${dir}${d.name}${d.isDir ? "/" : ""}`);
|
|
26237
26532
|
return { dir, entries };
|
|
26238
26533
|
} catch {
|
|
@@ -26315,14 +26610,14 @@ function shortPath(p) {
|
|
|
26315
26610
|
}
|
|
26316
26611
|
function gitBranch(cwd) {
|
|
26317
26612
|
try {
|
|
26318
|
-
return
|
|
26613
|
+
return execFileSync3("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd, encoding: "utf8", timeout: 500, stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
26319
26614
|
} catch {
|
|
26320
26615
|
return "";
|
|
26321
26616
|
}
|
|
26322
26617
|
}
|
|
26323
26618
|
function listFiles(cwd) {
|
|
26324
26619
|
try {
|
|
26325
|
-
const out =
|
|
26620
|
+
const out = execFileSync3("git", ["ls-files", "--cached", "--others", "--exclude-standard"], {
|
|
26326
26621
|
cwd,
|
|
26327
26622
|
encoding: "utf8",
|
|
26328
26623
|
timeout: 2e3,
|
|
@@ -29221,19 +29516,19 @@ function usePermissionController(getMode, onPlanModeBlocked) {
|
|
|
29221
29516
|
const onPlanModeBlockedRef = useRef3(onPlanModeBlocked);
|
|
29222
29517
|
onPlanModeBlockedRef.current = onPlanModeBlocked;
|
|
29223
29518
|
const askPermission = useCallback2(
|
|
29224
|
-
(req, askOpts) => new Promise((
|
|
29519
|
+
(req, askOpts) => new Promise((resolve20) => {
|
|
29225
29520
|
const outcome = decidePermission(req, getModeRef.current(), askOpts);
|
|
29226
29521
|
if (outcome.kind === "resolve") {
|
|
29227
|
-
|
|
29522
|
+
resolve20(outcome.decision);
|
|
29228
29523
|
return;
|
|
29229
29524
|
}
|
|
29230
29525
|
if (outcome.kind === "plan_blocked") {
|
|
29231
29526
|
onPlanModeBlockedRef.current(outcome.toolName);
|
|
29232
|
-
|
|
29527
|
+
resolve20(AUTO_DENY);
|
|
29233
29528
|
return;
|
|
29234
29529
|
}
|
|
29235
|
-
resolveRef.current =
|
|
29236
|
-
setPending({ tool: req.tool, args: req.args, resolve:
|
|
29530
|
+
resolveRef.current = resolve20;
|
|
29531
|
+
setPending({ tool: req.tool, args: req.args, resolve: resolve20 });
|
|
29237
29532
|
}),
|
|
29238
29533
|
[]
|
|
29239
29534
|
);
|
|
@@ -29578,9 +29873,9 @@ var init_queue_plan_picker = __esm({
|
|
|
29578
29873
|
});
|
|
29579
29874
|
|
|
29580
29875
|
// src/agent/jev-context.ts
|
|
29581
|
-
import { execFileSync as
|
|
29582
|
-
import { readFile as
|
|
29583
|
-
import { basename as basename8, join as
|
|
29876
|
+
import { execFileSync as execFileSync4 } from "child_process";
|
|
29877
|
+
import { readFile as readFile30 } from "fs/promises";
|
|
29878
|
+
import { basename as basename8, join as join45, resolve as resolve17 } from "path";
|
|
29584
29879
|
function messageText(message2) {
|
|
29585
29880
|
if (typeof message2.content === "string") return message2.content.trim();
|
|
29586
29881
|
if (!Array.isArray(message2.content)) return "";
|
|
@@ -29591,18 +29886,18 @@ function redactCommonSecrets(text) {
|
|
|
29591
29886
|
}
|
|
29592
29887
|
function projectRoot(cwd) {
|
|
29593
29888
|
try {
|
|
29594
|
-
return
|
|
29889
|
+
return execFileSync4("git", ["-C", cwd, "rev-parse", "--show-toplevel"], {
|
|
29595
29890
|
encoding: "utf8",
|
|
29596
29891
|
stdio: ["ignore", "pipe", "ignore"],
|
|
29597
29892
|
timeout: 1e3
|
|
29598
29893
|
}).trim();
|
|
29599
29894
|
} catch {
|
|
29600
|
-
return
|
|
29895
|
+
return resolve17(cwd);
|
|
29601
29896
|
}
|
|
29602
29897
|
}
|
|
29603
29898
|
async function readPackageMetadata(root) {
|
|
29604
29899
|
try {
|
|
29605
|
-
const parsed = JSON.parse(await
|
|
29900
|
+
const parsed = JSON.parse(await readFile30(join45(root, "package.json"), "utf8"));
|
|
29606
29901
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
29607
29902
|
const pkg = parsed;
|
|
29608
29903
|
const metadata = {};
|
|
@@ -29619,7 +29914,7 @@ async function readPackageMetadata(root) {
|
|
|
29619
29914
|
async function readLicenseEvidence(root) {
|
|
29620
29915
|
for (const name of ["LICENSE", "LICENSE.md", "LICENSE.txt", "LICENCE", "COPYING"]) {
|
|
29621
29916
|
try {
|
|
29622
|
-
const content = (await
|
|
29917
|
+
const content = (await readFile30(join45(root, name), "utf8")).trim();
|
|
29623
29918
|
if (content) return { source: `project license (${name})`, content: content.slice(0, 700) };
|
|
29624
29919
|
} catch {
|
|
29625
29920
|
}
|
|
@@ -29652,7 +29947,7 @@ async function buildJevContext(question, messages, cwd = process.cwd()) {
|
|
|
29652
29947
|
conversationRemaining -= source.length + content.length + 2;
|
|
29653
29948
|
}
|
|
29654
29949
|
}
|
|
29655
|
-
const currentDirectory = basename8(
|
|
29950
|
+
const currentDirectory = basename8(resolve17(cwd));
|
|
29656
29951
|
const escapedDirectory = currentDirectory.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
29657
29952
|
const namesCurrentDirectory = currentDirectory.length >= 5 && !/^(?:agent|app|code|lib|project|repo|src|test|tests|workspace)$/i.test(currentDirectory) && new RegExp(`\\b${escapedDirectory}\\b`, "i").test(question);
|
|
29658
29953
|
if (CURRENT_PROJECT_REFERENCE.test(question) || namesCurrentDirectory) {
|
|
@@ -30701,8 +30996,8 @@ var init_frontmatter = __esm({
|
|
|
30701
30996
|
});
|
|
30702
30997
|
|
|
30703
30998
|
// src/skills/loader.ts
|
|
30704
|
-
import { readFile as
|
|
30705
|
-
import { join as
|
|
30999
|
+
import { readFile as readFile31, readdir as readdir9, stat as stat11 } from "fs/promises";
|
|
31000
|
+
import { join as join46, extname } from "path";
|
|
30706
31001
|
function normalizeManifest(raw, filePath) {
|
|
30707
31002
|
const name = typeof raw.name === "string" ? raw.name : "";
|
|
30708
31003
|
const description = typeof raw.description === "string" ? raw.description : "";
|
|
@@ -30716,7 +31011,7 @@ function normalizeManifest(raw, filePath) {
|
|
|
30716
31011
|
return { name, description, match, scope, priority, enabled: enabled2 };
|
|
30717
31012
|
}
|
|
30718
31013
|
async function loadSkillFile(filePath) {
|
|
30719
|
-
const raw = await
|
|
31014
|
+
const raw = await readFile31(filePath, "utf-8");
|
|
30720
31015
|
const parsed = parseFrontmatter(raw);
|
|
30721
31016
|
const manifest = normalizeManifest(parsed.data, filePath);
|
|
30722
31017
|
const body = parsed.content.trim();
|
|
@@ -30735,11 +31030,11 @@ async function loadSkillFile(filePath) {
|
|
|
30735
31030
|
}
|
|
30736
31031
|
async function loadSkillsFromDir(dirPath) {
|
|
30737
31032
|
try {
|
|
30738
|
-
const entries = await
|
|
31033
|
+
const entries = await readdir9(dirPath);
|
|
30739
31034
|
const files = [];
|
|
30740
31035
|
for (const entry of entries) {
|
|
30741
|
-
const full =
|
|
30742
|
-
const s = await
|
|
31036
|
+
const full = join46(dirPath, entry);
|
|
31037
|
+
const s = await stat11(full);
|
|
30743
31038
|
if (s.isFile() && extname(entry) === ".md") {
|
|
30744
31039
|
files.push(full);
|
|
30745
31040
|
}
|
|
@@ -30766,12 +31061,12 @@ var init_loader = __esm({
|
|
|
30766
31061
|
});
|
|
30767
31062
|
|
|
30768
31063
|
// src/skills/manager.ts
|
|
30769
|
-
import { mkdir as
|
|
30770
|
-
import { join as
|
|
31064
|
+
import { mkdir as mkdir18, writeFile as writeFile16, unlink as unlink4, readFile as readFile32 } from "fs/promises";
|
|
31065
|
+
import { join as join47 } from "path";
|
|
30771
31066
|
function getSkillDirs(cwd) {
|
|
30772
31067
|
return {
|
|
30773
|
-
projectDir:
|
|
30774
|
-
globalDir:
|
|
31068
|
+
projectDir: join47(cwd, ".kimiflare", "skills"),
|
|
31069
|
+
globalDir: join47(process.env.HOME ?? "", ".config", "kimiflare", "skills")
|
|
30775
31070
|
};
|
|
30776
31071
|
}
|
|
30777
31072
|
async function listAllSkills(cwd) {
|
|
@@ -30785,7 +31080,7 @@ async function listAllSkills(cwd) {
|
|
|
30785
31080
|
async function createSkill(opts2) {
|
|
30786
31081
|
const dirs = getSkillDirs(opts2.cwd);
|
|
30787
31082
|
const dir = opts2.scope === "project" ? dirs.projectDir : dirs.globalDir;
|
|
30788
|
-
const filepath =
|
|
31083
|
+
const filepath = join47(dir, `${opts2.name}.md`);
|
|
30789
31084
|
const frontmatter = {
|
|
30790
31085
|
name: opts2.name,
|
|
30791
31086
|
enabled: true,
|
|
@@ -30806,8 +31101,8 @@ ${yaml}
|
|
|
30806
31101
|
|
|
30807
31102
|
Add your instructions here.
|
|
30808
31103
|
`;
|
|
30809
|
-
await
|
|
30810
|
-
await
|
|
31104
|
+
await mkdir18(dir, { recursive: true });
|
|
31105
|
+
await writeFile16(filepath, content, "utf8");
|
|
30811
31106
|
return { filepath };
|
|
30812
31107
|
}
|
|
30813
31108
|
async function deleteSkill(name, cwd) {
|
|
@@ -30821,7 +31116,7 @@ async function setSkillEnabled(name, enabled2, cwd) {
|
|
|
30821
31116
|
const all = await listAllSkills(cwd);
|
|
30822
31117
|
const skill = all.project.find((s) => s.name === name) ?? all.global.find((s) => s.name === name);
|
|
30823
31118
|
if (!skill) throw new Error(`skill "${name}" not found`);
|
|
30824
|
-
const raw = await
|
|
31119
|
+
const raw = await readFile32(skill.filePath, "utf-8");
|
|
30825
31120
|
const parsed = parseFrontmatter(raw);
|
|
30826
31121
|
parsed.data.enabled = enabled2;
|
|
30827
31122
|
const yaml = Object.entries(parsed.data).map(([k, v]) => {
|
|
@@ -30833,7 +31128,7 @@ ${v.map((item) => ` - ${item}`).join("\n")}`;
|
|
|
30833
31128
|
${yaml}
|
|
30834
31129
|
---
|
|
30835
31130
|
${parsed.content}`;
|
|
30836
|
-
await
|
|
31131
|
+
await writeFile16(skill.filePath, content, "utf8");
|
|
30837
31132
|
return { filepath: skill.filePath };
|
|
30838
31133
|
}
|
|
30839
31134
|
async function findSkillFile(name, cwd) {
|
|
@@ -31093,15 +31388,15 @@ var tui_report_exports = {};
|
|
|
31093
31388
|
__export(tui_report_exports, {
|
|
31094
31389
|
getCategoryReportText: () => getCategoryReportText
|
|
31095
31390
|
});
|
|
31096
|
-
import { readFile as
|
|
31097
|
-
import { join as
|
|
31391
|
+
import { readFile as readFile33 } from "fs/promises";
|
|
31392
|
+
import { join as join48 } from "path";
|
|
31098
31393
|
import { homedir as homedir27 } from "os";
|
|
31099
31394
|
function usageDir3() {
|
|
31100
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
31101
|
-
return
|
|
31395
|
+
const xdg = process.env.XDG_DATA_HOME || join48(homedir27(), ".local", "share");
|
|
31396
|
+
return join48(xdg, "kimiflare");
|
|
31102
31397
|
}
|
|
31103
31398
|
function usagePath4() {
|
|
31104
|
-
return
|
|
31399
|
+
return join48(usageDir3(), "usage.json");
|
|
31105
31400
|
}
|
|
31106
31401
|
function today3() {
|
|
31107
31402
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -31113,7 +31408,7 @@ function daysAgo2(n) {
|
|
|
31113
31408
|
}
|
|
31114
31409
|
async function loadLog3() {
|
|
31115
31410
|
try {
|
|
31116
|
-
const raw = await
|
|
31411
|
+
const raw = await readFile33(usagePath4(), "utf8");
|
|
31117
31412
|
return JSON.parse(raw);
|
|
31118
31413
|
} catch {
|
|
31119
31414
|
return { version: 1, days: [], sessions: [] };
|
|
@@ -31170,7 +31465,7 @@ var init_tui_report = __esm({
|
|
|
31170
31465
|
});
|
|
31171
31466
|
|
|
31172
31467
|
// src/ui/slash-commands.ts
|
|
31173
|
-
import { join as
|
|
31468
|
+
import { join as join49 } from "path";
|
|
31174
31469
|
import QRCode from "qrcode";
|
|
31175
31470
|
function executeFreshStart(ctx, planText, overrideMode, opts2 = {}) {
|
|
31176
31471
|
const oldSessionId = ctx.sessionIdRef.current;
|
|
@@ -31641,7 +31936,7 @@ auto (default) lets the coordinator assess substantial tasks and delegate indepe
|
|
|
31641
31936
|
const context = noContext ? [] : await buildJevContext(question.prompt, ctx.messagesRef.current, process.cwd());
|
|
31642
31937
|
const receipt = formatJevContextReceipt(context, showContext);
|
|
31643
31938
|
setResult(eventKey, { kind: "info", key: eventKey, text: `Jev is evaluating \xB7 ${receipt}`, pending: true });
|
|
31644
|
-
await new Promise((
|
|
31939
|
+
await new Promise((resolve20) => setTimeout(resolve20, 0));
|
|
31645
31940
|
const answer = await askJev(apiKey, question, { context });
|
|
31646
31941
|
const presentation = presentJevAnswer(question, answer);
|
|
31647
31942
|
setResult(eventKey, {
|
|
@@ -32102,7 +32397,7 @@ ${lines.join("\n")}` }]);
|
|
|
32102
32397
|
void (async () => {
|
|
32103
32398
|
try {
|
|
32104
32399
|
const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
|
|
32105
|
-
const file = await loadSession(
|
|
32400
|
+
const file = await loadSession(join49(sessionsDir3(), `${currentId}.json`));
|
|
32106
32401
|
const cps = file.checkpoints ?? [];
|
|
32107
32402
|
if (cps.length === 0) {
|
|
32108
32403
|
setEvents((e) => [...e, { kind: "info", key: mkKey2(), text: "no checkpoints in this session" }]);
|
|
@@ -32147,7 +32442,7 @@ ${lines.join("\n")}` }]);
|
|
|
32147
32442
|
try {
|
|
32148
32443
|
ctx.ensureSessionId();
|
|
32149
32444
|
const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
|
|
32150
|
-
const filePath =
|
|
32445
|
+
const filePath = join49(sessionsDir3(), `${ctx.sessionIdRef.current}.json`);
|
|
32151
32446
|
await addCheckpoint(filePath, cp);
|
|
32152
32447
|
setEvents((e) => [...e, { kind: "info", key: mkKey2(), text: `checkpoint saved: "${label}"` }]);
|
|
32153
32448
|
} catch (e) {
|
|
@@ -33203,9 +33498,9 @@ async function startLoopbackListener(opts2 = {}) {
|
|
|
33203
33498
|
rejectCode(e);
|
|
33204
33499
|
finish();
|
|
33205
33500
|
}
|
|
33206
|
-
await new Promise((
|
|
33501
|
+
await new Promise((resolve20, reject) => {
|
|
33207
33502
|
server.once("error", reject);
|
|
33208
|
-
server.listen(0, "127.0.0.1", () =>
|
|
33503
|
+
server.listen(0, "127.0.0.1", () => resolve20());
|
|
33209
33504
|
});
|
|
33210
33505
|
const address = server.address();
|
|
33211
33506
|
const port = typeof address === "object" && address ? address.port : 0;
|
|
@@ -33631,15 +33926,15 @@ var init_frontmatter2 = __esm({
|
|
|
33631
33926
|
});
|
|
33632
33927
|
|
|
33633
33928
|
// src/commands/loader.ts
|
|
33634
|
-
import { open, realpath as
|
|
33929
|
+
import { open, realpath as realpath7 } from "fs/promises";
|
|
33635
33930
|
import { homedir as homedir28 } from "os";
|
|
33636
|
-
import { join as
|
|
33931
|
+
import { join as join50, relative as relative11, sep as sep7 } from "path";
|
|
33637
33932
|
function projectCommandsDir(cwd = process.cwd()) {
|
|
33638
|
-
return
|
|
33933
|
+
return join50(cwd, ".kimiflare", "commands");
|
|
33639
33934
|
}
|
|
33640
33935
|
function globalCommandsDir() {
|
|
33641
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
33642
|
-
return
|
|
33936
|
+
const xdg = process.env.XDG_CONFIG_HOME || join50(homedir28(), ".config");
|
|
33937
|
+
return join50(xdg, "kimiflare", "commands");
|
|
33643
33938
|
}
|
|
33644
33939
|
async function loadCustomCommands(cwd = process.cwd()) {
|
|
33645
33940
|
const warnings = [];
|
|
@@ -33678,7 +33973,7 @@ async function loadCustomCommands(cwd = process.cwd()) {
|
|
|
33678
33973
|
async function resolveSafeDir(dir, source, cwd, warnings) {
|
|
33679
33974
|
let realDir;
|
|
33680
33975
|
try {
|
|
33681
|
-
realDir = await
|
|
33976
|
+
realDir = await realpath7(dir);
|
|
33682
33977
|
} catch (err) {
|
|
33683
33978
|
const code = err.code;
|
|
33684
33979
|
if (code !== "ENOENT" && code !== "ENOTDIR") {
|
|
@@ -33689,11 +33984,11 @@ async function resolveSafeDir(dir, source, cwd, warnings) {
|
|
|
33689
33984
|
if (source === "project") {
|
|
33690
33985
|
let realCwd;
|
|
33691
33986
|
try {
|
|
33692
|
-
realCwd = await
|
|
33987
|
+
realCwd = await realpath7(cwd);
|
|
33693
33988
|
} catch {
|
|
33694
33989
|
return null;
|
|
33695
33990
|
}
|
|
33696
|
-
const rel =
|
|
33991
|
+
const rel = relative11(realCwd, realDir);
|
|
33697
33992
|
if (rel !== "" && isPathOutside(rel)) {
|
|
33698
33993
|
warnings.push(`commands dir ${dir} escapes workspace via symlink \u2014 skipped`);
|
|
33699
33994
|
return null;
|
|
@@ -33768,10 +34063,10 @@ async function loadOne(file, rootDir, source, warnings) {
|
|
|
33768
34063
|
return cmd;
|
|
33769
34064
|
}
|
|
33770
34065
|
function filenameToCommandName(file, rootDir) {
|
|
33771
|
-
const rel =
|
|
34066
|
+
const rel = relative11(rootDir, file);
|
|
33772
34067
|
if (!rel || isPathOutside(rel)) return null;
|
|
33773
34068
|
const noExt = rel.replace(/\.md$/i, "");
|
|
33774
|
-
const parts = noExt.split(
|
|
34069
|
+
const parts = noExt.split(sep7).filter((p) => p.length > 0);
|
|
33775
34070
|
if (parts.length === 0) return null;
|
|
33776
34071
|
if (parts.some((p) => !/^[\w.-]+$/.test(p))) return null;
|
|
33777
34072
|
return parts.join("/");
|
|
@@ -33791,8 +34086,8 @@ var init_loader2 = __esm({
|
|
|
33791
34086
|
|
|
33792
34087
|
// src/commands/renderer.ts
|
|
33793
34088
|
import { exec } from "child_process";
|
|
33794
|
-
import { open as open2, realpath as
|
|
33795
|
-
import { isAbsolute as
|
|
34089
|
+
import { open as open2, realpath as realpath8 } from "fs/promises";
|
|
34090
|
+
import { isAbsolute as isAbsolute8, relative as relative12, resolve as resolvePathJoin, basename as pathBasename } from "path";
|
|
33796
34091
|
import { promisify as promisify9 } from "util";
|
|
33797
34092
|
function tokenizeArgs(s) {
|
|
33798
34093
|
return [...s.matchAll(ARG_TOKEN_RE)].map((match) => {
|
|
@@ -33883,7 +34178,7 @@ async function replaceFiles(prompt, warnings, cmd, cwd, maxFileBytes) {
|
|
|
33883
34178
|
return "" + trailing;
|
|
33884
34179
|
});
|
|
33885
34180
|
}
|
|
33886
|
-
const realCwd = await
|
|
34181
|
+
const realCwd = await realpath8(cwd).catch(() => cwd);
|
|
33887
34182
|
const replacements = await Promise.all(
|
|
33888
34183
|
matches.map(async (match) => {
|
|
33889
34184
|
const rawPath = match[1] ?? "";
|
|
@@ -33892,23 +34187,23 @@ async function replaceFiles(prompt, warnings, cmd, cwd, maxFileBytes) {
|
|
|
33892
34187
|
warnings.push(`file inclusion blocked: @${rawPath} \u2014 secret file pattern`);
|
|
33893
34188
|
return "";
|
|
33894
34189
|
}
|
|
33895
|
-
if (
|
|
34190
|
+
if (isAbsolute8(rawPath) || rawPath.startsWith("~")) {
|
|
33896
34191
|
warnings.push(`file inclusion skipped: @${rawPath} \u2014 outside workspace`);
|
|
33897
34192
|
return "";
|
|
33898
34193
|
}
|
|
33899
34194
|
const resolved = resolvePathJoin(cwd, rawPath);
|
|
33900
|
-
if (isPathOutside(
|
|
34195
|
+
if (isPathOutside(relative12(cwd, resolved))) {
|
|
33901
34196
|
warnings.push(`file inclusion skipped: @${rawPath} \u2014 outside workspace`);
|
|
33902
34197
|
return "";
|
|
33903
34198
|
}
|
|
33904
34199
|
let real;
|
|
33905
34200
|
try {
|
|
33906
|
-
real = await
|
|
34201
|
+
real = await realpath8(resolved);
|
|
33907
34202
|
} catch (error) {
|
|
33908
34203
|
warnings.push(`file inclusion failed: @${rawPath} \u2014 ${message(error)}`);
|
|
33909
34204
|
return "";
|
|
33910
34205
|
}
|
|
33911
|
-
if (isPathOutside(
|
|
34206
|
+
if (isPathOutside(relative12(realCwd, real))) {
|
|
33912
34207
|
warnings.push(`file inclusion skipped: @${rawPath} \u2014 symlink escapes workspace`);
|
|
33913
34208
|
return "";
|
|
33914
34209
|
}
|
|
@@ -34021,11 +34316,11 @@ var init_wcag = __esm({
|
|
|
34021
34316
|
});
|
|
34022
34317
|
|
|
34023
34318
|
// src/ui/theme-loader.ts
|
|
34024
|
-
import { readFile as
|
|
34025
|
-
import { join as
|
|
34319
|
+
import { readFile as readFile34, readdir as readdir10 } from "fs/promises";
|
|
34320
|
+
import { join as join51 } from "path";
|
|
34026
34321
|
import { homedir as homedir29 } from "os";
|
|
34027
34322
|
function projectThemesDir(cwd = process.cwd()) {
|
|
34028
|
-
return
|
|
34323
|
+
return join51(cwd, ".kimiflare", "themes");
|
|
34029
34324
|
}
|
|
34030
34325
|
function isHexColor(c) {
|
|
34031
34326
|
return /^#[0-9a-fA-F]{6}$/.test(c);
|
|
@@ -34109,15 +34404,15 @@ async function loadThemesFromDir(dir, source) {
|
|
|
34109
34404
|
const errors = [];
|
|
34110
34405
|
let files;
|
|
34111
34406
|
try {
|
|
34112
|
-
files = await
|
|
34407
|
+
files = await readdir10(dir);
|
|
34113
34408
|
} catch {
|
|
34114
34409
|
return { themes, errors };
|
|
34115
34410
|
}
|
|
34116
34411
|
for (const file of files.filter((f) => f.endsWith(".json"))) {
|
|
34117
|
-
const path =
|
|
34412
|
+
const path = join51(dir, file);
|
|
34118
34413
|
let raw;
|
|
34119
34414
|
try {
|
|
34120
|
-
raw = await
|
|
34415
|
+
raw = await readFile34(path, "utf-8");
|
|
34121
34416
|
} catch (e) {
|
|
34122
34417
|
errors.push(`${path}: ${e instanceof Error ? e.message : String(e)}`);
|
|
34123
34418
|
continue;
|
|
@@ -34263,8 +34558,8 @@ var init_theme_loader = __esm({
|
|
|
34263
34558
|
"use strict";
|
|
34264
34559
|
init_wcag();
|
|
34265
34560
|
init_theme();
|
|
34266
|
-
USER_THEMES_DIR =
|
|
34267
|
-
process.env.XDG_CONFIG_HOME ||
|
|
34561
|
+
USER_THEMES_DIR = join51(
|
|
34562
|
+
process.env.XDG_CONFIG_HOME || join51(homedir29(), ".config"),
|
|
34268
34563
|
"kimiflare",
|
|
34269
34564
|
"themes"
|
|
34270
34565
|
);
|
|
@@ -36795,9 +37090,9 @@ var init_resume_progress = __esm({
|
|
|
36795
37090
|
});
|
|
36796
37091
|
|
|
36797
37092
|
// src/agent/supervisor.ts
|
|
36798
|
-
import { readdir as
|
|
37093
|
+
import { readdir as readdir11, readFile as readFile35, stat as stat12 } from "fs/promises";
|
|
36799
37094
|
import { createHash as createHash7 } from "crypto";
|
|
36800
|
-
import { resolve as
|
|
37095
|
+
import { resolve as resolve18, join as join52 } from "path";
|
|
36801
37096
|
var TurnSupervisor;
|
|
36802
37097
|
var init_supervisor = __esm({
|
|
36803
37098
|
"src/agent/supervisor.ts"() {
|
|
@@ -37187,12 +37482,12 @@ var init_input_handlers = __esm({
|
|
|
37187
37482
|
|
|
37188
37483
|
// src/init/context-generator.ts
|
|
37189
37484
|
import { existsSync as existsSync9, statSync as statSync6 } from "fs";
|
|
37190
|
-
import { join as
|
|
37485
|
+
import { join as join53 } from "path";
|
|
37191
37486
|
function detectFlavor(cwd) {
|
|
37192
37487
|
for (const [flavor, signatures] of Object.entries(FLAVOR_SIGNATURES)) {
|
|
37193
37488
|
if (flavor === "generic") continue;
|
|
37194
37489
|
for (const sig of signatures) {
|
|
37195
|
-
const path =
|
|
37490
|
+
const path = join53(cwd, sig);
|
|
37196
37491
|
if (sig.includes("*")) {
|
|
37197
37492
|
try {
|
|
37198
37493
|
const parts = sig.split("*");
|
|
@@ -37213,14 +37508,14 @@ function detectFlavor(cwd) {
|
|
|
37213
37508
|
}
|
|
37214
37509
|
function findFile(cwd, candidates) {
|
|
37215
37510
|
for (const c of candidates) {
|
|
37216
|
-
if (existsSync9(
|
|
37511
|
+
if (existsSync9(join53(cwd, c))) return c;
|
|
37217
37512
|
}
|
|
37218
37513
|
return null;
|
|
37219
37514
|
}
|
|
37220
37515
|
function findSourceRoots(cwd) {
|
|
37221
37516
|
const roots = [];
|
|
37222
37517
|
for (const r of SOURCE_ROOT_CANDIDATES) {
|
|
37223
|
-
const p =
|
|
37518
|
+
const p = join53(cwd, r);
|
|
37224
37519
|
try {
|
|
37225
37520
|
const s = statSync6(p);
|
|
37226
37521
|
if (s.isDirectory()) roots.push(r);
|
|
@@ -37231,9 +37526,9 @@ function findSourceRoots(cwd) {
|
|
|
37231
37526
|
}
|
|
37232
37527
|
function findCiConfig(cwd) {
|
|
37233
37528
|
for (const c of CI_PATHS) {
|
|
37234
|
-
if (existsSync9(
|
|
37529
|
+
if (existsSync9(join53(cwd, c))) {
|
|
37235
37530
|
try {
|
|
37236
|
-
const s = statSync6(
|
|
37531
|
+
const s = statSync6(join53(cwd, c));
|
|
37237
37532
|
return s.isDirectory() ? c : c;
|
|
37238
37533
|
} catch {
|
|
37239
37534
|
}
|
|
@@ -37370,7 +37665,7 @@ function analyzeProject(cwd) {
|
|
|
37370
37665
|
ciConfig: findCiConfig(cwd),
|
|
37371
37666
|
readme: findFile(cwd, ["README.md", "README.rst", "README.txt", "Readme.md"]),
|
|
37372
37667
|
sourceRoots: findSourceRoots(cwd),
|
|
37373
|
-
hasGit: existsSync9(
|
|
37668
|
+
hasGit: existsSync9(join53(cwd, ".git"))
|
|
37374
37669
|
};
|
|
37375
37670
|
}
|
|
37376
37671
|
function bashDiscoveryCommands(profile) {
|
|
@@ -37535,7 +37830,7 @@ Aim for 100\u2013200 lines total. Use markdown tables where they save space.
|
|
|
37535
37830
|
}
|
|
37536
37831
|
function buildInitPrompt(cwd) {
|
|
37537
37832
|
const existingName = ["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].find(
|
|
37538
|
-
(n) => existsSync9(
|
|
37833
|
+
(n) => existsSync9(join53(cwd, n))
|
|
37539
37834
|
);
|
|
37540
37835
|
const isRefresh = existingName !== void 0;
|
|
37541
37836
|
const targetFilename = existingName ?? "AGENTS.md";
|
|
@@ -37619,7 +37914,7 @@ var init_context_generator = __esm({
|
|
|
37619
37914
|
|
|
37620
37915
|
// src/init/run-init.ts
|
|
37621
37916
|
import { existsSync as existsSync10 } from "fs";
|
|
37622
|
-
import { join as
|
|
37917
|
+
import { join as join54 } from "path";
|
|
37623
37918
|
async function runInit(deps) {
|
|
37624
37919
|
const {
|
|
37625
37920
|
cfg,
|
|
@@ -37712,7 +38007,7 @@ async function runInit(deps) {
|
|
|
37712
38007
|
lspManagerRef.current.notifyChange(path, content);
|
|
37713
38008
|
} else {
|
|
37714
38009
|
void import("fs/promises").then(
|
|
37715
|
-
({ readFile:
|
|
38010
|
+
({ readFile: readFile37 }) => readFile37(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
|
|
37716
38011
|
})
|
|
37717
38012
|
);
|
|
37718
38013
|
}
|
|
@@ -37817,7 +38112,7 @@ async function runInit(deps) {
|
|
|
37817
38112
|
}
|
|
37818
38113
|
}
|
|
37819
38114
|
});
|
|
37820
|
-
if (existsSync10(
|
|
38115
|
+
if (existsSync10(join54(cwd, targetFilename))) {
|
|
37821
38116
|
if (cacheStableRef.current) {
|
|
37822
38117
|
messagesRef.current[1] = {
|
|
37823
38118
|
role: "system",
|
|
@@ -37909,11 +38204,11 @@ var init_run_init = __esm({
|
|
|
37909
38204
|
});
|
|
37910
38205
|
|
|
37911
38206
|
// src/skills/discovery.ts
|
|
37912
|
-
import { readdir as
|
|
37913
|
-
import { join as
|
|
38207
|
+
import { readdir as readdir12, stat as stat13, readFile as readFile36 } from "fs/promises";
|
|
38208
|
+
import { join as join55, extname as extname2 } from "path";
|
|
37914
38209
|
async function dirExists(path) {
|
|
37915
38210
|
try {
|
|
37916
|
-
const s = await
|
|
38211
|
+
const s = await stat13(path);
|
|
37917
38212
|
return s.isDirectory();
|
|
37918
38213
|
} catch {
|
|
37919
38214
|
return false;
|
|
@@ -37921,7 +38216,7 @@ async function dirExists(path) {
|
|
|
37921
38216
|
}
|
|
37922
38217
|
async function fileExists(path) {
|
|
37923
38218
|
try {
|
|
37924
|
-
const s = await
|
|
38219
|
+
const s = await stat13(path);
|
|
37925
38220
|
return s.isFile();
|
|
37926
38221
|
} catch {
|
|
37927
38222
|
return false;
|
|
@@ -37929,25 +38224,25 @@ async function fileExists(path) {
|
|
|
37929
38224
|
}
|
|
37930
38225
|
async function scanSkillDir(dirPath, source) {
|
|
37931
38226
|
if (!await dirExists(dirPath)) return [];
|
|
37932
|
-
const entries = await
|
|
38227
|
+
const entries = await readdir12(dirPath, { withFileTypes: true });
|
|
37933
38228
|
const files = [];
|
|
37934
38229
|
for (const entry of entries) {
|
|
37935
38230
|
if (!entry.isFile()) continue;
|
|
37936
38231
|
if (!SKILL_EXTENSIONS.has(extname2(entry.name))) continue;
|
|
37937
|
-
files.push({ filePath:
|
|
38232
|
+
files.push({ filePath: join55(dirPath, entry.name), source });
|
|
37938
38233
|
}
|
|
37939
38234
|
return files;
|
|
37940
38235
|
}
|
|
37941
38236
|
async function discoverSkills(cwd) {
|
|
37942
|
-
const agentsSkills = await scanSkillDir(
|
|
37943
|
-
const agentsMd = await fileExists(
|
|
37944
|
-
const githubSkills = await scanSkillDir(
|
|
37945
|
-
const kimiflareSkills = await scanSkillDir(
|
|
38237
|
+
const agentsSkills = await scanSkillDir(join55(cwd, ".agents", "skills"), "agents");
|
|
38238
|
+
const agentsMd = await fileExists(join55(cwd, "AGENTS.md")) ? [{ filePath: join55(cwd, "AGENTS.md"), source: "agents-md" }] : [];
|
|
38239
|
+
const githubSkills = await scanSkillDir(join55(cwd, ".github", "skills"), "github");
|
|
38240
|
+
const kimiflareSkills = await scanSkillDir(join55(cwd, ".kimiflare", "skills"), "kimiflare");
|
|
37946
38241
|
const ordered = [...agentsSkills, ...agentsMd, ...githubSkills, ...kimiflareSkills];
|
|
37947
38242
|
return ordered;
|
|
37948
38243
|
}
|
|
37949
38244
|
async function readSkillFile(filePath) {
|
|
37950
|
-
const bytes = await
|
|
38245
|
+
const bytes = await readFile36(filePath);
|
|
37951
38246
|
return { bytes, text: bytes.toString("utf-8") };
|
|
37952
38247
|
}
|
|
37953
38248
|
var SKILL_EXTENSIONS;
|
|
@@ -38153,7 +38448,7 @@ var init_skills = __esm({
|
|
|
38153
38448
|
|
|
38154
38449
|
// src/ui/run-startup-tasks.ts
|
|
38155
38450
|
import { existsSync as existsSync11 } from "fs";
|
|
38156
|
-
import { join as
|
|
38451
|
+
import { join as join56 } from "path";
|
|
38157
38452
|
function runStartupTasks(deps) {
|
|
38158
38453
|
const {
|
|
38159
38454
|
cfg,
|
|
@@ -38176,7 +38471,7 @@ function runStartupTasks(deps) {
|
|
|
38176
38471
|
}
|
|
38177
38472
|
});
|
|
38178
38473
|
if (cfg.memoryEnabled) {
|
|
38179
|
-
const dbPath = cfg.memoryDbPath ??
|
|
38474
|
+
const dbPath = cfg.memoryDbPath ?? join56(process.cwd(), ".kimiflare", "memory.db");
|
|
38180
38475
|
const manager = new MemoryManager({
|
|
38181
38476
|
dbPath,
|
|
38182
38477
|
...auth,
|
|
@@ -38208,7 +38503,7 @@ function runStartupTasks(deps) {
|
|
|
38208
38503
|
});
|
|
38209
38504
|
const cwd = process.cwd();
|
|
38210
38505
|
sessionStartRecallRef.current = manager.recall({ text: cwd, repoPath: cwd, limit: 5 });
|
|
38211
|
-
if (["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].some((name) => existsSync11(
|
|
38506
|
+
if (["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].some((name) => existsSync11(join56(cwd, name)))) {
|
|
38212
38507
|
const lastRefresh = manager.getLastKimiMdRefreshTime(cwd);
|
|
38213
38508
|
const driftCount = manager.countHighSignalMemoriesSince(cwd, lastRefresh);
|
|
38214
38509
|
if (driftCount >= 5) {
|
|
@@ -38219,7 +38514,7 @@ function runStartupTasks(deps) {
|
|
|
38219
38514
|
memoryManagerRef.current?.close();
|
|
38220
38515
|
memoryManagerRef.current = null;
|
|
38221
38516
|
}
|
|
38222
|
-
const skillDbPath = cfg.memoryDbPath ??
|
|
38517
|
+
const skillDbPath = cfg.memoryDbPath ?? join56(process.cwd(), ".kimiflare", "memory.db");
|
|
38223
38518
|
const skillDb = getMemoryDb() ?? openMemoryDb(skillDbPath);
|
|
38224
38519
|
initSkillsSchema(skillDb);
|
|
38225
38520
|
void indexSkills({
|
|
@@ -38576,7 +38871,7 @@ var init_run_compact = __esm({
|
|
|
38576
38871
|
});
|
|
38577
38872
|
|
|
38578
38873
|
// src/commands/save.ts
|
|
38579
|
-
import { mkdir as
|
|
38874
|
+
import { mkdir as mkdir19, writeFile as writeFile17, unlink as unlink5 } from "fs/promises";
|
|
38580
38875
|
import { dirname as dirname21 } from "path";
|
|
38581
38876
|
async function saveCustomCommand(opts2) {
|
|
38582
38877
|
const dir = opts2.source === "project" ? projectCommandsDir(opts2.cwd) : globalCommandsDir();
|
|
@@ -38588,8 +38883,8 @@ async function saveCustomCommand(opts2) {
|
|
|
38588
38883
|
if (opts2.effort) data.effort = opts2.effort;
|
|
38589
38884
|
const frontmatter = serializeFrontmatter(data);
|
|
38590
38885
|
const content = frontmatter + opts2.template;
|
|
38591
|
-
await
|
|
38592
|
-
await
|
|
38886
|
+
await mkdir19(dirname21(filepath), { recursive: true });
|
|
38887
|
+
await writeFile17(filepath, content, "utf8");
|
|
38593
38888
|
return { filepath };
|
|
38594
38889
|
}
|
|
38595
38890
|
async function deleteCustomCommand(cmd) {
|
|
@@ -38712,7 +39007,7 @@ __export(app_exports, {
|
|
|
38712
39007
|
import React25, { useState as useState27, useRef as useRef9, useEffect as useEffect11, useCallback as useCallback8, useMemo as useMemo6 } from "react";
|
|
38713
39008
|
import { Box as Box40, Text as Text41, useApp, useInput as useInput19, useWindowSize as useWindowSize2, render } from "ink";
|
|
38714
39009
|
import { existsSync as existsSync12 } from "fs";
|
|
38715
|
-
import { join as
|
|
39010
|
+
import { join as join57, resolve as resolve19 } from "path";
|
|
38716
39011
|
import { homedir as homedir30 } from "os";
|
|
38717
39012
|
import { jsx as jsx42, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
38718
39013
|
function App({
|
|
@@ -38844,6 +39139,7 @@ function App({
|
|
|
38844
39139
|
hasAnyModal
|
|
38845
39140
|
} = modals;
|
|
38846
39141
|
const [queue2, setQueue] = useState27([]);
|
|
39142
|
+
const [queueDrainRevision, setQueueDrainRevision] = useState27(0);
|
|
38847
39143
|
const runningSubagents = useSubagentList();
|
|
38848
39144
|
const announcedSubagentsRef = useRef9(/* @__PURE__ */ new Set());
|
|
38849
39145
|
const queueRef = useRef9([]);
|
|
@@ -39039,8 +39335,8 @@ ${wcagWarnings.join("\n")}` }
|
|
|
39039
39335
|
const exactDirectory = query === "~" || query === "." || query === ".." || query.endsWith("/..");
|
|
39040
39336
|
const prefix = exactDirectory ? `${query.replace(/\/$/, "")}/` : slash >= 0 ? query.slice(0, slash + 1) : "";
|
|
39041
39337
|
const directory = exactDirectory ? query : slash >= 0 ? query.slice(0, slash + 1) : query;
|
|
39042
|
-
const expanded = directory.startsWith("~") ?
|
|
39043
|
-
const target =
|
|
39338
|
+
const expanded = directory.startsWith("~") ? join57(homedir30(), directory.slice(1)) : directory;
|
|
39339
|
+
const target = resolve19(cwd, expanded || ".");
|
|
39044
39340
|
const entries2 = await glob("*", {
|
|
39045
39341
|
cwd: target,
|
|
39046
39342
|
dot: false,
|
|
@@ -40022,7 +40318,7 @@ ${result2.output ?? "(output not captured)"}`,
|
|
|
40022
40318
|
}
|
|
40023
40319
|
}
|
|
40024
40320
|
turnCounterRef.current += 1;
|
|
40025
|
-
if (turnCounterRef.current % 15 === 0 && ["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].some((name) => existsSync12(
|
|
40321
|
+
if (turnCounterRef.current % 15 === 0 && ["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].some((name) => existsSync12(join57(process.cwd(), name))) && !kimiMdStale) {
|
|
40026
40322
|
setEvents((e) => [
|
|
40027
40323
|
...e,
|
|
40028
40324
|
{ kind: "info", key: mkKey(), text: "Tip: Rerunning /init occasionally helps autopilot (formerly kimiflare) stay accurate as your project evolves." }
|
|
@@ -40046,7 +40342,7 @@ ${result2.output ?? "(output not captured)"}`,
|
|
|
40046
40342
|
};
|
|
40047
40343
|
ensureSessionId();
|
|
40048
40344
|
const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
|
|
40049
|
-
const filePath =
|
|
40345
|
+
const filePath = join57(sessionsDir3(), `${sessionIdRef.current}.json`);
|
|
40050
40346
|
await addCheckpoint(filePath, cp);
|
|
40051
40347
|
}
|
|
40052
40348
|
const summary = await generateContinuationSummary({
|
|
@@ -40257,6 +40553,7 @@ ${result2.output ?? "(output not captured)"}`,
|
|
|
40257
40553
|
const asstId = activeAsstIdRef.current;
|
|
40258
40554
|
if (asstId !== null) updateAssistant(asstId, () => ({ streaming: false }));
|
|
40259
40555
|
endTurn();
|
|
40556
|
+
setQueueDrainRevision((revision) => revision + 1);
|
|
40260
40557
|
activeAsstIdRef.current = null;
|
|
40261
40558
|
activeScopeRef.current = null;
|
|
40262
40559
|
clearPermissionResolveRef();
|
|
@@ -40376,7 +40673,7 @@ ${result2.output ?? "(output not captured)"}`,
|
|
|
40376
40673
|
lspManagerRef.current.notifyChange(path, content2);
|
|
40377
40674
|
} else {
|
|
40378
40675
|
void import("fs/promises").then(
|
|
40379
|
-
({ readFile:
|
|
40676
|
+
({ readFile: readFile37 }) => readFile37(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
|
|
40380
40677
|
})
|
|
40381
40678
|
);
|
|
40382
40679
|
}
|
|
@@ -40569,7 +40866,7 @@ ${result2.output ?? "(output not captured)"}`,
|
|
|
40569
40866
|
};
|
|
40570
40867
|
ensureSessionId();
|
|
40571
40868
|
const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
|
|
40572
|
-
const filePath =
|
|
40869
|
+
const filePath = join57(sessionsDir3(), `${sessionIdRef.current}.json`);
|
|
40573
40870
|
await addCheckpoint(filePath, cp);
|
|
40574
40871
|
}
|
|
40575
40872
|
const summary = await generateContinuationSummary({
|
|
@@ -40648,7 +40945,12 @@ ${result2.output ?? "(output not captured)"}`,
|
|
|
40648
40945
|
[cfg, handleSlash, updateAssistant, updateTool, saveSessionSafe, updateResponseMeta, setShowPlanCompletePicker, runUserShellCommand, ensureTraceStarted]
|
|
40649
40946
|
);
|
|
40650
40947
|
useEffect11(() => {
|
|
40651
|
-
if (
|
|
40948
|
+
if (canDrainQueue({
|
|
40949
|
+
busy,
|
|
40950
|
+
queuePlanOpen: queuePlanDraft !== null,
|
|
40951
|
+
supervisorIdle: supervisorRef.current.phase === "idle",
|
|
40952
|
+
hasPendingWork: pendingPromptEditRef.current !== null || pendingSteersRef.current.length > 0 || queue2.length > 0
|
|
40953
|
+
})) {
|
|
40652
40954
|
const pendingEdit = pendingPromptEditRef.current;
|
|
40653
40955
|
if (pendingEdit) {
|
|
40654
40956
|
pendingPromptEditRef.current = null;
|
|
@@ -40674,7 +40976,7 @@ ${result2.output ?? "(output not captured)"}`,
|
|
|
40674
40976
|
});
|
|
40675
40977
|
}
|
|
40676
40978
|
}
|
|
40677
|
-
}, [busy, queue2, queuePlanDraft, processMessage]);
|
|
40979
|
+
}, [busy, queue2, queuePlanDraft, processMessage, queueDrainRevision]);
|
|
40678
40980
|
const handleQueuePlanPick = useCallback8(
|
|
40679
40981
|
(choice) => {
|
|
40680
40982
|
if (choice === "group" && queuePlanDraft) {
|
|
@@ -41131,7 +41433,7 @@ ${result2.output ?? "(output not captured)"}`,
|
|
|
41131
41433
|
lsp: {
|
|
41132
41434
|
servers: cfg?.lspServers ?? {},
|
|
41133
41435
|
scope: lspScope,
|
|
41134
|
-
hasProjectDir: existsSync12(
|
|
41436
|
+
hasProjectDir: existsSync12(join57(process.cwd(), ".kimiflare"))
|
|
41135
41437
|
}
|
|
41136
41438
|
});
|
|
41137
41439
|
});
|
|
@@ -41188,7 +41490,7 @@ ${result2.output ?? "(output not captured)"}`,
|
|
|
41188
41490
|
onCommandDelete: handleCommandDelete2,
|
|
41189
41491
|
lspServers: cfg?.lspServers ?? {},
|
|
41190
41492
|
lspScope,
|
|
41191
|
-
hasProjectDir: existsSync12(
|
|
41493
|
+
hasProjectDir: existsSync12(join57(process.cwd(), ".kimiflare")),
|
|
41192
41494
|
onLspSave: handleLspSave2,
|
|
41193
41495
|
themes: themeList(),
|
|
41194
41496
|
onPickTheme: handleThemePick,
|
|
@@ -41675,11 +41977,11 @@ init_classify();
|
|
|
41675
41977
|
init_subagent_policy();
|
|
41676
41978
|
init_trace();
|
|
41677
41979
|
init_registry2();
|
|
41678
|
-
import { readFile as
|
|
41679
|
-
import { resolve as
|
|
41980
|
+
import { readFile as readFile16 } from "fs/promises";
|
|
41981
|
+
import { resolve as resolve7, basename as basename3 } from "path";
|
|
41680
41982
|
async function resolveSession(opts2) {
|
|
41681
41983
|
if (opts2.sessionId) {
|
|
41682
|
-
const filePath =
|
|
41984
|
+
const filePath = resolve7(sessionsDir(), `${opts2.sessionId}.json`);
|
|
41683
41985
|
try {
|
|
41684
41986
|
const file = await loadSession(filePath);
|
|
41685
41987
|
return { sessionFile: file, isNew: false };
|
|
@@ -41687,7 +41989,7 @@ async function resolveSession(opts2) {
|
|
|
41687
41989
|
}
|
|
41688
41990
|
}
|
|
41689
41991
|
if (opts2.continueSession) {
|
|
41690
|
-
const cwd = opts2.dir ?
|
|
41992
|
+
const cwd = opts2.dir ? resolve7(opts2.dir) : process.cwd();
|
|
41691
41993
|
const sessions = await listSessions(1, cwd);
|
|
41692
41994
|
if (sessions.length > 0) {
|
|
41693
41995
|
const filePath = sessions[0].filePath;
|
|
@@ -41700,7 +42002,7 @@ async function resolveSession(opts2) {
|
|
|
41700
42002
|
return {
|
|
41701
42003
|
sessionFile: {
|
|
41702
42004
|
id,
|
|
41703
|
-
cwd: opts2.dir ?
|
|
42005
|
+
cwd: opts2.dir ? resolve7(opts2.dir) : process.cwd(),
|
|
41704
42006
|
model: opts2.model,
|
|
41705
42007
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
41706
42008
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -41714,9 +42016,9 @@ async function resolveFiles(filePatterns, cwd) {
|
|
|
41714
42016
|
const resolved = /* @__PURE__ */ new Set();
|
|
41715
42017
|
for (const pattern of filePatterns) {
|
|
41716
42018
|
try {
|
|
41717
|
-
const
|
|
41718
|
-
if (
|
|
41719
|
-
resolved.add(
|
|
42019
|
+
const stat14 = await import("fs/promises").then((m) => m.stat(resolve7(cwd, pattern)));
|
|
42020
|
+
if (stat14.isFile()) {
|
|
42021
|
+
resolved.add(resolve7(cwd, pattern));
|
|
41720
42022
|
continue;
|
|
41721
42023
|
}
|
|
41722
42024
|
} catch {
|
|
@@ -41744,7 +42046,7 @@ async function buildUserMessage(prompt, files, cwd) {
|
|
|
41744
42046
|
}
|
|
41745
42047
|
} else {
|
|
41746
42048
|
try {
|
|
41747
|
-
const content = await
|
|
42049
|
+
const content = await readFile16(filePath, "utf8");
|
|
41748
42050
|
const relPath = filePath.startsWith(cwd) ? filePath.slice(cwd.length + 1) : filePath;
|
|
41749
42051
|
fileContents.push(`
|
|
41750
42052
|
--- ${relPath} ---
|
|
@@ -41779,7 +42081,7 @@ async function runPrintMode(opts2) {
|
|
|
41779
42081
|
`
|
|
41780
42082
|
);
|
|
41781
42083
|
}
|
|
41782
|
-
const cwd = opts2.dir ?
|
|
42084
|
+
const cwd = opts2.dir ? resolve7(opts2.dir) : process.cwd();
|
|
41783
42085
|
const baseWorkerTools = getWorkerTools(opts2.workerProfile);
|
|
41784
42086
|
const { HooksManager: HooksManager2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports));
|
|
41785
42087
|
const hooks = new HooksManager2(cwd);
|
|
@@ -42459,11 +42761,11 @@ async function promptHidden(question) {
|
|
|
42459
42761
|
}
|
|
42460
42762
|
});
|
|
42461
42763
|
const rl = createInterface4({ input: process.stdin, output, terminal: true });
|
|
42462
|
-
return new Promise((
|
|
42764
|
+
return new Promise((resolve20) => {
|
|
42463
42765
|
rl.question(question, (answer) => {
|
|
42464
42766
|
rl.close();
|
|
42465
42767
|
process.stdout.write("\n");
|
|
42466
|
-
|
|
42768
|
+
resolve20(answer);
|
|
42467
42769
|
});
|
|
42468
42770
|
muted = true;
|
|
42469
42771
|
});
|