autopilot-ai 1.24.2 → 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 +763 -471
- 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 {
|
|
@@ -23422,10 +23727,9 @@ __export(app_helpers_exports, {
|
|
|
23422
23727
|
replaceUserPromptEvent: () => replaceUserPromptEvent,
|
|
23423
23728
|
trackRecentFile: () => trackRecentFile
|
|
23424
23729
|
});
|
|
23425
|
-
import { execSync as execSync3
|
|
23730
|
+
import { execSync as execSync3 } from "child_process";
|
|
23426
23731
|
import { existsSync as existsSync8, readFileSync as readFileSync6, statSync as statSync5 } from "fs";
|
|
23427
|
-
import { join as
|
|
23428
|
-
import { platform as platform3 } from "os";
|
|
23732
|
+
import { join as join42 } from "path";
|
|
23429
23733
|
function replaceQueuedPrompt(queue2, key, full, display) {
|
|
23430
23734
|
const index = queue2.findIndex((item) => item.key === key);
|
|
23431
23735
|
if (index >= 0) {
|
|
@@ -23532,7 +23836,7 @@ function buildFilePickerIgnoreList(cwd) {
|
|
|
23532
23836
|
];
|
|
23533
23837
|
const gitignorePatterns = [];
|
|
23534
23838
|
try {
|
|
23535
|
-
const gitignorePath =
|
|
23839
|
+
const gitignorePath = join42(cwd, ".gitignore");
|
|
23536
23840
|
const stats = statSync5(gitignorePath);
|
|
23537
23841
|
if (stats.size > MAX_GITIGNORE_SIZE) {
|
|
23538
23842
|
return hardcoded;
|
|
@@ -23563,19 +23867,6 @@ function costLookupFromConfig(cfg, meta) {
|
|
|
23563
23867
|
if (resolveCustomEndpoint(cfg)) return void 0;
|
|
23564
23868
|
return { apiKey: cfg.openrouterApiKey, meta };
|
|
23565
23869
|
}
|
|
23566
|
-
function openBrowser(url) {
|
|
23567
|
-
if (process.env.KIMIFLARE_NO_BROWSER === "1" || process.env.BROWSER === "none") return false;
|
|
23568
|
-
try {
|
|
23569
|
-
const os2 = platform3();
|
|
23570
|
-
const [cmd, args] = os2 === "darwin" ? ["open", [url]] : os2 === "win32" ? ["cmd", ["/c", "start", "", url]] : ["xdg-open", [url]];
|
|
23571
|
-
const child = spawn7(cmd, args, { detached: true, stdio: "ignore" });
|
|
23572
|
-
child.on("error", () => void 0);
|
|
23573
|
-
child.unref();
|
|
23574
|
-
return true;
|
|
23575
|
-
} catch {
|
|
23576
|
-
return false;
|
|
23577
|
-
}
|
|
23578
|
-
}
|
|
23579
23870
|
function detectGitHubRepo(cachedRepo) {
|
|
23580
23871
|
if (cachedRepo) {
|
|
23581
23872
|
const parts = cachedRepo.split("/");
|
|
@@ -23694,6 +23985,7 @@ var init_app_helpers = __esm({
|
|
|
23694
23985
|
init_system_prompt();
|
|
23695
23986
|
init_image();
|
|
23696
23987
|
init_queue_batch();
|
|
23988
|
+
init_open_browser();
|
|
23697
23989
|
MAX_GITIGNORE_SIZE = 1 * 1024 * 1024;
|
|
23698
23990
|
CONTEXT_LIMIT = 262e3;
|
|
23699
23991
|
AUTO_COMPACT_THRESHOLD = 0.8;
|
|
@@ -23710,9 +24002,9 @@ var init_app_helpers = __esm({
|
|
|
23710
24002
|
|
|
23711
24003
|
// src/ui/bang-command.ts
|
|
23712
24004
|
import { spawn as spawn8 } from "child_process";
|
|
23713
|
-
import { mkdtemp as
|
|
23714
|
-
import { tmpdir as
|
|
23715
|
-
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";
|
|
23716
24008
|
function registerInkInstance(instance) {
|
|
23717
24009
|
inkInstance = instance;
|
|
23718
24010
|
}
|
|
@@ -23720,13 +24012,13 @@ function registerTerminalHandoff(h) {
|
|
|
23720
24012
|
terminalHandoff = h;
|
|
23721
24013
|
}
|
|
23722
24014
|
function runCaptured(inv, cwd) {
|
|
23723
|
-
return new Promise((
|
|
24015
|
+
return new Promise((resolve20) => {
|
|
23724
24016
|
const child = spawn8(inv.file, inv.args, { cwd, stdio: ["ignore", "pipe", "pipe"], env: inv.env ?? process.env });
|
|
23725
24017
|
let output = "";
|
|
23726
24018
|
child.stdout?.on("data", (c) => output += c.toString("utf8"));
|
|
23727
24019
|
child.stderr?.on("data", (c) => output += c.toString("utf8"));
|
|
23728
|
-
child.once("error", (e) =>
|
|
23729
|
-
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 }));
|
|
23730
24022
|
});
|
|
23731
24023
|
}
|
|
23732
24024
|
function isTerminalHandedOff() {
|
|
@@ -23794,10 +24086,10 @@ function swallow() {
|
|
|
23794
24086
|
});
|
|
23795
24087
|
}
|
|
23796
24088
|
function spawnInherit(inv, cwd) {
|
|
23797
|
-
return new Promise((
|
|
24089
|
+
return new Promise((resolve20, reject) => {
|
|
23798
24090
|
const child = spawn8(inv.file, inv.args, { cwd, stdio: "inherit", env: inv.env ?? process.env });
|
|
23799
24091
|
child.once("error", reject);
|
|
23800
|
-
child.once("exit", (code, signal) =>
|
|
24092
|
+
child.once("exit", (code, signal) => resolve20({ code, signal }));
|
|
23801
24093
|
});
|
|
23802
24094
|
}
|
|
23803
24095
|
async function runBangCommand(command, cwd) {
|
|
@@ -23815,8 +24107,8 @@ async function runBangCommand(command, cwd) {
|
|
|
23815
24107
|
const origErr = stderr.write;
|
|
23816
24108
|
const readable = stdin.listeners("readable");
|
|
23817
24109
|
const wasRaw = stdin.isTTY ? stdin.isRaw : false;
|
|
23818
|
-
const logDir2 = isWindows ? null : await
|
|
23819
|
-
const logPath = logDir2 ?
|
|
24110
|
+
const logDir2 = isWindows ? null : await mkdtemp3(join43(tmpdir5(), "autopilot-bang-"));
|
|
24111
|
+
const logPath = logDir2 ? join43(logDir2, "out.log") : null;
|
|
23820
24112
|
const viaScript = logPath ? scriptInvocation(command, shell, logPath) : null;
|
|
23821
24113
|
inkInstance?.clear();
|
|
23822
24114
|
origOut.call(stdout, `
|
|
@@ -23858,9 +24150,9 @@ $ ${command}
|
|
|
23858
24150
|
}
|
|
23859
24151
|
let output = spawnError ? `failed to start: ${spawnError}` : null;
|
|
23860
24152
|
if (captured && logPath) {
|
|
23861
|
-
output = cleanTerminalOutput(await
|
|
24153
|
+
output = cleanTerminalOutput(await readFile29(logPath, "utf8").catch(() => ""));
|
|
23862
24154
|
}
|
|
23863
|
-
if (logDir2) await
|
|
24155
|
+
if (logDir2) await rm6(logDir2, { recursive: true, force: true }).catch(() => {
|
|
23864
24156
|
});
|
|
23865
24157
|
return { command, exitCode: result2.code, signal: result2.signal, output };
|
|
23866
24158
|
}
|
|
@@ -26050,10 +26342,10 @@ __export(camouflage_view_exports, {
|
|
|
26050
26342
|
toolSummary: () => toolSummary,
|
|
26051
26343
|
validateCommandName: () => validateCommandName
|
|
26052
26344
|
});
|
|
26053
|
-
import { execFileSync as
|
|
26054
|
-
import { readdir as
|
|
26345
|
+
import { execFileSync as execFileSync3, spawn as spawn10 } from "child_process";
|
|
26346
|
+
import { readdir as readdir8 } from "fs/promises";
|
|
26055
26347
|
import { homedir as homedir26 } from "os";
|
|
26056
|
-
import { join as
|
|
26348
|
+
import { join as join44, resolve as resolve16 } from "path";
|
|
26057
26349
|
async function loadSdk() {
|
|
26058
26350
|
const sdk = await import("camouflage-tui").catch((err) => {
|
|
26059
26351
|
throw new CamouflageUnavailable(`camouflage-tui is not installed (${err.message})`);
|
|
@@ -26142,14 +26434,14 @@ async function runCamouflageView(opts2) {
|
|
|
26142
26434
|
}
|
|
26143
26435
|
}
|
|
26144
26436
|
function runShell2(command) {
|
|
26145
|
-
return new Promise((
|
|
26437
|
+
return new Promise((resolve20) => {
|
|
26146
26438
|
const { shell, args } = getShellCommand();
|
|
26147
26439
|
const child = spawn10(shell, [...args, command], { env: process.env });
|
|
26148
26440
|
let out = "";
|
|
26149
26441
|
child.stdout?.on("data", (c) => out += c.toString("utf8"));
|
|
26150
26442
|
child.stderr?.on("data", (c) => out += c.toString("utf8"));
|
|
26151
|
-
child.on("close", (code) =>
|
|
26152
|
-
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 }));
|
|
26153
26445
|
});
|
|
26154
26446
|
}
|
|
26155
26447
|
function syncSlashCommands(custom, lastKey, send) {
|
|
@@ -26232,10 +26524,10 @@ function truncateText(s, max) {
|
|
|
26232
26524
|
async function listMentionDir(cwd, query) {
|
|
26233
26525
|
const exact = query === "~" || query === "." || query === ".." || query.endsWith("/..");
|
|
26234
26526
|
const dir = exact ? `${query}/` : query.slice(0, query.lastIndexOf("/") + 1);
|
|
26235
|
-
const expanded = dir.startsWith("~") ?
|
|
26236
|
-
const target =
|
|
26527
|
+
const expanded = dir.startsWith("~") ? join44(homedir26(), dir.slice(1)) : dir;
|
|
26528
|
+
const target = resolve16(cwd, expanded || ".");
|
|
26237
26529
|
try {
|
|
26238
|
-
const items = await
|
|
26530
|
+
const items = await readdir8(target, { withFileTypes: true });
|
|
26239
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 ? "/" : ""}`);
|
|
26240
26532
|
return { dir, entries };
|
|
26241
26533
|
} catch {
|
|
@@ -26318,14 +26610,14 @@ function shortPath(p) {
|
|
|
26318
26610
|
}
|
|
26319
26611
|
function gitBranch(cwd) {
|
|
26320
26612
|
try {
|
|
26321
|
-
return
|
|
26613
|
+
return execFileSync3("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd, encoding: "utf8", timeout: 500, stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
26322
26614
|
} catch {
|
|
26323
26615
|
return "";
|
|
26324
26616
|
}
|
|
26325
26617
|
}
|
|
26326
26618
|
function listFiles(cwd) {
|
|
26327
26619
|
try {
|
|
26328
|
-
const out =
|
|
26620
|
+
const out = execFileSync3("git", ["ls-files", "--cached", "--others", "--exclude-standard"], {
|
|
26329
26621
|
cwd,
|
|
26330
26622
|
encoding: "utf8",
|
|
26331
26623
|
timeout: 2e3,
|
|
@@ -29224,19 +29516,19 @@ function usePermissionController(getMode, onPlanModeBlocked) {
|
|
|
29224
29516
|
const onPlanModeBlockedRef = useRef3(onPlanModeBlocked);
|
|
29225
29517
|
onPlanModeBlockedRef.current = onPlanModeBlocked;
|
|
29226
29518
|
const askPermission = useCallback2(
|
|
29227
|
-
(req, askOpts) => new Promise((
|
|
29519
|
+
(req, askOpts) => new Promise((resolve20) => {
|
|
29228
29520
|
const outcome = decidePermission(req, getModeRef.current(), askOpts);
|
|
29229
29521
|
if (outcome.kind === "resolve") {
|
|
29230
|
-
|
|
29522
|
+
resolve20(outcome.decision);
|
|
29231
29523
|
return;
|
|
29232
29524
|
}
|
|
29233
29525
|
if (outcome.kind === "plan_blocked") {
|
|
29234
29526
|
onPlanModeBlockedRef.current(outcome.toolName);
|
|
29235
|
-
|
|
29527
|
+
resolve20(AUTO_DENY);
|
|
29236
29528
|
return;
|
|
29237
29529
|
}
|
|
29238
|
-
resolveRef.current =
|
|
29239
|
-
setPending({ tool: req.tool, args: req.args, resolve:
|
|
29530
|
+
resolveRef.current = resolve20;
|
|
29531
|
+
setPending({ tool: req.tool, args: req.args, resolve: resolve20 });
|
|
29240
29532
|
}),
|
|
29241
29533
|
[]
|
|
29242
29534
|
);
|
|
@@ -29581,9 +29873,9 @@ var init_queue_plan_picker = __esm({
|
|
|
29581
29873
|
});
|
|
29582
29874
|
|
|
29583
29875
|
// src/agent/jev-context.ts
|
|
29584
|
-
import { execFileSync as
|
|
29585
|
-
import { readFile as
|
|
29586
|
-
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";
|
|
29587
29879
|
function messageText(message2) {
|
|
29588
29880
|
if (typeof message2.content === "string") return message2.content.trim();
|
|
29589
29881
|
if (!Array.isArray(message2.content)) return "";
|
|
@@ -29594,18 +29886,18 @@ function redactCommonSecrets(text) {
|
|
|
29594
29886
|
}
|
|
29595
29887
|
function projectRoot(cwd) {
|
|
29596
29888
|
try {
|
|
29597
|
-
return
|
|
29889
|
+
return execFileSync4("git", ["-C", cwd, "rev-parse", "--show-toplevel"], {
|
|
29598
29890
|
encoding: "utf8",
|
|
29599
29891
|
stdio: ["ignore", "pipe", "ignore"],
|
|
29600
29892
|
timeout: 1e3
|
|
29601
29893
|
}).trim();
|
|
29602
29894
|
} catch {
|
|
29603
|
-
return
|
|
29895
|
+
return resolve17(cwd);
|
|
29604
29896
|
}
|
|
29605
29897
|
}
|
|
29606
29898
|
async function readPackageMetadata(root) {
|
|
29607
29899
|
try {
|
|
29608
|
-
const parsed = JSON.parse(await
|
|
29900
|
+
const parsed = JSON.parse(await readFile30(join45(root, "package.json"), "utf8"));
|
|
29609
29901
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
29610
29902
|
const pkg = parsed;
|
|
29611
29903
|
const metadata = {};
|
|
@@ -29622,7 +29914,7 @@ async function readPackageMetadata(root) {
|
|
|
29622
29914
|
async function readLicenseEvidence(root) {
|
|
29623
29915
|
for (const name of ["LICENSE", "LICENSE.md", "LICENSE.txt", "LICENCE", "COPYING"]) {
|
|
29624
29916
|
try {
|
|
29625
|
-
const content = (await
|
|
29917
|
+
const content = (await readFile30(join45(root, name), "utf8")).trim();
|
|
29626
29918
|
if (content) return { source: `project license (${name})`, content: content.slice(0, 700) };
|
|
29627
29919
|
} catch {
|
|
29628
29920
|
}
|
|
@@ -29655,7 +29947,7 @@ async function buildJevContext(question, messages, cwd = process.cwd()) {
|
|
|
29655
29947
|
conversationRemaining -= source.length + content.length + 2;
|
|
29656
29948
|
}
|
|
29657
29949
|
}
|
|
29658
|
-
const currentDirectory = basename8(
|
|
29950
|
+
const currentDirectory = basename8(resolve17(cwd));
|
|
29659
29951
|
const escapedDirectory = currentDirectory.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
29660
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);
|
|
29661
29953
|
if (CURRENT_PROJECT_REFERENCE.test(question) || namesCurrentDirectory) {
|
|
@@ -30704,8 +30996,8 @@ var init_frontmatter = __esm({
|
|
|
30704
30996
|
});
|
|
30705
30997
|
|
|
30706
30998
|
// src/skills/loader.ts
|
|
30707
|
-
import { readFile as
|
|
30708
|
-
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";
|
|
30709
31001
|
function normalizeManifest(raw, filePath) {
|
|
30710
31002
|
const name = typeof raw.name === "string" ? raw.name : "";
|
|
30711
31003
|
const description = typeof raw.description === "string" ? raw.description : "";
|
|
@@ -30719,7 +31011,7 @@ function normalizeManifest(raw, filePath) {
|
|
|
30719
31011
|
return { name, description, match, scope, priority, enabled: enabled2 };
|
|
30720
31012
|
}
|
|
30721
31013
|
async function loadSkillFile(filePath) {
|
|
30722
|
-
const raw = await
|
|
31014
|
+
const raw = await readFile31(filePath, "utf-8");
|
|
30723
31015
|
const parsed = parseFrontmatter(raw);
|
|
30724
31016
|
const manifest = normalizeManifest(parsed.data, filePath);
|
|
30725
31017
|
const body = parsed.content.trim();
|
|
@@ -30738,11 +31030,11 @@ async function loadSkillFile(filePath) {
|
|
|
30738
31030
|
}
|
|
30739
31031
|
async function loadSkillsFromDir(dirPath) {
|
|
30740
31032
|
try {
|
|
30741
|
-
const entries = await
|
|
31033
|
+
const entries = await readdir9(dirPath);
|
|
30742
31034
|
const files = [];
|
|
30743
31035
|
for (const entry of entries) {
|
|
30744
|
-
const full =
|
|
30745
|
-
const s = await
|
|
31036
|
+
const full = join46(dirPath, entry);
|
|
31037
|
+
const s = await stat11(full);
|
|
30746
31038
|
if (s.isFile() && extname(entry) === ".md") {
|
|
30747
31039
|
files.push(full);
|
|
30748
31040
|
}
|
|
@@ -30769,12 +31061,12 @@ var init_loader = __esm({
|
|
|
30769
31061
|
});
|
|
30770
31062
|
|
|
30771
31063
|
// src/skills/manager.ts
|
|
30772
|
-
import { mkdir as
|
|
30773
|
-
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";
|
|
30774
31066
|
function getSkillDirs(cwd) {
|
|
30775
31067
|
return {
|
|
30776
|
-
projectDir:
|
|
30777
|
-
globalDir:
|
|
31068
|
+
projectDir: join47(cwd, ".kimiflare", "skills"),
|
|
31069
|
+
globalDir: join47(process.env.HOME ?? "", ".config", "kimiflare", "skills")
|
|
30778
31070
|
};
|
|
30779
31071
|
}
|
|
30780
31072
|
async function listAllSkills(cwd) {
|
|
@@ -30788,7 +31080,7 @@ async function listAllSkills(cwd) {
|
|
|
30788
31080
|
async function createSkill(opts2) {
|
|
30789
31081
|
const dirs = getSkillDirs(opts2.cwd);
|
|
30790
31082
|
const dir = opts2.scope === "project" ? dirs.projectDir : dirs.globalDir;
|
|
30791
|
-
const filepath =
|
|
31083
|
+
const filepath = join47(dir, `${opts2.name}.md`);
|
|
30792
31084
|
const frontmatter = {
|
|
30793
31085
|
name: opts2.name,
|
|
30794
31086
|
enabled: true,
|
|
@@ -30809,8 +31101,8 @@ ${yaml}
|
|
|
30809
31101
|
|
|
30810
31102
|
Add your instructions here.
|
|
30811
31103
|
`;
|
|
30812
|
-
await
|
|
30813
|
-
await
|
|
31104
|
+
await mkdir18(dir, { recursive: true });
|
|
31105
|
+
await writeFile16(filepath, content, "utf8");
|
|
30814
31106
|
return { filepath };
|
|
30815
31107
|
}
|
|
30816
31108
|
async function deleteSkill(name, cwd) {
|
|
@@ -30824,7 +31116,7 @@ async function setSkillEnabled(name, enabled2, cwd) {
|
|
|
30824
31116
|
const all = await listAllSkills(cwd);
|
|
30825
31117
|
const skill = all.project.find((s) => s.name === name) ?? all.global.find((s) => s.name === name);
|
|
30826
31118
|
if (!skill) throw new Error(`skill "${name}" not found`);
|
|
30827
|
-
const raw = await
|
|
31119
|
+
const raw = await readFile32(skill.filePath, "utf-8");
|
|
30828
31120
|
const parsed = parseFrontmatter(raw);
|
|
30829
31121
|
parsed.data.enabled = enabled2;
|
|
30830
31122
|
const yaml = Object.entries(parsed.data).map(([k, v]) => {
|
|
@@ -30836,7 +31128,7 @@ ${v.map((item) => ` - ${item}`).join("\n")}`;
|
|
|
30836
31128
|
${yaml}
|
|
30837
31129
|
---
|
|
30838
31130
|
${parsed.content}`;
|
|
30839
|
-
await
|
|
31131
|
+
await writeFile16(skill.filePath, content, "utf8");
|
|
30840
31132
|
return { filepath: skill.filePath };
|
|
30841
31133
|
}
|
|
30842
31134
|
async function findSkillFile(name, cwd) {
|
|
@@ -31096,15 +31388,15 @@ var tui_report_exports = {};
|
|
|
31096
31388
|
__export(tui_report_exports, {
|
|
31097
31389
|
getCategoryReportText: () => getCategoryReportText
|
|
31098
31390
|
});
|
|
31099
|
-
import { readFile as
|
|
31100
|
-
import { join as
|
|
31391
|
+
import { readFile as readFile33 } from "fs/promises";
|
|
31392
|
+
import { join as join48 } from "path";
|
|
31101
31393
|
import { homedir as homedir27 } from "os";
|
|
31102
31394
|
function usageDir3() {
|
|
31103
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
31104
|
-
return
|
|
31395
|
+
const xdg = process.env.XDG_DATA_HOME || join48(homedir27(), ".local", "share");
|
|
31396
|
+
return join48(xdg, "kimiflare");
|
|
31105
31397
|
}
|
|
31106
31398
|
function usagePath4() {
|
|
31107
|
-
return
|
|
31399
|
+
return join48(usageDir3(), "usage.json");
|
|
31108
31400
|
}
|
|
31109
31401
|
function today3() {
|
|
31110
31402
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -31116,7 +31408,7 @@ function daysAgo2(n) {
|
|
|
31116
31408
|
}
|
|
31117
31409
|
async function loadLog3() {
|
|
31118
31410
|
try {
|
|
31119
|
-
const raw = await
|
|
31411
|
+
const raw = await readFile33(usagePath4(), "utf8");
|
|
31120
31412
|
return JSON.parse(raw);
|
|
31121
31413
|
} catch {
|
|
31122
31414
|
return { version: 1, days: [], sessions: [] };
|
|
@@ -31173,7 +31465,7 @@ var init_tui_report = __esm({
|
|
|
31173
31465
|
});
|
|
31174
31466
|
|
|
31175
31467
|
// src/ui/slash-commands.ts
|
|
31176
|
-
import { join as
|
|
31468
|
+
import { join as join49 } from "path";
|
|
31177
31469
|
import QRCode from "qrcode";
|
|
31178
31470
|
function executeFreshStart(ctx, planText, overrideMode, opts2 = {}) {
|
|
31179
31471
|
const oldSessionId = ctx.sessionIdRef.current;
|
|
@@ -31644,7 +31936,7 @@ auto (default) lets the coordinator assess substantial tasks and delegate indepe
|
|
|
31644
31936
|
const context = noContext ? [] : await buildJevContext(question.prompt, ctx.messagesRef.current, process.cwd());
|
|
31645
31937
|
const receipt = formatJevContextReceipt(context, showContext);
|
|
31646
31938
|
setResult(eventKey, { kind: "info", key: eventKey, text: `Jev is evaluating \xB7 ${receipt}`, pending: true });
|
|
31647
|
-
await new Promise((
|
|
31939
|
+
await new Promise((resolve20) => setTimeout(resolve20, 0));
|
|
31648
31940
|
const answer = await askJev(apiKey, question, { context });
|
|
31649
31941
|
const presentation = presentJevAnswer(question, answer);
|
|
31650
31942
|
setResult(eventKey, {
|
|
@@ -32105,7 +32397,7 @@ ${lines.join("\n")}` }]);
|
|
|
32105
32397
|
void (async () => {
|
|
32106
32398
|
try {
|
|
32107
32399
|
const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
|
|
32108
|
-
const file = await loadSession(
|
|
32400
|
+
const file = await loadSession(join49(sessionsDir3(), `${currentId}.json`));
|
|
32109
32401
|
const cps = file.checkpoints ?? [];
|
|
32110
32402
|
if (cps.length === 0) {
|
|
32111
32403
|
setEvents((e) => [...e, { kind: "info", key: mkKey2(), text: "no checkpoints in this session" }]);
|
|
@@ -32150,7 +32442,7 @@ ${lines.join("\n")}` }]);
|
|
|
32150
32442
|
try {
|
|
32151
32443
|
ctx.ensureSessionId();
|
|
32152
32444
|
const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
|
|
32153
|
-
const filePath =
|
|
32445
|
+
const filePath = join49(sessionsDir3(), `${ctx.sessionIdRef.current}.json`);
|
|
32154
32446
|
await addCheckpoint(filePath, cp);
|
|
32155
32447
|
setEvents((e) => [...e, { kind: "info", key: mkKey2(), text: `checkpoint saved: "${label}"` }]);
|
|
32156
32448
|
} catch (e) {
|
|
@@ -33206,9 +33498,9 @@ async function startLoopbackListener(opts2 = {}) {
|
|
|
33206
33498
|
rejectCode(e);
|
|
33207
33499
|
finish();
|
|
33208
33500
|
}
|
|
33209
|
-
await new Promise((
|
|
33501
|
+
await new Promise((resolve20, reject) => {
|
|
33210
33502
|
server.once("error", reject);
|
|
33211
|
-
server.listen(0, "127.0.0.1", () =>
|
|
33503
|
+
server.listen(0, "127.0.0.1", () => resolve20());
|
|
33212
33504
|
});
|
|
33213
33505
|
const address = server.address();
|
|
33214
33506
|
const port = typeof address === "object" && address ? address.port : 0;
|
|
@@ -33634,15 +33926,15 @@ var init_frontmatter2 = __esm({
|
|
|
33634
33926
|
});
|
|
33635
33927
|
|
|
33636
33928
|
// src/commands/loader.ts
|
|
33637
|
-
import { open, realpath as
|
|
33929
|
+
import { open, realpath as realpath7 } from "fs/promises";
|
|
33638
33930
|
import { homedir as homedir28 } from "os";
|
|
33639
|
-
import { join as
|
|
33931
|
+
import { join as join50, relative as relative11, sep as sep7 } from "path";
|
|
33640
33932
|
function projectCommandsDir(cwd = process.cwd()) {
|
|
33641
|
-
return
|
|
33933
|
+
return join50(cwd, ".kimiflare", "commands");
|
|
33642
33934
|
}
|
|
33643
33935
|
function globalCommandsDir() {
|
|
33644
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
33645
|
-
return
|
|
33936
|
+
const xdg = process.env.XDG_CONFIG_HOME || join50(homedir28(), ".config");
|
|
33937
|
+
return join50(xdg, "kimiflare", "commands");
|
|
33646
33938
|
}
|
|
33647
33939
|
async function loadCustomCommands(cwd = process.cwd()) {
|
|
33648
33940
|
const warnings = [];
|
|
@@ -33681,7 +33973,7 @@ async function loadCustomCommands(cwd = process.cwd()) {
|
|
|
33681
33973
|
async function resolveSafeDir(dir, source, cwd, warnings) {
|
|
33682
33974
|
let realDir;
|
|
33683
33975
|
try {
|
|
33684
|
-
realDir = await
|
|
33976
|
+
realDir = await realpath7(dir);
|
|
33685
33977
|
} catch (err) {
|
|
33686
33978
|
const code = err.code;
|
|
33687
33979
|
if (code !== "ENOENT" && code !== "ENOTDIR") {
|
|
@@ -33692,11 +33984,11 @@ async function resolveSafeDir(dir, source, cwd, warnings) {
|
|
|
33692
33984
|
if (source === "project") {
|
|
33693
33985
|
let realCwd;
|
|
33694
33986
|
try {
|
|
33695
|
-
realCwd = await
|
|
33987
|
+
realCwd = await realpath7(cwd);
|
|
33696
33988
|
} catch {
|
|
33697
33989
|
return null;
|
|
33698
33990
|
}
|
|
33699
|
-
const rel =
|
|
33991
|
+
const rel = relative11(realCwd, realDir);
|
|
33700
33992
|
if (rel !== "" && isPathOutside(rel)) {
|
|
33701
33993
|
warnings.push(`commands dir ${dir} escapes workspace via symlink \u2014 skipped`);
|
|
33702
33994
|
return null;
|
|
@@ -33771,10 +34063,10 @@ async function loadOne(file, rootDir, source, warnings) {
|
|
|
33771
34063
|
return cmd;
|
|
33772
34064
|
}
|
|
33773
34065
|
function filenameToCommandName(file, rootDir) {
|
|
33774
|
-
const rel =
|
|
34066
|
+
const rel = relative11(rootDir, file);
|
|
33775
34067
|
if (!rel || isPathOutside(rel)) return null;
|
|
33776
34068
|
const noExt = rel.replace(/\.md$/i, "");
|
|
33777
|
-
const parts = noExt.split(
|
|
34069
|
+
const parts = noExt.split(sep7).filter((p) => p.length > 0);
|
|
33778
34070
|
if (parts.length === 0) return null;
|
|
33779
34071
|
if (parts.some((p) => !/^[\w.-]+$/.test(p))) return null;
|
|
33780
34072
|
return parts.join("/");
|
|
@@ -33794,8 +34086,8 @@ var init_loader2 = __esm({
|
|
|
33794
34086
|
|
|
33795
34087
|
// src/commands/renderer.ts
|
|
33796
34088
|
import { exec } from "child_process";
|
|
33797
|
-
import { open as open2, realpath as
|
|
33798
|
-
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";
|
|
33799
34091
|
import { promisify as promisify9 } from "util";
|
|
33800
34092
|
function tokenizeArgs(s) {
|
|
33801
34093
|
return [...s.matchAll(ARG_TOKEN_RE)].map((match) => {
|
|
@@ -33886,7 +34178,7 @@ async function replaceFiles(prompt, warnings, cmd, cwd, maxFileBytes) {
|
|
|
33886
34178
|
return "" + trailing;
|
|
33887
34179
|
});
|
|
33888
34180
|
}
|
|
33889
|
-
const realCwd = await
|
|
34181
|
+
const realCwd = await realpath8(cwd).catch(() => cwd);
|
|
33890
34182
|
const replacements = await Promise.all(
|
|
33891
34183
|
matches.map(async (match) => {
|
|
33892
34184
|
const rawPath = match[1] ?? "";
|
|
@@ -33895,23 +34187,23 @@ async function replaceFiles(prompt, warnings, cmd, cwd, maxFileBytes) {
|
|
|
33895
34187
|
warnings.push(`file inclusion blocked: @${rawPath} \u2014 secret file pattern`);
|
|
33896
34188
|
return "";
|
|
33897
34189
|
}
|
|
33898
|
-
if (
|
|
34190
|
+
if (isAbsolute8(rawPath) || rawPath.startsWith("~")) {
|
|
33899
34191
|
warnings.push(`file inclusion skipped: @${rawPath} \u2014 outside workspace`);
|
|
33900
34192
|
return "";
|
|
33901
34193
|
}
|
|
33902
34194
|
const resolved = resolvePathJoin(cwd, rawPath);
|
|
33903
|
-
if (isPathOutside(
|
|
34195
|
+
if (isPathOutside(relative12(cwd, resolved))) {
|
|
33904
34196
|
warnings.push(`file inclusion skipped: @${rawPath} \u2014 outside workspace`);
|
|
33905
34197
|
return "";
|
|
33906
34198
|
}
|
|
33907
34199
|
let real;
|
|
33908
34200
|
try {
|
|
33909
|
-
real = await
|
|
34201
|
+
real = await realpath8(resolved);
|
|
33910
34202
|
} catch (error) {
|
|
33911
34203
|
warnings.push(`file inclusion failed: @${rawPath} \u2014 ${message(error)}`);
|
|
33912
34204
|
return "";
|
|
33913
34205
|
}
|
|
33914
|
-
if (isPathOutside(
|
|
34206
|
+
if (isPathOutside(relative12(realCwd, real))) {
|
|
33915
34207
|
warnings.push(`file inclusion skipped: @${rawPath} \u2014 symlink escapes workspace`);
|
|
33916
34208
|
return "";
|
|
33917
34209
|
}
|
|
@@ -34024,11 +34316,11 @@ var init_wcag = __esm({
|
|
|
34024
34316
|
});
|
|
34025
34317
|
|
|
34026
34318
|
// src/ui/theme-loader.ts
|
|
34027
|
-
import { readFile as
|
|
34028
|
-
import { join as
|
|
34319
|
+
import { readFile as readFile34, readdir as readdir10 } from "fs/promises";
|
|
34320
|
+
import { join as join51 } from "path";
|
|
34029
34321
|
import { homedir as homedir29 } from "os";
|
|
34030
34322
|
function projectThemesDir(cwd = process.cwd()) {
|
|
34031
|
-
return
|
|
34323
|
+
return join51(cwd, ".kimiflare", "themes");
|
|
34032
34324
|
}
|
|
34033
34325
|
function isHexColor(c) {
|
|
34034
34326
|
return /^#[0-9a-fA-F]{6}$/.test(c);
|
|
@@ -34112,15 +34404,15 @@ async function loadThemesFromDir(dir, source) {
|
|
|
34112
34404
|
const errors = [];
|
|
34113
34405
|
let files;
|
|
34114
34406
|
try {
|
|
34115
|
-
files = await
|
|
34407
|
+
files = await readdir10(dir);
|
|
34116
34408
|
} catch {
|
|
34117
34409
|
return { themes, errors };
|
|
34118
34410
|
}
|
|
34119
34411
|
for (const file of files.filter((f) => f.endsWith(".json"))) {
|
|
34120
|
-
const path =
|
|
34412
|
+
const path = join51(dir, file);
|
|
34121
34413
|
let raw;
|
|
34122
34414
|
try {
|
|
34123
|
-
raw = await
|
|
34415
|
+
raw = await readFile34(path, "utf-8");
|
|
34124
34416
|
} catch (e) {
|
|
34125
34417
|
errors.push(`${path}: ${e instanceof Error ? e.message : String(e)}`);
|
|
34126
34418
|
continue;
|
|
@@ -34266,8 +34558,8 @@ var init_theme_loader = __esm({
|
|
|
34266
34558
|
"use strict";
|
|
34267
34559
|
init_wcag();
|
|
34268
34560
|
init_theme();
|
|
34269
|
-
USER_THEMES_DIR =
|
|
34270
|
-
process.env.XDG_CONFIG_HOME ||
|
|
34561
|
+
USER_THEMES_DIR = join51(
|
|
34562
|
+
process.env.XDG_CONFIG_HOME || join51(homedir29(), ".config"),
|
|
34271
34563
|
"kimiflare",
|
|
34272
34564
|
"themes"
|
|
34273
34565
|
);
|
|
@@ -36798,9 +37090,9 @@ var init_resume_progress = __esm({
|
|
|
36798
37090
|
});
|
|
36799
37091
|
|
|
36800
37092
|
// src/agent/supervisor.ts
|
|
36801
|
-
import { readdir as
|
|
37093
|
+
import { readdir as readdir11, readFile as readFile35, stat as stat12 } from "fs/promises";
|
|
36802
37094
|
import { createHash as createHash7 } from "crypto";
|
|
36803
|
-
import { resolve as
|
|
37095
|
+
import { resolve as resolve18, join as join52 } from "path";
|
|
36804
37096
|
var TurnSupervisor;
|
|
36805
37097
|
var init_supervisor = __esm({
|
|
36806
37098
|
"src/agent/supervisor.ts"() {
|
|
@@ -37190,12 +37482,12 @@ var init_input_handlers = __esm({
|
|
|
37190
37482
|
|
|
37191
37483
|
// src/init/context-generator.ts
|
|
37192
37484
|
import { existsSync as existsSync9, statSync as statSync6 } from "fs";
|
|
37193
|
-
import { join as
|
|
37485
|
+
import { join as join53 } from "path";
|
|
37194
37486
|
function detectFlavor(cwd) {
|
|
37195
37487
|
for (const [flavor, signatures] of Object.entries(FLAVOR_SIGNATURES)) {
|
|
37196
37488
|
if (flavor === "generic") continue;
|
|
37197
37489
|
for (const sig of signatures) {
|
|
37198
|
-
const path =
|
|
37490
|
+
const path = join53(cwd, sig);
|
|
37199
37491
|
if (sig.includes("*")) {
|
|
37200
37492
|
try {
|
|
37201
37493
|
const parts = sig.split("*");
|
|
@@ -37216,14 +37508,14 @@ function detectFlavor(cwd) {
|
|
|
37216
37508
|
}
|
|
37217
37509
|
function findFile(cwd, candidates) {
|
|
37218
37510
|
for (const c of candidates) {
|
|
37219
|
-
if (existsSync9(
|
|
37511
|
+
if (existsSync9(join53(cwd, c))) return c;
|
|
37220
37512
|
}
|
|
37221
37513
|
return null;
|
|
37222
37514
|
}
|
|
37223
37515
|
function findSourceRoots(cwd) {
|
|
37224
37516
|
const roots = [];
|
|
37225
37517
|
for (const r of SOURCE_ROOT_CANDIDATES) {
|
|
37226
|
-
const p =
|
|
37518
|
+
const p = join53(cwd, r);
|
|
37227
37519
|
try {
|
|
37228
37520
|
const s = statSync6(p);
|
|
37229
37521
|
if (s.isDirectory()) roots.push(r);
|
|
@@ -37234,9 +37526,9 @@ function findSourceRoots(cwd) {
|
|
|
37234
37526
|
}
|
|
37235
37527
|
function findCiConfig(cwd) {
|
|
37236
37528
|
for (const c of CI_PATHS) {
|
|
37237
|
-
if (existsSync9(
|
|
37529
|
+
if (existsSync9(join53(cwd, c))) {
|
|
37238
37530
|
try {
|
|
37239
|
-
const s = statSync6(
|
|
37531
|
+
const s = statSync6(join53(cwd, c));
|
|
37240
37532
|
return s.isDirectory() ? c : c;
|
|
37241
37533
|
} catch {
|
|
37242
37534
|
}
|
|
@@ -37373,7 +37665,7 @@ function analyzeProject(cwd) {
|
|
|
37373
37665
|
ciConfig: findCiConfig(cwd),
|
|
37374
37666
|
readme: findFile(cwd, ["README.md", "README.rst", "README.txt", "Readme.md"]),
|
|
37375
37667
|
sourceRoots: findSourceRoots(cwd),
|
|
37376
|
-
hasGit: existsSync9(
|
|
37668
|
+
hasGit: existsSync9(join53(cwd, ".git"))
|
|
37377
37669
|
};
|
|
37378
37670
|
}
|
|
37379
37671
|
function bashDiscoveryCommands(profile) {
|
|
@@ -37538,7 +37830,7 @@ Aim for 100\u2013200 lines total. Use markdown tables where they save space.
|
|
|
37538
37830
|
}
|
|
37539
37831
|
function buildInitPrompt(cwd) {
|
|
37540
37832
|
const existingName = ["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].find(
|
|
37541
|
-
(n) => existsSync9(
|
|
37833
|
+
(n) => existsSync9(join53(cwd, n))
|
|
37542
37834
|
);
|
|
37543
37835
|
const isRefresh = existingName !== void 0;
|
|
37544
37836
|
const targetFilename = existingName ?? "AGENTS.md";
|
|
@@ -37622,7 +37914,7 @@ var init_context_generator = __esm({
|
|
|
37622
37914
|
|
|
37623
37915
|
// src/init/run-init.ts
|
|
37624
37916
|
import { existsSync as existsSync10 } from "fs";
|
|
37625
|
-
import { join as
|
|
37917
|
+
import { join as join54 } from "path";
|
|
37626
37918
|
async function runInit(deps) {
|
|
37627
37919
|
const {
|
|
37628
37920
|
cfg,
|
|
@@ -37715,7 +38007,7 @@ async function runInit(deps) {
|
|
|
37715
38007
|
lspManagerRef.current.notifyChange(path, content);
|
|
37716
38008
|
} else {
|
|
37717
38009
|
void import("fs/promises").then(
|
|
37718
|
-
({ readFile:
|
|
38010
|
+
({ readFile: readFile37 }) => readFile37(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
|
|
37719
38011
|
})
|
|
37720
38012
|
);
|
|
37721
38013
|
}
|
|
@@ -37820,7 +38112,7 @@ async function runInit(deps) {
|
|
|
37820
38112
|
}
|
|
37821
38113
|
}
|
|
37822
38114
|
});
|
|
37823
|
-
if (existsSync10(
|
|
38115
|
+
if (existsSync10(join54(cwd, targetFilename))) {
|
|
37824
38116
|
if (cacheStableRef.current) {
|
|
37825
38117
|
messagesRef.current[1] = {
|
|
37826
38118
|
role: "system",
|
|
@@ -37912,11 +38204,11 @@ var init_run_init = __esm({
|
|
|
37912
38204
|
});
|
|
37913
38205
|
|
|
37914
38206
|
// src/skills/discovery.ts
|
|
37915
|
-
import { readdir as
|
|
37916
|
-
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";
|
|
37917
38209
|
async function dirExists(path) {
|
|
37918
38210
|
try {
|
|
37919
|
-
const s = await
|
|
38211
|
+
const s = await stat13(path);
|
|
37920
38212
|
return s.isDirectory();
|
|
37921
38213
|
} catch {
|
|
37922
38214
|
return false;
|
|
@@ -37924,7 +38216,7 @@ async function dirExists(path) {
|
|
|
37924
38216
|
}
|
|
37925
38217
|
async function fileExists(path) {
|
|
37926
38218
|
try {
|
|
37927
|
-
const s = await
|
|
38219
|
+
const s = await stat13(path);
|
|
37928
38220
|
return s.isFile();
|
|
37929
38221
|
} catch {
|
|
37930
38222
|
return false;
|
|
@@ -37932,25 +38224,25 @@ async function fileExists(path) {
|
|
|
37932
38224
|
}
|
|
37933
38225
|
async function scanSkillDir(dirPath, source) {
|
|
37934
38226
|
if (!await dirExists(dirPath)) return [];
|
|
37935
|
-
const entries = await
|
|
38227
|
+
const entries = await readdir12(dirPath, { withFileTypes: true });
|
|
37936
38228
|
const files = [];
|
|
37937
38229
|
for (const entry of entries) {
|
|
37938
38230
|
if (!entry.isFile()) continue;
|
|
37939
38231
|
if (!SKILL_EXTENSIONS.has(extname2(entry.name))) continue;
|
|
37940
|
-
files.push({ filePath:
|
|
38232
|
+
files.push({ filePath: join55(dirPath, entry.name), source });
|
|
37941
38233
|
}
|
|
37942
38234
|
return files;
|
|
37943
38235
|
}
|
|
37944
38236
|
async function discoverSkills(cwd) {
|
|
37945
|
-
const agentsSkills = await scanSkillDir(
|
|
37946
|
-
const agentsMd = await fileExists(
|
|
37947
|
-
const githubSkills = await scanSkillDir(
|
|
37948
|
-
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");
|
|
37949
38241
|
const ordered = [...agentsSkills, ...agentsMd, ...githubSkills, ...kimiflareSkills];
|
|
37950
38242
|
return ordered;
|
|
37951
38243
|
}
|
|
37952
38244
|
async function readSkillFile(filePath) {
|
|
37953
|
-
const bytes = await
|
|
38245
|
+
const bytes = await readFile36(filePath);
|
|
37954
38246
|
return { bytes, text: bytes.toString("utf-8") };
|
|
37955
38247
|
}
|
|
37956
38248
|
var SKILL_EXTENSIONS;
|
|
@@ -38156,7 +38448,7 @@ var init_skills = __esm({
|
|
|
38156
38448
|
|
|
38157
38449
|
// src/ui/run-startup-tasks.ts
|
|
38158
38450
|
import { existsSync as existsSync11 } from "fs";
|
|
38159
|
-
import { join as
|
|
38451
|
+
import { join as join56 } from "path";
|
|
38160
38452
|
function runStartupTasks(deps) {
|
|
38161
38453
|
const {
|
|
38162
38454
|
cfg,
|
|
@@ -38179,7 +38471,7 @@ function runStartupTasks(deps) {
|
|
|
38179
38471
|
}
|
|
38180
38472
|
});
|
|
38181
38473
|
if (cfg.memoryEnabled) {
|
|
38182
|
-
const dbPath = cfg.memoryDbPath ??
|
|
38474
|
+
const dbPath = cfg.memoryDbPath ?? join56(process.cwd(), ".kimiflare", "memory.db");
|
|
38183
38475
|
const manager = new MemoryManager({
|
|
38184
38476
|
dbPath,
|
|
38185
38477
|
...auth,
|
|
@@ -38211,7 +38503,7 @@ function runStartupTasks(deps) {
|
|
|
38211
38503
|
});
|
|
38212
38504
|
const cwd = process.cwd();
|
|
38213
38505
|
sessionStartRecallRef.current = manager.recall({ text: cwd, repoPath: cwd, limit: 5 });
|
|
38214
|
-
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)))) {
|
|
38215
38507
|
const lastRefresh = manager.getLastKimiMdRefreshTime(cwd);
|
|
38216
38508
|
const driftCount = manager.countHighSignalMemoriesSince(cwd, lastRefresh);
|
|
38217
38509
|
if (driftCount >= 5) {
|
|
@@ -38222,7 +38514,7 @@ function runStartupTasks(deps) {
|
|
|
38222
38514
|
memoryManagerRef.current?.close();
|
|
38223
38515
|
memoryManagerRef.current = null;
|
|
38224
38516
|
}
|
|
38225
|
-
const skillDbPath = cfg.memoryDbPath ??
|
|
38517
|
+
const skillDbPath = cfg.memoryDbPath ?? join56(process.cwd(), ".kimiflare", "memory.db");
|
|
38226
38518
|
const skillDb = getMemoryDb() ?? openMemoryDb(skillDbPath);
|
|
38227
38519
|
initSkillsSchema(skillDb);
|
|
38228
38520
|
void indexSkills({
|
|
@@ -38579,7 +38871,7 @@ var init_run_compact = __esm({
|
|
|
38579
38871
|
});
|
|
38580
38872
|
|
|
38581
38873
|
// src/commands/save.ts
|
|
38582
|
-
import { mkdir as
|
|
38874
|
+
import { mkdir as mkdir19, writeFile as writeFile17, unlink as unlink5 } from "fs/promises";
|
|
38583
38875
|
import { dirname as dirname21 } from "path";
|
|
38584
38876
|
async function saveCustomCommand(opts2) {
|
|
38585
38877
|
const dir = opts2.source === "project" ? projectCommandsDir(opts2.cwd) : globalCommandsDir();
|
|
@@ -38591,8 +38883,8 @@ async function saveCustomCommand(opts2) {
|
|
|
38591
38883
|
if (opts2.effort) data.effort = opts2.effort;
|
|
38592
38884
|
const frontmatter = serializeFrontmatter(data);
|
|
38593
38885
|
const content = frontmatter + opts2.template;
|
|
38594
|
-
await
|
|
38595
|
-
await
|
|
38886
|
+
await mkdir19(dirname21(filepath), { recursive: true });
|
|
38887
|
+
await writeFile17(filepath, content, "utf8");
|
|
38596
38888
|
return { filepath };
|
|
38597
38889
|
}
|
|
38598
38890
|
async function deleteCustomCommand(cmd) {
|
|
@@ -38715,7 +39007,7 @@ __export(app_exports, {
|
|
|
38715
39007
|
import React25, { useState as useState27, useRef as useRef9, useEffect as useEffect11, useCallback as useCallback8, useMemo as useMemo6 } from "react";
|
|
38716
39008
|
import { Box as Box40, Text as Text41, useApp, useInput as useInput19, useWindowSize as useWindowSize2, render } from "ink";
|
|
38717
39009
|
import { existsSync as existsSync12 } from "fs";
|
|
38718
|
-
import { join as
|
|
39010
|
+
import { join as join57, resolve as resolve19 } from "path";
|
|
38719
39011
|
import { homedir as homedir30 } from "os";
|
|
38720
39012
|
import { jsx as jsx42, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
38721
39013
|
function App({
|
|
@@ -39043,8 +39335,8 @@ ${wcagWarnings.join("\n")}` }
|
|
|
39043
39335
|
const exactDirectory = query === "~" || query === "." || query === ".." || query.endsWith("/..");
|
|
39044
39336
|
const prefix = exactDirectory ? `${query.replace(/\/$/, "")}/` : slash >= 0 ? query.slice(0, slash + 1) : "";
|
|
39045
39337
|
const directory = exactDirectory ? query : slash >= 0 ? query.slice(0, slash + 1) : query;
|
|
39046
|
-
const expanded = directory.startsWith("~") ?
|
|
39047
|
-
const target =
|
|
39338
|
+
const expanded = directory.startsWith("~") ? join57(homedir30(), directory.slice(1)) : directory;
|
|
39339
|
+
const target = resolve19(cwd, expanded || ".");
|
|
39048
39340
|
const entries2 = await glob("*", {
|
|
39049
39341
|
cwd: target,
|
|
39050
39342
|
dot: false,
|
|
@@ -40026,7 +40318,7 @@ ${result2.output ?? "(output not captured)"}`,
|
|
|
40026
40318
|
}
|
|
40027
40319
|
}
|
|
40028
40320
|
turnCounterRef.current += 1;
|
|
40029
|
-
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) {
|
|
40030
40322
|
setEvents((e) => [
|
|
40031
40323
|
...e,
|
|
40032
40324
|
{ kind: "info", key: mkKey(), text: "Tip: Rerunning /init occasionally helps autopilot (formerly kimiflare) stay accurate as your project evolves." }
|
|
@@ -40050,7 +40342,7 @@ ${result2.output ?? "(output not captured)"}`,
|
|
|
40050
40342
|
};
|
|
40051
40343
|
ensureSessionId();
|
|
40052
40344
|
const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
|
|
40053
|
-
const filePath =
|
|
40345
|
+
const filePath = join57(sessionsDir3(), `${sessionIdRef.current}.json`);
|
|
40054
40346
|
await addCheckpoint(filePath, cp);
|
|
40055
40347
|
}
|
|
40056
40348
|
const summary = await generateContinuationSummary({
|
|
@@ -40381,7 +40673,7 @@ ${result2.output ?? "(output not captured)"}`,
|
|
|
40381
40673
|
lspManagerRef.current.notifyChange(path, content2);
|
|
40382
40674
|
} else {
|
|
40383
40675
|
void import("fs/promises").then(
|
|
40384
|
-
({ readFile:
|
|
40676
|
+
({ readFile: readFile37 }) => readFile37(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
|
|
40385
40677
|
})
|
|
40386
40678
|
);
|
|
40387
40679
|
}
|
|
@@ -40574,7 +40866,7 @@ ${result2.output ?? "(output not captured)"}`,
|
|
|
40574
40866
|
};
|
|
40575
40867
|
ensureSessionId();
|
|
40576
40868
|
const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
|
|
40577
|
-
const filePath =
|
|
40869
|
+
const filePath = join57(sessionsDir3(), `${sessionIdRef.current}.json`);
|
|
40578
40870
|
await addCheckpoint(filePath, cp);
|
|
40579
40871
|
}
|
|
40580
40872
|
const summary = await generateContinuationSummary({
|
|
@@ -41141,7 +41433,7 @@ ${result2.output ?? "(output not captured)"}`,
|
|
|
41141
41433
|
lsp: {
|
|
41142
41434
|
servers: cfg?.lspServers ?? {},
|
|
41143
41435
|
scope: lspScope,
|
|
41144
|
-
hasProjectDir: existsSync12(
|
|
41436
|
+
hasProjectDir: existsSync12(join57(process.cwd(), ".kimiflare"))
|
|
41145
41437
|
}
|
|
41146
41438
|
});
|
|
41147
41439
|
});
|
|
@@ -41198,7 +41490,7 @@ ${result2.output ?? "(output not captured)"}`,
|
|
|
41198
41490
|
onCommandDelete: handleCommandDelete2,
|
|
41199
41491
|
lspServers: cfg?.lspServers ?? {},
|
|
41200
41492
|
lspScope,
|
|
41201
|
-
hasProjectDir: existsSync12(
|
|
41493
|
+
hasProjectDir: existsSync12(join57(process.cwd(), ".kimiflare")),
|
|
41202
41494
|
onLspSave: handleLspSave2,
|
|
41203
41495
|
themes: themeList(),
|
|
41204
41496
|
onPickTheme: handleThemePick,
|
|
@@ -41685,11 +41977,11 @@ init_classify();
|
|
|
41685
41977
|
init_subagent_policy();
|
|
41686
41978
|
init_trace();
|
|
41687
41979
|
init_registry2();
|
|
41688
|
-
import { readFile as
|
|
41689
|
-
import { resolve as
|
|
41980
|
+
import { readFile as readFile16 } from "fs/promises";
|
|
41981
|
+
import { resolve as resolve7, basename as basename3 } from "path";
|
|
41690
41982
|
async function resolveSession(opts2) {
|
|
41691
41983
|
if (opts2.sessionId) {
|
|
41692
|
-
const filePath =
|
|
41984
|
+
const filePath = resolve7(sessionsDir(), `${opts2.sessionId}.json`);
|
|
41693
41985
|
try {
|
|
41694
41986
|
const file = await loadSession(filePath);
|
|
41695
41987
|
return { sessionFile: file, isNew: false };
|
|
@@ -41697,7 +41989,7 @@ async function resolveSession(opts2) {
|
|
|
41697
41989
|
}
|
|
41698
41990
|
}
|
|
41699
41991
|
if (opts2.continueSession) {
|
|
41700
|
-
const cwd = opts2.dir ?
|
|
41992
|
+
const cwd = opts2.dir ? resolve7(opts2.dir) : process.cwd();
|
|
41701
41993
|
const sessions = await listSessions(1, cwd);
|
|
41702
41994
|
if (sessions.length > 0) {
|
|
41703
41995
|
const filePath = sessions[0].filePath;
|
|
@@ -41710,7 +42002,7 @@ async function resolveSession(opts2) {
|
|
|
41710
42002
|
return {
|
|
41711
42003
|
sessionFile: {
|
|
41712
42004
|
id,
|
|
41713
|
-
cwd: opts2.dir ?
|
|
42005
|
+
cwd: opts2.dir ? resolve7(opts2.dir) : process.cwd(),
|
|
41714
42006
|
model: opts2.model,
|
|
41715
42007
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
41716
42008
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -41724,9 +42016,9 @@ async function resolveFiles(filePatterns, cwd) {
|
|
|
41724
42016
|
const resolved = /* @__PURE__ */ new Set();
|
|
41725
42017
|
for (const pattern of filePatterns) {
|
|
41726
42018
|
try {
|
|
41727
|
-
const
|
|
41728
|
-
if (
|
|
41729
|
-
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));
|
|
41730
42022
|
continue;
|
|
41731
42023
|
}
|
|
41732
42024
|
} catch {
|
|
@@ -41754,7 +42046,7 @@ async function buildUserMessage(prompt, files, cwd) {
|
|
|
41754
42046
|
}
|
|
41755
42047
|
} else {
|
|
41756
42048
|
try {
|
|
41757
|
-
const content = await
|
|
42049
|
+
const content = await readFile16(filePath, "utf8");
|
|
41758
42050
|
const relPath = filePath.startsWith(cwd) ? filePath.slice(cwd.length + 1) : filePath;
|
|
41759
42051
|
fileContents.push(`
|
|
41760
42052
|
--- ${relPath} ---
|
|
@@ -41789,7 +42081,7 @@ async function runPrintMode(opts2) {
|
|
|
41789
42081
|
`
|
|
41790
42082
|
);
|
|
41791
42083
|
}
|
|
41792
|
-
const cwd = opts2.dir ?
|
|
42084
|
+
const cwd = opts2.dir ? resolve7(opts2.dir) : process.cwd();
|
|
41793
42085
|
const baseWorkerTools = getWorkerTools(opts2.workerProfile);
|
|
41794
42086
|
const { HooksManager: HooksManager2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports));
|
|
41795
42087
|
const hooks = new HooksManager2(cwd);
|
|
@@ -42469,11 +42761,11 @@ async function promptHidden(question) {
|
|
|
42469
42761
|
}
|
|
42470
42762
|
});
|
|
42471
42763
|
const rl = createInterface4({ input: process.stdin, output, terminal: true });
|
|
42472
|
-
return new Promise((
|
|
42764
|
+
return new Promise((resolve20) => {
|
|
42473
42765
|
rl.question(question, (answer) => {
|
|
42474
42766
|
rl.close();
|
|
42475
42767
|
process.stdout.write("\n");
|
|
42476
|
-
|
|
42768
|
+
resolve20(answer);
|
|
42477
42769
|
});
|
|
42478
42770
|
muted = true;
|
|
42479
42771
|
});
|