autopilot-ai 1.24.2 → 1.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,9 +1,5 @@
1
- var __create = Object.create;
2
1
  var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
2
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
3
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
4
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
5
  }) : x)(function(x) {
@@ -18,33 +14,10 @@ var __esm = (fn, res, err) => function __init() {
18
14
  throw err = [e], e;
19
15
  }
20
16
  };
21
- var __commonJS = (cb, mod) => function __require2() {
22
- try {
23
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
24
- } catch (e) {
25
- throw mod = 0, e;
26
- }
27
- };
28
17
  var __export = (target, all) => {
29
18
  for (var name in all)
30
19
  __defProp(target, name, { get: all[name], enumerable: true });
31
20
  };
32
- var __copyProps = (to, from, except, desc) => {
33
- if (from && typeof from === "object" || typeof from === "function") {
34
- for (let key of __getOwnPropNames(from))
35
- if (!__hasOwnProp.call(to, key) && key !== except)
36
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
37
- }
38
- return to;
39
- };
40
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
41
- // If the importer is in node compatibility mode or this is not an ESM
42
- // file that has been converted to a CommonJS file using a Babel-
43
- // compatible transform (i.e. "__esModule" has not been set), then set
44
- // "default" to the CommonJS "module.exports" for node compatibility.
45
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
46
- mod
47
- ));
48
21
 
49
22
  // src/util/log-sink.ts
50
23
  var log_sink_exports = {};
