@ai-sdk/harness-opencode 1.0.65 → 1.0.67

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.
@@ -22,6 +22,7 @@ export type TranslationState = {
22
22
  legacyTextPartIds: Set<string>;
23
23
  legacyReasoningPartIds: Set<string>;
24
24
  legacyStepFinishPartIds: Set<string>;
25
+ dynamicToolCallIds: Set<string>;
25
26
  };
26
27
 
27
28
  export function createTranslationState(): TranslationState {
@@ -40,6 +41,7 @@ export function createTranslationState(): TranslationState {
40
41
  legacyTextPartIds: new Set(),
41
42
  legacyReasoningPartIds: new Set(),
42
43
  legacyStepFinishPartIds: new Set(),
44
+ dynamicToolCallIds: new Set(),
43
45
  };
44
46
  }
45
47
 
@@ -15,6 +15,7 @@ export const startMessageSchema = harnessV1BridgeStartBaseSchema.extend({
15
15
  variant: z.string().optional(),
16
16
  instructions: z.string().optional(),
17
17
  resumeSessionId: z.string().optional(),
18
+ mcpServers: z.record(z.string(), z.unknown()).optional(),
18
19
  });
19
20
 
20
21
  export type StartMessage = z.infer<typeof startMessageSchema>;
@@ -67,6 +67,11 @@ const OPENCODE_CLIENT_APP = `ai-sdk/harness-opencode/${VERSION}`;
67
67
 
68
68
  export type OpenCodeHarnessSettings = {
69
69
  readonly auth?: OpenCodeAuthOptions;
70
+ /**
71
+ * MCP server definitions keyed by server name. Each definition uses the
72
+ * underlying runtime's native MCP server configuration format.
73
+ */
74
+ readonly mcpServers?: Record<string, unknown>;
70
75
  readonly model?: string;
71
76
  readonly provider?: string;
72
77
  /**
@@ -77,6 +82,11 @@ export type OpenCodeHarnessSettings = {
77
82
  readonly reasoningVariant?: string;
78
83
  readonly port?: number;
79
84
  readonly startupTimeoutMs?: number;
85
+ /**
86
+ * Creates the authentication token used by the sandbox bridge. Defaults to
87
+ * a random 32-byte hexadecimal token.
88
+ */
89
+ readonly mintBridgeToken?: (sandboxId: string) => string;
80
90
  };
81
91
 
82
92
  const optionalStringRecord = z.record(z.string(), z.unknown()).optional();
