@ai-sdk/harness-opencode 1.0.103 → 1.0.105
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/CHANGELOG.md +21 -0
- package/dist/bridge/index.mjs +10 -2
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/index.js +35 -51
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/bridge/index.ts +12 -2
- package/src/opencode-bridge-protocol.ts +1 -0
- package/src/opencode-harness.ts +50 -65
package/src/bridge/index.ts
CHANGED
|
@@ -342,8 +342,15 @@ function buildProviderConfig(
|
|
|
342
342
|
apiKey: procEnv.AI_GATEWAY_API_KEY,
|
|
343
343
|
baseURL: toOpenCodeGatewayBaseUrl(procEnv.AI_GATEWAY_BASE_URL),
|
|
344
344
|
...(HARNESS_CLIENT_APP
|
|
345
|
-
? {
|
|
346
|
-
|
|
345
|
+
? {
|
|
346
|
+
headers: {
|
|
347
|
+
...start.headers,
|
|
348
|
+
'x-client-app': HARNESS_CLIENT_APP,
|
|
349
|
+
},
|
|
350
|
+
}
|
|
351
|
+
: start.headers
|
|
352
|
+
? { headers: start.headers }
|
|
353
|
+
: {}),
|
|
347
354
|
},
|
|
348
355
|
...(modelID
|
|
349
356
|
? {
|
|
@@ -369,6 +376,7 @@ function buildProviderConfig(
|
|
|
369
376
|
...(procEnv.OPENAI_BASE_URL
|
|
370
377
|
? { baseURL: procEnv.OPENAI_BASE_URL }
|
|
371
378
|
: {}),
|
|
379
|
+
...(start.headers ? { headers: start.headers } : {}),
|
|
372
380
|
...parseOpenAIQueryParams(),
|
|
373
381
|
},
|
|
374
382
|
...(modelID
|
|
@@ -400,6 +408,7 @@ function buildProviderConfig(
|
|
|
400
408
|
...(procEnv.ANTHROPIC_BASE_URL
|
|
401
409
|
? { baseURL: procEnv.ANTHROPIC_BASE_URL }
|
|
402
410
|
: {}),
|
|
411
|
+
...(start.headers ? { headers: start.headers } : {}),
|
|
403
412
|
},
|
|
404
413
|
},
|
|
405
414
|
};
|
|
@@ -422,6 +431,7 @@ function buildProviderConfig(
|
|
|
422
431
|
...(procEnv.OPENAI_PROJECT
|
|
423
432
|
? { project: procEnv.OPENAI_PROJECT }
|
|
424
433
|
: {}),
|
|
434
|
+
...(start.headers ? { headers: start.headers } : {}),
|
|
425
435
|
...parseOpenAIQueryParams(),
|
|
426
436
|
},
|
|
427
437
|
},
|
|
@@ -18,6 +18,7 @@ export const startMessageSchema = harnessV1BridgeStartBaseSchema.extend({
|
|
|
18
18
|
resumeSessionId: z.string().optional(),
|
|
19
19
|
openCodeConfig: z.record(z.string(), z.unknown()).optional(),
|
|
20
20
|
mcpServers: z.record(z.string(), z.unknown()).optional(),
|
|
21
|
+
headers: z.record(z.string(), z.string()).optional(),
|
|
21
22
|
});
|
|
22
23
|
|
|
23
24
|
export type StartMessage = z.infer<typeof startMessageSchema>;
|
package/src/opencode-harness.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
type HarnessV1PermissionMode,
|
|
15
15
|
type HarnessV1Prompt,
|
|
16
16
|
type HarnessV1PromptControl,
|
|
17
|
+
type HarnessV1ResponseFormat,
|
|
17
18
|
type HarnessV1PortEndpoint,
|
|
18
19
|
type HarnessV1ResumeSessionState,
|
|
19
20
|
type HarnessV1Session,
|
|
@@ -39,7 +40,7 @@ import {
|
|
|
39
40
|
warnCredentialBrokeringUnavailable,
|
|
40
41
|
waitForBridgeReady,
|
|
41
42
|
withBridgeToken,
|
|
42
|
-
writeSkills
|
|
43
|
+
writeSkills,
|
|
43
44
|
type WriteSkillsResult,
|
|
44
45
|
} from '@ai-sdk/harness/utils';
|
|
45
46
|
import {
|
|
@@ -412,6 +413,7 @@ export function createOpenCode(
|
|
|
412
413
|
reasoningVariant: settings.reasoningVariant,
|
|
413
414
|
openCodeConfig: settings.openCodeConfig,
|
|
414
415
|
mcpServers: settings.mcpServers,
|
|
416
|
+
headers: startOpts.headers,
|
|
415
417
|
openCodeSessionId: resumeSessionId,
|
|
416
418
|
isResume: true,
|
|
417
419
|
seedResumeSessionOnFirstPrompt: false,
|
|
@@ -569,6 +571,7 @@ export function createOpenCode(
|
|
|
569
571
|
reasoningVariant: settings.reasoningVariant,
|
|
570
572
|
openCodeConfig: settings.openCodeConfig,
|
|
571
573
|
mcpServers: settings.mcpServers,
|
|
574
|
+
headers: startOpts.headers,
|
|
572
575
|
openCodeSessionId: resumeSessionId,
|
|
573
576
|
isResume: respawnStrategy !== undefined,
|
|
574
577
|
seedResumeSessionOnFirstPrompt: respawnStrategy !== undefined,
|
|
@@ -653,30 +656,6 @@ async function resolveBridgeEndpoint({
|
|
|
653
656
|
});
|
|
654
657
|
}
|
|
655
658
|
|
|
656
|
-
async function writeOpenCodeSkills({
|
|
657
|
-
sandbox,
|
|
658
|
-
skills,
|
|
659
|
-
homeDir,
|
|
660
|
-
abortSignal,
|
|
661
|
-
}: {
|
|
662
|
-
sandbox: SandboxSession;
|
|
663
|
-
skills: ReadonlyArray<HarnessV1Skill>;
|
|
664
|
-
homeDir: string;
|
|
665
|
-
abortSignal?: AbortSignal;
|
|
666
|
-
}): Promise<WriteSkillsResult> {
|
|
667
|
-
const skillsDir = path.posix.join(homeDir, '.agents', 'skills');
|
|
668
|
-
return writeHarnessSkills({
|
|
669
|
-
sandbox,
|
|
670
|
-
rootDir: skillsDir,
|
|
671
|
-
skills,
|
|
672
|
-
abortSignal,
|
|
673
|
-
invalidSkillNameMessage: ({ name }) =>
|
|
674
|
-
`Invalid OpenCode skill name: ${name}`,
|
|
675
|
-
invalidSkillFilePathMessage: ({ skillName, filePath }) =>
|
|
676
|
-
`Invalid OpenCode skill file path for ${skillName}: ${filePath}`,
|
|
677
|
-
});
|
|
678
|
-
}
|
|
679
|
-
|
|
680
659
|
function openWebSocket({
|
|
681
660
|
endpoint,
|
|
682
661
|
helloTimeoutMs,
|
|
@@ -786,6 +765,7 @@ function createSession({
|
|
|
786
765
|
reasoningVariant,
|
|
787
766
|
openCodeConfig,
|
|
788
767
|
mcpServers,
|
|
768
|
+
headers,
|
|
789
769
|
openCodeSessionId,
|
|
790
770
|
isResume,
|
|
791
771
|
seedResumeSessionOnFirstPrompt,
|
|
@@ -809,6 +789,7 @@ function createSession({
|
|
|
809
789
|
reasoningVariant: string | undefined;
|
|
810
790
|
openCodeConfig: Record<string, unknown> | undefined;
|
|
811
791
|
mcpServers: Record<string, unknown> | undefined;
|
|
792
|
+
headers: Readonly<Record<string, string>> | undefined;
|
|
812
793
|
openCodeSessionId: string | undefined;
|
|
813
794
|
isResume: boolean;
|
|
814
795
|
seedResumeSessionOnFirstPrompt: boolean;
|
|
@@ -990,6 +971,7 @@ function createSession({
|
|
|
990
971
|
...(reasoningVariant ? { variant: reasoningVariant } : {}),
|
|
991
972
|
...(openCodeConfig == null ? {} : { openCodeConfig }),
|
|
992
973
|
...(mcpServers == null ? {} : { mcpServers }),
|
|
974
|
+
...(headers == null ? {} : { headers }),
|
|
993
975
|
...(permissionMode ? { permissionMode } : {}),
|
|
994
976
|
...(builtinToolFiltering ? { builtinToolFiltering } : {}),
|
|
995
977
|
...(pendingResumeSessionId
|
|
@@ -1000,30 +982,48 @@ function createSession({
|
|
|
1000
982
|
...(debug ? { debug } : {}),
|
|
1001
983
|
});
|
|
1002
984
|
|
|
985
|
+
const prepareTurn = async (opts: {
|
|
986
|
+
responseFormat?: HarnessV1ResponseFormat;
|
|
987
|
+
skills: ReadonlyArray<HarnessV1Skill>;
|
|
988
|
+
emit: (event: HarnessV1StreamPart) => void;
|
|
989
|
+
abortSignal?: AbortSignal;
|
|
990
|
+
}): Promise<{
|
|
991
|
+
control: HarnessV1PromptControl;
|
|
992
|
+
skillWriteResult: WriteSkillsResult;
|
|
993
|
+
}> => {
|
|
994
|
+
if (
|
|
995
|
+
opts.responseFormat?.type === 'json' &&
|
|
996
|
+
opts.responseFormat.schema == null
|
|
997
|
+
) {
|
|
998
|
+
throw new HarnessCapabilityUnsupportedError({
|
|
999
|
+
message:
|
|
1000
|
+
"Harness 'opencode' requires a JSON schema for structured output.",
|
|
1001
|
+
harnessId: 'opencode',
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
const skillWriteResult = await writeSkills({
|
|
1005
|
+
sandbox,
|
|
1006
|
+
homePath: sandboxHomeDir,
|
|
1007
|
+
skillsDir: '.agents/skills',
|
|
1008
|
+
skills: opts.skills,
|
|
1009
|
+
abortSignal: opts.abortSignal,
|
|
1010
|
+
invalidSkillNameMessage: ({ name }) =>
|
|
1011
|
+
`Invalid OpenCode skill name: ${name}`,
|
|
1012
|
+
invalidSkillFilePathMessage: ({ skillName, filePath }) =>
|
|
1013
|
+
`Invalid OpenCode skill file path for ${skillName}: ${filePath}`,
|
|
1014
|
+
});
|
|
1015
|
+
const control = wireTurn({
|
|
1016
|
+
emit: opts.emit,
|
|
1017
|
+
abortSignal: opts.abortSignal,
|
|
1018
|
+
});
|
|
1019
|
+
return { control, skillWriteResult };
|
|
1020
|
+
};
|
|
1021
|
+
|
|
1003
1022
|
return {
|
|
1004
1023
|
sessionId,
|
|
1005
1024
|
isResume,
|
|
1006
1025
|
doPromptTurn: async promptOpts => {
|
|
1007
|
-
|
|
1008
|
-
promptOpts.responseFormat?.type === 'json' &&
|
|
1009
|
-
promptOpts.responseFormat.schema == null
|
|
1010
|
-
) {
|
|
1011
|
-
throw new HarnessCapabilityUnsupportedError({
|
|
1012
|
-
message:
|
|
1013
|
-
"Harness 'opencode' requires a JSON schema for structured output.",
|
|
1014
|
-
harnessId: 'opencode',
|
|
1015
|
-
});
|
|
1016
|
-
}
|
|
1017
|
-
const skillWriteResult = await writeOpenCodeSkills({
|
|
1018
|
-
sandbox,
|
|
1019
|
-
skills: promptOpts.skills,
|
|
1020
|
-
homeDir: sandboxHomeDir,
|
|
1021
|
-
abortSignal: promptOpts.abortSignal,
|
|
1022
|
-
});
|
|
1023
|
-
const control = wireTurn({
|
|
1024
|
-
emit: promptOpts.emit,
|
|
1025
|
-
abortSignal: promptOpts.abortSignal,
|
|
1026
|
-
});
|
|
1026
|
+
const { control, skillWriteResult } = await prepareTurn(promptOpts);
|
|
1027
1027
|
const turnModel = promptOpts.model ?? selectedModel;
|
|
1028
1028
|
if (turnModel) selectedModel = turnModel;
|
|
1029
1029
|
channel.send({
|
|
@@ -1048,26 +1048,7 @@ function createSession({
|
|
|
1048
1048
|
return control;
|
|
1049
1049
|
},
|
|
1050
1050
|
doContinueTurn: async continueOpts => {
|
|
1051
|
-
|
|
1052
|
-
continueOpts.responseFormat?.type === 'json' &&
|
|
1053
|
-
continueOpts.responseFormat.schema == null
|
|
1054
|
-
) {
|
|
1055
|
-
throw new HarnessCapabilityUnsupportedError({
|
|
1056
|
-
message:
|
|
1057
|
-
"Harness 'opencode' requires a JSON schema for structured output.",
|
|
1058
|
-
harnessId: 'opencode',
|
|
1059
|
-
});
|
|
1060
|
-
}
|
|
1061
|
-
const skillWriteResult = await writeOpenCodeSkills({
|
|
1062
|
-
sandbox,
|
|
1063
|
-
skills: continueOpts.skills,
|
|
1064
|
-
homeDir: sandboxHomeDir,
|
|
1065
|
-
abortSignal: continueOpts.abortSignal,
|
|
1066
|
-
});
|
|
1067
|
-
const control = wireTurn({
|
|
1068
|
-
emit: continueOpts.emit,
|
|
1069
|
-
abortSignal: continueOpts.abortSignal,
|
|
1070
|
-
});
|
|
1051
|
+
const { control, skillWriteResult } = await prepareTurn(continueOpts);
|
|
1071
1052
|
if (rerunContinue) {
|
|
1072
1053
|
const turnModel = continueOpts.model ?? selectedModel;
|
|
1073
1054
|
if (turnModel) selectedModel = turnModel;
|
|
@@ -1116,6 +1097,7 @@ function createSession({
|
|
|
1116
1097
|
debug,
|
|
1117
1098
|
openCodeConfig,
|
|
1118
1099
|
mcpServers,
|
|
1100
|
+
headers,
|
|
1119
1101
|
resumeSessionId: latestOpenCodeSessionId,
|
|
1120
1102
|
onCompaction: part => pendingCompactionParts.push(part),
|
|
1121
1103
|
});
|
|
@@ -1289,6 +1271,7 @@ async function runCompactOperation({
|
|
|
1289
1271
|
debug,
|
|
1290
1272
|
openCodeConfig,
|
|
1291
1273
|
mcpServers,
|
|
1274
|
+
headers,
|
|
1292
1275
|
resumeSessionId,
|
|
1293
1276
|
onCompaction,
|
|
1294
1277
|
}: {
|
|
@@ -1299,6 +1282,7 @@ async function runCompactOperation({
|
|
|
1299
1282
|
debug: HarnessV1DebugConfig | undefined;
|
|
1300
1283
|
openCodeConfig: Record<string, unknown> | undefined;
|
|
1301
1284
|
mcpServers: Record<string, unknown> | undefined;
|
|
1285
|
+
headers: Readonly<Record<string, string>> | undefined;
|
|
1302
1286
|
resumeSessionId: string | undefined;
|
|
1303
1287
|
onCompaction: (part: HarnessV1StreamPart) => void;
|
|
1304
1288
|
}): Promise<void> {
|
|
@@ -1328,6 +1312,7 @@ async function runCompactOperation({
|
|
|
1328
1312
|
provider,
|
|
1329
1313
|
...(openCodeConfig == null ? {} : { openCodeConfig }),
|
|
1330
1314
|
...(mcpServers == null ? {} : { mcpServers }),
|
|
1315
|
+
...(headers == null ? {} : { headers }),
|
|
1331
1316
|
...(permissionMode ? { permissionMode } : {}),
|
|
1332
1317
|
...(resumeSessionId ? { resumeSessionId } : {}),
|
|
1333
1318
|
...(debug ? { debug } : {}),
|