You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
get-actor-run = data-only, mode-independent (same ToolEntry returned in both modes)
get-actor-run-widget = widget-only, additive in apps mode
No -internal equivalent existed, so nothing to delete
Why the widget variant now (not later)
Under today's call-actor-widget auto-polling model, WORKFLOW_RULES forbids calling get-actor-run after a widget render β so the apps-mode widget branch was effectively dead. Forward direction: call-actor becomes always-async (returns runId immediately, no UI), and the LLM picks get-actor-run (silent status) or get-actor-run-widget (UI progress) based on whether the user wants a visual. Shipping the widget variant now keeps the six-tool split symmetric with #722 / #723 / #724 and prepares the infrastructure before the async-execution policy change (tracked separately per #582).
Scope
Shipped (Approach A β same as peers)
get-actor-run across modes = data-only (current default behavior). Dropped tool-level widget _meta; trimmed stale "NEVER call in UI mode" block from base description (that rule lives in WORKFLOW_RULES now).
Created src/tools/apps/get_actor_run_widget.ts:
Input: { runId }.strict()
Output: widget-shaped run status (reuses shared buildGetActorRunSuccessResponse({ widget: true }))
src/tools/categories.ts: runs entry is now plain defaultGetActorRun; ui[] gets { apps: getActorRunWidgetTool }
src/utils/server-instructions/apps.ts: fourth disambiguation bullet pairing the base tool with the widget variant. WORKFLOW_RULES untouched β the "NEVER poll after call-actor-widget" rule is orthogonal.
Structured output schema changes (existing getActorRunOutputSchema is shared between variants; no new schema needed)
Design notes
Base tool is the same frozen ToolEntry in both modes (defaultResult.runs === appsResult.runs for get-actor-run). The widget sibling lives only in ui category.
get_actor_run_common.ts (per refactor: Deduplicate get-actor-run handler logicΒ #699) already exposes shared builders. The widget tool calls fetchActorRunData() + buildGetActorRunSuccessResponse({ widget: true }); the base tool calls the same with widget: false.
widget in UI category, base on no-widget-meta list (runs category)
tests/unit/tools.categories.test.ts
flip not.toBe β toBe for get-actor-run (mode-independent now)
Internal repo impact
Purely additive on the widget side. Base get-actor-run keeps the same name and byte-identical input/output schemas across modes. The shared buildGetActorRunSuccessResponse widget branch now emits openai/widgetDescription on the response β harmless for consumers that ignore extra _meta keys. Internal repo should not need edits; called out for reviewer confirmation in PR #734.
Testing strategy
Unit
get-actor-run identical output in both modes (shared ToolEntry)
π PR chain β step 6 of 6 in #577
openaiβappsfetch-actor-detailssplit (pilot)search-actorssplitcall-actorsplitParent: #577. Final child. Completes the umbrella.
Context and motivation
Final child of #577. Mirrors #716, #717, #718. Depends on #714, #715.
After this PR:
get-actor-run= data-only, mode-independent (same ToolEntry returned in both modes)get-actor-run-widget= widget-only, additive inappsmode-internalequivalent existed, so nothing to deleteWhy the widget variant now (not later)
Under today's
call-actor-widgetauto-polling model,WORKFLOW_RULESforbids callingget-actor-runafter a widget render β so the apps-mode widget branch was effectively dead. Forward direction:call-actorbecomes always-async (returns runId immediately, no UI), and the LLM picksget-actor-run(silent status) orget-actor-run-widget(UI progress) based on whether the user wants a visual. Shipping the widget variant now keeps the six-tool split symmetric with #722 / #723 / #724 and prepares the infrastructure before the async-execution policy change (tracked separately per #582).Scope
Shipped (Approach A β same as peers)
get-actor-runacross modes = data-only (currentdefaultbehavior). Dropped tool-level widget_meta; trimmed stale "NEVER call in UI mode" block from base description (that rule lives inWORKFLOW_RULESnow).src/tools/apps/get_actor_run_widget.ts:{ runId }.strict()buildGetActorRunSuccessResponse({ widget: true }))_meta.ui.resourceUri = ui://widget/actor-run.html_meta.ui.visibility = ["model","app"], non-empty_meta.ui.cspopenai/widgetDescriptionACTOR_RUNS_GET_WIDGETtoHelperToolssrc/tools/categories.ts:runsentry is now plaindefaultGetActorRun;ui[]gets{ apps: getActorRunWidgetTool }src/utils/server-instructions/apps.ts: fourth disambiguation bullet pairing the base tool with the widget variant.WORKFLOW_RULESuntouched β the "NEVER poll aftercall-actor-widget" rule is orthogonal.Out of scope
#582(waitSecs/ always-async policy) β tracked separatelygetActorRunOutputSchemais shared between variants; no new schema needed)Design notes
ToolEntryin both modes (defaultResult.runs===appsResult.runsforget-actor-run). The widget sibling lives only inuicategory.get_actor_run_common.ts(per refactor: Deduplicate get-actor-run handler logicΒ #699) already exposes shared builders. The widget tool callsfetchActorRunData()+buildGetActorRunSuccessResponse({ widget: true }); the base tool calls the same withwidget: false.Files changed (PR #734)
src/tools/apps/get_actor_run_widget.tssrc/tools/apps/get_actor_run.tssrc/tools/categories.tsget-actor-runplain entry; register widget inuisrc/const.tsACTOR_RUNS_GET_WIDGET = 'get-actor-run-widget'src/tools/core/get_actor_run_common.ts_metafrom base metadata; addopenai/widgetDescriptionto widget response; trim descriptionsrc/utils/server-instructions/apps.tstests/unit/tools.get_actor_run.widget.response.test.tstests/unit/tools.mode_contract.test.tstests/unit/tools.categories.test.tsnot.toBeβtoBeforget-actor-run(mode-independent now)Internal repo impact
Purely additive on the widget side. Base
get-actor-runkeeps the same name and byte-identical input/output schemas across modes. The sharedbuildGetActorRunSuccessResponsewidget branch now emitsopenai/widgetDescriptionon the response β harmless for consumers that ignore extra_metakeys. Internal repo should not need edits; called out for reviewer confirmation in PR #734.Testing strategy
Unit
get-actor-runidentical output in both modes (shared ToolEntry)get-actor-run-widgetreturns widget shape + widget_meta+openai/widgetDescriptiontests/unit/tools.mode_contract.test.tsandtests/unit/tools.categories.test.tsIntegration
npm run test:integration) β not covered by this PR's agent verificationmcpc probe (raw JSON-RPC over stdin)
Acceptance criteria:
get-actor-run; no-widgetget-actor-runANDget-actor-run-widgetget-actor-runinputSchema+outputSchemabyte-identical between modesget-actor-run_metahas noui.*keys in either modeget-actor-run-widget._meta.ui.resourceUri==ui://widget/actor-run.htmlget-actor-run-widget._meta.ui.visibility==["model","app"]get-actor-run-widget._meta.ui.cspis a non-empty objectManual
Verification checklist
npm run type-checkpassesnpm run lintpassesnpm run test:unitpasses (615 tests)npm run buildpasses