@ai-sdk/harness-claude-code 1.0.66 → 1.0.68

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.
package/dist/index.js CHANGED
@@ -134,10 +134,12 @@ var thinkingSchema = z.discriminatedUnion("type", [
134
134
  z.object({ type: z.literal("disabled") })
135
135
  ]);
136
136
  var startMessageSchema = harnessV1BridgeStartBaseSchema.extend({
137
+ instructions: z.string().optional(),
137
138
  thinking: thinkingSchema,
138
139
  maxTurns: z.number().optional(),
139
140
  env: z.record(z.string(), z.string()).optional(),
140
141
  skills: z.array(z.string()).optional(),
142
+ mcpServers: z.record(z.string(), z.unknown()).optional(),
141
143
  // Resume signal. When true, the bridge passes `{ continue: true }` to the
142
144
  // Claude SDK so the in-workdir thread state is rehydrated. The host sets this
143
145
  // on the first prompt after a cross-process resume.
@@ -149,10 +151,35 @@ var inboundMessageSchema = z.discriminatedUnion("type", [
149
151
  ]);
150
152
 
151
153
  // src/version.ts
152
- var VERSION = true ? "1.0.66" : "0.0.0-test";
154
+ var VERSION = true ? "1.0.68" : "0.0.0-test";
153
155
 
154
156
  // src/claude-code-harness.ts
155
157
  var CLAUDE_CODE_CLIENT_APP = `ai-sdk/harness-claude-code/${VERSION}`;
158
+ var listMcpResourcesInputSchema = z2.object({
159
+ server: z2.string().optional()
160
+ });
161
+ var readMcpResourceInputSchema = z2.object({
162
+ server: z2.string(),
163
+ uri: z2.string()
164
+ });
165
+ var structuredTeamMessageSchema = z2.discriminatedUnion("type", [
166
+ z2.object({
167
+ type: z2.literal("shutdown_request"),
168
+ reason: z2.string().optional()
169
+ }),
170
+ z2.object({
171
+ type: z2.literal("shutdown_response"),
172
+ request_id: z2.string(),
173
+ approve: z2.boolean(),
174
+ reason: z2.string().optional()
175
+ }),
176
+ z2.object({
177
+ type: z2.literal("plan_approval_response"),
178
+ request_id: z2.string(),
179
+ approve: z2.boolean(),
180
+ feedback: z2.string().optional()
181
+ })
182
+ ]);
156
183
  var CLAUDE_CODE_BUILTIN_TOOLS = {
157
184
  read: commonTool("read", {
158
185
  nativeName: "Read",
@@ -337,23 +364,64 @@ var CLAUDE_CODE_BUILTIN_TOOLS = {
337
364
  timeout: z2.number()
338
365
  })
339
366
  }),
340
- Monitor: tool({
341
- description: "Run and monitor a shell command",
342
- inputSchema: z2.object({
343
- command: z2.string(),
344
- description: z2.string().optional(),
345
- timeout_ms: z2.number().optional(),
346
- persistent: z2.boolean().optional()
347
- })
348
- }),
349
- ListMcpResources: tool({
350
- description: "List resources available from MCP servers",
351
- inputSchema: z2.object({ server: z2.string().optional() })
352
- }),
353
- ReadMcpResource: tool({
354
- description: "Read a specific MCP resource by URI",
355
- inputSchema: z2.object({ server: z2.string(), uri: z2.string() })
356
- }),
367
+ Monitor: {
368
+ ...tool({
369
+ description: "Run and monitor a shell command or WebSocket",
370
+ inputSchema: z2.object({
371
+ description: z2.string().optional(),
372
+ timeout_ms: z2.number().optional(),
373
+ persistent: z2.boolean().optional(),
374
+ command: z2.string().optional(),
375
+ ws: z2.object({
376
+ url: z2.string(),
377
+ protocols: z2.array(z2.string()).optional()
378
+ }).optional()
379
+ })
380
+ }),
381
+ toolUseKind: "bash"
382
+ },
383
+ ListMcpResources: {
384
+ ...tool({
385
+ description: "List resources available from MCP servers",
386
+ inputSchema: listMcpResourcesInputSchema
387
+ }),
388
+ toolUseKind: "readonly"
389
+ },
390
+ ListMcpResourcesTool: {
391
+ ...tool({
392
+ description: "List resources available from MCP servers",
393
+ inputSchema: listMcpResourcesInputSchema
394
+ }),
395
+ toolUseKind: "readonly"
396
+ },
397
+ ReadMcpResource: {
398
+ ...tool({
399
+ description: "Read a specific MCP resource by URI",
400
+ inputSchema: readMcpResourceInputSchema
401
+ }),
402
+ toolUseKind: "readonly"
403
+ },
404
+ ReadMcpResourceTool: {
405
+ ...tool({
406
+ description: "Read a specific MCP resource by URI",
407
+ inputSchema: readMcpResourceInputSchema
408
+ }),
409
+ toolUseKind: "readonly"
410
+ },
411
+ ReadMcpResourceDirTool: {
412
+ ...tool({
413
+ description: "List direct children of an MCP directory resource",
414
+ inputSchema: readMcpResourceInputSchema
415
+ }),
416
+ toolUseKind: "readonly"
417
+ },
418
+ RefreshMcpTools: {
419
+ ...tool({
420
+ description: "Refresh tools from one or all connected MCP servers",
421
+ inputSchema: z2.object({ server: z2.string().optional() })
422
+ }),
423
+ toolUseKind: "readonly"
424
+ },
357
425
  ExitPlanMode: tool({
358
426
  description: "Exit plan mode with optional permission approvals",
359
427
  inputSchema: z2.looseObject({
@@ -365,6 +433,13 @@ var CLAUDE_CODE_BUILTIN_TOOLS = {
365
433
  ).optional()
366
434
  })
367
435
  }),
436
+ EnterPlanMode: {
437
+ ...tool({
438
+ description: "Enter plan mode",
439
+ inputSchema: z2.object({})
440
+ }),
441
+ toolUseKind: "readonly"
442
+ },
368
443
  EnterWorktree: tool({
369
444
  description: "Create or enter an isolated git worktree",
370
445
  inputSchema: z2.object({
@@ -423,7 +498,255 @@ var CLAUDE_CODE_BUILTIN_TOOLS = {
423
498
  query: z2.string(),
424
499
  max_results: z2.number().optional()
425
500
  })
426
- })
501
+ }),
502
+ Artifact: {
503
+ ...tool({
504
+ description: "Publish or list claude.ai artifacts",
505
+ inputSchema: z2.object({
506
+ action: z2.enum(["publish", "list"]).optional(),
507
+ file_path: z2.string().optional(),
508
+ favicon: z2.string().optional(),
509
+ limit: z2.number().optional(),
510
+ scope: z2.enum(["mine", "shared", "all"]).optional(),
511
+ title: z2.string().optional(),
512
+ description: z2.string().optional(),
513
+ label: z2.string().optional(),
514
+ url: z2.string().optional(),
515
+ force: z2.boolean().optional()
516
+ })
517
+ }),
518
+ toolUseKind: "edit"
519
+ },
520
+ CronCreate: {
521
+ ...tool({
522
+ description: "Schedule a recurring or one-shot prompt",
523
+ inputSchema: z2.object({
524
+ cron: z2.string(),
525
+ prompt: z2.string(),
526
+ recurring: z2.boolean().optional(),
527
+ durable: z2.boolean().optional()
528
+ })
529
+ }),
530
+ toolUseKind: "edit"
531
+ },
532
+ CronDelete: {
533
+ ...tool({
534
+ description: "Delete a scheduled prompt by id",
535
+ inputSchema: z2.object({ id: z2.string() })
536
+ }),
537
+ toolUseKind: "edit"
538
+ },
539
+ CronList: {
540
+ ...tool({
541
+ description: "List scheduled prompts for the current session",
542
+ inputSchema: z2.object({})
543
+ }),
544
+ toolUseKind: "readonly"
545
+ },
546
+ DesignSync: {
547
+ ...tool({
548
+ description: "Read or update claude.ai Design projects",
549
+ inputSchema: z2.object({
550
+ method: z2.enum([
551
+ "list_projects",
552
+ "get_project",
553
+ "list_files",
554
+ "get_file",
555
+ "finalize_plan",
556
+ "write_files",
557
+ "delete_files",
558
+ "register_assets",
559
+ "unregister_assets",
560
+ "create_project",
561
+ "report_validate"
562
+ ]),
563
+ projectId: z2.string().optional(),
564
+ path: z2.string().optional(),
565
+ writes: z2.array(z2.string()).max(256).optional(),
566
+ deletes: z2.array(z2.string()).max(256).optional(),
567
+ planId: z2.string().optional(),
568
+ files: z2.array(
569
+ z2.object({
570
+ path: z2.string(),
571
+ localPath: z2.string().optional(),
572
+ data: z2.string().optional(),
573
+ encoding: z2.literal("base64").optional(),
574
+ mimeType: z2.string().optional()
575
+ })
576
+ ).max(256).optional(),
577
+ paths: z2.array(z2.string()).max(256).optional(),
578
+ name: z2.string().optional(),
579
+ assets: z2.array(
580
+ z2.object({
581
+ name: z2.string(),
582
+ path: z2.string(),
583
+ subtitle: z2.string().optional(),
584
+ viewport: z2.object({
585
+ width: z2.number(),
586
+ height: z2.number().optional()
587
+ }).optional(),
588
+ group: z2.string().optional()
589
+ })
590
+ ).max(256).optional(),
591
+ localDir: z2.string().optional(),
592
+ counts: z2.object({
593
+ total: z2.number(),
594
+ bad: z2.number(),
595
+ thin: z2.number(),
596
+ variantsIdentical: z2.number(),
597
+ iterations: z2.number()
598
+ }).optional()
599
+ })
600
+ }),
601
+ toolUseKind: "edit"
602
+ },
603
+ LSP: {
604
+ ...tool({
605
+ description: "Query a language server for code intelligence",
606
+ inputSchema: z2.object({
607
+ operation: z2.enum([
608
+ "goToDefinition",
609
+ "findReferences",
610
+ "hover",
611
+ "documentSymbol",
612
+ "workspaceSymbol",
613
+ "goToImplementation",
614
+ "prepareCallHierarchy",
615
+ "incomingCalls",
616
+ "outgoingCalls"
617
+ ]),
618
+ filePath: z2.string(),
619
+ line: z2.number().int().positive(),
620
+ character: z2.number().int().positive(),
621
+ query: z2.string().optional()
622
+ })
623
+ }),
624
+ toolUseKind: "readonly"
625
+ },
626
+ PowerShell: {
627
+ ...tool({
628
+ description: "Execute a PowerShell command, optionally in background",
629
+ inputSchema: z2.object({
630
+ command: z2.string(),
631
+ timeout: z2.number().optional(),
632
+ description: z2.string().optional(),
633
+ run_in_background: z2.boolean().optional(),
634
+ dangerouslyDisableSandbox: z2.boolean().optional()
635
+ })
636
+ }),
637
+ toolUseKind: "bash"
638
+ },
639
+ PushNotification: {
640
+ ...tool({
641
+ description: "Send a notification for proactive or scheduled work",
642
+ inputSchema: z2.object({
643
+ message: z2.string(),
644
+ status: z2.literal("proactive")
645
+ })
646
+ }),
647
+ toolUseKind: "edit"
648
+ },
649
+ RemoteTrigger: {
650
+ ...tool({
651
+ description: "List, manage, or run a claude.ai Routine trigger",
652
+ inputSchema: z2.object({
653
+ action: z2.enum(["list", "get", "create", "update", "run"]),
654
+ trigger_id: z2.string().optional(),
655
+ body: z2.record(z2.string(), z2.unknown()).optional()
656
+ })
657
+ }),
658
+ toolUseKind: "edit"
659
+ },
660
+ ReportFindings: {
661
+ ...tool({
662
+ description: "Return verified code-review findings",
663
+ inputSchema: z2.object({
664
+ level: z2.enum(["low", "medium", "high", "xhigh", "max"]).optional(),
665
+ findings: z2.array(
666
+ z2.object({
667
+ file: z2.string(),
668
+ line: z2.number().optional(),
669
+ summary: z2.string(),
670
+ short_summary: z2.string().optional(),
671
+ failure_scenario: z2.string(),
672
+ category: z2.string().optional(),
673
+ verdict: z2.enum(["CONFIRMED", "PLAUSIBLE"]).optional(),
674
+ outcome: z2.enum(["fixed", "skipped", "no_change_needed"]).optional()
675
+ })
676
+ ).max(32)
677
+ })
678
+ }),
679
+ toolUseKind: "readonly"
680
+ },
681
+ ScheduleWakeup: {
682
+ ...tool({
683
+ description: "Schedule or stop the next iteration of a dynamic loop",
684
+ inputSchema: z2.object({
685
+ delaySeconds: z2.number().optional(),
686
+ reason: z2.string().optional(),
687
+ prompt: z2.string().optional(),
688
+ stop: z2.boolean().optional()
689
+ })
690
+ }),
691
+ toolUseKind: "edit"
692
+ },
693
+ SendMessage: {
694
+ ...tool({
695
+ description: "Send a plain-text or protocol message to another agent",
696
+ inputSchema: z2.object({
697
+ to: z2.string(),
698
+ summary: z2.string().max(200).optional(),
699
+ message: z2.union([z2.string(), structuredTeamMessageSchema])
700
+ })
701
+ }),
702
+ toolUseKind: "edit"
703
+ },
704
+ SendUserFile: {
705
+ ...tool({
706
+ description: "Send one or more files to the user",
707
+ inputSchema: z2.object({
708
+ files: z2.union([z2.string(), z2.array(z2.string()).min(1)]),
709
+ caption: z2.string().optional(),
710
+ status: z2.enum(["normal", "proactive"]),
711
+ display: z2.enum(["render", "attach"]).optional()
712
+ })
713
+ }),
714
+ toolUseKind: "readonly"
715
+ },
716
+ ShareOnboardingGuide: {
717
+ ...tool({
718
+ description: "Create, update, inspect, or delete an onboarding guide",
719
+ inputSchema: z2.object({
720
+ mode: z2.enum(["check", "update", "create", "delete"]).optional(),
721
+ short_code: z2.string().regex(/^[A-Za-z0-9_-]{1,64}$/).optional()
722
+ })
723
+ }),
724
+ toolUseKind: "edit"
725
+ },
726
+ WaitForMcpServers: {
727
+ ...tool({
728
+ description: "Wait for MCP servers that are still connecting",
729
+ inputSchema: z2.object({
730
+ servers: z2.array(z2.string()).optional()
731
+ })
732
+ }),
733
+ toolUseKind: "readonly"
734
+ },
735
+ Workflow: {
736
+ ...tool({
737
+ description: "Run or resume a dynamic multi-agent workflow",
738
+ inputSchema: z2.object({
739
+ script: z2.string().optional(),
740
+ name: z2.string().optional(),
741
+ description: z2.string().optional(),
742
+ title: z2.string().optional(),
743
+ args: z2.record(z2.string(), z2.unknown()).optional(),
744
+ scriptPath: z2.string().optional(),
745
+ resumeFromRunId: z2.string().optional()
746
+ })
747
+ }),
748
+ toolUseKind: "edit"
749
+ }
427
750
  };
