@crowdedkingdoms/crowdyjs 11.1.0 → 12.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/MIGRATION.md +152 -0
  2. package/README.md +262 -0
  3. package/dist/crowdy-agent/browser-dispatcher.d.ts +41 -0
  4. package/dist/crowdy-agent/browser-dispatcher.d.ts.map +1 -0
  5. package/dist/crowdy-agent/browser-dispatcher.js +264 -0
  6. package/dist/crowdy-agent/controller.d.ts +144 -0
  7. package/dist/crowdy-agent/controller.d.ts.map +1 -0
  8. package/dist/crowdy-agent/controller.js +1239 -0
  9. package/dist/crowdy-agent/errors.d.ts +37 -0
  10. package/dist/crowdy-agent/errors.d.ts.map +1 -0
  11. package/dist/crowdy-agent/errors.js +107 -0
  12. package/dist/crowdy-agent/graphql-transport.d.ts +154 -0
  13. package/dist/crowdy-agent/graphql-transport.d.ts.map +1 -0
  14. package/dist/crowdy-agent/graphql-transport.js +854 -0
  15. package/dist/crowdy-agent/index.d.ts +16 -0
  16. package/dist/crowdy-agent/index.d.ts.map +1 -0
  17. package/dist/crowdy-agent/index.js +15 -0
  18. package/dist/crowdy-agent/registry.d.ts +29 -0
  19. package/dist/crowdy-agent/registry.d.ts.map +1 -0
  20. package/dist/crowdy-agent/registry.js +281 -0
  21. package/dist/crowdy-agent/schema.d.ts +72 -0
  22. package/dist/crowdy-agent/schema.d.ts.map +1 -0
  23. package/dist/crowdy-agent/schema.js +467 -0
  24. package/dist/crowdy-agent/studio-tools.d.ts +15 -0
  25. package/dist/crowdy-agent/studio-tools.d.ts.map +1 -0
  26. package/dist/crowdy-agent/studio-tools.js +280 -0
  27. package/dist/crowdy-agent/tool-descriptors.d.ts +4 -0
  28. package/dist/crowdy-agent/tool-descriptors.d.ts.map +1 -0
  29. package/dist/crowdy-agent/tool-descriptors.js +1049 -0
  30. package/dist/crowdy-agent/transport.d.ts +152 -0
  31. package/dist/crowdy-agent/transport.d.ts.map +1 -0
  32. package/dist/crowdy-agent/transport.js +27 -0
  33. package/dist/crowdy-agent/types.d.ts +328 -0
  34. package/dist/crowdy-agent/types.d.ts.map +1 -0
  35. package/dist/crowdy-agent/types.js +37 -0
  36. package/dist/crowdy-client.d.ts +3 -0
  37. package/dist/crowdy-client.d.ts.map +1 -1
  38. package/dist/crowdy-client.js +6 -0
  39. package/dist/crowdy-studio/agent-dom-shell.d.ts +68 -0
  40. package/dist/crowdy-studio/agent-dom-shell.d.ts.map +1 -0
  41. package/dist/crowdy-studio/agent-dom-shell.js +418 -0
  42. package/dist/crowdy-studio/controller.d.ts +74 -4
  43. package/dist/crowdy-studio/controller.d.ts.map +1 -1
  44. package/dist/crowdy-studio/controller.js +450 -17
  45. package/dist/crowdy-studio/dom-shell.d.ts +50 -4
  46. package/dist/crowdy-studio/dom-shell.d.ts.map +1 -1
  47. package/dist/crowdy-studio/dom-shell.js +554 -123
  48. package/dist/crowdy-studio/embed/dock.d.ts +56 -0
  49. package/dist/crowdy-studio/embed/dock.d.ts.map +1 -0
  50. package/dist/crowdy-studio/embed/dock.js +231 -0
  51. package/dist/crowdy-studio/embed/embed-styles.d.ts +12 -0
  52. package/dist/crowdy-studio/embed/embed-styles.d.ts.map +1 -0
  53. package/dist/crowdy-studio/embed/embed-styles.js +549 -0
  54. package/dist/crowdy-studio/embed/hud-layer.d.ts +40 -0
  55. package/dist/crowdy-studio/embed/hud-layer.d.ts.map +1 -0
  56. package/dist/crowdy-studio/embed/hud-layer.js +100 -0
  57. package/dist/crowdy-studio/embed/index.d.ts +5 -0
  58. package/dist/crowdy-studio/embed/index.d.ts.map +1 -0
  59. package/dist/crowdy-studio/embed/index.js +4 -0
  60. package/dist/crowdy-studio/embed/panel.d.ts +162 -0
  61. package/dist/crowdy-studio/embed/panel.d.ts.map +1 -0
  62. package/dist/crowdy-studio/embed/panel.js +642 -0
  63. package/dist/crowdy-studio/index.d.ts +9 -3
  64. package/dist/crowdy-studio/index.d.ts.map +1 -1
  65. package/dist/crowdy-studio/index.js +6 -0
  66. package/dist/crowdy-studio/layout.d.ts +50 -0
  67. package/dist/crowdy-studio/layout.d.ts.map +1 -0
  68. package/dist/crowdy-studio/layout.js +155 -0
  69. package/dist/crowdy-studio/models.d.ts +67 -0
  70. package/dist/crowdy-studio/models.d.ts.map +1 -1
  71. package/dist/crowdy-studio/mount.d.ts +15 -0
  72. package/dist/crowdy-studio/mount.d.ts.map +1 -1
  73. package/dist/crowdy-studio/mount.js +132 -3
  74. package/dist/crowdy-studio/splitter.d.ts +33 -0
  75. package/dist/crowdy-studio/splitter.d.ts.map +1 -0
  76. package/dist/crowdy-studio/splitter.js +133 -0
  77. package/dist/crowdy-studio/styles.d.ts +1 -1
  78. package/dist/crowdy-studio/styles.d.ts.map +1 -1
  79. package/dist/crowdy-studio/styles.js +128 -11
  80. package/dist/generated/graphql.d.ts +3753 -1
  81. package/dist/generated/graphql.d.ts.map +1 -1
  82. package/dist/generated/graphql.js +296 -0
  83. package/dist/index.d.ts +1 -1
  84. package/dist/index.js +1 -1
  85. package/dist/kit/npcs.d.ts.map +1 -1
  86. package/dist/kit/social.d.ts.map +1 -1
  87. package/dist/player-host/control-banner.d.ts +40 -0
  88. package/dist/player-host/control-banner.d.ts.map +1 -0
  89. package/dist/player-host/control-banner.js +252 -0
  90. package/dist/player-host/control-gate.d.ts +77 -0
  91. package/dist/player-host/control-gate.d.ts.map +1 -0
  92. package/dist/player-host/control-gate.js +197 -0
  93. package/dist/player-host/index.d.ts +7 -0
  94. package/dist/player-host/index.d.ts.map +1 -0
  95. package/dist/player-host/index.js +5 -0
  96. package/dist/player-host/lease-manager.d.ts +66 -0
  97. package/dist/player-host/lease-manager.d.ts.map +1 -0
  98. package/dist/player-host/lease-manager.js +428 -0
  99. package/dist/player-host/schemas.d.ts +9 -0
  100. package/dist/player-host/schemas.d.ts.map +1 -0
  101. package/dist/player-host/schemas.js +347 -0
  102. package/dist/player-host/tools.d.ts +13 -0
  103. package/dist/player-host/tools.d.ts.map +1 -0
  104. package/dist/player-host/tools.js +79 -0
  105. package/dist/player-host/types.d.ts +203 -0
  106. package/dist/player-host/types.d.ts.map +1 -0
  107. package/dist/player-host/types.js +1 -0
  108. package/package.json +17 -2
