@rallycry/conveyor-agent 7.0.9 → 7.0.11

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.
@@ -501,23 +501,17 @@ var ModeController = class {
501
501
  this._mode = "code-review";
502
502
  return this._mode;
503
503
  }
504
- if (this._mode === "auto") {
505
- const pastPlanning = context.status !== "Planning" && context.status !== "Unidentified";
506
- if (pastPlanning) {
507
- this.transitionToBuilding(context);
508
- return this._mode;
509
- }
504
+ if (this._mode === "auto" && this.canBypassPlanning(context)) {
505
+ this.transitionToBuilding(context);
506
+ return this._mode;
510
507
  }
511
508
  return this._mode;
512
509
  }
513
510
  /** Check if auto-mode can bypass planning (task already has plan + properties) */
514
511
  canBypassPlanning(context) {
515
512
  if (this._mode !== "auto") return false;
516
- const pastPlanning = context.status !== "Planning" && context.status !== "Unidentified";
517
- if (pastPlanning) return true;
518
- if (context.status === "Planning" && context.plan?.trim() && context.storyPointId) {
519
- return true;
520
- }
513
+ if (context.status !== "Planning") return true;
514
+ if (context.plan?.trim() && context.storyPointId) return true;
521
515
  return false;
522
516
  }
523
517
  // ── Mode transitions ───────────────────────────────────────────────
@@ -678,6 +672,28 @@ function syncWithBaseBranch(cwd, baseBranch) {
678
672
  `);
679
673
  return true;
680
674
  }
675
+ function ensureOnTaskBranch(cwd, taskBranch) {
676
+ if (!taskBranch) return true;
677
+ const current = getCurrentBranch(cwd);
678
+ if (current === taskBranch) return true;
679
+ try {
680
+ execSync(`git fetch origin ${taskBranch}`, { cwd, stdio: "ignore", timeout: 6e4 });
681
+ } catch {
682
+ process.stderr.write(`[conveyor-agent] Warning: git fetch origin ${taskBranch} failed
683
+ `);
684
+ return false;
685
+ }
686
+ try {
687
+ execSync(`git checkout ${taskBranch}`, { cwd, stdio: "ignore", timeout: 3e4 });
688
+ } catch {
689
+ process.stderr.write(`[conveyor-agent] Warning: git checkout ${taskBranch} failed
690
+ `);
691
+ return false;
692
+ }
693
+ process.stderr.write(`[conveyor-agent] Checked out task branch ${taskBranch}
694
+ `);
695
+ return true;
696
+ }
681
697
  function hasUncommittedChanges(cwd) {
682
698
  const status = execSync("git status --porcelain", {
683
699
  cwd,
@@ -941,7 +957,8 @@ var GetSuggestionsRequestSchema = z.object({
941
957
  sessionId: z.string()
942
958
  });
943
959
  var GetTaskIncidentsRequestSchema = z.object({
944
- sessionId: z.string()
960
+ sessionId: z.string(),
961
+ taskId: z.string().optional()
945
962
  });
946
963
  var CreatePullRequestRequestSchema = CreatePRInputSchema.extend({ sessionId: z.string() });
947
964
  var UpdateTaskStatusRequestSchema = z.object({
@@ -1022,7 +1039,8 @@ var UpdateTaskPropertiesRequestSchema = z.object({
1022
1039
  sessionId: z.string(),
1023
1040
  title: z.string().optional(),
1024
1041
  storyPointValue: z.number().int().positive().optional(),
1025
- tagIds: z.array(z.string()).optional()
1042
+ tagIds: z.array(z.string()).optional(),
1043
+ githubPRUrl: z.string().url().optional()
1026
1044
  });
1027
1045
  var ListIconsRequestSchema = z.object({
1028
1046
  sessionId: z.string()
@@ -2308,6 +2326,33 @@ async function resolveTaskTagContext(context) {
2308
2326
  );
2309
2327
  return injectedSection || null;
2310
2328
  }
2329
+ function formatRepoRefs(repoRefs) {
2330
+ const parts = [];
2331
+ parts.push(`
2332
+ ## Repository References`);
2333
+ for (const ref of repoRefs) {
2334
+ const icon = ref.refType === "folder" ? "folder" : "file";
2335
+ parts.push(`- [${icon}] \`${ref.path}\``);
2336
+ }
2337
+ return parts;
2338
+ }
2339
+ function formatIncidents(incidents) {
2340
+ const parts = [];
2341
+ parts.push(`
2342
+ ## Linked Incidents`);
2343
+ parts.push(
2344
+ `This task has linked incidents. Review them for context on the problem being addressed.
2345
+ `
2346
+ );
2347
+ for (const inc of incidents) {
2348
+ const severity = inc.severity ? ` [${inc.severity}]` : "";
2349
+ const status = inc.status ? ` (${inc.status})` : "";
2350
+ parts.push(`### ${inc.title}${severity}${status}`);
2351
+ if (inc.description) parts.push(inc.description);
2352
+ if (inc.source) parts.push(`Source: ${inc.source}`);
2353
+ }
2354
+ return parts;
2355
+ }
2311
2356
  async function buildTaskBody(context) {
2312
2357
  const parts = [];
2313
2358
  parts.push(`# Task: ${context.title}`);
@@ -2335,15 +2380,13 @@ ${context.plan}`);
2335
2380
  }
2336
2381
  }
2337
2382
  if (context.repoRefs && context.repoRefs.length > 0) {
2338
- parts.push(`
2339
- ## Repository References`);
2340
- for (const ref of context.repoRefs) {
2341
- const icon = ref.refType === "folder" ? "folder" : "file";
2342
- parts.push(`- [${icon}] \`${ref.path}\``);
2343
- }
2383
+ parts.push(...formatRepoRefs(context.repoRefs));
2344
2384
  }
