@bolt-foundry/gambit 0.6.2 → 0.6.3

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.
Files changed (2) hide show
  1. package/bin/gambit.cjs +81 -10
  2. package/package.json +2 -2
package/bin/gambit.cjs CHANGED
@@ -7,10 +7,21 @@ const os = require("os");
7
7
  const https = require("https");
8
8
  const http = require("http");
9
9
  const crypto = require("crypto");
10
+ const zlib = require("zlib");
11
+ const { pipeline } = require("stream/promises");
10
12
  const { spawnSync } = require("child_process");
11
13
 
12
14
  const MAX_REDIRECTS = 5;
13
15
 
16
+ const fileExists = async (filePath) => {
17
+ try {
18
+ await fs.promises.access(filePath, fs.constants.F_OK);
19
+ return true;
20
+ } catch {
21
+ return false;
22
+ }
23
+ };
24
+
14
25
  const readJson = (filePath) => {
15
26
  const raw = fs.readFileSync(filePath, "utf8");
16
27
  return JSON.parse(raw);
@@ -88,6 +99,17 @@ const downloadFile = async (url, dest) => {
88
99
  await fs.promises.rename(tmpDest, dest);
89
100
  };
90
101
 
102
+ const gunzipFile = async (source, dest) => {
103
+ const tmpDest = `${dest}.tmp-${process.pid}`;
104
+ await fs.promises.mkdir(path.dirname(dest), { recursive: true });
105
+ await pipeline(
106
+ fs.createReadStream(source),
107
+ zlib.createGunzip(),
108
+ fs.createWriteStream(tmpDest, { mode: 0o755 }),
109
+ );
110
+ await fs.promises.rename(tmpDest, dest);
111
+ };
112
+
91
113
  const fetchText = async (url) => {
92
114
  const res = await request(url);
93
115
  const chunks = [];
@@ -149,38 +171,87 @@ const main = async () => {
149
171
 
150
172
  const baseUrl = process.env.GAMBIT_BINARY_BASE_URL ||
151
173
  `https://github.com/bolt-foundry/gambit/releases/download/v${version}`;
152
- const binaryUrl = process.env.GAMBIT_BINARY_URL || `${baseUrl}/${assetName}`;
174
+ const binaryUrl = process.env.GAMBIT_BINARY_URL ||
175
+ `${baseUrl}/${assetName}.gz`;
153
176
  const checksumUrl = process.env.GAMBIT_BINARY_CHECKSUM_URL ||
154
177
  `${baseUrl}/SHA256SUMS`;
178
+ const downloadName = (() => {
179
+ try {
180
+ return path.posix.basename(new URL(binaryUrl).pathname);
181
+ } catch {
182
+ return path.posix.basename(binaryUrl);
183
+ }
184
+ })();
185
+ const expectsGzip = downloadName.endsWith(".gz");
155
186
 
156
187
  const cacheDir = getCacheDir(version);
157
188
  const binPath = path.join(cacheDir, assetName);
189
+ const archivePath = expectsGzip ? `${binPath}.gz` : binPath;
158
190
  const ensureBinary = async () => {
159
- if (fs.existsSync(binPath)) {
191
+ const hasBin = await fileExists(binPath);
192
+ const hasArchive = await fileExists(archivePath);
193
+ if (!hasBin && expectsGzip && hasArchive) {
160
194
  try {
161
- await verifyChecksum(checksumUrl, assetName, binPath);
195
+ await verifyChecksum(checksumUrl, downloadName, archivePath);
196
+ await gunzipFile(archivePath, binPath);
162
197
  return;
163
198
  } catch (err) {
164
- console.warn(
165
- `Cached binary failed checksum; deleting and re-downloading.`,
166
- );
167
199
  try {
168
- await fs.promises.unlink(binPath);
200
+ await fs.promises.unlink(archivePath);
169
201
  } catch {
170
202
  // ignore
171
203
  }
172
204
  }
173
205
  }
206
+ if (hasBin) {
207
+ if (expectsGzip && !hasArchive) {
208
+ console.warn(`Cached binary missing archive; re-downloading.`);
209
+ } else {
210
+ try {
211
+ await verifyChecksum(checksumUrl, downloadName, archivePath);
212
+ if (expectsGzip) {
213
+ await gunzipFile(archivePath, binPath);
214
+ }
215
+ return;
216
+ } catch (err) {
217
+ console.warn(
218
+ `Cached binary failed checksum; deleting and re-downloading.`,
219
+ );
220
+ try {
221
+ await fs.promises.unlink(binPath);
222
+ } catch {
223
+ // ignore
224
+ }
225
+ if (expectsGzip) {
226
+ try {
227
+ await fs.promises.unlink(archivePath);
228
+ } catch {
229
+ // ignore
230
+ }
231
+ }
232
+ }
233
+ }
234
+ }
174
235
  console.log(`Downloading ${binaryUrl}...`);
175
- await downloadFile(binaryUrl, binPath);
236
+ await downloadFile(binaryUrl, archivePath);
176
237
  try {
177
- await verifyChecksum(checksumUrl, assetName, binPath);
238
+ await verifyChecksum(checksumUrl, downloadName, archivePath);
239
+ if (expectsGzip) {
240
+ await gunzipFile(archivePath, binPath);
241
+ }
178
242
  } catch (err) {
179
243
  try {
180
- await fs.promises.unlink(binPath);
244
+ await fs.promises.unlink(archivePath);
181
245
  } catch {
182
246
  // ignore
183
247
  }
248
+ if (expectsGzip) {
249
+ try {
250
+ await fs.promises.unlink(binPath);
251
+ } catch {
252
+ // ignore
253
+ }
254
+ }
184
255
  throw err;
185
256
  }
186
257
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bolt-foundry/gambit",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "description": "Agent harness framework for building, running, and verifying LLM workflows in Markdown and code.",
5
5
  "homepage": "https://github.com/bolt-foundry/gambit",
6
6
  "repository": {
@@ -24,7 +24,7 @@
24
24
  "gambit": "bin/gambit.cjs"
25
25
  },
26
26
  "dependencies": {
27
- "@bolt-foundry/gambit-core": "^0.6.2",
27
+ "@bolt-foundry/gambit-core": "^0.6.3",
28
28
  "zod": "^3.23.8",
29
29
  "@deno/shim-deno": "~0.18.0"
30
30
  },