c8ctl-plugin-nano 1.18.1 → 1.19.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.
Files changed (3) hide show
  1. package/README.md +39 -1
  2. package/c8ctl-plugin.js +157 -10
  3. package/package.json +8 -10
package/README.md CHANGED
@@ -24,7 +24,7 @@ It adds a single `nano` command:
24
24
 
25
25
  ```bash
26
26
  c8ctl nano start|status|stop|restart|logs|pause|resume|clean|set|config|update
27
- c8ctl nano hire|work # turn a CLI agent harness into a Nano job worker
27
+ c8ctl nano hire|assign|work # hire/assign manage agent profiles; work runs one as a Nano job worker
28
28
  ```
29
29
 
30
30
  `nano start N` spawns **N** nanobpmn node processes wired to talk to each other
@@ -157,6 +157,24 @@ c8ctl nano hire --name coder --rank senior --command copilot --arg --allow-all
157
157
  c8ctl nano hire --list
158
158
  ```
159
159
 
160
+ **`assign <name> [capabilities...]`** grants new capabilities (roles) to an
161
+ existing hire without re-running `hire`. Capabilities are **added** to (unioned
162
+ with) the profile's current set — `assign` never removes a role — and the
163
+ updated job-type matrix is printed. Restart the profile's workers so they pick
164
+ up the new job types:
165
+
166
+ ```bash
167
+ # Give an existing reviewer two more capabilities
168
+ c8ctl nano assign reviewer triage refactoring
169
+
170
+ # --capabilities works too (comma-separated), equivalent to the positionals above
171
+ c8ctl nano assign reviewer --capabilities triage,refactoring
172
+
173
+ # then restart its workers to service the new job types
174
+ c8ctl nano work reviewer
175
+ ```
176
+
177
+
160
178
  **`work <name>`** loads the profile, connects with the c8ctl SDK client, and
161
179
  registers one job worker per token in the **rank × capability matrix**, then
162
180
  polls for work in the foreground until Ctrl-C. For rank `senior` and
@@ -217,6 +235,16 @@ config`).
217
235
  > Raising `--job-timeout` alone does **not** fix this — it moves both coupled
218
236
  > deadlines together; widen `--lock-grace` (or keep the default) instead.
219
237
 
238
+ > **Long-poll window.** `--poll-timeout` (default `30000`ms) is how long the
239
+ > broker holds each `activateJobs` request open waiting for work before returning
240
+ > empty. A longer window keeps an idle worker on **one** connection for that whole
241
+ > window instead of reconnecting every few seconds — cutting the number of
242
+ > connection establishments, and thus the chances of hitting a transient connect
243
+ > error (`ECONNREFUSED` / connect-timeout) on a flaky link. It maps straight to
244
+ > the SDK's `pollTimeoutMs` → the broker's `requestTimeout`: `0` selects the
245
+ > broker's own default (~5s) and a negative value returns immediately when no job
246
+ > is available.
247
+
220
248
  > **Trust boundary.** The profile `command` is run through a shell so you can
221
249
  > write a full invocation (args, pipes, multi-word commands). It is
222
250
  > **operator-authored** — only what you put in your own `config.json` is
@@ -246,6 +274,16 @@ Element templates emit flat dotpath header keys (strings); the plugin expands
246
274
  them into a nested object and coerces `"true"/"false"` → bool and numeric
247
275
  strings → int. The normalized shape is
248
276
  `{ schemaVersion, repository{provider,url,ref,depth,submodules,authRef}, branch{base,create,push}, setup{commands,env,secretRefs}, task{prompt,promptFile,maxIterations,timeoutMs,allowPr,prBase} }`.
