@ai-sdk/harness-pi 1.0.103 → 1.0.105
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 +23 -0
- package/dist/index.js +137 -98
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/pi-auth.ts +23 -2
- package/src/pi-harness.ts +1 -0
- package/src/pi-session.ts +75 -25
- package/src/pi-skills.ts +0 -25
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @ai-sdk/harness-pi
|
|
2
2
|
|
|
3
|
+
## 1.0.105
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- a514695: fix(harness-pi): let extensions read host-backed session workspaces
|
|
8
|
+
- c359fc0: fix(harness-pi): expose tools registered by inline extensions to models
|
|
9
|
+
- Updated dependencies [9e1d1b2]
|
|
10
|
+
- Updated dependencies [a495511]
|
|
11
|
+
- @ai-sdk/provider-utils@5.0.37
|
|
12
|
+
- @ai-sdk/harness@1.0.103
|
|
13
|
+
|
|
14
|
+
## 1.0.104
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- eeed977: feat(harness): allow passing arbitrary headers with inference requests via `headers` property in `HarnessAgentSettings`
|
|
19
|
+
- a39c8bf: chore(harness): clarify `writeSkills` helper intent to require materializing skills in HOME directory
|
|
20
|
+
- Updated dependencies [fe86f8f]
|
|
21
|
+
- Updated dependencies [255cccf]
|
|
22
|
+
- Updated dependencies [eeed977]
|
|
23
|
+
- Updated dependencies [a39c8bf]
|
|
24
|
+
- @ai-sdk/harness@1.0.102
|
|
25
|
+
|
|
3
26
|
## 1.0.103
|
|
4
27
|
|
|
5
28
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -111,16 +111,18 @@ import {
|
|
|
111
111
|
SessionManager,
|
|
112
112
|
SettingsManager
|
|
113
113
|
} from "@earendil-works/pi-coding-agent";
|
|
114
|
-
import {
|
|
114
|
+
import { randomUUID } from "crypto";
|
|
115
|
+
import { mkdir as mkdir3, rm as rm2, writeFile as writeFile3 } from "fs/promises";
|
|
115
116
|
import { tmpdir } from "os";
|
|
116
|
-
import
|
|
117
|
+
import path6 from "path";
|
|
117
118
|
import { Type as Type2 } from "typebox";
|
|
118
119
|
import {
|
|
119
120
|
HarnessCapabilityUnsupportedError as HarnessCapabilityUnsupportedError2
|
|
120
121
|
} from "@ai-sdk/harness";
|
|
121
122
|
import {
|
|
122
123
|
getRestrictedSandboxSession,
|
|
123
|
-
resolveSandboxHomeDir
|
|
124
|
+
resolveSandboxHomeDir,
|
|
125
|
+
writeSkills
|
|
124
126
|
} from "@ai-sdk/harness/utils";
|
|
125
127
|
|
|
126
128
|
// src/pi-auth.ts
|
|
@@ -134,7 +136,7 @@ import {
|
|
|
134
136
|
import { access } from "fs/promises";
|
|
135
137
|
|
|
136
138
|
// src/version.ts
|
|
137
|
-
var VERSION = true ? "1.0.
|
|
139
|
+
var VERSION = true ? "1.0.105" : "0.0.0-test";
|
|
138
140
|
|
|
139
141
|
// src/pi-auth.ts
|
|
140
142
|
var DEFAULT_GATEWAY_BASE_URL = "https://ai-gateway.vercel.sh";
|
|
@@ -242,13 +244,15 @@ async function createPiModelRuntime({
|
|
|
242
244
|
function createGatewayProviderConfig({
|
|
243
245
|
apiKey,
|
|
244
246
|
baseUrl,
|
|
245
|
-
clientApp
|
|
247
|
+
clientApp,
|
|
248
|
+
headers
|
|
246
249
|
}) {
|
|
247
250
|
return {
|
|
248
251
|
apiKey,
|
|
249
252
|
baseUrl,
|
|
250
253
|
authHeader: true,
|
|
251
254
|
headers: {
|
|
255
|
+
...headers,
|
|
252
256
|
"User-Agent": clientApp,
|
|
253
257
|
"x-client-app": clientApp
|
|
254
258
|
}
|
|
@@ -335,7 +339,8 @@ async function registerPiProviders({
|
|
|
335
339
|
options,
|
|
336
340
|
resolvedEnv,
|
|
337
341
|
registries,
|
|
338
|
-
clientApp = HARNESS_CLIENT_APP
|
|
342
|
+
clientApp = HARNESS_CLIENT_APP,
|
|
343
|
+
headers
|
|
339
344
|
}) {
|
|
340
345
|
const suppliedEnvironment = isHarnessAuthenticationEnvironment(options);
|
|
341
346
|
const authenticationEnvironment = suppliedEnvironment ? options : process.env;
|
|
@@ -346,7 +351,8 @@ async function registerPiProviders({
|
|
|
346
351
|
await registerCustomProviders({
|
|
347
352
|
customEnv: { ...pickOpenAIEnv(authenticationEnvironment), ...env },
|
|
348
353
|
registries,
|
|
349
|
-
clientApp
|
|
354
|
+
clientApp,
|
|
355
|
+
headers
|
|
350
356
|
});
|
|
351
357
|
return;
|
|
352
358
|
}
|
|
@@ -355,7 +361,8 @@ async function registerPiProviders({
|
|
|
355
361
|
await registerCustomProviders({
|
|
356
362
|
customEnv: { ...pickAnthropicEnv(authenticationEnvironment), ...env },
|
|
357
363
|
registries,
|
|
358
|
-
clientApp
|
|
364
|
+
clientApp,
|
|
365
|
+
headers
|
|
359
366
|
});
|
|
360
367
|
return;
|
|
361
368
|
}
|
|
@@ -364,7 +371,8 @@ async function registerPiProviders({
|
|
|
364
371
|
await registerCustomProviders({
|
|
365
372
|
customEnv: { ...pickProviderEnv(authenticationEnvironment), ...env },
|
|
366
373
|
registries,
|
|
367
|
-
clientApp
|
|
374
|
+
clientApp,
|
|
375
|
+
headers
|
|
368
376
|
});
|
|
369
377
|
return;
|
|
370
378
|
}
|
|
@@ -382,7 +390,8 @@ async function registerPiProviders({
|
|
|
382
390
|
config: createGatewayProviderConfig({
|
|
383
391
|
apiKey: gatewayApiKey,
|
|
384
392
|
baseUrl: gatewayBaseUrl,
|
|
385
|
-
clientApp
|
|
393
|
+
clientApp,
|
|
394
|
+
headers
|
|
386
395
|
})
|
|
387
396
|
});
|
|
388
397
|
return;
|
|
@@ -402,7 +411,8 @@ async function registerPiProviders({
|
|
|
402
411
|
config: createGatewayProviderConfig({
|
|
403
412
|
apiKey: gatewayApiKey,
|
|
404
413
|
baseUrl: gatewayBaseUrl,
|
|
405
|
-
clientApp
|
|
414
|
+
clientApp,
|
|
415
|
+
headers
|
|
406
416
|
})
|
|
407
417
|
});
|
|
408
418
|
return;
|
|
@@ -411,7 +421,8 @@ async function registerPiProviders({
|
|
|
411
421
|
await registerCustomProviders({
|
|
412
422
|
customEnv: { ...pickProviderEnv(authenticationEnvironment), ...env },
|
|
413
423
|
registries,
|
|
414
|
-
clientApp
|
|
424
|
+
clientApp,
|
|
425
|
+
headers
|
|
415
426
|
});
|
|
416
427
|
return;
|
|
417
428
|
}
|
|
@@ -444,7 +455,8 @@ function pickProviderEnv(env) {
|
|
|
444
455
|
async function registerCustomProviders({
|
|
445
456
|
customEnv,
|
|
446
457
|
registries,
|
|
447
|
-
clientApp
|
|
458
|
+
clientApp,
|
|
459
|
+
headers
|
|
448
460
|
}) {
|
|
449
461
|
const gatewayKey = customEnv.AI_GATEWAY_API_KEY;
|
|
450
462
|
if (gatewayKey) {
|
|
@@ -456,7 +468,8 @@ async function registerCustomProviders({
|
|
|
456
468
|
config: createGatewayProviderConfig({
|
|
457
469
|
apiKey: gatewayKey,
|
|
458
470
|
baseUrl,
|
|
459
|
-
clientApp
|
|
471
|
+
clientApp,
|
|
472
|
+
headers
|
|
460
473
|
})
|
|
461
474
|
});
|
|
462
475
|
}
|
|
@@ -469,7 +482,8 @@ async function registerCustomProviders({
|
|
|
469
482
|
config: {
|
|
470
483
|
apiKey: customEnv.OPENAI_API_KEY,
|
|
471
484
|
baseUrl,
|
|
472
|
-
authHeader: true
|
|
485
|
+
authHeader: true,
|
|
486
|
+
...headers ? { headers } : {}
|
|
473
487
|
}
|
|
474
488
|
});
|
|
475
489
|
}
|
|
@@ -482,9 +496,12 @@ async function registerCustomProviders({
|
|
|
482
496
|
config: {
|
|
483
497
|
apiKey: customEnv.ANTHROPIC_API_KEY,
|
|
484
498
|
baseUrl,
|
|
485
|
-
...customEnv.ANTHROPIC_AUTH_TOKEN ? {
|
|
499
|
+
...headers || customEnv.ANTHROPIC_AUTH_TOKEN ? {
|
|
486
500
|
headers: {
|
|
487
|
-
|
|
501
|
+
...headers,
|
|
502
|
+
...customEnv.ANTHROPIC_AUTH_TOKEN ? {
|
|
503
|
+
authorization: `Bearer ${customEnv.ANTHROPIC_AUTH_TOKEN}`
|
|
504
|
+
} : {}
|
|
488
505
|
}
|
|
489
506
|
} : {}
|
|
490
507
|
}
|
|
@@ -510,7 +527,8 @@ async function registerCustomProviders({
|
|
|
510
527
|
config: {
|
|
511
528
|
apiKey,
|
|
512
529
|
baseUrl,
|
|
513
|
-
authHeader: true
|
|
530
|
+
authHeader: true,
|
|
531
|
+
...headers ? { headers } : {}
|
|
514
532
|
}
|
|
515
533
|
});
|
|
516
534
|
}
|
|
@@ -839,7 +857,7 @@ function createPiRemoteOps(options) {
|
|
|
839
857
|
}
|
|
840
858
|
return Buffer.from(bytes);
|
|
841
859
|
};
|
|
842
|
-
const
|
|
860
|
+
const writeFile4 = async (inputPath, content) => {
|
|
843
861
|
const remotePath = options.paths.toSandboxPath(inputPath);
|
|
844
862
|
const resolvedPath = await resolveWritableSandboxPath(
|
|
845
863
|
remotePath,
|
|
@@ -865,7 +883,7 @@ function createPiRemoteOps(options) {
|
|
|
865
883
|
const updated = `${current.slice(0, index)}${newText}${current.slice(
|
|
866
884
|
index + oldText.length
|
|
867
885
|
)}`;
|
|
868
|
-
await
|
|
886
|
+
await writeFile4(inputPath, updated);
|
|
869
887
|
return updated;
|
|
870
888
|
};
|
|
871
889
|
const listDirectory = async (inputPath = ".", limit = 500) => {
|
|
@@ -955,7 +973,7 @@ function createPiRemoteOps(options) {
|
|
|
955
973
|
return {
|
|
956
974
|
paths: options.paths,
|
|
957
975
|
readBuffer,
|
|
958
|
-
writeFile:
|
|
976
|
+
writeFile: writeFile4,
|
|
959
977
|
editFile,
|
|
960
978
|
listDirectory,
|
|
961
979
|
findFiles,
|
|
@@ -986,20 +1004,6 @@ function createPiRemoteOps(options) {
|
|
|
986
1004
|
};
|
|
987
1005
|
}
|
|
988
1006
|
|
|
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
1007
|
// src/pi-translate.ts
|
|
1004
1008
|
import { randomBytes } from "crypto";
|
|
1005
1009
|
import { secureJsonParse } from "@ai-sdk/provider-utils";
|
|
@@ -1362,7 +1366,7 @@ function toolSpecToTypeBoxParameters(jsonSchema) {
|
|
|
1362
1366
|
// src/pi-workspace-vfs.ts
|
|
1363
1367
|
import fs from "fs";
|
|
1364
1368
|
import { syncBuiltinESMExports } from "module";
|
|
1365
|
-
import
|
|
1369
|
+
import path4 from "path";
|
|
1366
1370
|
var mountedRoots = /* @__PURE__ */ new Map();
|
|
1367
1371
|
var mutableFs = fs;
|
|
1368
1372
|
var mutableFsPromises = fs.promises;
|
|
@@ -1392,11 +1396,11 @@ var originalFsPromises = {
|
|
|
1392
1396
|
writeFile: fs.promises.writeFile.bind(fs.promises)
|
|
1393
1397
|
};
|
|
1394
1398
|
function isInsidePath2(parent, candidate) {
|
|
1395
|
-
const relative =
|
|
1396
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
1399
|
+
const relative = path4.relative(parent, candidate);
|
|
1400
|
+
return relative === "" || !relative.startsWith("..") && !path4.isAbsolute(relative);
|
|
1397
1401
|
}
|
|
1398
1402
|
function resolveAbsolutePath(inputPath) {
|
|
1399
|
-
return
|
|
1403
|
+
return path4.isAbsolute(inputPath) ? path4.normalize(inputPath) : path4.resolve(inputPath);
|
|
1400
1404
|
}
|
|
1401
1405
|
function findMountedRoot(inputPath) {
|
|
1402
1406
|
const resolvedPath = resolveAbsolutePath(inputPath);
|
|
@@ -1417,26 +1421,26 @@ function mapToBackingPath(inputPath) {
|
|
|
1417
1421
|
return null;
|
|
1418
1422
|
}
|
|
1419
1423
|
const resolvedPath = resolveAbsolutePath(inputPath);
|
|
1420
|
-
const relativePath =
|
|
1421
|
-
return relativePath ?
|
|
1424
|
+
const relativePath = path4.relative(mountedRoot.mountPoint, resolvedPath);
|
|
1425
|
+
return relativePath ? path4.join(mountedRoot.backingRoot, relativePath) : mountedRoot.backingRoot;
|
|
1422
1426
|
}
|
|
1423
1427
|
function mapRealpathResult(inputPath, result) {
|
|
1424
1428
|
const mountedRoot = findMountedRoot(inputPath);
|
|
1425
1429
|
if (!mountedRoot) {
|
|
1426
1430
|
return result;
|
|
1427
1431
|
}
|
|
1428
|
-
let normalizedBackingRoot =
|
|
1432
|
+
let normalizedBackingRoot = path4.resolve(mountedRoot.backingRoot);
|
|
1429
1433
|
try {
|
|
1430
1434
|
const realpath = originalFsSyncMethods.realpathSync.native ?? originalFsSyncMethods.realpathSync;
|
|
1431
|
-
normalizedBackingRoot =
|
|
1435
|
+
normalizedBackingRoot = path4.resolve(realpath(mountedRoot.backingRoot));
|
|
1432
1436
|
} catch {
|
|
1433
1437
|
}
|
|
1434
|
-
const normalizedResult =
|
|
1438
|
+
const normalizedResult = path4.resolve(result);
|
|
1435
1439
|
if (!isInsidePath2(normalizedBackingRoot, normalizedResult)) {
|
|
1436
1440
|
return result;
|
|
1437
1441
|
}
|
|
1438
|
-
const relativePath =
|
|
1439
|
-
return relativePath ?
|
|
1442
|
+
const relativePath = path4.relative(normalizedBackingRoot, normalizedResult);
|
|
1443
|
+
return relativePath ? path4.join(mountedRoot.mountPoint, relativePath) : mountedRoot.mountPoint;
|
|
1440
1444
|
}
|
|
1441
1445
|
function mapRenamePaths(sourcePath, destinationPath) {
|
|
1442
1446
|
const sourceRoot = findMountedRoot(sourcePath);
|
|
@@ -1631,8 +1635,8 @@ var PiWorkspaceVfs = class {
|
|
|
1631
1635
|
if (this.backingRoot === backingRoot && this.mountPoint === mountPoint) {
|
|
1632
1636
|
return;
|
|
1633
1637
|
}
|
|
1634
|
-
const resolvedBackingRoot =
|
|
1635
|
-
const resolvedMountPoint =
|
|
1638
|
+
const resolvedBackingRoot = path4.resolve(backingRoot);
|
|
1639
|
+
const resolvedMountPoint = path4.resolve(mountPoint);
|
|
1636
1640
|
if (this.mountPoint) {
|
|
1637
1641
|
this.disposeMount();
|
|
1638
1642
|
}
|
|
@@ -1661,7 +1665,7 @@ import {
|
|
|
1661
1665
|
stat,
|
|
1662
1666
|
writeFile as writeFile2
|
|
1663
1667
|
} from "fs/promises";
|
|
1664
|
-
import
|
|
1668
|
+
import path5 from "path";
|
|
1665
1669
|
import { gunzipSync } from "zlib";
|
|
1666
1670
|
import { shellQuote as shellQuote2 } from "@ai-sdk/harness/utils";
|
|
1667
1671
|
var PI_CONFIG_DIRS = [".pi", ".agents"];
|
|
@@ -1669,9 +1673,9 @@ var PI_CONTEXT_FILENAMES = ["AGENTS.md", "AGENTS.MD"];
|
|
|
1669
1673
|
var ARCHIVE_BATCH_SIZE = 300;
|
|
1670
1674
|
var TAR_BLOCK_SIZE = 512;
|
|
1671
1675
|
function normalizeRelativePath(inputPath) {
|
|
1672
|
-
const normalized = inputPath.split(
|
|
1673
|
-
const relative =
|
|
1674
|
-
if (relative === "" || relative === "." ||
|
|
1676
|
+
const normalized = inputPath.split(path5.posix.sep).join(path5.sep);
|
|
1677
|
+
const relative = path5.normalize(normalized);
|
|
1678
|
+
if (relative === "" || relative === "." || path5.isAbsolute(relative) || relative === ".." || relative.startsWith(`..${path5.sep}`)) {
|
|
1675
1679
|
throw new Error(
|
|
1676
1680
|
`Sandbox workspace mirror received an invalid relative path: ${inputPath}`
|
|
1677
1681
|
);
|
|
@@ -1694,7 +1698,7 @@ async function listRemoteWorkspaceEntries(sandbox, sandboxWorkDir) {
|
|
|
1694
1698
|
];
|
|
1695
1699
|
const listCommand = [
|
|
1696
1700
|
`pi_config_sources=(${scopedPaths.map(
|
|
1697
|
-
(scopedPath) => shellQuote2(
|
|
1701
|
+
(scopedPath) => shellQuote2(path5.posix.join(sandboxWorkDir, scopedPath.slice(2)))
|
|
1698
1702
|
).join(" ")})`,
|
|
1699
1703
|
`pi_config_relatives=(${scopedPaths.map((scopedPath) => shellQuote2(scopedPath.slice(2))).join(" ")})`,
|
|
1700
1704
|
`pi_config_ancestors=(${scopedPaths.map(() => "''").join(" ")})`,
|
|
@@ -1887,8 +1891,8 @@ async function collectHostSubtree(rootDir, currentDir, directories, files) {
|
|
|
1887
1891
|
const entries = await readdir(currentDir, { withFileTypes: true });
|
|
1888
1892
|
for (const entry of entries) {
|
|
1889
1893
|
if (entry.isSymbolicLink()) continue;
|
|
1890
|
-
const absolutePath =
|
|
1891
|
-
const relativePath =
|
|
1894
|
+
const absolutePath = path5.join(currentDir, entry.name);
|
|
1895
|
+
const relativePath = path5.relative(rootDir, absolutePath);
|
|
1892
1896
|
if (entry.isDirectory()) {
|
|
1893
1897
|
directories.push(relativePath);
|
|
1894
1898
|
await collectHostSubtree(rootDir, absolutePath, directories, files);
|
|
@@ -1901,14 +1905,14 @@ async function collectHostScopedEntries(rootDir) {
|
|
|
1901
1905
|
const directories = [];
|
|
1902
1906
|
const files = [];
|
|
1903
1907
|
for (const dir of PI_CONFIG_DIRS) {
|
|
1904
|
-
const configDir =
|
|
1908
|
+
const configDir = path5.join(rootDir, dir);
|
|
1905
1909
|
if (await pathKind(configDir) === "directory") {
|
|
1906
1910
|
directories.push(dir);
|
|
1907
1911
|
await collectHostSubtree(rootDir, configDir, directories, files);
|
|
1908
1912
|
}
|
|
1909
1913
|
}
|
|
1910
1914
|
for (const name of PI_CONTEXT_FILENAMES) {
|
|
1911
|
-
if (await pathKind(
|
|
1915
|
+
if (await pathKind(path5.join(rootDir, name)) === "file") {
|
|
1912
1916
|
files.push(name);
|
|
1913
1917
|
}
|
|
1914
1918
|
}
|
|
@@ -1920,10 +1924,10 @@ function buildRequiredDirectories(remoteDirectories, remoteFiles) {
|
|
|
1920
1924
|
directories.add(normalizeRelativePath(directory));
|
|
1921
1925
|
}
|
|
1922
1926
|
for (const file of remoteFiles) {
|
|
1923
|
-
let current =
|
|
1924
|
-
while (current !== "." && current !==
|
|
1927
|
+
let current = path5.dirname(normalizeRelativePath(file.relativePath));
|
|
1928
|
+
while (current !== "." && current !== path5.sep && current.length > 0) {
|
|
1925
1929
|
directories.add(current);
|
|
1926
|
-
current =
|
|
1930
|
+
current = path5.dirname(current);
|
|
1927
1931
|
}
|
|
1928
1932
|
}
|
|
1929
1933
|
return directories;
|
|
@@ -1944,12 +1948,12 @@ async function syncHostWorkspaceFromSandbox(args) {
|
|
|
1944
1948
|
);
|
|
1945
1949
|
for (const relativePath of hostEntries.files) {
|
|
1946
1950
|
if (!remoteFiles.has(relativePath)) {
|
|
1947
|
-
await rm(
|
|
1951
|
+
await rm(path5.join(hostWorkDir, relativePath), { force: true });
|
|
1948
1952
|
}
|
|
1949
1953
|
}
|
|
1950
1954
|
const removableDirectories = [...hostEntries.directories].filter((p) => !requiredDirectories.has(p)).sort((a, b) => b.length - a.length);
|
|
1951
1955
|
for (const relativePath of removableDirectories) {
|
|
1952
|
-
await rm(
|
|
1956
|
+
await rm(path5.join(hostWorkDir, relativePath), {
|
|
1953
1957
|
recursive: true,
|
|
1954
1958
|
force: true
|
|
1955
1959
|
});
|
|
@@ -1957,7 +1961,7 @@ async function syncHostWorkspaceFromSandbox(args) {
|
|
|
1957
1961
|
for (const relativePath of [...requiredDirectories].sort(
|
|
1958
1962
|
(a, b) => a.length - b.length
|
|
1959
1963
|
)) {
|
|
1960
|
-
await mkdir2(
|
|
1964
|
+
await mkdir2(path5.join(hostWorkDir, relativePath), { recursive: true });
|
|
1961
1965
|
}
|
|
1962
1966
|
for (let offset = 0; offset < remoteEntries.files.length; offset += ARCHIVE_BATCH_SIZE) {
|
|
1963
1967
|
const batch = remoteEntries.files.slice(
|
|
@@ -1979,7 +1983,7 @@ async function syncHostWorkspaceFromSandbox(args) {
|
|
|
1979
1983
|
}
|
|
1980
1984
|
content = Buffer.from(bytes);
|
|
1981
1985
|
}
|
|
1982
|
-
const hostPath =
|
|
1986
|
+
const hostPath = path5.join(hostWorkDir, relativePath);
|
|
1983
1987
|
let shouldWrite = true;
|
|
1984
1988
|
try {
|
|
1985
1989
|
const existing = await readFile2(hostPath);
|
|
@@ -1988,7 +1992,7 @@ async function syncHostWorkspaceFromSandbox(args) {
|
|
|
1988
1992
|
shouldWrite = true;
|
|
1989
1993
|
}
|
|
1990
1994
|
if (shouldWrite) {
|
|
1991
|
-
await mkdir2(
|
|
1995
|
+
await mkdir2(path5.dirname(hostPath), { recursive: true });
|
|
1992
1996
|
await writeFile2(hostPath, content);
|
|
1993
1997
|
}
|
|
1994
1998
|
}
|
|
@@ -2000,8 +2004,8 @@ var HARNESS_ID2 = "pi";
|
|
|
2000
2004
|
var PI_MCP_ADAPTER_PACKAGE = "pi-mcp-adapter";
|
|
2001
2005
|
var parkedPiSessions = /* @__PURE__ */ new Map();
|
|
2002
2006
|
function isWithinDirectory(parent, child) {
|
|
2003
|
-
const rel =
|
|
2004
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
2007
|
+
const rel = path6.relative(parent, child);
|
|
2008
|
+
return rel === "" || !rel.startsWith("..") && !path6.isAbsolute(rel);
|
|
2005
2009
|
}
|
|
2006
2010
|
function isWithinWorkspace(candidate, sessionWorkDir, hostWorkDir) {
|
|
2007
2011
|
return isWithinDirectory(sessionWorkDir, candidate) || isWithinDirectory(hostWorkDir, candidate);
|
|
@@ -2012,8 +2016,8 @@ function createHarnessPiSkills({
|
|
|
2012
2016
|
}) {
|
|
2013
2017
|
return skills.map((skill) => {
|
|
2014
2018
|
const name = safePiMetadataSegment(skill.name, "skill");
|
|
2015
|
-
const baseDir =
|
|
2016
|
-
const filePath =
|
|
2019
|
+
const baseDir = path6.posix.join(sandboxSkillRootDir, name);
|
|
2020
|
+
const filePath = path6.posix.join(baseDir, "SKILL.md");
|
|
2017
2021
|
return {
|
|
2018
2022
|
name: skill.name,
|
|
2019
2023
|
description: skill.description,
|
|
@@ -2071,6 +2075,26 @@ function resolveActivePiBuiltinNames(toolFiltering) {
|
|
|
2071
2075
|
(native) => !toolFiltering.toolNames.includes(NATIVE_TO_COMMON[native] ?? native)
|
|
2072
2076
|
);
|
|
2073
2077
|
}
|
|
2078
|
+
async function isWorkspaceAvailableOnHost({
|
|
2079
|
+
sandbox,
|
|
2080
|
+
sessionWorkDir
|
|
2081
|
+
}) {
|
|
2082
|
+
const probePath = path6.join(
|
|
2083
|
+
sessionWorkDir,
|
|
2084
|
+
`.ai-sdk-harness-pi-${randomUUID()}`
|
|
2085
|
+
);
|
|
2086
|
+
const probeContent = randomUUID();
|
|
2087
|
+
try {
|
|
2088
|
+
await writeFile3(probePath, probeContent, { flag: "wx" });
|
|
2089
|
+
const sandboxContent = await sandbox.readBinaryFile({ path: probePath });
|
|
2090
|
+
return sandboxContent != null && Buffer.from(sandboxContent).equals(Buffer.from(probeContent));
|
|
2091
|
+
} catch {
|
|
2092
|
+
return false;
|
|
2093
|
+
} finally {
|
|
2094
|
+
await rm2(probePath, { force: true }).catch(() => {
|
|
2095
|
+
});
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2074
2098
|
async function createPiSession(input) {
|
|
2075
2099
|
if (input.isResume) {
|
|
2076
2100
|
const parkedSession = parkedPiSessions.get(input.sessionId);
|
|
@@ -2083,17 +2107,21 @@ async function createPiSession(input) {
|
|
|
2083
2107
|
}
|
|
2084
2108
|
}
|
|
2085
2109
|
const safeSessionId = input.sessionId.replace(/[\\/: ]/g, "-");
|
|
2086
|
-
const hostRoot =
|
|
2087
|
-
const
|
|
2088
|
-
const
|
|
2089
|
-
const
|
|
2110
|
+
const hostRoot = path6.join(tmpdir(), "ai-sdk-harness", "pi", safeSessionId);
|
|
2111
|
+
const hostAgentDir = path6.join(hostRoot, "agent");
|
|
2112
|
+
const hostSessionDir = path6.join(hostRoot, "sessions");
|
|
2113
|
+
const toolSafeSandboxSession = getRestrictedSandboxSession(
|
|
2114
|
+
input.sandboxSession
|
|
2115
|
+
);
|
|
2090
2116
|
const sessionWorkDir = input.sessionWorkDir;
|
|
2117
|
+
const workspaceAvailableOnHost = await isWorkspaceAvailableOnHost({
|
|
2118
|
+
sandbox: toolSafeSandboxSession,
|
|
2119
|
+
sessionWorkDir
|
|
2120
|
+
});
|
|
2121
|
+
const hostWorkDir = workspaceAvailableOnHost ? path6.resolve(sessionWorkDir) : path6.join(hostRoot, "workspace");
|
|
2091
2122
|
await mkdir3(hostWorkDir, { recursive: true });
|
|
2092
2123
|
await mkdir3(hostAgentDir, { recursive: true });
|
|
2093
2124
|
await mkdir3(hostSessionDir, { recursive: true });
|
|
2094
|
-
const toolSafeSandboxSession = getRestrictedSandboxSession(
|
|
2095
|
-
input.sandboxSession
|
|
2096
|
-
);
|
|
2097
2125
|
const sandboxHomeDir = await resolveSandboxHomeDir({
|
|
2098
2126
|
sandbox: toolSafeSandboxSession,
|
|
2099
2127
|
...input.abortSignal ? { abortSignal: input.abortSignal } : {}
|
|
@@ -2104,7 +2132,7 @@ async function createPiSession(input) {
|
|
|
2104
2132
|
sessionId: input.sessionId
|
|
2105
2133
|
});
|
|
2106
2134
|
const permissionMode = input.permissionMode ?? "allow-all";
|
|
2107
|
-
const sandboxSkillRootDir =
|
|
2135
|
+
const sandboxSkillRootDir = path6.posix.join(
|
|
2108
2136
|
sandboxHomeDir,
|
|
2109
2137
|
".agents",
|
|
2110
2138
|
"skills"
|
|
@@ -2123,13 +2151,17 @@ async function createPiSession(input) {
|
|
|
2123
2151
|
...input.abortSignal ? { abortSignal: input.abortSignal } : {}
|
|
2124
2152
|
});
|
|
2125
2153
|
}
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2154
|
+
if (!workspaceAvailableOnHost) {
|
|
2155
|
+
await syncHostWorkspaceFromSandbox({
|
|
2156
|
+
sandbox: toolSafeSandboxSession,
|
|
2157
|
+
sandboxWorkDir: input.sessionWorkDir,
|
|
2158
|
+
hostWorkDir
|
|
2159
|
+
});
|
|
2160
|
+
}
|
|
2131
2161
|
const workspaceVfs = new PiWorkspaceVfs();
|
|
2132
|
-
|
|
2162
|
+
if (!workspaceAvailableOnHost) {
|
|
2163
|
+
workspaceVfs.mount(hostWorkDir, sessionWorkDir);
|
|
2164
|
+
}
|
|
2133
2165
|
const paths = createPiPathMapper({
|
|
2134
2166
|
hostWorkDir,
|
|
2135
2167
|
sandboxWorkDir: sessionWorkDir,
|
|
@@ -2138,8 +2170,8 @@ async function createPiSession(input) {
|
|
|
2138
2170
|
const agentDir = input.agentDir ?? hostAgentDir;
|
|
2139
2171
|
const modelRuntime = await createPiModelRuntime({
|
|
2140
2172
|
auth: input.settings.auth,
|
|
2141
|
-
authPath:
|
|
2142
|
-
modelsPath:
|
|
2173
|
+
authPath: path6.join(agentDir, "auth.json"),
|
|
2174
|
+
modelsPath: path6.join(agentDir, "models.json")
|
|
2143
2175
|
});
|
|
2144
2176
|
const modelRegistry = new ModelRegistry(modelRuntime);
|
|
2145
2177
|
const settingsManager = input.agentDir != null ? SettingsManager.create(hostWorkDir, agentDir) : SettingsManager.inMemory();
|
|
@@ -2154,7 +2186,8 @@ async function createPiSession(input) {
|
|
|
2154
2186
|
modelRegistry,
|
|
2155
2187
|
modelRuntime
|
|
2156
2188
|
},
|
|
2157
|
-
clientApp: input.clientApp
|
|
2189
|
+
clientApp: input.clientApp,
|
|
2190
|
+
headers: input.settings.headers
|
|
2158
2191
|
});
|
|
2159
2192
|
const resolveModel = createPiModelResolver({
|
|
2160
2193
|
modelRegistry,
|
|
@@ -2363,7 +2396,7 @@ async function createPiSession(input) {
|
|
|
2363
2396
|
deliveredDanglingResults.clear();
|
|
2364
2397
|
if (!sessionFileName) {
|
|
2365
2398
|
sessionFileName = safePiSessionFileName(
|
|
2366
|
-
|
|
2399
|
+
path6.basename(resumeSessionFilePath)
|
|
2367
2400
|
);
|
|
2368
2401
|
}
|
|
2369
2402
|
return true;
|
|
@@ -2563,7 +2596,7 @@ async function createPiSession(input) {
|
|
|
2563
2596
|
settingsManager,
|
|
2564
2597
|
resourceLoader,
|
|
2565
2598
|
customTools,
|
|
2566
|
-
...
|
|
2599
|
+
...hasExtensionFactories ? { noTools: "builtin" } : { tools: toolNames },
|
|
2567
2600
|
...input.settings.thinkingLevel ? { thinkingLevel: input.settings.thinkingLevel } : {},
|
|
2568
2601
|
...activeResolvedModel ? { model: activeResolvedModel } : {}
|
|
2569
2602
|
});
|
|
@@ -2573,7 +2606,7 @@ async function createPiSession(input) {
|
|
|
2573
2606
|
}
|
|
2574
2607
|
const candidatePath = sessionManager.getSessionFile();
|
|
2575
2608
|
if (candidatePath) {
|
|
2576
|
-
sessionFileName = safePiSessionFileName(
|
|
2609
|
+
sessionFileName = safePiSessionFileName(path6.basename(candidatePath));
|
|
2577
2610
|
}
|
|
2578
2611
|
translatorState = createPiTranslatorState({
|
|
2579
2612
|
builtinToolNames: builtinNames,
|
|
@@ -2598,11 +2631,14 @@ async function createPiSession(input) {
|
|
|
2598
2631
|
if (stopped) {
|
|
2599
2632
|
throw new Error("Pi session has been stopped.");
|
|
2600
2633
|
}
|
|
2601
|
-
const skillWriteResult = await
|
|
2634
|
+
const skillWriteResult = await writeSkills({
|
|
2602
2635
|
sandbox: toolSafeSandboxSession,
|
|
2603
|
-
sandboxHomeDir,
|
|
2636
|
+
homePath: sandboxHomeDir,
|
|
2637
|
+
skillsDir: ".agents/skills",
|
|
2604
2638
|
skills: turnOpts.skills,
|
|
2605
|
-
abortSignal: turnOpts.abortSignal
|
|
2639
|
+
abortSignal: turnOpts.abortSignal,
|
|
2640
|
+
invalidSkillNameMessage: ({ name }) => `Invalid Pi skill name: ${name}`,
|
|
2641
|
+
invalidSkillFilePathMessage: ({ skillName, filePath }) => `Invalid Pi skill file path for ${skillName}: ${filePath}`
|
|
2606
2642
|
});
|
|
2607
2643
|
harnessSkills = createHarnessPiSkills({
|
|
2608
2644
|
skills: turnOpts.skills,
|
|
@@ -2649,11 +2685,13 @@ async function createPiSession(input) {
|
|
|
2649
2685
|
await reloadResourcesOnly();
|
|
2650
2686
|
turnAbortController.signal.throwIfAborted();
|
|
2651
2687
|
}
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2688
|
+
if (!workspaceAvailableOnHost) {
|
|
2689
|
+
await syncHostWorkspaceFromSandbox({
|
|
2690
|
+
sandbox: toolSafeSandboxSession,
|
|
2691
|
+
sandboxWorkDir: input.sessionWorkDir,
|
|
2692
|
+
hostWorkDir
|
|
2693
|
+
});
|
|
2694
|
+
}
|
|
2657
2695
|
turnAbortController.signal.throwIfAborted();
|
|
2658
2696
|
translatorState = createPiTranslatorState({
|
|
2659
2697
|
builtinToolNames: [...PI_NATIVE_BUILTIN_NAMES],
|
|
@@ -3272,7 +3310,8 @@ function createPi(settings = {}) {
|
|
|
3272
3310
|
...settings.model == null ? {} : { model: settings.model },
|
|
3273
3311
|
...settings.thinkingLevel ? { thinkingLevel: settings.thinkingLevel } : {},
|
|
3274
3312
|
...settings.mcpServers ? { mcpServers: settings.mcpServers } : {},
|
|
3275
|
-
...settings.extensionFactories ? { extensionFactories: settings.extensionFactories } : {}
|
|
3313
|
+
...settings.extensionFactories ? { extensionFactories: settings.extensionFactories } : {},
|
|
3314
|
+
...startOpts.headers ? { headers: startOpts.headers } : {}
|
|
3276
3315
|
},
|
|
3277
3316
|
clientApp: PI_CLIENT_APP,
|
|
3278
3317
|
isResume: lifecycleState != null,
|