mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 05:16:23 -06:00
87b56458a1
* feat(plugin-sdk): add in-process hook agent dispatch seam * feat(plugins): add imap inbound email trigger plugin * fix(imap): coalesce sweep wakeups and drop test-only gate exports * docs(imap): fix agents bindings command invocation * fix(gateway): guard optional bound context in plugin hook dispatch Post-rebase drift made resolveBoundGatewayContext possibly-undefined; the plugin hook dispatch path invoked it unconditionally. Use the optional-call guard consistent with sibling runtime accessors. * fix(imap): bump mailparser to 3.9.16 off vulnerable deepmerge-ts mailparser 3.9.15 pinned html-to-text@10.0.0 -> deepmerge-ts@7.1.6 (GHSA HIGH, stack exhaustion, <8.0.0). 3.9.16 pins html-to-text@10.0.1 -> deepmerge-ts@8.0.2, clearing the production audit gate. * refactor(gateway): extract plugin hooks runtime to keep server-plugins under max-lines The dispatchHookAgentTurn seam pushed server-plugins.ts to 702 effective lines (cap 700). Extract createGatewayHooksRuntime into the sibling runtime-helpers module, mirroring createGatewayNodesRuntime/createGatewaySubagentRuntime; no suppression added. * docs(secrets): register imap plugin password in secretref credential matrix The bundled imap plugin declares a secretInput (accounts.*.password); regenerate the user-supplied credentials matrix and surface list so the target-registry docs sync test stays green.
70 lines
2.3 KiB
TypeScript
70 lines
2.3 KiB
TypeScript
import {
|
|
definePluginEntry,
|
|
type OpenClawPluginApi,
|
|
type OpenClawPluginServiceContext,
|
|
} from "openclaw/plugin-sdk/plugin-entry";
|
|
import { resolveImapConfig } from "./src/config.js";
|
|
import { createImapState } from "./src/state.js";
|
|
import { ImapAccountWatcher } from "./src/watcher.js";
|
|
|
|
const imapConfigSchema = { parse: resolveImapConfig };
|
|
|
|
export default definePluginEntry({
|
|
id: "imap",
|
|
name: "IMAP email trigger",
|
|
description: "Dispatch authenticated incoming IMAP email to isolated agent sessions.",
|
|
configSchema: imapConfigSchema,
|
|
register(api: OpenClawPluginApi) {
|
|
if (api.registrationMode !== "full") {
|
|
return;
|
|
}
|
|
let generation = 0;
|
|
let watchers: ImapAccountWatcher[] = [];
|
|
api.registerService({
|
|
id: "imap-watch",
|
|
start(context: OpenClawPluginServiceContext) {
|
|
const previous = watchers;
|
|
const activeGeneration = ++generation;
|
|
watchers = [];
|
|
const start = async () => {
|
|
await Promise.all(previous.map((watcher) => watcher.stop()));
|
|
if (activeGeneration !== generation) {
|
|
return;
|
|
}
|
|
const config = imapConfigSchema.parse(api.pluginConfig, (accountId) => {
|
|
context.logger.warn(
|
|
`imap: account=${accountId} unavailable; resolve its IMAP password and reload configuration`,
|
|
);
|
|
});
|
|
const accounts = Object.entries(config.accounts);
|
|
if (!accounts.length) {
|
|
context.logger.warn(
|
|
"imap: no accounts configured; add plugins.entries.imap.config.accounts",
|
|
);
|
|
return;
|
|
}
|
|
const state = createImapState(api.runtime);
|
|
watchers = accounts.map(
|
|
([accountId, account]) =>
|
|
new ImapAccountWatcher({ accountId, account, runtime: api.runtime, state, context }),
|
|
);
|
|
for (const watcher of watchers) {
|
|
watcher.start();
|
|
}
|
|
};
|
|
void start().catch((error: unknown) => {
|
|
if (activeGeneration === generation) {
|
|
context.serviceHealth?.reportFailure(error);
|
|
}
|
|
});
|
|
},
|
|
async stop() {
|
|
generation++;
|
|
const active = watchers;
|
|
watchers = [];
|
|
await Promise.all(active.map((watcher) => watcher.stop()));
|
|
},
|
|
});
|
|
},
|
|
});
|