2345
2385
  const tagSection = await resolveTaskTagContext(context);
2346
2386
  if (tagSection) parts.push(tagSection);
2387
+ if (context.incidents && context.incidents.length > 0) {
2388
+ parts.push(...formatIncidents(context.incidents));
2389
+ }
2347
2390
  if (context.chatHistory.length > 0) {
2348
2391
  parts.push(...formatChatHistory(context.chatHistory));
2349
2392
  }
@@ -3425,21 +3468,24 @@ function buildDiscoveryTools(connection) {
3425
3468
  {
3426
3469
  title: z4.string().optional().describe("The new task title"),
3427
3470
  storyPointValue: z4.number().optional().describe(SP_DESCRIPTION2),
3428
- tagIds: z4.array(z4.string()).optional().describe("Array of tag IDs to assign")
3471
+ tagIds: z4.array(z4.string()).optional().describe("Array of tag IDs to assign"),
3472
+ githubPRUrl: z4.string().url().optional().describe("GitHub pull request URL to link to this task")
3429
3473
  },
3430
- async ({ title, storyPointValue, tagIds }) => {
3474
+ async ({ title, storyPointValue, tagIds, githubPRUrl }) => {
3431
3475
  try {
3432
3476
  await connection.call("updateTaskProperties", {
3433
3477
  sessionId: connection.sessionId,
3434
3478
  title,
3435
3479
  storyPointValue,
3436
- tagIds
3480
+ tagIds,
3481
+ githubPRUrl
3437
3482
  });
3438
3483
  const updatedFields = [];
3439
3484
  if (title !== void 0) updatedFields.push(`title to "${title}"`);
3440
3485
  if (storyPointValue !== void 0)
3441
3486
  updatedFields.push(`story points to ${storyPointValue}`);
3442
3487
  if (tagIds !== void 0) updatedFields.push(`tags (${tagIds.length} tag(s))`);
3488
+ if (githubPRUrl !== void 0) updatedFields.push(`PR link to "${githubPRUrl}"`);
3443
3489
  return textResult(`Task properties updated: ${updatedFields.join(", ")}`);
3444
3490
  } catch (error) {
3445
3491
  return textResult(
@@ -5769,6 +5815,7 @@ async function emitRetryStatus(host, attempt, delayMs) {
5769
5815
  await host.callbacks.onStatusChange("running");
5770
5816
  }
5771
5817
  function handleRateLimitPause(host, rateLimitResetsAt) {
5818
+ host.wasRateLimited = true;
5772
5819
  host.connection.emitRateLimitPause(rateLimitResetsAt);
5773
5820
  host.connection.postChatMessage(
5774
5821
  `Rate limited. The task will be automatically re-queued and resume after ${new Date(rateLimitResetsAt).toLocaleString()}.`
@@ -5889,6 +5936,7 @@ var QueryBridge = class {
5889
5936
  pendingToolOutputs = [];
5890
5937
  _stopped = false;
5891
5938
  _isParentTask = false;
5939
+ _wasRateLimited = false;
5892
5940
  _abortController = null;
5893
5941
  /** Called by SessionRunner when ExitPlanMode triggers a mode transition. */
5894
5942
  onModeTransition;
@@ -5903,6 +5951,9 @@ var QueryBridge = class {
5903
5951
  set isParentTask(val) {
5904
5952
  this._isParentTask = val;
5905
5953
  }
5954
+ get wasRateLimited() {
5955
+ return this._wasRateLimited;
5956
+ }
5906
5957
  stop() {
5907
5958
  this._stopped = true;
5908
5959
  this._abortController?.abort();
@@ -5917,6 +5968,7 @@ var QueryBridge = class {
5917
5968
  */
5918
5969
  async execute(context, followUpContent) {
5919
5970
  this._stopped = false;
5971
+ this._wasRateLimited = false;
5920
5972
  this._abortController = new AbortController();
5921
5973
  const host = this.buildHost();
5922
5974
  try {
@@ -5966,6 +6018,12 @@ var QueryBridge = class {
5966
6018
  set pendingModeRestart(val) {
5967
6019
  bridge.mode.pendingModeRestart = val;
5968
6020
  },
6021
+ get wasRateLimited() {
6022
+ return bridge._wasRateLimited;
6023
+ },
6024
+ set wasRateLimited(val) {
6025
+ bridge._wasRateLimited = val;
6026
+ },
5969
6027
  get activeQuery() {
5970
6028
  return bridge.activeQuery;
5971
6029
  },
@@ -5998,6 +6056,27 @@ var QueryBridge = class {
5998
6056
  };
5999
6057
 
6000
6058
  // src/runner/session-runner.ts
6059
+ function mapChatHistory(messages) {
6060
+ if (!messages) return [];
6061
+ return messages.map((m) => ({
6062
+ role: m.role ?? "user",
6063
+ content: m.content ?? "",
6064
+ userId: m.userId,
6065
+ userName: m.user?.name ?? void 0,
6066
+ createdAt: m.createdAt,
6067
+ ...m.files && m.files.length > 0 ? {
6068
+ files: m.files.map((f) => ({
6069
+ fileId: f.id,
6070
+ fileName: f.fileName,
6071
+ mimeType: f.mimeType,
6072
+ fileSize: f.fileSize,
6073
+ downloadUrl: f.downloadUrl ?? "",
6074
+ content: f.content,
6075
+ contentEncoding: f.contentEncoding
6076
+ }))
6077
+ } : {}
6078
+ }));
6079
+ }
6001
6080
  var SessionRunner = class _SessionRunner {
6002
6081
  connection;
6003
6082
  mode;
@@ -6104,13 +6183,20 @@ var SessionRunner = class _SessionRunner {
6104
6183
  await this.shutdown("error");
6105
6184
  return;
6106
6185
  }
6186
+ if (this.fullContext?.githubBranch) {
6187
+ ensureOnTaskBranch(this.config.workspaceDir, this.fullContext.githubBranch);
6188
+ }
6107
6189
  if (this.fullContext?.baseBranch) {
6108
6190
  syncWithBaseBranch(this.config.workspaceDir, this.fullContext.baseBranch);
6109
6191
  }
6110
6192
  this.mode.resolveInitialMode(this.taskContext);
6111
6193
  this.queryBridge = this.createQueryBridge();
6112
6194
  this.logInitialization();
6195
+ const staleMessageCount = this.pendingMessages.length;
6113
6196
  await this.executeInitialMode();
6197
+ if (staleMessageCount > 0) {
6198
+ this.pendingMessages.splice(0, staleMessageCount);
6199
+ }
6114
6200
  if (!this.stopped && this._state !== "error") {
6115
6201
  this.hasCompleted = true;
6116
6202
  }
@@ -6135,14 +6221,31 @@ var SessionRunner = class _SessionRunner {
6135
6221
  await this.run();
6136
6222
  }
6137
6223
  // ── Message filtering ──────────────────────────────────────────────
6138
- /** Returns true if the message should be skipped (not processed). */
6224
+ /**
6225
+ * Returns true if the message should be skipped (not processed).
6226
+ *
6227
+ * After the agent has completed, we only process:
6228
+ * 1. Critical automated sources (e.g. CI failure) — always process
6229
+ * 2. Messages with source: "user" — real user typed in chat
6230
+ * 3. Messages from flushAllCombined — have a real userId but no source
6231
+ *
6232
+ * Everything else (system messages, stale history replays) is skipped.
6233
+ */
6139
6234
  shouldSkipMessage(msg) {
6140
- if (!this.hasCompleted || msg.userId !== "system") return false;
6235
+ if (!this.hasCompleted) return false;
6141
6236
  const isCritical = !!msg.source && CRITICAL_AUTOMATED_SOURCES.has(msg.source);
6142
6237
  if (isCritical) {
6143
6238
  this.hasCompleted = false;
6144
6239
  return false;
6145
6240
  }
6241
+ if (msg.source === "user") {
6242
+ this.hasCompleted = false;
6243
+ return false;
6244
+ }
6245
+ if (!msg.source && msg.userId !== "system") {
6246
+ this.hasCompleted = false;
6247
+ return false;
6248
+ }
6146
6249
  return true;
6147
6250
  }
6148
6251
  // ── Core loop ──────────────────────────────────────────────────────
@@ -6160,9 +6263,6 @@ var SessionRunner = class _SessionRunner {
6160
6263
  break;
6161
6264
  }
6162
6265
  if (this.shouldSkipMessage(msg)) continue;
6163
- if (msg.userId !== "system") {
6164
- this.hasCompleted = false;
6165
- }
6166
6266
  await this.setState("running");
6167
6267
  this.interrupted = false;
6168
6268
  await this.callbacks.onEvent({
@@ -6271,6 +6371,7 @@ var SessionRunner = class _SessionRunner {
6271
6371
  static MAX_PR_NUDGES = 3;
6272
6372
  needsPRNudge() {
6273
6373
  if (!this.config.isAuto || this.stopped) return false;
6374
+ if (this.queryBridge?.wasRateLimited) return false;
6274
6375
  if (this.prNudgeCount > _SessionRunner.MAX_PR_NUDGES) return false;
6275
6376
  if (!this.taskContext) return false;
6276
6377
  return this.taskContext.status === "InProgress" && !this.taskContext.githubPRUrl;
@@ -6323,24 +6424,7 @@ var SessionRunner = class _SessionRunner {
6323
6424
  }
6324
6425
  // ── Context & bridge construction ────────────────────────────────
6325
6426
  buildFullContext(ctx) {
6326
- const chatHistory = (ctx.chatHistory ?? []).map((m) => ({
6327
- role: m.role ?? "user",
6328
- content: m.content ?? "",
6329
- userId: m.userId,
6330
- userName: m.user?.name ?? void 0,
6331
- createdAt: m.createdAt,
6332
- ...m.files && m.files.length > 0 ? {
6333
- files: m.files.map((f) => ({
6334
- fileId: f.id,
6335
- fileName: f.fileName,
6336
- mimeType: f.mimeType,
6337
- fileSize: f.fileSize,
6338
- downloadUrl: f.downloadUrl ?? "",
6339
- content: f.content,
6340
- contentEncoding: f.contentEncoding
6341
- }))
6342
- } : {}
6343
- }));
6427
+ const chatHistory = mapChatHistory(ctx.chatHistory);
6344
6428
  return {
6345
6429
  taskId: ctx.id,
6346
6430
  projectId: ctx.projectId ?? "",
@@ -6349,7 +6433,8 @@ var SessionRunner = class _SessionRunner {
6349
6433
  plan: ctx.plan,
6350
6434
  status: ctx.status,
6351
6435
  chatHistory,
6352
- agentId: null,
6436
+ agentId: ctx.agentId ?? null,
6437
+ _runnerSessionId: this.sessionId,
6353
6438
  agentInstructions: ctx.agentInstructions ?? "",
6354
6439
  model: ctx.model,
6355
6440
  githubBranch: ctx.githubBranch ?? "",
@@ -6363,7 +6448,8 @@ var SessionRunner = class _SessionRunner {
6363
6448
  projectAgents: ctx.projectAgents ?? void 0,
6364
6449
  projectTags: ctx.projectTags ?? void 0,
6365
6450
  taskTagIds: ctx.taskTagIds ?? void 0,
6366
- projectObjectives: ctx.projectObjectives ?? void 0
6451
+ projectObjectives: ctx.projectObjectives ?? void 0,
6452
+ incidents: ctx.incidents ?? void 0
6367
6453
  };
6368
6454
  }
6369
6455
  createQueryBridge() {
@@ -7450,7 +7536,7 @@ var ProjectRunner = class {
7450
7536
  async handleAuditTags(request) {
7451
7537
  this.connection.emitStatus("busy");
7452
7538
  try {
7453
- const { handleTagAudit } = await import("./tag-audit-handler-4RRGIHVB.js");
7539
+ const { handleTagAudit } = await import("./tag-audit-handler-L7YPDXTA.js");
7454
7540
  await handleTagAudit(request, this.connection, this.projectDir);
7455
7541
  } catch (error) {
7456
7542
  const msg = error instanceof Error ? error.message : String(error);
@@ -7871,4 +7957,4 @@ export {
7871
7957
  loadForwardPorts,
7872
7958
  loadConveyorConfig
7873
7959
  };
7874
- //# sourceMappingURL=chunk-LKO3CBJU.js.map
7960
+ //# sourceMappingURL=chunk-OUARAX27.js.map