@octos-org/octos 1.1.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.
package/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # @octos-org/octos
2
+
3
+ One-line installer for the [Octos](https://github.com/octos-org/octos) server — a
4
+ Rust-native, API-first Agentic OS.
5
+
6
+ ```bash
7
+ npm install -g @octos-org/octos
8
+ octos serve
9
+ ```
10
+
11
+ This package downloads the prebuilt release bundle for your platform and installs
12
+ the `octos` server **together with its bundled skills** (`news_fetch`,
13
+ `deep-search`, `deep_crawl`, `send_email`, `account_manager`, `voice`, `clock`,
14
+ `weather`). The skills are kept as siblings of the `octos` binary so that
15
+ `octos serve` can discover them at startup.
16
+
17
+ ## Supported platforms
18
+
19
+ - macOS Apple Silicon (`darwin-arm64`)
20
+ - Linux x86_64 (`linux-x64`)
21
+ - Linux ARM64 (`linux-arm64`)
22
+ - Windows x64 (`win32-x64`)
23
+
24
+ macOS Intel is not supported (no prebuilt build is published).
25
+
26
+ ## Environment overrides
27
+
28
+ - `OCTOS_SKIP_DOWNLOAD=1` — skip the postinstall download (offline / CI).
29
+ - `OCTOS_BUNDLE_URL=<url>` — install from a specific bundle URL (`file://` works).
30
+ - `HTTPS_PROXY` — honored when downloading.
31
+
32
+ ## Alternatives
33
+
34
+ ```bash
35
+ # Homebrew
36
+ brew install octos-org/tap/octos
37
+
38
+ # Shell installer (sets up octos serve as a service)
39
+ curl -fsSL https://github.com/octos-org/octos/releases/latest/download/install.sh | bash
40
+ ```
package/bin/octos.js ADDED
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env node
2
+ // Launcher: spawn the real native `octos` binary that postinstall placed in
3
+ // vendor/, forwarding all args, stdio, and the exit code.
4
+ //
5
+ // The skills bundled next to it (vendor/news_fetch, deep-search, ...) are
6
+ // discovered by `octos serve` as siblings of this binary at runtime — so the
7
+ // native binary must run from vendor/, not be copied elsewhere.
8
+
9
+ "use strict";
10
+
11
+ const os = require("os");
12
+ const path = require("path");
13
+ const fs = require("fs");
14
+ const { spawnSync } = require("child_process");
15
+
16
+ const exeSuffix = os.platform() === "win32" ? ".exe" : "";
17
+ const binary = path.join(__dirname, "..", "vendor", "octos" + exeSuffix);
18
+
19
+ if (!fs.existsSync(binary)) {
20
+ console.error(
21
+ "[@octos-org/octos] native binary not found at " +
22
+ binary +
23
+ ".\nThe postinstall download did not run (was the package installed with " +
24
+ "--ignore-scripts?).\nReinstall without --ignore-scripts, or run " +
25
+ "`node " +
26
+ path.join(__dirname, "..", "install.js") +
27
+ "` manually."
28
+ );
29
+ process.exit(1);
30
+ }
31
+
32
+ const result = spawnSync(binary, process.argv.slice(2), { stdio: "inherit" });
33
+
34
+ if (result.error) {
35
+ console.error("[@octos-org/octos] failed to launch octos: " + result.error.message);
36
+ process.exit(1);
37
+ }
38
+
39
+ // Propagate a signal-terminated child as a non-zero exit; otherwise the code.
40
+ if (result.signal) {
41
+ process.exit(1);
42
+ }
43
+ process.exit(result.status === null ? 1 : result.status);
package/install.js ADDED
@@ -0,0 +1,270 @@
1
+ #!/usr/bin/env node
2
+ // postinstall: download the prebuilt octos release bundle for this platform,
3
+ // extract every binary into vendor/, and assert the full skill set is present.
4
+ //
5
+ // The bundle ships `octos` alongside its 8 skill binaries. At `octos serve`
6
+ // startup, bootstrap discovers those skills as SIBLINGS of the resolved
7
+ // `octos` executable, so they must all land in the same dir (vendor/).
8
+ //
9
+ // Escapes:
10
+ // OCTOS_SKIP_DOWNLOAD=1 skip the download entirely (CI / offline installs)
11
+ // OCTOS_BUNDLE_URL=<url> override the download URL (file:// supported for tests)
12
+
13
+ "use strict";
14
+
15
+ const fs = require("fs");
16
+ const os = require("os");
17
+ const path = require("path");
18
+ const https = require("https");
19
+ const http = require("http");
20
+ const { spawnSync } = require("child_process");
21
+ const { URL } = require("url");
22
+
23
+ const VENDOR_DIR = path.join(__dirname, "vendor");
24
+ const REPO = "octos-org/octos";
25
+
26
+ // Every binary the release bundle is expected to contain. `octos` is the
27
+ // server; the rest are the bundled skills discovered as siblings at runtime.
28
+ const EXPECTED_BINS = [
29
+ "octos",
30
+ "news_fetch",
31
+ "deep-search",
32
+ "deep_crawl",
33
+ "send_email",
34
+ "account_manager",
35
+ "voice",
36
+ "clock",
37
+ "weather",
38
+ ];
39
+
40
+ function fail(msg) {
41
+ console.error("\n[@octos-org/octos] install failed: " + msg + "\n");
42
+ process.exit(1);
43
+ }
44
+
45
+ // Map this Node platform/arch to the release triple + archive extension.
46
+ // Mirrors scripts/install.sh platform detection.
47
+ function resolveTarget() {
48
+ const platform = os.platform();
49
+ const arch = os.arch();
50
+
51
+ if (platform === "darwin") {
52
+ if (arch === "arm64") {
53
+ return { triple: "aarch64-apple-darwin", ext: "tar.gz" };
54
+ }
55
+ fail(
56
+ "octos requires Apple Silicon on macOS; no x86_64 macOS build is published."
57
+ );
58
+ }
59
+ if (platform === "linux") {
60
+ if (arch === "x64") {
61
+ return { triple: "x86_64-unknown-linux-gnu", ext: "tar.gz" };
62
+ }
63
+ if (arch === "arm64") {
64
+ return { triple: "aarch64-unknown-linux-gnu", ext: "tar.gz" };
65
+ }
66
+ fail("Unsupported Linux architecture: " + arch + " (need x64 or arm64).");
67
+ }
68
+ if (platform === "win32") {
69
+ if (arch === "x64") {
70
+ return { triple: "x86_64-pc-windows-msvc", ext: "zip" };
71
+ }
72
+ fail("Unsupported Windows architecture: " + arch + " (need x64).");
73
+ }
74
+ fail("Unsupported platform: " + platform);
75
+ }
76
+
77
+ // Resolve the release tag from the package version. CI sets the package
78
+ // version to the released tag (minus the leading "v"), so the tag is
79
+ // "v" + version. The "0.0.0-managed" placeholder is never published.
80
+ function resolveTag() {
81
+ const version = require("./package.json").version;
82
+ if (version === "0.0.0-managed") {
83
+ fail(
84
+ "package version is the unmanaged placeholder (0.0.0-managed); " +
85
+ "this build was not produced by the publish workflow. " +
86
+ "Set OCTOS_BUNDLE_URL to install manually."
87
+ );
88
+ }
89
+ return version.startsWith("v") ? version : "v" + version;
90
+ }
91
+
92
+ function bundleUrl(target) {
93
+ if (process.env.OCTOS_BUNDLE_URL) {
94
+ return process.env.OCTOS_BUNDLE_URL;
95
+ }
96
+ const tag = resolveTag();
97
+ return (
98
+ "https://github.com/" +
99
+ REPO +
100
+ "/releases/download/" +
101
+ tag +
102
+ "/octos-bundle-" +
103
+ target.triple +
104
+ "." +
105
+ target.ext
106
+ );
107
+ }
108
+
109
+ // Download to a file, following redirects, honoring HTTPS_PROXY when set.
110
+ function download(urlStr, destFile, redirects, cb) {
111
+ if (redirects > 10) {
112
+ return cb(new Error("too many redirects"));
113
+ }
114
+
115
+ let url;
116
+ try {
117
+ url = new URL(urlStr);
118
+ } catch (e) {
119
+ return cb(new Error("invalid URL: " + urlStr));
120
+ }
121
+
122
+ // file:// override — copy locally (used by tests / offline installs).
123
+ // Use fileURLToPath so Windows `file:///C:/...` maps correctly (pathname
124
+ // would yield `/C:/...`).
125
+ if (url.protocol === "file:") {
126
+ try {
127
+ fs.copyFileSync(require("url").fileURLToPath(url), destFile);
128
+ return cb(null);
129
+ } catch (e) {
130
+ return cb(new Error("could not read " + urlStr + ": " + e.message));
131
+ }
132
+ }
133
+
134
+ // Direct request only. Corporate HTTP/HTTPS proxies are NOT supported here
135
+ // (Node core has no CONNECT helper, and absolute-form GET to an HTTP proxy
136
+ // fails for https targets). Behind a proxy: pre-download the bundle and point
137
+ // the installer at it with OCTOS_BUNDLE_URL=file:///path, or set
138
+ // OCTOS_SKIP_DOWNLOAD=1 and place the binaries under vendor/ yourself.
139
+ const transport = url.protocol === "https:" ? https : http;
140
+ const requestOptions = {
141
+ protocol: url.protocol,
142
+ hostname: url.hostname,
143
+ port: url.port,
144
+ path: url.pathname + url.search,
145
+ headers: { "User-Agent": "octos-npm-installer" },
146
+ };
147
+
148
+ transport
149
+ .get(requestOptions, (res) => {
150
+ // Follow redirects (GitHub release assets redirect to a CDN).
151
+ if (
152
+ res.statusCode >= 300 &&
153
+ res.statusCode < 400 &&
154
+ res.headers.location
155
+ ) {
156
+ res.resume();
157
+ const next = new URL(res.headers.location, urlStr).toString();
158
+ return download(next, destFile, redirects + 1, cb);
159
+ }
160
+ if (res.statusCode !== 200) {
161
+ res.resume();
162
+ return cb(
163
+ new Error("HTTP " + res.statusCode + " fetching " + urlStr)
164
+ );
165
+ }
166
+ const out = fs.createWriteStream(destFile);
167
+ res.pipe(out);
168
+ out.on("finish", () => out.close(() => cb(null)));
169
+ out.on("error", (e) => cb(e));
170
+ })
171
+ .on("error", (e) => cb(e));
172
+ }
173
+
174
+ // Extract the archive into vendor/ using the platform's native tool.
175
+ function extract(archiveFile, ext) {
176
+ fs.mkdirSync(VENDOR_DIR, { recursive: true });
177
+ let res;
178
+ if (ext === "zip") {
179
+ if (os.platform() === "win32") {
180
+ res = spawnSync(
181
+ "powershell",
182
+ [
183
+ "-NoProfile",
184
+ "-Command",
185
+ "Expand-Archive -Force -LiteralPath '" +
186
+ archiveFile +
187
+ "' -DestinationPath '" +
188
+ VENDOR_DIR +
189
+ "'",
190
+ ],
191
+ { stdio: "inherit" }
192
+ );
193
+ } else {
194
+ res = spawnSync("unzip", ["-o", archiveFile, "-d", VENDOR_DIR], {
195
+ stdio: "inherit",
196
+ });
197
+ }
198
+ } else {
199
+ res = spawnSync("tar", ["-xzf", archiveFile, "-C", VENDOR_DIR], {
200
+ stdio: "inherit",
201
+ });
202
+ }
203
+ if (res.error) {
204
+ fail("extraction tool failed to launch: " + res.error.message);
205
+ }
206
+ if (res.status !== 0) {
207
+ fail("extraction exited with status " + res.status);
208
+ }
209
+ }
210
+
211
+ // Make all extracted binaries executable and assert the full set is present.
212
+ function finalizeAndVerify() {
213
+ const exeSuffix = os.platform() === "win32" ? ".exe" : "";
214
+ const missing = [];
215
+ for (const name of EXPECTED_BINS) {
216
+ const p = path.join(VENDOR_DIR, name + exeSuffix);
217
+ if (fs.existsSync(p)) {
218
+ try {
219
+ fs.chmodSync(p, 0o755);
220
+ } catch (e) {
221
+ // Best-effort on Windows where chmod is largely a no-op.
222
+ }
223
+ } else {
224
+ missing.push(name + exeSuffix);
225
+ }
226
+ }
227
+ if (missing.length > 0) {
228
+ fail(
229
+ "the downloaded bundle is missing expected binaries: " +
230
+ missing.join(", ") +
231
+ ". The release archive may be corrupt or incomplete."
232
+ );
233
+ }
234
+ }
235
+
236
+ function main() {
237
+ if (process.env.OCTOS_SKIP_DOWNLOAD === "1") {
238
+ console.log(
239
+ "[@octos-org/octos] OCTOS_SKIP_DOWNLOAD=1 set; skipping bundle download."
240
+ );
241
+ return;
242
+ }
243
+
244
+ const target = resolveTarget();
245
+ const url = bundleUrl(target);
246
+ console.log("[@octos-org/octos] downloading " + url);
247
+
248
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "octos-npm-"));
249
+ const archiveFile = path.join(tmpDir, "bundle." + target.ext);
250
+
251
+ download(url, archiveFile, 0, (err) => {
252
+ if (err) {
253
+ fail(err.message);
254
+ }
255
+ extract(archiveFile, target.ext);
256
+ finalizeAndVerify();
257
+ try {
258
+ fs.rmSync(tmpDir, { recursive: true, force: true });
259
+ } catch (e) {
260
+ // non-fatal cleanup failure
261
+ }
262
+ console.log(
263
+ "[@octos-org/octos] installed octos + " +
264
+ (EXPECTED_BINS.length - 1) +
265
+ " bundled skills into vendor/"
266
+ );
267
+ });
268
+ }
269
+
270
+ main();
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@octos-org/octos",
3
+ "version": "1.1.0",
4
+ "description": "Rust-native, API-first Agentic OS server (octos serve + bundled skills). Installs the prebuilt release bundle.",
5
+ "homepage": "https://github.com/octos-org/octos",
6
+ "license": "Apache-2.0",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/octos-org/octos.git"
10
+ },
11
+ "bin": {
12
+ "octos": "bin/octos.js"
13
+ },
14
+ "scripts": {
15
+ "postinstall": "node install.js"
16
+ },
17
+ "files": [
18
+ "bin",
19
+ "install.js",
20
+ "README.md"
21
+ ],
22
+ "os": [
23
+ "darwin",
24
+ "linux",
25
+ "win32"
26
+ ],
27
+ "cpu": [
28
+ "arm64",
29
+ "x64"
30
+ ],
31
+ "engines": {
32
+ "node": ">=18"
33
+ }
34
+ }