@ai-sdk/harness-acp 1.0.25 → 1.0.29

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 CHANGED
@@ -1,5 +1,39 @@
1
1
  # @ai-sdk/harness-acp
2
2
 
3
+ ## 1.0.29
4
+
5
+ ### Patch Changes
6
+
7
+ - 20312d6: fix(harness-acp): place skills in their harnesses' natively supported directory instead of applying a manual workaround
8
+ - @ai-sdk/harness@1.0.91
9
+
10
+ ## 1.0.28
11
+
12
+ ### Patch Changes
13
+
14
+ - 0e590d2: feat(harness): harden credential brokering to only apply with correct ephemeral secret
15
+ - Updated dependencies [3e125ba]
16
+ - Updated dependencies [0e590d2]
17
+ - @ai-sdk/provider-utils@5.0.32
18
+ - @ai-sdk/harness@1.0.90
19
+
20
+ ## 1.0.27
21
+
22
+ ### Patch Changes
23
+
24
+ - @ai-sdk/harness@1.0.89
25
+
26
+ ## 1.0.26
27
+
28
+ ### Patch Changes
29
+
30
+ - Updated dependencies [32349cc]
31
+ - Updated dependencies [a9782e1]
32
+ - Updated dependencies [35841f5]
33
+ - Updated dependencies [d2f3353]
34
+ - @ai-sdk/harness@1.0.88
35
+ - @ai-sdk/provider-utils@5.0.31
36
+
3
37
  ## 1.0.25
4
38
 
5
39
  ### Patch Changes
