You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor: centralize event names in DEVFRAME_EVENTS / HUB_EVENTS maps
Introduce one source-of-truth event map per package and reference it from
every call site, so event/broadcast/shared-state/channel names stop living
as scattered string literals:
- packages/devframe/src/events.ts (DEVFRAME_EVENTS) — agent host bus events,
client connection events, and server->client broadcasts; re-exported from
devframe/constants.
- packages/hub/src/events.ts (HUB_EVENTS) — the docks/terminals/messages/
commands bus events, hub: RPC methods, devframe: broadcasts, shared-state
keys, and channels; re-exported from @devframes/hub/constants.
Call sites across both packages (plus hub-ui and the messages dev harness)
now reference the maps instead of literals. The unavoidable type-position
keys (EventEmitter<...> maps, RPC augmentation interfaces) mirror the maps.
Document the core devframe channels in the Events Reference and note that
the two maps back the page; add an AGENTS.md rule requiring the maps and
events.md to move together and forbidding magic event names.
Public constant types are preserved (DOCK_RENDERERS_STATE_KEY,
FRAME_NAV_CHANNEL, DEVFRAME_REMOTE_ASSETS_ERROR_MESSAGE_TYPE stay `string`);
the snapshot change is purely the additive HUB_EVENTS / DEVFRAME_EVENTS.
Copy file name to clipboardExpand all lines: AGENTS.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -41,6 +41,7 @@ Ahead-of-time build artifacts that live under `src/` - the shadow-root styleshee
41
41
## Conventions
42
42
43
43
- RPC functions must use `defineRpcFunction`; always namespace IDs `devframes:plugin:<slug>:<fn-name>` (matching the plugin's `@devframes/plugin-<slug>` package name).
44
+
- **No magic event names — use the centralized event maps.** Every event, broadcast, shared-state key, and channel name lives in one of two source-of-truth maps: `DEVFRAME_EVENTS` (`packages/devframe/src/events.ts`, re-exported from `devframe/constants`) for the core runtime, and `HUB_EVENTS` (`packages/hub/src/events.ts`, re-exported from `@devframes/hub/constants`) for the hub. Reference `DEVFRAME_EVENTS.*` / `HUB_EVENTS.*` at call sites (`.events.emit`/`.on`, `rpc.broadcast({ method })`, `sharedState.get(key)`, `defineHubRpcFunction({ name })`, `rpc.call`) instead of re-typing a string literal. The two maps and the [`docs/guide/events.md`](docs/guide/events.md) Events Reference are kept in lockstep: adding, renaming, or removing a name means editing the map **and** that page in the same change — every name in the maps appears in the tables, and vice versa. The only literals left are unavoidable type-position keys (the `EventEmitter<…>` maps in `types/*` and the `DevframeRpcClientFunctions`/`DevframeRpcServerFunctions` augmentations), which mirror the maps; a package that deliberately avoids a hub dependency (e.g. `@devframes/plugin-terminals`, which models the hub bridge structurally) keeps a local literal rather than importing `HUB_EVENTS`.
44
45
-**Stay validator-neutral.**`devframe` and every `@devframes/*` package must not introduce a preferred schema validator dependency - no `valibot`, `zod`, `arktype`, etc. in their runtime `dependencies`. `args`/`returns`/flag schemas are typed against [Standard Schema](https://standardschema.dev/) (`@standard-schema/spec`, types-only); first-party code that needs to author a schema uses the built-in zero-dep `devframe/utils/simple-schema` builder (deliberately minimal - not a general validator). JSON-schema conversion uses each schema's own Standard JSON Schema converter (`~standard.jsonSchema`, implemented by e.g. zod 4) when present and degrades to a permissive object otherwise - no converter library and no vendor dependency is required. Docs, by contrast, should point *users* at a real validator for their own integrations - recommend **valibot** (lightest) or **zod** (worth reusing if they already pull it via the JSON-render or MCP integrations).
45
46
- Shared state via `devframe/utils/shared-state`; keep values serializable.
46
47
- Utility imports use the package-path form `devframe/utils/*`, never relative `../utils/*`.
Copy file name to clipboardExpand all lines: docs/guide/events.md
+51-5Lines changed: 51 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,13 +2,17 @@
2
2
outline: deep
3
3
---
4
4
5
-
# Hub Events Reference
5
+
# Events Reference
6
6
7
-
The hub carries change notifications across three distinct channels. What separates them is **direction and reach**: an in-process event bus that never leaves the node process, server RPC methods a client calls, and server-pushed broadcasts and shared state a client reads.
7
+
Devframe carries change notifications across a few distinct channels. What separates them is **direction and reach**: an in-process event bus that never leaves the node process, server RPC methods a client calls, and server-pushed broadcasts and shared state a client reads.
8
8
9
9
Two naming prefixes mark the wire surface: `hub:` for hub-layer server RPC (client → server actions), and `devframe:` for the client-facing devframe protocol (broadcasts, shared state, and streams pushed server → client). The internal event bus mirrors the same plural subsystem vocabulary (`docks`, `terminals`, `messages`, `commands`), so each internal event lines up with its wire counterpart — `docks:activate` fans out to `devframe:docks:activate`.
10
10
11
-
## Internal node event bus
11
+
Every name on this page has one home in code: the [`HUB_EVENTS`](https://github.com/devframes/devframe/blob/main/packages/hub/src/events.ts) map (`@devframes/hub/constants`) backs the hub tables, and the [`DEVFRAME_EVENTS`](https://github.com/devframes/devframe/blob/main/packages/devframe/src/events.ts) map (`devframe/constants`) backs the core tables. Call sites reference `HUB_EVENTS.*` / `DEVFRAME_EVENTS.*` rather than re-typing a literal, and this page and those maps move together — changing one without the other is a bug.
12
+
13
+
## Hub events
14
+
15
+
### Internal node event bus
12
16
13
17
Each subsystem host emits on `ctx.<subsystem>.events`. These fire and are consumed **inside the same node process** — chiefly by `createHubContext`, which fans them out onto the wire. They never cross to the browser.
14
18
@@ -22,7 +26,7 @@ Each subsystem host emits on `ctx.<subsystem>.events`. These fire and are consum
22
26
23
27
The `docks:entry:updated` and `terminals:session:updated` middle nouns (`entry`, `session`) name the specific record type; the messages and commands subsystems imply their record in the subsystem name, so they carry the verb directly.
24
28
25
-
## Server RPC methods — client → server
29
+
###Server RPC methods — client → server
26
30
27
31
A connected client (any mounted iframe or panel, on its own RPC client) calls these; the hub node handles them. Carry the `hub:` prefix.
28
32
@@ -40,7 +44,7 @@ A connected client (any mounted iframe or panel, on its own RPC client) calls th
40
44
|`hub:terminals:restart`|`(id) => void`| Re-run a session's command in place. |
41
45
|`hub:terminals:remove`|`(id) => void`| Kill a session's process and drop it from the registry. |
42
46
43
-
## Broadcasts & shared state — server → client
47
+
###Broadcasts & shared state — server → client
44
48
45
49
The server pushes these; a hub-aware client reads or subscribes. Carry the `devframe:` prefix. A UI subscribes to broadcasts via `rpc.client.register(...)`; the [client host](./client-context) registers the `devframe:docks:activate` handler for you.
46
50
@@ -56,3 +60,45 @@ The server pushes these; a hub-aware client reads or subscribes. Carry the `devf
56
60
|`devframe:terminals`| streaming channel | Live terminal output stream, keyed by session id. |
57
61
58
62
The [`devframe:docks:active`](./shared-state) mirror pairs with the `devframe:docks:activate` broadcast: the broadcast reaches docks already on screen, while the mirror lets a dock that mounts *because* of the switch converge on the same request instead of missing it.
63
+
64
+
## Core devframe events
65
+
66
+
The core `devframe` runtime (below the hub) carries its own notification channels — the agent host's change events, the client connection lifecycle, and the server-pushed broadcasts that power shared state and streaming. These are backed by `DEVFRAME_EVENTS` (`devframe/constants`).
67
+
68
+
This map covers notifications only. The request/response RPC endpoints of the shared-state, streaming, and auth-handshake protocols (`devframe:rpc:server-state:*`, `devframe:streaming:subscribe`, `anonymous:devframe:auth`, …) are defined at their handlers and typed in `types/rpc-augments.ts` — they aren't events.
69
+
70
+
### Node host bus
71
+
72
+
Emitted on `ctx.agent.events` as the agent-exposed tool/resource surface changes; protocol adapters (e.g. the MCP server) subscribe to re-publish their manifest.
73
+
74
+
| Event | Emitted by | Payload |
75
+
|---|---|---|
76
+
|`agent:manifest:changed`| any tool/resource/provider change | — |
77
+
|`agent:tool:registered` / `agent:tool:unregistered`|`registerTool` / `unregisterTool`|`AgentTool` / id |
78
+
|`agent:resource:registered` / `agent:resource:unregistered`|`registerResource` / `unregisterResource`|`AgentResource` / id |
79
+
80
+
### Client connection events
81
+
82
+
Emitted on the RPC client's `rpc.events` emitter (`RpcClientEvents`) for a UI to track connection lifecycle and surface errors.
|`rpc:error`| An RPC call rejected (`error`, `method`). |
88
+
|`connection:status`| Connection status changed (`status`, `previous`). |
89
+
|`connection:error`| A connection-level error (WebSocket errored, or trust refused). |
90
+
91
+
### Broadcasts — server → client
92
+
93
+
Pushed from the server to subscribed clients over the `devframe:` protocol. Wired by the framework's own hosts; not registered manually.
94
+
95
+
| Name | Carries |
96
+
|---|---|
97
+
|`devframe:auth:revoked`| This connection's bearer token was revoked; the client drops to untrusted. |
98
+
|`devframe:rpc:client-state:updated`| Full shared-state snapshot for a key. |
99
+
|`devframe:rpc:client-state:patch`| Incremental shared-state patch for a key. |
100
+
|`devframe:streaming:chunk`| A streaming chunk for a subscribed channel/id. |
101
+
|`devframe:streaming:end`| A streaming terminator (optionally an error). |
102
+
|`devframe:streaming:upload-cancel`| Server-side cancel of an in-flight upload. |
103
+
104
+
Plus one `postMessage` channel, `devframe:remote-assets-error`, that the remote-assets fallback page posts to `window.parent` so an embedding viewer can replace the bare 502 page with its own UI.
0 commit comments