@dxos/plugin-chess 0.10.0 → 0.11.1

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 (163) hide show
  1. package/dist/lib/ChessPlugin.mjs +2 -0
  2. package/dist/lib/ChessPlugin.node.mjs +19 -0
  3. package/dist/lib/ChessPlugin.node.mjs.map +1 -0
  4. package/dist/lib/ChessPlugin.workerd.mjs +15 -0
  5. package/dist/lib/ChessPlugin.workerd.mjs.map +1 -0
  6. package/dist/lib/capabilities/node.mjs +8 -0
  7. package/dist/lib/capabilities/node.mjs.map +1 -0
  8. package/dist/lib/capabilities.mjs +9 -0
  9. package/dist/lib/capabilities.mjs.map +1 -0
  10. package/dist/lib/chunk-ChessArticle.mjs +89 -0
  11. package/dist/lib/chunk-ChessArticle.mjs.map +1 -0
  12. package/dist/lib/chunk-ChessCard.mjs +25 -0
  13. package/dist/lib/chunk-ChessCard.mjs.map +1 -0
  14. package/dist/lib/chunk-ChessPlugin.mjs +26 -0
  15. package/dist/lib/chunk-ChessPlugin.mjs.map +1 -0
  16. package/dist/lib/chunk-game-variant.mjs +34 -0
  17. package/dist/lib/chunk-game-variant.mjs.map +1 -0
  18. package/dist/lib/chunk-meta.mjs +29 -0
  19. package/dist/lib/chunk-meta.mjs.map +1 -0
  20. package/dist/lib/chunk-move.mjs +23 -0
  21. package/dist/lib/chunk-move.mjs.map +1 -0
  22. package/dist/lib/chunk-operation-handler.mjs +11 -0
  23. package/dist/lib/chunk-operation-handler.mjs.map +1 -0
  24. package/dist/lib/chunk-play.mjs +32 -0
  25. package/dist/lib/chunk-play.mjs.map +1 -0
  26. package/dist/lib/chunk-print.mjs +18 -0
  27. package/dist/lib/chunk-print.mjs.map +1 -0
  28. package/dist/lib/chunk-rebuild-position-index.mjs +126 -0
  29. package/dist/lib/chunk-rebuild-position-index.mjs.map +1 -0
  30. package/dist/lib/chunk-skill-definition.mjs +10 -0
  31. package/dist/lib/chunk-skill-definition.mjs.map +1 -0
  32. package/dist/lib/{neutral/chunk-IKWULCKX.mjs → chunk-skills.mjs} +14 -20
  33. package/dist/lib/chunk-skills.mjs.map +1 -0
  34. package/dist/lib/chunk-types.mjs +202 -0
  35. package/dist/lib/chunk-types.mjs.map +1 -0
  36. package/dist/lib/components.mjs +224 -0
  37. package/dist/lib/components.mjs.map +1 -0
  38. package/dist/lib/containers.mjs +8 -0
  39. package/dist/lib/containers.mjs.map +1 -0
  40. package/dist/lib/index.mjs +4 -0
  41. package/dist/lib/meta.mjs +2 -0
  42. package/dist/lib/operations.mjs +7 -0
  43. package/dist/lib/operations.mjs.map +1 -0
  44. package/dist/lib/plugin.mjs +9 -0
  45. package/dist/lib/plugin.mjs.map +1 -0
  46. package/dist/lib/skills.mjs +2 -0
  47. package/dist/lib/testing.mjs +2 -0
  48. package/dist/lib/translations.mjs +51 -0
  49. package/dist/lib/translations.mjs.map +1 -0
  50. package/dist/lib/types.mjs +2 -0
  51. package/dist/types/src/capabilities/game-variant.d.ts +1 -1
  52. package/dist/types/src/capabilities/node.d.ts +5 -0
  53. package/dist/types/src/capabilities/node.d.ts.map +1 -0
  54. package/dist/types/src/capabilities/operation-handler.d.ts +1 -1
  55. package/dist/types/src/components/Chessboard/Chessboard.stories.d.ts +52 -4
  56. package/dist/types/src/components/Chessboard/Chessboard.stories.d.ts.map +1 -1
  57. package/dist/types/src/components/Chessboard/types.d.ts +1 -1
  58. package/dist/types/src/components/Chessboard/types.d.ts.map +1 -1
  59. package/dist/types/src/containers/ChessArticle/ChessArticle.d.ts +4 -1
  60. package/dist/types/src/containers/ChessArticle/ChessArticle.d.ts.map +1 -1
  61. package/dist/types/src/containers/ChessArticle/ChessArticle.stories.d.ts +52 -4
  62. package/dist/types/src/containers/ChessArticle/ChessArticle.stories.d.ts.map +1 -1
  63. package/dist/types/src/containers/ChessCard/ChessCard.d.ts +4 -1
  64. package/dist/types/src/containers/ChessCard/ChessCard.d.ts.map +1 -1
  65. package/dist/types/src/internal/position-index.d.ts +34 -0
  66. package/dist/types/src/internal/position-index.d.ts.map +1 -0
  67. package/dist/types/src/operations/index.d.ts.map +1 -1
  68. package/dist/types/src/operations/move.d.ts.map +1 -1
  69. package/dist/types/src/operations/play.d.ts.map +1 -1
  70. package/dist/types/src/operations/rebuild-position-index.d.ts +4 -0
  71. package/dist/types/src/operations/rebuild-position-index.d.ts.map +1 -0
  72. package/dist/types/src/operations/rebuild-position-index.test.d.ts +2 -0
  73. package/dist/types/src/operations/rebuild-position-index.test.d.ts.map +1 -0
  74. package/dist/types/src/translations.d.ts +52 -4
  75. package/dist/types/src/translations.d.ts.map +1 -1
  76. package/dist/types/src/types/ChessOperation.d.ts +11 -3
  77. package/dist/types/src/types/ChessOperation.d.ts.map +1 -1
  78. package/dist/types/src/types/ChessPositionIndex.d.ts +50 -0
  79. package/dist/types/src/types/ChessPositionIndex.d.ts.map +1 -0
  80. package/dist/types/src/types/PlayerReview.d.ts +23 -0
  81. package/dist/types/src/types/PlayerReview.d.ts.map +1 -0
  82. package/dist/types/src/types/index.d.ts +2 -0
  83. package/dist/types/src/types/index.d.ts.map +1 -1
  84. package/dist/types/tsconfig.tsbuildinfo +1 -1
  85. package/dx.config.ts +1 -1
  86. package/package.json +50 -43
  87. package/src/ChessPlugin.node.ts +2 -2
  88. package/src/ChessPlugin.tsx +2 -2
  89. package/src/ChessPlugin.workerd.ts +2 -2
  90. package/src/capabilities/node.ts +16 -0
  91. package/src/components/Chessboard/Info.tsx +2 -2
  92. package/src/components/Chessboard/types.ts +1 -1
  93. package/src/containers/ChessArticle/ChessArticle.stories.tsx +2 -2
  94. package/src/containers/ChessArticle/ChessArticle.tsx +19 -13
  95. package/src/containers/ChessCard/ChessCard.stories.tsx +2 -2
  96. package/src/containers/ChessCard/ChessCard.tsx +2 -0
  97. package/src/internal/position-index.ts +148 -0
  98. package/src/operations/index.ts +1 -0
  99. package/src/operations/move.ts +1 -2
  100. package/src/operations/play.ts +1 -2
  101. package/src/operations/rebuild-position-index.test.ts +118 -0
  102. package/src/operations/rebuild-position-index.ts +73 -0
  103. package/src/translations.ts +19 -1
  104. package/src/types/ChessOperation.ts +25 -4
  105. package/src/types/ChessPositionIndex.ts +53 -0
  106. package/src/types/PlayerReview.ts +48 -0
  107. package/src/types/index.ts +2 -0
  108. package/dist/lib/neutral/ChessArticle-MPRT54KQ.mjs +0 -89
  109. package/dist/lib/neutral/ChessArticle-MPRT54KQ.mjs.map +0 -7
  110. package/dist/lib/neutral/ChessCard-VJ3I6MIB.mjs +0 -24
  111. package/dist/lib/neutral/ChessCard-VJ3I6MIB.mjs.map +0 -7
  112. package/dist/lib/neutral/ChessPlugin.mjs +0 -10
  113. package/dist/lib/neutral/ChessPlugin.mjs.map +0 -7
  114. package/dist/lib/neutral/ChessPlugin.node.mjs +0 -23
  115. package/dist/lib/neutral/ChessPlugin.node.mjs.map +0 -7
  116. package/dist/lib/neutral/ChessPlugin.workerd.mjs +0 -21
  117. package/dist/lib/neutral/ChessPlugin.workerd.mjs.map +0 -7
  118. package/dist/lib/neutral/capabilities/index.mjs +0 -13
  119. package/dist/lib/neutral/capabilities/index.mjs.map +0 -7
  120. package/dist/lib/neutral/chunk-AMXVX7V2.mjs +0 -8
  121. package/dist/lib/neutral/chunk-AMXVX7V2.mjs.map +0 -7
  122. package/dist/lib/neutral/chunk-DXIET5G2.mjs +0 -148
  123. package/dist/lib/neutral/chunk-DXIET5G2.mjs.map +0 -7
  124. package/dist/lib/neutral/chunk-EXZ3XFEG.mjs +0 -41
  125. package/dist/lib/neutral/chunk-EXZ3XFEG.mjs.map +0 -7
  126. package/dist/lib/neutral/chunk-IKWULCKX.mjs.map +0 -7
  127. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
  128. package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
  129. package/dist/lib/neutral/chunk-YZTKZ5F7.mjs +0 -42
  130. package/dist/lib/neutral/chunk-YZTKZ5F7.mjs.map +0 -7
  131. package/dist/lib/neutral/components/index.mjs +0 -240
  132. package/dist/lib/neutral/components/index.mjs.map +0 -7
  133. package/dist/lib/neutral/containers/index.mjs +0 -11
  134. package/dist/lib/neutral/containers/index.mjs.map +0 -7
  135. package/dist/lib/neutral/game-variant-ZLPEN2QK.mjs +0 -41
  136. package/dist/lib/neutral/game-variant-ZLPEN2QK.mjs.map +0 -7
  137. package/dist/lib/neutral/index.mjs +0 -18
  138. package/dist/lib/neutral/index.mjs.map +0 -7
  139. package/dist/lib/neutral/meta.json +0 -1
  140. package/dist/lib/neutral/meta.mjs +0 -8
  141. package/dist/lib/neutral/meta.mjs.map +0 -7
  142. package/dist/lib/neutral/move-UMDTQST4.mjs +0 -37
  143. package/dist/lib/neutral/move-UMDTQST4.mjs.map +0 -7
  144. package/dist/lib/neutral/operation-handler-EKZKFQUG.mjs +0 -13
  145. package/dist/lib/neutral/operation-handler-EKZKFQUG.mjs.map +0 -7
  146. package/dist/lib/neutral/operations/index.mjs +0 -8
  147. package/dist/lib/neutral/operations/index.mjs.map +0 -7
  148. package/dist/lib/neutral/play-7XTJZ4N6.mjs +0 -46
  149. package/dist/lib/neutral/play-7XTJZ4N6.mjs.map +0 -7
  150. package/dist/lib/neutral/plugin.mjs +0 -16
  151. package/dist/lib/neutral/plugin.mjs.map +0 -7
  152. package/dist/lib/neutral/print-JR4VB3UX.mjs +0 -29
  153. package/dist/lib/neutral/print-JR4VB3UX.mjs.map +0 -7
  154. package/dist/lib/neutral/skill-definition-ZGQBUE4R.mjs +0 -15
  155. package/dist/lib/neutral/skill-definition-ZGQBUE4R.mjs.map +0 -7
  156. package/dist/lib/neutral/skills/index.mjs +0 -8
  157. package/dist/lib/neutral/skills/index.mjs.map +0 -7
  158. package/dist/lib/neutral/testing.mjs +0 -8
  159. package/dist/lib/neutral/testing.mjs.map +0 -7
  160. package/dist/lib/neutral/translations.mjs +0 -39
  161. package/dist/lib/neutral/translations.mjs.map +0 -7
  162. package/dist/lib/neutral/types/index.mjs +0 -10
  163. package/dist/lib/neutral/types/index.mjs.map +0 -7
