@rallycry/conveyor-agent 5.10.3 → 5.11.1

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.
@@ -427,6 +427,23 @@ var ConveyorConnection = class _ConveyorConnection {
427
427
  triggerIdentification() {
428
428
  return triggerIdentification(this.socket);
429
429
  }
430
+ async refreshAuthToken() {
431
+ const codespaceName = process.env.CODESPACE_NAME;
432
+ const apiUrl = process.env.CONVEYOR_API_URL ?? this.config.conveyorApiUrl;
433
+ if (!codespaceName || !apiUrl) return false;
434
+ try {
435
+ const response = await fetch(`${apiUrl}/api/codespace/bootstrap/${codespaceName}`);
436
+ if (!response.ok) return false;
437
+ const config = await response.json();
438
+ if (config.envVars?.CLAUDE_CODE_OAUTH_TOKEN) {
439
+ process.env.CLAUDE_CODE_OAUTH_TOKEN = config.envVars.CLAUDE_CODE_OAUTH_TOKEN;
440
+ return true;
441
+ }
442
+ return false;
443
+ } catch {
444
+ return false;
445
+ }
446
+ }
430
447
  emitModeTransition(payload) {
431
448
  if (!this.socket) return;
432
449
  this.socket.emit("agentRunner:modeTransition", payload);
@@ -572,6 +589,10 @@ var ProjectConnection = class {
572
589
  if (!this.socket) return;
573
590
  this.socket.emit("conveyor:tagAuditResult", data);
574
591
  }
592
+ emitAuditProgress(data) {
593
+ if (!this.socket) return;
594
+ this.socket.emit("conveyor:tagAuditProgress", data);
595
+ }
575
596
  sendHeartbeat() {
576
597
  if (!this.socket) return;
577
598
  this.socket.emit("projectRunner:heartbeat", {});
@@ -838,6 +859,10 @@ async function processAssistantEvent(event, host, turnToolCalls) {
838
859
  }
839
860
  var API_ERROR_PATTERN = /API Error: [45]\d\d/;
840
861
  var IMAGE_ERROR_PATTERN = /Could not process image/i;
862
+ var AUTH_ERROR_PATTERN = /Not logged in|Please run \/login|authentication failed|invalid.*token|unauthorized/i;
863
+ function isAuthError(msg) {
864
+ return AUTH_ERROR_PATTERN.test(msg);
865
+ }
841
866
  function isRetriableMessage(msg) {
842
867
  if (IMAGE_ERROR_PATTERN.test(msg)) return true;
843
868
  if (API_ERROR_PATTERN.test(msg)) return true;
@@ -918,6 +943,10 @@ function handleErrorResult(event, host) {
918
943
  if (isStaleSession) {
919
944
  return { retriable: false, staleSession: true };
920
945
  }
946
+ if (isAuthError(errorMsg)) {
947
+ host.connection.sendEvent({ type: "error", message: errorMsg });
948
+ return { retriable: false, authError: true };
949
+ }
921
950
  const retriable = isRetriableMessage(errorMsg);
922
951
  host.connection.sendEvent({ type: "error", message: errorMsg });
923
952
  return { retriable };
@@ -957,7 +986,8 @@ async function emitResultEvent(event, host, context, startTime, lastAssistantUsa
957
986
  return {
958
987
  retriable: result.retriable,
959
988
  resultSummary: result.resultSummary,
960
- staleSession: result.staleSession
989
+ staleSession: result.staleSession,
990
+ authError: result.authError
961
991
  };
962
992
  }
963
993
  function handleRateLimitEvent(event, host) {
@@ -1057,6 +1087,7 @@ async function handleResultCase(event, host, context, startTime, isTyping, lastA
1057
1087
  retriable: resultInfo.retriable,
1058
1088
  resultSummary: resultInfo.resultSummary,
1059
1089
  staleSession: resultInfo.staleSession,
1090
+ authError: resultInfo.authError,
1060
1091
  stoppedTyping
1061
1092
  };
1062
1093
  }
@@ -1104,6 +1135,7 @@ async function processResultCase(event, host, context, startTime, state) {
1104
1135
  state.retriable = info.retriable;
1105
1136
  state.resultSummary = info.resultSummary;
1106
1137
  if (info.staleSession) state.staleSession = true;
1138
+ if (info.authError) state.authError = true;
1107
1139
  }
1108
1140
  async function processEvents(events, context, host) {
1109
1141
  const startTime = Date.now();
@@ -1117,6 +1149,7 @@ async function processEvents(events, context, host) {
1117
1149
  resultSummary: void 0,
1118
1150
  rateLimitResetsAt: void 0,
1119
1151
  staleSession: void 0,
1152
+ authError: void 0,
1120
1153
  lastAssistantUsage: void 0,
1121
1154
  turnToolCalls: []
1122
1155
  };
@@ -1156,7 +1189,8 @@ async function processEvents(events, context, host) {
1156
1189
  retriable: state.retriable || state.sawApiError,
1157
1190
  resultSummary: state.resultSummary,
1158
1191
  rateLimitResetsAt: state.rateLimitResetsAt,
1159
- ...state.staleSession && { staleSession: state.staleSession }
1192
+ ...state.staleSession && { staleSession: state.staleSession },
1193
+ ...state.authError && { authError: state.authError }
1160
1194
  };
1161
1195
  }
1162
1196
 
@@ -2357,11 +2391,14 @@ function buildCreatePullRequestTool(connection) {
2357
2391
  "Create a GitHub pull request for this task. Use this instead of gh CLI or git commands to create PRs.",
2358
2392
  {
2359
2393
  title: z.string().describe("The PR title"),
2360
- body: z.string().describe("The PR description/body in markdown")
2394
+ body: z.string().describe("The PR description/body in markdown"),
2395
+ branch: z.string().optional().describe(
2396
+ "The head branch name for the PR. If the task doesn't have a branch set, this will be used. Defaults to the task's existing branch."
2397
+ )
2361
2398
  },
2362
- async ({ title, body }) => {
2399
+ async ({ title, body, branch }) => {
2363
2400
  try {
2364
- const result = await connection.createPR({ title, body });
2401
+ const result = await connection.createPR({ title, body, branch });
2365
2402
  connection.sendEvent({
2366
2403
  type: "pr_created",
2367
2404
  url: result.url,
@@ -3108,6 +3145,29 @@ async function buildRetryQuery(host, context, options, lastErrorWasImage) {
3108
3145
  options: { ...options, resume: void 0 }
3109
3146
  });
3110
3147
  }
3148
+ async function handleAuthError(context, host, options) {
3149
+ host.connection.postChatMessage("Authentication expired. Re-bootstrapping credentials...");
3150
+ const refreshed = await host.connection.refreshAuthToken();
3151
+ if (!refreshed) {
3152
+ host.connection.postChatMessage("Failed to refresh authentication. Agent will restart.");
3153
+ host.connection.sendEvent({
3154
+ type: "error",
3155
+ message: "Auth re-bootstrap failed, exiting for restart"
3156
+ });
3157
+ process.exit(1);
3158
+ }
3159
+ context.claudeSessionId = null;
3160
+ host.connection.storeSessionId("");
3161
+ const freshPrompt = buildMultimodalPrompt(
3162
+ await buildInitialPrompt(host.config.mode, context, host.config.isAuto, host.agentMode),
3163
+ context
3164
+ );
3165
+ const freshQuery = query({
3166
+ prompt: host.createInputStream(freshPrompt),
3167
+ options: { ...options, resume: void 0 }
3168
+ });
3169
+ return runWithRetry(freshQuery, context, host, options);
3170
+ }
3111
3171
  async function handleStaleSession(context, host, options) {
3112
3172
  context.claudeSessionId = null;
3113
3173
  host.connection.storeSessionId("");
@@ -3176,26 +3236,41 @@ function handleRetryError(error, context, host, options, prevImageError) {
3176
3236
  if (isStaleOrExitedSession(error, context) && context.claudeSessionId) {
3177
3237
  return handleStaleSession(context, host, options);
3178
3238
  }
3239
+ if (isAuthError(getErrorMessage(error))) {
3240
+ return handleAuthError(context, host, options);
3241
+ }
3179
3242
  if (!isRetriableError(error)) throw error;
3180
3243
  return { action: "continue", lastErrorWasImage: classifyImageError(error) || prevImageError };
3181
3244
  }
3245
+ function handleProcessResult(result, context, host, options) {
3246
+ if (result.modeRestart || host.isStopped()) return { action: "return" };
3247
+ if (result.rateLimitResetsAt) {
3248
+ handleRateLimitPause(host, result.rateLimitResetsAt);
3249
+ return { action: "return" };
3250
+ }
3251
+ if (result.staleSession && context.claudeSessionId) {
3252
+ return { action: "return_promise", promise: handleStaleSession(context, host, options) };
3253
+ }
3254
+ if (result.authError) {
3255
+ return { action: "return_promise", promise: handleAuthError(context, host, options) };
3256
+ }
3257
+ if (!result.retriable) return { action: "return" };
3258
+ return {
3259
+ action: "continue",
3260
+ lastErrorWasImage: IMAGE_ERROR_PATTERN2.test(result.resultSummary ?? "")
3261
+ };
3262
+ }
3182
3263
  async function runWithRetry(initialQuery, context, host, options) {
3183
3264
  let lastErrorWasImage = false;
3184
3265
  for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt++) {
3185
3266
  if (host.isStopped()) return;
3186
3267
  const agentQuery = attempt === 0 ? initialQuery : await buildRetryQuery(host, context, options, lastErrorWasImage);
3187
3268
  try {
3188
- const { retriable, resultSummary, modeRestart, rateLimitResetsAt, staleSession } = await processEvents(agentQuery, context, host);
3189
- if (modeRestart || host.isStopped()) return;
3190
- if (rateLimitResetsAt) {
3191
- handleRateLimitPause(host, rateLimitResetsAt);
3192
- return;
3193
- }
3194
- if (staleSession && context.claudeSessionId) {
3195
- return handleStaleSession(context, host, options);
3196
- }
3197
- if (!retriable) return;
3198
- lastErrorWasImage = IMAGE_ERROR_PATTERN2.test(resultSummary ?? "");
3269
+ const result = await processEvents(agentQuery, context, host);
3270
+ const outcome = handleProcessResult(result, context, host, options);
3271
+ if (outcome.action === "return") return;
3272
+ if (outcome.action === "return_promise") return outcome.promise;
3273
+ lastErrorWasImage = outcome.lastErrorWasImage;
3199
3274
  } catch (error) {
3200
3275
  const outcome = handleRetryError(error, context, host, options, lastErrorWasImage);
3201
3276
  if (outcome instanceof Promise) return outcome;
@@ -4603,6 +4678,23 @@ function buildAuditSystemPrompt(projectName, tags, heatmapData, projectDir) {
4603
4678
  "Analyze actual file contents, not just file names."
4604
4679
  ].join("\n");
4605
4680
  }
4681
+ function emitToolCallProgress(event, request, connection) {
4682
+ if (event.type !== "assistant") return;
4683
+ const assistantEvent = event;
4684
+ for (const block of assistantEvent.message.content) {
4685
+ if (block.type === "tool_use" && block.name) {
4686
+ const inputStr = typeof block.input === "string" ? block.input : JSON.stringify(block.input);
4687
+ connection.emitAuditProgress({
4688
+ requestId: request.requestId,
4689
+ activity: {
4690
+ tool: block.name,
4691
+ input: inputStr.slice(0, 500),
4692
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
4693
+ }
4694
+ });
4695
+ }
4696
+ }
4697
+ }
4606
4698
  async function runAuditQuery(request, connection, projectDir) {
4607
4699
  connection.emitAgentStatus("fetching_context");
4608
4700
  let agentCtx = null;
@@ -4650,7 +4742,7 @@ async function runAuditQuery(request, connection, projectDir) {
4650
4742
  allowDangerouslySkipPermissions: true,
4651
4743
  tools: { type: "preset", preset: "claude_code" },
4652
4744
  mcpServers: { "tag-audit": createAuditMcpServer(collector, onRecommendation) },
4653
- maxTurns: settings.maxTurns ?? 30,
4745
+ maxTurns: settings.maxTurns ?? 75,
4654
4746
  maxBudgetUsd: settings.maxBudgetUsd ?? 5,
4655
4747
  effort: settings.effort,
4656
4748
  thinking: settings.thinking
@@ -4660,6 +4752,7 @@ async function runAuditQuery(request, connection, projectDir) {
4660
4752
  const turnToolCalls = [];
4661
4753
  const isTyping = { value: false };
4662
4754
  for await (const event of events) {
4755
+ emitToolCallProgress(event, request, connection);
4663
4756
  const done = processEventStream(event, connection, responseParts, turnToolCalls, isTyping);
4664
4757
  if (done) break;
4665
4758
  }
@@ -5363,4 +5456,4 @@ export {
5363
5456
  ProjectRunner,
5364
5457
  FileCache
5365
5458
  };
5366
- //# sourceMappingURL=chunk-ASK2L7IU.js.map
5459
+ //# sourceMappingURL=chunk-U3YWTVH3.js.map