feat: Split fetch-actor-details into data + -widget tools#722
Merged
jirispilka merged 5 commits intomasterfrom Apr 27, 2026
Merged
feat: Split fetch-actor-details into data + -widget tools#722jirispilka merged 5 commits intomasterfrom
jirispilka merged 5 commits intomasterfrom
Conversation
This was referenced Apr 19, 2026
jirispilka
pushed a commit
that referenced
this pull request
Apr 19, 2026
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
12 tasks
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
112d214 to
f9c12ca
Compare
527ad06 to
e23510a
Compare
jirispilka
pushed a commit
that referenced
this pull request
Apr 20, 2026
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
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
jirispilka
pushed a commit
that referenced
this pull request
Apr 22, 2026
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
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
Contributor
There was a problem hiding this comment.
Pull request overview
Implements the decoupled “data tool + -widget sibling” pattern for fetch-actor-details, making the base tool mode-independent and introducing an apps-only widget tool for UI rendering.
Changes:
- Removes widget
_metafrom the basefetch-actor-detailstool and makes it shared across modes. - Adds
fetch-actor-details-widget(apps-only) with strictactor-only input and widget-shaped structured output. - Updates tool registration, constants, server instructions, and unit/integration tests to reflect the new tool split and removal of
fetch-actor-details-internal.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/const.ts | Replaces ACTOR_GET_DETAILS_INTERNAL with ACTOR_GET_DETAILS_WIDGET. |
| src/tools/categories.ts | Makes fetch-actor-details mode-independent; registers fetch-actor-details-widget in ui (apps-only). |
| src/tools/core/fetch_actor_details_common.ts | Removes tool-level widget _meta; simplifies base handler route handling. |
| src/tools/default/fetch_actor_details.ts | Updates base tool call to match new shared handler signature. |
| src/tools/structured_output_schemas.ts | Adds actorDetailsWidgetOutputSchema for the new widget tool. |
| src/tools/apps/fetch_actor_details_widget.ts | Introduces the new apps-only widget tool implementation. |
| src/tools/apps/fetch_actor_details.ts | Deletes old apps-mode variant (widget-on-base behavior). |
| src/tools/apps/fetch_actor_details_internal.ts | Deletes the old internal silent lookup tool. |
| src/tools/apps/search_actors.ts | Updates guidance text to steer between base vs widget details tools. |
| src/tools/core/call_actor_common.ts | Narrows helper-tool typing to the base details tool (no internal variant). |
| src/tools/apps/call_actor.ts | Updates to reference the base details tool constant. |
| src/utils/server-instructions/index.ts | Updates rollout/disambiguation wording for the per-tool -widget migration. |
| tests/unit/utils.tools_loader.test.ts | Updates expected apps UI tool names to include the new widget tool. |
| tests/unit/tools.search_actors.widget.response.test.ts | Updates expected instruction text to reference fetch-actor-details-widget + base tool. |
| tests/unit/tools.mode_contract.test.ts | Updates apps ui category expectations; adds assertion that base details tool has no widget meta. |
| tests/unit/tools.call_actor_common.test.ts | Updates expected helper-tool names in apps descriptions/error responses. |
| tests/unit/tools.fetch_actor_details.widget.response.test.ts | Adds unit coverage for the new widget tool response/meta/schema behavior. |
| tests/integration/suite.ts | Updates integration expectations to call/validate fetch-actor-details-widget in apps mode. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Collaborator
Author
|
@copilot please fix all the review comments, they make sense |
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
Contributor
MQ37
left a comment
There was a problem hiding this comment.
LGTM — solid refactor, great tests.
One personal preference on naming: I find getActors() and getActorsAsTools() confusing since both return ToolEntry[] but at different abstraction levels. I'd suggest:
getActorsAsTools→fetchActorsAsTools(it hits the Apify API)getActors→getActorsFromInput(resolves actor names fromInput)
Not blocking — ship it!
b784f4d to
6cc397d
Compare
28c8530 to
72114c7
Compare
jirispilka
pushed a commit
that referenced
this pull request
Apr 27, 2026
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
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
72114c7 to
80e059a
Compare
Decoupled-pattern pilot (#716, part of #577): - fetch-actor-details is now one mode-independent tool returning pure data. - New fetch-actor-details-widget (apps-only) renders the interactive UI element with only { actorDetails: { actorInfo, readme } }. - Removed fetch-actor-details-internal; the base tool now serves the silent lookup role. - Updated apps server instructions and search-actors/call-actor guidance to steer between silent data lookups and widget rendering. https://claude.ai/code/session_01ZsYYZ6u64jAWyxj3GTPwpG
…improve server instructions - Renamed `detectClientSupportsUi` to `isUiSupportedByClient` for better readability and alignment with other methods. - Updated initialize handler to include mode-aware server instructions in response payload. - Enhanced `getServerInstructions` to dynamically include apps-specific sections based on server mode, avoiding irrelevant content for default-mode clients.
…riant refs, actorCard in widget contract
- `fetchActorDetailsWidgetArgsSchema` comment now reflects that AJV
`removeAdditional: true` silently strips stray keys (Zod `.strict()` is
belt-and-braces for any path that bypasses AJV).
- `fetchActorDetailsToolArgsSchema` / `fetchActorDetailsMetadata` docstrings
no longer claim a separate "apps variant" exists — the base tool is
mode-independent and the `-widget` sibling has its own schema/metadata.
- Widget response test docstring + it-title + assertions now match the
actual `{ actorDetails: { actorInfo, actorCard, readme } }` contract.
https://claude.ai/code/session_01ZsYYZ6u64jAWyxj3GTPwpG
80e059a to
9b80bc4
Compare
jirispilka
pushed a commit
that referenced
this pull request
Apr 27, 2026
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
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> --------- 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
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 3 of 6. Stacked on #721; rebase to
masteronce #720+#721 merge.closes #716
Closes #716.
Summary
Pilot of the decoupled pattern on
fetch-actor-details:fetch-actor-detailsis mode-independent, data-only. No widget_metaon the base tool in either mode.fetch-actor-details-widget(apps-only). Strict input (actoronly). Output:{ actorDetails: { actorInfo, actorCard, readme } }.fetch-actor-details-internalremoved — base tool covers silent lookup.File history preserved via
git mv src/tools/apps/fetch_actor_details.ts src/tools/apps/fetch_actor_details_widget.ts.Test plan
npm run type-checknpm run lintnpm run test:unit(597/597)npm run buildtools/liststable, notools/list_changed:fetch-actor-detailsonly, no widget_meta-widget(widgetui.resourceUri,visibility=[model,app], non-emptycsp)--ui on→ same as auto+UI (forced)--ui off+ UI caps → same as default (override wins)ActorSearchDetailpaths on stdio/SSE/streamable-HTTP)`apify-mcp-server-internal` impact
https://claude.ai/code/session_01ZsYYZ6u64jAWyxj3GTPwpG