@rallycry/conveyor-agent 6.1.0 → 6.2.0

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.
@@ -158,6 +158,9 @@ function searchIncidents(socket, status, source) {
158
158
  function getTaskIncidents(socket, taskId) {
159
159
  return emitRpc(requireSocket(socket), "agentRunner:getTaskIncidents", { taskId });
160
160
  }
161
+ function requestScaleUp(socket, tier, reason) {
162
+ return emitRpc(requireSocket(socket), "agentRunner:scaleUp", { tier, reason });
163
+ }
161
164
 
162
165
  // src/connection/task-connection.ts
163
166
  var ConveyorConnection = class _ConveyorConnection {
@@ -165,6 +168,7 @@ var ConveyorConnection = class _ConveyorConnection {
165
168
  config;
166
169
  eventBuffer = [];
167
170
  flushTimer = null;
171
+ lastEmittedStatus = null;
168
172
  static EVENT_BATCH_MS = 500;
169
173
  earlyMessages = [];
170
174
  earlyStop = false;
@@ -252,6 +256,9 @@ var ConveyorConnection = class _ConveyorConnection {
252
256
  this.socket.io.on("reconnect", (attempt) => {
253
257
  process.stderr.write(`[conveyor] Reconnected after ${attempt} attempt(s)
254
258
  `);
259
+ if (this.socket && this.lastEmittedStatus) {
260
+ this.socket.emit("agentRunner:statusUpdate", { status: this.lastEmittedStatus });
261
+ }
255
262
  });
256
263
  this.socket.io.on("reconnect_error", (err) => {
257
264
  process.stderr.write(`[conveyor] Reconnection error: ${err.message}
@@ -296,6 +303,7 @@ var ConveyorConnection = class _ConveyorConnection {
296
303
  }
297
304
  updateStatus(status) {
298
305
  if (!this.socket) throw new Error("Not connected");
306
+ this.lastEmittedStatus = status;
299
307
  this.socket.emit("agentRunner:statusUpdate", { status });
300
308
  }
301
309
  postChatMessage(content) {
@@ -387,6 +395,7 @@ var ConveyorConnection = class _ConveyorConnection {
387
395
  }
388
396
  emitStatus(status) {
389
397
  if (!this.socket) return;
398
+ this.lastEmittedStatus = status;
390
399
  this.socket.emit("agentRunner:statusUpdate", { status });
391
400
  }
392
401
  emitRateLimitPause(resetsAt) {
@@ -497,6 +506,9 @@ var ConveyorConnection = class _ConveyorConnection {
497
506
  getTaskIncidents(taskId) {
498
507
  return getTaskIncidents(this.socket, taskId);
499
508
  }
509
+ requestScaleUp(tier, reason) {
510
+ return requestScaleUp(this.socket, tier, reason);
511
+ }
500
512
  disconnect() {
501
513
  this.flushEvents();
502
514
  this.socket?.disconnect();
@@ -617,6 +629,7 @@ var ProjectConnection = class {
617
629
  this.socket.io.on("reconnect", (attempt) => {
618
630
  process.stderr.write(`[conveyor] Project socket reconnected after ${attempt} attempt(s)
619
631
  `);
632
+ this.socket?.emit("projectRunner:heartbeat", {});
620
633
  });
621
634
  this.socket.io.on("reconnect_error", (err) => {
622
635
  process.stderr.write(`[conveyor] Project socket reconnection error: ${err.message}
@@ -957,6 +970,51 @@ function unshallowRepo(workspaceDir) {
957
970
  import { randomUUID as randomUUID2 } from "crypto";
958
971
  import { execSync as execSync5 } from "child_process";
959
972
 
973
+ // src/harness/types.ts
974
+ function defineTool(name, description, schema, handler, options) {
975
+ return {
976
+ name,
977
+ description,
978
+ schema,
979
+ handler,
980
+ annotations: options?.annotations
981
+ };
982
+ }
983
+
984
+ // src/harness/claude-code/index.ts
985
+ import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
986
+ var ClaudeCodeHarness = class {
987
+ async *executeQuery(opts) {
988
+ const sdkEvents = query({
989
+ prompt: opts.prompt,
990
+ options: {
991
+ ...opts.options,
992
+ ...opts.resume ? { resume: opts.resume } : {}
993
+ }
994
+ });
995
+ for await (const event of sdkEvents) {
996
+ yield event;
997
+ }
998
+ }
999
+ createMcpServer(config) {
1000
+ const sdkTools = config.tools.map(
1001
+ (t) => tool(
1002
+ t.name,
1003
+ t.description,
1004
+ t.schema,
1005
+ t.handler,
1006
+ t.annotations ? { annotations: t.annotations } : void 0
1007
+ )
1008
+ );
1009
+ return createSdkMcpServer({ name: config.name, tools: sdkTools });
1010
+ }
1011
+ };
1012
+
1013
+ // src/harness/index.ts
1014
+ function createHarness() {
1015
+ return new ClaudeCodeHarness();
1016
+ }
1017
+
960
1018
  // src/connection/tunnel-client.ts
961
1019
  import { request as httpRequest } from "http";
962
1020
  var logger2 = createServiceLogger("TunnelClient");
@@ -1229,11 +1287,11 @@ async function processAssistantEvent(event, host, turnToolCalls) {
1229
1287
  const { content } = event.message;
1230
1288
  const turnTextParts = [];
1231
1289
  for (const block of content) {
1232
- if (block.type === "text") {
1290
+ if (block.type === "text" && block.text) {
1233
1291
  turnTextParts.push(block.text);
1234
1292
  host.connection.sendEvent({ type: "message", content: block.text });
1235
1293
  await host.callbacks.onEvent({ type: "message", content: block.text });
1236
- } else if (block.type === "tool_use") {
1294
+ } else if (block.type === "tool_use" && block.name) {
1237
1295
  const inputStr = typeof block.input === "string" ? block.input : JSON.stringify(block.input);
1238
1296
  const isContentTool = ["edit", "write"].includes(block.name.toLowerCase());
1239
1297
  const inputLimit = isContentTool ? 1e4 : 500;
@@ -1322,7 +1380,9 @@ function handleSuccessResult(event, host, context, startTime, lastAssistantUsage
1322
1380
  const cumulativeTotal = host.costTracker.addQueryCost(event.total_cost_usd);
1323
1381
  const { modelUsage } = event;
1324
1382
  if (modelUsage && typeof modelUsage === "object") {
1325
- host.costTracker.addModelUsage(modelUsage);
1383
+ host.costTracker.addModelUsage(
1384
+ modelUsage
1385
+ );
1326
1386
  }
1327
1387
  host.connection.sendEvent({ type: "completed", summary, costUsd: cumulativeTotal, durationMs });
1328
1388
  if (modelUsage && typeof modelUsage === "object") {
@@ -1603,11 +1663,6 @@ async function processEvents(events, context, host) {
1603
1663
  };
1604
1664
  }
1605
1665
 
1606
- // src/execution/query-executor.ts
1607
- import {
1608
- query
1609
- } from "@anthropic-ai/claude-agent-sdk";
1610
-
1611
1666
  // src/execution/pack-runner-prompt.ts
1612
1667
  function findLastAgentMessageIndex(history) {
1613
1668
  for (let i = history.length - 1; i >= 0; i--) {
@@ -2018,8 +2073,8 @@ function buildModePrompt(agentMode, context) {
2018
2073
  switch (agentMode) {
2019
2074
  case "discovery":
2020
2075
  return buildDiscoveryPrompt(context);
2021
- case "building":
2022
- return [
2076
+ case "building": {
2077
+ const parts = [
2023
2078
  `
2024
2079
  ## Mode: Building`,
2025
2080
  `You are in Building mode \u2014 executing the plan.`,
@@ -2027,7 +2082,22 @@ function buildModePrompt(agentMode, context) {
2027
2082
  `- Safety rules: no destructive operations, use --force-with-lease instead of --force`,
2028
2083
  `- If this is a leaf task (no children): execute the plan directly`,
2029
2084
  `- Goal: implement the plan, run tests, open a PR when done`
2030
- ].join("\n");
2085
+ ];
2086
+ if (process.env.CLAUDESPACE_NAME) {
2087
+ parts.push(
2088
+ ``,
2089
+ `### Resource Management`,
2090
+ `Your pod starts with minimal resources (0.25 CPU / 1 Gi). Before running resource-intensive`,
2091
+ `operations, use the \`scale_up_resources\` tool to request more capacity:`,
2092
+ `- **light** (1 CPU / 4 Gi) \u2014 package installs, basic dev servers, light builds`,
2093
+ `- **standard** (2 CPU / 8 Gi) \u2014 full dev servers, test suites, typecheck, lint`,
2094
+ `- **heavy** (4 CPU / 16 Gi) \u2014 E2E/browser automation, large parallel builds`,
2095
+ `Scaling is one-way (up only) and capped by project limits. If you forget to scale,`,
2096
+ `operations may be slow or OOM \u2014 scale up proactively before running builds or tests.`
2097
+ );
2098
+ }
2099
+ return parts.join("\n");
2100
+ }
2031
2101
  case "review":
2032
2102
  return [
2033
2103
  `
@@ -2632,11 +2702,7 @@ async function buildInitialPrompt(mode, context, isAuto, agentMode) {
2632
2702
  return [...body, ...instructions].join("\n");
2633
2703
  }
2634
2704
 
2635
- // src/tools/index.ts
2636
- import { createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
2637
-
2638
2705
  // src/tools/common-tools.ts
2639
- import { tool } from "@anthropic-ai/claude-agent-sdk";
2640
2706
  import { z } from "zod";
2641
2707
  function isImageMimeType(mimeType) {
2642
2708
  return mimeType.startsWith("image/");
@@ -2657,7 +2723,7 @@ function formatCliEvent(e) {
2657
2723
  return formatter ? formatter(e) : JSON.stringify(e);
2658
2724
  }
2659
2725
  function buildReadTaskChatTool(connection) {
2660
- return tool(
2726
+ return defineTool(
2661
2727
  "read_task_chat",
2662
2728
  "Read recent messages from a task chat. Omit task_id to read the current task's chat, or provide a child task ID to read a child's chat.",
2663
2729
  {
@@ -2680,7 +2746,7 @@ function buildReadTaskChatTool(connection) {
2680
2746
  );
2681
2747
  }
2682
2748
  function buildPostToChatTool(connection) {
2683
- return tool(
2749
+ return defineTool(
2684
2750
  "post_to_chat",
2685
2751
  "Post a message to a task chat. Your normal replies already appear in chat \u2014 only use this for explicit out-of-band updates or posting to a child task's chat.",
2686
2752
  {
@@ -2704,7 +2770,7 @@ function buildPostToChatTool(connection) {
2704
2770
  );
2705
2771
  }
2706
2772
  function buildForceUpdateTaskStatusTool(connection) {
2707
- return tool(
2773
+ return defineTool(
2708
2774
  "force_update_task_status",
2709
2775
  "EMERGENCY ONLY: Force-override a task's Kanban status. Status transitions happen automatically (building sets InProgress, PR creation sets ReviewPR, merge sets ReviewDev). Only use this if an automatic transition failed or a task is stuck in the wrong status. Omit task_id to update the current task, or provide a child task ID.",
2710
2776
  {
@@ -2728,7 +2794,7 @@ function buildForceUpdateTaskStatusTool(connection) {
2728
2794
  );
2729
2795
  }
2730
2796
  function buildGetTaskPlanTool(connection, config) {
2731
- return tool(
2797
+ return defineTool(
2732
2798
  "get_task_plan",
2733
2799
  "Re-read the latest task plan in case it was updated",
2734
2800
  {},
@@ -2744,7 +2810,7 @@ function buildGetTaskPlanTool(connection, config) {
2744
2810
  );
2745
2811
  }
2746
2812
  function buildGetTaskTool(connection) {
2747
- return tool(
2813
+ return defineTool(
2748
2814
  "get_task",
2749
2815
  "Look up a task by slug or ID to get its title, description, plan, and status",
2750
2816
  {
@@ -2764,7 +2830,7 @@ function buildGetTaskTool(connection) {
2764
2830
  );
2765
2831
  }
2766
2832
  function buildGetTaskCliTool(connection) {
2767
- return tool(
2833
+ return defineTool(
2768
2834
  "get_task_cli",
2769
2835
  "Read CLI execution logs from a task. Returns agent reasoning, tool calls, setup output, and other execution events. Use 'source' to filter: 'agent' for agent reasoning/tool calls only, 'application' for setup/dev-server output only.",
2770
2836
  {
@@ -2792,7 +2858,7 @@ function buildGetTaskCliTool(connection) {
2792
2858
  );
2793
2859
  }
2794
2860
  function buildListTaskFilesTool(connection) {
2795
- return tool(
2861
+ return defineTool(
2796
2862
  "list_task_files",
2797
2863
  "List all files attached to this task with metadata (name, type, size) and download URLs",
2798
2864
  {},
@@ -2817,7 +2883,7 @@ function buildListTaskFilesTool(connection) {
2817
2883
  );
2818
2884
  }
2819
2885
  function buildGetTaskFileTool(connection) {
2820
- return tool(
2886
+ return defineTool(
2821
2887
  "get_task_file",
2822
2888
  "Get a specific task file's content and download URL by file ID",
2823
2889
  { fileId: z.string().describe("The file ID to retrieve") },
@@ -2844,7 +2910,7 @@ function buildGetTaskFileTool(connection) {
2844
2910
  );
2845
2911
  }
2846
2912
  function buildSearchIncidentsTool(connection) {
2847
- return tool(
2913
+ return defineTool(
2848
2914
  "search_incidents",
2849
2915
  "Search incidents in the current project. Optionally filter by status (Open, Acknowledged, Investigating, Resolved, Closed) or source.",
2850
2916
  {
@@ -2865,7 +2931,7 @@ function buildSearchIncidentsTool(connection) {
2865
2931
  );
2866
2932
  }
2867
2933
  function buildGetTaskIncidentsTool(connection) {
2868
- return tool(
2934
+ return defineTool(
2869
2935
  "get_task_incidents",
2870
2936
  "Get all incidents linked to the current task (or a specified task). Returns full incident details including title, description, severity, status, and source.",
2871
2937
  {
@@ -2885,7 +2951,7 @@ function buildGetTaskIncidentsTool(connection) {
2885
2951
  );
2886
2952
  }
2887
2953
  function buildCreatePullRequestTool(connection) {
2888
- return tool(
2954
+ return defineTool(
2889
2955
  "create_pull_request",
2890
2956
  "Create a GitHub pull request for this task. Use this instead of gh CLI or git commands to create PRs.",
2891
2957
  {
@@ -2911,8 +2977,40 @@ function buildCreatePullRequestTool(connection) {
2911
2977
  }
2912
2978
  );
2913
2979
  }
2980
+ function buildScaleUpResourcesTool(connection) {
2981
+ return defineTool(
2982
+ "scale_up_resources",
2983
+ "Scale up the pod's CPU and memory resources. Use before running dev servers, tests, builds, or other resource-intensive operations. Tiers: 'light' (1 CPU / 4 Gi \u2014 installs, basic dev servers), 'standard' (2 CPU / 8 Gi \u2014 full dev servers, test suites, typecheck), 'heavy' (4 CPU / 16 Gi \u2014 E2E tests, large parallel builds). Scaling is one-way (up only) and capped by project limits.",
2984
+ {
2985
+ tier: z.enum(["light", "standard", "heavy"]).describe("The resource tier to scale up to"),
2986
+ reason: z.string().optional().describe("Brief reason for scaling (e.g., 'running test suite')")
2987
+ },
2988
+ async ({ tier, reason }) => {
2989
+ try {
2990
+ const result = await connection.requestScaleUp(tier, reason);
2991
+ if (result.success) {
2992
+ if (result.currentTier === result.previousTier) {
2993
+ return textResult(
2994
+ `Already at ${result.currentTier} tier (${result.cpu} CPU / ${result.memory} Gi). No scaling needed.`
2995
+ );
2996
+ }
2997
+ return textResult(
2998
+ `Scaled to ${result.cpu} CPU / ${result.memory} Gi (${result.currentTier} tier, was ${result.previousTier}).`
2999
+ );
3000
+ }
3001
+ return textResult(
3002
+ `Scale-up not available: ${result.error ?? "unknown error"}. Continuing at current resources.`
3003
+ );
3004
+ } catch (error) {
3005
+ return textResult(
3006
+ `Scale-up failed: ${error instanceof Error ? error.message : "unknown error"}. Continuing at current resources.`
3007
+ );
3008
+ }
3009
+ }
3010
+ );
3011
+ }
2914
3012
  function buildCommonTools(connection, config) {
2915
- return [
3013
+ const tools = [
2916
3014
  buildReadTaskChatTool(connection),
2917
3015
  buildPostToChatTool(connection),
2918
3016
  buildGetTaskPlanTool(connection, config),
@@ -2924,10 +3022,13 @@ function buildCommonTools(connection, config) {
2924
3022
  buildGetTaskIncidentsTool(connection),
2925
3023
  buildCreatePullRequestTool(connection)
2926
3024
  ];
3025
+ if (process.env.CLAUDESPACE_NAME) {
3026
+ tools.push(buildScaleUpResourcesTool(connection));
3027
+ }
3028
+ return tools;
2927
3029
  }
2928
3030
 
2929
3031
  // src/tools/pm-tools.ts
2930
- import { tool as tool2 } from "@anthropic-ai/claude-agent-sdk";
2931
3032
  import { z as z2 } from "zod";
2932
3033
  function buildStoryPointDescription(storyPoints) {
2933
3034
  if (storyPoints && storyPoints.length > 0) {
@@ -2938,7 +3039,7 @@ function buildStoryPointDescription(storyPoints) {
2938
3039
  }
2939
3040
  function buildSubtaskTools(connection, spDescription) {
2940
3041
  return [
2941
- tool2(
3042
+ defineTool(
2942
3043
  "create_subtask",
2943
3044
  "Create a subtask under the current parent task. Use for breaking complex tasks into smaller pieces.",
2944
3045
  {
@@ -2959,7 +3060,7 @@ function buildSubtaskTools(connection, spDescription) {
2959
3060
  }
2960
3061
  }
2961
3062
  ),
2962
- tool2(
3063
+ defineTool(
2963
3064
  "update_subtask",
2964
3065
  "Update an existing subtask's fields",
2965
3066
  {
@@ -2979,7 +3080,7 @@ function buildSubtaskTools(connection, spDescription) {
2979
3080
  }
2980
3081
  }
2981
3082
  ),
2982
- tool2(
3083
+ defineTool(
2983
3084
  "delete_subtask",
2984
3085
  "Delete a subtask",
2985
3086
  { subtaskId: z2.string().describe("The subtask ID to delete") },
@@ -2992,7 +3093,7 @@ function buildSubtaskTools(connection, spDescription) {
2992
3093
  }
2993
3094
  }
2994
3095
  ),
2995
- tool2(
3096
+ defineTool(
2996
3097
  "list_subtasks",
2997
3098
  "List all subtasks under the current parent task. Returns status, PR info (githubPRNumber, githubPRUrl), agent assignment (agentId), and plan for each child.",
2998
3099
  {},
@@ -3009,7 +3110,7 @@ function buildSubtaskTools(connection, spDescription) {
3009
3110
  ];
3010
3111
  }
3011
3112
  function buildUpdateTaskTool(connection) {
3012
- return tool2(
3113
+ return defineTool(
3013
3114
  "update_task",
3014
3115
  "Save the finalized task plan and/or description",
3015
3116
  {
@@ -3034,7 +3135,7 @@ function buildPmTools(connection, storyPoints, options) {
3034
3135
  }
3035
3136
  function buildPackTools(connection) {
3036
3137
  return [
3037
- tool2(
3138
+ defineTool(
3038
3139
  "start_child_cloud_build",
3039
3140
  "Start a cloud build for a child task. The child must be in Open status with story points and an agent assigned.",
3040
3141
  {
@@ -3051,7 +3152,7 @@ function buildPackTools(connection) {
3051
3152
  }
3052
3153
  }
3053
3154
  ),
3054
- tool2(
3155
+ defineTool(
3055
3156
  "stop_child_build",
3056
3157
  "Stop a running cloud build for a child task. Sends a stop signal to the child agent.",
3057
3158
  {
@@ -3068,7 +3169,7 @@ function buildPackTools(connection) {
3068
3169
  }
3069
3170
  }
3070
3171
  ),
3071
- tool2(
3172
+ defineTool(
3072
3173
  "approve_and_merge_pr",
3073
3174
  "Approve and merge a child task's pull request. Only succeeds if all CI/CD checks are passing. Returns an error if checks are pending (retry after waiting) or failed (investigate). The child task must be in ReviewPR status.",
3074
3175
  {
@@ -3096,11 +3197,10 @@ function buildPackTools(connection) {
3096
3197
  }
3097
3198
 
3098
3199
  // src/tools/discovery-tools.ts
3099
- import { tool as tool3 } from "@anthropic-ai/claude-agent-sdk";
3100
3200
  import { z as z3 } from "zod";
3101
3201
  function buildIconTools(connection) {
3102
3202
  return [
3103
- tool3(
3203
+ defineTool(
3104
3204
  "list_icons",
3105
3205
  "List available icons (default library + user-created). Returns icon IDs, names, and whether they're defaults. Call this FIRST before update_task_properties to check for existing matches.",
3106
3206
  {},
@@ -3116,7 +3216,7 @@ function buildIconTools(connection) {
3116
3216
  },
3117
3217
  { annotations: { readOnlyHint: true } }
3118
3218
  ),
3119
- tool3(
3219
+ defineTool(
3120
3220
  "generate_task_icon",
3121
3221
  "Generate a new SVG icon using AI and assign it to this task. Only use if no existing icon from list_icons is a good fit. Provide a concise visual description.",
3122
3222
  {
@@ -3141,7 +3241,7 @@ function buildIconTools(connection) {
3141
3241
  function buildDiscoveryTools(connection, context) {
3142
3242
  const spDescription = buildStoryPointDescription(context?.storyPoints);
3143
3243
  return [
3144
- tool3(
3244
+ defineTool(
3145
3245
  "update_task_properties",
3146
3246
  "Set one or more task properties in a single call. All fields are optional \u2014 only include the fields you want to update.",
3147
3247
  {
@@ -3177,11 +3277,9 @@ function buildDiscoveryTools(connection, context) {
3177
3277
  }
3178
3278
 
3179
3279
  // src/tools/debug-tools.ts
3180
- import { tool as tool6 } from "@anthropic-ai/claude-agent-sdk";
3181
3280
  import { z as z6 } from "zod";
3182
3281
 
3183
3282
  // src/tools/telemetry-tools.ts
3184
- import { tool as tool4 } from "@anthropic-ai/claude-agent-sdk";
3185
3283
  import { z as z4 } from "zod";
3186
3284
 
3187
3285
  // src/debug/telemetry-injector.ts
@@ -3573,7 +3671,7 @@ function formatError(error) {
3573
3671
  return error instanceof Error ? error.message : "Unknown error";
3574
3672
  }
3575
3673
  function buildGetTelemetryTool(manager) {
3576
- return tool4(
3674
+ return defineTool(
3577
3675
  "debug_get_telemetry",
3578
3676
  "Query structured telemetry events (HTTP requests, database queries, Socket.IO events, errors) captured from the running dev server. Returns filtered, structured data instead of raw logs.",
3579
3677
  {
@@ -3609,7 +3707,7 @@ function buildGetTelemetryTool(manager) {
3609
3707
  );
3610
3708
  }
3611
3709
  function buildClearTelemetryTool(manager) {
3612
- return tool4(
3710
+ return defineTool(
3613
3711
  "debug_clear_telemetry",
3614
3712
  "Clear all captured telemetry events from the buffer. Useful to reset before reproducing a specific issue.",
3615
3713
  {},
@@ -3626,7 +3724,7 @@ function buildClearTelemetryTool(manager) {
3626
3724
  );
3627
3725
  }
3628
3726
  function buildTelemetryStatusTool(manager) {
3629
- return tool4(
3727
+ return defineTool(
3630
3728
  "debug_telemetry_status",
3631
3729
  "Check if telemetry is active, how many events have been captured, and which framework patches (Express, Prisma, Socket.IO) were successfully applied.",
3632
3730
  {},
@@ -3652,7 +3750,6 @@ function buildTelemetryTools(manager) {
3652
3750
  }
3653
3751
 
3654
3752
  // src/tools/client-debug-tools.ts
3655
- import { tool as tool5 } from "@anthropic-ai/claude-agent-sdk";
3656
3753
  import { z as z5 } from "zod";
3657
3754
  function requirePlaywrightClient(manager) {
3658
3755
  if (!manager.isClientDebugMode()) {
@@ -3669,7 +3766,7 @@ function formatError2(error) {
3669
3766
  }
3670
3767
  function buildClientBreakpointTools(manager) {
3671
3768
  return [
3672
- tool5(
3769
+ defineTool(
3673
3770
  "debug_set_client_breakpoint",
3674
3771
  "Set a breakpoint in client-side code running in the headless Chromium browser. V8 resolves source maps automatically, so original .tsx/.ts file paths work. Use this for React components, client utilities, and browser-side code.",
3675
3772
  {
@@ -3695,7 +3792,7 @@ Breakpoint ID: ${breakpointId}${sourceMapNote}`
3695
3792
  }
3696
3793
  }
3697
3794
  ),
3698
- tool5(
3795
+ defineTool(
3699
3796
  "debug_remove_client_breakpoint",
3700
3797
  "Remove a previously set client-side breakpoint by its ID.",
3701
3798
  {
@@ -3712,7 +3809,7 @@ Breakpoint ID: ${breakpointId}${sourceMapNote}`
3712
3809
  }
3713
3810
  }
3714
3811
  ),
3715
- tool5(
3812
+ defineTool(
3716
3813
  "debug_list_client_breakpoints",
3717
3814
  "List all active client-side breakpoints with their file, line, and condition.",
3718
3815
  {},
@@ -3732,7 +3829,7 @@ Breakpoint ID: ${breakpointId}${sourceMapNote}`
3732
3829
  }
3733
3830
  function buildClientInspectionTools(manager) {
3734
3831
  return [
3735
- tool5(
3832
+ defineTool(
3736
3833
  "debug_inspect_client_paused",
3737
3834
  "When the client-side debugger is paused at a breakpoint, returns the call stack and local variables. Includes React component state, props, and hooks when paused inside a component.",
3738
3835
  {},
@@ -3775,7 +3872,7 @@ ${JSON.stringify(queuedHits, null, 2)}`
3775
3872
  },
3776
3873
  { annotations: { readOnlyHint: true } }
3777
3874
  ),
3778
- tool5(
3875
+ defineTool(
3779
3876
  "debug_evaluate_client",
3780
3877
  "Evaluate a JavaScript expression in the client-side browser context. When paused at a client breakpoint, evaluates in the paused scope. Can access DOM, window, React internals, etc.",
3781
3878
  {
@@ -3803,7 +3900,7 @@ ${JSON.stringify(queuedHits, null, 2)}`
3803
3900
  }
3804
3901
  function buildClientExecutionTools(manager) {
3805
3902
  return [
3806
- tool5(
3903
+ defineTool(
3807
3904
  "debug_continue_client",
3808
3905
  "Resume client-side execution after the browser debugger has paused at a breakpoint.",
3809
3906
  {},
@@ -3825,7 +3922,7 @@ function buildClientExecutionTools(manager) {
3825
3922
  }
3826
3923
  function buildClientInteractionTools(manager) {
3827
3924
  return [
3828
- tool5(
3925
+ defineTool(
3829
3926
  "debug_client_screenshot",
3830
3927
  "Take a screenshot of the current page state in the headless browser. Returns the image as base64-encoded PNG.",
3831
3928
  {},
@@ -3849,7 +3946,7 @@ function buildClientInteractionTools(manager) {
3849
3946
  },
3850
3947
  { annotations: { readOnlyHint: true } }
3851
3948
  ),
3852
- tool5(
3949
+ defineTool(
3853
3950
  "debug_navigate_client",
3854
3951
  "Navigate the headless browser to a specific URL. Use this to reproduce specific flows or visit different pages.",
3855
3952
  {
@@ -3866,7 +3963,7 @@ function buildClientInteractionTools(manager) {
3866
3963
  }
3867
3964
  }
3868
3965
  ),
3869
- tool5(
3966
+ defineTool(
3870
3967
  "debug_click_client",
3871
3968
  "Click an element on the page in the headless browser. Use CSS selectors to target elements. Useful for reproducing bugs by interacting with the UI programmatically.",
3872
3969
  {
@@ -3888,7 +3985,7 @@ function buildClientInteractionTools(manager) {
3888
3985
  ];
3889
3986
  }
3890
3987
  function buildClientConsoleTool(manager) {
3891
- return tool5(
3988
+ return defineTool(
3892
3989
  "debug_get_client_console",
3893
3990
  "Get console messages captured from the headless browser. Includes console.log, warn, error, etc.",
3894
3991
  {
@@ -3916,7 +4013,7 @@ ${formatted}`);
3916
4013
  );
3917
4014
  }
3918
4015
  function buildClientNetworkTool(manager) {
3919
- return tool5(
4016
+ return defineTool(
3920
4017
  "debug_get_client_network",
3921
4018
  "Get network requests captured from the headless browser. Shows URLs, methods, status codes, and timing.",
3922
4019
  {
@@ -3945,7 +4042,7 @@ ${formatted}`);
3945
4042
  );
3946
4043
  }
3947
4044
  function buildClientErrorsTool(manager) {
3948
- return tool5(
4045
+ return defineTool(
3949
4046
  "debug_get_client_errors",
3950
4047
  "Get uncaught errors captured from the headless browser. Includes error messages and source-mapped stack traces.",
3951
4048
  {
@@ -4039,7 +4136,7 @@ Set breakpoints to test your hypothesis.${sourceMapWarning}` : `Debug mode activ
4039
4136
  }
4040
4137
  function buildDebugLifecycleTools(manager) {
4041
4138
  return [
4042
- tool6(
4139
+ defineTool(
4043
4140
  "debug_enter_mode",
4044
4141
  "Activate debug mode: restarts the dev server with Node.js --inspect flag and connects the CDP debugger. Optionally launch a headless Chromium browser for client-side debugging. Use serverSide for backend breakpoints, clientSide for frontend breakpoints, or both for full-stack.",
4045
4142
  {
@@ -4060,7 +4157,7 @@ function buildDebugLifecycleTools(manager) {
4060
4157
  }
4061
4158
  }
4062
4159
  ),
4063
- tool6(
4160
+ defineTool(
4064
4161
  "debug_exit_mode",
4065
4162
  "Exit debug mode: removes all breakpoints, disconnects the debugger, and restarts the dev server normally.",
4066
4163
  {},
@@ -4080,7 +4177,7 @@ function buildDebugLifecycleTools(manager) {
4080
4177
  }
4081
4178
  function buildBreakpointTools(manager) {
4082
4179
  return [
4083
- tool6(
4180
+ defineTool(
4084
4181
  "debug_set_breakpoint",
4085
4182
  "Set a breakpoint at the specified file and line number. Optionally provide a condition expression that must evaluate to true for the breakpoint to pause execution.",
4086
4183
  {
@@ -4104,7 +4201,7 @@ Breakpoint ID: ${breakpointId}`
4104
4201
  }
4105
4202
  }
4106
4203
  ),
4107
- tool6(
4204
+ defineTool(
4108
4205
  "debug_remove_breakpoint",
4109
4206
  "Remove a previously set breakpoint by its ID.",
4110
4207
  {
@@ -4122,7 +4219,7 @@ Breakpoint ID: ${breakpointId}`
4122
4219
  }
4123
4220
  }
4124
4221
  ),
4125
- tool6(
4222
+ defineTool(
4126
4223
  "debug_list_breakpoints",
4127
4224
  "List all currently active breakpoints with their file, line, and condition.",
4128
4225
  {},
@@ -4142,7 +4239,7 @@ Breakpoint ID: ${breakpointId}`
4142
4239
  }
4143
4240
  function buildInspectionTools(manager) {
4144
4241
  return [
4145
- tool6(
4242
+ defineTool(
4146
4243
  "debug_inspect_paused",
4147
4244
  "When the debugger is paused at a breakpoint, returns the call stack and local variables. Check this after a breakpoint is hit to understand the current execution state.",
4148
4245
  {},
@@ -4185,7 +4282,7 @@ ${JSON.stringify(queuedHits, null, 2)}`
4185
4282
  },
4186
4283
  { annotations: { readOnlyHint: true } }
4187
4284
  ),
4188
- tool6(
4285
+ defineTool(
4189
4286
  "debug_evaluate",
4190
4287
  "Evaluate a JavaScript expression in the current paused scope (or globally if not paused). When paused, use frameIndex to evaluate in a specific call frame.",
4191
4288
  {
@@ -4214,7 +4311,7 @@ ${JSON.stringify(queuedHits, null, 2)}`
4214
4311
  }
4215
4312
  function buildProbeManagementTools(manager) {
4216
4313
  return [
4217
- tool6(
4314
+ defineTool(
4218
4315
  "debug_add_probe",
4219
4316
  "Add a debug probe at a specific code location. Captures expression values each time the line executes \u2014 without pausing or modifying source files. Like console.log but better: structured, no diff pollution, auto-cleaned on debug exit.",
4220
4317
  {
@@ -4244,7 +4341,7 @@ Trigger the code path, then use debug_get_probe_results to see captured values.`
4244
4341
  }
4245
4342
  }
4246
4343
  ),
4247
- tool6(
4344
+ defineTool(
4248
4345
  "debug_remove_probe",
4249
4346
  "Remove a previously set debug probe by its ID.",
4250
4347
  {
@@ -4261,7 +4358,7 @@ Trigger the code path, then use debug_get_probe_results to see captured values.`
4261
4358
  }
4262
4359
  }
4263
4360
  ),
4264
- tool6(
4361
+ defineTool(
4265
4362
  "debug_list_probes",
4266
4363
  "List all active debug probes with their file, line, expressions, and labels.",
4267
4364
  {},
@@ -4284,7 +4381,7 @@ Trigger the code path, then use debug_get_probe_results to see captured values.`
4284
4381
  }
4285
4382
  function buildProbeResultTools(manager) {
4286
4383
  return [
4287
- tool6(
4384
+ defineTool(
4288
4385
  "debug_get_probe_results",
4289
4386
  "Fetch captured probe hit data. Returns expression values from each time a probed line executed.",
4290
4387
  {
@@ -4359,7 +4456,7 @@ function formatProbeValue(value) {
4359
4456
  }
4360
4457
  function buildExecutionControlTools(manager) {
4361
4458
  return [
4362
- tool6(
4459
+ defineTool(
4363
4460
  "debug_continue",
4364
4461
  "Resume execution after the debugger has paused at a breakpoint.",
4365
4462
  {},
@@ -4377,7 +4474,7 @@ function buildExecutionControlTools(manager) {
4377
4474
  }
4378
4475
  }
4379
4476
  ),
4380
- tool6(
4477
+ defineTool(
4381
4478
  "debug_step_over",
4382
4479
  "Step over the current line while paused at a breakpoint. Executes the current line and pauses at the next line in the same function.",
4383
4480
  {},
@@ -4395,7 +4492,7 @@ function buildExecutionControlTools(manager) {
4395
4492
  }
4396
4493
  }
4397
4494
  ),
4398
- tool6(
4495
+ defineTool(
4399
4496
  "debug_step_into",
4400
4497
  "Step into the function call on the current line while paused at a breakpoint. Pauses at the first line inside the called function.",
4401
4498
  {},
@@ -4429,11 +4526,10 @@ function buildDebugTools(manager) {
4429
4526
  }
4430
4527
 
4431
4528
  // src/tools/code-review-tools.ts
4432
- import { tool as tool7 } from "@anthropic-ai/claude-agent-sdk";
4433
4529
  import { z as z7 } from "zod";
4434
4530
  function buildCodeReviewTools(connection) {
4435
4531
  return [
4436
- tool7(
4532
+ defineTool(
4437
4533
  "approve_code_review",
4438
4534
  "Approve the code review. Use this when the code passes all review criteria and is ready to merge.",
4439
4535
  {
@@ -4455,7 +4551,7 @@ ${summary}`,
4455
4551
  return textResult("Code review approved. Exiting.");
4456
4552
  }
4457
4553
  ),
4458
- tool7(
4554
+ defineTool(
4459
4555
  "request_code_changes",
4460
4556
  "Request changes during code review. Use this when substantive issues are found that need to be fixed before merge.",
4461
4557
  {
@@ -4524,30 +4620,30 @@ function getModeTools(agentMode, connection, config, context) {
4524
4620
  return config.mode === "pm" ? buildPmTools(connection, context?.storyPoints, { includePackTools: false }) : [];
4525
4621
  }
4526
4622
  }
4527
- function createConveyorMcpServer(connection, config, context, agentMode, debugManager) {
4623
+ function buildConveyorTools(connection, config, context, agentMode, debugManager) {
4528
4624
  const effectiveMode = agentMode ?? context?.agentMode ?? void 0;
4529
4625
  if (effectiveMode === "code-review") {
4530
- return createSdkMcpServer({
4531
- name: "conveyor",
4532
- tools: [
4533
- buildReadTaskChatTool(connection),
4534
- buildGetTaskPlanTool(connection, config),
4535
- buildGetTaskTool(connection),
4536
- buildGetTaskCliTool(connection),
4537
- buildListTaskFilesTool(connection),
4538
- buildGetTaskFileTool(connection),
4539
- ...buildCodeReviewTools(connection)
4540
- ]
4541
- });
4626
+ return [
4627
+ buildReadTaskChatTool(connection),
4628
+ buildGetTaskPlanTool(connection, config),
4629
+ buildGetTaskTool(connection),
4630
+ buildGetTaskCliTool(connection),
4631
+ buildListTaskFilesTool(connection),
4632
+ buildGetTaskFileTool(connection),
4633
+ ...buildCodeReviewTools(connection)
4634
+ ];
4542
4635
  }
4543
4636
  const commonTools = buildCommonTools(connection, config);
4544
4637
  const modeTools = getModeTools(effectiveMode, connection, config, context);
4545
4638
  const discoveryTools = effectiveMode === "discovery" || effectiveMode === "auto" ? buildDiscoveryTools(connection, context) : [];
4546
4639
  const debugTools = debugManager && effectiveMode === "building" ? buildDebugTools(debugManager) : [];
4547
4640
  const emergencyTools = [buildForceUpdateTaskStatusTool(connection)];
4548
- return createSdkMcpServer({
4641
+ return [...commonTools, ...modeTools, ...discoveryTools, ...debugTools, ...emergencyTools];
4642
+ }
4643
+ function createConveyorMcpServer(harness, connection, config, context, agentMode, debugManager) {
4644
+ return harness.createMcpServer({
4549
4645
  name: "conveyor",
4550
- tools: [...commonTools, ...modeTools, ...discoveryTools, ...debugTools, ...emergencyTools]
4646
+ tools: buildConveyorTools(connection, config, context, agentMode, debugManager)
4551
4647
  });
4552
4648
  }
4553
4649
 
@@ -4801,7 +4897,7 @@ function buildQueryOptions(host, context) {
4801
4897
  mode
4802
4898
  );
4803
4899
  const settingSources = settings.settingSources ?? ["user", "project"];
4804
- const baseOptions = {
4900
+ return {
4805
4901
  model: context.model || host.config.model,
4806
4902
  systemPrompt: {
4807
4903
  type: "preset",
@@ -4814,7 +4910,10 @@ function buildQueryOptions(host, context) {
4814
4910
  allowDangerouslySkipPermissions: !needsCanUseTool,
4815
4911
  canUseTool: buildCanUseTool(host),
4816
4912
  tools: { type: "preset", preset: "claude_code" },
4817
- mcpServers: { conveyor: createConveyorMcpServer(host.connection, host.config, context, mode) },
4913
+ mcpServers: {
4914
+ conveyor: createConveyorMcpServer(host.harness, host.connection, host.config, context, mode)
4915
+ },
4916
+ sandbox: context.useSandbox ? { enabled: true } : { enabled: false },
4818
4917
  hooks: buildHooks(host),
4819
4918
  maxTurns: mode === "code-review" ? Math.min(settings.maxTurns ?? 15, 15) : settings.maxTurns,
4820
4919
  effort: settings.effort,
@@ -4827,7 +4926,6 @@ function buildQueryOptions(host, context) {
4827
4926
  logger3.warn("Claude Code stderr", { data: data.trimEnd() });
4828
4927
  }
4829
4928
  };
4830
- return baseOptions;
4831
4929
  }
4832
4930
  function buildMultimodalPrompt(textPrompt, context, skipImages = false) {
4833
4931
  if (skipImages) return textPrompt;
@@ -4900,9 +4998,10 @@ async function runSdkQuery(host, context, followUpContent) {
4900
4998
  const resume = context.claudeSessionId ?? void 0;
4901
4999
  if (followUpContent) {
4902
5000
  const prompt = await buildFollowUpPrompt(host, context, followUpContent);
4903
- const agentQuery = query({
5001
+ const agentQuery = host.harness.executeQuery({
4904
5002
  prompt: typeof prompt === "string" ? prompt : host.createInputStream(prompt),
4905
- options: { ...options, resume }
5003
+ options: { ...options },
5004
+ resume
4906
5005
  });
4907
5006
  host.activeQuery = agentQuery;
4908
5007
  try {
@@ -4920,9 +5019,10 @@ async function runSdkQuery(host, context, followUpContent) {
4920
5019
  mode
4921
5020
  );
4922
5021
  const prompt = buildMultimodalPrompt(initialPrompt, context);
4923
- const agentQuery = query({
5022
+ const agentQuery = host.harness.executeQuery({
4924
5023
  prompt: host.createInputStream(prompt),
4925
- options: { ...options, resume }
5024
+ options: { ...options },
5025
+ resume
4926
5026
  });
4927
5027
  host.activeQuery = agentQuery;
4928
5028
  try {
@@ -4946,9 +5046,10 @@ async function buildRetryQuery(host, context, options, lastErrorWasImage) {
4946
5046
  context,
4947
5047
  lastErrorWasImage
4948
5048
  );
4949
- return query({
5049
+ return host.harness.executeQuery({
4950
5050
  prompt: host.createInputStream(retryPrompt),
4951
- options: { ...options, resume: void 0 }
5051
+ options: { ...options },
5052
+ resume: void 0
4952
5053
  });
4953
5054
  }
4954
5055
  async function handleAuthError(context, host, options) {
@@ -4968,9 +5069,10 @@ async function handleAuthError(context, host, options) {
4968
5069
  await buildInitialPrompt(host.config.mode, context, host.config.isAuto, host.agentMode),
4969
5070
  context
4970
5071
  );
4971
- const freshQuery = query({
5072
+ const freshQuery = host.harness.executeQuery({
4972
5073
  prompt: host.createInputStream(freshPrompt),
4973
- options: { ...options, resume: void 0 }
5074
+ options: { ...options },
5075
+ resume: void 0
4974
5076
  });
4975
5077
  return runWithRetry(freshQuery, context, host, options);
4976
5078
  }
@@ -4981,9 +5083,10 @@ async function handleStaleSession(context, host, options) {
4981
5083
  await buildInitialPrompt(host.config.mode, context, host.config.isAuto, host.agentMode),
4982
5084
  context
4983
5085
  );
4984
- const freshQuery = query({
5086
+ const freshQuery = host.harness.executeQuery({
4985
5087
  prompt: host.createInputStream(freshPrompt),
4986
- options: { ...options, resume: void 0 }
5088
+ options: { ...options },
5089
+ resume: void 0
4987
5090
  });
4988
5091
  return runWithRetry(freshQuery, context, host, options);
4989
5092
  }
@@ -5226,7 +5329,26 @@ function pushSetupLog(setupLog, line) {
5226
5329
  setupLog.splice(0, setupLog.length - MAX_SETUP_LOG_LINES);
5227
5330
  }
5228
5331
  }
5332
+ function shouldAutoScale(setupCmd, startCmd) {
5333
+ const cmds = [setupCmd, startCmd].filter(Boolean).join(" ");
5334
+ const heavyPatterns = [
5335
+ /\bbun\s+(install|i)\b/,
5336
+ /\bnpm\s+(install|ci)\b/,
5337
+ /\byarn\s+(install)?\b/,
5338
+ /\bpnpm\s+(install|i)\b/,
5339
+ /\bbun\s+run\s+(dev|start|build|test)\b/,
5340
+ /\bnpm\s+run\s+(dev|start|build|test)\b/,
5341
+ /\bmake\b/,
5342
+ /\bcargo\s+build\b/,
5343
+ /\bpip\s+install\b/
5344
+ ];
5345
+ return heavyPatterns.some((p) => p.test(cmds));
5346
+ }
5229
5347
  async function executeSetupConfig(config, runnerConfig, connection, setupLog) {
5348
+ if (process.env.CLAUDESPACE_NAME && shouldAutoScale(config.setupCommand, config.startCommand)) {
5349
+ connection.requestScaleUp("light", "setup-phase auto-scale").catch(() => {
5350
+ });
5351
+ }
5230
5352
  if (config.setupCommand) {
5231
5353
  pushSetupLog(setupLog, `$ ${config.setupCommand}`);
5232
5354
  await runSetupCommand(config.setupCommand, runnerConfig.workspaceDir, (stream, data) => {
@@ -5478,6 +5600,7 @@ function buildQueryHost(deps) {
5478
5600
  config: deps.config,
5479
5601
  connection: deps.connection,
5480
5602
  callbacks: deps.callbacks,
5603
+ harness: deps.harness,
5481
5604
  setupLog: deps.setupLog,
5482
5605
  costTracker: deps.costTracker,
5483
5606
  get agentMode() {
@@ -5541,11 +5664,13 @@ var AgentRunner = class {
5541
5664
  conveyorConfig = null;
5542
5665
  _queryHost = null;
5543
5666
  tunnelClient = null;
5667
+ harness;
5544
5668
  constructor(config, callbacks) {
5545
5669
  this.config = config;
5546
5670
  this.connection = new ConveyorConnection(config);
5547
5671
  this.callbacks = callbacks;
5548
5672
  this.planSync = new PlanSync(config.workspaceDir, this.connection);
5673
+ this.harness = createHarness();
5549
5674
  }
5550
5675
  get state() {
5551
5676
  return this._state;
@@ -5928,6 +6053,7 @@ var AgentRunner = class {
5928
6053
  config: this.config,
5929
6054
  connection: this.connection,
5930
6055
  callbacks: this.callbacks,
6056
+ harness: this.harness,
5931
6057
  setupLog: this.setupLog,
5932
6058
  costTracker: this.costTracker,
5933
6059
  planSync: this.planSync,
@@ -6118,18 +6244,11 @@ var CommitWatcher = class {
6118
6244
  }
6119
6245
  };
6120
6246
 
6121
- // src/runner/project-chat-handler.ts
6122
- import {
6123
- query as query2,
6124
- createSdkMcpServer as createSdkMcpServer2
6125
- } from "@anthropic-ai/claude-agent-sdk";
6126
-
6127
6247
  // src/tools/project-tools.ts
6128
- import { tool as tool8 } from "@anthropic-ai/claude-agent-sdk";
6129
6248
  import { z as z8 } from "zod";
6130
6249
  function buildReadTools(connection) {
6131
6250
  return [
6132
- tool8(
6251
+ defineTool(
6133
6252
  "list_tasks",
6134
6253
  "List tasks in the project. Optionally filter by status or assignee.",
6135
6254
  {
@@ -6149,7 +6268,7 @@ function buildReadTools(connection) {
6149
6268
  },
6150
6269
  { annotations: { readOnlyHint: true } }
6151
6270
  ),
6152
- tool8(
6271
+ defineTool(
6153
6272
  "get_task",
6154
6273
  "Get detailed information about a task including its chat messages, child tasks, and codespace status.",
6155
6274
  { task_id: z8.string().describe("The task ID to look up") },
@@ -6165,7 +6284,7 @@ function buildReadTools(connection) {
6165
6284
  },
6166
6285
  { annotations: { readOnlyHint: true } }
6167
6286
  ),
6168
- tool8(
6287
+ defineTool(
6169
6288
  "search_tasks",
6170
6289
  "Search tasks by tags, text query, or status filters.",
6171
6290
  {
@@ -6186,7 +6305,7 @@ function buildReadTools(connection) {
6186
6305
  },
6187
6306
  { annotations: { readOnlyHint: true } }
6188
6307
  ),
6189
- tool8(
6308
+ defineTool(
6190
6309
  "list_tags",
6191
6310
  "List all tags available in the project.",
6192
6311
  {},
@@ -6202,7 +6321,7 @@ function buildReadTools(connection) {
6202
6321
  },
6203
6322
  { annotations: { readOnlyHint: true } }
6204
6323
  ),
6205
- tool8(
6324
+ defineTool(
6206
6325
  "get_project_summary",
6207
6326
  "Get a summary of the project including task counts by status and active builds.",
6208
6327
  {},
@@ -6222,7 +6341,7 @@ function buildReadTools(connection) {
6222
6341
  }
6223
6342
  function buildMutationTools(connection) {
6224
6343
  return [
6225
- tool8(
6344
+ defineTool(
6226
6345
  "create_task",
6227
6346
  "Create a new task in the project.",
6228
6347
  {
@@ -6243,7 +6362,7 @@ function buildMutationTools(connection) {
6243
6362
  }
6244
6363
  }
6245
6364
  ),
6246
- tool8(
6365
+ defineTool(
6247
6366
  "update_task",
6248
6367
  "Update an existing task's title, description, plan, status, or assignee.",
6249
6368
  {
@@ -6346,7 +6465,8 @@ async function fetchContext(connection, chatId) {
6346
6465
  function buildChatQueryOptions(agentCtx, projectDir, connection) {
6347
6466
  const model = agentCtx?.model || FALLBACK_MODEL;
6348
6467
  const settings = agentCtx?.agentSettings ?? {};
6349
- const mcpServer = createSdkMcpServer2({
6468
+ const harness = createHarness();
6469
+ const mcpServer = harness.createMcpServer({
6350
6470
  name: "conveyor",
6351
6471
  tools: buildProjectTools(connection)
6352
6472
  });
@@ -6434,7 +6554,8 @@ async function runChatQuery(message, connection, projectDir, sessionId) {
6434
6554
  const options = buildChatQueryOptions(agentCtx, projectDir, connection);
6435
6555
  const prompt = buildPrompt(message, chatHistory);
6436
6556
  connection.emitAgentStatus("running");
6437
- const events = query2({
6557
+ const harness = createHarness();
6558
+ const events = harness.executeQuery({
6438
6559
  prompt,
6439
6560
  options,
6440
6561
  ...sessionId ? { resume: sessionId } : {}
@@ -6479,12 +6600,8 @@ async function handleProjectChatMessage(message, connection, projectDir, session
6479
6600
  }
6480
6601
  }
6481
6602
 
6482
- // src/runner/project-audit-handler.ts
6483
- import { query as query3 } from "@anthropic-ai/claude-agent-sdk";
6484
-
6485
6603
  // src/tools/audit-tools.ts
6486
6604
  import { randomUUID as randomUUID3 } from "crypto";
6487
- import { tool as tool9, createSdkMcpServer as createSdkMcpServer3 } from "@anthropic-ai/claude-agent-sdk";
6488
6605
  import { z as z9 } from "zod";
6489
6606
  function mapCreateTag(input) {
6490
6607
  return {
@@ -6565,9 +6682,9 @@ function collectRecommendation(toolName, input, collector, onRecommendation) {
6565
6682
  onRecommendation?.({ tagName: rec.tagName ?? rec.type, type: rec.type });
6566
6683
  return JSON.stringify({ success: true, recommendationId: rec.id });
6567
6684
  }
6568
- function createAuditMcpServer(collector, onRecommendation) {
6569
- const auditTools = [
6570
- tool9(
6685
+ function buildAuditTools(collector, onRecommendation) {
6686
+ return [
6687
+ defineTool(
6571
6688
  "recommend_create_tag",
6572
6689
  "Recommend creating a new tag for an uncovered subsystem or area",
6573
6690
  {
@@ -6586,7 +6703,7 @@ function createAuditMcpServer(collector, onRecommendation) {
6586
6703
  return { content: [{ type: "text", text: result }] };
6587
6704
  }
6588
6705
  ),
6589
- tool9(
6706
+ defineTool(
6590
6707
  "recommend_update_description",
6591
6708
  "Recommend updating a tag's description to better reflect its scope",
6592
6709
  {
@@ -6605,7 +6722,7 @@ function createAuditMcpServer(collector, onRecommendation) {
6605
6722
  return { content: [{ type: "text", text: result }] };
6606
6723
  }
6607
6724
  ),
6608
- tool9(
6725
+ defineTool(
6609
6726
  "recommend_context_link",
6610
6727
  "Recommend linking a doc, rule, file, or folder to a tag's contextPaths",
6611
6728
  {
@@ -6626,7 +6743,7 @@ function createAuditMcpServer(collector, onRecommendation) {
6626
6743
  return { content: [{ type: "text", text: result }] };
6627
6744
  }
6628
6745
  ),
6629
- tool9(
6746
+ defineTool(
6630
6747
  "flag_documentation_gap",
6631
6748
  "Flag a file that agents read heavily but has no tag documentation linked",
6632
6749
  {
@@ -6647,7 +6764,7 @@ function createAuditMcpServer(collector, onRecommendation) {
6647
6764
  return { content: [{ type: "text", text: result }] };
6648
6765
  }
6649
6766
  ),
6650
- tool9(
6767
+ defineTool(
6651
6768
  "recommend_merge_tags",
6652
6769
  "Recommend merging one tag into another",
6653
6770
  {
@@ -6667,7 +6784,7 @@ function createAuditMcpServer(collector, onRecommendation) {
6667
6784
  return { content: [{ type: "text", text: result }] };
6668
6785
  }
6669
6786
  ),
6670
- tool9(
6787
+ defineTool(
6671
6788
  "recommend_rename_tag",
6672
6789
  "Recommend renaming a tag",
6673
6790
  {
@@ -6686,7 +6803,7 @@ function createAuditMcpServer(collector, onRecommendation) {
6686
6803
  return { content: [{ type: "text", text: result }] };
6687
6804
  }
6688
6805
  ),
6689
- tool9(
6806
+ defineTool(
6690
6807
  "complete_audit",
6691
6808
  "Signal that the audit is complete with a summary of all findings",
6692
6809
  { summary: z9.string().describe("Brief overview of all findings") },
@@ -6697,9 +6814,11 @@ function createAuditMcpServer(collector, onRecommendation) {
6697
6814
  }
6698
6815
  )
6699
6816
  ];
6700
- return createSdkMcpServer3({
6817
+ }
6818
+ function createAuditMcpServer(harness, collector, onRecommendation) {
6819
+ return harness.createMcpServer({
6701
6820
  name: "tag-audit",
6702
- tools: auditTools
6821
+ tools: buildAuditTools(collector, onRecommendation)
6703
6822
  });
6704
6823
  }
6705
6824
 
@@ -6809,7 +6928,8 @@ async function runAuditQuery(request, connection, projectDir) {
6809
6928
  "Start by exploring the codebase structure, then analyze each tag for accuracy and completeness.",
6810
6929
  "Call complete_audit when done."
6811
6930
  ].join("\n");
6812
- const events = query3({
6931
+ const harness = createHarness();
6932
+ const events = harness.executeQuery({
6813
6933
  prompt: userPrompt,
6814
6934
  options: {
6815
6935
  model,
@@ -6818,7 +6938,7 @@ async function runAuditQuery(request, connection, projectDir) {
6818
6938
  permissionMode: "bypassPermissions",
6819
6939
  allowDangerouslySkipPermissions: true,
6820
6940
  tools: { type: "preset", preset: "claude_code" },
6821
- mcpServers: { "tag-audit": createAuditMcpServer(collector, onRecommendation) },
6941
+ mcpServers: { "tag-audit": createAuditMcpServer(harness, collector, onRecommendation) },
6822
6942
  maxTurns: settings.maxTurns ?? 75,
6823
6943
  maxBudgetUsd: settings.maxBudgetUsd ?? 5,
6824
6944
  effort: settings.effort,
@@ -7408,7 +7528,10 @@ var ProjectRunner = class {
7408
7528
  }
7409
7529
  }
7410
7530
  handleStopTask(taskId) {
7411
- const agent = this.activeAgents.get(taskId);
7531
+ let agent = this.activeAgents.get(taskId);
7532
+ if (!agent) {
7533
+ agent = this.activeAgents.get(`${taskId}:code-review`);
7534
+ }
7412
7535
  if (!agent) return;
7413
7536
  const shortId = taskId.slice(0, 8);
7414
7537
  logger8.info("Stopping task", { taskId: shortId });
@@ -7545,4 +7668,4 @@ export {
7545
7668
  ProjectRunner,
7546
7669
  FileCache
7547
7670
  };
7548
- //# sourceMappingURL=chunk-EUNUBCGF.js.map
7671
+ //# sourceMappingURL=chunk-RMNWEID4.js.map