autopilot-ai 1.22.1 → 1.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -63,6 +63,13 @@ autopilot
63
63
 
64
64
  On first run, **Sign in with OpenRouter**: approve autopilot in your browser and a key is created for you (or paste one from <https://openrouter.ai/keys>). Then pick a model. That's it.
65
65
 
66
+ Or install with Homebrew on macOS or Linux (Homebrew installs Node.js for you):
67
+
68
+ ```sh
69
+ brew install sinameraji/tap/autopilot
70
+ autopilot
71
+ ```
72
+
66
73
  Or run without installing:
67
74
 
68
75
  ```sh
package/dist/index.js CHANGED
@@ -10,11 +10,20 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
10
10
  if (typeof require !== "undefined") return require.apply(this, arguments);
11
11
  throw Error('Dynamic require of "' + x + '" is not supported');
12
12
  });
13
- var __esm = (fn, res) => function __init() {
14
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
13
+ var __esm = (fn, res, err) => function __init() {
14
+ if (err) throw err[0];
15
+ try {
16
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
17
+ } catch (e) {
18
+ throw err = [e], e;
19
+ }
15
20
  };
16
21
  var __commonJS = (cb, mod) => function __require2() {
17
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
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
+ }
18
27
  };
19
28
  var __export = (target, all) => {
20
29
  for (var name in all)
@@ -8723,6 +8732,8 @@ var init_web_search = __esm({
8723
8732
  });
8724
8733
 
8725
8734
  // src/tools/github.ts
8735
+ import { execFile as execFileCallback } from "child_process";
8736
+ import { promisify as promisify3 } from "util";
8726
8737
  function getHeaders(token) {
8727
8738
  const headers = {
8728
8739
  Accept: "application/vnd.github+json",
@@ -8734,7 +8745,23 @@ function getHeaders(token) {
8734
8745
  }
8735
8746
  return headers;
8736
8747
  }
8737
- async function githubFetch(path, token) {
8748
+ async function ghApi(path, token, body) {
8749
+ const args = ["api", path.replace(/^\/+/, "")];
8750
+ if (body !== void 0 && typeof body === "object" && body !== null) {
8751
+ args.push("-X", "POST");
8752
+ for (const [key, value] of Object.entries(body)) {
8753
+ if (value === void 0 || value === null) continue;
8754
+ args.push(typeof value === "boolean" ? "-F" : "-f", `${key}=${String(value)}`);
8755
+ }
8756
+ }
8757
+ const result2 = await execFile3("gh", args, {
8758
+ timeout: TIMEOUT_MS3,
8759
+ maxBuffer: 10 * 1024 * 1024,
8760
+ env: token ? { ...process.env, GH_TOKEN: token } : process.env
8761
+ });
8762
+ return JSON.parse(result2.stdout);
8763
+ }
8764
+ async function githubFetch(path, token, cliFallback = ghApi) {
8738
8765
  const controller = new AbortController();
8739
8766
  const timer3 = setTimeout(() => controller.abort(), TIMEOUT_MS3);
8740
8767
  try {
@@ -8747,6 +8774,12 @@ async function githubFetch(path, token) {
8747
8774
  throw new Error(`GitHub API ${res.status}: ${res.statusText}${body ? ` \u2014 ${body.slice(0, 200)}` : ""}`);
8748
8775
  }
8749
8776
  return await res.json();
8777
+ } catch (apiError) {
8778
+ try {
8779
+ return await cliFallback(path, token);
8780
+ } catch (cliError) {
8781
+ throw new Error(`${formatError(apiError)}; gh CLI fallback failed: ${formatError(cliError)}`);
8782
+ }
8750
8783
  } finally {
8751
8784
  clearTimeout(timer3);
8752
8785
  }
@@ -8769,6 +8802,12 @@ async function githubPost(path, body, token) {
8769
8802
  throw new Error(`GitHub API ${res.status}: ${res.statusText}${text ? ` \u2014 ${text.slice(0, 200)}` : ""}`);
8770
8803
  }
8771
8804
  return await res.json();
8805
+ } catch (apiError) {
8806
+ try {
8807
+ return await ghApi(path, token, body);
8808
+ } catch (cliError) {
8809
+ throw new Error(`${formatError(apiError)}; gh CLI fallback failed: ${formatError(cliError)}`);
8810
+ }
8772
8811
  } finally {
8773
8812
  clearTimeout(timer3);
8774
8813
  }
@@ -8784,11 +8823,12 @@ function formatError(err) {
8784
8823
  if (err instanceof Error) return err.message;
8785
8824
  return String(err);
8786
8825
  }
8787
- var GITHUB_API_BASE, TIMEOUT_MS3, githubListMergedPrsTool, githubListReleasesTool, githubReadPrTool, githubReadIssueTool, githubReadCodeTool, githubCreatePrTool;
8826
+ var execFile3, GITHUB_API_BASE, TIMEOUT_MS3, githubListMergedPrsTool, githubListReleasesTool, githubReadPrTool, githubReadIssueTool, githubReadCodeTool, githubCreatePrTool;
8788
8827
  var init_github = __esm({
8789
8828
  "src/tools/github.ts"() {
8790
8829
  "use strict";
8791
8830
  init_version();
8831
+ execFile3 = promisify3(execFileCallback);
8792
8832
  GITHUB_API_BASE = "https://api.github.com";
8793
8833
  TIMEOUT_MS3 = 2e4;
8794
8834
  githubListMergedPrsTool = {
@@ -9716,11 +9756,11 @@ var init_memory = __esm({
9716
9756
  });
9717
9757
 
9718
9758
  // src/tools/hotcell-snapshot.ts
9719
- import { execFile as execFile3 } from "child_process";
9759
+ import { execFile as execFile4 } from "child_process";
9720
9760
  import { mkdtemp, rm as rm2 } from "fs/promises";
9721
9761
  import { tmpdir as tmpdir3 } from "os";
9722
9762
  import { join as join20 } from "path";
9723
- import { promisify as promisify3 } from "util";
9763
+ import { promisify as promisify4 } from "util";
9724
9764
  async function git(args, cwd, env2) {
9725
9765
  const { stdout } = await execFileAsync2("git", args, {
9726
9766
  cwd,
@@ -9822,7 +9862,7 @@ var execFileAsync2, MAX_SNAPSHOT_PATCH_BYTES, MAX_ARCHIVE_BYTES, SECRET_EXCLUDES
9822
9862
  var init_hotcell_snapshot = __esm({
9823
9863
  "src/tools/hotcell-snapshot.ts"() {
9824
9864
  "use strict";
9825
- execFileAsync2 = promisify3(execFile3);
9865
+ execFileAsync2 = promisify4(execFile4);
9826
9866
  MAX_SNAPSHOT_PATCH_BYTES = 4 * 1024 * 1024;
9827
9867
  MAX_ARCHIVE_BYTES = 24 * 1024 * 1024;
9828
9868
  SECRET_EXCLUDES = [
@@ -9921,8 +9961,8 @@ var init_hotcell_worker_cache = __esm({
9921
9961
 
9922
9962
  // src/tools/hotcell-worker.ts
9923
9963
  import { spawn as spawn2 } from "child_process";
9924
- import { promisify as promisify4 } from "util";
9925
- import { execFile as execFile4 } from "child_process";
9964
+ import { promisify as promisify5 } from "util";
9965
+ import { execFile as execFile5 } from "child_process";
9926
9966
  import { resolve as resolve3 } from "path";
9927
9967
  async function runHotcellWorker(options) {
9928
9968
  const workerId = `hotcell-${crypto.randomUUID().slice(0, 8)}`;
@@ -9946,6 +9986,14 @@ async function runHotcellWorker(options) {
9946
9986
  const execute = options.processRunner ?? runProcess;
9947
9987
  const timeoutMs = options.timeoutMs ?? DEFAULT_CELL_TIMEOUT_MS;
9948
9988
  try {
9989
+ const started = await execute(command, ["start", "--defaults"], {
9990
+ cwd,
9991
+ signal: options.signal,
9992
+ timeoutMs: 3e4
9993
+ });
9994
+ if (started.code !== 0 || started.timedOut || started.aborted) {
9995
+ throw new Error(formatSetupFailure(started).replace("Hotcell setup failed", "Hotcell daemon startup failed"));
9996
+ }
9949
9997
  const useArchive = options.useArchive ?? process.env.KIMIFLARE_WORKER_ARCHIVE !== "0";
9950
9998
  const tree = useArchive ? await getWorkingTreeArchive(cwd) : { archive: null, files: 0, bytes: 0 };
9951
9999
  const repo = tree.archive ? null : await getRepositorySnapshot(cwd);
@@ -10337,10 +10385,10 @@ var init_hotcell_worker = __esm({
10337
10385
  init_registry();
10338
10386
  init_hotcell_snapshot();
10339
10387
  init_hotcell_worker_cache();
10340
- execFileAsync3 = promisify4(execFile4);
10388
+ execFileAsync3 = promisify5(execFile5);
10341
10389
  MAX_OUTPUT_BYTES = 1e6;
10342
10390
  MAX_PROMPT_CHARS = 4e4;
10343
- DEFAULT_CELL_TIMEOUT_MS = 3e5;
10391
+ DEFAULT_CELL_TIMEOUT_MS = 6e5;
10344
10392
  DEFAULT_SETUP_TIMEOUT_MS = 3e5;
10345
10393
  WORKER_BIN = `${CACHED_WORKER_DIR}/node_modules/.bin/${CLI_NAME}`;
10346
10394
  PACKAGE_SPEC = /^[\w@./:+~^=<>#-]+$/;
@@ -10575,7 +10623,7 @@ function fromLegacySpawnWorkerArgs(args) {
10575
10623
  }
10576
10624
  function formatWorkerResult(result2, model) {
10577
10625
  const lines = [
10578
- "Subagent " + result2.status + (result2.status === "budget_exhausted" ? " (partial result)" : "") + ".",
10626
+ "Subagent " + result2.status + (result2.status === "budget_exhausted" || result2.status === "spend_exhausted" ? " (partial result)" : "") + ".",
10579
10627
  "Model: " + (result2.model ?? model) + " \xB7 Tokens: " + result2.tokensUsed.toLocaleString() + " \xB7 Cost: " + (result2.costUsd > 0 ? result2.costUsd.toFixed(4) + " total cost" : "unavailable") + ".",
10580
10628
  ...result2.findings.map((finding) => "\n## " + finding.topic + (result2.structured ? " (" + finding.confidence + " confidence)" : "") + "\n" + finding.summary + (finding.sources.length ? "\nFiles: " + finding.sources.join(", ") : ""))
10581
10629
  ];
@@ -10591,7 +10639,7 @@ function formatWorkerResult(result2, model) {
10591
10639
  if (!result2.structured && result2.findings.length) {
10592
10640
  lines.push("\n(The subagent did not return a structured report; findings above are its raw answer and are unverified.)");
10593
10641
  }
10594
- if (result2.status === "budget_exhausted") {
10642
+ if (result2.status === "budget_exhausted" || result2.status === "spend_exhausted") {
10595
10643
  lines.push("\nThe subagent ran out of budget; review partial findings before relying on them.");
10596
10644
  }
10597
10645
  return lines.join("\n");
@@ -10621,7 +10669,7 @@ var init_subagent = __esm({
10621
10669
  init_hotcell_worker();
10622
10670
  init_worker_registry();
10623
10671
  init_subagent_stats();
10624
- DEFAULT_WORKER_TIMEOUT_MS = 3e5;
10672
+ DEFAULT_WORKER_TIMEOUT_MS = 6e5;
10625
10673
  subagentTool = {
10626
10674
  name: "subagent",
10627
10675
  description: [
@@ -10743,7 +10791,7 @@ var init_subagent = __esm({
10743
10791
  if (handle.cancelledByUser && !ctx.signal?.aborted) {
10744
10792
  return textOutput(userCancelledMessage(handle.index, args.mission));
10745
10793
  }
10746
- if (result2.status !== "completed" && result2.status !== "budget_exhausted") {
10794
+ if (result2.status !== "completed" && result2.status !== "budget_exhausted" && !(result2.status === "spend_exhausted" && result2.partialResult && result2.findings.length > 0)) {
10747
10795
  throw new Error("Subagent " + result2.status + ": " + (result2.error ?? "unknown error"));
10748
10796
  }
10749
10797
  return textOutput(formatWorkerResult(result2, model));
@@ -13422,11 +13470,11 @@ var init_retention = __esm({
13422
13470
  });
13423
13471
 
13424
13472
  // src/trace/session-start.ts
13425
- import { execFile as execFile5 } from "child_process";
13473
+ import { execFile as execFile6 } from "child_process";
13426
13474
  import { existsSync as existsSync5 } from "fs";
13427
13475
  import { dirname as dirname13, join as join27 } from "path";
13428
13476
  import { fileURLToPath as fileURLToPath4 } from "url";
13429
- import { promisify as promisify5 } from "util";
13477
+ import { promisify as promisify6 } from "util";
13430
13478
  async function git2(args, cwd) {
13431
13479
  try {
13432
13480
  const { stdout } = await execFileAsync4("git", args, { cwd, timeout: 3e3, windowsHide: true });
@@ -13482,7 +13530,7 @@ var init_session_start = __esm({
13482
13530
  init_version();
13483
13531
  init_blobs();
13484
13532
  init_redact();
13485
- execFileAsync4 = promisify5(execFile5);
13533
+ execFileAsync4 = promisify6(execFile6);
13486
13534
  }
13487
13535
  });
13488
13536
 
@@ -13994,11 +14042,11 @@ var init_tasks2 = __esm({
13994
14042
  });
13995
14043
 
13996
14044
  // src/eval/workspace.ts
13997
- import { execFile as execFile6 } from "child_process";
14045
+ import { execFile as execFile7 } from "child_process";
13998
14046
  import { createHash as createHash4 } from "crypto";
13999
14047
  import { mkdir as mkdir12, rm as rm4, stat as stat8 } from "fs/promises";
14000
14048
  import { isAbsolute as isAbsolute3, join as join30, resolve as resolve9 } from "path";
14001
- import { promisify as promisify6 } from "util";
14049
+ import { promisify as promisify7 } from "util";
14002
14050
  async function git3(args, cwd, timeoutMs = 6e5) {
14003
14051
  const { stdout } = await execFileAsync5("git", args, { cwd, timeout: timeoutMs, maxBuffer: 64 * 1024 * 1024 });
14004
14052
  return stdout.trim();
@@ -14056,7 +14104,7 @@ var execFileAsync5, preparing;
14056
14104
  var init_workspace = __esm({
14057
14105
  "src/eval/workspace.ts"() {
14058
14106
  "use strict";
14059
- execFileAsync5 = promisify6(execFile6);
14107
+ execFileAsync5 = promisify7(execFile7);
14060
14108
  preparing = /* @__PURE__ */ new Map();
14061
14109
  }
14062
14110
  });
@@ -19125,7 +19173,7 @@ var init_openapi = __esm({
19125
19173
  });
19126
19174
 
19127
19175
  // src/runs/worktrees.ts
19128
- import { execFile as execFile7 } from "child_process";
19176
+ import { execFile as execFile8 } from "child_process";
19129
19177
  import { access as access2, chmod as chmod2, mkdir as mkdir16, realpath as realpath4 } from "fs/promises";
19130
19178
  import { homedir as homedir25 } from "os";
19131
19179
  import { isAbsolute as isAbsolute5, join as join40, parse, relative as relative8, resolve as resolve12, sep as sep4 } from "path";
@@ -19142,7 +19190,7 @@ function isWithin2(parent, candidate) {
19142
19190
  }
19143
19191
  function runGit(args, cwd) {
19144
19192
  return new Promise((resolveOutput, reject) => {
19145
- execFile7("git", args, { cwd, encoding: "utf8", timeout: 3e4, maxBuffer: 1024 * 1024 }, (error, stdout, stderr) => {
19193
+ execFile8("git", args, { cwd, encoding: "utf8", timeout: 3e4, maxBuffer: 1024 * 1024 }, (error, stdout, stderr) => {
19146
19194
  if (error) {
19147
19195
  const detail = stderr.trim();
19148
19196
  reject(new Error(`git ${args[0]} failed${detail ? `: ${detail}` : ""}`, { cause: error }));
@@ -20097,9 +20145,9 @@ data: ${JSON.stringify(event.data)}
20097
20145
  });
20098
20146
 
20099
20147
  // src/server/aster-cell-runtime.ts
20100
- import { execFile as execFile8 } from "child_process";
20148
+ import { execFile as execFile9 } from "child_process";
20101
20149
  import { readFile as readFile26 } from "fs/promises";
20102
- import { promisify as promisify7 } from "util";
20150
+ import { promisify as promisify8 } from "util";
20103
20151
  import { randomUUID as randomUUID8 } from "crypto";
20104
20152
  async function writeCellFileChunked(cell, path, content) {
20105
20153
  if (Buffer.byteLength(content, "utf8") <= CELL_FILE_WRITE_CHUNK_CHARS) {
@@ -20189,7 +20237,7 @@ var init_aster_cell_runtime = __esm({
20189
20237
  "use strict";
20190
20238
  init_version();
20191
20239
  init_aster_tools();
20192
- execFileAsync6 = promisify7(execFile8);
20240
+ execFileAsync6 = promisify8(execFile9);
20193
20241
  CELL_WORKSPACE = "/workspace";
20194
20242
  CELL_STATE_DIR = "/workspace/.aster";
20195
20243
  CHECKPOINT_MESSAGE_FILE = `${CELL_STATE_DIR}/checkpoint-message`;
@@ -25943,13 +25991,17 @@ function activityFromSubagent(worker) {
25943
25991
  return {
25944
25992
  id: `agent:${worker.id}`,
25945
25993
  kind: "agent",
25946
- title: `subagent #${worker.index}: ${worker.task}`,
25994
+ title: `subagent #${worker.index}: ${activityTaskPreview(worker.task)}`,
25947
25995
  status: "running",
25948
25996
  stoppable: worker.status === "running",
25949
25997
  ...worker.status === "cancelling" ? { summary: "Stopping\u2026" } : {},
25950
25998
  started_at_ms: worker.startedAt
25951
25999
  };
