C-1: sendCommand now races against a 10s per-command timeout so a Redis
instance that accepts the TCP connection but then stalls will reject and
flow into the existing fail-closed path instead of hanging dispatch
indefinitely.
C-3: resolveRedisLockUrl no longer falls back to REDIS_URL. ACP Redis
locking now activates only when OPENCLAW_ACP_SESSION_LOCK_REDIS_URL is
explicitly set, preventing unrelated Redis deployments from being
silently opted into fail-closed ACP locking.
Tests: added two cases to session-lock-manager.test.ts confirming that
REDIS_URL alone selects the local backend, and that
OPENCLAW_ACP_SESSION_LOCK_REDIS_URL takes precedence and triggers
fail-closed when the URL is invalid.
- add SessionLockManager abstraction for ACP execution locking
- add local, redis, and fail-closed lock manager implementations
- use Redis SET NX PX plus owner-checked Lua release/renew
- wire lock acquire/release/renew into ACP dispatch flow
- skip with acp_execution_locked when lock is contended or acquire fails
- document ACP session lock Redis env vars in .env.example
- add unit and dispatch tests for lock behavior
* build: mirror uuid for msteams
Add uuid to both the msteams bundled extension and the root package so the workspace build can resolve @microsoft/agents-hosting during tsdown while standalone extension installs also have the runtime dependency available.
Regeneration-Prompt: |
pnpm build failed because @microsoft/agents-hosting 1.3.1 requires uuid in its published JS but does not declare it in its package manifest. The msteams extension dynamically imports that package, and the workspace build resolves it from the root dependency graph. Mirror uuid into the root package for workspace builds and keep it in extensions/msteams/package.json so standalone plugin installs also resolve it. Update the lockfile to match the manifest changes.
* build: prune stale plugin dist symlinks
Remove stale dist and dist-runtime plugin node_modules symlinks before tsdown runs. These links point back into extension installs, and tsdown's clean step can traverse them on rebuilds and hollow out the active pnpm dependency tree before plugin-sdk declaration generation runs.
Regeneration-Prompt: |
pnpm build was intermittently failing in the plugin-sdk:dts phase after earlier build steps had already run. The symptom looked like missing root packages such as zod, ajv, commander, and undici even though a fresh install briefly fixed the problem. Investigate the build pipeline step by step rather than patching TypeScript errors. Confirm whether rebuilds mutate node_modules, identify the first step that does it, and preserve existing runtime-postbuild behavior.
The key constraint is that dist and dist-runtime plugin node_modules links are intentional for runtime packaging, so do not remove that feature globally. Instead, make rebuilds safe by deleting only stale symlinks left in generated output before invoking tsdown, so tsdown cleanup cannot recurse back into the live pnpm install tree. Verify with repeated pnpm build runs.
import the config-backed Slack directory helpers into the Slack channel plugin so directory.listPeers and directory.listGroups no longer throw at runtime, and add a regression test covering configured DM peer listing