refactor: remove channel turn runtime aliases

This commit is contained in:
Peter Steinberger
2026-05-27 11:37:10 +01:00
parent 83ab0ba99f
commit 6c3740255f
10 changed files with 20 additions and 106 deletions
+2 -2
View File
@@ -694,8 +694,8 @@ channel-owned dispatcher
-> messages.send for final delivery
```
The old `channel.turn` runtime surface remains a deprecated alias only. New code
uses inbound/message nouns.
The old `channel.turn` runtime surface was removed. Runtime callers use
`channel.inbound.*`; channel docs and SDK subpaths use inbound/message nouns.
## Compatibility guardrails
+7 -11
View File
@@ -57,18 +57,14 @@ prefer message adapters and durable message helpers.
## Migration
- `runtime.channel.turn.run(...)` -> `runtime.channel.inbound.run(...)`
- `runtime.channel.turn.runPrepared(...)` ->
`runtime.channel.inbound.runPreparedReply(...)`
- `runtime.channel.turn.runAssembled(...)` ->
`runtime.channel.inbound.dispatchReply(...)`
- `runtime.channel.turn.buildContext(...)` ->
`runtime.channel.inbound.buildContext(...)`
The old `runtime.channel.turn.*` runtime aliases were removed. Use:
- `runtime.channel.inbound.run(...)` for raw inbound events.
- `runtime.channel.inbound.dispatchReply(...)` for assembled reply contexts.
- `runtime.channel.inbound.buildContext(...)` for inbound context payloads.
- `runtime.channel.inbound.runPreparedReply(...)` only for channel-owned prepared
dispatch paths that already assemble their own dispatch closure.
New plugin code should not introduce `turn`-named channel APIs. Keep model or
agent turn vocabulary inside agent/provider code; channel plugins use inbound,
message, delivery, and reply terms.
The `runtime.channel.turn.*` aliases remain only as deprecated compatibility
for already published plugins. They can be removed in the next major SDK cleanup
after external plugins have had a migration window.
+2 -4
View File
@@ -5,7 +5,5 @@ title: "Channel turn"
This page moved to [Channel inbound API](/plugins/sdk-channel-inbound).
The old channel-turn runtime names remain deprecated compatibility only. New
plugin code should use `runtime.channel.inbound.*`, `channel-inbound`, and
`channel-outbound`; the aliases can be removed in the next major SDK cleanup
after external plugin migration.
The old channel-turn runtime aliases were removed. Plugin code should use
`runtime.channel.inbound.*`, `channel-inbound`, and `channel-outbound`.
+1 -1
View File
@@ -132,7 +132,7 @@ migration window, keep repo/bundled plugins on `channel-inbound` and
`channel-outbound`, then remove the compatibility subpaths in the next major
SDK cleanup. This applies to the old channel message/runtime, channel
streaming, direct-DM access, inbound helper splinter, reply-options,
pairing-path, and runtime `channel.turn.*` families.
and pairing-path families.
<Accordion title="Provider subpaths">
| Subpath | Key exports |
-20
View File
@@ -51,7 +51,6 @@ import type {
PreparedChannelTurn,
PreflightFacts,
RunChannelTurnParams,
RunResolvedChannelTurnParams,
} from "./types.js";
export { createChannelDeliveryResultFromReceipt } from "./delivery-result.js";
export {
@@ -88,7 +87,6 @@ export type {
ReplyPlanFacts,
RouteFacts,
RunChannelTurnParams,
RunResolvedChannelTurnParams,
SenderFacts,
SupplementalContextFacts,
} from "./types.js";
@@ -764,21 +762,3 @@ export async function runChannelTurn<
}
export const runChannelInboundEvent = runChannelTurn;
export async function runResolvedChannelTurn<
TRaw,
TDispatchResult = DispatchedChannelTurnResult["dispatchResult"],
>(
params: RunResolvedChannelTurnParams<TRaw, TDispatchResult>,
): Promise<ChannelTurnResult<TDispatchResult>> {
return await runChannelTurn({
channel: params.channel,
accountId: params.accountId,
raw: params.raw,
log: params.log,
adapter: {
ingest: (raw) => (typeof params.input === "function" ? params.input(raw) : params.input),
resolveTurn: params.resolveTurn,
},
});
}
-15
View File
@@ -457,18 +457,3 @@ export type RunChannelTurnParams<TRaw, TDispatchResult = DispatchFromConfigResul
adapter: ChannelTurnAdapter<TRaw, TDispatchResult>;
log?: (event: ChannelTurnLogEvent) => void;
};
export type RunResolvedChannelTurnParams<TRaw, TDispatchResult = DispatchFromConfigResult> = {
channel: string;
accountId?: string;
raw: TRaw;
input:
| NormalizedTurnInput
| ((raw: TRaw) => Promise<NormalizedTurnInput | null> | NormalizedTurnInput | null);
resolveTurn: (
input: NormalizedTurnInput,
eventClass: ChannelEventClass,
preflight: PreflightFacts,
) => Promise<ChannelTurnResolved<TDispatchResult>> | ChannelTurnResolved<TDispatchResult>;
log?: (event: ChannelTurnLogEvent) => void;
};
@@ -14,15 +14,11 @@ describe("createPluginRuntimeMock", () => {
expect(vi.isMockFunction(debouncer.cancelKey)).toBe(true);
});
it("keeps deprecated turn runtime aliases aligned with inbound mocks", async () => {
it("exposes channel inbound helpers without the removed turn aliases", async () => {
const runtime = createPluginRuntimeMock();
const channel = "test";
expect(runtime.channel.turn.run).toBe(runtime.channel.inbound.run);
expect(runtime.channel.turn.runAssembled).toBe(runtime.channel.inbound.dispatchReply);
expect(runtime.channel.turn.buildContext).toBe(runtime.channel.inbound.buildContext);
expect(runtime.channel.turn.runPrepared).toBe(runtime.channel.inbound.runPreparedReply);
expect(runtime.channel.turn.dispatchAssembled).toBe(runtime.channel.inbound.dispatchReply);
expect("turn" in runtime.channel).toBe(false);
const input = vi.fn((raw: { id: string }) => ({
id: raw.id,
@@ -45,11 +41,13 @@ describe("createPluginRuntimeMock", () => {
runDispatch,
}));
const result = await runtime.channel.turn.runResolved({
const result = await runtime.channel.inbound.run({
channel,
raw: { id: "m1" },
input,
resolveTurn,
adapter: {
ingest: input,
resolveTurn,
},
});
expect(input).toHaveBeenCalledWith({ id: "m1" });
@@ -76,7 +74,7 @@ describe("createPluginRuntimeMock", () => {
it("routes untrusted group prompt facts into untrusted structured context", () => {
const runtime = createPluginRuntimeMock();
const ctx = runtime.channel.turn.buildContext({
const ctx = runtime.channel.inbound.buildContext({
channel: "test",
from: "test:user:u1",
sender: { id: "u1" },
@@ -727,29 +727,6 @@ export function createPluginRuntimeMock(overrides: DeepPartial<PluginRuntime> =
buildContext: buildChannelInboundEventContextMock,
runPreparedReply: runPreparedChannelTurnMock,
},
turn: {
run: runChannelTurnMock,
runAssembled:
dispatchAssembledChannelTurnMock as unknown as PluginRuntime["channel"]["turn"]["runAssembled"],
runResolved: vi.fn(
async (params: Parameters<PluginRuntime["channel"]["turn"]["runResolved"]>[0]) =>
await runChannelTurnMock({
channel: params.channel,
accountId: params.accountId,
raw: params.raw,
log: params.log,
adapter: {
ingest: (raw) =>
typeof params.input === "function" ? params.input(raw) : params.input,
resolveTurn: params.resolveTurn,
},
}),
) as unknown as PluginRuntime["channel"]["turn"]["runResolved"],
buildContext: buildChannelInboundEventContextMock,
runPrepared: runPreparedChannelTurnMock,
dispatchAssembled:
dispatchAssembledChannelTurnMock as unknown as PluginRuntime["channel"]["turn"]["dispatchAssembled"],
},
threadBindings: {
setIdleTimeoutBySessionKey:
vi.fn() as unknown as PluginRuntime["channel"]["threadBindings"]["setIdleTimeoutBySessionKey"],
-9
View File
@@ -55,7 +55,6 @@ import {
dispatchChannelInboundReply,
runChannelInboundEvent,
runPreparedInboundReply,
runResolvedChannelTurn,
} from "../../channels/turn/kernel.js";
import {
resolveChannelGroupPolicy,
@@ -186,14 +185,6 @@ export function createRuntimeChannel(): PluginRuntime["channel"] {
runPreparedReply: runPreparedInboundReply,
dispatchReply: dispatchChannelInboundReply,
},
turn: {
run: runChannelInboundEvent,
runAssembled: dispatchChannelInboundReply,
runResolved: runResolvedChannelTurn,
buildContext: buildChannelInboundEventContext,
runPrepared: runPreparedInboundReply,
dispatchAssembled: dispatchChannelInboundReply,
},
threadBindings: {
setIdleTimeoutBySessionKey: ({ channelId, targetSessionKey, accountId, idleTimeoutMs }) =>
setChannelConversationBindingIdleTimeoutBySessionKey({
-11
View File
@@ -184,17 +184,6 @@ export type PluginRuntimeChannel = {
runPreparedReply: typeof import("../../channels/turn/kernel.js").runPreparedInboundReply;
dispatchReply: typeof import("../../channels/turn/kernel.js").dispatchChannelInboundReply;
};
/** @deprecated Use `inbound`. */
turn: {
run: typeof import("../../channels/turn/kernel.js").runChannelInboundEvent;
runAssembled: typeof import("../../channels/turn/kernel.js").dispatchChannelInboundReply;
/** @deprecated Prefer `inbound.run(...)`. */
runResolved: typeof import("../../channels/turn/kernel.js").runResolvedChannelTurn;
buildContext: typeof import("../../channels/inbound-event/context.js").buildChannelInboundEventContext;
runPrepared: typeof import("../../channels/turn/kernel.js").runPreparedInboundReply;
/** @deprecated Prefer `inbound.dispatchReply(...)`. */
dispatchAssembled: typeof import("../../channels/turn/kernel.js").dispatchChannelInboundReply;
};
threadBindings: {
setIdleTimeoutBySessionKey: (params: {
channelId: string;