[plugin sdk] Add structured extraction media runtime#79334
Conversation
|
Codex review: needs real behavior proof before merge. Summary Reproducibility: unclear. The review failed before ClawSweeper could establish a reproduction path. Real behavior proof Next step before merge Review detailsBest possible solution: Retry the Codex review after fixing the execution failure. Do we have a high-confidence way to reproduce the issue? Unclear. The review failed before ClawSweeper could establish a reproduction path. Is this the best way to solve the issue? Unclear. Retry the review first so ClawSweeper can evaluate the actual issue and fix direction. What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against be9b083806e2. |
|
@garrytan this is for direct access + oauth through codex for Gbrain users vs separate API management (and anyone with similar plugin needs) for OpenClaw users of Gbrain |
6b8e9a1 to
61d1911
Compare
|
@clawsweeper re-review |
61d1911 to
3222475
Compare
|
Updated on the rebased head
@clawsweeper re-review |
3222475 to
a133146
Compare
|
Maintainer feedback here felt right, so I filed a separate follow-up for the broader plugin-runtime need: #80188.\n\nMy recommendation is to keep this PR intentionally narrow as the media-understanding structured extraction seam, and track the more general host-owned plugin inference shape under separately so we do not overload this PR with raw OAuth or generic plugin completion semantics. |
|
Maintainer feedback here felt right, so I filed a separate follow-up for the broader plugin-runtime need: #80188. My recommendation is to keep this PR intentionally narrow as the media-understanding structured extraction seam, and track the more general host-owned plugin inference shape under |
|
Following the earlier maintainer feedback about broader plugin auth/inference shapes, I opened the generic host-owned structured inference follow-up here: #80203.\n\nThe intent is for #79334 to stay the narrower media-understanding seam, while #80203 carries the general lane for plugins that need bounded structured inference without raw credential access. |
|
Following the earlier maintainer feedback about broader plugin auth/inference shapes, I opened the generic host-owned structured inference follow-up here: #80203. The intent is for #79334 to stay the narrower media-understanding seam, while #80203 carries the general |
|
Superseded by #80229, which now carries the combined proof and merge-ready consolidation branch. |
|
Closing temporarily for room. |
Why this matters
OpenClaw plugins increasingly need to turn unstructured user content into safe, typed data: receipts into expense records, screenshots into support evidence, invoices into accounting fields, customer messages into CRM notes, PDFs into knowledge-base snippets, and product photos into searchable inventory metadata.
Today each plugin has to choose between two bad options:
This PR adds the missing middle layer: a generic structured extraction capability in the media-understanding SDK. Product plugins keep owning their routes, schemas, storage, and UX, while OpenClaw owns the provider/runtime boundary, auth source, safety posture, and typed SDK contract.
What plugin authors can build with this
Examples this unlocks without adding plugin-specific logic to OpenClaw core:
The important part: the plugin defines the schema and decides what to do with the result. OpenClaw only provides the generic, bounded extraction lane.
New SDK shape
This PR adds:
MediaUnderstandingProvider.extractStructured(...)api.runtime.mediaUnderstanding.extractStructuredWithModel(...)schemaName,jsonSchema,jsonMode, andtimeoutMstext, parsed JSON when JSON mode is enabled, model/provider, and content typeExample plugin call:
Runtime architecture
For the bundled Codex provider, this uses the existing Codex app-server/OAuth path rather than requiring a user-supplied model API key.
Safety and boundaries
The Codex implementation keeps the same bounded posture as image understanding:
on-request, with approval requests denied by the provider handlerThis is intentionally a platform seam, not a feature-specific integration.
What changed
extractStructuredWithModel(...)to the plugin runtime media-understanding facade.extractStructured(...)in the bundled Codex provider.describeImageFileWithModel(...)on the full media-understanding registry instead of narrowing it to manifest-only plugin providers.Relationship to existing LLM surfaces
OpenClaw already has
api.runtime.llm.completefor trusted plugin text completions, andllm-taskfor workflow/tool-level JSON tasks. This PR is narrower and lower-level: a provider SDK/runtime media-understanding seam for schema-shaped extraction over image inputs with optional text context. That keeps extraction provider-owned and plugin-consumable without turning it into a general-purpose arbitrary Codex call API.Non-goals
Background
This closes #79321.
The immediate downstream need came from a GBrain/OpenClaw integration, but the implementation here is deliberately generic. GBrain, support, CRM, finance, inventory, migration, and knowledge-base plugins can all consume the same SDK seam while keeping their own product-specific routes and schemas outside OpenClaw core.
Real behavior proof
Behavior or issue addressed: The rebased branch exposes a typed plugin-runtime structured extraction seam that dispatches through a registered media-understanding provider, preserves the bounded Codex worker defaults, forwards the selected auth profile into the provider-owned runtime, and rejects text-only calls before provider dispatch.
Real environment tested: Local macOS OpenClaw checkout at
/Users/lume/openclaw-review-worktrees/pr-79334-rebase, rebased head78cfe4a76161fc7d3029beb4edcf7120a94a4d8b, using a standalonenode --import tsxproof command outside Vitest. The proof registers the real bundled Codex media-understanding provider in the active plugin runtime registry with a stubbed app-server client, then callscreatePluginRuntime().mediaUnderstanding.extractStructuredWithModel(...)once with image-plus-text input and once with text-only input.Exact steps or command run after this patch:
Evidence after fix:
{ "success": { "text": "{\"summary\":\"red square\",\"tags\":[\"shape\"]}", "model": "gpt-5.4", "provider": "codex", "contentType": "json", "parsed": { "summary": "red square", "tags": [ "shape" ] } }, "authProfileIds": [ "openai-codex:work" ], "requestMethods": [ "model/list", "thread/start", "turn/start" ], "threadStart": { "model": "gpt-5.4", "modelProvider": "openai", "cwd": "/Users/lume/openclaw-review-worktrees/pr-79334-rebase", "approvalPolicy": "on-request", "sandbox": "read-only", "serviceName": "OpenClaw", "developerInstructions": "You are OpenClaw's bounded structured-extraction worker. Return only the requested extraction. Do not call tools, edit files, ask follow-up questions, or include secrets.", "dynamicTools": [], "experimentalRawEvents": true, "persistExtendedHistory": false, "ephemeral": true }, "turnInput": [ { "type": "text", "text": "Return JSON with summary and tags.\n\nSchema name: proof.red-square\n\nJSON schema:\n{\"type\":\"object\",\"properties\":{\"summary\":{\"type\":\"string\"},\"tags\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"required\":[\"summary\"]}\n\nReturn valid JSON only. Do not wrap the JSON in Markdown fences.", "text_elements": [] }, { "type": "image", "url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+kX3sAAAAASUVORK5CYII=" }, { "type": "text", "text": "Return searchable evidence for the uploaded image.", "text_elements": [] } ], "guardError": "Structured extraction requires at least one image input." }Observed result after fix: The plugin runtime facade dispatched
extractStructuredWithModel(...)through the registered Codex media-understanding provider, the provider returned parsed JSON on the bounded app-server path, the selected auth profile reached the provider-owned runtime, and the text-only call failed early with the intended image-required guard instead of widening this seam into general text extraction.What was not tested: This proof intentionally uses a stubbed app-server client so it can exercise the real runtime/provider dispatch path deterministically in a local checkout without requiring a desktop-bound live OAuth session. The PR does not include a credentialed live Codex desktop turn artifact because that would require shipping private local auth/session material into public review evidence.
Validation
pnpm install --frozen-lockfilepnpm plugin-sdk:api:genpnpm plugin-sdk:api:checkpnpm test src/media-understanding/runtime.test.ts src/media-understanding/provider-registry.test.ts extensions/codex/media-understanding-provider.test.ts src/plugins/runtime/index.test.tspnpm check:changed