Fix #4355: Make session write lock timeout configurable

- Increase default timeout from 10s to 60s to prevent premature
  termination when multiple subagents compete for session file locks
- Add sessionWriteLockTimeoutMs config option to agent defaults
- Update call sites to use config value when available
- Maintain backwards compatibility for explicit timeoutMs callers

This fixes the issue where subagents would terminate prematurely with
'terminated' error when session write lock timeout (10s) was exceeded
during concurrent subagent execution.
This commit is contained in:
spiceoogway 2026-01-29 23:39:31 -05:00
parent bf6ec64fd9
commit f1b866e854
5 changed files with 32 additions and 28 deletions

53
pnpm-lock.yaml generated
View File

@ -172,6 +172,13 @@ importers:
zod:
specifier: ^4.3.6
version: 4.3.6
optionalDependencies:
'@napi-rs/canvas':
specifier: ^0.1.88
version: 0.1.88
node-llama-cpp:
specifier: 3.15.0
version: 3.15.0(typescript@5.9.3)
devDependencies:
'@grammyjs/types':
specifier: ^3.23.0
@ -254,13 +261,6 @@ importers:
wireit:
specifier: ^0.14.12
version: 0.14.12
optionalDependencies:
'@napi-rs/canvas':
specifier: ^0.1.88
version: 0.1.88
node-llama-cpp:
specifier: 3.15.0
version: 3.15.0(typescript@5.9.3)
extensions/bluebubbles: {}
@ -314,17 +314,17 @@ importers:
specifier: ^10.5.0
version: 10.5.0
devDependencies:
moltbot:
openclaw:
specifier: workspace:*
version: link:../../packages/moltbot
version: link:../..
extensions/imessage: {}
extensions/line:
devDependencies:
moltbot:
openclaw:
specifier: workspace:*
version: link:../../packages/moltbot
version: link:../..
extensions/llm-task: {}
@ -348,17 +348,17 @@ importers:
specifier: ^4.3.6
version: 4.3.6
devDependencies:
moltbot:
openclaw:
specifier: workspace:*
version: link:../../packages/moltbot
version: link:../..
extensions/mattermost: {}
extensions/memory-core:
devDependencies:
moltbot:
openclaw:
specifier: workspace:*
version: link:../../packages/moltbot
version: link:../..
extensions/memory-lancedb:
dependencies:
@ -386,9 +386,9 @@ importers:
express:
specifier: ^5.2.1
version: 5.2.1
moltbot:
openclaw:
specifier: workspace:*
version: link:../../packages/moltbot
version: link:../..
proper-lockfile:
specifier: ^4.1.2
version: 4.1.2
@ -397,12 +397,12 @@ importers:
extensions/nostr:
dependencies:
moltbot:
specifier: workspace:*
version: link:../../packages/moltbot
nostr-tools:
specifier: ^2.20.0
version: 2.20.0(typescript@5.9.3)
openclaw:
specifier: workspace:*
version: link:../..
zod:
specifier: ^4.3.6
version: 4.3.6
@ -439,9 +439,9 @@ importers:
specifier: ^4.3.5
version: 4.3.6
devDependencies:
moltbot:
openclaw:
specifier: workspace:*
version: link:../../packages/moltbot
version: link:../..
extensions/voice-call:
dependencies:
@ -459,9 +459,9 @@ importers:
extensions/zalo:
dependencies:
moltbot:
openclaw:
specifier: workspace:*
version: link:../../packages/moltbot
version: link:../..
undici:
specifier: 7.19.0
version: 7.19.0
@ -471,9 +471,9 @@ importers:
'@sinclair/typebox':
specifier: 0.34.47
version: 0.34.47
moltbot:
openclaw:
specifier: workspace:*
version: link:../../packages/moltbot
version: link:../..
packages/clawdbot:
dependencies:
@ -1328,7 +1328,6 @@ packages:
'@lancedb/lancedb@0.23.0':
resolution: {integrity: sha512-aYrIoEG24AC+wILCL57Ius/Y4yU+xFHDPKLvmjzzN4byAjzeIGF0TC86S5RBt4Ji+dxS7yIWV5Q/gE5/fybIFQ==}
engines: {node: '>= 18'}
cpu: [x64, arm64]
os: [darwin, linux, win32]
peerDependencies:
apache-arrow: '>=15.0.0 <=18.1.0'

View File

@ -351,6 +351,7 @@ export async function compactEmbeddedPiSessionDirect(
const sessionLock = await acquireSessionWriteLock({
sessionFile: params.sessionFile,
timeoutMs: params.config?.agents?.defaults?.sessionWriteLockTimeoutMs,
});
try {
await prewarmSessionFile(params.sessionFile);

View File

@ -386,6 +386,7 @@ export async function runEmbeddedAttempt(
const sessionLock = await acquireSessionWriteLock({
sessionFile: params.sessionFile,
timeoutMs: params.config?.agents?.defaults?.sessionWriteLockTimeoutMs,
});
let sessionManager: ReturnType<typeof guardSessionManager> | undefined;

View File

@ -107,7 +107,9 @@ export async function acquireSessionWriteLock(params: {
release: () => Promise<void>;
}> {
registerCleanupHandlers();
const timeoutMs = params.timeoutMs ?? 10_000;
// Default timeout increased from 10s to 60s to prevent premature termination
// when multiple subagents compete for session file locks (see issue #4355)
const timeoutMs = params.timeoutMs ?? 60_000;
const staleMs = params.staleMs ?? 30 * 60 * 1000;
const sessionFile = path.resolve(params.sessionFile);
const sessionDir = path.dirname(sessionFile);

View File

@ -123,6 +123,7 @@ export const AgentDefaultsSchema = z
blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(),
humanDelay: HumanDelaySchema.optional(),
timeoutSeconds: z.number().int().positive().optional(),
sessionWriteLockTimeoutMs: z.number().int().positive().optional(),
mediaMaxMb: z.number().positive().optional(),
typingIntervalSeconds: z.number().int().positive().optional(),
typingMode: z