dreamboard 0.1.21 → 0.1.23
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.
- package/dist/{chunk-EYYWGWTO.js → chunk-2RCUHMGL.js} +343 -1911
- package/dist/chunk-2RCUHMGL.js.map +1 -0
- package/dist/{chunk-MOVHYB6E.js → chunk-GN7232BY.js} +1025 -695
- package/dist/chunk-GN7232BY.js.map +1 -0
- package/dist/{chunk-BMYC6772.js → chunk-H3O43F5P.js} +9765 -3068
- package/dist/chunk-H3O43F5P.js.map +1 -0
- package/dist/dev-host/dev-api-proxy-plugin.ts +330 -0
- package/dist/dev-host/dev-diagnostics.ts +62 -0
- package/dist/dev-host/dev-fallback-stylesheet.ts +50 -0
- package/dist/dev-host/dev-host-controller.ts +686 -0
- package/dist/dev-host/dev-host-player-query.ts +17 -0
- package/dist/dev-host/dev-host-session-transport.ts +52 -0
- package/dist/dev-host/dev-host-storage.ts +56 -0
- package/dist/dev-host/dev-log-relay-plugin.ts +469 -0
- package/dist/dev-host/dev-runtime-config.ts +14 -0
- package/dist/dev-host/dev-runtime-platform.ts +419 -0
- package/dist/dev-host/dev-virtual-modules-plugin.ts +63 -0
- package/dist/dev-host/host-main.css +182 -0
- package/dist/dev-host/host-main.tsx +754 -0
- package/dist/dev-host/index.html +56 -0
- package/dist/dev-host/plugin-main.ts +55 -0
- package/dist/dev-host/plugin.html +24 -0
- package/dist/dev-host/start-dev-server.ts +138 -0
- package/dist/dev-host/virtual-modules.d.ts +27 -0
- package/dist/dist-FEPN3BDN.js +16543 -0
- package/dist/dist-FEPN3BDN.js.map +1 -0
- package/dist/{dist-WJRJNFLI.js → dist-FRURQI7Q.js} +4 -2
- package/dist/index.js +3 -3
- package/dist/internal.js +159 -124
- package/dist/internal.js.map +1 -1
- package/dist/runtime-packages/tailwind-config/shared-styles.css +146 -0
- package/dist/runtime-packages/ui/src/components/.gitkeep +0 -0
- package/dist/runtime-packages/ui/src/components/accordion.tsx +66 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/actions.tsx +65 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/artifact.tsx +147 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/branch.tsx +215 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/canvas.tsx +22 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/chain-of-thought.tsx +228 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/code-block.tsx +179 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/confirmation.tsx +158 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/connection.tsx +28 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/context.tsx +408 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/controls.tsx +18 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/conversation.tsx +97 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/edge.tsx +140 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/image.tsx +24 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/inline-citation.tsx +287 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/loader.tsx +96 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/message.tsx +463 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/node.tsx +71 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/open-in-chat.tsx +365 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/panel.tsx +15 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/plan.tsx +142 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/prompt-input.tsx +1380 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/queue.tsx +274 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/reasoning.tsx +182 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/response.tsx +22 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/shimmer.tsx +64 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/sources.tsx +77 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/suggestion.tsx +53 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/task.tsx +87 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/tool.tsx +165 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/toolbar.tsx +16 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/web-preview.tsx +263 -0
- package/dist/runtime-packages/ui/src/components/alert-dialog.tsx +157 -0
- package/dist/runtime-packages/ui/src/components/alert.tsx +66 -0
- package/dist/runtime-packages/ui/src/components/avatar.tsx +53 -0
- package/dist/runtime-packages/ui/src/components/badge.tsx +46 -0
- package/dist/runtime-packages/ui/src/components/button-group.tsx +83 -0
- package/dist/runtime-packages/ui/src/components/button.tsx +65 -0
- package/dist/runtime-packages/ui/src/components/card.tsx +92 -0
- package/dist/runtime-packages/ui/src/components/carousel.tsx +241 -0
- package/dist/runtime-packages/ui/src/components/collapsible.tsx +33 -0
- package/dist/runtime-packages/ui/src/components/command.tsx +184 -0
- package/dist/runtime-packages/ui/src/components/context-menu.tsx +252 -0
- package/dist/runtime-packages/ui/src/components/counter.tsx +11 -0
- package/dist/runtime-packages/ui/src/components/dialog.tsx +146 -0
- package/dist/runtime-packages/ui/src/components/drawer.tsx +132 -0
- package/dist/runtime-packages/ui/src/components/dropdown-menu.tsx +257 -0
- package/dist/runtime-packages/ui/src/components/form.tsx +168 -0
- package/dist/runtime-packages/ui/src/components/header.tsx +13 -0
- package/dist/runtime-packages/ui/src/components/hover-card.tsx +44 -0
- package/dist/runtime-packages/ui/src/components/input-group.tsx +178 -0
- package/dist/runtime-packages/ui/src/components/input.tsx +21 -0
- package/dist/runtime-packages/ui/src/components/item.tsx +193 -0
- package/dist/runtime-packages/ui/src/components/label.tsx +24 -0
- package/dist/runtime-packages/ui/src/components/navigation-menu.tsx +168 -0
- package/dist/runtime-packages/ui/src/components/popover.tsx +55 -0
- package/dist/runtime-packages/ui/src/components/progress.tsx +31 -0
- package/dist/runtime-packages/ui/src/components/radio-group.tsx +45 -0
- package/dist/runtime-packages/ui/src/components/resizable.tsx +56 -0
- package/dist/runtime-packages/ui/src/components/scroll-area.tsx +58 -0
- package/dist/runtime-packages/ui/src/components/select.tsx +187 -0
- package/dist/runtime-packages/ui/src/components/separator.tsx +28 -0
- package/dist/runtime-packages/ui/src/components/skeleton.tsx +13 -0
- package/dist/runtime-packages/ui/src/components/sonner.tsx +25 -0
- package/dist/runtime-packages/ui/src/components/spinner.tsx +16 -0
- package/dist/runtime-packages/ui/src/components/switch.tsx +31 -0
- package/dist/runtime-packages/ui/src/components/table.tsx +137 -0
- package/dist/runtime-packages/ui/src/components/tabs.tsx +74 -0
- package/dist/runtime-packages/ui/src/components/textarea.tsx +23 -0
- package/dist/runtime-packages/ui/src/components/theme-provider.tsx +73 -0
- package/dist/runtime-packages/ui/src/components/tooltip.tsx +61 -0
- package/dist/runtime-packages/ui/src/components/ui/file-upload.tsx +195 -0
- package/dist/runtime-packages/ui/src/hooks/.gitkeep +0 -0
- package/dist/runtime-packages/ui/src/index.ts +68 -0
- package/dist/runtime-packages/ui/src/lib/utils.ts +6 -0
- package/dist/runtime-packages/ui-host-runtime/src/actor-principal.ts +68 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/host-controls.tsx +359 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback-toaster.tsx +274 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback.tsx +214 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/host-session-metadata.tsx +135 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/index.ts +5 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/perf-overlay.tsx +194 -0
- package/dist/runtime-packages/ui-host-runtime/src/host-controls.tsx +1 -0
- package/dist/runtime-packages/ui-host-runtime/src/host-feedback.tsx +1 -0
- package/dist/runtime-packages/ui-host-runtime/src/host-session-transport.ts +162 -0
- package/dist/runtime-packages/ui-host-runtime/src/index.ts +2 -0
- package/dist/runtime-packages/ui-host-runtime/src/logger.ts +11 -0
- package/dist/runtime-packages/ui-host-runtime/src/perf.ts +253 -0
- package/dist/runtime-packages/ui-host-runtime/src/plugin-bridge.ts +195 -0
- package/dist/runtime-packages/ui-host-runtime/src/plugin-health-check.ts +138 -0
- package/dist/runtime-packages/ui-host-runtime/src/plugin-messages.ts +159 -0
- package/dist/runtime-packages/ui-host-runtime/src/plugin-session-gateway.ts +524 -0
- package/dist/runtime-packages/ui-host-runtime/src/runtime/index.ts +12 -0
- package/dist/runtime-packages/ui-host-runtime/src/screenshot/projection-to-snapshot.ts +122 -0
- package/dist/runtime-packages/ui-host-runtime/src/screenshot/static-store-api.ts +26 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-ingress-controller.ts +477 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-ingress.ts +209 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-live-runtime.ts +112 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-model.ts +318 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-projection.ts +211 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-state-reducer.ts +814 -0
- package/dist/runtime-packages/ui-host-runtime/src/sse-manager.ts +334 -0
- package/dist/runtime-packages/ui-host-runtime/src/unified-session-store.ts +180 -0
- package/dist/scaffold/assets/static/app/tsconfig.framework.json +3 -1
- package/dist/scaffold/assets/static/ui/tsconfig.framework.json +7 -19
- package/package.json +52 -17
- package/skills/dreamboard/SKILL.md +41 -75
- package/LICENSE +0 -89
- package/NOTICE +0 -1
- package/dist/chunk-BMYC6772.js.map +0 -1
- package/dist/chunk-EYYWGWTO.js.map +0 -1
- package/dist/chunk-MOVHYB6E.js.map +0 -1
- package/dist/scaffold/assets/static/ui/App.tsx +0 -22
- package/dist/src-CUL7EGGG.js +0 -634
- package/dist/src-CUL7EGGG.js.map +0 -1
- package/skills/dreamboard/references/authoring-lifecycle.md +0 -102
- package/skills/dreamboard/references/board-surfaces.md +0 -36
- package/skills/dreamboard/references/board-topology.md +0 -443
- package/skills/dreamboard/references/boards-and-topology.md +0 -100
- package/skills/dreamboard/references/card-actions.md +0 -107
- package/skills/dreamboard/references/cli.md +0 -120
- package/skills/dreamboard/references/core-concepts.md +0 -514
- package/skills/dreamboard/references/custom-renderers.md +0 -26
- package/skills/dreamboard/references/derived-values.md +0 -55
- package/skills/dreamboard/references/effects.md +0 -111
- package/skills/dreamboard/references/game-contract.md +0 -89
- package/skills/dreamboard/references/game-definition.md +0 -89
- package/skills/dreamboard/references/game-shell.md +0 -80
- package/skills/dreamboard/references/hand-surfaces.md +0 -33
- package/skills/dreamboard/references/index.md +0 -112
- package/skills/dreamboard/references/inputs-and-targets.md +0 -160
- package/skills/dreamboard/references/interactions.md +0 -158
- package/skills/dreamboard/references/manifest-fields.md +0 -137
- package/skills/dreamboard/references/manifest.md +0 -81
- package/skills/dreamboard/references/package-surfaces.md +0 -69
- package/skills/dreamboard/references/phases.md +0 -145
- package/skills/dreamboard/references/prompts-and-choices.md +0 -55
- package/skills/dreamboard/references/quickstart.md +0 -71
- package/skills/dreamboard/references/rule-authoring.md +0 -144
- package/skills/dreamboard/references/setup-bootstrap.md +0 -78
- package/skills/dreamboard/references/stages-and-zones.md +0 -59
- package/skills/dreamboard/references/static-views.md +0 -67
- package/skills/dreamboard/references/table-queries-and-ops.md +0 -103
- package/skills/dreamboard/references/testing-bases.md +0 -147
- package/skills/dreamboard/references/testing-generated-contracts.md +0 -142
- package/skills/dreamboard/references/testing-runtime-assertions.md +0 -124
- package/skills/dreamboard/references/testing-scenarios.md +0 -148
- package/skills/dreamboard/references/testing-ui-tests.md +0 -174
- package/skills/dreamboard/references/testing.md +0 -161
- package/skills/dreamboard/references/ui-architecture.md +0 -137
- package/skills/dreamboard/references/ui-components.md +0 -34
- package/skills/dreamboard/references/views.md +0 -72
- package/skills/dreamboard/references/workspace-layout.md +0 -136
- /package/dist/{dist-WJRJNFLI.js.map → dist-FRURQI7Q.js.map} +0 -0
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
# Game contract
|
|
2
|
-
|
|
3
|
-
Use defineGameContract to bind generated manifest types to reducer state and phase names.
|
|
4
|
-
|
|
5
|
-
`defineGameContract` is the reducer's type root. It connects the generated manifest contract to state schemas and the legal phase-name tuple.
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
import { z } from "zod";
|
|
9
|
-
import { ids, manifestContract } from "../shared/manifest-contract";
|
|
10
|
-
import {
|
|
11
|
-
defineGameContract,
|
|
12
|
-
sparseCounts,
|
|
13
|
-
type GameStateOf,
|
|
14
|
-
} from "@dreamboard/app-sdk/reducer";
|
|
15
|
-
|
|
16
|
-
export const gameContract = defineGameContract({
|
|
17
|
-
manifest: manifestContract,
|
|
18
|
-
phaseNames: ["setup", "playerTurn", "endGame"] as const,
|
|
19
|
-
state: {
|
|
20
|
-
public: z.object({
|
|
21
|
-
scores: sparseCounts(ids.playerId),
|
|
22
|
-
winnerPlayerId: ids.playerId.nullable(),
|
|
23
|
-
}),
|
|
24
|
-
private: z.object({}),
|
|
25
|
-
hidden: z.object({}),
|
|
26
|
-
},
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
export type GameContract = typeof gameContract;
|
|
30
|
-
export type GameState = GameStateOf<GameContract>;
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Contract inputs
|
|
34
|
-
|
|
35
|
-
| Field | Purpose |
|
|
36
|
-
| --- | --- |
|
|
37
|
-
| `manifest` | The generated `manifestContract` from `shared/manifest-contract`. |
|
|
38
|
-
| `phaseNames` | A readonly tuple of every phase name the game can enter. |
|
|
39
|
-
| `state.public` | State visible to all players and generally safe to project. |
|
|
40
|
-
| `state.private` | Per-player secret state. |
|
|
41
|
-
| `state.hidden` | Game-owned secret state. |
|
|
42
|
-
|
|
43
|
-
`phaseNames` must match the keys registered in `defineGame({ phases })`. `defineGame` checks this at runtime, and TypeScript narrows phase names for `fx.transition(...)`, generated UI contracts, and generated tests.
|
|
44
|
-
|
|
45
|
-
## Use manifest-backed schemas
|
|
46
|
-
|
|
47
|
-
Prefer manifest-backed id schemas over plain strings:
|
|
48
|
-
|
|
49
|
-
```ts
|
|
50
|
-
const playerId = gameContract.schemas.playerId;
|
|
51
|
-
const cardId = gameContract.schemas.cardId;
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
or import the generated `ids` namespace:
|
|
55
|
-
|
|
56
|
-
```ts
|
|
57
|
-
import { ids } from "../shared/manifest-contract";
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
This keeps state and interaction params anchored to the manifest. A raw `z.string()` for `playerId`, `cardId`, `zoneId`, or board ids removes the type signal the SDK is trying to preserve.
|
|
61
|
-
|
|
62
|
-
## Sparse records
|
|
63
|
-
|
|
64
|
-
For records keyed by manifest ids, prefer sparse helpers:
|
|
65
|
-
|
|
66
|
-
```ts
|
|
67
|
-
scores: sparseCounts(ids.playerId)
|
|
68
|
-
roadsByEdgeId: sparseMap(ids.edgeId, roadSchema)
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Sparse records model "some ids have entries" without forcing every possible generated id to exist in state. They also preserve the manifest id type.
|
|
72
|
-
|
|
73
|
-
## What belongs in state
|
|
74
|
-
|
|
75
|
-
State should contain mutable facts the reducer owns:
|
|
76
|
-
|
|
77
|
-
- scores
|
|
78
|
-
- pending decisions
|
|
79
|
-
- current turn flags
|
|
80
|
-
- player-specific secrets
|
|
81
|
-
- derived-source data that changes over time
|
|
82
|
-
|
|
83
|
-
State should not mirror table facts that are already represented by component location, zone contents, resource balances, or board occupancy. Read those through `q` and mutate them through `ops`.
|
|
84
|
-
|
|
85
|
-
## Related pages
|
|
86
|
-
|
|
87
|
-
- [Game definition](./game-definition.md) for assembling the contract into a runnable game.
|
|
88
|
-
- [Table queries and ops](./table-queries-and-ops.md) for reading and writing table state.
|
|
89
|
-
- [Derived values](./derived-values.md) for computed aggregates.
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
# Game definition
|
|
2
|
-
|
|
3
|
-
Use defineGame to assemble initial state, setup profiles, phases, views, and static views.
|
|
4
|
-
|
|
5
|
-
`defineGame` is the assembly point for a reducer-native game. It registers the contract, initial state callbacks, setup profiles, phases, dynamic views, and optional static view.
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
import { defineGame } from "@dreamboard/app-sdk/reducer";
|
|
9
|
-
import { gameContract } from "./game-contract";
|
|
10
|
-
import { phases } from "./phases";
|
|
11
|
-
import { playerView } from "./player-view";
|
|
12
|
-
import { boardStatic } from "./board-static";
|
|
13
|
-
import setupProfiles from "./setup-profiles";
|
|
14
|
-
|
|
15
|
-
export default defineGame({
|
|
16
|
-
contract: gameContract,
|
|
17
|
-
initial: {
|
|
18
|
-
public: ({ playerIds }) => ({
|
|
19
|
-
scores: Object.fromEntries(playerIds.map((id) => [id, 0])),
|
|
20
|
-
winnerPlayerId: null,
|
|
21
|
-
}),
|
|
22
|
-
private: () => ({}),
|
|
23
|
-
hidden: () => ({}),
|
|
24
|
-
},
|
|
25
|
-
initialPhase: "setup",
|
|
26
|
-
setupProfiles,
|
|
27
|
-
phases,
|
|
28
|
-
views: {
|
|
29
|
-
player: playerView,
|
|
30
|
-
},
|
|
31
|
-
staticView: boardStatic,
|
|
32
|
-
});
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Fields
|
|
36
|
-
|
|
37
|
-
| Field | Purpose |
|
|
38
|
-
| --- | --- |
|
|
39
|
-
| `contract` | The `defineGameContract` result. |
|
|
40
|
-
| `initial` | Optional callbacks for initial `public`, `private`, and `hidden` state. |
|
|
41
|
-
| `initialPhase` | Phase to enter when setup does not override it. |
|
|
42
|
-
| `setupProfiles` | Runtime setup presets, usually generated through `shared/manifest-contract`. |
|
|
43
|
-
| `phases` | Phase registry keyed by phase name. |
|
|
44
|
-
| `views` | Dynamic projections, commonly `{ player: playerView }`. |
|
|
45
|
-
| `staticView` | Optional session-scoped immutable projection. |
|
|
46
|
-
|
|
47
|
-
## Initial state
|
|
48
|
-
|
|
49
|
-
Initial callbacks receive runtime context, including player ids, setup selection,
|
|
50
|
-
and `rngSeed`. Use this when state depends on the actual player count or needs
|
|
51
|
-
deterministic setup shuffles:
|
|
52
|
-
|
|
53
|
-
```ts
|
|
54
|
-
public: ({ playerIds, rngSeed, setup }) => ({
|
|
55
|
-
scores: Object.fromEntries(playerIds.map((playerId) => [playerId, 0])),
|
|
56
|
-
setupProfileId: setup.profileId,
|
|
57
|
-
terrainSeed: rngSeed,
|
|
58
|
-
winnerPlayerId: null,
|
|
59
|
-
})
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
Do not hard-code the manifest-wide maximum player list when the session may use fewer players.
|
|
63
|
-
|
|
64
|
-
## Phase registry
|
|
65
|
-
|
|
66
|
-
Keep phase registry keys aligned with `gameContract.phaseNames`:
|
|
67
|
-
|
|
68
|
-
```ts
|
|
69
|
-
export const phases = {
|
|
70
|
-
setup,
|
|
71
|
-
playerTurn,
|
|
72
|
-
endGame,
|
|
73
|
-
} satisfies PhaseMapOf<GameContract>;
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
`defineGame` validates the runtime shape as well, which catches dynamic phase registries that TypeScript cannot fully prove.
|
|
77
|
-
|
|
78
|
-
## Generated consumers
|
|
79
|
-
|
|
80
|
-
The generated UI and testing contracts inspect the `defineGame` result. Registered phases, interactions, card actions, stages, zones, and views become:
|
|
81
|
-
|
|
82
|
-
- `PhaseName`
|
|
83
|
-
- `InteractionId`
|
|
84
|
-
- phase-qualified `InteractionKey`
|
|
85
|
-
- surface-specific interaction unions
|
|
86
|
-
- `GameView`
|
|
87
|
-
- generated scenario interaction params
|
|
88
|
-
|
|
89
|
-
If a generated UI or test type is stale, rerun `dreamboard sync` or `dreamboard test generate` before patching authored code.
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
# UI primitives
|
|
2
|
-
|
|
3
|
-
Compose generated Dreamboard UI primitives instead of using the old shell/surface API.
|
|
4
|
-
|
|
5
|
-
Dreamboard UI now starts from generated, Radix-style primitives. The previous
|
|
6
|
-
shell/render-map workflow has been replaced by component composition.
|
|
7
|
-
|
|
8
|
-
## Scaffold default
|
|
9
|
-
|
|
10
|
-
```tsx
|
|
11
|
-
import { PromptInbox } from "@dreamboard/ui-contract";
|
|
12
|
-
|
|
13
|
-
export default function App() {
|
|
14
|
-
return (
|
|
15
|
-
<main>
|
|
16
|
-
<PromptInbox.Root>
|
|
17
|
-
<PromptInbox.Empty>No available prompts.</PromptInbox.Empty>
|
|
18
|
-
<PromptInbox.Items />
|
|
19
|
-
</PromptInbox.Root>
|
|
20
|
-
</main>
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Common primitives
|
|
26
|
-
|
|
27
|
-
```tsx
|
|
28
|
-
import { Interaction, PromptInbox, Zone } from "@dreamboard/ui-contract";
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
- `Interaction.Root` binds a descriptor by typed interaction key.
|
|
32
|
-
- `Interaction.Submit` submits the current draft when required inputs are ready.
|
|
33
|
-
- `Interaction.Input` and `Interaction.CardInput` mutate typed draft params.
|
|
34
|
-
- `PromptInbox.Root`, `PromptInbox.Empty`, and `PromptInbox.Items` render
|
|
35
|
-
addressed prompt descriptors.
|
|
36
|
-
- `Zone.Root`, `Zone.List`, and `Zone.Item` render card or collection zones.
|
|
37
|
-
|
|
38
|
-
## Defaults
|
|
39
|
-
|
|
40
|
-
If you want package-owned layout wrappers, import defaults explicitly:
|
|
41
|
-
|
|
42
|
-
```tsx
|
|
43
|
-
import { DefaultPromptInbox, GameLayout } from "@dreamboard/ui-sdk/defaults";
|
|
44
|
-
|
|
45
|
-
export default function App() {
|
|
46
|
-
return (
|
|
47
|
-
<GameLayout.Root>
|
|
48
|
-
<GameLayout.Sidebar>
|
|
49
|
-
<DefaultPromptInbox />
|
|
50
|
-
</GameLayout.Sidebar>
|
|
51
|
-
</GameLayout.Root>
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
Defaults are wrappers over primitives. You can replace any default with local
|
|
57
|
-
React without changing reducer code.
|
|
58
|
-
|
|
59
|
-
## Custom layouts
|
|
60
|
-
|
|
61
|
-
Custom game UIs should own layout in React and CSS:
|
|
62
|
-
|
|
63
|
-
```tsx
|
|
64
|
-
<main className="game">
|
|
65
|
-
<section>
|
|
66
|
-
<Board />
|
|
67
|
-
</section>
|
|
68
|
-
<aside>
|
|
69
|
-
<Interaction.Root interaction="playerTurn.endTurn">
|
|
70
|
-
<Interaction.Submit>End turn</Interaction.Submit>
|
|
71
|
-
</Interaction.Root>
|
|
72
|
-
<PromptInbox.Root>
|
|
73
|
-
<PromptInbox.Items />
|
|
74
|
-
</PromptInbox.Root>
|
|
75
|
-
</aside>
|
|
76
|
-
</main>
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
Reducers own availability, input shape, prompt recipients, target eligibility,
|
|
80
|
-
and validation. React owns visual grouping, labels, layout, dialogs, and style.
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# Card zones
|
|
2
|
-
|
|
3
|
-
Render card hands and card actions with generated Zone and Interaction primitives.
|
|
4
|
-
|
|
5
|
-
Card hands and piles are just zones plus interactions. Use generated `Zone`
|
|
6
|
-
primitives to provide card context and `Interaction.CardInput` to mutate the
|
|
7
|
-
typed draft.
|
|
8
|
-
|
|
9
|
-
```tsx
|
|
10
|
-
import { Interaction, Zone } from "@dreamboard/ui-contract";
|
|
11
|
-
import { Card } from "@dreamboard/ui-sdk";
|
|
12
|
-
|
|
13
|
-
<Zone.Root zone="hand">
|
|
14
|
-
<Zone.List>
|
|
15
|
-
{view.hand.map((card) => (
|
|
16
|
-
<Zone.Item key={card.id} card={card.id}>
|
|
17
|
-
<Interaction.Root interaction="playerTurn.playCard">
|
|
18
|
-
<Interaction.CardInput input="cardId" card={card.id}>
|
|
19
|
-
<Card card={card} />
|
|
20
|
-
</Interaction.CardInput>
|
|
21
|
-
</Interaction.Root>
|
|
22
|
-
</Zone.Item>
|
|
23
|
-
))}
|
|
24
|
-
</Zone.List>
|
|
25
|
-
</Zone.Root>
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
For multi-card selection, `Interaction.CardInput` reads the reducer-projected
|
|
29
|
-
selection metadata. It updates the draft until the count is ready, then
|
|
30
|
-
`Interaction.Submit` can submit the interaction.
|
|
31
|
-
|
|
32
|
-
Keep card faces local to the game. Keep card legality in reducer target
|
|
33
|
-
collectors and card actions.
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
# Dreamboard
|
|
2
|
-
|
|
3
|
-
An agent-native framework for prototyping board games.
|
|
4
|
-
|
|
5
|
-
Dreamboard is a local-first authoring framework for building rule-enforced multiplayer board games. It is great for early-stage board game prototyping where rules are changing fast and components need to be added or removed from the game for quick iteration.
|
|
6
|
-
You regenerate contracts with `dreamboard sync`, compile the authored head with `dreamboard compile`, and then run `dreamboard dev` to play locally while you iterate. The same compiled game can be opened from desktop browser or mobile phone.
|
|
7
|
-
|
|
8
|
-
It achieves this by providing strong defaults, templates and components for common types for board games, but it is flexible enough for user to customize the game when needed.
|
|
9
|
-
And because of the opinionated choice, it works very well with coding agents (Claude Code, Codex, Cursor and etc) when pair with the skill.
|
|
10
|
-
|
|
11
|
-
## The authoring loop
|
|
12
|
-
|
|
13
|
-
Most work happens in five files or folders:
|
|
14
|
-
|
|
15
|
-
| Layer | File or folder | Owns |
|
|
16
|
-
| --- | --- | --- |
|
|
17
|
-
| Intent | `rule.md` | Human-readable game rules and design decisions. |
|
|
18
|
-
| Topology | `manifest.ts` | Game components (e.g. boards, cards, zones, pieces, dice, resources) and player setup. |
|
|
19
|
-
| Game | `app/` | Core logic for the game. |
|
|
20
|
-
| Interface | `ui/` | React UI built from generated view and interaction contracts. |
|
|
21
|
-
| Verification | `test/` | Game logic and UI tests by simulating real runs. |
|
|
22
|
-
|
|
23
|
-
The CLI ties those files together:
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
dreamboard sync
|
|
27
|
-
dreamboard compile
|
|
28
|
-
dreamboard dev
|
|
29
|
-
dreamboard test generate
|
|
30
|
-
dreamboard test run
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
`sync` regenerates workspace contracts, `compile` builds the reducer bundle, `dev` runs a playable local session, and `test` replays scenarios against the same reducer definition.
|
|
34
|
-
|
|
35
|
-
## A small example
|
|
36
|
-
|
|
37
|
-
In `manifest.ts`, define the static table shape:
|
|
38
|
-
|
|
39
|
-
```ts
|
|
40
|
-
import { defineTopologyManifest } from "@dreamboard/sdk-types";
|
|
41
|
-
|
|
42
|
-
export default defineTopologyManifest({
|
|
43
|
-
players: { minPlayers: 2, maxPlayers: 4, optimalPlayers: 3 },
|
|
44
|
-
cardSets: [
|
|
45
|
-
{
|
|
46
|
-
type: "manual",
|
|
47
|
-
id: "things",
|
|
48
|
-
name: "Things",
|
|
49
|
-
cardSchema: { properties: { label: { type: "string" } } },
|
|
50
|
-
cards: [
|
|
51
|
-
{ type: "moon", name: "Moon", count: 1, properties: { label: "Moon" } },
|
|
52
|
-
],
|
|
53
|
-
},
|
|
54
|
-
],
|
|
55
|
-
zones: [
|
|
56
|
-
{ id: "draw", name: "Draw", scope: "shared", allowedCardSetIds: ["things"] },
|
|
57
|
-
{ id: "hand", name: "Hand", scope: "perPlayer", allowedCardSetIds: ["things"] },
|
|
58
|
-
],
|
|
59
|
-
boards: [],
|
|
60
|
-
});
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
In `app/game-contract.ts`, bind generated manifest types to reducer state:
|
|
64
|
-
|
|
65
|
-
```ts
|
|
66
|
-
import { z } from "zod";
|
|
67
|
-
import { ids, manifestContract } from "../shared/manifest-contract";
|
|
68
|
-
import { defineGameContract } from "@dreamboard/app-sdk/reducer";
|
|
69
|
-
|
|
70
|
-
export const gameContract = defineGameContract({
|
|
71
|
-
manifest: manifestContract,
|
|
72
|
-
phaseNames: ["play"] as const,
|
|
73
|
-
state: {
|
|
74
|
-
public: z.object({ winnerPlayerId: ids.playerId.nullable() }) // state visible to all players,
|
|
75
|
-
private: z.object({}) // player state for each player,
|
|
76
|
-
hidden: z.object({}) // internal state for game - not visible,
|
|
77
|
-
},
|
|
78
|
-
});
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
In a phase, declare typed interactions. The reducer stays authoritative; the UI receives typed descriptors and eligible targets from the same definition.
|
|
82
|
-
|
|
83
|
-
```ts
|
|
84
|
-
import { z } from "zod";
|
|
85
|
-
import {
|
|
86
|
-
defineInteraction,
|
|
87
|
-
definePhase,
|
|
88
|
-
pipe,
|
|
89
|
-
} from "@dreamboard/app-sdk/reducer";
|
|
90
|
-
|
|
91
|
-
const play = definePhase<GameContract>()({
|
|
92
|
-
kind: "player",
|
|
93
|
-
state: z.object({}),
|
|
94
|
-
initialState: () => ({}),
|
|
95
|
-
actor: ({ state }) => state.flow.activePlayers,
|
|
96
|
-
interactions: {
|
|
97
|
-
endTurn: defineInteraction<GameContract>()({
|
|
98
|
-
inputs: {},
|
|
99
|
-
reduce({ state, accept, fx, ops }) {
|
|
100
|
-
return accept(pipe(state, ops.advanceActivePlayer())) // keep same state, advance to next player;
|
|
101
|
-
},
|
|
102
|
-
}),
|
|
103
|
-
},
|
|
104
|
-
});
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
## What to read next
|
|
108
|
-
|
|
109
|
-
- [Quickstart](./quickstart.md) gets a fresh workspace running.
|
|
110
|
-
- [Workspace layout](./workspace-layout.md) explains generated and authored files.
|
|
111
|
-
- [Core concepts](./core-concepts.md) defines the vocabulary used across the docs.
|
|
112
|
-
- [Manifest](./manifest.md) and [Game contract](./game-contract.md) are the first two authoring references.
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
# Inputs and targets
|
|
2
|
-
|
|
3
|
-
Use collectors and target rules to type interaction params, project eligible targets, and validate submissions.
|
|
4
|
-
|
|
5
|
-
Inputs define interaction params. Targets define finite eligibility. Together they are the canonical path for player choices.
|
|
6
|
-
|
|
7
|
-
## Target rules
|
|
8
|
-
|
|
9
|
-
A target rule starts from a candidate set and filters it through predicates.
|
|
10
|
-
|
|
11
|
-
```ts
|
|
12
|
-
export const buildPathTarget = boardTarget
|
|
13
|
-
.edge<GameState, EdgeId>("main-board")
|
|
14
|
-
.where({
|
|
15
|
-
id: "empty",
|
|
16
|
-
errorCode: "EDGE_OCCUPIED",
|
|
17
|
-
message: "That edge already has a path.",
|
|
18
|
-
test: ({ state, targetId }) => !state.publicState.pathsByEdgeId[targetId],
|
|
19
|
-
})
|
|
20
|
-
.where({
|
|
21
|
-
id: "connected",
|
|
22
|
-
errorCode: "NOT_CONNECTED",
|
|
23
|
-
message: "Path must connect to your network.",
|
|
24
|
-
test: ({ state, q, targetId, playerId }) =>
|
|
25
|
-
isConnectedPathTarget(state, q, targetId, playerId),
|
|
26
|
-
})
|
|
27
|
-
.build();
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
The built rule exposes:
|
|
31
|
-
|
|
32
|
-
- `eligible(ctx)`
|
|
33
|
-
- `validate(ctx, id)`
|
|
34
|
-
- `isEligible(ctx, id)`
|
|
35
|
-
- `bind(ctx)` for a state/player/query-scoped rule
|
|
36
|
-
|
|
37
|
-
Use the same rule in collectors and any reducer code that needs to re-check a second optional target.
|
|
38
|
-
|
|
39
|
-
## Board inputs
|
|
40
|
-
|
|
41
|
-
```ts
|
|
42
|
-
inputs: {
|
|
43
|
-
edgeId: boardInput.edge<GameState, EdgeId>({
|
|
44
|
-
target: buildPathTarget,
|
|
45
|
-
}),
|
|
46
|
-
}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
Board inputs support `vertex`, `edge`, `space`, and `tile`. They carry target
|
|
50
|
-
metadata such as board id and target kind so generated board helpers can
|
|
51
|
-
highlight eligible board elements.
|
|
52
|
-
|
|
53
|
-
## Card inputs
|
|
54
|
-
|
|
55
|
-
```ts
|
|
56
|
-
const playableCardTarget = cardTarget
|
|
57
|
-
.zones<GameState, ThingsDeckCardId>(["things-hand"])
|
|
58
|
-
.build();
|
|
59
|
-
|
|
60
|
-
inputs: {
|
|
61
|
-
cardId: cardInput<GameState, ThingsDeckCardId>({
|
|
62
|
-
target: playableCardTarget,
|
|
63
|
-
}),
|
|
64
|
-
}
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
Card targets enumerate cards from a shared or per-player zone, then apply predicates.
|
|
68
|
-
|
|
69
|
-
## Choice targets and prompts
|
|
70
|
-
|
|
71
|
-
Finite prompt choices should use `choiceTarget` with `promptInput`.
|
|
72
|
-
|
|
73
|
-
```ts
|
|
74
|
-
const responseTarget = choiceTarget
|
|
75
|
-
.options<GameState, "accept" | "reject">([
|
|
76
|
-
{ id: "accept", label: "Accept" },
|
|
77
|
-
{ id: "reject", label: "Reject" },
|
|
78
|
-
])
|
|
79
|
-
.build();
|
|
80
|
-
|
|
81
|
-
inputs: {
|
|
82
|
-
response: promptInput({
|
|
83
|
-
schema: z.enum(["accept", "reject"]),
|
|
84
|
-
target: responseTarget,
|
|
85
|
-
}),
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
The target provides labeled options for UI and server-side validation for submit.
|
|
90
|
-
|
|
91
|
-
## Form inputs
|
|
92
|
-
|
|
93
|
-
Use `formInput(schema)` for free-form Zod-backed params. Prefer domain-specific helpers when the UI or agents can benefit from constraints:
|
|
94
|
-
|
|
95
|
-
```ts
|
|
96
|
-
formInput.choice<ResourceId>({ choices: RESOURCE_CHOICES })
|
|
97
|
-
formInput.choiceList<PlayerId>({ choices: PLAYER_CHOICES, min: 1 })
|
|
98
|
-
formInput.number({ min: 0, max: ({ q, playerId }) => q.player.resource(playerId, "coin") })
|
|
99
|
-
formInput.resourceMap({ resources: [{ resourceId: "coin", max: 3 }] })
|
|
100
|
-
formInput.resourceChoices({ decorate: ({ resourceId }) => ({ badge: resourceId }) })
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
Free-form schemas are valid, but they are opaque to automated UI and bot flows.
|
|
104
|
-
|
|
105
|
-
Use `defaultValue` when a form control should start with a real selection or value:
|
|
106
|
-
|
|
107
|
-
```ts
|
|
108
|
-
inputs: {
|
|
109
|
-
giveResource: formInput.choice<ResourceId>({
|
|
110
|
-
choices: RESOURCE_CHOICES,
|
|
111
|
-
defaultValue: resources.lumber,
|
|
112
|
-
}),
|
|
113
|
-
}
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
Defaults are not requiredness flags. `formInput.choice(...)` is already required unless its schema is optional or nullable. Defaults are projected to UI descriptors, applied by generated client schemas, and exposed through `handle.values` so custom renderers can read the effective draft without local fallback casts. `handle.draft` remains partial because it is still the raw in-progress draft.
|
|
117
|
-
|
|
118
|
-
## Multi-select collectors
|
|
119
|
-
|
|
120
|
-
Wrap a target collector with `many(...)` when one interaction needs several
|
|
121
|
-
values from the same target domain:
|
|
122
|
-
|
|
123
|
-
```ts
|
|
124
|
-
inputs: {
|
|
125
|
-
cardIds: many(cardInput<GameState, CardId>({ target: playableCardTarget }), {
|
|
126
|
-
min: 1,
|
|
127
|
-
max: 3,
|
|
128
|
-
distinct: true,
|
|
129
|
-
}),
|
|
130
|
-
},
|
|
131
|
-
commit: { mode: "manual" },
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
`many(...)` supports `{ count }` or `{ min, max, distinct }`. It cannot wrap
|
|
135
|
-
`rngInput` collectors, and it always represents a manual draft selection: the
|
|
136
|
-
player picks a set, then submits explicitly.
|
|
137
|
-
|
|
138
|
-
## Engine-sampled inputs
|
|
139
|
-
|
|
140
|
-
`rngInput.*` collectors are sampled by the trusted engine on submit. Clients do not supply these fields.
|
|
141
|
-
|
|
142
|
-
```ts
|
|
143
|
-
inputs: {
|
|
144
|
-
dice: rngInput.d6(2),
|
|
145
|
-
},
|
|
146
|
-
reduce({ input }) {
|
|
147
|
-
const values = input.params.dice.values;
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
Use `rngInput` when the random result belongs to one interaction. Use [Effects](./effects.md) when randomness should be queued as an engine instruction.
|
|
152
|
-
|
|
153
|
-
## One source of truth
|
|
154
|
-
|
|
155
|
-
Do not duplicate eligibility in the UI. The target rule should be the shared source for:
|
|
156
|
-
|
|
157
|
-
- projected eligible targets
|
|
158
|
-
- submit validation
|
|
159
|
-
- reducer business logic that needs the same predicate
|
|
160
|
-
- tests
|