@11agents/cli 0.1.39 → 0.1.41

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@11agents/cli",
3
- "version": "0.1.39",
3
+ "version": "0.1.41",
4
4
  "description": "11agents local runtime and telemetry CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -83,7 +83,6 @@ function runtimeDeps(overrides = {}) {
83
83
  sleep: overrides.sleep || sleep,
84
84
  syncKnowledge: overrides.syncKnowledge || syncKnowledge,
85
85
  mcpKnowledgeSync: overrides.mcpKnowledgeSync || mcpKnowledgeSync,
86
- cpuCount: overrides.cpuCount ?? os.cpus().length,
87
86
  }
88
87
  }
89
88
 
@@ -248,7 +247,7 @@ export async function scanRuntime(flags = {}) {
248
247
  return scan
249
248
  }
250
249
 
251
- export async function registerRuntime(flags = {}, deps = {}) {
250
+ export async function registerRuntime(flags = {}, deps = {}, { maxConcurrent } = {}) {
252
251
  const { buildRuntimeScan: scanBuilder, log, requestJson: request } = runtimeDeps(deps)
253
252
  const config = configFromFlags(flags)
254
253
  if (!config.token) throw new Error('GTM_WRITES_TOKEN or --token is required')
@@ -256,9 +255,13 @@ export async function registerRuntime(flags = {}, deps = {}) {
256
255
  const scan = await scanBuilder({ env: scanEnvWithOverrides(flags), cliVersion: CLI_VERSION })
257
256
  if (!scan.runtimes.length) throw new Error('no local AI runtimes detected on PATH')
258
257
 
258
+ const body = maxConcurrent
259
+ ? { ...scan, runtimes: scan.runtimes.map(r => ({ ...r, max_concurrent: maxConcurrent })) }
260
+ : scan
261
+
259
262
  const result = await request('/api/runtime/machines/register', {
260
263
  method: 'POST',
261
- body: scan,
264
+ body,
262
265
  config,
263
266
  })
264
267
  log(JSON.stringify(result, null, 2))
@@ -1641,11 +1644,7 @@ async function claimAndRunRuntimeTasks(registration, flags, deps, handlerModule,
1641
1644
  const config = configFromFlags(flags)
1642
1645
  const machineKey = registration?.machine?.machine_key || machineOverride(flags) || ''
1643
1646
 
1644
- // Each runtime gets (vCPUs - 1) slots so the host stays responsive.
1645
- // maxConcurrent is honoured when it exceeds the CPU-derived default.
1646
- const perRuntime = Math.max(1, (deps.cpuCount ?? os.cpus().length) - 1)
1647
- const effectiveConcurrent = Math.max(maxConcurrent, runtimes.length * perRuntime)
1648
- const slots = Array.from({ length: effectiveConcurrent }, (_, i) => runtimes[i % runtimes.length])
1647
+ const slots = Array.from({ length: maxConcurrent }, (_, i) => runtimes[i % runtimes.length])
1649
1648
  const results = await Promise.allSettled(
1650
1649
  slots.map(runtime => runOneRuntimeTaskSlot(runtime, config, machineKey, registration, flags, deps, handlerModule, retryState, heartbeatIntervalMs))
1651
1650
  )
@@ -1653,12 +1652,28 @@ async function claimAndRunRuntimeTasks(registration, flags, deps, handlerModule,
1653
1652
  }
1654
1653
 
1655
1654
  async function drainRuntimeTasks(registration, flags, deps, handlerModule, retryState = createRetryState(), heartbeatIntervalMs = 15000, maxConcurrent = 1) {
1655
+ if (!handlerModule) return 0
1656
+ const runtimes = (registration?.runtimes || []).filter(r => r?.id)
1657
+ if (!runtimes.length) return 0
1658
+ const config = configFromFlags(flags)
1659
+ const machineKey = registration?.machine?.machine_key || machineOverride(flags) || ''
1660
+
1656
1661
  let completed = 0
1657
- while (true) {
1658
- const claimed = await claimAndRunRuntimeTasks(registration, flags, deps, handlerModule, retryState, heartbeatIntervalMs, maxConcurrent)
1659
- completed += claimed
1660
- if (claimed === 0) return completed
1661
- }
1662
+ // Worker pool: each worker loops claiming tasks until the queue is empty,
1663
+ // so a fast worker immediately picks up the next task without waiting for
1664
+ // slow workers to finish (unlike the old batched Promise.allSettled approach).
1665
+ const workers = Array.from({ length: maxConcurrent }, (_, i) => {
1666
+ const runtime = runtimes[i % runtimes.length]
1667
+ return (async () => {
1668
+ while (true) {
1669
+ const ran = await runOneRuntimeTaskSlot(runtime, config, machineKey, registration, flags, deps, handlerModule, retryState, heartbeatIntervalMs)
1670
+ if (!ran) break
1671
+ completed++
1672
+ }
1673
+ })()
1674
+ })
1675
+ await Promise.allSettled(workers)
1676
+ return completed
1662
1677
  }
1663
1678
 
1664
1679
  export async function startRuntimeDaemon(flags = {}, deps = {}) {
@@ -1667,11 +1682,9 @@ export async function startRuntimeDaemon(flags = {}, deps = {}) {
1667
1682
  const scanIntervalMs = Number(flag(flags, 'scan-interval', '60')) * 1000
1668
1683
  const taskIntervalMs = Number(flag(flags, 'task-interval', flag(flags, 'heartbeat-interval', '15'))) * 1000
1669
1684
  const projectRefreshIntervalMs = Number(flag(flags, 'project-refresh-interval', '1800')) * 1000
1670
- const cpuCount = resolvedDeps.cpuCount ?? os.cpus().length
1671
- const cpuDefault = Math.max(1, cpuCount - 1)
1672
1685
  const envMax = Number(process.env.DAEMON_MAX_CONCURRENCY)
1673
- const envConcurrency = Number.isInteger(envMax) && envMax > 0 && envMax <= cpuCount - 1 ? envMax : null
1674
- const maxConcurrent = envConcurrency ?? Math.max(1, Number(flag(flags, 'concurrency', String(cpuDefault))) || cpuDefault)
1686
+ const envConcurrency = Number.isInteger(envMax) && envMax > 0 ? envMax : null
1687
+ const maxConcurrent = envConcurrency ?? Math.max(1, Number(flag(flags, 'concurrency', '10')) || 10)
1675
1688
  const once = Boolean(flags.once)
1676
1689
  const handlerPath = flag(flags, 'handler')
1677
1690
 
@@ -1692,7 +1705,7 @@ export async function startRuntimeDaemon(flags = {}, deps = {}) {
1692
1705
  const retryState = createRetryState()
1693
1706
  const uninstallExitHandlers = installCurrentClaimExitHandlers(flags, resolvedDeps)
1694
1707
  try {
1695
- let registration = await runWithDaemonRetry('register runtime', () => registerRuntime(flags, resolvedDeps), resolvedDeps, retryState)
1708
+ let registration = await runWithDaemonRetry('register runtime', () => registerRuntime(flags, resolvedDeps, { maxConcurrent }), resolvedDeps, retryState)
1696
1709
  await runWithDaemonRetry('recover current claimed task', () => failAllPersistedClaims(
1697
1710
  flags,
1698
1711
  resolvedDeps,