25952
26000
  }
26001
+ function activityTaskPreview(task) {
26002
+ const oneLine2 = task.replace(/\s+/g, " ").trim();
26003
+ return oneLine2.length > 72 ? `${oneLine2.slice(0, 71)}\u2026` : oneLine2;
26004
+ }
25953
26005
  function diffActivityItems(previous, current, snapshotSent) {
25954
26006
  if (!snapshotSent) return [{ type: "ActivitySnapshot", payload: { items: [...current] } }];
25955
26007
  const next = new Map(current.map((item) => [item.id, item]));
@@ -33022,6 +33074,22 @@ var init_task_list = __esm({
33022
33074
  }
33023
33075
  });
33024
33076
 
33077
+ // src/ui/terminal-title.ts
33078
+ function terminalTitleSequence(title) {
33079
+ const safeTitle = title.replace(/[\u0000-\u001f\u007f\u009b\u009d]/g, " ").trim();
33080
+ return safeTitle ? `\x1B]0;${safeTitle}\x07` : null;
33081
+ }
33082
+ function setTerminalTitle(title) {
33083
+ if (!process.stdout.isTTY) return;
33084
+ const sequence = terminalTitleSequence(title);
33085
+ if (sequence) process.stdout.write(sequence);
33086
+ }
33087
+ var init_terminal_title = __esm({
33088
+ "src/ui/terminal-title.ts"() {
33089
+ "use strict";
33090
+ }
33091
+ });
33092
+
33025
33093
  // src/models/openrouter-oauth.ts
