Skip to content

feat(platform): generate event types from AsyncAPI, and Mintlify docs for @base44/platform - #312

Merged
amitbardos merged 32 commits into
mainfrom
amitb/platform-event-codegen
Oct 13, 2026
Merged

amitbardos merged 32 commits into
mainfrom
amitb/platform-event-codegen

Conversation

@amitbardos

@amitbardos amitbardos commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Generates the @base44/platform event types from the service's AsyncAPI document and runs the app SDK's Mintlify pipeline for the package.

  • packages/platform/asyncapi.json: the committed protocol document (alpha, from base44-dev/mintlify-docs#2426). npm run sync:asyncapi -- <url> (or ASYNCAPI_URL) refreshes it and refuses a document with no messages. Production serves none while events are alpha, so point it at a dev backend (http://localhost:8000/api/asyncapi.json) until beta.
  • npm run gen:events writes src/modules/builder.events.generated.ts with json-schema-to-typescript: one type per schema, plus ServerEventMap, ClientMessageMap and the runtime event-name list. PlatformEventMap, PlatformEvent, PlatformSnapshot, ToolCall and GuardApproval derive from it. A new backend event needs only a sync and a regen.
  • Breaking type names: the backend model names replace the hand-written ones (ChatMessage → Message, AppStatus → StatusObject, Snapshot → PlatformSnapshot, SnapshotQueue → QueueState, Tool*Arguments → per-tool *Call variants). Runtime behavior is unchanged.
  • CI: npm run check:events in unit-tests.yml fails when the generated file drifts from asyncapi.json.
  • Docs: file-processing.js and copy-to-local-docs.js take --package-dir. @base44/sdk output is byte-identical (checked the generated content and the docs.json update against main). The platform reference lands in mintlify-docs developers/references/platform-sdk/docs (pushed to base44-dev/mintlify-docs#2426). The Socket messages page documents the service's protocol, so mintlify-docs builds it from the AsyncAPI document production serves; this package only links to it.
  • JSDoc rewritten in the app SDK's voice with examples. serverUrl is the session's socket_url.

Needs attention before merge

  • New devDependency json-schema-to-typescript@16.0.0, locked in package-lock.json from registry.npmjs.org.
  • 286 of 412 schema properties have no description in the backend, so the generator falls back to the field title (Turn ID.). Adding Field(description=...) in the backend fixes this, and also fixes the Socket messages page.

🤖 Generated with Claude Code

amitbardos and others added 8 commits October 9, 2026 19:58
…script

The service's AsyncAPI document is the source of truth for the socket
protocol. sync-asyncapi.mjs replaces the committed copy from a URL
(argument or ASYNCAPI_URL, default production) and refuses a document
with no messages, which is what production serves while events are alpha.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gen-events.mjs compiles components.schemas with json-schema-to-typescript
into builder.events.generated.ts: one type per schema, plus ServerEventMap
and ClientMessageMap from the operations, and the runtime list of event
names. PlatformEventMap, PlatformEvent, ToolCall and GuardApproval are
derived from them, so a new backend event needs only sync and regen.

Types now carry the backend model names (Message, StatusObject, ...);
Snapshot becomes PlatformSnapshot. Adds json-schema-to-typescript 16.0.0
as a devDependency.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
….json

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
file-processing.js and copy-to-local-docs.js take --package-dir and read
that package's docs folder and config. An optional mintlify-target.json
sets the mintlify-docs path and nav dropdown; without it the SDK defaults
apply, so @base44/sdk output is byte-identical. The platform package adds
its config and create-docs / copy-docs-local scripts, landing the
reference in developers/references/platform-sdk/docs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds examples to the client, its options, the builder module and session
methods, errors and events, and fixes serverUrl: it is the session's
socket_url from POST /api/service/socket-sessions. The README describes
the generated event types and the sync and regen workflow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lets the platform reference list its Client group first. The SDK's map
already lists its groups in the old fixed order, so its nav is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Nav: a target's `groups` moves single pages, so PlatformSocketError sits in
  Errors instead of Client.
- Section names (types with their own methods, Type Definitions groups) move
  from file-processing.js to each package's page-sections.json. BuilderSession
  becomes "Session methods" and PlatformEvent a Type Definition, like actors.
- Client and subscription options render only as nested fields under
  Parameters, without their own appended sections.
- connect() documents what it rejects with.
- Each PlatformSocketErrorCode value has its own comment, rendered as a field
  on the PlatformSocketError page.

The @base44/sdk docs output and nav are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every resolved URL and integrity matches registry.npmjs.org, and every
version is past the 14-day release cooldown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

🚀 Package Preview Available!


Install this PR's preview build with npm:

npm i @base44-preview/sdk@0.8.53-pr.312.2bf40bc

Prefer not to change any import paths? Install using npm alias so your code still imports @base44/sdk:

npm i "@base44/sdk@npm:@base44-preview/sdk@0.8.53-pr.312.2bf40bc"

Or add it to your package.json dependencies:

{
  "dependencies": {
    "@base44/sdk": "npm:@base44-preview/sdk@0.8.53-pr.312.2bf40bc"
  }
}

Preview published to npm registry — try new features instantly!

amitbardos and others added 21 commits October 9, 2026 22:35
…d socket host

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
roomNotices and the new sessionEndings are typed by ServerEventMap and
SessionEnded, so a new room notice or session-end reason fails to compile
until the SDK maps it to a code.

The five codes the server sends now link to their event for the meaning and
say only what to do. The type's summary defines "retryable", and
session_replaced no longer reads as both retryable and not.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t handle

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…docs.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The constructor's Returns lists the instance's properties, like a
function's Returns lists its result. Class pages now drop the separate
## Properties section and the class description repeated inside Returns.
@base44/sdk has no classes, so its output is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e app SDK's modules

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…terface

When the return type has no properties to expand, the Returns section lost
its type line. It now falls back to the type TypeDoc linked. This adds
`ActorSubscription` to subscribe() on the app SDK's actors page and
`BuilderSession` to init() on the Platform SDK's builder page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PlatformSocketErrorCode is now SessionErrorCode | AppErrorCode, each value
documented with what it means and what to do. The PlatformSocketError page
lists them in two sections right after its properties.

Pipeline, both generic: a literal union drops its one-line signature and
type badge, since every value is listed below it; a class page without a
documented constructor keeps its Properties. The constructor is @internal,
since only the SDK creates these errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ent types

page-sections.json groups can now name their section; the error codes sit
under "Error codes" instead of "Type Definitions". init() links its
result to the session methods, and onEvent links to PlatformEvent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e and appId relate

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nts it

init() now links BuilderSession to Session methods. On the app SDK's actors
page, Connection and ActorSubscription link to their methods sections.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A class without a documented constructor lists its properties as
ResponseFields, like a Returns. @base44/sdk has no classes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nt()

The client is created like the app SDK's: createPlatformClient(options)
returns a PlatformClient with builder. Its reference page is now a function
page with the same shape as createClient: signature, description,
Parameters, Returns, then the example.

Also: the builder property no longer describes init(); options read
"Configuration object for the client."; maxTypeConversionDepth 3 for this
package, so getSessionToken shows Promise<string> instead of Promise<...>.

BREAKING CHANGE: `new Base44PlatformClient(options)` is now
`createPlatformClient(options)`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The value is the session's socket_url, the socket origin, which in
production is a different host from the REST API. In the app SDK,
serverUrl is the REST origin, so the shared name read as the same thing.

BREAKING CHANGE: pass `socketUrl` instead of `serverUrl` to
`createPlatformClient()`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When a Returns links to a section of the same page, its description is
left to that section. The *** separator right under a methods section or a
type heading is dropped. On the app SDK this changes the actors page
(Connection, ActorSubscription) and the separators under Type Definitions
headings on agents, connectors, entities and functions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…from class pages

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No page documents a constructor any more, so the class page rule keeps only
"no Extends" and properties as fields. The nav's per-page group override is
replaced by mapping classes to "Errors" in the platform's category map,
whose key order already places it last. Output is unchanged for both
packages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@amitbardos
amitbardos marked this pull request as ready for review October 10, 2026 11:27
…line

create-docs now renders docs/content/events/builder-events.mdx from the
committed asyncapi.json (scripts/events-to-mdx.mjs, the renderer moved from
mintlify-docs), for exactly the events eventNames forwards to onEvent, so
the page and the types come from the same copy and release. It opens with
how an event reaches onEvent, with no AsyncAPI connection prose. The nav
gets an Events group from the category map.

Also: PlatformSnapshot is documented on the builder page, linked from
onSnapshot; properties under Type Definitions render as fields; error codes
for server notices describe the notice instead of linking to events the
page no longer lists; socketUrl's JSDoc says it is fixed per environment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ozsay

ozsay commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

Double-checked head 3090447: one correctness issue to fix before merge, plus two small documentation corrections.

PlatformSnapshot.queue is required in the type but can be absent at runtime. PlatformSnapshot extends Snapshot inherits queue: QueueState, while decodeSnapshot still omits it when the incoming queue is missing or null. The existing real-socket test sends snapshots without a queue, so this is an already-supported input. The new type test permits snapshot.queue.items; I built this revision and reproduced TypeError: Cannot read properties of undefined (reading 'items') for both missing and null queues.

The smallest compatibility-preserving fix is to retain optionality in the SDK wrapper:

export interface PlatformSnapshot extends Omit<Snapshot, "queue"> {
  room: string;
  queue?: QueueState;
}

Update the type test accordingly. Alternatively, the decoder would need to guarantee a queue value for every accepted snapshot.

Small documentation corrections:

  • The PR body's lockfile warning is stale: package-lock.json is committed, the added resolved URLs use registry.npmjs.org, and the CI job containing npm ci passed.
  • ToolCall's “Check name to narrow it to that tool's call” JSDoc overstates the guarantee: OtherToolCall.name: string remains in the narrowed union. The type test already accounts for this with "results" in call; qualify the wording to reflect that.

The factory and option renames are acceptable for this new package with no users; no compatibility objection there. Broad generated exports and placeholder field descriptions are advisory, not merge blockers.

Validation: platform build, type checks, and all 27 unit tests passed locally. The queue failure was reproduced separately against the built decoder. I did not regenerate the docs.

…t delivers it

decodeSnapshot leaves queue out when the server sends none or null, but
PlatformSnapshot inherited Snapshot's required queue, so snapshot.queue.items
compiled and threw. The ToolCall JSDoc says that narrowing by name keeps
OtherToolCall in the union.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

🚀 Package Preview Available! (@base44/platform)


Install this PR's preview build with npm:

npm i @base44-preview/platform@0.1.0-pr.312.2bf40bc

Prefer not to change any import paths? Install using npm alias so your code still imports @base44/platform:

npm i "@base44/platform@npm:@base44-preview/platform@0.1.0-pr.312.2bf40bc"

Or add it to your package.json dependencies:

{
  "dependencies": {
    "@base44/platform": "npm:@base44-preview/platform@0.1.0-pr.312.2bf40bc"
  }
}

Preview published to npm registry — try new features instantly!

The events page documents the service's protocol, so mintlify-docs builds
it from the AsyncAPI document production serves, as it does the REST
references. events-to-mdx.mjs, create-docs:events and the Events nav
category are removed, and the JSDoc links point to
/developers/references/platform-sdk/socket-messages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@amitbardos
amitbardos force-pushed the amitb/platform-event-codegen branch from 7e08ce4 to 419e113 Compare October 12, 2026 14:19
@amitbardos

Copy link
Copy Markdown
Contributor Author

Thanks @ozsay. Fixed in dd8b394:

  • PlatformSnapshot keeps queue optional (extends Omit<Snapshot, "queue"> with queue?: QueueState), matching what decodeSnapshot delivers. The type test checks that snapshot.queue?.items compiles and snapshot.queue.items doesn't.
  • The ToolCall JSDoc says narrowing by name keeps OtherToolCall in the union, so check a field with in before using it.
  • The stale lockfile note is gone from the description.

One more change since your review, in 419e113: the events page is no longer generated here. It documents the service's protocol, so mintlify-docs builds it from the AsyncAPI document production serves, like the REST references (base44-dev/mintlify-docs#2479). events-to-mdx.mjs, create-docs:events and the Events nav category are removed, and the JSDoc links to /developers/references/apps-api/sections/socket-messages.

Could you take another look?

🤖 Generated with Claude Code

@amitbardos
amitbardos merged commit 7601903 into main Oct 13, 2026
8 checks passed
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.

2 participants