package/dx.config.ts CHANGED
@@ -17,7 +17,7 @@ export default Config2.make({
17
17
  source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-chess',
18
18
  icon: { key: 'ph--shield-chevron--regular', hue: 'amber' },
19
19
  spec: 'PLUGIN.mdl',
20
- tags: ['game'],
20
+ tags: ['alpha', 'game'],
21
21
  screenshots: [{ dark: 'https://dxos.network/plugin-details-chess-dark.png' }],
22
22
  dependsOn: ['org.dxos.plugin.game'],
23
23
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-chess",
3
- "version": "0.10.0",
3
+ "version": "0.11.1",
4
4
  "description": "Chess for new plugin",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -16,32 +16,36 @@
16
16
  "#skills": {
17
17
  "source": "./src/skills/index.ts",
18
18
  "types": "./dist/types/src/skills/index.d.ts",
19
- "default": "./dist/lib/neutral/skills/index.mjs"
19
+ "default": "./dist/lib/skills.mjs"
20
20
  },
21
21
  "#capabilities": {
22
- "source": "./src/capabilities/index.ts",
22
+ "source": {
23
+ "node": "./src/capabilities/node.ts",
24
+ "default": "./src/capabilities/index.ts"
25
+ },
23
26
  "types": "./dist/types/src/capabilities/index.d.ts",
24
- "default": "./dist/lib/neutral/capabilities/index.mjs"
27
+ "node": "./dist/lib/capabilities/node.mjs",
28
+ "default": "./dist/lib/capabilities.mjs"
25
29
  },
26
30
  "#components": {
27
31
  "source": "./src/components/index.ts",
28
32
  "types": "./dist/types/src/components/index.d.ts",
29
- "default": "./dist/lib/neutral/components/index.mjs"
33
+ "default": "./dist/lib/components.mjs"
30
34
  },
31
35
  "#containers": {
32
36
  "source": "./src/containers/index.ts",
33
37
  "types": "./dist/types/src/containers/index.d.ts",
34
- "default": "./dist/lib/neutral/containers/index.mjs"
38
+ "default": "./dist/lib/containers.mjs"
35
39
  },
36
40
  "#meta": {
37
41
  "source": "./src/meta.ts",
38
42
  "types": "./dist/types/src/meta.d.ts",
39
- "default": "./dist/lib/neutral/meta.mjs"
43
+ "default": "./dist/lib/meta.mjs"
40
44
  },
41
45
  "#operations": {
42
46
  "source": "./src/operations/index.ts",
43
47
  "types": "./dist/types/src/operations/index.d.ts",
44
- "default": "./dist/lib/neutral/operations/index.mjs"
48
+ "default": "./dist/lib/operations.mjs"
45
49
  },
46
50
  "#plugin": {
47
51
  "source": {
@@ -50,52 +54,52 @@
50
54
  "default": "./src/ChessPlugin.tsx"
51
55
  },
52
56
  "types": "./dist/types/src/ChessPlugin.d.ts",
53
- "workerd": "./dist/lib/neutral/ChessPlugin.workerd.mjs",
54
- "node": "./dist/lib/neutral/ChessPlugin.node.mjs",
55
- "default": "./dist/lib/neutral/ChessPlugin.mjs"
57
+ "workerd": "./dist/lib/ChessPlugin.workerd.mjs",
58
+ "node": "./dist/lib/ChessPlugin.node.mjs",
59
+ "default": "./dist/lib/ChessPlugin.mjs"
56
60
  },
57
61
  "#translations": {
58
62
  "source": "./src/translations.ts",
59
63
  "types": "./dist/types/src/translations.d.ts",
60
- "default": "./dist/lib/neutral/translations.mjs"
64
+ "default": "./dist/lib/translations.mjs"
61
65
  },
62
66
  "#types": {
63
67
  "source": "./src/types/index.ts",
64
68
  "types": "./dist/types/src/types/index.d.ts",
65
- "default": "./dist/lib/neutral/types/index.mjs"
69
+ "default": "./dist/lib/types.mjs"
66
70
  }
67
71
  },
68
72
  "exports": {
69
73
  ".": {
70
74
  "source": "./src/index.ts",
71
75
  "types": "./dist/types/src/index.d.ts",
72
- "default": "./dist/lib/neutral/index.mjs"
76
+ "import": "./dist/lib/index.mjs"
73
77
  },
74
78
  "./assets/PLUGIN.mdl": "./PLUGIN.mdl",
75
79
  "./skills": {
76
80
  "source": "./src/skills/index.ts",
77
81
  "types": "./dist/types/src/skills/index.d.ts",
78
- "default": "./dist/lib/neutral/skills/index.mjs"
82
+ "import": "./dist/lib/skills.mjs"
79
83
  },
80
84
  "./plugin": {
81
85
  "source": "./src/plugin.ts",
82
86
  "types": "./dist/types/src/plugin.d.ts",
83
- "default": "./dist/lib/neutral/plugin.mjs"
87
+ "import": "./dist/lib/plugin.mjs"
84
88
  },
85
89
  "./testing": {
86
90
  "source": "./src/testing.ts",
87
91
  "types": "./dist/types/src/testing.d.ts",
88
- "default": "./dist/lib/neutral/testing.mjs"
92
+ "import": "./dist/lib/testing.mjs"
89
93
  },
90
94
  "./translations": {
91
95
  "source": "./src/translations.ts",
92
96
  "types": "./dist/types/src/translations.d.ts",
93
- "default": "./dist/lib/neutral/translations.mjs"
97
+ "import": "./dist/lib/translations.mjs"
94
98
  },
95
99
  "./types": {
96
100
  "source": "./src/types/index.ts",
97
101
  "types": "./dist/types/src/types/index.d.ts",
98
- "default": "./dist/lib/neutral/types/index.mjs"
102
+ "import": "./dist/lib/types.mjs"
99
103
  }
100
104
  },
101
105
  "types": "dist/types/src/index.d.ts",
@@ -106,43 +110,46 @@
106
110
  "PLUGIN.mdl"
107
111
  ],
