refactor(host): share the fenced-live-agent resolution between agentFor paths
The live fast-path fence and the raced-collision catch duplicated the same subagent-ownership classification, tripping the duplication gate. Extract `fencedLiveAgent` so both paths resolve one live identity through the fence identically.
This commit is contained in:
@@ -1065,17 +1065,24 @@ export function createApiProxy(ctx: Context, defaults: ApiProxyDefaults): ApiPro
|
|||||||
return inspected
|
return inspected
|
||||||
}
|
}
|
||||||
|
|
||||||
async function agentFor(sessionId: SessionId): Promise<{ agent: Agent } | { error: RpcError }> {
|
/**
|
||||||
|
* Resolve one live registered identity through the subagent-ownership
|
||||||
|
* fence: subagent-owned agents answer `agent-busy`, plain agents pass.
|
||||||
|
* Fences the live agent's own session rather than trusting a
|
||||||
|
* "registered ⇒ attached-store" invariant — a registered subagent whose
|
||||||
|
* session is ever absent from the attached store must still not be handed
|
||||||
|
* out through generic Host routing. `undefined` means no live agent.
|
||||||
|
*/
|
||||||
|
function fencedLiveAgent(sessionId: SessionId): { agent: Agent } | { error: RpcError } | undefined {
|
||||||
const live = ctx.agents.get(sessionId)
|
const live = ctx.agents.get(sessionId)
|
||||||
if (live !== undefined) {
|
if (live === undefined) return undefined
|
||||||
// Fence the live agent's own session rather than trusting a
|
if (hasSubagentOwner(live.session, live)) return { error: subagentOwnershipError(sessionId) }
|
||||||
// "registered ⇒ attached-store" invariant: a registered subagent whose
|
return { agent: live }
|
||||||
// session is ever absent from the attached store must still not be
|
}
|
||||||
// handed out through generic Host routing (ensureSession's `.catch`
|
|
||||||
// already fences `live.session`; this is the same check on the fast path).
|
async function agentFor(sessionId: SessionId): Promise<{ agent: Agent } | { error: RpcError }> {
|
||||||
if (hasSubagentOwner(live.session, live)) return { error: subagentOwnershipError(sessionId) }
|
const fenced = fencedLiveAgent(sessionId)
|
||||||
return { agent: live }
|
if (fenced !== undefined) return fenced
|
||||||
}
|
|
||||||
const attached = ctx.sessions.get(sessionId)
|
const attached = ctx.sessions.get(sessionId)
|
||||||
if (attached !== undefined && hasSubagentOwner(attached, undefined)) {
|
if (attached !== undefined && hasSubagentOwner(attached, undefined)) {
|
||||||
return { error: subagentOwnershipError(sessionId) }
|
return { error: subagentOwnershipError(sessionId) }
|
||||||
@@ -1119,11 +1126,8 @@ export function createApiProxy(ctx: Context, defaults: ApiProxyDefaults): ApiPro
|
|||||||
// rejection falls through here. Mirror ensureSession's `.catch` in
|
// rejection falls through here. Mirror ensureSession's `.catch` in
|
||||||
// full: classify a subagent-owned winner into the stable ownership
|
// full: classify a subagent-owned winner into the stable ownership
|
||||||
// error, and hand a clean plain-agent winner straight back.
|
// error, and hand a clean plain-agent winner straight back.
|
||||||
const live = ctx.agents.get(sessionId)
|
const fenced = fencedLiveAgent(sessionId)
|
||||||
if (live !== undefined) {
|
if (fenced !== undefined) return fenced
|
||||||
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)) {
|
||||||
return { error: subagentOwnershipError(sessionId) }
|
return { error: subagentOwnershipError(sessionId) }
|
||||||
|
|||||||
Reference in New Issue
Block a user