277
+
278
+ **Prompt = base + optional verbatim append.** The agent's prompt resolves to
279
+ `task.prompt` (typically a model header filled at deploy time), falling back to a
280
+ plain `prompt`/`task` variable. Because a header-delivered base prompt can't be
281
+ composed in FEEL, a task may supply per-instance context via **`task.appendPrompt`**
282
+ (reserved) or a plain **`appendPrompt`** variable — it is concatenated onto the base
283
+ **verbatim, with no injected separator** (the model's ioMapping owns any leading
284
+ separator/preamble), so a null/empty append leaves the base untouched. This lets the
285
+ static prompt live in a model header/side-car while the dynamic tail (e.g. plan-revision
286
+ feedback, a per-task brief) is built per instance.
249
287
  On completion the plugin writes an **output envelope** back under
250
288
  `io.nanobpm.agentResult` (`{schemaVersion, status, sandbox, image, output, truncated, stderrTruncated, exitCode, signal, error}`). When a repository was
251
289
  provisioned (below) it also carries `{repository, branch, baseSha, headSha, commits[], pushed, pushError?, gitError?, pr?}`.
package/c8ctl-plugin.js CHANGED
@@ -368,7 +368,7 @@ function launcherEnvMarkers(resolved) {
368
368
  // Argument parsing
369
369
  // ---------------------------------------------------------------------------
370
370
 
371
- const VALID_SUBCOMMANDS = ['start', 'stop', 'status', 'logs', 'log', 'restart', 'pause', 'resume', 'clean', 'set', 'config', 'update', 'hire', 'work'];
371
+ const VALID_SUBCOMMANDS = ['start', 'stop', 'status', 'logs', 'log', 'restart', 'pause', 'resume', 'clean', 'set', 'config', 'update', 'hire', 'assign', 'work'];
372
372
 
373
373
  /**
374
374
  * Parse positional args + flags into a normalized request.
@@ -1518,7 +1518,32 @@ function deriveJobLockMs(jobTimeoutMs, lockGraceMs) {
1518
1518
  return { killMs, lockMs: killMs + grace };
1519
1519
  }
1520
1520
 
1521
- /** A profile name must be a safe, filesystem/token-friendly slug. */
1521
+ /**
1522
+ * Resolve the broker long-poll window (ms) each `activateJobs` request is held
1523
+ * open before returning empty. A longer window keeps an idle worker on ONE open
1524
+ * connection for that whole window instead of reconnecting every few seconds,
1525
+ * cutting the number of connection establishments — and thus the number of
1526
+ * chances to hit a transient connect failure (ECONNREFUSED / connect-timeout)
1527
+ * on a flaky link.
1528
+ *
1529
+ * The value is passed straight through to the SDK as `pollTimeoutMs` → the
1530
+ * broker's `requestTimeout`, so the documented broker semantics apply: `0` =
1531
+ * broker default (~5s), a negative value = return immediately when no job is
1532
+ * available. Parsing is `parseInt`-style: only a flag with no leading integer
1533
+ * (absent, blank, or non-numeric such as `"abc"`) falls back to the default,
1534
+ * while a leading integer with trailing junk (e.g. `"30000ms"`) is honoured as
1535
+ * that integer. `0` and negatives are honoured too (which is why this cannot
1536
+ * reuse `intFlag`, whose "> 0" guard would floor them to the default).
1537
+ *
1538
+ * @returns {number}
1539
+ */
1540
+ function derivePollTimeoutMs(flagValue, dflt = 30_000) {
1541
+ if (flagValue === undefined || flagValue === null || String(flagValue).trim() === '') {
1542
+ return dflt;
1543
+ }
1544
+ const n = Number.parseInt(String(flagValue), 10);
1545
+ return Number.isFinite(n) ? n : dflt;
1546
+ }
1522
1547
  function isValidProfileName(name) {
1523
1548
  return typeof name === 'string' && /^[a-z0-9][a-z0-9._-]*$/i.test(name);
1524
1549
  }
@@ -1597,7 +1622,99 @@ function normalizeStoredProfile(name, profile) {
1597
1622
  }
1598
1623
 
1599
1624
  /**
1600
- * hire create (or overwrite) an agent profile. Interactive by default; every
1625
+ * Merge additional capabilities into an already-normalized profile, returning a
1626
+ * new profile object with the union of capabilities (canonical order) and a
1627
+ * refreshed `updatedAt`. Pure (no config I/O), so it is unit-testable. Existing
1628
+ * fields — including `createdAt` — are preserved. `incoming` may be a
1629
+ * comma-string or an array. Returns `{ profile, added }`, where `added` lists
1630
+ * the newly gained capabilities (empty when the assign is a no-op).
1631
+ */
1632
+ function applyAssign(existing, incoming, now = new Date().toISOString()) {
1633
+ const before = new Set(normalizeCapabilities(existing && existing.capabilities));
1634
+ const union = normalizeCapabilities([...before, ...normalizeCapabilities(incoming)]);
1635
+ const added = union.filter((c) => !before.has(c));
1636
+ return {
1637
+ profile: { ...existing, capabilities: union, updatedAt: now },
1638
+ added,
1639
+ };
1640
+ }
1641
+
1642
+ /**
1643
+ * Resolve the profile name and the raw comma-joined capability string for an
1644
+ * `assign` invocation from parsed positionals + flags. Pure (no I/O) so the
1645
+ * positional-slicing rules are unit-testable.
1646
+ *
1647
+ * When `--name` is supplied the name does NOT consume a positional, so every
1648
+ * positional is a capability. Otherwise the first positional is the name and
1649
+ * the rest are capabilities. `--capabilities a,b` is always appended.
1650
+ */
1651
+ function resolveAssignInputs(req, flags) {
1652
+ const positional = Array.isArray(req?.positional) ? req.positional : [];
1653
+ const name = flags?.name ? String(flags.name).trim() : positional[0];
1654
+ const positionalCaps = flags?.name ? positional : positional.slice(1);
1655
+ const flagCaps = flags?.capabilities !== undefined ? String(flags.capabilities) : '';
1656
+ const incomingRaw = [...positionalCaps, flagCaps].filter(Boolean).join(',');
1657
+ return { name, incomingRaw };
1658
+ }
1659
+
1660
+ /**
1661
+ * assign — grant new capabilities (roles) to an existing hire without
1662
+ * re-running `hire`. The profile name is positional[0] (or `--name`);
1663
+ * capabilities are the remaining positionals and/or `--capabilities a,b`.
1664
+ * Capabilities are unioned with the profile's existing set (additive; assign
1665
+ * never removes a role) and the updated rank×capability job-type matrix is
1666
+ * printed. Re-run `work` to pick up the new job types.
1667
+ */
1668
+ async function assignCapabilities(req, flags) {
1669
+ const logger = getLogger();
1670
+ const { name, incomingRaw } = resolveAssignInputs(req, flags);
1671
+ if (!name) {
1672
+ logger.error('Usage: c8ctl nano assign <profileName> [<capability> ...] [--name <n>] [--capabilities <a,b>]');
1673
+ logger.info('Grant new capabilities to an existing hire. List profiles with: c8ctl nano hire --list');
1674
+ process.exit(1);
1675
+ }
1676
+ if (!isValidProfileName(name)) {
1677
+ logger.error(`Invalid profile name "${name}". Use letters, digits, dot, dash or underscore.`);
1678
+ process.exit(1);
1679
+ }
1680
+
1681
+ if (normalizeCapabilities(incomingRaw).length === 0) {
1682
+ logger.error('Provide at least one capability to assign.');
1683
+ logger.info(`Example: c8ctl nano assign ${name} code-review testing`);
1684
+ process.exit(1);
1685
+ }
1686
+
1687
+ const raw = readHires()[name];
1688
+ if (!raw) {
1689
+ logger.error(`No hire named "${name}". List profiles with: c8ctl nano hire --list`);
1690
+ process.exit(1);
1691
+ }
1692
+ const normalized = normalizeStoredProfile(name, raw);
1693
+ if (normalized.error) {
1694
+ logger.error(`Cannot assign to "${name}": ${normalized.error}. Re-create it with: c8ctl nano hire`);
1695
+ process.exit(1);
1696
+ }
1697
+
1698
+ // Preserve createdAt (normalizeStoredProfile drops it) on the canonical form.
1699
+ const base = {
1700
+ ...normalized.profile,
1701
+ createdAt: typeof raw.createdAt === 'string' ? raw.createdAt : new Date().toISOString(),
1702
+ };
1703
+ const { profile, added } = applyAssign(base, incomingRaw);
1704
+ if (added.length === 0) {
1705
+ logger.info(`"${name}" already has: ${profile.capabilities.join(', ') || '(none)'} — no change.`);
1706
+ return;
1707
+ }
1708
+ writeHire(profile);
1709
+
1710
+ const matrix = jobTypeMatrix(profile.rank, profile.capabilities);
1711
+ logger.info(`Assigned to "${name}" [${profile.rank}]: +${added.join(', ')}`);
1712
+ logger.info(` capabilities: ${profile.capabilities.join(', ')}`);
1713
+ logger.info(` job types (${matrix.length}): ${matrix.join(' ')}`);
1714
+ logger.info(`Restart its workers to pick up the new roles: c8ctl nano work ${name}`);
1715
+ }
1716
+
1717
+ /**
1601
1718
  * field can also be supplied via a flag (--name/--rank/--command/--model/
1602
1719
  * --capabilities) for scripting. Prompts only for the fields still missing.
1603
1720
  * `--list` prints existing profiles instead.
@@ -2006,8 +2123,21 @@ function normalizeTaskEnvelope(customHeaders, variables) {
2006
2123
  };
2007
2124
 
2008
2125
  const task = isPlainObject(raw.task) ? raw.task : {};
2126
+ // Base prompt: the reserved `task.prompt` (typically a model header filled at deploy time),
2127
+ // else a plain `prompt`/`task` job variable (the pre-header delivery path).
2128
+ const basePrompt = str(task.prompt) ?? str(variables?.prompt) ?? str(variables?.task);
2129
+ // Verbatim dynamic append: a header-delivered base prompt can't be composed in FEEL, so a task
2130
+ // may supply per-instance context (e.g. plan-revision feedback, a per-task brief) via the
2131
+ // reserved `task.appendPrompt`, or a plain `appendPrompt` variable. It is concatenated onto the
2132
+ // base with NO injected separator — the caller (the model's ioMapping) owns any leading
2133
+ // separator/preamble — so a null/empty append leaves the base prompt untouched.
2134
+ const appendPrompt = str(task.appendPrompt) ?? str(variables?.appendPrompt);
2135
+ const prompt =
2136
+ appendPrompt != null && appendPrompt !== ''
2137
+ ? `${basePrompt ?? ''}${appendPrompt}`
2138
+ : basePrompt;
2009
2139
  env.task = {
2010
- prompt: str(task.prompt) ?? str(variables?.prompt) ?? str(variables?.task),
2140
+ prompt,
2011
2141
  promptFile: str(task.promptFile),
2012
2142
  maxIterations: coerceInt(task.maxIterations, undefined),
2013
2143
  timeoutMs: coerceInt(task.timeoutMs, undefined),
@@ -2730,6 +2860,11 @@ async function workAgent(req, flags) {
2730
2860
  // MUST enforce the clamped `jobKillMs` (not the raw --job-timeout), or a very
2731
2861
  // large --job-timeout would outlive the broker lock and re-break the invariant.
2732
2862
  const { killMs: jobKillMs, lockMs: jobLockMs } = deriveJobLockMs(jobTimeoutMs, lockGraceMs);
2863
+ // Broker long-poll window: how long each activateJobs request is held open
2864
+ // waiting for work. 30s default so idle workers hold one connection open ~30s
2865
+ // rather than reconnecting every few seconds — fewer reconnects, fewer chances
2866
+ // to hit a transient connect error on a flaky link. Passed to the SDK verbatim.
2867
+ const pollTimeoutMs = derivePollTimeoutMs(flags?.['poll-timeout']);
2733
2868
 
2734
2869
  // Sandbox: flag overrides the stored profile default. `none` runs on the host
2735
2870
  // (legacy); `docker`/`podman` run each job in a throwaway labelled container.
@@ -2837,7 +2972,7 @@ async function workAgent(req, flags) {
2837
2972
  if (profileEnvKeys.length > 0) logger.info(` harness env: ${profileEnvKeys.join(', ')}`);
2838
2973
  const extraNote = extraJobTypes.length > 0 ? ` (${extraJobTypes.length} via --job-type)` : '';
2839
2974
  logger.info(` listening on ${jobTypes.length} job type(s)${extraNote}: ${jobTypes.join(' ')}`);
2840
- logger.info(` max parallel: ${maxParallelJobs}; job timeout: ${jobKillMs}ms; activation lock: ${jobLockMs}ms`);
2975
+ logger.info(` max parallel: ${maxParallelJobs}; job timeout: ${jobKillMs}ms; activation lock: ${jobLockMs}ms; poll timeout: ${pollTimeoutMs}ms`);
2841
2976
  logger.info('Polling for work — press Ctrl-C to stop.');
2842
2977
 
2843
2978
  const workers = jobTypes.map((jobType) =>
@@ -2846,6 +2981,7 @@ async function workAgent(req, flags) {
2846
2981
  workerName: `${name}:${jobType}`,
2847
2982
  maxParallelJobs,
2848
2983
  jobTimeoutMs: jobLockMs,
2984
+ pollTimeoutMs,
2849
2985
  jobHandler: async (job) => {
2850
2986
  logger.info(`[${jobType}] job ${job.jobKey} (instance ${job.processInstanceKey ?? '-'}) → ${buildAgentCommandLine(profile.command, effectiveArgs)}`);
2851
2987
 
@@ -4373,6 +4509,7 @@ export {
4373
4509
  webConsoleUrl,
4374
4510
  consoleLinkLabel,
4375
4511
  hireWorker,
4512
+ assignCapabilities,
4376
4513
  };
4377
4514
  export {
4378
4515
  normalizeTaskEnvelope,
@@ -4407,9 +4544,12 @@ export {
4407
4544
  agentRunsRoot,
4408
4545
  ProvisionError,
4409
4546
  normalizeStoredProfile,
4547
+ applyAssign,
4548
+ resolveAssignInputs,
4410
4549
  jobTypeMatrix,
4411
4550
  parseJobTypeFlags,
4412
4551
  deriveJobLockMs,
4552
+ derivePollTimeoutMs,
4413
4553
  AGENT_TASK_NS,
4414
4554
  AGENT_RESULT_KEY,
4415
4555
  RESULT_SENTINEL,
@@ -4495,12 +4635,12 @@ export const commands = {
4495
4635
  workspace: { type: 'boolean', description: 'clean: also delete the workspace (models + workers)' },
4496
4636
  check: { type: 'boolean', description: 'update: only report whether a new release is available; do not install' },
4497
4637
  binary: { type: 'string', description: 'Path to the nanobpmn server binary' },
4498
- name: { type: 'string', description: 'hire/work: agent profile name (alt to positional arg)' },
4638
+ name: { type: 'string', description: 'hire/work/assign: agent profile name (alt to positional arg)' },
4499
4639
  rank: { type: 'string', description: 'hire: agent rank (principal|senior|junior|decider)' },
4500
4640
  command: { type: 'string', description: 'hire: CLI command that runs the agent harness (e.g. copilot, claude, pi)' },
4501
4641
  arg: { type: 'string', multiple: true, description: 'hire/work: command-line switch/arg appended to the harness command (repeatable), e.g. --arg --allow-all. Persisted on hire; work appends more.' },
4502
4642
  model: { type: 'string', description: 'hire: model name passed to the harness (AGENT_MODEL)' },
4503
- capabilities: { type: 'string', description: 'hire: comma-separated capability list' },
4643
+ capabilities: { type: 'string', description: 'hire/assign: comma-separated capability list' },
4504
4644
  sandbox: { type: 'string', description: 'hire/work: execution sandbox none|docker|podman (default none). Containers isolate each job.' },
4505
4645
  image: { type: 'string', description: 'hire/work: container image the agent runs in (required for --sandbox docker|podman)' },
4506
4646
  env: { type: 'string', multiple: true, description: 'hire/work: static env var for the harness as NAME=VALUE (repeatable); persisted on hire, work extends/overrides. E.g. permission toggles.' },
@@ -4515,6 +4655,7 @@ export const commands = {
4515
4655
  'max-parallel': { type: 'string', description: 'work: max concurrent jobs per worker (default 1)' },
4516
4656
  'job-timeout': { type: 'string', description: 'work: max harness runtime per job in ms; the spawned process is killed past this (default 300000)' },
4517
4657
  'lock-grace': { type: 'string', description: 'work: extra ms added to --job-timeout to derive the broker activation lock, so the worker reports before the lock lapses (default 120000)' },
4658
+ 'poll-timeout': { type: 'string', description: 'work: broker long-poll window in ms each activateJobs request is held open (fewer reconnects → fewer transient connect errors); default 30000, 0 = broker default, negative = return immediately' },
4518
4659
  'job-type': { type: 'string', multiple: true, description: 'work: extra job type to service alongside the rank×capability matrix (repeatable)' },
4519
4660
  },
4520
4661
  handler: async (args, flags) => {
@@ -4567,6 +4708,9 @@ export const commands = {
4567
4708
  case 'hire':
4568
4709
  await hireWorker(req, flags);
4569
4710
  break;
4711
+ case 'assign':
4712
+ await assignCapabilities(req, flags);
4713
+ break;
4570
4714
  case 'work':
4571
4715
  await workAgent(req, flags);
4572
4716
  break;
@@ -4659,7 +4803,8 @@ function printUsage() {
4659
4803
  console.log(' c8ctl nano config');
4660
4804
  console.log(' c8ctl nano update [--check]');
4661
4805
  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]');
4662
- console.log(' c8ctl nano work <profileName> [--arg <switch> ...] [--max-parallel <n>] [--job-timeout <ms>] [--lock-grace <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]');
4806
+ console.log(' c8ctl nano assign <profileName> [<capability> ...] [--name <n>] [--capabilities <a,b>]');
4807
+ console.log(' c8ctl nano work <profileName> [--arg <switch> ...] [--max-parallel <n>] [--job-timeout <ms>] [--lock-grace <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]');
4663
4808
  console.log('');
4664
4809
  console.log('Subcommands:');
4665
4810
  console.log(' start Spawn an N-node local cluster wired to talk to each other on localhost');
@@ -4674,6 +4819,7 @@ function printUsage() {
4674
4819
  console.log(' config Show current configuration and on-disk locations');
4675
4820
  console.log(' update Pull the latest published nano release (--check to only report)');
4676
4821
  console.log(' hire Create a CLI agent worker profile (rank + capabilities → job-type matrix)');
4822
+ console.log(' assign Grant new capabilities (roles) to an existing hire (additive)');
4677
4823
  console.log(' work Run a hired profile as Nano job workers, polling for work until Ctrl-C');
4678
4824
  console.log('');
4679
4825
  console.log('Options:');
@@ -4690,11 +4836,11 @@ function printUsage() {
4690
4836
  console.log(' --purge stop: also delete per-node engine data');
4691
4837
  console.log(' --force start: stop any existing cluster first');
4692
4838
  console.log(' --workspace clean: also delete the workspace (models + workers)');
4693
- console.log(' --name <n> hire/work: agent profile name (alt to positional arg)');
4839
+ console.log(' --name <n> hire/work/assign: agent profile name (alt to positional arg)');
4694
4840
  console.log(' --rank <r> hire: agent rank (principal|senior|junior|decider)');
4695
4841
  console.log(' --command <c> hire: CLI command that runs the agent harness');
4696
4842
  console.log(' --model <m> hire: model name passed to the harness (AGENT_MODEL)');
4697
- console.log(' --capabilities <a,b> hire: comma-separated capability list');
4843
+ console.log(' --capabilities <a,b> hire/assign: comma-separated capability list');
4698
4844
  console.log(' --sandbox <s> hire/work: execution sandbox none|docker|podman (default none)');
4699
4845
  console.log(' --image <ref> hire/work: container image the agent runs in (required for docker|podman)');
4700
4846
  console.log(' --env NAME=VALUE hire/work: static env var for the harness (repeatable); persisted on hire, work extends/overrides');
@@ -4703,6 +4849,7 @@ function printUsage() {
4703
4849
  console.log(' --job-type <token> work: extra job type to service alongside the rank×capability matrix (repeatable)');
4704
4850
  console.log(' --job-timeout <ms> work: max harness runtime per job in ms (default 300000)');
4705
4851
  console.log(' --lock-grace <ms> work: extra ms over --job-timeout for the broker activation lock (default 120000)');
4852
+ console.log(' --poll-timeout <ms> work: broker long-poll window per activateJobs request (default 30000; 0 = broker default, negative = immediate)');
4706
4853
  console.log(' --secret-resolver <r> work: secret resolver for task secretRefs (host; default host)');
4707
4854
  console.log(' --reap-age <ms> work: age before a finished agent container/workspace is reaped (default 3600000)');
4708
4855
  console.log(' --reap-interval <ms> work: how often to sweep finished agent containers/workspaces (default 300000)');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c8ctl-plugin-nano",
3
- "version": "1.18.1",
3
+ "version": "1.19.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",
@@ -42,19 +42,17 @@
42
42
  "devDependencies": {
43
43
  "@commitlint/cli": "^20.4.1",
44
44
  "@commitlint/config-conventional": "^20.4.1",
45
- "@semantic-release/changelog": "^6.0.3",
46
45
  "@semantic-release/exec": "^7.1.0",
47
- "@semantic-release/git": "^10.0.1",
48
46
  "@semantic-release/github": "^12.0.6",
49
47
  "semantic-release": "^25.0.3"
50
48
  },
51
49
  "optionalDependencies": {
52
- "@nanobpm/c8ctl-plugin-nano-darwin-arm64": "1.18.1",
53
- "@nanobpm/c8ctl-plugin-nano-darwin-x64": "1.18.1",
54
- "@nanobpm/c8ctl-plugin-nano-linux-x64": "1.18.1",
55
- "@nanobpm/c8ctl-plugin-nano-linux-arm64": "1.18.1",
56
- "@nanobpm/c8ctl-plugin-nano-linux-armv7": "1.18.1",
57
- "@nanobpm/c8ctl-plugin-nano-linux-armv6": "1.18.1",
58
- "@nanobpm/c8ctl-plugin-nano-win32-x64": "1.18.1"
50
+ "@nanobpm/c8ctl-plugin-nano-darwin-arm64": "1.19.0",
51
+ "@nanobpm/c8ctl-plugin-nano-darwin-x64": "1.19.0",
52
+ "@nanobpm/c8ctl-plugin-nano-linux-x64": "1.19.0",
53
+ "@nanobpm/c8ctl-plugin-nano-linux-arm64": "1.19.0",
54
+ "@nanobpm/c8ctl-plugin-nano-linux-armv7": "1.19.0",
55
+ "@nanobpm/c8ctl-plugin-nano-linux-armv6": "1.19.0",
56
+ "@nanobpm/c8ctl-plugin-nano-win32-x64": "1.19.0"
59
57
  }
60
58
  }