@ai-sdk/harness-pi 1.0.102 → 1.0.104

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,25 @@
1
1
  # @ai-sdk/harness-pi
2
2
 
3
+ ## 1.0.104
4
+
5
+ ### Patch Changes
6
+
7
+ - eeed977: feat(harness): allow passing arbitrary headers with inference requests via `headers` property in `HarnessAgentSettings`
8
+ - a39c8bf: chore(harness): clarify `writeSkills` helper intent to require materializing skills in HOME directory
9
+ - Updated dependencies [fe86f8f]
10
+ - Updated dependencies [255cccf]
11
+ - Updated dependencies [eeed977]
12
+ - Updated dependencies [a39c8bf]
13
+ - @ai-sdk/harness@1.0.102
14
+
15
+ ## 1.0.103
16
+
17
+ ### Patch Changes
18
+
19
+ - 951c54d: feat(harness): support `askUserQuestions` tool including support for normalization across harness adapters
20
+ - Updated dependencies [951c54d]
21
+ - @ai-sdk/harness@1.0.101
22
+
3
23
  ## 1.0.102
4
24
 
5
25
  ### Patch Changes
package/dist/index.js CHANGED
@@ -113,14 +113,15 @@ import {
113
113
  } from "@earendil-works/pi-coding-agent";
114
114
  import { mkdir as mkdir3, rm as rm2 } from "fs/promises";
115
115
  import { tmpdir } from "os";
116
- import path7 from "path";
116
+ import path6 from "path";
117
117
  import { Type as Type2 } from "typebox";
118
118
  import {
119
119
  HarnessCapabilityUnsupportedError as HarnessCapabilityUnsupportedError2
120
120
  } from "@ai-sdk/harness";
121
121
  import {
122
122
  getRestrictedSandboxSession,
123
- resolveSandboxHomeDir
123
+ resolveSandboxHomeDir,
124
+ writeSkills
124
125
  } from "@ai-sdk/harness/utils";
125
126
 
126
127
  // src/pi-auth.ts
