import { beforeEach, describe, expect, it, vi } from "vitest" ;
import {
__testing,
registerSessionBindingAdapter,
type SessionBindingAdapter,
type SessionBindingRecord,
} from "../../infra/outbound/session-binding-service.js" ;
import type { ResolvedAgentRoute } from "../../routing/resolve-route.js" ;
import { resolveRuntimeConversationBindingRoute } from "./binding-routing.js" ;
function createRoute(): ResolvedAgentRoute {
return {
agentId: "main" ,
channel: "demo" ,
accountId: "default" ,
sessionKey: "agent:main:main" ,
mainSessionKey: "agent:main:main" ,
lastRoutePolicy: "main" ,
matchedBy: "default" ,
};
}
function createBinding(overrides?: Partial<SessionBindingRecord>): SessionBindingRecord {
return {
bindingId: "binding-1" ,
targetSessionKey: "agent:review:acp:session-1" ,
targetKind: "session" ,
conversation: {
channel: "demo" ,
accountId: "default" ,
conversationId: "room-1" ,
},
status: "active" ,
boundAt: 1 ,
...overrides,
};
}
function registerAdapter(record: SessionBindingRecord | null ): {
resolveByConversation: ReturnType<typeof vi.fn>;
touch: ReturnType<typeof vi.fn>;
} {
const resolveByConversation = vi.fn<SessionBindingAdapter["resolveByConversation" ]>(() => record);
const touch = vi.fn<NonNullable<SessionBindingAdapter["touch" ]>>();
registerSessionBindingAdapter({
channel: "demo" ,
accountId: "default" ,
listBySession: () => [],
resolveByConversation,
touch,
});
return { resolveByConversation, touch };
}
describe("runtime conversation binding route" , () => {
beforeEach(() => {
__testing.resetSessionBindingAdaptersForTests();
});
it("rewrites the route to a runtime-bound ACP session and touches the binding" , () => {
const binding = createBinding();
const { resolveByConversation, touch } = registerAdapter(binding);
const result = resolveRuntimeConversationBindingRoute({
route: createRoute(),
conversation: {
channel: "demo" ,
accountId: "default" ,
conversationId: "room-1" ,
},
});
expect(resolveByConversation).toHaveBeenCalledWith({
channel: "demo" ,
accountId: "default" ,
conversationId: "room-1" ,
});
expect(touch).toHaveBeenCalledWith("binding-1" , undefined);
expect(result.boundSessionKey).toBe("agent:review:acp:session-1" );
expect(result.boundAgentId).toBe("review" );
expect(result.route).toMatchObject({
agentId: "review" ,
sessionKey: "agent:review:acp:session-1" ,
lastRoutePolicy: "session" ,
matchedBy: "binding.channel" ,
});
});
it("touches plugin-owned bindings without rewriting the channel route" , () => {
const route = createRoute();
const binding = createBinding({
metadata: {
pluginBindingOwner: "plugin" ,
pluginId: "demo-plugin" ,
pluginRoot: "/tmp/demo-plugin" ,
},
});
const { touch } = registerAdapter(binding);
const result = resolveRuntimeConversationBindingRoute({
route,
conversation: {
channel: "demo" ,
accountId: "default" ,
conversationId: "room-1" ,
},
});
expect(touch).toHaveBeenCalledWith("binding-1" , undefined);
expect(result.bindingRecord).toBe(binding);
expect(result.boundSessionKey).toBeUndefined();
expect(result.route).toBe(route);
});
});
Messung V0.5 in Prozent C=92 H=97 G=94
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-07)
¤
*© Formatika GbR, Deutschland