@the-open-engine-company/zeroshot 10.8.0 → 10.9.1
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/lib/install.js +38 -14
- package/lib/release-artifacts.js +49 -24
- package/package.json +1 -1
- package/skills/zeroshot/SKILL.md +35 -0
- package/targets.json +10 -5
package/lib/install.js
CHANGED
|
@@ -7,7 +7,7 @@ const { URL } = require('url');
|
|
|
7
7
|
const { installSkills } = require('./skills');
|
|
8
8
|
const {
|
|
9
9
|
archiveName,
|
|
10
|
-
|
|
10
|
+
extractExecutables,
|
|
11
11
|
parseChecksumManifest,
|
|
12
12
|
targetForHost,
|
|
13
13
|
verifyArchive,
|
|
@@ -25,8 +25,40 @@ const HOST_TARGETS = Object.freeze(
|
|
|
25
25
|
);
|
|
26
26
|
|
|
27
27
|
function selectTarget(platform = process.platform, arch = process.arch) {
|
|
28
|
-
const { target, executable } = targetForHost(TARGETS, platform, arch);
|
|
29
|
-
return { target, executable };
|
|
28
|
+
const { target, executable, resticExecutable } = targetForHost(TARGETS, platform, arch);
|
|
29
|
+
return { target, executable, resticExecutable };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function installExecutables(nativeDirectory, entries) {
|
|
33
|
+
fs.mkdirSync(nativeDirectory, { recursive: true });
|
|
34
|
+
const stage = fs.mkdtempSync(path.join(nativeDirectory, '.install-'));
|
|
35
|
+
const replaced = [];
|
|
36
|
+
const backups = [];
|
|
37
|
+
try {
|
|
38
|
+
for (const [name, contents] of entries) {
|
|
39
|
+
fs.writeFileSync(path.join(stage, name), contents, { mode: 0o755, flag: 'wx' });
|
|
40
|
+
}
|
|
41
|
+
for (const [name] of entries) {
|
|
42
|
+
const destination = path.join(nativeDirectory, name);
|
|
43
|
+
if (fs.existsSync(destination)) {
|
|
44
|
+
const backup = path.join(stage, `${name}.previous`);
|
|
45
|
+
fs.renameSync(destination, backup);
|
|
46
|
+
backups.push([destination, backup]);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
for (const [name] of entries) {
|
|
50
|
+
const destination = path.join(nativeDirectory, name);
|
|
51
|
+
fs.renameSync(path.join(stage, name), destination);
|
|
52
|
+
replaced.push(destination);
|
|
53
|
+
if (process.platform !== 'win32') fs.chmodSync(destination, 0o755);
|
|
54
|
+
}
|
|
55
|
+
} catch (error) {
|
|
56
|
+
for (const destination of replaced.reverse()) fs.rmSync(destination, { force: true });
|
|
57
|
+
for (const [destination, backup] of backups.reverse()) fs.renameSync(backup, destination);
|
|
58
|
+
throw error;
|
|
59
|
+
} finally {
|
|
60
|
+
fs.rmSync(stage, { recursive: true, force: true });
|
|
61
|
+
}
|
|
30
62
|
}
|
|
31
63
|
|
|
32
64
|
function download(url, maximumBytes, redirects = 0) {
|
|
@@ -108,19 +140,11 @@ async function install(options = {}) {
|
|
|
108
140
|
const manifest = await fetchBuffer(`${baseUrl}/SHA256SUMS`, MAX_MANIFEST_BYTES);
|
|
109
141
|
const archive = await fetchBuffer(`${baseUrl}/${filename}`, MAX_ARCHIVE_BYTES);
|
|
110
142
|
verifyArchive(filename, archive, manifest.toString('utf8'));
|
|
111
|
-
const
|
|
143
|
+
const executables = extractExecutables(archive, [selected.executable, selected.resticExecutable]);
|
|
112
144
|
|
|
113
145
|
const nativeDirectory = path.join(packageRoot, 'bin', 'native');
|
|
114
146
|
const destination = path.join(nativeDirectory, selected.executable);
|
|
115
|
-
|
|
116
|
-
fs.mkdirSync(nativeDirectory, { recursive: true });
|
|
117
|
-
try {
|
|
118
|
-
fs.writeFileSync(temporary, executable, { mode: 0o755, flag: 'wx' });
|
|
119
|
-
fs.renameSync(temporary, destination);
|
|
120
|
-
if (process.platform !== 'win32') fs.chmodSync(destination, 0o755);
|
|
121
|
-
} finally {
|
|
122
|
-
fs.rmSync(temporary, { force: true });
|
|
123
|
-
}
|
|
147
|
+
installExecutables(nativeDirectory, executables);
|
|
124
148
|
const skillResults = installSkills({
|
|
125
149
|
packageRoot,
|
|
126
150
|
homeDirectory: options.homeDirectory,
|
|
@@ -136,7 +160,7 @@ module.exports = {
|
|
|
136
160
|
RELEASE_BASE_URL,
|
|
137
161
|
RELEASE_TAG_PREFIX,
|
|
138
162
|
archiveName,
|
|
139
|
-
|
|
163
|
+
extractExecutables,
|
|
140
164
|
install,
|
|
141
165
|
parseChecksumManifest,
|
|
142
166
|
selectTarget,
|
package/lib/release-artifacts.js
CHANGED
|
@@ -58,43 +58,68 @@ function parseTarSize(header) {
|
|
|
58
58
|
return Number.parseInt(value, 8);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
function
|
|
62
|
-
let tar;
|
|
61
|
+
function decompressArchive(archive) {
|
|
63
62
|
try {
|
|
64
|
-
|
|
63
|
+
return zlib.gunzipSync(archive);
|
|
65
64
|
} catch (error) {
|
|
66
65
|
throw new Error(`ARCHIVE_INVALID: cannot decompress release archive: ${error.message}`);
|
|
67
66
|
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function readTarEntry(tar, offset, expected, executables) {
|
|
70
|
+
const header = tar.subarray(offset, offset + 512);
|
|
71
|
+
if (header.every((byte) => byte === 0)) {
|
|
72
|
+
if (!tar.subarray(offset).every((byte) => byte === 0)) {
|
|
73
|
+
throw new Error('ARCHIVE_INVALID: unexpected data after tar terminator');
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
const name = header.subarray(0, 100).toString('utf8').replace(/\0.*$/, '');
|
|
78
|
+
const size = parseTarSize(header.subarray(124, 136));
|
|
79
|
+
const start = offset + 512;
|
|
80
|
+
const end = start + size;
|
|
81
|
+
if (end > tar.length) throw new Error('ARCHIVE_INVALID: truncated tar entry');
|
|
82
|
+
if (!expected.has(name) || ![0, '0'.charCodeAt(0)].includes(header[156])) {
|
|
83
|
+
throw new Error(`ARCHIVE_INVALID: unexpected archive entry ${name}`);
|
|
84
|
+
}
|
|
85
|
+
if (executables.has(name)) throw new Error(`ARCHIVE_INVALID: duplicate ${name}`);
|
|
86
|
+
executables.set(name, Buffer.from(tar.subarray(start, end)));
|
|
87
|
+
return start + Math.ceil(size / 512) * 512;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function requireExpectedExecutables(expected, executables) {
|
|
91
|
+
for (const name of expected) {
|
|
92
|
+
if (!executables.has(name)) {
|
|
93
|
+
throw new Error(`ARCHIVE_INVALID: archive does not contain ${name}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function extractExecutables(archive, expectedNames) {
|
|
99
|
+
const expected = new Set(expectedNames);
|
|
100
|
+
if (expected.size !== expectedNames.length || expected.size === 0) {
|
|
101
|
+
throw new Error('ARCHIVE_INVALID: expected executable names must be unique');
|
|
102
|
+
}
|
|
103
|
+
const tar = decompressArchive(archive);
|
|
68
104
|
let offset = 0;
|
|
69
|
-
let
|
|
105
|
+
let terminated = false;
|
|
106
|
+
const executables = new Map();
|
|
70
107
|
while (offset + 512 <= tar.length) {
|
|
71
|
-
const
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
throw new Error('ARCHIVE_INVALID: unexpected data after tar terminator');
|
|
75
|
-
}
|
|
108
|
+
const next = readTarEntry(tar, offset, expected, executables);
|
|
109
|
+
if (next === null) {
|
|
110
|
+
terminated = true;
|
|
76
111
|
break;
|
|
77
112
|
}
|
|
78
|
-
|
|
79
|
-
const size = parseTarSize(header.subarray(124, 136));
|
|
80
|
-
const start = offset + 512;
|
|
81
|
-
const end = start + size;
|
|
82
|
-
if (end > tar.length) throw new Error('ARCHIVE_INVALID: truncated tar entry');
|
|
83
|
-
if (name === expectedName) {
|
|
84
|
-
if (executable) throw new Error(`ARCHIVE_INVALID: duplicate ${expectedName}`);
|
|
85
|
-
executable = Buffer.from(tar.subarray(start, end));
|
|
86
|
-
} else {
|
|
87
|
-
throw new Error(`ARCHIVE_INVALID: unexpected archive entry ${name}`);
|
|
88
|
-
}
|
|
89
|
-
offset = start + Math.ceil(size / 512) * 512;
|
|
113
|
+
offset = next;
|
|
90
114
|
}
|
|
91
|
-
if (!
|
|
92
|
-
|
|
115
|
+
if (!terminated) throw new Error('ARCHIVE_INVALID: archive has no tar terminator');
|
|
116
|
+
requireExpectedExecutables(expected, executables);
|
|
117
|
+
return executables;
|
|
93
118
|
}
|
|
94
119
|
|
|
95
120
|
module.exports = {
|
|
96
121
|
archiveName,
|
|
97
|
-
|
|
122
|
+
extractExecutables,
|
|
98
123
|
parseChecksumManifest,
|
|
99
124
|
sha256,
|
|
100
125
|
targetForHost,
|
package/package.json
CHANGED
package/skills/zeroshot/SKILL.md
CHANGED
|
@@ -52,6 +52,41 @@ zeroshot connection list --target cloud --scope org
|
|
|
52
52
|
Do not assume a profile creates a pull request. `--pr` requests pull-request delivery and `--ship`
|
|
53
53
|
requests merge delivery when materializing a compatible template; use either only when intended.
|
|
54
54
|
|
|
55
|
+
## Prepare the execution environment
|
|
56
|
+
|
|
57
|
+
Environments belong to a run, independently of its profile. A `local:NAME` profile can run on a
|
|
58
|
+
Docker target with its own environment. For Docker or Cloud, pass
|
|
59
|
+
`--environment environment.json` with a flat definition such as:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"setup": "apt-get update && apt-get install -y jq",
|
|
64
|
+
"startup": "npm ci",
|
|
65
|
+
"variables": { "CI": "true" }
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Cloud resolves an omitted environment from the repository's User default, then Org default, then
|
|
70
|
+
Base. `--no-environment` bypasses defaults. Choose saved environments through Cloud's UI or API;
|
|
71
|
+
the CLI accepts a concrete JSON file. Local runs use the invoking machine and reject setup/startup
|
|
72
|
+
and hook connections.
|
|
73
|
+
|
|
74
|
+
Setup runs as root before checkout or restoration, so it cannot read repository files. Startup
|
|
75
|
+
runs as the workspace user in the checkout; workers and reviewers share its dependencies and
|
|
76
|
+
services. Both hooks rerun on resume, so startup must tolerate existing workspace files.
|
|
77
|
+
Checkpoints restore files and graph progress, not running services or agent conversations.
|
|
78
|
+
|
|
79
|
+
Put shared executables in `$ZEROSHOT_TOOLS/bin` and project dependencies in the workspace.
|
|
80
|
+
Shell exports do not persist between hooks or agents; use `variables` for nonsecret values and
|
|
81
|
+
`connections` for required secret field names. Hook connections and node connections are separate.
|
|
82
|
+
On a direct Docker target, root setup changes the container shared by its runs.
|
|
83
|
+
|
|
84
|
+
Preparation failures stop before agent execution without spending repair attempts. Inspect the
|
|
85
|
+
failed phase and logs; fix the environment instead of requesting unrelated code repairs. Resume
|
|
86
|
+
reuses the accepted definition, so an edited environment requires a new run. For a pinned Node
|
|
87
|
+
installation and service/Docker conventions, see the
|
|
88
|
+
[environment guide](https://the-open-engine.github.io/zeroshot/current/guides/runtime-environments/).
|
|
89
|
+
|
|
55
90
|
## Expose a profile over ACP
|
|
56
91
|
|
|
57
92
|
Start `zeroshot acp` only when the user explicitly asks to expose a Zeroshot graph as an ACP agent.
|
package/targets.json
CHANGED
|
@@ -3,30 +3,35 @@
|
|
|
3
3
|
"platform": "linux",
|
|
4
4
|
"arch": "x64",
|
|
5
5
|
"target": "x86_64-unknown-linux-musl",
|
|
6
|
-
"executable": "zeroshot"
|
|
6
|
+
"executable": "zeroshot",
|
|
7
|
+
"resticExecutable": "restic"
|
|
7
8
|
},
|
|
8
9
|
{
|
|
9
10
|
"platform": "linux",
|
|
10
11
|
"arch": "arm64",
|
|
11
12
|
"target": "aarch64-unknown-linux-musl",
|
|
12
|
-
"executable": "zeroshot"
|
|
13
|
+
"executable": "zeroshot",
|
|
14
|
+
"resticExecutable": "restic"
|
|
13
15
|
},
|
|
14
16
|
{
|
|
15
17
|
"platform": "darwin",
|
|
16
18
|
"arch": "x64",
|
|
17
19
|
"target": "x86_64-apple-darwin",
|
|
18
|
-
"executable": "zeroshot"
|
|
20
|
+
"executable": "zeroshot",
|
|
21
|
+
"resticExecutable": "restic"
|
|
19
22
|
},
|
|
20
23
|
{
|
|
21
24
|
"platform": "darwin",
|
|
22
25
|
"arch": "arm64",
|
|
23
26
|
"target": "aarch64-apple-darwin",
|
|
24
|
-
"executable": "zeroshot"
|
|
27
|
+
"executable": "zeroshot",
|
|
28
|
+
"resticExecutable": "restic"
|
|
25
29
|
},
|
|
26
30
|
{
|
|
27
31
|
"platform": "win32",
|
|
28
32
|
"arch": "x64",
|
|
29
33
|
"target": "x86_64-pc-windows-msvc",
|
|
30
|
-
"executable": "zeroshot.exe"
|
|
34
|
+
"executable": "zeroshot.exe",
|
|
35
|
+
"resticExecutable": "restic.exe"
|
|
31
36
|
}
|
|
32
37
|
]
|