@11agents/cli 0.1.17 → 0.1.19

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
@@ -125,17 +125,29 @@ export async function handleRuntimeTask(task) {
125
125
  }
126
126
  ```
127
127
 
128
- ## MCP Project Sync Server
129
-
130
- Run the local MCP server over stdio:
131
-
132
- ```bash
133
- 11agents mcp start
128
+ ## Hosted MCP
129
+
130
+ Runtime agents and MCP clients should use the hosted project MCP endpoint:
131
+
132
+ ```json
133
+ {
134
+ "mcpServers": {
135
+ "11agents-project-sync": {
136
+ "url": "https://app.11agents.ai/mcp",
137
+ "transport": "streamable-http",
138
+ "headers": {
139
+ "Authorization": "Bearer $PROJECT_SWARM_TOKEN"
140
+ }
141
+ }
142
+ }
143
+ }
134
144
  ```
135
145
 
136
- Configure your MCP client to run that command. The server automatically reads matching project tokens from `~/.11agents/credentials`; a tool-call token can still be passed explicitly when needed. The server exposes:
146
+ The hosted server exposes project-scoped tools such as:
137
147
 
138
148
  - `knowledge_sync` — pull/push the project knowledge base between cloud and `~/.11agents/<project>/knowledge_base/`.
149
+ - `database_sync` — pull/push the cloud project database snapshot.
150
+ - `agent_planning` — list, import, generate, and dispatch agent calendar work.
139
151
 
140
152
  ## Telemetry Compatibility
141
153
 
package/bin/11agents.js CHANGED
@@ -21,13 +21,12 @@ Usage:
21
21
  11agents -v | --version
22
22
  11agents runtime scan
23
23
  11agents runtime register [--server <url>] [--token <token>] [--machine <key>]
24
- 11agents daemon start [--server <url>] [--token <token>] [--machine <key>] [--task-interval <seconds>] [--project-refresh-interval <seconds>] [--background]
24
+ 11agents daemon start [--server <url>] [--token <token>] [--machine <key>] [--concurrency <n>] [--task-interval <seconds>] [--project-refresh-interval <seconds>] [--background]
25
25
  11agents daemon status
26
26
  11agents daemon stop
27
27
  11agents daemon start --handler ./worker.js # optional custom worker override
28
28
  11agents logs daemon [--tail 200]
29
29
  11agents logs task <task-id> [--project <slug>] [--tail 120]
30
- 11agents mcp start
31
30
  11agents validate <file>
32
31
  11agents push batch <file>
33
32
  11agents push artifact --workspace <slug> --agent <key> --platform x --type post --external-id <id>
@@ -42,7 +41,7 @@ Environment:
42
41
  GTM_WRITES_TOKEN control-plane token for runtime registration
43
42
  ELEVENAGENTS_MACHINE stable machine key, defaults to hostname
44
43
  GTM_SWARM_TOKEN project swarm token for push/node commands
45
- ~/.11agents/credentials project token map for MCP knowledge sync
44
+ ~/.11agents/credentials project token map for hosted MCP and sync commands
46
45
 
47
46
  Runtime task workspace:
48
47
  Daemon project headquarters live under ~/.11agents/<project>/.
@@ -99,6 +98,7 @@ async function main() {
99
98
  console.log(`log: ${result.logPath}`)
100
99
  return
101
100
  }
101
+ if (flags.concurrency === undefined) flags.concurrency = '3'
102
102
  await startRuntimeDaemon(flags)
103
103
  return
104
104
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@11agents/cli",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
4
4
  "description": "11agents local runtime and telemetry CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -772,7 +772,15 @@ async function materializeSkillsIfChanged({ task, workdir, flags, deps }) {
772
772
  const statePath = path.join(skillsDir, 'skills-state.json')
773
773
  const nextHash = stableHash(skills)
774
774
  const current = await readJsonFile(statePath, {})
775
- if (current.hash === nextHash) return { changed: false, count: skills.length }
775
+ if (current.hash === nextHash) {
776
+ const allExist = (await Promise.all(
777
+ skills.map(skill =>
778
+ readFile(path.join(skillsDir, slugify(skill.name, 'skill'), 'SKILL.md'), 'utf8')
779
+ .then(() => true).catch(() => false)
780
+ )
781
+ )).every(Boolean)
782
+ if (allExist) return { changed: false, count: skills.length }
783
+ }
776
784
 
777
785
  await mkdir(skillsDir, { recursive: true })
