mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-07 20:42:55 +00:00
* refactor: centralize inbound supplemental context * refactor: trim supplemental finalizer typing * docs: clarify supplemental context projection * refactor: move inbound finalization into core * refactor: simplify channel inbound facts * refactor: fold supplemental media into inbound finalizer * refactor: migrate channel inbound callers to builder * docs: mark inbound finalizer compat types deprecated * refactor: wire runtime turn context builder * refactor: replace channel turn runtime API * fix: respect discord quote visibility * fix: avoid deprecated line dispatch helper * refactor: deprecate channel message SDK seams * docs: trim channel outbound SDK page * test: migrate irc inbound assertion * refactor: deprecate outbound SDK facades * refactor: deprecate channel helper SDK facades * refactor: deprecate channel streaming SDK facade * refactor: move direct dm helpers into inbound SDK * chore: mark legacy test-utils SDK alias deprecated * refactor: remove unused allow-from read helper * refactor: route remaining channel dispatch through core * refactor: enforce modern extension SDK imports * test: give slow image root tests more time * ci: support node fallback on windows * fix: add transcripts tool display metadata * refactor: trim legacy channel test seams * fix: preserve channel compat after rebase * fix: keep deprecated channel inbound aliases * fix: preserve discord thread context visibility * fix: clean final rebase conflicts * fix: preserve channel message dispatch aliases * fix: sync channel refactor after rebase * fix: sync channel refactor after latest main * fix: dedupe memory-core subagent mock * test: align clickclack inbound dispatch assertions * fix: sync plugin sdk api hash after rebase * fix: sync channel refactor after latest main * fix: sync plugin sdk api hash after rebase * fix: sync plugin sdk api hash after latest main * test: remove stale inbound context awaits
126 lines
3.9 KiB
TypeScript
126 lines
3.9 KiB
TypeScript
import {
|
|
buildMentionRegexes,
|
|
implicitMentionKindWhen,
|
|
matchesMentionPatterns,
|
|
matchesMentionWithExplicit,
|
|
resolveInboundMentionDecision,
|
|
} from "openclaw/plugin-sdk/channel-inbound";
|
|
import type { PluginRuntime } from "openclaw/plugin-sdk/runtime-store";
|
|
|
|
type SessionRecord = {
|
|
sessionKey: string;
|
|
body: string;
|
|
};
|
|
|
|
export function createQaRunnerRuntime(): PluginRuntime {
|
|
const sessions = new Map<string, SessionRecord>();
|
|
return {
|
|
channel: {
|
|
routing: {
|
|
resolveAgentRoute({
|
|
accountId,
|
|
peer,
|
|
}: {
|
|
accountId?: string | null;
|
|
peer?: { kind?: string; id?: string } | null;
|
|
}) {
|
|
return {
|
|
agentId: "qa-agent",
|
|
accountId: accountId ?? "default",
|
|
sessionKey: `qa-agent:${peer?.kind ?? "direct"}:${peer?.id ?? "default"}`,
|
|
mainSessionKey: "qa-agent:main",
|
|
lastRoutePolicy: "session",
|
|
matchedBy: "default",
|
|
channel: "qa-channel",
|
|
};
|
|
},
|
|
},
|
|
session: {
|
|
resolveStorePath(_store: string | undefined, { agentId }: { agentId: string }) {
|
|
return agentId;
|
|
},
|
|
readSessionUpdatedAt({ sessionKey }: { sessionKey: string }) {
|
|
return sessions.has(sessionKey) ? Date.now() : undefined;
|
|
},
|
|
recordInboundSession({
|
|
sessionKey,
|
|
ctx,
|
|
}: {
|
|
sessionKey: string;
|
|
ctx: { BodyForAgent?: string; Body?: string };
|
|
}) {
|
|
sessions.set(sessionKey, {
|
|
sessionKey,
|
|
body: ctx.BodyForAgent ?? ctx.Body ?? "",
|
|
});
|
|
},
|
|
},
|
|
mentions: {
|
|
buildMentionRegexes,
|
|
matchesMentionPatterns,
|
|
matchesMentionWithExplicit,
|
|
implicitMentionKindWhen,
|
|
resolveInboundMentionDecision,
|
|
},
|
|
reply: {
|
|
resolveEnvelopeFormatOptions() {
|
|
return {};
|
|
},
|
|
formatAgentEnvelope({ body }: { body: string }) {
|
|
return body;
|
|
},
|
|
finalizeInboundContext(ctx: Record<string, unknown>) {
|
|
return ctx as typeof ctx & { CommandAuthorized: boolean };
|
|
},
|
|
async dispatchReplyWithBufferedBlockDispatcher({
|
|
ctx,
|
|
dispatcherOptions,
|
|
}: {
|
|
ctx: { BodyForAgent?: string; Body?: string };
|
|
dispatcherOptions: { deliver: (payload: { text: string }) => Promise<void> };
|
|
}) {
|
|
await dispatcherOptions.deliver({
|
|
text: `qa-echo: ${ctx.BodyForAgent ?? ctx.Body ?? ""}`,
|
|
});
|
|
},
|
|
},
|
|
inbound: {
|
|
async dispatchReply(
|
|
params: Parameters<PluginRuntime["channel"]["inbound"]["dispatchReply"]>[0],
|
|
) {
|
|
const sessionKey =
|
|
typeof params.ctxPayload.SessionKey === "string"
|
|
? params.ctxPayload.SessionKey
|
|
: params.routeSessionKey;
|
|
await params.recordInboundSession({
|
|
storePath: params.storePath,
|
|
sessionKey,
|
|
ctx: params.ctxPayload,
|
|
onRecordError: params.record?.onRecordError ?? (() => undefined),
|
|
});
|
|
const dispatchResult = await params.dispatchReplyWithBufferedBlockDispatcher({
|
|
ctx: params.ctxPayload,
|
|
cfg: params.cfg,
|
|
dispatcherOptions: {
|
|
...params.dispatcherOptions,
|
|
deliver: async (payload, info) => {
|
|
await params.delivery.deliver(payload, info);
|
|
},
|
|
onError: params.delivery.onError,
|
|
},
|
|
replyOptions: params.replyOptions,
|
|
replyResolver: params.replyResolver,
|
|
});
|
|
return {
|
|
admission: params.admission ?? { kind: "dispatch" },
|
|
dispatched: true,
|
|
ctxPayload: params.ctxPayload,
|
|
routeSessionKey: params.routeSessionKey,
|
|
dispatchResult,
|
|
};
|
|
},
|
|
},
|
|
},
|
|
} as unknown as PluginRuntime;
|
|
}
|