dejima 0.8.1 → 0.8.7
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 +12 -11
- package/bin/dejima.js +37 -8
- package/package.json +9 -5
- package/install.js +0 -169
package/README.md
CHANGED
|
@@ -8,10 +8,11 @@ npm install -g dejima
|
|
|
8
8
|
dejima --version
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
The prebuilt `dejima` binary for your platform ships inside a per-platform
|
|
12
|
+
package (`@dejima/cli-<platform>-<arch>`) that npm installs automatically as an
|
|
13
|
+
optional dependency — only the one matching your OS/CPU. There's **no install
|
|
14
|
+
script** (so it works under npm 11's default script-blocking), and no Go
|
|
15
|
+
toolchain required; the `dejima` command lands on your PATH.
|
|
15
16
|
|
|
16
17
|
## What this installs (and what it doesn't)
|
|
17
18
|
|
|
@@ -46,13 +47,13 @@ See <https://dejima.tech/> for the full picture.
|
|
|
46
47
|
|
|
47
48
|
## Environment knobs
|
|
48
49
|
|
|
49
|
-
- `
|
|
50
|
-
|
|
51
|
-
- `DEJIMA_BINARY=/path/to/dejima` — run a specific binary instead of the
|
|
52
|
-
downloaded one.
|
|
50
|
+
- `DEJIMA_BINARY=/path/to/dejima` — run a specific binary instead of the bundled
|
|
51
|
+
platform one (offline installs, `npm i --no-optional`, or a binary you built).
|
|
53
52
|
|
|
54
53
|
## Notes
|
|
55
54
|
|
|
56
|
-
- Requires Node 16
|
|
57
|
-
- macOS binaries are currently unsigned
|
|
58
|
-
quarantine
|
|
55
|
+
- Requires Node 16+.
|
|
56
|
+
- macOS binaries are currently unsigned. When downloaded via npm, Gatekeeper may
|
|
57
|
+
quarantine them; if macOS blocks the binary, clear it with
|
|
58
|
+
`xattr -d com.apple.quarantine "$(npm root -g)/dejima/node_modules/@dejima/cli-darwin-arm64/bin/dejima"`
|
|
59
|
+
(adjust the arch). Notarization is on the roadmap.
|
package/bin/dejima.js
CHANGED
|
@@ -1,20 +1,49 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
2
|
+
// Launcher for the `dejima` CLI. The real binary ships INSIDE a per-platform
|
|
3
|
+
// package (@dejima/cli-<platform>-<arch>) declared as an optionalDependency, so
|
|
4
|
+
// npm installs only the one matching this host (os/cpu fields) and skips the
|
|
5
|
+
// rest. There is NO postinstall download — that was blocked by npm 11's default
|
|
6
|
+
// script-blocking and left the CLI non-functional. This shim resolves the
|
|
7
|
+
// platform package and execs its binary, forwarding argv, stdio, and exit code.
|
|
8
|
+
//
|
|
9
|
+
// DEJIMA_BINARY overrides the resolved path (offline installs / CI / a binary
|
|
10
|
+
// you provide yourself, e.g. when installed with --no-optional).
|
|
5
11
|
'use strict';
|
|
6
12
|
|
|
7
13
|
const fs = require('fs');
|
|
8
14
|
const path = require('path');
|
|
9
15
|
const { spawnSync } = require('child_process');
|
|
10
16
|
|
|
17
|
+
// node's process.platform is already darwin|linux|win32; process.arch is
|
|
18
|
+
// x64|arm64 — the exact suffixes our platform packages use.
|
|
19
|
+
const pkgName = `@dejima/cli-${process.platform}-${process.arch}`;
|
|
11
20
|
const exe = process.platform === 'win32' ? 'dejima.exe' : 'dejima';
|
|
12
|
-
const binary = process.env.DEJIMA_BINARY || path.join(__dirname, '..', 'binary', exe);
|
|
13
21
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
22
|
+
function resolveBinary() {
|
|
23
|
+
if (process.env.DEJIMA_BINARY) {
|
|
24
|
+
return process.env.DEJIMA_BINARY;
|
|
25
|
+
}
|
|
26
|
+
// Resolve the package's own package.json (always present + resolvable) and
|
|
27
|
+
// join the binary path, rather than require.resolve-ing the extensionless
|
|
28
|
+
// binary directly — more robust across node versions and bundlers. esbuild,
|
|
29
|
+
// swc and turbo resolve their platform binaries the same way.
|
|
30
|
+
try {
|
|
31
|
+
const pkgJson = require.resolve(`${pkgName}/package.json`);
|
|
32
|
+
return path.join(path.dirname(pkgJson), 'bin', exe);
|
|
33
|
+
} catch (_) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const binary = resolveBinary();
|
|
39
|
+
if (!binary || !fs.existsSync(binary)) {
|
|
40
|
+
console.error(`dejima: no prebuilt binary for ${process.platform}-${process.arch}.`);
|
|
41
|
+
console.error(`Expected the optional dependency ${pkgName} to be installed.`);
|
|
42
|
+
console.error('This usually means the platform is unsupported, or the package was');
|
|
43
|
+
console.error('installed with --no-optional / --omit=optional. Alternatives:');
|
|
44
|
+
console.error(' • curl -fsSL https://dejima.tech/install-client.sh | bash');
|
|
45
|
+
console.error(' • brew install aoos/dejima/dejima');
|
|
46
|
+
console.error(' • set DEJIMA_BINARY to the path of a dejima binary you provide.');
|
|
18
47
|
process.exit(1);
|
|
19
48
|
}
|
|
20
49
|
|
package/package.json
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dejima",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.7",
|
|
4
4
|
"description": "CLI for Dejima — run a fleet of isolated AI coding agents on hardware you own.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"bin": {
|
|
7
7
|
"dejima": "bin/dejima.js"
|
|
8
8
|
},
|
|
9
|
-
"scripts": {
|
|
10
|
-
"postinstall": "node ./install.js"
|
|
11
|
-
},
|
|
12
9
|
"files": [
|
|
13
10
|
"bin/dejima.js",
|
|
14
|
-
"install.js",
|
|
15
11
|
"README.md"
|
|
16
12
|
],
|
|
13
|
+
"optionalDependencies": {
|
|
14
|
+
"@dejima/cli-darwin-arm64": "0.8.7",
|
|
15
|
+
"@dejima/cli-darwin-x64": "0.8.7",
|
|
16
|
+
"@dejima/cli-linux-arm64": "0.8.7",
|
|
17
|
+
"@dejima/cli-linux-x64": "0.8.7",
|
|
18
|
+
"@dejima/cli-win32-arm64": "0.8.7",
|
|
19
|
+
"@dejima/cli-win32-x64": "0.8.7"
|
|
20
|
+
},
|
|
17
21
|
"engines": {
|
|
18
22
|
"node": ">=16"
|
|
19
23
|
},
|
package/install.js
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Postinstall hook for the `dejima` npm package.
|
|
3
|
-
//
|
|
4
|
-
// Downloads the dejima CLI binary that matches this package's version from the
|
|
5
|
-
// GitHub Release, verifies its SHA256 against the release's SHA256SUMS, and
|
|
6
|
-
// unpacks it into ./binary/. The bin shim (bin/dejima.js) execs it.
|
|
7
|
-
//
|
|
8
|
-
// This package ships only the CLI *client* — the cross-platform binary you
|
|
9
|
-
// drive a Dejima host with. The daemon (dejimad) and the island image are
|
|
10
|
-
// Unix-host-only; install those with `curl -fsSL https://dejima.tech/install.sh
|
|
11
|
-
// | bash` or Homebrew. See README.md.
|
|
12
|
-
//
|
|
13
|
-
// Knobs:
|
|
14
|
-
// DEJIMA_SKIP_DOWNLOAD=1 skip the download (e.g. offline CI); provide your
|
|
15
|
-
// own binary via DEJIMA_BINARY at runtime instead.
|
|
16
|
-
'use strict';
|
|
17
|
-
|
|
18
|
-
const fs = require('fs');
|
|
19
|
-
const path = require('path');
|
|
20
|
-
const https = require('https');
|
|
21
|
-
const crypto = require('crypto');
|
|
22
|
-
const { execFileSync } = require('child_process');
|
|
23
|
-
|
|
24
|
-
const REPO = 'aoos/dejima';
|
|
25
|
-
const pkg = require('./package.json');
|
|
26
|
-
const version = String(pkg.version).replace(/^v/, '');
|
|
27
|
-
const tag = `v${version}`;
|
|
28
|
-
|
|
29
|
-
if (process.env.DEJIMA_SKIP_DOWNLOAD === '1') {
|
|
30
|
-
console.log('dejima: DEJIMA_SKIP_DOWNLOAD=1 set — skipping binary download.');
|
|
31
|
-
process.exit(0);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function mapPlatform() {
|
|
35
|
-
switch (process.platform) {
|
|
36
|
-
case 'darwin': return 'darwin';
|
|
37
|
-
case 'linux': return 'linux';
|
|
38
|
-
case 'win32': return 'windows';
|
|
39
|
-
default: throw new Error(`unsupported platform: ${process.platform}`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
function mapArch() {
|
|
43
|
-
switch (process.arch) {
|
|
44
|
-
case 'x64': return 'amd64';
|
|
45
|
-
case 'arm64': return 'arm64';
|
|
46
|
-
default: throw new Error(`unsupported arch: ${process.arch}`);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const plat = mapPlatform();
|
|
51
|
-
const arch = mapArch();
|
|
52
|
-
const ext = plat === 'windows' ? 'zip' : 'tar.gz';
|
|
53
|
-
const asset = `dejima_${tag}_${plat}_${arch}.${ext}`;
|
|
54
|
-
const base = `https://github.com/${REPO}/releases/download/${tag}`;
|
|
55
|
-
|
|
56
|
-
// GET that follows redirects (GitHub release assets 302 to a CDN) and buffers
|
|
57
|
-
// the body. Caps redirects so a misconfigured mirror can't loop forever.
|
|
58
|
-
function get(url, redirects = 0) {
|
|
59
|
-
return new Promise((resolve, reject) => {
|
|
60
|
-
if (redirects > 10) return reject(new Error('too many redirects'));
|
|
61
|
-
https
|
|
62
|
-
.get(url, { headers: { 'User-Agent': 'dejima-npm-installer' } }, (res) => {
|
|
63
|
-
const { statusCode, headers } = res;
|
|
64
|
-
if (statusCode >= 300 && statusCode < 400 && headers.location) {
|
|
65
|
-
res.resume();
|
|
66
|
-
resolve(get(headers.location, redirects + 1));
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
if (statusCode !== 200) {
|
|
70
|
-
res.resume();
|
|
71
|
-
reject(new Error(`GET ${url} -> HTTP ${statusCode}`));
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const chunks = [];
|
|
75
|
-
res.on('data', (c) => chunks.push(c));
|
|
76
|
-
res.on('end', () => resolve(Buffer.concat(chunks)));
|
|
77
|
-
})
|
|
78
|
-
.on('error', reject);
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
async function verifyChecksum(tarball) {
|
|
83
|
-
let sums;
|
|
84
|
-
try {
|
|
85
|
-
sums = (await get(`${base}/SHA256SUMS`)).toString('utf8');
|
|
86
|
-
} catch (e) {
|
|
87
|
-
console.warn(`dejima: could not fetch SHA256SUMS (${e.message}) — skipping checksum.`);
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
const row = sums
|
|
91
|
-
.split('\n')
|
|
92
|
-
.map((l) => l.trim().split(/\s+/))
|
|
93
|
-
.find((p) => p[1] === asset);
|
|
94
|
-
if (!row) {
|
|
95
|
-
console.warn(`dejima: ${asset} not listed in SHA256SUMS — skipping checksum.`);
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
const got = crypto.createHash('sha256').update(tarball).digest('hex');
|
|
99
|
-
if (got !== row[0]) {
|
|
100
|
-
throw new Error(`checksum mismatch for ${asset}\n want ${row[0]}\n got ${got}`);
|
|
101
|
-
}
|
|
102
|
-
console.log('dejima: checksum OK');
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async function main() {
|
|
106
|
-
const binDir = path.join(__dirname, 'binary');
|
|
107
|
-
fs.mkdirSync(binDir, { recursive: true });
|
|
108
|
-
|
|
109
|
-
console.log(`dejima: downloading ${asset} …`);
|
|
110
|
-
let tarball;
|
|
111
|
-
try {
|
|
112
|
-
tarball = await get(`${base}/${asset}`);
|
|
113
|
-
} catch (e) {
|
|
114
|
-
// A 404 here almost always means there's no published Release for this exact
|
|
115
|
-
// version/platform yet (or the tag isn't out). Say so plainly instead of
|
|
116
|
-
// surfacing a raw "HTTP 404" the way a generic failure would.
|
|
117
|
-
if (/HTTP 404/.test(e.message)) {
|
|
118
|
-
throw new Error(
|
|
119
|
-
`no prebuilt binary for this version/platform yet — ${asset} isn't in ` +
|
|
120
|
-
`release ${tag}.\n See https://github.com/${REPO}/releases for what's published.`
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
throw e;
|
|
124
|
-
}
|
|
125
|
-
await verifyChecksum(tarball);
|
|
126
|
-
|
|
127
|
-
// Unpack with the system tar. bsdtar (Windows 10+ `tar.exe`) reads .zip too;
|
|
128
|
-
// gnutar/bsdtar read .tar.gz on Unix. Archives carry dejima (+ dejimad on
|
|
129
|
-
// Unix, which we leave unused) and LICENSE/README.
|
|
130
|
-
const archivePath = path.join(binDir, asset);
|
|
131
|
-
fs.writeFileSync(archivePath, tarball);
|
|
132
|
-
const flags = ext === 'tar.gz' ? ['-xzf'] : ['-xf'];
|
|
133
|
-
execFileSync('tar', [...flags, archivePath, '-C', binDir], { stdio: 'inherit' });
|
|
134
|
-
fs.unlinkSync(archivePath);
|
|
135
|
-
|
|
136
|
-
const exe = plat === 'windows' ? 'dejima.exe' : 'dejima';
|
|
137
|
-
const exePath = path.join(binDir, exe);
|
|
138
|
-
if (!fs.existsSync(exePath)) {
|
|
139
|
-
throw new Error(`expected ${exe} in ${asset}, but it was not found after extraction`);
|
|
140
|
-
}
|
|
141
|
-
if (plat !== 'windows') fs.chmodSync(exePath, 0o755);
|
|
142
|
-
|
|
143
|
-
// Drop the extras the archive carries (dejimad, LICENSE, README) — this
|
|
144
|
-
// package is the CLI client only, so keep just the one binary.
|
|
145
|
-
for (const f of fs.readdirSync(binDir)) {
|
|
146
|
-
if (f !== exe) fs.rmSync(path.join(binDir, f), { force: true });
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Strip the macOS quarantine xattr — binaries are unsigned until notarization
|
|
150
|
-
// lands, so Gatekeeper would otherwise block the downloaded executable.
|
|
151
|
-
if (plat === 'darwin') {
|
|
152
|
-
try {
|
|
153
|
-
execFileSync('xattr', ['-d', 'com.apple.quarantine', exePath], { stdio: 'ignore' });
|
|
154
|
-
} catch (_) {
|
|
155
|
-
/* attribute may be absent; ignore */
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
console.log(`dejima ${version} installed → ${exePath}`);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
main().catch((err) => {
|
|
163
|
-
console.error(`\ndejima: install failed: ${err.message}\n`);
|
|
164
|
-
console.error('Alternatives:');
|
|
165
|
-
console.error(' • curl -fsSL https://dejima.tech/install-client.sh | bash');
|
|
166
|
-
console.error(' • brew install aoos/dejima/dejima');
|
|
167
|
-
console.error(' • set DEJIMA_SKIP_DOWNLOAD=1 and point DEJIMA_BINARY at a dejima binary.');
|
|
168
|
-
process.exit(1);
|
|
169
|
-
});
|