コンテンツにスキップ

Plugin SDK と Runtime のリファクタリング計画

開発を進めていると、コア機能と拡張機能の境界線が曖昧になり、コードが複雑に絡み合ってしまうことがあります。内部の変更が予期せぬ場所でエラーを引き起こし、メンテナンスが困難になるのは、多くの開発者が経験する悩みです。

現在のシステムでは、コネクタがコアの内部コードを直接参照していたり、独自のヘルパーが散在していたりするため、アップグレードが壊れやすく、外部プラグインの導入を妨げる要因となっています。これを解決するために、全てのメッセージングコネクタを独立したプラグインとして扱う新しいアーキテクチャへ移行します。

  • OpenClaw Core
  • TypeScript の基礎知識
  • Node.js 環境

新しい設計では、プラグインは src/** から直接インポートするのではなく、SDK または Runtime を介してのみコア機能にアクセスします。

コンパイル時に使用する安定した API として openclaw/plugin-sdk を使用します。ここには型定義や設定用のヘルパーが含まれます。

実行時の動作は、注入された OpenClawPluginApi.runtime を通じて操作します。

export type PluginRuntime = {
channel: {
text: {
chunkMarkdownText(text: string, limit: number): string[];
resolveTextChunkLimit(cfg: OpenClawConfig, channel: string, accountId?: string): number;
hasControlCommand(text: string, cfg: OpenClawConfig): boolean;
};
reply: {
dispatchReplyWithBufferedBlockDispatcher(params: {
ctx: unknown;
cfg: unknown;
dispatcherOptions: {
deliver: (payload: {
text?: string;
mediaUrls?: string[];
mediaUrl?: string;
}) => void | Promise\<void\>;
onError?: (err: unknown, info: { kind: string }) => void;
};
}): Promise\<void\>;
createReplyDispatcherWithTyping?: unknown; // adapter for Teams-style flows
};
routing: {
resolveAgentRoute(params: {
cfg: unknown;
channel: string;
accountId: string;
peer: { kind: RoutePeerKind; id: string };
}): { sessionKey: string; accountId: string };
};
pairing: {
buildPairingReply(params: { channel: string; idLine: string; code: string }): string;
readAllowFromStore(channel: string): Promise<string[]>;
upsertPairingRequest(params: {
channel: string;
id: string;
meta?: { name?: string };
}): Promise<{ code: string; created: boolean }>;
};
media: {
fetchRemoteMedia(params: { url: string }): Promise<{ buffer: Buffer; contentType?: string }>;
saveMediaBuffer(
buffer: Uint8Array,
contentType: string | undefined,
direction: "inbound" | "outbound",
maxBytes: number,
): Promise<{ path: string; contentType?: string }>;
};
mentions: {
buildMentionRegexes(cfg: OpenClawConfig, agentId?: string): RegExp[];
matchesMentionPatterns(text: string, regexes: RegExp[]): boolean;
};
groups: {
resolveGroupPolicy(
cfg: OpenClawConfig,
channel: string,
accountId: string,
groupId: string,
): {
allowlistEnabled: boolean;
allowed: boolean;
groupConfig?: unknown;
defaultConfig?: unknown;
};
resolveRequireMention(
cfg: OpenClawConfig,
channel: string,
accountId: string,
groupId: string,
override?: boolean,
): boolean;
};
debounce: {
createInboundDebouncer<T>(opts: {
debounceMs: number;
buildKey: (v: T) => string | null;
shouldDebounce: (v: T) => boolean;
onFlush: (entries: T[]) => Promise\<void\>;
onError?: (err: unknown) => void;
}): { push: (v: T) => void; flush: () => Promise\<void\> };
resolveInboundDebounceMs(cfg: OpenClawConfig, channel: string): number;
};
commands: {
resolveCommandAuthorizedFromAuthorizers(params: {
useAccessGroups: boolean;
authorizers: Array<{ configured: boolean; allowed: boolean }>;
}): boolean;
};
};
logging: {
shouldLogVerbose(): boolean;
getChildLogger(name: string): PluginLogger;
};
state: {
resolveStateDir(cfg: OpenClawConfig): string;
};
};

アップグレード時にコネクタが破損する

Section titled “アップグレード時にコネクタが破損する”

現在のコネクタがコアの内部構造に依存していることが原因です。SDK と Runtime の 2 層構造に移行することで、コアの変更からプラグインを保護します。

コアのソースコードにアクセスせずにプラグインを開発できない現状があります。openclaw/plugin-sdk を公開し、Semver によるバージョン管理を行うことで、外部からの開発を可能にします。

質問がある場合や、セットアップで困ったときは AI Setup Assistant を活用してください。

OpenClaw

OpenClaw Expert

まだ解決しませんか?

このページで解決しない場合は、OpenClaw Expertに直接質問してください。