778
786
  for (const skill of skills) {
@@ -886,21 +894,31 @@ function agentEnvironment(task) {
886
894
 
887
895
  async function prepareRuntimeTask(task, flags, deps, config) {
888
896
  const workdir = flag(flags, 'codex-workdir') || projectDirForTask(task, flags, deps)
889
- const tmpDir = path.join(workdir, 'tmp', sanitizeTaskId(task.id))
897
+ const agentDir = path.join(workdir, 'agents', slugify(agentNameForTask(task), 'agent'))
898
+ const agentSkillsDir = path.join(agentDir, 'skills')
899
+ const agentMemoryDir = path.join(agentDir, 'memory')
900
+ const agentResultsDir = path.join(agentDir, 'results')
901
+ const tmpDir = path.join(agentDir, 'tmp', sanitizeTaskId(task.id))
890
902
  const runDir = path.join(workdir, 'runs', sanitizeTaskId(task.id))
891
903
  await mkdir(tmpDir, { recursive: true })
892
904
  await mkdir(runDir, { recursive: true })
905
+ await mkdir(agentResultsDir, { recursive: true })
906
+ await mkdir(agentMemoryDir, { recursive: true })
893
907
 
894
908
  const database = await syncDatabaseIfNeeded({ task, workdir, config, flags, deps })
895
909
  const skills = await materializeSkillsIfChanged({ task, workdir, flags, deps })
896
910
 
897
- // Resolve and inject the project token so MCP subprocesses (e.g. `11agents mcp start`)
898
- // spawned by the runtime agent can authenticate without needing credentials on disk.
911
+ // Resolve and inject the project token so hosted MCP calls spawned by the
912
+ // runtime agent can authenticate without needing credentials on disk.
899
913
  const projectToken = await projectSyncToken(projectTokenCandidatesForTask(task, flags), flags, deps)
900
914
  const env = {
901
915
  ...process.env,
902
916
  ...agentEnvironment(task),
903
917
  ELEVENAGENTS_PROJECT_DIR: workdir,
918
+ ELEVENAGENTS_AGENT_DIR: agentDir,
919
+ ELEVENAGENTS_AGENT_SKILLS_DIR: agentSkillsDir,
920
+ ELEVENAGENTS_AGENT_MEMORY_DIR: agentMemoryDir,
921
+ ELEVENAGENTS_AGENT_RESULTS_DIR: agentResultsDir,
904
922
  ELEVENAGENTS_TASK_TMP: tmpDir,
905
923
  ELEVENAGENTS_TASK_ID: String(task.id || ''),
906
924
  ...(projectToken ? { GTM_SWARM_TOKEN: projectToken } : {}),
@@ -908,6 +926,10 @@ async function prepareRuntimeTask(task, flags, deps, config) {
908
926
 
909
927
  return {
910
928
  workdir,
929
+ agent_dir: agentDir,
930
+ agent_skills_dir: agentSkillsDir,
931
+ agent_memory_dir: agentMemoryDir,
932
+ agent_results_dir: agentResultsDir,
911
933
  tmp_dir: tmpDir,
912
934
  run_dir: runDir,
913
935
  project_slug: projectSlugForTask(task, flags),
@@ -926,13 +948,23 @@ function buildCodexPrompt(task) {
926
948
  'Execution workspace:',
927
949
  compactJson({
928
950
  workdir: task.execution_context?.workdir,
951
+ agent_skills_dir: task.execution_context?.agent_skills_dir,
952
+ agent_memory_dir: task.execution_context?.agent_memory_dir,
953
+ agent_results_dir: task.execution_context?.agent_results_dir,
929
954
  tmp_dir: task.execution_context?.tmp_dir,
930
955
  project_slug: task.execution_context?.project_slug,
931
- knowledge_base: './knowledge_base/',
932
- rule: 'Treat the project directory as read-only project context except ./knowledge_base/ for durable project knowledge updates and ./tmp/<taskId>/ for temporary scratch files.',
933
- cleanup: 'Temporary files under ./tmp/<taskId>/ are removed by the CLI after the task finishes.',
956
+ knowledge_base: task.execution_context?.workdir ? path.join(task.execution_context.workdir, 'knowledge_base') : './knowledge_base',
934
957
  }),
935
958
  '',
959
+ 'Directory rules — follow strictly:',
960
+ '1. agent_skills_dir: BEFORE starting work, list files here to see which skills are installed.',
961
+ ' Each skill is a subdirectory with a SKILL.md. If a skill you need is present, read its SKILL.md and follow it.',
962
+ '2. agent_results_dir: Write all final deliverables and task outputs here (generated content, reports, files).',
963
+ '3. agent_memory_dir: After completing work, record key decisions, facts, and learned context here.',
964
+ ' Append to index.qmd or create new .qmd files. This memory persists across future task runs.',
965
+ '4. tmp_dir: Scratch/working files only. This directory is deleted by the CLI after the task finishes — do NOT put deliverables here.',
966
+ '5. workdir: Treat as read-only project context except for the four agent directories and knowledge_base above.',
967
+ '',
936
968
  'Task context:',
937
969
  compactJson({
938
970
  queue_event: task.queue_event,
@@ -1196,156 +1228,160 @@ function defaultTaskHandler(flags, deps) {
1196
1228
  }
1197
1229
  }
1198
1230
 
1199
- async function claimAndRunRuntimeTasks(registration, flags, deps, handlerModule, retryState = createRetryState(), heartbeatIntervalMs = 15000) {
1200
- if (!handlerModule) return 0
1201
- const config = configFromFlags(flags)
1202
- const machineKey = registration?.machine?.machine_key || machineOverride(flags) || ''
1203
- let handled = 0
1204
-
1205
- for (const runtime of registration?.runtimes || []) {
1206
- if (!runtime?.id) continue
1207
- const claim = await runWithDaemonRetry('claim runtime task', () => (
1208
- deps.requestJson('/api/runtime/tasks/claim', {
1209
- method: 'POST',
1210
- body: {
1211
- runtime_id: runtime.id,
1212
- machine_key: machineKey,
1213
- },
1214
- config,
1215
- })
1216
- ), deps, retryState)
1217
- const task = claim?.task
1218
- if (!task) continue
1219
-
1220
- const runtimeTask = {
1221
- ...task,
1222
- runtime_id: task.runtime_id || runtime.id,
1223
- runtime: {
1224
- provider: runtime.provider,
1225
- model: runtime.model || '',
1226
- ...(task.runtime || {}),
1227
- id: task.runtime?.id || runtime.id,
1228
- machine_key: task.runtime?.machine_key || machineKey,
1231
+ async function runOneRuntimeTaskSlot(runtime, config, machineKey, registration, flags, deps, handlerModule, retryState, heartbeatIntervalMs) {
1232
+ const claim = await runWithDaemonRetry('claim runtime task', () => (
1233
+ deps.requestJson('/api/runtime/tasks/claim', {
1234
+ method: 'POST',
1235
+ body: {
1236
+ runtime_id: runtime.id,
1237
+ machine_key: machineKey,
1229
1238
  },
1239
+ config,
1240
+ })
1241
+ ), deps, retryState)
1242
+ const task = claim?.task
1243
+ if (!task) return false
1244
+
1245
+ const runtimeTask = {
1246
+ ...task,
1247
+ runtime_id: task.runtime_id || runtime.id,
1248
+ runtime: {
1249
+ provider: runtime.provider,
1250
+ model: runtime.model || '',
1251
+ ...(task.runtime || {}),
1252
+ id: task.runtime?.id || runtime.id,
1253
+ machine_key: task.runtime?.machine_key || machineKey,
1254
+ },
1255
+ }
1256
+
1257
+ deps.log(JSON.stringify({ claimed: runtimeTask.id, runtime_id: runtime.id }, null, 2))
1258
+ await writeCurrentClaim(deps, runtimeTask, machineKey)
1259
+ let completion = null
1260
+ let executionContext = null
1261
+ if (runtimeTask.workspace?.slug) {
1262
+ const token = await projectSyncToken(projectTokenCandidatesForTask(runtimeTask, flags), flags, deps)
1263
+ const syncConfig = { ...config, token }
1264
+ try {
1265
+ await runWithTaskRetry('sync knowledge base', () => (
1266
+ deps.syncKnowledge({
1267
+ project: runtimeTask.workspace.slug,
1268
+ mode: 'pull',
1269
+ server: flags.server,
1270
+ token,
1271
+ }, {
1272
+ requestJson: (apiPath, options = {}) => deps.requestJson(apiPath, { ...options, config: syncConfig }),
1273
+ log: () => {},
1274
+ })
1275
+ ), deps)
1276
+ } catch (error) {
1277
+ completion = {
1278
+ comment: `Knowledge sync pull failed before task execution: ${errorMessage(error)}`,
1279
+ status: 'failed',
1280
+ }
1281
+ }
1282
+ }
1283
+ if (!completion) {
1284
+ executionContext = await prepareRuntimeTask(runtimeTask, flags, deps, config)
1285
+ runtimeTask.execution_context = executionContext
1286
+ await updateRunMeta(executionContext.run_dir, {
1287
+ task_id: String(runtimeTask.id || ''),
1288
+ runtime_id: String(runtimeTask.runtime_id || ''),
1289
+ provider: runtimeTask.runtime?.provider || runtime.provider || '',
1290
+ project_slug: executionContext.project_slug,
1291
+ agent: agentNameForTask(runtimeTask),
1292
+ issue_title: runtimeTask.issue?.title || '',
1293
+ started_at: new Date().toISOString(),
1294
+ })
1295
+ try {
1296
+ completion = await runWithRuntimeHeartbeat(
1297
+ () => handlerModule.handleRuntimeTask(runtimeTask),
1298
+ registration,
1299
+ flags,
1300
+ deps,
1301
+ heartbeatIntervalMs
1302
+ )
1303
+ } catch (error) {
1304
+ completion = {
1305
+ comment: error instanceof Error ? error.message : String(error),
1306
+ status: 'failed',
1307
+ }
1308
+ } finally {
1309
+ await rm(executionContext.tmp_dir, { recursive: true, force: true })
1230
1310
  }
1311
+ }
1312
+ if (executionContext) {
1313
+ await writeRunFile(executionContext.run_dir, 'completion.json', JSON.stringify(normalizeTaskCompletion(runtimeTask, completion), null, 2))
1314
+ await updateRunMeta(executionContext.run_dir, { ended_at: new Date().toISOString() })
1315
+ }
1316
+ if (executionContext) {
1317
+ await appendTaskMemoryDelta({ task: runtimeTask, completion, workdir: executionContext.workdir })
1318
+ }
1231
1319
 
1232
- deps.log(JSON.stringify({ claimed: runtimeTask.id, runtime_id: runtime.id }, null, 2))
1233
- await writeCurrentClaim(deps, runtimeTask, machineKey)
1234
- let completion = null
1235
- let executionContext = null
1236
- if (runtimeTask.workspace?.slug) {
1237
- const token = await projectSyncToken(projectTokenCandidatesForTask(runtimeTask, flags), flags, deps)
1238
- const syncConfig = { ...config, token }
1320
+ if (executionContext && runtimeTask.workspace?.slug) {
1321
+ const isDeepOrganize = Boolean(knowledgeDeepOrganizeSpec(runtimeTask))
1322
+ const syncBack = isDeepOrganize ? deps.mcpKnowledgeSync : deps.syncKnowledge
1323
+ const token = await projectSyncToken(projectTokenCandidatesForTask(runtimeTask, flags), flags, deps)
1324
+ const syncConfig = { ...config, token }
1325
+ const pushKnowledge = () => syncBack({
1326
+ project: runtimeTask.workspace.slug,
1327
+ mode: 'push',
1328
+ server: flags.server,
1329
+ token,
1330
+ }, {
1331
+ requestJson: (apiPath, options = {}) => deps.requestJson(apiPath, { ...options, config: syncConfig }),
1332
+ log: () => {},
1333
+ })
1334
+ if (isDeepOrganize) {
1239
1335
  try {
1240
- await runWithTaskRetry('sync knowledge base', () => (
1241
- deps.syncKnowledge({
1242
- project: runtimeTask.workspace.slug,
1243
- mode: 'pull',
1244
- server: flags.server,
1245
- token,
1246
- }, {
1247
- requestJson: (apiPath, options = {}) => deps.requestJson(apiPath, { ...options, config: syncConfig }),
1248
- log: () => {},
1249
- })
1250
- ), deps)
1336
+ await pushKnowledge()
1251
1337
  } catch (error) {
1338
+ const message = `Knowledge sync push failed before task completion: ${errorMessage(error)}. If a knowledge_snapshot is included in completion, the platform will write it directly.`
1252
1339
  completion = {
1253
- comment: `Knowledge sync pull failed before task execution: ${errorMessage(error)}`,
1254
- status: 'failed',
1340
+ ...(completion && typeof completion === 'object' ? completion : {}),
1341
+ comment: [String(completion?.comment || completion?.summary || '').trim(), message].filter(Boolean).join('\n\n'),
1342
+ memory_delta: [String(completion?.memory_delta || completion?.memoryDelta || '').trim(), message].filter(Boolean).join('\n'),
1255
1343
  }
1256
1344
  }
1257
- }
1258
- if (!completion) {
1259
- executionContext = await prepareRuntimeTask(runtimeTask, flags, deps, config)
1260
- runtimeTask.execution_context = executionContext
1261
- await updateRunMeta(executionContext.run_dir, {
1262
- task_id: String(runtimeTask.id || ''),
1263
- runtime_id: String(runtimeTask.runtime_id || ''),
1264
- provider: runtimeTask.runtime?.provider || runtime.provider || '',
1265
- project_slug: executionContext.project_slug,
1266
- agent: agentNameForTask(runtimeTask),
1267
- issue_title: runtimeTask.issue?.title || '',
1268
- started_at: new Date().toISOString(),
1269
- })
1345
+ } else {
1270
1346
  try {
1271
- completion = await runWithRuntimeHeartbeat(
1272
- () => handlerModule.handleRuntimeTask(runtimeTask),
1273
- registration,
1274
- flags,
1275
- deps,
1276
- heartbeatIntervalMs
1277
- )
1347
+ await runWithTaskRetry('sync knowledge base back to cloud', pushKnowledge, deps)
1278
1348
  } catch (error) {
1349
+ const message = `Knowledge sync push failed before task completion: ${errorMessage(error)}`
1279
1350
  completion = {
1280
- comment: error instanceof Error ? error.message : String(error),
1351
+ ...(completion && typeof completion === 'object' ? completion : {}),
1352
+ comment: [String(completion?.comment || completion?.summary || '').trim(), message].filter(Boolean).join('\n\n'),
1353
+ memory_delta: [String(completion?.memory_delta || completion?.memoryDelta || '').trim(), message].filter(Boolean).join('\n'),
1281
1354
  status: 'failed',
1282
1355
  }
1283
- } finally {
1284
- await rm(executionContext.tmp_dir, { recursive: true, force: true })
1285
1356
  }
1286
1357
  }
1287
- if (executionContext) {
1288
- await writeRunFile(executionContext.run_dir, 'completion.json', JSON.stringify(normalizeTaskCompletion(runtimeTask, completion), null, 2))
1289
- await updateRunMeta(executionContext.run_dir, { ended_at: new Date().toISOString() })
1290
- }
1291
- if (executionContext) {
1292
- await appendTaskMemoryDelta({ task: runtimeTask, completion, workdir: executionContext.workdir })
1293
- }
1358
+ }
1294
1359
 
1295
- if (executionContext && runtimeTask.workspace?.slug) {
1296
- const isDeepOrganize = Boolean(knowledgeDeepOrganizeSpec(runtimeTask))
1297
- const syncBack = isDeepOrganize ? deps.mcpKnowledgeSync : deps.syncKnowledge
1298
- const token = await projectSyncToken(projectTokenCandidatesForTask(runtimeTask, flags), flags, deps)
1299
- const syncConfig = { ...config, token }
1300
- const pushKnowledge = () => syncBack({
1301
- project: runtimeTask.workspace.slug,
1302
- mode: 'push',
1303
- server: flags.server,
1304
- token,
1305
- }, {
1306
- requestJson: (apiPath, options = {}) => deps.requestJson(apiPath, { ...options, config: syncConfig }),
1307
- log: () => {},
1308
- })
1309
- if (isDeepOrganize) {
1310
- try {
1311
- await pushKnowledge()
1312
- } catch (error) {
1313
- const message = `Knowledge sync push failed before task completion: ${errorMessage(error)}. If a knowledge_snapshot is included in completion, the platform will write it directly.`
1314
- completion = {
1315
- ...(completion && typeof completion === 'object' ? completion : {}),
1316
- comment: [String(completion?.comment || completion?.summary || '').trim(), message].filter(Boolean).join('\n\n'),
1317
- memory_delta: [String(completion?.memory_delta || completion?.memoryDelta || '').trim(), message].filter(Boolean).join('\n'),
1318
- }
1319
- }
1320
- } else {
1321
- try {
1322
- await runWithTaskRetry('sync knowledge base back to cloud', pushKnowledge, deps)
1323
- } catch (error) {
1324
- const message = `Knowledge sync push failed before task completion: ${errorMessage(error)}`
1325
- completion = {
1326
- ...(completion && typeof completion === 'object' ? completion : {}),
1327
- comment: [String(completion?.comment || completion?.summary || '').trim(), message].filter(Boolean).join('\n\n'),
1328
- memory_delta: [String(completion?.memory_delta || completion?.memoryDelta || '').trim(), message].filter(Boolean).join('\n'),
1329
- status: 'failed',
1330
- }
1331
- }
1332
- }
1333
- }
1360
+ const body = normalizeTaskCompletion(runtimeTask, completion)
1361
+ const result = await runWithDaemonRetry('complete runtime task', () => (
1362
+ deps.requestJson('/api/runtime/tasks/complete', {
1363
+ method: 'POST',
1364
+ body,
1365
+ config,
1366
+ })
1367
+ ), deps, retryState)
1368
+ await clearCurrentClaim(deps)
1369
+ deps.log(JSON.stringify(result, null, 2))
1370
+ return true
1371
+ }
1334
1372
 
1335
- const body = normalizeTaskCompletion(runtimeTask, completion)
1336
- const result = await runWithDaemonRetry('complete runtime task', () => (
1337
- deps.requestJson('/api/runtime/tasks/complete', {
1338
- method: 'POST',
1339
- body,
1340
- config,
1341
- })
1342
- ), deps, retryState)
1343
- await clearCurrentClaim(deps)
1344
- deps.log(JSON.stringify(result, null, 2))
1345
- handled += 1
1346
- }
1373
+ async function claimAndRunRuntimeTasks(registration, flags, deps, handlerModule, retryState = createRetryState(), heartbeatIntervalMs = 15000, maxConcurrent = 1) {
1374
+ if (!handlerModule) return 0
1375
+ const runtimes = (registration?.runtimes || []).filter(r => r?.id)
1376
+ if (!runtimes.length) return 0
1377
+ const config = configFromFlags(flags)
1378
+ const machineKey = registration?.machine?.machine_key || machineOverride(flags) || ''
1347
1379
 
1348
- return handled
1380
+ const slots = Array.from({ length: maxConcurrent }, (_, i) => runtimes[i % runtimes.length])
1381
+ const results = await Promise.allSettled(
1382
+ slots.map(runtime => runOneRuntimeTaskSlot(runtime, config, machineKey, registration, flags, deps, handlerModule, retryState, heartbeatIntervalMs))
1383
+ )
1384
+ return results.filter(r => r.status === 'fulfilled' && r.value === true).length
1349
1385
  }
1350
1386
 
1351
1387
  export async function startRuntimeDaemon(flags = {}, deps = {}) {
@@ -1354,6 +1390,7 @@ export async function startRuntimeDaemon(flags = {}, deps = {}) {
1354
1390
  const scanIntervalMs = Number(flag(flags, 'scan-interval', '60')) * 1000
1355
1391
  const taskIntervalMs = Number(flag(flags, 'task-interval', flag(flags, 'heartbeat-interval', '15'))) * 1000
1356
1392
  const projectRefreshIntervalMs = Number(flag(flags, 'project-refresh-interval', '1800')) * 1000
1393
+ const maxConcurrent = Math.max(1, Number(flag(flags, 'concurrency', '1')) || 1)
1357
1394
  const once = Boolean(flags.once)
1358
1395
  const handlerPath = flag(flags, 'handler')
1359
1396
 
@@ -1381,7 +1418,7 @@ export async function startRuntimeDaemon(flags = {}, deps = {}) {
1381
1418
  'Runtime task failed locally: daemon restarted with a persisted claimed task that had not completed.'
1382
1419
  ), resolvedDeps, retryState)
1383
1420
  await syncRuntimeProjectMetadataBestEffort(flags, resolvedDeps)
1384
- await claimAndRunRuntimeTasks(registration, flags, resolvedDeps, handlerModule, retryState, heartbeatIntervalMs)
1421
+ await claimAndRunRuntimeTasks(registration, flags, resolvedDeps, handlerModule, retryState, heartbeatIntervalMs, maxConcurrent)
1385
1422
  if (once) return
1386
1423
 
1387
1424
  let lastScan = Date.now()
@@ -1400,7 +1437,7 @@ export async function startRuntimeDaemon(flags = {}, deps = {}) {
1400
1437
  lastHeartbeat = now
1401
1438
  }
1402
1439
  if (now - lastTaskPoll >= taskIntervalMs) {
1403
- await claimAndRunRuntimeTasks(registration, flags, resolvedDeps, handlerModule, retryState, heartbeatIntervalMs)
1440
+ await claimAndRunRuntimeTasks(registration, flags, resolvedDeps, handlerModule, retryState, heartbeatIntervalMs, maxConcurrent)
1404
1441
  lastTaskPoll = now
1405
1442
  }
1406
1443
  if (now - lastProjectRefresh >= projectRefreshIntervalMs) {