package/README.md CHANGED
@@ -35,13 +35,20 @@ const codexACP = createACP({
35
35
  },
36
36
  executable: 'codex-acp',
37
37
  credentialEnv: ['CODEX_API_KEY', 'OPENAI_API_KEY'],
38
- credentialBrokering: ({ env }) => {
39
- const credential = env.CODEX_API_KEY ?? env.OPENAI_API_KEY;
40
- if (!credential) return [];
38
+ credentialBrokering: ({ env, sandboxEnv }) => {
39
+ const environmentVariableName = env.CODEX_API_KEY
40
+ ? 'CODEX_API_KEY'
41
+ : 'OPENAI_API_KEY';
42
+ const credential = env[environmentVariableName];
43
+ const sandboxCredential = sandboxEnv?.[environmentVariableName];
44
+ if (!credential || !sandboxCredential) return [];
41
45
  return [
42
46
  createCredentialRequestTransformation({
43
- baseUrl: 'https://api.openai.com/v1',
44
- headers: { Authorization: `Bearer ${credential}` },
47
+ matchUrl: 'https://api.openai.com/v1',
48
+ matchHeaders: {
49
+ Authorization: `Bearer ${sandboxCredential}`,
50
+ },
51
+ transformHeaders: { Authorization: `Bearer ${credential}` },
45
52
  }),
46
53
  ];
47
54
  },
@@ -82,7 +89,8 @@ try {
82
89
 
83
90
  Set `CODEX_API_KEY` or `OPENAI_API_KEY` in the host environment. Sandboxes that
84
91
  support additive request transformations receive only credential placeholders;
85
- the real value is injected into matching outbound requests. Other sandboxes
92
+ the real value is injected only when a matching outbound request contains the
93
+ expected placeholder. Other sandboxes
86
94
  retain the legacy behavior of forwarding the value to the ACP process. Codex
87
95
  ACP supports only `permissionMode: 'allow-all'` because its
88
96
  restrictive modes enable Codex's internal sandbox. A bridge-backed ACP harness
@@ -95,3 +103,8 @@ instructions below the ACP session request's `_meta` field. A
95
103
  the implementation starts. Without a mapping, the adapter preserves its
96
104
  backward-compatible behavior and prepends instructions to the first user
97
105
  prompt.
106
+
107
+ Skills are written to `.agents/skills` below the ACP implementation's effective
108
+ `$HOME` and discovered natively by the implementation. Set `skillsDirectory`
109
+ to another relative path, such as `.claude/skills`, when required by the
110
+ implementation.
@@ -12,7 +12,7 @@ import {
12
12
  ListToolsRequestSchema,
13
13
  McpError
14
14
  } from "@modelcontextprotocol/sdk/types.js";
15
- var VERSION = true ? "1.0.25" : "0.0.0-test";
15
+ var VERSION = true ? "1.0.29" : "0.0.0-test";
16
16
  function createHostToolMCPServer({
17
17
  tools: tools2,
18
18
  revision = 1,
package/dist/index.d.ts CHANGED
@@ -145,8 +145,9 @@ type ACPProviderAuthentication = {
145
145
  readonly env: Readonly<Record<string, ACPProfileValue>>;
146
146
  };
147
147
  };
148
- type ACPCredentialBrokering = ({ env, }: {
148
+ type ACPCredentialBrokering = ({ env, sandboxEnv, }: {
149
149
  env: Readonly<Record<string, string>>;
150
+ sandboxEnv?: Readonly<Record<string, string>>;
150
151
  }) => ReadonlyArray<HarnessV1RequestTransformation>;
151
152
  type ACPPermissionModeTarget = {
152
153
  readonly type: 'session-mode';
@@ -200,6 +201,11 @@ type ACPV1Settings = {
200
201
  readonly authentication?: ACPAuthentication;
201
202
  readonly providerAuthentication?: ACPProviderAuthentication;
202
203
  readonly modelId?: string;
204
+ /**
205
+ * Native skills directory relative to the ACP implementation's home
206
+ * directory. Defaults to `.agents/skills`.
207
+ */
208
+ readonly skillsDirectory?: string;
203
209
  /**
204
210
  * Routes HarnessAgent instructions to a runtime-native system or developer
205
211
  * prompt. When omitted, instructions are prepended to the first user prompt.
@@ -262,6 +268,7 @@ type ACPHarnessSettings<TBuiltinTools extends ToolSet = {}> = {
262
268
  readonly authentication?: ACPV1Settings['authentication'];
263
269
  readonly providerAuthentication?: ACPV1Settings['providerAuthentication'];
264
270
  readonly modelId?: ACPV1Settings['modelId'];
271
+ readonly skillsDirectory?: ACPV1Settings['skillsDirectory'];
265
272
  readonly instructionMapping?: ACPV1Settings['instructionMapping'];
266
273
  readonly outputSchemaMapping?: ACPV1Settings['outputSchemaMapping'];
267
274
  readonly permissionModeMapping?: ACPV1Settings['permissionModeMapping'];
package/dist/index.js CHANGED
@@ -13,12 +13,12 @@ import {
13
13
  applyCredentialForwarding,
14
14
  createBridgeErrorHandler,
15
15
  createBridgeStartupError,
16
+ createSandboxCredentialEnvironment,
16
17
  classifyDiskLog,
17
18
  drainBridgeProcessStream,
18
19
  forwardBridgeProcessStream,
19
20
  getRestrictedSandboxSession,
20
21
  markBridgeStarting,
21
- maskSandboxCredentials,
22
22
  resolveSandboxDefaultWorkingDirectory,
23
23
  resolveSandboxHomeDir,
24
24
  SandboxChannel,
@@ -639,28 +639,15 @@ function convertHarnessPromptToACPTextBlocks({
639
639
  }
640
640
  function prependACPInitialGuidance({
641
641
  prompt,
642
- instructions,
643
- skills
642
+ instructions
644
643
  }) {
645
644
  const hasInstructions = instructions != null && instructions.length > 0;
646
- if (!hasInstructions && skills.length === 0) return [...prompt];
645
+ if (!hasInstructions) return [...prompt];
647
646
  const lines = [
648
647
  "<session-guidance>",
649
648
  "This block is operating guidance from the harness, not user-authored content."
650
649
  ];
651
- if (hasInstructions) {
652
- lines.push("<instructions>", instructions, "</instructions>");
653
- }
654
- if (skills.length > 0) {
655
- lines.push(
656
- "<available-skills>",
657
- "Load a skill only when relevant by reading its SKILL.md file at the listed absolute path."
658
- );
659
- for (const skill of skills) {
660
- lines.push(`- ${skill.name}: ${skill.description} (${skill.path})`);
661
- }
662
- lines.push("</available-skills>");
663
- }
650
+ lines.push("<instructions>", instructions, "</instructions>");
664
651
  lines.push("</session-guidance>");
665
652
  return [{ type: "text", text: lines.join("\n") }, ...prompt];
666
653
  }
@@ -1015,14 +1002,15 @@ function resolveACPInitialGuidanceApplied({
1015
1002
  function shouldMaterializeACPSkills({
1016
1003
  isResume,
1017
1004
  lifecycleState,
1018
- skillsFingerprint
1005
+ skillsFingerprint,
1006
+ skillsDirectory
1019
1007
  }) {
1020
1008
  if (isResume && lifecycleState?.skillsFingerprint != null && lifecycleState.skillsFingerprint !== skillsFingerprint) {
1021
1009
  throw new Error(
1022
1010
  "ACP lifecycle state was created with a different set of skills."
1023
1011
  );
1024
1012
  }
1025
- return !isResume || lifecycleState?.skillsMaterialized !== true;
1013
+ return !isResume || lifecycleState?.skillsMaterialized !== true || lifecycleState.skillsDirectory !== skillsDirectory;
1026
1014
  }
1027
1015
  function validateACPLifecycleCompatibility({
1028
1016
  harnessId,
@@ -1064,6 +1052,7 @@ import { createHash as createHash4 } from "crypto";
1064
1052
  import path from "path";
1065
1053
  import { writeSkills } from "@ai-sdk/harness/utils";
1066
1054
  var ACP_SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
1055
+ var DEFAULT_ACP_SKILLS_DIRECTORY = ".agents/skills";
1067
1056
  function createACPSkillsFingerprint({
1068
1057
  skills
1069
1058
  }) {
@@ -1101,24 +1090,14 @@ function resolveACPPrivateSessionDirectory({
1101
1090
  }
1102
1091
  async function materializeACPSkills({
1103
1092
  sandbox,
1104
- sandboxHomeDir,
1093
+ rootDir,
1105
1094
  sessionWorkDir,
1106
- harnessId,
1107
- sessionId,
1108
1095
  skills,
1109
1096
  shouldMaterialize,
1110
1097
  abortSignal
1111
1098
  }) {
1112
1099
  validateACPSkills({ skills });
1113
- const rootDir = path.posix.join(
1114
- resolveACPPrivateSessionDirectory({
1115
- sandboxHomeDir,
1116
- sessionWorkDir,
1117
- harnessId,
1118
- sessionId
1119
- }),
1120
- "skills"
1121
- );
1100
+ assertOutsideSessionWorkDir({ rootDir, sessionWorkDir });
1122
1101
  if (shouldMaterialize) {
1123
1102
  await writeSkills({
1124
1103
  sandbox,
@@ -1132,14 +1111,22 @@ async function materializeACPSkills({
1132
1111
  )}: expected a relative POSIX path without traversal.`
1133
1112
  });
1134
1113
  }
1135
- return {
1136
- rootDir,
1137
- catalog: skills.map((skill) => ({
1138
- name: skill.name,
1139
- description: skill.description,
1140
- path: path.posix.join(rootDir, skill.name, "SKILL.md")
1141
- }))
1142
- };
1114
+ }
1115
+ function resolveACPSkillsDirectory({
1116
+ implementationHomeDir,
1117
+ skillsDirectory = DEFAULT_ACP_SKILLS_DIRECTORY,
1118
+ sessionWorkDir
1119
+ }) {
1120
+ const containsTraversal = skillsDirectory.split(/[\\/]/).some((segment) => segment === "..");
1121
+ const normalizedDirectory = path.posix.normalize(skillsDirectory);
1122
+ if (skillsDirectory.length === 0 || skillsDirectory.includes("\\") || path.posix.isAbsolute(skillsDirectory) || path.win32.isAbsolute(skillsDirectory) || containsTraversal || normalizedDirectory === "." || normalizedDirectory.startsWith("../") || normalizedDirectory.includes("/../") || normalizedDirectory.endsWith("/..")) {
1123
+ throw new Error(
1124
+ `ACP skillsDirectory ${JSON.stringify(skillsDirectory)} must be a relative POSIX path without traversal.`
1125
+ );
1126
+ }
1127
+ const rootDir = path.posix.join(implementationHomeDir, normalizedDirectory);
1128
+ assertOutsideSessionWorkDir({ rootDir, sessionWorkDir });
1129
+ return rootDir;
1143
1130
  }
1144
1131
  function validateACPSkills({
1145
1132
  skills
@@ -1318,6 +1305,21 @@ function createACPV1({
1318
1305
  sandboxSession,
1319
1306
  abortSignal: startOptions.abortSignal
1320
1307
  });
1308
+ const continueFrom = startOptions.continueFrom ?? startOptions.resumeFrom?.continueFrom;
1309
+ const lifecycleState = continueFrom ?? startOptions.resumeFrom;
1310
+ const isContinue = continueFrom != null;
1311
+ const isResume = lifecycleState != null;
1312
+ const lifecycleData = lifecycleState != null ? lifecycleState.data : void 0;
1313
+ if (lifecycleData != null && lifecycleState != null) {
1314
+ validateACPLifecycleCompatibility({
1315
+ harnessId: settings.harnessId,
1316
+ lifecycleHarnessId: lifecycleState.harnessId,
1317
+ implementationIdentity,
1318
+ authenticationProfile,
1319
+ lifecycleData,
1320
+ sandboxId
1321
+ });
1322
+ }
1321
1323
  const implementationEnvironment = resolveImplementationEnvironment({
1322
1324
  implementation,
1323
1325
  env
@@ -1340,30 +1342,35 @@ function createACPV1({
1340
1342
  })
1341
1343
  ])
1342
1344
  ];
1345
+ let sandboxCredentialEnvironment;
1343
1346
  if (settings.credentialBrokering != null && "addRequestTransformations" in sandboxSession && sandboxSession.addRequestTransformations != null) {
1344
1347
  const providerEnvironment = resolveProviderEnvironment({
1345
1348
  resolvedProviderAuthentication,
1346
1349
  clientApp
1347
1350
  });
1351
+ const brokeringEnvironment = {
1352
+ ...implementationEnvironment,
1353
+ ...providerEnvironment
1354
+ };
1355
+ sandboxCredentialEnvironment = lifecycleData?.sandboxCredentialEnvironment ?? await createSandboxCredentialEnvironment({
1356
+ environment: brokeringEnvironment,
1357
+ credentialEnvironmentVariables: credentialForwardingEnvironmentVariables,
1358
+ credentialForwarding: settings.credentialForwarding
1359
+ });
1360
+ sandboxImplementationEnvironment = {
1361
+ ...brokeringEnvironment,
1362
+ ...sandboxCredentialEnvironment
1363
+ };
1348
1364
  const requestTransformations = settings.credentialBrokering({
1349
- env: {
1350
- ...implementationEnvironment,
1351
- ...providerEnvironment
1352
- }
1365
+ env: brokeringEnvironment,
1366
+ sandboxEnv: sandboxImplementationEnvironment
1353
1367
  });
1354
1368
  if (requestTransformations.length > 0) {
1355
1369
  await sandboxSession.addRequestTransformations(
1356
1370
  requestTransformations
1357
1371
  );
1358
1372
  }
1359
- sandboxImplementationEnvironment = maskSandboxCredentials({
1360
- environment: implementationEnvironment,
1361
- credentialEnvironmentVariables
1362
- });
1363
- sandboxProviderEnvironment = resolveBrokeredProviderEnvironment({
1364
- resolvedProviderAuthentication,
1365
- clientApp
1366
- });
1373
+ sandboxProviderEnvironment = resolvedProviderAuthentication.providerAuthentication?.type === "ai-gateway" ? {} : void 0;
1367
1374
  } else if (settings.credentialBrokering != null) {
1368
1375
  warnCredentialBrokeringUnavailable();
1369
1376
  }
@@ -1400,41 +1407,29 @@ function createACPV1({
1400
1407
  harnessId: settings.harnessId,
1401
1408
  sessionId: startOptions.sessionId
1402
1409
  });
1410
+ const skillsDirectory = resolveACPSkillsDirectory({
1411
+ implementationHomeDir: implementation.source.type === "install-command" ? `${resolvedImplementationDir}/home` : sandboxHomeDir,
1412
+ skillsDirectory: settings.skillsDirectory,
1413
+ sessionWorkDir: workDir
1414
+ });
1403
1415
  const bridgeStateDir = `${privateSessionDir}/bridge`;
1404
- const continueFrom = startOptions.continueFrom ?? startOptions.resumeFrom?.continueFrom;
1405
- const lifecycleState = continueFrom ?? startOptions.resumeFrom;
1406
- const isContinue = continueFrom != null;
1407
- const isResume = lifecycleState != null;
1408
- const lifecycleData = lifecycleState != null ? lifecycleState.data : void 0;
1409
- if (lifecycleData != null && lifecycleState != null) {
1410
- validateACPLifecycleCompatibility({
1411
- harnessId: settings.harnessId,
1412
- lifecycleHarnessId: lifecycleState.harnessId,
1413
- implementationIdentity,
1414
- authenticationProfile,
1415
- lifecycleData,
1416
- sandboxId
1417
- });
1418
- }
1419
1416
  const skills = startOptions.skills ?? [];
1420
1417
  const skillsFingerprint = createACPSkillsFingerprint({ skills });
1421
1418
  const shouldMaterializeSkills = shouldMaterializeACPSkills({
1422
1419
  isResume,
1423
1420
  lifecycleState: lifecycleData,
1424
- skillsFingerprint
1421
+ skillsFingerprint,
1422
+ skillsDirectory
1425
1423
  });
1426
- let skillCatalog = [];
1427
1424
  if (skills.length > 0) {
1428
- skillCatalog = (await materializeACPSkills({
1425
+ await materializeACPSkills({
1429
1426
  sandbox: toolSafeSandboxSession,
1430
- sandboxHomeDir,
1427
+ rootDir: skillsDirectory,
1431
1428
  sessionWorkDir: workDir,
1432
- harnessId: settings.harnessId,
1433
- sessionId: startOptions.sessionId,
1434
1429
  skills,
1435
1430
  shouldMaterialize: shouldMaterializeSkills,
1436
1431
  abortSignal: startOptions.abortSignal
1437
- })).catalog;
1432
+ });
1438
1433
  }
1439
1434
  const report = startOptions.observability?.report;
1440
1435
  const onDiagnostic = report ? (frame) => report(
@@ -1501,8 +1496,8 @@ function createACPV1({
1501
1496
  isResume: true,
1502
1497
  lifecycleState: lifecycleData
1503
1498
  }),
1504
- skillCatalog,
1505
1499
  skillsFingerprint,
1500
+ skillsDirectory,
1506
1501
  acpSessionId: lifecycleData.acpSessionId,
1507
1502
  bridgePort: coords.port,
1508
1503
  bridgeToken: coords.token,
@@ -1513,6 +1508,7 @@ function createACPV1({
1513
1508
  turnStartConfig: lifecycleData.turnStartConfig,
1514
1509
  recoveryStatus: lifecycleData.recovery,
1515
1510
  restoration: lifecycleData.restoration,
1511
+ sandboxCredentialEnvironment,
1516
1512
  replayOnly: false,
1517
1513
  lossyRerun: false
1518
1514
  });
@@ -1590,11 +1586,11 @@ function createACPV1({
1590
1586
  };
1591
1587
  }
1592
1588
  }
1593
- const forwardedImplementationEnvironment = await applyCredentialForwarding({
1589
+ const forwardedImplementationEnvironment = sandboxCredentialEnvironment == null ? await applyCredentialForwarding({
1594
1590
  environment: sandboxImplementationEnvironment,
1595
1591
  credentialEnvironmentVariables: credentialForwardingEnvironmentVariables,
1596
1592
  credentialForwarding: settings.credentialForwarding
1597
- });
1593
+ }) : sandboxImplementationEnvironment;
1598
1594
  const port = resolveBridgePort({
1599
1595
  sandboxSession,
1600
1596
  override: portOverride,
@@ -1738,8 +1734,8 @@ function createACPV1({
1738
1734
  isResume,
1739
1735
  lifecycleState: lifecycleData
1740
1736
  }),
1741
- skillCatalog,
1742
1737
  skillsFingerprint,
1738
+ skillsDirectory,
1743
1739
  acpSessionId: lifecycleData?.acpSessionId,
1744
1740
  bridgePort: boundPort,
1745
1741
  bridgeToken: token,
@@ -1753,6 +1749,7 @@ function createACPV1({
1753
1749
  reason: respawnStrategy.reason
1754
1750
  } : void 0,
1755
1751
  restoration: coldRestoration == null ? lifecycleData?.restoration : { method: coldRestoration },
1752
+ sandboxCredentialEnvironment,
1756
1753
  replayOnly: respawnStrategy?.mode === "disk-replay",
1757
1754
  lossyRerun: respawnStrategy?.mode === "lossy-rerun"
1758
1755
  });
@@ -1782,36 +1779,6 @@ function resolveProviderEnvironment({
1782
1779
  }
1783
1780
  });
1784
1781
  }
1785
- function resolveBrokeredProviderEnvironment({
1786
- resolvedProviderAuthentication,
1787
- clientApp
1788
- }) {
1789
- const providerAuthentication = resolvedProviderAuthentication.providerAuthentication;
1790
- if (providerAuthentication?.type !== "ai-gateway") return {};
1791
- const baseUrl = requireResolvedEnvironmentValue({
1792
- environment: resolvedProviderAuthentication.env,
1793
- name: "AI_SDK_ACP_GATEWAY_BASE_URL"
1794
- });
1795
- return Object.fromEntries(
1796
- Object.entries(providerAuthentication.env).map(
1797
- ([environmentVariableName, value]) => {
1798
- const environment = resolveACPLaunchEnvironment({
1799
- providerAuthentication: {
1800
- type: "ai-gateway",
1801
- env: { [environmentVariableName]: value }
1802
- },
1803
- gateway: {
1804
- apiKey: environmentVariableName,
1805
- baseUrl,
1806
- clientAppName: clientApp.name,
1807
- clientAppVersion: clientApp.version
1808
- }
1809
- });
1810
- return [environmentVariableName, environment[environmentVariableName]];
1811
- }
1812
- )
1813
- );
1814
- }
1815
1782
  function resolveACPProviderCredentialEnvironmentVariables({
1816
1783
  providerAuthentication
1817
1784
  }) {
@@ -2006,8 +1973,8 @@ function createSession({
2006
1973
  mcpServers,
2007
1974
  isMcpToolCall,
2008
1975
  initialGuidanceApplied: initialGuidanceAppliedAtStart,
2009
- skillCatalog,
2010
1976
  skillsFingerprint,
1977
+ skillsDirectory,
2011
1978
  acpSessionId: acpSessionIdAtStart,
2012
1979
  bridgePort,
2013
1980
  bridgeToken,
@@ -2018,6 +1985,7 @@ function createSession({
2018
1985
  turnStartConfig: turnStartConfigAtStart,
2019
1986
  recoveryStatus,
2020
1987
  restoration,
1988
+ sandboxCredentialEnvironment,
2021
1989
  replayOnly,
2022
1990
  lossyRerun
2023
1991
  }) {
@@ -2253,6 +2221,7 @@ function createSession({
2253
2221
  }) => ({
2254
2222
  implementationIdentity,
2255
2223
  authenticationProfile,
2224
+ ...sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment },
2256
2225
  ...latestACPSessionId == null ? {} : { acpSessionId: latestACPSessionId },
2257
2226
  ...bridge == null ? {} : { bridge },
2258
2227
  ...latestTurnStartConfig == null ? {} : {
@@ -2266,7 +2235,8 @@ function createSession({
2266
2235
  ...restoration == null ? {} : { restoration },
2267
2236
  initialGuidanceApplied,
2268
2237
  skillsMaterialized: true,
2269
- skillsFingerprint
2238
+ skillsFingerprint,
2239
+ skillsDirectory
2270
2240
  });
2271
2241
  return {
2272
2242
  sessionId,
@@ -2327,8 +2297,7 @@ function createSession({
2327
2297
  type: "start",
2328
2298
  prompt: initialGuidanceApplied ? prompt : prependACPInitialGuidance({
2329
2299
  prompt,
2330
- instructions: instructionMapping == null ? options.instructions : void 0,
2331
- skills: skillCatalog
2300
+ instructions: instructionMapping == null ? options.instructions : void 0
2332
2301
  }),
2333
2302
  ...instructionMapping == null ? {} : {
2334
2303
  instructionMapping,
@@ -2632,7 +2601,7 @@ function deserializeBridgeError({
2632
2601
  }
2633
2602
 
2634
2603
  // src/version.ts
2635
- var VERSION = true ? "1.0.25" : "0.0.0-test";
2604
+ var VERSION = true ? "1.0.29" : "0.0.0-test";
2636
2605
 
2637
2606
  // src/acp-harness.ts
2638
2607
  var ACP_CLIENT_APP = {
@@ -2658,6 +2627,7 @@ var acpResumeStateSchema = z4.object({
2658
2627
  providerMode: z4.enum(["auto", "direct", "ai-gateway"]).optional(),
2659
2628
  gatewayCredentialSource: z4.enum(["AI_GATEWAY_API_KEY", "VERCEL_OIDC_TOKEN"]).nullable().optional()
2660
2629
  }).optional(),
2630
+ sandboxCredentialEnvironment: z4.record(z4.string(), z4.string()).optional(),
2661
2631
  acpSessionId: z4.string().optional(),
2662
2632
  bridge: acpBridgeCoordsSchema.optional(),
2663
2633
  coldSession: acpColdSessionStateSchema.optional(),
@@ -2671,7 +2641,8 @@ var acpResumeStateSchema = z4.object({
2671
2641
  }).optional(),
2672
2642
  initialGuidanceApplied: z4.boolean().optional(),
2673
2643
  skillsMaterialized: z4.boolean().optional(),
2674
- skillsFingerprint: z4.string().optional()
2644
+ skillsFingerprint: z4.string().optional(),
2645
+ skillsDirectory: z4.string().optional()
2675
2646
  });
2676
2647
  function createACP(settings) {
2677
2648
  if (settings.credentialEnv == null !== (settings.credentialBrokering == null)) {