c8ctl-plugin-nano 1.25.0 → 1.26.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 CHANGED
@@ -106,6 +106,10 @@ c8ctl nano clean
106
106
  c8ctl nano set bin ~/workspace/nanobpmn/server/target/release/nanobpm-gateway-rest-server
107
107
  c8ctl nano set model-dir ~/bpmn-workspace
108
108
 
109
+ # Clear a custom setting (back to the managed/release binary, or default workspace)
110
+ c8ctl nano unset bin
111
+ c8ctl nano unset model-dir
112
+
109
113
  # Show current configuration and on-disk locations
110
114
  c8ctl nano config
111
115
  ```
@@ -575,17 +579,23 @@ c8ctl nano start --console off # headless: no console router at all
575
579
  env var is honored when the flag is not passed. The plugin passes the choice
576
580
  through as `NANOBPMN_CONSOLE` on every node.
577
581
 
578
- ## Configuration (`set` / `config`)
582
+ ## Configuration (`set` / `unset` / `config`)
579
583
 
580
584
  Persistent settings are stored in `<state home>/config.json`:
581
585
 
582
- | Setting | Env mapping | Set with |
583
- |---------------------|--------------------------|-----------------------------------|
584
- | Binary path | (used to launch nodes) | `c8ctl nano set bin <path>` |
585
- | Workspace directory | `NANOBPMN_WORKSPACE_DIR` | `c8ctl nano set model-dir <path>` |
586
+ | Setting | Env mapping | Set with | Clear with |
587
+ |---------------------|--------------------------|-----------------------------------|-------------------------------|
588
+ | Binary path | (used to launch nodes) | `c8ctl nano set bin <path>` | `c8ctl nano unset bin` |
589
+ | Workspace directory | `NANOBPMN_WORKSPACE_DIR` | `c8ctl nano set model-dir <path>` | `c8ctl nano unset model-dir` |
586
590
 
587
591
  Show the effective configuration and all on-disk locations with `c8ctl nano config`.
588
592
 
593
+ `unset bin` clears a custom binary path so node launches fall back to the
594
+ managed platform binary — i.e. back on the release train that `c8ctl nano
595
+ update` tracks. (Note: a `NANOBPMN_BINARY` environment variable still overrides
596
+ even after `unset`.) `unset model-dir` returns the workspace to its default
597
+ (`<state home>/workspace`).
598
+
589
599
  ## Updating to a new release (`update`)
590
600
 
591
601
  The plugin and the bundled server binary (delivered via the matching platform
package/c8ctl-plugin.js CHANGED
@@ -450,7 +450,7 @@ function launcherEnvMarkers(resolved) {
450
450
  // Argument parsing
451
451
  // ---------------------------------------------------------------------------
452
452
 
453
- const VALID_SUBCOMMANDS = ['start', 'stop', 'status', 'logs', 'log', 'restart', 'pause', 'resume', 'clean', 'set', 'config', 'update', 'hire', 'assign', 'work', 'supervisor'];
453
+ const VALID_SUBCOMMANDS = ['start', 'stop', 'status', 'logs', 'log', 'restart', 'pause', 'resume', 'clean', 'set', 'unset', 'config', 'update', 'hire', 'assign', 'work', 'supervisor'];
454
454
 
455
455
  /**
456
456
  * Parse positional args + flags into a normalized request.
@@ -1387,7 +1387,7 @@ function setConfig(req) {
1387
1387
  const key = req.positional[0];
1388
1388
  const value = req.positional[1];
1389
1389
 
1390
- if (!key || !(key in SETTING_ALIASES)) {
1390
+ if (!key || !Object.hasOwn(SETTING_ALIASES, key)) {
1391
1391
  logger.error('Usage: c8ctl nano set <bin|model-dir> <path>');
1392
1392
  logger.info('Settings:');
1393
1393
  logger.info(' bin <path> Path to the nanobpmn server binary');
@@ -1423,12 +1423,69 @@ function setConfig(req) {
1423
1423
  }
1424
1424
  }
1425
1425
 
1426
+ /**
1427
+ * Clear a configured setting so resolution falls back to the default. The
1428
+ * headline use is `unset bin`: after `set bin <path>` pins a self-managed
1429
+ * binary (source 'configured', which disables self-update), clearing it lets
1430
+ * the plugin fall back to the managed npm platform package — i.e. back on the
1431
+ * release train. `unset model-dir` returns the workspace to its default.
1432
+ */
1433
+ function unsetConfig(req) {
1434
+ const logger = getLogger();
1435
+ const key = req.positional[0];
1436
+
1437
+ if (!key || !Object.hasOwn(SETTING_ALIASES, key)) {
1438
+ logger.error('Usage: c8ctl nano unset <bin|model-dir>');
1439
+ logger.info('Settings:');
1440
+ logger.info(' bin Clear the custom server binary (back to the managed/release binary)');
1441
+ logger.info(' model-dir Clear the custom workspace dir (back to the default)');
1442
+ process.exit(1);
1443
+ }
1444
+
1445
+ const field = SETTING_ALIASES[key];
1446
+ const cfg = readConfig();
1447
+ const prev = cfg[field];
1448
+ const wasSet = prev !== undefined && prev !== null && prev !== '';
1449
+ const label = field === 'binary' ? 'custom binary override' : 'custom workspace override';
1450
+
1451
+ if (!wasSet) {
1452
+ logger.info(`No ${label} is configured — nothing to clear.`);
1453
+ } else {
1454
+ delete cfg[field];
1455
+ writeConfig(cfg);
1456
+ logger.info(`Cleared ${label} (was ${prev}).`);
1457
+ }
1458
+
1459
+ if (field === 'binary') {
1460
+ // Report what resolves now, so the operator can see they are back on the
1461
+ // managed release train (or what still overrides it).
1462
+ try {
1463
+ const r = resolveBinary({});
1464
+ logger.info(`Now using: ${r.path} (${r.from}).`);
1465
+ if (r.source === 'managed-npm') {
1466
+ logger.info('Back on the managed release train — "c8ctl nano update" now tracks the published release.');
1467
+ } else if (r.source === 'configured') {
1468
+ logger.warn('Still pinned by NANOBPMN_BINARY in your environment; unset that to use the managed binary.');
1469
+ }
1470
+ } catch (err) {
1471
+ logger.warn(`No binary resolves now: ${err instanceof Error ? err.message : err}`);
1472
+ logger.info('Reinstall the plugin to fetch the managed platform binary, or set one again with "c8ctl nano set bin <path>".');
1473
+ }
1474
+ } else if (field === 'workspaceDir') {
1475
+ logger.info(`Workspace is now the default: ${getWorkspaceDir()}.`);
1476
+ const running = readState();
1477
+ if (running && liveNodeCount(running) > 0) {
1478
+ logger.warn('A cluster is running — restart it for the new workspace to take effect.');
1479
+ }
1480
+ }
1481
+ }
1482
+
1426
1483
  function showConfig() {
1427
1484
  const cfg = readConfig();
1428
1485
  console.log('Nano plugin configuration:');
1429
1486
  console.log('');
1430
1487
  console.log(` state home ${getStateHome()}`);
1431
- console.log(` binary ${cfg.binary || '(auto-detect: $NANOBPMN_BINARY or repo build)'}`);
1488
+ console.log(` binary ${cfg.binary || '(auto-detect: $NANOBPMN_BINARY, managed platform package, or repo build)'}`);
1432
1489
  const bundled = readBundledBinaryInfo();
1433
1490
  if (bundled) {
1434
1491
  const at = bundled.commit && bundled.commit !== 'unknown' ? ` (${bundled.commit})` : '';
@@ -1441,6 +1498,7 @@ function showConfig() {
1441
1498
  console.log(` config file ${getConfigFile()}`);
1442
1499
  console.log('');
1443
1500
  console.log(' Change with: c8ctl nano set bin <path> | c8ctl nano set model-dir <path>');
1501
+ console.log(' Clear with: c8ctl nano unset bin | c8ctl nano unset model-dir');
1444
1502
  }
1445
1503
 
1446
1504
  // ---------------------------------------------------------------------------
@@ -1730,13 +1788,14 @@ function resolveAssignInputs(req, flags) {
1730
1788
  * capabilities are the remaining positionals and/or `--capabilities a,b`.
1731
1789
  * Capabilities are unioned with the profile's existing set (additive; assign
1732
1790
  * never removes a role) and the updated rank×capability job-type matrix is
1733
- * printed. Re-run `work` to pick up the new job types.
1791
+ * printed. Running workers hot-reload the new job types within ~1.5s — no
1792
+ * restart needed.
1734
1793
  */
1735
1794
  async function assignCapabilities(req, flags) {
1736
1795
  const logger = getLogger();
1737
1796
  const { name, incomingRaw } = resolveAssignInputs(req, flags);
1738
1797
  if (!name) {
1739
- logger.error('Usage: c8ctl nano assign <profileName> [<capability> ...] [--name <n>] [--capabilities <a,b>]');
1798
+ logger.error('Usage: c8ctl nano assign <profileName> <cap[,cap...]> [--name <n>] [--capabilities <a,b>]');
1740
1799
  logger.info('Grant new capabilities to an existing hire. List profiles with: c8ctl nano hire --list');
1741
1800
  process.exit(1);
1742
1801
  }
@@ -1747,7 +1806,7 @@ async function assignCapabilities(req, flags) {
1747
1806
 
1748
1807
  if (normalizeCapabilities(incomingRaw).length === 0) {
1749
1808
  logger.error('Provide at least one capability to assign.');
1750
- logger.info(`Example: c8ctl nano assign ${name} code-review testing`);
1809
+ logger.info(`Example: c8ctl nano assign ${name} code-review,testing`);
1751
1810
  process.exit(1);
1752
1811
  }
1753
1812
 
@@ -1778,7 +1837,7 @@ async function assignCapabilities(req, flags) {
1778
1837
  logger.info(`Assigned to "${name}" [${profile.rank}]: +${added.join(', ')}`);
1779
1838
  logger.info(` capabilities: ${profile.capabilities.join(', ')}`);
1780
1839
  logger.info(` job types (${matrix.length}): ${matrix.join(' ')}`);
1781
- logger.info(`Restart its workers to pick up the new roles: c8ctl nano work ${name}`);
1840
+ logger.info(`Running workers pick this up automatically within ~1.5s no restart needed.`);
1782
1841
  }
1783
1842
 
1784
1843
  /**
@@ -6120,6 +6179,7 @@ function parseProcessosRequest(args, flags) {
6120
6179
  // Internal helpers exported for tests/tooling only. c8ctl consumes just
6121
6180
  // `metadata` and `commands`; these named exports are inert to it.
6122
6181
  export { resolveBinary, findBinary, launcherEnvMarkers };
6182
+ export { setConfig, unsetConfig, readConfig, writeConfig, getConfigFile, SETTING_ALIASES };
6123
6183
  export { buildNpmInvocation };
6124
6184
  export {
6125
6185
  webConsoleUrl,
@@ -6230,6 +6290,7 @@ export const metadata = {
6230
6290
  { command: 'c8ctl nano restart --purge', description: 'Restart the cluster from a clean slate (delete engine data)' },
6231
6291
  { command: 'c8ctl nano clean', description: 'Wipe journal/data + logs on disk (keeps models/workers)' },
6232
6292
  { command: 'c8ctl nano set bin <path>', description: 'Set the nanobpmn server binary path' },
6293
+ { command: 'c8ctl nano unset bin', description: 'Clear a custom binary path and return to the managed/release binary' },
6233
6294
  { command: 'c8ctl nano set model-dir <path>', description: 'Set the workspace dir (models + workers)' },
6234
6295
  { command: 'c8ctl nano config', description: 'Show current plugin configuration and paths' },
6235
6296
  { command: 'c8ctl nano update', description: 'Pull the latest published nano release (re-installs via npm)' },
@@ -6240,6 +6301,7 @@ export const metadata = {
6240
6301
  { command: 'c8ctl nano hire --name coder --rank senior --command copilot --env COPILOT_ENABLE_ALL_TOOLS=1', description: 'Persist a harness startup env var (e.g. permissions) on the profile' },
6241
6302
  { command: 'c8ctl nano hire --list', description: 'List hired agent profiles' },
6242
6303
  { command: 'c8ctl nano hire --name coder --rank senior --command "agent-harness" --sandbox docker --image ghcr.io/acme/agent:1', description: 'Create a profile that runs each job in a throwaway Docker container' },
6304
+ { command: 'c8ctl nano assign reviewer code-review,testing', description: 'Grant more capabilities (comma-separated, like hire) to an existing hire — additive; running workers hot-reload it' },
6243
6305
  { command: 'c8ctl nano work reviewer', description: 'Spawn Nano job workers for the "reviewer" profile and poll for work' },
6244
6306
  { command: 'c8ctl nano work coder --sandbox docker --image ghcr.io/acme/agent:1', description: 'Run jobs in isolated containers with disk-hygiene reaping' },
6245
6307
  { command: 'c8ctl nano supervisor start --worker reviewer --worker coder', description: 'Start a detached supervisor managing several workers from one terminal' },
@@ -6358,6 +6420,9 @@ export const commands = {
6358
6420
  case 'set':
6359
6421
  setConfig(req);
6360
6422
  break;
6423
+ case 'unset':
6424
+ unsetConfig(req);
6425
+ break;
6361
6426
  case 'config':
6362
6427
  showConfig();
6363
6428
  break;
@@ -6462,10 +6527,11 @@ function printUsage() {
6462
6527
  console.log(' c8ctl nano restart [<nodes>] [--purge] ...');
6463
6528
  console.log(' c8ctl nano clean [--workspace]');
6464
6529
  console.log(' c8ctl nano set <bin|model-dir> <path>');
6530
+ console.log(' c8ctl nano unset <bin|model-dir>');
6465
6531
  console.log(' c8ctl nano config');
6466
6532
  console.log(' c8ctl nano update [--check]');
6467
6533
  console.log(' c8ctl nano hire [--name <n>] [--rank <r>] [--command <c>] [--arg <switch> ...] [--model <m>] [--capabilities <a,b>] [--sandbox none|docker|podman] [--image <ref>] [--env NAME=VALUE ...] [--list]');
6468
- console.log(' c8ctl nano assign <profileName> [<capability> ...] [--name <n>] [--capabilities <a,b>]');
6534
+ console.log(' c8ctl nano assign <profileName> <cap[,cap...]> [--name <n>] [--capabilities <a,b>]');
6469
6535
  console.log(' c8ctl nano work <profileName> [--arg <switch> ...] [--max-parallel <n>] [--recovery-window <ms>] [--idle-timeout <ms>] [--job-timeout <ms>] [--poll-timeout <ms>] [--job-type <token> ...] [--sandbox none|docker|podman] [--image <ref>] [--env NAME=VALUE ...] [--secret-resolver host] [--min-free-mb <n>] [--clone-timeout <ms>] [--keep-runs] [--stream]');
6470
6536
  console.log(' c8ctl nano supervisor [start|status|add|remove|restart|stop|logs|attach] ... (manage many workers from one terminal)');
6471
6537
  console.log('');
@@ -6479,10 +6545,11 @@ function printUsage() {
6479
6545
  console.log(' restart Stop then start');
6480
6546
  console.log(' clean Wipe journal/data + logs on disk (keeps models/workers)');
6481
6547
  console.log(' set Persist a setting: "bin <path>" or "model-dir <path>"');
6548
+ console.log(' unset Clear a setting ("bin" or "model-dir") back to its default');
6482
6549
  console.log(' config Show current configuration and on-disk locations');
6483
6550
  console.log(' update Pull the latest published nano release (--check to only report)');
6484
6551
  console.log(' hire Create a CLI agent worker profile (rank + capabilities → job-type matrix)');
6485
- console.log(' assign Grant new capabilities (roles) to an existing hire (additive)');
6552
+ console.log(' assign Grant new capabilities (roles) to an existing hire (additive; comma-separated; workers hot-reload)');
6486
6553
  console.log(' work Run a hired profile as Nano job workers, polling for work until Ctrl-C');
6487
6554
  console.log(' supervisor Run/manage a fleet of workers from one terminal (detachable console + non-interactive control)');
6488
6555
  console.log('');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c8ctl-plugin-nano",
3
- "version": "1.25.0",
3
+ "version": "1.26.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",
@@ -47,12 +47,12 @@
47
47
  "semantic-release": "^25.0.3"
48
48
  },
49
49
  "optionalDependencies": {
50
- "@nanobpm/c8ctl-plugin-nano-darwin-arm64": "1.25.0",
51
- "@nanobpm/c8ctl-plugin-nano-darwin-x64": "1.25.0",
52
- "@nanobpm/c8ctl-plugin-nano-linux-x64": "1.25.0",
53
- "@nanobpm/c8ctl-plugin-nano-linux-arm64": "1.25.0",
54
- "@nanobpm/c8ctl-plugin-nano-linux-armv7": "1.25.0",
55
- "@nanobpm/c8ctl-plugin-nano-linux-armv6": "1.25.0",
56
- "@nanobpm/c8ctl-plugin-nano-win32-x64": "1.25.0"
50
+ "@nanobpm/c8ctl-plugin-nano-darwin-arm64": "1.26.0",
51
+ "@nanobpm/c8ctl-plugin-nano-darwin-x64": "1.26.0",
52
+ "@nanobpm/c8ctl-plugin-nano-linux-x64": "1.26.0",
53
+ "@nanobpm/c8ctl-plugin-nano-linux-arm64": "1.26.0",
54
+ "@nanobpm/c8ctl-plugin-nano-linux-armv7": "1.26.0",
55
+ "@nanobpm/c8ctl-plugin-nano-linux-armv6": "1.26.0",
56
+ "@nanobpm/c8ctl-plugin-nano-win32-x64": "1.26.0"
57
57
  }
58
58
  }