@ours.network/install 0.12.0-nightly.6 → 0.12.0-nightly.8
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/install.mjs +11 -6
- package/lib/logic.mjs +39 -0
- package/package.json +1 -1
package/install.mjs
CHANGED
|
@@ -24,10 +24,14 @@ import { askLine, askYesNo, isCancel } from './lib/prompt.mjs';
|
|
|
24
24
|
import {
|
|
25
25
|
suggestPort, parsePort, validateBroker, mergeConfig, parseVersion, parseStatus,
|
|
26
26
|
detectPlatform, classifyHarnessProbe, buildHandoffPrompt,
|
|
27
|
-
DEFAULT_PORT,
|
|
27
|
+
DEFAULT_PORT, resolveChannel, pkgSpec,
|
|
28
28
|
} from './lib/logic.mjs';
|
|
29
29
|
|
|
30
30
|
const NPM = process.env.OURS_NPM || 'npm';
|
|
31
|
+
// Release channel: OURS_CHANNEL=nightly installs @nightly for mcp/tg-connector/plugin
|
|
32
|
+
// launchers but keeps @ours.network/fleet at @latest (fleet has no nightly). Default: latest.
|
|
33
|
+
const CHANNEL = resolveChannel(process.env.OURS_CHANNEL || process.env.OURS_INSTALL_CHANNEL);
|
|
34
|
+
const spec = (pkgKey) => pkgSpec(pkgKey, CHANNEL); // → "@ours.network/<key>@<tag>"
|
|
31
35
|
let DRY = !!process.env.OURS_INSTALL_DRY_RUN;
|
|
32
36
|
const SELFHOST_URL = 'ours.network';
|
|
33
37
|
const CLAUDE_MARKET = 'adapt-toolkit/ours-claude-marketplace';
|
|
@@ -317,7 +321,7 @@ async function main() {
|
|
|
317
321
|
// Without a daemon the rest is moot; go straight to the summary.
|
|
318
322
|
return endScreen({ ttyFd, summary, chosenPort, chosenBroker });
|
|
319
323
|
}
|
|
320
|
-
await actSpin(
|
|
324
|
+
await actSpin(`ensuring ${spec('mcp')}…`, `npm i -g ${spec('mcp')}`, () => runAsync(NPM, ['i', '-g', spec('mcp')]));
|
|
321
325
|
const patch = { port: chosenPort };
|
|
322
326
|
if (chosenBroker) patch.brokerUrl = chosenBroker;
|
|
323
327
|
await act(`write config (${configPath()}) with port ${chosenPort}${chosenBroker ? ' + custom broker' : ''}`, async () => { writeConfigPatch(patch); return { ok: true }; });
|
|
@@ -332,7 +336,7 @@ async function main() {
|
|
|
332
336
|
const running = daemonRunning();
|
|
333
337
|
const upd = yes(` ours core is installed (${before || '?'}) — check for an update now?`, false);
|
|
334
338
|
if (upd) {
|
|
335
|
-
await actSpin(
|
|
339
|
+
await actSpin(`updating ${spec('mcp')}…`, `npm i -g ${spec('mcp')}`, () => runAsync(NPM, ['i', '-g', spec('mcp')]));
|
|
336
340
|
const after = parseVersion(daemonVersionLine());
|
|
337
341
|
if (before && after && before !== after) {
|
|
338
342
|
await act(`ours-mcp restart (now v${after})`, async () => { if (!run('ours-mcp', ['restart']).ok) run('ours-mcp', ['start']); return { ok: true }; });
|
|
@@ -413,7 +417,7 @@ async function main() {
|
|
|
413
417
|
const add = await act(`codex plugin marketplace add ${CODEX_MARKET}`, async () => run('codex', ['plugin', 'marketplace', 'add', CODEX_MARKET], { capture: true }));
|
|
414
418
|
const inst = add.ok ? await act('codex plugin add ours@ours-codex-marketplace', async () => run('codex', ['plugin', 'add', 'ours@ours-codex-marketplace'], { capture: true })) : add;
|
|
415
419
|
// Owner-mandated: choosing the Codex plugin ALSO installs the ours-codex live launcher, same step.
|
|
416
|
-
const wrap = inst.ok ? await actSpin('installing the ours-codex live launcher…',
|
|
420
|
+
const wrap = inst.ok ? await actSpin('installing the ours-codex live launcher…', `npm i -g ${spec('codex')} (provides ours-codex)`, () => runAsync(NPM, ['i', '-g', spec('codex')])) : inst;
|
|
417
421
|
if (inst.ok && wrap.ok) {
|
|
418
422
|
line(ok(`Codex plugin + ours-codex live launcher installed — pointed at port ${chosenPort}. No problems.`));
|
|
419
423
|
// Plain-language: what ours-codex is and why you'd use it (background wake vs blocking).
|
|
@@ -451,7 +455,8 @@ async function main() {
|
|
|
451
455
|
line(info('over Telegram so they talk to each other — and it all configures maximally easily.'));
|
|
452
456
|
const goFleet = yes(' Install it?', true);
|
|
453
457
|
if (goFleet) {
|
|
454
|
-
|
|
458
|
+
// ours-fleet is ALWAYS @latest — it has no nightly tag (pkgSpec pins it even under OURS_CHANNEL=nightly).
|
|
459
|
+
await actSpin(`installing ${spec('fleet')}…`, `npm i -g ${spec('fleet')}`, () => runAsync(NPM, ['i', '-g', spec('fleet')]));
|
|
455
460
|
const init = await act('ours-fleet init (one-time host setup: units, dirs, linger)', async () => run('ours-fleet', ['init']));
|
|
456
461
|
if (!init.ok) line(warn(`ours-fleet host setup didn't finish — retry '${c.cyan('ours-fleet init')}'.`));
|
|
457
462
|
|
|
@@ -494,7 +499,7 @@ async function main() {
|
|
|
494
499
|
line(info("Telegram. (You'll set up the actual bot later, with your agent — not here.)"));
|
|
495
500
|
const goTg = yes(' Install it?', false);
|
|
496
501
|
if (goTg) {
|
|
497
|
-
await actSpin(
|
|
502
|
+
await actSpin(`installing ${spec('tg-connector')}…`, `npm i -g ${spec('tg-connector')}`, () => runAsync(NPM, ['i', '-g', spec('tg-connector')]));
|
|
498
503
|
const asService = yes(' Keep it running in the background so it starts automatically on boot?', true);
|
|
499
504
|
if (asService) {
|
|
500
505
|
const svc = await act('ours-tg-connector install-service (starts on boot)', async () => run('ours-tg-connector', ['install-service']));
|
package/lib/logic.mjs
CHANGED
|
@@ -26,6 +26,45 @@ export function canonHarnesses(raw) {
|
|
|
26
26
|
return { names, unknown };
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
// ── Release CHANNEL / npm dist-tag selection (owner 2026-07-17) ─────────────────
|
|
30
|
+
// The installer normally installs everything at @latest (stable). Setting
|
|
31
|
+
// OURS_CHANNEL=nightly (or OURS_INSTALL_CHANNEL) makes it install the NIGHTLY tag
|
|
32
|
+
// for the packages that HAVE a nightly (mcp, tg-connector, and the harness-plugin
|
|
33
|
+
// launchers claude-code/codex/hermes — all lockstep-published to the `nightly` tag),
|
|
34
|
+
// but keep @ours.network/fleet at @latest ALWAYS: ours-fleet lives in its own repo
|
|
35
|
+
// and publishes NO nightly tag, so `@nightly` there would 404 the whole install.
|
|
36
|
+
export const DEFAULT_CHANNEL = 'latest';
|
|
37
|
+
|
|
38
|
+
// Packages that follow the selected channel (nightly ⇒ @nightly). Short keys map to
|
|
39
|
+
// the @ours.network/<key> npm name. NOTE fleet is deliberately ABSENT — it is pinned.
|
|
40
|
+
const CHANNEL_TRACKING_PKGS = new Set(['mcp', 'tg-connector', 'claude-code', 'codex', 'hermes']);
|
|
41
|
+
// Packages ALWAYS pinned to @latest regardless of channel (no nightly tag exists).
|
|
42
|
+
const STABLE_ONLY_PKGS = new Set(['fleet']);
|
|
43
|
+
|
|
44
|
+
// Normalize a raw channel selection to 'latest' | 'nightly'. Anything unrecognized
|
|
45
|
+
// (incl. undefined/'') falls back to the safe default 'latest' — never guesses a tag.
|
|
46
|
+
export function resolveChannel(raw) {
|
|
47
|
+
const v = String(raw || '').trim().toLowerCase();
|
|
48
|
+
if (v === 'nightly' || v === 'prerelease' || v === 'next') return 'nightly';
|
|
49
|
+
return DEFAULT_CHANNEL; // 'latest' and everything else
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// The npm dist-tag to install for one package key under a channel. fleet is ALWAYS
|
|
53
|
+
// 'latest'; channel-tracking packages take the channel; anything else defaults to 'latest'.
|
|
54
|
+
export function pkgTag(pkgKey, channel = DEFAULT_CHANNEL) {
|
|
55
|
+
const key = String(pkgKey || '').replace(/^@ours\.network\//, '');
|
|
56
|
+
if (STABLE_ONLY_PKGS.has(key)) return 'latest';
|
|
57
|
+
const ch = resolveChannel(channel);
|
|
58
|
+
if (ch === 'nightly' && CHANNEL_TRACKING_PKGS.has(key)) return 'nightly';
|
|
59
|
+
return 'latest';
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Full `@ours.network/<key>@<tag>` spec for `npm i -g`, honoring the channel.
|
|
63
|
+
export function pkgSpec(pkgKey, channel = DEFAULT_CHANNEL) {
|
|
64
|
+
const key = String(pkgKey || '').replace(/^@ours\.network\//, '');
|
|
65
|
+
return `@ours.network/${key}@${pkgTag(key, channel)}`;
|
|
66
|
+
}
|
|
67
|
+
|
|
29
68
|
// The Telegram connector owns 3051 — the installer must never hand a daemon that port.
|
|
30
69
|
export const RESERVED_PORTS = [3051];
|
|
31
70
|
export const DEFAULT_PORT = 3050;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ours.network/install",
|
|
3
|
-
"version": "0.12.0-nightly.
|
|
3
|
+
"version": "0.12.0-nightly.8",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "The unified ours.network stack installer (ours-install): one guided ~3-minute flow for ours core (the daemon) + the harness plugins (Claude Code / Codex) + ours-fleet + the Telegram connector, then a single copy-paste hand-off prompt. Self-contained (Node built-ins only); run as `ours-install` or via curl|bash (install.sh).",
|
|
6
6
|
"type": "module",
|