@ai-sdk/harness-acp 1.0.10 → 1.0.12
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 +15 -0
- package/dist/bridge/host-tool-mcp.mjs +1 -1
- package/dist/bridge/index.mjs +96 -21
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +70 -6
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/acp-harness.ts +1 -0
- package/src/index.ts +1 -0
- package/src/v1/acp-v1-bridge-protocol.ts +19 -0
- package/src/v1/acp-v1-harness.ts +57 -0
- package/src/v1/acp-v1-settings.ts +10 -0
- package/src/v1/acp-v1-turn-start-config.ts +21 -0
- package/src/v1/bridge/index.ts +82 -1
- package/src/v1/bridge/recovered-session.ts +25 -0
- package/src/v1/index.ts +1 -0
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.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"ws": "^8.21.0",
|
|
30
|
-
"@ai-sdk/harness": "1.0.
|
|
30
|
+
"@ai-sdk/harness": "1.0.74",
|
|
31
31
|
"@ai-sdk/provider-utils": "5.0.27"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
package/src/acp-harness.ts
CHANGED
|
@@ -40,6 +40,7 @@ export type ACPHarnessSettings<TBuiltinTools extends ToolSet = {}> = {
|
|
|
40
40
|
readonly providerAuthentication?: ACPV1Settings['providerAuthentication'];
|
|
41
41
|
readonly modelId?: ACPV1Settings['modelId'];
|
|
42
42
|
readonly instructionMapping?: ACPV1Settings['instructionMapping'];
|
|
43
|
+
readonly outputSchemaMapping?: ACPV1Settings['outputSchemaMapping'];
|
|
43
44
|
readonly permissionModeMapping?: ACPV1Settings['permissionModeMapping'];
|
|
44
45
|
readonly session?: ACPV1Settings['session'];
|
|
45
46
|
readonly mintBridgeToken?: ACPV1Settings['mintBridgeToken'];
|
package/src/index.ts
CHANGED
|
@@ -100,6 +100,17 @@ const instructionMappingSchema: z.ZodType<ACPInstructionMapping> =
|
|
|
100
100
|
}),
|
|
101
101
|
]);
|
|
102
102
|
|
|
103
|
+
type ACPSerializableOutputSchemaMapping = {
|
|
104
|
+
readonly type: 'session-prompt-meta';
|
|
105
|
+
readonly path: string[];
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const outputSchemaMappingSchema: z.ZodType<ACPSerializableOutputSchemaMapping> =
|
|
109
|
+
z.object({
|
|
110
|
+
type: z.literal('session-prompt-meta'),
|
|
111
|
+
path: z.array(z.string().min(1)).min(1),
|
|
112
|
+
});
|
|
113
|
+
|
|
103
114
|
export type ACPTurnStartConfig = {
|
|
104
115
|
readonly version: 1;
|
|
105
116
|
readonly configurationFingerprint: string;
|
|
@@ -109,6 +120,10 @@ export type ACPTurnStartConfig = {
|
|
|
109
120
|
readonly permissionMode: HarnessV1PermissionMode;
|
|
110
121
|
readonly permissionModeMapping?: ACPPermissionModeMapping;
|
|
111
122
|
readonly debug?: HarnessV1DebugConfig;
|
|
123
|
+
readonly responseFormat?: z.infer<
|
|
124
|
+
typeof harnessV1BridgeStartBaseSchema
|
|
125
|
+
>['responseFormat'];
|
|
126
|
+
readonly outputSchemaMapping?: ACPSerializableOutputSchemaMapping;
|
|
112
127
|
};
|
|
113
128
|
|
|
114
129
|
export const acpTurnStartConfigSchema = z.object({
|
|
@@ -120,6 +135,9 @@ export const acpTurnStartConfigSchema = z.object({
|
|
|
120
135
|
permissionMode: harnessV1BridgeStartBaseSchema.shape.permissionMode.unwrap(),
|
|
121
136
|
permissionModeMapping: permissionModeMappingSchema.optional(),
|
|
122
137
|
debug: harnessV1BridgeStartBaseSchema.shape.debug.optional(),
|
|
138
|
+
responseFormat:
|
|
139
|
+
harnessV1BridgeStartBaseSchema.shape.responseFormat.optional(),
|
|
140
|
+
outputSchemaMapping: outputSchemaMappingSchema.optional(),
|
|
123
141
|
}) satisfies z.ZodType<ACPTurnStartConfig>;
|
|
124
142
|
|
|
125
143
|
export type ACPColdSessionState = Omit<
|
|
@@ -166,6 +184,7 @@ export const startMessageSchema = harnessV1BridgeStartBaseSchema.extend({
|
|
|
166
184
|
prompt: z.array(acpTextContentBlockSchema),
|
|
167
185
|
instructions: z.string().optional(),
|
|
168
186
|
instructionMapping: instructionMappingSchema.optional(),
|
|
187
|
+
outputSchemaMapping: outputSchemaMappingSchema.optional(),
|
|
169
188
|
mcpServers: z.record(z.string(), z.unknown()).optional(),
|
|
170
189
|
tools: z.array(acpSerializableToolSpecSchema).optional(),
|
|
171
190
|
builtinTools: z.array(builtinToolSchema).readonly().default([]),
|
package/src/v1/acp-v1-harness.ts
CHANGED
|
@@ -76,6 +76,7 @@ import {
|
|
|
76
76
|
} from './acp-v1-prompt';
|
|
77
77
|
import type {
|
|
78
78
|
ACPInstructionMapping,
|
|
79
|
+
ACPOutputSchemaMapping,
|
|
79
80
|
ACPPermissionModeMapping,
|
|
80
81
|
ACPPermissionModeTarget,
|
|
81
82
|
ACPSerializableValue,
|
|
@@ -388,6 +389,7 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
|
|
|
388
389
|
modelId: settings.modelId,
|
|
389
390
|
sessionMeta: settings.session?.meta,
|
|
390
391
|
instructionMapping: settings.instructionMapping,
|
|
392
|
+
outputSchemaMapping: settings.outputSchemaMapping,
|
|
391
393
|
debug: startOptions.observability?.debug,
|
|
392
394
|
implementationIdentity,
|
|
393
395
|
authenticationProfile,
|
|
@@ -446,6 +448,7 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
|
|
|
446
448
|
authenticationProfile,
|
|
447
449
|
sessionMeta: settings.session?.meta,
|
|
448
450
|
instructionMapping: settings.instructionMapping,
|
|
451
|
+
outputSchemaMapping: settings.outputSchemaMapping,
|
|
449
452
|
builtinTools: builtinToolCatalog,
|
|
450
453
|
permissionModeMapping,
|
|
451
454
|
mcpServers: settings.mcpServers,
|
|
@@ -477,6 +480,7 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
|
|
|
477
480
|
authenticationProfile,
|
|
478
481
|
sessionMeta: settings.session?.meta,
|
|
479
482
|
instructionMapping: settings.instructionMapping,
|
|
483
|
+
outputSchemaMapping: settings.outputSchemaMapping,
|
|
480
484
|
builtinTools: builtinToolCatalog,
|
|
481
485
|
permissionModeMapping,
|
|
482
486
|
mcpServers: settings.mcpServers,
|
|
@@ -638,6 +642,7 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
|
|
|
638
642
|
modelId: settings.modelId,
|
|
639
643
|
sessionMeta: settings.session?.meta,
|
|
640
644
|
instructionMapping: settings.instructionMapping,
|
|
645
|
+
outputSchemaMapping: settings.outputSchemaMapping,
|
|
641
646
|
debug: startOptions.observability?.debug,
|
|
642
647
|
implementationIdentity,
|
|
643
648
|
authenticationProfile,
|
|
@@ -879,6 +884,7 @@ function createSession({
|
|
|
879
884
|
modelId,
|
|
880
885
|
sessionMeta,
|
|
881
886
|
instructionMapping,
|
|
887
|
+
outputSchemaMapping,
|
|
882
888
|
debug,
|
|
883
889
|
implementationIdentity,
|
|
884
890
|
authenticationProfile,
|
|
@@ -910,6 +916,7 @@ function createSession({
|
|
|
910
916
|
modelId: string | undefined;
|
|
911
917
|
sessionMeta: Readonly<Record<string, ACPSerializableValue>> | undefined;
|
|
912
918
|
instructionMapping: ACPInstructionMapping | undefined;
|
|
919
|
+
outputSchemaMapping: ACPOutputSchemaMapping | undefined;
|
|
913
920
|
debug: HarnessV1DebugConfig | undefined;
|
|
914
921
|
implementationIdentity: string;
|
|
915
922
|
authenticationProfile: ACPAuthenticationProfileIdentity;
|
|
@@ -1211,6 +1218,20 @@ function createSession({
|
|
|
1211
1218
|
isResume,
|
|
1212
1219
|
...(modelId == null ? {} : { modelId }),
|
|
1213
1220
|
doPromptTurn: async options => {
|
|
1221
|
+
if (options.responseFormat?.type === 'json') {
|
|
1222
|
+
if (options.responseFormat.schema == null) {
|
|
1223
|
+
throw unsupported({
|
|
1224
|
+
harnessId,
|
|
1225
|
+
message: `${harnessId} requires a JSON schema for structured output.`,
|
|
1226
|
+
});
|
|
1227
|
+
}
|
|
1228
|
+
if (outputSchemaMapping == null) {
|
|
1229
|
+
throw unsupported({
|
|
1230
|
+
harnessId,
|
|
1231
|
+
message: `${harnessId} does not support structured output through ACP.`,
|
|
1232
|
+
});
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1214
1235
|
if (replayOnly) {
|
|
1215
1236
|
throw new Error(
|
|
1216
1237
|
`${harnessId} recovered this turn through disk replay only and has no restored ACP process for a subsequent prompt.`,
|
|
@@ -1237,6 +1258,8 @@ function createSession({
|
|
|
1237
1258
|
authenticationProfile,
|
|
1238
1259
|
sessionMeta,
|
|
1239
1260
|
instructionMapping,
|
|
1261
|
+
responseFormat: options.responseFormat,
|
|
1262
|
+
outputSchemaMapping,
|
|
1240
1263
|
});
|
|
1241
1264
|
const control = wireTurn({
|
|
1242
1265
|
emit: options.emit,
|
|
@@ -1272,6 +1295,12 @@ function createSession({
|
|
|
1272
1295
|
builtinTools,
|
|
1273
1296
|
permissionMode,
|
|
1274
1297
|
permissionModeMapping,
|
|
1298
|
+
...(options.responseFormat == null
|
|
1299
|
+
? {}
|
|
1300
|
+
: { responseFormat: options.responseFormat }),
|
|
1301
|
+
...(turnStartConfig.outputSchemaMapping == null
|
|
1302
|
+
? {}
|
|
1303
|
+
: { outputSchemaMapping: turnStartConfig.outputSchemaMapping }),
|
|
1275
1304
|
...(mcpServers == null ? {} : { mcpServers }),
|
|
1276
1305
|
tools: options.tools == null ? undefined : turnStartConfig.tools,
|
|
1277
1306
|
turnStartConfig,
|
|
@@ -1283,6 +1312,20 @@ function createSession({
|
|
|
1283
1312
|
return control;
|
|
1284
1313
|
},
|
|
1285
1314
|
doContinueTurn: async options => {
|
|
1315
|
+
if (options.responseFormat?.type === 'json') {
|
|
1316
|
+
if (options.responseFormat.schema == null) {
|
|
1317
|
+
throw unsupported({
|
|
1318
|
+
harnessId,
|
|
1319
|
+
message: `${harnessId} requires a JSON schema for structured output.`,
|
|
1320
|
+
});
|
|
1321
|
+
}
|
|
1322
|
+
if (outputSchemaMapping == null) {
|
|
1323
|
+
throw unsupported({
|
|
1324
|
+
harnessId,
|
|
1325
|
+
message: `${harnessId} does not support structured output through ACP.`,
|
|
1326
|
+
});
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1286
1329
|
if (!turnInFlight) {
|
|
1287
1330
|
throw new Error(`${harnessId} has no in-flight ACP turn to continue.`);
|
|
1288
1331
|
}
|
|
@@ -1310,6 +1353,12 @@ function createSession({
|
|
|
1310
1353
|
builtinTools: turnStartConfig.builtinTools,
|
|
1311
1354
|
permissionMode: turnStartConfig.permissionMode,
|
|
1312
1355
|
permissionModeMapping: turnStartConfig.permissionModeMapping,
|
|
1356
|
+
...(turnStartConfig.responseFormat == null
|
|
1357
|
+
? {}
|
|
1358
|
+
: { responseFormat: turnStartConfig.responseFormat }),
|
|
1359
|
+
...(turnStartConfig.outputSchemaMapping == null
|
|
1360
|
+
? {}
|
|
1361
|
+
: { outputSchemaMapping: turnStartConfig.outputSchemaMapping }),
|
|
1313
1362
|
...(instructionMapping == null
|
|
1314
1363
|
? {}
|
|
1315
1364
|
: {
|
|
@@ -1482,6 +1531,7 @@ function validateACPTurnStartConfig({
|
|
|
1482
1531
|
authenticationProfile,
|
|
1483
1532
|
sessionMeta,
|
|
1484
1533
|
instructionMapping,
|
|
1534
|
+
outputSchemaMapping,
|
|
1485
1535
|
builtinTools,
|
|
1486
1536
|
permissionModeMapping,
|
|
1487
1537
|
mcpServers,
|
|
@@ -1490,6 +1540,7 @@ function validateACPTurnStartConfig({
|
|
|
1490
1540
|
authenticationProfile: ACPAuthenticationProfileIdentity;
|
|
1491
1541
|
sessionMeta: Readonly<Record<string, ACPSerializableValue>> | undefined;
|
|
1492
1542
|
instructionMapping: ACPInstructionMapping | undefined;
|
|
1543
|
+
outputSchemaMapping: ACPOutputSchemaMapping | undefined;
|
|
1493
1544
|
builtinTools: ReadonlyArray<ACPBuiltinToolMapping>;
|
|
1494
1545
|
permissionModeMapping: ACPPermissionModeMapping | undefined;
|
|
1495
1546
|
mcpServers: Record<string, unknown> | undefined;
|
|
@@ -1505,6 +1556,8 @@ function validateACPTurnStartConfig({
|
|
|
1505
1556
|
authenticationProfile,
|
|
1506
1557
|
sessionMeta,
|
|
1507
1558
|
instructionMapping,
|
|
1559
|
+
responseFormat: turnStartConfig.responseFormat,
|
|
1560
|
+
outputSchemaMapping,
|
|
1508
1561
|
});
|
|
1509
1562
|
if (
|
|
1510
1563
|
current.configurationFingerprint !==
|
|
@@ -1523,6 +1576,7 @@ function validateACPColdSessionConfiguration({
|
|
|
1523
1576
|
authenticationProfile,
|
|
1524
1577
|
sessionMeta,
|
|
1525
1578
|
instructionMapping,
|
|
1579
|
+
outputSchemaMapping,
|
|
1526
1580
|
builtinTools,
|
|
1527
1581
|
permissionModeMapping,
|
|
1528
1582
|
mcpServers,
|
|
@@ -1534,6 +1588,7 @@ function validateACPColdSessionConfiguration({
|
|
|
1534
1588
|
authenticationProfile: ACPAuthenticationProfileIdentity;
|
|
1535
1589
|
sessionMeta: Readonly<Record<string, ACPSerializableValue>> | undefined;
|
|
1536
1590
|
instructionMapping: ACPInstructionMapping | undefined;
|
|
1591
|
+
outputSchemaMapping: ACPOutputSchemaMapping | undefined;
|
|
1537
1592
|
builtinTools: ReadonlyArray<ACPBuiltinToolMapping>;
|
|
1538
1593
|
permissionModeMapping: ACPPermissionModeMapping | undefined;
|
|
1539
1594
|
mcpServers: Record<string, unknown> | undefined;
|
|
@@ -1550,6 +1605,8 @@ function validateACPColdSessionConfiguration({
|
|
|
1550
1605
|
authenticationProfile,
|
|
1551
1606
|
sessionMeta,
|
|
1552
1607
|
instructionMapping,
|
|
1608
|
+
responseFormat: coldSession.responseFormat,
|
|
1609
|
+
outputSchemaMapping,
|
|
1553
1610
|
});
|
|
1554
1611
|
if (
|
|
1555
1612
|
current.configurationFingerprint !== coldSession.configurationFingerprint ||
|
|
@@ -100,6 +100,11 @@ export type ACPInstructionMapping =
|
|
|
100
100
|
readonly path: ReadonlyArray<string>;
|
|
101
101
|
};
|
|
102
102
|
|
|
103
|
+
export type ACPOutputSchemaMapping = {
|
|
104
|
+
readonly type: 'session-prompt-meta';
|
|
105
|
+
readonly path: ReadonlyArray<string>;
|
|
106
|
+
};
|
|
107
|
+
|
|
103
108
|
export type ACPV1Settings = {
|
|
104
109
|
readonly version?: 'v1';
|
|
105
110
|
readonly harnessId: string;
|
|
@@ -125,6 +130,11 @@ export type ACPV1Settings = {
|
|
|
125
130
|
* prompt. When omitted, instructions are prepended to the first user prompt.
|
|
126
131
|
*/
|
|
127
132
|
readonly instructionMapping?: ACPInstructionMapping;
|
|
133
|
+
/**
|
|
134
|
+
* Maps structured output JSON Schema to an implementation-specific path
|
|
135
|
+
* below the ACP session prompt's `_meta` field.
|
|
136
|
+
*/
|
|
137
|
+
readonly outputSchemaMapping?: ACPOutputSchemaMapping;
|
|
128
138
|
readonly permissionModeMapping?: ACPPermissionModeMapping;
|
|
129
139
|
readonly session?: {
|
|
130
140
|
readonly meta?: Readonly<Record<string, ACPSerializableValue>>;
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import type { ACPTextContentBlock } from './acp-v1-prompt';
|
|
12
12
|
import type {
|
|
13
13
|
ACPInstructionMapping,
|
|
14
|
+
ACPOutputSchemaMapping,
|
|
14
15
|
ACPPermissionModeMapping,
|
|
15
16
|
ACPSerializableValue,
|
|
16
17
|
} from './acp-v1-settings';
|
|
@@ -26,6 +27,8 @@ export function createACPTurnStartConfig({
|
|
|
26
27
|
authenticationProfile,
|
|
27
28
|
sessionMeta,
|
|
28
29
|
instructionMapping,
|
|
30
|
+
responseFormat,
|
|
31
|
+
outputSchemaMapping,
|
|
29
32
|
}: {
|
|
30
33
|
prompt: ReadonlyArray<ACPTextContentBlock>;
|
|
31
34
|
tools: ReadonlyArray<HarnessV1ToolSpec>;
|
|
@@ -37,6 +40,8 @@ export function createACPTurnStartConfig({
|
|
|
37
40
|
authenticationProfile: ACPAuthenticationProfileIdentity;
|
|
38
41
|
sessionMeta: Readonly<Record<string, ACPSerializableValue>> | undefined;
|
|
39
42
|
instructionMapping: ACPInstructionMapping | undefined;
|
|
43
|
+
responseFormat: StartMessage['responseFormat'];
|
|
44
|
+
outputSchemaMapping: ACPOutputSchemaMapping | undefined;
|
|
40
45
|
}): ACPTurnStartConfig {
|
|
41
46
|
return {
|
|
42
47
|
version: 1,
|
|
@@ -46,6 +51,7 @@ export function createACPTurnStartConfig({
|
|
|
46
51
|
authenticationProfile,
|
|
47
52
|
sessionMeta: sessionMeta ?? null,
|
|
48
53
|
...(instructionMapping == null ? {} : { instructionMapping }),
|
|
54
|
+
...(outputSchemaMapping == null ? {} : { outputSchemaMapping }),
|
|
49
55
|
builtinTools,
|
|
50
56
|
permissionModeMapping: permissionModeMapping ?? null,
|
|
51
57
|
mcpServers: mcpServers ?? null,
|
|
@@ -56,6 +62,15 @@ export function createACPTurnStartConfig({
|
|
|
56
62
|
tools: tools.map(tool => acpSerializableToolSpecSchema.parse(tool)),
|
|
57
63
|
builtinTools: [...builtinTools],
|
|
58
64
|
permissionMode,
|
|
65
|
+
...(responseFormat == null ? {} : { responseFormat }),
|
|
66
|
+
...(outputSchemaMapping == null
|
|
67
|
+
? {}
|
|
68
|
+
: {
|
|
69
|
+
outputSchemaMapping: {
|
|
70
|
+
type: outputSchemaMapping.type,
|
|
71
|
+
path: [...outputSchemaMapping.path],
|
|
72
|
+
},
|
|
73
|
+
}),
|
|
59
74
|
...(permissionModeMapping == null ? {} : { permissionModeMapping }),
|
|
60
75
|
...(debug == null ? {} : { debug }),
|
|
61
76
|
};
|
|
@@ -74,6 +89,12 @@ export function createACPColdSessionState({
|
|
|
74
89
|
tools: turnStartConfig.tools,
|
|
75
90
|
builtinTools: turnStartConfig.builtinTools,
|
|
76
91
|
permissionMode: turnStartConfig.permissionMode,
|
|
92
|
+
...(turnStartConfig.responseFormat == null
|
|
93
|
+
? {}
|
|
94
|
+
: { responseFormat: turnStartConfig.responseFormat }),
|
|
95
|
+
...(turnStartConfig.outputSchemaMapping == null
|
|
96
|
+
? {}
|
|
97
|
+
: { outputSchemaMapping: turnStartConfig.outputSchemaMapping }),
|
|
77
98
|
...(turnStartConfig.permissionModeMapping == null
|
|
78
99
|
? {}
|
|
79
100
|
: { permissionModeMapping: turnStartConfig.permissionModeMapping }),
|
package/src/v1/bridge/index.ts
CHANGED
|
@@ -261,7 +261,13 @@ async function runTurn(start: StartMessage, turn: BridgeTurn): Promise<void> {
|
|
|
261
261
|
};
|
|
262
262
|
hostToolRelay?.bindTurn({ turn: relayTurn });
|
|
263
263
|
try {
|
|
264
|
-
|
|
264
|
+
const promptMeta = createOutputSchemaPromptMeta({ start });
|
|
265
|
+
void promptActiveSession({
|
|
266
|
+
session: activeSession,
|
|
267
|
+
agent: connection!.agent,
|
|
268
|
+
prompt: start.prompt,
|
|
269
|
+
meta: promptMeta,
|
|
270
|
+
});
|
|
265
271
|
if (turn.abortSignal.aborted) {
|
|
266
272
|
await cancel();
|
|
267
273
|
} else {
|
|
@@ -706,6 +712,81 @@ function isRecord(value: unknown): value is Readonly<Record<string, unknown>> {
|
|
|
706
712
|
return value != null && typeof value === 'object' && !Array.isArray(value);
|
|
707
713
|
}
|
|
708
714
|
|
|
715
|
+
function createOutputSchemaPromptMeta({
|
|
716
|
+
start,
|
|
717
|
+
}: {
|
|
718
|
+
start: StartMessage;
|
|
719
|
+
}): Record<string, unknown> | undefined {
|
|
720
|
+
if (
|
|
721
|
+
start.responseFormat?.type !== 'json' ||
|
|
722
|
+
start.responseFormat.schema == null ||
|
|
723
|
+
start.outputSchemaMapping?.type !== 'session-prompt-meta'
|
|
724
|
+
) {
|
|
725
|
+
return undefined;
|
|
726
|
+
}
|
|
727
|
+
const root: Record<string, unknown> = {};
|
|
728
|
+
let target = root;
|
|
729
|
+
const path = start.outputSchemaMapping.path;
|
|
730
|
+
for (let index = 0; index < path.length - 1; index++) {
|
|
731
|
+
const child: Record<string, unknown> = {};
|
|
732
|
+
target[path[index]!] = child;
|
|
733
|
+
target = child;
|
|
734
|
+
}
|
|
735
|
+
target[path[path.length - 1]!] = start.responseFormat.schema;
|
|
736
|
+
return root;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
function promptActiveSession({
|
|
740
|
+
session,
|
|
741
|
+
agent,
|
|
742
|
+
prompt,
|
|
743
|
+
meta,
|
|
744
|
+
}: {
|
|
745
|
+
session: ACPActiveSession;
|
|
746
|
+
agent: acp.ClientContext;
|
|
747
|
+
prompt: Array<acp.ContentBlock>;
|
|
748
|
+
meta: Record<string, unknown> | undefined;
|
|
749
|
+
}): Promise<acp.PromptResponse> {
|
|
750
|
+
if (meta == null) return session.prompt(prompt);
|
|
751
|
+
if (session.promptWithMeta != null) {
|
|
752
|
+
return session.promptWithMeta({ prompt, meta });
|
|
753
|
+
}
|
|
754
|
+
const updates = (
|
|
755
|
+
session as unknown as {
|
|
756
|
+
updates?: {
|
|
757
|
+
clearErrors(): void;
|
|
758
|
+
enqueue(value: acp.ActiveSessionMessage): void;
|
|
759
|
+
reject(error: unknown): void;
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
).updates;
|
|
763
|
+
if (updates == null) {
|
|
764
|
+
throw new Error(
|
|
765
|
+
'The installed ACP SDK cannot send session prompt metadata while preserving streamed updates.',
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
updates.clearErrors();
|
|
769
|
+
const response = agent.request<acp.PromptResponse, acp.PromptRequest>(
|
|
770
|
+
acp.methods.agent.session.prompt,
|
|
771
|
+
{
|
|
772
|
+
sessionId: session.sessionId,
|
|
773
|
+
prompt,
|
|
774
|
+
_meta: meta,
|
|
775
|
+
},
|
|
776
|
+
);
|
|
777
|
+
void response.then(
|
|
778
|
+
value => {
|
|
779
|
+
updates.enqueue({
|
|
780
|
+
kind: 'stop',
|
|
781
|
+
response: value,
|
|
782
|
+
stopReason: value.stopReason,
|
|
783
|
+
});
|
|
784
|
+
},
|
|
785
|
+
error => updates.reject(error),
|
|
786
|
+
);
|
|
787
|
+
return response;
|
|
788
|
+
}
|
|
789
|
+
|
|
709
790
|
async function readImplementationDescriptor({
|
|
710
791
|
path,
|
|
711
792
|
}: {
|
|
@@ -6,6 +6,10 @@ export type ACPActiveSession = {
|
|
|
6
6
|
readonly sessionId: string;
|
|
7
7
|
readonly newSessionResponse: acp.NewSessionResponse;
|
|
8
8
|
prompt(prompt: Array<acp.ContentBlock>): Promise<acp.PromptResponse>;
|
|
9
|
+
promptWithMeta?(options: {
|
|
10
|
+
prompt: Array<acp.ContentBlock>;
|
|
11
|
+
meta: Record<string, unknown>;
|
|
12
|
+
}): Promise<acp.PromptResponse>;
|
|
9
13
|
nextUpdate(): Promise<acp.ActiveSessionMessage>;
|
|
10
14
|
dispose(): void;
|
|
11
15
|
};
|
|
@@ -70,6 +74,27 @@ export function createACPRecoveredSession({
|
|
|
70
74
|
);
|
|
71
75
|
return response;
|
|
72
76
|
},
|
|
77
|
+
promptWithMeta: async ({ prompt, meta }) => {
|
|
78
|
+
if (disposed) {
|
|
79
|
+
throw new Error('Recovered ACP session is disposed.');
|
|
80
|
+
}
|
|
81
|
+
updates.clearErrors();
|
|
82
|
+
const response = agent.request<acp.PromptResponse, acp.PromptRequest>(
|
|
83
|
+
acp.methods.agent.session.prompt,
|
|
84
|
+
{ sessionId, prompt, _meta: meta },
|
|
85
|
+
);
|
|
86
|
+
void response.then(
|
|
87
|
+
value => {
|
|
88
|
+
updates.enqueue({
|
|
89
|
+
kind: 'stop',
|
|
90
|
+
response: value,
|
|
91
|
+
stopReason: value.stopReason,
|
|
92
|
+
});
|
|
93
|
+
},
|
|
94
|
+
error => updates.reject(error),
|
|
95
|
+
);
|
|
96
|
+
return response;
|
|
97
|
+
},
|
|
73
98
|
nextUpdate: () => updates.next(),
|
|
74
99
|
dispose: () => {
|
|
75
100
|
if (disposed) return;
|