v0.6.3
Fix: Lead hangs indefinitely during team_spawn
This release fixes a persistent bug where the team lead would hang with a loading spinner after spawning teammates. The teammates were actually working (permission popups appeared, code was being written in worktrees), but the lead's tool call never returned.
Three root causes were identified across v0.6.1–v0.6.3. The first two patches (v0.6.1, v0.6.2) treated symptoms; this release fixes the actual bugs.
Root cause 1: await on fire-and-forget promptAsync
promptAsync is HTTP 204 on the server — it accepts the message and returns immediately with no body. But the plugin code awaited it. Through a proxy or slow transport, the await blocked the tool call indefinitely. The lead's team_spawn never returned, so the model never generated its "team is started" response.
- All
promptAsynccalls inteam_spawn,team_message, andteam_broadcastare now fire-and-forget (noawait) - Messages are persisted in the DB before the
promptAsynccall - Async
.catch()handles rollback on failure - If a spawn fails, the lead receives a system message:
Teammate "X" failed to start and was removed
Root cause 2: v1→v2 SDK transport extraction
The plugin framework provides a v1 SDK client. We extract its HeyAPI transport and pass it to the v2 SDK constructor. The v1 SDK stores the transport as ._client (underscore), while the v2 SDK stores it as .client (no underscore). An earlier patch accidentally changed the extraction to read .client from the v1 class, which returned undefined. The v2 constructor fell back to a default HTTP transport that couldn't reach the server — every session.create() failed with "Unable to connect".
- Restored correct
._clientproperty extraction from v1 plugin client - Added
V2Transporttype alias to avoidas anycast - Documented the v1/v2 property name difference in AGENTS.md as a settled decision
Root cause 3: Teammate messages interrupting the lead's active stream (v0.6.2)
When teammates finished fast and sent messages back via promptAsync while the lead was busy, the proxy would cancel the lead's active stream. This was fixed in v0.6.2 with a busy-session guard and idle-flush backstop, and remains in place.
Also in this release
- Biome linter added with
noExplicitAny: error— theas anycast that caused root cause 2 is now a lint error - All non-null assertions (
!) replaced with nullish coalescing (?? "unknown") - Dead code removed from
notify.ts allSessionIds()public method replaces private property access onMemberRegistry- Async rollback in
team_spawnwrapped in try/catch to prevent unhandled rejections - DB rollback uses
session_idinstead ofnameto prevent race with re-spawned teammates
Why it took three patches
v0.6.1 reduced payload sizes and added sequential spawn guidance — treating the proxy truncation symptom, not the blocking await cause. v0.6.2 correctly identified the message-interruption race but missed that the lead was hanging during the spawn itself, before any messages arrived. v0.6.3 identified both the await blocking and the transport extraction bug through a thorough SDK source audit, and added Biome enforcement to prevent as any casts from hiding type mismatches in the future.
Full Changelog: v0.6.2...v0.6.3