@ai-sdk/harness-pi 1.0.101 → 1.0.102
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 +8 -0
- package/dist/index.js +104 -20
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/pi-workspace-mirror.ts +157 -20
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @ai-sdk/harness-pi
|
|
2
2
|
|
|
3
|
+
## 1.0.102
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7c3211d: fix (harness-pi): transfer the workspace mirror as batched archives instead of one request per file
|
|
8
|
+
- Updated dependencies [0c37bf0]
|
|
9
|
+
- @ai-sdk/harness@1.0.100
|
|
10
|
+
|
|
3
11
|
## 1.0.101
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -134,7 +134,7 @@ import {
|
|
|
134
134
|
import { access } from "fs/promises";
|
|
135
135
|
|
|
136
136
|
// src/version.ts
|
|
137
|
-
var VERSION = true ? "1.0.
|
|
137
|
+
var VERSION = true ? "1.0.102" : "0.0.0-test";
|
|
138
138
|
|
|
139
139
|
// src/pi-auth.ts
|
|
140
140
|
var DEFAULT_GATEWAY_BASE_URL = "https://ai-gateway.vercel.sh";
|
|
@@ -1662,9 +1662,12 @@ import {
|
|
|
1662
1662
|
writeFile as writeFile2
|
|
1663
1663
|
} from "fs/promises";
|
|
1664
1664
|
import path6 from "path";
|
|
1665
|
+
import { gunzipSync } from "zlib";
|
|
1665
1666
|
import { shellQuote as shellQuote2 } from "@ai-sdk/harness/utils";
|
|
1666
1667
|
var PI_CONFIG_DIRS = [".pi", ".agents"];
|
|
1667
1668
|
var PI_CONTEXT_FILENAMES = ["AGENTS.md", "AGENTS.MD"];
|
|
1669
|
+
var ARCHIVE_BATCH_SIZE = 300;
|
|
1670
|
+
var TAR_BLOCK_SIZE = 512;
|
|
1668
1671
|
function normalizeRelativePath(inputPath) {
|
|
1669
1672
|
const normalized = inputPath.split(path6.posix.sep).join(path6.sep);
|
|
1670
1673
|
const relative = path6.normalize(normalized);
|
|
@@ -1802,6 +1805,74 @@ async function listRemoteWorkspaceEntries(sandbox, sandboxWorkDir) {
|
|
|
1802
1805
|
}
|
|
1803
1806
|
return { directories, files };
|
|
1804
1807
|
}
|
|
1808
|
+
function readTarString(header, offset, length) {
|
|
1809
|
+
const field = header.subarray(offset, offset + length);
|
|
1810
|
+
const end = field.indexOf(0);
|
|
1811
|
+
return field.subarray(0, end === -1 ? field.length : end).toString("utf8");
|
|
1812
|
+
}
|
|
1813
|
+
function parseTarFiles(archive) {
|
|
1814
|
+
const files = /* @__PURE__ */ new Map();
|
|
1815
|
+
let overrideName;
|
|
1816
|
+
let offset = 0;
|
|
1817
|
+
while (offset + TAR_BLOCK_SIZE <= archive.length) {
|
|
1818
|
+
const header = archive.subarray(offset, offset + TAR_BLOCK_SIZE);
|
|
1819
|
+
if (header.every((byte) => byte === 0)) break;
|
|
1820
|
+
const size = Number.parseInt(
|
|
1821
|
+
readTarString(header, 124, 12).trim() || "0",
|
|
1822
|
+
8
|
|
1823
|
+
);
|
|
1824
|
+
const typeFlag = String.fromCharCode(header[156]);
|
|
1825
|
+
const dataStart = offset + TAR_BLOCK_SIZE;
|
|
1826
|
+
const data = archive.subarray(dataStart, dataStart + size);
|
|
1827
|
+
offset = dataStart + Math.ceil(size / TAR_BLOCK_SIZE) * TAR_BLOCK_SIZE;
|
|
1828
|
+
if (typeFlag === "L") {
|
|
1829
|
+
overrideName = readTarString(data, 0, data.length);
|
|
1830
|
+
continue;
|
|
1831
|
+
}
|
|
1832
|
+
if (typeFlag === "x" || typeFlag === "X") {
|
|
1833
|
+
const pathRecord = data.toString("utf8").split("\n").map((record) => /^\d+ path=(.*)$/.exec(record)?.[1]).find((value) => value != null);
|
|
1834
|
+
if (pathRecord != null) overrideName = pathRecord;
|
|
1835
|
+
continue;
|
|
1836
|
+
}
|
|
1837
|
+
if (typeFlag === "0" || typeFlag === "\0") {
|
|
1838
|
+
const name = readTarString(header, 0, 100);
|
|
1839
|
+
const prefix = readTarString(header, 345, 155);
|
|
1840
|
+
files.set(
|
|
1841
|
+
overrideName ?? (prefix === "" ? name : `${prefix}/${name}`),
|
|
1842
|
+
Buffer.from(data)
|
|
1843
|
+
);
|
|
1844
|
+
}
|
|
1845
|
+
overrideName = void 0;
|
|
1846
|
+
}
|
|
1847
|
+
return files;
|
|
1848
|
+
}
|
|
1849
|
+
async function readSandboxFilesAsArchive(sandbox, sandboxPaths) {
|
|
1850
|
+
const members = sandboxPaths.map(
|
|
1851
|
+
(sandboxPath) => sandboxPath.replace(/^\/+/, "")
|
|
1852
|
+
);
|
|
1853
|
+
const command = `tar -C / -czf - -- ${members.map(shellQuote2).join(" ")} 2>/dev/null | base64`;
|
|
1854
|
+
let encoded;
|
|
1855
|
+
try {
|
|
1856
|
+
encoded = (await readCommandOutput(sandbox, command)).replace(/\s+/g, "");
|
|
1857
|
+
} catch {
|
|
1858
|
+
return /* @__PURE__ */ new Map();
|
|
1859
|
+
}
|
|
1860
|
+
if (encoded === "") return /* @__PURE__ */ new Map();
|
|
1861
|
+
let entries;
|
|
1862
|
+
try {
|
|
1863
|
+
entries = parseTarFiles(gunzipSync(Buffer.from(encoded, "base64")));
|
|
1864
|
+
} catch {
|
|
1865
|
+
return /* @__PURE__ */ new Map();
|
|
1866
|
+
}
|
|
1867
|
+
const contents = /* @__PURE__ */ new Map();
|
|
1868
|
+
for (const [index, member] of members.entries()) {
|
|
1869
|
+
const content = entries.get(member);
|
|
1870
|
+
if (content != null) {
|
|
1871
|
+
contents.set(sandboxPaths[index], content);
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
return contents;
|
|
1875
|
+
}
|
|
1805
1876
|
async function pathKind(target) {
|
|
1806
1877
|
try {
|
|
1807
1878
|
const stats = await stat(target);
|
|
@@ -1888,25 +1959,38 @@ async function syncHostWorkspaceFromSandbox(args) {
|
|
|
1888
1959
|
)) {
|
|
1889
1960
|
await mkdir2(path6.join(hostWorkDir, relativePath), { recursive: true });
|
|
1890
1961
|
}
|
|
1891
|
-
for (
|
|
1892
|
-
const
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1962
|
+
for (let offset = 0; offset < remoteEntries.files.length; offset += ARCHIVE_BATCH_SIZE) {
|
|
1963
|
+
const batch = remoteEntries.files.slice(
|
|
1964
|
+
offset,
|
|
1965
|
+
offset + ARCHIVE_BATCH_SIZE
|
|
1966
|
+
);
|
|
1967
|
+
const archived = await readSandboxFilesAsArchive(
|
|
1968
|
+
sandbox,
|
|
1969
|
+
batch.map((file) => file.sandboxPath)
|
|
1970
|
+
);
|
|
1971
|
+
for (const { relativePath, sandboxPath } of batch) {
|
|
1972
|
+
let content = archived.get(sandboxPath);
|
|
1973
|
+
if (content == null) {
|
|
1974
|
+
const bytes = await sandbox.readBinaryFile({ path: sandboxPath });
|
|
1975
|
+
if (!bytes) {
|
|
1976
|
+
throw new Error(
|
|
1977
|
+
`Sandbox workspace file disappeared during mirror sync: ${sandboxPath}`
|
|
1978
|
+
);
|
|
1979
|
+
}
|
|
1980
|
+
content = Buffer.from(bytes);
|
|
1981
|
+
}
|
|
1982
|
+
const hostPath = path6.join(hostWorkDir, relativePath);
|
|
1983
|
+
let shouldWrite = true;
|
|
1984
|
+
try {
|
|
1985
|
+
const existing = await readFile2(hostPath);
|
|
1986
|
+
shouldWrite = !existing.equals(content);
|
|
1987
|
+
} catch {
|
|
1988
|
+
shouldWrite = true;
|
|
1989
|
+
}
|
|
1990
|
+
if (shouldWrite) {
|
|
1991
|
+
await mkdir2(path6.dirname(hostPath), { recursive: true });
|
|
1992
|
+
await writeFile2(hostPath, content);
|
|
1993
|
+
}
|
|
1910
1994
|
}
|
|
1911
1995
|
}
|
|
1912
1996
|
}
|