@rallycry/conveyor-agent 11.0.34 → 11.0.36

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.
@@ -383,8 +383,8 @@ var AgentConnection = class _AgentConnection {
383
383
  /** (Re)arm the recycle timer — called on every successful (re)connect. */
384
384
  scheduleSocketRecycle() {
385
385
  this.clearSocketRecycle();
386
- const delay2 = _AgentConnection.SOCKET_RECYCLE_BASE_MS + Math.random() * _AgentConnection.SOCKET_RECYCLE_JITTER_MS;
387
- this.armRecycleTimer(delay2);
386
+ const delay3 = _AgentConnection.SOCKET_RECYCLE_BASE_MS + Math.random() * _AgentConnection.SOCKET_RECYCLE_JITTER_MS;
387
+ this.armRecycleTimer(delay3);
388
388
  }
389
389
  clearSocketRecycle() {
390
390
  if (this.recycleTimer) {
@@ -392,11 +392,11 @@ var AgentConnection = class _AgentConnection {
392
392
  this.recycleTimer = null;
393
393
  }
394
394
  }
395
- armRecycleTimer(delay2) {
395
+ armRecycleTimer(delay3) {
396
396
  this.recycleTimer = setTimeout(() => {
397
397
  this.recycleTimer = null;
398
398
  this.attemptSocketRecycle();
399
- }, delay2);
399
+ }, delay3);
400
400
  this.recycleTimer.unref?.();
401
401
  }
402
402
  attemptSocketRecycle() {
@@ -4313,6 +4313,25 @@ async function verifyGitCredential(cwd) {
4313
4313
  // src/runner/git-utils.ts
4314
4314
  import { realpathSync } from "fs";
4315
4315
 
4316
+ // src/runner/git-fetch-retry.ts
4317
+ import { setTimeout as delay } from "timers/promises";
4318
+ async function fetchWithRetry(cwd, args) {
4319
+ for (let attempt = 0; ; attempt++) {
4320
+ try {
4321
+ return await git(cwd, ["fetch", ...args]);
4322
+ } catch (error) {
4323
+ const detail = error;
4324
+ const transient = detail.killed === true || /connection reset|could not resolve host|failed to connect|timed out|early EOF|HTTP\/2 stream|remote end hung up|TLS connection was non-properly terminated/i.test(
4325
+ `${detail.message ?? ""}
4326
+ ${detail.stderr ?? ""}`
4327
+ );
4328
+ if (!transient || attempt >= 2) throw error;
4329
+ process.stderr.write("[conveyor-agent] Retrying git fetch after a transport failure\n");
4330
+ await delay(1e3 * (attempt + 1));
4331
+ }
4332
+ }
4333
+ }
4334
+
4316
4335
  // src/runner/force-fresh-cooldown.ts
4317
4336
  var FORCE_FRESH_COOLDOWN_MS = 30 * 60 * 1e3;
4318
4337
  var blockedUntil = 0;
@@ -4340,8 +4359,7 @@ async function ensureOnTaskBranch(cwd, taskBranch, baseBranch) {
4340
4359
  if (await getCurrentBranch(cwd) === taskBranch) return true;
4341
4360
  let existsOnOrigin = true;
4342
4361
  try {
4343
- await git(cwd, [
4344
- "fetch",
4362
+ await fetchWithRetry(cwd, [
4345
4363
  "origin",
4346
4364
  `+refs/heads/${taskBranch}:refs/remotes/origin/${taskBranch}`
4347
4365
  ]);
@@ -4362,8 +4380,7 @@ async function ensureOnTaskBranch(cwd, taskBranch, baseBranch) {
4362
4380
  );
4363
4381
  return false;
4364
4382
  }
4365
- await git(cwd, [
4366
- "fetch",
4383
+ await fetchWithRetry(cwd, [
4367
4384
  "origin",
4368
4385
  `+refs/heads/${baseBranch}:refs/remotes/origin/${baseBranch}`
4369
4386
  ]);
@@ -4524,7 +4541,7 @@ async function restoreWipSnapshot(cwd, branch) {
4524
4541
  if (!branch) return "none";
4525
4542
  const ref = wipRefForBranch(branch);
4526
4543
  try {
4527
- await git(cwd, ["fetch", "origin", `+refs/heads/${ref}:refs/remotes/origin/${ref}`]);
4544
+ await fetchWithRetry(cwd, ["origin", `+refs/heads/${ref}:refs/remotes/origin/${ref}`]);
4528
4545
  } catch (err) {
4529
4546
  if (isMissingRefError(err)) return "none";
4530
4547
  wipRefPreserved.add(cwd);
@@ -4549,7 +4566,12 @@ async function restoreWipSnapshot(cwd, branch) {
4549
4566
  return "stale";
4550
4567
  }
4551
4568
  }
4552
- await git(cwd, ["stash", "apply", sha], GIT_SLOW_TIMEOUT_MS);
4569
+ try {
4570
+ await git(cwd, ["stash", "apply", sha], GIT_SLOW_TIMEOUT_MS);
4571
+ } catch {
4572
+ wipRefPreserved.add(cwd);
4573
+ return "conflict";
4574
+ }
4553
4575
  wipRefPushed.add(cwd);
4554
4576
  wipRefPreserved.delete(cwd);
4555
4577
  return "applied";
@@ -4916,11 +4938,11 @@ var Lifecycle = class {
4916
4938
  * window every time it defers. */
4917
4939
  startIdleTimer(overrideMs) {
4918
4940
  this.clearIdleTimers();
4919
- const delay2 = Math.max(0, overrideMs ?? this.config.idleTimeoutMs);
4941
+ const delay3 = Math.max(0, overrideMs ?? this.config.idleTimeoutMs);
4920
4942
  this.idleTimer = setTimeout(() => {
4921
4943
  this.idleTimer = null;
4922
4944
  this.callbacks.onIdleTimeout();
4923
- }, delay2);
4945
+ }, delay3);
4924
4946
  }
4925
4947
  cancelIdleTimer() {
4926
4948
  this.clearIdleTimers();
@@ -4941,10 +4963,10 @@ var Lifecycle = class {
4941
4963
  * deadline regardless of message volume. */
4942
4964
  startDormantTimer(overrideMs) {
4943
4965
  this.cancelDormantTimer();
4944
- const delay2 = Math.max(0, overrideMs ?? this.config.dormantTimeoutMs);
4966
+ const delay3 = Math.max(0, overrideMs ?? this.config.dormantTimeoutMs);
4945
4967
  this.dormantTimer = setTimeout(() => {
4946
4968
  this.callbacks.onDormantTimeout();
4947
- }, delay2);
4969
+ }, delay3);
4948
4970
  }
4949
4971
  cancelDormantTimer() {
4950
4972
  if (this.dormantTimer) {
@@ -4988,7 +5010,7 @@ function awaitGitReady(opts = {}) {
4988
5010
  opts.onLog?.("waiting for workspace git (workbench daemon)");
4989
5011
  return pollDaemon(clientFn, timeoutMs, pollMs, opts.onLog, opts.signal);
4990
5012
  }
4991
- function delay(ms, signal) {
5013
+ function delay2(ms, signal) {
4992
5014
  if (!signal) {
4993
5015
  return new Promise((resolve) => {
4994
5016
  setTimeout(resolve, ms);
@@ -5047,7 +5069,7 @@ async function pollDaemon(clientFn, timeoutMs, pollMs, onLog, signal) {
5047
5069
  onLog?.(`workspace git not ready after ${timeoutMs}ms \u2014 giving up`);
5048
5070
  return "timeout";
5049
5071
  }
5050
- await delay(pollMs, signal);
5072
+ await delay2(pollMs, signal);
5051
5073
  }
5052
5074
  }
5053
5075
 
@@ -97,7 +97,7 @@ import {
97
97
  statWorkspacePath,
98
98
  updateRemoteToken,
99
99
  verifyGitCredential
100
- } from "./chunk-VDK54VLS.js";
100
+ } from "./chunk-B4YQABDZ.js";
101
101
  import {
102
102
  registerBootMilestoneSocketFallback,
103
103
  reportBootMilestone
@@ -6881,7 +6881,7 @@ function buildTaskAgentPreamble(context, workspaceDir, runtimeTui, agentMode) {
6881
6881
  Environment \u2014 already built${managedStack ? " and running" : ""}. These are the facts you would otherwise spend calls discovering:`,
6882
6882
  `- The repo is cloned at your working directory with \`${context.githubBranch}\` checked out, dependencies installed, database migrated, git configured${managedStack ? ", and the dev stack up" : ""}. Commit and push directly to this branch.`,
6883
6883
  ...stackLines,
6884
- `- Browser automation is the Playwright CLI (\`playwright\`, pinned 1.62.1), NOT an MCP server \u2014 there are no \`mcp__playwright__*\` tools here. Only the headless shell is baked, so a launch must name it AND disable the sandbox: \`chromium.launch({ channel: "chromium-headless-shell", args: ["--no-sandbox"] })\`. A bare \`chromium.launch()\` FAILS: since playwright 1.49 that resolves to the full browser, which is deliberately not installed (pods have no display and cannot run Chromium's sandbox). Screenshots land wherever you write them \u2014 move or delete them before committing.`,
6884
+ `- Browser automation is the Playwright CLI (\`playwright\`, pinned 1.63.0), NOT an MCP server \u2014 there are no \`mcp__playwright__*\` tools here. Only the headless shell is baked, so a launch must name it AND disable the sandbox: \`chromium.launch({ channel: "chromium-headless-shell", args: ["--no-sandbox"] })\`. A bare \`chromium.launch()\` FAILS: since playwright 1.49 that resolves to the full browser, which is deliberately not installed (pods have no display and cannot run Chromium's sandbox). Screenshots land wherever you write them \u2014 move or delete them before committing.`,
6885
6885
  `- The clone is \`--single-branch\`, so a bare \`git fetch origin <branch>\` does NOT create \`origin/<branch>\`. To reference any other branch, use the explicit refspec: \`git fetch origin <branch>:refs/remotes/origin/<branch>\`.`,
6886
6886
  `- The shell cwd resets between Bash calls, and so does every shell variable. A var you export in one call is EMPTY in the next, which silently redirects output to \`/\` and loses it. Write literal absolute paths (\`git -C\`, \`bun run --cwd\`), and \`mkdir -p\` a directory in the SAME call as the redirect that writes to it.`,
6887
6887
  `- The \`gh\` CLI is available for READ-ONLY PR and CI state (\`gh pr view\`, \`gh pr checks\`, \`gh pr diff\`), one read at a time. ${ciWaitRule(agentMode)} Use the mcp__conveyor__* tools for anything that mutates a PR or card.`,
@@ -15380,14 +15380,18 @@ var SessionRunner = class _SessionRunner {
15380
15380
  this.fullContext.baseBranch ?? void 0
15381
15381
  );
15382
15382
  if (!ok) {
15383
- process.stderr.write("[conveyor-agent] WARNING: task-branch checkout failed\n");
15383
+ const message = "Task branch checkout failed; workspace startup stopped. Resume to retry.";
15384
+ process.stderr.write(`[conveyor-agent] ${message}
15385
+ `);
15386
+ this.connection.sendEvent({ type: "error", message });
15387
+ await this.callbacks.onEvent({ type: "error", message });
15388
+ await prewarmInitial;
15389
+ await this.shutdown("error");
15390
+ return;
15384
15391
  }
15385
- if (ok) void reportBootMilestone({ key: "branch_ready" });
15392
+ void reportBootMilestone({ key: "branch_ready" });
15386
15393
  }
15387
15394
  if (this.fullContext?.githubBranch) await this.refreshSkillsForCheckout();
15388
- if (!this.stopped) {
15389
- this.lifecycle.startGitFlush();
15390
- }
15391
15395
  if (this.fullContext?.githubBranch) {
15392
15396
  const restored = await restoreWipSnapshot(
15393
15397
  this.config.workspaceDir,
@@ -15397,7 +15401,16 @@ var SessionRunner = class _SessionRunner {
15397
15401
  process.stderr.write(`[conveyor-agent] WIP snapshot restore: ${restored}
15398
15402
  `);
15399
15403
  }
15404
+ if (restored === "failed") {
15405
+ const message = "Saved work could not be restored; workspace startup stopped. Resume to retry.";
15406
+ this.connection.sendEvent({ type: "error", message });
15407
+ await this.callbacks.onEvent({ type: "error", message });
15408
+ await prewarmInitial;
15409
+ await this.shutdown("error");
15410
+ return;
15411
+ }
15400
15412
  }
15413
+ if (!this.stopped) this.lifecycle.startGitFlush();
15401
15414
  this.workspaceCommands?.notifyWorkspaceReady();
15402
15415
  if (this.fullContext?.isAuto && PRE_BUILD_TASK_STATUSES.has(this.taskContext.status) && this.mode.isBuildCapable && hasTaskPlan(this.fullContext.plan)) {
15403
15416
  void this.connection.triggerIdentification().catch(() => {
@@ -8,7 +8,7 @@ import {
8
8
  readWorkspaceBytes,
9
9
  statWorkspacePath,
10
10
  workspacePathExists
11
- } from "./chunk-VDK54VLS.js";
11
+ } from "./chunk-B4YQABDZ.js";
12
12
  import {
13
13
  reportBootMilestone
14
14
  } from "./chunk-Q4FQOJ7D.js";
package/dist/cli.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  WorkspaceCommandSupervisor,
8
8
  startWorkspaceCommandsAfterConnect,
9
9
  stopWorkspaceCommands
10
- } from "./chunk-6WVCWKDN.js";
10
+ } from "./chunk-WQC2YQT4.js";
11
11
  import {
12
12
  PtyHarness,
13
13
  SessionRunner,
@@ -27,7 +27,7 @@ import {
27
27
  runUsageProbe,
28
28
  sampleKeyUsage,
29
29
  usesNativeUsageReporting
30
- } from "./chunk-IQP2LHB4.js";
30
+ } from "./chunk-PLDR42JP.js";
31
31
  import "./chunk-37J5MMQT.js";
32
32
  import {
33
33
  inheritedEnv,
@@ -46,7 +46,7 @@ import {
46
46
  createServiceLogger,
47
47
  fetchBootstrap,
48
48
  loadConveyorConfig
49
- } from "./chunk-VDK54VLS.js";
49
+ } from "./chunk-B4YQABDZ.js";
50
50
  import "./chunk-Q4FQOJ7D.js";
51
51
  import "./chunk-W4LZ7R6Z.js";
52
52
  import "./chunk-372R6E4C.js";
@@ -1468,7 +1468,7 @@ if (!RUNNER_MODES.includes(CONVEYOR_MODE)) {
1468
1468
  process.exit(1);
1469
1469
  }
1470
1470
  if (CONVEYOR_MODE === "serving") {
1471
- const { runServingSession } = await import("./serve-boot-QOXREHJK.js");
1471
+ const { runServingSession } = await import("./serve-boot-KXWMUVAG.js");
1472
1472
  exitContext.runnerMode = "serving";
1473
1473
  exitContext.sessionId = process.env.CONVEYOR_SESSION_ID ?? exitContext.sessionId;
1474
1474
  const outcome = await runServingSession({
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  SessionRunner,
3
3
  unshallowRepo
4
- } from "./chunk-IQP2LHB4.js";
4
+ } from "./chunk-PLDR42JP.js";
5
5
  import "./chunk-37J5MMQT.js";
6
6
  import "./chunk-EKTPDG3G.js";
7
7
  import {
@@ -17,7 +17,7 @@ import {
17
17
  stageAndCommit,
18
18
  updateRemoteToken,
19
19
  workspacePathExists
20
- } from "./chunk-VDK54VLS.js";
20
+ } from "./chunk-B4YQABDZ.js";
21
21
  import "./chunk-Q4FQOJ7D.js";
22
22
  import {
23
23
  runAuthTokenCommand,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  WorkspaceCommandSupervisor
3
- } from "./chunk-6WVCWKDN.js";
3
+ } from "./chunk-WQC2YQT4.js";
4
4
  import {
5
5
  AgentConnection,
6
6
  CodespacePortVisibility,
@@ -11,7 +11,7 @@ import {
11
11
  createServiceLogger,
12
12
  ensureOnTaskBranch,
13
13
  loadConveyorConfig
14
- } from "./chunk-VDK54VLS.js";
14
+ } from "./chunk-B4YQABDZ.js";
15
15
  import "./chunk-Q4FQOJ7D.js";
16
16
  import "./chunk-W4LZ7R6Z.js";
17
17
  import "./chunk-IA45XHOA.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rallycry/conveyor-agent",
3
- "version": "11.0.34",
3
+ "version": "11.0.36",
4
4
  "description": "Conveyor Agent Runner v10 - PTY harness for the task chat (SDK harness for audit/project-chat). Agent-as-User architecture with BaseService patterns. Works locally too.",
5
5
  "keywords": [
6
6
  "agent",
@@ -38,17 +38,17 @@
38
38
  "typecheck": "tsgo --noEmit"
39
39
  },
40
40
  "dependencies": {
41
- "@anthropic-ai/claude-agent-sdk": "^0.3.280",
42
- "@modelcontextprotocol/sdk": "^1.30.0",
43
- "node-pty": "^1.0.0",
44
- "socket.io-client": "^4.8.3",
45
- "tar": "^7.5.21",
46
- "zod": "^4.0.0"
41
+ "@anthropic-ai/claude-agent-sdk": "^0.3.283",
42
+ "@modelcontextprotocol/sdk": "^1.30.1",
43
+ "node-pty": "^1.1.0",
44
+ "socket.io-client": "^4.8.4",
45
+ "tar": "^7.5.22",
46
+ "zod": "^4.6.5"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@project/shared": "workspace:*",
50
- "tsup": "^8.0.0",
51
- "typescript": "^5.3.0",
52
- "vitest": "^5.0.1"
50
+ "tsup": "^8.5.1",
51
+ "typescript": "~6.0.3",
52
+ "vitest": "^5.0.2"
53
53
  }
54
54
  }