@your_conscience/dotagents 0.7.0

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.
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+ const { spawnSync } = require("child_process");
7
+
8
+ const binary = path.join(__dirname, "dotagents");
9
+
10
+ if (!fs.existsSync(binary)) {
11
+ console.error("The dotagents binary was not downloaded during install.");
12
+ console.error(`Run: node ${path.join(path.dirname(__dirname), "install.js")}`);
13
+ console.error("Or reinstall with install scripts enabled: npm rebuild -g dotagents");
14
+ process.exit(1);
15
+ }
16
+
17
+ const result = spawnSync(binary, process.argv.slice(2), { stdio: "inherit" });
18
+ if (result.error) {
19
+ console.error(result.error.message);
20
+ process.exit(1);
21
+ }
22
+ process.exit(result.status === null ? 1 : result.status);
package/install.js ADDED
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+
3
+ // Downloads the dotagents binary for this platform from GitHub Releases and
4
+ // verifies its sha256 against the published checksums.txt before extraction.
5
+ // No code from the archive is executed; only the checksum-verified binary is
6
+ // unpacked next to the bin shim.
7
+
8
+ const crypto = require("crypto");
9
+ const fs = require("fs");
10
+ const https = require("https");
11
+ const os = require("os");
12
+ const path = require("path");
13
+ const { spawnSync } = require("child_process");
14
+
15
+ const REPO = "yourconscience/dotagents";
16
+ const MAX_REDIRECTS = 5;
17
+
18
+ function platformTarget(platform = process.platform, arch = process.arch) {
19
+ const goos = platform === "darwin" ? "darwin" : platform === "linux" ? "linux" : null;
20
+ const goarch = arch === "arm64" ? "arm64" : arch === "x64" ? "amd64" : null;
21
+ if (!goos || !goarch) {
22
+ return null;
23
+ }
24
+ return { goos, goarch };
25
+ }
26
+
27
+ function assetName(version, target) {
28
+ return `dotagents_${version}_${target.goos}_${target.goarch}.tar.gz`;
29
+ }
30
+
31
+ function releaseAssetUrl(version, name) {
32
+ return `https://github.com/${REPO}/releases/download/v${version}/${name}`;
33
+ }
34
+
35
+ function sha256(buffer) {
36
+ return crypto.createHash("sha256").update(buffer).digest("hex");
37
+ }
38
+
39
+ function expectedChecksum(checksumsText, filename) {
40
+ for (const line of checksumsText.split("\n")) {
41
+ const parts = line.trim().split(/\s+/);
42
+ if (parts.length === 2 && parts[1] === filename) {
43
+ return parts[0];
44
+ }
45
+ }
46
+ return null;
47
+ }
48
+
49
+ function fetchBuffer(url, redirects = 0) {
50
+ return new Promise((resolve, reject) => {
51
+ https
52
+ .get(url, (response) => {
53
+ if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
54
+ response.resume();
55
+ if (redirects >= MAX_REDIRECTS) {
56
+ reject(new Error(`too many redirects fetching ${url}`));
57
+ return;
58
+ }
59
+ fetchBuffer(new URL(response.headers.location, url).toString(), redirects + 1).then(resolve, reject);
60
+ return;
61
+ }
62
+ if (response.statusCode !== 200) {
63
+ response.resume();
64
+ reject(new Error(`${response.statusCode} ${response.statusMessage} fetching ${url}`));
65
+ return;
66
+ }
67
+ const chunks = [];
68
+ response.on("data", (chunk) => chunks.push(chunk));
69
+ response.on("end", () => resolve(Buffer.concat(chunks)));
70
+ response.on("error", reject);
71
+ })
72
+ .on("error", reject);
73
+ });
74
+ }
75
+
76
+ async function install(options = {}) {
77
+ const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8"));
78
+ const version = options.version || process.env.DOTAGENTS_VERSION || pkg.version;
79
+ const target = platformTarget(options.platform, options.arch);
80
+ if (!target) {
81
+ throw new Error(
82
+ `dotagents has no prebuilt binary for ${options.platform || process.platform}/${options.arch || process.arch}; use brew or scripts/install.sh instead`,
83
+ );
84
+ }
85
+
86
+ const name = assetName(version, target);
87
+ const [archive, checksums] = await Promise.all([
88
+ fetchBuffer(releaseAssetUrl(version, name)),
89
+ fetchBuffer(releaseAssetUrl(version, "checksums.txt")),
90
+ ]);
91
+
92
+ const want = expectedChecksum(checksums.toString("utf8"), name);
93
+ const got = sha256(archive);
94
+ if (!want || want !== got) {
95
+ throw new Error(`checksum mismatch for ${name}: expected ${want || "<missing>"}, got ${got}`);
96
+ }
97
+
98
+ const binDir = path.join(__dirname, "bin");
99
+ fs.mkdirSync(binDir, { recursive: true });
100
+ const tmpArchive = path.join(os.tmpdir(), `${name}.${process.pid}`);
101
+ try {
102
+ fs.writeFileSync(tmpArchive, archive);
103
+ const extract = spawnSync("tar", ["-xzf", tmpArchive, "-C", binDir], { stdio: "pipe", encoding: "utf8" });
104
+ if (extract.error) {
105
+ throw extract.error;
106
+ }
107
+ if (extract.status !== 0) {
108
+ throw new Error(`tar exited ${extract.status}: ${extract.stderr}`);
109
+ }
110
+ } finally {
111
+ fs.rmSync(tmpArchive, { force: true });
112
+ }
113
+
114
+ const binary = path.join(binDir, "dotagents");
115
+ fs.chmodSync(binary, 0o755);
116
+ return binary;
117
+ }
118
+
119
+ module.exports = { platformTarget, assetName, releaseAssetUrl, sha256, expectedChecksum, install };
120
+
121
+ if (require.main === module) {
122
+ install()
123
+ .then((binary) => {
124
+ console.log(`dotagents installed to ${binary}`);
125
+ })
126
+ .catch((error) => {
127
+ console.error(`dotagents postinstall failed: ${error.message}`);
128
+ console.error("The CLI still works via brew or scripts/install.sh; see the README.");
129
+ process.exit(1);
130
+ });
131
+ }
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@your_conscience/dotagents",
3
+ "version": "0.7.0",
4
+ "description": "Dotfiles for your AI agents: one ~/.agents repo synced to every coding agent.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/yourconscience/dotagents.git"
9
+ },
10
+ "bin": {
11
+ "dotagents": "bin/dotagents.js"
12
+ },
13
+ "scripts": {
14
+ "postinstall": "node install.js",
15
+ "test": "node --test"
16
+ },
17
+ "files": [
18
+ "bin/",
19
+ "install.js"
20
+ ],
21
+ "engines": {
22
+ "node": ">=18"
23
+ }
24
+ }