Skip to content

feat: Split call-actor into data + -widget tools#724

Merged
jirispilka merged 12 commits intomasterfrom
claude/call-actor-split-I2C7T
Apr 29, 2026
Merged

feat: Split call-actor into data + -widget tools#724
jirispilka merged 12 commits intomasterfrom
claude/call-actor-split-I2C7T

Conversation

@jirispilka
Copy link
Copy Markdown
Collaborator

@jirispilka jirispilka commented Apr 20, 2026

🔗 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 to master once #720#723 merge).

# Issue PR Status
1 #714 — Rename openaiapps #720 in review
2 #715 — Capability auto-detect + gating #721 in review
3 #716fetch-actor-details split (pilot) #722 in review
4 #717search-actors split #723 in review
5 #718call-actor split this PR in review
6 #719get-actor-run split #734 in review

Closes #718.

Note on #594 (async call-actor redesign): #594 is an independent track that makes call-actor always return immediately with a uniform {runId, status, storages, hint} shape and adds waitSecs to get-actor-run. Once #594 lands, the silent-variant rationale for call-actor-widget should be re-evaluated — the split may become redundant or shrink to just stripping _meta in apps mode. Pairing/auto-include follow-up tracked in #746.


Summary

Applies the decoupled-pattern recipe validated in #722 / #723 to call-actor. Approach A (split) chosen — see "A vs B decision" below.

  • call-actor now returns pure data in both modes. No tool-level widget _meta anywhere; 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.
  • New call-actor-widget (apps-only) renders the live progress widget.
  • Apps server instructions: the "NEVER poll get-actor-run after call-actor" rule is scoped to call-actor-widget only; polling after the silent call-actor is fine and expected. A third disambiguation bullet pairs call-actor (silent async start, no UI) with call-actor-widget (renders live progress widget) using the same vocabulary as the other two splits.

Decision

Test plan

  • npm run type-check passes
  • npm run lint passes
  • npm run test:unit passes (607/607)
  • npm run build succeeds
  • mcpc-style JSON-RPC probe matrix — verified tools/list on first call, no notifications/tools/list_changed emitted in any case:
    • A default (no UI caps, no --ui) → only call-actor; no -widget; base _meta has no ui/openai/* keys
    • B --ui=truecall-actor + call-actor-widget; widget has ui.resourceUri=ui://widget/actor-run.html, ui.visibility=[model,app], non-empty ui.csp
    • Base call-actor inputSchema byte-identical across modes
  • mcpc tool-call sanity (real APIFY_TOKEN):
    • call-actor default async → {runId, actorName, status, startedAt, input}, no widget meta
    • call-actor apps (silent) → {runId, ...}, no widget meta
    • call-actor-widget apps → {runId, ...} + response-level widget _meta with openai/widgetDescription
  • Integration tests (human-run — needs APIFY_TOKEN)
  • Manual real-session evidence: MCPJam picks under varied prompts ("run X", "run X silently", "show me progress") — record findings before merge

apify-mcp-server-internal impact

  • HelperTools.ACTOR_CALL_WIDGET is new; no existing references to remove.
  • Base call-actor no longer carries ui.* / openai/* _meta in any mode (apps or default). Any wrapper in the private repo that previously read widget config from call-actor's _meta (to render progress in apps mode) must switch to reading from call-actor-widget.
  • Widget response structuredContent shape ({ runId, actorName, status, startedAt, input }) is unchanged vs the previous apps-mode call-actor response — the actor-run-widget iframe already consumes it.
  • Apps server instructions: the "NEVER poll get-actor-run after call-actor" rule now scopes to call-actor-widget. If the internal repo overrides instructions, mirror the scope change.

https://claude.ai/code/session_01LPzCFY7ReLm8wvmFHJLyun

image image

@jirispilka jirispilka changed the title Add call-actor-widget tool for interactive Actor run progress UI feat: Add call-actor-widget tool for interactive Actor run progress UI Apr 20, 2026
@jirispilka jirispilka changed the title feat: Add call-actor-widget tool for interactive Actor run progress UI feat: Split call-actor into data + -widget tools Apr 20, 2026
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
@jirispilka jirispilka force-pushed the claude/search-actors-decoupled-pattern-awSCQ branch from e7d755e to 3f2503b Compare April 20, 2026 21:35
@jirispilka jirispilka force-pushed the claude/call-actor-split-I2C7T branch from 57df5bc to 8b19378 Compare April 20, 2026 21:36
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
@jirispilka jirispilka force-pushed the claude/search-actors-decoupled-pattern-awSCQ branch from 3f2503b to a833d7f Compare April 22, 2026 15:38
@jirispilka jirispilka force-pushed the claude/call-actor-split-I2C7T branch from 8b19378 to 66c1cae Compare April 22, 2026 15:39
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
@jirispilka jirispilka force-pushed the claude/search-actors-decoupled-pattern-awSCQ branch from a833d7f to fab37f4 Compare April 24, 2026 11:11
@jirispilka jirispilka force-pushed the claude/call-actor-split-I2C7T branch from 66c1cae to 153dc48 Compare April 24, 2026 14:42
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
@jirispilka
Copy link
Copy Markdown
Collaborator Author

Follow-up tracked in #746 — widget tools should pair with their base tools instead of being unconditionally auto-included via the ui category. That fix lands post-#724 to avoid a window where call-actor-widget is dangerously auto-sprayed into restricted tool sets like tools: ['docs'].

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 _meta from base call-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 _meta for 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.

Comment thread src/tools/categories.ts
Comment thread src/tools/apps/call_actor_widget.ts Outdated
Comment thread src/tools/core/get_actor_run_common.ts
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
@jirispilka jirispilka force-pushed the claude/search-actors-decoupled-pattern-awSCQ branch from 5d4e6dd to 7821f21 Compare April 27, 2026 11:32
@jirispilka jirispilka force-pushed the claude/call-actor-split-I2C7T branch from 5422636 to 48ac831 Compare April 27, 2026 11:35
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 jirispilka self-assigned this Apr 27, 2026
@jirispilka jirispilka added the t-ai Issues owned by the AI team. label Apr 27, 2026
@jirispilka jirispilka requested a review from MQ37 April 27, 2026 11:47
@jirispilka jirispilka marked this pull request as ready for review April 27, 2026 11:48
claude and others added 5 commits April 27, 2026 20:30
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
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@jirispilka jirispilka force-pushed the claude/search-actors-decoupled-pattern-awSCQ branch from 7821f21 to 72ada61 Compare April 27, 2026 18:33
claude and others added 6 commits April 27, 2026 21:51
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>
@jirispilka jirispilka force-pushed the claude/call-actor-split-I2C7T branch from 48ac831 to f1764e6 Compare April 27, 2026 19:52
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
Copy link
Copy Markdown
Contributor

@MQ37 MQ37 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Base automatically changed from claude/search-actors-decoupled-pattern-awSCQ to master April 29, 2026 07:36
# 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
@github-actions github-actions Bot added the tested Temporary label used only programatically for some analytics. label Apr 29, 2026
@jirispilka jirispilka merged commit 92870a6 into master Apr 29, 2026
12 checks passed
@jirispilka jirispilka deleted the claude/call-actor-split-I2C7T branch April 29, 2026 07:51
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

t-ai Issues owned by the AI team. tested Temporary label used only programatically for some analytics.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Split call-actor into data + -widget tools

6 participants