feat: Split call-actor into data + -widget tools#724
Conversation
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
e7d755e to
3f2503b
Compare
57df5bc to
8b19378
Compare
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
3f2503b to
a833d7f
Compare
8b19378 to
66c1cae
Compare
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
66c1cae to
153dc48
Compare
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
There was a problem hiding this comment.
Pull request overview
Part of the #577 decoupled-pattern rollout: splits call-actor into a mode-independent, data-only tool and introduces an apps-only call-actor-widget sibling for rendering the live progress widget, while updating instructions and tests to reflect the new separation.
Changes:
- Removed widget
_metafrom basecall-actor(default + apps) so it returns pure data in all modes. - Added
call-actor-widget(apps-only) that starts the run and returns response-level widget_metafor the progress UI. - Updated server instructions and unit/integration tests to reflect the new base vs widget tool behavior and guidance.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/tools.mode_contract.test.ts | Updates mode-contract expectations for new call-actor-widget and base-tool no-widget-meta assertions. |
| tests/unit/tools.call_actor_widget.response.test.ts | Adds unit tests validating call-actor-widget response shape, widget _meta, and strict input behavior. |
| tests/unit/tools.call_actor_common.test.ts | Updates description-building expectations for apps-mode call-actor guidance (silent async + points to widget). |
| tests/integration/suite.ts | Updates integration assertions to expect widget meta on *-widget tools and calls search-actors-widget in widget test. |
| src/utils/server-instructions/index.ts | Adjusts apps-mode workflow rules and disambiguation to include call-actor-widget and scope “don’t poll” rule to it. |
| src/tools/default/call_actor.ts | Removes tool-level widget _meta; routes pre-execution logging via callActorPreExecute(..., { route }). |
| src/tools/core/get_actor_run_common.ts | Removes legacy “never call after call-actor in UI mode” block; updates usage guidance. |
| src/tools/core/call_actor_common.ts | Updates apps-mode description text (silent async + widget sibling), and adds route option to callActorPreExecute. |
| src/tools/categories.ts | Registers call-actor-widget in the ui category for apps mode. |
| src/tools/apps/call_actor_widget.ts | Introduces the new apps-only widget tool with tool-level + response-level widget _meta. |
| src/tools/apps/call_actor.ts | Removes widget _meta and ensures apps call-actor returns non-widget async-start response. |
| src/const.ts | Adds HelperTools.ACTOR_CALL_WIDGET constant. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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
5d4e6dd to
7821f21
Compare
5422636 to
48ac831
Compare
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
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
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
- 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>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
48ac831 to
f1764e6
Compare
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
There was a problem hiding this comment.
Heads-up on Skyfire: call-actor-widget is the first widget split with paymentRequired: true. Its ajvValidate is compiled from a .strict() schema; Skyfire's decorateToolSchema adds skyfire-pay-id to advertised properties but doesn't recompile the validator. In practice removePaymentFields strips it before AJV runs, so it's masked. Base call-actor sidesteps this with additionalProperties: true (call_actor_common.ts:269).
Skyfire skyfire-pay-id input passing should work — worth retesting on staging with a real PAY JWT before release.
# Conflicts: # src/utils/server-instructions/index.ts # tests/integration/suite.ts # tests/unit/tools.call_actor_common.test.ts # tests/unit/tools.mode_contract.test.ts
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
* 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>
* 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>
🔗 PR chain — part of #577
Step 5 of 6 in the #577 umbrella rollout. Depends on #723 (stacked on
claude/search-actors-decoupled-pattern-awSCQ; rebase tomasteronce #720–#723 merge).openai→appsfetch-actor-detailssplit (pilot)search-actorssplitcall-actorsplitget-actor-runsplitCloses #718.
Summary
Applies the decoupled-pattern recipe validated in #722 / #723 to
call-actor. Approach A (split) chosen — see "A vs B decision" below.call-actornow returns pure data in both modes. No tool-level widget_metaanywhere; The apps variant still runs asynchronously (it started that way in refactor: Adopt MCP Apps decoupled pattern for UI tools #577, and stays that way.call-actor-widget(apps-only) renders the live progress widget.get-actor-runaftercall-actor" rule is scoped tocall-actor-widgetonly; polling after the silentcall-actoris fine and expected. A third disambiguation bullet pairscall-actor(silent async start, no UI) withcall-actor-widget(renders live progress widget) using the same vocabulary as the other two splits.Decision
get-actor-run/ fetchget-actor-outputwithout forcing the user to look at a progress widget. This matters when the Actor is a subroutine (e.g. an intermediate scrape before synthesis) rather than the answer.Test plan
npm run type-checkpassesnpm run lintpassesnpm run test:unitpasses (607/607)npm run buildsucceedstools/liston first call, nonotifications/tools/list_changedemitted in any case:--ui) → onlycall-actor; no-widget; base_metahas noui/openai/*keys--ui=true→call-actor+call-actor-widget; widget hasui.resourceUri=ui://widget/actor-run.html,ui.visibility=[model,app], non-emptyui.cspcall-actorinputSchemabyte-identical across modesAPIFY_TOKEN):call-actordefault async →{runId, actorName, status, startedAt, input}, no widget metacall-actorapps (silent) →{runId, ...}, no widget metacall-actor-widgetapps →{runId, ...}+ response-level widget_metawithopenai/widgetDescriptionAPIFY_TOKEN)apify-mcp-server-internalimpactHelperTools.ACTOR_CALL_WIDGETis new; no existing references to remove.call-actorno longer carriesui.*/openai/*_metain any mode (apps or default). Any wrapper in the private repo that previously read widget config fromcall-actor's_meta(to render progress in apps mode) must switch to reading fromcall-actor-widget.{ runId, actorName, status, startedAt, input }) is unchanged vs the previous apps-modecall-actorresponse — theactor-run-widgetiframe already consumes it.call-actor-widget. If the internal repo overrides instructions, mirror the scope change.https://claude.ai/code/session_01LPzCFY7ReLm8wvmFHJLyun