108
112
  "dependencies": {
113
+ "@effect-atom/atom": "^0.5.3",
109
114
  "@effect-atom/atom-react": "^0.5.0",
110
115
  "chess.js": "^1.0.0",
111
116
  "effect": "3.21.4",
112
- "@dxos/app-framework": "0.10.0",
113
- "@dxos/app-toolkit": "0.10.0",
114
- "@dxos/async": "0.10.0",
115
- "@dxos/compute": "0.10.0",
116
- "@dxos/echo": "0.10.0",
117
- "@dxos/invariant": "0.10.0",
118
- "@dxos/echo-react": "0.10.0",
119
- "@dxos/log": "0.10.0",
120
- "@dxos/keys": "0.10.0",
121
- "@dxos/plugin-client": "0.10.0",
122
- "@dxos/plugin-game": "0.10.0",
123
- "@dxos/react-client": "0.10.0",
124
- "@dxos/react-ui-audio": "0.10.0",
125
- "@dxos/react-ui-gameboard": "0.10.0",
126
- "@dxos/util": "0.10.0",
127
- "@dxos/react-ui-mosaic": "0.10.0"
117
+ "@dxos/app-framework": "0.11.1",
118
+ "@dxos/app-toolkit": "0.11.1",
119
+ "@dxos/async": "0.11.1",
120
+ "@dxos/compute": "0.11.1",
121
+ "@dxos/echo": "0.11.1",
122
+ "@dxos/echo-react": "0.11.1",
123
+ "@dxos/invariant": "0.11.1",
124
+ "@dxos/keys": "0.11.1",
125
+ "@dxos/log": "0.11.1",
126
+ "@dxos/plugin-client": "0.11.1",
127
+ "@dxos/plugin-game": "0.11.1",
128
+ "@dxos/react-client": "0.11.1",
129
+ "@dxos/react-ui-audio": "0.11.1",
130
+ "@dxos/react-ui-gameboard": "0.11.1",
131
+ "@dxos/react-ui-mosaic": "0.11.1",
132
+ "@dxos/util": "0.11.1"
128
133
  },
