@11agents/cli 0.1.18 → 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 +19 -7
- package/bin/11agents.js +3 -3
- package/package.json +1 -1
- package/src/commands/runtime.js +141 -136
package/README.md
CHANGED
|
@@ -125,17 +125,29 @@ export async function handleRuntimeTask(task) {
|
|
|
125
125
|
}
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
-
## MCP
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
```
|
|
133
|
-
|
|
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
|
-
|
|
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
|
|
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
package/src/commands/runtime.js
CHANGED
|
@@ -908,8 +908,8 @@ async function prepareRuntimeTask(task, flags, deps, config) {
|
|
|
908
908
|
const database = await syncDatabaseIfNeeded({ task, workdir, config, flags, deps })
|
|
909
909
|
const skills = await materializeSkillsIfChanged({ task, workdir, flags, deps })
|
|
910
910
|
|
|
911
|
-
// Resolve and inject the project token so MCP
|
|
912
|
-
//
|
|
911
|
+
// Resolve and inject the project token so hosted MCP calls spawned by the
|
|
912
|
+
// runtime agent can authenticate without needing credentials on disk.
|
|
913
913
|
const projectToken = await projectSyncToken(projectTokenCandidatesForTask(task, flags), flags, deps)
|
|
914
914
|
const env = {
|
|
915
915
|
...process.env,
|
|
@@ -1228,156 +1228,160 @@ function defaultTaskHandler(flags, deps) {
|
|
|
1228
1228
|
}
|
|
1229
1229
|
}
|
|
1230
1230
|
|
|
1231
|
-
async function
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
if (!runtime?.id) continue
|
|
1239
|
-
const claim = await runWithDaemonRetry('claim runtime task', () => (
|
|
1240
|
-
deps.requestJson('/api/runtime/tasks/claim', {
|
|
1241
|
-
method: 'POST',
|
|
1242
|
-
body: {
|
|
1243
|
-
runtime_id: runtime.id,
|
|
1244
|
-
machine_key: machineKey,
|
|
1245
|
-
},
|
|
1246
|
-
config,
|
|
1247
|
-
})
|
|
1248
|
-
), deps, retryState)
|
|
1249
|
-
const task = claim?.task
|
|
1250
|
-
if (!task) continue
|
|
1251
|
-
|
|
1252
|
-
const runtimeTask = {
|
|
1253
|
-
...task,
|
|
1254
|
-
runtime_id: task.runtime_id || runtime.id,
|
|
1255
|
-
runtime: {
|
|
1256
|
-
provider: runtime.provider,
|
|
1257
|
-
model: runtime.model || '',
|
|
1258
|
-
...(task.runtime || {}),
|
|
1259
|
-
id: task.runtime?.id || runtime.id,
|
|
1260
|
-
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,
|
|
1261
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 })
|
|
1262
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
|
+
}
|
|
1263
1319
|
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
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) {
|
|
1271
1335
|
try {
|
|
1272
|
-
await
|
|
1273
|
-
deps.syncKnowledge({
|
|
1274
|
-
project: runtimeTask.workspace.slug,
|
|
1275
|
-
mode: 'pull',
|
|
1276
|
-
server: flags.server,
|
|
1277
|
-
token,
|
|
1278
|
-
}, {
|
|
1279
|
-
requestJson: (apiPath, options = {}) => deps.requestJson(apiPath, { ...options, config: syncConfig }),
|
|
1280
|
-
log: () => {},
|
|
1281
|
-
})
|
|
1282
|
-
), deps)
|
|
1336
|
+
await pushKnowledge()
|
|
1283
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.`
|
|
1284
1339
|
completion = {
|
|
1285
|
-
|
|
1286
|
-
|
|
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'),
|
|
1287
1343
|
}
|
|
1288
1344
|
}
|
|
1289
|
-
}
|
|
1290
|
-
if (!completion) {
|
|
1291
|
-
executionContext = await prepareRuntimeTask(runtimeTask, flags, deps, config)
|
|
1292
|
-
runtimeTask.execution_context = executionContext
|
|
1293
|
-
await updateRunMeta(executionContext.run_dir, {
|
|
1294
|
-
task_id: String(runtimeTask.id || ''),
|
|
1295
|
-
runtime_id: String(runtimeTask.runtime_id || ''),
|
|
1296
|
-
provider: runtimeTask.runtime?.provider || runtime.provider || '',
|
|
1297
|
-
project_slug: executionContext.project_slug,
|
|
1298
|
-
agent: agentNameForTask(runtimeTask),
|
|
1299
|
-
issue_title: runtimeTask.issue?.title || '',
|
|
1300
|
-
started_at: new Date().toISOString(),
|
|
1301
|
-
})
|
|
1345
|
+
} else {
|
|
1302
1346
|
try {
|
|
1303
|
-
|
|
1304
|
-
() => handlerModule.handleRuntimeTask(runtimeTask),
|
|
1305
|
-
registration,
|
|
1306
|
-
flags,
|
|
1307
|
-
deps,
|
|
1308
|
-
heartbeatIntervalMs
|
|
1309
|
-
)
|
|
1347
|
+
await runWithTaskRetry('sync knowledge base back to cloud', pushKnowledge, deps)
|
|
1310
1348
|
} catch (error) {
|
|
1349
|
+
const message = `Knowledge sync push failed before task completion: ${errorMessage(error)}`
|
|
1311
1350
|
completion = {
|
|
1312
|
-
|
|
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'),
|
|
1313
1354
|
status: 'failed',
|
|
1314
1355
|
}
|
|
1315
|
-
} finally {
|
|
1316
|
-
await rm(executionContext.tmp_dir, { recursive: true, force: true })
|
|
1317
1356
|
}
|
|
1318
1357
|
}
|
|
1319
|
-
|
|
1320
|
-
await writeRunFile(executionContext.run_dir, 'completion.json', JSON.stringify(normalizeTaskCompletion(runtimeTask, completion), null, 2))
|
|
1321
|
-
await updateRunMeta(executionContext.run_dir, { ended_at: new Date().toISOString() })
|
|
1322
|
-
}
|
|
1323
|
-
if (executionContext) {
|
|
1324
|
-
await appendTaskMemoryDelta({ task: runtimeTask, completion, workdir: executionContext.workdir })
|
|
1325
|
-
}
|
|
1358
|
+
}
|
|
1326
1359
|
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
log: () => {},
|
|
1340
|
-
})
|
|
1341
|
-
if (isDeepOrganize) {
|
|
1342
|
-
try {
|
|
1343
|
-
await pushKnowledge()
|
|
1344
|
-
} catch (error) {
|
|
1345
|
-
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.`
|
|
1346
|
-
completion = {
|
|
1347
|
-
...(completion && typeof completion === 'object' ? completion : {}),
|
|
1348
|
-
comment: [String(completion?.comment || completion?.summary || '').trim(), message].filter(Boolean).join('\n\n'),
|
|
1349
|
-
memory_delta: [String(completion?.memory_delta || completion?.memoryDelta || '').trim(), message].filter(Boolean).join('\n'),
|
|
1350
|
-
}
|
|
1351
|
-
}
|
|
1352
|
-
} else {
|
|
1353
|
-
try {
|
|
1354
|
-
await runWithTaskRetry('sync knowledge base back to cloud', pushKnowledge, deps)
|
|
1355
|
-
} catch (error) {
|
|
1356
|
-
const message = `Knowledge sync push failed before task completion: ${errorMessage(error)}`
|
|
1357
|
-
completion = {
|
|
1358
|
-
...(completion && typeof completion === 'object' ? completion : {}),
|
|
1359
|
-
comment: [String(completion?.comment || completion?.summary || '').trim(), message].filter(Boolean).join('\n\n'),
|
|
1360
|
-
memory_delta: [String(completion?.memory_delta || completion?.memoryDelta || '').trim(), message].filter(Boolean).join('\n'),
|
|
1361
|
-
status: 'failed',
|
|
1362
|
-
}
|
|
1363
|
-
}
|
|
1364
|
-
}
|
|
1365
|
-
}
|
|
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
|
+
}
|
|
1366
1372
|
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
})
|
|
1374
|
-
), deps, retryState)
|
|
1375
|
-
await clearCurrentClaim(deps)
|
|
1376
|
-
deps.log(JSON.stringify(result, null, 2))
|
|
1377
|
-
handled += 1
|
|
1378
|
-
}
|
|
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) || ''
|
|
1379
1379
|
|
|
1380
|
-
|
|
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
|
|
1381
1385
|
}
|
|
1382
1386
|
|
|
1383
1387
|
export async function startRuntimeDaemon(flags = {}, deps = {}) {
|
|
@@ -1386,6 +1390,7 @@ export async function startRuntimeDaemon(flags = {}, deps = {}) {
|
|
|
1386
1390
|
const scanIntervalMs = Number(flag(flags, 'scan-interval', '60')) * 1000
|
|
1387
1391
|
const taskIntervalMs = Number(flag(flags, 'task-interval', flag(flags, 'heartbeat-interval', '15'))) * 1000
|
|
1388
1392
|
const projectRefreshIntervalMs = Number(flag(flags, 'project-refresh-interval', '1800')) * 1000
|
|
1393
|
+
const maxConcurrent = Math.max(1, Number(flag(flags, 'concurrency', '1')) || 1)
|
|
1389
1394
|
const once = Boolean(flags.once)
|
|
1390
1395
|
const handlerPath = flag(flags, 'handler')
|
|
1391
1396
|
|
|
@@ -1413,7 +1418,7 @@ export async function startRuntimeDaemon(flags = {}, deps = {}) {
|
|
|
1413
1418
|
'Runtime task failed locally: daemon restarted with a persisted claimed task that had not completed.'
|
|
1414
1419
|
), resolvedDeps, retryState)
|
|
1415
1420
|
await syncRuntimeProjectMetadataBestEffort(flags, resolvedDeps)
|
|
1416
|
-
await claimAndRunRuntimeTasks(registration, flags, resolvedDeps, handlerModule, retryState, heartbeatIntervalMs)
|
|
1421
|
+
await claimAndRunRuntimeTasks(registration, flags, resolvedDeps, handlerModule, retryState, heartbeatIntervalMs, maxConcurrent)
|
|
1417
1422
|
if (once) return
|
|
1418
1423
|
|
|
1419
1424
|
let lastScan = Date.now()
|
|
@@ -1432,7 +1437,7 @@ export async function startRuntimeDaemon(flags = {}, deps = {}) {
|
|
|
1432
1437
|
lastHeartbeat = now
|
|
1433
1438
|
}
|
|
1434
1439
|
if (now - lastTaskPoll >= taskIntervalMs) {
|
|
1435
|
-
await claimAndRunRuntimeTasks(registration, flags, resolvedDeps, handlerModule, retryState, heartbeatIntervalMs)
|
|
1440
|
+
await claimAndRunRuntimeTasks(registration, flags, resolvedDeps, handlerModule, retryState, heartbeatIntervalMs, maxConcurrent)
|
|
1436
1441
|
lastTaskPoll = now
|
|
1437
1442
|
}
|
|
1438
1443
|
if (now - lastProjectRefresh >= projectRefreshIntervalMs) {
|