Skip to content

[pull] main from UsefulSoftwareCo:main - #77

Merged
pull[bot] merged 25 commits into
midego1:mainfrom
UsefulSoftwareCo:main
Sep 15, 2026
Merged

pull[bot] merged 25 commits into
midego1:mainfrom
UsefulSoftwareCo:main

Conversation

@pull

@pull pull Bot commented Sep 15, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

smrht and others added 25 commits September 14, 2026 17:52
)

* fix(openapi): fetch analyticsdata Discovery from the service host

The central Discovery directory does not list the GA4 Data API, so
https://www.googleapis.com/discovery/v1/apis/analyticsdata/v1beta/rest
answers 404 and importing the source fails. Route analyticsdata to its
own host the way forms, keep and photospicker already are.

* Test queue timeout with a controlled clock

* Verify Analytics Data discovery import end to end

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* Advertise refresh-token grant in OAuth client metadata

* Test OAuth metadata through connection and tool use

* Test queue timeout with a controlled clock

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* fix(mcp): shut down scoped executor on session eviction (#1917)

Retain the scoped Executor created for each MCP session and shut it down when an in-memory MCP session is evicted, closed, or fails eager initialization. This ensures child tool subprocesses and connection pools owned by the session are properly cleaned up.

* test(cloud): fix flaky timer precision assertion in session build semaphore test

* Verify MCP session disposal closes upstream resources

* Test queue timeout with a controlled clock

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* fix(mcp): bound discovery connection teardown

Discovery cleanup runs in an interruption-masked finalizer. Bound an unresponsive transport close so a completed tool listing cannot strand health checks or other callers indefinitely.

* test(mcp): match current discovery client contract

* test(mcp): avoid wall-clock teardown assertion

* Exercise discovery teardown with real MCP connections

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
)

* fix(react): honor prefers-reduced-motion in the shared stylesheet

* Test queue timeout with a controlled clock

* Cover reduced motion changes in the browser

---------

Co-authored-by: pt-act <211776491+pt-act@users.noreply.github.com>
Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* Keep artifact deletion optimistic across navigation

* Restore gallery-card delete coverage and bound the Saved artifacts wait in the artifacts e2e

* Test queue timeout with a controlled clock

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* Surface unreachable upstreams as network error

* Test queue timeout with a controlled clock

* Classify transport failures without hiding invocation defects

* Name the integration and origin in the unreachable-upstream message

Executor sends the request, not the user's browser, so "check your
network" pointed at the wrong place. Name the integration and the origin
that could not be reached and tell the user to verify the base URL and
that the service is online. Only the host is lifted off the transport
failure; the path, query, and headers stay out of the message.

* Record the cause of unreachable upstreams without the request

Classifying transport failures as a typed tool result took them off the
hosts' defect path, which was the only place the cause was logged. Lift
the errno-style code (ECONNREFUSED, ENOTFOUND, UND_ERR_SOCKET, ...) off
the fetch cause chain, log a warning and annotate the span with the
integration, host, and code, and return the same sanitized pair in the
tool result details. The raw TransportError stays out of details on
purpose: it carries the whole request, including resolved auth headers.

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* fix(mcp): report completed connected tool

* Test queue timeout with a controlled clock

* Verify connected tool provenance over MCP

* Exclude upstream tool failures from completion metadata

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* Return tool annotations from describe.tool

`ToolSchemaView` carried everything about a tool except the annotations a
plugin declares on it, so code written inside `execute` could not tell an
approval-gated tool from a plain one except by reading its prose description.
The data was already persisted on the tool row and already used by the
executor's own approval copy.

`tools.schema` now projects the three fields declared in `ToolAnnotations`
(`requiresApproval`, `approvalDescription`, `mayElicit`), and `describe.tool`
passes them through. The fields are picked explicitly rather than spread,
because plugins keep private bookkeeping alongside the contract: the mcp
plugin stores its upstream tool name and `_meta` map in the same column, and
none of that should reach a caller.

The key is omitted when a tool declares no annotations, so the describe
payload does not grow for the tools that have nothing to say.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Test queue timeout with a controlled clock

* Verify annotation projections and expose resume failure context

* Model private annotation metadata through the test adapter

* Use the static tool address for schema discovery

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* fix(oauth): request offline_access for Vercel MCP

* Test queue timeout with a controlled clock

* Verify Vercel lifecycle scopes through an OAuth connection

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* fix(cloud): require CSRF state in the WorkOS login callback

* Test queue timeout with a controlled clock

* Exercise browser binding and replay protection for login state

* Capture provider redirect before testing callback state

* Wait for key revocation before checking authentication

---------

Co-authored-by: pt-act <211776491+pt-act@users.noreply.github.com>
Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* Fix HubSpot optional scopes for workspace OAuth

* chore: rerun flaky cloud E2E

* Honor integration-declared HubSpot optional scopes

* Test queue timeout with a controlled clock

* Verify optional OAuth scopes through consent and tool execution

---------

Co-authored-by: Lloyd Vickery <lvickery@Lloyds-MacBook-Pro.local>
Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* Support POST health checks for HTTP RPC APIs

* Preserve existing health-check method behavior

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
…1895)

* trim to the openSession restart-retry backstop

Per review: the concurrency half is superseded by #1907 (already on
main, stricter). Rebased onto current main and kept only the retry
loop on the documented 503 restart envelope.

* Match the exact MCP restart envelope before retrying

* Test queue timeout with a controlled clock

---------

Co-authored-by: pt-act <pt-act@users.noreply.github.com>
Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* fix: use public origin for approval URLs

CLI browser approval links ignored EXECUTOR_WEB_BASE_URL and inherited the
internal HTTP listener scheme, so TLS-proxied deployments got unreachable
http:// URLs.

* fix: skip port-0 web base URL for approval links

CLI --port 0 installs EXECUTOR_WEB_BASE_URL as http://127.0.0.1:0 before
the OS assigns a listen port. Chrome rejects that origin as ERR_UNSAFE_PORT,
so approval URLs fall back to the request origin in that case.

* Exercise browser approvals through a TLS proxy

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* fix(oauth): complete browser callbacks before tool sync

Persist the refreshed OAuth grant and connection before returning the popup callback, then keep remote catalog synchronization alive through the host lifecycle. Preserve synchronous completion for programmatic callers and cover slow MCP discovery with unit and browser E2E tests.

* Verify OAuth callbacks with blocked and failing catalogs

* Release catalog gate before the separate health probe

* Verify OAuth discovery recovery through explicit refresh

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* test: cover hyphenated paths in browser

* refactor: narrow hyphenated artifact path fix

* Test queue timeout with a controlled clock

* Handle single-quoted artifact integration paths

* Use the catalog path for the artifact schema query

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
…ability (#1915)

* Bridge generated-UI `target=_blank` links through the host openLink capability

The sandbox iframe omits allow-popups, so artifact links silently failed. The
trusted renderer now relays a user click across the frame boundary, guarded by
a per-render closure nonce, and the host opens only http(s) URLs.

* Test queue timeout with a controlled clock

* Prevent generated artifacts from replacing link authorization

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* fix(mcp): pause active timeout during elicitation

* Test approval waits beyond the MCP active-work deadline

* Test queue timeout with a controlled clock

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* Add search and invoke MCP mode

* Preserve full annotations in MCP scenario decoding
* Return artifact source from show-artifact

* Preserve artifact deletion regression coverage

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* fix(mcp): pause active timeout during elicitation

* Carry an approval's persistence choice through elicitation

Codex Computer Use offers `persist: ["session", "always"]` in the terms of
its "Allow Computer Use to use X?" prompt and remembers the app only when
the answer names one. Executor lost the offer on the way in — the terms
projection kept strings only — and the choice on the way out, because every
adapter rebuilt the reply from `action` and `content`. So each accept was a
one-time approval and the same app prompted on every call.

- `ElicitationResponse.meta.persist` carries the choice; the vocabulary is
  closed so no host can grant more than the prompt offered.
- `approvalTerms` keeps string lists, so the offered scopes reach the host.
- The MCP plugin, the app-server bridge, and the MCP host (native mode)
  pass `_meta` through in both directions.
- The model-mode `resume` tool takes `persist`; the pause output names the
  offered scopes and says a bare accept is one-time.
- The HTTP resume API takes `persist`, and the browser approval page offers
  the scopes in a select. Nothing is chosen automatically.

Fixes #1962

* Preserve approval lifetime through browser and cloud resume paths

* Test approval waits beyond the MCP active-work deadline

* Test queue timeout with a controlled clock

* Test queue timeout with a controlled clock

---------

Co-authored-by: mikemikimike <13286568797@163.com>
Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* test(host-cloudflare): classify toolkit MCP paths

* fix(cloudflare): bind MCP sessions to their resource

* fix(host-cloudflare): serve toolkit MCP routes

* style: format toolkit route changes

* fix(mcp): pause active timeout during elicitation

* Carry an approval's persistence choice through elicitation

Codex Computer Use offers `persist: ["session", "always"]` in the terms of
its "Allow Computer Use to use X?" prompt and remembers the app only when
the answer names one. Executor lost the offer on the way in — the terms
projection kept strings only — and the choice on the way out, because every
adapter rebuilt the reply from `action` and `content`. So each accept was a
one-time approval and the same app prompted on every call.

- `ElicitationResponse.meta.persist` carries the choice; the vocabulary is
  closed so no host can grant more than the prompt offered.
- `approvalTerms` keeps string lists, so the offered scopes reach the host.
- The MCP plugin, the app-server bridge, and the MCP host (native mode)
  pass `_meta` through in both directions.
- The model-mode `resume` tool takes `persist`; the pause output names the
  offered scopes and says a bare accept is one-time.
- The HTTP resume API takes `persist`, and the browser approval page offers
  the scopes in a select. Nothing is chosen automatically.

Fixes #1962

* Preserve approval lifetime through browser and cloud resume paths

* Test approval waits beyond the MCP active-work deadline

* Test queue timeout with a controlled clock

* Test queue timeout with a controlled clock

* Verify toolkit session isolation across resources and methods

---------

Co-authored-by: Don Pansacola <1178461+donmasakayan@users.noreply.github.com>
Co-authored-by: mikemikimike <13286568797@163.com>
Co-authored-by: Dara Adedeji <shawnadedeji@gmail.com>
Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
* Add payment method update to billing page

* Change an existing card through the billing portal

* Recover the card button when the payment form fails to open

* Bump @executor-js/emulate to 0.14.2

* Handle payment form failures with Effect
@pull pull Bot locked and limited conversation to collaborators Sep 15, 2026
@pull pull Bot added the ⤵️ pull label Sep 15, 2026
@pull
pull Bot merged commit 7422219 into midego1:main Sep 15, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.