Skip to content

feat(tools): add target_client_id to host_file_* and computer_use_* tools#29397

Merged
credence-the-bot[bot] merged 1 commit into
Credence/targeted-host-proxy-phase2from
Credence/targeted-host-proxy-phase2-pr3
May 3, 2026
Merged

feat(tools): add target_client_id to host_file_* and computer_use_* tools#29397
credence-the-bot[bot] merged 1 commit into
Credence/targeted-host-proxy-phase2from
Credence/targeted-host-proxy-phase2-pr3

Conversation

@credence-the-bot
Copy link
Copy Markdown
Contributor

@credence-the-bot credence-the-bot Bot commented May 3, 2026

Adds optional target_client_id field to host_file_read, host_file_write, host_file_edit schemas and all 8 computer_use_* action tools schemas. Threads it from executor through to the proxy request call. Includes multi-client guard (requires explicit target when >1 capable client from non-host-proxy interface). Depends on PR #29394 (core proxy changes, already merged into feature branch).


Open in Devin Review

…ools

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@credence-the-bot credence-the-bot Bot merged commit 0eb6e76 into Credence/targeted-host-proxy-phase2 May 3, 2026
11 of 12 checks passed
@credence-the-bot credence-the-bot Bot deleted the Credence/targeted-host-proxy-phase2-pr3 branch May 3, 2026 13:22
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9e7b58fd91

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +72 to +76
targetClientId == null &&
transportInterface != null &&
!supportsHostProxy(transportInterface) &&
assistantEventHub.listClientsByCapability("host_file").length > 1
) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reject disconnected explicit host_file target before fallback

The new target_client_id path only guards the targetClientId == null case, so if a caller specifies a target that disconnects before execution, this code skips the ambiguity check and later falls through to local filesystem execution when HostFileProxy.instance.isAvailable() is false. That can run host_file_read/write/edit against the daemon/container filesystem instead of the intended host client, which is a correctness and safety regression introduced by adding explicit targeting.

Useful? React with 👍 / 👎.

Comment on lines 1792 to +1795
ctx.hostCuProxy.stepCount,
reasoning,
signal,
targetClientId,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Validate computer_use target client before dispatch

Passing target_client_id straight into hostCuProxy.request without checking that the client is still connected and has host_cu capability causes a bad/stale ID to hang until proxy timeout instead of failing fast. This is newly introduced by threading target_client_id through CU actions; a typo or stale ID now adds repeated 60s delays per step in multi-client sessions.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 2 potential issues.

View 1 additional finding in Devin Review.

Open in Devin Review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Missing target_client_id on computer_use_observe — incomplete transformation across proxied CU tools

The PR adds target_client_id to every proxied computer-use tool definition in definitions.ts (click, type_text, key, scroll, drag, wait, open_app, run_applescript) but omits it from computer_use_observe. The observe tool IS proxied to the client — it falls through to the non-terminal branch in surfaceProxyResolver at assistant/src/daemon/conversation-surfaces.ts:1787-1796, where targetClientId is extracted from input.target_client_id and forwarded to ctx.hostCuProxy.request(). Without the property in the observe tool's schema (properties: {} at line 498), the LLM has no way to provide a target_client_id for observe calls, so in multi-client setups the observation request cannot be targeted to a specific client. Terminal tools (computer_use_done, computer_use_respond) correctly omit it since they resolve locally without a client round-trip.

(Refers to lines 496-499)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚩 Pre-existing: buildUserFacingLabel reads cancelLabel for deny action

At conversation-surfaces.ts:1724, the deny branch reads surfaceData?.cancelLabel instead of surfaceData?.denyLabel. This means the deny action's user-facing label falls back to the cancel button's label rather than a dedicated deny label. This is a pre-existing issue not introduced by this PR, but it's in adjacent unchanged code within the same function.

(Refers to lines 1724-1726)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

credence-the-bot Bot added a commit that referenced this pull request May 3, 2026
…ools (#29397)

Co-authored-by: credence-the-bot <credence@vellum.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
noanflaherty pushed a commit that referenced this pull request May 3, 2026
…29398)

* feat(host-proxy): add targetClientId support to HostFileProxy and HostProxyBase

- Add targetClientId to HostFileReadRequest, HostFileWriteRequest, HostFileEditRequest, HostFileCancelRequest
- Add targetClientId to HostCuRequest and HostCuCancelRequest
- HostFileProxy.request() resolves target client (auto-resolve single, validate explicit, undefined for untargeted)
- Thread targetClientId through all broadcastMessage calls (request, abort cancel, dispose cancel)
- Add targetClientId to HostProxyBase.PendingEntry and dispatchRequest (covers HostCuProxy via inheritance)
- Update broadcastDynamic to accept and forward targetClientId as options to broadcastMessage
- Register targetClientId in assistant-event-hub.ts for host_file and host_cu pending interactions

