feat: Split search-actors into data + -widget tools#723
Merged
jirispilka merged 5 commits intomasterfrom Apr 29, 2026
Merged
Conversation
This was referenced Apr 19, 2026
jirispilka
pushed a commit
that referenced
this pull request
Apr 20, 2026
Step 5 of 6 in the #577 umbrella. Mirrors the decoupled-pattern recipe from #716/PR #722 (fetch-actor-details) and #723 (search-actors): - call-actor now always returns pure data in both modes. No tool-level widget _meta anywhere, and buildStartAsyncResponse({ widget: false }) in apps mode returns runId without response-level widget _meta. The apps variant still runs asynchronously. - New call-actor-widget (apps-only) renders the live progress widget. Input is strict: { actor, input, callOptions? } only — async and previewOutput are rejected. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). - Apps server instructions reshaped: the "never poll get-actor-run" rule now scopes to call-actor-widget only; polling after the silent call-actor is fine. Added a third disambiguation bullet pairing call-actor with call-actor-widget using the same "interactive UI element / widget" vocabulary as the other two splits. - buildCallActorDescription alwaysAsync branch flipped to describe the silent-async behavior and point to call-actor-widget for UI. https://claude.ai/code/session_01LPzCFY7ReLm8wvmFHJLyun
14 tasks
jirispilka
pushed a commit
that referenced
this pull request
Apr 20, 2026
Final step (6 of 6) of the #577 umbrella rollout. Mirrors the decoupled-pattern recipe from #722 (fetch-actor-details), #723 (search-actors), and #724 (call-actor): - get-actor-run is now mode-independent and data-only. No tool-level widget _meta in either mode; runs category entry is a plain ToolEntry instead of a mode map. - New get-actor-run-widget (apps-only) renders the live progress widget. Input is strict: { runId } only. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). Reuses the shared buildGetActorRunSuccessResponse({ widget: true }) helper. - buildGetActorRunSuccessResponse widget branch now also sets openai/widgetDescription on the response _meta, matching the other three widget tools. - Apps server instructions: added the fourth disambiguation bullet pairing get-actor-run (silent data lookup) with get-actor-run-widget (live progress widget), using the same vocabulary as the existing three splits. WORKFLOW_RULES untouched — the "NEVER poll get-actor-run after call-actor-widget" rule is orthogonal. - Deleted src/tools/apps/get_actor_run.ts; widget rendering now lives in the sibling tool rather than a mode toggle. https://claude.ai/code/session_01SF9P6g91UrVMahn4bLsUNf
8 tasks
527ad06 to
e23510a
Compare
e7d755e to
3f2503b
Compare
jirispilka
pushed a commit
that referenced
this pull request
Apr 20, 2026
Step 5 of 6 in the #577 umbrella. Mirrors the decoupled-pattern recipe from #716/PR #722 (fetch-actor-details) and #723 (search-actors): - call-actor now always returns pure data in both modes. No tool-level widget _meta anywhere, and buildStartAsyncResponse({ widget: false }) in apps mode returns runId without response-level widget _meta. The apps variant still runs asynchronously. - New call-actor-widget (apps-only) renders the live progress widget. Input is strict: { actor, input, callOptions? } only — async and previewOutput are rejected. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). - Apps server instructions reshaped: the "never poll get-actor-run" rule now scopes to call-actor-widget only; polling after the silent call-actor is fine. Added a third disambiguation bullet pairing call-actor with call-actor-widget using the same "interactive UI element / widget" vocabulary as the other two splits. - buildCallActorDescription alwaysAsync branch flipped to describe the silent-async behavior and point to call-actor-widget for UI. https://claude.ai/code/session_01LPzCFY7ReLm8wvmFHJLyun
jirispilka
pushed a commit
that referenced
this pull request
Apr 20, 2026
Final step (6 of 6) of the #577 umbrella rollout. Mirrors the decoupled-pattern recipe from #722 (fetch-actor-details), #723 (search-actors), and #724 (call-actor): - get-actor-run is now mode-independent and data-only. No tool-level widget _meta in either mode; runs category entry is a plain ToolEntry instead of a mode map. - New get-actor-run-widget (apps-only) renders the live progress widget. Input is strict: { runId } only. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). Reuses the shared buildGetActorRunSuccessResponse({ widget: true }) helper. - buildGetActorRunSuccessResponse widget branch now also sets openai/widgetDescription on the response _meta, matching the other three widget tools. - Apps server instructions: added the fourth disambiguation bullet pairing get-actor-run (silent data lookup) with get-actor-run-widget (live progress widget), using the same vocabulary as the existing three splits. WORKFLOW_RULES untouched — the "NEVER poll get-actor-run after call-actor-widget" rule is orthogonal. - Deleted src/tools/apps/get_actor_run.ts; widget rendering now lives in the sibling tool rather than a mode toggle. https://claude.ai/code/session_01SF9P6g91UrVMahn4bLsUNf
c88e25a to
5909cb6
Compare
3f2503b to
a833d7f
Compare
jirispilka
pushed a commit
that referenced
this pull request
Apr 22, 2026
Step 5 of 6 in the #577 umbrella. Mirrors the decoupled-pattern recipe from #716/PR #722 (fetch-actor-details) and #723 (search-actors): - call-actor now always returns pure data in both modes. No tool-level widget _meta anywhere, and buildStartAsyncResponse({ widget: false }) in apps mode returns runId without response-level widget _meta. The apps variant still runs asynchronously. - New call-actor-widget (apps-only) renders the live progress widget. Input is strict: { actor, input, callOptions? } only — async and previewOutput are rejected. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). - Apps server instructions reshaped: the "never poll get-actor-run" rule now scopes to call-actor-widget only; polling after the silent call-actor is fine. Added a third disambiguation bullet pairing call-actor with call-actor-widget using the same "interactive UI element / widget" vocabulary as the other two splits. - buildCallActorDescription alwaysAsync branch flipped to describe the silent-async behavior and point to call-actor-widget for UI. https://claude.ai/code/session_01LPzCFY7ReLm8wvmFHJLyun
jirispilka
pushed a commit
that referenced
this pull request
Apr 22, 2026
Final step (6 of 6) of the #577 umbrella rollout. Mirrors the decoupled-pattern recipe from #722 (fetch-actor-details), #723 (search-actors), and #724 (call-actor): - get-actor-run is now mode-independent and data-only. No tool-level widget _meta in either mode; runs category entry is a plain ToolEntry instead of a mode map. - New get-actor-run-widget (apps-only) renders the live progress widget. Input is strict: { runId } only. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). Reuses the shared buildGetActorRunSuccessResponse({ widget: true }) helper. - buildGetActorRunSuccessResponse widget branch now also sets openai/widgetDescription on the response _meta, matching the other three widget tools. - Apps server instructions: added the fourth disambiguation bullet pairing get-actor-run (silent data lookup) with get-actor-run-widget (live progress widget), using the same vocabulary as the existing three splits. WORKFLOW_RULES untouched — the "NEVER poll get-actor-run after call-actor-widget" rule is orthogonal. - Deleted src/tools/apps/get_actor_run.ts; widget rendering now lives in the sibling tool rather than a mode toggle. https://claude.ai/code/session_01SF9P6g91UrVMahn4bLsUNf
a833d7f to
fab37f4
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Refactors the search-actors tool to follow the decoupled “data tool + -widget UI tool” pattern in apps mode, removing the old -internal helper and updating instructions/tests accordingly.
Changes:
- Makes
search-actorsmode-independent and data-only; removes tool-level widget_metafrom the base tool. - Introduces
search-actors-widget(apps-only) with strict input schema and widget-shaped output + widget_meta. - Removes
search-actors-internal, updates helper tool constants, server instructions, and unit/integration tests to match the new tool surface.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
src/const.ts |
Replaces STORE_SEARCH_INTERNAL with STORE_SEARCH_WIDGET helper constant. |
src/tools/core/search_actors_common.ts |
Removes widget _meta from base search-actors metadata; updates docs. |
src/tools/apps/search_actors_widget.ts |
Adds new apps-only widget tool that renders the search widget and returns widget payload + _meta. |
src/tools/apps/search_actors.ts |
Deleted apps-mode variant now that base tool is mode-independent. |
src/tools/apps/search_actors_internal.ts |
Deleted obsolete internal helper tool. |
src/tools/structured_output_schemas.ts |
Renames internal output schema to actorSearchWidgetOutputSchema and requires widgetActors. |
src/tools/categories.ts |
Registers search-actors as a plain ToolEntry and adds search-actors-widget to ui category. |
src/tools/core/call_actor_common.ts |
Simplifies call-actor description/error text to reference public search-actors when available. |
src/tools/apps/call_actor.ts |
Updates apps call-actor description/error usage to match removal of -internal search. |
src/tools/default/call_actor.ts |
Updates default call-actor description/error usage to match simplified call-actor helpers. |
src/utils/server-instructions/index.ts |
Updates apps-mode disambiguation rules to search-actors (silent) vs search-actors-widget (UI). |
tests/unit/tools.search_actors.widget.response.test.ts |
Rewrites tests to target search-actors-widget and assert tool/response widget _meta and strict schema behavior. |
tests/unit/tools.mode_contract.test.ts |
Updates mode contract expectations for new widget tool and base tool no-widget-meta invariant. |
tests/unit/mcp.server.capability_gating.test.ts |
Updates capability gating assertions to the new base+widget split. |
tests/unit/utils.tools_loader.test.ts |
Updates tools-loader expectations from internal to widget helper tool. |
tests/unit/tools.categories.test.ts |
Adjusts category tests to reflect mode-independent tools vs mode-specific call-actor. |
tests/unit/tools.call_actor_common.test.ts |
Updates description/error-response tests for the new search tool guidance language. |
tests/integration/suite.ts |
Updates integration expectations to STORE_SEARCH_WIDGET presence/absence in apps/default modes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
jirispilka
pushed a commit
that referenced
this pull request
Apr 24, 2026
Step 5 of 6 in the #577 umbrella. Mirrors the decoupled-pattern recipe from #716/PR #722 (fetch-actor-details) and #723 (search-actors): - call-actor now always returns pure data in both modes. No tool-level widget _meta anywhere, and buildStartAsyncResponse({ widget: false }) in apps mode returns runId without response-level widget _meta. The apps variant still runs asynchronously. - New call-actor-widget (apps-only) renders the live progress widget. Input is strict: { actor, input, callOptions? } only — async and previewOutput are rejected. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). - Apps server instructions reshaped: the "never poll get-actor-run" rule now scopes to call-actor-widget only; polling after the silent call-actor is fine. Added a third disambiguation bullet pairing call-actor with call-actor-widget using the same "interactive UI element / widget" vocabulary as the other two splits. - buildCallActorDescription alwaysAsync branch flipped to describe the silent-async behavior and point to call-actor-widget for UI. https://claude.ai/code/session_01LPzCFY7ReLm8wvmFHJLyun
jirispilka
pushed a commit
that referenced
this pull request
Apr 24, 2026
Final step (6 of 6) of the #577 umbrella rollout. Mirrors the decoupled-pattern recipe from #722 (fetch-actor-details), #723 (search-actors), and #724 (call-actor): - get-actor-run is now mode-independent and data-only. No tool-level widget _meta in either mode; runs category entry is a plain ToolEntry instead of a mode map. - New get-actor-run-widget (apps-only) renders the live progress widget. Input is strict: { runId } only. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). Reuses the shared buildGetActorRunSuccessResponse({ widget: true }) helper. - buildGetActorRunSuccessResponse widget branch now also sets openai/widgetDescription on the response _meta, matching the other three widget tools. - Apps server instructions: added the fourth disambiguation bullet pairing get-actor-run (silent data lookup) with get-actor-run-widget (live progress widget), using the same vocabulary as the existing three splits. WORKFLOW_RULES untouched — the "NEVER poll get-actor-run after call-actor-widget" rule is orthogonal. - Deleted src/tools/apps/get_actor_run.ts; widget rendering now lives in the sibling tool rather than a mode toggle. https://claude.ai/code/session_01SF9P6g91UrVMahn4bLsUNf
6 tasks
jirispilka
pushed a commit
that referenced
this pull request
Apr 24, 2026
Final step (6 of 6) of the #577 umbrella rollout. Mirrors the decoupled-pattern recipe from #722 (fetch-actor-details), #723 (search-actors), and #724 (call-actor): - get-actor-run is now mode-independent and data-only. No tool-level widget _meta in either mode; runs category entry is a plain ToolEntry instead of a mode map. - New get-actor-run-widget (apps-only) renders the live progress widget. Input is strict: { runId } only. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). Reuses the shared buildGetActorRunSuccessResponse({ widget: true }) helper. - buildGetActorRunSuccessResponse widget branch now also sets openai/widgetDescription on the response _meta, matching the other three widget tools. - Apps server instructions: added the fourth disambiguation bullet pairing get-actor-run (silent data lookup) with get-actor-run-widget (live progress widget), using the same vocabulary as the existing three splits. WORKFLOW_RULES untouched — the "NEVER poll get-actor-run after call-actor-widget" rule is orthogonal. - Deleted src/tools/apps/get_actor_run.ts; widget rendering now lives in the sibling tool rather than a mode toggle. https://claude.ai/code/session_01SF9P6g91UrVMahn4bLsUNf
MQ37
approved these changes
Apr 27, 2026
28c8530 to
72114c7
Compare
5d4e6dd to
7821f21
Compare
jirispilka
pushed a commit
that referenced
this pull request
Apr 27, 2026
Step 5 of 6 in the #577 umbrella. Mirrors the decoupled-pattern recipe from #716/PR #722 (fetch-actor-details) and #723 (search-actors): - call-actor now always returns pure data in both modes. No tool-level widget _meta anywhere, and buildStartAsyncResponse({ widget: false }) in apps mode returns runId without response-level widget _meta. The apps variant still runs asynchronously. - New call-actor-widget (apps-only) renders the live progress widget. Input is strict: { actor, input, callOptions? } only — async and previewOutput are rejected. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). - Apps server instructions reshaped: the "never poll get-actor-run" rule now scopes to call-actor-widget only; polling after the silent call-actor is fine. Added a third disambiguation bullet pairing call-actor with call-actor-widget using the same "interactive UI element / widget" vocabulary as the other two splits. - buildCallActorDescription alwaysAsync branch flipped to describe the silent-async behavior and point to call-actor-widget for UI. https://claude.ai/code/session_01LPzCFY7ReLm8wvmFHJLyun
jirispilka
pushed a commit
that referenced
this pull request
Apr 27, 2026
Final step (6 of 6) of the #577 umbrella rollout. Mirrors the decoupled-pattern recipe from #722 (fetch-actor-details), #723 (search-actors), and #724 (call-actor): - get-actor-run is now mode-independent and data-only. No tool-level widget _meta in either mode; runs category entry is a plain ToolEntry instead of a mode map. - New get-actor-run-widget (apps-only) renders the live progress widget. Input is strict: { runId } only. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). Reuses the shared buildGetActorRunSuccessResponse({ widget: true }) helper. - buildGetActorRunSuccessResponse widget branch now also sets openai/widgetDescription on the response _meta, matching the other three widget tools. - Apps server instructions: added the fourth disambiguation bullet pairing get-actor-run (silent data lookup) with get-actor-run-widget (live progress widget), using the same vocabulary as the existing three splits. WORKFLOW_RULES untouched — the "NEVER poll get-actor-run after call-actor-widget" rule is orthogonal. - Deleted src/tools/apps/get_actor_run.ts; widget rendering now lives in the sibling tool rather than a mode toggle. https://claude.ai/code/session_01SF9P6g91UrVMahn4bLsUNf
80e059a to
9b80bc4
Compare
Step 4 of 6 in the #577 umbrella. Mirrors the decoupled-pattern recipe validated by the fetch-actor-details split in #716 / PR #722: - search-actors is now a mode-independent plain ToolEntry that returns pure data. Identical inputSchema / outputSchema / _meta across default and apps modes — no tool-level widget _meta anywhere. - New search-actors-widget (apps-only) renders the interactive UI element. Input is searchActorsBaseArgsSchema.strict() — keywords/limit/offset only, stray keys rejected. Tool- and response-level widget _meta. - search-actors-internal is removed. The base search-actors now serves the silent name-resolution role — no LLM-opaque jargon. - Apps server instructions and call-actor apps description flipped to steer between base (silent data) and -widget (renders an interactive UI element) using the "interactive UI element / widget" vocabulary. File history is preserved via git mv search_actors.ts -> search_actors_widget.ts. https://claude.ai/code/session_01BKQYsF54uFxW7ELzoQbQ3n
…ll actor descriptions
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…ular test Agent-Logs-Url: https://github.com/apify/apify-mcp-server/sessions/ca1ebeb2-8719-4f87-b715-394215202a55 Co-authored-by: jirispilka <19406805+jirispilka@users.noreply.github.com>
7821f21 to
72ada61
Compare
jirispilka
pushed a commit
that referenced
this pull request
Apr 27, 2026
Step 5 of 6 in the #577 umbrella. Mirrors the decoupled-pattern recipe from #716/PR #722 (fetch-actor-details) and #723 (search-actors): - call-actor now always returns pure data in both modes. No tool-level widget _meta anywhere, and buildStartAsyncResponse({ widget: false }) in apps mode returns runId without response-level widget _meta. The apps variant still runs asynchronously. - New call-actor-widget (apps-only) renders the live progress widget. Input is strict: { actor, input, callOptions? } only — async and previewOutput are rejected. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). - Apps server instructions reshaped: the "never poll get-actor-run" rule now scopes to call-actor-widget only; polling after the silent call-actor is fine. Added a third disambiguation bullet pairing call-actor with call-actor-widget using the same "interactive UI element / widget" vocabulary as the other two splits. - buildCallActorDescription alwaysAsync branch flipped to describe the silent-async behavior and point to call-actor-widget for UI. https://claude.ai/code/session_01LPzCFY7ReLm8wvmFHJLyun
jirispilka
pushed a commit
that referenced
this pull request
Apr 27, 2026
Final step (6 of 6) of the #577 umbrella rollout. Mirrors the decoupled-pattern recipe from #722 (fetch-actor-details), #723 (search-actors), and #724 (call-actor): - get-actor-run is now mode-independent and data-only. No tool-level widget _meta in either mode; runs category entry is a plain ToolEntry instead of a mode map. - New get-actor-run-widget (apps-only) renders the live progress widget. Input is strict: { runId } only. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). Reuses the shared buildGetActorRunSuccessResponse({ widget: true }) helper. - buildGetActorRunSuccessResponse widget branch now also sets openai/widgetDescription on the response _meta, matching the other three widget tools. - Apps server instructions: added the fourth disambiguation bullet pairing get-actor-run (silent data lookup) with get-actor-run-widget (live progress widget), using the same vocabulary as the existing three splits. WORKFLOW_RULES untouched — the "NEVER poll get-actor-run after call-actor-widget" rule is orthogonal. - Deleted src/tools/apps/get_actor_run.ts; widget rendering now lives in the sibling tool rather than a mode toggle. https://claude.ai/code/session_01SF9P6g91UrVMahn4bLsUNf
jirispilka
added a commit
that referenced
this pull request
Apr 29, 2026
* feat: Split search-actors into data + -widget tools Step 4 of 6 in the #577 umbrella. Mirrors the decoupled-pattern recipe validated by the fetch-actor-details split in #716 / PR #722: - search-actors is now a mode-independent plain ToolEntry that returns pure data. Identical inputSchema / outputSchema / _meta across default and apps modes — no tool-level widget _meta anywhere. - New search-actors-widget (apps-only) renders the interactive UI element. Input is searchActorsBaseArgsSchema.strict() — keywords/limit/offset only, stray keys rejected. Tool- and response-level widget _meta. - search-actors-internal is removed. The base search-actors now serves the silent name-resolution role — no LLM-opaque jargon. - Apps server instructions and call-actor apps description flipped to steer between base (silent data) and -widget (renders an interactive UI element) using the "interactive UI element / widget" vocabulary. File history is preserved via git mv search_actors.ts -> search_actors_widget.ts. https://claude.ai/code/session_01BKQYsF54uFxW7ELzoQbQ3n * refactor: Remove storeSearchTool and useInternalSearchWarning from call actor descriptions * refactor: Improve error messaging and response structure for empty actor searches * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * fix: reword .strict() comment to reflect AJV strip behavior; fix singular test Agent-Logs-Url: https://github.com/apify/apify-mcp-server/sessions/ca1ebeb2-8719-4f87-b715-394215202a55 Co-authored-by: jirispilka <19406805+jirispilka@users.noreply.github.com> * feat: Split call-actor into data + -widget tools Step 5 of 6 in the #577 umbrella. Mirrors the decoupled-pattern recipe from #716/PR #722 (fetch-actor-details) and #723 (search-actors): - call-actor now always returns pure data in both modes. No tool-level widget _meta anywhere, and buildStartAsyncResponse({ widget: false }) in apps mode returns runId without response-level widget _meta. The apps variant still runs asynchronously. - New call-actor-widget (apps-only) renders the live progress widget. Input is strict: { actor, input, callOptions? } only — async and previewOutput are rejected. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). - Apps server instructions reshaped: the "never poll get-actor-run" rule now scopes to call-actor-widget only; polling after the silent call-actor is fine. Added a third disambiguation bullet pairing call-actor with call-actor-widget using the same "interactive UI element / widget" vocabulary as the other two splits. - buildCallActorDescription alwaysAsync branch flipped to describe the silent-async behavior and point to call-actor-widget for UI. https://claude.ai/code/session_01LPzCFY7ReLm8wvmFHJLyun * fix: Remove storeSearchTool arg dropped from CallActorErrorResponseParams * fix: Address review findings on call-actor split - Remove contradictory 'NEVER call in UI mode' block from get-actor-run description; server instructions already scope the rule to call-actor-widget. - Reject MCP actor:tool syntax in call-actor-widget — previously fell through to a non-widget response. Drop the misleading "For MCP server Actors" hint from the widget input description. - Thread an explicit route parameter through callActorPreExecute so widget vs base traffic separates in telemetry. - Server instructions: drop call-actor from the stale "still on base names" list; scope async-parameter guidance to non-apps mode. - Widget docstring + test title: match silent-strip behavior (matches the correction in 5d4e6dd for the sibling widget). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor: Update ActorSearch widget test to reflect name change in tool * Update src/tools/apps/call_actor_widget.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/tools/core/get_actor_run_common.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
jirispilka
pushed a commit
that referenced
this pull request
Apr 29, 2026
Final step (6 of 6) of the #577 umbrella rollout. Mirrors the decoupled-pattern recipe from #722 (fetch-actor-details), #723 (search-actors), and #724 (call-actor): - get-actor-run is now mode-independent and data-only. No tool-level widget _meta in either mode; runs category entry is a plain ToolEntry instead of a mode map. - New get-actor-run-widget (apps-only) renders the live progress widget. Input is strict: { runId } only. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). Reuses the shared buildGetActorRunSuccessResponse({ widget: true }) helper. - buildGetActorRunSuccessResponse widget branch now also sets openai/widgetDescription on the response _meta, matching the other three widget tools. - Apps server instructions: added the fourth disambiguation bullet pairing get-actor-run (silent data lookup) with get-actor-run-widget (live progress widget), using the same vocabulary as the existing three splits. WORKFLOW_RULES untouched — the "NEVER poll get-actor-run after call-actor-widget" rule is orthogonal. - Deleted src/tools/apps/get_actor_run.ts; widget rendering now lives in the sibling tool rather than a mode toggle. https://claude.ai/code/session_01SF9P6g91UrVMahn4bLsUNf
jirispilka
added a commit
that referenced
this pull request
Apr 29, 2026
* feat: Split get-actor-run into data + -widget tools Final step (6 of 6) of the #577 umbrella rollout. Mirrors the decoupled-pattern recipe from #722 (fetch-actor-details), #723 (search-actors), and #724 (call-actor): - get-actor-run is now mode-independent and data-only. No tool-level widget _meta in either mode; runs category entry is a plain ToolEntry instead of a mode map. - New get-actor-run-widget (apps-only) renders the live progress widget. Input is strict: { runId } only. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). Reuses the shared buildGetActorRunSuccessResponse({ widget: true }) helper. - buildGetActorRunSuccessResponse widget branch now also sets openai/widgetDescription on the response _meta, matching the other three widget tools. - Apps server instructions: added the fourth disambiguation bullet pairing get-actor-run (silent data lookup) with get-actor-run-widget (live progress widget), using the same vocabulary as the existing three splits. WORKFLOW_RULES untouched — the "NEVER poll get-actor-run after call-actor-widget" rule is orthogonal. - Deleted src/tools/apps/get_actor_run.ts; widget rendering now lives in the sibling tool rather than a mode toggle. https://claude.ai/code/session_01SF9P6g91UrVMahn4bLsUNf * chore: Address staff review findings post-split - Drop stale rolling-rollout note from server-instructions header (split is now complete) - Extend "no polling after widget" rule to also cover get-actor-run-widget - Rename integration test to drop misleading "widget" label (it exercises the data tool) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor: Remove paymentRequired flag from get-actor-run tools * Update src/tools/core/get_actor_run_common.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/tools/apps/get_actor_run_widget.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * test: Add integration test for x402 _meta advertising on paid tools (#768) Asserts that tools with paymentRequired: true advertise _meta.x402 with the expected fields (scheme, network, asset, payTo, amount) when the server runs in x402 payment mode, and that free tools do not. Pins the expected paid set with a hardcoded list so silent drift (e.g. a tool losing paymentRequired) is caught here. Tracks #766. * feat: Add paymentRequired flag to get-actor-run tools and update documentation * refactor: Skip tests for auto mode client capabilities and rename itemCount to totalItemCount --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Jakub Kopecký <themq37@gmail.com>
jirispilka
added a commit
that referenced
this pull request
Apr 29, 2026
* feat: Split search-actors into data + -widget tools Step 4 of 6 in the #577 umbrella. Mirrors the decoupled-pattern recipe validated by the fetch-actor-details split in #716 / PR #722: - search-actors is now a mode-independent plain ToolEntry that returns pure data. Identical inputSchema / outputSchema / _meta across default and apps modes — no tool-level widget _meta anywhere. - New search-actors-widget (apps-only) renders the interactive UI element. Input is searchActorsBaseArgsSchema.strict() — keywords/limit/offset only, stray keys rejected. Tool- and response-level widget _meta. - search-actors-internal is removed. The base search-actors now serves the silent name-resolution role — no LLM-opaque jargon. - Apps server instructions and call-actor apps description flipped to steer between base (silent data) and -widget (renders an interactive UI element) using the "interactive UI element / widget" vocabulary. File history is preserved via git mv search_actors.ts -> search_actors_widget.ts. https://claude.ai/code/session_01BKQYsF54uFxW7ELzoQbQ3n * refactor: Remove storeSearchTool and useInternalSearchWarning from call actor descriptions * refactor: Improve error messaging and response structure for empty actor searches * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * fix: reword .strict() comment to reflect AJV strip behavior; fix singular test Agent-Logs-Url: https://github.com/apify/apify-mcp-server/sessions/ca1ebeb2-8719-4f87-b715-394215202a55 Co-authored-by: jirispilka <19406805+jirispilka@users.noreply.github.com> * feat: Split call-actor into data + -widget tools Step 5 of 6 in the #577 umbrella. Mirrors the decoupled-pattern recipe from #716/PR #722 (fetch-actor-details) and #723 (search-actors): - call-actor now always returns pure data in both modes. No tool-level widget _meta anywhere, and buildStartAsyncResponse({ widget: false }) in apps mode returns runId without response-level widget _meta. The apps variant still runs asynchronously. - New call-actor-widget (apps-only) renders the live progress widget. Input is strict: { actor, input, callOptions? } only — async and previewOutput are rejected. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). - Apps server instructions reshaped: the "never poll get-actor-run" rule now scopes to call-actor-widget only; polling after the silent call-actor is fine. Added a third disambiguation bullet pairing call-actor with call-actor-widget using the same "interactive UI element / widget" vocabulary as the other two splits. - buildCallActorDescription alwaysAsync branch flipped to describe the silent-async behavior and point to call-actor-widget for UI. https://claude.ai/code/session_01LPzCFY7ReLm8wvmFHJLyun * fix: Remove storeSearchTool arg dropped from CallActorErrorResponseParams * fix: Address review findings on call-actor split - Remove contradictory 'NEVER call in UI mode' block from get-actor-run description; server instructions already scope the rule to call-actor-widget. - Reject MCP actor:tool syntax in call-actor-widget — previously fell through to a non-widget response. Drop the misleading "For MCP server Actors" hint from the widget input description. - Thread an explicit route parameter through callActorPreExecute so widget vs base traffic separates in telemetry. - Server instructions: drop call-actor from the stale "still on base names" list; scope async-parameter guidance to non-apps mode. - Widget docstring + test title: match silent-strip behavior (matches the correction in 5d4e6dd for the sibling widget). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor: Update ActorSearch widget test to reflect name change in tool * Update src/tools/apps/call_actor_widget.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/tools/core/get_actor_run_common.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * feat: Split get-actor-run into data + -widget tools Final step (6 of 6) of the #577 umbrella rollout. Mirrors the decoupled-pattern recipe from #722 (fetch-actor-details), #723 (search-actors), and #724 (call-actor): - get-actor-run is now mode-independent and data-only. No tool-level widget _meta in either mode; runs category entry is a plain ToolEntry instead of a mode map. - New get-actor-run-widget (apps-only) renders the live progress widget. Input is strict: { runId } only. Tool- and response-level widget _meta (ui.resourceUri = ui://widget/actor-run.html). Reuses the shared buildGetActorRunSuccessResponse({ widget: true }) helper. - buildGetActorRunSuccessResponse widget branch now also sets openai/widgetDescription on the response _meta, matching the other three widget tools. - Apps server instructions: added the fourth disambiguation bullet pairing get-actor-run (silent data lookup) with get-actor-run-widget (live progress widget), using the same vocabulary as the existing three splits. WORKFLOW_RULES untouched — the "NEVER poll get-actor-run after call-actor-widget" rule is orthogonal. - Deleted src/tools/apps/get_actor_run.ts; widget rendering now lives in the sibling tool rather than a mode toggle. https://claude.ai/code/session_01SF9P6g91UrVMahn4bLsUNf * chore: Address staff review findings post-split - Drop stale rolling-rollout note from server-instructions header (split is now complete) - Extend "no polling after widget" rule to also cover get-actor-run-widget - Rename integration test to drop misleading "widget" label (it exercises the data tool) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor: Remove paymentRequired flag from get-actor-run tools * Update src/tools/core/get_actor_run_common.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/tools/apps/get_actor_run_widget.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: Pair widget tools with their base tools instead of unconditional UI auto-include Closes #746. In apps mode, the loader unconditionally appended every entry of the `ui` category whenever any non-empty tool selection was made. A caller asking for `tools: ['docs']` silently received `search-actors-widget`, `fetch-actor-details-widget`, `call-actor-widget`, and `get-actor-run-widget` they did not request — including the paid call-actor widget added in #724. Replace the unconditional `ui` push with a `WIDGET_BY_BASE_TOOL` map keyed by base tool name. After the resolved tool list is composed (and after get-actor-run / get-actor-output auto-inject), append a widget if and only if its base tool is in the result. The existing de-dup pass handles uniqueness. Removes the now-empty `ui` category. Tests updated to assert the new pairing behavior end-to-end via `getToolsForServerMode`. * chore: Note that pairing-pass duplicates are stripped by the de-dup pass Inline reminder at the widget push so a future reader doesn't add a redundant `result.some(...)` guard. * test: Add integration test for x402 _meta advertising on paid tools (#768) Asserts that tools with paymentRequired: true advertise _meta.x402 with the expected fields (scheme, network, asset, payTo, amount) when the server runs in x402 payment mode, and that free tools do not. Pins the expected paid set with a hardcoded list so silent drift (e.g. a tool losing paymentRequired) is caught here. Tracks #766. * feat: Add paymentRequired flag to get-actor-run tools and update documentation * refactor: Skip tests for auto mode client capabilities and rename itemCount to totalItemCount * feat: Include widget tools in apps mode for direct selection * Update tests/unit/utils.tools_loader.test.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * test: Add integration test for x402 _meta advertising on paid tools (#768) Asserts that tools with paymentRequired: true advertise _meta.x402 with the expected fields (scheme, network, asset, payTo, amount) when the server runs in x402 payment mode, and that free tools do not. Pins the expected paid set with a hardcoded list so silent drift (e.g. a tool losing paymentRequired) is caught here. Tracks #766. * feat: Add paymentRequired flag to get-actor-run tools and update documentation * refactor: Skip tests for auto mode client capabilities and rename itemCount to totalItemCount * refactor: Simplify tool selection logic in tools_loader and update tests * feat: Enhance server mode handling for get-actor-run inclusion in tools * feat: Add additional integration test scripts for actor server functionality * feat: Update documentation for widget-base tool pairing and enhance test for duplicate handling * feat: Update types for WIDGET_BY_BASE_TOOL and improve related documentation --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Jakub Kopecký <themq37@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔗 PR chain — part of #577
Step 4 of 6 in the #577 umbrella rollout. Depends on #722 (stacked on
claude/implement-issue-716-5kTwG; rebase tomasteronce #720+#721+#722 merge).openai→appsfetch-actor-detailssplit (pilot)search-actorssplitcall-actorsplitget-actor-runsplitCloses #717.
Summary
Replicates the decoupled-pattern recipe validated in #722 on
search-actors:search-actorsis now one mode-independent tool that returns pure data. IdenticalinputSchema/outputSchema/_metaacross default and apps modes — no tool-level widget_metaanywhere.search-actors-widget(apps-only) renders the interactive UI element. Input issearchActorsBaseArgsSchema.strict()—keywords/limit/offsetonly, stray keys rejected. Output is{ actors, query, count, widgetActors }, matching what the existingsearch-actors-widgetiframe consumes.search-actors-internalis removed. The base tool now serves the silent name-resolution role — no LLM-opaque jargon.call-actordescription flipped to steer between base (silent data) and-widget(renders an interactive UI element) using the "interactive UI element / widget" vocabulary.File history is preserved via
git mv src/tools/apps/search_actors.ts src/tools/apps/search_actors_widget.ts(the old apps variant already built the widget payload, so the widget tool is its closest successor).Test plan
npm run type-checkpassesnpm run lintpassesnpm run test:unitpasses (599/599)npm run buildsucceedstools/liston first call, nonotifications/tools/list_changedemitted in any case:--ui) → onlysearch-actors; base_metahas noui/openai/*keysinitialize.capabilities.extensions['io.modelcontextprotocol/ui']withtext/html;profile=mcp-app→search-actors+search-actors-widget; widget hasui.resourceUri=ui://widget/search-actors.html,ui.visibility=[model,app], non-emptyui.csp(connectDomains,resourceDomains)--ui=true(no caps) → same as B (forced)--ui=false+ UI caps → same as A (override wins)search-actors(name,_meta,inputSchema,outputSchema) byte-identical across all four casesAPIFY_TOKEN)apify-mcp-server-internalimpactHelperTools.STORE_SEARCH_INTERNALremoved. The private repo must not reference the literal'search-actors-internal'or the enum member. Coordinate the audit.search-actorsno longer carriesui.*/openai/*_metain apps mode. Any wrapper that previously read widget config from the base tool's_metamust switch to reading from the-widgetsibling.structuredContentshape ({ actors, query, count, widgetActors }) matches what the existingsearch-actors-widgetiframe already consumes — no web UI changes needed.https://claude.ai/code/session_01BKQYsF54uFxW7ELzoQbQ3n