diff --git a/docs/.generated/plugin-sdk-api-baseline.sha256 b/docs/.generated/plugin-sdk-api-baseline.sha256 index 26fd1bcf83c..273b5e4ee9e 100644 --- a/docs/.generated/plugin-sdk-api-baseline.sha256 +++ b/docs/.generated/plugin-sdk-api-baseline.sha256 @@ -1,2 +1,2 @@ -5b59db88172a184e0cbac3301c51304686b6184c952ae5ed9f09b001dd65e3f3 plugin-sdk-api-baseline.json -a195e76ddd1e09cb4023b247a684cd4e93c2662971adb4378ec126a78c537582 plugin-sdk-api-baseline.jsonl +1fb6adb8edadd5ec27c0c4866478f6919bc33ce38816d28f3548fc7cac9dacb9 plugin-sdk-api-baseline.json +0840e1f2a59b8b660f58ab1810dc333b6b535e3235fdbb377da6f1e913fb1a87 plugin-sdk-api-baseline.jsonl diff --git a/docs/plugins/sdk-subpaths.md b/docs/plugins/sdk-subpaths.md index bbd13571cbb..63ee84e7cd6 100644 --- a/docs/plugins/sdk-subpaths.md +++ b/docs/plugins/sdk-subpaths.md @@ -71,7 +71,7 @@ For the plugin authoring guide, see [Plugin SDK overview](/plugins/sdk-overview) | `plugin-sdk/interactive-runtime` | Semantic message presentation, delivery, and legacy interactive reply helpers. See [Message Presentation](/plugins/message-presentation) | | `plugin-sdk/channel-inbound` | Compatibility barrel for inbound debounce, mention matching, mention-policy helpers, and envelope helpers | | `plugin-sdk/channel-inbound-debounce` | Narrow inbound debounce helpers | - | `plugin-sdk/channel-mention-gating` | Narrow mention-policy and mention text helpers without the broader inbound runtime surface | + | `plugin-sdk/channel-mention-gating` | Narrow mention-policy, mention marker, and mention text helpers without the broader inbound runtime surface | | `plugin-sdk/channel-envelope` | Narrow inbound envelope formatting helpers | | `plugin-sdk/channel-location` | Channel location context and formatting helpers | | `plugin-sdk/channel-logging` | Channel logging helpers for inbound drops and typing/ack failures | @@ -170,7 +170,7 @@ For the plugin authoring guide, see [Plugin SDK overview](/plugins/sdk-overview) | `plugin-sdk/approval-runtime` | Exec/plugin approval helpers, approval-capability builders, auth/profile helpers, native routing/runtime helpers, and structured approval display path formatting | | `plugin-sdk/reply-runtime` | Shared inbound/reply runtime helpers, chunking, dispatch, heartbeat, reply planner | | `plugin-sdk/reply-dispatch-runtime` | Narrow reply dispatch/finalize and conversation-label helpers | - | `plugin-sdk/reply-history` | Shared short-window reply-history helpers such as `buildHistoryContext`, `recordPendingHistoryEntry`, and `clearHistoryEntriesIfEnabled` | + | `plugin-sdk/reply-history` | Shared short-window reply-history helpers and markers such as `buildHistoryContext`, `HISTORY_CONTEXT_MARKER`, `recordPendingHistoryEntry`, and `clearHistoryEntriesIfEnabled` | | `plugin-sdk/reply-reference` | `createReplyReferencePlanner` | | `plugin-sdk/reply-chunking` | Narrow text/markdown chunking helpers | | `plugin-sdk/session-store-runtime` | Session store path, session-key, updated-at, and store mutation helpers | @@ -257,7 +257,7 @@ For the plugin authoring guide, see [Plugin SDK overview](/plugins/sdk-overview) | `plugin-sdk/webhook-path` | Webhook path normalization helpers | | `plugin-sdk/web-media` | Shared remote/local media loading helpers | | `plugin-sdk/zod` | Re-exported `zod` for plugin SDK consumers | - | `plugin-sdk/testing` | Public extension test helpers including plugin registry/runtime mocks, schema/media/live-test helpers, `installCommonResolveTargetErrorCases`, `writeSkill`, `createTestRegistry`, and live generation env loading | + | `plugin-sdk/testing` | Public extension test helpers including plugin registry/runtime mocks, schema/media/live-test helpers, `installCommonResolveTargetErrorCases`, `writeSkill`, `createTestRegistry`, and live generation env loading. Extension `*.test-support.ts` helpers stay on this or focused SDK subpaths, not core internals | diff --git a/scripts/check-no-extension-test-core-imports.ts b/scripts/check-no-extension-test-core-imports.ts index 898f16bb980..63fe83f6672 100644 --- a/scripts/check-no-extension-test-core-imports.ts +++ b/scripts/check-no-extension-test-core-imports.ts @@ -36,6 +36,7 @@ const FORBIDDEN_PATTERNS: Array<{ pattern: RegExp; hint: string }> = [ ]; const STATIC_RELATIVE_MODULE_PATTERN = /\b(?:import|export)\b[\s\S]*?\bfrom\s*["']([^"']+)["']/g; +const DYNAMIC_RELATIVE_MODULE_PATTERN = /\bimport\s*\(\s*["']([^"']+)["']\s*\)/g; const RELATIVE_CORE_HINT = "Use openclaw/plugin-sdk/testing or a focused plugin-sdk test/runtime subpath instead of core internals."; @@ -45,7 +46,11 @@ function isExtensionTestFile(filePath: string): boolean { } function isExtensionTestSupportFile(filePath: string): boolean { - return /(?:^|[/\\])test-support(?:[/\\]|$)/u.test(filePath) && /\.[cm]?[jt]sx?$/u.test(filePath); + return ( + (/(?:^|[/\\])test-support(?:[/\\]|$)/u.test(filePath) || + /(?:\.|-|_)test-support\.[cm]?[jt]sx?$/u.test(filePath)) && + /\.[cm]?[jt]sx?$/u.test(filePath) + ); } function collectExtensionTestFiles(rootDir: string): string[] { @@ -74,9 +79,17 @@ function resolvesToRepoSrc(filePath: string, specifier: string): boolean { return repoRelative === "src" || repoRelative.startsWith("src/"); } -function collectRelativeCoreImportOffenders(filePath: string, content: string): Offender[] { +function collectRelativeCoreImportOffenders( + filePath: string, + content: string, + opts: { includeDynamic: boolean }, +): Offender[] { const offenders: Offender[] = []; - for (const match of content.matchAll(STATIC_RELATIVE_MODULE_PATTERN)) { + const matches = [ + ...content.matchAll(STATIC_RELATIVE_MODULE_PATTERN), + ...(opts.includeDynamic ? [...content.matchAll(DYNAMIC_RELATIVE_MODULE_PATTERN)] : []), + ]; + for (const match of matches) { const specifier = match[1]; if (!specifier || !resolvesToRepoSrc(filePath, specifier)) { continue; @@ -105,7 +118,11 @@ function main() { offenders.push({ file, hint: rule.hint }); break; } - offenders.push(...collectRelativeCoreImportOffenders(file, content)); + offenders.push( + ...collectRelativeCoreImportOffenders(file, content, { + includeDynamic: true, + }), + ); } if (offenders.length > 0) { diff --git a/src/plugin-sdk/channel-mention-gating.ts b/src/plugin-sdk/channel-mention-gating.ts index dff01d0d421..8c85e70da5a 100644 --- a/src/plugin-sdk/channel-mention-gating.ts +++ b/src/plugin-sdk/channel-mention-gating.ts @@ -19,4 +19,8 @@ export { // @deprecated Prefer `resolveInboundMentionDecision({ facts, policy })`. resolveMentionGatingWithBypass, } from "../channels/mention-gating.js"; -export { buildMentionRegexes, normalizeMentionText } from "../auto-reply/reply/mentions.js"; +export { + CURRENT_MESSAGE_MARKER, + buildMentionRegexes, + normalizeMentionText, +} from "../auto-reply/reply/mentions.js"; diff --git a/src/plugin-sdk/native-command-registry.ts b/src/plugin-sdk/native-command-registry.ts index 663d5ffd232..05de39bdc66 100644 --- a/src/plugin-sdk/native-command-registry.ts +++ b/src/plugin-sdk/native-command-registry.ts @@ -3,6 +3,7 @@ export { findCommandByNativeName, formatCommandArgMenuTitle, listChatCommands, + listNativeCommandSpecs, listNativeCommandSpecsForConfig, parseCommandArgs, resolveCommandArgChoices, diff --git a/src/plugin-sdk/proxy-capture.ts b/src/plugin-sdk/proxy-capture.ts index f2f2dc2bde5..4e37dd68371 100644 --- a/src/plugin-sdk/proxy-capture.ts +++ b/src/plugin-sdk/proxy-capture.ts @@ -12,6 +12,8 @@ export { export { captureHttpExchange, captureWsEvent, + finalizeDebugProxyCapture, + initializeDebugProxyCapture, isDebugProxyGlobalFetchPatchInstalled, } from "../proxy-capture/runtime.js"; export type { diff --git a/src/plugin-sdk/reply-history.ts b/src/plugin-sdk/reply-history.ts index d327b767a99..c811d455098 100644 --- a/src/plugin-sdk/reply-history.ts +++ b/src/plugin-sdk/reply-history.ts @@ -2,6 +2,7 @@ export type { HistoryEntry } from "../auto-reply/reply/history.js"; export { DEFAULT_GROUP_HISTORY_LIMIT, + HISTORY_CONTEXT_MARKER, buildHistoryContext, buildHistoryContextFromEntries, buildHistoryContextFromMap,