feat(surface): trigger namespaces for every relayfile adapter with webhooks - #456
Conversation
Regenerated `packages/surface/src/triggers/github.ts` from the core GitHub mapping in AgentWorkforce/relayfile-adapters#279, which declares `check_run` and `issue_comment` as action-bearing webhook keys. The surface gains `github.check_run(action?)` and `github.issue_comment(action?)` — the two events a PR reviewer needs for merge-on-green and comment-driven directives — and `providerEventTypes.github` lists them, so `flows check` admits a subscription to either instead of refusing it as unpublished. Generated with the adapters checkout's `packages/core/mappings` alone, which is byte-for-byte what the published `@relayfile/adapter-core` tarball will carry, so `generate-triggers.mjs --check` reproduces these files once the SDK's pinned adapter-core is bumped to the release that contains #279. Until that bump the check refuses, by design. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The GitHub source setting `events` (AgentWorkforce/cloud#3772) selects which records wake a listener: `issues` (default) or `pull_request`. The CLI validates it client-side like the other settings and the doc describes the pull-request run's input. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The release carrying relayfile-adapters#279 (`check_run` and `issue_comment` webhook keys). `generate-triggers.mjs` against the installed tarball reproduces the committed trigger modules byte for byte, and `--check` passes again. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…bhooks `scripts/generate-triggers.mjs` read only the mapping YAML that @relayfile/adapter-core bundles, and that was the two core fallbacks, so `flow().on(...)` could subscribe to Slack and GitHub and nothing else, although relayfile ingests events from 47 providers. The generator now applies three sources per provider: the core fallback mappings, each adapter's own mapping (`mappings/adapters/` in the package since relayfile-adapters#280, or `packages/<adapter>/` in a checkout) which supersedes the fallback as a whole, and the trigger catalog (`@relayfile/adapter-core/triggers`, fed by every adapter's `supportedEvents()`) for providers with no `webhooks:` block. Mapping-backed providers keep payload-aware signatures (`github.pull_request(action?)`); catalog-backed ones get `(filter?)`. Result: 47 namespaces, 502 events; `github` and `slack` are supersets of what #446 generated, so `--on github:events=` and the six fallback GitHub events are unchanged. Also: a reserved-namespace guard (`webhook`, `flow`, `schedule`, …), a generated `PROVIDERS.md` table covered by `--check`, and hyphenated ids mapped to identifiers (`azure_blob`, `google_drive`) with upstream spelling kept in the lowered filter. Merge condition: adapter-core published with relayfile-adapters#280 and the SDK pin bumped; until then `generate-triggers.mjs --check` (and its test) report github.ts/gitlab.ts/index.ts/PROVIDERS.md drift against 0.5.25 — 45 of the 47 providers already generate identically from the catalog it ships. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Warning Review limit reachedNext included review available in 16 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (56)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…trigger test Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Review swarm: maintainabilityNo fresh transcript was produced for run |
Review swarm: historyNo fresh transcript was produced for run |
Review swarm: structureNo fresh transcript was produced for run |
Review swarm: FAILED
Cloud run: |
…rovider trigger namespace Merges origin/main (#446) and moves the pin to 0.5.26, the first release that bundles every adapter's own mapping under mappings/adapters/ (relayfile-adapters#280). Triggers are regenerated from the installed tarball alone — no --adapters-dir — and `generate-triggers.mjs --check` passes: 47 providers, 502 events, PROVIDERS.md in sync. Conflicts resolved by taking main's cloud-deploy.* (untouched here) and this branch's superset github-events test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
| // A provider with a `webhooks:` block keeps its mapping-defined vocabulary. | ||
| if (mappings.has(provider) && Object.keys(mappings.get(provider)).length) continue; | ||
| if (!events.length) continue; | ||
| mappings.set(provider, Object.fromEntries([...new Set(events)].sort().map(event => [event, {}]))); | ||
| catalogProviders.add(provider); |
There was a problem hiding this comment.
🔴 Mapping providers lose supported events
For providers with any mapping webhook, readCatalog drops every catalog-only event. GitLab loses 39 delivered event types, so ingress rejects them.
Learn more
The trigger catalog records the event types emitted by each adapter's supportedEvents(). Adapter mappings carry richer definitions for some events, but they are not a complete replacement vocabulary. The upstream catalog generator explicitly unions supported events with mapping webhook keys for this reason. Here, the provider-level early return keeps only mapping keys whenever one exists. This affects GitHub, GitLab, and Slack; GitLab's generated registry has 8 entries while its pinned catalog has 47.
Example: The pinned GitLab catalog includes merge_request.open, but its mapping has only merge_request. Generation omits merge_request.open. A flow cannot use gitlab.merge_request_open(), and providerInboxEvent('gitlab', { type: 'merge_request.open', payload: {} }) rejects a real adapter event.
Recommended fix: Merge catalog events into each provider's mapping vocabulary. Preserve each mapping definition for matching event names, and add catalog-only names with {} so they receive the plain filter signature. Keep collision validation after the union.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Fixed in eb5640c: catalog events are unioned into every provider (mapping-declared events keep their signature), so gitlab now has all 53, github 26, slack 21 — 570 events across 47 providers. One wrinkle surfaced: slack publishes both reaction.added and reaction_added, which mangle to one identifier; the mapping-declared one owns the method and the other stays in providerEventTypes (accepted by flows check/ingress via webhook('slack', { provider, type })), listed in PROVIDERS.md. Generator test added for both rules; full SDK suite 1861 passed.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit bf3929e. Configure here.
Devin on #456: a provider with any `webhooks:` block lost every event the catalog listed but the mapping did not — gitlab kept 8 of the 53 it delivers, so ingress would refuse the other 45 and `flows check` had no namespace for them. The mapping describes payload shape for some events, never the delivered set; `supportedEvents()` does. Catalog events are now unioned into every provider with the plain `(filter?)` signature; a mapping-declared event keeps its signature. Where two upstream names mangle to one identifier (slack publishes both `reaction.added` and `reaction_added`) the mapping-declared event owns the method and the other remains in `providerEventTypes`, subscribable via `webhook(provider, { provider, type })` and listed in PROVIDERS.md. 47 providers, 570 events (was 502): gitlab 53, github 26, slack 21. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…cond action Cursor on #456: `pull_request_edited(action?)` pinned the type to `pull_request.edited` and still accepted an action, a dual vocabulary that is easy to misuse. Only an aggregate event whose mapping extracts `action` takes one now (`pull_request`, `check_run`, `issue_comment`). Both spellings stay, because two ingresses deliver them: the aggregate form is what raw GitHub and the local receiver carry, the action-qualified form is what relayfile's Cloud ingress normalizes to; the README says which to use. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Stacked on #446 (
feat/github-trigger-vocabulary); rebase ontomainonce it merges. Draft until the merge condition below is met.Why
flow().on(...)could subscribe to Slack and GitHub only.scripts/generate-triggers.mjsread the mapping YAML bundled in@relayfile/adapter-core, and that was the two core fallbacks — while relayfile ingests events from 47 providers (linear 33, gitlab 47, ramp 47, notion 13, cloudflare 8, …).What
The generator applies three sources per provider, in order:
mappings/*.mapping.yaml);mappings/adapters/*.mapping.yamlin the package once relayfile-adapters#280 ships,packages/<adapter>/in a checkout — superseding the fallback as a whole;@relayfile/adapter-core/triggers(KNOWN_TRIGGER_CATALOG, fed by every adapter'ssupportedEvents()) for providers with nowebhooks:block.Mapping-backed providers keep payload-aware signatures (
github.pull_request(action?)); catalog-backed ones get(filter?). 47 namespaces, 570 events (catalog events unioned into every provider; a mapping only adds payload shape) — full table in the generatedpackages/surface/src/triggers/PROVIDERS.md(covered by--check).github/slackare strict supersets of #446's output (6 fallback GitHub events and their signatures unchanged), soflows deploy --on github:events=…is unaffected. Hyphenated ids become identifiers (azure_blob.file_created()lowers to{ provider: 'azure-blob', type: 'file.created' }); a reserved-namespace guard refuses a provider named like a surface export (webhook,flow,schedule, …).flows check's provider-event refusal (provider-trigger-contract.ts) readsproviderEventTypes, so it now covers all 47 with no change of its own.Merge condition
@relayfile/adapter-core≥ 0.5.26, then bump the pin inpackages/sdk/package.json, runnode scripts/generate-triggers.mjs --check, un-draft.--check(andtests/generate-triggers.test.ts"reproduces all checked-in modules") reports drift ongithub.ts,gitlab.ts,index.ts,PROVIDERS.mdonly — 45 of 47 providers already generate identically from the catalog 0.5.25 ships.Tests
triggers-all-providers.test.ts(≥40 providers present; every registry event has a frozen namespace method lowering to{provider,type}; hyphenated ids; catalog-only signature),triggers-github-events.test.tsrelaxed to a superset.(filter?), mapping-backed never overridden,PROVIDERS.mdgenerated and drift-checked, reserved namespaces refused);provider-trigger-contract.test.tsaccepts one subscription from each of github/slack/linear/notion/gitlab, refusesno.such.eventon five providers, andflows checkpasses a five-provider flow.What Cloud still gates (not implemented here)
Local ingress delivers any of these providers today (
flows serve-webhook→POST /providers/<name>→providerInboxEvent). Hosted deployments do not:cloud/packages/web/lib/flows/flow-trigger-sources.ts(FLOW_TRIGGER_PROVIDERS = ["github","linear","jira","shortcut","slack"],flowIssueFromEvent→ per-provider*IssueFromEvent) andlaunch-flow-deployment.ts(skipped: "not_a_ticket",inputs: { approver, issue, event }) admit only ticket-shaped events from those five, plus PR events after cloud#3772;prepare-flow-deploy.tsbuilds watch rules from the same list (buildFlowWatchRules,flowSourceTriggers).Proposed generalisation: at deploy time, derive the deployment's subscriptions from the flow's declared sources — each
.on(<provider>.<event>(filter))is{ provider, eventType, filter }(already whatproviderDeclaration()extracts in the SDK) — persist them on the deployment record (flow-deployment-store.ts), build one watch rule per(provider, eventType)on that provider's relayfile projection (the rule paths per provider come from each adapter'sinbound.ts/ path-mapper, not a hand-kept table), and inlaunch-flow-deployment.tsadmit any delivered event whose(provider, eventType)the deployment declared, passing the raw record asinputs.eventand dispatching the matching handler body (the #301 handler-dispatch work) — withissue/pullRequestprojections kept as conveniences for the five ticket providers. Until #301 lands, the default body runs withinputs.eventonly.🤖 Generated with Claude Code
Summary by cubic
Adds trigger namespaces for every relayfile adapter provider, so
flow().on(...)can subscribe to all 47 providers (570 events) instead of only GitHub and Slack. The generator now merges core fallback mappings, adapter-local mappings, and the trigger catalog, and unions catalog events into every provider so awebhooks:block can no longer hide events ingress actually delivers. Mapping-backed providers keep payload-aware signatures likegithub.pull_request(action?), while catalog-only events take(filter?); GitHub and Slack are strict supersets, so existing subscriptions keep their signatures.Details
@relayfile/adapter-coreto 0.5.26, which bundles adapter-local mappings, and regenerates all trigger modules from the installed tarball;generate-triggers.mjs --checknow passes.azure_blob) but keep their upstream spelling when lowered.PROVIDERS.mdis covered by the generator's drift check, andflows checknow admits events from all 47 providers.webhook,flow, andschedule.github.check_run(action?)andgithub.issue_comment(action?), andflows deploy --on github:events=pull_requestnow selects PR events for hosted GitHub listeners.pull_request_editednow take a plain(filter?); only aggregate events (pull_request,check_run,issue_comment) still accept an action, and both spellings stay because two ingresses deliver them.reaction.addedandreaction_added), the mapping-declared event owns the method and the other stays inproviderEventTypes, subscribable viawebhook(...).Not included
Written for commit 179fb09. Summary will update on new commits.
Note
Medium Risk
Large generated public API surface and expanded
providerEventTypesaffectflows checkand all provider subscriptions; backward compatibility relies on GitHub/Slack remaining supersets of prior exports.Overview
Expands flow trigger authoring from GitHub and Slack only to 47 providers and 570 events by regenerating
@relayflows/surfacetrigger modules from an upgraded generator and@relayfile/adapter-core0.5.26.generate-triggers.mjsnow merges three inputs per provider: core fallback mappings, adapter-local mappings (new in adapter-core), andKNOWN_TRIGGER_CATALOG(unioned so catalog events are always present; mapping YAML only shapes signatures for events it declares). It emits per-provider TypeScript namespaces, an expandedproviderEventTypesregistry, and a drift-checkedPROVIDERS.md. Mapping-backed events keep payload-aware APIs (e.g.github.pull_request(action?)); catalog-only events use(filter?). Action-qualified names likepull_request.editedstay filter-only even when the mapping extractsaction. Colliding identifiers favor mapping-declared events; registry-only duplicates remain valid viawebhook(provider, { provider, type }). Reserved surface names (webhook,flow,schedule, …) are rejected as provider namespaces.GitHub and Slack are strict supersets of the prior vocabulary (existing six GitHub mapping events and signatures preserved). Tests cover catalog union, drift on
PROVIDERS.md, multi-providerflows check, and namespace coverage across providers.Reviewed by Cursor Bugbot for commit 179fb09. Bugbot is set up for automated code reviews on this repo. Configure here.