autopilot-ai 1.10.0 → 1.10.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
@@ -20920,11 +20920,179 @@ var init_app_helpers = __esm({
20920
20920
  }
20921
20921
  });
20922
20922
 
20923
- // src/remote/deploy-commute.ts
20923
+ // src/ui/bang-command.ts
20924
20924
  import { spawn as spawn7 } from "child_process";
20925
- import { mkdtemp, readFile as readFile22, writeFile as writeFile13, rm as rm2 } from "fs/promises";
20926
- import { tmpdir as tmpdir3 } from "os";
20925
+ import { mkdtemp, readFile as readFile22, rm as rm2 } from "fs/promises";
20926
+ import { tmpdir as tmpdir3, platform as platform4 } from "os";
20927
20927
  import { join as join33 } from "path";
20928
+ function registerInkInstance(instance) {
20929
+ inkInstance = instance;
20930
+ }
20931
+ function registerTerminalHandoff(h) {
20932
+ terminalHandoff = h;
20933
+ }
20934
+ function runCaptured(inv, cwd) {
20935
+ return new Promise((resolve15) => {
20936
+ const child = spawn7(inv.file, inv.args, { cwd, stdio: ["ignore", "pipe", "pipe"], env: inv.env ?? process.env });
20937
+ let output = "";
20938
+ child.stdout?.on("data", (c) => output += c.toString("utf8"));
20939
+ child.stderr?.on("data", (c) => output += c.toString("utf8"));
20940
+ child.once("error", (e) => resolve15({ code: 127, signal: null, output: `failed to start: ${e.message}` }));
20941
+ child.once("exit", (code, signal) => resolve15({ code, signal, output }));
20942
+ });
20943
+ }
20944
+ function isTerminalHandedOff() {
20945
+ return handedOff;
20946
+ }
20947
+ function parseBangCommand(input) {
20948
+ const t = input.trimStart();
20949
+ if (!t.startsWith("!")) return null;
20950
+ return t.slice(1).trim();
20951
+ }
20952
+ function scriptInvocation(command, shell, logPath, plat = platform4()) {
20953
+ if (plat === "darwin" || plat === "freebsd" || plat === "openbsd" || plat === "netbsd") {
20954
+ return { file: "script", args: ["-q", logPath, shell, "-c", command] };
20955
+ }
20956
+ if (plat === "linux") {
20957
+ return { file: "script", args: ["-q", "-e", "-c", command, logPath], env: { ...process.env, SHELL: shell } };
20958
+ }
20959
+ return null;
20960
+ }
20961
+ function cleanTerminalOutput(raw) {
20962
+ const text = raw.replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g, "").replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, "").replace(/\x1b[@-Z\\-_]/g, "").replace(/^Script (?:started|done) on .*$/gm, "");
20963
+ const lines = text.split(/\r?\n/).map((line) => {
20964
+ const segs = line.split("\r");
20965
+ let out = segs[segs.length - 1] ?? "";
20966
+ if (!out && segs.length > 1) out = segs.filter(Boolean).pop() ?? "";
20967
+ while (/[^\x08]\x08/.test(out)) out = out.replace(/[^\x08]\x08/, "");
20968
+ return out.replace(/[\x00-\x08\x0b-\x1f\x7f]/g, "");
20969
+ });
20970
+ return lines.join("\n").replace(/\n{3,}/g, "\n\n").trim();
20971
+ }
20972
+ function truncateMiddle2(text, max = MAX_CONTEXT_CHARS) {
20973
+ if (text.length <= max) return text;
20974
+ const half = Math.floor(max / 2);
20975
+ return `${text.slice(0, half)}
20976
+
20977
+ [\u2026 ${text.length - max} chars omitted \u2026]
20978
+
20979
+ ${text.slice(-half)}`;
20980
+ }
20981
+ function formatBangContext(r) {
20982
+ const status = r.signal ? `killed by ${r.signal}` : `exit code ${r.exitCode ?? "?"}`;
20983
+ const body = r.output === null ? "(output was shown in the user's terminal but could not be captured)" : r.output ? truncateMiddle2(r.output) : "(no output)";
20984
+ return `[The user ran this shell command themselves with \`!\` in the autopilot prompt. This is context for you, not a new request.]
20985
+ $ ${r.command}
20986
+ (${status})
20987
+ ${body}`;
20988
+ }
20989
+ function stopReading(stdin) {
20990
+ stdin.pause();
20991
+ const stream = stdin;
20992
+ try {
20993
+ if (stream._handle?.reading && stream._handle.readStop) {
20994
+ stream._handle.readStop();
20995
+ stream._handle.reading = false;
20996
+ if (stream._readableState) stream._readableState.reading = false;
20997
+ }
20998
+ } catch {
20999
+ }
21000
+ }
21001
+ function swallow() {
21002
+ return ((_chunk, encOrCb, cb) => {
21003
+ const done = typeof encOrCb === "function" ? encOrCb : cb;
21004
+ if (typeof done === "function") done();
21005
+ return true;
21006
+ });
21007
+ }
21008
+ function spawnInherit(inv, cwd) {
21009
+ return new Promise((resolve15, reject) => {
21010
+ const child = spawn7(inv.file, inv.args, { cwd, stdio: "inherit", env: inv.env ?? process.env });
21011
+ child.once("error", reject);
21012
+ child.once("exit", (code, signal) => resolve15({ code, signal }));
21013
+ });
21014
+ }
21015
+ async function runBangCommand(command, cwd) {
21016
+ const isWindows = platform4() === "win32";
21017
+ const shell = isWindows ? process.env.COMSPEC || "cmd.exe" : process.env.SHELL || "/bin/sh";
21018
+ const direct = isWindows ? { file: shell, args: ["/c", command] } : { file: shell, args: ["-c", command] };
21019
+ if (terminalHandoff && !await terminalHandoff.suspend()) {
21020
+ const r = await runCaptured(direct, cwd);
21021
+ return { command, exitCode: r.code, signal: r.signal, output: cleanTerminalOutput(r.output) };
21022
+ }
21023
+ const stdin = process.stdin;
21024
+ const stdout = process.stdout;
21025
+ const stderr = process.stderr;
21026
+ const origOut = stdout.write;
21027
+ const origErr = stderr.write;
21028
+ const readable = stdin.listeners("readable");
21029
+ const wasRaw = stdin.isTTY ? stdin.isRaw : false;
21030
+ const logDir2 = isWindows ? null : await mkdtemp(join33(tmpdir3(), "autopilot-bang-"));
21031
+ const logPath = logDir2 ? join33(logDir2, "out.log") : null;
21032
+ const viaScript = logPath ? scriptInvocation(command, shell, logPath) : null;
21033
+ inkInstance?.clear();
21034
+ origOut.call(stdout, `
21035
+ $ ${command}
21036
+ `);
21037
+ stdout.write = swallow();
21038
+ stderr.write = swallow();
21039
+ for (const l of readable) stdin.removeListener("readable", l);
21040
+ if (stdin.isTTY) stdin.setRawMode(false);
21041
+ stopReading(stdin);
21042
+ handedOff = true;
21043
+ let result2;
21044
+ let captured = false;
21045
+ let spawnError = null;
21046
+ try {
21047
+ if (viaScript) {
21048
+ try {
21049
+ result2 = await spawnInherit(viaScript, cwd);
21050
+ captured = true;
21051
+ } catch (e) {
21052
+ logger.warn("bang:script_unavailable", { error: e.message });
21053
+ result2 = await spawnInherit(direct, cwd);
21054
+ }
21055
+ } else {
21056
+ result2 = await spawnInherit(direct, cwd);
21057
+ }
21058
+ } catch (e) {
21059
+ result2 = { code: 127, signal: null };
21060
+ spawnError = e.message;
21061
+ logger.warn("bang:spawn_failed", { error: spawnError });
21062
+ } finally {
21063
+ handedOff = false;
21064
+ stdout.write = origOut;
21065
+ stderr.write = origErr;
21066
+ if (stdin.isTTY) stdin.setRawMode(wasRaw);
21067
+ for (const l of readable) stdin.addListener("readable", l);
21068
+ origOut.call(stdout, "\n");
21069
+ terminalHandoff?.resume();
21070
+ }
21071
+ let output = spawnError ? `failed to start: ${spawnError}` : null;
21072
+ if (captured && logPath) {
21073
+ output = cleanTerminalOutput(await readFile22(logPath, "utf8").catch(() => ""));
21074
+ }
21075
+ if (logDir2) await rm2(logDir2, { recursive: true, force: true }).catch(() => {
21076
+ });
21077
+ return { command, exitCode: result2.code, signal: result2.signal, output };
21078
+ }
21079
+ var inkInstance, handedOff, terminalHandoff, MAX_CONTEXT_CHARS;
21080
+ var init_bang_command = __esm({
21081
+ "src/ui/bang-command.ts"() {
21082
+ "use strict";
21083
+ init_logger();
21084
+ inkInstance = null;
21085
+ handedOff = false;
21086
+ terminalHandoff = null;
21087
+ MAX_CONTEXT_CHARS = 16e3;
21088
+ }
21089
+ });
21090
+
21091
+ // src/remote/deploy-commute.ts
21092
+ import { spawn as spawn8 } from "child_process";
21093
+ import { mkdtemp as mkdtemp2, readFile as readFile23, writeFile as writeFile13, rm as rm3 } from "fs/promises";
21094
+ import { tmpdir as tmpdir4 } from "os";
21095
+ import { join as join34 } from "path";
20928
21096
  import { randomBytes as randomBytes3 } from "crypto";