package/MIGRATION.md CHANGED
@@ -1,3 +1,155 @@
1
+ # CrowdyJS v12.1 — Crowdy Studio embed kit (additive)
2
+
3
+ Version 12.1 ships the reusable game-embed chrome that previously lived only
4
+ in Blocks with Friends. Nothing breaks; games that already hand-roll a shell
5
+ can adopt incrementally.
6
+
7
+ New from `@crowdedkingdoms/crowdyjs/crowdy-studio`:
8
+
9
+ - `createCrowdyStudioEmbed(options)` / `CrowdyStudioEmbed` — responsive
10
+ dock/fullscreen panel with focus trap, Escape/close-key semantics, compact
11
+ header, on-demand Context drawer (grid bounds, permission cards, optional
12
+ HUD preview), loading/error/retry chrome, and assembly of the full
13
+ `mountCrowdyStudio` call (agent block included when the client exposes
14
+ `crowdyStudioAgent` and the game passes `playerHost`).
15
+ - `CrowdyStudioEmbedDock` — accessible game/studio splitter with persisted
16
+ width under `ck:crowdy-studio:embed:dock-width:v1`.
17
+ - `CrowdyStudioTextHud` — text-only presentation sink for CLIENT-mod
18
+ `hud_set` payloads plus the drawer preview mount.
19
+ - `CROWDY_STUDIO_EMBED_STYLES` / `ensureCrowdyStudioEmbedStyles()` — injected
20
+ `ck-crowdy-studio-embed-*` styling; the docked panel sets
21
+ `--ck-game-right-inset` on `document.body` for game HUD insets.
22
+
23
+ New from `@crowdedkingdoms/crowdyjs/player-host`:
24
+
25
+ - `PlayerControlGate` — the synchronous human-takeover seam (capture-phase
26
+ keyboard/pointer preemption, offline Stop, page-hide/visibility handling),
27
+ parameterized on a `clearAgentIntent` hook.
28
+ - `AgentControlBanner` — the always-visible-on-control Pause/Stop safety
29
+ region with self-injected `ck-agent-control-*` styles.
30
+
31
+ New package subpath:
32
+
33
+ - `@crowdedkingdoms/crowdyjs/player-glue-worker` — the self-starting tokenless
34
+ CLIENT-mod glue worker entry. Bundle it as a same-origin module worker (for
35
+ example Vite's `?worker&url`) instead of copying a worker wrapper into the
36
+ game.
37
+
38
+ Migrating from the Blocks with Friends copies: `CrowdyStudioPanel` →
39
+ `CrowdyStudioEmbed`, `CrowdyStudioDock` → `CrowdyStudioEmbedDock`,
40
+ `ModHudLayer` → `CrowdyStudioTextHud`, `bwf-crowdy-studio-*` CSS →
41
+ `ck-crowdy-studio-embed-*`, `bwf-agent-control-*` → `ck-agent-control-*`,
42
+ `--bwf-game-right-inset` → `--ck-game-right-inset`. The persisted dock width
43
+ key changes from `bwf:crowdy-studio:dock-width:v1` to the `ck:` key above
44
+ (previous widths reset once).
45
+
46
+ # CrowdyJS v12 — Agentic Crowdy Studio contract (BREAKING)
47
+
48
+ Version 12 establishes the greenfield public contracts
49
+ `crowdy.studio-agent/1`, `crowdy.agent-tools/1`, and
50
+ `crowdy.player-host/1`. The major bump reserves their authority, event,
51
+ descriptor, and browser-control semantics before rollout; changing those
52
+ semantics later requires another major contract version.
53
+
54
+ New package subpaths:
55
+
56
+ - `@crowdedkingdoms/crowdyjs/agent` — immutable descriptor registry, bounded
57
+ JSON-schema validator, stable errors, injectable durable transport,
58
+ ordered/reconnecting session controller, exact approvals, and execute-once
59
+ browser dispatch.
60
+ - `@crowdedkingdoms/crowdyjs/player-host` — generic host capability,
61
+ observation, command, and result contracts plus the revocable Play lease
62
+ manager/gate.
63
+ - `@crowdedkingdoms/crowdyjs/crowdy-studio` re-exports both surfaces and adds
64
+ the integrated Ask/Build/Play dock.
65
+
66
+ The reconciled Game API SDL and generated agent operations are now committed.
67
+ `client.crowdyStudioAgent` is a production `CrowdyAgentGraphQLTransport`
68
+ implementing every `CrowdyStudioAgentTransportV1` query, Relay connection,
69
+ mutation, heartbeat, and typed event subscription. Tests and non-GraphQL hosts
70
+ may still inject the interface; do not add a generic raw-GraphQL callback.
71
+
72
+ Creation now carries optional `providerDataConsent`; attach carries a stable
73
+ `clientInstanceId` and consumes `replayAfterSeq`; the public transport
74
+ `message` maps to Game API `content`; cancellation requires the exact run id;
75
+ and nested browser results map to `AgentToolResultEnvelopeInput`. PLAY sends a
76
+ two-second heartbeat only while attached, active, and visible, stopping and
77
+ clearing local authority on pause, disconnect, stale epoch, kill, or destroy.
78
+ Descriptor builds verify the full registry and canonical 28-tool Game API
79
+ follow-up subset (14 mandatory game plus 14 Studio/diagnostic/runtime tools)
80
+ against the copied digest fixture.
81
+
82
+ Mode changes now consume the server-repinned registry/policy/context fields.
83
+ BUILD mounts derive `projectId` from the selected saved Studio project after
84
+ initialization; callers should no longer guess it. An existing session for a
85
+ different project fails closed, and project switches require a new session
86
+ until Game API adds an explicit set-project mutation.
87
+
88
+ BUILD workspace leases renew every ten seconds through agent heartbeat and
89
+ stop on human edit, project/context change, revocation, disconnect, or destroy.
90
+ Backend-advertised draft/live/stop/invoke tools execute through the headless
91
+ Studio controller, with exact approval for live work. Run events now preserve
92
+ typed code/error details, aborted handlers clear local intent, and inner
93
+ `OUTCOME_UNKNOWN` can no longer be wrapped as outer success.
94
+
95
+ Runtime draft/live calls now require an exact full-project target plan. Live
96
+ execution also binds the post-autosave revision, content/module hash, and
97
+ pairing preference; mismatches fail before any compile/deploy. Invoke verifies
98
+ the running DRAFT/LIVE environment and export, while stop remains an
99
+ all-project safety action.
100
+
101
+ Existing manual mounts continue to work:
102
+
103
+ ```ts
104
+ await mountCrowdyStudio(host, existingOptions);
105
+ ```
106
+
107
+ To enable the agent dock, inject the transport and either an existing session
108
+ or create-session input:
109
+
110
+ ```ts
111
+ await mountCrowdyStudio(host, {
112
+ ...existingOptions,
113
+ agent: {
114
+ transport: game.crowdyStudioAgent,
115
+ sessionId,
116
+ playerHost, // optional; required for generic Play tools
117
+ },
118
+ });
119
+ ```
120
+
121
+ `CrowdyStudioHandle` now exposes `agent` and `controlLeaseManager` (both `null`
122
+ when agent mode is not configured). `CrowdyStudioController.testDraft()` and
123
+ `deployLive()` now resolve typed `CrowdyStudioDeployResult` values; code that
124
+ ignored their previous `void` result remains valid.
125
+
126
+ Headless integrations should adopt:
127
+
128
+ - `prepareForAgentWork()` before sending a turn;
129
+ - `applyAtomicPatch()` / `synchronizeProject()` for complete revision-fenced
130
+ project updates;
131
+ - `CrowdyStudioSynchronizationProvider` for durable checkpoint list, atomic
132
+ patch, and approved restore hooks;
133
+ - `state.runtimeSync` instead of inferring saved-versus-running status from the
134
+ display phase.
135
+
136
+ Game integrations implement `PlayerHostAdapterV1`, route commands through the
137
+ same intent services as human input, and call
138
+ `AgentControlLeaseManager.preempt(reason)` synchronously on human input,
139
+ Escape, Stop, death, disconnect, or context/target changes. Do not adapt the
140
+ agent through DOM events, raw UDP/GraphQL/CrowdyJS methods,
141
+ `PlayerCodeBroker`, or client-mod `host_call`.
142
+
143
+ The current Game API pilot advertises its canonical 28-tool follow-up subset,
144
+ including all 14 mandatory game tools. CrowdyJS dispatches the game tools
145
+ through `PlayerHostAdapterV1`;
146
+ BWF Play still requires the concrete BWF adapter/shared-intent integration and
147
+ matching host/app policy.
148
+
149
+ The browser package contains no provider client or key. Provider routing,
150
+ policy, budgets, durable approvals, and server tools remain Game API
151
+ responsibilities.
152
+
1
153
  # CrowdyJS v11.1 — responsive Crowdy Studio embedding
2
154
 
3
155
  Crowdy Studio now sizes to its host instead of imposing a 680-pixel minimum
package/README.md CHANGED
@@ -12,6 +12,21 @@ npm install @crowdedkingdoms/crowdyjs
12
12
 
13
13
  CrowdyJS v4 targets browsers by default and uses native `fetch`, `WebSocket`, `crypto`, `btoa`, and `atob`. Node tools can still use the SDK, but must provide browser-compatible globals when opening realtime connections.
14
14
 
15
+ > **CrowdyJS v12 (breaking): Agentic Crowdy Studio.** v12 adds the accepted
16
+ > `crowdy.studio-agent/1`, `crowdy.agent-tools/1`, and
17
+ > `crowdy.player-host/1` browser contracts. Import the provider-neutral durable
18
+ > client and immutable tool registry from
19
+ > `@crowdedkingdoms/crowdyjs/agent`, and generic game observations/control from
20
+ > `@crowdedkingdoms/crowdyjs/player-host`. Crowdy Studio can mount the
21
+ > integrated Ask/Build/Play dock when given an injectable agent transport.
22
+ > There is deliberately no OpenRouter key/client, raw GraphQL executor, DOM
23
+ > driver, `fetch`, shell, unrestricted SDK bridge, or client-mod `host_call` in
24
+ > these surfaces. The reconciled Game API SDL, generated operations, and
25
+ > production `CrowdyAgentGraphQLTransport` are included and exposed as
26
+ > `client.crowdyStudioAgent`; tests may still inject
27
+ > `CrowdyStudioAgentTransportV1`. Existing manual Studio mounting remains
28
+ > unchanged when `agent` is omitted.
29
+ >
15
30
  > **Server compatibility (v8.13):** v8.13 adds the **flow-correlation surface**: `gameModel.flow({ appId, flowId })` stitches one flow correlation id into a single cross-engine timeline (model events + automation runs + compute module runs, each time-ascending), and the default event/run fragments now select the nullable `flowId` field on `GmEvent` / `GmAutomationRun` / `WasmModuleRun`. Both require the 2026-07-19 `cks-game-api` dev line (the `2026-07-19-compute-fleet-hardening` migration for the columns and the `gameModelFlow` query for the timeline); older servers reject the operations with a GraphQL validation error, and everything else keeps working. `gameModel.flow` requires the app-admin `manage_apps` permission (it is a diagnostics surface). v8.13 also extends the kit invoke helpers' gameplay-verdict mapping: the typed invoke-contract violation `computeInvoke` raises (`BAD_REQUEST` with an "Invoke params violate ..." message, game-api 2026-07-19+) now maps onto `{ success: false, errorMessage }` (`kitInvoke`) / `{ success: false, reason }` (engine invokes) instead of throwing — see the exported `isKitVerdictError` predicate.
16
31
  >
17
32
  > **Server compatibility:** v8.12's **container query predicates** (`where`/`limit`/`offset` on `gameModel.containers`), **automation compute actions** (`actionKind: 'compute_invoke'` with `computeModuleName`/`computeExport` on `gameModel.upsertAutomation`; `property_changed` events additionally carry `oldValue`/`newValue` to compute modules), **container-change push** (`gameModel.containerChanged` — metadata-only pull-on-push over graphql-transport-ws; on Node ≤ 21 pass `webSocketImpl`), and **invoke-trigger contracts** (`contractJson` on `compute.upsertTrigger`/`moduleTriggers`, validated server-side pre-sandbox) require the 2026-07 `cks-game-api` dev line with the `2026-07-19-automation-compute-action` migration; older servers reject the new arguments/fields (omit them and everything else keeps working). (npm 8.11.0 is a partial cut of this surface — prefer 8.12.0.) v8.12 also adds the `runOptimisticAction` kit helper (client-only: the packaged optimistic apply → referee invoke → confirm/rollback loop with actionId receipts). v5.2+ targets environments on release **v0.1.19 or later** (`cks-game-api >= v0.10.3`, `cks-management-api >= v0.1.70`). The destructive mutations send an `idempotencyKey` argument that older servers don't define. v6.1's `client.gameApps.deleteGrid` additionally requires release **v0.1.33+** (`cks-game-api >= v0.12.3`). The game-model **permission effects** fields (`permissionEffects` on `gameModel.upsertFunction`/`seed`, `permissionEffectsAppliedJson` on events) require a `cks-game-api` build with the `2026-07-17-model-permission-effects` migration (v0.13.11+); older servers reject queries/mutations that include them (omit the fields and everything else keeps working). The **permission-read** surface (the `has_grid_permission`/`grid_at`/`has_chunk_permission` expression builtins the kit's `chunkPermission` locks compile to, and selector `*PermissionWhere` predicates) additionally requires `cks-game-api` **v0.13.12+**. Older `cks-game-api` builds report game-model **invoke policy denials** as `FORBIDDEN` GraphQL errors instead of resolving with `success: false`; as of this version the kit's invoke helpers map that error onto the documented `{ success: false, errorMessage }` result, so kit callers behave identically against both server generations. v8.6's **`client.compute`** (Compute Modules — server-side Rust/WASM logic) requires a `cks-game-api` build with the compute surface (the `compute*` root fields, v0.13.13+ dev line); older servers reject these operations with a GraphQL validation error, and everything else keeps working. v8.9's **realtime + live-ops surfaces** (`kit.abilities`/`movement`/`territory`/`racing`/`liveops`/`moderation`/`telemetry`, the loot engine path, `client.compute.deployTemplate` + `kit.deploy({engines})`, and the type-94..98 event parsers) complete the 30-abstraction catalog; v8.8's **session-genre engine surfaces** (`kit.instances`/`director`/`matchmaking`/`minigames`, the engine paths on matches/decks/leaderboards, `economy.orderBook`, and the type-91/92/93 event parsers) talk to the Wave 2 engine templates; capability detection keeps model-only deployments on today's behavior. v8.7's **engine kit surfaces** (`kit.mobs`, `kit.pets`, `kit.combat.attackRouted`, `kit.worldsim.forecast`, and the `kit/wire` pose/lane registry) talk to compute-module game engines built on the Wave 0/1 `cks-game-api` dev line (`crowdy-game-kit` crates); capability detection makes them degrade gracefully — model-only deployments keep today's behavior.