428
751
  var BOOTSTRAP_DIR = ".harness-bootstrap/claude-code";
429
752
  var claudeCodeBridgeCoordsSchema = z2.object({
@@ -436,6 +759,11 @@ var claudeCodeResumeStateSchema = z2.looseObject({
436
759
  bridge: claudeCodeBridgeCoordsSchema.optional()
437
760
  });
438
761
  function createClaudeCode(settings = {}) {
762
+ if (settings.mcpServers != null && Object.prototype.hasOwnProperty.call(settings.mcpServers, "harness-tools")) {
763
+ throw new Error(
764
+ 'Claude Code MCP server name "harness-tools" is reserved for HarnessAgent tools.'
765
+ );
766
+ }
439
767
  let cachedBootstrap;
440
768
  const thinking = settings.thinking ?? {
441
769
  type: "adaptive",
@@ -538,7 +866,8 @@ function createClaudeCode(settings = {}) {
538
866
  debug: startOpts.observability?.debug,
539
867
  permissionMode: startOpts.permissionMode,
540
868
  builtinToolFiltering: startOpts.builtinToolFiltering,
541
- skills: startOpts.skills ?? []
869
+ skills: startOpts.skills ?? [],
870
+ mcpServers: settings.mcpServers
542
871
  });
543
872
  } catch {
544
873
  }
@@ -560,7 +889,7 @@ function createClaudeCode(settings = {}) {
560
889
  abortSignal: startOpts.abortSignal
561
890
  }) : void 0;
562
891
  const port = resolveBridgePort(sandboxSession, settings.port);
563
- const token = randomBytes(32).toString("hex");
892
+ const token = settings.mintBridgeToken == null ? randomBytes(32).toString("hex") : settings.mintBridgeToken(sandboxId);
564
893
  const authEnv = resolveClaudeCodeEnv(settings.auth);
565
894
  const env = {
566
895
  ...authEnv,
@@ -669,7 +998,8 @@ function createClaudeCode(settings = {}) {
669
998
  debug: startOpts.observability?.debug,
670
999
  permissionMode: startOpts.permissionMode,
671
1000
  builtinToolFiltering: startOpts.builtinToolFiltering,
672
- skills: startOpts.skills ?? []
1001
+ skills: startOpts.skills ?? [],
1002
+ mcpServers: settings.mcpServers
673
1003
  });
674
1004
  }
