@dougbots/avenor-core 0.1.0 → 0.2.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/README.md +3 -1
- package/dist/index.d.ts +13 -6
- package/dist/index.js +81 -17
- package/dist/install-path-C7QXqbJO.js +30 -0
- package/dist/install-path-DagQIDKB.d.ts +6 -0
- package/dist/postinstall.d.ts +9 -0
- package/dist/postinstall.js +95 -0
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -44,11 +44,13 @@ const result = await spawnTool({
|
|
|
44
44
|
prompt: 'Write a function to reverse a string',
|
|
45
45
|
label: 'reverse-string',
|
|
46
46
|
model: 'claude-sonnet-4',
|
|
47
|
+
backend: 'opencode-http',
|
|
48
|
+
serverUrl: 'http://127.0.0.1:4096',
|
|
47
49
|
})
|
|
48
50
|
// { run_id: '...', label: 'reverse-string', supervisor_id: '/path/to/socket' }
|
|
49
51
|
```
|
|
50
52
|
|
|
51
|
-
Accepts `agent`, `prompt`, `promptFile`, `label`, `dir`, `timeout`, `model`, `sessionId`, and `supervisorId` (to target a specific socket).
|
|
53
|
+
Accepts `agent`, `prompt`, `promptFile`, `label`, `dir`, `timeout`, `model`, `backend`, `serverUrl`, `sessionId`, and `supervisorId` (to target a specific socket).
|
|
52
54
|
|
|
53
55
|
### `statusTool`
|
|
54
56
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { n as getVersion, r as installerBinaryPath, t as getInstallDir } from "./install-path-DagQIDKB.js";
|
|
1
2
|
import * as net from "node:net";
|
|
2
3
|
|
|
3
4
|
//#region src/client.d.ts
|
|
@@ -15,6 +16,8 @@ interface SpawnParams {
|
|
|
15
16
|
label?: string;
|
|
16
17
|
timeout?: number;
|
|
17
18
|
model?: string;
|
|
19
|
+
backend?: string;
|
|
20
|
+
server_url?: string;
|
|
18
21
|
session_id?: string;
|
|
19
22
|
sentinel_file?: string;
|
|
20
23
|
on_event?: string;
|
|
@@ -98,6 +101,8 @@ declare function spawnTool(args: {
|
|
|
98
101
|
dir?: string;
|
|
99
102
|
timeout?: string;
|
|
100
103
|
model?: string;
|
|
104
|
+
backend?: string;
|
|
105
|
+
serverUrl?: string;
|
|
101
106
|
sessionId?: string;
|
|
102
107
|
supervisorId?: string;
|
|
103
108
|
}): Promise<{
|
|
@@ -157,11 +162,13 @@ declare function eventsTool(args: {
|
|
|
157
162
|
types?: string[];
|
|
158
163
|
limit?: number;
|
|
159
164
|
supervisorId?: string;
|
|
160
|
-
}): Promise<
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
+
}): Promise<{
|
|
166
|
+
events: Array<{
|
|
167
|
+
type: string;
|
|
168
|
+
ts: number;
|
|
169
|
+
[key: string]: unknown;
|
|
170
|
+
}>;
|
|
171
|
+
}>;
|
|
165
172
|
//#endregion
|
|
166
173
|
//#region src/tools/shutdown.d.ts
|
|
167
174
|
declare function shutdownTool(args: {
|
|
@@ -172,4 +179,4 @@ declare function shutdownTool(args: {
|
|
|
172
179
|
cleaned_up: string[];
|
|
173
180
|
}>;
|
|
174
181
|
//#endregion
|
|
175
|
-
export { type Client, type Event, type RunInfo, type SpawnParams, type StatusResult, Supervisor, type SupervisorOptions, answerPermissionTool, dial, eventsTool, findAvenorBinary, followUpTool, shutdownTool, spawnTool, statusTool };
|
|
182
|
+
export { type Client, type Event, type RunInfo, type SpawnParams, type StatusResult, Supervisor, type SupervisorOptions, answerPermissionTool, dial, eventsTool, findAvenorBinary, followUpTool, getInstallDir, getVersion, installerBinaryPath, shutdownTool, spawnTool, statusTool };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { n as getVersion, r as installerBinaryPath, t as getInstallDir } from "./install-path-C7QXqbJO.js";
|
|
1
2
|
import * as net from "node:net";
|
|
2
3
|
import * as readline from "node:readline";
|
|
3
4
|
import { execSync, spawn } from "node:child_process";
|
|
@@ -222,12 +223,20 @@ function findAvenorBinary() {
|
|
|
222
223
|
throw new Error(`AVENOR_BIN path not executable: ${envBin}`);
|
|
223
224
|
}
|
|
224
225
|
try {
|
|
225
|
-
const binPath = execSync("which avenor", {
|
|
226
|
+
const binPath = execSync("which avenor", {
|
|
227
|
+
encoding: "utf-8",
|
|
228
|
+
env: process.env
|
|
229
|
+
}).trim();
|
|
226
230
|
if (binPath) {
|
|
227
231
|
fs.accessSync(binPath, fs.constants.X_OK);
|
|
228
232
|
return binPath;
|
|
229
233
|
}
|
|
230
234
|
} catch {}
|
|
235
|
+
try {
|
|
236
|
+
const installPath = installerBinaryPath();
|
|
237
|
+
fs.accessSync(installPath, fs.constants.X_OK);
|
|
238
|
+
return installPath;
|
|
239
|
+
} catch {}
|
|
231
240
|
const homeBin = path.join(os.homedir(), ".botfiles", "bin", "avenor");
|
|
232
241
|
try {
|
|
233
242
|
fs.accessSync(homeBin, fs.constants.X_OK);
|
|
@@ -443,12 +452,33 @@ function validateSupervisorSocketPath(supervisorId) {
|
|
|
443
452
|
return canonical;
|
|
444
453
|
}
|
|
445
454
|
//#endregion
|
|
455
|
+
//#region src/tools/get-supervisor-client.ts
|
|
456
|
+
async function getSupervisorClient(supervisorId) {
|
|
457
|
+
const id = validateSupervisorSocketPath(supervisorId);
|
|
458
|
+
if (Supervisor.isCurrentInstance(id)) {
|
|
459
|
+
const sup = Supervisor.currentInstance();
|
|
460
|
+
if (!sup) throw new Error(`Supervisor.isCurrentInstance() returned true but currentInstance() is null (id: ${id})`);
|
|
461
|
+
return {
|
|
462
|
+
client: sup.getClient(),
|
|
463
|
+
isSingleton: true,
|
|
464
|
+
sup,
|
|
465
|
+
supervisorId: id
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
return {
|
|
469
|
+
client: await dial(id),
|
|
470
|
+
isSingleton: false,
|
|
471
|
+
sup: null,
|
|
472
|
+
supervisorId: id
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
//#endregion
|
|
446
476
|
//#region src/tools/spawn.ts
|
|
447
477
|
async function spawnTool(args) {
|
|
448
478
|
const runId = crypto.randomUUID();
|
|
449
479
|
const label = args.label ?? runId;
|
|
450
480
|
if (args.supervisorId) {
|
|
451
|
-
const client = await
|
|
481
|
+
const { client, isSingleton, supervisorId } = await getSupervisorClient(args.supervisorId);
|
|
452
482
|
const { sentinelPath, eventLogPath } = ensureRunPaths(runId);
|
|
453
483
|
try {
|
|
454
484
|
return {
|
|
@@ -460,15 +490,17 @@ async function spawnTool(args) {
|
|
|
460
490
|
dir: args.dir,
|
|
461
491
|
timeout: args.timeout !== void 0 ? validateTimeout(args.timeout) : void 0,
|
|
462
492
|
model: args.model,
|
|
493
|
+
backend: args.backend,
|
|
494
|
+
server_url: args.serverUrl,
|
|
463
495
|
session_id: args.sessionId,
|
|
464
496
|
sentinel_file: sentinelPath,
|
|
465
497
|
on_event: eventLogPath
|
|
466
498
|
})).runtime_id ?? runId,
|
|
467
499
|
label,
|
|
468
|
-
supervisor_id:
|
|
500
|
+
supervisor_id: supervisorId
|
|
469
501
|
};
|
|
470
502
|
} finally {
|
|
471
|
-
client.close();
|
|
503
|
+
if (!isSingleton) client.close();
|
|
472
504
|
}
|
|
473
505
|
}
|
|
474
506
|
const sup = await Supervisor.get();
|
|
@@ -480,6 +512,8 @@ async function spawnTool(args) {
|
|
|
480
512
|
dir: args.dir,
|
|
481
513
|
timeout: args.timeout !== void 0 ? validateTimeout(args.timeout) : void 0,
|
|
482
514
|
model: args.model,
|
|
515
|
+
backend: args.backend,
|
|
516
|
+
server_url: args.serverUrl,
|
|
483
517
|
session_id: args.sessionId
|
|
484
518
|
});
|
|
485
519
|
return {
|
|
@@ -574,7 +608,7 @@ async function buildRunStatus(client, runInfo, liveStatus) {
|
|
|
574
608
|
}
|
|
575
609
|
async function statusTool(args) {
|
|
576
610
|
if (args.supervisorId) {
|
|
577
|
-
const client = await
|
|
611
|
+
const { client, isSingleton } = await getSupervisorClient(args.supervisorId);
|
|
578
612
|
try {
|
|
579
613
|
if (args.runId) {
|
|
580
614
|
validateRunId(args.runId);
|
|
@@ -612,19 +646,46 @@ async function statusTool(args) {
|
|
|
612
646
|
session_id: entry.session_id
|
|
613
647
|
}));
|
|
614
648
|
} finally {
|
|
615
|
-
client.close();
|
|
649
|
+
if (!isSingleton) client.close();
|
|
616
650
|
}
|
|
617
651
|
}
|
|
618
652
|
const sup = await Supervisor.get();
|
|
619
653
|
const client = sup.getClient();
|
|
620
654
|
if (args.runId) {
|
|
621
655
|
const runInfo = findRunByLabel$3(sup, args.runId);
|
|
622
|
-
if (
|
|
656
|
+
if (runInfo) {
|
|
657
|
+
let liveStatus = null;
|
|
658
|
+
if (runInfo.runtimeId) try {
|
|
659
|
+
liveStatus = await client.status(runInfo.runtimeId);
|
|
660
|
+
} catch {}
|
|
661
|
+
return buildRunStatus(client, runInfo, liveStatus);
|
|
662
|
+
}
|
|
663
|
+
validateRunId(args.runId);
|
|
623
664
|
let liveStatus = null;
|
|
624
|
-
|
|
625
|
-
liveStatus = await client.status(
|
|
665
|
+
try {
|
|
666
|
+
liveStatus = await client.status(args.runId);
|
|
626
667
|
} catch {}
|
|
627
|
-
|
|
668
|
+
const sentinelPath = path.join(runsRoot(), args.runId, "sentinel.done");
|
|
669
|
+
let sentinel = null;
|
|
670
|
+
if (await sentinelExists(sentinelPath)) sentinel = await parseSentinel$1(sentinelPath);
|
|
671
|
+
return {
|
|
672
|
+
run_id: args.runId,
|
|
673
|
+
label: args.runId,
|
|
674
|
+
status: translateStatus(liveStatus?.phase ?? liveStatus?.status ?? "running", sentinel),
|
|
675
|
+
phase: liveStatus?.phase,
|
|
676
|
+
phase_label: liveStatus?.phase_label,
|
|
677
|
+
session_id: sentinel?.SESSION ?? liveStatus?.session_id ?? void 0,
|
|
678
|
+
stop_reason: sentinel?._status ?? void 0,
|
|
679
|
+
pending_permission: liveStatus?.pending_permission ? {
|
|
680
|
+
request_id: liveStatus.pending_permission.request_id ?? "",
|
|
681
|
+
description: liveStatus.pending_permission.description ?? "",
|
|
682
|
+
options: Array.isArray(liveStatus.pending_permission.options) ? liveStatus.pending_permission.options.map((o) => ({
|
|
683
|
+
option_id: o.option_id ?? "",
|
|
684
|
+
label: o.label ?? "",
|
|
685
|
+
kind: o.kind ?? ""
|
|
686
|
+
})) : []
|
|
687
|
+
} : void 0
|
|
688
|
+
};
|
|
628
689
|
}
|
|
629
690
|
const list = await client.list();
|
|
630
691
|
const results = [];
|
|
@@ -659,12 +720,15 @@ async function answerPermissionTool(args) {
|
|
|
659
720
|
let client;
|
|
660
721
|
let sup = null;
|
|
661
722
|
let requestId = args.requestId;
|
|
662
|
-
|
|
723
|
+
let supervisorId;
|
|
724
|
+
let isSingleton = false;
|
|
725
|
+
if (args.supervisorId) ({client, isSingleton, sup, supervisorId} = await getSupervisorClient(args.supervisorId));
|
|
663
726
|
else {
|
|
664
727
|
sup = await Supervisor.get();
|
|
665
728
|
client = sup.getClient();
|
|
666
729
|
}
|
|
667
730
|
try {
|
|
731
|
+
validateRunId(args.runId);
|
|
668
732
|
const runtimeId = (sup ? findRunByLabel$2(sup, args.runId) : void 0)?.runtimeId ?? args.runId;
|
|
669
733
|
if (!requestId) {
|
|
670
734
|
const pp = (await client.status(runtimeId))?.pending_permission;
|
|
@@ -674,7 +738,7 @@ async function answerPermissionTool(args) {
|
|
|
674
738
|
await client.answerPermission(runtimeId, requestId, args.optionId);
|
|
675
739
|
return { ok: true };
|
|
676
740
|
} finally {
|
|
677
|
-
if (
|
|
741
|
+
if (supervisorId && !isSingleton) client.close();
|
|
678
742
|
}
|
|
679
743
|
}
|
|
680
744
|
//#endregion
|
|
@@ -705,7 +769,7 @@ async function parseSentinel(filePath) {
|
|
|
705
769
|
}
|
|
706
770
|
async function followUpTool(args) {
|
|
707
771
|
if (args.supervisorId) {
|
|
708
|
-
const client = await
|
|
772
|
+
const { client, isSingleton } = await getSupervisorClient(args.supervisorId);
|
|
709
773
|
try {
|
|
710
774
|
validateRunId(args.runId);
|
|
711
775
|
let liveStatus = null;
|
|
@@ -731,7 +795,7 @@ async function followUpTool(args) {
|
|
|
731
795
|
label: followUpLabel
|
|
732
796
|
};
|
|
733
797
|
} finally {
|
|
734
|
-
client.close();
|
|
798
|
+
if (!isSingleton) client.close();
|
|
735
799
|
}
|
|
736
800
|
}
|
|
737
801
|
const sup = await Supervisor.get();
|
|
@@ -783,7 +847,7 @@ async function eventsTool(args) {
|
|
|
783
847
|
await handle.close();
|
|
784
848
|
}
|
|
785
849
|
} catch {
|
|
786
|
-
return [];
|
|
850
|
+
return { events: [] };
|
|
787
851
|
}
|
|
788
852
|
const lines = raw.split("\n").filter((line) => line.trim());
|
|
789
853
|
let events = [];
|
|
@@ -792,7 +856,7 @@ async function eventsTool(args) {
|
|
|
792
856
|
} catch {}
|
|
793
857
|
if (args.types && args.types.length > 0) events = events.filter((e) => args.types.includes(e.type ?? e.event ?? ""));
|
|
794
858
|
if (events.length > limit) events = events.slice(events.length - limit);
|
|
795
|
-
return events;
|
|
859
|
+
return { events };
|
|
796
860
|
}
|
|
797
861
|
//#endregion
|
|
798
862
|
//#region src/tools/shutdown.ts
|
|
@@ -851,4 +915,4 @@ async function shutdownTool(args) {
|
|
|
851
915
|
};
|
|
852
916
|
}
|
|
853
917
|
//#endregion
|
|
854
|
-
export { Supervisor, answerPermissionTool, dial, eventsTool, findAvenorBinary, followUpTool, shutdownTool, spawnTool, statusTool };
|
|
918
|
+
export { Supervisor, answerPermissionTool, dial, eventsTool, findAvenorBinary, followUpTool, getInstallDir, getVersion, installerBinaryPath, shutdownTool, spawnTool, statusTool };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as os from "node:os";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
//#region src/install-path.ts
|
|
5
|
+
const SEMVER_RE = /^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$/;
|
|
6
|
+
function getVersion(packageJsonPath) {
|
|
7
|
+
const envVer = process.env.AVENOR_VERSION;
|
|
8
|
+
if (envVer) {
|
|
9
|
+
if (!SEMVER_RE.test(envVer)) throw new Error(`Invalid AVENOR_VERSION: ${envVer}. Must be a semver string like 1.2.3`);
|
|
10
|
+
return envVer;
|
|
11
|
+
}
|
|
12
|
+
const pkgVer = process.env.npm_package_version;
|
|
13
|
+
if (pkgVer) {
|
|
14
|
+
if (!SEMVER_RE.test(pkgVer)) throw new Error(`Invalid npm_package_version: ${pkgVer}. Must be a semver string like 1.2.3`);
|
|
15
|
+
return pkgVer;
|
|
16
|
+
}
|
|
17
|
+
const pkgPath = packageJsonPath ?? new URL("../package.json", import.meta.url);
|
|
18
|
+
const v = JSON.parse(fs.readFileSync(pkgPath, "utf-8")).version;
|
|
19
|
+
if (!SEMVER_RE.test(v)) throw new Error(`Invalid package version: ${v}. Must be a semver string like 1.2.3`);
|
|
20
|
+
return v;
|
|
21
|
+
}
|
|
22
|
+
function getInstallDir(version) {
|
|
23
|
+
if (process.env.AVENOR_INSTALL_DIR) return process.env.AVENOR_INSTALL_DIR;
|
|
24
|
+
return path.join(os.homedir(), ".cache", "avenor", "bin", "avenor", version);
|
|
25
|
+
}
|
|
26
|
+
function installerBinaryPath(version = getVersion()) {
|
|
27
|
+
return path.join(getInstallDir(version), "avenor");
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { getVersion as n, installerBinaryPath as r, getInstallDir as t };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
//#region src/install-path.d.ts
|
|
2
|
+
declare function getVersion(packageJsonPath?: string): string;
|
|
3
|
+
declare function getInstallDir(version: string): string;
|
|
4
|
+
declare function installerBinaryPath(version?: string): string;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { getVersion as n, installerBinaryPath as r, getInstallDir as t };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { n as getVersion, r as installerBinaryPath, t as getInstallDir } from "./install-path-DagQIDKB.js";
|
|
2
|
+
|
|
3
|
+
//#region src/postinstall.d.ts
|
|
4
|
+
declare function platformMapping(platform: string, arch: string): string | null;
|
|
5
|
+
declare function verifyChecksum(buffer: Buffer, expectedHash: string): boolean;
|
|
6
|
+
declare function parseChecksums(content: string, assetName: string): string | null;
|
|
7
|
+
declare function postinstall(fetchFn?: typeof globalThis.fetch, platform?: string, arch?: string): Promise<void>;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { getInstallDir, getVersion, installerBinaryPath, parseChecksums, platformMapping, postinstall, verifyChecksum };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { n as getVersion, r as installerBinaryPath, t as getInstallDir } from "./install-path-C7QXqbJO.js";
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
|
+
import * as fs from "node:fs";
|
|
4
|
+
import * as crypto from "node:crypto";
|
|
5
|
+
//#region src/postinstall.ts
|
|
6
|
+
function platformMapping(platform, arch) {
|
|
7
|
+
return {
|
|
8
|
+
"darwin/arm64": "avenor_darwin_arm64",
|
|
9
|
+
"darwin/x64": "avenor_darwin_amd64",
|
|
10
|
+
"linux/x64": "avenor_linux_amd64",
|
|
11
|
+
"linux/arm64": "avenor_linux_arm64"
|
|
12
|
+
}[`${platform}/${arch}`] ?? null;
|
|
13
|
+
}
|
|
14
|
+
function verifyChecksum(buffer, expectedHash) {
|
|
15
|
+
return crypto.createHash("sha256").update(buffer).digest("hex") === expectedHash;
|
|
16
|
+
}
|
|
17
|
+
function parseChecksums(content, assetName) {
|
|
18
|
+
for (const line of content.split("\n")) {
|
|
19
|
+
const trimmed = line.trim();
|
|
20
|
+
if (!trimmed) continue;
|
|
21
|
+
const parts = trimmed.split(/\s+/);
|
|
22
|
+
if (parts.length >= 2 && parts[1] === assetName) return parts[0];
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
async function postinstall(fetchFn = globalThis.fetch, platform, arch) {
|
|
27
|
+
const envBin = process.env.AVENOR_BIN;
|
|
28
|
+
if (envBin) try {
|
|
29
|
+
fs.accessSync(envBin, fs.constants.X_OK);
|
|
30
|
+
return;
|
|
31
|
+
} catch {}
|
|
32
|
+
try {
|
|
33
|
+
const whichBin = execSync("which avenor", {
|
|
34
|
+
encoding: "utf-8",
|
|
35
|
+
env: process.env
|
|
36
|
+
}).trim();
|
|
37
|
+
if (whichBin) try {
|
|
38
|
+
fs.accessSync(whichBin, fs.constants.X_OK);
|
|
39
|
+
return;
|
|
40
|
+
} catch {}
|
|
41
|
+
} catch {}
|
|
42
|
+
if (process.env.AVENOR_SKIP_DOWNLOAD === "1") {
|
|
43
|
+
console.warn("[avenor-postinstall] AVENOR_SKIP_DOWNLOAD=1, skipping download. Binary may not be available.");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const plat = platform ?? process.platform;
|
|
47
|
+
const a = arch ?? process.arch;
|
|
48
|
+
const asset = platformMapping(plat, a);
|
|
49
|
+
if (!asset) {
|
|
50
|
+
console.warn(`[avenor-postinstall] Unsupported platform: ${plat}/${a}`);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const version = getVersion();
|
|
54
|
+
const installDir = getInstallDir(version);
|
|
55
|
+
const binaryPath = installerBinaryPath(version);
|
|
56
|
+
const url = `https://github.com/sdougbrown/avenor/releases/download/v${version}/${asset}`;
|
|
57
|
+
try {
|
|
58
|
+
fs.mkdirSync(installDir, {
|
|
59
|
+
recursive: true,
|
|
60
|
+
mode: 448
|
|
61
|
+
});
|
|
62
|
+
const response = await fetchFn(url);
|
|
63
|
+
if (!response.ok) {
|
|
64
|
+
console.warn(`[avenor-postinstall] Download failed: HTTP ${response.status} from ${url}`);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
68
|
+
const checksumsUrl = `https://github.com/sdougbrown/avenor/releases/download/v${version}/checksums.txt`;
|
|
69
|
+
try {
|
|
70
|
+
const checksumsResponse = await fetchFn(checksumsUrl);
|
|
71
|
+
if (checksumsResponse.ok) {
|
|
72
|
+
const expectedHash = parseChecksums(await checksumsResponse.text(), asset);
|
|
73
|
+
if (expectedHash) {
|
|
74
|
+
if (!verifyChecksum(buffer, expectedHash)) {
|
|
75
|
+
console.warn(`[avenor-postinstall] Checksum mismatch for ${asset}, skipping installation`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
} else console.warn(`[avenor-postinstall] Checksums not available for ${asset}, skipping verification`);
|
|
79
|
+
} else console.warn(`[avenor-postinstall] Checksums not available (HTTP ${checksumsResponse.status}), skipping verification`);
|
|
80
|
+
} catch {
|
|
81
|
+
console.warn(`[avenor-postinstall] Checksums not available, skipping verification`);
|
|
82
|
+
}
|
|
83
|
+
fs.writeFileSync(binaryPath, buffer);
|
|
84
|
+
fs.chmodSync(binaryPath, 493);
|
|
85
|
+
} catch (err) {
|
|
86
|
+
console.warn(`[avenor-postinstall] Failed to install avenor binary: ${err instanceof Error ? err.message : String(err)}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const arg1 = process.argv[1];
|
|
90
|
+
if (!!arg1 && (arg1.endsWith("postinstall.js") || arg1.endsWith("postinstall.ts"))) postinstall().catch((err) => {
|
|
91
|
+
console.warn(`[avenor-postinstall] Unhandled error: ${err instanceof Error ? err.message : String(err)}`);
|
|
92
|
+
process.exit(0);
|
|
93
|
+
});
|
|
94
|
+
//#endregion
|
|
95
|
+
export { getInstallDir, getVersion, installerBinaryPath, parseChecksums, platformMapping, postinstall, verifyChecksum };
|
package/package.json
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dougbots/avenor-core",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"type": "module",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/sdougbrown/avenor",
|
|
8
|
+
"directory": "packages/core"
|
|
9
|
+
},
|
|
5
10
|
"files": [
|
|
6
11
|
"dist"
|
|
7
12
|
],
|
|
@@ -20,7 +25,8 @@
|
|
|
20
25
|
"build": "tsdown",
|
|
21
26
|
"test": "bun test",
|
|
22
27
|
"test:e2e": "AVENOR_REAL_INTEGRATION=1 bun test",
|
|
23
|
-
"dev": "tsdown --watch"
|
|
28
|
+
"dev": "tsdown --watch",
|
|
29
|
+
"postinstall": "node -e \"const fs=require('fs');if(fs.existsSync('dist/postinstall.js')){require('./dist/postinstall.js')}\""
|
|
24
30
|
},
|
|
25
31
|
"devDependencies": {
|
|
26
32
|
"@types/bun": "^1.3.12",
|