Co-authored-by: credence-the-bot <credence@vellum.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(routes): enforce targetClientId binding on host-file-result and host-cu-result (#29395)

Co-authored-by: credence-the-bot <credence-the-bot@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(tools): add target_client_id to host_file_* and computer_use_* tools (#29397)

Co-authored-by: credence-the-bot <credence@vellum.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(macos): targetClientId acceptance guard and result header for host_file and host_cu (#29396)

Co-authored-by: credence-the-bot <credence-the-bot@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(host-proxy): unit + route tests for Phase 2 targetClientId (#29402)

Adds targeted tests for Phase 2 proxy changes:
- HostFileProxy target resolution (auto-resolve, explicit validate,
  unknown/incapable client rejection, cancel with targetClientId,
  timeout message with clientId)
- host-file-result route 403 guard (correct/missing/wrong
  x-vellum-client-id header, untargeted regression)
- host-cu-result route 403 guard (same 4 cases, mocked conversation
  store via dynamic import to avoid deep service-contracts chain)
- target_client_id passthrough to HostFileProxy.instance.request in
  host_file_read, host_file_write, and host_file_edit tools

Co-authored-by: credence-the-bot <credence@vellum.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(host-proxy): update TOOLS.json, test mock, and openapi spec for Phase 2

- Add target_client_id to 8 CU action tools in bundled TOOLS.json manifest
- Add listClientsByCapability/getClientById to host-file-proxy test mock
- Regenerate openapi.yaml: adds 400/403 responses to host-cu-result and host-file-result routes

* fix(host-proxy): correct Phase 2 proxy fixes for file/cu routes

- Add `additionalResponses` to host-file-routes and host-cu-routes so the
  OpenAPI generator emits the 400/403 responses into the spec
- Use ConflictError→ForbiddenError (HTTP 403) for wrong-client submissions
- Read targetClientId from input object (tool callers embed it there) in
  addition to the legacy 4th parameter path
- Differentiate error messages: unknown client vs incapable client
- Include resolvedTargetClientId in request/cancel/dispose message bodies
  so receiving clients can verify the intended target
- Update timeout message to name the targeted clientId
- Fix getByKind mock to return {requestId, ...interaction} matching the
  real pending-interactions implementation
- Rename resolveResult→resolve in HostFileProxy (aligns with host-bash pattern)

All 9 host-file-proxy-targeted tests now pass (was 1/9).

* fix(host-proxy): trim x-vellum-client-id, descriptive 403 message, fix test mocks

Routes:
- Trim x-vellum-client-id header; treat whitespace-only as missing (BadRequestError)
  Fixes test: 'throws BadRequestError (400) when header is empty string'
- ForbiddenError message now names both submitting and expected client IDs
  e.g. 'Client "B" is not the target for this request (expected "A")'
  Fixes test: 'ForbiddenError message names both submitting and expected client'

Tests:
- host-file-routes-targeted: HostFileProxy.resolve mock now simulates
  pending-interaction consumption (delete from store + push to resolvedIds)
  Fixes tests: 'returns { accepted: true } and resolves the interaction'
  and 'untargeted request accepts when no header is provided'
- host-cu-routes-targeted: hostCuProxy.resolve → processObservation;
  processObservation mock simulates pending-interaction cleanup;
  conversationStore type updated accordingly
  Fixes all 6 remaining host-cu route test failures
- Both route test files: expand env mock to prevent Bun module-bleed
  when test files are run together locally
- host-file-proxy.test.ts: rename resolveResult → resolve (method was
  renamed in the previous commit)

* fix(host-proxy): trim header + descriptive 403 msg + fix host-cu-routes test mock

Routes (host-cu-routes.ts, host-file-routes.ts):
- Trim x-vellum-client-id before comparison; whitespace-only → BadRequestError
- ForbiddenError message names both client IDs:
  'Client "B" is not the target for this request (expected "A")'

Tests (host-cu-routes-targeted.test.ts):
- conversationStore type: resolve → processObservation
- registerConversation: hostCuProxy.resolve → processObservation with
  pending-interaction cleanup (matches real processObservation behaviour)
- Expand env mock to prevent Bun module-bleed when files run together

* fix(host-cu-proxy): include targetClientId in request body and cancel messages

Three fixes mirroring the pattern established in host-file-proxy.ts:

1. host_cu_request body: add `...(targetClientId != null ? { targetClientId } : {})`
   so the Swift HostCuRequest.targetClientId field is non-nil and
   EventStreamClient.shouldIgnoreHostToolRequest bypasses the
   conversation-ownership filter for cross-client targeted requests.

2. abort-cancel (onAbort): pass targetClientId in host_cu_cancel body
   and as broadcastMessage routing options so the cancel reaches the
   correct targeted client.

3. dispose-cancel: same fix using entry.targetClientId from the
   pending interaction record.

Resolves Devin 🔴 BUG_0002 and BUG_0003 on commit 4e7fcbc.

---------

Co-authored-by: credence-the-bot[bot] <277301654+credence-the-bot[bot]@users.noreply.github.com>
Co-authored-by: credence-the-bot <credence@vellum.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: credence-the-bot <credence-the-bot@users.noreply.github.com>
Co-authored-by: credence-the-bot[bot] <credence-the-bot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants