@ai-sdk/harness-opencode 1.0.93 → 1.0.95

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
@@ -94,7 +94,8 @@ async function readBridgeAsset(name) {
94
94
  // src/opencode-auth.ts
95
95
  import {
96
96
  createCredentialRequestTransformation,
97
- getAiGatewayAuthFromEnv
97
+ getAiGatewayAuthFromEnv,
98
+ isHarnessAuthenticationEnvironment
98
99
  } from "@ai-sdk/harness/utils";
99
100
  var OPENCODE_CREDENTIAL_ENVIRONMENT_VARIABLES = [
100
101
  "AI_GATEWAY_API_KEY",
@@ -211,29 +212,22 @@ function resolveOpenCodeEnv({
211
212
  provider,
212
213
  processEnv = process.env
213
214
  }) {
214
- const normalizedAuth = normalizeOpenCodeAuthToLegacyAuth(auth);
215
+ const suppliedEnvironment = isHarnessAuthenticationEnvironment(auth);
216
+ const authenticationEnvironment = suppliedEnvironment ? auth : processEnv;
215
217
  const selectedProvider = resolveOpenCodeProvider({ model, provider });
216
- if (normalizedAuth?.openaiCompatible) {
217
- return pickOpenAICompatible(normalizedAuth.openaiCompatible, processEnv);
218
+ if (selectedProvider === "openai" && auth === "openai") {
219
+ return pickOpenAI({ processEnv: authenticationEnvironment });
218
220
  }
219
- if (selectedProvider === "openai") {
220
- if (normalizedAuth?.openai) {
221
- return pickOpenAI({ explicit: normalizedAuth.openai, processEnv });
222
- }
223
- } else if (normalizedAuth?.anthropic) {
224
- return pickAnthropic({ explicit: normalizedAuth.anthropic, processEnv });
225
- }
226
- const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({ env: processEnv });
227
- if (normalizedAuth?.gateway) {
228
- return pickGateway({
229
- explicit: normalizedAuth.gateway,
230
- gatewayAuthFromEnv
231
- });
221
+ if (selectedProvider === "anthropic" && auth === "anthropic") {
222
+ return pickAnthropic({ processEnv: authenticationEnvironment });
232
223
  }
233
- if (gatewayAuthFromEnv.apiKey) {
234
- return pickGateway({ explicit: {}, gatewayAuthFromEnv });
224
+ const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({
225
+ env: authenticationEnvironment
226
+ });
227
+ if (auth === "ai-gateway" || gatewayAuthFromEnv.apiKey) {
228
+ return pickGateway({ gatewayAuthFromEnv });
235
229
  }
236
- return selectedProvider === "openai" ? pickOpenAI({ processEnv }) : pickAnthropic({ processEnv });
230
+ return selectedProvider === "openai" ? pickOpenAI({ processEnv: authenticationEnvironment }) : pickAnthropic({ processEnv: authenticationEnvironment });
237
231
  }
238
232
  function resolveOpenCodeAuthenticationMode({
239
233
  auth,
@@ -241,17 +235,17 @@ function resolveOpenCodeAuthenticationMode({
241
235
  provider,
242
236
  processEnv = process.env
243
237
  }) {
244
- if (typeof auth !== "string" && auth?.openaiCompatible) {
245
- return "openai";
238
+ if (isHarnessAuthenticationEnvironment(auth)) {
239
+ return getAiGatewayAuthFromEnv({ env: auth }).apiKey ? "ai-gateway" : resolveOpenCodeProvider({ model, provider });
246
240
  }
247
241
  const selectedProvider = resolveOpenCodeProvider({ model, provider });
248
- if (selectedProvider === "openai" && (auth === "openai" || typeof auth !== "string" && auth?.openai)) {
242
+ if (selectedProvider === "openai" && auth === "openai") {
249
243
  return "openai";
250
244
  }
251
- if (selectedProvider === "anthropic" && (auth === "anthropic" || typeof auth !== "string" && auth?.anthropic)) {
245
+ if (selectedProvider === "anthropic" && auth === "anthropic") {
252
246
  return "anthropic";
253
247
  }
254
- if (auth === "ai-gateway" || typeof auth !== "string" && auth?.gateway) {
248
+ if (auth === "ai-gateway") {
255
249
  return "ai-gateway";
256
250
  }
257
251
  if (getAiGatewayAuthFromEnv({ env: processEnv }).apiKey) {
@@ -259,80 +253,39 @@ function resolveOpenCodeAuthenticationMode({
259
253
  }
260
254
  return selectedProvider;
261
255
  }
262
- function normalizeOpenCodeAuthToLegacyAuth(auth) {
263
- if (auth == null || auth === "auto") {
264
- return void 0;
265
- }
266
- if (typeof auth === "string") {
267
- switch (auth) {
268
- case "anthropic":
269
- return { anthropic: {} };
270
- case "openai":
271
- return { openai: {} };
272
- case "ai-gateway":
273
- return { gateway: {} };
274
- default:
275
- return void 0;
276
- }
277
- }
278
- console.warn(
279
- '[opencode] Passing an object to auth options is deprecated. Use a string mode ("auto" | "anthropic" | "openai" | "ai-gateway") instead, and pass credentials via environment variables.'
280
- );
281
- return auth;
282
- }
283
- function pickOpenAICompatible(explicit, processEnv) {
284
- const env = {};
285
- const apiKey = explicit.apiKey ?? processEnv.OPENAI_API_KEY;
286
- if (apiKey) env.OPENAI_API_KEY = apiKey;
287
- const baseUrl = explicit.baseUrl ?? processEnv.OPENAI_BASE_URL;
288
- if (baseUrl) env.OPENAI_BASE_URL = baseUrl;
289
- const name = explicit.name ?? processEnv.OPENAI_NAME;
290
- if (name) env.OPENAI_NAME = name;
291
- if (explicit.queryParams && Object.keys(explicit.queryParams).length > 0) {
292
- env.OPENAI_QUERY_PARAMS_JSON = JSON.stringify(explicit.queryParams);
293
- } else if (processEnv.OPENAI_QUERY_PARAMS_JSON) {
294
- env.OPENAI_QUERY_PARAMS_JSON = processEnv.OPENAI_QUERY_PARAMS_JSON;
295
- }
296
- return env;
297
- }
298
256
  function pickOpenAI({
299
- explicit,
300
257
  processEnv
301
258
  }) {
302
259
  const env = {};
303
- const apiKey = explicit?.apiKey ?? processEnv.OPENAI_API_KEY;
260
+ const apiKey = processEnv.OPENAI_API_KEY;
304
261
  if (apiKey) env.OPENAI_API_KEY = apiKey;
305
- const baseUrl = explicit?.baseUrl ?? processEnv.OPENAI_BASE_URL;
262
+ const baseUrl = processEnv.OPENAI_BASE_URL;
306
263
  if (baseUrl) env.OPENAI_BASE_URL = baseUrl;
307
- const organization = explicit?.organization ?? processEnv.OPENAI_ORGANIZATION;
264
+ const organization = processEnv.OPENAI_ORGANIZATION;
308
265
  if (organization) env.OPENAI_ORGANIZATION = organization;
309
- const project = explicit?.project ?? processEnv.OPENAI_PROJECT;
266
+ const project = processEnv.OPENAI_PROJECT;
310
267
  if (project) env.OPENAI_PROJECT = project;
311
268
  return env;
312
269
  }
313
270
  function pickAnthropic({
314
- explicit,
315
271
  processEnv
316
272
  }) {
317
273
  const env = {};
318
- const apiKey = explicit?.apiKey ?? processEnv.ANTHROPIC_API_KEY;
274
+ const apiKey = processEnv.ANTHROPIC_API_KEY;
319
275
  if (apiKey) env.ANTHROPIC_API_KEY = apiKey;
320
- const authToken = explicit?.authToken ?? processEnv.ANTHROPIC_AUTH_TOKEN;
276
+ const authToken = processEnv.ANTHROPIC_AUTH_TOKEN;
321
277
  if (authToken) env.ANTHROPIC_AUTH_TOKEN = authToken;
322
- const baseUrl = explicit?.baseUrl ?? processEnv.ANTHROPIC_BASE_URL;
278
+ const baseUrl = processEnv.ANTHROPIC_BASE_URL;
323
279
  if (baseUrl) env.ANTHROPIC_BASE_URL = baseUrl;
324
280
  return env;
325
281
  }
326
282
  function pickGateway({
327
- explicit,
328
283
  gatewayAuthFromEnv
329
284
  }) {
330
285
  const env = {};
331
- const apiKey = explicit.apiKey ?? gatewayAuthFromEnv.apiKey;
286
+ const apiKey = gatewayAuthFromEnv.apiKey;
332
287
  if (apiKey) env.AI_GATEWAY_API_KEY = apiKey;
333
- const baseUrl = toOpenCodeGatewayBaseUrl(
334
- explicit.baseUrl ?? gatewayAuthFromEnv.baseUrl
335
- );
288
+ const baseUrl = toOpenCodeGatewayBaseUrl(gatewayAuthFromEnv.baseUrl);
336
289
  env.AI_GATEWAY_BASE_URL = baseUrl;
337
290
  return env;
338
291
  }
@@ -355,7 +308,9 @@ var startMessageSchema = harnessV1BridgeStartBaseSchema.extend({
355
308
  provider: z.string().optional(),
356
309
  variant: z.string().optional(),
357
310
  instructions: z.string().optional(),
311
+ skillsChanged: z.boolean().optional(),
358
312
  resumeSessionId: z.string().optional(),
313
+ openCodeConfig: z.record(z.string(), z.unknown()).optional(),
359
314
  mcpServers: z.record(z.string(), z.unknown()).optional()
360
315
  });
361
316
  var inboundMessageSchema = z.discriminatedUnion("type", [
@@ -364,7 +319,7 @@ var inboundMessageSchema = z.discriminatedUnion("type", [
364
319
  ]);
365
320
 
366
321
  // src/version.ts
367
- var VERSION = true ? "1.0.93" : "0.0.0-test";
322
+ var VERSION = true ? "1.0.95" : "0.0.0-test";
368
323
 
369
324
  // src/opencode-harness.ts
370
325
  var OPENCODE_CLIENT_APP = `ai-sdk/harness-opencode/${VERSION}`;
@@ -492,6 +447,7 @@ function createOpenCode(settings = {}) {
492
447
  lifecycleStateSchema: openCodeResumeStateSchema,
493
448
  getBootstrap: getOpenCodeBootstrap,
494
449
  doStart: async (startOpts) => {
450
+ const configuredModel = startOpts.model ?? settings.model;
495
451
  const sandboxSession = startOpts.sandboxSession;
496
452
  const toolSafeSandboxSession = getRestrictedSandboxSession(sandboxSession);
497
453
  const sandboxId = "id" in sandboxSession ? sandboxSession.id : void 0;
@@ -518,12 +474,12 @@ function createOpenCode(settings = {}) {
518
474
  const coords = resumeData?.bridge;
519
475
  const authenticationMode = resolveOpenCodeAuthenticationMode({
520
476
  auth: settings.auth,
521
- model: settings.model,
477
+ model: configuredModel,
522
478
  provider: settings.provider
523
479
  });
524
480
  const resolvedAuthEnvironment = resolveOpenCodeEnv({
525
481
  auth: settings.auth,
526
- model: settings.model,
482
+ model: configuredModel,
527
483
  provider: settings.provider
528
484
  });
529
485
  let sandboxAuthEnvironment = resolvedAuthEnvironment;
@@ -558,10 +514,18 @@ function createOpenCode(settings = {}) {
558
514
  OPENCODE_BOOTSTRAP_DIR
559
515
  );
560
516
  const workDir = startOpts.sessionWorkDir;
517
+ const sandboxHomeDir = await resolveSandboxHomeDir({
518
+ sandbox: toolSafeSandboxSession,
519
+ abortSignal: startOpts.abortSignal
520
+ });
521
+ const skillsDir = path.posix.join(sandboxHomeDir, ".agents", "skills");
561
522
  const sessionDataDir = `${defaultWorkingDirectory}/.agent-runs/${startOpts.sessionId}`;
562
523
  const bridgeStateDir = `${sessionDataDir}/bridge`;
563
524
  const timeoutMs = settings.startupTimeoutMs ?? 12e4;
564
- const model = splitOpenCodeModel(settings.model, settings.provider).model;
525
+ const model = splitOpenCodeModel(
526
+ configuredModel,
527
+ settings.provider
528
+ ).model;
565
529
  const report = startOpts.observability?.report;
566
530
  const onDiagnostic = report ? (frame) => report(
567
531
  harnessV1DiagnosticFromBridgeFrame(frame, {
@@ -606,6 +570,7 @@ function createOpenCode(settings = {}) {
606
570
  model,
607
571
  provider: settings.provider,
608
572
  reasoningVariant: settings.reasoningVariant,
573
+ openCodeConfig: settings.openCodeConfig,
609
574
  mcpServers: settings.mcpServers,
610
575
  openCodeSessionId: resumeSessionId,
611
576
  isResume: true,
@@ -618,6 +583,8 @@ function createOpenCode(settings = {}) {
618
583
  debug: startOpts.observability?.debug,
619
584
  permissionMode: startOpts.permissionMode,
620
585
  builtinToolFiltering: startOpts.builtinToolFiltering,
586
+ sandbox: toolSafeSandboxSession,
587
+ sandboxHomeDir,
621
588
  supportsUserMessageResponses: () => supportsUserMessageResponses2
622
589
  });
623
590
  } catch {
@@ -640,20 +607,6 @@ function createOpenCode(settings = {}) {
640
607
  override: settings.port
641
608
  });
642
609
  const token = settings.mintBridgeToken == null ? randomBytes(32).toString("hex") : settings.mintBridgeToken(sandboxId);
643
- const sandboxHomeDir = await resolveSandboxHomeDir({
644
- sandbox: toolSafeSandboxSession,
645
- abortSignal: startOpts.abortSignal
646
- });
647
- const xdgConfigHome = `${sandboxHomeDir}/.config`;
648
- const xdgCacheHome = `${sandboxHomeDir}/.cache`;
649
- const xdgDataHome = `${sandboxHomeDir}/.local/share`;
650
- const xdgStateHome = `${sandboxHomeDir}/.local/state`;
651
- const skillSetup = startOpts.skills && startOpts.skills.length > 0 ? await writeOpenCodeSkills({
652
- sandbox: toolSafeSandboxSession,
653
- skills: startOpts.skills,
654
- homeDir: sandboxHomeDir,
655
- abortSignal: startOpts.abortSignal
656
- }) : void 0;
657
610
  const forwardedAuthEnvironment = credentialsBrokered ? sandboxAuthEnvironment : await applyCredentialForwarding({
658
611
  environment: sandboxAuthEnvironment,
659
612
  credentialEnvironmentVariables: OPENCODE_CREDENTIAL_ENVIRONMENT_VARIABLES,
@@ -664,17 +617,11 @@ function createOpenCode(settings = {}) {
664
617
  AI_SDK_HARNESS_CLIENT_APP: OPENCODE_CLIENT_APP,
665
618
  BRIDGE_CHANNEL_TOKEN: token,
666
619
  BRIDGE_WS_PORT: String(port),
667
- HOME: sandboxHomeDir,
668
- USERPROFILE: sandboxHomeDir,
669
- XDG_CONFIG_HOME: xdgConfigHome,
670
- XDG_CACHE_HOME: xdgCacheHome,
671
- XDG_DATA_HOME: xdgDataHome,
672
- XDG_STATE_HOME: xdgStateHome,
673
620
  ...respawnStrategy === "replay" ? { BRIDGE_REPLAY_FROM_DISK: "1" } : {}
674
621
  };
675
622
  if (respawnStrategy === void 0) {
676
623
  await toolSafeSandboxSession.run({
677
- command: `mkdir -p ${shellQuote(workDir)} ${shellQuote(bridgeStateDir)} ${shellQuote(xdgConfigHome)} ${shellQuote(xdgCacheHome)} ${shellQuote(xdgDataHome)} ${shellQuote(xdgStateHome)}`,
624
+ command: `mkdir -p ${shellQuote(workDir)} ${shellQuote(bridgeStateDir)}`,
678
625
  abortSignal: startOpts.abortSignal
679
626
  });
680
627
  }
@@ -685,7 +632,7 @@ function createOpenCode(settings = {}) {
685
632
  abortSignal: startOpts.abortSignal
686
633
  });
687
634
  const proc = await toolSafeSandboxSession.spawn({
688
- command: `node ${shellQuote(`${bootstrapDir}/bridge.mjs`)} --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)} --bootstrap-dir ${shellQuote(bootstrapDir)}${skillSetup ? ` --skills-dir ${shellQuote(skillSetup.skillsDir)}` : ""}`,
635
+ command: `node ${shellQuote(`${bootstrapDir}/bridge.mjs`)} --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)} --bootstrap-dir ${shellQuote(bootstrapDir)} --skills-dir ${shellQuote(skillsDir)}`,
689
636
  env,
690
637
  abortSignal: startOpts.abortSignal
691
638
  });
@@ -749,6 +696,7 @@ function createOpenCode(settings = {}) {
749
696
  model,
750
697
  provider: settings.provider,
751
698
  reasoningVariant: settings.reasoningVariant,
699
+ openCodeConfig: settings.openCodeConfig,
752
700
  mcpServers: settings.mcpServers,
753
701
  openCodeSessionId: resumeSessionId,
754
702
  isResume: respawnStrategy !== void 0,
@@ -761,6 +709,8 @@ function createOpenCode(settings = {}) {
761
709
  debug: startOpts.observability?.debug,
762
710
  permissionMode: startOpts.permissionMode,
763
711
  builtinToolFiltering: startOpts.builtinToolFiltering,
712
+ sandbox: toolSafeSandboxSession,
713
+ sandboxHomeDir,
764
714
  supportsUserMessageResponses: () => supportsUserMessageResponses
765
715
  });
766
716
  }
@@ -819,7 +769,7 @@ async function writeOpenCodeSkills({
819
769
  abortSignal
820
770
  }) {
821
771
  const skillsDir = path.posix.join(homeDir, ".agents", "skills");
822
- await writeHarnessSkills({
772
+ return writeHarnessSkills({
823
773
  sandbox,
824
774
  rootDir: skillsDir,
825
775
  skills,
@@ -827,7 +777,6 @@ async function writeOpenCodeSkills({
827
777
  invalidSkillNameMessage: ({ name }) => `Invalid OpenCode skill name: ${name}`,
828
778
  invalidSkillFilePathMessage: ({ skillName, filePath }) => `Invalid OpenCode skill file path for ${skillName}: ${filePath}`
829
779
  });
830
- return { skillsDir };
831
780
  }
832
781
  function openWebSocket({
833
782
  endpoint,
@@ -927,6 +876,7 @@ function createSession({
927
876
  model,
928
877
  provider,
929
878
  reasoningVariant,
879
+ openCodeConfig,
930
880
  mcpServers,
931
881
  openCodeSessionId,
932
882
  isResume,
@@ -939,6 +889,8 @@ function createSession({
939
889
  debug,
940
890
  permissionMode,
941
891
  builtinToolFiltering,
892
+ sandbox,
893
+ sandboxHomeDir,
942
894
  supportsUserMessageResponses
943
895
  }) {
944
896
  let stopped = false;
@@ -1084,6 +1036,7 @@ function createSession({
1084
1036
  model,
1085
1037
  provider,
1086
1038
  ...reasoningVariant ? { variant: reasoningVariant } : {},
1039
+ ...openCodeConfig == null ? {} : { openCodeConfig },
1087
1040
  ...mcpServers == null ? {} : { mcpServers },
1088
1041
  ...permissionMode ? { permissionMode } : {},
1089
1042
  ...builtinToolFiltering ? { builtinToolFiltering } : {},
@@ -1101,6 +1054,12 @@ function createSession({
1101
1054
  harnessId: "opencode"
1102
1055
  });
1103
1056
  }
1057
+ const skillWriteResult = await writeOpenCodeSkills({
1058
+ sandbox,
1059
+ skills: promptOpts.skills,
1060
+ homeDir: sandboxHomeDir,
1061
+ abortSignal: promptOpts.abortSignal
1062
+ });
1104
1063
  const control = wireTurn({
1105
1064
  emit: promptOpts.emit,
1106
1065
  abortSignal: promptOpts.abortSignal
@@ -1116,6 +1075,7 @@ function createSession({
1116
1075
  })),
1117
1076
  ...promptOpts.responseFormat == null ? {} : { responseFormat: promptOpts.responseFormat },
1118
1077
  ...promptOpts.instructions ? { instructions: promptOpts.instructions } : {},
1078
+ skillsChanged: skillWriteResult.changed,
1119
1079
  ...startBase()
1120
1080
  });
1121
1081
  pendingResumeSessionId = void 0;
@@ -1128,6 +1088,12 @@ function createSession({
1128
1088
  harnessId: "opencode"
1129
1089
  });
1130
1090
  }
1091
+ const skillWriteResult = await writeOpenCodeSkills({
1092
+ sandbox,
1093
+ skills: continueOpts.skills,
1094
+ homeDir: sandboxHomeDir,
1095
+ abortSignal: continueOpts.abortSignal
1096
+ });
1131
1097
  const control = wireTurn({
1132
1098
  emit: continueOpts.emit,
1133
1099
  abortSignal: continueOpts.abortSignal
@@ -1144,6 +1110,7 @@ function createSession({
1144
1110
  })),
1145
1111
  ...continueOpts.responseFormat == null ? {} : { responseFormat: continueOpts.responseFormat },
1146
1112
  ...continueOpts.instructions ? { instructions: continueOpts.instructions } : {},
1113
+ skillsChanged: skillWriteResult.changed,
1147
1114
  ...startBase()
1148
1115
  });
1149
1116
  pendingResumeSessionId = void 0;
@@ -1169,6 +1136,7 @@ function createSession({
1169
1136
  provider,
1170
1137
  permissionMode,
1171
1138
  debug,
1139
+ openCodeConfig,
1172
1140
  mcpServers,
1173
1141
  resumeSessionId: latestOpenCodeSessionId,
1174
1142
  onCompaction: (part) => pendingCompactionParts.push(part)
@@ -1326,6 +1294,7 @@ async function runCompactOperation({
1326
1294
  provider,
1327
1295
  permissionMode,
1328
1296
  debug,
1297
+ openCodeConfig,
1329
1298
  mcpServers,
1330
1299
  resumeSessionId,
1331
1300
  onCompaction
@@ -1354,6 +1323,7 @@ async function runCompactOperation({
1354
1323
  tools: [],
1355
1324
  model,
1356
1325
  provider,
1326
+ ...openCodeConfig == null ? {} : { openCodeConfig },
1357
1327
  ...mcpServers == null ? {} : { mcpServers },
1358
1328
  ...permissionMode ? { permissionMode } : {},
1359
1329
  ...resumeSessionId ? { resumeSessionId } : {},