fix: read canonical ACP metadata for deleted-agent guard

This commit is contained in:
Shakker
2026-06-09 18:50:55 +01:00
committed by Shakker
parent b502a92bf1
commit a93bc61a84
3 changed files with 25 additions and 16 deletions
+1 -1
View File
@@ -842,7 +842,7 @@ describe("gateway session utils", () => {
state: "idle",
lastActivityAt: 1,
},
}) as Pick<SessionEntry, "acp">;
}) as SessionEntry;
const claudeKey = "agent:claude:acp:11111111-1111-4111-8111-111111111111";
const cursorKey = "agent:cursor:acp:22222222-2222-4222-8222-222222222222";
expect(
+11 -7
View File
@@ -9,7 +9,7 @@ import {
} from "@openclaw/normalization-core/string-coerce";
import { uniqueStrings } from "@openclaw/normalization-core/string-normalization";
import type { SessionsListParams } from "../../packages/gateway-protocol/src/index.js";
import { readAcpSessionMeta } from "../acp/runtime/session-meta.js";
import { readAcpSessionMeta, readAcpSessionMetaForEntry } from "../acp/runtime/session-meta.js";
import { resolveModelAgentRuntimeMetadata } from "../agents/agent-runtime-metadata.js";
import {
listAgentIds,
@@ -922,17 +922,21 @@ function resolveTranscriptUsageFallback(params: {
export function resolveDeletedAgentIdFromSessionKey(
cfg: OpenClawConfig,
sessionKey: string,
entry?: Pick<SessionEntry, "acp"> | null,
entry?: SessionEntry | null,
): string | null {
const parsed = parseAgentSessionKey(sessionKey);
if (!parsed) {
return null;
}
// Free ACP runtime keys use agent:<harnessId>:acp:<uuid>, but key shape is
// not proof: ACP bridge sessions can use ACP-shaped keys without SessionAcpMeta.
// Configured acp:binding keys stay owner-scoped even when ACP metadata exists.
if (isAcpSessionKey(sessionKey) && !parsed.rest.startsWith("acp:binding:") && entry?.acp) {
return null;
if (isAcpSessionKey(sessionKey) && !parsed.rest.startsWith("acp:binding:")) {
// Free ACP runtime keys use agent:<harnessId>:acp:<uuid>, but key shape is
// not proof: ACP bridge sessions can use ACP-shaped keys without SessionAcpMeta.
// Configured acp:binding keys stay owner-scoped even when ACP metadata exists.
const acpMeta =
entry?.acp ?? readAcpSessionMetaForEntry({ sessionKey, entry: entry ?? undefined });
if (acpMeta) {
return null;
}
}
const agentId = normalizeAgentId(parsed.agentId);
if (listAgentIds(cfg).includes(agentId)) {
+13 -8
View File
@@ -4,6 +4,7 @@
import path from "node:path";
import { describe, expect, it } from "vitest";
import { ErrorCodes } from "../../packages/gateway-protocol/src/index.js";
import { writeAcpSessionMetaForMigration } from "../acp/runtime/session-meta.js";
import { resolveStorePath, saveSessionStore } from "../config/sessions.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { withStateDirEnv } from "../test-helpers/state-dir-env.js";
@@ -222,14 +223,18 @@ describe("resolveSessionKeyFromResolveParams store canonicalization", () => {
sessionId: "sess-acp-harness",
label: "claude-delegate",
updatedAt: freshUpdatedAt(),
acp: {
backend: "acpx",
agent: "claude",
runtimeSessionName: acpKey,
mode: "oneshot",
state: "idle",
lastActivityAt: freshUpdatedAt(),
},
},
});
writeAcpSessionMetaForMigration({
sessionKey: acpKey,
sessionId: "sess-acp-harness",
meta: {
backend: "acpx",
agent: "claude",
runtimeSessionName: acpKey,
mode: "oneshot",
state: "idle",
lastActivityAt: freshUpdatedAt(),
},
});