129
134
  "devDependencies": {
130
135
  "@types/react": "~19.2.17",
131
136
  "@types/react-dom": "~19.2.3",
132
137
  "react": "~19.2.7",
133
138
  "react-dom": "~19.2.7",
134
- "vite": "^8.0.16",
135
- "@dxos/plugin-testing": "0.10.0",
136
- "@dxos/react-ui": "0.10.0",
137
- "@dxos/storybook-utils": "0.10.0",
138
- "@dxos/ui-theme": "0.10.0",
139
- "@dxos/plugin-theme": "0.10.0"
139
+ "vite": "^8.1.4",
140
+ "@dxos/agent-runtime": "0.11.1",
141
+ "@dxos/effect": "0.11.1",
142
+ "@dxos/plugin-testing": "0.11.1",
143
+ "@dxos/plugin-theme": "0.11.1",
144
+ "@dxos/react-ui": "0.11.1",
145
+ "@dxos/storybook-utils": "0.11.1",
146
+ "@dxos/ui-theme": "0.11.1"
140
147
  },
141
148
  "peerDependencies": {
142
149
  "react": "~19.2.7",
143
150
  "react-dom": "~19.2.7",
144
- "@dxos/react-ui": "0.10.0",
145
- "@dxos/ui-theme": "0.10.0"
151
+ "@dxos/react-ui": "^0.11.1",
152
+ "@dxos/ui-theme": "^0.11.1"
146
153
  },