@@ -201,6 +211,14 @@ type OpenCodeBridgeCoords = z.infer<typeof openCodeBridgeCoordsSchema>;
201
211
  export function createOpenCode(
202
212
  settings: OpenCodeHarnessSettings = {},
203
213
  ): HarnessV1<typeof OPENCODE_BUILTIN_TOOLS> {
214
+ if (
215
+ settings.mcpServers != null &&
216
+ Object.prototype.hasOwnProperty.call(settings.mcpServers, 'harness-tools')
217
+ ) {
218
+ throw new Error(
219
+ 'OpenCode MCP server name "harness-tools" is reserved for HarnessAgent tools.',
220
+ );
221
+ }
204
222
  let cachedBootstrap: HarnessV1Bootstrap | undefined;
205
223
 
206
224
  return {
@@ -309,6 +327,7 @@ export function createOpenCode(
309
327
  model,
310
328
  provider: settings.provider,
311
329
  reasoningVariant: settings.reasoningVariant,
330
+ mcpServers: settings.mcpServers,
312
331
  openCodeSessionId: resumeSessionId,
313
332
  isResume: true,
314
333
  seedResumeSessionOnFirstPrompt: false,
@@ -339,7 +358,10 @@ export function createOpenCode(
339
358
  }
340
359
 
341
360
  const port = resolveBridgePort(sandboxSession, settings.port);
342
- const token = randomBytes(32).toString('hex');
361
+ const token =
362
+ settings.mintBridgeToken == null
363
+ ? randomBytes(32).toString('hex')
364
+ : settings.mintBridgeToken(sandboxId);
343
365
  const sandboxHomeDir = await resolveSandboxHomeDir({
344
366
  sandbox: session,
345
367
  abortSignal: startOpts.abortSignal,
@@ -456,6 +478,7 @@ export function createOpenCode(
456
478
  model,
457
479
  provider: settings.provider,
458
480
  reasoningVariant: settings.reasoningVariant,
481
+ mcpServers: settings.mcpServers,
459
482
  openCodeSessionId: resumeSessionId,
460
483
  isResume: respawnStrategy !== undefined,
461
484
  seedResumeSessionOnFirstPrompt: respawnStrategy !== undefined,
@@ -552,6 +575,7 @@ function createSession({
552
575
  model,
553
576
  provider,
554
577
  reasoningVariant,
578
+ mcpServers,
555
579
  openCodeSessionId,
556
580
  isResume,
557
581
  seedResumeSessionOnFirstPrompt,
@@ -569,6 +593,7 @@ function createSession({
569
593
  model: string | undefined;
570
594
  provider: string | undefined;
571
595
  reasoningVariant: string | undefined;
596
+ mcpServers: Record<string, unknown> | undefined;
572
597
  openCodeSessionId: string | undefined;
573
598
  isResume: boolean;
574
599
  seedResumeSessionOnFirstPrompt: boolean;
@@ -586,7 +611,6 @@ function createSession({
586
611
  let pendingResumeSessionId = seedResumeSessionOnFirstPrompt
587
612
  ? openCodeSessionId
588
613
  : undefined;
589
- let instructionsApplied = isResume;
590
614
  let activeTurn = false;
591
615
  const pendingCompactionParts: HarnessV1StreamPart[] = [];
592
616
 
@@ -729,6 +753,7 @@ function createSession({
729
753
  model,
730
754
  provider,
731
755
  ...(reasoningVariant ? { variant: reasoningVariant } : {}),
756
+ ...(mcpServers == null ? {} : { mcpServers }),
732
757
  ...(permissionMode ? { permissionMode } : {}),
733
758
  ...(builtinToolFiltering ? { builtinToolFiltering } : {}),
734
759
  ...(pendingResumeSessionId
@@ -748,9 +773,6 @@ function createSession({
748
773
  emit: promptOpts.emit,
749
774
  abortSignal: promptOpts.abortSignal,
750
775
  });
751
- const applyInstructions =
752
- !instructionsApplied && !!promptOpts.instructions;
753
- instructionsApplied = true;
754
776
  channel.send({
755
777
  type: 'start',
756
778
  operation: 'prompt',
@@ -760,7 +782,9 @@ function createSession({
760
782
  description: t.description,
761
783
  inputSchema: t.inputSchema,
762
784
  })),
763
- ...(applyInstructions ? { instructions: promptOpts.instructions } : {}),
785
+ ...(promptOpts.instructions
786
+ ? { instructions: promptOpts.instructions }
787
+ : {}),
764
788
  ...startBase(),
765
789
  });
766
790
  pendingResumeSessionId = undefined;
@@ -781,6 +805,9 @@ function createSession({
781
805
  description: t.description,
782
806
  inputSchema: t.inputSchema,
783
807
  })),
808
+ ...(continueOpts.instructions
809
+ ? { instructions: continueOpts.instructions }
810
+ : {}),
784
811
  ...startBase(),
785
812
  });
786
813
  pendingResumeSessionId = undefined;
@@ -808,6 +835,7 @@ function createSession({
808
835
  provider,
809
836
  permissionMode,
810
837
  debug,
838
+ mcpServers,
811
839
  resumeSessionId: latestOpenCodeSessionId,
812
840
  onCompaction: part => pendingCompactionParts.push(part),
813
841
  });
@@ -964,6 +992,7 @@ async function runCompactOperation({
964
992
  provider,
965
993
  permissionMode,
966
994
  debug,
995
+ mcpServers,
967
996
  resumeSessionId,
968
997
  onCompaction,
969
998
  }: {
@@ -972,6 +1001,7 @@ async function runCompactOperation({
972
1001
  provider: string | undefined;
973
1002
  permissionMode: HarnessV1PermissionMode | undefined;
974
1003
  debug: HarnessV1DebugConfig | undefined;
1004
+ mcpServers: Record<string, unknown> | undefined;
975
1005
  resumeSessionId: string | undefined;
976
1006
  onCompaction: (part: HarnessV1StreamPart) => void;
977
1007
  }): Promise<void> {
@@ -999,6 +1029,7 @@ async function runCompactOperation({
999
1029
  tools: [],
1000
1030
  model,
1001
1031
  provider,
1032
+ ...(mcpServers == null ? {} : { mcpServers }),
1002
1033
  ...(permissionMode ? { permissionMode } : {}),
1003
1034
  ...(resumeSessionId ? { resumeSessionId } : {}),
1004
1035
  ...(debug ? { debug } : {}),