@ai-sdk/harness-acp 1.0.31 → 1.0.33
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 +20 -0
- package/README.md +10 -9
- package/dist/bridge/host-tool-mcp.mjs +1 -1
- package/dist/bridge/index.mjs +59 -24
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/index.d.ts +13 -17
- package/dist/index.js +86 -75
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/acp-harness.ts +8 -3
- package/src/index.ts +1 -2
- package/src/v1/{acp-bootstrap.ts → acp-v1-bootstrap.ts} +12 -20
- package/src/v1/acp-v1-bridge-protocol.ts +27 -6
- package/src/v1/acp-v1-harness.ts +41 -49
- package/src/v1/acp-v1-settings.ts +12 -16
- package/src/v1/acp-v1-turn-start-config.ts +7 -3
- package/src/v1/bridge/acp-v1-bridge-environment.ts +4 -8
- package/src/v1/bridge/index.ts +10 -2
- package/src/v1/bridge/model-mapping.ts +35 -0
- package/src/v1/bridge/protocol-configuration.ts +6 -2
- package/src/v1/implementation.ts +8 -0
- package/src/v1/index.ts +1 -2
- package/src/acp-bridge-protocol.ts +0 -13
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/harness-acp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.33",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@ai-sdk/harness": "1.0.
|
|
30
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
29
|
+
"@ai-sdk/harness": "1.0.95",
|
|
30
|
+
"@ai-sdk/provider-utils": "5.0.34",
|
|
31
31
|
"ws": "^8.21.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
package/src/acp-harness.ts
CHANGED
|
@@ -48,11 +48,12 @@ export type ACPHarnessSettings<TBuiltinTools extends ToolSet = {}> = {
|
|
|
48
48
|
readonly credentialForwarding?: ACPV1Settings['credentialForwarding'];
|
|
49
49
|
readonly env?: ACPV1Settings['env'];
|
|
50
50
|
readonly authentication?: ACPV1Settings['authentication'];
|
|
51
|
+
readonly clientCapabilities?: ACPV1Settings['clientCapabilities'];
|
|
51
52
|
readonly providerAuthentication?: ACPV1Settings['providerAuthentication'];
|
|
52
53
|
/**
|
|
53
|
-
* Maps
|
|
54
|
+
* Maps the HarnessAgent model identifier to an ACP session operation.
|
|
54
55
|
*/
|
|
55
|
-
readonly
|
|
56
|
+
readonly modelMapping: ACPV1Settings['modelMapping'];
|
|
56
57
|
/**
|
|
57
58
|
* @deprecated Use `model` on `HarnessAgent` instead.
|
|
58
59
|
*/
|
|
@@ -114,6 +115,8 @@ const acpResumeStateSchema = z.object({
|
|
|
114
115
|
skillsDirectory: z.string().optional(),
|
|
115
116
|
});
|
|
116
117
|
|
|
118
|
+
type ACPBridgeCoords = z.infer<typeof acpBridgeCoordsSchema>;
|
|
119
|
+
|
|
117
120
|
export function createACP<TBuiltinTools extends ToolSet = {}>(
|
|
118
121
|
settings: ACPHarnessSettings<TBuiltinTools>,
|
|
119
122
|
): HarnessV1<TBuiltinTools> {
|
|
@@ -148,7 +151,9 @@ export function createACP<TBuiltinTools extends ToolSet = {}>(
|
|
|
148
151
|
portEndpoint: settings.portEndpoint,
|
|
149
152
|
startupTimeoutMs: settings.startupTimeoutMs,
|
|
150
153
|
clientApp,
|
|
151
|
-
lifecycleStateSchema: acpResumeStateSchema
|
|
154
|
+
lifecycleStateSchema: acpResumeStateSchema satisfies z.ZodType<{
|
|
155
|
+
bridge?: ACPBridgeCoords;
|
|
156
|
+
}>,
|
|
152
157
|
});
|
|
153
158
|
}
|
|
154
159
|
default:
|
package/src/index.ts
CHANGED
|
@@ -120,31 +120,23 @@ export function createACPBootstrap({
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
async function readBridgeAsset({ name }: { name: string }): Promise<string> {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;
|
|
133
|
-
lastError = error;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
throw lastError ?? new Error(`ACP bridge asset not found: ${name}`);
|
|
123
|
+
return readFile(
|
|
124
|
+
fileURLToPath(
|
|
125
|
+
resolveBridgeAssetUrl({
|
|
126
|
+
name,
|
|
127
|
+
moduleUrl: import.meta.url,
|
|
128
|
+
}),
|
|
129
|
+
),
|
|
130
|
+
'utf8',
|
|
131
|
+
);
|
|
137
132
|
}
|
|
138
133
|
|
|
139
|
-
export function
|
|
134
|
+
export function resolveBridgeAssetUrl({
|
|
140
135
|
name,
|
|
141
136
|
moduleUrl,
|
|
142
137
|
}: {
|
|
143
138
|
name: string;
|
|
144
139
|
moduleUrl: string | URL;
|
|
145
|
-
}): URL
|
|
146
|
-
return
|
|
147
|
-
new URL(`./bridge/${name}`, moduleUrl),
|
|
148
|
-
new URL(`../bridge/${name}`, moduleUrl),
|
|
149
|
-
];
|
|
140
|
+
}): URL {
|
|
141
|
+
return new URL(`./bridge/${name}`, moduleUrl);
|
|
150
142
|
}
|
|
@@ -14,6 +14,7 @@ import { z } from 'zod/v4';
|
|
|
14
14
|
import type { ACPToolCall } from '../acp-tool-call';
|
|
15
15
|
import type {
|
|
16
16
|
ACPInstructionMapping,
|
|
17
|
+
ACPModelMapping,
|
|
17
18
|
ACPPermissionModeMapping,
|
|
18
19
|
} from './acp-v1-settings';
|
|
19
20
|
import { acpTextContentBlockSchema } from './acp-v1-prompt';
|
|
@@ -125,6 +126,20 @@ const outputSchemaMappingSchema: z.ZodType<ACPSerializableOutputSchemaMapping> =
|
|
|
125
126
|
path: z.array(z.string().min(1)).min(1),
|
|
126
127
|
});
|
|
127
128
|
|
|
129
|
+
const modelMappingSchema: z.ZodType<ACPModelMapping> = z.discriminatedUnion(
|
|
130
|
+
'type',
|
|
131
|
+
[
|
|
132
|
+
z.object({
|
|
133
|
+
type: z.literal('session-config-option'),
|
|
134
|
+
path: z.string().min(1),
|
|
135
|
+
}),
|
|
136
|
+
z.object({
|
|
137
|
+
type: z.literal('session-model'),
|
|
138
|
+
path: z.string().min(1),
|
|
139
|
+
}),
|
|
140
|
+
],
|
|
141
|
+
);
|
|
142
|
+
|
|
128
143
|
export type ACPTurnStartConfig = {
|
|
129
144
|
readonly version: 1;
|
|
130
145
|
readonly configurationFingerprint: string;
|
|
@@ -133,6 +148,8 @@ export type ACPTurnStartConfig = {
|
|
|
133
148
|
readonly builtinTools: Array<ACPBuiltinToolMapping>;
|
|
134
149
|
readonly permissionMode: HarnessV1PermissionMode;
|
|
135
150
|
readonly permissionModeMapping?: ACPPermissionModeMapping;
|
|
151
|
+
readonly model?: string;
|
|
152
|
+
readonly modelMapping?: ACPModelMapping;
|
|
136
153
|
readonly debug?: HarnessV1DebugConfig;
|
|
137
154
|
readonly responseFormat?: z.infer<
|
|
138
155
|
typeof harnessV1BridgeStartBaseSchema
|
|
@@ -148,6 +165,8 @@ export const acpTurnStartConfigSchema = z.object({
|
|
|
148
165
|
builtinTools: z.array(builtinToolSchema).default([]),
|
|
149
166
|
permissionMode: harnessV1BridgeStartBaseSchema.shape.permissionMode.unwrap(),
|
|
150
167
|
permissionModeMapping: permissionModeMappingSchema.optional(),
|
|
168
|
+
model: harnessV1BridgeStartBaseSchema.shape.model.optional(),
|
|
169
|
+
modelMapping: modelMappingSchema.optional(),
|
|
151
170
|
debug: harnessV1BridgeStartBaseSchema.shape.debug.optional(),
|
|
152
171
|
responseFormat:
|
|
153
172
|
harnessV1BridgeStartBaseSchema.shape.responseFormat.optional(),
|
|
@@ -156,14 +175,15 @@ export const acpTurnStartConfigSchema = z.object({
|
|
|
156
175
|
|
|
157
176
|
export type ACPColdSessionState = Omit<
|
|
158
177
|
ACPTurnStartConfig,
|
|
159
|
-
'prompt' | 'debug'
|
|
160
|
-
|
|
161
|
-
readonly modelId?: string;
|
|
162
|
-
};
|
|
178
|
+
'prompt' | 'debug' | 'model' | 'modelMapping'
|
|
179
|
+
>;
|
|
163
180
|
|
|
164
181
|
export const acpColdSessionStateSchema: z.ZodType<ACPColdSessionState> =
|
|
165
|
-
acpTurnStartConfigSchema.omit({
|
|
166
|
-
|
|
182
|
+
acpTurnStartConfigSchema.omit({
|
|
183
|
+
prompt: true,
|
|
184
|
+
debug: true,
|
|
185
|
+
model: true,
|
|
186
|
+
modelMapping: true,
|
|
167
187
|
});
|
|
168
188
|
|
|
169
189
|
const lossyRecoverySchema = z.object({
|
|
@@ -203,6 +223,7 @@ export const startMessageSchema = harnessV1BridgeStartBaseSchema.extend({
|
|
|
203
223
|
tools: z.array(acpSerializableToolSpecSchema).optional(),
|
|
204
224
|
builtinTools: z.array(builtinToolSchema).readonly().default([]),
|
|
205
225
|
permissionModeMapping: permissionModeMappingSchema.optional(),
|
|
226
|
+
modelMapping: modelMappingSchema.optional(),
|
|
206
227
|
turnStartConfig: acpTurnStartConfigSchema,
|
|
207
228
|
recoveryMode: z
|
|
208
229
|
.discriminatedUnion('type', [lossyRecoverySchema, coldRestoreSchema])
|
package/src/v1/acp-v1-harness.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createHash
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
2
|
import { posix } from 'node:path';
|
|
3
3
|
import {
|
|
4
4
|
HarnessCapabilityUnsupportedError,
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
import { HarnessBridgeCapabilityUnsupportedError } from '@ai-sdk/harness/bridge';
|
|
17
17
|
import {
|
|
18
18
|
applyCredentialForwarding,
|
|
19
|
+
createBridgeToken,
|
|
19
20
|
createBridgeErrorHandler,
|
|
20
21
|
createBridgeStartupError,
|
|
21
22
|
createSandboxCredentialEnvironment,
|
|
@@ -30,6 +31,7 @@ import {
|
|
|
30
31
|
shellQuote,
|
|
31
32
|
warnCredentialBrokeringUnavailable,
|
|
32
33
|
waitForBridgeReady,
|
|
34
|
+
withBridgeToken,
|
|
33
35
|
} from '@ai-sdk/harness/utils';
|
|
34
36
|
import {
|
|
35
37
|
asSchema,
|
|
@@ -53,7 +55,7 @@ import {
|
|
|
53
55
|
resolveImplementationEnvironment,
|
|
54
56
|
validateACPV1Implementation,
|
|
55
57
|
} from './implementation';
|
|
56
|
-
import { createACPBootstrap } from './acp-bootstrap';
|
|
58
|
+
import { createACPBootstrap } from './acp-v1-bootstrap';
|
|
57
59
|
import {
|
|
58
60
|
outboundMessageSchema,
|
|
59
61
|
type ACPBuiltinToolMapping,
|
|
@@ -80,6 +82,7 @@ import {
|
|
|
80
82
|
} from './acp-v1-prompt';
|
|
81
83
|
import type {
|
|
82
84
|
ACPInstructionMapping,
|
|
85
|
+
ACPModelMapping,
|
|
83
86
|
ACPOutputSchemaMapping,
|
|
84
87
|
ACPPermissionModeMapping,
|
|
85
88
|
ACPPermissionModeTarget,
|
|
@@ -158,11 +161,11 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
|
|
|
158
161
|
`ACP harnessId must be a stable kebab-case identifier; received ${JSON.stringify(settings.harnessId)}.`,
|
|
159
162
|
);
|
|
160
163
|
}
|
|
161
|
-
const
|
|
162
|
-
validateACPV1Implementation(
|
|
164
|
+
const implementation = createACPV1Implementation({ settings });
|
|
165
|
+
validateACPV1Implementation(implementation);
|
|
163
166
|
const bootstrap = createACPBootstrap({
|
|
164
167
|
harnessId: settings.harnessId,
|
|
165
|
-
implementation
|
|
168
|
+
implementation,
|
|
166
169
|
});
|
|
167
170
|
const permissionModeMapping = isCompletePermissionModeMapping({
|
|
168
171
|
value: settings.permissionModeMapping,
|
|
@@ -186,24 +189,6 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
|
|
|
186
189
|
'ACP built-in tool filtering is not available in this initial ACP v1 implementation.',
|
|
187
190
|
});
|
|
188
191
|
}
|
|
189
|
-
const modelId = startOptions.model ?? settings.modelId;
|
|
190
|
-
const modelConfiguration =
|
|
191
|
-
modelId == null ? undefined : settings.resolveModel({ model: modelId });
|
|
192
|
-
const implementation = {
|
|
193
|
-
...baseImplementation,
|
|
194
|
-
...(modelConfiguration?.args == null
|
|
195
|
-
? {}
|
|
196
|
-
: { args: modelConfiguration.args }),
|
|
197
|
-
...(modelConfiguration?.env == null
|
|
198
|
-
? {}
|
|
199
|
-
: {
|
|
200
|
-
env: {
|
|
201
|
-
...baseImplementation.env,
|
|
202
|
-
...modelConfiguration.env,
|
|
203
|
-
},
|
|
204
|
-
}),
|
|
205
|
-
};
|
|
206
|
-
validateACPV1Implementation(implementation);
|
|
207
192
|
const permissionMode = startOptions.permissionMode ?? 'allow-all';
|
|
208
193
|
const env = { ...process.env };
|
|
209
194
|
const authenticationEnvironment = resolveACPAuthenticationEnvironment({
|
|
@@ -221,6 +206,8 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
|
|
|
221
206
|
acpVersion: 'v1',
|
|
222
207
|
implementation,
|
|
223
208
|
clientApp,
|
|
209
|
+
clientCapabilities: settings.clientCapabilities,
|
|
210
|
+
modelMapping: settings.modelMapping,
|
|
224
211
|
providerAuthentication: providerAuthenticationCompatibility,
|
|
225
212
|
permissionModeMapping: settings.permissionModeMapping,
|
|
226
213
|
});
|
|
@@ -452,7 +439,8 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
|
|
|
452
439
|
harnessId: settings.harnessId,
|
|
453
440
|
channel: attachChannel,
|
|
454
441
|
proc: undefined,
|
|
455
|
-
|
|
442
|
+
modelMapping: settings.modelMapping,
|
|
443
|
+
defaultModelId: settings.modelId,
|
|
456
444
|
sessionMeta: settings.session?.meta,
|
|
457
445
|
instructionMapping: settings.instructionMapping,
|
|
458
446
|
outputSchemaMapping: settings.outputSchemaMapping,
|
|
@@ -518,6 +506,7 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
|
|
|
518
506
|
sessionMeta: settings.session?.meta,
|
|
519
507
|
instructionMapping: settings.instructionMapping,
|
|
520
508
|
outputSchemaMapping: settings.outputSchemaMapping,
|
|
509
|
+
modelMapping: settings.modelMapping,
|
|
521
510
|
builtinTools: builtinToolCatalog,
|
|
522
511
|
permissionModeMapping,
|
|
523
512
|
mcpServers: settings.mcpServers,
|
|
@@ -544,12 +533,12 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
|
|
|
544
533
|
}
|
|
545
534
|
const turnStartConfig = validateACPColdSessionConfiguration({
|
|
546
535
|
coldSession,
|
|
547
|
-
modelId,
|
|
548
536
|
permissionMode,
|
|
549
537
|
authenticationProfile,
|
|
550
538
|
sessionMeta: settings.session?.meta,
|
|
551
539
|
instructionMapping: settings.instructionMapping,
|
|
552
540
|
outputSchemaMapping: settings.outputSchemaMapping,
|
|
541
|
+
modelMapping: settings.modelMapping,
|
|
553
542
|
builtinTools: builtinToolCatalog,
|
|
554
543
|
permissionModeMapping,
|
|
555
544
|
mcpServers: settings.mcpServers,
|
|
@@ -579,7 +568,7 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
|
|
|
579
568
|
});
|
|
580
569
|
const token =
|
|
581
570
|
settings.mintBridgeToken == null
|
|
582
|
-
?
|
|
571
|
+
? createBridgeToken()
|
|
583
572
|
: settings.mintBridgeToken(sandboxId!);
|
|
584
573
|
await toolSafeSandboxSession.run({
|
|
585
574
|
command: `mkdir -p ${shellQuote(workDir)} ${shellQuote(bridgeStateDir)}`,
|
|
@@ -608,8 +597,7 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
|
|
|
608
597
|
providerEnvironment:
|
|
609
598
|
sandboxProviderEnvironment == null ? undefined : {},
|
|
610
599
|
sessionMeta: settings.session?.meta,
|
|
611
|
-
|
|
612
|
-
implementationEnv: modelConfiguration?.env,
|
|
600
|
+
clientCapabilities: settings.clientCapabilities,
|
|
613
601
|
}),
|
|
614
602
|
...sandboxProviderAuthenticationEnvironment,
|
|
615
603
|
BRIDGE_CHANNEL_TOKEN: token,
|
|
@@ -722,7 +710,8 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
|
|
|
722
710
|
harnessId: settings.harnessId,
|
|
723
711
|
channel,
|
|
724
712
|
proc,
|
|
725
|
-
|
|
713
|
+
modelMapping: settings.modelMapping,
|
|
714
|
+
defaultModelId: settings.modelId,
|
|
726
715
|
sessionMeta: settings.session?.meta,
|
|
727
716
|
instructionMapping: settings.instructionMapping,
|
|
728
717
|
outputSchemaMapping: settings.outputSchemaMapping,
|
|
@@ -945,18 +934,6 @@ function openWebSocket({
|
|
|
945
934
|
});
|
|
946
935
|
}
|
|
947
936
|
|
|
948
|
-
function withBridgeToken({
|
|
949
|
-
endpoint,
|
|
950
|
-
token,
|
|
951
|
-
}: {
|
|
952
|
-
endpoint: HarnessV1PortEndpoint;
|
|
953
|
-
token: string;
|
|
954
|
-
}): HarnessV1PortEndpoint {
|
|
955
|
-
const bridgeUrl = new URL(endpoint.url);
|
|
956
|
-
bridgeUrl.searchParams.set('agent_bridge_token', token);
|
|
957
|
-
return { ...endpoint, url: bridgeUrl.toString() };
|
|
958
|
-
}
|
|
959
|
-
|
|
960
937
|
function restoreColdACPSession({
|
|
961
938
|
channel,
|
|
962
939
|
harnessId,
|
|
@@ -1046,7 +1023,8 @@ function createSession({
|
|
|
1046
1023
|
harnessId,
|
|
1047
1024
|
channel,
|
|
1048
1025
|
proc,
|
|
1049
|
-
|
|
1026
|
+
modelMapping,
|
|
1027
|
+
defaultModelId,
|
|
1050
1028
|
sessionMeta,
|
|
1051
1029
|
instructionMapping,
|
|
1052
1030
|
outputSchemaMapping,
|
|
@@ -1081,7 +1059,8 @@ function createSession({
|
|
|
1081
1059
|
harnessId: string;
|
|
1082
1060
|
channel: ACPChannel;
|
|
1083
1061
|
proc: Experimental_SandboxProcess | undefined;
|
|
1084
|
-
|
|
1062
|
+
modelMapping: ACPModelMapping;
|
|
1063
|
+
defaultModelId: string | undefined;
|
|
1085
1064
|
sessionMeta: Readonly<Record<string, ACPSerializableValue>> | undefined;
|
|
1086
1065
|
instructionMapping: ACPInstructionMapping | undefined;
|
|
1087
1066
|
outputSchemaMapping: ACPOutputSchemaMapping | undefined;
|
|
@@ -1375,7 +1354,6 @@ function createSession({
|
|
|
1375
1354
|
: {
|
|
1376
1355
|
coldSession: createACPColdSessionState({
|
|
1377
1356
|
turnStartConfig: latestTurnStartConfig,
|
|
1378
|
-
modelId,
|
|
1379
1357
|
}),
|
|
1380
1358
|
}),
|
|
1381
1359
|
...(!includeTurnStartConfig || latestTurnStartConfig == null
|
|
@@ -1407,7 +1385,6 @@ function createSession({
|
|
|
1407
1385
|
return {
|
|
1408
1386
|
sessionId,
|
|
1409
1387
|
isResume,
|
|
1410
|
-
...(modelId == null ? {} : { modelId }),
|
|
1411
1388
|
doPromptTurn: async options => {
|
|
1412
1389
|
await synchronizeSkills({
|
|
1413
1390
|
skills: options.skills,
|
|
@@ -1442,6 +1419,7 @@ function createSession({
|
|
|
1442
1419
|
prompt: options.prompt,
|
|
1443
1420
|
harnessId,
|
|
1444
1421
|
});
|
|
1422
|
+
const model = options.model ?? defaultModelId;
|
|
1445
1423
|
const turnStartConfig = createACPTurnStartConfig({
|
|
1446
1424
|
prompt,
|
|
1447
1425
|
tools: options.tools ?? [],
|
|
@@ -1455,6 +1433,8 @@ function createSession({
|
|
|
1455
1433
|
instructionMapping,
|
|
1456
1434
|
responseFormat: options.responseFormat,
|
|
1457
1435
|
outputSchemaMapping,
|
|
1436
|
+
model,
|
|
1437
|
+
modelMapping,
|
|
1458
1438
|
});
|
|
1459
1439
|
const nextInstructionsFingerprint = fingerprintValue({
|
|
1460
1440
|
value: options.instructions ?? null,
|
|
@@ -1491,6 +1471,7 @@ function createSession({
|
|
|
1491
1471
|
builtinTools,
|
|
1492
1472
|
permissionMode,
|
|
1493
1473
|
permissionModeMapping,
|
|
1474
|
+
...(model == null ? {} : { model, modelMapping }),
|
|
1494
1475
|
...(options.responseFormat == null
|
|
1495
1476
|
? {}
|
|
1496
1477
|
: { responseFormat: options.responseFormat }),
|
|
@@ -1554,6 +1535,12 @@ function createSession({
|
|
|
1554
1535
|
builtinTools: turnStartConfig.builtinTools,
|
|
1555
1536
|
permissionMode: turnStartConfig.permissionMode,
|
|
1556
1537
|
permissionModeMapping: turnStartConfig.permissionModeMapping,
|
|
1538
|
+
...(turnStartConfig.model == null
|
|
1539
|
+
? {}
|
|
1540
|
+
: {
|
|
1541
|
+
model: turnStartConfig.model,
|
|
1542
|
+
modelMapping: turnStartConfig.modelMapping,
|
|
1543
|
+
}),
|
|
1557
1544
|
...(turnStartConfig.responseFormat == null
|
|
1558
1545
|
? {}
|
|
1559
1546
|
: { responseFormat: turnStartConfig.responseFormat }),
|
|
@@ -1751,6 +1738,7 @@ function validateACPTurnStartConfig({
|
|
|
1751
1738
|
sessionMeta,
|
|
1752
1739
|
instructionMapping,
|
|
1753
1740
|
outputSchemaMapping,
|
|
1741
|
+
modelMapping,
|
|
1754
1742
|
builtinTools,
|
|
1755
1743
|
permissionModeMapping,
|
|
1756
1744
|
mcpServers,
|
|
@@ -1760,6 +1748,7 @@ function validateACPTurnStartConfig({
|
|
|
1760
1748
|
sessionMeta: Readonly<Record<string, ACPSerializableValue>> | undefined;
|
|
1761
1749
|
instructionMapping: ACPInstructionMapping | undefined;
|
|
1762
1750
|
outputSchemaMapping: ACPOutputSchemaMapping | undefined;
|
|
1751
|
+
modelMapping: ACPModelMapping;
|
|
1763
1752
|
builtinTools: ReadonlyArray<ACPBuiltinToolMapping>;
|
|
1764
1753
|
permissionModeMapping: ACPPermissionModeMapping | undefined;
|
|
1765
1754
|
mcpServers: Record<string, unknown> | undefined;
|
|
@@ -1777,6 +1766,8 @@ function validateACPTurnStartConfig({
|
|
|
1777
1766
|
instructionMapping,
|
|
1778
1767
|
responseFormat: turnStartConfig.responseFormat,
|
|
1779
1768
|
outputSchemaMapping,
|
|
1769
|
+
model: turnStartConfig.model,
|
|
1770
|
+
modelMapping,
|
|
1780
1771
|
});
|
|
1781
1772
|
if (
|
|
1782
1773
|
current.configurationFingerprint !==
|
|
@@ -1790,24 +1781,24 @@ function validateACPTurnStartConfig({
|
|
|
1790
1781
|
|
|
1791
1782
|
function validateACPColdSessionConfiguration({
|
|
1792
1783
|
coldSession,
|
|
1793
|
-
modelId,
|
|
1794
1784
|
permissionMode,
|
|
1795
1785
|
authenticationProfile,
|
|
1796
1786
|
sessionMeta,
|
|
1797
1787
|
instructionMapping,
|
|
1798
1788
|
outputSchemaMapping,
|
|
1789
|
+
modelMapping,
|
|
1799
1790
|
builtinTools,
|
|
1800
1791
|
permissionModeMapping,
|
|
1801
1792
|
mcpServers,
|
|
1802
1793
|
debug,
|
|
1803
1794
|
}: {
|
|
1804
1795
|
coldSession: ACPColdSessionState;
|
|
1805
|
-
modelId: string | undefined;
|
|
1806
1796
|
permissionMode: NonNullable<StartMessage['permissionMode']>;
|
|
1807
1797
|
authenticationProfile: ACPAuthenticationProfileIdentity;
|
|
1808
1798
|
sessionMeta: Readonly<Record<string, ACPSerializableValue>> | undefined;
|
|
1809
1799
|
instructionMapping: ACPInstructionMapping | undefined;
|
|
1810
1800
|
outputSchemaMapping: ACPOutputSchemaMapping | undefined;
|
|
1801
|
+
modelMapping: ACPModelMapping;
|
|
1811
1802
|
builtinTools: ReadonlyArray<ACPBuiltinToolMapping>;
|
|
1812
1803
|
permissionModeMapping: ACPPermissionModeMapping | undefined;
|
|
1813
1804
|
mcpServers: Record<string, unknown> | undefined;
|
|
@@ -1826,11 +1817,12 @@ function validateACPColdSessionConfiguration({
|
|
|
1826
1817
|
instructionMapping,
|
|
1827
1818
|
responseFormat: coldSession.responseFormat,
|
|
1828
1819
|
outputSchemaMapping,
|
|
1820
|
+
model: undefined,
|
|
1821
|
+
modelMapping,
|
|
1829
1822
|
});
|
|
1830
1823
|
if (
|
|
1831
1824
|
current.configurationFingerprint !== coldSession.configurationFingerprint ||
|
|
1832
|
-
coldSession.permissionMode !== permissionMode
|
|
1833
|
-
coldSession.modelId !== modelId
|
|
1825
|
+
coldSession.permissionMode !== permissionMode
|
|
1834
1826
|
) {
|
|
1835
1827
|
throw new Error(
|
|
1836
1828
|
'ACP cold-session state is incompatible with the current non-secret session configuration.',
|
|
@@ -75,20 +75,15 @@ export type ACPProviderAuthentication = {
|
|
|
75
75
|
};
|
|
76
76
|
};
|
|
77
77
|
|
|
78
|
-
export type
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
export type ACPModelResolver = (options: {
|
|
90
|
-
readonly model: string;
|
|
91
|
-
}) => ACPModelResolution;
|
|
78
|
+
export type ACPModelMapping =
|
|
79
|
+
| {
|
|
80
|
+
readonly type: 'session-config-option';
|
|
81
|
+
readonly path: string;
|
|
82
|
+
}
|
|
83
|
+
| {
|
|
84
|
+
readonly type: 'session-model';
|
|
85
|
+
readonly path: string;
|
|
86
|
+
};
|
|
92
87
|
|
|
93
88
|
export type ACPCredentialBrokering = ({
|
|
94
89
|
env,
|
|
@@ -158,11 +153,12 @@ export type ACPV1Settings = {
|
|
|
158
153
|
*/
|
|
159
154
|
readonly env?: Readonly<Record<string, string>>;
|
|
160
155
|
readonly authentication?: ACPAuthentication;
|
|
156
|
+
readonly clientCapabilities?: Readonly<Record<string, ACPSerializableValue>>;
|
|
161
157
|
readonly providerAuthentication?: ACPProviderAuthentication;
|
|
162
158
|
/**
|
|
163
|
-
* Maps
|
|
159
|
+
* Maps the HarnessAgent model identifier to an ACP session operation.
|
|
164
160
|
*/
|
|
165
|
-
readonly
|
|
161
|
+
readonly modelMapping: ACPModelMapping;
|
|
166
162
|
/**
|
|
167
163
|
* @deprecated Use `model` on `HarnessAgent` instead.
|
|
168
164
|
*/
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import type { ACPTextContentBlock } from './acp-v1-prompt';
|
|
12
12
|
import type {
|
|
13
13
|
ACPInstructionMapping,
|
|
14
|
+
ACPModelMapping,
|
|
14
15
|
ACPOutputSchemaMapping,
|
|
15
16
|
ACPPermissionModeMapping,
|
|
16
17
|
ACPSerializableValue,
|
|
@@ -29,6 +30,8 @@ export function createACPTurnStartConfig({
|
|
|
29
30
|
instructionMapping,
|
|
30
31
|
responseFormat,
|
|
31
32
|
outputSchemaMapping,
|
|
33
|
+
model,
|
|
34
|
+
modelMapping,
|
|
32
35
|
}: {
|
|
33
36
|
prompt: ReadonlyArray<ACPTextContentBlock>;
|
|
34
37
|
tools: ReadonlyArray<HarnessV1ToolSpec>;
|
|
@@ -42,6 +45,8 @@ export function createACPTurnStartConfig({
|
|
|
42
45
|
instructionMapping: ACPInstructionMapping | undefined;
|
|
43
46
|
responseFormat: StartMessage['responseFormat'];
|
|
44
47
|
outputSchemaMapping: ACPOutputSchemaMapping | undefined;
|
|
48
|
+
model: string | undefined;
|
|
49
|
+
modelMapping: ACPModelMapping;
|
|
45
50
|
}): ACPTurnStartConfig {
|
|
46
51
|
return {
|
|
47
52
|
version: 1,
|
|
@@ -52,6 +57,7 @@ export function createACPTurnStartConfig({
|
|
|
52
57
|
sessionMeta: sessionMeta ?? null,
|
|
53
58
|
...(instructionMapping == null ? {} : { instructionMapping }),
|
|
54
59
|
...(outputSchemaMapping == null ? {} : { outputSchemaMapping }),
|
|
60
|
+
modelMapping,
|
|
55
61
|
builtinTools,
|
|
56
62
|
permissionModeMapping: permissionModeMapping ?? null,
|
|
57
63
|
mcpServers: mcpServers ?? null,
|
|
@@ -62,6 +68,7 @@ export function createACPTurnStartConfig({
|
|
|
62
68
|
tools: tools.map(tool => acpSerializableToolSpecSchema.parse(tool)),
|
|
63
69
|
builtinTools: [...builtinTools],
|
|
64
70
|
permissionMode,
|
|
71
|
+
...(model == null ? {} : { model, modelMapping }),
|
|
65
72
|
...(responseFormat == null ? {} : { responseFormat }),
|
|
66
73
|
...(outputSchemaMapping == null
|
|
67
74
|
? {}
|
|
@@ -78,10 +85,8 @@ export function createACPTurnStartConfig({
|
|
|
78
85
|
|
|
79
86
|
export function createACPColdSessionState({
|
|
80
87
|
turnStartConfig,
|
|
81
|
-
modelId,
|
|
82
88
|
}: {
|
|
83
89
|
turnStartConfig: ACPTurnStartConfig;
|
|
84
|
-
modelId: string | undefined;
|
|
85
90
|
}): ACPColdSessionState {
|
|
86
91
|
return {
|
|
87
92
|
version: turnStartConfig.version,
|
|
@@ -98,7 +103,6 @@ export function createACPColdSessionState({
|
|
|
98
103
|
...(turnStartConfig.permissionModeMapping == null
|
|
99
104
|
? {}
|
|
100
105
|
: { permissionModeMapping: turnStartConfig.permissionModeMapping }),
|
|
101
|
-
...(modelId == null ? {} : { modelId }),
|
|
102
106
|
};
|
|
103
107
|
}
|
|
104
108
|
|
|
@@ -59,8 +59,7 @@ export type ACPBridgeConfiguration = {
|
|
|
59
59
|
readonly providerAuthentication?: ACPResolvedProviderAuthentication;
|
|
60
60
|
readonly providerEnvironment?: Readonly<Record<string, string>>;
|
|
61
61
|
readonly sessionMeta?: Readonly<Record<string, ACPSerializableValue>>;
|
|
62
|
-
readonly
|
|
63
|
-
readonly implementationEnv?: Readonly<Record<string, string>>;
|
|
62
|
+
readonly clientCapabilities?: Readonly<Record<string, ACPSerializableValue>>;
|
|
64
63
|
};
|
|
65
64
|
|
|
66
65
|
const bridgeConfigurationSchema: z.ZodType<ACPBridgeConfiguration> = z.object({
|
|
@@ -68,8 +67,7 @@ const bridgeConfigurationSchema: z.ZodType<ACPBridgeConfiguration> = z.object({
|
|
|
68
67
|
providerAuthentication: providerAuthenticationSchema.optional(),
|
|
69
68
|
providerEnvironment: z.record(z.string(), z.string()).optional(),
|
|
70
69
|
sessionMeta: serializableRecordSchema.optional(),
|
|
71
|
-
|
|
72
|
-
implementationEnv: z.record(z.string(), z.string()).optional(),
|
|
70
|
+
clientCapabilities: serializableRecordSchema.optional(),
|
|
73
71
|
});
|
|
74
72
|
|
|
75
73
|
export function createACPBridgeEnvironment({
|
|
@@ -77,8 +75,7 @@ export function createACPBridgeEnvironment({
|
|
|
77
75
|
providerAuthentication,
|
|
78
76
|
providerEnvironment,
|
|
79
77
|
sessionMeta,
|
|
80
|
-
|
|
81
|
-
implementationEnv,
|
|
78
|
+
clientCapabilities,
|
|
82
79
|
}: ACPBridgeConfiguration): Record<string, string> {
|
|
83
80
|
return {
|
|
84
81
|
[ACP_BRIDGE_CONFIGURATION_ENV]: JSON.stringify({
|
|
@@ -86,8 +83,7 @@ export function createACPBridgeEnvironment({
|
|
|
86
83
|
...(providerAuthentication == null ? {} : { providerAuthentication }),
|
|
87
84
|
...(providerEnvironment == null ? {} : { providerEnvironment }),
|
|
88
85
|
...(sessionMeta == null ? {} : { sessionMeta }),
|
|
89
|
-
...(
|
|
90
|
-
...(implementationEnv == null ? {} : { implementationEnv }),
|
|
86
|
+
...(clientCapabilities == null ? {} : { clientCapabilities }),
|
|
91
87
|
}),
|
|
92
88
|
};
|
|
93
89
|
}
|
package/src/v1/bridge/index.ts
CHANGED
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
} from './refresh-host-tool-catalog';
|
|
45
45
|
import { createACPPermissionController } from './permission-controller';
|
|
46
46
|
import { configureACPPermissionMode } from './permission-mode';
|
|
47
|
+
import { configureACPModel } from './model-mapping';
|
|
47
48
|
import {
|
|
48
49
|
assertACPResumeCapability,
|
|
49
50
|
createACPRecoveredSession,
|
|
@@ -214,6 +215,13 @@ async function runTurn(start: StartMessage, turn: BridgeTurn): Promise<void> {
|
|
|
214
215
|
return;
|
|
215
216
|
}
|
|
216
217
|
|
|
218
|
+
await configureACPModel({
|
|
219
|
+
agent: connection!.agent,
|
|
220
|
+
sessionId: activeSession.sessionId,
|
|
221
|
+
model: start.model,
|
|
222
|
+
mapping: start.modelMapping,
|
|
223
|
+
});
|
|
224
|
+
|
|
217
225
|
let rejectCancellationFailure!: (error: unknown) => void;
|
|
218
226
|
const cancellationFailure = new Promise<never>((_, reject) => {
|
|
219
227
|
rejectCancellationFailure = reject;
|
|
@@ -419,12 +427,11 @@ async function ensureSession({
|
|
|
419
427
|
implementationDir,
|
|
420
428
|
privateHome: implementation.privateHome,
|
|
421
429
|
}),
|
|
422
|
-
...bridgeConfiguration.implementationEnv,
|
|
423
430
|
},
|
|
424
431
|
});
|
|
425
432
|
child = spawn(
|
|
426
433
|
`${implementationDir}/${implementation.executablePath}`,
|
|
427
|
-
[...
|
|
434
|
+
[...implementation.args],
|
|
428
435
|
{
|
|
429
436
|
cwd: workDir,
|
|
430
437
|
env: instructionConfiguration.environment,
|
|
@@ -475,6 +482,7 @@ async function ensureSession({
|
|
|
475
482
|
protocolVersion: acp.PROTOCOL_VERSION,
|
|
476
483
|
clientApp,
|
|
477
484
|
authentication,
|
|
485
|
+
clientCapabilities: bridgeConfiguration.clientCapabilities,
|
|
478
486
|
supportsBooleanSessionConfigOptions: Object.values(
|
|
479
487
|
start.permissionModeMapping ?? {},
|
|
480
488
|
).some(
|