Repository navigation
feat: streaming + JSON-RPC core; openai, anthropic, openrouter, acp, codex SDKs - #754
sam-goodwin wants to merge 14 commits into
Conversation
Operations whose success response is `text/event-stream` are now emitted
with `API.makeStream` and return a `Stream` of decoded events.
- `com.distilled#eventStream` operation trait ({ requestFlag?, done? })
- OpenAPI converter: stream-only endpoints become stream ops; dual-mode
endpoints (JSON + SSE) keep their JSON op and gain an `<Op>Stream`
sibling that forces the `stream` body flag
- `Protocol.decodeEvent`: REST applies the same key mapping, strict
validation and sensitive wrapping to each event as to a JSON body
- opencode regenerated: subscribeEvent, subscribeV2Event,
subscribeGlobalEvent and v2SessionEvents now stream
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A general JSON-RPC 2.0 stack so any JSON-RPC API becomes a distilled
package: ACP and Codex app-server now, MCP / LSP / EVM chains next.
Runtime (`core/jsonrpc`):
- bidirectional `Peer`: request/response correlation, inbound request
dispatch, notification pub/sub, termination fails pending calls
- swappable parts: NDJSON framing; child-process stdio and in-memory
transports
- typed operations like REST: `JsonRpc.request` / `notify` /
`notifications`, per-package `Connection` tag + `protocol` const;
error codes map to typed errors through `errorMatchers`
- `bindHandlers` turns a generated inbound table + typed handlers into
the peer's dispatch maps
Codegen (`core/codegen/jsonrpc`):
- IR traits: com.distilled.jsonrpc#{jsonRpc2,method,notification,inbound}
- `json-schema-rpc` dialect: JSON Schema definitions + an explicit
method list → Smithy, reusing the OpenAPI schema converter
- `jsonRpcEmission`: SdkSpec operation/header/footer hooks emitting
callables, notification streams, and the inbound handler table
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Found building the acp and codex packages:
- normalize JSON Schema `const` → `enum` and literal-only oneOf/anyOf →
one enum, so discriminated unions narrow
- non-object params (unions) are the operation input directly, not a
`{ body }` wrapper
- methods without params take no argument and send no `params`
(`com.distilled.jsonrpc#noParams`)
- an operation name colliding with a definition or shape fails loudly
- `jsonRpcEmission().postProcess` drops an unused traits import
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Found building the openai, anthropic and openrouter packages:
- JSON Schema `const` is a one-value enum, so `type: { const: "x" }`
discriminators narrow
- `x-speakeasy-sse-sentinel` sets the event stream's `done`
- a dual-mode op's `*Stream` sibling gets its own `errors` list, so
patches appending to one no longer leak into the other
- opt-in `unionCaseTitles`: name union cases after branch titles
instead of `Case<n>` (on by default for json-schema-rpc)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- openai: 349 ops in 47 service modules from openai/openai-openapi; project and admin keys chosen per operation; responses/chat/completions event streams - anthropic: 237 ops from the last published Stainless spec; admin and api keys per route, beta routes, messages + session event streams - openrouter: 151 ops from openrouter.ai/openapi.json; management vs inference keys; chat/responses/messages/images event streams - acp: Agent Client Protocol (JSON-RPC over stdio) from the ACP schema release; typed inbound handlers for permissions, fs, terminals - codex: Codex app-server protocol from openai/codex's published JSON Schemas; omits the jsonrpc version member like the server Spec mirrors are added to SPEC_REPOS and created by the distilled-submodules stack on merge. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Install the packages built from this commit: Distilled@distilled.cloud/core bun add https://pkg.ing/@distilled.cloud/core/5695317@distilled.cloud/aws bun add https://pkg.ing/@distilled.cloud/aws/5695317@distilled.cloud/axiom bun add https://pkg.ing/@distilled.cloud/axiom/5695317@distilled.cloud/azure bun add https://pkg.ing/@distilled.cloud/azure/5695317@distilled.cloud/cloudflare bun add https://pkg.ing/@distilled.cloud/cloudflare/5695317@distilled.cloud/coinbase bun add https://pkg.ing/@distilled.cloud/coinbase/5695317@distilled.cloud/discord bun add https://pkg.ing/@distilled.cloud/discord/5695317@distilled.cloud/expo-eas bun add https://pkg.ing/@distilled.cloud/expo-eas/5695317@distilled.cloud/fly-io bun add https://pkg.ing/@distilled.cloud/fly-io/5695317@distilled.cloud/forgejo bun add https://pkg.ing/@distilled.cloud/forgejo/5695317@distilled.cloud/gcp bun add https://pkg.ing/@distilled.cloud/gcp/5695317@distilled.cloud/github bun add https://pkg.ing/@distilled.cloud/github/5695317@distilled.cloud/hetzner bun add https://pkg.ing/@distilled.cloud/hetzner/5695317@distilled.cloud/kubernetes bun add https://pkg.ing/@distilled.cloud/kubernetes/5695317@distilled.cloud/mongodb-atlas bun add https://pkg.ing/@distilled.cloud/mongodb-atlas/5695317@distilled.cloud/neon bun add https://pkg.ing/@distilled.cloud/neon/5695317@distilled.cloud/planetscale bun add https://pkg.ing/@distilled.cloud/planetscale/5695317@distilled.cloud/posthog bun add https://pkg.ing/@distilled.cloud/posthog/5695317@distilled.cloud/prisma bun add https://pkg.ing/@distilled.cloud/prisma/5695317@distilled.cloud/railway bun add https://pkg.ing/@distilled.cloud/railway/5695317@distilled.cloud/stripe bun add https://pkg.ing/@distilled.cloud/stripe/5695317@distilled.cloud/supabase bun add https://pkg.ing/@distilled.cloud/supabase/5695317@distilled.cloud/turso bun add https://pkg.ing/@distilled.cloud/turso/5695317@distilled.cloud/typesense bun add https://pkg.ing/@distilled.cloud/typesense/5695317@distilled.cloud/vercel bun add https://pkg.ing/@distilled.cloud/vercel/5695317@distilled.cloud/workos bun add https://pkg.ing/@distilled.cloud/workos/5695317 |
…dmin_api_keys) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- openai: ProjectNotFound, ServiceAccountNotFound, ProjectApiKeyNotFound on the projects/service-account/api-key ops; nested ResponseErrorEvent.error matching the wire; service-account and admin key `value` marked sensitive - openrouter: KeyNotFound and GuardrailNotFound; createKey `key` marked sensitive Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Distilled only speaks the protocol. Drop JsonRpc.childProcess/layer and
the acp/codex layerChildProcess/layerTransport; add JsonRpc.fromStreams,
JsonRpc.fromSocket and JsonRpc.connect, plus Acp.connect / Codex.connect
(transport, { handlers }).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Manual Smithy spec for the Artifacts namespaces/repos/tokens API (in Cloudflare's OpenAPI, absent from the docs the converter reads), with typed errors verified live. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A JSON Schema object with shared properties beside a oneOf/anyOf of object variants means base AND one variant; the converter kept one side. ACP's SessionConfigOption lost id/name/category and SetSessionConfigOptionRequest lost value (so set_config_option, the model switch, was unusable). Regenerates acp and codex. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Regenerate opencode from main's newer spec with this branch's event-stream codegen. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Install the packages built from this commit: @distilled.cloudpnpm install https://pkg.distilled.cloud/@distilled.cloud/acme/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/acp/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/adyen/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/anthropic/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/apache-superset/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/archil/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/argocd/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/auth0/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/aws/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/axiom/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/azure/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/boat-dev/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/celld/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/chronosphere/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/clerk/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/cloudflare/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/codex/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/coinbase/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/coolify/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/core/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/customerio/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/datadog/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/daytona/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/digitalocean/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/discord/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/docker/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/doppler/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/elasticsearch/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/expo-eas/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/fly-io/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/forgejo/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/gcp/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/github/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/google-workspace/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/grafana/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/growthbook/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/gusto/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/hetzner/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/hostinger/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/huggingface/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/iceberg/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/infisical/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/inngest/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/intercom/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/kubernetes/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/launchdarkly/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/meilisearch/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/mercury/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/metabase/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/modal/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/modrinth/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/mongodb-atlas/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/neon/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/notion/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/okta/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/onepassword/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/openai/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/opencode/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/openrouter/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/ovh/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/paypal/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/plaid/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/planetscale/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/polar/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/porkbun/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/posthog/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/prisma/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/railway/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/redis-cloud/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/remote/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/render/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/resend/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/s2/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/sentry/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/slack/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/spacetimedb/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/squarespace/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/stackit/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/stripe/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/supabase/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/surrealdb/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/temporal/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/trigger-dev/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/turbopuffer/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/turso/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/typesense/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/unkey/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/vanta/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/vercel/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/whop/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/workos/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/xata/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/zendesk/pr:754:b3217abpnpm install https://pkg.distilled.cloud/@distilled.cloud/zerossl/pr:754:b3217abPublished |
Streaming and JSON-RPC in core, plus SDKs for OpenAI, Anthropic, OpenRouter, the Agent Client Protocol and the Codex app-server.
REST + streaming
Dual-mode endpoints keep their JSON op and gain an
<Op>Streamsibling that sendsstream: truefor you. A non-2xx response fails the stream with the op's typed error.JSON-RPC (ACP, Codex)
Operations are typed callables, like REST ops. The peer can also call back into you through typed handlers.
Distilled only speaks the protocol. You hand it an endpoint, and it never spawns or hosts anything:
Codex.connect(transport, { handlers })works the same way.Error codes map to typed errors through the usual
errorMatchers(AcpAuthRequired,CodexServerOverloaded, …), so they're patchable like any provider.Tree-shaking
Services are namespaced (
OpenAI.responses,OpenAI.adminApiKeys, …), and namespace access tree-shakes completely. Measured with rolldown, minified, effect external:import * as OpenAI→OpenAI.responses.createResponseStreamimport { createResponseStream } from "@distilled.cloud/openai/responses"OpenAI.assistants.createAssistantThe root import costs nothing over the subpath import. Unused services never enter the bundle.
What changed
API.makeStream,com.distilled#eventStream), and the JSON-RPC protocol family (bidirectionalPeer, NDJSON framing,fromStreams/fromSocket/ in-memory transports, thejson-schema-rpcdialect and emission).constbecomes a one-value enum,x-speakeasy-sse-sentinelsetsdone, stream siblings get their ownerrors, and union cases can opt in to being named from their titles.openai: 349 ops, 47 service modulesanthropic: 237 ops, from the last published Stainless specopenrouter: 151 opsacpcodexopencoderegenerated, sosubscribeEventnow streamscloudflare/artifacts: the Artifacts REST API (namespaces, repos, tokens) from a manual spec, with typed errorsSPEC_REPOS, and created by the distilled-submodules stack on merge.🤖 Generated with Claude Code