@asm-agent/coding-agent 0.8.7 → 0.9.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/CHANGELOG.md +19 -0
- package/README.md +2 -7
- package/dist/asm-agent-runtime/src/__pycache__/asm_cm_driver.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/src/__pycache__/phase76_address_head.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__init__.py +1 -1
- package/dist/asm-agent-runtime/src/rlm/__pycache__/__init__.cpython-312.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/_winjob.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/bash.cpython-312.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/bash.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/harness.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/mcp.cpython-312.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/mcp.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/mcp_base.cpython-312.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/mcp_base.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/repl.cpython-312.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/repl.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/skill.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/bash.py +94 -31
- package/dist/asm-agent-runtime/src/rlm/repl.md +3 -3
- package/dist/asm-agent-runtime/src/rlm/repl.py +46 -45
- package/dist/asm-agent-runtime/test/__pycache__/test_agent_message_skill.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/test/__pycache__/test_bash.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/test/__pycache__/test_harness.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/test/__pycache__/test_mcp.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/test/__pycache__/test_mcp_base.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/test/__pycache__/test_repl.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/test/__pycache__/test_subagent_registry.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/test/__pycache__/test_winjob.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/test/test_bash.py +74 -19
- package/dist/asm-agent-runtime/test/test_repl.py +67 -3
- package/dist/asm-agent-runtime/uv.lock +446 -155
- package/dist/bundle/{anthropic-XSMQHGYB.js → anthropic-ZOZNPFXS.js} +2 -2
- package/dist/bundle/{azure-openai-responses-XLQAIKKH.js → azure-openai-responses-TDHCU647.js} +2 -2
- package/dist/bundle/{bundled-modules-5OCN73BM.js → bundled-modules-Q2YODC4B.js} +3 -3
- package/dist/bundle/{chunk-IAQLPSMN.js → chunk-AMKLNEAK.js} +47 -47
- package/dist/bundle/{chunk-2LPSALBF.js → chunk-FPY7FFJS.js} +978 -1821
- package/dist/bundle/{chunk-E3YE2Q7A.js → chunk-G6SC4YYW.js} +4973 -1926
- package/dist/bundle/{chunk-YPNK4MRU.js → chunk-QLHAP3FT.js} +1 -1
- package/dist/bundle/{cli-main-QYX5R3LF.js → cli-main-277AG2BR.js} +3 -3
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/{google-ZXJEPWJA.js → google-Q3AJWUOY.js} +1 -1
- package/dist/bundle/{google-vertex-WAF3RIJ6.js → google-vertex-2CSNOUBS.js} +1 -1
- package/dist/bundle/{main-EOUAQCJH.js → main-TNXWJXIU.js} +3 -3
- package/dist/bundle/{mistral-GDZXSXRS.js → mistral-XRYJGLLG.js} +1 -1
- package/dist/bundle/{openai-codex-responses-7XMPW4LG.js → openai-codex-responses-C6BRO2BN.js} +2 -2
- package/dist/bundle/{openai-completions-LNSVGDMF.js → openai-completions-DNXCK2JW.js} +4 -4
- package/dist/bundle/{openai-responses-MFZOBMIT.js → openai-responses-BEMWVIXE.js} +2 -2
- package/dist/config.d.ts +0 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -3
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-config.d.ts +1 -2
- package/dist/core/agent-session-config.d.ts.map +1 -1
- package/dist/core/agent-session-config.js +0 -3
- package/dist/core/agent-session-config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +0 -8
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +0 -2
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +0 -22
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +8 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +100 -22
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/kernel/bootstrap.d.ts.map +1 -1
- package/dist/core/kernel/bootstrap.js +1 -1
- package/dist/core/kernel/bootstrap.js.map +1 -1
- package/dist/core/kernel/repl-manager.d.ts +32 -8
- package/dist/core/kernel/repl-manager.d.ts.map +1 -1
- package/dist/core/kernel/repl-manager.js +401 -102
- package/dist/core/kernel/repl-manager.js.map +1 -1
- package/dist/core/kernel/shared.d.ts +11 -7
- package/dist/core/kernel/shared.d.ts.map +1 -1
- package/dist/core/kernel/shared.js +2 -5
- package/dist/core/kernel/shared.js.map +1 -1
- package/dist/core/mcp/mcp-manager.d.ts +4 -2
- package/dist/core/mcp/mcp-manager.d.ts.map +1 -1
- package/dist/core/mcp/mcp-manager.js +9 -7
- package/dist/core/mcp/mcp-manager.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +1 -1
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/ollama-models.d.ts +3 -1
- package/dist/core/ollama-models.d.ts.map +1 -1
- package/dist/core/ollama-models.js +31 -10
- package/dist/core/ollama-models.js.map +1 -1
- package/dist/core/prime-inference-auth.d.ts +0 -9
- package/dist/core/prime-inference-auth.d.ts.map +1 -1
- package/dist/core/prime-inference-auth.js +0 -50
- package/dist/core/prime-inference-auth.js.map +1 -1
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +0 -1
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/core/session-manager.d.ts +0 -4
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +0 -22
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +4 -16
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +13 -43
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +0 -5
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tools/acp-mcp.d.ts +6 -0
- package/dist/core/tools/acp-mcp.d.ts.map +1 -0
- package/dist/core/tools/acp-mcp.js +86 -0
- package/dist/core/tools/acp-mcp.js.map +1 -0
- package/dist/core/tools/index.d.ts +1 -0
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +1 -0
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ipython.d.ts.map +1 -1
- package/dist/core/tools/ipython.js +9 -4
- package/dist/core/tools/ipython.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +2 -11
- package/dist/main.js.map +1 -1
- package/dist/modes/acp/acp-mode.d.ts.map +1 -1
- package/dist/modes/acp/acp-mode.js +1 -1
- package/dist/modes/acp/acp-mode.js.map +1 -1
- package/dist/modes/agent-connection/daemon-agent-connection.d.ts +0 -2
- package/dist/modes/agent-connection/daemon-agent-connection.d.ts.map +1 -1
- package/dist/modes/agent-connection/daemon-agent-connection.js +0 -2
- package/dist/modes/agent-connection/daemon-agent-connection.js.map +1 -1
- package/dist/modes/agents-view/agents-view-mode.d.ts.map +1 -1
- package/dist/modes/agents-view/agents-view-mode.js +0 -19
- package/dist/modes/agents-view/agents-view-mode.js.map +1 -1
- package/dist/modes/daemon/daemon-mode.d.ts +1 -10
- package/dist/modes/daemon/daemon-mode.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-mode.js +134 -274
- package/dist/modes/daemon/daemon-mode.js.map +1 -1
- package/dist/modes/daemon/daemon-protocol.d.ts +11 -5
- package/dist/modes/daemon/daemon-protocol.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-protocol.js +6 -8
- package/dist/modes/daemon/daemon-protocol.js.map +1 -1
- package/dist/modes/daemon/daemon-supervisor.d.ts +0 -3
- package/dist/modes/daemon/daemon-supervisor.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-supervisor.js +18 -52
- package/dist/modes/daemon/daemon-supervisor.js.map +1 -1
- package/dist/modes/daemon/daemon-worker-protocol.d.ts +1 -6
- package/dist/modes/daemon/daemon-worker-protocol.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-worker-protocol.js +0 -2
- package/dist/modes/daemon/daemon-worker-protocol.js.map +1 -1
- package/dist/modes/interactive/auth-flows.d.ts +0 -2
- package/dist/modes/interactive/auth-flows.d.ts.map +1 -1
- package/dist/modes/interactive/auth-flows.js +1 -101
- package/dist/modes/interactive/auth-flows.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +6 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +13 -3
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +2 -2
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/mermaid.d.ts +12 -0
- package/dist/modes/interactive/components/mermaid.d.ts.map +1 -0
- package/dist/modes/interactive/components/mermaid.js +63 -0
- package/dist/modes/interactive/components/mermaid.js.map +1 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +10 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/feature-hints.d.ts.map +1 -1
- package/dist/modes/interactive/feature-hints.js +0 -4
- package/dist/modes/interactive/feature-hints.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -7
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +23 -279
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +1 -1
- package/dist/utils/version-check.js.map +1 -1
- package/docs/settings.md +1 -31
- package/docs/usage.md +1 -4
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +6 -5
- package/dist/core/agent-traces.d.ts +0 -130
- package/dist/core/agent-traces.d.ts.map +0 -1
- package/dist/core/agent-traces.js +0 -746
- package/dist/core/agent-traces.js.map +0 -1
- package/dist/core/telemetry.d.ts +0 -92
- package/dist/core/telemetry.d.ts.map +0 -1
- package/dist/core/telemetry.js +0 -633
- package/dist/core/telemetry.js.map +0 -1
|
@@ -14,7 +14,7 @@ import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
|
14
14
|
import { getLogger } from "@asm-agent/ai";
|
|
15
15
|
import { createCliSubprocessEnv, createCliSubprocessLaunchSpec } from "../../cli/subprocess-launch.js";
|
|
16
16
|
import { appendRotatingLog, getCronJobsPath, getDaemonLogPath, getDaemonUpdateRestartManifestPath, getSessionsDir, VERSION, } from "../../config.js";
|
|
17
|
-
import { AGENT_FAMILY_REACH_ERROR, AGENT_MESSAGE_SOURCE, AgentSessionMessageRateLimiter, agentFamilyRelationship, assertAgentFamilyReach,
|
|
17
|
+
import { AGENT_FAMILY_REACH_ERROR, AGENT_MESSAGE_SOURCE, AgentSessionMessageRateLimiter, agentFamilyRelationship, assertAgentFamilyReach, assertAgentSessionNameAvailable, assertDirectAgentMessageTarget, buildAgentFamilyRoster, createAgentSessionMessage, createAgentSessionMessageId, createAgentSessionMessageReceipt, DEFAULT_AGENT_MESSAGE_MAX_CHARS, DEFAULT_AGENT_MESSAGE_MAX_PENDING_PER_SESSION, DEFAULT_AGENT_MESSAGE_RATE_LIMIT_CAPACITY, DEFAULT_AGENT_MESSAGE_RATE_LIMIT_REFILL_MS, formatAgentSessionNameUnavailable, normalizeAgentSessionMessage, sessionNameReservationKey, } from "../../core/agent-messages.js";
|
|
18
18
|
import { createAgentObserveMessagePreview, normalizeObserveLimit, normalizeObserveMaxChars, } from "../../core/agent-observe.js";
|
|
19
19
|
import { rlmChildLabel } from "../../core/agent-session.js";
|
|
20
20
|
import { mergeAgentSessionRuntimeConfig } from "../../core/agent-session-config.js";
|
|
@@ -245,13 +245,6 @@ export class AgentDaemon {
|
|
|
245
245
|
agentDir;
|
|
246
246
|
cronScheduler;
|
|
247
247
|
agentMessageRateLimiter = new AgentSessionMessageRateLimiter();
|
|
248
|
-
remoteAgentPeers = new Map();
|
|
249
|
-
agentMessagePendingReservations = new Map();
|
|
250
|
-
agentMessageTargetLocks = new Map();
|
|
251
|
-
agentMessageAcceptingTargets = new Set();
|
|
252
|
-
// Refcount of prompts in preflight (accepted but not yet streaming); >0 makes
|
|
253
|
-
// concurrent agent messages queue instead of racing agent.prompt.
|
|
254
|
-
agentMessagePreparingTargets = new Map();
|
|
255
248
|
asmCmDriver = new AsmCmDriver();
|
|
256
249
|
phase76AddressHead = new Phase76AddressHeadDriver();
|
|
257
250
|
asmRuntimePersistence = new AsmRuntimePersistence();
|
|
@@ -1368,16 +1361,10 @@ export class AgentDaemon {
|
|
|
1368
1361
|
return "skipped";
|
|
1369
1362
|
}
|
|
1370
1363
|
const session = state.runtime.session;
|
|
1371
|
-
const isAgentMessagePromptInProgress = this.agentMessageAcceptingTargets.has(state.activeSessionId) ||
|
|
1372
|
-
this.agentMessagePreparingTargets.has(state.activeSessionId);
|
|
1373
|
-
if (isHeartbeatCronJob(runnableJob) && isAgentMessagePromptInProgress) {
|
|
1374
|
-
return "skipped";
|
|
1375
|
-
}
|
|
1376
1364
|
if (shouldDeferHeartbeatCronJob(runnableJob, session)) {
|
|
1377
1365
|
return "skipped";
|
|
1378
1366
|
}
|
|
1379
|
-
const shouldQueueCronPrompt =
|
|
1380
|
-
session.isStreaming ||
|
|
1367
|
+
const shouldQueueCronPrompt = session.isStreaming ||
|
|
1381
1368
|
session.isCompacting ||
|
|
1382
1369
|
session.isRetrying ||
|
|
1383
1370
|
session.isBashRunning ||
|
|
@@ -1395,104 +1382,44 @@ export class AgentDaemon {
|
|
|
1395
1382
|
const current = requirePersistedJob ? this.getRunnableCronJob(job.id) : runnableJob;
|
|
1396
1383
|
return current && this.isCronJobRunnableForState(current, state, requirePersistedJob) ? current : undefined;
|
|
1397
1384
|
};
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
streamingBehavior,
|
|
1402
|
-
followUpQueueKey: `heartbeat:${runnableJob.id}`,
|
|
1403
|
-
source: "rpc",
|
|
1404
|
-
}, getRunnableJob);
|
|
1405
|
-
return didPrompt ? undefined : "skipped";
|
|
1385
|
+
const current = getRunnableJob();
|
|
1386
|
+
if (!current) {
|
|
1387
|
+
return "skipped";
|
|
1406
1388
|
}
|
|
1407
|
-
|
|
1408
|
-
const
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
}
|
|
1414
|
-
getRunnableCronJob(jobId) {
|
|
1415
|
-
return this.cronStore.getClaimedJob(jobId) ?? this.cronStore.getDueJob(jobId);
|
|
1416
|
-
}
|
|
1417
|
-
// Wraps session.prompt so the target counts as "preparing" until the turn
|
|
1418
|
-
// starts streaming (or the prompt settles); concurrent agent messages queue
|
|
1419
|
-
// instead of racing agent.prompt during the preflight awaits. Refcounted so
|
|
1420
|
-
// overlapping prompts each hold their own registration.
|
|
1421
|
-
async promptWithAgentMessagePreparingGuard(state, message, options, canPrompt, waitForCompletion = true) {
|
|
1422
|
-
return this.withAgentMessagePreparingGuard(state, (session, clearPreparing) => {
|
|
1423
|
-
const prompt = options?.agentMessageId !== undefined && options.expandPromptTemplates === false
|
|
1424
|
-
? session.acceptAgentMessagePrompt.bind(session)
|
|
1425
|
-
: waitForCompletion
|
|
1426
|
-
? (session.promptAndWait ?? session.prompt).bind(session)
|
|
1427
|
-
: (session.promptUntilAccepted ?? session.prompt).bind(session);
|
|
1428
|
-
return prompt(message, {
|
|
1429
|
-
...options,
|
|
1430
|
-
preflightResult: (didSucceed, queued) => {
|
|
1431
|
-
if (didSucceed && session.isStreaming) {
|
|
1432
|
-
clearPreparing();
|
|
1433
|
-
}
|
|
1434
|
-
options?.preflightResult?.(didSucceed, queued);
|
|
1435
|
-
},
|
|
1436
|
-
});
|
|
1437
|
-
}, canPrompt, options?.signal);
|
|
1438
|
-
}
|
|
1439
|
-
async promptHeartbeatWithAgentMessagePreparingGuard(state, job, options, getPromptJob) {
|
|
1440
|
-
let promptJob = job;
|
|
1441
|
-
return this.withAgentMessagePreparingGuard(state, (session, clearPreparing) => session.promptHeartbeat(promptJob, {
|
|
1442
|
-
...options,
|
|
1443
|
-
preflightResult: (didSucceed) => {
|
|
1444
|
-
if (didSucceed && session.isStreaming) {
|
|
1445
|
-
clearPreparing();
|
|
1446
|
-
}
|
|
1447
|
-
options?.preflightResult?.(didSucceed);
|
|
1448
|
-
},
|
|
1449
|
-
}), () => {
|
|
1450
|
-
if (!getPromptJob) {
|
|
1451
|
-
return true;
|
|
1452
|
-
}
|
|
1453
|
-
const current = getPromptJob();
|
|
1454
|
-
if (!current) {
|
|
1455
|
-
return false;
|
|
1456
|
-
}
|
|
1457
|
-
promptJob = current;
|
|
1458
|
-
return true;
|
|
1459
|
-
});
|
|
1460
|
-
}
|
|
1461
|
-
async withAgentMessagePreparingGuard(state, run, canRun, signal) {
|
|
1462
|
-
const activeSessionId = state.activeSessionId;
|
|
1463
|
-
this.agentMessagePreparingTargets.set(activeSessionId, (this.agentMessagePreparingTargets.get(activeSessionId) ?? 0) + 1);
|
|
1464
|
-
let cleared = false;
|
|
1465
|
-
const clearPreparing = () => {
|
|
1466
|
-
if (cleared) {
|
|
1467
|
-
return;
|
|
1468
|
-
}
|
|
1469
|
-
cleared = true;
|
|
1470
|
-
const next = (this.agentMessagePreparingTargets.get(activeSessionId) ?? 1) - 1;
|
|
1471
|
-
if (next <= 0) {
|
|
1472
|
-
this.agentMessagePreparingTargets.delete(activeSessionId);
|
|
1473
|
-
}
|
|
1474
|
-
else {
|
|
1475
|
-
this.agentMessagePreparingTargets.set(activeSessionId, next);
|
|
1389
|
+
// Re-check after the session admission fence wait: the job may have been cancelled, completed, or updated meanwhile.
|
|
1390
|
+
const unrunnableAtAdmission = new Error("Cron job became unrunnable before admission");
|
|
1391
|
+
const admissionCommitted = () => {
|
|
1392
|
+
const refreshed = getRunnableJob();
|
|
1393
|
+
if (!refreshed || refreshed.prompt !== current.prompt || refreshed.deliveryMode !== current.deliveryMode) {
|
|
1394
|
+
throw unrunnableAtAdmission;
|
|
1476
1395
|
}
|
|
1477
1396
|
};
|
|
1478
1397
|
try {
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
return
|
|
1398
|
+
if (isHeartbeatCronJob(current)) {
|
|
1399
|
+
await session.promptHeartbeat(current, {
|
|
1400
|
+
streamingBehavior: resolveHeartbeatStreamingBehavior(current.deliveryMode),
|
|
1401
|
+
followUpQueueKey: `heartbeat:${current.id}`,
|
|
1402
|
+
source: "rpc",
|
|
1403
|
+
admissionCommitted,
|
|
1404
|
+
});
|
|
1405
|
+
return;
|
|
1487
1406
|
}
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1407
|
+
await session.promptUntilAccepted(current.prompt, {
|
|
1408
|
+
streamingBehavior: "followUp",
|
|
1409
|
+
source: "rpc",
|
|
1410
|
+
admissionCommitted,
|
|
1411
|
+
});
|
|
1491
1412
|
}
|
|
1492
|
-
|
|
1493
|
-
|
|
1413
|
+
catch (error) {
|
|
1414
|
+
if (error === unrunnableAtAdmission) {
|
|
1415
|
+
return "skipped";
|
|
1416
|
+
}
|
|
1417
|
+
throw error;
|
|
1494
1418
|
}
|
|
1495
1419
|
}
|
|
1420
|
+
getRunnableCronJob(jobId) {
|
|
1421
|
+
return this.cronStore.getClaimedJob(jobId) ?? this.cronStore.getDueJob(jobId);
|
|
1422
|
+
}
|
|
1496
1423
|
createCronJobForState(state, schedule, prompt) {
|
|
1497
1424
|
const session = state.runtime.session;
|
|
1498
1425
|
const sessionFile = session.sessionFile;
|
|
@@ -2150,11 +2077,7 @@ export class AgentDaemon {
|
|
|
2150
2077
|
.filter((job) => job.activeSessionId === state.activeSessionId &&
|
|
2151
2078
|
job.status !== "cancelled" &&
|
|
2152
2079
|
job.status !== "completed");
|
|
2153
|
-
const hasPendingAdmission = this.
|
|
2154
|
-
this.agentMessagePreparingTargets.has(state.activeSessionId) ||
|
|
2155
|
-
this.agentMessageTargetLocks.has(state.activeSessionId) ||
|
|
2156
|
-
[...this.promptAdmissions.values()].some((admission) => admission.activeSessionId === state.activeSessionId && admission.status !== "cancelled") ||
|
|
2157
|
-
state.runtime.session.hasPendingAdmissionWaiters;
|
|
2080
|
+
const hasPendingAdmission = [...this.promptAdmissions.values()].some((admission) => admission.activeSessionId === state.activeSessionId && admission.status !== "cancelled") || state.runtime.session.hasPendingAdmissionWaiters;
|
|
2158
2081
|
return {
|
|
2159
2082
|
isSessionActive: summary.isSessionActive || summary.hasRunningRlmChildren === true || hasPendingAdmission,
|
|
2160
2083
|
attachedClients: state.clients.size + state.pendingAttaches,
|
|
@@ -3022,13 +2945,6 @@ export class AgentDaemon {
|
|
|
3022
2945
|
this.write(client, success(command.id, "detach"));
|
|
3023
2946
|
return;
|
|
3024
2947
|
}
|
|
3025
|
-
case "worker_sync_agent_peers":
|
|
3026
|
-
this.remoteAgentPeers.clear();
|
|
3027
|
-
for (const peer of command.peers) {
|
|
3028
|
-
this.remoteAgentPeers.set(peer.activeSessionId, peer);
|
|
3029
|
-
}
|
|
3030
|
-
this.writeWorkerSuccess(client, command);
|
|
3031
|
-
return;
|
|
3032
2948
|
case "worker_archive_and_shutdown": {
|
|
3033
2949
|
for (const state of [...this.sessions.values()]) {
|
|
3034
2950
|
await this.closeSession(state, "killed");
|
|
@@ -3103,6 +3019,12 @@ export class AgentDaemon {
|
|
|
3103
3019
|
this.writeWorkerSuccess(client, command);
|
|
3104
3020
|
return;
|
|
3105
3021
|
}
|
|
3022
|
+
default: {
|
|
3023
|
+
// Legacy commands from older supervisors (e.g. worker_sync_agent_peers) must fail fast, not time out.
|
|
3024
|
+
const unknown = command;
|
|
3025
|
+
this.write(client, failure(unknown.id, unknown.type, `Unknown worker command: ${unknown.type}`));
|
|
3026
|
+
return;
|
|
3027
|
+
}
|
|
3106
3028
|
}
|
|
3107
3029
|
}
|
|
3108
3030
|
catch (error) {
|
|
@@ -3453,7 +3375,7 @@ export class AgentDaemon {
|
|
|
3453
3375
|
};
|
|
3454
3376
|
if (command.type === "prompt_and_wait") {
|
|
3455
3377
|
try {
|
|
3456
|
-
await
|
|
3378
|
+
await state.runtime.session.promptAndWait(promptMessage, {
|
|
3457
3379
|
...options,
|
|
3458
3380
|
preflightResult: (didSucceed) => {
|
|
3459
3381
|
if (didSucceed)
|
|
@@ -3474,7 +3396,10 @@ export class AgentDaemon {
|
|
|
3474
3396
|
responseSent = true;
|
|
3475
3397
|
this.write(client, success(command.id, "prompt"));
|
|
3476
3398
|
};
|
|
3477
|
-
|
|
3399
|
+
const prompt = command.agentMessageId !== undefined && command.expandPromptTemplates === false
|
|
3400
|
+
? state.runtime.session.acceptAgentMessagePrompt.bind(state.runtime.session)
|
|
3401
|
+
: state.runtime.session.promptUntilAccepted.bind(state.runtime.session);
|
|
3402
|
+
void prompt(promptMessage, {
|
|
3478
3403
|
...options,
|
|
3479
3404
|
agentMessageId: command.agentMessageId,
|
|
3480
3405
|
customMessage: command.customMessage,
|
|
@@ -3487,7 +3412,7 @@ export class AgentDaemon {
|
|
|
3487
3412
|
preflightRejected = true;
|
|
3488
3413
|
}
|
|
3489
3414
|
},
|
|
3490
|
-
}
|
|
3415
|
+
})
|
|
3491
3416
|
.then(() => {
|
|
3492
3417
|
if (preflightRejected) {
|
|
3493
3418
|
const error = new Error("Prompt was not accepted by the session.");
|
|
@@ -3610,10 +3535,8 @@ export class AgentDaemon {
|
|
|
3610
3535
|
}
|
|
3611
3536
|
case "agent_messages_clear": {
|
|
3612
3537
|
const state = this.getSessionState(command.activeSessionId);
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
return state.runtime.session.clearQueuedUserMessagesMatching(isAgentSessionMessagePrompt);
|
|
3616
|
-
});
|
|
3538
|
+
this.agentMessageRateLimiter.clearMatching((key) => key.endsWith(`->${state.activeSessionId}`));
|
|
3539
|
+
const cleared = state.runtime.session.clearQueuedAgentMessages();
|
|
3617
3540
|
return success(command.id, "agent_messages_clear", cleared);
|
|
3618
3541
|
}
|
|
3619
3542
|
case "abort": {
|
|
@@ -4538,7 +4461,29 @@ export class AgentDaemon {
|
|
|
4538
4461
|
...(session.sessionFile ? { sessionPath: session.sessionFile } : {}),
|
|
4539
4462
|
};
|
|
4540
4463
|
}
|
|
4541
|
-
async
|
|
4464
|
+
async listSupervisorAgentPeers() {
|
|
4465
|
+
const supervisorSocketPath = this.supervisorSocketPathFromEnv();
|
|
4466
|
+
if (!this.options.worker || !supervisorSocketPath)
|
|
4467
|
+
return [];
|
|
4468
|
+
const client = new DaemonClient(supervisorSocketPath);
|
|
4469
|
+
try {
|
|
4470
|
+
await client.connect(1000);
|
|
4471
|
+
await client.waitForHello(1000);
|
|
4472
|
+
const response = await client.request({ type: "list_agent_peers", workerToken: this.options.worker.authenticationToken }, 5000);
|
|
4473
|
+
if (!response.success)
|
|
4474
|
+
throw deserializeDaemonError(response);
|
|
4475
|
+
// SAFETY: The authenticated supervisor constructs the peer response.
|
|
4476
|
+
return response.data.peers;
|
|
4477
|
+
}
|
|
4478
|
+
catch {
|
|
4479
|
+
return [];
|
|
4480
|
+
}
|
|
4481
|
+
finally {
|
|
4482
|
+
client.close();
|
|
4483
|
+
}
|
|
4484
|
+
}
|
|
4485
|
+
async createAgentMessageListResult(current, peers) {
|
|
4486
|
+
peers ??= await this.listSupervisorAgentPeers();
|
|
4542
4487
|
const localAgents = this.listTargetableSessionStates(current).map((state) => this.createAgentMessageAgentSummary(state));
|
|
4543
4488
|
for (const passive of await this.listPassiveRlmSubagents()) {
|
|
4544
4489
|
const { entry, info } = passive;
|
|
@@ -4568,23 +4513,20 @@ export class AgentDaemon {
|
|
|
4568
4513
|
});
|
|
4569
4514
|
}
|
|
4570
4515
|
const localIds = new Set(localAgents.map((agent) => agent.activeSessionId));
|
|
4516
|
+
const remoteAgents = peers.filter((peer) => !localIds.has(peer.activeSessionId) && !this.closingSessions.has(peer.activeSessionId));
|
|
4571
4517
|
return {
|
|
4572
4518
|
current: this.createAgentSessionMessageEndpoint(current),
|
|
4573
|
-
agents: [
|
|
4574
|
-
...localAgents,
|
|
4575
|
-
...[...this.remoteAgentPeers.values()].filter((peer) => peer.status !== "inactive" &&
|
|
4576
|
-
!localIds.has(peer.activeSessionId) &&
|
|
4577
|
-
!this.closingSessions.has(peer.activeSessionId)),
|
|
4578
|
-
],
|
|
4519
|
+
agents: [...localAgents, ...remoteAgents],
|
|
4579
4520
|
};
|
|
4580
4521
|
}
|
|
4581
4522
|
async createAgentFamilyCatalog(currentState) {
|
|
4582
4523
|
const current = currentState ?? [...this.sessions.values()].find((state) => !this.bindingSessions.has(state.activeSessionId));
|
|
4583
|
-
const
|
|
4584
|
-
const
|
|
4524
|
+
const remotePeers = current ? await this.listSupervisorAgentPeers() : [];
|
|
4525
|
+
const listed = current ? await this.createAgentMessageListResult(current, remotePeers) : { agents: [] };
|
|
4526
|
+
const remotePeerSet = new Set(remotePeers);
|
|
4585
4527
|
const localAgents = current
|
|
4586
|
-
? [this.createAgentMessageAgentSummary(current), ...listed.agents.filter((agent) => !
|
|
4587
|
-
: listed.agents
|
|
4528
|
+
? [this.createAgentMessageAgentSummary(current), ...listed.agents.filter((agent) => !remotePeerSet.has(agent))]
|
|
4529
|
+
: listed.agents;
|
|
4588
4530
|
const activePaths = new Set(localAgents.flatMap((agent) => (agent.sessionPath ? [canonicalSessionPath(agent.sessionPath)] : [])));
|
|
4589
4531
|
const savedRoots = (await SessionManager.listAll(undefined, this.options.defaultSessionConfig.sessionDir))
|
|
4590
4532
|
.filter((info) => (info.rlmDepth ?? (info.parentSessionPath ? -1 : 0)) === 0 &&
|
|
@@ -4618,7 +4560,7 @@ export class AgentDaemon {
|
|
|
4618
4560
|
...(agent.sessionPath ? { sessionPath: canonicalSessionPath(agent.sessionPath) } : {}),
|
|
4619
4561
|
});
|
|
4620
4562
|
};
|
|
4621
|
-
for (const peer of
|
|
4563
|
+
for (const peer of remotePeers)
|
|
4622
4564
|
addAgent(peer);
|
|
4623
4565
|
for (const agent of localAgents)
|
|
4624
4566
|
addAgent(agent);
|
|
@@ -4752,50 +4694,11 @@ export class AgentDaemon {
|
|
|
4752
4694
|
return `cli:${this.socketPath}`;
|
|
4753
4695
|
}
|
|
4754
4696
|
async clearQueuedAgentSessionMessagesForState(state) {
|
|
4755
|
-
return
|
|
4697
|
+
return state.runtime.session.clearQueuedAgentMessages();
|
|
4756
4698
|
}
|
|
4757
4699
|
async clearQueuedAgentSessionMessagesForAllStates() {
|
|
4758
4700
|
await Promise.all([...this.sessions.values()].map((state) => this.clearQueuedAgentSessionMessagesForState(state)));
|
|
4759
4701
|
}
|
|
4760
|
-
reserveAgentMessageQueueSlot(targetState) {
|
|
4761
|
-
const activeSessionId = targetState.activeSessionId;
|
|
4762
|
-
const reserved = this.agentMessagePendingReservations.get(activeSessionId) ?? 0;
|
|
4763
|
-
assertAgentMessageQueueCapacity(targetState.runtime.session.unfinishedActionCount + reserved, DEFAULT_AGENT_MESSAGE_MAX_PENDING_PER_SESSION);
|
|
4764
|
-
this.agentMessagePendingReservations.set(activeSessionId, reserved + 1);
|
|
4765
|
-
let released = false;
|
|
4766
|
-
return () => {
|
|
4767
|
-
if (released) {
|
|
4768
|
-
return;
|
|
4769
|
-
}
|
|
4770
|
-
released = true;
|
|
4771
|
-
const next = (this.agentMessagePendingReservations.get(activeSessionId) ?? 1) - 1;
|
|
4772
|
-
if (next <= 0) {
|
|
4773
|
-
this.agentMessagePendingReservations.delete(activeSessionId);
|
|
4774
|
-
}
|
|
4775
|
-
else {
|
|
4776
|
-
this.agentMessagePendingReservations.set(activeSessionId, next);
|
|
4777
|
-
}
|
|
4778
|
-
};
|
|
4779
|
-
}
|
|
4780
|
-
async withAgentMessageTargetLock(activeSessionId, run) {
|
|
4781
|
-
const previous = this.agentMessageTargetLocks.get(activeSessionId) ?? Promise.resolve();
|
|
4782
|
-
let releaseCurrent = () => { };
|
|
4783
|
-
const current = new Promise((resolve) => {
|
|
4784
|
-
releaseCurrent = resolve;
|
|
4785
|
-
});
|
|
4786
|
-
const next = previous.catch(() => undefined).then(() => current);
|
|
4787
|
-
this.agentMessageTargetLocks.set(activeSessionId, next);
|
|
4788
|
-
await previous.catch(() => undefined);
|
|
4789
|
-
try {
|
|
4790
|
-
return await run();
|
|
4791
|
-
}
|
|
4792
|
-
finally {
|
|
4793
|
-
releaseCurrent();
|
|
4794
|
-
if (this.agentMessageTargetLocks.get(activeSessionId) === next) {
|
|
4795
|
-
this.agentMessageTargetLocks.delete(activeSessionId);
|
|
4796
|
-
}
|
|
4797
|
-
}
|
|
4798
|
-
}
|
|
4799
4702
|
agentFamilyEntry(state) {
|
|
4800
4703
|
const metadata = state.runtime.metadata;
|
|
4801
4704
|
const depth = state.runtime.session.rlmDepth ?? 0;
|
|
@@ -4946,12 +4849,10 @@ export class AgentDaemon {
|
|
|
4946
4849
|
if (options.origin === "agent" && options.fromState) {
|
|
4947
4850
|
this.assertAgentFamilyReachable(options.fromState, targetState);
|
|
4948
4851
|
}
|
|
4949
|
-
const releaseQueueSlot = this.reserveAgentMessageQueueSlot(targetState);
|
|
4950
4852
|
const senderKey = options.senderKey ?? options.fromState?.activeSessionId ?? `client:${options.clientId ?? "unknown"}`;
|
|
4951
4853
|
const rateLimitKey = `${senderKey}->${targetState.activeSessionId}`;
|
|
4952
4854
|
const rateLimit = this.agentMessageRateLimiter.tryConsume(rateLimitKey);
|
|
4953
4855
|
if (!rateLimit.ok) {
|
|
4954
|
-
releaseQueueSlot();
|
|
4955
4856
|
throw new Error(`Agent messaging rate limit exceeded; retry after ${rateLimit.retryAfterMs}ms`);
|
|
4956
4857
|
}
|
|
4957
4858
|
const payload = {
|
|
@@ -4964,29 +4865,13 @@ export class AgentDaemon {
|
|
|
4964
4865
|
target: this.createAgentSessionMessageEndpoint(targetState),
|
|
4965
4866
|
};
|
|
4966
4867
|
try {
|
|
4967
|
-
const { status } = await this.
|
|
4968
|
-
if (this.agentMessagesPaused) {
|
|
4969
|
-
throw new Error("Agent messaging is paused");
|
|
4970
|
-
}
|
|
4971
|
-
if (!this.sessions.has(targetState.activeSessionId) ||
|
|
4972
|
-
this.closingSessions.has(targetState.activeSessionId)) {
|
|
4973
|
-
throw new Error("Target session is closing before agent message delivery");
|
|
4974
|
-
}
|
|
4975
|
-
if (targetState.runtime.session.sessionId !== payload.target.sessionId) {
|
|
4976
|
-
throw new Error("Target session changed before agent message delivery");
|
|
4977
|
-
}
|
|
4978
|
-
return this.acceptAgentSessionMessage(targetState, payload, releaseQueueSlot);
|
|
4979
|
-
});
|
|
4868
|
+
const { status } = await this.acceptAgentSessionMessage(targetState, payload);
|
|
4980
4869
|
return createAgentSessionMessageReceipt(payload, status);
|
|
4981
4870
|
}
|
|
4982
4871
|
catch (error) {
|
|
4983
4872
|
this.agentMessageRateLimiter.refund(rateLimitKey);
|
|
4984
4873
|
throw error;
|
|
4985
4874
|
}
|
|
4986
|
-
finally {
|
|
4987
|
-
// Error-path backstop; success paths release inside acceptAgentSessionMessage.
|
|
4988
|
-
releaseQueueSlot();
|
|
4989
|
-
}
|
|
4990
4875
|
}
|
|
4991
4876
|
async sendRemoteAgentSessionMessage(fromState, targetSelector, message) {
|
|
4992
4877
|
const supervisorSocketPath = this.supervisorSocketPathFromEnv();
|
|
@@ -4994,100 +4879,75 @@ export class AgentDaemon {
|
|
|
4994
4879
|
throw new Error(`Unknown active session: ${targetSelector}`);
|
|
4995
4880
|
}
|
|
4996
4881
|
const deadline = Date.now() + 30_000;
|
|
4882
|
+
let client;
|
|
4997
4883
|
let lastError;
|
|
4998
4884
|
while (Date.now() < deadline && !this.shuttingDown) {
|
|
4999
|
-
const
|
|
5000
|
-
let receivedResponse = false;
|
|
4885
|
+
const candidate = new DaemonClient(supervisorSocketPath);
|
|
5001
4886
|
try {
|
|
5002
|
-
await
|
|
5003
|
-
await
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
targetActiveSessionId: targetSelector,
|
|
5007
|
-
message,
|
|
5008
|
-
fromActiveSessionId: fromState.activeSessionId,
|
|
5009
|
-
agentOrigin: true,
|
|
5010
|
-
}, 30_000);
|
|
5011
|
-
receivedResponse = true;
|
|
5012
|
-
if (!response.success) {
|
|
5013
|
-
throw deserializeDaemonError(response);
|
|
5014
|
-
}
|
|
5015
|
-
if (!response.data || typeof response.data !== "object") {
|
|
5016
|
-
throw new Error("Supervisor returned an invalid agent-message receipt");
|
|
5017
|
-
}
|
|
5018
|
-
return response.data;
|
|
4887
|
+
await candidate.connect(1000);
|
|
4888
|
+
await candidate.waitForHello(1000);
|
|
4889
|
+
client = candidate;
|
|
4890
|
+
break;
|
|
5019
4891
|
}
|
|
5020
4892
|
catch (error) {
|
|
5021
4893
|
lastError = error;
|
|
5022
|
-
|
|
5023
|
-
throw error;
|
|
5024
|
-
}
|
|
5025
|
-
}
|
|
5026
|
-
finally {
|
|
5027
|
-
client.close();
|
|
4894
|
+
candidate.close();
|
|
5028
4895
|
}
|
|
5029
4896
|
await new Promise((resolveDelay) => setTimeout(resolveDelay, 250));
|
|
5030
4897
|
}
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
const session = targetState.runtime.session;
|
|
5035
|
-
const reserved = this.agentMessagePendingReservations.get(targetState.activeSessionId) ?? 0;
|
|
5036
|
-
const otherReservations = Math.max(0, reserved - 1);
|
|
5037
|
-
assertAgentMessageQueueCapacity(session.unfinishedActionCount + otherReservations, DEFAULT_AGENT_MESSAGE_MAX_PENDING_PER_SESSION);
|
|
5038
|
-
const shouldQueue = this.agentMessageAcceptingTargets.has(targetState.activeSessionId) ||
|
|
5039
|
-
this.agentMessagePreparingTargets.has(targetState.activeSessionId) ||
|
|
5040
|
-
session.isStreaming ||
|
|
5041
|
-
session.isCompacting ||
|
|
5042
|
-
session.isRetrying ||
|
|
5043
|
-
session.isBashRunning ||
|
|
5044
|
-
session.unfinishedActionCount > 0;
|
|
5045
|
-
const streamingBehavior = "steer";
|
|
5046
|
-
const message = createAgentSessionMessage(payload);
|
|
5047
|
-
const prompt = message.content;
|
|
5048
|
-
if (shouldQueue) {
|
|
5049
|
-
const didQueue = await session.queueAgentMessagePrompt(prompt, streamingBehavior, message);
|
|
5050
|
-
if (!didQueue) {
|
|
5051
|
-
throw new Error("Agent message was not queued");
|
|
5052
|
-
}
|
|
5053
|
-
// The queued message now counts in unfinishedActionCount.
|
|
5054
|
-
releaseReservation();
|
|
5055
|
-
// Do not await delivery: a queued message delivers only when the target's
|
|
5056
|
-
// turn progresses, and the sender is blocked inside its own turn — awaiting
|
|
5057
|
-
// here deadlocks mutual sends between busy sessions.
|
|
5058
|
-
return { status: "queued" };
|
|
5059
|
-
}
|
|
5060
|
-
this.agentMessageAcceptingTargets.add(targetState.activeSessionId);
|
|
5061
|
-
let preflightFailed = false;
|
|
5062
|
-
let preflightQueued = false;
|
|
4898
|
+
if (!client) {
|
|
4899
|
+
throw lastError instanceof Error ? lastError : new Error(`Unknown active session: ${targetSelector}`);
|
|
4900
|
+
}
|
|
5063
4901
|
try {
|
|
5064
|
-
const
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
if (typeof session.acceptAgentMessagePrompt === "function") {
|
|
5074
|
-
await session.acceptAgentMessagePrompt(prompt, {
|
|
5075
|
-
...promptOptions,
|
|
5076
|
-
customMessage: message,
|
|
5077
|
-
});
|
|
5078
|
-
}
|
|
5079
|
-
else {
|
|
5080
|
-
await session.prompt(prompt, promptOptions);
|
|
4902
|
+
const response = await client.request({
|
|
4903
|
+
type: "send_message",
|
|
4904
|
+
targetActiveSessionId: targetSelector,
|
|
4905
|
+
message,
|
|
4906
|
+
fromActiveSessionId: fromState.activeSessionId,
|
|
4907
|
+
agentOrigin: true,
|
|
4908
|
+
}, 30_000);
|
|
4909
|
+
if (!response.success) {
|
|
4910
|
+
throw deserializeDaemonError(response);
|
|
5081
4911
|
}
|
|
5082
|
-
if (
|
|
5083
|
-
throw new Error("
|
|
4912
|
+
if (!response.data || typeof response.data !== "object") {
|
|
4913
|
+
throw new Error("Supervisor returned an invalid agent-message receipt");
|
|
5084
4914
|
}
|
|
5085
|
-
|
|
5086
|
-
return { status: preflightQueued ? "queued" : "delivered" };
|
|
4915
|
+
return response.data;
|
|
5087
4916
|
}
|
|
5088
4917
|
finally {
|
|
5089
|
-
|
|
4918
|
+
client.close();
|
|
4919
|
+
}
|
|
4920
|
+
}
|
|
4921
|
+
async acceptAgentSessionMessage(targetState, payload) {
|
|
4922
|
+
const message = createAgentSessionMessage(payload);
|
|
4923
|
+
let preflightFailed = false;
|
|
4924
|
+
let preflightQueued = false;
|
|
4925
|
+
await targetState.runtime.session.acceptAgentMessagePrompt(message.content, {
|
|
4926
|
+
expandPromptTemplates: false,
|
|
4927
|
+
streamingBehavior: "steer",
|
|
4928
|
+
queueIfBusy: true,
|
|
4929
|
+
customMessage: message,
|
|
4930
|
+
admissionCommitted: () => {
|
|
4931
|
+
if (this.agentMessagesPaused) {
|
|
4932
|
+
throw new Error("Agent messaging is paused");
|
|
4933
|
+
}
|
|
4934
|
+
if (!this.sessions.has(targetState.activeSessionId) ||
|
|
4935
|
+
this.closingSessions.has(targetState.activeSessionId)) {
|
|
4936
|
+
throw new Error("Target session is closing before agent message delivery");
|
|
4937
|
+
}
|
|
4938
|
+
if (targetState.runtime.session.sessionId !== payload.target.sessionId) {
|
|
4939
|
+
throw new Error("Target session changed before agent message delivery");
|
|
4940
|
+
}
|
|
4941
|
+
},
|
|
4942
|
+
preflightResult: (didSucceed, didQueue) => {
|
|
4943
|
+
preflightFailed = !didSucceed;
|
|
4944
|
+
preflightQueued = didSucceed && didQueue === true;
|
|
4945
|
+
},
|
|
4946
|
+
});
|
|
4947
|
+
if (preflightFailed) {
|
|
4948
|
+
throw new Error("Agent message was not accepted");
|
|
5090
4949
|
}
|
|
4950
|
+
return { status: preflightQueued ? "queued" : "delivered" };
|
|
5091
4951
|
}
|
|
5092
4952
|
detachClientFromSession(client, state) {
|
|
5093
4953
|
const acpMcpOwner = this.acpMcpOwners.get(state.activeSessionId);
|