@webority/ensemble 0.5.7 → 0.5.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/README.md +1 -1
- package/bin/ensemble.js +9 -7
- package/lib/core.js +35 -41
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -53,7 +53,7 @@ Fleet playbook: `docs/FLEET.md`.
|
|
|
53
53
|
### Grok / Codex MCP (existing config)
|
|
54
54
|
When `~/.grok/config.toml` (or Codex) already exists, install **upserts** only
|
|
55
55
|
`[mcp_servers.ensemble]` — other servers (e.g. weborityos) and UI/cli sections are kept.
|
|
56
|
-
Command points at `~/.ensemble/bin/ensemble-runtime` (
|
|
56
|
+
Command points at `~/.ensemble/bin/ensemble-runtime` only (no `ensemble-bus` binary or alias).
|
|
57
57
|
|
|
58
58
|
## Security model
|
|
59
59
|
Machine ⇄ server auth is a **per-machine token**, resolved server-side to your organization; every
|
package/bin/ensemble.js
CHANGED
|
@@ -123,9 +123,7 @@ async function status(args) {
|
|
|
123
123
|
const t = fs.readFileSync(tokenFile, 'utf8').trim();
|
|
124
124
|
core.log('Ensemble status @ ' + api);
|
|
125
125
|
const runtimeExe = core.runtimeBin();
|
|
126
|
-
const busCompat = path.join(core.BIN_DIR, 'ensemble-bus' + core.platform().exe);
|
|
127
126
|
core.log('• runtime binary: ' + (core.isUsableBinary(runtimeExe) ? 'ok (' + runtimeExe + ')' : 'MISSING/STUB — ensemble install'));
|
|
128
|
-
core.log('• bus compat alias: ' + (core.isUsableBinary(busCompat) ? 'ok' : 'missing — ensemble install'));
|
|
129
127
|
const engines = ['claude', 'codex', 'grok', 'opencode', 'omp', 'gemini', 'antigravity'];
|
|
130
128
|
const present = engines.filter((e) => core.enginePresent(e));
|
|
131
129
|
core.log('• engines detected: ' + (present.join(', ') || 'none'));
|
|
@@ -135,10 +133,13 @@ async function status(args) {
|
|
|
135
133
|
if (fs.existsSync(grokToml)) {
|
|
136
134
|
const txt = fs.readFileSync(grokToml, 'utf8');
|
|
137
135
|
const hasEnsemble = /\[mcp_servers\.ensemble\]/.test(txt);
|
|
138
|
-
const pointsRuntime = /ensemble-runtime/.test(txt)
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
136
|
+
const pointsRuntime = /ensemble-runtime/.test(txt);
|
|
137
|
+
const hasLegacyBus = /ensemble-bus/.test(txt);
|
|
138
|
+
core.log('• grok MCP: ' + (hasEnsemble && pointsRuntime && !hasLegacyBus
|
|
139
|
+
? 'configured (ensemble-runtime) in ~/.grok/config.toml'
|
|
140
|
+
: hasLegacyBus
|
|
141
|
+
? 'LEGACY ensemble-bus path — run: ensemble hooks'
|
|
142
|
+
: 'NOT wired — run: ensemble hooks'));
|
|
142
143
|
} else {
|
|
143
144
|
core.log('• grok MCP: no ~/.grok/config.toml — run: ensemble hooks');
|
|
144
145
|
}
|
|
@@ -195,8 +196,9 @@ Run \`ensemble login\` and approve the machine in your browser.`);
|
|
|
195
196
|
else if (cmd === 'status') await status(args);
|
|
196
197
|
else if (cmd === 'hooks') {
|
|
197
198
|
// Ensure a usable (non-stub) runtime BEFORE wiring — otherwise every engine gets pointed at a
|
|
198
|
-
// dead path.
|
|
199
|
+
// dead path. Fails closed on unsupported platforms. No ensemble-bus compat alias.
|
|
199
200
|
await core.ensureRuntime();
|
|
201
|
+
core.removeLegacyBusArtifacts();
|
|
200
202
|
const wired = core.wireHooks();
|
|
201
203
|
core.log('wired hooks+MCP: ' + (wired.join(', ') || 'none'));
|
|
202
204
|
if (!wired.some((w) => w.endsWith(':mcp'))) {
|
package/lib/core.js
CHANGED
|
@@ -92,8 +92,7 @@ function runtimeBin() {
|
|
|
92
92
|
return runtimePaths().runtimePath;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
// Real runtime/runner single-file binaries are tens of MB.
|
|
96
|
-
// from earlier renames must never count as installed — wiring would point engines at a dead path.
|
|
95
|
+
// Real runtime/runner single-file binaries are tens of MB. Anything smaller is corrupt/stub.
|
|
97
96
|
const MIN_BINARY_BYTES = 1_000_000;
|
|
98
97
|
|
|
99
98
|
function isUsableBinary(filePath) {
|
|
@@ -202,7 +201,7 @@ async function ensureRuntime() {
|
|
|
202
201
|
// an explicit `ensemble install`, which was the only upgrade path before and left the fleet stale. [BUG-06673]
|
|
203
202
|
if (runtimeInstalled() && installedVersionCurrent()) {
|
|
204
203
|
const p = runtimePaths();
|
|
205
|
-
|
|
204
|
+
removeLegacyBusArtifacts();
|
|
206
205
|
return p;
|
|
207
206
|
}
|
|
208
207
|
return ensureBinaries({ force: true });
|
|
@@ -228,50 +227,44 @@ function platformPackageDir() {
|
|
|
228
227
|
}
|
|
229
228
|
}
|
|
230
229
|
|
|
231
|
-
//
|
|
232
|
-
//
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
if (!isUsableBinary(runtimePath)) return;
|
|
237
|
-
const busPath = path.join(BIN_DIR, 'ensemble-bus' + pf.exe);
|
|
238
|
-
if (isUsableBinary(busPath) && fs.statSync(busPath).size === fs.statSync(runtimePath).size) {
|
|
239
|
-
return; // already a full runtime copy
|
|
240
|
-
}
|
|
230
|
+
// No backward-compat binary. Delete leftover ensemble-bus* (and framework-dependent debris that
|
|
231
|
+
// sometimes landed next to a bad publish) so only ensemble-runtime remains the bus CLI.
|
|
232
|
+
function removeLegacyBusArtifacts() {
|
|
233
|
+
ensureDirs();
|
|
234
|
+
let names;
|
|
241
235
|
try {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
236
|
+
names = fs.readdirSync(BIN_DIR);
|
|
237
|
+
} catch (e) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
for (const name of names) {
|
|
241
|
+
const lower = name.toLowerCase();
|
|
242
|
+
const drop =
|
|
243
|
+
lower.startsWith('ensemble-bus')
|
|
244
|
+
|| lower.startsWith('microsoft.')
|
|
245
|
+
|| lower.startsWith('modelcontextprotocol')
|
|
246
|
+
|| lower === 'system.diagnostics.eventlog.dll'
|
|
247
|
+
|| lower === 'runtimes';
|
|
248
|
+
if (!drop) continue;
|
|
249
|
+
const full = path.join(BIN_DIR, name);
|
|
251
250
|
try {
|
|
252
|
-
if (fs.
|
|
253
|
-
|
|
251
|
+
if (fs.statSync(full).isDirectory()) {
|
|
252
|
+
fs.rmSync(full, { recursive: true, force: true });
|
|
253
|
+
} else {
|
|
254
|
+
fs.unlinkSync(full);
|
|
254
255
|
}
|
|
255
|
-
fs.renameSync(tmp, busPath);
|
|
256
256
|
} catch (e) {
|
|
257
|
+
// Locked (running MCP still holds a handle): rename aside so nothing can launch it by name.
|
|
257
258
|
try {
|
|
258
|
-
|
|
259
|
-
|
|
259
|
+
const trash = full + '.trash-' + Date.now();
|
|
260
|
+
fs.renameSync(full, trash);
|
|
261
|
+
warn('moved locked legacy ' + name + ' aside → ' + path.basename(trash) +
|
|
262
|
+
' (delete after restarting agents)');
|
|
260
263
|
} catch (e2) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
warn('could not replace ensemble-bus compat alias (file locked by a running agent MCP?) — ' +
|
|
264
|
-
'new wiring uses ensemble-runtime; restart agents and re-run `ensemble hooks` to refresh the alias. ' +
|
|
265
|
-
'(' + (e2 && e2.message ? e2.message : e2) + ')');
|
|
266
|
-
return;
|
|
264
|
+
warn('could not remove legacy ' + name + ' (locked) — restart agents and re-run `ensemble install`. (' +
|
|
265
|
+
(e2 && e2.message ? e2.message : e2) + ')');
|
|
267
266
|
}
|
|
268
267
|
}
|
|
269
|
-
if (pf.os !== 'windows') {
|
|
270
|
-
fs.chmodSync(busPath, 0o755);
|
|
271
|
-
if (pf.os === 'mac') spawnSync('codesign', ['-s', '-', '-f', busPath], { stdio: 'ignore' });
|
|
272
|
-
}
|
|
273
|
-
} catch (e) {
|
|
274
|
-
warn('could not write ensemble-bus compat alias: ' + (e && e.message ? e.message : e));
|
|
275
268
|
}
|
|
276
269
|
}
|
|
277
270
|
|
|
@@ -327,7 +320,7 @@ async function ensureBinaries(opts) {
|
|
|
327
320
|
if (pf.os === 'mac') spawnSync('codesign', ['-s', '-', '-f', t.dest], { stdio: 'ignore' });
|
|
328
321
|
}
|
|
329
322
|
}
|
|
330
|
-
|
|
323
|
+
removeLegacyBusArtifacts();
|
|
331
324
|
writeInstalledVersion();
|
|
332
325
|
// A replaced runner binary only takes effect once the daemon restarts onto it.
|
|
333
326
|
if (runnerRefreshed) restartRunner(pf, runnerPath);
|
|
@@ -699,6 +692,7 @@ function has(cmd) {
|
|
|
699
692
|
// Ensemble owns — used to dedup on re-run so our entry never stacks.
|
|
700
693
|
function isEnsembleHook(h) {
|
|
701
694
|
const cmd = typeof h === 'string' ? h : (h && (h.command || h.cmd || h.run)) || '';
|
|
695
|
+
// Match ensemble-runtime and any leftover ensemble-bus paths so re-wire strips outdated entries.
|
|
702
696
|
return /ensemble-(bus|runtime)/i.test(String(cmd));
|
|
703
697
|
}
|
|
704
698
|
|
|
@@ -869,6 +863,6 @@ module.exports = {
|
|
|
869
863
|
ensureBinaries, enrollMachine, writeRunnerConfig, wireHooks, wireMcpServers, enginePresent, installAutostart, startRunner, request,
|
|
870
864
|
sleep, openBrowser, startDevice, pollDevice, finishSetup, assertSupported,
|
|
871
865
|
runtimePaths, runtimeBin, runtimeInstalled, requireRuntime, ensureRuntime,
|
|
872
|
-
isUsableBinary,
|
|
866
|
+
isUsableBinary, removeLegacyBusArtifacts, MIN_BINARY_BYTES,
|
|
873
867
|
writeEngineHooks, upsertTomlMcp, installedVersionCurrent, readInstalledVersion, PKG_VERSION,
|
|
874
868
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webority/ensemble",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.8",
|
|
4
4
|
"description": "Connect this machine to Ensemble — runs the local agent runner and wires the ensemble session bus so your coding sessions talk (per-org, isolated).",
|
|
5
5
|
"bin": {
|
|
6
6
|
"ensemble": "bin/ensemble.js"
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
"node": ">=18"
|
|
10
10
|
},
|
|
11
11
|
"optionalDependencies": {
|
|
12
|
-
"@webority/ensemble-darwin-arm64": "0.5.
|
|
13
|
-
"@webority/ensemble-darwin-x64": "0.5.
|
|
14
|
-
"@webority/ensemble-linux-arm64": "0.5.
|
|
15
|
-
"@webority/ensemble-linux-x64": "0.5.
|
|
16
|
-
"@webority/ensemble-win-x64": "0.5.
|
|
12
|
+
"@webority/ensemble-darwin-arm64": "0.5.8",
|
|
13
|
+
"@webority/ensemble-darwin-x64": "0.5.8",
|
|
14
|
+
"@webority/ensemble-linux-arm64": "0.5.8",
|
|
15
|
+
"@webority/ensemble-linux-x64": "0.5.8",
|
|
16
|
+
"@webority/ensemble-win-x64": "0.5.8"
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
19
|
"bin",
|