@rallycry/conveyor-agent 11.0.4 → 11.0.5

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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  startWorkbenchServer
3
- } from "./chunk-UBDSLM44.js";
3
+ } from "./chunk-D57S4UR5.js";
4
4
  import {
5
5
  TOMBSTONE_MESSAGE,
6
6
  isLegacyEntrypointLaunch
@@ -8,7 +8,7 @@ import {
8
8
  import {
9
9
  readAgentVersion
10
10
  } from "./chunk-XORJ6SII.js";
11
- import "./chunk-3F4ZZKCA.js";
11
+ import "./chunk-W6VILPQE.js";
12
12
  import {
13
13
  GitPrepJob,
14
14
  defaultGit,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  loadPtySpawn
3
- } from "./chunk-3F4ZZKCA.js";
3
+ } from "./chunk-W6VILPQE.js";
4
4
  import {
5
5
  terminateProcessGroup
6
6
  } from "./chunk-W4LZ7R6Z.js";
@@ -9,6 +9,7 @@ import {
9
9
  buildPromptBytes,
10
10
  buildSpawnArgs,
11
11
  cleanTerminalOutput,
12
+ ensureSessionTarget,
12
13
  inheritedEnv,
13
14
  killPtyWithEscalation,
14
15
  needsRawReadyGate,
@@ -27,7 +28,7 @@ import {
27
28
  spawnOptionsFingerprint,
28
29
  transcriptSize,
29
30
  turnOptionsFrom
30
- } from "./chunk-3F4ZZKCA.js";
31
+ } from "./chunk-W6VILPQE.js";
31
32
  import {
32
33
  AgentConnection,
33
34
  CodespacePortVisibility,
@@ -5720,13 +5721,19 @@ var PtyHarness = class _PtyHarness {
5720
5721
  }
5721
5722
  async *executeQuery(opts) {
5722
5723
  const want = opts.resume ?? opts.options.resume ?? this.parked?.reportedSessionId ?? void 0;
5723
- const fingerprint = this.fingerprintOf(opts.options);
5724
+ const options = ensureSessionTarget(opts.options, want);
5725
+ if (options !== opts.options) {
5726
+ _PtyHarness.log.warn("spawn had no session target \u2014 minted one", {
5727
+ sessionId: options.sessionId
5728
+ });
5729
+ }
5730
+ const fingerprint = this.fingerprintOf(options);
5724
5731
  let session;
5725
- if (this.parked?.canReuse(want, fingerprint) && !await this.parkedHomeDied(opts.options)) {
5732
+ if (this.parked?.canReuse(want, fingerprint) && !await this.parkedHomeDied(options)) {
5726
5733
  session = this.parked;
5727
5734
  this.parked = null;
5728
5735
  this.cancelEndedTimer();
5729
- await session.beginTurn(opts.prompt, opts.options);
5736
+ await session.beginTurn(opts.prompt, options);
5730
5737
  } else {
5731
5738
  if (this.parked) {
5732
5739
  const stale = this.parked;
@@ -5734,10 +5741,10 @@ var PtyHarness = class _PtyHarness {
5734
5741
  this.cancelEndedTimer();
5735
5742
  await stale.teardown();
5736
5743
  }
5737
- session = await this.spawnSession(opts.prompt, opts.options, want);
5744
+ session = await this.spawnSession(opts.prompt, options, want);
5738
5745
  }
5739
5746
  yield* this.drain(session);
5740
- yield* this.recoverFailedDelivery(session, opts.options, want);
5747
+ yield* this.recoverFailedDelivery(session, options, want);
5741
5748
  }
5742
5749
  /**
5743
5750
  * Did the shared `~/.claude` mount die while this session sat parked?
@@ -6768,8 +6775,8 @@ function wrapBridgeWithDirectStream(inner, reporter, options = {}) {
6768
6775
  }
6769
6776
 
6770
6777
  // src/execution/query-executor.ts
6771
- import { createHash as createHash2 } from "crypto";
6772
- import { existsSync, readFileSync as readFileSync2, truncateSync } from "fs";
6778
+ import { createHash as createHash2, randomUUID as randomUUID2 } from "crypto";
6779
+ import { existsSync, readFileSync as readFileSync2, renameSync, truncateSync } from "fs";
6773
6780
 
6774
6781
  // src/execution/chat-instructions.ts
6775
6782
  function buildChatInstructions(context, scenario, newMessages) {
@@ -7678,11 +7685,8 @@ function tagContextIntro(runnerMode) {
7678
7685
  return `These docs match this task's tags. They auto-load when you edit matching files, and you can Read any of them the moment you need its detail \u2014 do NOT read them all up front.`;
7679
7686
  }
7680
7687
  function formatResolvedTags(resolved, subProject, mentioned, runnerMode) {
7681
- const parts = [
7682
- `
7683
- ## Reference Guides (load on demand)`,
7684
- tagContextIntro(runnerMode)
7685
- ];
7688
+ const parts = [`
7689
+ ## Reference Guides (load on demand)`, tagContextIntro(runnerMode)];
7686
7690
  for (const tag of resolved) {
7687
7691
  if (tag.entries.length === 0 && !tag.hasOverview) continue;
7688
7692
  const desc = tag.description ? ` \u2014 ${tag.description}` : "";
@@ -8122,7 +8126,10 @@ function buildRelaunchWithSession(mode, context, agentMode, isAuto) {
8122
8126
  parts.push(`You were relaunched but no new instructions have been given since your last run.`);
8123
8127
  if (agentMode === "auto" || agentMode === "building" || isAuto) {
8124
8128
  parts.push(
8125
- ...builderKickoff(context, `You are the Builder on this card \u2014 pick up where you left off.`)
8129
+ ...builderKickoff(
8130
+ context,
8131
+ `You are the Builder on this card \u2014 pick up where you left off.`
8132
+ )
8126
8133
  );
8127
8134
  } else {
8128
8135
  parts.push(
@@ -9405,7 +9412,9 @@ var driveListFilesContract = defineToolContract({
9405
9412
  fields: {
9406
9413
  folderId: f.optional(f.string({ desc: `Folder to list. ${ROOT_DEFAULT}` })),
9407
9414
  search: f.optional(f.string({ desc: "Only return names containing this text", max: 200 })),
9408
- limit: f.optional(f.number({ desc: "Max entries (default 100)", int: true, min: 1, max: 200 }))
9415
+ limit: f.optional(
9416
+ f.number({ desc: "Max entries (default 100)", int: true, min: 1, max: 200 })
9417
+ )
9409
9418
  }
9410
9419
  },
9411
9420
  mcp: {
@@ -9414,7 +9423,9 @@ var driveListFilesContract = defineToolContract({
9414
9423
  projectId: mcpProjectId,
9415
9424
  folderId: f.optional(f.string({ desc: `Folder to list. ${ROOT_DEFAULT}` })),
9416
9425
  search: f.optional(f.string({ desc: "Only return names containing this text", max: 200 })),
9417
- limit: f.optional(f.number({ desc: "Max entries (default 100)", int: true, min: 1, max: 200 }))
9426
+ limit: f.optional(
9427
+ f.number({ desc: "Max entries (default 100)", int: true, min: 1, max: 200 })
9428
+ )
9418
9429
  }
9419
9430
  }
9420
9431
  });
@@ -9517,7 +9528,12 @@ var listMeetingsContract = defineToolContract({
9517
9528
  description: `List this project's meetings, newest first \u2014 each with its title, date, source, status, participants, and a short summary preview. Start here when you are asked about "the meeting", "what did we decide", or "what came out of that call". ${SUMMARY_NOTE}`,
9518
9529
  fields: {
9519
9530
  limit: f.optional(
9520
- f.number({ desc: "How many to return (default 20, maximum 50).", int: true, min: 1, max: 50 })
9531
+ f.number({
9532
+ desc: "How many to return (default 20, maximum 50).",
9533
+ int: true,
9534
+ min: 1,
9535
+ max: 50
9536
+ })
9521
9537
  ),
9522
9538
  search: f.optional(
9523
9539
  f.string({ desc: "Case-insensitive match on the meeting title.", max: 200 })
@@ -9529,7 +9545,12 @@ var listMeetingsContract = defineToolContract({
9529
9545
  fields: {
9530
9546
  projectId: mcpProjectId,
9531
9547
  limit: f.optional(
9532
- f.number({ desc: "How many to return (default 20, maximum 50).", int: true, min: 1, max: 50 })
9548
+ f.number({
9549
+ desc: "How many to return (default 20, maximum 50).",
9550
+ int: true,
9551
+ min: 1,
9552
+ max: 50
9553
+ })
9533
9554
  ),
9534
9555
  search: f.optional(
9535
9556
  f.string({ desc: "Case-insensitive match on the meeting title.", max: 200 })
@@ -9583,9 +9604,7 @@ var SINCE_MINUTES = f.optional(
9583
9604
  max: 10080
9584
9605
  })
9585
9606
  );
9586
- var START_TIME = f.optional(
9587
- f.string({ desc: "ISO 8601 lower bound (overrides sinceMinutes)" })
9588
- );
9607
+ var START_TIME = f.optional(f.string({ desc: "ISO 8601 lower bound (overrides sinceMinutes)" }));
9589
9608
  var END_TIME = f.optional(f.string({ desc: "ISO 8601 upper bound (default now)" }));
9590
9609
  var LIMIT = f.optional(
9591
9610
  f.number({ desc: "Max entries per page (default 50)", int: true, min: 1, max: 200 })
@@ -9619,7 +9638,10 @@ var gcpFields = {
9619
9638
  })
9620
9639
  ),
9621
9640
  search: f.optional(
9622
- f.string({ desc: "Free-text search across all log fields (exact substring, not regex)", max: 256 })
9641
+ f.string({
9642
+ desc: "Free-text search across all log fields (exact substring, not regex)",
9643
+ max: 256
9644
+ })
9623
9645
  ),
9624
9646
  filter: f.optional(
9625
9647
  f.string({
@@ -11246,7 +11268,9 @@ var CONTEXT_PATH_SHAPE = z18.object({
11246
11268
  locator: z18.string().min(1).max(CONTEXT_LINK_LOCATOR_MAX).regex(/^[^\r\n]*$/, "Locator cannot contain line breaks").optional().describe(
11247
11269
  'Verified-link tether: text that must keep existing in the file. With locatorType "test" it must appear inside a real it/test/describe TITLE; with "code" anywhere in the file. Validated at write time against the checkout and re-checked by the periodic sweep \u2014 a rename/delete flags the link stale. Locators containing <> are placeholders and never checked.'
11248
11270
  ),
11249
- locatorType: z18.enum(["test", "code"]).optional().describe("How the locator must match \u2014 required iff locator is set; not valid on folder links")
11271
+ locatorType: z18.enum(["test", "code"]).optional().describe(
11272
+ "How the locator must match \u2014 required iff locator is set; not valid on folder links"
11273
+ )
11250
11274
  }).refine((link) => link.locator === void 0 === (link.locatorType === void 0), {
11251
11275
  message: "locator and locatorType must be provided together"
11252
11276
  }).refine((link) => link.locator === void 0 || link.type !== "folder", {
@@ -11640,52 +11664,43 @@ function buildDriveCreateFileTool(connection, projectId) {
11640
11664
  );
11641
11665
  }
11642
11666
  function buildDriveUpdateFileTool(connection, projectId) {
11643
- return defineContractTool(
11644
- driveUpdateFileContract,
11645
- async ({ fileId, content, mimeType }) => {
11646
- try {
11647
- const file = await connection.call("updateProjectDriveFile", {
11648
- projectId,
11649
- fileId,
11650
- content,
11651
- mimeType
11652
- });
11653
- return textResult(`Updated "${file.name}" (${file.id})`);
11654
- } catch (error) {
11655
- return errText2("Failed to update the Google Drive file", error);
11656
- }
11667
+ return defineContractTool(driveUpdateFileContract, async ({ fileId, content, mimeType }) => {
11668
+ try {
11669
+ const file = await connection.call("updateProjectDriveFile", {
11670
+ projectId,
11671
+ fileId,
11672
+ content,
11673
+ mimeType
11674
+ });
11675
+ return textResult(`Updated "${file.name}" (${file.id})`);
11676
+ } catch (error) {
11677
+ return errText2("Failed to update the Google Drive file", error);
11657
11678
  }
11658
- );
11679
+ });
11659
11680
  }
11660
11681
  function buildDriveDeleteFileTool(connection, projectId) {
11661
- return defineContractTool(
11662
- driveDeleteFileContract,
11663
- async ({ fileId }) => {
11664
- try {
11665
- const result = await connection.call("deleteProjectDriveFile", { projectId, fileId });
11666
- return textResult(`Moved "${result.name}" (${result.id}) to the Google Drive trash`);
11667
- } catch (error) {
11668
- return errText2("Failed to delete the Google Drive file", error);
11669
- }
11682
+ return defineContractTool(driveDeleteFileContract, async ({ fileId }) => {
11683
+ try {
11684
+ const result = await connection.call("deleteProjectDriveFile", { projectId, fileId });
11685
+ return textResult(`Moved "${result.name}" (${result.id}) to the Google Drive trash`);
11686
+ } catch (error) {
11687
+ return errText2("Failed to delete the Google Drive file", error);
11670
11688
  }
11671
- );
11689
+ });
11672
11690
  }
11673
11691
  function buildDriveCreateFolderTool(connection, projectId) {
11674
- return defineContractTool(
11675
- driveCreateFolderContract,
11676
- async ({ name, folderId }) => {
11677
- try {
11678
- const folder = await connection.call("createProjectDriveFolder", {
11679
- projectId,
11680
- name,
11681
- folderId
11682
- });
11683
- return textResult(`Created folder "${folder.name}" (${folder.id})`);
11684
- } catch (error) {
11685
- return errText2("Failed to create the Google Drive folder", error);
11686
- }
11692
+ return defineContractTool(driveCreateFolderContract, async ({ name, folderId }) => {
11693
+ try {
11694
+ const folder = await connection.call("createProjectDriveFolder", {
11695
+ projectId,
11696
+ name,
11697
+ folderId
11698
+ });
11699
+ return textResult(`Created folder "${folder.name}" (${folder.id})`);
11700
+ } catch (error) {
11701
+ return errText2("Failed to create the Google Drive folder", error);
11687
11702
  }
11688
- );
11703
+ });
11689
11704
  }
11690
11705
  function buildDriveTools(connection, projectId) {
11691
11706
  return [
@@ -13681,6 +13696,29 @@ async function runInitialQuery(host, context, options, resume, promptDelivery) {
13681
13696
  }
13682
13697
  await trackAndRun(host, context, queryOptions, agentQuery);
13683
13698
  }
13699
+ function rotateSessionFile(cwd, sessionUuid) {
13700
+ const path = sessionTranscriptPath(cwd, sessionUuid);
13701
+ try {
13702
+ if (!existsSync(path)) return true;
13703
+ renameSync(path, `${path.replace(/\.jsonl$/, "")}.aborted-${Date.now()}.jsonl`);
13704
+ return true;
13705
+ } catch (error) {
13706
+ logger5.warn("Could not rotate an aborted transcript aside", {
13707
+ path,
13708
+ error: error instanceof Error ? error.message : String(error)
13709
+ });
13710
+ return false;
13711
+ }
13712
+ }
13713
+ function freshSessionOptions(host, context, options) {
13714
+ const lineageUuid = taskIdToSessionUuid(
13715
+ sessionLineageKey(context.taskId, host.agentMode, host.config.mode)
13716
+ );
13717
+ if (rotateSessionFile(host.config.workspaceDir, lineageUuid)) {
13718
+ return { ...options, sessionId: lineageUuid };
13719
+ }
13720
+ return { ...options, sessionId: randomUUID2() };
13721
+ }
13684
13722
  async function buildRetryQuery(host, context, options, lastErrorWasImage) {
13685
13723
  if (lastErrorWasImage) {
13686
13724
  host.connection.postChatMessage(
@@ -13700,10 +13738,7 @@ async function buildRetryQuery(host, context, options, lastErrorWasImage) {
13700
13738
  );
13701
13739
  return host.harness.executeQuery({
13702
13740
  prompt: host.createInputStream(retryPrompt),
13703
- // Strip sessionId on retry — if the failing query partially created a
13704
- // session with that ID, passing it again would error. Let the SDK
13705
- // auto-generate on retry attempts.
13706
- options: { ...options, sessionId: void 0 },
13741
+ options: freshSessionOptions(host, context, options),
13707
13742
  resume: void 0
13708
13743
  });
13709
13744
  }
@@ -13735,7 +13770,7 @@ async function handleAuthError(context, host, options) {
13735
13770
  );
13736
13771
  const freshQuery = host.harness.executeQuery({
13737
13772
  prompt: host.createInputStream(freshPrompt),
13738
- options: { ...options, sessionId: void 0 },
13773
+ options: freshSessionOptions(host, context, options),
13739
13774
  resume: void 0
13740
13775
  });
13741
13776
  return runWithRetry(freshQuery, context, host, options);
@@ -13756,7 +13791,7 @@ async function handleStaleSession(context, host, options) {
13756
13791
  );
13757
13792
  const freshQuery = host.harness.executeQuery({
13758
13793
  prompt: host.createInputStream(freshPrompt),
13759
- options: { ...options, sessionId: void 0 },
13794
+ options: freshSessionOptions(host, context, options),
13760
13795
  resume: void 0
13761
13796
  });
13762
13797
  return runWithRetry(freshQuery, context, host, options);
@@ -13856,7 +13891,7 @@ async function handleUsageCapRejection(context, host, options, rateLimitType, re
13856
13891
  );
13857
13892
  const freshQuery = host.harness.executeQuery({
13858
13893
  prompt: host.createInputStream(freshPrompt),
13859
- options: { ...options, sessionId: void 0 },
13894
+ options: freshSessionOptions(host, context, options),
13860
13895
  resume: void 0
13861
13896
  });
13862
13897
  return runWithRetry(freshQuery, context, host, options);
@@ -14654,10 +14689,8 @@ var BackgroundWorkTracker = class {
14654
14689
  this.prune(now);
14655
14690
  if (this.deadlines.length === 0) return;
14656
14691
  this.deadlines.shift();
14657
- this.log(
14658
- `[conveyor-agent] background work finished; ${this.deadlines.length} outstanding
14659
- `
14660
- );
14692
+ this.log(`[conveyor-agent] background work finished; ${this.deadlines.length} outstanding
14693
+ `);
14661
14694
  this.onChange?.();
14662
14695
  }
14663
14696
  /** Is any non-expired background work outstanding? */
@@ -14886,8 +14919,10 @@ var SessionRunner = class _SessionRunner {
14886
14919
  if (this.backgroundWork.hasPending()) holding = "background work outstanding";
14887
14920
  else if (isHeavyGateActive()) holding = "a gate process is running";
14888
14921
  } catch (err) {
14889
- process.stderr.write(`[conveyor-agent] Background-work probe failed, not deferring: ${err}
14890
- `);
14922
+ process.stderr.write(
14923
+ `[conveyor-agent] Background-work probe failed, not deferring: ${err}
14924
+ `
14925
+ );
14891
14926
  return false;
14892
14927
  }
14893
14928
  if (!holding) {
@@ -4,6 +4,7 @@ import {
4
4
  } from "./chunk-W4LZ7R6Z.js";
5
5
 
6
6
  // src/harness/pty/pty-support.ts
7
+ import { randomUUID } from "crypto";
7
8
  import { stat } from "fs/promises";
8
9
  import { tmpdir } from "os";
9
10
 
@@ -153,6 +154,10 @@ function resolvePlanDialogTiming() {
153
154
  windowMs: envMs("CONVEYOR_PTY_PLAN_DIALOG_WINDOW_MS", PLAN_DIALOG_WINDOW_MS)
154
155
  };
155
156
  }
157
+ function ensureSessionTarget(options, want, mintId = randomUUID) {
158
+ if (want || options.sessionId) return options;
159
+ return { ...options, sessionId: mintId() };
160
+ }
156
161
  function turnOptionsFrom(options) {
157
162
  return {
158
163
  canUseTool: options.canUseTool,
@@ -278,6 +283,7 @@ export {
278
283
  resolveSubmitNudgeTiming,
279
284
  resolveSubmitRedeliveryMaxAttempts,
280
285
  resolvePlanDialogTiming,
286
+ ensureSessionTarget,
281
287
  turnOptionsFrom,
282
288
  killPtyWithEscalation,
283
289
  loadPtySpawn,
package/dist/cli.js CHANGED
@@ -27,13 +27,13 @@ import {
27
27
  resolveTuiKindFromEnv,
28
28
  runUsageProbe,
29
29
  sampleKeyUsage
30
- } from "./chunk-HYPX6FEX.js";
30
+ } from "./chunk-J2NPWBVZ.js";
31
31
  import "./chunk-XORJ6SII.js";
32
32
  import {
33
33
  inheritedEnv,
34
34
  resolvePtySpawn,
35
35
  sessionTempBase
36
- } from "./chunk-3F4ZZKCA.js";
36
+ } from "./chunk-W6VILPQE.js";
37
37
  import {
38
38
  AgentConnection,
39
39
  CodespacePortVisibility,
@@ -1201,7 +1201,7 @@ function wireSpawnChildren(mode, connection, supervisors, logger7) {
1201
1201
 
1202
1202
  // src/cli.ts
1203
1203
  if (process.argv[2] === "boot") {
1204
- const { runBoot } = await import("./boot-SWUVT5B4.js");
1204
+ const { runBoot } = await import("./boot-7XH4FFLO.js");
1205
1205
  process.exit(await runBoot(process.argv.slice(3)));
1206
1206
  }
1207
1207
  if (isLegacyEntrypointLaunch(process.env)) {
@@ -1303,7 +1303,7 @@ process.on("unhandledRejection", (reason) => {
1303
1303
  process.exit(1);
1304
1304
  });
1305
1305
  if (process.env.CONVEYOR_MODE === "workbench") {
1306
- const { startWorkbenchServer } = await import("./server-7XH7RYUX.js");
1306
+ const { startWorkbenchServer } = await import("./server-2Z5V3IPA.js");
1307
1307
  const { oomWatchdogOptionsFromEnv } = await import("./oom-watchdog-PAC5OJJG.js");
1308
1308
  const { DEFAULT_WORKBENCH_PORT } = await import("./protocol-QBCYO4GI.js");
1309
1309
  const port = Number(process.env.CONVEYOR_WORKBENCH_PORT) || DEFAULT_WORKBENCH_PORT;
package/dist/gate-cli.js CHANGED
@@ -79,7 +79,9 @@ function runGate(argv, options = {}) {
79
79
  try {
80
80
  process.exitCode = await runGate(process.argv.slice(2));
81
81
  } catch (error) {
82
- process.stderr.write(`conveyor-gate: ${error instanceof Error ? error.message : String(error)}
83
- `);
82
+ process.stderr.write(
83
+ `conveyor-gate: ${error instanceof Error ? error.message : String(error)}
84
+ `
85
+ );
84
86
  process.exitCode = 2;
85
87
  }
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  SessionRunner,
3
3
  unshallowRepo
4
- } from "./chunk-HYPX6FEX.js";
4
+ } from "./chunk-J2NPWBVZ.js";
5
5
  import "./chunk-XORJ6SII.js";
6
- import "./chunk-3F4ZZKCA.js";
6
+ import "./chunk-W6VILPQE.js";
7
7
  import {
8
8
  AgentConnection,
9
9
  GIT_TIMEOUT_MS,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  startWorkbenchServer
3
- } from "./chunk-UBDSLM44.js";
4
- import "./chunk-3F4ZZKCA.js";
3
+ } from "./chunk-D57S4UR5.js";
4
+ import "./chunk-W6VILPQE.js";
5
5
  import "./chunk-W4LZ7R6Z.js";
6
6
  import "./chunk-6Q6LQBWO.js";
7
7
  import "./chunk-6W6UZ4SJ.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rallycry/conveyor-agent",
3
- "version": "11.0.4",
3
+ "version": "11.0.5",
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",