33026
33094
  var openrouter_oauth_exports = {};
33027
33095
  __export(openrouter_oauth_exports, {
@@ -33716,7 +33784,7 @@ var init_loader2 = __esm({
33716
33784
  import { exec } from "child_process";
33717
33785
  import { open as open2, realpath as realpath7 } from "fs/promises";
33718
33786
  import { isAbsolute as isAbsolute7, relative as relative11, resolve as resolvePathJoin, basename as pathBasename } from "path";
33719
- import { promisify as promisify8 } from "util";
33787
+ import { promisify as promisify9 } from "util";
33720
33788
  function tokenizeArgs(s) {
33721
33789
  return [...s.matchAll(ARG_TOKEN_RE)].map((match) => {
33722
33790
  const token = match[0];
@@ -33869,7 +33937,7 @@ var init_renderer2 = __esm({
33869
33937
  "src/commands/renderer.ts"() {
33870
33938
  "use strict";
33871
33939
  init_paths2();
33872
- execAsync = promisify8(exec);
33940
+ execAsync = promisify9(exec);
33873
33941
  ARG_TOKEN_RE = /(?:"[^"]*"|'[^']*'|[^\s"']+)/g;
33874
33942
  POSITIONAL_RE = /\$(\d+)/g;
33875
33943
  HAS_POSITIONAL = /\$\d+/;
@@ -36451,6 +36519,8 @@ function useSessionManager(deps) {
36451
36519
  endTrace(checkpointId ? "restore_checkpoint" : "exit");
36452
36520
  turnHistoryRef.current = [];
36453
36521
  sessionIdRef.current = file.id;
36522
+ sessionTitleRef.current = file.title ?? null;
36523
+ if (file.title) setTerminalTitle(file.title);
36454
36524
  setLogSessionId(file.id);
36455
36525
  sessionCreatedAtRef.current = file.createdAt;
36456
36526
  if (file.sessionState && d.compiledContextRef.current) {
@@ -36632,6 +36702,7 @@ ${summary}`
36632
36702
  setLogSessionId(null);
36633
36703
  sessionCreatedAtRef.current = null;
36634
36704
  sessionTitleRef.current = null;
36705
+ setTerminalTitle("autopilot");
36635
36706
  const d = depsRef.current;
36636
36707
  d.sessionStateRef.current = emptySessionState();
36637
36708
  d.artifactStoreRef.current = new ArtifactStore();
@@ -36669,6 +36740,7 @@ ${summary}`
36669
36740
  var init_use_session_manager = __esm({
36670
36741
  "src/ui/use-session-manager.ts"() {
36671
36742
  "use strict";
36743
+ init_terminal_title();
36672
36744
  init_sessions();
36673
36745
  init_session_state();
36674
36746
  init_llm_auth();
@@ -40006,6 +40078,7 @@ ${result2.output ?? "(output not captured)"}`,
40006
40078
  setIntentTier(classification.tier);
40007
40079
  if (!sessionTitleRef.current) {
40008
40080
  sessionTitleRef.current = generateSessionTitle(trimmed, classification.intent);
40081
+ setTerminalTitle(sessionTitleRef.current);
40009
40082
  }
40010
40083
  const effortForTier = {
40011
40084
  light: "low",
@@ -41406,6 +41479,7 @@ var init_app = __esm({
41406
41479
  init_completion_check();
41407
41480
  init_task_list();
41408
41481
  init_text_input();
41482
+ init_terminal_title();
41409
41483
  init_update_check();
41410
41484
  init_onboarding();
41411
41485
  init_welcome();