@ai-sdk/harness-acp 1.0.15 → 1.0.17
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 +16 -0
- package/dist/bridge/host-tool-mcp.mjs +1 -1
- package/dist/bridge/index.mjs +140 -5
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +82 -20
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/acp-harness.ts +7 -1
- package/src/v1/acp-v1-harness.ts +97 -19
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HarnessV1RequestTransformation, HarnessV1PermissionMode, HarnessV1 } from '@ai-sdk/harness';
|
|
1
|
+
import { HarnessV1RequestTransformation, HarnessV1PermissionMode, HarnessV1PortEndpoint, HarnessV1 } from '@ai-sdk/harness';
|
|
2
2
|
import { ToolSet } from '@ai-sdk/provider-utils';
|
|
3
3
|
|
|
4
4
|
type ACPMetadata = Record<string, unknown>;
|
|
@@ -224,6 +224,11 @@ type ACPHarnessSettings<TBuiltinTools extends ToolSet = {}> = {
|
|
|
224
224
|
readonly mcpServers?: Record<string, unknown>;
|
|
225
225
|
readonly isMcpToolCall?: (toolCall: ACPToolCall) => boolean;
|
|
226
226
|
readonly port?: number;
|
|
227
|
+
/**
|
|
228
|
+
* Override the host endpoint used to connect to the sandbox bridge. Required
|
|
229
|
+
* together with `port` when using a basic sandbox session.
|
|
230
|
+
*/
|
|
231
|
+
readonly portEndpoint?: HarnessV1PortEndpoint;
|
|
227
232
|
readonly startupTimeoutMs?: number;
|
|
228
233
|
readonly clientApp?: ACPClientApp;
|
|
229
234
|
readonly version?: ACPV1Settings['version'];
|
package/dist/index.js
CHANGED
|
@@ -15,8 +15,10 @@ import {
|
|
|
15
15
|
classifyDiskLog,
|
|
16
16
|
drainBridgeProcessStream,
|
|
17
17
|
forwardBridgeProcessStream,
|
|
18
|
+
getRestrictedSandboxSession,
|
|
18
19
|
markBridgeStarting,
|
|
19
20
|
maskSandboxCredentials,
|
|
21
|
+
resolveSandboxDefaultWorkingDirectory,
|
|
20
22
|
resolveSandboxHomeDir,
|
|
21
23
|
SandboxChannel,
|
|
22
24
|
shellQuote,
|
|
@@ -1158,6 +1160,7 @@ function createACPV1({
|
|
|
1158
1160
|
settings,
|
|
1159
1161
|
builtinTools,
|
|
1160
1162
|
port: portOverride,
|
|
1163
|
+
portEndpoint: portEndpointOverride,
|
|
1161
1164
|
startupTimeoutMs,
|
|
1162
1165
|
clientApp,
|
|
1163
1166
|
lifecycleStateSchema
|
|
@@ -1233,6 +1236,24 @@ function createACPV1({
|
|
|
1233
1236
|
compatibility: providerAuthenticationCompatibility
|
|
1234
1237
|
});
|
|
1235
1238
|
const sandboxSession = startOptions.sandboxSession;
|
|
1239
|
+
const toolSafeSandboxSession = getRestrictedSandboxSession(sandboxSession);
|
|
1240
|
+
const sandboxId = "id" in sandboxSession ? sandboxSession.id : void 0;
|
|
1241
|
+
validateBasicSandboxSettings({
|
|
1242
|
+
sandboxSession,
|
|
1243
|
+
port: portOverride,
|
|
1244
|
+
portEndpoint: portEndpointOverride,
|
|
1245
|
+
harnessId: settings.harnessId
|
|
1246
|
+
});
|
|
1247
|
+
if (settings.mintBridgeToken != null && sandboxId == null) {
|
|
1248
|
+
throw unsupported({
|
|
1249
|
+
harnessId: settings.harnessId,
|
|
1250
|
+
message: `The ${settings.harnessId} ACP harness cannot use \`mintBridgeToken\` with a sandbox session that does not expose an id.`
|
|
1251
|
+
});
|
|
1252
|
+
}
|
|
1253
|
+
const defaultWorkingDirectory = await resolveSandboxDefaultWorkingDirectory({
|
|
1254
|
+
sandboxSession,
|
|
1255
|
+
abortSignal: startOptions.abortSignal
|
|
1256
|
+
});
|
|
1236
1257
|
const implementationEnvironment = resolveImplementationEnvironment({
|
|
1237
1258
|
implementation,
|
|
1238
1259
|
env
|
|
@@ -1240,7 +1261,7 @@ function createACPV1({
|
|
|
1240
1261
|
let sandboxImplementationEnvironment = implementationEnvironment;
|
|
1241
1262
|
let sandboxProviderAuthenticationEnvironment = resolvedProviderAuthentication.env;
|
|
1242
1263
|
let sandboxProviderEnvironment;
|
|
1243
|
-
if (settings.credentialBrokering != null && sandboxSession.addRequestTransformations != null) {
|
|
1264
|
+
if (settings.credentialBrokering != null && "addRequestTransformations" in sandboxSession && sandboxSession.addRequestTransformations != null) {
|
|
1244
1265
|
const providerEnvironment = resolveProviderEnvironment({
|
|
1245
1266
|
resolvedProviderAuthentication,
|
|
1246
1267
|
clientApp
|
|
@@ -1283,15 +1304,14 @@ function createACPV1({
|
|
|
1283
1304
|
} else if (settings.credentialBrokering != null) {
|
|
1284
1305
|
warnCredentialBrokeringUnavailable();
|
|
1285
1306
|
}
|
|
1286
|
-
const sandbox = sandboxSession.restricted();
|
|
1287
1307
|
const resolvedBridgeDir = posix.resolve(
|
|
1288
|
-
|
|
1308
|
+
defaultWorkingDirectory,
|
|
1289
1309
|
bootstrap.bootstrapDir
|
|
1290
1310
|
);
|
|
1291
1311
|
const resolvedImplementationDir = `${resolvedBridgeDir}/implementation`;
|
|
1292
1312
|
const workDir = startOptions.sessionWorkDir;
|
|
1293
1313
|
const sandboxHomeDir = await resolveSandboxHomeDir({
|
|
1294
|
-
sandbox,
|
|
1314
|
+
sandbox: toolSafeSandboxSession,
|
|
1295
1315
|
abortSignal: startOptions.abortSignal
|
|
1296
1316
|
});
|
|
1297
1317
|
const privateSessionDir = resolveACPPrivateSessionDirectory({
|
|
@@ -1313,7 +1333,7 @@ function createACPV1({
|
|
|
1313
1333
|
implementationIdentity,
|
|
1314
1334
|
authenticationProfile,
|
|
1315
1335
|
lifecycleData,
|
|
1316
|
-
sandboxId
|
|
1336
|
+
sandboxId
|
|
1317
1337
|
});
|
|
1318
1338
|
}
|
|
1319
1339
|
const skills = startOptions.skills ?? [];
|
|
@@ -1326,7 +1346,7 @@ function createACPV1({
|
|
|
1326
1346
|
let skillCatalog = [];
|
|
1327
1347
|
if (skills.length > 0) {
|
|
1328
1348
|
skillCatalog = (await materializeACPSkills({
|
|
1329
|
-
sandbox,
|
|
1349
|
+
sandbox: toolSafeSandboxSession,
|
|
1330
1350
|
sandboxHomeDir,
|
|
1331
1351
|
sessionWorkDir: workDir,
|
|
1332
1352
|
harnessId: settings.harnessId,
|
|
@@ -1362,9 +1382,11 @@ function createACPV1({
|
|
|
1362
1382
|
}
|
|
1363
1383
|
if (coords != null) {
|
|
1364
1384
|
try {
|
|
1365
|
-
const endpoint2 = await
|
|
1385
|
+
const endpoint2 = await resolveBridgeEndpoint({
|
|
1386
|
+
sandboxSession,
|
|
1387
|
+
override: portEndpointOverride,
|
|
1366
1388
|
port: coords.port,
|
|
1367
|
-
|
|
1389
|
+
harnessId: settings.harnessId
|
|
1368
1390
|
});
|
|
1369
1391
|
const attachEndpoint = withBridgeToken({
|
|
1370
1392
|
endpoint: endpoint2,
|
|
@@ -1404,7 +1426,7 @@ function createACPV1({
|
|
|
1404
1426
|
acpSessionId: lifecycleData.acpSessionId,
|
|
1405
1427
|
bridgePort: coords.port,
|
|
1406
1428
|
bridgeToken: coords.token,
|
|
1407
|
-
sandboxId
|
|
1429
|
+
sandboxId,
|
|
1408
1430
|
isResume: true,
|
|
1409
1431
|
turnInFlight: isContinue,
|
|
1410
1432
|
bridgeStateDir,
|
|
@@ -1417,7 +1439,7 @@ function createACPV1({
|
|
|
1417
1439
|
} catch (error) {
|
|
1418
1440
|
if (isContinue) {
|
|
1419
1441
|
const eventLog = await Promise.resolve(
|
|
1420
|
-
|
|
1442
|
+
toolSafeSandboxSession.readTextFile({
|
|
1421
1443
|
path: `${bridgeStateDir}/event-log.ndjson`,
|
|
1422
1444
|
abortSignal: startOptions.abortSignal
|
|
1423
1445
|
})
|
|
@@ -1493,18 +1515,18 @@ function createACPV1({
|
|
|
1493
1515
|
override: portOverride,
|
|
1494
1516
|
harnessId: settings.harnessId
|
|
1495
1517
|
});
|
|
1496
|
-
const token = settings.mintBridgeToken == null ? randomBytes(32).toString("hex") : settings.mintBridgeToken(
|
|
1497
|
-
await
|
|
1518
|
+
const token = settings.mintBridgeToken == null ? randomBytes(32).toString("hex") : settings.mintBridgeToken(sandboxId);
|
|
1519
|
+
await toolSafeSandboxSession.run({
|
|
1498
1520
|
command: `mkdir -p ${shellQuote(workDir)} ${shellQuote(bridgeStateDir)}`,
|
|
1499
1521
|
abortSignal: startOptions.abortSignal
|
|
1500
1522
|
});
|
|
1501
1523
|
await markBridgeStarting({
|
|
1502
|
-
sandbox,
|
|
1524
|
+
sandbox: toolSafeSandboxSession,
|
|
1503
1525
|
bridgeStateDir,
|
|
1504
1526
|
bridgeType: settings.harnessId,
|
|
1505
1527
|
abortSignal: startOptions.abortSignal
|
|
1506
1528
|
});
|
|
1507
|
-
const proc = await
|
|
1529
|
+
const proc = await toolSafeSandboxSession.spawn({
|
|
1508
1530
|
command: `node ${shellQuote(`${resolvedBridgeDir}/bridge.mjs`)} --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)} --implementation-dir ${shellQuote(resolvedImplementationDir)} --bridge-type ${shellQuote(settings.harnessId)}`,
|
|
1509
1531
|
env: {
|
|
1510
1532
|
...sandboxImplementationEnvironment,
|
|
@@ -1533,7 +1555,7 @@ function createACPV1({
|
|
|
1533
1555
|
const timeoutMs = startupTimeoutMs ?? 12e4;
|
|
1534
1556
|
const { port: boundPort } = await waitForBridgeReady({
|
|
1535
1557
|
proc,
|
|
1536
|
-
sandbox,
|
|
1558
|
+
sandbox: toolSafeSandboxSession,
|
|
1537
1559
|
bridgeStateDir,
|
|
1538
1560
|
bridgeType: settings.harnessId,
|
|
1539
1561
|
timeoutMs,
|
|
@@ -1554,9 +1576,11 @@ function createACPV1({
|
|
|
1554
1576
|
})
|
|
1555
1577
|
});
|
|
1556
1578
|
void drainBridgeProcessStream(proc.stdout);
|
|
1557
|
-
const endpoint = await
|
|
1579
|
+
const endpoint = await resolveBridgeEndpoint({
|
|
1580
|
+
sandboxSession,
|
|
1581
|
+
override: portEndpointOverride,
|
|
1558
1582
|
port: boundPort,
|
|
1559
|
-
|
|
1583
|
+
harnessId: settings.harnessId
|
|
1560
1584
|
});
|
|
1561
1585
|
const bridgeEndpoint = withBridgeToken({ endpoint, token });
|
|
1562
1586
|
const channel = new SandboxChannel({
|
|
@@ -1634,7 +1658,7 @@ function createACPV1({
|
|
|
1634
1658
|
acpSessionId: lifecycleData?.acpSessionId,
|
|
1635
1659
|
bridgePort: boundPort,
|
|
1636
1660
|
bridgeToken: token,
|
|
1637
|
-
sandboxId
|
|
1661
|
+
sandboxId,
|
|
1638
1662
|
isResume,
|
|
1639
1663
|
turnInFlight: respawnStrategy?.mode === "disk-replay" || respawnStrategy?.mode === "lossy-rerun",
|
|
1640
1664
|
bridgeStateDir,
|
|
@@ -1690,12 +1714,49 @@ function resolveBridgePort({
|
|
|
1690
1714
|
harnessId
|
|
1691
1715
|
}) {
|
|
1692
1716
|
if (override !== void 0) return override;
|
|
1693
|
-
if (sandboxSession.ports.length > 0)
|
|
1717
|
+
if ("ports" in sandboxSession && sandboxSession.ports.length > 0) {
|
|
1718
|
+
return sandboxSession.ports[0];
|
|
1719
|
+
}
|
|
1694
1720
|
throw unsupported({
|
|
1695
1721
|
harnessId,
|
|
1696
1722
|
message: `The ${harnessId} ACP harness needs a TCP port exposed by the sandbox. Create the sandbox with \`ports: [<port>]\` or configure the harness \`port\`.`
|
|
1697
1723
|
});
|
|
1698
1724
|
}
|
|
1725
|
+
function validateBasicSandboxSettings({
|
|
1726
|
+
sandboxSession,
|
|
1727
|
+
port,
|
|
1728
|
+
portEndpoint,
|
|
1729
|
+
harnessId
|
|
1730
|
+
}) {
|
|
1731
|
+
if ("getPortEndpoint" in sandboxSession) return;
|
|
1732
|
+
if (port == null) {
|
|
1733
|
+
throw unsupported({
|
|
1734
|
+
harnessId,
|
|
1735
|
+
message: `The ${harnessId} ACP harness requires an explicit \`port\` when using a basic sandbox session.`
|
|
1736
|
+
});
|
|
1737
|
+
}
|
|
1738
|
+
if (portEndpoint == null) {
|
|
1739
|
+
throw unsupported({
|
|
1740
|
+
harnessId,
|
|
1741
|
+
message: `The ${harnessId} ACP harness requires an explicit \`portEndpoint\` when using a basic sandbox session.`
|
|
1742
|
+
});
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
async function resolveBridgeEndpoint({
|
|
1746
|
+
sandboxSession,
|
|
1747
|
+
override,
|
|
1748
|
+
port,
|
|
1749
|
+
harnessId
|
|
1750
|
+
}) {
|
|
1751
|
+
if (override != null) return override;
|
|
1752
|
+
if ("getPortEndpoint" in sandboxSession) {
|
|
1753
|
+
return sandboxSession.getPortEndpoint({ port, protocol: "ws" });
|
|
1754
|
+
}
|
|
1755
|
+
throw unsupported({
|
|
1756
|
+
harnessId,
|
|
1757
|
+
message: `The ${harnessId} ACP harness requires an explicit \`portEndpoint\` when using a basic sandbox session.`
|
|
1758
|
+
});
|
|
1759
|
+
}
|
|
1699
1760
|
function openWebSocket({
|
|
1700
1761
|
url,
|
|
1701
1762
|
headers
|
|
@@ -2433,7 +2494,7 @@ function deserializeBridgeError({
|
|
|
2433
2494
|
}
|
|
2434
2495
|
|
|
2435
2496
|
// src/version.ts
|
|
2436
|
-
var VERSION = true ? "1.0.
|
|
2497
|
+
var VERSION = true ? "1.0.17" : "0.0.0-test";
|
|
2437
2498
|
|
|
2438
2499
|
// src/acp-harness.ts
|
|
2439
2500
|
var ACP_CLIENT_APP = {
|
|
@@ -2496,6 +2557,7 @@ function createACP(settings) {
|
|
|
2496
2557
|
settings,
|
|
2497
2558
|
builtinTools: settings.builtinTools ?? ACP_BUILTIN_TOOLS,
|
|
2498
2559
|
port: settings.port,
|
|
2560
|
+
portEndpoint: settings.portEndpoint,
|
|
2499
2561
|
startupTimeoutMs: settings.startupTimeoutMs,
|
|
2500
2562
|
clientApp,
|
|
2501
2563
|
lifecycleStateSchema: acpResumeStateSchema
|