c8ctl-plugin-nano 1.15.0 → 1.17.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/c8ctl-plugin.js +46 -35
- package/package.json +8 -8
package/c8ctl-plugin.js
CHANGED
|
@@ -120,15 +120,6 @@ const PROCESSOS_STATE_FILE = 'processos.json';
|
|
|
120
120
|
const PROCESSOS_DEFAULT_PORT = 8090;
|
|
121
121
|
const DEFAULT_NANO_URL = 'http://localhost:8080';
|
|
122
122
|
|
|
123
|
-
// Guided-journey deep links (ADR 0049 §2). The console renders a first-run tour
|
|
124
|
-
// chosen by `…/console?tour=<journeyId>`, and the *command the user ran* already
|
|
125
|
-
// encodes the persona — so the CLI bakes the journey into the console URL it
|
|
126
|
-
// prints rather than making the console guess. These ids are a contract with the
|
|
127
|
-
// console (`console/src/lib/tour`): an unknown id is silently ignored, so they
|
|
128
|
-
// are asserted verbatim in the tests.
|
|
129
|
-
const JOURNEY_LOCALDEV = 'localdev';
|
|
130
|
-
const JOURNEY_AGENTIC_AUTHOR = 'agentic-author';
|
|
131
|
-
|
|
132
123
|
// Passive update notifier (npm-style): refresh the latest published version
|
|
133
124
|
// from the registry in a detached background process at most once per day, and
|
|
134
125
|
// surface a one-line "update available" notice at most once per day. Never
|
|
@@ -459,27 +450,28 @@ function liveNodeCount(state) {
|
|
|
459
450
|
}
|
|
460
451
|
|
|
461
452
|
/**
|
|
462
|
-
* Compose a web-console URL for a node's base URL
|
|
463
|
-
*
|
|
464
|
-
*
|
|
453
|
+
* Compose a web-console URL for a node's base URL. Never hardcodes a port:
|
|
454
|
+
* `baseUrl` is the real address the node came up on.
|
|
455
|
+
*
|
|
456
|
+
* No longer carries a `?tour=<id>` deep link: onboarding is chosen in the
|
|
457
|
+
* console's own startup persona panel (nano-bpm #464), not sprayed across every
|
|
458
|
+
* command's output.
|
|
465
459
|
*/
|
|
466
|
-
function webConsoleUrl(baseUrl
|
|
467
|
-
|
|
468
|
-
return journey ? `${base}?tour=${encodeURIComponent(journey)}` : base;
|
|
460
|
+
function webConsoleUrl(baseUrl) {
|
|
461
|
+
return `${baseUrl}/console`;
|
|
469
462
|
}
|
|
470
463
|
|
|
471
464
|
/**
|
|
472
|
-
*
|
|
473
|
-
*
|
|
474
|
-
*
|
|
475
|
-
*
|
|
465
|
+
* Human label for the console link, keyed on the runtime console profile.
|
|
466
|
+
* The default `studio` profile IS the full web IDE, so name it as such — users
|
|
467
|
+
* kept missing that Nano ships a browser IDE when it was labelled "Web console".
|
|
468
|
+
* `observe` is the read-only console. `off` serves no console, so the label is
|
|
469
|
+
* meaningless there; callers must guard `profile !== 'off'` before rendering it,
|
|
470
|
+
* and this helper returns null for `off` to enforce that contract.
|
|
476
471
|
*/
|
|
477
|
-
function
|
|
478
|
-
if (
|
|
479
|
-
|
|
480
|
-
return (alive || state.nodes[0]).url;
|
|
481
|
-
}
|
|
482
|
-
return DEFAULT_NANO_URL;
|
|
472
|
+
function consoleLinkLabel(profile) {
|
|
473
|
+
if (profile === 'off') return null;
|
|
474
|
+
return profile === 'studio' ? 'Web IDE (Studio)' : `Web console (${profile})`;
|
|
483
475
|
}
|
|
484
476
|
|
|
485
477
|
/** Probe a node's always-on GET /v2/topology endpoint for reachability. */
|
|
@@ -809,6 +801,7 @@ async function startCluster(req) {
|
|
|
809
801
|
inMemory,
|
|
810
802
|
historyMax: historyMax ?? null,
|
|
811
803
|
basePort,
|
|
804
|
+
consoleProfile,
|
|
812
805
|
nodes,
|
|
813
806
|
};
|
|
814
807
|
writeState(state);
|
|
@@ -855,15 +848,22 @@ async function printSummary(state) {
|
|
|
855
848
|
// The landing page (and the /docs user guide + /console) only exist in builds
|
|
856
849
|
// compiled with the web console; probe so we advertise the right entry point.
|
|
857
850
|
const hasConsole = await probePath(entry.url, '/');
|
|
858
|
-
|
|
859
|
-
|
|
851
|
+
const profile = state.consoleProfile ?? 'studio';
|
|
852
|
+
// Lead with the web IDE — it is Nano's headline surface and the thing users
|
|
853
|
+
// most often did not realise was there. Only advertise it when this build
|
|
854
|
+
// actually serves a console and the profile is not 'off'.
|
|
855
|
+
if (hasConsole && profile !== 'off') {
|
|
856
|
+
console.log(` ${consoleLinkLabel(profile)} ${webConsoleUrl(entry.url)}`);
|
|
857
|
+
const surface = profile === 'studio' ? 'the Nano web IDE' : 'the Nano web console';
|
|
858
|
+
console.log(` ^ open this in your browser: ${surface}`);
|
|
859
|
+
console.log('');
|
|
860
860
|
}
|
|
861
|
-
console.log(` REST API ${entry.url}/v2`);
|
|
862
|
-
console.log(` Topology ${entry.url}/v2/topology`);
|
|
863
861
|
if (hasConsole) {
|
|
864
|
-
console.log(`
|
|
862
|
+
console.log(` Landing ${entry.url}/ (console, user guide & API docs)`);
|
|
865
863
|
console.log(` User guide ${entry.url}/docs`);
|
|
866
864
|
}
|
|
865
|
+
console.log(` REST API ${entry.url}/v2`);
|
|
866
|
+
console.log(` Topology ${entry.url}/v2/topology`);
|
|
867
867
|
if (state.workspaceDir) {
|
|
868
868
|
console.log(` Workspace ${state.workspaceDir} (models/, workers/)`);
|
|
869
869
|
}
|
|
@@ -1073,6 +1073,21 @@ async function statusCluster(req) {
|
|
|
1073
1073
|
}
|
|
1074
1074
|
console.log('');
|
|
1075
1075
|
|
|
1076
|
+
// Surface the web IDE again here so it stays discoverable long after the
|
|
1077
|
+
// initial `start` scrolled off — probe a healthy node so we only advertise a
|
|
1078
|
+
// console that is actually served (API-only builds 404 `/`).
|
|
1079
|
+
const profile = state.consoleProfile ?? 'studio';
|
|
1080
|
+
if (overall !== 'stopped' && profile !== 'off') {
|
|
1081
|
+
// Only probe a HEALTHY node: it already answered /v2/topology this run, so
|
|
1082
|
+
// GET / returns fast. Falling back to a merely-alive (unreachable) node
|
|
1083
|
+
// would add a full probe timeout to every `nano status` in a degraded state.
|
|
1084
|
+
const consoleNode = checks.find((c) => c.healthy);
|
|
1085
|
+
if (consoleNode && (await probePath(consoleNode.url, '/'))) {
|
|
1086
|
+
console.log(` ${consoleLinkLabel(profile)} ${webConsoleUrl(consoleNode.url)}`);
|
|
1087
|
+
console.log('');
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1076
1091
|
// Enrich with the live topology when reachable — the authoritative view of
|
|
1077
1092
|
// partition leadership across the cluster.
|
|
1078
1093
|
if (topo) {
|
|
@@ -1662,7 +1677,6 @@ async function hireWorker(req, flags) {
|
|
|
1662
1677
|
if (envKeys.length > 0) logger.info(` env: ${envKeys.join(', ')}`);
|
|
1663
1678
|
logger.info(` job types (${matrix.length}): ${matrix.join(' ')}`);
|
|
1664
1679
|
logger.info(`Put it to work with: c8ctl nano work ${name}`);
|
|
1665
|
-
logger.info(`Open the console: ${webConsoleUrl(runningConsoleBaseUrl(), JOURNEY_AGENTIC_AUTHOR)}`);
|
|
1666
1680
|
}
|
|
1667
1681
|
|
|
1668
1682
|
/**
|
|
@@ -2707,7 +2721,6 @@ async function workAgent(req, flags) {
|
|
|
2707
2721
|
const extraNote = extraJobTypes.length > 0 ? ` (${extraJobTypes.length} via --job-type)` : '';
|
|
2708
2722
|
logger.info(` listening on ${jobTypes.length} job type(s)${extraNote}: ${jobTypes.join(' ')}`);
|
|
2709
2723
|
logger.info(` max parallel: ${maxParallelJobs}; job timeout: ${jobTimeoutMs}ms`);
|
|
2710
|
-
logger.info(` console: ${webConsoleUrl(runningConsoleBaseUrl(), JOURNEY_AGENTIC_AUTHOR)}`);
|
|
2711
2724
|
logger.info('Polling for work — press Ctrl-C to stop.');
|
|
2712
2725
|
|
|
2713
2726
|
const workers = jobTypes.map((jobType) =>
|
|
@@ -4240,10 +4253,8 @@ export { resolveBinary, findBinary, launcherEnvMarkers };
|
|
|
4240
4253
|
export { buildNpmInvocation };
|
|
4241
4254
|
export {
|
|
4242
4255
|
webConsoleUrl,
|
|
4243
|
-
|
|
4256
|
+
consoleLinkLabel,
|
|
4244
4257
|
hireWorker,
|
|
4245
|
-
JOURNEY_LOCALDEV,
|
|
4246
|
-
JOURNEY_AGENTIC_AUTHOR,
|
|
4247
4258
|
};
|
|
4248
4259
|
export {
|
|
4249
4260
|
normalizeTaskEnvelope,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "c8ctl-plugin-nano",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "c8ctl plugin to start, inspect, and stop a local Nano BPM (nanobpmn) cluster",
|
|
6
6
|
"main": "c8ctl-plugin.js",
|
|
@@ -49,12 +49,12 @@
|
|
|
49
49
|
"semantic-release": "^25.0.3"
|
|
50
50
|
},
|
|
51
51
|
"optionalDependencies": {
|
|
52
|
-
"@nanobpm/c8ctl-plugin-nano-darwin-arm64": "1.
|
|
53
|
-
"@nanobpm/c8ctl-plugin-nano-darwin-x64": "1.
|
|
54
|
-
"@nanobpm/c8ctl-plugin-nano-linux-x64": "1.
|
|
55
|
-
"@nanobpm/c8ctl-plugin-nano-linux-arm64": "1.
|
|
56
|
-
"@nanobpm/c8ctl-plugin-nano-linux-armv7": "1.
|
|
57
|
-
"@nanobpm/c8ctl-plugin-nano-linux-armv6": "1.
|
|
58
|
-
"@nanobpm/c8ctl-plugin-nano-win32-x64": "1.
|
|
52
|
+
"@nanobpm/c8ctl-plugin-nano-darwin-arm64": "1.17.0",
|
|
53
|
+
"@nanobpm/c8ctl-plugin-nano-darwin-x64": "1.17.0",
|
|
54
|
+
"@nanobpm/c8ctl-plugin-nano-linux-x64": "1.17.0",
|
|
55
|
+
"@nanobpm/c8ctl-plugin-nano-linux-arm64": "1.17.0",
|
|
56
|
+
"@nanobpm/c8ctl-plugin-nano-linux-armv7": "1.17.0",
|
|
57
|
+
"@nanobpm/c8ctl-plugin-nano-linux-armv6": "1.17.0",
|
|
58
|
+
"@nanobpm/c8ctl-plugin-nano-win32-x64": "1.17.0"
|
|
59
59
|
}
|
|
60
60
|
}
|