20929
21097
  async function cfApiFetch(accountId, apiToken, path, init) {
20930
21098
  const url = `${CF_API}/accounts/${encodeURIComponent(accountId)}${path}`;
@@ -20995,7 +21163,7 @@ function generateSecret2() {
20995
21163
  }
20996
21164
  function runCmd(cmd, args, opts2 = {}) {
20997
21165
  return new Promise((resolve15) => {
20998
- const child = spawn7(cmd, args, {
21166
+ const child = spawn8(cmd, args, {
20999
21167
  cwd: opts2.cwd,
21000
21168
  env: { ...process.env, ...opts2.env ?? {} },
21001
21169
  stdio: [opts2.input ? "pipe" : "ignore", "pipe", "pipe"]
@@ -21155,8 +21323,8 @@ ${wranglerInstall.stderr.slice(-600)}`,
21155
21323
  ok: true
21156
21324
  };
21157
21325
  yield { message: "Prerequisites ready", ok: true };
21158
- const tmpRoot = await mkdtemp(join33(tmpdir3(), "kimiflare-commute-"));
21159
- const repoDir = join33(tmpRoot, "kimiflare-commute");
21326
+ const tmpRoot = await mkdtemp2(join34(tmpdir4(), "kimiflare-commute-"));
21327
+ const repoDir = join34(tmpRoot, "kimiflare-commute");
21160
21328
  yield { message: `Fetching worker source from GitHub (${COMMUTE_REPO})\u2026` };
21161
21329
  const clone = await runCmd("git", ["clone", "--depth", "1", "--branch", COMMUTE_BRANCH, COMMUTE_REPO, repoDir], { timeoutMs: 6e4 });
21162
21330
  if (clone.code !== 0) {
@@ -21165,8 +21333,8 @@ ${(clone.stderr || clone.stdout).slice(0, 400)}`, error: true };
21165
21333
  throw new Error("clone failed");
21166
21334
  }
21167
21335
  yield { message: "Source fetched from GitHub", ok: true };
21168
- const workerDir = join33(repoDir, "remote", "worker");
21169
- const wranglerToml = join33(workerDir, "wrangler.toml");
21336
+ const workerDir = join34(repoDir, "remote", "worker");
21337
+ const wranglerToml = join34(workerDir, "wrangler.toml");
21170
21338
  yield { message: "Installing Worker dependencies (npm install)\u2026" };
21171
21339
  const install = await runCmd("npm", ["install", "--no-audit", "--no-fund", "--loglevel=error"], {
21172
21340
  cwd: workerDir,
@@ -21255,7 +21423,7 @@ ${(install.stderr || install.stdout).slice(-1200).trim()}`,
21255
21423
  ok: true
21256
21424
  };
21257
21425
  yield { message: "Patching wrangler.toml\u2026" };
21258
- let toml = await readFile22(wranglerToml, "utf8");
21426
+ let toml = await readFile23(wranglerToml, "utf8");
21259
21427
  toml = toml.replace(/^name\s*=\s*"[^"]+"/m, `name = "${workerName}"`);
21260
21428
  toml = toml.replace(
21261
21429
  /(\[\[kv_namespaces\]\][\s\S]*?binding\s*=\s*"OAUTH_KV"[\s\S]*?id\s*=\s*")[^"]+(")/,
@@ -21339,7 +21507,7 @@ invocation_logs = true
21339
21507
  };
21340
21508
  await saveConfig(next);
21341
21509
  yield { message: "Saved to ~/.config/kimiflare/config.json", ok: true };
21342
- await rm2(tmpRoot, { recursive: true, force: true }).catch(() => {
21510
+ await rm3(tmpRoot, { recursive: true, force: true }).catch(() => {
21343
21511
  });
21344
21512
  yield { message: "Setup complete \u2014 multi-agent is ready to use.", done: true };
21345
21513
  return { workerEndpoint: workerUrl, workerApiKey };
@@ -22593,7 +22761,7 @@ var init_text_input = __esm({
22593
22761
  import { useState as useState5 } from "react";
22594
22762
  import { Box as Box5, Text as Text5 } from "ink";
22595
22763
  import SelectInput3 from "ink-select-input";
22596
- import { spawn as spawn8 } from "child_process";
22764
+ import { spawn as spawn9 } from "child_process";
22597
22765
  import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
22598
22766
  function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
22599
22767
  const theme = useTheme();
@@ -22607,7 +22775,7 @@ function LspWizard({ servers, currentScope, hasProjectDir, onDone, onSave }) {
22607
22775
  const runInstall = (command) => {
22608
22776
  setInstallState({ status: "running", output: "Installing..." });
22609
22777
  const { shell, args } = getShellCommand();
22610
- const child = spawn8(shell, [...args, command], {
22778
+ const child = spawn9(shell, [...args, command], {
22611
22779
  env: process.env
22612
22780
  });
22613
22781
  let stdout = "";
@@ -23115,7 +23283,7 @@ var init_lsp_wizard = __esm({
23115
23283
  });
23116
23284
 
23117
23285
  // src/hooks/recommended.ts
23118
- import { platform as platform4 } from "os";
23286
+ import { platform as platform5 } from "os";
23119
23287
  function getRecommendedHook(id) {
23120
23288
  return RECOMMENDED_HOOKS.find((r) => r.id === id);
23121
23289
  }
@@ -23123,7 +23291,7 @@ var isMac, RECOMMENDED_HOOKS;
23123
23291
  var init_recommended = __esm({
23124
23292
  "src/hooks/recommended.ts"() {
23125
23293
  "use strict";
23126
- isMac = platform4() === "darwin";
23294
+ isMac = platform5() === "darwin";
23127
23295
  RECOMMENDED_HOOKS = [
23128
23296
  // ── Stop notifications ───────────────────────────────────────────────
23129
23297
  {
@@ -23599,10 +23767,10 @@ __export(camouflage_view_exports, {
23599
23767
  toolSummary: () => toolSummary,
23600
23768
  validateCommandName: () => validateCommandName
23601
23769
  });
23602
- import { execFileSync as execFileSync3, spawn as spawn9 } from "child_process";
23770
+ import { execFileSync as execFileSync3, spawn as spawn10 } from "child_process";
23603
23771
  import { readdir as readdir6 } from "fs/promises";
23604
23772
  import { homedir as homedir23 } from "os";
23605
- import { join as join34, resolve as resolve12 } from "path";
23773
+ import { join as join35, resolve as resolve12 } from "path";
23606
23774
  async function loadSdk() {
23607
23775
  const sdk = await import("camouflage-tui").catch((err) => {
23608
23776
  throw new CamouflageUnavailable(`camouflage-tui is not installed (${err.message})`);
@@ -23643,6 +23811,10 @@ async function runCamouflageView(opts2) {
23643
23811
  cam.send("MentionCandidatesRegistered", { candidates: files.map((token) => ({ token, kind: "file" })) });
23644
23812
  }
23645
23813
  const view = new View(cam, sdk);
23814
+ registerTerminalHandoff({
23815
+ suspend: async () => sdk.suspendTerminal ? (await sdk.suspendTerminal(cam)).supported : false,
23816
+ resume: () => sdk.resumeTerminal?.(cam)
23817
+ });
23646
23818
  cam.on("userInput", (text) => {
23647
23819
  view.echoed.push(text.trim());
23648
23820
  view.actions?.submit(text);
@@ -23663,6 +23835,7 @@ async function runCamouflageView(opts2) {
23663
23835
  const finish = async () => {
23664
23836
  if (closing) return;
23665
23837
  closing = true;
23838
+ registerTerminalHandoff(null);
23666
23839
  await cam.close().catch(() => void 0);
23667
23840
  restoreConsole();
23668
23841
  };
@@ -23682,7 +23855,7 @@ async function runCamouflageView(opts2) {
23682
23855
  function runShell(command) {
23683
23856
  return new Promise((resolve15) => {
23684
23857
  const { shell, args } = getShellCommand();
23685
- const child = spawn9(shell, [...args, command], { env: process.env });
23858
+ const child = spawn10(shell, [...args, command], { env: process.env });
23686
23859
  let out = "";
23687
23860
  child.stdout?.on("data", (c) => out += c.toString("utf8"));
23688
23861
  child.stderr?.on("data", (c) => out += c.toString("utf8"));
@@ -23738,7 +23911,7 @@ function truncateText(s, max) {
23738
23911
  async function listMentionDir(cwd, query) {
23739
23912
  const exact = query === "~" || query === "." || query === ".." || query.endsWith("/..");
23740
23913
  const dir = exact ? `${query}/` : query.slice(0, query.lastIndexOf("/") + 1);
23741
- const expanded = dir.startsWith("~") ? join34(homedir23(), dir.slice(1)) : dir;
23914
+ const expanded = dir.startsWith("~") ? join35(homedir23(), dir.slice(1)) : dir;
23742
23915
  const target = resolve12(cwd, expanded || ".");
23743
23916
  try {
23744
23917
  const items = await readdir6(target, { withFileTypes: true });
@@ -23870,6 +24043,7 @@ var init_camouflage_view = __esm({
23870
24043
  init_model_picker();
23871
24044
  init_help_menu();
23872
24045
  init_app_helpers();
24046
+ init_bang_command();
23873
24047
  init_deploy_commute();
23874
24048
  init_remote_dashboard();
23875
24049
  init_worker_client();
@@ -26449,7 +26623,7 @@ var init_status = __esm({
26449
26623
  // src/ui/permission.tsx
26450
26624
  import { useState as useState9, useCallback } from "react";
26451
26625
  import { Box as Box13, Text as Text14, useInput as useInput6 } from "ink";
26452
- import { platform as platform5 } from "os";
26626
+ import { platform as platform6 } from "os";
26453
26627
  import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
26454
26628
  function formatSelection(label, shortcut) {
26455
26629
  return `${label} [${MOD_KEY}+${shortcut}]`;
@@ -26613,7 +26787,7 @@ var init_permission = __esm({
26613
26787
  { value: { decision: "deny", scope: "once" }, label: "Something else", key: 3 }
26614
26788
  ];
26615
26789
  DENY = { decision: "deny", scope: "once" };
26616
- MOD_KEY = platform5() === "darwin" ? "\u2325" : "Alt";
26790
+ MOD_KEY = platform6() === "darwin" ? "\u2325" : "Alt";
26617
26791
  }
26618
26792
  });
26619
26793
 
@@ -27812,13 +27986,13 @@ var init_frontmatter = __esm({
27812
27986
  // src/commands/loader.ts
27813
27987
  import { open, realpath as realpath6 } from "fs/promises";
27814
27988
  import { homedir as homedir24 } from "os";
27815
- import { join as join35, relative as relative10, sep as sep6 } from "path";
27989
+ import { join as join36, relative as relative10, sep as sep6 } from "path";
27816
27990
  function projectCommandsDir(cwd = process.cwd()) {
27817
- return join35(cwd, ".kimiflare", "commands");
27991
+ return join36(cwd, ".kimiflare", "commands");
27818
27992
  }
27819
27993
  function globalCommandsDir() {
27820
- const xdg = process.env.XDG_CONFIG_HOME || join35(homedir24(), ".config");
27821
- return join35(xdg, "kimiflare", "commands");
27994
+ const xdg = process.env.XDG_CONFIG_HOME || join36(homedir24(), ".config");
27995
+ return join36(xdg, "kimiflare", "commands");
27822
27996
  }
27823
27997
  async function loadCustomCommands(cwd = process.cwd()) {
27824
27998
  const warnings = [];
@@ -29026,11 +29200,11 @@ var init_wcag = __esm({
29026
29200
  });
29027
29201
 
29028
29202
  // src/ui/theme-loader.ts
29029
- import { readFile as readFile23, readdir as readdir7 } from "fs/promises";
29030
- import { join as join36 } from "path";
29203
+ import { readFile as readFile24, readdir as readdir7 } from "fs/promises";
29204
+ import { join as join37 } from "path";
29031
29205
  import { homedir as homedir25 } from "os";
29032
29206
  function projectThemesDir(cwd = process.cwd()) {
29033
- return join36(cwd, ".kimiflare", "themes");
29207
+ return join37(cwd, ".kimiflare", "themes");
29034
29208
  }
29035
29209
  function isHexColor(c) {
29036
29210
  return /^#[0-9a-fA-F]{6}$/.test(c);
@@ -29119,10 +29293,10 @@ async function loadThemesFromDir(dir, source) {
29119
29293
  return { themes, errors };
29120
29294
  }
29121
29295
  for (const file of files.filter((f) => f.endsWith(".json"))) {
29122
- const path = join36(dir, file);
29296
+ const path = join37(dir, file);
29123
29297
  let raw;
29124
29298
  try {
29125
- raw = await readFile23(path, "utf-8");
29299
+ raw = await readFile24(path, "utf-8");
29126
29300
  } catch (e) {
29127
29301
  errors.push(`${path}: ${e instanceof Error ? e.message : String(e)}`);
29128
29302
  continue;
@@ -29268,8 +29442,8 @@ var init_theme_loader = __esm({
29268
29442
  "use strict";
29269
29443
  init_wcag();
29270
29444
  init_theme();
29271
- USER_THEMES_DIR = join36(
29272
- process.env.XDG_CONFIG_HOME || join36(homedir25(), ".config"),
29445
+ USER_THEMES_DIR = join37(
29446
+ process.env.XDG_CONFIG_HOME || join37(homedir25(), ".config"),
29273
29447
  "kimiflare",
29274
29448
  "themes"
29275
29449
  );
@@ -32388,8 +32562,8 @@ var init_input_handlers = __esm({
32388
32562
 
32389
32563
  // src/agent/jev-context.ts
32390
32564
  import { execFileSync as execFileSync4 } from "child_process";
32391
- import { readFile as readFile24 } from "fs/promises";
32392
- import { basename as basename6, join as join37, resolve as resolve13 } from "path";
32565
+ import { readFile as readFile25 } from "fs/promises";
32566
+ import { basename as basename6, join as join38, resolve as resolve13 } from "path";
32393
32567
  function messageText(message2) {
32394
32568
  if (typeof message2.content === "string") return message2.content.trim();
32395
32569
  if (!Array.isArray(message2.content)) return "";
@@ -32411,7 +32585,7 @@ function projectRoot(cwd) {
32411
32585
  }
32412
32586
  async function readPackageMetadata(root) {
32413
32587
  try {
32414
- const parsed = JSON.parse(await readFile24(join37(root, "package.json"), "utf8"));
32588
+ const parsed = JSON.parse(await readFile25(join38(root, "package.json"), "utf8"));
32415
32589
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
32416
32590
  const pkg = parsed;
32417
32591
  const metadata = {};
@@ -32428,7 +32602,7 @@ async function readPackageMetadata(root) {
32428
32602
  async function readLicenseEvidence(root) {
32429
32603
  for (const name of ["LICENSE", "LICENSE.md", "LICENSE.txt", "LICENCE", "COPYING"]) {
32430
32604
  try {
32431
- const content = (await readFile24(join37(root, name), "utf8")).trim();
32605
+ const content = (await readFile25(join38(root, name), "utf8")).trim();
32432
32606
  if (content) return { source: `project license (${name})`, content: content.slice(0, 700) };
32433
32607
  } catch {
32434
32608
  }
@@ -32437,7 +32611,7 @@ async function readLicenseEvidence(root) {
32437
32611
  }
32438
32612
  async function buildJevContext(question, messages, cwd = process.cwd()) {
32439
32613
  const entries = [];
32440
- let remaining = MAX_CONTEXT_CHARS;
32614
+ let remaining = MAX_CONTEXT_CHARS2;
32441
32615
  const add = (source, content, limit = remaining) => {
32442
32616
  if (remaining <= 0 || !content.trim()) return;
32443
32617
  const sourceText = source.slice(0, 160);
@@ -32504,11 +32678,11 @@ function formatJevContextReceipt(entries, includeContent = false) {
32504
32678
  "Chat/project context is reference data, not verified fact."
32505
32679
  ].join("\n");
32506
32680
  }
32507
- var MAX_CONTEXT_CHARS, MAX_CONVERSATION_CHARS, CURRENT_PROJECT_REFERENCE, LICENSE_QUESTION, CONVERSATION_REFERENCE, SECRET_PATTERNS3;
32681
+ var MAX_CONTEXT_CHARS2, MAX_CONVERSATION_CHARS, CURRENT_PROJECT_REFERENCE, LICENSE_QUESTION, CONVERSATION_REFERENCE, SECRET_PATTERNS3;
32508
32682
  var init_jev_context = __esm({
32509
32683
  "src/agent/jev-context.ts"() {
32510
32684
  "use strict";
32511
- MAX_CONTEXT_CHARS = 6e3;
32685
+ MAX_CONTEXT_CHARS2 = 6e3;
32512
32686
  MAX_CONVERSATION_CHARS = 4e3;
32513
32687
  CURRENT_PROJECT_REFERENCE = /\b(?:this|that|our|current|local|working)\s+(?:repo(?:sitory)?|project|workspace|codebase|harness)\b/i;
32514
32688
  LICENSE_QUESTION = /\bopen[\s-]?source\b|\blicen[cs](?:e|ed|ing)?\b|\bspdx\b|\bcopyleft\b/i;
@@ -32684,8 +32858,8 @@ var init_frontmatter2 = __esm({
32684
32858
  });
32685
32859
 
32686
32860
  // src/skills/loader.ts
32687
- import { readFile as readFile25, readdir as readdir8, stat as stat8 } from "fs/promises";
32688
- import { join as join38, extname } from "path";
32861
+ import { readFile as readFile26, readdir as readdir8, stat as stat8 } from "fs/promises";
32862
+ import { join as join39, extname } from "path";
32689
32863
  function normalizeManifest(raw, filePath) {
32690
32864
  const name = typeof raw.name === "string" ? raw.name : "";
32691
32865
  const description = typeof raw.description === "string" ? raw.description : "";
@@ -32699,7 +32873,7 @@ function normalizeManifest(raw, filePath) {
32699
32873
  return { name, description, match, scope, priority, enabled: enabled2 };
32700
32874
  }
32701
32875
  async function loadSkillFile(filePath) {
32702
- const raw = await readFile25(filePath, "utf-8");
32876
+ const raw = await readFile26(filePath, "utf-8");
32703
32877
  const parsed = parseFrontmatter2(raw);
32704
32878
  const manifest = normalizeManifest(parsed.data, filePath);
32705
32879
  const body = parsed.content.trim();
@@ -32721,7 +32895,7 @@ async function loadSkillsFromDir(dirPath) {
32721
32895
  const entries = await readdir8(dirPath);
32722
32896
  const files = [];
32723
32897
  for (const entry of entries) {
32724
- const full = join38(dirPath, entry);
32898
+ const full = join39(dirPath, entry);
32725
32899
  const s = await stat8(full);
32726
32900
  if (s.isFile() && extname(entry) === ".md") {
32727
32901
  files.push(full);
@@ -32749,12 +32923,12 @@ var init_loader2 = __esm({
32749
32923
  });
32750
32924
 
32751
32925
  // src/skills/manager.ts
32752
- import { mkdir as mkdir13, writeFile as writeFile14, unlink as unlink4, readFile as readFile26 } from "fs/promises";
32753
- import { join as join39 } from "path";
32926
+ import { mkdir as mkdir13, writeFile as writeFile14, unlink as unlink4, readFile as readFile27 } from "fs/promises";
32927
+ import { join as join40 } from "path";
32754
32928
  function getSkillDirs(cwd) {
32755
32929
  return {
32756
- projectDir: join39(cwd, ".kimiflare", "skills"),
32757
- globalDir: join39(process.env.HOME ?? "", ".config", "kimiflare", "skills")
32930
+ projectDir: join40(cwd, ".kimiflare", "skills"),
32931
+ globalDir: join40(process.env.HOME ?? "", ".config", "kimiflare", "skills")
32758
32932
  };
32759
32933
  }
32760
32934
  async function listAllSkills(cwd) {
@@ -32768,7 +32942,7 @@ async function listAllSkills(cwd) {
32768
32942
  async function createSkill(opts2) {
32769
32943
  const dirs = getSkillDirs(opts2.cwd);
32770
32944
  const dir = opts2.scope === "project" ? dirs.projectDir : dirs.globalDir;
32771
- const filepath = join39(dir, `${opts2.name}.md`);
32945
+ const filepath = join40(dir, `${opts2.name}.md`);
32772
32946
  const frontmatter = {
32773
32947
  name: opts2.name,
32774
32948
  enabled: true,
@@ -32804,7 +32978,7 @@ async function setSkillEnabled(name, enabled2, cwd) {
32804
32978
  const all = await listAllSkills(cwd);
32805
32979
  const skill = all.project.find((s) => s.name === name) ?? all.global.find((s) => s.name === name);
32806
32980
  if (!skill) throw new Error(`skill "${name}" not found`);
32807
- const raw = await readFile26(skill.filePath, "utf-8");
32981
+ const raw = await readFile27(skill.filePath, "utf-8");
32808
32982
  const parsed = parseFrontmatter2(raw);
32809
32983
  parsed.data.enabled = enabled2;
32810
32984
  const yaml = Object.entries(parsed.data).map(([k, v]) => {
@@ -32860,9 +33034,9 @@ var init_plan_resolver = __esm({
32860
33034
 
32861
33035
  // src/util/clipboard.ts
32862
33036
  import { execSync as execSync5 } from "child_process";
32863
- import { platform as platform6 } from "os";
33037
+ import { platform as platform7 } from "os";
32864
33038
  function writeToClipboard(text) {
32865
- const os2 = platform6();
33039
+ const os2 = platform7();
32866
33040
  try {
32867
33041
  if (os2 === "darwin") {
32868
33042
  execSync5("pbcopy", { input: text, timeout: 5e3 });
@@ -32897,15 +33071,15 @@ var tui_report_exports = {};
32897
33071
  __export(tui_report_exports, {
32898
33072
  getCategoryReportText: () => getCategoryReportText
32899
33073
  });
32900
- import { readFile as readFile27 } from "fs/promises";
32901
- import { join as join40 } from "path";
33074
+ import { readFile as readFile28 } from "fs/promises";
33075
+ import { join as join41 } from "path";
32902
33076
  import { homedir as homedir26 } from "os";
32903
33077
  function usageDir3() {
32904
- const xdg = process.env.XDG_DATA_HOME || join40(homedir26(), ".local", "share");
32905
- return join40(xdg, "kimiflare");
33078
+ const xdg = process.env.XDG_DATA_HOME || join41(homedir26(), ".local", "share");
33079
+ return join41(xdg, "kimiflare");
32906
33080
  }
32907
33081
  function usagePath4() {
32908
- return join40(usageDir3(), "usage.json");
33082
+ return join41(usageDir3(), "usage.json");
32909
33083
  }
32910
33084
  function today3() {
32911
33085
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -32917,7 +33091,7 @@ function daysAgo2(n) {
32917
33091
  }
32918
33092
  async function loadLog3() {
32919
33093
  try {
32920
- const raw = await readFile27(usagePath4(), "utf8");
33094
+ const raw = await readFile28(usagePath4(), "utf8");
32921
33095
  return JSON.parse(raw);
32922
33096
  } catch {
32923
33097
  return { version: 1, days: [], sessions: [] };
@@ -32974,7 +33148,7 @@ var init_tui_report = __esm({
32974
33148
  });
32975
33149
 
32976
33150
  // src/ui/slash-commands.ts
32977
- import { join as join41 } from "path";
33151
+ import { join as join42 } from "path";
32978
33152
  import QRCode from "qrcode";
32979
33153
  function executeFreshStart(ctx, planText, overrideMode, opts2 = {}) {
32980
33154
  const oldSessionId = ctx.sessionIdRef.current;
@@ -33898,7 +34072,7 @@ ${lines.join("\n")}` }]);
33898
34072
  void (async () => {
33899
34073
  try {
33900
34074
  const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
33901
- const file = await loadSession(join41(sessionsDir3(), `${currentId}.json`));
34075
+ const file = await loadSession(join42(sessionsDir3(), `${currentId}.json`));
33902
34076
  const cps = file.checkpoints ?? [];
33903
34077
  if (cps.length === 0) {
33904
34078
  setEvents((e) => [...e, { kind: "info", key: mkKey2(), text: "no checkpoints in this session" }]);
@@ -33943,7 +34117,7 @@ ${lines.join("\n")}` }]);
33943
34117
  try {
33944
34118
  ctx.ensureSessionId();
33945
34119
  const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
33946
- const filePath = join41(sessionsDir3(), `${ctx.sessionIdRef.current}.json`);
34120
+ const filePath = join42(sessionsDir3(), `${ctx.sessionIdRef.current}.json`);
33947
34121
  await addCheckpoint(filePath, cp);
33948
34122
  setEvents((e) => [...e, { kind: "info", key: mkKey2(), text: `checkpoint saved: "${label}"` }]);
33949
34123
  } catch (e) {
@@ -34575,12 +34749,12 @@ project: ${projectSettingsPath(cwd)}`
34575
34749
 
34576
34750
  // src/init/context-generator.ts
34577
34751
  import { existsSync as existsSync6, statSync as statSync6 } from "fs";
34578
- import { join as join42 } from "path";
34752
+ import { join as join43 } from "path";
34579
34753
  function detectFlavor(cwd) {
34580
34754
  for (const [flavor, signatures] of Object.entries(FLAVOR_SIGNATURES)) {
34581
34755
  if (flavor === "generic") continue;
34582
34756
  for (const sig of signatures) {
34583
- const path = join42(cwd, sig);
34757
+ const path = join43(cwd, sig);
34584
34758
  if (sig.includes("*")) {
34585
34759
  try {
34586
34760
  const parts = sig.split("*");
@@ -34601,14 +34775,14 @@ function detectFlavor(cwd) {
34601
34775
  }
34602
34776
  function findFile(cwd, candidates) {
34603
34777
  for (const c of candidates) {
34604
- if (existsSync6(join42(cwd, c))) return c;
34778
+ if (existsSync6(join43(cwd, c))) return c;
34605
34779
  }
34606
34780
  return null;
34607
34781
  }
34608
34782
  function findSourceRoots(cwd) {
34609
34783
  const roots = [];
34610
34784
  for (const r of SOURCE_ROOT_CANDIDATES) {
34611
- const p = join42(cwd, r);
34785
+ const p = join43(cwd, r);
34612
34786
  try {
34613
34787
  const s = statSync6(p);
34614
34788
  if (s.isDirectory()) roots.push(r);
@@ -34619,9 +34793,9 @@ function findSourceRoots(cwd) {
34619
34793
  }
34620
34794
  function findCiConfig(cwd) {
34621
34795
  for (const c of CI_PATHS) {
34622
- if (existsSync6(join42(cwd, c))) {
34796
+ if (existsSync6(join43(cwd, c))) {
34623
34797
  try {
34624
- const s = statSync6(join42(cwd, c));
34798
+ const s = statSync6(join43(cwd, c));
34625
34799
  return s.isDirectory() ? c : c;
34626
34800
  } catch {
34627
34801
  }
@@ -34758,7 +34932,7 @@ function analyzeProject(cwd) {
34758
34932
  ciConfig: findCiConfig(cwd),
34759
34933
  readme: findFile(cwd, ["README.md", "README.rst", "README.txt", "Readme.md"]),
34760
34934
  sourceRoots: findSourceRoots(cwd),
34761
- hasGit: existsSync6(join42(cwd, ".git"))
34935
+ hasGit: existsSync6(join43(cwd, ".git"))
34762
34936
  };
34763
34937
  }
34764
34938
  function bashDiscoveryCommands(profile) {
@@ -34923,7 +35097,7 @@ Aim for 100\u2013200 lines total. Use markdown tables where they save space.
34923
35097
  }
34924
35098
  function buildInitPrompt(cwd) {
34925
35099
  const existingName = ["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].find(
34926
- (n) => existsSync6(join42(cwd, n))
35100
+ (n) => existsSync6(join43(cwd, n))
34927
35101
  );
34928
35102
  const isRefresh = existingName !== void 0;
34929
35103
  const targetFilename = existingName ?? "AGENTS.md";
@@ -35007,7 +35181,7 @@ var init_context_generator = __esm({
35007
35181
 
35008
35182
  // src/init/run-init.ts
35009
35183
  import { existsSync as existsSync7 } from "fs";
35010
- import { join as join43 } from "path";
35184
+ import { join as join44 } from "path";
35011
35185
  async function runInit(deps) {
35012
35186
  const {
35013
35187
  cfg,
@@ -35205,7 +35379,7 @@ async function runInit(deps) {
35205
35379
  }
35206
35380
  }
35207
35381
  });
35208
- if (existsSync7(join43(cwd, targetFilename))) {
35382
+ if (existsSync7(join44(cwd, targetFilename))) {
35209
35383
  if (cacheStableRef.current) {
35210
35384
  messagesRef.current[1] = {
35211
35385
  role: "system",
@@ -35297,8 +35471,8 @@ var init_run_init = __esm({
35297
35471
  });
35298
35472
 
35299
35473
  // src/skills/discovery.ts
35300
- import { readdir as readdir9, stat as stat9, readFile as readFile28 } from "fs/promises";
35301
- import { join as join44, extname as extname2 } from "path";
35474
+ import { readdir as readdir9, stat as stat9, readFile as readFile29 } from "fs/promises";
35475
+ import { join as join45, extname as extname2 } from "path";
35302
35476
  async function dirExists(path) {
35303
35477
  try {
35304
35478
  const s = await stat9(path);
@@ -35322,20 +35496,20 @@ async function scanSkillDir(dirPath, source) {
35322
35496
  for (const entry of entries) {
35323
35497
  if (!entry.isFile()) continue;
35324
35498
  if (!SKILL_EXTENSIONS.has(extname2(entry.name))) continue;
35325
- files.push({ filePath: join44(dirPath, entry.name), source });
35499
+ files.push({ filePath: join45(dirPath, entry.name), source });
35326
35500
  }
35327
35501
  return files;
35328
35502
  }
35329
35503
  async function discoverSkills(cwd) {
35330
- const agentsSkills = await scanSkillDir(join44(cwd, ".agents", "skills"), "agents");
35331
- const agentsMd = await fileExists(join44(cwd, "AGENTS.md")) ? [{ filePath: join44(cwd, "AGENTS.md"), source: "agents-md" }] : [];
35332
- const githubSkills = await scanSkillDir(join44(cwd, ".github", "skills"), "github");
35333
- const kimiflareSkills = await scanSkillDir(join44(cwd, ".kimiflare", "skills"), "kimiflare");
35504
+ const agentsSkills = await scanSkillDir(join45(cwd, ".agents", "skills"), "agents");
35505
+ const agentsMd = await fileExists(join45(cwd, "AGENTS.md")) ? [{ filePath: join45(cwd, "AGENTS.md"), source: "agents-md" }] : [];
35506
+ const githubSkills = await scanSkillDir(join45(cwd, ".github", "skills"), "github");
35507
+ const kimiflareSkills = await scanSkillDir(join45(cwd, ".kimiflare", "skills"), "kimiflare");
35334
35508
  const ordered = [...agentsSkills, ...agentsMd, ...githubSkills, ...kimiflareSkills];
35335
35509
  return ordered;
35336
35510
  }
35337
35511
  async function readSkillFile(filePath) {
35338
- const bytes = await readFile28(filePath);
35512
+ const bytes = await readFile29(filePath);
35339
35513
  return { bytes, text: bytes.toString("utf-8") };
35340
35514
  }
35341
35515
  var SKILL_EXTENSIONS;
@@ -35541,7 +35715,7 @@ var init_skills = __esm({
35541
35715
 
35542
35716
  // src/ui/run-startup-tasks.ts
35543
35717
  import { existsSync as existsSync8 } from "fs";
35544
- import { join as join45 } from "path";
35718
+ import { join as join46 } from "path";
35545
35719
  function runStartupTasks(deps) {
35546
35720
  const {
35547
35721
  cfg,
@@ -35563,7 +35737,7 @@ function runStartupTasks(deps) {
35563
35737
  }
35564
35738
  });
35565
35739
  if (cfg.memoryEnabled) {
35566
- const dbPath = cfg.memoryDbPath ?? join45(process.cwd(), ".kimiflare", "memory.db");
35740
+ const dbPath = cfg.memoryDbPath ?? join46(process.cwd(), ".kimiflare", "memory.db");
35567
35741
  const manager = new MemoryManager({
35568
35742
  dbPath,
35569
35743
  ...auth,
@@ -35595,7 +35769,7 @@ function runStartupTasks(deps) {
35595
35769
  });
35596
35770
  const cwd = process.cwd();
35597
35771
  sessionStartRecallRef.current = manager.recall({ text: cwd, repoPath: cwd, limit: 5 });
35598
- if (["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].some((name) => existsSync8(join45(cwd, name)))) {
35772
+ if (["AGENTS.md", "KIMI.md", "KIMIFLARE.md", "AGENT.md"].some((name) => existsSync8(join46(cwd, name)))) {
35599
35773
  const lastRefresh = manager.getLastKimiMdRefreshTime(cwd);
35600
35774
  const driftCount = manager.countHighSignalMemoriesSince(cwd, lastRefresh);
35601
35775
  if (driftCount >= 5) {
@@ -35606,7 +35780,7 @@ function runStartupTasks(deps) {
35606
35780
  memoryManagerRef.current?.close();
35607
35781
  memoryManagerRef.current = null;
35608
35782
  }
35609
- const skillDbPath = cfg.memoryDbPath ?? join45(process.cwd(), ".kimiflare", "memory.db");
35783
+ const skillDbPath = cfg.memoryDbPath ?? join46(process.cwd(), ".kimiflare", "memory.db");
35610
35784
  const skillDb = getMemoryDb() ?? openMemoryDb(skillDbPath);
35611
35785
  initSkillsSchema(skillDb);
35612
35786
  void indexSkills({
@@ -35957,155 +36131,6 @@ var init_run_compact = __esm({
35957
36131
  }
35958
36132
  });
35959
36133
 
35960
- // src/ui/bang-command.ts
35961
- import { spawn as spawn10 } from "child_process";
35962
- import { mkdtemp as mkdtemp2, readFile as readFile29, rm as rm3 } from "fs/promises";
35963
- import { tmpdir as tmpdir4, platform as platform7 } from "os";
35964
- import { join as join46 } from "path";
35965
- function registerInkInstance(instance) {
35966
- inkInstance = instance;
35967
- }
35968
- function isTerminalHandedOff() {
35969
- return handedOff;
35970
- }
35971
- function parseBangCommand(input) {
35972
- const t = input.trimStart();
35973
- if (!t.startsWith("!")) return null;
35974
- return t.slice(1).trim();
35975
- }
35976
- function scriptInvocation(command, shell, logPath, plat = platform7()) {
35977
- if (plat === "darwin" || plat === "freebsd" || plat === "openbsd" || plat === "netbsd") {
35978
- return { file: "script", args: ["-q", logPath, shell, "-c", command] };
35979
- }
35980
- if (plat === "linux") {
35981
- return { file: "script", args: ["-q", "-e", "-c", command, logPath], env: { ...process.env, SHELL: shell } };
35982
- }
35983
- return null;
35984
- }
35985
- function cleanTerminalOutput(raw) {
35986
- const text = raw.replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g, "").replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, "").replace(/\x1b[@-Z\\-_]/g, "").replace(/^Script (?:started|done) on .*$/gm, "");
35987
- const lines = text.split(/\r?\n/).map((line) => {
35988
- const segs = line.split("\r");
35989
- let out = segs[segs.length - 1] ?? "";
35990
- if (!out && segs.length > 1) out = segs.filter(Boolean).pop() ?? "";
35991
- while (/[^\x08]\x08/.test(out)) out = out.replace(/[^\x08]\x08/, "");
35992
- return out.replace(/[\x00-\x08\x0b-\x1f\x7f]/g, "");
35993
- });
35994
- return lines.join("\n").replace(/\n{3,}/g, "\n\n").trim();
35995
- }
35996
- function truncateMiddle2(text, max = MAX_CONTEXT_CHARS2) {
35997
- if (text.length <= max) return text;
35998
- const half = Math.floor(max / 2);
35999
- return `${text.slice(0, half)}
36000
-
36001
- [\u2026 ${text.length - max} chars omitted \u2026]
36002
-
36003
- ${text.slice(-half)}`;
36004
- }
36005
- function formatBangContext(r) {
36006
- const status = r.signal ? `killed by ${r.signal}` : `exit code ${r.exitCode ?? "?"}`;
36007
- const body = r.output === null ? "(output was shown in the user's terminal but could not be captured)" : r.output ? truncateMiddle2(r.output) : "(no output)";
36008
- return `[The user ran this shell command themselves with \`!\` in the autopilot prompt. This is context for you, not a new request.]
36009
- $ ${r.command}
36010
- (${status})
36011
- ${body}`;
36012
- }
36013
- function stopReading(stdin) {
36014
- stdin.pause();
36015
- const stream = stdin;
36016
- try {
36017
- if (stream._handle?.reading && stream._handle.readStop) {
36018
- stream._handle.readStop();
36019
- stream._handle.reading = false;
36020
- if (stream._readableState) stream._readableState.reading = false;
36021
- }
36022
- } catch {
36023
- }
36024
- }
36025
- function swallow() {
36026
- return ((_chunk, encOrCb, cb) => {
36027
- const done = typeof encOrCb === "function" ? encOrCb : cb;
36028
- if (typeof done === "function") done();
36029
- return true;
36030
- });
36031
- }
36032
- function spawnInherit(inv, cwd) {
36033
- return new Promise((resolve15, reject) => {
36034
- const child = spawn10(inv.file, inv.args, { cwd, stdio: "inherit", env: inv.env ?? process.env });
36035
- child.once("error", reject);
36036
- child.once("exit", (code, signal) => resolve15({ code, signal }));
36037
- });
36038
- }
36039
- async function runBangCommand(command, cwd) {
36040
- const isWindows = platform7() === "win32";
36041
- const shell = isWindows ? process.env.COMSPEC || "cmd.exe" : process.env.SHELL || "/bin/sh";
36042
- const direct = isWindows ? { file: shell, args: ["/c", command] } : { file: shell, args: ["-c", command] };
36043
- const stdin = process.stdin;
36044
- const stdout = process.stdout;
36045
- const stderr = process.stderr;
36046
- const origOut = stdout.write;
36047
- const origErr = stderr.write;
36048
- const readable = stdin.listeners("readable");
36049
- const wasRaw = stdin.isTTY ? stdin.isRaw : false;
36050
- const logDir2 = isWindows ? null : await mkdtemp2(join46(tmpdir4(), "autopilot-bang-"));
36051
- const logPath = logDir2 ? join46(logDir2, "out.log") : null;
36052
- const viaScript = logPath ? scriptInvocation(command, shell, logPath) : null;
36053
- inkInstance?.clear();
36054
- origOut.call(stdout, `
36055
- $ ${command}
36056
- `);
36057
- stdout.write = swallow();
36058
- stderr.write = swallow();
36059
- for (const l of readable) stdin.removeListener("readable", l);
36060
- if (stdin.isTTY) stdin.setRawMode(false);
36061
- stopReading(stdin);
36062
- handedOff = true;
36063
- let result2;
36064
- let captured = false;
36065
- let spawnError = null;
36066
- try {
36067
- if (viaScript) {
36068
- try {
36069
- result2 = await spawnInherit(viaScript, cwd);
36070
- captured = true;
36071
- } catch (e) {
36072
- logger.warn("bang:script_unavailable", { error: e.message });
36073
- result2 = await spawnInherit(direct, cwd);
36074
- }
36075
- } else {
36076
- result2 = await spawnInherit(direct, cwd);
36077
- }
36078
- } catch (e) {
36079
- result2 = { code: 127, signal: null };
36080
- spawnError = e.message;
36081
- logger.warn("bang:spawn_failed", { error: spawnError });
36082
- } finally {
36083
- handedOff = false;
36084
- stdout.write = origOut;
36085
- stderr.write = origErr;
36086
- if (stdin.isTTY) stdin.setRawMode(wasRaw);
36087
- for (const l of readable) stdin.addListener("readable", l);
36088
- origOut.call(stdout, "\n");
36089
- }
36090
- let output = spawnError ? `failed to start: ${spawnError}` : null;
36091
- if (captured && logPath) {
36092
- output = cleanTerminalOutput(await readFile29(logPath, "utf8").catch(() => ""));
36093
- }
36094
- if (logDir2) await rm3(logDir2, { recursive: true, force: true }).catch(() => {
36095
- });
36096
- return { command, exitCode: result2.code, signal: result2.signal, output };
36097
- }
36098
- var inkInstance, handedOff, MAX_CONTEXT_CHARS2;
36099
- var init_bang_command = __esm({
36100
- "src/ui/bang-command.ts"() {
36101
- "use strict";
36102
- init_logger();
36103
- inkInstance = null;
36104
- handedOff = false;
36105
- MAX_CONTEXT_CHARS2 = 16e3;
36106
- }
36107
- });
36108
-
36109
36134
  // src/commands/save.ts
36110
36135
  import { mkdir as mkdir14, writeFile as writeFile15, unlink as unlink5 } from "fs/promises";
36111
36136
  import { dirname as dirname17 } from "path";