675
1005
  };
@@ -857,12 +1187,12 @@ function createSession({
857
1187
  debug,
858
1188
  permissionMode,
859
1189
  builtinToolFiltering,
860
- skills
1190
+ skills,
1191
+ mcpServers
861
1192
  }) {
862
1193
  let stopped = false;
863
1194
  let stopPromise;
864
1195
  let pendingResumeFlag = continueOnFirstPrompt;
865
- let instructionsApplied = isResume;
866
1196
  const wireTurn = (turnOpts) => {
867
1197
  let pendingResolve;
868
1198
  let pendingReject;
@@ -985,24 +1315,21 @@ function createSession({
985
1315
  emit: promptOpts.emit,
986
1316
  abortSignal: promptOpts.abortSignal
987
1317
  });
988
- let promptText = extractUserText(promptOpts.prompt);
989
- if (!instructionsApplied && promptOpts.instructions) {
990
- promptText = frameInstructions(promptOpts.instructions, promptText);
991
- }
992
- instructionsApplied = true;
993
1318
  const startMessage = {
994
1319
  type: "start",
995
- prompt: promptText,
1320
+ prompt: extractUserText(promptOpts.prompt),
996
1321
  tools: (promptOpts.tools ?? []).map((t) => ({
997
1322
  name: t.name,
998
1323
  description: t.description,
999
1324
  inputSchema: t.inputSchema
1000
1325
  })),
1326
+ ...promptOpts.instructions ? { instructions: promptOpts.instructions } : {},
1001
1327
  model,
1002
1328
  maxTurns,
1003
1329
  ...env !== void 0 ? { env } : {},
1004
1330
  thinking,
1005
1331
  ...skills.length > 0 ? { skills: skills.map((skill) => skill.name) } : {},
1332
+ ...mcpServers == null ? {} : { mcpServers },
1006
1333
  ...permissionMode ? { permissionMode } : {},
1007
1334
  ...builtinToolFiltering ? { builtinToolFiltering } : {},
1008
1335
  ...debug ? { debug } : {},
@@ -1034,11 +1361,13 @@ function createSession({
1034
1361
  description: t.description,
1035
1362
  inputSchema: t.inputSchema
1036
1363
  })),
1364
+ ...continueOpts.instructions ? { instructions: continueOpts.instructions } : {},
1037
1365
  model,
1038
1366
  maxTurns,
1039
1367
  ...env !== void 0 ? { env } : {},
1040
1368
  thinking,
1041
1369
  ...skills.length > 0 ? { skills: skills.map((skill) => skill.name) } : {},
1370
+ ...mcpServers == null ? {} : { mcpServers },
1042
1371
  ...permissionMode ? { permissionMode } : {},
1043
1372
  ...builtinToolFiltering ? { builtinToolFiltering } : {},
1044
1373
  ...debug ? { debug } : {},
@@ -1190,17 +1519,6 @@ function createSession({
1190
1519
  }
1191
1520
  };
1192
1521
  }
1193
- function frameInstructions(instructions, userText) {
1194
- return `<session-instructions>
1195
- The block below is operating guidance from the system, not a message from the user \u2014 follow it, but do not mention it or attribute it to the user.
1196
-
1197
- ${instructions}
1198
- </session-instructions>
1199
-
1200
- <user-message>
1201
- ${userText}
1202
- </user-message>`;
1203
- }
1204
1522
  function extractUserText(prompt) {
1205
1523
  if (typeof prompt === "string") return prompt;
1206
1524
  const { content } = prompt;