147
154
  "publishConfig": {
148
155
  "access": "public"
@@ -7,14 +7,14 @@ import { AppPlugin } from '@dxos/app-toolkit';
7
7
 
8
8
  import { OperationHandler, SkillDefinition } from '#capabilities';
9
9
  import { meta } from '#meta';
10
- import { Chess } from '#types';
10
+ import { Chess, ChessPositionIndex, PlayerReview } from '#types';
11
11
 
12
12
  /**
13
13
  * Headless variant of ChessPlugin (no React surfaces / GameVariant).
14
14
  * Used in node contexts (CLI, agents) where rendering is unavailable.
15
15
  */
16
16
  export const ChessPlugin = Plugin.define(meta).pipe(
17
- AppPlugin.addSchemaModule({ schema: [Chess.State] }),
17
+ AppPlugin.addSchemaModule({ schema: [Chess.State, ChessPositionIndex.PositionIndex, PlayerReview.Review] }),
18
18
  AppPlugin.addSkillDefinitionModule({ activate: SkillDefinition }),
19
19
  AppPlugin.addOperationHandlerModule({ activate: OperationHandler }),
20
20
  Plugin.make,
@@ -8,7 +8,7 @@ import { AppActivationEvents, AppPlugin } from '@dxos/app-toolkit';
8
8
  import { GameVariant, OperationHandler, SkillDefinition } from '#capabilities';
9
9
  import { meta } from '#meta';
10
10
  import { translations } from '#translations';
11
- import { Chess } from '#types';
11
+ import { Chess, ChessPositionIndex, PlayerReview } from '#types';
12
12
 
13
13
  // eslint-disable-next-line import/no-relative-packages
14
14
  import pluginSpec from '../PLUGIN.mdl?raw';
@@ -24,7 +24,7 @@ export const ChessPlugin = Plugin.define(meta).pipe(
24
24
  AppPlugin.addPluginAssetModule({
25
25
  asset: { pluginId: meta.profile.key, path: 'PLUGIN.mdl', content: pluginSpec, mimeType: 'application/x-mdl' },
26
26
  }),
27
- AppPlugin.addSchemaModule({ schema: [Chess.State] }),
27
+ AppPlugin.addSchemaModule({ schema: [Chess.State, ChessPositionIndex.PositionIndex, PlayerReview.Review] }),
28
28
  AppPlugin.addTranslationsModule({ translations }),
29
29
  Plugin.make,
30
30
  );
@@ -7,11 +7,11 @@ import { AppPlugin } from '@dxos/app-toolkit';
7
7
 
8
8
  import { OperationHandler } from '#capabilities';
9
9
  import { meta } from '#meta';
10
- import { Chess } from '#types';
10
+ import { Chess, ChessPositionIndex, PlayerReview } from '#types';
11
11
 
12
12
  export const ChessPlugin = Plugin.define(meta).pipe(
13
13
  AppPlugin.addOperationHandlerModule({ activate: OperationHandler }),
14
- AppPlugin.addSchemaModule({ schema: [Chess.State] }),
14
+ AppPlugin.addSchemaModule({ schema: [Chess.State, ChessPositionIndex.PositionIndex, PlayerReview.Review] }),
15
15
  Plugin.make,
16
16
  );
17
17
 
@@ -0,0 +1,16 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { Capability } from '@dxos/app-framework';
6
+ import type { OperationHandlerSet } from '@dxos/compute';
7
+
8
+ // The capabilities `ChessPlugin.node` activates, and only those. `Capability.lazy` defers the
9
+ // import at runtime but a bundler still walks it, so listing the React surfaces here would pull
10
+ // the plugin's components into every node and bun build.
11
+
12
+ export const SkillDefinition = Capability.lazy('SkillDefinition', () => import('./skill-definition'));
13
+ export const OperationHandler = Capability.lazy<OperationHandlerSet.OperationHandlerSet>(
14
+ 'OperationHandler',
15
+ () => import('./operation-handler'),
16
+ );
@@ -30,7 +30,7 @@ export const Info = ({ classNames, orientation = 'white', onOrientationChange, o
30
30
  return (
31
31
  <div
32
32
  className={mx(
33
- 'grid grid-rows-[min-content_1fr_min-content] w-full min-w-[18rem] p-2 overflow-hidden bg-group-surface rounded-xs',
33
+ 'grid grid-rows-[min-content_1fr_min-content] w-full min-w-[18rem] p-2 overflow-hidden dx-group-surface rounded-xs',
34
34
  classNames,
35
35
  )}
36
36
  >
@@ -180,7 +180,7 @@ type PlayerIndicatorProps = PropsWithChildren<{
180
180
  const PlayerIndicator = ({ children, model, player, icon }: PlayerIndicatorProps) => {
181
181
  const turn = player === (model.game.turn() === 'w' ? 'white' : 'black');
182
182
  return (
183
- <div className='grid grid-cols-[2rem_1fr_2rem] gap-2 h-(--dx-rail-size) px-1 flex items-center overflow-hidden'>
183
+ <div className='grid grid-cols-[var(--dx-rail-item)_1fr_var(--dx-rail-item)] gap-2 h-(--dx-rail-size) px-1 flex items-center overflow-hidden'>
184
184
  <div className='place-items-center'>
185
185
  <Icon
186
186
  icon={turn ? 'ph--circle--fill' : 'ph--circle--thin'}
@@ -2,7 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { type Registry } from '@effect-atom/atom-react';
5
+ import { type Registry } from '@effect-atom/atom';
6
6
 
7
7
  import { ChessModel } from '@dxos/react-ui-gameboard';
8
8
 
@@ -6,7 +6,7 @@ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
  import React, { useMemo } from 'react';
7
7
 
8
8
  import { type Obj } from '@dxos/echo';
9
- import { make as makeGame } from '@dxos/plugin-game';
9
+ import { Game } from '@dxos/plugin-game';
10
10
  import { withClientProvider } from '@dxos/react-client/testing';
11
11
  import { withLayout, withTheme } from '@dxos/react-ui/testing';
12
12
 
@@ -22,7 +22,7 @@ type StoryArgs = {
22
22
  const DefaultStory = ({ pgn }: StoryArgs) => {
23
23
  const { game, state } = useMemo(() => {
24
24
  const state = Chess.make(pgn ? { pgn } : undefined);
25
- const game = makeGame({ name: 'Story game', variant: state as Obj.Unknown });
25
+ const game = Game.make({ name: 'Story game', variant: state as Obj.Unknown });
26
26
  return { game, state };
27
27
  }, [pgn]);
28
28
  return <ChessArticle role='article' attendableId='story' game={game} variant={state} />;
@@ -7,6 +7,7 @@ import React, { useCallback, useRef, useState } from 'react';
7
7
 
8
8
  import { AppSurface } from '@dxos/app-toolkit/ui';
9
9
  import { Obj } from '@dxos/echo';
10
+ import { useObject } from '@dxos/echo-react';
10
11
  import { type GameVariantSurfaceProps } from '@dxos/plugin-game/types';
11
12
  import { Panel, Toolbar, useTranslation } from '@dxos/react-ui';
12
13
  import { type Player } from '@dxos/react-ui-gameboard';
@@ -28,16 +29,20 @@ export const ChessArticle = ({ role, variant }: ChessArticleProps) => {
28
29
  controller.current?.setMoveNumber(index);
29
30
  }, []);
30
31
 
32
+ const state = Obj.instanceOf(Chess.State, variant) ? variant : undefined;
33
+ const [pgn] = useObject(state, 'pgn');
34
+ const [fen] = useObject(state, 'fen');
35
+
31
36
  const isGameOver = (() => {
32
- if (!Obj.instanceOf(Chess.State, variant) || (!variant.pgn && !variant.fen)) {
37
+ if (!pgn && !fen) {
33
38
  return false;
34
39
  }
35
40
  try {
36
41
  const chess = new ChessJS();
37
- if (variant.pgn) {
38
- chess.loadPgn(variant.pgn);
39
- } else if (variant.fen) {
40
- chess.load(variant.fen);
42
+ if (pgn) {
43
+ chess.loadPgn(pgn);
44
+ } else if (fen) {
45
+ chess.load(fen);
41
46
  }
42
47
  return chess.isGameOver();
43
48
  } catch {
@@ -46,22 +51,21 @@ export const ChessArticle = ({ role, variant }: ChessArticleProps) => {
46
51
  })();
47
52
 
48
53
  const handleNewGame = useCallback(() => {
49
- if (!Obj.instanceOf(Chess.State, variant)) {
54
+ if (!state) {
50
55
  return;
51
56
  }
52
- Obj.update(variant, (variant) => {
53
- const mutable = variant as Obj.Mutable<typeof variant>;
54
- mutable.pgn = undefined;
55
- mutable.fen = undefined;
57
+ Obj.update(state, (state) => {
58
+ state.pgn = undefined;
59
+ state.fen = undefined;
56
60
  });
57
- }, [variant]);
61
+ }, [state]);
58
62
 
59
- if (!Obj.instanceOf(Chess.State, variant)) {
63
+ if (!state) {
60
64
  return null;
61
65
  }
62
66
 
63
67
  return (
64
- <Chessboard.Root state={variant} ref={controller}>
68
+ <Chessboard.Root state={state} ref={controller}>
65
69
  <Panel.Root role={role} classNames='@container'>
66
70
  <Panel.Toolbar asChild>
67
71
  <Toolbar.Root>
@@ -107,3 +111,5 @@ export const ChessArticle = ({ role, variant }: ChessArticleProps) => {
107
111
  </Chessboard.Root>
108
112
  );
109
113
  };
114
+
115
+ ChessArticle.displayName = 'ChessArticle';
@@ -5,7 +5,7 @@
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
  import React, { useMemo } from 'react';
7
7
 
8
- import { make as makeGame } from '@dxos/plugin-game';
8
+ import { Game } from '@dxos/plugin-game';
9
9
  import { CardContainer } from '@dxos/react-ui-mosaic/testing';
10
10
  import { withLayout, withTheme } from '@dxos/react-ui/testing';
11
11
 
@@ -20,7 +20,7 @@ const SAMPLE_PGN =
20
20
  const CardStory = () => {
21
21
  const { game, state } = useMemo(() => {
22
22
  const state = Chess.make({ pgn: SAMPLE_PGN });
23
- const game = makeGame({ name: 'Story game', variant: state });
23
+ const game = Game.make({ name: 'Story game', variant: state });
24
24
  return { game, state };
25
25
  }, []);
26
26
  return (
@@ -32,3 +32,5 @@ export const ChessCard = ({ variant }: ChessCardProps) => {
32
32
  </Card.Body>
33
33
  );
34
34
  };
35
+
36
+ ChessCard.displayName = 'ChessCard';
@@ -0,0 +1,148 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { Chess as ChessJS } from 'chess.js';
6
+
7
+ import { Obj, Ref } from '@dxos/echo';
8
+ import { type Game } from '@dxos/plugin-game/types';
9
+
10
+ import * as ChessPositionIndex from '../types/ChessPositionIndex';
11
+ import * as PlayerReview from '../types/PlayerReview';
12
+
13
+ /** Normalizes a FEN to the position key (board, side, castling, en passant). */
14
+ export const normalizeFen = (fen: string): string => fen.split(' ').slice(0, 4).join(' ');
15
+
16
+ const sideToTurn = (side: ChessPositionIndex.Side): 'w' | 'b' => (side === 'white' ? 'w' : 'b');
17
+
18
+ /** Maximum full moves per game indexed (opening window). */
19
+ export const OPENING_FULL_MOVE_LIMIT = 10;
20
+
21
+ /** Half-move cap for the opening window. */
22
+ export const OPENING_PLY_LIMIT = OPENING_FULL_MOVE_LIMIT * 2;
23
+
24
+ /**
25
+ * Positions where `side` is to move, derived from chess state PGN/FEN.
26
+ * Only positions within the first {@link OPENING_FULL_MOVE_LIMIT} full moves are indexed.
27
+ */
28
+ export const positionsForSide = ({
29
+ pgn,
30
+ fen,
31
+ side,
32
+ }: {
33
+ pgn?: string;
34
+ fen?: string;
35
+ side: ChessPositionIndex.Side;
36
+ }): string[] => {
37
+ const probe = new ChessJS();
38
+ const chess = new ChessJS();
39
+ try {
40
+ if (pgn) {
41
+ probe.loadPgn(pgn);
42
+ } else if (fen) {
43
+ // A FEN-only game has no move history to replay, so index from the supplied position itself.
44
+ probe.load(fen);
45
+ chess.load(fen);
46
+ }
47
+ } catch {
48
+ // chess.js throws on malformed PGN/FEN; a single bad record must not abort the rebuild.
49
+ return [];
50
+ }
51
+
52
+ const moves = probe.history().slice(0, OPENING_PLY_LIMIT);
53
+ const turn = sideToTurn(side);
54
+ const fens: string[] = [];
55
+
56
+ if (chess.turn() === turn) {
57
+ fens.push(normalizeFen(chess.fen()));
58
+ }
59
+
60
+ for (const move of moves) {
61
+ chess.move(move);
62
+ if (chess.turn() === turn) {
63
+ fens.push(normalizeFen(chess.fen()));
64
+ }
65
+ }
66
+
67
+ return fens;
68
+ };
69
+
70
+ /** Resolves which side the reviewed player played in a game, if any. */
71
+ export const playerSideInGame = (review: PlayerReview.Review, game: Game.Game): ChessPositionIndex.Side | undefined => {
72
+ for (const player of game.players ?? []) {
73
+ if (review.playerIdentity && player.identity === review.playerIdentity) {
74
+ return player.role === 'black' ? 'black' : 'white';
75
+ }
76
+ if (review.playerName && player.name?.trim().toLowerCase() === review.playerName.trim().toLowerCase()) {
77
+ return player.role === 'black' ? 'black' : 'white';
78
+ }
79
+ }
80
+ return undefined;
81
+ };
82
+
83
+ export type BuiltSideIndex = Record<string, Game.Game[]>;
84
+
85
+ export type BuiltIndex = Record<ChessPositionIndex.Side, BuiltSideIndex>;
86
+
87
+ /** Builds a fresh side→fen→games index from processed games. */
88
+ export const buildIndex = (
89
+ entries: ReadonlyArray<{ game: Game.Game; side: ChessPositionIndex.Side; fens: readonly string[] }>,
90
+ ): BuiltIndex => {
91
+ const index: BuiltIndex = { white: {}, black: {} };
92
+ for (const { game, side, fens } of entries) {
93
+ for (const fen of fens) {
94
+ const bucket = index[side][fen] ?? [];
95
+ if (!bucket.some((existing) => existing.id === game.id)) {
96
+ bucket.push(game);
97
+ }
98
+ index[side][fen] = bucket;
99
+ }
100
+ }
101
+ return index;
102
+ };
103
+
104
+ const gameIdsKey = (games: ReadonlyArray<{ id: string }>): string =>
105
+ games
106
+ .map((game) => game.id)
107
+ .toSorted()
108
+ .join('\0');
109
+
110
+ const refsGameIdsKey = (games: ReadonlyArray<Ref.Ref<Game.Game>>): string =>
111
+ games
112
+ .map((gameRef) => gameRef.target?.id ?? gameRef.uri)
113
+ .toSorted()
114
+ .join('\0');
115
+
116
+ /**
117
+ * Applies a rebuilt index onto an existing {@link ChessPositionIndex.PositionIndex},
118
+ * mutating only FEN leaves whose game sets changed and removing stale FEN keys.
119
+ */
120
+ export const applyIndexDiff = (positionIndex: ChessPositionIndex.PositionIndex, next: BuiltIndex): number => {
121
+ let updatedLeaves = 0;
122
+
123
+ Obj.update(positionIndex, (positionIndex) => {
124
+ for (const side of ['white', 'black'] as const) {
125
+ const sideIndex = positionIndex.index[side];
126
+ const nextSide = next[side];
127
+
128
+ for (const fen of Object.keys(sideIndex)) {
129
+ if (!nextSide[fen]) {
130
+ delete sideIndex[fen];
131
+ updatedLeaves++;
132
+ }
133
+ }
134
+
135
+ for (const [fen, games] of Object.entries(nextSide)) {
136
+ const existing = sideIndex[fen];
137
+ if (existing && refsGameIdsKey(existing.games) === gameIdsKey(games)) {
138
+ continue;
139
+ }
140
+
141
+ sideIndex[fen] = { games: games.map((game) => Ref.make(game)) };
142
+ updatedLeaves++;
143
+ }
144
+ }
145
+ });
146
+
147
+ return updatedLeaves;
148
+ };
@@ -8,4 +8,5 @@ export const ChessOperationHandlerSet = OperationHandlerSet.lazy(
8
8
  () => import('./move'),
9
9
  () => import('./play'),
10
10
  () => import('./print'),
11
+ () => import('./rebuild-position-index'),
11
12
  );
@@ -25,8 +25,7 @@ const handler: Operation.WithHandler<typeof ChessOperation.Move> = ChessOperatio
25
25
  chess.move(move, { strict: false });
26
26
  const pgn = chess.pgn();
27
27
  Obj.update(variant, (variant) => {
28
- const mutable = variant as Obj.Mutable<typeof variant>;
29
- mutable.pgn = pgn;
28
+ variant.pgn = pgn;
30
29
  });
31
30
  return { pgn };
32
31
  }),
@@ -34,8 +34,7 @@ const handler: Operation.WithHandler<typeof ChessOperation.Play> = ChessOperatio
34
34
  chess.move(move, { strict: false });
35
35
  const pgn = chess.pgn();
36
36
  Obj.update(variant, (variant) => {
37
- const mutable = variant as Obj.Mutable<typeof variant>;
38
- mutable.pgn = pgn;
37
+ variant.pgn = pgn;
39
38
  });
40
39
  return { move, pgn };
41
40
  }),