From 8a3f5c862b5658ea5d881517c5c90151b40a971f Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Thu, 30 Jul 2026 18:20:07 +0800 Subject: [PATCH] fix(plugin-sdk): ship documented public typings (#116345) * fix(plugin-sdk): ship documented public typings * fix(plugin-sdk): refresh public contract artifacts --- .../.generated/plugin-sdk-api-baseline.sha256 | 2 + docs/plugins/sdk-subpaths.md | 2 + .../tsconfig.package-boundary.paths.json | 6 --- extensions/xai/tsconfig.json | 6 --- package.json | 4 +- ...lugin-sdk-private-local-only-subpaths.json | 2 - scripts/plugin-sdk-surface-report.mjs | 9 ++-- ...in-sdk-package-contract-guardrails.test.ts | 54 ++++++++++++++++++- 8 files changed, 64 insertions(+), 21 deletions(-) diff --git a/docs/.generated/plugin-sdk-api-baseline.sha256 b/docs/.generated/plugin-sdk-api-baseline.sha256 index 8b22b1f32506..8517f202d532 100644 --- a/docs/.generated/plugin-sdk-api-baseline.sha256 +++ b/docs/.generated/plugin-sdk-api-baseline.sha256 @@ -121,6 +121,7 @@ aa8a411ad37c1d1143b67376bf2d20255b9eedff61d80815f42e4f8ed7bd8e58 module/secret- 57dcb1462d4c4f9a98d934c4ca975b163d704758af9821a64001ff3ac05637c3 module/secret-input-runtime e576b537880f63b3a91f3608f7e84c873bce6c6a3d9a0ba98c247f46de788d25 module/secret-ref-runtime 62ccaafc8e0677e850339f4a4333f9f16ae9fed979bcef003890b2a47507147f module/security-runtime +673c64502fdffb2d6361a7cf2ad0c33ffe15707b5e5027de1d88701ce3d8ade1 module/session-catalog 31b785e74f1f8f56241b7756ef6a5d86199c5ce177cbb1c234a261866972f270 module/session-discussion f112bdabc51ba8659b37d0a6f6a32a2b1d471e5b49b56e108bf750ec55a7ea71 module/session-store-runtime 36affbe151431a6141664b6838e20f2d121ff210d57a3c1b4b41a8818b5c81d8 module/setup @@ -138,6 +139,7 @@ ff35f9f74d35d37a2eb6126b57f3dc5a4d580b6222fe3a34c9368779ad32eab7 module/state-p 0e230313a7a27a915a7aa399c0afd94c4c3e10d485c7b513e757f41bfc362dbe module/text-chunking 25b5366f5d0f5826f520f847e0ae701936e97302d5ac62042d65f5be0f6974d2 module/text-runtime a94c9ff59cc361b04f8731a47d722c4bc88cfabf942221369a8cb67bdcda7249 module/tool-plugin +89846974257b7551d46a514902998d0592fc67b1d8ce036c6514d7b9cd1bc159 module/tool-results 9d6ab352913a573b226e054e1dc8c6d088493aea9954950c65585923b5b6895a module/tool-send 541df9dea799f25e83ea483d481ecebc5b91c016effab593c54d3efe3ee6517b module/web-media 2d9a53e49d9092804945248efa6d03ce0099cfa7a1c9d7836782754b5e99ebb3 module/webhook-ingress diff --git a/docs/plugins/sdk-subpaths.md b/docs/plugins/sdk-subpaths.md index 70d02cc66517..ced2954ae0f1 100644 --- a/docs/plugins/sdk-subpaths.md +++ b/docs/plugins/sdk-subpaths.md @@ -248,6 +248,7 @@ Use `isLoopbackHost(host)` when a plugin must accept only the local machine. It | `plugin-sdk/reply-reference` | Private-local after July 2026; `createReplyReferencePlanner` | | `plugin-sdk/reply-chunking` | Narrow text/markdown chunking helpers | | `plugin-sdk/session-store-runtime` | Session workflow helpers (`getSessionEntry`, `listSessionEntries`, `patchSessionEntry`, `upsertSessionEntry`), repair/lifecycle helpers (`deleteSessionEntry`, `cleanupSessionLifecycleArtifacts`, `resolveSessionStoreBackupPaths`), marker helpers for transitional `sessionFile` values, bounded recent user/assistant transcript text reads by session identity, session store path/session-key helpers, and updated-at reads, without broad config writes/maintenance imports | + | `plugin-sdk/session-catalog` | External session catalog contracts, projections, adoption helpers, and history import | | `plugin-sdk/session-transcript-runtime` | Private-local after July 2026; Transcript identity, bounded raw and visible cursors, scoped target/read/write helpers, visible message-entry projection, update publishing, write locks, and transcript memory hit keys | | `plugin-sdk/sqlite-runtime` | Private-local after July 2026; Focused SQLite agent-schema, path, and transaction helpers for first-party runtime, without database lifecycle controls | | `plugin-sdk/cron-store-runtime` | Private-local after July 2026; Cron store path/load/save helpers | @@ -262,6 +263,7 @@ Use `isLoopbackHost(host)` when a plugin must accept only the local machine. It | `plugin-sdk/param-readers` | Common tool/CLI param readers | | `plugin-sdk/tool-plugin` | Define a simple typed agent-tool plugin and expose static metadata for manifest generation | | `plugin-sdk/tool-payload` | Private-local after July 2026; Extract normalized payloads from tool result objects | + | `plugin-sdk/tool-results` | Typed text and JSON agent tool result builders | | `plugin-sdk/tool-send` | Extract canonical send target fields from tool args | | `plugin-sdk/sandbox` | Private-local after July 2026; Sandbox backend types and SSH/OpenShell command helpers, including fail-fast exec command preflight | | `plugin-sdk/temp-path` | Shared temp-download path helpers and private secure temp workspaces | diff --git a/extensions/tsconfig.package-boundary.paths.json b/extensions/tsconfig.package-boundary.paths.json index e44cf06f8cf9..63a9b63b3378 100644 --- a/extensions/tsconfig.package-boundary.paths.json +++ b/extensions/tsconfig.package-boundary.paths.json @@ -296,9 +296,6 @@ "openclaw/plugin-sdk/session-binding-runtime": [ "../packages/plugin-sdk/dist/src/plugin-sdk/session-binding-runtime.d.ts" ], - "openclaw/plugin-sdk/session-catalog": [ - "../packages/plugin-sdk/dist/src/plugin-sdk/session-catalog.d.ts" - ], "openclaw/plugin-sdk/session-catalog-runtime": [ "../packages/plugin-sdk/dist/src/plugin-sdk/session-catalog-runtime.d.ts" ], @@ -515,9 +512,6 @@ "openclaw/plugin-sdk/tool-payload": [ "../packages/plugin-sdk/dist/src/plugin-sdk/tool-payload.d.ts" ], - "openclaw/plugin-sdk/tool-results": [ - "../packages/plugin-sdk/dist/src/plugin-sdk/tool-results.d.ts" - ], "openclaw/plugin-sdk/webhook-targets": [ "../packages/plugin-sdk/dist/src/plugin-sdk/webhook-targets.d.ts" ], diff --git a/extensions/xai/tsconfig.json b/extensions/xai/tsconfig.json index 032ffd063092..0e62e7e38f8f 100644 --- a/extensions/xai/tsconfig.json +++ b/extensions/xai/tsconfig.json @@ -294,9 +294,6 @@ "openclaw/plugin-sdk/session-binding-runtime": [ "../../packages/plugin-sdk/dist/src/plugin-sdk/session-binding-runtime.d.ts" ], - "openclaw/plugin-sdk/session-catalog": [ - "../../packages/plugin-sdk/dist/src/plugin-sdk/session-catalog.d.ts" - ], "openclaw/plugin-sdk/session-catalog-runtime": [ "../../packages/plugin-sdk/dist/src/plugin-sdk/session-catalog-runtime.d.ts" ], @@ -513,9 +510,6 @@ "openclaw/plugin-sdk/tool-payload": [ "../../packages/plugin-sdk/dist/src/plugin-sdk/tool-payload.d.ts" ], - "openclaw/plugin-sdk/tool-results": [ - "../../packages/plugin-sdk/dist/src/plugin-sdk/tool-results.d.ts" - ], "openclaw/plugin-sdk/webhook-targets": [ "../../packages/plugin-sdk/dist/src/plugin-sdk/webhook-targets.d.ts" ], diff --git a/package.json b/package.json index d83f5bc5e7db..68710a62dbcb 100644 --- a/package.json +++ b/package.json @@ -183,7 +183,6 @@ "!dist/plugin-sdk/secret-file-runtime.d.ts", "!dist/plugin-sdk/secure-random-runtime.d.ts", "!dist/plugin-sdk/session-binding-runtime.d.ts", - "!dist/plugin-sdk/session-catalog.d.ts", "!dist/plugin-sdk/session-catalog-runtime.d.ts", "!dist/plugin-sdk/session-key-runtime.d.ts", "!dist/plugin-sdk/session-transcript-hit.d.ts", @@ -224,7 +223,6 @@ "!dist/plugin-sdk/thread-bindings-session-runtime.d.ts", "!dist/plugin-sdk/time-runtime.d.ts", "!dist/plugin-sdk/tool-payload.d.ts", - "!dist/plugin-sdk/tool-results.d.ts", "!dist/plugin-sdk/transcripts.d.ts", "!dist/plugin-sdk/transport-ready-runtime.d.ts", "!dist/plugin-sdk/tts-runtime.d.ts", @@ -1022,6 +1020,7 @@ "default": "./dist/plugin-sdk/session-binding-runtime.js" }, "./plugin-sdk/session-catalog": { + "types": "./dist/plugin-sdk/session-catalog.d.ts", "default": "./dist/plugin-sdk/session-catalog.js" }, "./plugin-sdk/session-catalog-runtime": { @@ -1370,6 +1369,7 @@ "default": "./dist/plugin-sdk/tool-payload.js" }, "./plugin-sdk/tool-results": { + "types": "./dist/plugin-sdk/tool-results.d.ts", "default": "./dist/plugin-sdk/tool-results.js" }, "./plugin-sdk/tool-send": { diff --git a/scripts/lib/plugin-sdk-private-local-only-subpaths.json b/scripts/lib/plugin-sdk-private-local-only-subpaths.json index 890aefc7f65b..9ec713bada00 100644 --- a/scripts/lib/plugin-sdk-private-local-only-subpaths.json +++ b/scripts/lib/plugin-sdk-private-local-only-subpaths.json @@ -136,7 +136,6 @@ "secret-file-runtime", "secure-random-runtime", "session-binding-runtime", - "session-catalog", "session-catalog-runtime", "session-key-runtime", "session-transcript-hit", @@ -167,7 +166,6 @@ "thread-bindings-session-runtime", "time-runtime", "tool-payload", - "tool-results", "transcripts", "transport-ready-runtime", "tts-runtime", diff --git a/scripts/plugin-sdk-surface-report.mjs b/scripts/plugin-sdk-surface-report.mjs index 0e3a8b1b42f5..442b6bd890cf 100644 --- a/scripts/plugin-sdk-surface-report.mjs +++ b/scripts/plugin-sdk-surface-report.mjs @@ -158,7 +158,8 @@ export function readPluginSdkSurfaceBudgets(env = process.env) { // +1: bounded archive extraction and single-entry reads. // +1: budgeted root-bounded directory walking. // +1: pinned secret reads and first-writer-wins creation. - 146, + // +2: restore the documented session-catalog and tool-results plugin contracts. + 148, env, ), publicExports: readPluginSdkSurfaceBudgetEnv( @@ -204,7 +205,8 @@ export function readPluginSdkSurfaceBudgets(env = process.env) { // +2: shared ingress error factory through channel-outbound and channel-message. // +2: shared ingress retention defaults through channel-outbound and channel-message. // +1: collision-safe MCP server-name assignment for native harness catalogs. - 4774, + // +45: restore typed session-catalog and tool-results exports promised to plugins. + 4819, env, ), publicFunctionExports: readPluginSdkSurfaceBudgetEnv( @@ -242,7 +244,8 @@ export function readPluginSdkSurfaceBudgets(env = process.env) { // +1: inbound media-fact metadata projection for plugin-owned channel ingestion. // +2: shared ingress error factory through channel-outbound and channel-message. // +1: collision-safe MCP server-name assignment for native harness catalogs. - 2882, + // +14: restore callable session-catalog and tool-results helpers promised to plugins. + 2896, env, ), publicDeprecatedExports: readPluginSdkSurfaceBudgetEnv( diff --git a/src/plugins/contracts/plugin-sdk-package-contract-guardrails.test.ts b/src/plugins/contracts/plugin-sdk-package-contract-guardrails.test.ts index df47b37a6442..4095f5b116ce 100644 --- a/src/plugins/contracts/plugin-sdk-package-contract-guardrails.test.ts +++ b/src/plugins/contracts/plugin-sdk-package-contract-guardrails.test.ts @@ -27,6 +27,7 @@ const PUBLIC_CONTRACT_REFERENCE_FILES = [ "docs/plugins/architecture.md", "src/plugins/contracts/plugin-sdk-subpaths.test.ts", ] as const; +const TYPED_PUBLIC_CONTRACT_REFERENCE_FILES = ["docs/plugins/sdk-entrypoints.md"] as const; const PLUGIN_SDK_SUBPATH_PATTERN = /openclaw\/plugin-sdk\/([a-z0-9][a-z0-9-]*)\b/g; const BUNDLED_PLUGIN_FACADE_LOADER_PATTERN = /\bload(?:Activated)?BundledPluginPublicSurfaceModuleSync\b/; @@ -142,9 +143,39 @@ function collectPluginSdkPackageExports(): string[] { return subpaths.toSorted(); } -function collectPluginSdkSubpathReferences() { +function collectTypedPluginSdkPackageExports(): Set { + const packageJson = JSON.parse(fs.readFileSync(resolve(REPO_ROOT, "package.json"), "utf8")) as { + exports?: Record; + }; + const typedSubpaths = new Set(); + for (const [key, value] of Object.entries(packageJson.exports ?? {})) { + if ( + key.startsWith("./plugin-sdk/") && + value && + typeof value === "object" && + "types" in value && + typeof value.types === "string" + ) { + typedSubpaths.add(key.slice("./plugin-sdk/".length)); + } + } + return typedSubpaths; +} + +function collectPackExcludedPluginSdkDeclarations(): Set { + const packageJson = readRootPackageJson(); + return new Set( + (packageJson.files ?? []) + .map((entry) => /^!dist\/plugin-sdk\/([a-z0-9][a-z0-9-]*)\.d\.ts$/u.exec(entry)?.[1]) + .filter((subpath): subpath is string => Boolean(subpath)), + ); +} + +function collectPluginSdkSubpathReferences( + files: readonly string[] = PUBLIC_CONTRACT_REFERENCE_FILES, +) { const references: Array<{ file: string; subpath: string }> = []; - for (const file of PUBLIC_CONTRACT_REFERENCE_FILES) { + for (const file of files) { const source = fs.readFileSync(resolve(REPO_ROOT, file), "utf8"); for (const match of source.matchAll(PLUGIN_SDK_SUBPATH_PATTERN)) { const subpath = match[1]; @@ -876,6 +907,25 @@ describe("plugin-sdk package contract guardrails", () => { expect(failures).toStrictEqual([]); }); + it("keeps SDK entrypoint guide imports on typed public package exports", () => { + const publicEntrypoints = new Set(publicPluginSdkEntrypoints); + const typedExports = collectTypedPluginSdkPackageExports(); + const excludedDeclarations = collectPackExcludedPluginSdkDeclarations(); + const failures = collectPluginSdkSubpathReferences(TYPED_PUBLIC_CONTRACT_REFERENCE_FILES) + .filter( + ({ subpath }) => + !publicEntrypoints.has(subpath) || + !typedExports.has(subpath) || + excludedDeclarations.has(subpath), + ) + .map( + ({ file, subpath }) => + `${file} references openclaw/plugin-sdk/${subpath}, but its declaration is not included in the typed public package`, + ); + + expect(failures).toStrictEqual([]); + }); + it("keeps deprecated public SDK subpaths unused by extension production code", () => { const publicEntrypoints = new Set(publicPluginSdkEntrypoints); const unknownDeprecated = deprecatedPublicPluginSdkEntrypoints.filter(