@@ -134,7 +135,7 @@ import {
134
135
  import { access } from "fs/promises";
135
136
 
136
137
  // src/version.ts
137
- var VERSION = true ? "1.0.102" : "0.0.0-test";
138
+ var VERSION = true ? "1.0.104" : "0.0.0-test";
138
139
 
139
140
  // src/pi-auth.ts
140
141
  var DEFAULT_GATEWAY_BASE_URL = "https://ai-gateway.vercel.sh";
@@ -242,13 +243,15 @@ async function createPiModelRuntime({
242
243
  function createGatewayProviderConfig({
243
244
  apiKey,
244
245
  baseUrl,
245
- clientApp
246
+ clientApp,
247
+ headers
246
248
  }) {
247
249
  return {
248
250
  apiKey,
249
251
  baseUrl,
250
252
  authHeader: true,
251
253
  headers: {
254
+ ...headers,
252
255
  "User-Agent": clientApp,
253
256
  "x-client-app": clientApp
254
257
  }
@@ -335,7 +338,8 @@ async function registerPiProviders({
335
338
  options,
336
339
  resolvedEnv,
337
340
  registries,
338
- clientApp = HARNESS_CLIENT_APP
341
+ clientApp = HARNESS_CLIENT_APP,
342
+ headers
339
343
  }) {
340
344
  const suppliedEnvironment = isHarnessAuthenticationEnvironment(options);
341
345
  const authenticationEnvironment = suppliedEnvironment ? options : process.env;
@@ -346,7 +350,8 @@ async function registerPiProviders({
346
350
  await registerCustomProviders({
347
351
  customEnv: { ...pickOpenAIEnv(authenticationEnvironment), ...env },
348
352
  registries,
349
- clientApp
353
+ clientApp,
354
+ headers
350
355
  });
351
356
  return;
352
357
  }
@@ -355,7 +360,8 @@ async function registerPiProviders({
355
360
  await registerCustomProviders({
356
361
  customEnv: { ...pickAnthropicEnv(authenticationEnvironment), ...env },
357
362
  registries,
358
- clientApp
363
+ clientApp,
364
+ headers
359
365
  });
360
366
  return;
361
367
  }
@@ -364,7 +370,8 @@ async function registerPiProviders({
364
370
  await registerCustomProviders({
365
371
  customEnv: { ...pickProviderEnv(authenticationEnvironment), ...env },
366
372
  registries,
367
- clientApp
373
+ clientApp,
374
+ headers
368
375
  });
369
376
  return;
370
377
  }
@@ -382,7 +389,8 @@ async function registerPiProviders({
382
389
  config: createGatewayProviderConfig({
383
390
  apiKey: gatewayApiKey,
384
391
  baseUrl: gatewayBaseUrl,
385
- clientApp
392
+ clientApp,
393
+ headers
386
394
  })
387
395
  });
388
396
  return;
@@ -402,7 +410,8 @@ async function registerPiProviders({
402
410
  config: createGatewayProviderConfig({
403
411
  apiKey: gatewayApiKey,
404
412
  baseUrl: gatewayBaseUrl,
405
- clientApp
413
+ clientApp,
414
+ headers
406
415
  })
407
416
  });
408
417
  return;
@@ -411,7 +420,8 @@ async function registerPiProviders({
411
420
  await registerCustomProviders({
412
421
  customEnv: { ...pickProviderEnv(authenticationEnvironment), ...env },
413
422
  registries,
414
- clientApp
423
+ clientApp,
424
+ headers
415
425
  });
416
426
  return;
417
427
  }
@@ -444,7 +454,8 @@ function pickProviderEnv(env) {
444
454
  async function registerCustomProviders({
445
455
  customEnv,
446
456
  registries,
447
- clientApp
457
+ clientApp,
458
+ headers
448
459
  }) {
449
460
  const gatewayKey = customEnv.AI_GATEWAY_API_KEY;
450
461
  if (gatewayKey) {
@@ -456,7 +467,8 @@ async function registerCustomProviders({
456
467
  config: createGatewayProviderConfig({
457
468
  apiKey: gatewayKey,
458
469
  baseUrl,
459
- clientApp
470
+ clientApp,
471
+ headers
460
472
  })
461
473
  });
462
474
  }
@@ -469,7 +481,8 @@ async function registerCustomProviders({
469
481
  config: {
470
482
  apiKey: customEnv.OPENAI_API_KEY,
471
483
  baseUrl,
472
- authHeader: true
484
+ authHeader: true,
485
+ ...headers ? { headers } : {}
473
486
  }
474
487
  });
475
488
  }
@@ -482,9 +495,12 @@ async function registerCustomProviders({
482
495
  config: {
483
496
  apiKey: customEnv.ANTHROPIC_API_KEY,
484
497
  baseUrl,
485
- ...customEnv.ANTHROPIC_AUTH_TOKEN ? {
498
+ ...headers || customEnv.ANTHROPIC_AUTH_TOKEN ? {
486
499
  headers: {
487
- authorization: `Bearer ${customEnv.ANTHROPIC_AUTH_TOKEN}`
500
+ ...headers,
501
+ ...customEnv.ANTHROPIC_AUTH_TOKEN ? {
502
+ authorization: `Bearer ${customEnv.ANTHROPIC_AUTH_TOKEN}`
503
+ } : {}
488
504
  }
489
505
  } : {}
490
506
  }
@@ -510,7 +526,8 @@ async function registerCustomProviders({
510
526
  config: {
511
527
  apiKey,
512
528
  baseUrl,
513
- authHeader: true
529
+ authHeader: true,
530
+ ...headers ? { headers } : {}
514
531
  }
515
532
  });
516
533
  }
@@ -986,20 +1003,6 @@ function createPiRemoteOps(options) {
986
1003
  };
987
1004
  }
988
1005
 
989
- // src/pi-skills.ts
990
- import path4 from "path";
991
- import { writeSkills } from "@ai-sdk/harness/utils";
992
- async function writePiSkills(args) {
993
- return writeSkills({
994
- sandbox: args.sandbox,
995
- rootDir: path4.posix.join(args.sandboxHomeDir, ".agents", "skills"),
996
- skills: args.skills,
997
- abortSignal: args.abortSignal,
998
- invalidSkillNameMessage: ({ name }) => `Invalid Pi skill name: ${name}`,
999
- invalidSkillFilePathMessage: ({ skillName, filePath }) => `Invalid Pi skill file path for ${skillName}: ${filePath}`
1000
- });
1001
- }
1002
-
1003
1006
  // src/pi-translate.ts
1004
1007
  import { randomBytes } from "crypto";
1005
1008
  import { secureJsonParse } from "@ai-sdk/provider-utils";
@@ -1362,7 +1365,7 @@ function toolSpecToTypeBoxParameters(jsonSchema) {
1362
1365
  // src/pi-workspace-vfs.ts
1363
1366
  import fs from "fs";
1364
1367
  import { syncBuiltinESMExports } from "module";
1365
- import path5 from "path";
1368
+ import path4 from "path";
1366
1369
  var mountedRoots = /* @__PURE__ */ new Map();
1367
1370
  var mutableFs = fs;
1368
1371
  var mutableFsPromises = fs.promises;
@@ -1392,11 +1395,11 @@ var originalFsPromises = {
1392
1395
  writeFile: fs.promises.writeFile.bind(fs.promises)
1393
1396
  };
1394
1397
  function isInsidePath2(parent, candidate) {
1395
- const relative = path5.relative(parent, candidate);
1396
- return relative === "" || !relative.startsWith("..") && !path5.isAbsolute(relative);
1398
+ const relative = path4.relative(parent, candidate);
1399
+ return relative === "" || !relative.startsWith("..") && !path4.isAbsolute(relative);
1397
1400
  }
1398
1401
  function resolveAbsolutePath(inputPath) {
1399
- return path5.isAbsolute(inputPath) ? path5.normalize(inputPath) : path5.resolve(inputPath);
1402
+ return path4.isAbsolute(inputPath) ? path4.normalize(inputPath) : path4.resolve(inputPath);
1400
1403
  }
1401
1404
  function findMountedRoot(inputPath) {
1402
1405
  const resolvedPath = resolveAbsolutePath(inputPath);
@@ -1417,26 +1420,26 @@ function mapToBackingPath(inputPath) {
1417
1420
  return null;
1418
1421
  }
1419
1422
  const resolvedPath = resolveAbsolutePath(inputPath);
1420
- const relativePath = path5.relative(mountedRoot.mountPoint, resolvedPath);
1421
- return relativePath ? path5.join(mountedRoot.backingRoot, relativePath) : mountedRoot.backingRoot;
1423
+ const relativePath = path4.relative(mountedRoot.mountPoint, resolvedPath);
1424
+ return relativePath ? path4.join(mountedRoot.backingRoot, relativePath) : mountedRoot.backingRoot;
1422
1425
  }
1423
1426
  function mapRealpathResult(inputPath, result) {
1424
1427
  const mountedRoot = findMountedRoot(inputPath);
1425
1428
  if (!mountedRoot) {
1426
1429
  return result;
1427
1430
  }
1428
- let normalizedBackingRoot = path5.resolve(mountedRoot.backingRoot);
1431
+ let normalizedBackingRoot = path4.resolve(mountedRoot.backingRoot);
1429
1432
  try {
1430
1433
  const realpath = originalFsSyncMethods.realpathSync.native ?? originalFsSyncMethods.realpathSync;
1431
- normalizedBackingRoot = path5.resolve(realpath(mountedRoot.backingRoot));
1434
+ normalizedBackingRoot = path4.resolve(realpath(mountedRoot.backingRoot));
1432
1435
  } catch {
1433
1436
  }
1434
- const normalizedResult = path5.resolve(result);
1437
+ const normalizedResult = path4.resolve(result);
1435
1438
  if (!isInsidePath2(normalizedBackingRoot, normalizedResult)) {
1436
1439
  return result;
1437
1440
  }
1438
- const relativePath = path5.relative(normalizedBackingRoot, normalizedResult);
1439
- return relativePath ? path5.join(mountedRoot.mountPoint, relativePath) : mountedRoot.mountPoint;
1441
+ const relativePath = path4.relative(normalizedBackingRoot, normalizedResult);
1442
+ return relativePath ? path4.join(mountedRoot.mountPoint, relativePath) : mountedRoot.mountPoint;
1440
1443
  }
1441
1444
  function mapRenamePaths(sourcePath, destinationPath) {
1442
1445
  const sourceRoot = findMountedRoot(sourcePath);
@@ -1631,8 +1634,8 @@ var PiWorkspaceVfs = class {
1631
1634
  if (this.backingRoot === backingRoot && this.mountPoint === mountPoint) {
1632
1635
  return;
1633
1636
  }
1634
- const resolvedBackingRoot = path5.resolve(backingRoot);
1635
- const resolvedMountPoint = path5.resolve(mountPoint);
1637
+ const resolvedBackingRoot = path4.resolve(backingRoot);
1638
+ const resolvedMountPoint = path4.resolve(mountPoint);
1636
1639
  if (this.mountPoint) {
1637
1640
  this.disposeMount();
1638
1641
  }
@@ -1661,7 +1664,7 @@ import {
1661
1664
  stat,
1662
1665
  writeFile as writeFile2
1663
1666
  } from "fs/promises";
1664
- import path6 from "path";
1667
+ import path5 from "path";
1665
1668
  import { gunzipSync } from "zlib";
1666
1669
  import { shellQuote as shellQuote2 } from "@ai-sdk/harness/utils";
1667
1670
  var PI_CONFIG_DIRS = [".pi", ".agents"];
@@ -1669,9 +1672,9 @@ var PI_CONTEXT_FILENAMES = ["AGENTS.md", "AGENTS.MD"];
1669
1672
  var ARCHIVE_BATCH_SIZE = 300;
1670
1673
  var TAR_BLOCK_SIZE = 512;
1671
1674
  function normalizeRelativePath(inputPath) {
1672
- const normalized = inputPath.split(path6.posix.sep).join(path6.sep);
1673
- const relative = path6.normalize(normalized);
1674
- if (relative === "" || relative === "." || path6.isAbsolute(relative) || relative === ".." || relative.startsWith(`..${path6.sep}`)) {
1675
+ const normalized = inputPath.split(path5.posix.sep).join(path5.sep);
1676
+ const relative = path5.normalize(normalized);
1677
+ if (relative === "" || relative === "." || path5.isAbsolute(relative) || relative === ".." || relative.startsWith(`..${path5.sep}`)) {
1675
1678
  throw new Error(
1676
1679
  `Sandbox workspace mirror received an invalid relative path: ${inputPath}`
1677
1680
  );
@@ -1694,7 +1697,7 @@ async function listRemoteWorkspaceEntries(sandbox, sandboxWorkDir) {
1694
1697
  ];
1695
1698
  const listCommand = [
1696
1699
  `pi_config_sources=(${scopedPaths.map(
1697
- (scopedPath) => shellQuote2(path6.posix.join(sandboxWorkDir, scopedPath.slice(2)))
1700
+ (scopedPath) => shellQuote2(path5.posix.join(sandboxWorkDir, scopedPath.slice(2)))
1698
1701
  ).join(" ")})`,
1699
1702
  `pi_config_relatives=(${scopedPaths.map((scopedPath) => shellQuote2(scopedPath.slice(2))).join(" ")})`,
1700
1703
  `pi_config_ancestors=(${scopedPaths.map(() => "''").join(" ")})`,
@@ -1887,8 +1890,8 @@ async function collectHostSubtree(rootDir, currentDir, directories, files) {
1887
1890
  const entries = await readdir(currentDir, { withFileTypes: true });
1888
1891
  for (const entry of entries) {
1889
1892
  if (entry.isSymbolicLink()) continue;
1890
- const absolutePath = path6.join(currentDir, entry.name);
1891
- const relativePath = path6.relative(rootDir, absolutePath);
1893
+ const absolutePath = path5.join(currentDir, entry.name);
1894
+ const relativePath = path5.relative(rootDir, absolutePath);
1892
1895
  if (entry.isDirectory()) {
1893
1896
  directories.push(relativePath);
1894
1897
  await collectHostSubtree(rootDir, absolutePath, directories, files);
@@ -1901,14 +1904,14 @@ async function collectHostScopedEntries(rootDir) {
1901
1904
  const directories = [];
1902
1905
  const files = [];
1903
1906
  for (const dir of PI_CONFIG_DIRS) {
1904
- const configDir = path6.join(rootDir, dir);
1907
+ const configDir = path5.join(rootDir, dir);
1905
1908
  if (await pathKind(configDir) === "directory") {
1906
1909
  directories.push(dir);
1907
1910
  await collectHostSubtree(rootDir, configDir, directories, files);
1908
1911
  }
1909
1912
  }
1910
1913
  for (const name of PI_CONTEXT_FILENAMES) {
1911
- if (await pathKind(path6.join(rootDir, name)) === "file") {
1914
+ if (await pathKind(path5.join(rootDir, name)) === "file") {
1912
1915
  files.push(name);
1913
1916
  }
1914
1917
  }
@@ -1920,10 +1923,10 @@ function buildRequiredDirectories(remoteDirectories, remoteFiles) {
1920
1923
  directories.add(normalizeRelativePath(directory));
1921
1924
  }
1922
1925
  for (const file of remoteFiles) {
1923
- let current = path6.dirname(normalizeRelativePath(file.relativePath));
1924
- while (current !== "." && current !== path6.sep && current.length > 0) {
1926
+ let current = path5.dirname(normalizeRelativePath(file.relativePath));
1927
+ while (current !== "." && current !== path5.sep && current.length > 0) {
1925
1928
  directories.add(current);
1926
- current = path6.dirname(current);
1929
+ current = path5.dirname(current);
1927
1930
  }
1928
1931
  }
1929
1932
  return directories;
@@ -1944,12 +1947,12 @@ async function syncHostWorkspaceFromSandbox(args) {
1944
1947
  );
1945
1948
  for (const relativePath of hostEntries.files) {
1946
1949
  if (!remoteFiles.has(relativePath)) {
1947
- await rm(path6.join(hostWorkDir, relativePath), { force: true });
1950
+ await rm(path5.join(hostWorkDir, relativePath), { force: true });
1948
1951
  }
1949
1952
  }
1950
1953
  const removableDirectories = [...hostEntries.directories].filter((p) => !requiredDirectories.has(p)).sort((a, b) => b.length - a.length);
1951
1954
  for (const relativePath of removableDirectories) {
1952
- await rm(path6.join(hostWorkDir, relativePath), {
1955
+ await rm(path5.join(hostWorkDir, relativePath), {
1953
1956
  recursive: true,
1954
1957
  force: true
1955
1958
  });
@@ -1957,7 +1960,7 @@ async function syncHostWorkspaceFromSandbox(args) {
1957
1960
  for (const relativePath of [...requiredDirectories].sort(
1958
1961
  (a, b) => a.length - b.length
1959
1962
  )) {
1960
- await mkdir2(path6.join(hostWorkDir, relativePath), { recursive: true });
1963
+ await mkdir2(path5.join(hostWorkDir, relativePath), { recursive: true });
1961
1964
  }
1962
1965
  for (let offset = 0; offset < remoteEntries.files.length; offset += ARCHIVE_BATCH_SIZE) {
1963
1966
  const batch = remoteEntries.files.slice(
@@ -1979,7 +1982,7 @@ async function syncHostWorkspaceFromSandbox(args) {
1979
1982
  }
1980
1983
  content = Buffer.from(bytes);
1981
1984
  }
1982
- const hostPath = path6.join(hostWorkDir, relativePath);
1985
+ const hostPath = path5.join(hostWorkDir, relativePath);
1983
1986
  let shouldWrite = true;
1984
1987
  try {
1985
1988
  const existing = await readFile2(hostPath);
@@ -1988,7 +1991,7 @@ async function syncHostWorkspaceFromSandbox(args) {
1988
1991
  shouldWrite = true;
1989
1992
  }
1990
1993
  if (shouldWrite) {
1991
- await mkdir2(path6.dirname(hostPath), { recursive: true });
1994
+ await mkdir2(path5.dirname(hostPath), { recursive: true });
1992
1995
  await writeFile2(hostPath, content);
1993
1996
  }
1994
1997
  }
@@ -2000,8 +2003,8 @@ var HARNESS_ID2 = "pi";
2000
2003
  var PI_MCP_ADAPTER_PACKAGE = "pi-mcp-adapter";
2001
2004
  var parkedPiSessions = /* @__PURE__ */ new Map();
2002
2005
  function isWithinDirectory(parent, child) {
2003
- const rel = path7.relative(parent, child);
2004
- return rel === "" || !rel.startsWith("..") && !path7.isAbsolute(rel);
2006
+ const rel = path6.relative(parent, child);
2007
+ return rel === "" || !rel.startsWith("..") && !path6.isAbsolute(rel);
2005
2008
  }
2006
2009
  function isWithinWorkspace(candidate, sessionWorkDir, hostWorkDir) {
2007
2010
  return isWithinDirectory(sessionWorkDir, candidate) || isWithinDirectory(hostWorkDir, candidate);
@@ -2012,8 +2015,8 @@ function createHarnessPiSkills({
2012
2015
  }) {
2013
2016
  return skills.map((skill) => {
2014
2017
  const name = safePiMetadataSegment(skill.name, "skill");
2015
- const baseDir = path7.posix.join(sandboxSkillRootDir, name);
2016
- const filePath = path7.posix.join(baseDir, "SKILL.md");
2018
+ const baseDir = path6.posix.join(sandboxSkillRootDir, name);
2019
+ const filePath = path6.posix.join(baseDir, "SKILL.md");
2017
2020
  return {
2018
2021
  name: skill.name,
2019
2022
  description: skill.description,
@@ -2083,10 +2086,10 @@ async function createPiSession(input) {
2083
2086
  }
2084
2087
  }
2085
2088
  const safeSessionId = input.sessionId.replace(/[\\/: ]/g, "-");
2086
- const hostRoot = path7.join(tmpdir(), "ai-sdk-harness", "pi", safeSessionId);
2087
- const hostWorkDir = path7.join(hostRoot, "workspace");
2088
- const hostAgentDir = path7.join(hostRoot, "agent");
2089
- const hostSessionDir = path7.join(hostRoot, "sessions");
2089
+ const hostRoot = path6.join(tmpdir(), "ai-sdk-harness", "pi", safeSessionId);
2090
+ const hostWorkDir = path6.join(hostRoot, "workspace");
2091
+ const hostAgentDir = path6.join(hostRoot, "agent");
2092
+ const hostSessionDir = path6.join(hostRoot, "sessions");
2090
2093
  const sessionWorkDir = input.sessionWorkDir;
2091
2094
  await mkdir3(hostWorkDir, { recursive: true });
2092
2095
  await mkdir3(hostAgentDir, { recursive: true });
@@ -2104,7 +2107,7 @@ async function createPiSession(input) {
2104
2107
  sessionId: input.sessionId
2105
2108
  });
2106
2109
  const permissionMode = input.permissionMode ?? "allow-all";
2107
- const sandboxSkillRootDir = path7.posix.join(
2110
+ const sandboxSkillRootDir = path6.posix.join(
2108
2111
  sandboxHomeDir,
2109
2112
  ".agents",
2110
2113
  "skills"
@@ -2138,8 +2141,8 @@ async function createPiSession(input) {
2138
2141
  const agentDir = input.agentDir ?? hostAgentDir;
2139
2142
  const modelRuntime = await createPiModelRuntime({
2140
2143
  auth: input.settings.auth,
2141
- authPath: path7.join(agentDir, "auth.json"),
2142
- modelsPath: path7.join(agentDir, "models.json")
2144
+ authPath: path6.join(agentDir, "auth.json"),
2145
+ modelsPath: path6.join(agentDir, "models.json")
2143
2146
  });
2144
2147
  const modelRegistry = new ModelRegistry(modelRuntime);
2145
2148
  const settingsManager = input.agentDir != null ? SettingsManager.create(hostWorkDir, agentDir) : SettingsManager.inMemory();
@@ -2154,7 +2157,8 @@ async function createPiSession(input) {
2154
2157
  modelRegistry,
2155
2158
  modelRuntime
2156
2159
  },
2157
- clientApp: input.clientApp
2160
+ clientApp: input.clientApp,
2161
+ headers: input.settings.headers
2158
2162
  });
2159
2163
  const resolveModel = createPiModelResolver({
2160
2164
  modelRegistry,
@@ -2363,7 +2367,7 @@ async function createPiSession(input) {
2363
2367
  deliveredDanglingResults.clear();
2364
2368
  if (!sessionFileName) {
2365
2369
  sessionFileName = safePiSessionFileName(
2366
- path7.basename(resumeSessionFilePath)
2370
+ path6.basename(resumeSessionFilePath)
2367
2371
  );
2368
2372
  }
2369
2373
  return true;
@@ -2573,7 +2577,7 @@ async function createPiSession(input) {
2573
2577
  }
2574
2578
  const candidatePath = sessionManager.getSessionFile();
2575
2579
  if (candidatePath) {
2576
- sessionFileName = safePiSessionFileName(path7.basename(candidatePath));
2580
+ sessionFileName = safePiSessionFileName(path6.basename(candidatePath));
2577
2581
  }
2578
2582
  translatorState = createPiTranslatorState({
2579
2583
  builtinToolNames: builtinNames,
@@ -2598,11 +2602,14 @@ async function createPiSession(input) {
2598
2602
  if (stopped) {
2599
2603
  throw new Error("Pi session has been stopped.");
2600
2604
  }
2601
- const skillWriteResult = await writePiSkills({
2605
+ const skillWriteResult = await writeSkills({
2602
2606
  sandbox: toolSafeSandboxSession,
2603
- sandboxHomeDir,
2607
+ homePath: sandboxHomeDir,
2608
+ skillsDir: ".agents/skills",
2604
2609
  skills: turnOpts.skills,
2605
- abortSignal: turnOpts.abortSignal
2610
+ abortSignal: turnOpts.abortSignal,
2611
+ invalidSkillNameMessage: ({ name }) => `Invalid Pi skill name: ${name}`,
2612
+ invalidSkillFilePathMessage: ({ skillName, filePath }) => `Invalid Pi skill file path for ${skillName}: ${filePath}`
2606
2613
  });
2607
2614
  harnessSkills = createHarnessPiSkills({
2608
2615
  skills: turnOpts.skills,
@@ -3272,7 +3279,8 @@ function createPi(settings = {}) {
3272
3279
  ...settings.model == null ? {} : { model: settings.model },
3273
3280
  ...settings.thinkingLevel ? { thinkingLevel: settings.thinkingLevel } : {},
3274
3281
  ...settings.mcpServers ? { mcpServers: settings.mcpServers } : {},
3275
- ...settings.extensionFactories ? { extensionFactories: settings.extensionFactories } : {}
3282
+ ...settings.extensionFactories ? { extensionFactories: settings.extensionFactories } : {},
3283
+ ...startOpts.headers ? { headers: startOpts.headers } : {}
3276
3284
  },
3277
3285
  clientApp: PI_CLIENT_APP,
3278
3286
  isResume: lifecycleState != null,