@buildautomaton/cli 0.1.77 → 0.1.78

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/cli.js CHANGED
@@ -8413,7 +8413,11 @@ var init_migrate_cli_sqlite = __esm({
8413
8413
  });
8414
8414
 
8415
8415
  // src/sqlite/cli-database.ts
8416
- var cliSqlite, safeCloseCliSqliteDatabase, closeAllCliSqliteConnections, openCliSqliteConnection, withCliSqliteSync, withCliSqlite, ensureCliSqliteInitialized;
8416
+ function closeAllCliSqliteConnections() {
8417
+ legacyImportDoneForPath = null;
8418
+ cliSqlite.closeAllConnections();
8419
+ }
8420
+ var legacyImportDoneForPath, cliSqlite, safeCloseCliSqliteDatabase, openCliSqliteConnection, withCliSqliteSync, withCliSqlite, ensureCliSqliteInitialized;
8417
8421
  var init_cli_database = __esm({
8418
8422
  "src/sqlite/cli-database.ts"() {
8419
8423
  "use strict";
@@ -8423,16 +8427,19 @@ var init_cli_database = __esm({
8423
8427
  init_import_cli_legacy_disk_data();
8424
8428
  init_migrate_cli_sqlite();
8425
8429
  init_sqlite_errors();
8430
+ legacyImportDoneForPath = null;
8426
8431
  cliSqlite = createSqliteDatabaseAccess({
8427
8432
  getPath: getCliSqlitePath,
8428
8433
  ensureParentDir: ensureCliSqliteParentDir,
8429
8434
  migrate: migrateCliSqlite,
8430
8435
  afterOpen: (db, options) => {
8436
+ const sqlitePath = getCliSqlitePath();
8437
+ if (legacyImportDoneForPath === sqlitePath) return;
8431
8438
  importCliSqliteLegacyDiskData(db, options?.logLegacyMigration);
8439
+ legacyImportDoneForPath = sqlitePath;
8432
8440
  }
8433
8441
  });
8434
8442
  safeCloseCliSqliteDatabase = cliSqlite.safeClose;
8435
- closeAllCliSqliteConnections = cliSqlite.closeAllConnections;
8436
8443
  openCliSqliteConnection = cliSqlite.openConnection;
8437
8444
  withCliSqliteSync = cliSqlite.withSync;
8438
8445
  withCliSqlite = cliSqlite.withAsync;
@@ -31064,7 +31071,7 @@ var {
31064
31071
  } = import_index.default;
31065
31072
 
31066
31073
  // src/cli-version.ts
31067
- var CLI_VERSION = "0.1.77".length > 0 ? "0.1.77" : "0.0.0-dev";
31074
+ var CLI_VERSION = "0.1.78".length > 0 ? "0.1.78" : "0.0.0-dev";
31068
31075
 
31069
31076
  // src/cli/defaults.ts
31070
31077
  var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
@@ -36801,13 +36808,15 @@ import { existsSync as existsSync4, statSync } from "node:fs";
36801
36808
  // src/git/get-git-repo-root-sync.ts
36802
36809
  import { execFileSync as execFileSync3 } from "node:child_process";
36803
36810
  import * as path28 from "node:path";
36811
+ var GIT_LOOKUP_TIMEOUT_MS = 2e3;
36804
36812
  function getGitRepoRootSync(startDir) {
36805
36813
  try {
36806
36814
  const out = execFileSync3("git", ["rev-parse", "--show-toplevel"], {
36807
36815
  cwd: path28.resolve(startDir),
36808
36816
  encoding: "utf8",
36809
36817
  stdio: ["ignore", "pipe", "ignore"],
36810
- maxBuffer: 1024 * 1024
36818
+ maxBuffer: 1024 * 1024,
36819
+ timeout: GIT_LOOKUP_TIMEOUT_MS
36811
36820
  }).trim();
36812
36821
  return out ? path28.resolve(out) : null;
36813
36822
  } catch {
@@ -36819,6 +36828,7 @@ function getGitRepoRootSync(startDir) {
36819
36828
  import { execFileSync as execFileSync4 } from "node:child_process";
36820
36829
  import { readFileSync as readFileSync4 } from "node:fs";
36821
36830
  import * as path29 from "node:path";
36831
+ var GIT_FILE_READ_TIMEOUT_MS = 2e3;
36822
36832
  function resolveWorkspaceFilePath(sessionParentPath, rawPath) {
36823
36833
  const trimmed2 = rawPath.trim();
36824
36834
  if (!trimmed2) return null;
@@ -36880,7 +36890,8 @@ function readGitHeadBlob(sessionParentPath, displayPath) {
36880
36890
  return execFileSync4("git", ["show", `HEAD:${displayPath}`], {
36881
36891
  cwd: execCwd,
36882
36892
  encoding: "utf8",
36883
- maxBuffer: 50 * 1024 * 1024
36893
+ maxBuffer: 50 * 1024 * 1024,
36894
+ timeout: GIT_FILE_READ_TIMEOUT_MS
36884
36895
  });
36885
36896
  } catch {
36886
36897
  return "";
@@ -36888,6 +36899,7 @@ function readGitHeadBlob(sessionParentPath, displayPath) {
36888
36899
  }
36889
36900
 
36890
36901
  // src/agents/acp/session-file-change-path-kind.ts
36902
+ var GIT_PATH_KIND_TIMEOUT_MS = 2e3;
36891
36903
  function gitHeadPathObjectType(sessionParentPath, displayPath) {
36892
36904
  if (!displayPath || displayPath.includes("..")) return null;
36893
36905
  const gitRoot = getGitRepoRootSync(sessionParentPath);
@@ -36895,7 +36907,8 @@ function gitHeadPathObjectType(sessionParentPath, displayPath) {
36895
36907
  try {
36896
36908
  return execFileSync5("git", ["cat-file", "-t", `HEAD:${displayPath}`], {
36897
36909
  cwd: gitRoot,
36898
- encoding: "utf8"
36910
+ encoding: "utf8",
36911
+ timeout: GIT_PATH_KIND_TIMEOUT_MS
36899
36912
  }).trim();
36900
36913
  } catch {
36901
36914
  return null;
@@ -38003,23 +38016,30 @@ function augmentPromptResultAuthFields(agentType, errorText) {
38003
38016
  }
38004
38017
 
38005
38018
  // src/agents/planning/submit-planning-todos-for-turn.ts
38019
+ var PLANNING_TODO_SUBMIT_TIMEOUT_MS = 3e3;
38006
38020
  async function submitPlanningTodosForTurn(params) {
38007
38021
  const token = params.getCloudAccessToken();
38008
38022
  if (!token.trim()) return { ok: false, error: "Missing cloud access token" };
38009
38023
  const base = params.cloudApiBaseUrl.replace(/\/$/, "");
38010
38024
  const url2 = `${base}/internal/sessions/todos/submit`;
38011
- const res = await fetch(url2, {
38012
- method: "POST",
38013
- headers: {
38014
- Authorization: `Bearer ${token}`,
38015
- "Content-Type": "application/json"
38016
- },
38017
- body: JSON.stringify({
38018
- sessionId: params.sessionId,
38019
- turnId: params.turnId,
38020
- items: params.items
38021
- })
38022
- });
38025
+ let res;
38026
+ try {
38027
+ res = await fetch(url2, {
38028
+ method: "POST",
38029
+ signal: AbortSignal.timeout(PLANNING_TODO_SUBMIT_TIMEOUT_MS),
38030
+ headers: {
38031
+ Authorization: `Bearer ${token}`,
38032
+ "Content-Type": "application/json"
38033
+ },
38034
+ body: JSON.stringify({
38035
+ sessionId: params.sessionId,
38036
+ turnId: params.turnId,
38037
+ items: params.items
38038
+ })
38039
+ });
38040
+ } catch (error40) {
38041
+ return { ok: false, error: error40 instanceof Error ? error40.message : String(error40) };
38042
+ }
38023
38043
  if (!res.ok) {
38024
38044
  const body = await res.json().catch(() => null);
38025
38045
  return { ok: false, error: body?.error ?? `Planning todo submit failed (${res.status})` };
@@ -38906,6 +38926,7 @@ async function resolveSendPromptImages(params) {
38906
38926
  }
38907
38927
 
38908
38928
  // src/agents/acp/prompts/send-prompt-to-agent.ts
38929
+ var SLOW_ACP_PROMPT_MS = 5e3;
38909
38930
  async function sendPromptToAgent(options) {
38910
38931
  const {
38911
38932
  handle,
@@ -38952,7 +38973,12 @@ async function sendPromptToAgent(options) {
38952
38973
  sendResult(imagesResolved.errorResult);
38953
38974
  return;
38954
38975
  }
38976
+ const promptStartedAt = Date.now();
38955
38977
  const result = await handle.sendPrompt(prepared.agentPromptText, imagesResolved.sendOpts);
38978
+ const promptDurationMs = Date.now() - promptStartedAt;
38979
+ if (promptDurationMs >= SLOW_ACP_PROMPT_MS) {
38980
+ log2(`[Agent] ACP session/prompt completed after ${promptDurationMs}ms.`);
38981
+ }
38956
38982
  await finalizeAndSendPromptResult({
38957
38983
  result,
38958
38984
  sessionId,
@@ -49525,9 +49551,13 @@ import * as fs50 from "node:fs";
49525
49551
  import * as path71 from "node:path";
49526
49552
 
49527
49553
  // src/git/snapshot/git.ts
49554
+ var SNAPSHOT_GIT_TIMEOUT_MS = 5e3;
49528
49555
  async function gitStashCreate(repoRoot, log2) {
49529
49556
  try {
49530
- const { stdout } = await execGitFile(["stash", "create"], { cwd: repoRoot });
49557
+ const { stdout } = await execGitFile(["stash", "create"], {
49558
+ cwd: repoRoot,
49559
+ timeout: SNAPSHOT_GIT_TIMEOUT_MS
49560
+ });
49531
49561
  return stdout.trim();
49532
49562
  } catch (e) {
49533
49563
  log2(
@@ -49538,7 +49568,10 @@ async function gitStashCreate(repoRoot, log2) {
49538
49568
  }
49539
49569
  async function gitUntrackedPaths(repoRoot, log2) {
49540
49570
  try {
49541
- const { stdout } = await execGitFile(["ls-files", "--others", "--exclude-standard"], { cwd: repoRoot });
49571
+ const { stdout } = await execGitFile(["ls-files", "--others", "--exclude-standard"], {
49572
+ cwd: repoRoot,
49573
+ timeout: SNAPSHOT_GIT_TIMEOUT_MS
49574
+ });
49542
49575
  return stdout.split("\n").map((l) => l.trim()).filter(Boolean);
49543
49576
  } catch (e) {
49544
49577
  log2(
@@ -52223,14 +52256,20 @@ async function startPromptQueueRuns(entries, deps) {
52223
52256
  }
52224
52257
 
52225
52258
  // src/prompt-turn-queue/runner/apply-prompt-queue-state-from-server.ts
52259
+ var SLOW_QUEUE_SYNC_MS = 2e3;
52226
52260
  async function applyPromptQueueStateFromServer(msg, deps) {
52227
52261
  const raw = msg.queues;
52228
52262
  if (!raw || typeof raw !== "object") return;
52263
+ const startedAt = Date.now();
52229
52264
  const entries = promptQueueSnapshotEntries(raw);
52230
52265
  await persistPromptQueueSnapshot(entries);
52231
52266
  await handlePromptQueueCancellations(entries, deps);
52232
52267
  const started = await startPromptQueueRuns(entries, deps);
52233
52268
  await dispatchStartedPromptQueueRuns(entries, started, deps);
52269
+ const durationMs = Date.now() - startedAt;
52270
+ if (durationMs >= SLOW_QUEUE_SYNC_MS) {
52271
+ deps.log(`[Queue] Queue state sync and dispatch took ${durationMs}ms.`);
52272
+ }
52234
52273
  }
52235
52274
 
52236
52275
  // src/agents/acp/from-bridge/bridge-prompt-wiring.ts
@@ -52307,59 +52346,93 @@ function parseWorktreeBaseBranches(msg) {
52307
52346
  return Object.keys(out).length > 0 ? out : void 0;
52308
52347
  }
52309
52348
 
52310
- // src/agents/acp/from-bridge/bridge-prompt-preamble.ts
52349
+ // src/agents/acp/from-bridge/parse-follow-up-prompt-fields.ts
52350
+ function parseFollowUpFieldsFromPromptMessage(msg) {
52351
+ const value = msg.followUpCatalogPromptId;
52352
+ return {
52353
+ followUpCatalogPromptId: typeof value === "string" && value.trim() !== "" ? value.trim() : null
52354
+ };
52355
+ }
52356
+
52357
+ // src/agents/acp/from-bridge/prepare-bridge-prompt-git-state.ts
52311
52358
  import { execFile as execFile8 } from "node:child_process";
52312
52359
  import { promisify as promisify9 } from "node:util";
52360
+
52361
+ // src/agents/acp/from-bridge/git-state-preparation-timeout.ts
52362
+ async function awaitGitStatePreparation(options) {
52363
+ const { label, timeoutMs, work, fallback, log: log2 } = options;
52364
+ let timer;
52365
+ try {
52366
+ return await Promise.race([
52367
+ work,
52368
+ new Promise((resolve37) => {
52369
+ timer = setTimeout(() => {
52370
+ log2(`[Agent] ${label} exceeded ${timeoutMs}ms; continuing without it.`);
52371
+ resolve37(fallback);
52372
+ }, timeoutMs);
52373
+ timer.unref?.();
52374
+ })
52375
+ ]);
52376
+ } finally {
52377
+ if (timer) clearTimeout(timer);
52378
+ }
52379
+ }
52380
+
52381
+ // src/agents/acp/from-bridge/prepare-bridge-prompt-git-state.ts
52313
52382
  var execFileAsync7 = promisify9(execFile8);
52383
+ var GIT_STATE_DISCOVERY_TIMEOUT_MS = 2e3;
52314
52384
  async function readGitBranch(cwd) {
52315
52385
  try {
52316
- const { stdout } = await execFileAsync7("git", ["branch", "--show-current"], { cwd, maxBuffer: 64 * 1024 });
52317
- const b = stdout.trim();
52318
- return b || null;
52386
+ const { stdout } = await execFileAsync7("git", ["branch", "--show-current"], {
52387
+ cwd,
52388
+ maxBuffer: 64 * 1024,
52389
+ timeout: GIT_STATE_DISCOVERY_TIMEOUT_MS
52390
+ });
52391
+ return stdout.trim() || null;
52319
52392
  } catch {
52320
52393
  return null;
52321
52394
  }
52322
52395
  }
52323
- async function runBridgePromptPreamble(params) {
52396
+ async function prepareBridgePromptGitState(params) {
52324
52397
  const { getWs, log: log2, sessionWorktreeManager, sessionId, runId, effectiveCwd } = params;
52325
- const s = getWs();
52326
- const repoCheckoutPaths = await sessionWorktreeManager.ensureRepoCheckoutPathsForSessionAsync(sessionId);
52398
+ const repoCheckoutPaths = await awaitGitStatePreparation({
52399
+ label: "Session worktree discovery",
52400
+ timeoutMs: GIT_STATE_DISCOVERY_TIMEOUT_MS,
52401
+ work: sessionWorktreeManager.ensureRepoCheckoutPathsForSessionAsync(sessionId),
52402
+ fallback: void 0,
52403
+ log: log2
52404
+ });
52327
52405
  const repoRoots = await resolveSnapshotRepoRoots({
52328
52406
  worktreePaths: repoCheckoutPaths,
52329
52407
  fallbackCwd: effectiveCwd,
52330
52408
  sessionId: sessionId?.trim() || void 0,
52331
52409
  log: log2
52332
52410
  });
52333
- if (s && sessionId) {
52334
- const usesWt = sessionWorktreeManager.usesWorktreeSession(sessionId);
52335
- const cliGitBranch = repoRoots.length > 0 ? await readGitBranch(effectiveCwd) : null;
52336
- const isolatedSessionParentPath = sessionWorktreeManager.getIsolatedSessionParentPathForSession(sessionId);
52337
- sendWsMessage(s, {
52411
+ const socket = getWs();
52412
+ if (socket && sessionId) {
52413
+ const usesWorktree = sessionWorktreeManager.usesWorktreeSession(sessionId);
52414
+ sendWsMessage(socket, {
52338
52415
  type: "session_git_context_report",
52339
52416
  sessionId,
52340
- cliGitBranch,
52341
- agentUsesWorktree: usesWt,
52342
- sessionParent: usesWt ? "worktrees_root" : "bridge_root",
52343
- sessionParentPath: usesWt ? isolatedSessionParentPath ?? effectiveCwd : getBridgeRoot()
52417
+ cliGitBranch: repoRoots.length > 0 ? await readGitBranch(effectiveCwd) : null,
52418
+ agentUsesWorktree: usesWorktree,
52419
+ sessionParent: usesWorktree ? "worktrees_root" : "bridge_root",
52420
+ sessionParentPath: usesWorktree ? sessionWorktreeManager.getIsolatedSessionParentPathForSession(sessionId) ?? effectiveCwd : getBridgeRoot()
52344
52421
  });
52345
52422
  }
52346
- if (s && sessionId && runId) {
52347
- const cap = repoRoots.length > 0 ? await capturePreTurnSnapshot({ runId, repoRoots, agentCwd: effectiveCwd, log: log2 }) : { ok: false, error: "No git repos" };
52348
- sendWsMessage(s, {
52423
+ if (socket && sessionId && runId) {
52424
+ const snapshot = repoRoots.length > 0 ? await capturePreTurnSnapshot({ runId, repoRoots, agentCwd: effectiveCwd, log: log2 }) : { ok: false };
52425
+ sendWsMessage(socket, {
52349
52426
  type: "pre_turn_snapshot_report",
52350
52427
  sessionId,
52351
52428
  turnId: runId,
52352
- captured: cap.ok
52429
+ captured: snapshot.ok
52353
52430
  });
52354
52431
  }
52355
52432
  }
52356
- function parseFollowUpFieldsFromPromptMessage(msg) {
52357
- const followUpCatalogPromptId = typeof msg.followUpCatalogPromptId === "string" && msg.followUpCatalogPromptId.trim() !== "" ? msg.followUpCatalogPromptId.trim() : null;
52358
- return { followUpCatalogPromptId };
52359
- }
52360
52433
 
52361
- // src/agents/acp/from-bridge/handle-bridge-prompt/run-preamble-and-prompt.ts
52362
- async function runPreambleAndPrompt(params) {
52434
+ // src/agents/acp/from-bridge/handle-bridge-prompt/prepare-git-state-and-run-prompt.ts
52435
+ async function prepareGitStateAndRunPrompt(params) {
52363
52436
  const {
52364
52437
  deps,
52365
52438
  msg,
@@ -52378,7 +52451,7 @@ async function runPreambleAndPrompt(params) {
52378
52451
  senders: { sendResult, sendSessionUpdate }
52379
52452
  } = params;
52380
52453
  const effectiveCwd = resolveSessionParentPathForAgentProcess(resolvedCwd);
52381
- await runBridgePromptPreamble({
52454
+ await prepareBridgePromptGitState({
52382
52455
  getWs,
52383
52456
  log: log2,
52384
52457
  sessionWorktreeManager,
@@ -52449,7 +52522,7 @@ function handleBridgePrompt(msg, deps) {
52449
52522
  sessionParentPath,
52450
52523
  ...worktreeBaseBranches ? { worktreeBaseBranches } : {}
52451
52524
  }).then(
52452
- (cwd) => runPreambleAndPrompt({
52525
+ (cwd) => prepareGitStateAndRunPrompt({
52453
52526
  deps,
52454
52527
  msg,
52455
52528
  getWs,
@@ -52468,7 +52541,7 @@ function handleBridgePrompt(msg, deps) {
52468
52541
  })
52469
52542
  ).catch((err) => {
52470
52543
  log2(`[Agent] Session parent path resolve failed: ${err instanceof Error ? err.message : String(err)}`);
52471
- void runPreambleAndPrompt({
52544
+ void prepareGitStateAndRunPrompt({
52472
52545
  deps,
52473
52546
  msg,
52474
52547
  getWs,