Amp-Thread-ID: https://ampcode.com/threads/T-019bc4e0-fcb1-77be-b0b5-0d498f0c7197 Co-authored-by: Amp <amp@ampcode.com>
68 lines
2.0 KiB
TypeScript
68 lines
2.0 KiB
TypeScript
import type { ClawdbotConfig } from "../../config/config.js";
|
|
import type { RuntimeEnv } from "../../runtime.js";
|
|
import {
|
|
type ChannelId,
|
|
getChannelPlugin,
|
|
listChannelPlugins,
|
|
normalizeChannelId,
|
|
} from "./index.js";
|
|
import type { ChannelPairingAdapter } from "./types.js";
|
|
|
|
export function listPairingChannels(): ChannelId[] {
|
|
// Channel docking: pairing support is declared via plugin.pairing.
|
|
return listChannelPlugins()
|
|
.filter((plugin) => plugin.pairing)
|
|
.map((plugin) => plugin.id);
|
|
}
|
|
|
|
export function getPairingAdapter(channelId: ChannelId): ChannelPairingAdapter | null {
|
|
const plugin = getChannelPlugin(channelId);
|
|
return plugin?.pairing ?? null;
|
|
}
|
|
|
|
export function requirePairingAdapter(channelId: ChannelId): ChannelPairingAdapter {
|
|
const adapter = getPairingAdapter(channelId);
|
|
if (!adapter) {
|
|
throw new Error(`Channel ${channelId} does not support pairing`);
|
|
}
|
|
return adapter;
|
|
}
|
|
|
|
export function resolvePairingChannel(raw: unknown): ChannelId {
|
|
const value = (
|
|
typeof raw === "string"
|
|
? raw
|
|
: typeof raw === "number" || typeof raw === "boolean"
|
|
? String(raw)
|
|
: ""
|
|
)
|
|
.trim()
|
|
.toLowerCase();
|
|
const normalized = normalizeChannelId(value);
|
|
const channels = listPairingChannels();
|
|
if (!normalized || !channels.includes(normalized)) {
|
|
throw new Error(
|
|
`Invalid channel: ${value || "(empty)"} (expected one of: ${channels.join(", ")})`,
|
|
);
|
|
}
|
|
return normalized;
|
|
}
|
|
|
|
export async function notifyPairingApproved(params: {
|
|
channelId: ChannelId;
|
|
id: string;
|
|
cfg: ClawdbotConfig;
|
|
runtime?: RuntimeEnv;
|
|
/** Extension channels can pass their adapter directly to bypass registry lookup. */
|
|
pairingAdapter?: ChannelPairingAdapter;
|
|
}): Promise<void> {
|
|
// Extensions may provide adapter directly to bypass ESM module isolation
|
|
const adapter = params.pairingAdapter ?? requirePairingAdapter(params.channelId);
|
|
if (!adapter.notifyApproval) return;
|
|
await adapter.notifyApproval({
|
|
cfg: params.cfg,
|
|
id: params.id,
|
|
runtime: params.runtime,
|
|
});
|
|
}
|