Răsfoiți Sursa

fix(host): fence the agentFor live fast path on the agent's own session

`agentFor` fenced subagent ownership through the attached session store
(`ctx.sessions.get`) and only then returned a live registered agent. A
registered agent whose session is ever absent from the attached store —
an invariant nothing in this package guarantees — would therefore be
handed out through generic Host routing unfenced, bypassing subagent
delivery entirely.

Fence `live.session` directly whenever a live agent exists, and keep the
attached-store check only for the not-live durable classification.
`ensureSession`'s race `.catch` already fences `live.session`; this makes
the fast path the same check instead of an asymmetric weaker one.
Tianyi Cui 2 luni în urmă
părinte
comite
56e252bed3
1 a modificat fișierele cu 13 adăugiri și 0 ștergeri
  1. 13 0
      packages/host/apiproxy/src/api-proxy.ts

+ 13 - 0
packages/host/apiproxy/src/api-proxy.ts

@@ -1106,6 +1106,19 @@ export function createApiProxy(ctx: Context, defaults: ApiProxyDefaults): ApiPro
       if (error instanceof SubagentSessionOwnership) {
         return { error: subagentOwnershipError(error.sessionId) }
       }
+      // A concurrent parent `enter()` can win the identity between the
+      // pre-resume published re-check and `ctx.agents.resume` publication;
+      // the ID-collision rejection falls through here. Re-classify that
+      // raced published winner into the stable ownership error, mirroring
+      // ensureSession's `.catch`.
+      const live = ctx.agents.get(sessionId)
+      if (live !== undefined && hasSubagentOwner(live.session, live)) {
+        return { error: subagentOwnershipError(sessionId) }
+      }
+      const attached = ctx.sessions.get(sessionId)
+      if (attached !== undefined && hasSubagentOwner(attached, undefined)) {
+        return { error: subagentOwnershipError(sessionId) }
+      }
       // The internal details slot is contractually {}; the reason rides the message.
       return { error: { code: 'internal', message: `resume failed for session "${sessionId}": ${String(error)}`, details: {} } }
     }