Skip to content

feat: add forceReleaseLock + onLockConflict for interrupt/steerability#193

Merged
haydenbleasel merged 17 commits intovercel:mainfrom
gakonst:feat/force-release-lock
Mar 8, 2026
Merged

feat: add forceReleaseLock + onLockConflict for interrupt/steerability#193
haydenbleasel merged 17 commits intovercel:mainfrom
gakonst:feat/force-release-lock

Conversation

@gakonst
Copy link
Contributor

@gakonst gakonst commented Mar 7, 2026

Problem

When building AI agents on top of the chat SDK, users need to be able to interrupt a running agent by sending a follow-up message. Currently, if a handler is still processing (e.g., streaming an LLM response), the thread lock blocks the new message and it gets silently dropped via LockError.

This makes it impossible to steer or interrupt long-running agent turns from chat.

Solution

Two changes:

  1. StateAdapter.forceReleaseLock(threadId) — unconditionally releases a thread lock regardless of ownership token. The previous lock holder's finally block will call releaseLock() with a stale token, which is already a no-op (both Redis and memory impls verify the token before deleting).

  2. onLockConflict config option — controls behavior when acquireLock fails:

    • 'drop' (default, preserves current behavior) — throw LockError
    • 'force' — force-release the existing lock and re-acquire
    • (threadId, message) => 'force' | 'drop' — callback for custom logic
const chat = new Chat({
  userName: 'my-bot',
  state: createRedisState(),
  onLockConflict: 'force', // always allow interrupt
});

Why this matters

Any chat SDK user building long-running handlers (AI agents, workflows, async tasks) needs this. The current lock-or-drop behavior was designed for short idempotent handlers, not multi-minute streaming sessions. This is a non-breaking, backwards-compatible addition.

@vercel
Copy link
Contributor

vercel bot commented Mar 7, 2026

@gakonst is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

haydenbleasel and others added 9 commits March 7, 2026 23:18
Implements the new StateAdapter.forceReleaseLock method in the mock
adapter so tests using createMockState() don't break.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Allow the onLockConflict callback to return a Promise, enabling
users to check external state (e.g. DB queries) before deciding
whether to force-release or drop.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Covers: default drop behavior, force mode, sync/async callbacks
returning force/drop, and forceReleaseLock on memory adapter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…dapter

Biome enforces alphabetical ordering on interface members. Also adds
the missing forceReleaseLock implementation to the ioredis state adapter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
haydenbleasel and others added 4 commits March 7, 2026 23:30
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Contributor

vercel bot commented Mar 8, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
chat Ready Ready Preview, Comment, Open in v0 Mar 8, 2026 7:41am
chat-sdk-nextjs-chat Ready Ready Preview, Comment, Open in v0 Mar 8, 2026 7:41am

haydenbleasel and others added 2 commits March 7, 2026 23:35
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@haydenbleasel
Copy link
Member

great stuff @gakonst 🙏

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@haydenbleasel haydenbleasel merged commit eb49b2a into vercel:main Mar 8, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants