fix(host): hand a raced plain-agent winner back from agentFor

The raced-collision catch mirrored only the subagent-owned half of
ensureSession's `.catch`: a concurrent plain-agent publish winning the
identity still fell through to `internal`, where ensureSession returns
the winner. Mirror in full — classify a subagent-owned winner as
`agent-busy`, return a clean plain-agent winner directly.
This commit is contained in:
Tianyi Cui
2026-08-02 13:47:24 +08:00
parent fb6ccdff04
commit d7a70f6efa

View File

@@ -1114,14 +1114,15 @@ export function createApiProxy(ctx: Context, defaults: ApiProxyDefaults): ApiPro
if (error instanceof SubagentSessionOwnership) { if (error instanceof SubagentSessionOwnership) {
return { error: subagentOwnershipError(error.sessionId) } return { error: subagentOwnershipError(error.sessionId) }
} }
// A concurrent parent `enter()` can win the identity between the // A concurrent publish can win the identity between the pre-resume
// pre-resume published re-check and `ctx.agents.resume` publication; // re-check and `ctx.agents.resume` publication; the ID-collision
// the ID-collision rejection falls through here. Re-classify that // rejection falls through here. Mirror ensureSession's `.catch` in
// raced published winner into the stable ownership error, mirroring // full: classify a subagent-owned winner into the stable ownership
// ensureSession's `.catch`. // error, and hand a clean plain-agent winner straight back.
const live = ctx.agents.get(sessionId) const live = ctx.agents.get(sessionId)
if (live !== undefined && hasSubagentOwner(live.session, live)) { if (live !== undefined) {
return { error: subagentOwnershipError(sessionId) } if (hasSubagentOwner(live.session, live)) return { error: subagentOwnershipError(sessionId) }
return { agent: live }
} }
const attached = ctx.sessions.get(sessionId) const attached = ctx.sessions.get(sessionId)
if (attached !== undefined && hasSubagentOwner(attached, undefined)) { if (attached !== undefined && hasSubagentOwner(attached, undefined)) {