@@ -102,8 +75,8 @@ async function flushAndCloseForTesting() {
102
75
  const s = currentStream;
103
76
  currentStream = null;
104
77
  currentDate = null;
105
- await new Promise((resolve19) => {
106
- s.end(() => resolve19());
78
+ await new Promise((resolve20) => {
79
+ s.end(() => resolve20());
107
80
  });
108
81
  }
109
82
  function isLogSinkEnabled() {
@@ -1289,13 +1262,13 @@ async function checkDeployStatus() {
1289
1262
  }
1290
1263
  return { wrangler, wranglerAuth, docker, workerUrl };
1291
1264
  }
1292
- var __dirname2, REMOTE_DIR, WORKER_DIR;
1265
+ var __dirname, REMOTE_DIR, WORKER_DIR;
1293
1266
  var init_deploy = __esm({
1294
1267
  "src/remote/deploy.ts"() {
1295
1268
  "use strict";
1296
1269
  init_config();
1297
- __dirname2 = dirname4(fileURLToPath3(import.meta.url));
1298
- REMOTE_DIR = join7(__dirname2, "..", "..", "..", "remote");
1270
+ __dirname = dirname4(fileURLToPath3(import.meta.url));
1271
+ REMOTE_DIR = join7(__dirname, "..", "..", "..", "remote");
1299
1272
  WORKER_DIR = join7(REMOTE_DIR, "worker");
1300
1273
  }
1301
1274
  });
@@ -1342,10 +1315,10 @@ async function* readSSE(stream, signal, idleTimeoutMs, postFirstByteIdleTimeoutM
1342
1315
  gotFirstByte = true;
1343
1316
  buffer += decoder.decode(value, { stream: true });
1344
1317
  buffer = buffer.replace(/\r\n/g, "\n");
1345
- let sep7;
1346
- while ((sep7 = buffer.indexOf("\n\n")) !== -1) {
1347
- const event = buffer.slice(0, sep7);
1348
- buffer = buffer.slice(sep7 + 2);
1318
+ let sep8;
1319
+ while ((sep8 = buffer.indexOf("\n\n")) !== -1) {
1320
+ const event = buffer.slice(0, sep8);
1321
+ buffer = buffer.slice(sep8 + 2);
1349
1322
  const data = extractData(event);
1350
1323
  if (data !== null) yield data;
1351
1324
  }
@@ -2782,7 +2755,8 @@ async function* parseStream(body, signal, idleTimeoutMs = DEFAULT_IDLE_TIMEOUT_M
2782
2755
  index: idx,
2783
2756
  id: buf.id,
2784
2757
  name: buf.name,
2785
- arguments: buf.args
2758
+ arguments: buf.args,
2759
+ finishReason
2786
2760
  };
2787
2761
  }
2788
2762
  yield { type: "done", finishReason, usage: lastUsage };
@@ -2850,11 +2824,11 @@ function extractApiError(parsed, rawText) {
2850
2824
  return null;
2851
2825
  }
2852
2826
  function sleep(ms, signal) {
2853
- return new Promise((resolve19, reject) => {
2827
+ return new Promise((resolve20, reject) => {
2854
2828
  if (signal?.aborted) return reject(new DOMException("aborted", "AbortError"));
2855
2829
  const t = setTimeout(() => {
2856
2830
  signal?.removeEventListener("abort", onAbort);
2857
- resolve19();
2831
+ resolve20();
2858
2832
  }, ms);
2859
2833
  const onAbort = () => {
2860
2834
  clearTimeout(t);
@@ -2993,7 +2967,7 @@ async function pruneFiles(files, maxAgeDays, maxCount) {
2993
2967
  return removed;
2994
2968
  }
2995
2969
  async function rotateJsonl(path, maxBytes, rotations) {
2996
- const { rename: rename3 } = await import("fs/promises");
2970
+ const { rename: rename4 } = await import("fs/promises");
2997
2971
  let s;
2998
2972
  try {
2999
2973
  s = await stat2(path);
@@ -3005,7 +2979,7 @@ async function rotateJsonl(path, maxBytes, rotations) {
3005
2979
  const src = i === 1 ? path : `${path}.${i - 1}`;
3006
2980
  const dst = `${path}.${i}`;
3007
2981
  try {
3008
- await rename3(src, dst);
2982
+ await rename4(src, dst);
3009
2983
  } catch {
3010
2984
  }
3011
2985
  }
@@ -3574,197 +3548,6 @@ var init_api_generator = __esm({
3574
3548
  }
3575
3549
  });
3576
3550
 
3577
- // node_modules/node-gyp-build/node-gyp-build.js
3578
- var require_node_gyp_build = __commonJS({
3579
- "node_modules/node-gyp-build/node-gyp-build.js"(exports, module) {
3580
- "use strict";
3581
- var fs = __require("fs");
3582
- var path = __require("path");
3583
- var os2 = __require("os");
3584
- var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
3585
- var vars = process.config && process.config.variables || {};
3586
- var prebuildsOnly = !!process.env.PREBUILDS_ONLY;
3587
- var abi = process.versions.modules;
3588
- var runtime = isElectron() ? "electron" : isNwjs() ? "node-webkit" : "node";
3589
- var arch = process.env.npm_config_arch || os2.arch();
3590
- var platform8 = process.env.npm_config_platform || os2.platform();
3591
- var libc = process.env.LIBC || (isAlpine(platform8) ? "musl" : "glibc");
3592
- var armv = process.env.ARM_VERSION || (arch === "arm64" ? "8" : vars.arm_version) || "";
3593
- var uv = (process.versions.uv || "").split(".")[0];
3594
- module.exports = load;
3595
- function load(dir) {
3596
- return runtimeRequire(load.resolve(dir));
3597
- }
3598
- load.resolve = load.path = function(dir) {
3599
- dir = path.resolve(dir || ".");
3600
- try {
3601
- var name = runtimeRequire(path.join(dir, "package.json")).name.toUpperCase().replace(/-/g, "_");
3602
- if (process.env[name + "_PREBUILD"]) dir = process.env[name + "_PREBUILD"];
3603
- } catch (err) {
3604
- }
3605
- if (!prebuildsOnly) {
3606
- var release2 = getFirst(path.join(dir, "build/Release"), matchBuild);
3607
- if (release2) return release2;
3608
- var debug = getFirst(path.join(dir, "build/Debug"), matchBuild);
3609
- if (debug) return debug;
3610
- }
3611
- var prebuild = resolve19(dir);
3612
- if (prebuild) return prebuild;
3613
- var nearby = resolve19(path.dirname(process.execPath));
3614
- if (nearby) return nearby;
3615
- var target = [
3616
- "platform=" + platform8,
3617
- "arch=" + arch,
3618
- "runtime=" + runtime,
3619
- "abi=" + abi,
3620
- "uv=" + uv,
3621
- armv ? "armv=" + armv : "",
3622
- "libc=" + libc,
3623
- "node=" + process.versions.node,
3624
- process.versions.electron ? "electron=" + process.versions.electron : "",
3625
- typeof __webpack_require__ === "function" ? "webpack=true" : ""
3626
- // eslint-disable-line
3627
- ].filter(Boolean).join(" ");
3628
- throw new Error("No native build was found for " + target + "\n loaded from: " + dir + "\n");
3629
- function resolve19(dir2) {
3630
- var tuples = readdirSync2(path.join(dir2, "prebuilds")).map(parseTuple);
3631
- var tuple = tuples.filter(matchTuple(platform8, arch)).sort(compareTuples)[0];
3632
- if (!tuple) return;
3633
- var prebuilds = path.join(dir2, "prebuilds", tuple.name);
3634
- var parsed = readdirSync2(prebuilds).map(parseTags);
3635
- var candidates = parsed.filter(matchTags(runtime, abi));
3636
- var winner = candidates.sort(compareTags(runtime))[0];
3637
- if (winner) return path.join(prebuilds, winner.file);
3638
- }
3639
- };
3640
- function readdirSync2(dir) {
3641
- try {
3642
- return fs.readdirSync(dir);
3643
- } catch (err) {
3644
- return [];
3645
- }
3646
- }
3647
- function getFirst(dir, filter) {
3648
- var files = readdirSync2(dir).filter(filter);
3649
- return files[0] && path.join(dir, files[0]);
3650
- }
3651
- function matchBuild(name) {
3652
- return /\.node$/.test(name);
3653
- }
3654
- function parseTuple(name) {
3655
- var arr = name.split("-");
3656
- if (arr.length !== 2) return;
3657
- var platform9 = arr[0];
3658
- var architectures = arr[1].split("+");
3659
- if (!platform9) return;
3660
- if (!architectures.length) return;
3661
- if (!architectures.every(Boolean)) return;
3662
- return { name, platform: platform9, architectures };
3663
- }
3664
- function matchTuple(platform9, arch2) {
3665
- return function(tuple) {
3666
- if (tuple == null) return false;
3667
- if (tuple.platform !== platform9) return false;
3668
- return tuple.architectures.includes(arch2);
3669
- };
3670
- }
3671
- function compareTuples(a, b) {
3672
- return a.architectures.length - b.architectures.length;
3673
- }
3674
- function parseTags(file) {
3675
- var arr = file.split(".");
3676
- var extension = arr.pop();
3677
- var tags = { file, specificity: 0 };
3678
- if (extension !== "node") return;
3679
- for (var i = 0; i < arr.length; i++) {
3680
- var tag2 = arr[i];
3681
- if (tag2 === "node" || tag2 === "electron" || tag2 === "node-webkit") {
3682
- tags.runtime = tag2;
3683
- } else if (tag2 === "napi") {
3684
- tags.napi = true;
3685
- } else if (tag2.slice(0, 3) === "abi") {
3686
- tags.abi = tag2.slice(3);
3687
- } else if (tag2.slice(0, 2) === "uv") {
3688
- tags.uv = tag2.slice(2);
3689
- } else if (tag2.slice(0, 4) === "armv") {
3690
- tags.armv = tag2.slice(4);
3691
- } else if (tag2 === "glibc" || tag2 === "musl") {
3692
- tags.libc = tag2;
3693
- } else {
3694
- continue;
3695
- }
3696
- tags.specificity++;
3697
- }
3698
- return tags;
3699
- }
3700
- function matchTags(runtime2, abi2) {
3701
- return function(tags) {
3702
- if (tags == null) return false;
3703
- if (tags.runtime && tags.runtime !== runtime2 && !runtimeAgnostic(tags)) return false;
3704
- if (tags.abi && tags.abi !== abi2 && !tags.napi) return false;
3705
- if (tags.uv && tags.uv !== uv) return false;
3706
- if (tags.armv && tags.armv !== armv) return false;
3707
- if (tags.libc && tags.libc !== libc) return false;
3708
- return true;
3709
- };
3710
- }
3711
- function runtimeAgnostic(tags) {
3712
- return tags.runtime === "node" && tags.napi;
3713
- }
3714
- function compareTags(runtime2) {
3715
- return function(a, b) {
3716
- if (a.runtime !== b.runtime) {
3717
- return a.runtime === runtime2 ? -1 : 1;
3718
- } else if (a.abi !== b.abi) {
3719
- return a.abi ? -1 : 1;
3720
- } else if (a.specificity !== b.specificity) {
3721
- return a.specificity > b.specificity ? -1 : 1;
3722
- } else {
3723
- return 0;
3724
- }
3725
- };
3726
- }
3727
- function isNwjs() {
3728
- return !!(process.versions && process.versions.nw);
3729
- }
3730
- function isElectron() {
3731
- if (process.versions && process.versions.electron) return true;
3732
- if (process.env.ELECTRON_RUN_AS_NODE) return true;
3733
- return typeof window !== "undefined" && window.process && window.process.type === "renderer";
3734
- }
3735
- function isAlpine(platform9) {
3736
- return platform9 === "linux" && fs.existsSync("/etc/alpine-release");
3737
- }
3738
- load.parseTags = parseTags;
3739
- load.matchTags = matchTags;
3740
- load.compareTags = compareTags;
3741
- load.parseTuple = parseTuple;
3742
- load.matchTuple = matchTuple;
3743
- load.compareTuples = compareTuples;
3744
- }
3745
- });
3746
-
3747
- // node_modules/node-gyp-build/index.js
3748
- var require_node_gyp_build2 = __commonJS({
3749
- "node_modules/node-gyp-build/index.js"(exports, module) {
3750
- "use strict";
3751
- var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
3752
- if (typeof runtimeRequire.addon === "function") {
3753
- module.exports = runtimeRequire.addon.bind(runtimeRequire);
3754
- } else {
3755
- module.exports = require_node_gyp_build();
3756
- }
3757
- }
3758
- });
3759
-
3760
- // node_modules/isolated-vm/isolated-vm.js
3761
- var require_isolated_vm = __commonJS({
3762
- "node_modules/isolated-vm/isolated-vm.js"(exports, module) {
3763
- "use strict";
3764
- module.exports = require_node_gyp_build2()(__dirname).ivm;
3765
- }
3766
- });
3767
-
3768
3551
  // src/code-mode/sandbox.ts
3769
3552
  import { join as join12, dirname as dirname5 } from "path";
3770
3553
  import { pathToFileURL } from "url";
@@ -3819,9 +3602,38 @@ async function transpileOrStrip(code, cwd) {
3819
3602
  warnings: ["TypeScript not found in node_modules. Using fallback parser; install typescript for reliable transpilation."]
3820
3603
  };
3821
3604
  }
3605
+ async function loadIsolatedVm() {
3606
+ const mod = await import("isolated-vm");
3607
+ const ivm = mod.default?.Isolate ? mod.default : mod;
3608
+ if (typeof ivm.Isolate !== "function") throw new Error("isolated-vm loaded but exposes no Isolate constructor");
3609
+ return ivm;
3610
+ }
3611
+ function makeToolBridge(opts2, toolCalls) {
3612
+ let mutationTail = Promise.resolve();
3613
+ return (tool) => async (args) => {
3614
+ const invoke = async () => {
3615
+ const toolCallId = `code_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
3616
+ return opts2.executor.run(
3617
+ { id: toolCallId, name: tool.name, arguments: JSON.stringify(args ?? {}) },
3618
+ opts2.askPermission,
3619
+ opts2.ctx
3620
+ );
3621
+ };
3622
+ let result2;
3623
+ if (tool.isReadOnly === true || tool.concurrent === true) {
3624
+ result2 = await invoke();
3625
+ } else {
3626
+ const run = mutationTail.then(invoke, invoke);
3627
+ mutationTail = run.catch(() => void 0);
3628
+ result2 = await run;
3629
+ }
3630
+ toolCalls.push({ name: tool.name, args, result: result2.content, ok: result2.ok });
3631
+ return result2.content;
3632
+ };
3633
+ }
3822
3634
  async function runWithIsolatedVm(opts2) {
3823
- const { Isolate } = await Promise.resolve().then(() => __toESM(require_isolated_vm(), 1));
3824
- const isolate = new Isolate({ memoryLimit: opts2.memoryLimitMB ?? 128 });
3635
+ const ivm = await loadIsolatedVm();
3636
+ const isolate = new ivm.Isolate({ memoryLimit: opts2.memoryLimitMB ?? 128 });
3825
3637
  const context = await isolate.createContext();
3826
3638
  const jail = context.global;
3827
3639
  await jail.set("global", jail.derefInto());
@@ -3835,30 +3647,15 @@ async function runWithIsolatedVm(opts2) {
3835
3647
  { arguments: { reference: true } }
3836
3648
  );
3837
3649
  await context.eval(`var console = { log: function(...args) { _log(args.map(String).join(" ")); } };`);
3838
- const toolMap = new Map(opts2.tools.map((t) => [t.name, t]));
3650
+ const bridge = makeToolBridge(opts2, toolCalls);
3839
3651
  for (const tool of opts2.tools) {
3840
- const ref = new (await Promise.resolve().then(() => __toESM(require_isolated_vm(), 1))).Reference(
3841
- async (argsJson) => {
3842
- const args = JSON.parse(argsJson);
3843
- const toolCallId = `code_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
3844
- const result2 = await opts2.executor.run(
3845
- { id: toolCallId, name: tool.name, arguments: JSON.stringify(args) },
3846
- opts2.askPermission,
3847
- opts2.ctx
3848
- );
3849
- toolCalls.push({
3850
- name: tool.name,
3851
- args,
3852
- result: result2.content
3853
- });
3854
- return result2.content;
3855
- }
3856
- );
3652
+ const call = bridge(tool);
3653
+ const host = async (argsJson) => call(JSON.parse(argsJson));
3857
3654
  await context.evalClosure(
3858
3655
  `globalThis["_api_${tool.name}"] = function(argsJson) {
3859
3656
  return $0.applySyncPromise(undefined, [argsJson], { arguments: { copy: true } });
3860
3657
  };`,
3861
- [ref],
3658
+ [host],
3862
3659
  { arguments: { reference: true } }
3863
3660
  );
3864
3661
  }
@@ -3932,22 +3729,10 @@ async function runWithNodeVm(opts2) {
3932
3729
  NaN: NaN,
3933
3730
  undefined: void 0
3934
3731
  };
3732
+ const bridge = makeToolBridge(opts2, toolCalls);
3935
3733
  for (const tool of opts2.tools) {
3936
- sandbox.api[tool.name] = async (input) => {
3937
- const args = input ?? {};
3938
- const toolCallId = `code_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
3939
- const result2 = await opts2.executor.run(
3940
- { id: toolCallId, name: tool.name, arguments: JSON.stringify(args) },
3941
- opts2.askPermission,
3942
- opts2.ctx
3943
- );
3944
- toolCalls.push({
3945
- name: tool.name,
3946
- args,
3947
- result: result2.content
3948
- });
3949
- return result2.content;
3950
- };
3734
+ const call = bridge(tool);
3735
+ sandbox.api[tool.name] = (input) => call(input ?? {});
3951
3736
  }
3952
3737
  const { js: jsCode, warnings } = await transpileOrStrip(opts2.code, opts2.ctx.cwd);
3953
3738
  const wrapped = `"use strict";
@@ -4047,7 +3832,7 @@ function truncateForEmbedding(text) {
4047
3832
  return text.slice(0, MAX_EMBED_CHARS);
4048
3833
  }
4049
3834
  async function sleep2(ms) {
4050
- return new Promise((resolve19) => setTimeout(resolve19, ms));
3835
+ return new Promise((resolve20) => setTimeout(resolve20, ms));
4051
3836
  }
4052
3837
  async function fetchWithRetry(url, init, retries = 3) {
4053
3838
  let lastError;
@@ -4662,7 +4447,8 @@ How to work:
4662
4447
  - Prefer calling tools over guessing. Read files before editing them. Use \`glob\` and \`grep\` to explore code before assuming structure.
4663
4448
  - Before any mutating tool call (write, edit, bash), state in one short sentence what you're about to do, then call the tool. The user will be asked to approve each mutating call.
4664
4449
  - When the user asks for a change, make the change. Do not paste code in chat that you could apply with \`edit\` or \`write\`.
4665
- - When working through a multi-step task list, you MUST call \`tasks_set\` **immediately before starting each new step** and **immediately after completing each step**. Do not execute mutating tools (\`write\`, \`edit\`, \`bash\`) without updating task progress first. Skip \`tasks_set\` for trivial single-step requests.
4450
+ - For any request that needs two or more distinct steps, proactively create a visible checklist with \`tasks_set\` before doing work; do not wait for the user to ask. Keep it high-level (about 2\u20136 steps) and skip it only for a genuinely quick single-action request.
4451
+ - When working through a task list, call \`tasks_set\` **immediately before starting each new step** and **immediately after completing each step**. Pass the full list and show exactly one active step. Do not execute mutating tools (\`write\`, \`edit\`, \`bash\`) without updating task progress first.
4666
4452
  - Keep responses concise, but make them useful: the user sees tool calls inline, so do not re-summarize routine progress.
4667
4453
  - Treat blockers as problems to work through, not as a stopping point. After an error or failed attempt, diagnose the cause and try a safe, materially different recovery or verification path when possible; do not repeat the same failed attempt blindly.
4668
4454
  - Prefer resolving a blocker yourself with available tools over shifting diagnosis to the user. If you still cannot finish after reasonable attempts, say what remains undone, why it is blocked, and the single most useful next action. Make that action concrete (for example, an exact command, setting to check, or specific input you need). Ask the user to act only when their access, choice, or interactive participation is genuinely required, and never imply unverified work succeeded.
@@ -4699,6 +4485,8 @@ If the user asks what model you are, answer with exactly: \`${opts2.model}\`. Th
4699
4485
  - Today: ${date}`;
4700
4486
  const hasLsp = opts2.tools.some((t) => t.name.startsWith("lsp_"));
4701
4487
  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." : "";
4488
+ const hasArtifactTool = opts2.tools.some((t) => t.name === "create_artifact");
4489
+ 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
4490
  const tools = `Tools available:
4703
4491
  ${toolsBlock}`;
4704
4492
  const userShellBlock = userShellCommandsEnabled() ? `
@@ -4740,7 +4528,7 @@ ${opts2.lspContext}` : "";
4740
4528
  The following MCP server information was pre-computed by the coordinator.
4741
4529
 
4742
4530
  ${opts2.mcpContext}` : "";
4743
- return identity + "\n\n" + env2 + "\n\n" + tools + lspBlock + userShellBlock + contextBlock + modeBlock + skillsBlock + memoryBlock + lspContextBlock + mcpContextBlock;
4531
+ return identity + "\n\n" + env2 + "\n\n" + tools + artifactGuidance + lspBlock + userShellBlock + contextBlock + modeBlock + skillsBlock + memoryBlock + lspContextBlock + mcpContextBlock;
4744
4532
  }
4745
4533
  function buildSystemPrompt(opts2) {
4746
4534
  return buildStaticPrefix(opts2) + "\n\n" + buildSessionPrefix(opts2);
@@ -5128,7 +4916,7 @@ function shouldCheckCompletion(input, tier) {
5128
4916
  }
5129
4917
  function createJevCompletionCheck(apiKey, ask = askJev) {
5130
4918
  return async (input, signal) => {
5131
- const clip2 = (text, max) => redactPrompt(text.replace(/\s+/g, " ").trim()).slice(0, max);
4919
+ const clip3 = (text, max) => redactPrompt(text.replace(/\s+/g, " ").trim()).slice(0, max);
5132
4920
  const used = input.toolsUsed.length ? `${input.toolsUsed.length} tool calls (${[...new Set(input.toolsUsed)].join(", ")}); ${input.toolsUsed.some((t) => WRITE_TOOLS.has(t)) ? "it ran commands or edited files" : "it only read or searched"}` : "no tool calls";
5133
4921
  const timeout = AbortSignal.timeout(COMPLETION_CHECK_TIMEOUT_MS);
5134
4922
  try {
@@ -5136,9 +4924,9 @@ function createJevCompletionCheck(apiKey, ask = askJev) {
5136
4924
  kind: "yes",
5137
4925
  prompt: [
5138
4926
  "Did the assistant end its turn legitimately \u2014 either by fully completing the user's request, or by clearly explaining a blocker or question that needs the user \u2014 as opposed to stopping early, only planning, or announcing next steps it has not done?",
5139
- `User asked: ${clip2(input.userRequest, 1200)}`,
4927
+ `User asked: ${clip3(input.userRequest, 1200)}`,
5140
4928
  `During the turn the assistant made ${used}.`,
5141
- `Assistant's final message: ${clip2(input.finalText, 1500)}`
4929
+ `Assistant's final message: ${clip3(input.finalText, 1500)}`
5142
4930
  ].join("\n")
5143
4931
  }, { signal: AbortSignal.any([timeout, signal]) });
5144
4932
  return answer.type === "noul" && typeof answer.noul === "number" ? answer.noul : null;
@@ -5438,15 +5226,15 @@ async function gitNumstat(cwd, opts2 = {}) {
5438
5226
  if (opts2.includeUntracked) {
5439
5227
  try {
5440
5228
  const { stdout } = await execFileAsync("git", ["ls-files", "--others", "--exclude-standard"], { cwd, timeout: 5e3 });
5441
- const { readFile: readFile36, stat: stat13 } = await import("fs/promises");
5442
- const { join: join57 } = await import("path");
5229
+ const { readFile: readFile38, stat: stat15 } = await import("fs/promises");
5230
+ const { join: join59 } = await import("path");
5443
5231
  for (const file of stdout.split("\n").filter(Boolean)) {
5444
5232
  let lines = 0;
5445
5233
  try {
5446
- const path = join57(cwd, file);
5447
- const size = (await stat13(path)).size;
5234
+ const path = join59(cwd, file);
5235
+ const size = (await stat15(path)).size;
5448
5236
  if (size > 0 && size <= 1024 * 1024) {
5449
- const text = await readFile36(path, "utf8");
5237
+ const text = await readFile38(path, "utf8");
5450
5238
  lines = text.split("\n").length - (text.endsWith("\n") ? 1 : 0);
5451
5239
  }
5452
5240
  } catch {
@@ -5815,7 +5603,9 @@ ${codeModeApiString}
5815
5603
 
5816
5604
  Use console.log() to return results. Only console.log output is sent back to you.
5817
5605
 
5818
- IMPORTANT \u2014 explore through code, not direct tools: to read files, run shell commands, grep, or glob, call api.read(...), api.bash(...), api.grep(...), api.glob(...) INSIDE this code block and console.log only what you need. Do NOT call read/bash/grep/glob as separate tools \u2014 their full output floods your context, while here only what you log returns. Batch multiple reads/greps/commands into a single execute_code call.` + (directTools.length > 0 ? `
5606
+ IMPORTANT \u2014 explore through code, not direct tools: to read files, run shell commands, grep, or glob, call api.read(...), api.bash(...), api.grep(...), api.glob(...) INSIDE this code block and console.log only what you need. Do NOT call read/bash/grep/glob as separate tools \u2014 their full output floods your context, while here only what you log returns. Batch multiple reads/greps/commands into a single execute_code call.
5607
+
5608
+ Mutating calls (edit, write, bash, \u2026) run one at a time in call order even inside Promise.all; apply edits to the same file sequentially and re-read the file before editing it again.` + (directTools.length > 0 ? `
5819
5609
 
5820
5610
  Not in this API \u2014 call these as separate tools instead: ${directTools.map((t) => t.name).join(", ")}.` : ""),
5821
5611
  parameters: {
@@ -6048,11 +5838,11 @@ Not in this API \u2014 call these as separate tools instead: ${directTools.map((
6048
5838
  opts2.callbacks.onToolCallArgs?.(ev.index, ev.argsDelta);
6049
5839
  break;
6050
5840
  case "tool_call_complete": {
6051
- const safeArgs = validateToolArguments(ev.arguments);
5841
+ const callArgs = validateToolArguments(ev.arguments, ev.name, ev.id, ev.finishReason, opts2.sessionId);
6052
5842
  const call = {
6053
5843
  id: ev.id,
6054
5844
  type: "function",
6055
- function: { name: normalizeToolName(ev.name, opts2.tools), arguments: safeArgs }
5845
+ function: { name: normalizeToolName(ev.name, opts2.tools), arguments: callArgs }
6056
5846
  };
6057
5847
  toolCalls.push(call);
6058
5848
  tr.toolsUsed.push(call.function.name);
@@ -6535,6 +6325,7 @@ Not in this API \u2014 call these as separate tools instead: ${directTools.map((
6535
6325
  turnId
6536
6326
  );
6537
6327
  }
6328
+ logger.debug("turn:code_mode_start", { sessionId: opts2.sessionId, toolCallId: tc.id, codeChars: code.length });
6538
6329
  const sandboxResult = await runInSandbox({
6539
6330
  code,
6540
6331
  tools: sandboxTools,
@@ -6556,12 +6347,23 @@ Not in this API \u2014 call these as separate tools instead: ${directTools.map((
6556
6347
  timeoutMs: 3e4,
6557
6348
  memoryLimitMB: 128
6558
6349
  });
6350
+ logger.debug("turn:code_mode_end", {
6351
+ sessionId: opts2.sessionId,
6352
+ toolCallId: tc.id,
6353
+ durationMs: Math.round(performance.now() - sandboxStartedAt),
6354
+ error: sandboxResult.error ?? null,
6355
+ calls: sandboxResult.toolCalls.map((c) => ({
6356
+ name: c.name,
6357
+ ok: c.ok,
6358
+ path: typeof c.args?.path === "string" ? c.args.path : void 0
6359
+ }))
6360
+ });
6559
6361
  for (const stc of sandboxResult.toolCalls) {
6560
6362
  const toolResult = {
6561
6363
  tool_call_id: tc.id,
6562
6364
  name: stc.name,
6563
6365
  content: stc.result,
6564
- ok: true
6366
+ ok: stc.ok
6565
6367
  };
6566
6368
  toolResults.push(toolResult);
6567
6369
  opts2.callbacks.onToolResult?.(toolResult);
@@ -6901,14 +6703,29 @@ function replaceMessagesInPlace(target, next) {
6901
6703
  function normalizeToolName(name, tools) {
6902
6704
  return name === "spawn_worker" && tools.some((t) => t.name === "subagent") ? "subagent" : name;
6903
6705
  }
6904
- function validateToolArguments(raw) {
6905
- if (!raw || !raw.trim()) return "{}";
6906
- try {
6907
- JSON.parse(raw);
6908
- return raw;
6909
- } catch {
6910
- return "{}";
6706
+ function validateToolArguments(raw, name, id, finishReason, sessionId) {
6707
+ let issue = null;
6708
+ if (!raw.trim()) {
6709
+ issue = "empty arguments";
6710
+ } else {
6711
+ try {
6712
+ const parsed = JSON.parse(raw);
6713
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) issue = "arguments must be a JSON object";
6714
+ } catch (error) {
6715
+ issue = error instanceof Error ? error.message : "invalid JSON";
6716
+ }
6717
+ }
6718
+ if (issue) {
6719
+ logger.warn("turn:tool_arguments_invalid", {
6720
+ sessionId,
6721
+ tool: name,
6722
+ toolCallId: id,
6723
+ argumentBytes: Buffer.byteLength(raw, "utf8"),
6724
+ finishReason,
6725
+ issue
6726
+ });
6911
6727
  }
6728
+ return raw;
6912
6729
  }
6913
6730
  function llmAuthOf(opts2) {
6914
6731
  return {
@@ -7649,14 +7466,79 @@ var init_read = __esm({
7649
7466
  }
7650
7467
  });
7651
7468
 
7469
+ // src/util/file-lock.ts
7470
+ import { realpath } from "fs/promises";
7471
+ async function lockKeyFor(absPath) {
7472
+ try {
7473
+ return await realpath(absPath);
7474
+ } catch {
7475
+ return absPath;
7476
+ }
7477
+ }
7478
+ async function withFileLock2(absPath, fn) {
7479
+ const key = await lockKeyFor(absPath);
7480
+ const prev = tails.get(key) ?? Promise.resolve();
7481
+ const run = prev.then(fn, fn);
7482
+ const tail = run.then(
7483
+ () => void 0,
7484
+ () => void 0
7485
+ );
7486
+ tails.set(key, tail);
7487
+ try {
7488
+ return await run;
7489
+ } finally {
7490
+ if (tails.get(key) === tail) tails.delete(key);
7491
+ }
7492
+ }
7493
+ var tails;
7494
+ var init_file_lock = __esm({
7495
+ "src/util/file-lock.ts"() {
7496
+ "use strict";
7497
+ tails = /* @__PURE__ */ new Map();
7498
+ }
7499
+ });
7500
+
7501
+ // src/util/safe-write.ts
7502
+ import { chmod as chmod2, readFile as readFile7, rename as rename3, stat as stat5, unlink as unlink2, writeFile as writeFile6 } from "fs/promises";
7503
+ import { basename as basename2, dirname as dirname7, join as join16 } from "path";
7504
+ async function writeFileVerified(absPath, content) {
7505
+ const target = await lockKeyFor(absPath);
7506
+ let mode;
7507
+ try {
7508
+ mode = (await stat5(target)).mode & 511;
7509
+ } catch {
7510
+ }
7511
+ const tmp = join16(dirname7(target), `.${basename2(target)}.${process.pid}.${Math.random().toString(36).slice(2, 8)}.tmp`);
7512
+ try {
7513
+ await writeFile6(tmp, content, "utf8");
7514
+ if (mode !== void 0) await chmod2(tmp, mode);
7515
+ await rename3(tmp, target);
7516
+ } catch {
7517
+ await unlink2(tmp).catch(() => void 0);
7518
+ await writeFile6(target, content, "utf8");
7519
+ }
7520
+ const onDisk = await readFile7(target, "utf8");
7521
+ if (onDisk !== content) {
7522
+ throw new Error(`write verification failed for ${absPath}: file on disk does not match the intended content`);
7523
+ }
7524
+ }
7525
+ var init_safe_write = __esm({
7526
+ "src/util/safe-write.ts"() {
7527
+ "use strict";
7528
+ init_file_lock();
7529
+ }
7530
+ });
7531
+
7652
7532
  // src/tools/write.ts
7653
- import { mkdir as mkdir7, readFile as readFile7, writeFile as writeFile6 } from "fs/promises";
7654
- import { dirname as dirname7 } from "path";
7533
+ import { mkdir as mkdir7, readFile as readFile8 } from "fs/promises";
7534
+ import { dirname as dirname8 } from "path";
7655
7535
  var writeTool;
7656
7536
  var init_write = __esm({
7657
7537
  "src/tools/write.ts"() {
7658
7538
  "use strict";
7659
7539
  init_paths2();
7540
+ init_file_lock();
7541
+ init_safe_write();
7660
7542
  writeTool = {
7661
7543
  name: "write",
7662
7544
  description: "Create a file or overwrite an existing one with the given contents. Prompts the user for permission first and shows a diff preview.",
@@ -7676,22 +7558,30 @@ var init_write = __esm({
7676
7558
  }),
7677
7559
  async run(args, ctx) {
7678
7560
  const abs = resolvePath(ctx.cwd, args.path);
7679
- let before = "";
7680
- try {
7681
- before = await readFile7(abs, "utf8");
7682
- } catch {
7683
- }
7684
- await mkdir7(dirname7(abs), { recursive: true });
7685
- await writeFile6(abs, args.content, "utf8");
7686
- const verb = before ? "Overwrote" : "Created";
7687
- return `${verb} ${args.path} (${args.content.length} chars).`;
7561
+ return withFileLock2(abs, async () => {
7562
+ let before = "";
7563
+ try {
7564
+ before = await readFile8(abs, "utf8");
7565
+ } catch {
7566
+ }
7567
+ await mkdir7(dirname8(abs), { recursive: true });
7568
+ await writeFileVerified(abs, args.content);
7569
+ const verb = before ? "Overwrote" : "Created";
7570
+ return `${verb} ${args.path} (${args.content.length} chars).`;
7571
+ });
7688
7572
  }
7689
7573
  };
7690
7574
  }
7691
7575
  });
7692
7576
 
7693
7577
  // src/tools/edit.ts
7694
- import { readFile as readFile8, writeFile as writeFile7 } from "fs/promises";
7578
+ import { readFile as readFile9 } from "fs/promises";
7579
+ function replaceLiteral(haystack, needle, replacement, all) {
7580
+ if (all) return haystack.split(needle).join(replacement);
7581
+ const i = haystack.indexOf(needle);
7582
+ if (i === -1) return haystack;
7583
+ return haystack.slice(0, i) + replacement + haystack.slice(i + needle.length);
7584
+ }
7695
7585
  function countOccurrences(haystack, needle) {
7696
7586
  if (!needle) return 0;
7697
7587
  let count = 0;
@@ -7708,6 +7598,8 @@ var init_edit = __esm({
7708
7598
  "src/tools/edit.ts"() {
7709
7599
  "use strict";
7710
7600
  init_paths2();
7601
+ init_file_lock();
7602
+ init_safe_write();
7711
7603
  editTool = {
7712
7604
  name: "edit",
7713
7605
  description: "Replace an exact string in a file. If replace_all is false (default), the old_string must appear exactly once or the call fails. Prompts the user for permission first and shows a diff preview.",
@@ -7729,17 +7621,19 @@ var init_edit = __esm({
7729
7621
  }),
7730
7622
  async run(args, ctx) {
7731
7623
  const abs = resolvePath(ctx.cwd, args.path);
7732
- const orig = await readFile8(abs, "utf8");
7733
- const occurrences = countOccurrences(orig, args.old_string);
7734
- if (occurrences === 0) throw new Error(`old_string not found in ${args.path}`);
7735
- if (occurrences > 1 && !args.replace_all) {
7736
- throw new Error(
7737
- `old_string appears ${occurrences} times in ${args.path}; pass replace_all=true or include more surrounding context`
7738
- );
7739
- }
7740
- const next = args.replace_all ? orig.split(args.old_string).join(args.new_string) : orig.replace(args.old_string, args.new_string);
7741
- await writeFile7(abs, next, "utf8");
7742
- return `Replaced ${occurrences} occurrence(s) in ${args.path}.`;
7624
+ return withFileLock2(abs, async () => {
7625
+ const orig = await readFile9(abs, "utf8");
7626
+ const occurrences = countOccurrences(orig, args.old_string);
7627
+ if (occurrences === 0) throw new Error(`old_string not found in ${args.path}`);
7628
+ if (occurrences > 1 && !args.replace_all) {
7629
+ throw new Error(
7630
+ `old_string appears ${occurrences} times in ${args.path}; pass replace_all=true or include more surrounding context`
7631
+ );
7632
+ }
7633
+ const next = replaceLiteral(orig, args.old_string, args.new_string, args.replace_all === true);
7634
+ await writeFileVerified(abs, next);
7635
+ return `Replaced ${occurrences} occurrence(s) in ${args.path}.`;
7636
+ });
7743
7637
  }
7744
7638
  };
7745
7639
  }
@@ -7748,7 +7642,7 @@ var init_edit = __esm({
7748
7642
  // src/tools/bash.ts
7749
7643
  import { spawn } from "child_process";
7750
7644
  import { tmpdir, platform as platform2 } from "os";
7751
- import { join as join16 } from "path";
7645
+ import { join as join17 } from "path";
7752
7646
  function getShellCommand(override) {
7753
7647
  const raw = override?.trim();
7754
7648
  if (raw && raw !== "auto") {
@@ -7813,15 +7707,15 @@ function makeErrorOutput(message2) {
7813
7707
  return { content: message2, rawBytes: bytes, reducedBytes: bytes };
7814
7708
  }
7815
7709
  async function execOnce(command, cwd) {
7816
- return new Promise((resolve19) => {
7710
+ return new Promise((resolve20) => {
7817
7711
  const child = spawn("bash", ["-lc", command], { cwd });
7818
7712
  let out = "";
7819
7713
  child.stdout.on("data", (d) => {
7820
7714
  out += d.toString("utf8");
7821
7715
  });
7822
7716
  child.on("close", (code) => {
7823
- if (code !== 0) return resolve19(void 0);
7824
- resolve19(out.trim() || void 0);
7717
+ if (code !== 0) return resolve20(void 0);
7718
+ resolve20(out.trim() || void 0);
7825
7719
  });
7826
7720
  });
7827
7721
  }
@@ -7950,7 +7844,7 @@ function injectCoauthor(command, coauthor) {
7950
7844
  if (movesHeadOnly) return unchanged;
7951
7845
  const env2 = {
7952
7846
  [COAUTHOR_TRAILER_ENV]: trailer,
7953
- [COAUTHOR_MSG_ENV]: join16(tmpdir(), `kf-coauthor-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`)
7847
+ [COAUTHOR_MSG_ENV]: join17(tmpdir(), `kf-coauthor-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`)
7954
7848
  };
7955
7849
  if (createsCommit || isRebaseContinue) {
7956
7850
  return { command: `(${command}) && { ${AMEND_BLOCK}
@@ -7975,7 +7869,7 @@ async function runBash(args, ctx) {
7975
7869
  if (pushGuard) return pushGuard;
7976
7870
  const { shell, args: shellArgs, isPosix } = getShellCommand(ctx.shell);
7977
7871
  const { command, env: coauthorEnv } = isPosix ? injectCoauthor(args.command, ctx.coauthor) : { command: args.command, env: {} };
7978
- return new Promise((resolve19, reject) => {
7872
+ return new Promise((resolve20, reject) => {
7979
7873
  logger.debug("bash:spawn", { command: args.command.slice(0, 200), cwd: ctx.cwd, shell });
7980
7874
  const child = spawn(shell, [...shellArgs, command], {
7981
7875
  cwd: ctx.cwd,
@@ -8040,7 +7934,7 @@ ${stderr}`
8040
7934
  if (hint) parts.push(hint);
8041
7935
  }
8042
7936
  const raw = parts.join("\n");
8043
- resolve19({
7937
+ resolve20({
8044
7938
  content: raw,
8045
7939
  rawBytes: Buffer.byteLength(raw, "utf8"),
8046
7940
  reducedBytes: Buffer.byteLength(raw, "utf8"),
@@ -8091,8 +7985,8 @@ var init_bash = __esm({
8091
7985
  });
8092
7986
 
8093
7987
  // src/util/glob.ts
8094
- import { readdir as readdir3, lstat, realpath } from "fs/promises";
8095
- import { join as join17, relative as relative2, resolve as resolve2 } from "path";
7988
+ import { readdir as readdir3, lstat, realpath as realpath2 } from "fs/promises";
7989
+ import { join as join18, relative as relative2, resolve as resolve2 } from "path";
8096
7990
  function parsePattern(pattern) {
8097
7991
  const parts = pattern.split(/\//g);
8098
7992
  return parts.map((p) => {
@@ -8201,7 +8095,7 @@ async function* walk(root, pattern, options) {
8201
8095
  if (!dot && name.startsWith(".")) continue;
8202
8096
  const matched = seg.type === "literal" ? seg.value === name : matchSegment(name, seg.value);
8203
8097
  if (!matched) continue;
8204
- const childPath = join17(dirPath, name);
8098
+ const childPath = join18(dirPath, name);
8205
8099
  const childRel = [...relativeParts, name];
8206
8100
  const childRelStr = childRel.join("/");
8207
8101
  if (shouldIgnore(childRelStr, ignorePatterns)) continue;
@@ -8226,14 +8120,14 @@ async function* walk(root, pattern, options) {
8226
8120
  if (!dot && name.startsWith(".")) continue;
8227
8121
  const matched = seg.type === "literal" ? seg.value === name : matchSegment(name, seg.value);
8228
8122
  if (!matched) continue;
8229
- const childPath = join17(dirPath, name);
8123
+ const childPath = join18(dirPath, name);
8230
8124
  const childRel = [...relativeParts, name];
8231
8125
  const childRelStr = childRel.join("/");
8232
8126
  if (shouldIgnore(childRelStr, ignorePatterns)) continue;
8233
8127
  let isDir = ent.isDirectory();
8234
8128
  if (!isDir && followSymbolicLinks && ent.isSymbolicLink()) {
8235
8129
  try {
8236
- const rp = await realpath(childPath);
8130
+ const rp = await realpath2(childPath);
8237
8131
  const s = await lstat(rp);
8238
8132
  isDir = s.isDirectory();
8239
8133
  } catch {
@@ -8268,7 +8162,7 @@ async function* walk(root, pattern, options) {
8268
8162
  const name = String(ent.name);
8269
8163
  if (name === "." || name === "..") continue;
8270
8164
  if (!dot && name.startsWith(".")) continue;
8271
- const childPath = join17(dirPath, name);
8165
+ const childPath = join18(dirPath, name);
8272
8166
  const childRel = [...relativeParts, name];
8273
8167
  const childRelStr = childRel.join("/");
8274
8168
  if (shouldIgnore(childRelStr, ignorePatterns)) continue;
@@ -8276,7 +8170,7 @@ async function* walk(root, pattern, options) {
8276
8170
  let isDir = ent.isDirectory();
8277
8171
  if (!isDir && followSymbolicLinks && ent.isSymbolicLink()) {
8278
8172
  try {
8279
- const rp = await realpath(childPath);
8173
+ const rp = await realpath2(childPath);
8280
8174
  const s = await lstat(rp);
8281
8175
  isDir = s.isDirectory();
8282
8176
  } catch {
@@ -8435,7 +8329,7 @@ var init_glob2 = __esm({
8435
8329
  // src/tools/grep.ts
8436
8330
  import { execFile as execFile2 } from "child_process";
8437
8331
  import { promisify as promisify2 } from "util";
8438
- import { readFile as readFile9 } from "fs/promises";
8332
+ import { readFile as readFile10 } from "fs/promises";
8439
8333
  async function hasRipgrep() {
8440
8334
  if (cachedHasRg !== null) return cachedHasRg;
8441
8335
  try {
@@ -8482,7 +8376,7 @@ async function runJsFallback(args, root, mode, signal) {
8482
8376
  if (signal?.aborted) throw new DOMException("aborted", "AbortError");
8483
8377
  const file = files[fi];
8484
8378
  try {
8485
- const content = await readFile9(file, "utf8");
8379
+ const content = await readFile10(file, "utf8");
8486
8380
  if (mode === "files") {
8487
8381
  if (re.test(content)) out.push(file);
8488
8382
  } else {
@@ -9085,9 +8979,9 @@ var changelog_image_exports = {};
9085
8979
  __export(changelog_image_exports, {
9086
8980
  changelogImageTool: () => changelogImageTool
9087
8981
  });
9088
- import { readFile as readFile10 } from "fs/promises";
9089
- import { writeFile as writeFile8 } from "fs/promises";
9090
- import { join as join18 } from "path";
8982
+ import { readFile as readFile11 } from "fs/promises";
8983
+ import { writeFile as writeFile7 } from "fs/promises";
8984
+ import { join as join19 } from "path";
9091
8985
  async function githubFetch2(path, token) {
9092
8986
  const controller = new AbortController();
9093
8987
  const timer3 = setTimeout(() => controller.abort(), TIMEOUT_MS4);
@@ -9118,7 +9012,7 @@ function escapeXml(str) {
9118
9012
  }
9119
9013
  async function loadLogoBase64() {
9120
9014
  try {
9121
- const buf = await readFile10(join18(process.cwd(), "docs", "logo.png"));
9015
+ const buf = await readFile11(join19(process.cwd(), "docs", "logo.png"));
9122
9016
  return `data:image/png;base64,${buf.toString("base64")}`;
9123
9017
  } catch {
9124
9018
  return null;
@@ -9420,7 +9314,7 @@ Format your response as plain text bullet points, one per line, starting with "\
9420
9314
  setTask("4", "completed");
9421
9315
  setTask("5", "in_progress");
9422
9316
  const outputPath = args.output ?? `./changelog-${args.repo}-${version.replace(/[^a-zA-Z0-9._-]/g, "_")}.png`;
9423
- await writeFile8(outputPath, pngBuffer);
9317
+ await writeFile7(outputPath, pngBuffer);
9424
9318
  setTask("5", "completed");
9425
9319
  const periodLabel = days === 1 ? "past day" : `past ${days} days`;
9426
9320
  const content = `\u2713 Changelog image saved to ${outputPath}
@@ -9435,10 +9329,10 @@ Format your response as plain text bullet points, one per line, starting with "\
9435
9329
  // src/tools/browser.ts
9436
9330
  import { mkdir as mkdir8 } from "fs/promises";
9437
9331
  import { tmpdir as tmpdir2 } from "os";
9438
- import { join as join19, dirname as dirname8 } from "path";
9332
+ import { join as join20, dirname as dirname9 } from "path";
9439
9333
  async function autoScroll(page) {
9440
9334
  await page.evaluate(async () => {
9441
- await new Promise((resolve19) => {
9335
+ await new Promise((resolve20) => {
9442
9336
  let totalHeight = 0;
9443
9337
  const distance = 300;
9444
9338
  const timer3 = setInterval(() => {
@@ -9447,12 +9341,12 @@ async function autoScroll(page) {
9447
9341
  totalHeight += distance;
9448
9342
  if (totalHeight >= scrollHeight) {
9449
9343
  clearInterval(timer3);
9450
- resolve19();
9344
+ resolve20();
9451
9345
  }
9452
9346
  }, 100);
9453
9347
  setTimeout(() => {
9454
9348
  clearInterval(timer3);
9455
- resolve19();
9349
+ resolve20();
9456
9350
  }, 1e4);
9457
9351
  });
9458
9352
  });
@@ -9511,8 +9405,8 @@ var init_browser = __esm({
9511
9405
  }
9512
9406
  let screenshotPath;
9513
9407
  if (args.screenshot) {
9514
- screenshotPath = join19(tmpdir2(), `kimiflare-browser-${Date.now()}.png`);
9515
- await mkdir8(dirname8(screenshotPath), { recursive: true });
9408
+ screenshotPath = join20(tmpdir2(), `kimiflare-browser-${Date.now()}.png`);
9409
+ await mkdir8(dirname9(screenshotPath), { recursive: true });
9516
9410
  await page.screenshot({ path: screenshotPath, fullPage: true });
9517
9411
  }
9518
9412
  const text = await page.evaluate(() => {
@@ -9551,6 +9445,288 @@ var init_browser = __esm({
9551
9445
  }
9552
9446
  });
9553
9447
 
9448
+ // src/util/open-browser.ts
9449
+ import { spawn as spawn2 } from "child_process";
9450
+ import { platform as platform3 } from "os";
9451
+ function openBrowser(url) {
9452
+ if (process.env.KIMIFLARE_NO_BROWSER === "1" || process.env.BROWSER === "none") return false;
9453
+ try {
9454
+ const os2 = platform3();
9455
+ const [cmd, args] = os2 === "darwin" ? ["open", [url]] : os2 === "win32" ? ["cmd", ["/c", "start", "", url]] : ["xdg-open", [url]];
9456
+ const child = spawn2(cmd, args, { detached: true, stdio: "ignore" });
9457
+ child.on("error", () => void 0);
9458
+ child.unref();
9459
+ return true;
9460
+ } catch {
9461
+ return false;
9462
+ }
9463
+ }
9464
+ var init_open_browser = __esm({
9465
+ "src/util/open-browser.ts"() {
9466
+ "use strict";
9467
+ }
9468
+ });
9469
+
9470
+ // src/tools/html-artifact.ts
9471
+ import { chmod as chmod3, lstat as lstat2, mkdir as mkdir9, mkdtemp, readFile as readFile12, readdir as readdir4, realpath as realpath3, rm as rm2, stat as stat6, writeFile as writeFile9 } from "fs/promises";
9472
+ import { execFileSync } from "child_process";
9473
+ import { tmpdir as tmpdir3 } from "os";
9474
+ import { isAbsolute as isAbsolute2, join as join21, relative as relative3, resolve as resolve3, sep as sep2 } from "path";
9475
+ import { pathToFileURL as pathToFileURL2 } from "url";
9476
+ async function createHtmlArtifactFromFile(args, cwd, options = {}) {
9477
+ assertArtifactSourceArgs(args);
9478
+ const workspaceRoot = await getWorkspaceRoot(cwd);
9479
+ const workspaceReal = await realpath3(workspaceRoot);
9480
+ const inputPath = resolvePath(cwd, args.sourcePath);
9481
+ let inputReal;
9482
+ try {
9483
+ inputReal = await realpath3(inputPath);
9484
+ } catch (error) {
9485
+ if (error.code === "ENOENT") {
9486
+ throw new ToolError({
9487
+ code: "not_found",
9488
+ message: `Artifact source file not found: ${args.sourcePath}`,
9489
+ suggestion: "Use the write tool to create the complete HTML file first, then pass its path as sourcePath."
9490
+ });
9491
+ }
9492
+ throw error;
9493
+ }
9494
+ if (!isWithin(workspaceReal, inputReal)) {
9495
+ throw new ToolError({
9496
+ code: "policy_rejection",
9497
+ message: "Artifact sourcePath must resolve to a file inside the current workspace.",
9498
+ suggestion: "Write the HTML file inside the workspace and retry with its workspace-relative path."
9499
+ });
9500
+ }
9501
+ const info = await stat6(inputReal);
9502
+ if (!info.isFile()) {
9503
+ throw new ToolError({ code: "invalid_args", message: "Artifact sourcePath must be a regular HTML file." });
9504
+ }
9505
+ if (info.size > MAX_ARTIFACT_HTML_LENGTH * 4) {
9506
+ throw new ToolError({ code: "invalid_args", message: `Artifact HTML exceeds ${MAX_ARTIFACT_HTML_LENGTH} characters.` });
9507
+ }
9508
+ const html = await readFile12(inputReal, "utf8");
9509
+ return createHtmlArtifact({ title: args.title, html }, cwd, options);
9510
+ }
9511
+ async function createHtmlArtifact(args, cwd, options = {}) {
9512
+ assertArtifactHtmlArgs(args);
9513
+ const rootDir = options.rootDir ?? join21(tmpdir3(), ARTIFACT_ROOT);
9514
+ const workspaceRoot = await getWorkspaceRoot(cwd);
9515
+ const workspaceReal = await realpath3(workspaceRoot);
9516
+ if (isWithin(workspaceReal, resolve3(rootDir))) {
9517
+ throw new Error("Refusing to store an artifact inside the workspace: " + rootDir);
9518
+ }
9519
+ await ensureSecureRoot(rootDir);
9520
+ const rootReal = await realpath3(rootDir);
9521
+ if (isWithin(workspaceReal, rootReal)) {
9522
+ throw new Error("Refusing to store an artifact inside the workspace: " + rootReal);
9523
+ }
9524
+ await cleanupOldArtifacts(rootDir, (options.now ?? Date.now)());
9525
+ const artifactDir = await mkdtemp(join21(rootDir, ARTIFACT_PREFIX));
9526
+ await chmod3(artifactDir, 448);
9527
+ const filePath = join21(artifactDir, "index.html");
9528
+ await writeFile9(filePath, buildArtifactHtml(args.title, args.html), {
9529
+ encoding: "utf8",
9530
+ flag: "wx",
9531
+ mode: 384
9532
+ });
9533
+ const opened = (options.open ?? openBrowser)(pathToFileURL2(filePath).href);
9534
+ const status = opened ? "Opened in your browser." : "Could not open a browser automatically.";
9535
+ return "Artifact: " + args.title + "\n" + status + "\nTemporary file: " + filePath;
9536
+ }
9537
+ async function cleanupOldArtifacts(rootDir, now2 = Date.now()) {
9538
+ let entries;
9539
+ try {
9540
+ entries = await readdir4(rootDir, { withFileTypes: true });
9541
+ } catch {
9542
+ return;
9543
+ }
9544
+ for (const entry of entries) {
9545
+ if (!entry.name.startsWith(ARTIFACT_PREFIX) || !entry.isDirectory() || entry.isSymbolicLink()) continue;
9546
+ const path = join21(rootDir, entry.name);
9547
+ try {
9548
+ const info = await lstat2(path);
9549
+ if (!info.isDirectory() || info.isSymbolicLink() || now2 - info.mtimeMs < ARTIFACT_MAX_AGE_MS) continue;
9550
+ await rm2(path, { recursive: true, force: true });
9551
+ } catch {
9552
+ }
9553
+ }
9554
+ }
9555
+ function buildArtifactHtml(title, html) {
9556
+ assertArtifactHtmlArgs({ title, html });
9557
+ const safeTitle = escapeHtml(title);
9558
+ const safeSrcdoc = escapeAttribute(html);
9559
+ const lines = [
9560
+ "<!doctype html>",
9561
+ '<html lang="en">',
9562
+ "<head>",
9563
+ ' <meta charset="utf-8">',
9564
+ ' <meta name="viewport" content="width=device-width, initial-scale=1">',
9565
+ ' <meta name="theme-color" content="#090909">',
9566
+ " <title>" + safeTitle + " \xB7 Autopilot</title>",
9567
+ " <style>",
9568
+ ' :root { color-scheme: dark; font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }',
9569
+ " * { box-sizing: border-box; }",
9570
+ " html, body { width: 100%; height: 100%; margin: 0; }",
9571
+ " body { display: grid; grid-template-rows: auto minmax(0, 1fr); overflow: hidden; background: #090909; color: #f4f4f5; }",
9572
+ " .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); }",
9573
+ " .autopilot-brand { display: inline-flex; align-items: center; gap: 9px; color: #f5f5f5; font-size: 14px; font-weight: 650; letter-spacing: -.025em; text-decoration: none; }",
9574
+ " .autopilot-mark { width: 20px; height: 20px; flex: none; }",
9575
+ " .autopilot-actions { display: flex; align-items: center; gap: 16px; }",
9576
+ " .autopilot-actions a { color: #a3a3a3; font-size: 12px; text-decoration: none; transition: color .15s ease; }",
9577
+ " .autopilot-actions a:hover { color: #fff; }",
9578
+ " .autopilot-actions .star { padding: 7px 11px; border: 1px solid #343434; border-radius: 7px; color: #f0f0f0; }",
9579
+ " .autopilot-actions .star:hover { border-color: #ff9933; color: #ffb15c; }",
9580
+ " main { min-width: 0; min-height: 0; }",
9581
+ " iframe { display: block; width: 100%; height: 100%; border: 0; background: #fff; }",
9582
+ " @media (max-width: 520px) { .autopilot-bar { min-height: 48px; padding: 0 14px; } .autopilot-actions { gap: 10px; } .autopilot-actions a { font-size: 11px; } }",
9583
+ " </style>",
9584
+ "</head>",
9585
+ "<body>",
9586
+ ' <header class="autopilot-bar">',
9587
+ ' <a class="autopilot-brand" href="' + AUTOPILOT_URL + '" target="_blank" rel="noopener noreferrer" aria-label="Autopilot on GitHub">',
9588
+ ' <svg class="autopilot-mark" viewBox="0 0 24 24" role="img" aria-label="Autopilot logo" xmlns="http://www.w3.org/2000/svg">',
9589
+ ' <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"/>',
9590
+ ' <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"/>',
9591
+ " </svg>",
9592
+ " <span>autopilot</span>",
9593
+ " </a>",
9594
+ ' <nav class="autopilot-actions" aria-label="Autopilot links">',
9595
+ ' <a href="' + AUTOPILOT_URL + '" target="_blank" rel="noopener noreferrer">About Autopilot \u2197</a>',
9596
+ ' <a class="star" href="' + AUTOPILOT_URL + '" target="_blank" rel="noopener noreferrer" aria-label="Star Autopilot on GitHub">\u2606 Star on GitHub</a>',
9597
+ " </nav>",
9598
+ " </header>",
9599
+ ' <main><iframe title="' + escapeAttribute(title) + '" sandbox="allow-scripts" srcdoc="' + safeSrcdoc + '"></iframe></main>',
9600
+ "</body>",
9601
+ "</html>"
9602
+ ];
9603
+ return lines.join("\n") + "\n";
9604
+ }
9605
+ function assertArtifactSourceArgs(value) {
9606
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
9607
+ throw new ToolError({
9608
+ code: "invalid_args",
9609
+ recoverable: true,
9610
+ message: "Invalid create_artifact arguments: expected an object with a title and sourcePath.",
9611
+ suggestion: "Use write to save the complete HTML file in the workspace, then pass its path as sourcePath."
9612
+ });
9613
+ }
9614
+ const args = value;
9615
+ const issues = [];
9616
+ if (typeof args.title !== "string" || args.title.trim().length === 0 || args.title.length > MAX_ARTIFACT_TITLE_LENGTH) {
9617
+ issues.push(`title must be a non-empty string of at most ${MAX_ARTIFACT_TITLE_LENGTH} characters`);
9618
+ }
9619
+ if (typeof args.sourcePath !== "string" || args.sourcePath.trim().length === 0) {
9620
+ issues.push("sourcePath must be a non-empty path to an HTML file created with write");
9621
+ }
9622
+ if (issues.length > 0) {
9623
+ throw new ToolError({
9624
+ code: "invalid_args",
9625
+ recoverable: true,
9626
+ message: `Invalid create_artifact arguments: ${issues.join("; ")}.`,
9627
+ suggestion: "Use write to save the complete HTML file in the workspace, then call create_artifact with its title and sourcePath."
9628
+ });
9629
+ }
9630
+ }
9631
+ function assertArtifactHtmlArgs(value) {
9632
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
9633
+ throw new ToolError({
9634
+ code: "invalid_args",
9635
+ recoverable: true,
9636
+ message: "Invalid artifact content: expected an object with a title and HTML document.",
9637
+ suggestion: "Provide a non-empty title and complete HTML content."
9638
+ });
9639
+ }
9640
+ const args = value;
9641
+ const issues = [];
9642
+ if (typeof args.title !== "string" || args.title.trim().length === 0 || args.title.length > MAX_ARTIFACT_TITLE_LENGTH) {
9643
+ issues.push(`title must be a non-empty string of at most ${MAX_ARTIFACT_TITLE_LENGTH} characters`);
9644
+ }
9645
+ if (typeof args.html !== "string" || args.html.trim().length === 0 || args.html.length > MAX_ARTIFACT_HTML_LENGTH) {
9646
+ issues.push(`html must be a non-empty string of at most ${MAX_ARTIFACT_HTML_LENGTH} characters`);
9647
+ }
9648
+ if (issues.length > 0) {
9649
+ throw new ToolError({
9650
+ code: "invalid_args",
9651
+ recoverable: true,
9652
+ message: `Invalid artifact content: ${issues.join("; ")}.`,
9653
+ suggestion: "Supply a non-empty title and complete HTML document."
9654
+ });
9655
+ }
9656
+ }
9657
+ async function ensureSecureRoot(rootDir) {
9658
+ await mkdir9(rootDir, { recursive: true, mode: 448 });
9659
+ const info = await lstat2(rootDir);
9660
+ if (!info.isDirectory() || info.isSymbolicLink()) throw new Error("Artifact storage path is not a real directory: " + rootDir);
9661
+ if (typeof process.getuid === "function" && info.uid !== process.getuid()) {
9662
+ throw new Error("Artifact storage directory is not owned by the current user: " + rootDir);
9663
+ }
9664
+ if ((info.mode & 63) !== 0) await chmod3(rootDir, 448);
9665
+ }
9666
+ async function getWorkspaceRoot(cwd) {
9667
+ try {
9668
+ return execFileSync("git", ["rev-parse", "--show-toplevel"], {
9669
+ cwd,
9670
+ encoding: "utf8",
9671
+ stdio: ["ignore", "pipe", "ignore"]
9672
+ }).trim();
9673
+ } catch {
9674
+ return cwd;
9675
+ }
9676
+ }
9677
+ function isWithin(parent, candidate) {
9678
+ const rel = relative3(parent, candidate);
9679
+ return rel === "" || rel !== ".." && !rel.startsWith(".." + sep2) && !isAbsolute2(rel);
9680
+ }
9681
+ function escapeHtml(value) {
9682
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
9683
+ }
9684
+ function escapeAttribute(value) {
9685
+ return escapeHtml(value).replaceAll('"', "&quot;").replaceAll("'", "&#39;");
9686
+ }
9687
+ var ARTIFACT_ROOT, ARTIFACT_PREFIX, ARTIFACT_MAX_AGE_MS, AUTOPILOT_URL, MAX_ARTIFACT_TITLE_LENGTH, MAX_ARTIFACT_HTML_LENGTH, htmlArtifactTool;
9688
+ var init_html_artifact = __esm({
9689
+ "src/tools/html-artifact.ts"() {
9690
+ "use strict";
9691
+ init_paths2();
9692
+ init_open_browser();
9693
+ init_tool_error();
9694
+ ARTIFACT_ROOT = "autopilot-artifacts";
9695
+ ARTIFACT_PREFIX = "artifact-";
9696
+ ARTIFACT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
9697
+ AUTOPILOT_URL = "https://github.com/sinameraji/autopilot";
9698
+ MAX_ARTIFACT_TITLE_LENGTH = 160;
9699
+ MAX_ARTIFACT_HTML_LENGTH = 1e6;
9700
+ htmlArtifactTool = {
9701
+ name: "create_artifact",
9702
+ 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.",
9703
+ parameters: {
9704
+ type: "object",
9705
+ properties: {
9706
+ title: {
9707
+ type: "string",
9708
+ description: "Non-empty, short human-readable artifact title."
9709
+ },
9710
+ sourcePath: {
9711
+ type: "string",
9712
+ description: "Workspace-relative path to the complete HTML file already created with the write tool."
9713
+ }
9714
+ },
9715
+ required: ["title", "sourcePath"],
9716
+ additionalProperties: false
9717
+ },
9718
+ needsPermission: true,
9719
+ render: (args) => ({
9720
+ title: "create artifact: " + String(args.title ?? "Missing title").slice(0, 80),
9721
+ body: `Read ${String(args.sourcePath ?? "Missing sourcePath")} \xB7 opens in your browser`
9722
+ }),
9723
+ async run(args, ctx) {
9724
+ return createHtmlArtifactFromFile(args, ctx.cwd);
9725
+ }
9726
+ };
9727
+ }
9728
+ });
9729
+
9554
9730
  // src/tools/tasks.ts
9555
9731
  var tasksSetTool;
9556
9732
  var init_tasks = __esm({
@@ -9561,8 +9737,8 @@ var init_tasks = __esm({
9561
9737
  name: "tasks_set",
9562
9738
  description: [
9563
9739
  "Set the visible task list shown to the user during this turn.",
9564
- "Call this when the user has given you a multi-step job, or whenever progress changes:",
9565
- "at the start (all tasks pending, with exactly one in_progress), and after each step completes",
9740
+ "Call this proactively for any request that needs two or more distinct steps, before starting work, and whenever progress changes:",
9741
+ "at the start (all tasks pending except exactly one in_progress), and after each step completes",
9566
9742
  "(flip that task to completed and the next to in_progress).",
9567
9743
  "Pass the ENTIRE task list each call \u2014 this replaces the panel.",
9568
9744
  "Keep tasks short (one imperative clause). Only one should be in_progress at a time.",
@@ -9766,9 +9942,9 @@ var init_memory = __esm({
9766
9942
 
9767
9943
  // src/tools/hotcell-snapshot.ts
9768
9944
  import { execFile as execFile4 } from "child_process";
9769
- import { mkdtemp, rm as rm2 } from "fs/promises";
9770
- import { tmpdir as tmpdir3 } from "os";
9771
- import { join as join20 } from "path";
9945
+ import { mkdtemp as mkdtemp2, rm as rm3 } from "fs/promises";
9946
+ import { tmpdir as tmpdir4 } from "os";
9947
+ import { join as join22 } from "path";
9772
9948
  import { promisify as promisify4 } from "util";
9773
9949
  async function git(args, cwd, env2) {
9774
9950
  const { stdout } = await execFileAsync2("git", args, {
@@ -9816,9 +9992,9 @@ async function getRepositorySnapshot(cwd) {
9816
9992
  if (!ref) {
9817
9993
  throw new Error("Could not find an origin branch containing the base commit. Run git fetch, then retry.");
9818
9994
  }
9819
- const scratch = await mkdtemp(join20(tmpdir3(), "autopilot-snapshot-"));
9995
+ const scratch = await mkdtemp2(join22(tmpdir4(), "autopilot-snapshot-"));
9820
9996
  try {
9821
- const env2 = { GIT_INDEX_FILE: join20(scratch, "index") };
9997
+ const env2 = { GIT_INDEX_FILE: join22(scratch, "index") };
9822
9998
  await git(["read-tree", "HEAD"], root, env2);
9823
9999
  await git(["add", "-A", "--", ".", ...SECRET_EXCLUDES], root, env2);
9824
10000
  const tree = (await git(["write-tree"], root, env2)).trim();
@@ -9837,15 +10013,15 @@ async function getRepositorySnapshot(cwd) {
9837
10013
  }
9838
10014
  return { url, ref, commit, patch: patch.toString("base64"), changedFiles: names.length };
9839
10015
  } finally {
9840
- await rm2(scratch, { recursive: true, force: true });
10016
+ await rm3(scratch, { recursive: true, force: true });
9841
10017
  }
9842
10018
  }
9843
10019
  async function getWorkingTreeArchive(cwd, limitBytes = MAX_ARCHIVE_BYTES) {
9844
10020
  const root = (await git(["rev-parse", "--show-toplevel"], cwd).catch(() => "")).trim();
9845
10021
  if (!root) throw new Error("Subagents need to run inside a Git repository.");
9846
- const scratch = await mkdtemp(join20(tmpdir3(), "autopilot-archive-"));
10022
+ const scratch = await mkdtemp2(join22(tmpdir4(), "autopilot-archive-"));
9847
10023
  try {
9848
- const env2 = { GIT_INDEX_FILE: join20(scratch, "index") };
10024
+ const env2 = { GIT_INDEX_FILE: join22(scratch, "index") };
9849
10025
  const hasHead = await git(["rev-parse", "--verify", "-q", "HEAD"], root).then(() => true, () => false);
9850
10026
  await git(hasHead ? ["read-tree", "HEAD"] : ["read-tree", "--empty"], root, env2);
9851
10027
  await git(["add", "-A", "--", ".", ...SECRET_EXCLUDES], root, env2);
@@ -9859,7 +10035,7 @@ async function getWorkingTreeArchive(cwd, limitBytes = MAX_ARCHIVE_BYTES) {
9859
10035
  bytes: tarball.byteLength
9860
10036
  };
9861
10037
  } finally {
9862
- await rm2(scratch, { recursive: true, force: true });
10038
+ await rm3(scratch, { recursive: true, force: true });
9863
10039
  }
9864
10040
  }
9865
10041
  function chunkPayload(base64, chunkSize = PAYLOAD_CHUNK_CHARS) {
@@ -9893,22 +10069,22 @@ var init_hotcell_snapshot = __esm({
9893
10069
  });
9894
10070
 
9895
10071
  // src/tools/hotcell-worker-cache.ts
9896
- import { mkdir as mkdir9, readFile as readFile11, writeFile as writeFile10 } from "fs/promises";
10072
+ import { mkdir as mkdir10, readFile as readFile13, writeFile as writeFile10 } from "fs/promises";
9897
10073
  import { homedir as homedir11 } from "os";
9898
- import { dirname as dirname9, join as join21 } from "path";
10074
+ import { dirname as dirname10, join as join23 } from "path";
9899
10075
  function workerCachePath() {
9900
- const xdg = process.env.XDG_CONFIG_HOME || join21(homedir11(), ".config");
9901
- return join21(xdg, "kimiflare", "hotcell-worker-cache.json");
10076
+ const xdg = process.env.XDG_CONFIG_HOME || join23(homedir11(), ".config");
10077
+ return join23(xdg, "kimiflare", "hotcell-worker-cache.json");
9902
10078
  }
9903
10079
  async function readCache2() {
9904
10080
  try {
9905
- return JSON.parse(await readFile11(workerCachePath(), "utf8"));
10081
+ return JSON.parse(await readFile13(workerCachePath(), "utf8"));
9906
10082
  } catch {
9907
10083
  return {};
9908
10084
  }
9909
10085
  }
9910
10086
  async function writeCache2(cache) {
9911
- await mkdir9(dirname9(workerCachePath()), { recursive: true });
10087
+ await mkdir10(dirname10(workerCachePath()), { recursive: true });
9912
10088
  await writeFile10(workerCachePath(), JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
9913
10089
  }
9914
10090
  function ensureWorkerBackup(opts2) {
@@ -9969,13 +10145,13 @@ var init_hotcell_worker_cache = __esm({
9969
10145
  });
9970
10146
 
9971
10147
  // src/tools/hotcell-worker.ts
9972
- import { spawn as spawn2 } from "child_process";
10148
+ import { spawn as spawn3 } from "child_process";
9973
10149
  import { promisify as promisify5 } from "util";
9974
10150
  import { execFile as execFile5 } from "child_process";
9975
- import { resolve as resolve3 } from "path";
10151
+ import { resolve as resolve4 } from "path";
9976
10152
  async function runHotcellWorker(options) {
9977
10153
  const workerId = `hotcell-${crypto.randomUUID().slice(0, 8)}`;
9978
- const cwd = resolve3(options.cwd ?? process.cwd());
10154
+ const cwd = resolve4(options.cwd ?? process.cwd());
9979
10155
  const model = options.model.trim();
9980
10156
  if (!model) throw new Error("Hotcell workers require the coordinator's explicit model ID.");
9981
10157
  validateModelId(model);
@@ -10283,7 +10459,7 @@ function parsePrintOutput(stdout) {
10283
10459
  async function runProcess(executable, args, options) {
10284
10460
  if (options.signal?.aborted) return { code: 130, stdout: "", stderr: "", aborted: true };
10285
10461
  return await new Promise((resolvePromise, reject) => {
10286
- const child = spawn2(executable, args, { cwd: options.cwd, stdio: ["ignore", "pipe", "pipe"] });
10462
+ const child = spawn3(executable, args, { cwd: options.cwd, stdio: ["ignore", "pipe", "pipe"] });
10287
10463
  const stdout = [];
10288
10464
  const stderr = [];
10289
10465
  let bytes = 0;
@@ -10515,17 +10691,17 @@ var init_worker_registry = __esm({
10515
10691
  });
10516
10692
 
10517
10693
  // src/tools/subagent-stats.ts
10518
- import { appendFile as appendFile2, mkdir as mkdir10, readFile as readFile12 } from "fs/promises";
10694
+ import { appendFile as appendFile2, mkdir as mkdir11, readFile as readFile14 } from "fs/promises";
10519
10695
  import { homedir as homedir12 } from "os";
10520
- import { dirname as dirname10, join as join22 } from "path";
10696
+ import { dirname as dirname11, join as join24 } from "path";
10521
10697
  function subagentStatsPath() {
10522
- const xdg = process.env.XDG_DATA_HOME || join22(homedir12(), ".local", "share");
10523
- return join22(xdg, "kimiflare", "subagents.jsonl");
10698
+ const xdg = process.env.XDG_DATA_HOME || join24(homedir12(), ".local", "share");
10699
+ return join24(xdg, "kimiflare", "subagents.jsonl");
10524
10700
  }
10525
10701
  async function recordSubagentEvent(event) {
10526
10702
  const path = subagentStatsPath();
10527
10703
  try {
10528
- await mkdir10(dirname10(path), { recursive: true });
10704
+ await mkdir11(dirname11(path), { recursive: true });
10529
10705
  await appendFile2(path, JSON.stringify(event) + "\n");
10530
10706
  } catch (error) {
10531
10707
  logger.debug("subagents:stats_write_failed", { error: String(error) });
@@ -10545,7 +10721,7 @@ function failureReason(error) {
10545
10721
  async function readSubagentStats(days = 7, now2 = Date.now()) {
10546
10722
  let raw = "";
10547
10723
  try {
10548
- raw = await readFile12(subagentStatsPath(), "utf8");
10724
+ raw = await readFile14(subagentStatsPath(), "utf8");
10549
10725
  } catch {
10550
10726
  }
10551
10727
  const since = now2 - days * 24 * 60 * 60 * 1e3;
@@ -11439,18 +11615,18 @@ var init_expand_artifact = __esm({
11439
11615
 
11440
11616
  // src/jobs/manager.ts
11441
11617
  import Database from "better-sqlite3";
11442
- import { spawn as spawn3, execFileSync } from "child_process";
11618
+ import { spawn as spawn4, execFileSync as execFileSync2 } from "child_process";
11443
11619
  import { mkdirSync as mkdirSync5, openSync, readFileSync as readFileSync4, readSync, existsSync as existsSync4, statSync as statSync3, closeSync, rmSync } from "fs";
11444
11620
  import { homedir as homedir13 } from "os";
11445
- import { dirname as dirname11, join as join23 } from "path";
11621
+ import { dirname as dirname12, join as join25 } from "path";
11446
11622
  import { randomUUID as randomUUID4 } from "crypto";
11447
11623
  function defaultJobDbPath() {
11448
- const root = process.env.XDG_STATE_HOME || join23(homedir13(), ".local", "state");
11449
- return process.env.AUTOPILOT_JOBS_DB || join23(root, "autopilot", "jobs.db");
11624
+ const root = process.env.XDG_STATE_HOME || join25(homedir13(), ".local", "state");
11625
+ return process.env.AUTOPILOT_JOBS_DB || join25(root, "autopilot", "jobs.db");
11450
11626
  }
11451
11627
  function isProcessGroupAlive(pgid) {
11452
11628
  try {
11453
- const rows = execFileSync("ps", ["-axo", "pgid=,state="], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
11629
+ const rows = execFileSync2("ps", ["-axo", "pgid=,state="], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
11454
11630
  return rows.split("\n").some((line) => {
11455
11631
  const match = line.trim().match(/^(\d+)\s+(\S+)/);
11456
11632
  return match?.[1] === String(pgid) && !match[2].startsWith("Z");
@@ -11476,22 +11652,22 @@ function waitForProcessStartTime(pid, jobId, exitPath) {
11476
11652
  function readProcessStartTime(pid) {
11477
11653
  if (process.platform === "linux") {
11478
11654
  try {
11479
- const stat13 = readFileSync4(`/proc/${pid}/stat`, "utf8");
11480
- const fieldsAfterCommand = stat13.slice(stat13.lastIndexOf(")") + 1).trim().split(/\s+/);
11655
+ const stat15 = readFileSync4(`/proc/${pid}/stat`, "utf8");
11656
+ const fieldsAfterCommand = stat15.slice(stat15.lastIndexOf(")") + 1).trim().split(/\s+/);
11481
11657
  return fieldsAfterCommand[19] ? `linux:${fieldsAfterCommand[19]}` : null;
11482
11658
  } catch {
11483
11659
  return null;
11484
11660
  }
11485
11661
  }
11486
11662
  try {
11487
- return execFileSync("ps", ["-o", "lstart=", "-o", "command=", "-p", String(pid)], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim() || null;
11663
+ return execFileSync2("ps", ["-o", "lstart=", "-o", "command=", "-p", String(pid)], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim() || null;
11488
11664
  } catch {
11489
11665
  return null;
11490
11666
  }
11491
11667
  }
11492
11668
  function isZombie(pid) {
11493
11669
  try {
11494
- const state = execFileSync("ps", ["-o", "state=", "-p", String(pid)], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
11670
+ const state = execFileSync2("ps", ["-o", "state=", "-p", String(pid)], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
11495
11671
  return state.startsWith("Z");
11496
11672
  } catch {
11497
11673
  return true;
@@ -11589,8 +11765,8 @@ child.on('close', (code, signal) => {
11589
11765
  db;
11590
11766
  jobsDir;
11591
11767
  constructor(dbPath = defaultJobDbPath()) {
11592
- mkdirSync5(dirname11(dbPath), { recursive: true, mode: 448 });
11593
- this.jobsDir = join23(dirname11(dbPath), "jobs");
11768
+ mkdirSync5(dirname12(dbPath), { recursive: true, mode: 448 });
11769
+ this.jobsDir = join25(dirname12(dbPath), "jobs");
11594
11770
  mkdirSync5(this.jobsDir, { recursive: true, mode: 448 });
11595
11771
  this.db = new Database(dbPath);
11596
11772
  this.db.pragma("journal_mode = WAL");
@@ -11641,13 +11817,13 @@ child.on('close', (code, signal) => {
11641
11817
  if (existing) return toJobRecord(existing);
11642
11818
  }
11643
11819
  const id = randomUUID4();
11644
- const jobDir = join23(this.jobsDir, id);
11820
+ const jobDir = join25(this.jobsDir, id);
11645
11821
  mkdirSync5(jobDir, { recursive: true, mode: 448 });
11646
11822
  const paths = {
11647
- stdoutPath: join23(jobDir, "stdout.log"),
11648
- stderrPath: join23(jobDir, "stderr.log"),
11649
- exitPath: join23(jobDir, "exit.json"),
11650
- pidPath: join23(jobDir, "pid")
11823
+ stdoutPath: join25(jobDir, "stdout.log"),
11824
+ stderrPath: join25(jobDir, "stderr.log"),
11825
+ exitPath: join25(jobDir, "exit.json"),
11826
+ pidPath: join25(jobDir, "pid")
11651
11827
  };
11652
11828
  const now2 = Date.now();
11653
11829
  try {
@@ -11671,7 +11847,7 @@ child.on('close', (code, signal) => {
11671
11847
  timeoutMs: options.timeoutMs ?? null,
11672
11848
  ...paths
11673
11849
  });
11674
- const child = spawn3(process.execPath, ["--input-type=module", "-e", JOB_WRAPPER, spec], {
11850
+ const child = spawn4(process.execPath, ["--input-type=module", "-e", JOB_WRAPPER, spec], {
11675
11851
  cwd: options.cwd,
11676
11852
  detached: true,
11677
11853
  stdio: "ignore",
@@ -11928,10 +12104,10 @@ import Database2 from "better-sqlite3";
11928
12104
  import { createHash as createHash2, randomUUID as randomUUID5 } from "crypto";
11929
12105
  import { chmodSync, mkdirSync as mkdirSync6 } from "fs";
11930
12106
  import { homedir as homedir14 } from "os";
11931
- import { dirname as dirname12, join as join24 } from "path";
12107
+ import { dirname as dirname13, join as join26 } from "path";
11932
12108
  function defaultRunsDbPath() {
11933
- const root = process.env.XDG_STATE_HOME || join24(homedir14(), ".local", "state");
11934
- return process.env.AUTOPILOT_RUNS_DB || join24(root, "autopilot", "runs.db");
12109
+ const root = process.env.XDG_STATE_HOME || join26(homedir14(), ".local", "state");
12110
+ return process.env.AUTOPILOT_RUNS_DB || join26(root, "autopilot", "runs.db");
11935
12111
  }
11936
12112
  function validateOptionalPositiveInteger(name, value, minimum = 1) {
11937
12113
  if (value !== null && (!Number.isSafeInteger(value) || value < minimum)) {
@@ -12019,7 +12195,7 @@ var init_store = __esm({
12019
12195
  RunStore = class {
12020
12196
  db;
12021
12197
  constructor(dbPath = defaultRunsDbPath()) {
12022
- mkdirSync6(dirname12(dbPath), { recursive: true, mode: 448 });
12198
+ mkdirSync6(dirname13(dbPath), { recursive: true, mode: 448 });
12023
12199
  this.db = new Database2(dbPath);
12024
12200
  this.db.pragma("journal_mode = WAL");
12025
12201
  this.db.pragma("foreign_keys = ON");
@@ -12541,8 +12717,8 @@ var init_wait_for = __esm({
12541
12717
  });
12542
12718
 
12543
12719
  // src/tools/executor.ts
12544
- import { realpath as realpath2 } from "fs/promises";
12545
- import { isAbsolute as isAbsolute2, relative as relative3, resolve as resolve4, sep as sep2 } from "path";
12720
+ import { realpath as realpath4 } from "fs/promises";
12721
+ import { isAbsolute as isAbsolute3, relative as relative4, resolve as resolve5, sep as sep3 } from "path";
12546
12722
  function getWorkerTools(profile) {
12547
12723
  return profile === "research" ? ALL_TOOLS.filter((tool) => RESEARCH_WORKER_TOOL_NAMES.has(tool.name) && tool.isReadOnly === true).map(restrictResearchTool) : ALL_TOOLS;
12548
12724
  }
@@ -12563,28 +12739,28 @@ function restrictResearchTool(tool) {
12563
12739
  }
12564
12740
  async function assertResearchPath(pathValue, cwd) {
12565
12741
  if (typeof pathValue !== "string" || !pathValue) throw new Error("Research worker paths must be non-empty strings.");
12566
- const root = await realpath2(cwd);
12567
- const candidate = resolve4(root, pathValue);
12742
+ const root = await realpath4(cwd);
12743
+ const candidate = resolve5(root, pathValue);
12568
12744
  assertInsideResearchRoot(candidate, root);
12569
12745
  assertNoSensitivePath(candidate, root);
12570
- const actual = await realpath2(candidate);
12746
+ const actual = await realpath4(candidate);
12571
12747
  assertInsideResearchRoot(actual, root);
12572
12748
  assertNoSensitivePath(actual, root);
12573
12749
  }
12574
12750
  function assertInsideResearchRoot(path, root) {
12575
- const rel = relative3(root, path);
12576
- if (rel === ".." || rel.startsWith(`..${sep2}`) || isAbsolute2(rel)) {
12751
+ const rel = relative4(root, path);
12752
+ if (rel === ".." || rel.startsWith(`..${sep3}`) || isAbsolute3(rel)) {
12577
12753
  throw new Error("Research workers may only inspect paths inside their cloned repository.");
12578
12754
  }
12579
12755
  }
12580
12756
  function assertNoSensitivePath(path, root) {
12581
- const parts = relative3(root, path).split(sep2).filter(Boolean).map((part) => part.toLowerCase());
12757
+ const parts = relative4(root, path).split(sep3).filter(Boolean).map((part) => part.toLowerCase());
12582
12758
  if (parts.some((part) => part === ".env" || part.startsWith(".env.") || SENSITIVE_RESEARCH_PATHS.has(part))) {
12583
12759
  throw new Error("Research worker access to environment, credential, and VCS metadata paths is blocked.");
12584
12760
  }
12585
12761
  }
12586
12762
  function assertSafePattern(value) {
12587
- if (typeof value !== "string" || !value || isAbsolute2(value)) {
12763
+ if (typeof value !== "string" || !value || isAbsolute3(value)) {
12588
12764
  throw new Error("Research worker glob patterns must be relative to the repository.");
12589
12765
  }
12590
12766
  const parts = value.replaceAll("\\\\", "/").split("/");
@@ -12637,9 +12813,6 @@ function normalizeToolOutput(result2) {
12637
12813
  }
12638
12814
  return result2;
12639
12815
  }
12640
- function truncateForError(s) {
12641
- return s.length <= 200 ? s : `${s.slice(0, 200)}... [${s.length - 200} more chars]`;
12642
- }
12643
12816
  var ALL_TOOLS, RESEARCH_WORKER_TOOL_NAMES, SENSITIVE_RESEARCH_PATHS, HOOK_RESULT_CONTENT_CAP_BYTES, ToolExecutor, TRACE_ARGS_INLINE_MAX, ToolTrace;
12644
12817
  var init_executor = __esm({
12645
12818
  "src/tools/executor.ts"() {
@@ -12658,6 +12831,7 @@ var init_executor = __esm({
12658
12831
  init_github();
12659
12832
  init_changelog_image();
12660
12833
  init_browser();
12834
+ init_html_artifact();
12661
12835
  init_tasks();
12662
12836
  init_memory();
12663
12837
  init_subagent();
@@ -12685,6 +12859,7 @@ var init_executor = __esm({
12685
12859
  githubCreatePrTool,
12686
12860
  { ...changelogImageTool, isReadOnly: true },
12687
12861
  { ...browserFetchTool, isReadOnly: true },
12862
+ htmlArtifactTool,
12688
12863
  tasksSetTool,
12689
12864
  memoryRememberTool,
12690
12865
  { ...memoryRecallTool, isReadOnly: true },
@@ -12783,17 +12958,23 @@ var init_executor = __esm({
12783
12958
  }
12784
12959
  let args;
12785
12960
  try {
12786
- args = call.arguments.trim() ? JSON.parse(call.arguments) : {};
12961
+ if (!call.arguments.trim()) throw new SyntaxError("tool arguments were empty");
12962
+ const parsed = JSON.parse(call.arguments);
12963
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
12964
+ throw new SyntaxError("tool arguments must be a JSON object");
12965
+ }
12966
+ args = parsed;
12787
12967
  } catch (e) {
12788
12968
  tr?.call(null, tool.needsPermission);
12969
+ 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
12970
  return {
12790
12971
  tool_call_id: call.id,
12791
12972
  name: call.name,
12792
- content: `Error: invalid JSON arguments for ${call.name}: ${e.message}. Arguments received: ${truncateForError(call.arguments)}`,
12973
+ content: `Error: invalid JSON arguments for ${call.name}: ${e.message}. No tool action was performed (${Buffer.byteLength(call.arguments, "utf8")} argument bytes).`,
12793
12974
  ok: false,
12794
12975
  errorCode: "invalid_args",
12795
- recoverable: false,
12796
- suggestion: "reformulate the tool call with valid JSON arguments"
12976
+ recoverable: true,
12977
+ suggestion: artifactSuggestion
12797
12978
  };
12798
12979
  }
12799
12980
  tr?.call(args, tool.needsPermission);
@@ -13110,12 +13291,12 @@ __export(sessions_exports, {
13110
13291
  saveSession: () => saveSession,
13111
13292
  sessionsDir: () => sessionsDir
13112
13293
  });
13113
- import { readFile as readFile13, writeFile as writeFile11, mkdir as mkdir11, readdir as readdir4, stat as stat5 } from "fs/promises";
13294
+ import { readFile as readFile15, writeFile as writeFile11, mkdir as mkdir12, readdir as readdir5, stat as stat7 } from "fs/promises";
13114
13295
  import { homedir as homedir15 } from "os";
13115
- import { join as join25 } from "path";
13296
+ import { join as join27 } from "path";
13116
13297
  function sessionsDir() {
13117
- const xdg = process.env.XDG_DATA_HOME || join25(homedir15(), ".local", "share");
13118
- return join25(xdg, "kimiflare", "sessions");
13298
+ const xdg = process.env.XDG_DATA_HOME || join27(homedir15(), ".local", "share");
13299
+ return join27(xdg, "kimiflare", "sessions");
13119
13300
  }
13120
13301
  function sanitize(text) {
13121
13302
  return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
@@ -13134,8 +13315,8 @@ function makeSessionId(firstPrompt) {
13134
13315
  }
13135
13316
  async function saveSession(file) {
13136
13317
  const dir = sessionsDir();
13137
- await mkdir11(dir, { recursive: true });
13138
- const path = join25(dir, `${file.id}.json`);
13318
+ await mkdir12(dir, { recursive: true });
13319
+ const path = join27(dir, `${file.id}.json`);
13139
13320
  await writeFile11(path, JSON.stringify(file, null, 2), "utf8");
13140
13321
  return path;
13141
13322
  }
@@ -13148,16 +13329,16 @@ async function listSessions(limit = 30, cwd) {
13148
13329
  const dir = sessionsDir();
13149
13330
  let entries;
13150
13331
  try {
13151
- entries = await readdir4(dir);
13332
+ entries = await readdir5(dir);
13152
13333
  } catch {
13153
13334
  return [];
13154
13335
  }
13155
13336
  const summaries = [];
13156
13337
  for (const name of entries) {
13157
13338
  if (!name.endsWith(".json")) continue;
13158
- const path = join25(dir, name);
13339
+ const path = join27(dir, name);
13159
13340
  try {
13160
- const [s, raw] = await Promise.all([stat5(path), readFile13(path, "utf8")]);
13341
+ const [s, raw] = await Promise.all([stat7(path), readFile15(path, "utf8")]);
13161
13342
  const parsed = JSON.parse(raw);
13162
13343
  if (cwd && parsed.cwd !== cwd) continue;
13163
13344
  const firstUser = parsed.messages.find((m) => m.role === "user");
@@ -13179,7 +13360,7 @@ async function listSessions(limit = 30, cwd) {
13179
13360
  return summaries.slice(0, limit);
13180
13361
  }
13181
13362
  async function loadSession(filePath) {
13182
- const raw = await readFile13(filePath, "utf8");
13363
+ const raw = await readFile15(filePath, "utf8");
13183
13364
  const file = JSON.parse(raw);
13184
13365
  if (Array.isArray(file.messages)) repairDanglingToolCalls(file.messages);
13185
13366
  return file;
@@ -13229,10 +13410,10 @@ var init_sessions = __esm({
13229
13410
  });
13230
13411
 
13231
13412
  // src/util/image.ts
13232
- import { readFile as readFile14 } from "fs/promises";
13233
- import { basename as basename2 } from "path";
13413
+ import { readFile as readFile16 } from "fs/promises";
13414
+ import { basename as basename3 } from "path";
13234
13415
  async function encodeImageFile(filePath) {
13235
- const buf = await readFile14(filePath);
13416
+ const buf = await readFile16(filePath);
13236
13417
  if (buf.byteLength > MAX_IMAGE_BYTES) {
13237
13418
  throw new Error(
13238
13419
  `image too large (${(buf.byteLength / 1024 / 1024).toFixed(1)} MB); max is ${MAX_IMAGE_BYTES / 1024 / 1024} MB`
@@ -13242,7 +13423,7 @@ async function encodeImageFile(filePath) {
13242
13423
  const mime = EXT_TO_MIME[ext] ?? "image/jpeg";
13243
13424
  const b64 = buf.toString("base64");
13244
13425
  return {
13245
- filename: basename2(filePath),
13426
+ filename: basename3(filePath),
13246
13427
  mime,
13247
13428
  dataUrl: `data:${mime};base64,${b64}`
13248
13429
  };
@@ -13268,7 +13449,7 @@ var init_image = __esm({
13268
13449
  });
13269
13450
 
13270
13451
  // src/permissions-evaluator.ts
13271
- import { resolve as resolve5, relative as relative4 } from "path";
13452
+ import { resolve as resolve6, relative as relative5 } from "path";
13272
13453
  import { homedir as homedir16 } from "os";
13273
13454
  function evaluatePermissionRules(req, rules) {
13274
13455
  const toolRules = rules[req.tool];
@@ -13285,7 +13466,7 @@ function evaluatePermissionRules(req, rules) {
13285
13466
  }
13286
13467
  function expandHome(path) {
13287
13468
  if (path.startsWith("~/")) {
13288
- return resolve5(homedir16(), path.slice(2));
13469
+ return resolve6(homedir16(), path.slice(2));
13289
13470
  }
13290
13471
  return path;
13291
13472
  }
@@ -13296,7 +13477,7 @@ function extractTarget(tool, args, cwd) {
13296
13477
  case "read":
13297
13478
  case "glob":
13298
13479
  case "grep":
13299
- return typeof args.path === "string" ? resolve5(cwd, expandHome(args.path)) : null;
13480
+ return typeof args.path === "string" ? resolve6(cwd, expandHome(args.path)) : null;
13300
13481
  case "bash":
13301
13482
  return typeof args.command === "string" ? args.command : null;
13302
13483
  case "browser_fetch":
@@ -13305,13 +13486,13 @@ function extractTarget(tool, args, cwd) {
13305
13486
  case "search_web":
13306
13487
  return typeof args.query === "string" ? args.query : null;
13307
13488
  default:
13308
- return (typeof args.path === "string" ? resolve5(cwd, expandHome(args.path)) : null) ?? (typeof args.url === "string" ? args.url : null) ?? (typeof args.command === "string" ? args.command : null);
13489
+ 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
13490
  }
13310
13491
  }
13311
13492
  function matchPattern(target, pattern, cwd) {
13312
13493
  let expandedPattern = pattern;
13313
13494
  if (pattern.startsWith("~/")) {
13314
- expandedPattern = resolve5(homedir16(), pattern.slice(2));
13495
+ expandedPattern = resolve6(homedir16(), pattern.slice(2));
13315
13496
  }
13316
13497
  if (target.startsWith(expandedPattern)) {
13317
13498
  return true;
@@ -13321,7 +13502,7 @@ function matchPattern(target, pattern, cwd) {
13321
13502
  return true;
13322
13503
  }
13323
13504
  try {
13324
- const relTarget = relative4(cwd, target);
13505
+ const relTarget = relative5(cwd, target);
13325
13506
  if (regex.test(relTarget)) {
13326
13507
  return true;
13327
13508
  }
@@ -13394,17 +13575,17 @@ __export(retention_exports, {
13394
13575
  listTraceSessions: () => listTraceSessions,
13395
13576
  pruneTraces: () => pruneTraces
13396
13577
  });
13397
- import { readdir as readdir5, rm as rm3, stat as stat6 } from "fs/promises";
13398
- import { join as join26 } from "path";
13578
+ import { readdir as readdir6, rm as rm4, stat as stat8 } from "fs/promises";
13579
+ import { join as join28 } from "path";
13399
13580
  async function dirSize(path) {
13400
13581
  let total = 0;
13401
- const entries = await readdir5(path, { withFileTypes: true });
13582
+ const entries = await readdir6(path, { withFileTypes: true });
13402
13583
  for (const entry of entries) {
13403
- const p = join26(path, entry.name);
13584
+ const p = join28(path, entry.name);
13404
13585
  if (entry.isDirectory()) total += await dirSize(p);
13405
13586
  else if (entry.isFile()) {
13406
13587
  try {
13407
- total += (await stat6(p)).size;
13588
+ total += (await stat8(p)).size;
13408
13589
  } catch {
13409
13590
  }
13410
13591
  }
@@ -13415,19 +13596,19 @@ async function listTraceSessions(root) {
13415
13596
  const base = traceRoot(root);
13416
13597
  let names;
13417
13598
  try {
13418
- names = await readdir5(base);
13599
+ names = await readdir6(base);
13419
13600
  } catch {
13420
13601
  return [];
13421
13602
  }
13422
13603
  const sessions = [];
13423
13604
  for (const name of names) {
13424
- const path = join26(base, name);
13605
+ const path = join28(base, name);
13425
13606
  try {
13426
- const s = await stat6(path);
13607
+ const s = await stat8(path);
13427
13608
  if (!s.isDirectory()) continue;
13428
13609
  let mtime = s.mtime;
13429
13610
  try {
13430
- mtime = (await stat6(join26(path, TRACE_FILE_NAME))).mtime;
13611
+ mtime = (await stat8(join28(path, TRACE_FILE_NAME))).mtime;
13431
13612
  } catch {
13432
13613
  }
13433
13614
  sessions.push({ sessionId: name, path, mtime, bytes: await dirSize(path) });
@@ -13452,7 +13633,7 @@ async function pruneTraces(opts2 = {}) {
13452
13633
  }
13453
13634
  const remove = async (s) => {
13454
13635
  try {
13455
- await rm3(s.path, { recursive: true, force: true });
13636
+ await rm4(s.path, { recursive: true, force: true });
13456
13637
  removed.push(s.sessionId);
13457
13638
  } catch {
13458
13639
  }
@@ -13481,7 +13662,7 @@ var init_retention = __esm({
13481
13662
  // src/trace/session-start.ts
13482
13663
  import { execFile as execFile6 } from "child_process";
13483
13664
  import { existsSync as existsSync5 } from "fs";
13484
- import { dirname as dirname13, join as join27 } from "path";
13665
+ import { dirname as dirname14, join as join29 } from "path";
13485
13666
  import { fileURLToPath as fileURLToPath4 } from "url";
13486
13667
  import { promisify as promisify6 } from "util";
13487
13668
  async function git2(args, cwd) {
@@ -13494,9 +13675,9 @@ async function git2(args, cwd) {
13494
13675
  }
13495
13676
  }
13496
13677
  function harnessCheckoutDir() {
13497
- const here = dirname13(fileURLToPath4(import.meta.url));
13498
- for (const candidate of [join27(here, "..", ".."), join27(here, "..")]) {
13499
- if (existsSync5(join27(candidate, "package.json")) && existsSync5(join27(candidate, ".git"))) return candidate;
13678
+ const here = dirname14(fileURLToPath4(import.meta.url));
13679
+ for (const candidate of [join29(here, "..", ".."), join29(here, "..")]) {
13680
+ if (existsSync5(join29(candidate, "package.json")) && existsSync5(join29(candidate, ".git"))) return candidate;
13500
13681
  }
13501
13682
  return null;
13502
13683
  }
@@ -13634,14 +13815,14 @@ var init_types2 = __esm({
13634
13815
  // src/hooks/settings.ts
13635
13816
  import { existsSync as existsSync6, readFileSync as readFileSync5, mkdirSync as mkdirSync7, writeFileSync as writeFileSync4 } from "fs";
13636
13817
  import { homedir as homedir17 } from "os";
13637
- import { join as join28, dirname as dirname14 } from "path";
13818
+ import { join as join30, dirname as dirname15 } from "path";
13638
13819
  import { createHash as createHash3 } from "crypto";
13639
13820
  function globalSettingsPath() {
13640
- const xdg = process.env.XDG_CONFIG_HOME || join28(homedir17(), ".config");
13641
- return join28(xdg, "kimiflare", "settings.json");
13821
+ const xdg = process.env.XDG_CONFIG_HOME || join30(homedir17(), ".config");
13822
+ return join30(xdg, "kimiflare", "settings.json");
13642
13823
  }
13643
13824
  function projectSettingsPath(cwd) {
13644
- return join28(cwd, ".kimiflare", "settings.json");
13825
+ return join30(cwd, ".kimiflare", "settings.json");
13645
13826
  }
13646
13827
  function readSettingsFile(path) {
13647
13828
  if (!existsSync6(path)) return null;
@@ -13717,7 +13898,7 @@ function appendHook(scope, cwd, event, hook) {
13717
13898
  return rest;
13718
13899
  });
13719
13900
  existing.hooks = hooks;
13720
- mkdirSync7(dirname14(path), { recursive: true });
13901
+ mkdirSync7(dirname15(path), { recursive: true });
13721
13902
  writeFileSync4(path, JSON.stringify(existing, null, 2) + "\n", "utf8");
13722
13903
  return path;
13723
13904
  }
@@ -13743,7 +13924,7 @@ function setHookEnabled(cwd, id, enabled2) {
13743
13924
  }
13744
13925
  }
13745
13926
  if (changed) {
13746
- mkdirSync7(dirname14(path), { recursive: true });
13927
+ mkdirSync7(dirname15(path), { recursive: true });
13747
13928
  writeFileSync4(path, JSON.stringify(existing, null, 2) + "\n", "utf8");
13748
13929
  return path;
13749
13930
  }
@@ -13759,7 +13940,7 @@ var init_settings = __esm({
13759
13940
  });
13760
13941
 
13761
13942
  // src/hooks/runner.ts
13762
- import { spawn as spawn4 } from "child_process";
13943
+ import { spawn as spawn5 } from "child_process";
13763
13944
  function isVetoEvent(event) {
13764
13945
  return event === "PreToolUse" || event === "UserPromptSubmit";
13765
13946
  }
@@ -13876,8 +14057,8 @@ var init_runner = __esm({
13876
14057
  init_logger();
13877
14058
  DEFAULT_TIMEOUT_MS = 3e4;
13878
14059
  STREAM_CAP_BYTES = 4 * 1024;
13879
- defaultSpawn = (command, payloadJson, env2, cwd, timeoutMs, signal) => new Promise((resolve19) => {
13880
- const child = spawn4(command, {
14060
+ defaultSpawn = (command, payloadJson, env2, cwd, timeoutMs, signal) => new Promise((resolve20) => {
14061
+ const child = spawn5(command, {
13881
14062
  shell: true,
13882
14063
  cwd,
13883
14064
  env: env2,
@@ -13891,7 +14072,7 @@ var init_runner = __esm({
13891
14072
  settled = true;
13892
14073
  clearTimeout(timer3);
13893
14074
  signal?.removeEventListener("abort", onAbort);
13894
- resolve19({ exitCode, stdout, stderr, timedOut });
14075
+ resolve20({ exitCode, stdout, stderr, timedOut });
13895
14076
  };
13896
14077
  const onAbort = () => {
13897
14078
  child.kill("SIGTERM");
@@ -13964,18 +14145,18 @@ var init_manager2 = __esm({
13964
14145
  });
13965
14146
 
13966
14147
  // src/eval/config.ts
13967
- import { readFile as readFile16 } from "fs/promises";
13968
- import { basename as basename4, resolve as resolve7 } from "path";
14148
+ import { readFile as readFile18 } from "fs/promises";
14149
+ import { basename as basename5, resolve as resolve8 } from "path";
13969
14150
  async function loadEvalConfig(file) {
13970
- const path = resolve7(file);
13971
- const raw = JSON.parse(await readFile16(path, "utf8"));
14151
+ const path = resolve8(file);
14152
+ const raw = JSON.parse(await readFile18(path, "utf8"));
13972
14153
  if (!raw || typeof raw !== "object") throw new Error(`${file}: config must be a JSON object`);
13973
14154
  const config2 = raw.config ?? {};
13974
14155
  if (typeof config2 !== "object" || Array.isArray(config2)) throw new Error(`${file}: "config" must be an object`);
13975
14156
  if (raw.model !== void 0 && typeof raw.model !== "string") throw new Error(`${file}: "model" must be a string`);
13976
14157
  if (raw.temperature !== void 0 && typeof raw.temperature !== "number") throw new Error(`${file}: "temperature" must be a number`);
13977
14158
  return {
13978
- name: typeof raw.name === "string" && raw.name ? raw.name : basename4(path).replace(/\.json$/, ""),
14159
+ name: typeof raw.name === "string" && raw.name ? raw.name : basename5(path).replace(/\.json$/, ""),
13979
14160
  ...raw.model ? { model: raw.model } : {},
13980
14161
  ...raw.temperature !== void 0 ? { temperature: raw.temperature } : {},
13981
14162
  config: config2
@@ -13988,8 +14169,8 @@ var init_config2 = __esm({
13988
14169
  });
13989
14170
 
13990
14171
  // src/eval/tasks.ts
13991
- import { readdir as readdir6, readFile as readFile17, stat as stat7 } from "fs/promises";
13992
- import { basename as basename5, join as join29, resolve as resolve8 } from "path";
14172
+ import { readdir as readdir7, readFile as readFile19, stat as stat9 } from "fs/promises";
14173
+ import { basename as basename6, join as join31, resolve as resolve9 } from "path";
13993
14174
  function isNonEmptyString(v) {
13994
14175
  return typeof v === "string" && v.trim().length > 0;
13995
14176
  }
@@ -14017,22 +14198,22 @@ function matchesTaskFilter(id, filter) {
14017
14198
  return filter.split(",").map((g) => g.trim()).filter(Boolean).some((g) => matchGlob(id, g));
14018
14199
  }
14019
14200
  async function loadTasks(dir, filter) {
14020
- const root = resolve8(dir);
14021
- const names = (await readdir6(root)).filter((n) => n.endsWith(".json")).sort();
14201
+ const root = resolve9(dir);
14202
+ const names = (await readdir7(root)).filter((n) => n.endsWith(".json")).sort();
14022
14203
  const tasks = [];
14023
14204
  const seen = /* @__PURE__ */ new Set();
14024
14205
  for (const name of names) {
14025
- const file = join29(root, name);
14026
- const task = validateTask(JSON.parse(await readFile17(file, "utf8")), name);
14027
- if (task.id !== basename5(name, ".json")) throw new Error(`${name}: "id" (${task.id}) must match the file name`);
14206
+ const file = join31(root, name);
14207
+ const task = validateTask(JSON.parse(await readFile19(file, "utf8")), name);
14208
+ if (task.id !== basename6(name, ".json")) throw new Error(`${name}: "id" (${task.id}) must match the file name`);
14028
14209
  if (seen.has(task.id)) throw new Error(`duplicate task id ${task.id}`);
14029
14210
  seen.add(task.id);
14030
14211
  if (!matchesTaskFilter(task.id, filter)) continue;
14031
14212
  const resolvedFiles = {};
14032
14213
  for (const [dest, src] of Object.entries(task.files ?? {})) {
14033
- const abs = resolve8(root, src);
14214
+ const abs = resolve9(root, src);
14034
14215
  if (!abs.startsWith(root)) throw new Error(`${name}: files["${dest}"] escapes the task directory`);
14035
- await stat7(abs).catch(() => {
14216
+ await stat9(abs).catch(() => {
14036
14217
  throw new Error(`${name}: files["${dest}"] -> ${src} does not exist`);
14037
14218
  });
14038
14219
  resolvedFiles[dest] = abs;
@@ -14053,15 +14234,15 @@ var init_tasks2 = __esm({
14053
14234
  // src/eval/workspace.ts
14054
14235
  import { execFile as execFile7 } from "child_process";
14055
14236
  import { createHash as createHash4 } from "crypto";
14056
- import { mkdir as mkdir12, rm as rm4, stat as stat8 } from "fs/promises";
14057
- import { isAbsolute as isAbsolute3, join as join30, resolve as resolve9 } from "path";
14237
+ import { mkdir as mkdir13, rm as rm5, stat as stat10 } from "fs/promises";
14238
+ import { isAbsolute as isAbsolute4, join as join32, resolve as resolve10 } from "path";
14058
14239
  import { promisify as promisify7 } from "util";
14059
14240
  async function git3(args, cwd, timeoutMs = 6e5) {
14060
14241
  const { stdout } = await execFileAsync5("git", args, { cwd, timeout: timeoutMs, maxBuffer: 64 * 1024 * 1024 });
14061
14242
  return stdout.trim();
14062
14243
  }
14063
14244
  function isLocalRepo(repo) {
14064
- return isAbsolute3(repo) || repo.startsWith(".") || repo.startsWith("~");
14245
+ return isAbsolute4(repo) || repo.startsWith(".") || repo.startsWith("~");
14065
14246
  }
14066
14247
  function prepareSourceRepo(repo, cacheDir) {
14067
14248
  const key = `${cacheDir}\0${repo}`;
@@ -14074,14 +14255,14 @@ function prepareSourceRepo(repo, cacheDir) {
14074
14255
  }
14075
14256
  async function prepareSourceRepoUncached(repo, cacheDir) {
14076
14257
  if (isLocalRepo(repo)) {
14077
- const path = resolve9(repo.replace(/^~/, process.env.HOME ?? ""));
14258
+ const path = resolve10(repo.replace(/^~/, process.env.HOME ?? ""));
14078
14259
  await git3(["rev-parse", "--git-dir"], path);
14079
14260
  return path;
14080
14261
  }
14081
14262
  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 = join30(cacheDir, slug);
14083
- await mkdir12(cacheDir, { recursive: true });
14084
- const exists = await stat8(join30(dir, ".git")).then(() => true).catch(() => false);
14263
+ const dir = join32(cacheDir, slug);
14264
+ await mkdir13(cacheDir, { recursive: true });
14265
+ const exists = await stat10(join32(dir, ".git")).then(() => true).catch(() => false);
14085
14266
  if (!exists) {
14086
14267
  await git3(["clone", "--quiet", "--no-checkout", repo, dir], cacheDir);
14087
14268
  } else {
@@ -14100,13 +14281,13 @@ async function ensureCommit(sourceRepo, commit) {
14100
14281
  async function createWorktree(sourceRepo, commit, path) {
14101
14282
  await ensureCommit(sourceRepo, commit);
14102
14283
  await removeWorktree({ sourceRepo, path }).catch(() => void 0);
14103
- await mkdir12(join30(path, ".."), { recursive: true });
14284
+ await mkdir13(join32(path, ".."), { recursive: true });
14104
14285
  await git3(["worktree", "add", "--quiet", "--detach", path, commit], sourceRepo);
14105
14286
  return { sourceRepo, path };
14106
14287
  }
14107
14288
  async function removeWorktree(wt) {
14108
14289
  await git3(["worktree", "remove", "--force", wt.path], wt.sourceRepo).catch(() => void 0);
14109
- await rm4(wt.path, { recursive: true, force: true });
14290
+ await rm5(wt.path, { recursive: true, force: true });
14110
14291
  await git3(["worktree", "prune"], wt.sourceRepo).catch(() => void 0);
14111
14292
  }
14112
14293
  var execFileAsync5, preparing;
@@ -14156,7 +14337,7 @@ __export(db_exports, {
14156
14337
  updateMemoryEmbedding: () => updateMemoryEmbedding
14157
14338
  });
14158
14339
  import Database3 from "better-sqlite3";
14159
- import { dirname as dirname15 } from "path";
14340
+ import { dirname as dirname16 } from "path";
14160
14341
  import { mkdirSync as mkdirSync8, statSync as statSync4 } from "fs";
14161
14342
  function initSchema(db) {
14162
14343
  db.exec(`
@@ -14241,7 +14422,7 @@ function openMemoryDb(dbPath) {
14241
14422
  if (dbInstance) {
14242
14423
  dbInstance.close();
14243
14424
  }
14244
- mkdirSync8(dirname15(dbPath), { recursive: true });
14425
+ mkdirSync8(dirname16(dbPath), { recursive: true });
14245
14426
  dbInstance = new Database3(dbPath);
14246
14427
  dbInstance.pragma("journal_mode = WAL");
14247
14428
  dbInstance.pragma("foreign_keys = ON");
@@ -14577,8 +14758,8 @@ function computeExactScore(memory, queryText, cwd) {
14577
14758
  let score = 0;
14578
14759
  const lowerQuery = queryText.toLowerCase();
14579
14760
  for (const file of memory.relatedFiles) {
14580
- const basename11 = file.split("/").pop() ?? file;
14581
- if (lowerQuery.includes(basename11.toLowerCase()) || basename11.toLowerCase().includes(lowerQuery)) {
14761
+ const basename12 = file.split("/").pop() ?? file;
14762
+ if (lowerQuery.includes(basename12.toLowerCase()) || basename12.toLowerCase().includes(lowerQuery)) {
14582
14763
  score += 0.3;
14583
14764
  }
14584
14765
  if (cwd && file.startsWith(cwd)) {
@@ -15201,7 +15382,7 @@ Context: This memory was explicitly provided by the user during a conversation.`
15201
15382
  });
15202
15383
 
15203
15384
  // src/lsp/connection.ts
15204
- import { spawn as spawn5 } from "child_process";
15385
+ import { spawn as spawn6 } from "child_process";
15205
15386
  import { EventEmitter as EventEmitter2 } from "events";
15206
15387
  var LspConnection;
15207
15388
  var init_connection = __esm({
@@ -15223,7 +15404,7 @@ var init_connection = __esm({
15223
15404
  if (this.child) {
15224
15405
  throw new Error("LSP connection already started");
15225
15406
  }
15226
- return new Promise((resolve19, reject) => {
15407
+ return new Promise((resolve20, reject) => {
15227
15408
  const abortController = new AbortController();
15228
15409
  const spawnTimer = setTimeout(() => {
15229
15410
  abortController.abort();
@@ -15231,7 +15412,7 @@ var init_connection = __esm({
15231
15412
  reject(new Error(`LSP server spawn timed out after ${spawnTimeoutMs}ms`));
15232
15413
  }, spawnTimeoutMs);
15233
15414
  try {
15234
- const child = spawn5(command[0], command.slice(1), {
15415
+ const child = spawn6(command[0], command.slice(1), {
15235
15416
  env: { ...process.env, ...env2 },
15236
15417
  stdio: ["pipe", "pipe", "pipe"]
15237
15418
  });
@@ -15262,7 +15443,7 @@ var init_connection = __esm({
15262
15443
  if (child.pid) {
15263
15444
  clearTimeout(spawnTimer);
15264
15445
  this.child = child;
15265
- resolve19();
15446
+ resolve20();
15266
15447
  }
15267
15448
  });
15268
15449
  } catch (err) {
@@ -15277,12 +15458,12 @@ var init_connection = __esm({
15277
15458
  }
15278
15459
  const id = this.nextId++;
15279
15460
  const msg = { jsonrpc: "2.0", id, method, params };
15280
- return new Promise((resolve19, reject) => {
15461
+ return new Promise((resolve20, reject) => {
15281
15462
  const timer3 = setTimeout(() => {
15282
15463
  this.pending.delete(id);
15283
15464
  reject(toolTimeoutError(`LSP request '${method}'`, this.requestTimeoutMs));
15284
15465
  }, this.requestTimeoutMs);
15285
- const pending = { resolve: resolve19, reject, signal, timer: timer3 };
15466
+ const pending = { resolve: resolve20, reject, signal, timer: timer3 };
15286
15467
  this.pending.set(id, pending);
15287
15468
  if (signal) {
15288
15469
  const onAbort = () => {
@@ -15375,9 +15556,9 @@ var init_connection = __esm({
15375
15556
  });
15376
15557
 
15377
15558
  // src/lsp/protocol.ts
15378
- import { pathToFileURL as pathToFileURL2, fileURLToPath as fileURLToPath5 } from "url";
15559
+ import { pathToFileURL as pathToFileURL3, fileURLToPath as fileURLToPath5 } from "url";
15379
15560
  function toUri(path) {
15380
- return pathToFileURL2(path).href;
15561
+ return pathToFileURL3(path).href;
15381
15562
  }
15382
15563
  function fromUri(uri) {
15383
15564
  return fileURLToPath5(uri);
@@ -15846,10 +16027,10 @@ var init_manager4 = __esm({
15846
16027
  });
15847
16028
 
15848
16029
  // src/lsp/adapter.ts
15849
- import { relative as relative5 } from "path";
16030
+ import { relative as relative6 } from "path";
15850
16031
  function formatLocation(loc, cwd) {
15851
16032
  const path = fromUri(loc.uri);
15852
- const rel = relative5(cwd, path) || path;
16033
+ const rel = relative6(cwd, path) || path;
15853
16034
  return `${rel}:${loc.range.start.line + 1}:${loc.range.start.character + 1}`;
15854
16035
  }
15855
16036
  function formatLocations(locs, cwd) {
@@ -15886,7 +16067,7 @@ function formatWorkspaceSymbols(symbols, cwd) {
15886
16067
  if (!symbols || symbols.length === 0) return "No symbols found.";
15887
16068
  return symbols.map((s) => {
15888
16069
  const path = fromUri(s.location.uri);
15889
- const rel = relative5(cwd, path) || path;
16070
+ const rel = relative6(cwd, path) || path;
15890
16071
  const container = s.containerName ? ` in ${s.containerName}` : "";
15891
16072
  return `${s.name} (${symbolKindName(s.kind)})${container} \u2014 ${rel}:${s.location.range.start.line + 1}:${s.location.range.start.character + 1}`;
15892
16073
  }).join("\n");
@@ -15906,7 +16087,7 @@ function formatWorkspaceEdit(edit, cwd) {
15906
16087
  if (edit.changes) {
15907
16088
  for (const [uri, edits] of Object.entries(edit.changes)) {
15908
16089
  const path = fromUri(uri);
15909
- const rel = relative5(cwd, path) || path;
16090
+ const rel = relative6(cwd, path) || path;
15910
16091
  lines.push(`File: ${rel}`);
15911
16092
  for (const e of edits) {
15912
16093
  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 +16112,7 @@ var init_adapter = __esm({
15931
16112
  });
15932
16113
 
15933
16114
  // src/tools/lsp.ts
15934
- import { relative as relative6 } from "path";
16115
+ import { relative as relative7 } from "path";
15935
16116
  function makeOutput2(content) {
15936
16117
  const bytes = Buffer.byteLength(content, "utf8");
15937
16118
  return { content, rawBytes: bytes, reducedBytes: bytes };
@@ -15939,7 +16120,7 @@ function makeOutput2(content) {
15939
16120
  function resolveLspPath(args, ctx) {
15940
16121
  const raw = typeof args.path === "string" ? args.path : "";
15941
16122
  const resolved = resolvePath(ctx.cwd, raw);
15942
- const rel = relative6(ctx.cwd, resolved);
16123
+ const rel = relative7(ctx.cwd, resolved);
15943
16124
  if (isPathOutside(rel)) {
15944
16125
  throw new Error(`Path outside workspace: ${raw}`);
15945
16126
  }
@@ -16205,12 +16386,12 @@ __export(openrouter_catalog_exports, {
16205
16386
  loadOpenRouterCatalog: () => loadOpenRouterCatalog,
16206
16387
  mapOpenRouterModel: () => mapOpenRouterModel
16207
16388
  });
16208
- import { readFile as readFile18, writeFile as writeFile12, mkdir as mkdir13 } from "fs/promises";
16389
+ import { readFile as readFile20, writeFile as writeFile12, mkdir as mkdir14 } from "fs/promises";
16209
16390
  import { homedir as homedir18 } from "os";
16210
- import { join as join32, dirname as dirname16 } from "path";
16391
+ import { join as join34, dirname as dirname17 } from "path";
16211
16392
  function catalogCachePath() {
16212
- const xdg = process.env.XDG_CONFIG_HOME || join32(homedir18(), ".config");
16213
- return join32(xdg, "kimiflare", "openrouter-models.json");
16393
+ const xdg = process.env.XDG_CONFIG_HOME || join34(homedir18(), ".config");
16394
+ return join34(xdg, "kimiflare", "openrouter-models.json");
16214
16395
  }
16215
16396
  function perMtok(perToken) {
16216
16397
  const n = Number(perToken);
@@ -16261,7 +16442,7 @@ async function fetchOpenRouterCatalog(fetchImpl2 = fetch) {
16261
16442
  }
16262
16443
  async function readCache3() {
16263
16444
  try {
16264
- const raw = await readFile18(catalogCachePath(), "utf8");
16445
+ const raw = await readFile20(catalogCachePath(), "utf8");
16265
16446
  const parsed = JSON.parse(raw);
16266
16447
  return parsed.version === CACHE_VERSION ? parsed : null;
16267
16448
  } catch {
@@ -16271,7 +16452,7 @@ async function readCache3() {
16271
16452
  async function writeCache3(models) {
16272
16453
  const path = catalogCachePath();
16273
16454
  try {
16274
- await mkdir13(dirname16(path), { recursive: true });
16455
+ await mkdir14(dirname17(path), { recursive: true });
16275
16456
  const cache = { version: CACHE_VERSION, fetchedAt: (/* @__PURE__ */ new Date()).toISOString(), models };
16276
16457
  await writeFile12(path, JSON.stringify(cache, null, 2), "utf8");
16277
16458
  } catch {
@@ -16320,12 +16501,12 @@ __export(requesty_catalog_exports, {
16320
16501
  loadRequestyCatalog: () => loadRequestyCatalog,
16321
16502
  mapRequestyModel: () => mapRequestyModel
16322
16503
  });
16323
- import { readFile as readFile19, writeFile as writeFile13, mkdir as mkdir14 } from "fs/promises";
16504
+ import { readFile as readFile21, writeFile as writeFile13, mkdir as mkdir15 } from "fs/promises";
16324
16505
  import { homedir as homedir19 } from "os";
16325
- import { join as join33, dirname as dirname17 } from "path";
16506
+ import { join as join35, dirname as dirname18 } from "path";
16326
16507
  function catalogCachePath2() {
16327
- const xdg = process.env.XDG_CONFIG_HOME || join33(homedir19(), ".config");
16328
- return join33(xdg, "kimiflare", "requesty-models.json");
16508
+ const xdg = process.env.XDG_CONFIG_HOME || join35(homedir19(), ".config");
16509
+ return join35(xdg, "kimiflare", "requesty-models.json");
16329
16510
  }
16330
16511
  function isSafeModelId(id) {
16331
16512
  return typeof id === "string" && id.length > 0 && !CONTROL_CHARS.test(id);
@@ -16381,7 +16562,7 @@ async function fetchRequestyCatalog(fetchImpl2 = fetch) {
16381
16562
  }
16382
16563
  async function readCache4() {
16383
16564
  try {
16384
- const raw = await readFile19(catalogCachePath2(), "utf8");
16565
+ const raw = await readFile21(catalogCachePath2(), "utf8");
16385
16566
  const parsed = JSON.parse(raw);
16386
16567
  if (parsed.version !== CACHE_VERSION2) return null;
16387
16568
  return {
@@ -16396,7 +16577,7 @@ async function readCache4() {
16396
16577
  async function writeCache4(catalog) {
16397
16578
  const path = catalogCachePath2();
16398
16579
  try {
16399
- await mkdir14(dirname17(path), { recursive: true });
16580
+ await mkdir15(dirname18(path), { recursive: true });
16400
16581
  const cache = { version: CACHE_VERSION2, fetchedAt: (/* @__PURE__ */ new Date()).toISOString(), ...catalog };
16401
16582
  await writeFile13(path, JSON.stringify(cache, null, 2), "utf8");
16402
16583
  } catch {
@@ -16491,15 +16672,15 @@ var session_exports = {};
16491
16672
  __export(session_exports, {
16492
16673
  createAgentSession: () => createAgentSession
16493
16674
  });
16494
- import { resolve as resolve10 } from "path";
16675
+ import { resolve as resolve11 } from "path";
16495
16676
  import { homedir as homedir20 } from "os";
16496
- import { join as join34 } from "path";
16677
+ import { join as join36 } from "path";
16497
16678
  import { existsSync as existsSync7 } from "fs";
16498
16679
  async function createAgentSession(opts2) {
16499
16680
  const config2 = await resolveSdkConfig(opts2);
16500
16681
  if (usesRequesty(llmAuthFromConfig(config2))) await ensureRequestyCatalog();
16501
16682
  else if (!resolveCustomEndpoint(config2)) await ensureOpenRouterCatalog();
16502
- const cwd = resolve10(opts2.cwd ?? process.cwd());
16683
+ const cwd = resolve11(opts2.cwd ?? process.cwd());
16503
16684
  const tools = opts2.tools ?? ALL_TOOLS;
16504
16685
  let hooks;
16505
16686
  if (opts2.enableHooks) {
@@ -16510,7 +16691,7 @@ async function createAgentSession(opts2) {
16510
16691
  let memoryManager = null;
16511
16692
  const memoryEnabled = opts2.memoryEnabled ?? config2.memoryEnabled ?? false;
16512
16693
  if (memoryEnabled) {
16513
- const dbPath = config2.memoryDbPath ?? join34(homedir20(), ".local", "share", "kimiflare", "memory.db");
16694
+ const dbPath = config2.memoryDbPath ?? join36(homedir20(), ".local", "share", "kimiflare", "memory.db");
16514
16695
  memoryManager = new MemoryManager({
16515
16696
  dbPath,
16516
16697
  ...llmAuthFromConfig(config2),
@@ -16540,7 +16721,7 @@ async function createAgentSession(opts2) {
16540
16721
  }
16541
16722
  let sessionFile;
16542
16723
  if (opts2.sessionId) {
16543
- const filePath = join34(sessionsDir(), `${opts2.sessionId}.json`);
16724
+ const filePath = join36(sessionsDir(), `${opts2.sessionId}.json`);
16544
16725
  try {
16545
16726
  sessionFile = await loadSession(filePath);
16546
16727
  } catch {
@@ -16739,8 +16920,8 @@ var init_session = __esm({
16739
16920
  const parts = [{ type: "text", text }];
16740
16921
  for (const img of options.images) {
16741
16922
  if ("path" in img) {
16742
- const { readFile: readFile36 } = await import("fs/promises");
16743
- const data = await readFile36(img.path, "base64");
16923
+ const { readFile: readFile38 } = await import("fs/promises");
16924
+ const data = await readFile38(img.path, "base64");
16744
16925
  const mimeType = img.path.endsWith(".png") ? "image/png" : img.path.endsWith(".jpg") || img.path.endsWith(".jpeg") ? "image/jpeg" : "image/webp";
16745
16926
  parts.push({ type: "image_url", image_url: { url: `data:${mimeType};base64,${data}` } });
16746
16927
  } else {
@@ -16999,12 +17180,12 @@ var init_session = __esm({
16999
17180
  toolName: req.tool.name,
17000
17181
  args: req.args
17001
17182
  });
17002
- const decision = await new Promise((resolve19) => {
17003
- this.permissionResolvers.set(requestId, resolve19);
17183
+ const decision = await new Promise((resolve20) => {
17184
+ this.permissionResolvers.set(requestId, resolve20);
17004
17185
  setTimeout(() => {
17005
17186
  if (this.permissionResolvers.has(requestId)) {
17006
17187
  this.permissionResolvers.delete(requestId);
17007
- resolve19("deny");
17188
+ resolve20("deny");
17008
17189
  }
17009
17190
  }, 3e5);
17010
17191
  });
@@ -17063,14 +17244,14 @@ var init_session = __esm({
17063
17244
  this.lspManager?.notifyChange(path, content);
17064
17245
  } else {
17065
17246
  void import("fs/promises").then(
17066
- ({ readFile: readFile36 }) => readFile36(path, "utf8").then((c) => this.lspManager?.notifyChange(path, c)).catch(() => {
17247
+ ({ readFile: readFile38 }) => readFile38(path, "utf8").then((c) => this.lspManager?.notifyChange(path, c)).catch(() => {
17067
17248
  })
17068
17249
  ).catch(() => {
17069
17250
  });
17070
17251
  }
17071
17252
  }
17072
17253
  });
17073
- if (["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].some((name) => existsSync7(join34(this.cwd, name)))) {
17254
+ if (["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].some((name) => existsSync7(join36(this.cwd, name)))) {
17074
17255
  this.messages[0] = {
17075
17256
  role: "system",
17076
17257
  content: buildSystemPrompt({
@@ -17094,13 +17275,13 @@ __export(run_exports, {
17094
17275
  runShell: () => runShell,
17095
17276
  summarizeTrace: () => summarizeTrace
17096
17277
  });
17097
- import { spawn as spawn6 } from "child_process";
17098
- import { appendFile as appendFile3, copyFile, mkdir as mkdir15, readFile as readFile20, writeFile as writeFile14 } from "fs/promises";
17099
- import { dirname as dirname18, join as join35, resolve as resolve11 } from "path";
17278
+ import { spawn as spawn7 } from "child_process";
17279
+ import { appendFile as appendFile3, copyFile, mkdir as mkdir16, readFile as readFile22, writeFile as writeFile14 } from "fs/promises";
17280
+ import { dirname as dirname19, join as join37, resolve as resolve12 } from "path";
17100
17281
  import { performance as performance2 } from "perf_hooks";
17101
17282
  function runShell(command, cwd, timeoutMs) {
17102
17283
  return new Promise((resolveShell) => {
17103
- const child = spawn6(process.platform === "win32" ? process.env.COMSPEC || "cmd.exe" : "bash", [process.platform === "win32" ? "/c" : "-lc", command], {
17284
+ const child = spawn7(process.platform === "win32" ? process.env.COMSPEC || "cmd.exe" : "bash", [process.platform === "win32" ? "/c" : "-lc", command], {
17104
17285
  cwd,
17105
17286
  env: { ...process.env, CI: "1", GIT_EDITOR: "true" }
17106
17287
  });
@@ -17129,8 +17310,8 @@ ${err.message}`, timedOut });
17129
17310
  }
17130
17311
  async function copyTaskFiles(task, worktree) {
17131
17312
  for (const [dest, src] of Object.entries(task.resolvedFiles)) {
17132
- const target = join35(worktree, dest);
17133
- await mkdir15(dirname18(target), { recursive: true });
17313
+ const target = join37(worktree, dest);
17314
+ await mkdir16(dirname19(target), { recursive: true });
17134
17315
  await copyFile(src, target);
17135
17316
  }
17136
17317
  }
@@ -17138,7 +17319,7 @@ async function summarizeTrace(traceFile) {
17138
17319
  const out = { cost_usd: 0, prompt_tokens: 0, completion_tokens: 0, turns: 0, tool_calls: 0, overflow: false };
17139
17320
  let raw;
17140
17321
  try {
17141
- raw = await readFile20(traceFile, "utf8");
17322
+ raw = await readFile22(traceFile, "utf8");
17142
17323
  } catch {
17143
17324
  return out;
17144
17325
  }
@@ -17170,7 +17351,7 @@ function sessionIdFor(runName, task, sample) {
17170
17351
  async function runOne(task, sample, ctx) {
17171
17352
  const startedAt2 = performance2.now();
17172
17353
  const sessionId = sessionIdFor(ctx.runName, task, sample);
17173
- const traceDir = join35(ctx.tracesRoot, sessionId);
17354
+ const traceDir = join37(ctx.tracesRoot, sessionId);
17174
17355
  const base = {
17175
17356
  task_id: task.id,
17176
17357
  sample,
@@ -17195,15 +17376,15 @@ async function runOne(task, sample, ctx) {
17195
17376
  });
17196
17377
  let worktree = null;
17197
17378
  try {
17198
- const sourceRepo = await prepareSourceRepo(task.repo, join35(ctx.out, "cache"));
17199
- worktree = await createWorktree(sourceRepo, task.base_commit, join35(ctx.out, "work", task.id, String(sample)));
17379
+ const sourceRepo = await prepareSourceRepo(task.repo, join37(ctx.out, "cache"));
17380
+ worktree = await createWorktree(sourceRepo, task.base_commit, join37(ctx.out, "work", task.id, String(sample)));
17200
17381
  await copyTaskFiles(task, worktree.path);
17201
17382
  const timeoutMs = (task.timeout_s ?? DEFAULT_TASK_TIMEOUT_S) * 1e3;
17202
17383
  if (task.setup) {
17203
17384
  ctx.log(`[${task.id}#${sample}] setup`);
17204
17385
  const setup = await runShell(task.setup, worktree.path, timeoutMs);
17205
17386
  if (setup.exitCode !== 0) {
17206
- await writeFile14(join35(worktree.path, ".eval-setup.log"), setup.log, "utf8").catch(() => void 0);
17387
+ await writeFile14(join37(worktree.path, ".eval-setup.log"), setup.log, "utf8").catch(() => void 0);
17207
17388
  return finish({ error: `setup failed (exit ${setup.exitCode}${setup.timedOut ? ", timed out" : ""}): ${setup.log.slice(-500)}` });
17208
17389
  }
17209
17390
  }
@@ -17237,8 +17418,8 @@ async function runOne(task, sample, ctx) {
17237
17418
  const test = await runShell(task.test, worktree.path, timeoutMs);
17238
17419
  const testMs = Math.round(performance2.now() - testStartedAt);
17239
17420
  const passed = test.exitCode === 0 && !test.timedOut;
17240
- await mkdir15(traceDir, { recursive: true }).catch(() => void 0);
17241
- await writeFile14(join35(traceDir, "test.log"), test.log, "utf8").catch(() => void 0);
17421
+ await mkdir16(traceDir, { recursive: true }).catch(() => void 0);
17422
+ await writeFile14(join37(traceDir, "test.log"), test.log, "utf8").catch(() => void 0);
17242
17423
  if (session.trace.enabled) {
17243
17424
  session.trace.emit(
17244
17425
  "outcome",
@@ -17256,7 +17437,7 @@ async function runOne(task, sample, ctx) {
17256
17437
  }
17257
17438
  session.dispose({ traceEndReason: "eval_done" });
17258
17439
  await session.trace.flush();
17259
- const stats = await summarizeTrace(join35(traceDir, "trace.jsonl"));
17440
+ const stats = await summarizeTrace(join37(traceDir, "trace.jsonl"));
17260
17441
  ctx.log(`[${task.id}#${sample}] ${passed ? "PASS" : "FAIL"} in ${agentMs + testMs} ms${agentError ? ` (${agentError.slice(0, 120)})` : ""}`);
17261
17442
  return finish({
17262
17443
  passed,
@@ -17274,7 +17455,7 @@ async function runOne(task, sample, ctx) {
17274
17455
  }
17275
17456
  }
17276
17457
  async function runEval(opts2) {
17277
- const out = resolve11(opts2.out);
17458
+ const out = resolve12(opts2.out);
17278
17459
  const log2 = opts2.log ?? ((line) => process.stderr.write(`${line}
17279
17460
  `));
17280
17461
  const evalConfig = await loadEvalConfig(opts2.configFile);
@@ -17285,12 +17466,12 @@ async function runEval(opts2) {
17285
17466
  const samples = Math.max(1, Math.floor(opts2.samples ?? 1));
17286
17467
  const concurrency = Math.max(1, Math.floor(opts2.concurrency ?? 1));
17287
17468
  const createSession = opts2.createSession ?? (await Promise.resolve().then(() => (init_session(), session_exports))).createAgentSession;
17288
- await mkdir15(out, { recursive: true });
17289
- const tracesRoot = join35(out, "traces");
17469
+ await mkdir16(out, { recursive: true });
17470
+ const tracesRoot = join37(out, "traces");
17290
17471
  const runName = evalConfig.name;
17291
- const resultsFile = join35(out, "results.jsonl");
17472
+ const resultsFile = join37(out, "results.jsonl");
17292
17473
  await writeFile14(
17293
- join35(out, "config.json"),
17474
+ join37(out, "config.json"),
17294
17475
  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
17476
  "utf8"
17296
17477
  );
@@ -17334,9 +17515,9 @@ __export(compare_exports, {
17334
17515
  perTask: () => perTask,
17335
17516
  summarizeArm: () => summarizeArm
17336
17517
  });
17337
- import { readFile as readFile21 } from "fs/promises";
17518
+ import { readFile as readFile23 } from "fs/promises";
17338
17519
  async function loadResults(file) {
17339
- const raw = await readFile21(file, "utf8");
17520
+ const raw = await readFile23(file, "utf8");
17340
17521
  return raw.split("\n").filter((l) => l.trim()).map((l) => JSON.parse(l));
17341
17522
  }
17342
17523
  function median(values) {
@@ -17469,16 +17650,16 @@ __export(cost_verify_exports, {
17469
17650
  verifySession: () => verifySession,
17470
17651
  verifyTurn: () => verifyTurn
17471
17652
  });
17472
- import { readFile as readFile22 } from "fs/promises";
17653
+ import { readFile as readFile24 } from "fs/promises";
17473
17654
  import { homedir as homedir21 } from "os";
17474
- import { join as join36 } from "path";
17655
+ import { join as join38 } from "path";
17475
17656
  function usagePath2() {
17476
- const xdg = process.env.XDG_DATA_HOME || join36(homedir21(), ".local", "share");
17477
- return join36(xdg, "kimiflare", "usage.json");
17657
+ const xdg = process.env.XDG_DATA_HOME || join38(homedir21(), ".local", "share");
17658
+ return join38(xdg, "kimiflare", "usage.json");
17478
17659
  }
17479
17660
  async function loadSessions() {
17480
17661
  try {
17481
- return JSON.parse(await readFile22(usagePath2(), "utf8")).sessions ?? [];
17662
+ return JSON.parse(await readFile24(usagePath2(), "utf8")).sessions ?? [];
17482
17663
  } catch {
17483
17664
  return [];
17484
17665
  }
@@ -17797,12 +17978,12 @@ function extOf(path) {
17797
17978
  const idx = path.lastIndexOf(".");
17798
17979
  return idx >= 0 ? path.slice(idx).toLowerCase() : "";
17799
17980
  }
17800
- function basename6(path) {
17981
+ function basename7(path) {
17801
17982
  const idx = Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
17802
17983
  return idx >= 0 ? path.slice(idx + 1) : path;
17803
17984
  }
17804
17985
  function classifyFile(path) {
17805
- const base = basename6(path);
17986
+ const base = basename7(path);
17806
17987
  const ext = extOf(path);
17807
17988
  if (TEST_PATTERNS.test(base)) return "writing-tests";
17808
17989
  if (base.toLowerCase().startsWith("readme")) return "reading-documentation";
@@ -17813,7 +17994,7 @@ function classifyFile(path) {
17813
17994
  return null;
17814
17995
  }
17815
17996
  function classifyWriteFile(path) {
17816
- const base = basename6(path);
17997
+ const base = basename7(path);
17817
17998
  const ext = extOf(path);
17818
17999
  if (TEST_PATTERNS.test(base)) return "writing-tests";
17819
18000
  if (base.toLowerCase().startsWith("readme") || DOC_EXTS.has(ext)) return "writing-documentation";
@@ -17822,7 +18003,7 @@ function classifyWriteFile(path) {
17822
18003
  return null;
17823
18004
  }
17824
18005
  function classifyEditFile(path) {
17825
- const base = basename6(path);
18006
+ const base = basename7(path);
17826
18007
  const ext = extOf(path);
17827
18008
  if (base.toLowerCase().startsWith("readme") || DOC_EXTS.has(ext)) return "editing-documentation";
17828
18009
  if (CONFIG_EXTS.has(ext)) return "editing-configuration";
@@ -18009,12 +18190,12 @@ var init_heuristic = __esm({
18009
18190
  });
18010
18191
 
18011
18192
  // src/cost-attribution/classify-from-session.ts
18012
- import { readFile as readFile23 } from "fs/promises";
18013
- import { join as join37 } from "path";
18193
+ import { readFile as readFile25 } from "fs/promises";
18194
+ import { join as join39 } from "path";
18014
18195
  import { homedir as homedir22 } from "os";
18015
18196
  function sessionsDir2() {
18016
- const xdg = process.env.XDG_DATA_HOME || join37(homedir22(), ".local", "share");
18017
- return join37(xdg, "kimiflare", "sessions");
18197
+ const xdg = process.env.XDG_DATA_HOME || join39(homedir22(), ".local", "share");
18198
+ return join39(xdg, "kimiflare", "sessions");
18018
18199
  }
18019
18200
  function parseToolCalls(calls) {
18020
18201
  return calls.map((c) => {
@@ -18028,7 +18209,7 @@ function parseToolCalls(calls) {
18028
18209
  }
18029
18210
  async function classifyFromSessionFile(sessionId) {
18030
18211
  try {
18031
- const raw = await readFile23(join37(sessionsDir2(), `${sessionId}.json`), "utf8");
18212
+ const raw = await readFile25(join39(sessionsDir2(), `${sessionId}.json`), "utf8");
18032
18213
  const session = JSON.parse(raw);
18033
18214
  const messages = session.messages ?? [];
18034
18215
  const turns = [];
@@ -18061,15 +18242,15 @@ var cli_exports = {};
18061
18242
  __export(cli_exports, {
18062
18243
  runCostCommand: () => runCostCommand
18063
18244
  });
18064
- import { readFile as readFile24 } from "fs/promises";
18065
- import { join as join38 } from "path";
18245
+ import { readFile as readFile26 } from "fs/promises";
18246
+ import { join as join40 } from "path";
18066
18247
  import { homedir as homedir23 } from "os";
18067
18248
  function usageDir2() {
18068
- const xdg = process.env.XDG_DATA_HOME || join38(homedir23(), ".local", "share");
18069
- return join38(xdg, "kimiflare");
18249
+ const xdg = process.env.XDG_DATA_HOME || join40(homedir23(), ".local", "share");
18250
+ return join40(xdg, "kimiflare");
18070
18251
  }
18071
18252
  function usagePath3() {
18072
- return join38(usageDir2(), "usage.json");
18253
+ return join40(usageDir2(), "usage.json");
18073
18254
  }
18074
18255
  function today2() {
18075
18256
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -18081,7 +18262,7 @@ function daysAgo(n) {
18081
18262
  }
18082
18263
  async function loadLog2() {
18083
18264
  try {
18084
- const raw = await readFile24(usagePath3(), "utf8");
18265
+ const raw = await readFile26(usagePath3(), "utf8");
18085
18266
  return JSON.parse(raw);
18086
18267
  } catch {
18087
18268
  return { version: 1, days: [], sessions: [] };
@@ -18171,12 +18352,12 @@ __export(aster_workspaces_exports, {
18171
18352
  findAsterWorkspace: () => findAsterWorkspace,
18172
18353
  loadAsterServerConfig: () => loadAsterServerConfig
18173
18354
  });
18174
- import { readFile as readFile25, realpath as realpath3, stat as stat9 } from "fs/promises";
18175
- import { isAbsolute as isAbsolute4, relative as relative7, sep as sep3 } from "path";
18355
+ import { readFile as readFile27, realpath as realpath5, stat as stat11 } from "fs/promises";
18356
+ import { isAbsolute as isAbsolute5, relative as relative8, sep as sep4 } from "path";
18176
18357
  async function loadAsterServerConfig(configPath3 = process.env.AUTOPILOT_ASTER_CONFIG || "/etc/autopilot/aster.json") {
18177
18358
  let raw;
18178
18359
  try {
18179
- raw = JSON.parse(await readFile25(configPath3, "utf8"));
18360
+ raw = JSON.parse(await readFile27(configPath3, "utf8"));
18180
18361
  } catch {
18181
18362
  throw new AsterConfigError();
18182
18363
  }
@@ -18209,15 +18390,15 @@ async function loadAsterServerConfig(configPath3 = process.env.AUTOPILOT_ASTER_C
18209
18390
  if (typeof workspace.displayName !== "string" || !workspace.displayName.trim() || workspace.displayName.length > 100) {
18210
18391
  throw new AsterConfigError();
18211
18392
  }
18212
- if (typeof workspace.rootPath !== "string" || !isAbsolute4(workspace.rootPath)) throw new AsterConfigError();
18393
+ if (typeof workspace.rootPath !== "string" || !isAbsolute5(workspace.rootPath)) throw new AsterConfigError();
18213
18394
  let rootPath;
18214
18395
  try {
18215
- rootPath = await realpath3(workspace.rootPath);
18216
- if (!(await stat9(rootPath)).isDirectory()) throw new Error("not a directory");
18396
+ rootPath = await realpath5(workspace.rootPath);
18397
+ if (!(await stat11(rootPath)).isDirectory()) throw new Error("not a directory");
18217
18398
  } catch {
18218
18399
  throw new AsterConfigError();
18219
18400
  }
18220
- if (roots.some((root) => isWithin(root, rootPath) || isWithin(rootPath, root))) {
18401
+ if (roots.some((root) => isWithin2(root, rootPath) || isWithin2(rootPath, root))) {
18221
18402
  throw new AsterConfigError();
18222
18403
  }
18223
18404
  ids.add(workspace.id);
@@ -18229,9 +18410,9 @@ async function loadAsterServerConfig(configPath3 = process.env.AUTOPILOT_ASTER_C
18229
18410
  function findAsterWorkspace(config2, workspaceId) {
18230
18411
  return config2.workspaces.find((workspace) => workspace.id === workspaceId);
18231
18412
  }
18232
- function isWithin(parent, candidate) {
18233
- const rel = relative7(parent, candidate);
18234
- return rel === "" || rel !== ".." && !rel.startsWith(`..${sep3}`) && !isAbsolute4(rel);
18413
+ function isWithin2(parent, candidate) {
18414
+ const rel = relative8(parent, candidate);
18415
+ return rel === "" || rel !== ".." && !rel.startsWith(`..${sep4}`) && !isAbsolute5(rel);
18235
18416
  }
18236
18417
  var AsterConfigError;
18237
18418
  var init_aster_workspaces = __esm({
@@ -18255,10 +18436,10 @@ import Database4 from "better-sqlite3";
18255
18436
  import { createHash as createHash5, randomBytes as randomBytes2, randomUUID as randomUUID6 } from "crypto";
18256
18437
  import { chmodSync as chmodSync2, mkdirSync as mkdirSync9 } from "fs";
18257
18438
  import { homedir as homedir24 } from "os";
18258
- import { dirname as dirname19, join as join39 } from "path";
18439
+ import { dirname as dirname20, join as join41 } from "path";
18259
18440
  function defaultAsterDbPath() {
18260
- const root = process.env.XDG_STATE_HOME || join39(homedir24(), ".local", "state");
18261
- return process.env.AUTOPILOT_ASTER_DB || join39(root, "autopilot", "aster.db");
18441
+ const root = process.env.XDG_STATE_HOME || join41(homedir24(), ".local", "state");
18442
+ return process.env.AUTOPILOT_ASTER_DB || join41(root, "autopilot", "aster.db");
18262
18443
  }
18263
18444
  function hashToken(token) {
18264
18445
  return createHash5("sha256").update(token).digest("hex");
@@ -18309,9 +18490,9 @@ var init_aster_store = __esm({
18309
18490
  AsterStore = class {
18310
18491
  db;
18311
18492
  constructor(dbPath = defaultAsterDbPath()) {
18312
- mkdirSync9(dirname19(dbPath), { recursive: true, mode: 448 });
18493
+ mkdirSync9(dirname20(dbPath), { recursive: true, mode: 448 });
18313
18494
  try {
18314
- chmodSync2(dirname19(dbPath), 448);
18495
+ chmodSync2(dirname20(dbPath), 448);
18315
18496
  } catch {
18316
18497
  }
18317
18498
  this.db = new Database4(dbPath);
@@ -18612,7 +18793,7 @@ __export(tui_auth_exports, {
18612
18793
  authGitHubForTui: () => authGitHubForTui
18613
18794
  });
18614
18795
  function sleep3(ms) {
18615
- return new Promise((resolve19) => setTimeout(resolve19, ms));
18796
+ return new Promise((resolve20) => setTimeout(resolve20, ms));
18616
18797
  }
18617
18798
  async function* authGitHubForTui() {
18618
18799
  yield { message: "Starting GitHub OAuth device flow..." };
@@ -19183,18 +19364,18 @@ var init_openapi = __esm({
19183
19364
 
19184
19365
  // src/runs/worktrees.ts
19185
19366
  import { execFile as execFile8 } from "child_process";
19186
- import { access as access2, chmod as chmod2, mkdir as mkdir16, realpath as realpath4 } from "fs/promises";
19367
+ import { access as access2, chmod as chmod4, mkdir as mkdir17, realpath as realpath6 } from "fs/promises";
19187
19368
  import { homedir as homedir25 } from "os";
19188
- import { isAbsolute as isAbsolute5, join as join40, parse, relative as relative8, resolve as resolve12, sep as sep4 } from "path";
19369
+ import { isAbsolute as isAbsolute6, join as join42, parse, relative as relative9, resolve as resolve13, sep as sep5 } from "path";
19189
19370
  function defaultWorktreesDir() {
19190
- const dataHome = process.env.XDG_DATA_HOME || join40(homedir25(), ".local", "share");
19191
- return join40(dataHome, "autopilot", "worktrees");
19371
+ const dataHome = process.env.XDG_DATA_HOME || join42(homedir25(), ".local", "share");
19372
+ return join42(dataHome, "autopilot", "worktrees");
19192
19373
  }
19193
19374
  function isOutside(path) {
19194
- return path === ".." || path.startsWith(`..${sep4}`) || isAbsolute5(path);
19375
+ return path === ".." || path.startsWith(`..${sep5}`) || isAbsolute6(path);
19195
19376
  }
19196
- function isWithin2(parent, candidate) {
19197
- const path = relative8(parent, candidate);
19377
+ function isWithin3(parent, candidate) {
19378
+ const path = relative9(parent, candidate);
19198
19379
  return path === "" || !isOutside(path);
19199
19380
  }
19200
19381
  function runGit(args, cwd) {
@@ -19222,24 +19403,24 @@ var init_worktrees = __esm({
19222
19403
  if (runId === "." || runId === ".." || !/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/.test(runId)) {
19223
19404
  throw new Error("runId must contain only letters, numbers, dots, underscores, or hyphens");
19224
19405
  }
19225
- const source = await realpath4(sourceCwd);
19406
+ const source = await realpath6(sourceCwd);
19226
19407
  const repositoryRoot = (await runGit(["rev-parse", "--show-toplevel"], source)).trim();
19227
- const repository = await realpath4(repositoryRoot);
19228
- const sourceRelativePath = relative8(repository, source);
19408
+ const repository = await realpath6(repositoryRoot);
19409
+ const sourceRelativePath = relative9(repository, source);
19229
19410
  if (isOutside(sourceRelativePath)) {
19230
19411
  throw new Error("sourceCwd must be inside the Git repository");
19231
19412
  }
19232
- const configuredRoot = resolve12(this.rootDir);
19233
- if (configuredRoot === parse(configuredRoot).root || isWithin2(repository, configuredRoot)) {
19413
+ const configuredRoot = resolve13(this.rootDir);
19414
+ if (configuredRoot === parse(configuredRoot).root || isWithin3(repository, configuredRoot)) {
19234
19415
  throw new Error("worktree root must be outside the source repository and not the filesystem root");
19235
19416
  }
19236
- await mkdir16(configuredRoot, { recursive: true, mode: 448 });
19237
- const worktreesRoot = await realpath4(configuredRoot);
19238
- if (isWithin2(repository, worktreesRoot)) {
19417
+ await mkdir17(configuredRoot, { recursive: true, mode: 448 });
19418
+ const worktreesRoot = await realpath6(configuredRoot);
19419
+ if (isWithin3(repository, worktreesRoot)) {
19239
19420
  throw new Error("worktree root must be outside the source repository");
19240
19421
  }
19241
- await chmod2(worktreesRoot, 448);
19242
- const worktreePath = join40(worktreesRoot, runId);
19422
+ await chmod4(worktreesRoot, 448);
19423
+ const worktreePath = join42(worktreesRoot, runId);
19243
19424
  try {
19244
19425
  await access2(worktreePath);
19245
19426
  throw new Error(`worktree path already exists for run ${runId}`);
@@ -19253,16 +19434,16 @@ var init_worktrees = __esm({
19253
19434
  repositoryRoot: repository,
19254
19435
  sourceCwd: source,
19255
19436
  worktreePath,
19256
- cwd: resolve12(worktreePath, sourceRelativePath),
19437
+ cwd: resolve13(worktreePath, sourceRelativePath),
19257
19438
  branch
19258
19439
  };
19259
19440
  }
19260
19441
  /** Remove a newly-created, still-clean worktree when run initialization fails. */
19261
19442
  async discard(worktree) {
19262
- const root = await realpath4(this.rootDir);
19263
- const target = await realpath4(worktree.worktreePath);
19264
- const repository = await realpath4(worktree.repositoryRoot);
19265
- if (target === root || !isWithin2(root, target)) {
19443
+ const root = await realpath6(this.rootDir);
19444
+ const target = await realpath6(worktree.worktreePath);
19445
+ const repository = await realpath6(worktree.repositoryRoot);
19446
+ if (target === root || !isWithin3(root, target)) {
19266
19447
  throw new Error("worktree path is outside the configured worktree root");
19267
19448
  }
19268
19449
  if (worktree.branch !== `autopilot/run/${worktree.runId}`) {
@@ -19407,8 +19588,8 @@ var init_wake_scheduler = __esm({
19407
19588
  });
19408
19589
 
19409
19590
  // src/server/aster-tools.ts
19410
- import { realpath as realpath5 } from "fs/promises";
19411
- import { isAbsolute as isAbsolute6, relative as relative9, sep as sep5 } from "path";
19591
+ import { realpath as realpath7 } from "fs/promises";
19592
+ import { isAbsolute as isAbsolute7, relative as relative10, sep as sep6 } from "path";
19412
19593
  function createAsterTools(workspaceRoot) {
19413
19594
  return ASTR_TOOLS.map((tool) => ({
19414
19595
  ...tool,
@@ -19420,25 +19601,25 @@ function createAsterTools(workspaceRoot) {
19420
19601
  }
19421
19602
  async function assertAsterWorkspacePath(workspaceRoot, value, allowMissing = false) {
19422
19603
  if (typeof value !== "string" || !value.trim()) throw new Error("workspace_path_invalid");
19423
- const root = await realpath5(workspaceRoot);
19604
+ const root = await realpath7(workspaceRoot);
19424
19605
  const candidate = resolvePath(root, value);
19425
19606
  assertInside(root, candidate);
19426
19607
  assertNotSensitive(root, candidate);
19427
19608
  let actual;
19428
19609
  try {
19429
- actual = await realpath5(candidate);
19610
+ actual = await realpath7(candidate);
19430
19611
  } catch (error) {
19431
19612
  if (!allowMissing || error.code !== "ENOENT") throw new Error("workspace_path_unavailable");
19432
19613
  let ancestor = candidate;
19433
19614
  while (true) {
19434
19615
  try {
19435
- actual = await realpath5(ancestor);
19616
+ actual = await realpath7(ancestor);
19436
19617
  break;
19437
19618
  } catch (ancestorError) {
19438
19619
  if (ancestorError.code !== "ENOENT") throw new Error("workspace_path_unavailable");
19439
- const parent = relative9(root, ancestor);
19620
+ const parent = relative10(root, ancestor);
19440
19621
  if (!parent || parent === ".") throw new Error("workspace_path_unavailable");
19441
- ancestor = ancestor.slice(0, ancestor.lastIndexOf(sep5));
19622
+ ancestor = ancestor.slice(0, ancestor.lastIndexOf(sep6));
19442
19623
  }
19443
19624
  }
19444
19625
  }
@@ -19460,11 +19641,11 @@ function redactLikelySecrets(value) {
19460
19641
  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
19642
  }
19462
19643
  function assertInside(root, candidate) {
19463
- const rel = relative9(root, candidate);
19464
- if (rel === ".." || rel.startsWith(`..${sep5}`) || isAbsolute6(rel)) throw new Error("workspace_path_forbidden");
19644
+ const rel = relative10(root, candidate);
19645
+ if (rel === ".." || rel.startsWith(`..${sep6}`) || isAbsolute7(rel)) throw new Error("workspace_path_forbidden");
19465
19646
  }
19466
19647
  function assertNotSensitive(root, candidate) {
19467
- const parts = relative9(root, candidate).split(sep5).filter(Boolean).map((part) => part.toLowerCase());
19648
+ const parts = relative10(root, candidate).split(sep6).filter(Boolean).map((part) => part.toLowerCase());
19468
19649
  if (parts.some((part) => part === ".env" || part.startsWith(".env.") || SENSITIVE_NAMES.has(part))) {
19469
19650
  throw new Error("workspace_sensitive_path_forbidden");
19470
19651
  }
@@ -19498,8 +19679,8 @@ var init_aster_tools = __esm({
19498
19679
 
19499
19680
  // src/server/aster-api.ts
19500
19681
  import { randomUUID as randomUUID7 } from "crypto";
19501
- import { unlink as unlink2 } from "fs/promises";
19502
- import { resolve as resolve13 } from "path";
19682
+ import { unlink as unlink3 } from "fs/promises";
19683
+ import { resolve as resolve14 } from "path";
19503
19684
  function parseCursor(header, query) {
19504
19685
  const value = (Array.isArray(header) ? header[0] : header) ?? query ?? "0";
19505
19686
  if (!/^\d{1,16}$/.test(value)) return void 0;
@@ -19812,7 +19993,7 @@ var init_aster_api = __esm({
19812
19993
  store.appendEvent(id, null, "conversation.created", { conversationId: id, workspaceId: workspace.id, model });
19813
19994
  json(res, 201, publicConversation(conversation));
19814
19995
  } catch {
19815
- await unlink2(resolve13(sessionsDir(), `${sessionId}.json`)).catch(() => {
19996
+ await unlink3(resolve14(sessionsDir(), `${sessionId}.json`)).catch(() => {
19816
19997
  });
19817
19998
  await worktreeManager.discard(worktree).catch(() => {
19818
19999
  });
@@ -19837,7 +20018,7 @@ var init_aster_api = __esm({
19837
20018
  sendError(res, 409, "conversation_busy", "A turn is already active for this conversation");
19838
20019
  return;
19839
20020
  }
19840
- const sessionPath = resolve13(sessionsDir(), conversation.sessionId + ".json");
20021
+ const sessionPath = resolve14(sessionsDir(), conversation.sessionId + ".json");
19841
20022
  let sessionFile;
19842
20023
  try {
19843
20024
  sessionFile = await loadSession(sessionPath);
@@ -20155,7 +20336,7 @@ data: ${JSON.stringify(event.data)}
20155
20336
 
20156
20337
  // src/server/aster-cell-runtime.ts
20157
20338
  import { execFile as execFile9 } from "child_process";
20158
- import { readFile as readFile26 } from "fs/promises";
20339
+ import { readFile as readFile28 } from "fs/promises";
20159
20340
  import { promisify as promisify8 } from "util";
20160
20341
  import { randomUUID as randomUUID8 } from "crypto";
20161
20342
  async function writeCellFileChunked(cell, path, content) {
@@ -20185,7 +20366,7 @@ async function writeCellFileChunked(cell, path, content) {
20185
20366
  async function readBundledCellSdkBundle() {
20186
20367
  for (const url of [new URL("./sdk/index.js", import.meta.url), new URL("../sdk/index.js", import.meta.url)]) {
20187
20368
  try {
20188
- return await readFile26(url, "utf8");
20369
+ return await readFile28(url, "utf8");
20189
20370
  } catch {
20190
20371
  }
20191
20372
  }
@@ -20238,7 +20419,7 @@ function boundedToolText(text, limit) {
20238
20419
  ${redacted.slice(-half)}`;
20239
20420
  }
20240
20421
  function sleep4(ms) {
20241
- return new Promise((resolve19) => setTimeout(resolve19, ms));
20422
+ return new Promise((resolve20) => setTimeout(resolve20, ms));
20242
20423
  }
20243
20424
  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
20425
  var init_aster_cell_runtime = __esm({
@@ -20681,9 +20862,9 @@ ${turn.userText}` : turn.userText;
20681
20862
  if (!isSafeArtifactPath(path)) throw new Error("invalid_artifact_path");
20682
20863
  const cell = await this.provider.getCell(cellId);
20683
20864
  const file = shellQuote2(`${ARTIFACTS_DIR}/${path}`);
20684
- const stat13 = await cell.exec(`[ -f ${file} ] && [ ! -L ${file} ] && stat -c %s -- ${file}`);
20685
- if (stat13.exitCode !== 0) throw new Error("artifact_not_found");
20686
- if (Number(stat13.stdout.trim()) > MAX_ARTIFACT_BYTES) throw new Error("artifact_too_large");
20865
+ const stat15 = await cell.exec(`[ -f ${file} ] && [ ! -L ${file} ] && stat -c %s -- ${file}`);
20866
+ if (stat15.exitCode !== 0) throw new Error("artifact_not_found");
20867
+ if (Number(stat15.stdout.trim()) > MAX_ARTIFACT_BYTES) throw new Error("artifact_too_large");
20687
20868
  const encoded = await cell.exec(`base64 -w0 -- ${file}`);
20688
20869
  if (encoded.exitCode !== 0) throw new Error("artifact_not_found");
20689
20870
  return { data: Buffer.from(encoded.stdout.trim(), "base64"), mimeType: artifactMimeType(path), name: path.split("/").pop() ?? path };
@@ -20980,8 +21161,8 @@ var init_hotcell_provider = __esm({
20980
21161
  // src/server/routes.ts
20981
21162
  import { randomUUID as randomUUID9 } from "crypto";
20982
21163
  import { URL as URL2 } from "url";
20983
- import { readFile as readFile27, unlink as unlink3 } from "fs/promises";
20984
- import { resolve as resolve14, basename as basename7 } from "path";
21164
+ import { readFile as readFile29, unlink as unlink4 } from "fs/promises";
21165
+ import { resolve as resolve15, basename as basename8 } from "path";
20985
21166
  function createHotcellAsterRuntime() {
20986
21167
  try {
20987
21168
  const idlePauseMs = Number(process.env.AUTOPILOT_ASTER_IDLE_PAUSE_MS ?? 15 * 60 * 1e3);
@@ -21064,9 +21245,9 @@ async function resolveFiles2(filePatterns, cwd) {
21064
21245
  const resolved = /* @__PURE__ */ new Set();
21065
21246
  for (const pattern of filePatterns) {
21066
21247
  try {
21067
- const stat13 = await import("fs/promises").then((m) => m.stat(resolve14(cwd, pattern)));
21068
- if (stat13.isFile()) {
21069
- resolved.add(resolve14(cwd, pattern));
21248
+ const stat15 = await import("fs/promises").then((m) => m.stat(resolve15(cwd, pattern)));
21249
+ if (stat15.isFile()) {
21250
+ resolved.add(resolve15(cwd, pattern));
21070
21251
  continue;
21071
21252
  }
21072
21253
  } catch {
@@ -21089,12 +21270,12 @@ async function buildUserMessage2(prompt, files, cwd) {
21089
21270
  imageParts.push({ type: "image_url", image_url: { url: img.dataUrl } });
21090
21271
  } catch (e) {
21091
21272
  fileContents.push(`
21092
- <!-- failed to attach image ${basename7(filePath)}: ${e.message} -->
21273
+ <!-- failed to attach image ${basename8(filePath)}: ${e.message} -->
21093
21274
  `);
21094
21275
  }
21095
21276
  } else {
21096
21277
  try {
21097
- const content = await readFile27(filePath, "utf8");
21278
+ const content = await readFile29(filePath, "utf8");
21098
21279
  const relPath = filePath.startsWith(cwd) ? filePath.slice(cwd.length + 1) : filePath;
21099
21280
  fileContents.push(`
21100
21281
  --- ${relPath} ---
@@ -21103,7 +21284,7 @@ ${content}
21103
21284
  `);
21104
21285
  } catch (e) {
21105
21286
  fileContents.push(`
21106
- <!-- failed to read ${basename7(filePath)}: ${e.message} -->
21287
+ <!-- failed to read ${basename8(filePath)}: ${e.message} -->
21107
21288
  `);
21108
21289
  }
21109
21290
  }
@@ -21123,7 +21304,7 @@ function setupRoutes(config2, options = {}) {
21123
21304
  if (!run.sessionId) throw new Error("Cannot restore run without a session id: " + run.id);
21124
21305
  const existing = activeRuns.get(run.id) ?? activeSessions.get(run.sessionId);
21125
21306
  if (existing) return existing;
21126
- const sessionFile = await loadSession(resolve14(sessionsDir(), run.sessionId + ".json"));
21307
+ const sessionFile = await loadSession(resolve15(sessionsDir(), run.sessionId + ".json"));
21127
21308
  const allowedTools = new Set(run.allowedTools);
21128
21309
  allowedTools.add("wait_for");
21129
21310
  const tools = ALL_TOOLS.filter((tool) => allowedTools.has(tool.name));
@@ -21258,7 +21439,7 @@ function setupRoutes(config2, options = {}) {
21258
21439
  const task = typeof body.task === "string" ? body.task.trim() : "";
21259
21440
  let cwd;
21260
21441
  try {
21261
- cwd = typeof body.cwd === "string" ? resolve14(body.cwd) : process.cwd();
21442
+ cwd = typeof body.cwd === "string" ? resolve15(body.cwd) : process.cwd();
21262
21443
  } catch {
21263
21444
  badRequest(res, "cwd must be a valid path");
21264
21445
  return;
@@ -21371,7 +21552,7 @@ function setupRoutes(config2, options = {}) {
21371
21552
  store.close();
21372
21553
  }
21373
21554
  } catch (error) {
21374
- await unlink3(resolve14(sessionsDir(), `${sessionId}.json`)).catch(() => {
21555
+ await unlink4(resolve15(sessionsDir(), `${sessionId}.json`)).catch(() => {
21375
21556
  });
21376
21557
  if (worktree) {
21377
21558
  await worktreeManager.discard(worktree).catch((cleanupError) => {
@@ -21506,7 +21687,7 @@ function setupRoutes(config2, options = {}) {
21506
21687
  return;
21507
21688
  }
21508
21689
  try {
21509
- const file = await loadSession(resolve14(sessionsDir(), `${sessionId}.json`));
21690
+ const file = await loadSession(resolve15(sessionsDir(), `${sessionId}.json`));
21510
21691
  json2(res, 200, {
21511
21692
  id: file.id,
21512
21693
  cwd: file.cwd,
@@ -21525,8 +21706,8 @@ function setupRoutes(config2, options = {}) {
21525
21706
  const sessionId = sessionMatch[1];
21526
21707
  activeSessions.delete(sessionId);
21527
21708
  try {
21528
- const { unlink: unlink6 } = await import("fs/promises");
21529
- await unlink6(resolve14(sessionsDir(), `${sessionId}.json`));
21709
+ const { unlink: unlink7 } = await import("fs/promises");
21710
+ await unlink7(resolve15(sessionsDir(), `${sessionId}.json`));
21530
21711
  } catch {
21531
21712
  }
21532
21713
  json2(res, 200, { deleted: sessionId });
@@ -21977,13 +22158,13 @@ async function startServer(opts2) {
21977
22158
  };
21978
22159
  process.on("SIGINT", shutdown);
21979
22160
  process.on("SIGTERM", shutdown);
21980
- return new Promise((resolve19, reject) => {
22161
+ return new Promise((resolve20, reject) => {
21981
22162
  server.listen(opts2.port, opts2.hostname, () => {
21982
22163
  logger.info("server: listening", { hostname: opts2.hostname, port: opts2.port });
21983
22164
  console.log(`kimiflare serve: http://${opts2.hostname}:${opts2.port}`);
21984
22165
  console.log(` API docs: http://${opts2.hostname}:${opts2.port}/doc`);
21985
22166
  console.log(` SSE stream: http://${opts2.hostname}:${opts2.port}/event`);
21986
- resolve19(server);
22167
+ resolve20(server);
21987
22168
  });
21988
22169
  server.on("error", reject);
21989
22170
  });
@@ -22288,8 +22469,8 @@ async function runEmitMode(opts2) {
22288
22469
  async function nextFollowUp() {
22289
22470
  if (followUpQueue.length > 0) return followUpQueue.shift();
22290
22471
  if (stdinClosed) return null;
22291
- return new Promise((resolve19) => {
22292
- followUpResolver = resolve19;
22472
+ return new Promise((resolve20) => {
22473
+ followUpResolver = resolve20;
22293
22474
  });
22294
22475
  }
22295
22476
  const cwd = process.cwd();
@@ -22426,8 +22607,8 @@ async function runEmitMode(opts2) {
22426
22607
  return "allow";
22427
22608
  }
22428
22609
  if (opts2.multiTurn) {
22429
- const choice = await new Promise((resolve19) => {
22430
- pendingPermissions.set(reqId, resolve19);
22610
+ const choice = await new Promise((resolve20) => {
22611
+ pendingPermissions.set(reqId, resolve20);
22431
22612
  });
22432
22613
  if (choice === "allow" || choice === "allow_session") {
22433
22614
  emit("PermissionGranted", { request_id: reqId });
@@ -22562,7 +22743,7 @@ async function runAttachMode(opts2) {
22562
22743
  async function streamSse(url, sessionId, format) {
22563
22744
  const eventSource = new EventSource(`${url}/event`);
22564
22745
  let done = false;
22565
- return new Promise((resolve19, reject) => {
22746
+ return new Promise((resolve20, reject) => {
22566
22747
  eventSource.onmessage = (event) => {
22567
22748
  try {
22568
22749
  const data = JSON.parse(event.data);
@@ -22609,7 +22790,7 @@ async function streamSse(url, sessionId, format) {
22609
22790
  done = true;
22610
22791
  eventSource.close();
22611
22792
  if (format === "text") process.stdout.write("\n");
22612
- resolve19(void 0);
22793
+ resolve20(void 0);
22613
22794
  break;
22614
22795
  case "error":
22615
22796
  done = true;
@@ -22622,7 +22803,7 @@ async function streamSse(url, sessionId, format) {
22622
22803
  process.stdout.write(JSON.stringify({ event: "error", message: data.message }) + "\n");
22623
22804
  }
22624
22805
  process.exitCode = 1;
22625
- resolve19(void 0);
22806
+ resolve20(void 0);
22626
22807
  break;
22627
22808
  }
22628
22809
  } catch {
@@ -22648,7 +22829,7 @@ async function streamSseJson(url, sessionId) {
22648
22829
  const toolResults = [];
22649
22830
  let usage;
22650
22831
  const eventSource = new EventSource(`${url}/event`);
22651
- return new Promise((resolve19, reject) => {
22832
+ return new Promise((resolve20, reject) => {
22652
22833
  eventSource.onmessage = (event) => {
22653
22834
  try {
22654
22835
  const data = JSON.parse(event.data);
@@ -22685,7 +22866,7 @@ async function streamSseJson(url, sessionId) {
22685
22866
  2
22686
22867
  ) + "\n"
22687
22868
  );
22688
- resolve19(void 0);
22869
+ resolve20(void 0);
22689
22870
  break;
22690
22871
  case "error":
22691
22872
  eventSource.close();
@@ -22693,7 +22874,7 @@ async function streamSseJson(url, sessionId) {
22693
22874
  JSON.stringify({ error: data.message, sessionId }, null, 2) + "\n"
22694
22875
  );
22695
22876
  process.exitCode = 1;
22696
- resolve19(void 0);
22877
+ resolve20(void 0);
22697
22878
  break;
22698
22879
  }
22699
22880
  } catch {
@@ -23422,10 +23603,9 @@ __export(app_helpers_exports, {
23422
23603
  replaceUserPromptEvent: () => replaceUserPromptEvent,
23423
23604
  trackRecentFile: () => trackRecentFile
23424
23605
  });
23425
- import { execSync as execSync3, spawn as spawn7 } from "child_process";
23606
+ import { execSync as execSync3 } from "child_process";
23426
23607
  import { existsSync as existsSync8, readFileSync as readFileSync6, statSync as statSync5 } from "fs";
23427
- import { join as join41 } from "path";
23428
- import { platform as platform3 } from "os";
23608
+ import { join as join43 } from "path";
23429
23609
  function replaceQueuedPrompt(queue2, key, full, display) {
23430
23610
  const index = queue2.findIndex((item) => item.key === key);
23431
23611
  if (index >= 0) {
@@ -23532,7 +23712,7 @@ function buildFilePickerIgnoreList(cwd) {
23532
23712
  ];
23533
23713
  const gitignorePatterns = [];
23534
23714
  try {
23535
- const gitignorePath = join41(cwd, ".gitignore");
23715
+ const gitignorePath = join43(cwd, ".gitignore");
23536
23716
  const stats = statSync5(gitignorePath);
23537
23717
  if (stats.size > MAX_GITIGNORE_SIZE) {
23538
23718
  return hardcoded;
@@ -23563,19 +23743,6 @@ function costLookupFromConfig(cfg, meta) {
23563
23743
  if (resolveCustomEndpoint(cfg)) return void 0;
23564
23744
  return { apiKey: cfg.openrouterApiKey, meta };
23565
23745
  }
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
23746
  function detectGitHubRepo(cachedRepo) {
23580
23747
  if (cachedRepo) {
23581
23748
  const parts = cachedRepo.split("/");
@@ -23694,6 +23861,7 @@ var init_app_helpers = __esm({
23694
23861
  init_system_prompt();
23695
23862
  init_image();
23696
23863
  init_queue_batch();
23864
+ init_open_browser();
23697
23865
  MAX_GITIGNORE_SIZE = 1 * 1024 * 1024;
23698
23866
  CONTEXT_LIMIT = 262e3;
23699
23867
  AUTO_COMPACT_THRESHOLD = 0.8;
@@ -23710,9 +23878,9 @@ var init_app_helpers = __esm({
23710
23878
 
23711
23879
  // src/ui/bang-command.ts
23712
23880
  import { spawn as spawn8 } from "child_process";
23713
- import { mkdtemp as mkdtemp2, readFile as readFile28, rm as rm5 } from "fs/promises";
23714
- import { tmpdir as tmpdir4, platform as platform4 } from "os";
23715
- import { join as join42 } from "path";
23881
+ import { mkdtemp as mkdtemp3, readFile as readFile30, rm as rm6 } from "fs/promises";
23882
+ import { tmpdir as tmpdir5, platform as platform4 } from "os";
23883
+ import { join as join44 } from "path";
23716
23884
  function registerInkInstance(instance) {
23717
23885
  inkInstance = instance;
23718
23886
  }
@@ -23720,13 +23888,13 @@ function registerTerminalHandoff(h) {
23720
23888
  terminalHandoff = h;
23721
23889
  }
23722
23890
  function runCaptured(inv, cwd) {
23723
- return new Promise((resolve19) => {
23891
+ return new Promise((resolve20) => {
23724
23892
  const child = spawn8(inv.file, inv.args, { cwd, stdio: ["ignore", "pipe", "pipe"], env: inv.env ?? process.env });
23725
23893
  let output = "";
23726
23894
  child.stdout?.on("data", (c) => output += c.toString("utf8"));
23727
23895
  child.stderr?.on("data", (c) => output += c.toString("utf8"));
23728
- child.once("error", (e) => resolve19({ code: 127, signal: null, output: `failed to start: ${e.message}` }));
23729
- child.once("exit", (code, signal) => resolve19({ code, signal, output }));
23896
+ child.once("error", (e) => resolve20({ code: 127, signal: null, output: `failed to start: ${e.message}` }));
23897
+ child.once("exit", (code, signal) => resolve20({ code, signal, output }));
23730
23898
  });
23731
23899
  }
23732
23900
  function isTerminalHandedOff() {
@@ -23794,10 +23962,10 @@ function swallow() {
23794
23962
  });
23795
23963
  }
23796
23964
  function spawnInherit(inv, cwd) {
23797
- return new Promise((resolve19, reject) => {
23965
+ return new Promise((resolve20, reject) => {
23798
23966
  const child = spawn8(inv.file, inv.args, { cwd, stdio: "inherit", env: inv.env ?? process.env });
23799
23967
  child.once("error", reject);
23800
- child.once("exit", (code, signal) => resolve19({ code, signal }));
23968
+ child.once("exit", (code, signal) => resolve20({ code, signal }));
23801
23969
  });
23802
23970
  }
23803
23971
  async function runBangCommand(command, cwd) {
@@ -23815,8 +23983,8 @@ async function runBangCommand(command, cwd) {
23815
23983
  const origErr = stderr.write;
23816
23984
  const readable = stdin.listeners("readable");
23817
23985
  const wasRaw = stdin.isTTY ? stdin.isRaw : false;
23818
- const logDir2 = isWindows ? null : await mkdtemp2(join42(tmpdir4(), "autopilot-bang-"));
23819
- const logPath = logDir2 ? join42(logDir2, "out.log") : null;
23986
+ const logDir2 = isWindows ? null : await mkdtemp3(join44(tmpdir5(), "autopilot-bang-"));
23987
+ const logPath = logDir2 ? join44(logDir2, "out.log") : null;
23820
23988
  const viaScript = logPath ? scriptInvocation(command, shell, logPath) : null;
23821
23989
  inkInstance?.clear();
23822
23990
  origOut.call(stdout, `
@@ -23858,9 +24026,9 @@ $ ${command}
23858
24026
  }
23859
24027
  let output = spawnError ? `failed to start: ${spawnError}` : null;
23860
24028
  if (captured && logPath) {
23861
- output = cleanTerminalOutput(await readFile28(logPath, "utf8").catch(() => ""));
24029
+ output = cleanTerminalOutput(await readFile30(logPath, "utf8").catch(() => ""));
23862
24030
  }
23863
- if (logDir2) await rm5(logDir2, { recursive: true, force: true }).catch(() => {
24031
+ if (logDir2) await rm6(logDir2, { recursive: true, force: true }).catch(() => {
23864
24032
  });
23865
24033
  return { command, exitCode: result2.code, signal: result2.signal, output };
23866
24034
  }
@@ -26039,6 +26207,7 @@ var init_activity = __esm({
26039
26207
  var camouflage_view_exports = {};
26040
26208
  __export(camouflage_view_exports, {
26041
26209
  CamouflageUnavailable: () => CamouflageUnavailable,
26210
+ executeCodeSummary: () => executeCodeSummary,
26042
26211
  helpOptions: () => helpOptions,
26043
26212
  listMentionDir: () => listMentionDir,
26044
26213
  modelOptions: () => modelOptions,
@@ -26050,10 +26219,10 @@ __export(camouflage_view_exports, {
26050
26219
  toolSummary: () => toolSummary,
26051
26220
  validateCommandName: () => validateCommandName
26052
26221
  });
26053
- import { execFileSync as execFileSync2, spawn as spawn10 } from "child_process";
26054
- import { readdir as readdir7 } from "fs/promises";
26222
+ import { execFileSync as execFileSync3, spawn as spawn10 } from "child_process";
26223
+ import { readdir as readdir8 } from "fs/promises";
26055
26224
  import { homedir as homedir26 } from "os";
26056
- import { join as join43, resolve as resolve15 } from "path";
26225
+ import { join as join45, resolve as resolve16 } from "path";
26057
26226
  async function loadSdk() {
26058
26227
  const sdk = await import("camouflage-tui").catch((err) => {
26059
26228
  throw new CamouflageUnavailable(`camouflage-tui is not installed (${err.message})`);
@@ -26142,14 +26311,14 @@ async function runCamouflageView(opts2) {
26142
26311
  }
26143
26312
  }
26144
26313
  function runShell2(command) {
26145
- return new Promise((resolve19) => {
26314
+ return new Promise((resolve20) => {
26146
26315
  const { shell, args } = getShellCommand();
26147
26316
  const child = spawn10(shell, [...args, command], { env: process.env });
26148
26317
  let out = "";
26149
26318
  child.stdout?.on("data", (c) => out += c.toString("utf8"));
26150
26319
  child.stderr?.on("data", (c) => out += c.toString("utf8"));
26151
- child.on("close", (code) => resolve19({ ok: code === 0, output: out || (code === 0 ? "" : `Exit code: ${code}`) }));
26152
- child.on("error", (err) => resolve19({ ok: false, output: err.message }));
26320
+ child.on("close", (code) => resolve20({ ok: code === 0, output: out || (code === 0 ? "" : `Exit code: ${code}`) }));
26321
+ child.on("error", (err) => resolve20({ ok: false, output: err.message }));
26153
26322
  });
26154
26323
  }
26155
26324
  function syncSlashCommands(custom, lastKey, send) {
@@ -26232,10 +26401,10 @@ function truncateText(s, max) {
26232
26401
  async function listMentionDir(cwd, query) {
26233
26402
  const exact = query === "~" || query === "." || query === ".." || query.endsWith("/..");
26234
26403
  const dir = exact ? `${query}/` : query.slice(0, query.lastIndexOf("/") + 1);
26235
- const expanded = dir.startsWith("~") ? join43(homedir26(), dir.slice(1)) : dir;
26236
- const target = resolve15(cwd, expanded || ".");
26404
+ const expanded = dir.startsWith("~") ? join45(homedir26(), dir.slice(1)) : dir;
26405
+ const target = resolve16(cwd, expanded || ".");
26237
26406
  try {
26238
- const items = await readdir7(target, { withFileTypes: true });
26407
+ const items = await readdir8(target, { withFileTypes: true });
26239
26408
  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
26409
  return { dir, entries };
26241
26410
  } catch {
@@ -26270,8 +26439,26 @@ function toolRow(name, title, rawArgs) {
26270
26439
  const rest = title.toLowerCase().startsWith(`${name.toLowerCase()} `) ? title.slice(name.length + 1) : title;
26271
26440
  return { label, args: rest.trim() };
26272
26441
  }
26442
+ if (name === "execute_code") {
26443
+ return { label: "Code", args: clip(executeCodeSummary(rawArgs)) };
26444
+ }
26273
26445
  const args = (rawArgs ?? "").replace(/\s+/g, " ").trim();
26274
- return { label, args: args.length > 120 ? `${args.slice(0, 119)}\u2026` : args };
26446
+ return { label, args: clip(args) };
26447
+ }
26448
+ function clip(s) {
26449
+ return s.length > 120 ? `${s.slice(0, 119)}\u2026` : s;
26450
+ }
26451
+ function executeCodeSummary(rawArgs) {
26452
+ let parsed = {};
26453
+ try {
26454
+ parsed = rawArgs ? JSON.parse(rawArgs) : {};
26455
+ } catch {
26456
+ return "running a code batch";
26457
+ }
26458
+ if (typeof parsed.reasoning === "string" && parsed.reasoning.trim()) return parsed.reasoning.replace(/\s+/g, " ").trim();
26459
+ const code = typeof parsed.code === "string" ? parsed.code : "";
26460
+ const first = code.split("\n").map((l) => l.trim()).find((l) => l && !l.startsWith("//"));
26461
+ return first ? first.replace(/\s+/g, " ") : "running a code batch";
26275
26462
  }
26276
26463
  function toolSummary(name, ok, declined, content) {
26277
26464
  if (declined) return "You declined this \xB7 tell autopilot what to do instead";
@@ -26318,14 +26505,14 @@ function shortPath(p) {
26318
26505
  }
26319
26506
  function gitBranch(cwd) {
26320
26507
  try {
26321
- return execFileSync2("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd, encoding: "utf8", timeout: 500, stdio: ["ignore", "pipe", "ignore"] }).trim();
26508
+ return execFileSync3("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd, encoding: "utf8", timeout: 500, stdio: ["ignore", "pipe", "ignore"] }).trim();
26322
26509
  } catch {
26323
26510
  return "";
26324
26511
  }
26325
26512
  }
26326
26513
  function listFiles(cwd) {
26327
26514
  try {
26328
- const out = execFileSync2("git", ["ls-files", "--cached", "--others", "--exclude-standard"], {
26515
+ const out = execFileSync3("git", ["ls-files", "--cached", "--others", "--exclude-standard"], {
26329
26516
  cwd,
26330
26517
  encoding: "utf8",
26331
26518
  timeout: 2e3,
@@ -29224,19 +29411,19 @@ function usePermissionController(getMode, onPlanModeBlocked) {
29224
29411
  const onPlanModeBlockedRef = useRef3(onPlanModeBlocked);
29225
29412
  onPlanModeBlockedRef.current = onPlanModeBlocked;
29226
29413
  const askPermission = useCallback2(
29227
- (req, askOpts) => new Promise((resolve19) => {
29414
+ (req, askOpts) => new Promise((resolve20) => {
29228
29415
  const outcome = decidePermission(req, getModeRef.current(), askOpts);
29229
29416
  if (outcome.kind === "resolve") {
29230
- resolve19(outcome.decision);
29417
+ resolve20(outcome.decision);
29231
29418
  return;
29232
29419
  }
29233
29420
  if (outcome.kind === "plan_blocked") {
29234
29421
  onPlanModeBlockedRef.current(outcome.toolName);
29235
- resolve19(AUTO_DENY);
29422
+ resolve20(AUTO_DENY);
29236
29423
  return;
29237
29424
  }
29238
- resolveRef.current = resolve19;
29239
- setPending({ tool: req.tool, args: req.args, resolve: resolve19 });
29425
+ resolveRef.current = resolve20;
29426
+ setPending({ tool: req.tool, args: req.args, resolve: resolve20 });
29240
29427
  }),
29241
29428
  []
29242
29429
  );
@@ -29581,9 +29768,9 @@ var init_queue_plan_picker = __esm({
29581
29768
  });
29582
29769
 
29583
29770
  // src/agent/jev-context.ts
29584
- import { execFileSync as execFileSync3 } from "child_process";
29585
- import { readFile as readFile29 } from "fs/promises";
29586
- import { basename as basename8, join as join44, resolve as resolve16 } from "path";
29771
+ import { execFileSync as execFileSync4 } from "child_process";
29772
+ import { readFile as readFile31 } from "fs/promises";
29773
+ import { basename as basename9, join as join46, resolve as resolve17 } from "path";
29587
29774
  function messageText(message2) {
29588
29775
  if (typeof message2.content === "string") return message2.content.trim();
29589
29776
  if (!Array.isArray(message2.content)) return "";
@@ -29594,18 +29781,18 @@ function redactCommonSecrets(text) {
29594
29781
  }
29595
29782
  function projectRoot(cwd) {
29596
29783
  try {
29597
- return execFileSync3("git", ["-C", cwd, "rev-parse", "--show-toplevel"], {
29784
+ return execFileSync4("git", ["-C", cwd, "rev-parse", "--show-toplevel"], {
29598
29785
  encoding: "utf8",
29599
29786
  stdio: ["ignore", "pipe", "ignore"],
29600
29787
  timeout: 1e3
29601
29788
  }).trim();
29602
29789
  } catch {
29603
- return resolve16(cwd);
29790
+ return resolve17(cwd);
29604
29791
  }
29605
29792
  }
29606
29793
  async function readPackageMetadata(root) {
29607
29794
  try {
29608
- const parsed = JSON.parse(await readFile29(join44(root, "package.json"), "utf8"));
29795
+ const parsed = JSON.parse(await readFile31(join46(root, "package.json"), "utf8"));
29609
29796
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
29610
29797
  const pkg = parsed;
29611
29798
  const metadata = {};
@@ -29622,7 +29809,7 @@ async function readPackageMetadata(root) {
29622
29809
  async function readLicenseEvidence(root) {
29623
29810
  for (const name of ["LICENSE", "LICENSE.md", "LICENSE.txt", "LICENCE", "COPYING"]) {
29624
29811
  try {
29625
- const content = (await readFile29(join44(root, name), "utf8")).trim();
29812
+ const content = (await readFile31(join46(root, name), "utf8")).trim();
29626
29813
  if (content) return { source: `project license (${name})`, content: content.slice(0, 700) };
29627
29814
  } catch {
29628
29815
  }
@@ -29655,13 +29842,13 @@ async function buildJevContext(question, messages, cwd = process.cwd()) {
29655
29842
  conversationRemaining -= source.length + content.length + 2;
29656
29843
  }
29657
29844
  }
29658
- const currentDirectory = basename8(resolve16(cwd));
29845
+ const currentDirectory = basename9(resolve17(cwd));
29659
29846
  const escapedDirectory = currentDirectory.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
29660
29847
  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
29848
  if (CURRENT_PROJECT_REFERENCE.test(question) || namesCurrentDirectory) {
29662
29849
  const root = projectRoot(cwd);
29663
29850
  const metadata = await readPackageMetadata(root);
29664
- if (!metadata.name) metadata.name = basename8(root);
29851
+ if (!metadata.name) metadata.name = basename9(root);
29665
29852
  add("project metadata (package.json or directory)", JSON.stringify(metadata));
29666
29853
  if (LICENSE_QUESTION.test(question)) {
29667
29854
  const license = await readLicenseEvidence(root);
@@ -30704,8 +30891,8 @@ var init_frontmatter = __esm({
30704
30891
  });
30705
30892
 
30706
30893
  // src/skills/loader.ts
30707
- import { readFile as readFile30, readdir as readdir8, stat as stat10 } from "fs/promises";
30708
- import { join as join45, extname } from "path";
30894
+ import { readFile as readFile32, readdir as readdir9, stat as stat12 } from "fs/promises";
30895
+ import { join as join47, extname } from "path";
30709
30896
  function normalizeManifest(raw, filePath) {
30710
30897
  const name = typeof raw.name === "string" ? raw.name : "";
30711
30898
  const description = typeof raw.description === "string" ? raw.description : "";
@@ -30719,7 +30906,7 @@ function normalizeManifest(raw, filePath) {
30719
30906
  return { name, description, match, scope, priority, enabled: enabled2 };
30720
30907
  }
30721
30908
  async function loadSkillFile(filePath) {
30722
- const raw = await readFile30(filePath, "utf-8");
30909
+ const raw = await readFile32(filePath, "utf-8");
30723
30910
  const parsed = parseFrontmatter(raw);
30724
30911
  const manifest = normalizeManifest(parsed.data, filePath);
30725
30912
  const body = parsed.content.trim();
@@ -30738,11 +30925,11 @@ async function loadSkillFile(filePath) {
30738
30925
  }
30739
30926
  async function loadSkillsFromDir(dirPath) {
30740
30927
  try {
30741
- const entries = await readdir8(dirPath);
30928
+ const entries = await readdir9(dirPath);
30742
30929
  const files = [];
30743
30930
  for (const entry of entries) {
30744
- const full = join45(dirPath, entry);
30745
- const s = await stat10(full);
30931
+ const full = join47(dirPath, entry);
30932
+ const s = await stat12(full);
30746
30933
  if (s.isFile() && extname(entry) === ".md") {
30747
30934
  files.push(full);
30748
30935
  }
@@ -30769,12 +30956,12 @@ var init_loader = __esm({
30769
30956
  });
30770
30957
 
30771
30958
  // src/skills/manager.ts
30772
- import { mkdir as mkdir17, writeFile as writeFile15, unlink as unlink4, readFile as readFile31 } from "fs/promises";
30773
- import { join as join46 } from "path";
30959
+ import { mkdir as mkdir18, writeFile as writeFile15, unlink as unlink5, readFile as readFile33 } from "fs/promises";
30960
+ import { join as join48 } from "path";
30774
30961
  function getSkillDirs(cwd) {
30775
30962
  return {
30776
- projectDir: join46(cwd, ".kimiflare", "skills"),
30777
- globalDir: join46(process.env.HOME ?? "", ".config", "kimiflare", "skills")
30963
+ projectDir: join48(cwd, ".kimiflare", "skills"),
30964
+ globalDir: join48(process.env.HOME ?? "", ".config", "kimiflare", "skills")
30778
30965
  };
30779
30966
  }
30780
30967
  async function listAllSkills(cwd) {
@@ -30788,7 +30975,7 @@ async function listAllSkills(cwd) {
30788
30975
  async function createSkill(opts2) {
30789
30976
  const dirs = getSkillDirs(opts2.cwd);
30790
30977
  const dir = opts2.scope === "project" ? dirs.projectDir : dirs.globalDir;
30791
- const filepath = join46(dir, `${opts2.name}.md`);
30978
+ const filepath = join48(dir, `${opts2.name}.md`);
30792
30979
  const frontmatter = {
30793
30980
  name: opts2.name,
30794
30981
  enabled: true,
@@ -30809,7 +30996,7 @@ ${yaml}
30809
30996
 
30810
30997
  Add your instructions here.
30811
30998
  `;
30812
- await mkdir17(dir, { recursive: true });
30999
+ await mkdir18(dir, { recursive: true });
30813
31000
  await writeFile15(filepath, content, "utf8");
30814
31001
  return { filepath };
30815
31002
  }
@@ -30817,14 +31004,14 @@ async function deleteSkill(name, cwd) {
30817
31004
  const all = await listAllSkills(cwd);
30818
31005
  const skill = all.project.find((s) => s.name === name) ?? all.global.find((s) => s.name === name);
30819
31006
  if (!skill) throw new Error(`skill "${name}" not found`);
30820
- await unlink4(skill.filePath);
31007
+ await unlink5(skill.filePath);
30821
31008
  return { filepath: skill.filePath };
30822
31009
  }
30823
31010
  async function setSkillEnabled(name, enabled2, cwd) {
30824
31011
  const all = await listAllSkills(cwd);
30825
31012
  const skill = all.project.find((s) => s.name === name) ?? all.global.find((s) => s.name === name);
30826
31013
  if (!skill) throw new Error(`skill "${name}" not found`);
30827
- const raw = await readFile31(skill.filePath, "utf-8");
31014
+ const raw = await readFile33(skill.filePath, "utf-8");
30828
31015
  const parsed = parseFrontmatter(raw);
30829
31016
  parsed.data.enabled = enabled2;
30830
31017
  const yaml = Object.entries(parsed.data).map(([k, v]) => {
@@ -31096,15 +31283,15 @@ var tui_report_exports = {};
31096
31283
  __export(tui_report_exports, {
31097
31284
  getCategoryReportText: () => getCategoryReportText
31098
31285
  });
31099
- import { readFile as readFile32 } from "fs/promises";
31100
- import { join as join47 } from "path";
31286
+ import { readFile as readFile34 } from "fs/promises";
31287
+ import { join as join49 } from "path";
31101
31288
  import { homedir as homedir27 } from "os";
31102
31289
  function usageDir3() {
31103
- const xdg = process.env.XDG_DATA_HOME || join47(homedir27(), ".local", "share");
31104
- return join47(xdg, "kimiflare");
31290
+ const xdg = process.env.XDG_DATA_HOME || join49(homedir27(), ".local", "share");
31291
+ return join49(xdg, "kimiflare");
31105
31292
  }
31106
31293
  function usagePath4() {
31107
- return join47(usageDir3(), "usage.json");
31294
+ return join49(usageDir3(), "usage.json");
31108
31295
  }
31109
31296
  function today3() {
31110
31297
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -31116,7 +31303,7 @@ function daysAgo2(n) {
31116
31303
  }
31117
31304
  async function loadLog3() {
31118
31305
  try {
31119
- const raw = await readFile32(usagePath4(), "utf8");
31306
+ const raw = await readFile34(usagePath4(), "utf8");
31120
31307
  return JSON.parse(raw);
31121
31308
  } catch {
31122
31309
  return { version: 1, days: [], sessions: [] };
@@ -31173,7 +31360,7 @@ var init_tui_report = __esm({
31173
31360
  });
31174
31361
 
31175
31362
  // src/ui/slash-commands.ts
31176
- import { join as join48 } from "path";
31363
+ import { join as join50 } from "path";
31177
31364
  import QRCode from "qrcode";
31178
31365
  function executeFreshStart(ctx, planText, overrideMode, opts2 = {}) {
31179
31366
  const oldSessionId = ctx.sessionIdRef.current;
@@ -31644,7 +31831,7 @@ auto (default) lets the coordinator assess substantial tasks and delegate indepe
31644
31831
  const context = noContext ? [] : await buildJevContext(question.prompt, ctx.messagesRef.current, process.cwd());
31645
31832
  const receipt = formatJevContextReceipt(context, showContext);
31646
31833
  setResult(eventKey, { kind: "info", key: eventKey, text: `Jev is evaluating \xB7 ${receipt}`, pending: true });
31647
- await new Promise((resolve19) => setTimeout(resolve19, 0));
31834
+ await new Promise((resolve20) => setTimeout(resolve20, 0));
31648
31835
  const answer = await askJev(apiKey, question, { context });
31649
31836
  const presentation = presentJevAnswer(question, answer);
31650
31837
  setResult(eventKey, {
@@ -32105,7 +32292,7 @@ ${lines.join("\n")}` }]);
32105
32292
  void (async () => {
32106
32293
  try {
32107
32294
  const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
32108
- const file = await loadSession(join48(sessionsDir3(), `${currentId}.json`));
32295
+ const file = await loadSession(join50(sessionsDir3(), `${currentId}.json`));
32109
32296
  const cps = file.checkpoints ?? [];
32110
32297
  if (cps.length === 0) {
32111
32298
  setEvents((e) => [...e, { kind: "info", key: mkKey2(), text: "no checkpoints in this session" }]);
@@ -32150,7 +32337,7 @@ ${lines.join("\n")}` }]);
32150
32337
  try {
32151
32338
  ctx.ensureSessionId();
32152
32339
  const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
32153
- const filePath = join48(sessionsDir3(), `${ctx.sessionIdRef.current}.json`);
32340
+ const filePath = join50(sessionsDir3(), `${ctx.sessionIdRef.current}.json`);
32154
32341
  await addCheckpoint(filePath, cp);
32155
32342
  setEvents((e) => [...e, { kind: "info", key: mkKey2(), text: `checkpoint saved: "${label}"` }]);
32156
32343
  } catch (e) {
@@ -32875,9 +33062,9 @@ async function triageIncoming(text, context, opts2 = {}) {
32875
33062
  "steer = it adjusts or adds to the current task and should be folded in at the next step;",
32876
33063
  "queue = it is separate work that should run after the current task;",
32877
33064
  "aside = it is a question about progress that can be answered without changing the work.",
32878
- `Current task: ${clip(context.currentTask)}`,
32879
- context.activity ? `Doing now: ${clip(context.activity, 200)}` : "",
32880
- `New message: ${clip(text)}`
33065
+ `Current task: ${clip2(context.currentTask)}`,
33066
+ context.activity ? `Doing now: ${clip2(context.activity, 200)}` : "",
33067
+ `New message: ${clip2(text)}`
32881
33068
  ].filter(Boolean).join("\n"),
32882
33069
  options: [...OPTIONS2]
32883
33070
  };
@@ -32905,7 +33092,7 @@ async function triageIncoming(text, context, opts2 = {}) {
32905
33092
  function unsure(reason, confidence) {
32906
33093
  return { kind: "queue", source: "default", reason, ...confidence === void 0 ? {} : { confidence } };
32907
33094
  }
32908
- function clip(text, max = MAX_CHARS) {
33095
+ function clip2(text, max = MAX_CHARS) {
32909
33096
  const single = text.replace(/\s+/g, " ").trim();
32910
33097
  return single.length > max ? `${single.slice(0, max - 1)}\u2026` : single;
32911
33098
  }
@@ -32952,7 +33139,7 @@ var init_inbox_triage = __esm({
32952
33139
 
32953
33140
  // src/agent/aside.ts
32954
33141
  async function answerAside(question, context, opts2) {
32955
- const clip2 = (text2, max) => (text2 ?? "").replace(/\s+/g, " ").trim().slice(0, max);
33142
+ const clip3 = (text2, max) => (text2 ?? "").replace(/\s+/g, " ").trim().slice(0, max);
32956
33143
  const messages = [
32957
33144
  {
32958
33145
  role: "system",
@@ -32961,11 +33148,11 @@ async function answerAside(question, context, opts2) {
32961
33148
  {
32962
33149
  role: "user",
32963
33150
  content: [
32964
- `Task: ${clip2(context.currentTask, 600)}`,
32965
- context.progress ? `Progress: ${clip2(context.progress, 600)}` : "",
32966
- context.activity ? `Running now: ${clip2(context.activity, 300)}` : "",
32967
- context.recentAssistantText ? `Latest agent message: ${clip2(context.recentAssistantText, 800)}` : "",
32968
- `Question: ${clip2(question, 400)}`
33151
+ `Task: ${clip3(context.currentTask, 600)}`,
33152
+ context.progress ? `Progress: ${clip3(context.progress, 600)}` : "",
33153
+ context.activity ? `Running now: ${clip3(context.activity, 300)}` : "",
33154
+ context.recentAssistantText ? `Latest agent message: ${clip3(context.recentAssistantText, 800)}` : "",
33155
+ `Question: ${clip3(question, 400)}`
32969
33156
  ].filter(Boolean).join("\n")
32970
33157
  }
32971
33158
  ];
@@ -33206,9 +33393,9 @@ async function startLoopbackListener(opts2 = {}) {
33206
33393
  rejectCode(e);
33207
33394
  finish();
33208
33395
  }
33209
- await new Promise((resolve19, reject) => {
33396
+ await new Promise((resolve20, reject) => {
33210
33397
  server.once("error", reject);
33211
- server.listen(0, "127.0.0.1", () => resolve19());
33398
+ server.listen(0, "127.0.0.1", () => resolve20());
33212
33399
  });
33213
33400
  const address = server.address();
33214
33401
  const port = typeof address === "object" && address ? address.port : 0;
@@ -33634,15 +33821,15 @@ var init_frontmatter2 = __esm({
33634
33821
  });
33635
33822
 
33636
33823
  // src/commands/loader.ts
33637
- import { open, realpath as realpath6 } from "fs/promises";
33824
+ import { open, realpath as realpath8 } from "fs/promises";
33638
33825
  import { homedir as homedir28 } from "os";
33639
- import { join as join49, relative as relative10, sep as sep6 } from "path";
33826
+ import { join as join51, relative as relative11, sep as sep7 } from "path";
33640
33827
  function projectCommandsDir(cwd = process.cwd()) {
33641
- return join49(cwd, ".kimiflare", "commands");
33828
+ return join51(cwd, ".kimiflare", "commands");
33642
33829
  }
33643
33830
  function globalCommandsDir() {
33644
- const xdg = process.env.XDG_CONFIG_HOME || join49(homedir28(), ".config");
33645
- return join49(xdg, "kimiflare", "commands");
33831
+ const xdg = process.env.XDG_CONFIG_HOME || join51(homedir28(), ".config");
33832
+ return join51(xdg, "kimiflare", "commands");
33646
33833
  }
33647
33834
  async function loadCustomCommands(cwd = process.cwd()) {
33648
33835
  const warnings = [];
@@ -33681,7 +33868,7 @@ async function loadCustomCommands(cwd = process.cwd()) {
33681
33868
  async function resolveSafeDir(dir, source, cwd, warnings) {
33682
33869
  let realDir;
33683
33870
  try {
33684
- realDir = await realpath6(dir);
33871
+ realDir = await realpath8(dir);
33685
33872
  } catch (err) {
33686
33873
  const code = err.code;
33687
33874
  if (code !== "ENOENT" && code !== "ENOTDIR") {
@@ -33692,11 +33879,11 @@ async function resolveSafeDir(dir, source, cwd, warnings) {
33692
33879
  if (source === "project") {
33693
33880
  let realCwd;
33694
33881
  try {
33695
- realCwd = await realpath6(cwd);
33882
+ realCwd = await realpath8(cwd);
33696
33883
  } catch {
33697
33884
  return null;
33698
33885
  }
33699
- const rel = relative10(realCwd, realDir);
33886
+ const rel = relative11(realCwd, realDir);
33700
33887
  if (rel !== "" && isPathOutside(rel)) {
33701
33888
  warnings.push(`commands dir ${dir} escapes workspace via symlink \u2014 skipped`);
33702
33889
  return null;
@@ -33771,10 +33958,10 @@ async function loadOne(file, rootDir, source, warnings) {
33771
33958
  return cmd;
33772
33959
  }
33773
33960
  function filenameToCommandName(file, rootDir) {
33774
- const rel = relative10(rootDir, file);
33961
+ const rel = relative11(rootDir, file);
33775
33962
  if (!rel || isPathOutside(rel)) return null;
33776
33963
  const noExt = rel.replace(/\.md$/i, "");
33777
- const parts = noExt.split(sep6).filter((p) => p.length > 0);
33964
+ const parts = noExt.split(sep7).filter((p) => p.length > 0);
33778
33965
  if (parts.length === 0) return null;
33779
33966
  if (parts.some((p) => !/^[\w.-]+$/.test(p))) return null;
33780
33967
  return parts.join("/");
@@ -33794,8 +33981,8 @@ var init_loader2 = __esm({
33794
33981
 
33795
33982
  // src/commands/renderer.ts
33796
33983
  import { exec } from "child_process";
33797
- import { open as open2, realpath as realpath7 } from "fs/promises";
33798
- import { isAbsolute as isAbsolute7, relative as relative11, resolve as resolvePathJoin, basename as pathBasename } from "path";
33984
+ import { open as open2, realpath as realpath9 } from "fs/promises";
33985
+ import { isAbsolute as isAbsolute8, relative as relative12, resolve as resolvePathJoin, basename as pathBasename } from "path";
33799
33986
  import { promisify as promisify9 } from "util";
33800
33987
  function tokenizeArgs(s) {
33801
33988
  return [...s.matchAll(ARG_TOKEN_RE)].map((match) => {
@@ -33886,7 +34073,7 @@ async function replaceFiles(prompt, warnings, cmd, cwd, maxFileBytes) {
33886
34073
  return "" + trailing;
33887
34074
  });
33888
34075
  }
33889
- const realCwd = await realpath7(cwd).catch(() => cwd);
34076
+ const realCwd = await realpath9(cwd).catch(() => cwd);
33890
34077
  const replacements = await Promise.all(
33891
34078
  matches.map(async (match) => {
33892
34079
  const rawPath = match[1] ?? "";
@@ -33895,23 +34082,23 @@ async function replaceFiles(prompt, warnings, cmd, cwd, maxFileBytes) {
33895
34082
  warnings.push(`file inclusion blocked: @${rawPath} \u2014 secret file pattern`);
33896
34083
  return "";
33897
34084
  }
33898
- if (isAbsolute7(rawPath) || rawPath.startsWith("~")) {
34085
+ if (isAbsolute8(rawPath) || rawPath.startsWith("~")) {
33899
34086
  warnings.push(`file inclusion skipped: @${rawPath} \u2014 outside workspace`);
33900
34087
  return "";
33901
34088
  }
33902
34089
  const resolved = resolvePathJoin(cwd, rawPath);
33903
- if (isPathOutside(relative11(cwd, resolved))) {
34090
+ if (isPathOutside(relative12(cwd, resolved))) {
33904
34091
  warnings.push(`file inclusion skipped: @${rawPath} \u2014 outside workspace`);
33905
34092
  return "";
33906
34093
  }
33907
34094
  let real;
33908
34095
  try {
33909
- real = await realpath7(resolved);
34096
+ real = await realpath9(resolved);
33910
34097
  } catch (error) {
33911
34098
  warnings.push(`file inclusion failed: @${rawPath} \u2014 ${message(error)}`);
33912
34099
  return "";
33913
34100
  }
33914
- if (isPathOutside(relative11(realCwd, real))) {
34101
+ if (isPathOutside(relative12(realCwd, real))) {
33915
34102
  warnings.push(`file inclusion skipped: @${rawPath} \u2014 symlink escapes workspace`);
33916
34103
  return "";
33917
34104
  }
@@ -34024,11 +34211,11 @@ var init_wcag = __esm({
34024
34211
  });
34025
34212
 
34026
34213
  // src/ui/theme-loader.ts
34027
- import { readFile as readFile33, readdir as readdir9 } from "fs/promises";
34028
- import { join as join50 } from "path";
34214
+ import { readFile as readFile35, readdir as readdir10 } from "fs/promises";
34215
+ import { join as join52 } from "path";
34029
34216
  import { homedir as homedir29 } from "os";
34030
34217
  function projectThemesDir(cwd = process.cwd()) {
34031
- return join50(cwd, ".kimiflare", "themes");
34218
+ return join52(cwd, ".kimiflare", "themes");
34032
34219
  }
34033
34220
  function isHexColor(c) {
34034
34221
  return /^#[0-9a-fA-F]{6}$/.test(c);
@@ -34112,15 +34299,15 @@ async function loadThemesFromDir(dir, source) {
34112
34299
  const errors = [];
34113
34300
  let files;
34114
34301
  try {
34115
- files = await readdir9(dir);
34302
+ files = await readdir10(dir);
34116
34303
  } catch {
34117
34304
  return { themes, errors };
34118
34305
  }
34119
34306
  for (const file of files.filter((f) => f.endsWith(".json"))) {
34120
- const path = join50(dir, file);
34307
+ const path = join52(dir, file);
34121
34308
  let raw;
34122
34309
  try {
34123
- raw = await readFile33(path, "utf-8");
34310
+ raw = await readFile35(path, "utf-8");
34124
34311
  } catch (e) {
34125
34312
  errors.push(`${path}: ${e instanceof Error ? e.message : String(e)}`);
34126
34313
  continue;
@@ -34266,8 +34453,8 @@ var init_theme_loader = __esm({
34266
34453
  "use strict";
34267
34454
  init_wcag();
34268
34455
  init_theme();
34269
- USER_THEMES_DIR = join50(
34270
- process.env.XDG_CONFIG_HOME || join50(homedir29(), ".config"),
34456
+ USER_THEMES_DIR = join52(
34457
+ process.env.XDG_CONFIG_HOME || join52(homedir29(), ".config"),
34271
34458
  "kimiflare",
34272
34459
  "themes"
34273
34460
  );
@@ -36798,9 +36985,9 @@ var init_resume_progress = __esm({
36798
36985
  });
36799
36986
 
36800
36987
  // src/agent/supervisor.ts
36801
- import { readdir as readdir10, readFile as readFile34, stat as stat11 } from "fs/promises";
36988
+ import { readdir as readdir11, readFile as readFile36, stat as stat13 } from "fs/promises";
36802
36989
  import { createHash as createHash7 } from "crypto";
36803
- import { resolve as resolve17, join as join51 } from "path";
36990
+ import { resolve as resolve18, join as join53 } from "path";
36804
36991
  var TurnSupervisor;
36805
36992
  var init_supervisor = __esm({
36806
36993
  "src/agent/supervisor.ts"() {
@@ -37190,12 +37377,12 @@ var init_input_handlers = __esm({
37190
37377
 
37191
37378
  // src/init/context-generator.ts
37192
37379
  import { existsSync as existsSync9, statSync as statSync6 } from "fs";
37193
- import { join as join52 } from "path";
37380
+ import { join as join54 } from "path";
37194
37381
  function detectFlavor(cwd) {
37195
37382
  for (const [flavor, signatures] of Object.entries(FLAVOR_SIGNATURES)) {
37196
37383
  if (flavor === "generic") continue;
37197
37384
  for (const sig of signatures) {
37198
- const path = join52(cwd, sig);
37385
+ const path = join54(cwd, sig);
37199
37386
  if (sig.includes("*")) {
37200
37387
  try {
37201
37388
  const parts = sig.split("*");
@@ -37216,14 +37403,14 @@ function detectFlavor(cwd) {
37216
37403
  }
37217
37404
  function findFile(cwd, candidates) {
37218
37405
  for (const c of candidates) {
37219
- if (existsSync9(join52(cwd, c))) return c;
37406
+ if (existsSync9(join54(cwd, c))) return c;
37220
37407
  }
37221
37408
  return null;
37222
37409
  }
37223
37410
  function findSourceRoots(cwd) {
37224
37411
  const roots = [];
37225
37412
  for (const r of SOURCE_ROOT_CANDIDATES) {
37226
- const p = join52(cwd, r);
37413
+ const p = join54(cwd, r);
37227
37414
  try {
37228
37415
  const s = statSync6(p);
37229
37416
  if (s.isDirectory()) roots.push(r);
@@ -37234,9 +37421,9 @@ function findSourceRoots(cwd) {
37234
37421
  }
37235
37422
  function findCiConfig(cwd) {
37236
37423
  for (const c of CI_PATHS) {
37237
- if (existsSync9(join52(cwd, c))) {
37424
+ if (existsSync9(join54(cwd, c))) {
37238
37425
  try {
37239
- const s = statSync6(join52(cwd, c));
37426
+ const s = statSync6(join54(cwd, c));
37240
37427
  return s.isDirectory() ? c : c;
37241
37428
  } catch {
37242
37429
  }
@@ -37373,7 +37560,7 @@ function analyzeProject(cwd) {
37373
37560
  ciConfig: findCiConfig(cwd),
37374
37561
  readme: findFile(cwd, ["README.md", "README.rst", "README.txt", "Readme.md"]),
37375
37562
  sourceRoots: findSourceRoots(cwd),
37376
- hasGit: existsSync9(join52(cwd, ".git"))
37563
+ hasGit: existsSync9(join54(cwd, ".git"))
37377
37564
  };
37378
37565
  }
37379
37566
  function bashDiscoveryCommands(profile) {
@@ -37536,19 +37723,33 @@ Aim for 100\u2013200 lines total. Use markdown tables where they save space.
37536
37723
  - State management approach
37537
37724
  `.trim();
37538
37725
  }
37726
+ function buildInitTasks(targetFilename) {
37727
+ return [
37728
+ { id: "identity", title: "Inspect project identity and configuration", status: "in_progress" },
37729
+ { id: "structure", title: "Discover source structure, tests, and conventions", status: "pending" },
37730
+ { id: "workflow", title: "Identify build and development workflows", status: "pending" },
37731
+ { id: "architecture", title: "Map architecture and project patterns", status: "pending" },
37732
+ { id: "write", title: "Write or refresh " + targetFilename, status: "pending" },
37733
+ { id: "verify", title: "Re-read and verify " + targetFilename, status: "pending" }
37734
+ ];
37735
+ }
37539
37736
  function buildInitPrompt(cwd) {
37540
37737
  const existingName = ["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].find(
37541
- (n) => existsSync9(join52(cwd, n))
37738
+ (n) => existsSync9(join54(cwd, n))
37542
37739
  );
37543
37740
  const isRefresh = existingName !== void 0;
37544
37741
  const targetFilename = existingName ?? "AGENTS.md";
37545
37742
  const profile = analyzeProject(cwd);
37546
37743
  const checklist = discoveryChecklist(profile);
37547
37744
  const sections = sectionTemplate();
37745
+ const tasks = buildInitTasks(targetFilename);
37548
37746
  const promptParts = [
37549
37747
  isRefresh ? `Regenerate \`${targetFilename}\` at the repository root to refresh project context. The file already exists \u2014 read it first and preserve anything still accurate, updating only what has changed or is missing.` : `Generate a \`${targetFilename}\` at the repository root so future agents have comprehensive project context.`,
37550
37748
  "",
37551
37749
  "This is a **structured investigation**. Follow the checklist below systematically. Use the `glob`, `read`, `grep`, and `bash` tools to gather information. Do not skip steps.",
37750
+ `Visible task list (already initialized in the UI; keep these IDs and titles):
37751
+ ${tasks.map((task) => "- " + task.id + ": " + task.status + ": " + task.title).join("\n")}`,
37752
+ "Keep the visible task checklist synchronized with your progress using `tasks_set`: update the current phase and mark the next phase active before moving on. Map the detailed checklist below onto these high-level tasks.",
37552
37753
  "",
37553
37754
  `**Detected project profile:** ${profile.primaryLanguage} (${profile.flavor})`,
37554
37755
  profile.packageFile ? `- Package file: ${profile.packageFile}` : null,
@@ -37570,10 +37771,10 @@ function buildInitPrompt(cwd) {
37570
37771
  "",
37571
37772
  isRefresh ? `After writing the file, re-read \`${targetFilename}\` and verify it is complete and accurate.` : "After writing the file, re-read it and verify all sections are present and accurate.",
37572
37773
  "",
37573
- "Do not call `tasks_set` for this. Just follow the checklist, gather information, then write the file."
37774
+ "The visible task checklist is already initialized. Mark investigation phases complete as you finish them, and complete the write and verification tasks only after re-reading the generated file."
37574
37775
  ];
37575
37776
  const prompt = promptParts.filter((p) => p !== null).join("\n");
37576
- return { prompt, targetFilename, isRefresh };
37777
+ return { prompt, targetFilename, isRefresh, tasks };
37577
37778
  }
37578
37779
  var FLAVOR_SIGNATURES, SOURCE_ROOT_CANDIDATES, CI_PATHS;
37579
37780
  var init_context_generator = __esm({
@@ -37622,7 +37823,7 @@ var init_context_generator = __esm({
37622
37823
 
37623
37824
  // src/init/run-init.ts
37624
37825
  import { existsSync as existsSync10 } from "fs";
37625
- import { join as join53 } from "path";
37826
+ import { join as join55 } from "path";
37626
37827
  async function runInit(deps) {
37627
37828
  const {
37628
37829
  cfg,
@@ -37636,6 +37837,7 @@ async function runInit(deps) {
37636
37837
  setUsage,
37637
37838
  setSessionUsage,
37638
37839
  setKimiMdStale,
37840
+ onTasks,
37639
37841
  beginTurn,
37640
37842
  endTurn,
37641
37843
  ensureSessionId,
@@ -37670,7 +37872,8 @@ async function runInit(deps) {
37670
37872
  return;
37671
37873
  }
37672
37874
  const cwd = process.cwd();
37673
- const { prompt, targetFilename, isRefresh } = buildInitPrompt(cwd);
37875
+ const { prompt, targetFilename, isRefresh, tasks } = buildInitPrompt(cwd);
37876
+ onTasks(tasks);
37674
37877
  setEvents((e) => [
37675
37878
  ...e,
37676
37879
  { kind: "user", key: mkKey2(), text: isRefresh ? `/init (refreshing ${targetFilename})` : "/init" }
@@ -37715,7 +37918,7 @@ async function runInit(deps) {
37715
37918
  lspManagerRef.current.notifyChange(path, content);
37716
37919
  } else {
37717
37920
  void import("fs/promises").then(
37718
- ({ readFile: readFile36 }) => readFile36(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
37921
+ ({ readFile: readFile38 }) => readFile38(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
37719
37922
  })
37720
37923
  );
37721
37924
  }
@@ -37800,6 +38003,7 @@ async function runInit(deps) {
37800
38003
  void getCostReport(sid).then((report) => setSessionUsage(report.session));
37801
38004
  },
37802
38005
  onResponseMeta: updateResponseMeta,
38006
+ onTasks,
37803
38007
  askPermission: (req) => askForPermission(req, { promptOnBlockedBash: true }),
37804
38008
  onGuardrail: (ev) => {
37805
38009
  setEvents((e) => [...e, { kind: "info", key: mkKey2(), text: ev.message }]);
@@ -37820,7 +38024,7 @@ async function runInit(deps) {
37820
38024
  }
37821
38025
  }
37822
38026
  });
37823
- if (existsSync10(join53(cwd, targetFilename))) {
38027
+ if (existsSync10(join55(cwd, targetFilename))) {
37824
38028
  if (cacheStableRef.current) {
37825
38029
  messagesRef.current[1] = {
37826
38030
  role: "system",
@@ -37885,6 +38089,7 @@ async function runInit(deps) {
37885
38089
  } finally {
37886
38090
  logger.info("runInit:finally");
37887
38091
  setCodeMode(false);
38092
+ onTasks([]);
37888
38093
  const asstId = activeAsstIdRef.current;
37889
38094
  if (asstId !== null) updateAssistant(asstId, () => ({ streaming: false }));
37890
38095
  endTurn();
@@ -37912,11 +38117,11 @@ var init_run_init = __esm({
37912
38117
  });
37913
38118
 
37914
38119
  // src/skills/discovery.ts
37915
- import { readdir as readdir11, stat as stat12, readFile as readFile35 } from "fs/promises";
37916
- import { join as join54, extname as extname2 } from "path";
38120
+ import { readdir as readdir12, stat as stat14, readFile as readFile37 } from "fs/promises";
38121
+ import { join as join56, extname as extname2 } from "path";
37917
38122
  async function dirExists(path) {
37918
38123
  try {
37919
- const s = await stat12(path);
38124
+ const s = await stat14(path);
37920
38125
  return s.isDirectory();
37921
38126
  } catch {
37922
38127
  return false;
@@ -37924,7 +38129,7 @@ async function dirExists(path) {
37924
38129
  }
37925
38130
  async function fileExists(path) {
37926
38131
  try {
37927
- const s = await stat12(path);
38132
+ const s = await stat14(path);
37928
38133
  return s.isFile();
37929
38134
  } catch {
37930
38135
  return false;
@@ -37932,25 +38137,25 @@ async function fileExists(path) {
37932
38137
  }
37933
38138
  async function scanSkillDir(dirPath, source) {
37934
38139
  if (!await dirExists(dirPath)) return [];
37935
- const entries = await readdir11(dirPath, { withFileTypes: true });
38140
+ const entries = await readdir12(dirPath, { withFileTypes: true });
37936
38141
  const files = [];
37937
38142
  for (const entry of entries) {
37938
38143
  if (!entry.isFile()) continue;
37939
38144
  if (!SKILL_EXTENSIONS.has(extname2(entry.name))) continue;
37940
- files.push({ filePath: join54(dirPath, entry.name), source });
38145
+ files.push({ filePath: join56(dirPath, entry.name), source });
37941
38146
  }
37942
38147
  return files;
37943
38148
  }
37944
38149
  async function discoverSkills(cwd) {
37945
- const agentsSkills = await scanSkillDir(join54(cwd, ".agents", "skills"), "agents");
37946
- const agentsMd = await fileExists(join54(cwd, "AGENTS.md")) ? [{ filePath: join54(cwd, "AGENTS.md"), source: "agents-md" }] : [];
37947
- const githubSkills = await scanSkillDir(join54(cwd, ".github", "skills"), "github");
37948
- const kimiflareSkills = await scanSkillDir(join54(cwd, ".kimiflare", "skills"), "kimiflare");
38150
+ const agentsSkills = await scanSkillDir(join56(cwd, ".agents", "skills"), "agents");
38151
+ const agentsMd = await fileExists(join56(cwd, "AGENTS.md")) ? [{ filePath: join56(cwd, "AGENTS.md"), source: "agents-md" }] : [];
38152
+ const githubSkills = await scanSkillDir(join56(cwd, ".github", "skills"), "github");
38153
+ const kimiflareSkills = await scanSkillDir(join56(cwd, ".kimiflare", "skills"), "kimiflare");
37949
38154
  const ordered = [...agentsSkills, ...agentsMd, ...githubSkills, ...kimiflareSkills];
37950
38155
  return ordered;
37951
38156
  }
37952
38157
  async function readSkillFile(filePath) {
37953
- const bytes = await readFile35(filePath);
38158
+ const bytes = await readFile37(filePath);
37954
38159
  return { bytes, text: bytes.toString("utf-8") };
37955
38160
  }
37956
38161
  var SKILL_EXTENSIONS;
@@ -38156,7 +38361,7 @@ var init_skills = __esm({
38156
38361
 
38157
38362
  // src/ui/run-startup-tasks.ts
38158
38363
  import { existsSync as existsSync11 } from "fs";
38159
- import { join as join55 } from "path";
38364
+ import { join as join57 } from "path";
38160
38365
  function runStartupTasks(deps) {
38161
38366
  const {
38162
38367
  cfg,
@@ -38179,7 +38384,7 @@ function runStartupTasks(deps) {
38179
38384
  }
38180
38385
  });
38181
38386
  if (cfg.memoryEnabled) {
38182
- const dbPath = cfg.memoryDbPath ?? join55(process.cwd(), ".kimiflare", "memory.db");
38387
+ const dbPath = cfg.memoryDbPath ?? join57(process.cwd(), ".kimiflare", "memory.db");
38183
38388
  const manager = new MemoryManager({
38184
38389
  dbPath,
38185
38390
  ...auth,
@@ -38211,7 +38416,7 @@ function runStartupTasks(deps) {
38211
38416
  });
38212
38417
  const cwd = process.cwd();
38213
38418
  sessionStartRecallRef.current = manager.recall({ text: cwd, repoPath: cwd, limit: 5 });
38214
- if (["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].some((name) => existsSync11(join55(cwd, name)))) {
38419
+ if (["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].some((name) => existsSync11(join57(cwd, name)))) {
38215
38420
  const lastRefresh = manager.getLastKimiMdRefreshTime(cwd);
38216
38421
  const driftCount = manager.countHighSignalMemoriesSince(cwd, lastRefresh);
38217
38422
  if (driftCount >= 5) {
@@ -38222,7 +38427,7 @@ function runStartupTasks(deps) {
38222
38427
  memoryManagerRef.current?.close();
38223
38428
  memoryManagerRef.current = null;
38224
38429
  }
38225
- const skillDbPath = cfg.memoryDbPath ?? join55(process.cwd(), ".kimiflare", "memory.db");
38430
+ const skillDbPath = cfg.memoryDbPath ?? join57(process.cwd(), ".kimiflare", "memory.db");
38226
38431
  const skillDb = getMemoryDb() ?? openMemoryDb(skillDbPath);
38227
38432
  initSkillsSchema(skillDb);
38228
38433
  void indexSkills({
@@ -38579,8 +38784,8 @@ var init_run_compact = __esm({
38579
38784
  });
38580
38785
 
38581
38786
  // src/commands/save.ts
38582
- import { mkdir as mkdir18, writeFile as writeFile16, unlink as unlink5 } from "fs/promises";
38583
- import { dirname as dirname21 } from "path";
38787
+ import { mkdir as mkdir19, writeFile as writeFile16, unlink as unlink6 } from "fs/promises";
38788
+ import { dirname as dirname22 } from "path";
38584
38789
  async function saveCustomCommand(opts2) {
38585
38790
  const dir = opts2.source === "project" ? projectCommandsDir(opts2.cwd) : globalCommandsDir();
38586
38791
  const filepath = `${dir}/${opts2.name}.md`;
@@ -38591,12 +38796,12 @@ async function saveCustomCommand(opts2) {
38591
38796
  if (opts2.effort) data.effort = opts2.effort;
38592
38797
  const frontmatter = serializeFrontmatter(data);
38593
38798
  const content = frontmatter + opts2.template;
38594
- await mkdir18(dirname21(filepath), { recursive: true });
38799
+ await mkdir19(dirname22(filepath), { recursive: true });
38595
38800
  await writeFile16(filepath, content, "utf8");
38596
38801
  return { filepath };
38597
38802
  }
38598
38803
  async function deleteCustomCommand(cmd) {
38599
- await unlink5(cmd.filepath);
38804
+ await unlink6(cmd.filepath);
38600
38805
  }
38601
38806
  var init_save = __esm({
38602
38807
  "src/commands/save.ts"() {
@@ -38715,7 +38920,7 @@ __export(app_exports, {
38715
38920
  import React25, { useState as useState27, useRef as useRef9, useEffect as useEffect11, useCallback as useCallback8, useMemo as useMemo6 } from "react";
38716
38921
  import { Box as Box40, Text as Text41, useApp, useInput as useInput19, useWindowSize as useWindowSize2, render } from "ink";
38717
38922
  import { existsSync as existsSync12 } from "fs";
38718
- import { join as join56, resolve as resolve18 } from "path";
38923
+ import { join as join58, resolve as resolve19 } from "path";
38719
38924
  import { homedir as homedir30 } from "os";
38720
38925
  import { jsx as jsx42, jsxs as jsxs39 } from "react/jsx-runtime";
38721
38926
  function App({
@@ -38950,6 +39155,21 @@ ${wcagWarnings.join("\n")}` }
38950
39155
  const effortRef = useRef9(effort);
38951
39156
  const usageRef = useRef9(null);
38952
39157
  const responseMetaRef = useRef9(null);
39158
+ const updateTaskTracking = useCallback8((nextTasks) => {
39159
+ const previousTasks = tasksRef.current;
39160
+ const prevEmpty = previousTasks.length === 0;
39161
+ const prevAllDone = previousTasks.length > 0 && previousTasks.every((task) => task.status === "completed");
39162
+ tasksRef.current = nextTasks;
39163
+ setTasks(nextTasks);
39164
+ if ((prevEmpty || prevAllDone) && nextTasks.length > 0) {
39165
+ setTasksStartedAt(Date.now());
39166
+ setTasksStartTokens(usageRef.current?.prompt_tokens ?? 0);
39167
+ }
39168
+ if (nextTasks.length === 0) {
39169
+ setTasksStartedAt(null);
39170
+ setTasksStartTokens(0);
39171
+ }
39172
+ }, [tasksRef, setTasks, setTasksStartedAt, setTasksStartTokens]);
38953
39173
  const lastApiErrorRef = useRef9(null);
38954
39174
  const updateCheckedRef = useRef9(false);
38955
39175
  const sessionStateRef = useRef9(emptySessionState());
@@ -39043,8 +39263,8 @@ ${wcagWarnings.join("\n")}` }
39043
39263
  const exactDirectory = query === "~" || query === "." || query === ".." || query.endsWith("/..");
39044
39264
  const prefix = exactDirectory ? `${query.replace(/\/$/, "")}/` : slash >= 0 ? query.slice(0, slash + 1) : "";
39045
39265
  const directory = exactDirectory ? query : slash >= 0 ? query.slice(0, slash + 1) : query;
39046
- const expanded = directory.startsWith("~") ? join56(homedir30(), directory.slice(1)) : directory;
39047
- const target = resolve18(cwd, expanded || ".");
39266
+ const expanded = directory.startsWith("~") ? join58(homedir30(), directory.slice(1)) : directory;
39267
+ const target = resolve19(cwd, expanded || ".");
39048
39268
  const entries2 = await glob("*", {
39049
39269
  cwd: target,
39050
39270
  dot: false,
@@ -39543,6 +39763,7 @@ ${wcagWarnings.join("\n")}` }
39543
39763
  setUsage,
39544
39764
  setSessionUsage,
39545
39765
  setKimiMdStale,
39766
+ onTasks: updateTaskTracking,
39546
39767
  beginTurn,
39547
39768
  endTurn,
39548
39769
  ensureSessionId,
@@ -39572,7 +39793,7 @@ ${wcagWarnings.join("\n")}` }
39572
39793
  lastApiErrorRef,
39573
39794
  supervisorRef
39574
39795
  });
39575
- }, [cfg, busy, updateAssistant, updateTool, updateResponseMeta]);
39796
+ }, [cfg, busy, updateAssistant, updateTool, updateResponseMeta, updateTaskTracking]);
39576
39797
  const handleThemePick = useCallback8(
39577
39798
  (picked) => {
39578
39799
  setShowThemePicker(false);
@@ -40026,7 +40247,7 @@ ${result2.output ?? "(output not captured)"}`,
40026
40247
  }
40027
40248
  }
40028
40249
  turnCounterRef.current += 1;
40029
- if (turnCounterRef.current % 15 === 0 && ["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].some((name) => existsSync12(join56(process.cwd(), name))) && !kimiMdStale) {
40250
+ if (turnCounterRef.current % 15 === 0 && ["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].some((name) => existsSync12(join58(process.cwd(), name))) && !kimiMdStale) {
40030
40251
  setEvents((e) => [
40031
40252
  ...e,
40032
40253
  { kind: "info", key: mkKey(), text: "Tip: Rerunning /init occasionally helps autopilot (formerly kimiflare) stay accurate as your project evolves." }
@@ -40050,7 +40271,7 @@ ${result2.output ?? "(output not captured)"}`,
40050
40271
  };
40051
40272
  ensureSessionId();
40052
40273
  const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
40053
- const filePath = join56(sessionsDir3(), `${sessionIdRef.current}.json`);
40274
+ const filePath = join58(sessionsDir3(), `${sessionIdRef.current}.json`);
40054
40275
  await addCheckpoint(filePath, cp);
40055
40276
  }
40056
40277
  const summary = await generateContinuationSummary({
@@ -40201,24 +40422,16 @@ ${result2.output ?? "(output not captured)"}`,
40201
40422
  void getCostReport(sid).then((report) => setSessionUsage(report.session));
40202
40423
  },
40203
40424
  onResponseMeta: updateResponseMeta,
40204
- onTasks: (nextTasks) => {
40205
- const prevEmpty = tasksRef.current.length === 0;
40206
- const prevAllDone = tasksRef.current.length > 0 && tasksRef.current.every((t) => t.status === "completed");
40207
- tasksRef.current = nextTasks;
40208
- setTasks(nextTasks);
40209
- if ((prevEmpty || prevAllDone) && nextTasks.length > 0) {
40210
- setTasksStartedAt(Date.now());
40211
- setTasksStartTokens(usageRef.current?.prompt_tokens ?? 0);
40212
- }
40213
- if (nextTasks.length === 0) {
40214
- setTasksStartedAt(null);
40215
- setTasksStartTokens(0);
40216
- }
40217
- },
40425
+ onTasks: updateTaskTracking,
40218
40426
  onPlanOptions: (options) => {
40219
40427
  planOptionsRef.current = options;
40220
40428
  },
40221
40429
  askPermission: askForPermission,
40430
+ // Sandbox/memory warnings (e.g. Code Mode falling back to the plain
40431
+ // node:vm sandbox) were previously dropped on the floor in the TUI.
40432
+ onWarning: (msg) => {
40433
+ setEvents((e) => [...e, { kind: "info", key: mkKey(), text: msg }]);
40434
+ },
40222
40435
  onGuardrail: (ev) => {
40223
40436
  if (ev.kind === "loop_recovery" || ev.kind === "loop_stopped") return;
40224
40437
  setEvents((e) => [...e, { kind: "info", key: mkKey(), text: ev.message }]);
@@ -40381,7 +40594,7 @@ ${result2.output ?? "(output not captured)"}`,
40381
40594
  lspManagerRef.current.notifyChange(path, content2);
40382
40595
  } else {
40383
40596
  void import("fs/promises").then(
40384
- ({ readFile: readFile36 }) => readFile36(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
40597
+ ({ readFile: readFile38 }) => readFile38(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
40385
40598
  })
40386
40599
  );
40387
40600
  }
@@ -40574,7 +40787,7 @@ ${result2.output ?? "(output not captured)"}`,
40574
40787
  };
40575
40788
  ensureSessionId();
40576
40789
  const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
40577
- const filePath = join56(sessionsDir3(), `${sessionIdRef.current}.json`);
40790
+ const filePath = join58(sessionsDir3(), `${sessionIdRef.current}.json`);
40578
40791
  await addCheckpoint(filePath, cp);
40579
40792
  }
40580
40793
  const summary = await generateContinuationSummary({
@@ -40650,7 +40863,7 @@ ${result2.output ?? "(output not captured)"}`,
40650
40863
  }
40651
40864
  );
40652
40865
  },
40653
- [cfg, handleSlash, updateAssistant, updateTool, saveSessionSafe, updateResponseMeta, setShowPlanCompletePicker, runUserShellCommand, ensureTraceStarted]
40866
+ [cfg, handleSlash, updateAssistant, updateTool, saveSessionSafe, updateResponseMeta, setShowPlanCompletePicker, runUserShellCommand, ensureTraceStarted, updateTaskTracking]
40654
40867
  );
40655
40868
  useEffect11(() => {
40656
40869
  if (canDrainQueue({
@@ -41141,7 +41354,7 @@ ${result2.output ?? "(output not captured)"}`,
41141
41354
  lsp: {
41142
41355
  servers: cfg?.lspServers ?? {},
41143
41356
  scope: lspScope,
41144
- hasProjectDir: existsSync12(join56(process.cwd(), ".kimiflare"))
41357
+ hasProjectDir: existsSync12(join58(process.cwd(), ".kimiflare"))
41145
41358
  }
41146
41359
  });
41147
41360
  });
@@ -41198,7 +41411,7 @@ ${result2.output ?? "(output not captured)"}`,
41198
41411
  onCommandDelete: handleCommandDelete2,
41199
41412
  lspServers: cfg?.lspServers ?? {},
41200
41413
  lspScope,
41201
- hasProjectDir: existsSync12(join56(process.cwd(), ".kimiflare")),
41414
+ hasProjectDir: existsSync12(join58(process.cwd(), ".kimiflare")),
41202
41415
  onLspSave: handleLspSave2,
41203
41416
  themes: themeList(),
41204
41417
  onPickTheme: handleThemePick,
@@ -41685,11 +41898,11 @@ init_classify();
41685
41898
  init_subagent_policy();
41686
41899
  init_trace();
41687
41900
  init_registry2();
41688
- import { readFile as readFile15 } from "fs/promises";
41689
- import { resolve as resolve6, basename as basename3 } from "path";
41901
+ import { readFile as readFile17 } from "fs/promises";
41902
+ import { resolve as resolve7, basename as basename4 } from "path";
41690
41903
  async function resolveSession(opts2) {
41691
41904
  if (opts2.sessionId) {
41692
- const filePath = resolve6(sessionsDir(), `${opts2.sessionId}.json`);
41905
+ const filePath = resolve7(sessionsDir(), `${opts2.sessionId}.json`);
41693
41906
  try {
41694
41907
  const file = await loadSession(filePath);
41695
41908
  return { sessionFile: file, isNew: false };
@@ -41697,7 +41910,7 @@ async function resolveSession(opts2) {
41697
41910
  }
41698
41911
  }
41699
41912
  if (opts2.continueSession) {
41700
- const cwd = opts2.dir ? resolve6(opts2.dir) : process.cwd();
41913
+ const cwd = opts2.dir ? resolve7(opts2.dir) : process.cwd();
41701
41914
  const sessions = await listSessions(1, cwd);
41702
41915
  if (sessions.length > 0) {
41703
41916
  const filePath = sessions[0].filePath;
@@ -41710,7 +41923,7 @@ async function resolveSession(opts2) {
41710
41923
  return {
41711
41924
  sessionFile: {
41712
41925
  id,
41713
- cwd: opts2.dir ? resolve6(opts2.dir) : process.cwd(),
41926
+ cwd: opts2.dir ? resolve7(opts2.dir) : process.cwd(),
41714
41927
  model: opts2.model,
41715
41928
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
41716
41929
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -41724,9 +41937,9 @@ async function resolveFiles(filePatterns, cwd) {
41724
41937
  const resolved = /* @__PURE__ */ new Set();
41725
41938
  for (const pattern of filePatterns) {
41726
41939
  try {
41727
- const stat13 = await import("fs/promises").then((m) => m.stat(resolve6(cwd, pattern)));
41728
- if (stat13.isFile()) {
41729
- resolved.add(resolve6(cwd, pattern));
41940
+ const stat15 = await import("fs/promises").then((m) => m.stat(resolve7(cwd, pattern)));
41941
+ if (stat15.isFile()) {
41942
+ resolved.add(resolve7(cwd, pattern));
41730
41943
  continue;
41731
41944
  }
41732
41945
  } catch {
@@ -41749,12 +41962,12 @@ async function buildUserMessage(prompt, files, cwd) {
41749
41962
  imageParts.push({ type: "image_url", image_url: { url: img.dataUrl } });
41750
41963
  } catch (e) {
41751
41964
  fileContents.push(`
41752
- <!-- failed to attach image ${basename3(filePath)}: ${e.message} -->
41965
+ <!-- failed to attach image ${basename4(filePath)}: ${e.message} -->
41753
41966
  `);
41754
41967
  }
41755
41968
  } else {
41756
41969
  try {
41757
- const content = await readFile15(filePath, "utf8");
41970
+ const content = await readFile17(filePath, "utf8");
41758
41971
  const relPath = filePath.startsWith(cwd) ? filePath.slice(cwd.length + 1) : filePath;
41759
41972
  fileContents.push(`
41760
41973
  --- ${relPath} ---
@@ -41763,7 +41976,7 @@ ${content}
41763
41976
  `);
41764
41977
  } catch (e) {
41765
41978
  fileContents.push(`
41766
- <!-- failed to read ${basename3(filePath)}: ${e.message} -->
41979
+ <!-- failed to read ${basename4(filePath)}: ${e.message} -->
41767
41980
  `);
41768
41981
  }
41769
41982
  }
@@ -41789,7 +42002,7 @@ async function runPrintMode(opts2) {
41789
42002
  `
41790
42003
  );
41791
42004
  }
41792
- const cwd = opts2.dir ? resolve6(opts2.dir) : process.cwd();
42005
+ const cwd = opts2.dir ? resolve7(opts2.dir) : process.cwd();
41793
42006
  const baseWorkerTools = getWorkerTools(opts2.workerProfile);
41794
42007
  const { HooksManager: HooksManager2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports));
41795
42008
  const hooks = new HooksManager2(cwd);
@@ -42469,11 +42682,11 @@ async function promptHidden(question) {
42469
42682
  }
42470
42683
  });
42471
42684
  const rl = createInterface4({ input: process.stdin, output, terminal: true });
42472
- return new Promise((resolve19) => {
42685
+ return new Promise((resolve20) => {
42473
42686
  rl.question(question, (answer) => {
42474
42687
  rl.close();
42475
42688
  process.stdout.write("\n");
42476
- resolve19(answer);
42689
+ resolve20(answer);
42477
42690
  });
42478
42691
  muted = true;
42479
42692
  });