@mmmbuto/nexuscrew 0.9.43 → 0.9.46
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/CHANGELOG.md +21 -0
- package/README.md +9 -5
- package/docs/ALIBABA_TOKEN_PLAN.md +4 -2
- package/docs/FLEET.md +12 -0
- package/docs/INSTALLATION.md +4 -1
- package/docs/MCP.md +11 -0
- package/frontend/dist/assets/index-BaqhMxzK.css +32 -0
- package/frontend/dist/assets/index-DN3krh50.js +169 -0
- package/frontend/dist/index.html +2 -2
- package/frontend/dist/version.json +1 -1
- package/lib/cli/commands.js +12 -2
- package/lib/files/telemetry.js +4 -3
- package/lib/fleet/cell-lease-server.js +4 -4
- package/lib/proxy/node-proxy.js +15 -7
- package/mcp-companions.json +6 -1
- package/package.json +1 -1
- package/skills/aidesktop/SKILL.md +6 -0
- package/skills/cellforge/references/definition.md +1 -1
- package/skills/cellforge/references/operations.md +7 -4
- package/skills/nexuscrew/SKILL.md +3 -0
- package/skills/nexuscrew-agent/SKILL.md +36 -5
- package/frontend/dist/assets/index-CeN87Vib.js +0 -169
- package/frontend/dist/assets/index-DDw517fP.css +0 -32
package/frontend/dist/index.html
CHANGED
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
<meta name="apple-mobile-web-app-title" content="NexusCrew" />
|
|
12
12
|
<link rel="manifest" href="/manifest.json" />
|
|
13
13
|
<title>NexusCrew</title>
|
|
14
|
-
<script type="module" crossorigin src="/assets/index-
|
|
15
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
14
|
+
<script type="module" crossorigin src="/assets/index-DN3krh50.js"></script>
|
|
15
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BaqhMxzK.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
|
18
18
|
<div id="root"></div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"0.9.
|
|
1
|
+
{"version":"0.9.46"}
|
package/lib/cli/commands.js
CHANGED
|
@@ -46,6 +46,15 @@ Usage:
|
|
|
46
46
|
nexuscrew help show this help
|
|
47
47
|
nexuscrew version show the installed version
|
|
48
48
|
|
|
49
|
+
Runtime commands for service managers, MCP clients and the boot integration
|
|
50
|
+
(not configuration surfaces):
|
|
51
|
+
|
|
52
|
+
nexuscrew serve run the runtime in the foreground (--pidfile available)
|
|
53
|
+
nexuscrew mcp serve the MCP bridge on stdio for AI sessions
|
|
54
|
+
nexuscrew fleet-boot start the cells marked boot:true
|
|
55
|
+
nexuscrew identity provision [--force] [--no-write-config] [--dir <path>]
|
|
56
|
+
write the node identity authority credentials
|
|
57
|
+
|
|
49
58
|
Configuration, engines, models and advanced lifecycle also live in the PWA.
|
|
50
59
|
NexusCrew binds only to 127.0.0.1 and automatically selects a free port.`;
|
|
51
60
|
|
|
@@ -1557,8 +1566,9 @@ function dispatch(argv, opts = {}) {
|
|
|
1557
1566
|
waitDelayMs: opts.waitDelayMs === undefined ? 250 : opts.waitDelayMs,
|
|
1558
1567
|
}).then(attesa);
|
|
1559
1568
|
}
|
|
1560
|
-
// Internal runtime commands used by service managers
|
|
1561
|
-
//
|
|
1569
|
+
// Internal runtime commands used by service managers, MCP clients and the
|
|
1570
|
+
// boot integration. They are not configuration surfaces: the help lists
|
|
1571
|
+
// them under their own heading, apart from the public commands.
|
|
1562
1572
|
if (cmd === 'serve') {
|
|
1563
1573
|
serve({ ...opts, pidfile: flags.pidfile, serverStart: opts.serverStart });
|
|
1564
1574
|
return { code: 0, keepAlive: true }; // server.listen tiene il processo vivo; non exit
|
package/lib/files/telemetry.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
// Telemetria per-cella: contesto LIBERO e tier 5h/7d USATI, letti dal file che
|
|
3
|
-
// la statusline di Claude Code scrive in <root>/<sessione>/telemetry.json
|
|
4
|
-
//
|
|
5
|
-
// statusline e'
|
|
3
|
+
// la statusline di Claude Code scrive in <root>/<sessione>/telemetry.json.
|
|
4
|
+
// Quel file e' dell'operatore: NexusCrew non installa ne' modifica la sua
|
|
5
|
+
// statusline, e legge solo cio' che lei ha gia' scritto. Il verso dei due dati
|
|
6
|
+
// e' OPPOSTO e i nomi del file lo
|
|
6
7
|
// portano scritto dentro: `contextFreePct` e' quanto RESTA, `tier*UsedPct` e'
|
|
7
8
|
// quanto e' STATO CONSUMATO. Confondere i versi produce una riga che dice il
|
|
8
9
|
// contrario del vero e fa prendere la decisione opposta a quella giusta.
|
|
@@ -369,10 +369,10 @@ function createLeaseManager(cfg = {}, seams = {}) {
|
|
|
369
369
|
return true;
|
|
370
370
|
}
|
|
371
371
|
|
|
372
|
-
//
|
|
373
|
-
//
|
|
374
|
-
//
|
|
375
|
-
//
|
|
372
|
+
// Il canale verify espone l'enum COMPLETO del contratto v1: a differenza
|
|
373
|
+
// del relay challenge-proof (che collassa i motivi sensibili), qui la
|
|
374
|
+
// diagnostica puntuale e' parte del contratto — il daemon decide il
|
|
375
|
+
// fail-closed.
|
|
376
376
|
function identityVerifyReason(reason) {
|
|
377
377
|
const known = new Set([
|
|
378
378
|
'malformed', 'expired', 'bad-proof', 'replay', 'challenge-replay',
|
package/lib/proxy/node-proxy.js
CHANGED
|
@@ -150,7 +150,7 @@ function notFound(res) { res.status(404).json({ error: 'not found' }); }
|
|
|
150
150
|
// passata (requireToken davanti). Ordine interno: name strict -> no-transitive ->
|
|
151
151
|
// resolve -> readonly -> proxy.
|
|
152
152
|
function createNodeProxy(deps) {
|
|
153
|
-
const { resolveNode, readonly = () => false, httpRequest = http.request } = deps;
|
|
153
|
+
const { resolveNode, readonly = () => false, httpRequest = http.request, proxyTimeoutMs = PROXY_TIMEOUT_MS } = deps;
|
|
154
154
|
return function nodeProxy(req, res) {
|
|
155
155
|
const parsed = splitNodePath(req.url);
|
|
156
156
|
if (!parsed) return notFound(res); // no name
|
|
@@ -164,11 +164,11 @@ function createNodeProxy(deps) {
|
|
|
164
164
|
if (readonly() && MUTATING.has(req.method)) {
|
|
165
165
|
return res.status(403).json({ error: 'READONLY: mutazione verso nodo bloccata' });
|
|
166
166
|
}
|
|
167
|
-
proxyHttp(req, res, node, parsed.rest, parsed.search, httpRequest);
|
|
167
|
+
proxyHttp(req, res, node, parsed.rest, parsed.search, httpRequest, proxyTimeoutMs);
|
|
168
168
|
};
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
function proxyHttp(req, res, node, rest, search, httpRequest) {
|
|
171
|
+
function proxyHttp(req, res, node, rest, search, httpRequest, timeoutMs) {
|
|
172
172
|
const options = {
|
|
173
173
|
host: '127.0.0.1', // upstream loopback ONLY, from config
|
|
174
174
|
port: node.localPort,
|
|
@@ -193,10 +193,18 @@ function proxyHttp(req, res, node, rest, search, httpRequest) {
|
|
|
193
193
|
if (!res.headersSent) res.status(502).json({ error: 'node non raggiungibile' });
|
|
194
194
|
return;
|
|
195
195
|
}
|
|
196
|
-
upstream.setTimeout(PROXY_TIMEOUT_MS, () => upstream.destroy(new Error(
|
|
197
|
-
upstream.on('error', () => {
|
|
198
|
-
|
|
199
|
-
|
|
196
|
+
upstream.setTimeout(timeoutMs || PROXY_TIMEOUT_MS, () => upstream.destroy(new Error("upstream timeout")));
|
|
197
|
+
upstream.on('error', (e) => {
|
|
198
|
+
// Il timeout di attesa (PROXY_TIMEOUT_MS) NON è un nodo morto: il nodo
|
|
199
|
+
// remoto può essere ancora al lavoro sulla richiesta (es. un avvio cella
|
|
200
|
+
// oltre i 30 s). Il `cause` distinto permette al client di trattarlo
|
|
201
|
+
// come attesa in corso e non come errore del nodo.
|
|
202
|
+
if (!res.headersSent) {
|
|
203
|
+
const waiting = e && e.message === 'upstream timeout';
|
|
204
|
+
res.status(502).json(waiting
|
|
205
|
+
? { error: 'node non raggiungibile', cause: 'upstream-timeout' }
|
|
206
|
+
: { error: 'node non raggiungibile' });
|
|
207
|
+
} else res.destroy();
|
|
200
208
|
});
|
|
201
209
|
req.on('aborted', () => upstream.destroy());
|
|
202
210
|
req.pipe(upstream);
|
package/mcp-companions.json
CHANGED
|
@@ -48,6 +48,9 @@
|
|
|
48
48
|
"msa_index_batch",
|
|
49
49
|
"msa_search",
|
|
50
50
|
"msa_fetch_doc",
|
|
51
|
+
"msa_list_collections",
|
|
52
|
+
"msa_stats",
|
|
53
|
+
"msa_manifest",
|
|
51
54
|
"msa_remember",
|
|
52
55
|
"msa_forget",
|
|
53
56
|
"msa_interleave_round"
|
|
@@ -72,7 +75,9 @@
|
|
|
72
75
|
"cell_result",
|
|
73
76
|
"cell_list",
|
|
74
77
|
"cell_send",
|
|
75
|
-
"cell_ask"
|
|
78
|
+
"cell_ask",
|
|
79
|
+
"cell_await",
|
|
80
|
+
"cell_inbox"
|
|
76
81
|
]
|
|
77
82
|
},
|
|
78
83
|
{
|
package/package.json
CHANGED
|
@@ -91,6 +91,12 @@ project actually owns is the two added lines below and their reasons. It also
|
|
|
91
91
|
means no registry to host, nothing to keep patched on your behalf, and a
|
|
92
92
|
recipe you can read before you run it.
|
|
93
93
|
|
|
94
|
+
The recipe needs a host that runs Docker with Compose v2 — see the
|
|
95
|
+
dependencies at the end. On a platform without Docker, Android/Termux
|
|
96
|
+
included, the container cannot build there: the `panelUrl` mechanics earlier
|
|
97
|
+
in this skill still apply to any loopback web UI that node can reach, and the
|
|
98
|
+
recipe simply runs on a different host.
|
|
99
|
+
|
|
94
100
|
Build it yourself from [`docker/`](docker/):
|
|
95
101
|
|
|
96
102
|
```bash
|
|
@@ -45,7 +45,7 @@ includes either is refused. Everything else is patchable.
|
|
|
45
45
|
| `mcp` | no | **names only**, up to 64, each matching `[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}` |
|
|
46
46
|
| `label`, `tmuxSession` | varies | display label ≤64 chars; session name ≤64 chars, immutable |
|
|
47
47
|
|
|
48
|
-
Ceilings on the document as a whole: **32 cells**, **
|
|
48
|
+
Ceilings on the document as a whole: **32 cells**, **100 engines**. These are not
|
|
49
49
|
close to most installs, but a restore that silently dropped entries would be
|
|
50
50
|
worse than one that fails, so a document over the cap is rejected rather than
|
|
51
51
|
truncated.
|
|
@@ -66,10 +66,13 @@ operation or it does not, and the set is reported in `capabilities` from
|
|
|
66
66
|
501 not supported by this fleet provider
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
So the honest sequence is: read `capabilities`, and if the one you need
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
So the honest sequence is: read `capabilities`, and if the one you need is
|
|
70
|
+
missing, **say so to the user** rather than retrying. The set varies by
|
|
71
|
+
provider; the built-in one reports `status`, `up`, `down`, `restart`, `engine`,
|
|
72
|
+
`boot`, `define`, `edit`, `remove`, `import`, `restore`, `schema`,
|
|
73
|
+
`definitions`, `credentials`, `model-test` and `edit-model`. A `501` here is a
|
|
74
|
+
statement about the provider, not about your payload — do not start rewriting
|
|
75
|
+
the body.
|
|
73
76
|
|
|
74
77
|
Separately, a provider in read-only mode refuses writes with `403`. Two
|
|
75
78
|
different refusals with two different meanings: `501` says "this provider can
|
|
@@ -46,9 +46,12 @@ Through the MCP bridge, when the tools are exposed in your session:
|
|
|
46
46
|
| tell the human something, or ask | `nc_notify`, `nc_ask` | `nexuscrew-agent` |
|
|
47
47
|
| read runtime state, identity, decks | `nc_status`, `nc_identity`, `nc_deck` | `nexuscrew-agent` |
|
|
48
48
|
| find and message another cell | `nc_cells` then `nc_send_cell` | `nexuscrew-agent` |
|
|
49
|
+
| manage a paired VL micro-device | `nc_vl_nodes`, then `nc_vl_command` (plus `nc_vl_invite` / `nc_vl_revoke`) | `nexuscrew-agent` |
|
|
49
50
|
| speak on a node or audio group | `nc_speak`, `nc_speak_group` | `nexuscrew-agent` |
|
|
51
|
+
| check or stop an utterance you started | `nc_speak_status`, `nc_speak_stop`, `nc_speak_group_status`, `nc_speak_group_stop` | `nexuscrew-agent` |
|
|
50
52
|
| hand a file to the human | `nc_send_file`, `nc_inbox` | `nexuscrew-agent` |
|
|
51
53
|
| find out why a cell will not start | `nc_cell_diagnostics` | `nexuscrew-agent` |
|
|
54
|
+
| register, renew or recover this cell's Live lease | `nc_lease_register`, `nc_lease_refresh`, `nc_lease_recovery` | `nexuscrew-agent` |
|
|
52
55
|
| keep state across sessions | Memory MCP | `memory` |
|
|
53
56
|
| index and retrieve documents | MSA MCP | `vl-msa` |
|
|
54
57
|
| delegate bounded work to workers | Crew MCP | `crew` |
|
|
@@ -31,6 +31,7 @@ When the client exposes the NexusCrew MCP server, use these tools directly:
|
|
|
31
31
|
| Check or stop a group utterance you started | `nc_speak_group_status`, `nc_speak_group_stop` |
|
|
32
32
|
| Read who the caller is, without a session or token | `nc_identity` |
|
|
33
33
|
| Read why a local Fleet cell failed to start | `nc_cell_diagnostics` |
|
|
34
|
+
| Register, renew or recover this cell's Live lease | `nc_lease_register`, `nc_lease_refresh`, `nc_lease_recovery` |
|
|
34
35
|
|
|
35
36
|
Apply these rules:
|
|
36
37
|
|
|
@@ -50,6 +51,27 @@ Apply these rules:
|
|
|
50
51
|
- `nc_cell_diagnostics` returns the redacted shell command and the last bounded spawn or start failure for one local Fleet cell. Use it when a cell will not come up, before reading state files.
|
|
51
52
|
- Do not treat an MCP notification as a substitute for the final response required by the active client.
|
|
52
53
|
|
|
54
|
+
### Live lease registration (`nc_lease_*`)
|
|
55
|
+
|
|
56
|
+
A cell can hold a **Live lease registration** on the node: it registers once,
|
|
57
|
+
then keeps the registration alive by presenting the proof it received. Three
|
|
58
|
+
tools, one job each — their return values do not overlap:
|
|
59
|
+
|
|
60
|
+
- `nc_lease_register {proof?}` — registers this cell under its own incarnation
|
|
61
|
+
and returns the first child proof. It can answer `{status:"pending"}` with a
|
|
62
|
+
`retryAfterMs` when the node is not tracking the cell yet: wait that long
|
|
63
|
+
and call it again rather than spinning.
|
|
64
|
+
- `nc_lease_refresh {proof}` — renews a live registration. Pass the last
|
|
65
|
+
received proof object back unchanged. Answers `{status:"live"}` with a new
|
|
66
|
+
proof; it is never pending, and `{status:"no-registration"}` means
|
|
67
|
+
`nc_lease_register` is the next call, not a retry.
|
|
68
|
+
- `nc_lease_recovery {proof}` — resumes the registration after a gap, keeping
|
|
69
|
+
the same incarnation; a proof that expired recently is still accepted. Every
|
|
70
|
+
attempt counts toward a cap — past it, register again.
|
|
71
|
+
|
|
72
|
+
Use them only when your runtime asks this cell to hold a Live lease. Treat
|
|
73
|
+
each status literally, and pass proofs through verbatim.
|
|
74
|
+
|
|
53
75
|
The MCP server is the stdio command `nexuscrew mcp` and must be registered in the host AI client. If the `nc_*` tools are not exposed, report that the bridge is not configured in that session and use the fallback flows below where applicable.
|
|
54
76
|
|
|
55
77
|
## Optional capability companions
|
|
@@ -82,9 +104,14 @@ Per session, NexusCrew watches `<root>/<session>/{inbox,outbox}` (root = `$NEXUS
|
|
|
82
104
|
When `nc_send_file` is unavailable, deliver with the helper (resolves the current tmux session, timestamps, never overwrites):
|
|
83
105
|
|
|
84
106
|
```bash
|
|
85
|
-
bin/nc-deliver report.pdf chart.png
|
|
107
|
+
"$(npm root -g)/@mmmbuto/nexuscrew/skills/nexuscrew-agent/bin/nc-deliver" report.pdf chart.png
|
|
108
|
+
# → ~/NexusFiles/<session>/outbox/
|
|
86
109
|
```
|
|
87
110
|
|
|
111
|
+
The helpers ship inside the npm package and are **not linked on `PATH`** — the
|
|
112
|
+
only global command is `nexuscrew` — so address them under the global package
|
|
113
|
+
root; `npm root -g` prints that root for the Node installation in use.
|
|
114
|
+
|
|
88
115
|
Don't hand-craft the path from a guessed session name — use `nc-deliver`, or derive the session with `tmux display-message -p '#S'`.
|
|
89
116
|
|
|
90
117
|
## Sending text to a tmux session
|
|
@@ -96,9 +123,10 @@ non-Fleet sessions; it must not bypass federation visibility or routing ACLs.
|
|
|
96
123
|
`tmux send-keys 'msg' Enter` is **not** reliable: a TUI's paste-burst detector swallows the Enter and the message just sits in the composer, while exit code is still 0. Use the helper:
|
|
97
124
|
|
|
98
125
|
```bash
|
|
99
|
-
bin/nc-send
|
|
100
|
-
|
|
101
|
-
|
|
126
|
+
NC_SEND="$(npm root -g)/@mmmbuto/nexuscrew/skills/nexuscrew-agent/bin/nc-send"
|
|
127
|
+
"$NC_SEND" <session> "text" # paste + submit
|
|
128
|
+
"$NC_SEND" <session> --file prompt.txt # from a file
|
|
129
|
+
"$NC_SEND" <session> --no-submit "text" # leave in composer, no Enter
|
|
102
130
|
```
|
|
103
131
|
|
|
104
132
|
It does: `load-buffer` → `paste-buffer -p` (bracketed paste) → burst-flush (`C-e`) → `Enter`. **Verify it landed** — never trust the exit code:
|
|
@@ -173,8 +201,11 @@ work. The setting is also applied to windows created later in that session.
|
|
|
173
201
|
## Dependencies
|
|
174
202
|
|
|
175
203
|
**Bundled (installed with the package):** the `nexuscrew` CLI, `lib/`, these
|
|
176
|
-
skills, and the `
|
|
204
|
+
skills, and the `nc-send` / `nc-deliver` helpers arrive with
|
|
177
205
|
`npm install -g @mmmbuto/nexuscrew` (Node.js >= 18 required by `engines`).
|
|
206
|
+
Only `nexuscrew` is linked on `PATH`; the helpers live inside the package at
|
|
207
|
+
`skills/nexuscrew-agent/bin/` — reach them through `npm root -g` as shown in
|
|
208
|
+
File exchange above.
|
|
178
209
|
|
|
179
210
|
**External (you must provide):**
|
|
180
211
|
|