@@ -144,6 +159,7 @@ If `managementUrl` is omitted, the SDK falls back to `httpUrl` for backwards-com
144
159
  | `client.compute` | **Compute Modules** — server-side Rust/WASM logic: author + deploy source (`upsertModule`, `deployVersion`, `waitForCompile`), triggers + policy, synchronous `invoke`, and monitoring (`moduleRuns`, `moduleStats`, `moduleLogs`, `appDiagnostics`). Modules run server-only; see [Compute Modules docs](https://docs.crowdedkingdoms.com/game-api/compute-modules). |
145
160
  | `client.playerCompute` | Player-authored SERVER/CLIENT Rust/WASM bound to player-owned grids: deploy source, activate/deactivate, list modules/versions, and delete self-authored modules. |
146
161
  | `client.crowdyStudio` | Cloud project, personal-library, and common-file APIs for Crowdy Studio: target-scoped files, metadata/module names, pairing preference, optimistic revisions, copy-by-value imports, and atomic metadata/file saves. Generated operations are pinned to the committed merged SDL. |
162
+ | `client.crowdyStudioAgent` | Generated, app-token Game API transport for durable agent sessions, Relay history/session pages, descriptors/budgets, exact approvals, browser tool results, heartbeat, control mutations, and ordered event subscriptions. |
147
163
  | `client.playerModel` | Player-owned flexible model containers and grid-confined automations (`containers`, `createContainer`, `setProperty`, `automations`, `createAutomation`, …). |
148
164
  | `client.marketplace` | Player-code store/install/consent flows plus player-authorized grid claims: `claimGridOwnership` preserves the existing-grid policy flow, while `claimGridChunk` atomically creates and owns one chunk under `SELF_CLAIM` and `releaseClaimedGrid` releases an eligible owner-created claim. |
149
165
  | `client.udp` | UDP proxy subscriptions + spatial mutations (`sendActorUpdate`, `sendVoxelUpdate`, `sendAudioPacket`, `sendTextPacket`, `sendClientEvent`). |
@@ -228,6 +244,65 @@ embedded index remains the byte-identical game export (`schemaVersion: 2`, Rust
228
244
  1.97.1, SDK 0.1.5, ABI 0, 725 symbols, content hash
229
245
  `3f5f39d4…18ffb`).
230
246
 
247
+ ### Embed Crowdy Studio in your game (v12.1)
248
+
249
+ Most games should not hand-roll the window chrome around `mountCrowdyStudio`.
250
+ The embed kit ships the proven Blocks with Friends shell as reusable, game
251
+ -agnostic components (exported from `@crowdedkingdoms/crowdyjs/crowdy-studio`):
252
+
253
+ - **`createCrowdyStudioEmbed(options)` / `CrowdyStudioEmbed`** — a responsive
254
+ panel that renders a resizable right dock on desktop and a focus-trapped
255
+ fullscreen modal below 1000 px. It owns Escape/close-key semantics, the
256
+ compact header (title, grid pill, on-demand Context drawer, Close), loading
257
+ and retry chrome, and assembles the `mountCrowdyStudio` call — including the
258
+ agent block when the client exposes `crowdyStudioAgent` and the game passes a
259
+ `playerHost`.
260
+ - **`CrowdyStudioEmbedDock`** — the accessible game/studio splitter with
261
+ persisted width (`ck:crowdy-studio:embed:dock-width:v1`), arrow-key/Home/End
262
+ resize, and ARIA value text.
263
+ - **`CrowdyStudioTextHud`** — the text-only presentation sink for CLIENT-mod
264
+ `hud_set` payloads plus the drawer HUD preview. Untrusted payloads render as
265
+ text, never HTML.
266
+ - **`ensureCrowdyStudioEmbedStyles()`** — injected `ck-crowdy-studio-embed-*`
267
+ styles; games restyle by overriding classes. While docked, the panel sets
268
+ `--ck-game-right-inset` on `document.body` so game HUDs can keep clear of
269
+ the dock.
270
+
271
+ ```ts
272
+ import { createCrowdyStudioEmbed } from '@crowdedkingdoms/crowdyjs/crowdy-studio';
273
+ // Self-starting glue worker for CLIENT mods (Vite shown; any bundler that
274
+ // packages module workers works):
275
+ import workerUrl from '@crowdedkingdoms/crowdyjs/player-glue-worker?worker&url';
276
+
277
+ const studio = createCrowdyStudioEmbed({
278
+ client: game, // CrowdyClient: crowdyStudio, playerCompute, playerWallet, crowdyStudioAgent
279
+ appId,
280
+ gameName: 'My Game',
281
+ suppressGameplayInput: () => pauseInput(),
282
+ onLayoutChange: () => resizeCanvas(),
283
+ });
284
+
285
+ // Per open (for example after the player claims a grid):
286
+ studio.toggle({
287
+ gridId,
288
+ targetPermissions: {
289
+ SERVER: { canWrite: true, canRun: true },
290
+ CLIENT: { canWrite: false, canRun: false }, // SERVER-only embeds omit workerUrl
291
+ },
292
+ });
293
+ ```
294
+
295
+ CLIENT-mod embeds additionally pass `grid`, `workerUrl`, `onHostCall`, an
296
+ optional `hud` sink, and a `playerHost` adapter. Note that CLIENT mods outside
297
+ Blocks with Friends remain gated by program decision D13; new games should
298
+ start SERVER-only exactly as above.
299
+
300
+ The visible agent safety chrome is exported from
301
+ `@crowdedkingdoms/crowdyjs/player-host`: **`PlayerControlGate`** (capture-phase
302
+ human preemption seam with offline Stop) and **`AgentControlBanner`** (the
303
+ always-visible-on-control Pause/Stop region, self-injected
304
+ `ck-agent-control-*` styles).
305
+
231
306
  ### Game API project contract
232
307
 
233
308
  `CrowdyStudioAPI` implements the transport-neutral
@@ -248,6 +323,193 @@ presentation enum to Crowdy Studio's runtime-oriented project kind and
248
323
  `CrowdyStudioRevisionConflictError` with the latest cloud project when that
249
324
  follow-up read succeeds.
250
325
 
326
+ ### Agent SDK, transport, and integrated dock (v12)
327
+
328
+ The v12 agent API remains provider-neutral, while CrowdyJS now ships generated
329
+ operations plus the production `CrowdyAgentGraphQLTransport` exposed as
330
+ `client.crowdyStudioAgent`:
331
+
332
+ ```ts
333
+ import {
334
+ CROWDY_AGENT_TOOL_REGISTRY_V1,
335
+ CrowdyStudioAgentController,
336
+ } from '@crowdedkingdoms/crowdyjs/agent';
337
+
338
+ const agent = new CrowdyStudioAgentController({
339
+ transport: game.crowdyStudioAgent,
340
+ createSession: {
341
+ appId,
342
+ projectId,
343
+ gridId,
344
+ mode: 'BUILD',
345
+ providerDataConsent: true,
346
+ idempotencyKey: crypto.randomUUID(),
347
+ },
348
+ beforeAgentWork: () => studio.controller.prepareForAgentWork(),
349
+ });
350
+ await agent.initialize(); // attach epoch → durable replay/gap fill → live tail
351
+ ```
352
+
353
+ `CROWDY_AGENT_TOOL_REGISTRY_V1` is an immutable, digest-pinned registry of the
354
+ minimum Studio/project/workspace/library/template/diagnostics/runtime and
355
+ generic game tools. Every descriptor has exact logical and provider wire names,
356
+ semantic version, bounded input/output JSON schemas,
357
+ `additionalProperties:false`, executor, mode, risk/effect/reversibility,
358
+ scope, approval, idempotency, timeout, and redaction metadata. Input schemas
359
+ reject caller-supplied identity, epoch, lease, approval, endpoint, token, and
360
+ other authority fields. `CrowdyAgentToolRegistry.fromWireName` is exact and
361
+ case-sensitive; browser dispatch is execute-once by `toolCallId`, and ambiguous
362
+ effects become `OUTCOME_UNKNOWN` instead of being repeated.
363
+
364
+ `CrowdyStudioAgentTransportV1` owns no credentials and exposes only typed
365
+ durable orchestration operations: session/history/descriptor/budget queries;
366
+ create/attach/mode/event-ack/message/approval/tool-result/lease/pause/resume/
367
+ cancel/close mutations; and the ordered event subscription. A generated adapter
368
+ maps these methods to the operation names in
369
+ `CROWDY_AGENT_GRAPHQL_OPERATIONS_V1`:
370
+
371
+ - `crowdyStudioAgentSession`, `crowdyStudioAgentSessions`,
372
+ `crowdyStudioAgentHistory`, `crowdyStudioAgentToolDescriptors`, and
373
+ `crowdyStudioAgentBudget`;
374
+ - `crowdyStudioAgentCreateSession`, `AttachClient`, `SetMode`,
375
+ `AcknowledgeEvents`, `Heartbeat`, `SendMessage`, `ApproveTool`, `RejectTool`,
376
+ `ToolResult`, `GrantLease`, `RevokeLease`, `Pause`, `Resume`, `CancelRun`,
377
+ and `CloseSession` (all with the `crowdyStudioAgent` prefix);
378
+ - `crowdyStudioAgentEvents(sessionId, afterSeq, clientEpoch)`.
379
+
380
+ The controller applies only contiguous decimal-string sequences, deduplicates
381
+ event IDs, fills gaps from durable history, acknowledges the highest
382
+ contiguous cursor, fences old attach epochs, and explicitly reconnects without
383
+ resuming a run or Play lease. Approval methods use the exact displayed argument
384
+ hash. Human edit/game input calls local preemption before best-effort transport
385
+ cleanup. Attach uses a stable `clientInstanceId` and the server
386
+ `replayAfterSeq`; public message input maps to Game API `content`, cancellation
387
+ always sends an explicit run id, and PLAY sends a two-second heartbeat only
388
+ while attached, active, and visible. Heartbeat, kill, and stale-epoch failures
389
+ immediately clear local authority.
390
+
391
+ Mode changes adopt the complete server-repinned session (registry digest,
392
+ provider/app policy revisions, and context version) before loading its new
393
+ effective descriptors. The Studio mount resolves the selected saved project
394
+ after `CrowdyStudioController.initialize()`, overrides caller guesses when
395
+ creating a BUILD session, and rejects an existing session bound to another
396
+ project. Because v1 has no set-project mutation, switching projects fences the
397
+ agent and requires a new session/remount.
398
+
399
+ An active BUILD workspace lease is renewed every ten seconds through the same
400
+ authenticated heartbeat; the server returns its renewed 30-second expiry.
401
+ Human edits, project/context changes, lease revocation, disconnect, and destroy
402
+ stop renewal and abort browser handlers. Run events retain their stable
403
+ `code`, `reason`, and typed safe `error`.
404
+
405
+ The committed descriptor digest fixture is checked on every build against the
406
+ canonical registry. Coordinated refreshes first run
407
+ `npm run agent-descriptors:drift -- --source <game-api-fixture>`; builds then
408
+ recompute the full and canonical 28-tool Game API subset digest (14 mandatory
409
+ game plus 14 Studio/diagnostic/runtime tools) so the fixture cannot silently
410
+ diverge.
411
+
412
+ Mount the responsive agent dock by adding `agent`; omit it to retain the v11
413
+ manual UI unchanged:
414
+
415
+ ```ts
416
+ const studio = await mountCrowdyStudio(host, {
417
+ projectProvider: game.crowdyStudio,
418
+ playerCompute: game.playerCompute,
419
+ appId,
420
+ gridId,
421
+ agent: {
422
+ transport: game.crowdyStudioAgent,
423
+ sessionId,
424
+ playerHost: bwfPlayerHostAdapter,
425
+ },
426
+ });
427
+
428
+ studio.agent?.sendMessage('Explain the current diagnostics');
429
+ studio.controlLeaseManager?.preempt('HUMAN_INPUT');
430
+ ```
431
+
432
+ The dock provides human-owned Ask/Build/Play selection, chat streaming,
433
+ plan/tool status, exact approval hashes, diff/checkpoint cards, budget, visible
434
+ lease scope/expiry, Pause/Resume/Stop, and checkpoint-restore requests. It uses
435
+ text nodes for all untrusted content, ARIA status/log/group labels, visible
436
+ focus, keyboard submission, and a container-query layout that moves the agent
437
+ dock below narrow embeds.
438
+
439
+ The headless `CrowdyStudioController` now also exposes:
440
+
441
+ - `prepareForAgentWork()` to flush autosave and fail closed on conflict/offline;
442
+ - `applyAtomicPatch()` and `synchronizeProject()` for all-or-none multi-file
443
+ updates, human-edit preemption, and Monaco synchronization;
444
+ - `refreshCheckpoints()` / `restoreCheckpoint()` through the optional
445
+ transport-neutral `CrowdyStudioSynchronizationProvider` (the provider is
446
+ required for agent writes/restores and must make checkpoint + revision
447
+ changes durable and atomic);
448
+ - typed draft/live results plus `runtimeSync` (`RUNNING_SAVED`,
449
+ `RUNNING_STALE`, `STOPPED`, or `NEVER_RUN`).
450
+
451
+ ### PlayerHostAdapter and Blocks with Friends integration
452
+
453
+ `@crowdedkingdoms/crowdyjs/player-host` exports
454
+ `PlayerHostAdapterV1`, capability/observation/command/result types and schemas,
455
+ `AgentControlLeaseManager`, and `createPlayerHostAgentTools`. A game adapter
456
+ implements only:
457
+
458
+ ```ts
459
+ interface PlayerHostAdapterV1 {
460
+ readonly contractVersion: 'crowdy.player-host/1';
461
+ capabilities(): Promise<PlayerHostCapabilitiesV1>;
462
+ observe(request: ObserveRequestV1): Promise<GameObservationV1>;
463
+ dispatch(command: GameCommandV1, gate: ValidatedGateV1):
464
+ Promise<GameCommandResultV1>;
465
+ clearAgentIntent(reason: CrowdyAgentPreemptionReason): void;
466
+ }
467
+ ```
468
+
469
+ For Blocks with Friends, implement this interface over the same typed intent
470
+ methods used by `PlayerController`, `ActionService`, `InventoryService`,
471
+ `FishingService`, `RideService`, and existing referee/model calls. Construct
472
+ `createPlayerHostAgentTools(adapter)` and pass `adapter` as the mount's
473
+ `playerHost`. The returned lease manager enforces TTL, scopes, client epoch,
474
+ host/controlled-entity revision, observation freshness, modal/death state,
475
+ per-command rate limits, approvals, and tool-call dedup. Call
476
+ `leaseManager.preempt('HUMAN_INPUT')` synchronously on key/mouse/touch input,
477
+ `ESCAPE` on Escape, and the corresponding reason on death, target/context
478
+ change, disconnect, or Stop. `clearAgentIntent` must immediately zero movement,
479
+ look, and pending action intent. BWF does not integrate through raw CrowdyJS,
480
+ DOM input, UDP packets, `PlayerCodeBroker`, or client-mod host calls.
481
+
482
+ BWF should pass only `game.crowdyStudioAgent` and its
483
+ `BwfPlayerHostAdapter` to the Studio mount; the mount derives the selected
484
+ project id. Its adapter must implement the exact 14 mandatory game surfaces,
485
+ classify combat as conditional approval, return typed failed/denied/unknown
486
+ outcomes, and make `clearAgentIntent` synchronously cancel shared movement and
487
+ action intents when the dispatcher aborts.
488
+
489
+ The reconciled Game API development pilot advertises the exact 28-tool
490
+ follow-up subset, including all 14 mandatory game descriptors. CrowdyJS routes
491
+ all game tools through
492
+ `PlayerHostAdapterV1`, the scoped lease gate, conditional combat approval,
493
+ safety stop, heartbeat fencing, and typed result continuation. BWF Play now
494
+ remains blocked only on the concrete BWF adapter/shared-intent wiring and its
495
+ host/app policy configuration.
496
+
497
+ The same browser dispatcher routes backend-advertised `runtime.test_draft`,
498
+ `runtime.deploy_live`, `runtime.invoke`, and `runtime.stop` through the
499
+ headless Studio controller. Draft testing is routine BUILD work; live deploy
500
+ and LIVE invoke require the exact approval grant; stop remains an idempotent
501
+ safety action. Inner game `FAILED`, `DENIED`, or `OUTCOME_UNKNOWN` results are
502
+ promoted to matching outer terminal tool results and are never reported as
503
+ successful.
504
+
505
+ Runtime execution is plan-bound: requested targets must exactly equal the
506
+ selected project’s authoritative target set, so a full-stack project cannot run
507
+ CLIENT after SERVER-only authorization. Live deploy additionally rechecks the
508
+ saved revision, canonical project content hash (including module names/files),
509
+ and pairing preference after autosave. Invoke checks the exact running
510
+ DRAFT/LIVE environment and export; stop always stops the complete selected
511
+ project as a safety action rather than interpreting a partial target.
512
+
251
513
  | `createWorldSession(client, appId, config)` (from `@crowdedkingdoms/crowdyjs/stores`) | World Stores: opt-in, SDK-managed game state — typed codecs (`structCodec` binary DSL), your own actor with a 5 Hz send loop (`session.self`), a remote-actor registry with lanes/history/staleness (`session.actors`), attributed send errors (`session.errors`), a chunk/voxel cache with realtime merge + worldgen write-back (`session.chunks`), channel/direct-message inboxes + a typed event router, host tracking, typed save/avatar state, and a game-model container mirror. Only configured stores exist (compile-time + runtime); unimported stores tree-shake away. |
252
514
  | `client.kit(appId)` | Game Kit: ready-made mappings of game concepts onto the game model — `kit.inventory`, `kit.objects` (lockable doors/chests with custom permissions), `kit.npcs`, `kit.plots` (buy/rent land with transactional, replication-enforced grid grants), and the genre layers `kit.economy` (wallets/shops/trades/market), `kit.progression` (xp/skills/achievements/rating), `kit.loot`, `kit.quests`, `kit.combat`, `kit.matches` (session lobbies/turns/scores with notify-to-pull channels), `kit.decks` (hidden hands), `kit.worldsim` (clock/nodes/crops/waves), `kit.social` (parties/guilds/chat over teams+channels), `kit.leaderboards`, `kit.features` (tier gates), and the engine-aware helpers `kit.mobs` (refereed attacks, defs/slots, contact-damage parsing), `kit.pets` (adopt/summon/dismiss/rename), `kit.instances` (private world slices, seeded runs), `kit.director` (encounter runs), `kit.matchmaking` (queues/proposals/rating), `kit.minigames` (invoke-loop wrapper), `kit.economy.orderBook` (escrowed bid/ask market), engine paths on `kit.matches`/`kit.decks`/`kit.leaderboards`, `kit.quests` tutorial sequencing, `kit.engines` (compute capability detection) with `kit/wire` (the engine pose codec, `engineLanes()`, and the 77/90/91/92/93 event parsers) — plus blueprint builders + `kit.deploy(...)` for the admin "load the rules" step. |
253
515
 
@@ -0,0 +1,41 @@
1
+ import type { CrowdyAgentMode, CrowdyAgentToolInvocationV1, CrowdyAgentToolResultV1 } from './types.js';
2
+ import { CrowdyAgentToolRegistry } from './registry.js';
3
+ export interface CrowdyAgentBrowserToolContextV1 {
4
+ readonly invocation: CrowdyAgentToolInvocationV1;
5
+ readonly signal: AbortSignal;
6
+ }
7
+ export type CrowdyAgentBrowserToolHandlerV1 = (argumentsValue: Readonly<Record<string, unknown>>, context: CrowdyAgentBrowserToolContextV1) => unknown | Promise<unknown>;
8
+ export type CrowdyAgentBrowserToolHandlersV1 = Readonly<Record<string, CrowdyAgentBrowserToolHandlerV1>>;
9
+ export interface CrowdyAgentBrowserDispatcherOptionsV1 {
10
+ readonly registry: CrowdyAgentToolRegistry;
11
+ readonly handlers: CrowdyAgentBrowserToolHandlersV1;
12
+ readonly getSessionId?: () => string | null;
13
+ readonly getClientEpoch: () => string | null;
14
+ readonly getContextVersion: () => string;
15
+ readonly getMode?: () => CrowdyAgentMode;
16
+ readonly now?: () => number;
17
+ readonly maxRememberedCalls?: number;
18
+ }
19
+ /**
20
+ * Exact browser tool router with execute-once semantics. It has no fallback
21
+ * executor: unknown names, raw SDK access, and missing handlers fail closed.
22
+ */
23
+ export declare class CrowdyAgentBrowserToolDispatcher {
24
+ private readonly options;
25
+ private readonly records;
26
+ private readonly active;
27
+ private readonly now;
28
+ constructor(options: CrowdyAgentBrowserDispatcherOptionsV1);
29
+ dispatch(invocation: CrowdyAgentToolInvocationV1): Promise<CrowdyAgentToolResultV1>;
30
+ has(toolCallId: string): boolean;
31
+ /** Abort pending browser work during human or context preemption. */
32
+ cancelActive(): void;
33
+ /**
34
+ * Cache lifetime is the attached session. Call only after that session is
35
+ * closed or fenced; clearing during a live session could repeat an effect.
36
+ */
37
+ clearClosedSession(): void;
38
+ private execute;
39
+ private validateEnvelope;
40
+ }
41
+ //# sourceMappingURL=browser-dispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-dispatcher.d.ts","sourceRoot":"","sources":["../../src/crowdy-agent/browser-dispatcher.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,eAAe,EACf,2BAA2B,EAC3B,uBAAuB,EACxB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAExD,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,UAAU,EAAE,2BAA2B,CAAC;IACjD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC9B;AAED,MAAM,MAAM,+BAA+B,GAAG,CAC5C,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACjD,OAAO,EAAE,+BAA+B,KACrC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEhC,MAAM,MAAM,gCAAgC,GAAG,QAAQ,CACrD,MAAM,CAAC,MAAM,EAAE,+BAA+B,CAAC,CAChD,CAAC;AAEF,MAAM,WAAW,qCAAqC;IACpD,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAC;IAC3C,QAAQ,CAAC,QAAQ,EAAE,gCAAgC,CAAC;IACpD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAC5C,QAAQ,CAAC,cAAc,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAC7C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,MAAM,CAAC;IACzC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,eAAe,CAAC;IACzC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACtC;AAOD;;;GAGG;AACH,qBAAa,gCAAgC;IAK/B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;IAC7D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsC;IAC7D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;gBAEN,OAAO,EAAE,qCAAqC;IAe3E,QAAQ,CACN,UAAU,EAAE,2BAA2B,GACtC,OAAO,CAAC,uBAAuB,CAAC;IA6CnC,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAIhC,qEAAqE;IACrE,YAAY,IAAI,IAAI;IAIpB;;;OAGG;IACH,kBAAkB,IAAI,IAAI;YAKZ,OAAO;IA6IrB,OAAO,CAAC,gBAAgB;CAyFzB"}