@xom11/whiteboard 0.24.2 → 0.25.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 (84) hide show
  1. package/README.md +84 -11
  2. package/dist/ai.d.mts +422 -566
  3. package/dist/ai.d.ts +422 -566
  4. package/dist/ai.js +1527 -407
  5. package/dist/ai.js.map +1 -1
  6. package/dist/ai.mjs +1008 -512
  7. package/dist/ai.mjs.map +1 -1
  8. package/dist/catalog.json +4 -4
  9. package/dist/{chunk-BKSXPNPQ.mjs → chunk-AYSFWUPK.mjs} +4 -3
  10. package/dist/chunk-AYSFWUPK.mjs.map +1 -0
  11. package/dist/chunk-B4NJJZFR.mjs +18 -0
  12. package/dist/chunk-B4NJJZFR.mjs.map +1 -0
  13. package/dist/{chunk-LVNCYP4J.mjs → chunk-CJBLJUWG.mjs} +5 -5
  14. package/dist/{chunk-LVNCYP4J.mjs.map → chunk-CJBLJUWG.mjs.map} +1 -1
  15. package/dist/{chunk-7WQXXEVR.mjs → chunk-ESVPQWHX.mjs} +5 -5
  16. package/dist/{chunk-7WQXXEVR.mjs.map → chunk-ESVPQWHX.mjs.map} +1 -1
  17. package/dist/{chunk-KRC2XOIG.mjs → chunk-I24QOHPU.mjs} +3 -3
  18. package/dist/{chunk-KRC2XOIG.mjs.map → chunk-I24QOHPU.mjs.map} +1 -1
  19. package/dist/{chunk-ZBJBQKJ2.mjs → chunk-IHUFOV7L.mjs} +4 -19
  20. package/dist/chunk-IHUFOV7L.mjs.map +1 -0
  21. package/dist/{chunk-AZIARTGX.mjs → chunk-M42TGYT6.mjs} +3 -3
  22. package/dist/{chunk-AZIARTGX.mjs.map → chunk-M42TGYT6.mjs.map} +1 -1
  23. package/dist/{chunk-45CGKJ7S.mjs → chunk-NDEZJKNY.mjs} +4 -4
  24. package/dist/{chunk-45CGKJ7S.mjs.map → chunk-NDEZJKNY.mjs.map} +1 -1
  25. package/dist/{chunk-BEZSQKPY.mjs → chunk-ONBCUWVI.mjs} +5 -4
  26. package/dist/chunk-ONBCUWVI.mjs.map +1 -0
  27. package/dist/{chunk-WM2VDYQA.mjs → chunk-REIJZDVZ.mjs} +4 -3
  28. package/dist/chunk-REIJZDVZ.mjs.map +1 -0
  29. package/dist/{chunk-2WF6KIGF.mjs → chunk-TB4CL25L.mjs} +9 -8
  30. package/dist/chunk-TB4CL25L.mjs.map +1 -0
  31. package/dist/chunk-VNCCIV6O.mjs +938 -0
  32. package/dist/chunk-VNCCIV6O.mjs.map +1 -0
  33. package/dist/{chunk-CGZZO4BX.mjs → chunk-VRHWDZ66.mjs} +5 -5
  34. package/dist/{chunk-CGZZO4BX.mjs.map → chunk-VRHWDZ66.mjs.map} +1 -1
  35. package/dist/{chunk-4DS3MKID.mjs → chunk-YSJOVBCD.mjs} +4 -4
  36. package/dist/{chunk-4DS3MKID.mjs.map → chunk-YSJOVBCD.mjs.map} +1 -1
  37. package/dist/geometry-2d.d.mts +2 -2
  38. package/dist/geometry-2d.d.ts +2 -2
  39. package/dist/geometry-2d.js +1383 -23
  40. package/dist/geometry-2d.js.map +1 -1
  41. package/dist/geometry-2d.mjs +6 -5
  42. package/dist/geometry-3d.d.mts +2 -2
  43. package/dist/geometry-3d.d.ts +2 -2
  44. package/dist/geometry-3d.js +2 -2
  45. package/dist/geometry-3d.js.map +1 -1
  46. package/dist/geometry-3d.mjs +5 -4
  47. package/dist/graph-2d.d.mts +2 -2
  48. package/dist/graph-2d.d.ts +2 -2
  49. package/dist/graph-2d.js +2 -2
  50. package/dist/graph-2d.js.map +1 -1
  51. package/dist/graph-2d.mjs +8 -7
  52. package/dist/{host-ZIQ77W33.mjs → host-A64ITWVX.mjs} +7 -6
  53. package/dist/host-A64ITWVX.mjs.map +1 -0
  54. package/dist/{host-EPZCNFLH.mjs → host-L7FMFZUW.mjs} +226 -29
  55. package/dist/host-L7FMFZUW.mjs.map +1 -0
  56. package/dist/{host-LKCMYEAV.mjs → host-QK53UYMD.mjs} +11 -10
  57. package/dist/host-QK53UYMD.mjs.map +1 -0
  58. package/dist/index.d.mts +3 -3
  59. package/dist/index.d.ts +3 -3
  60. package/dist/index.js +1414 -54
  61. package/dist/index.js.map +1 -1
  62. package/dist/index.mjs +18 -17
  63. package/dist/index.mjs.map +1 -1
  64. package/dist/latex.d.mts +2 -2
  65. package/dist/latex.d.ts +2 -2
  66. package/dist/render-3WTY7NZB.mjs +9 -0
  67. package/dist/{render-SA4JTOW3.mjs.map → render-3WTY7NZB.mjs.map} +1 -1
  68. package/dist/serialize-SRJVKYUG.mjs +8 -0
  69. package/dist/{serialize-JAVOU22E.mjs.map → serialize-SRJVKYUG.mjs.map} +1 -1
  70. package/dist/{types-vtvyKGAA.d.mts → types-DWRyCa2m.d.mts} +187 -2
  71. package/dist/{types-Crbefnfe.d.ts → types-DWRyCa2m.d.ts} +187 -2
  72. package/package.json +1 -1
  73. package/dist/chunk-2WF6KIGF.mjs.map +0 -1
  74. package/dist/chunk-BEZSQKPY.mjs.map +0 -1
  75. package/dist/chunk-BKSXPNPQ.mjs.map +0 -1
  76. package/dist/chunk-WM2VDYQA.mjs.map +0 -1
  77. package/dist/chunk-ZBJBQKJ2.mjs.map +0 -1
  78. package/dist/host-EPZCNFLH.mjs.map +0 -1
  79. package/dist/host-LKCMYEAV.mjs.map +0 -1
  80. package/dist/host-ZIQ77W33.mjs.map +0 -1
  81. package/dist/render-SA4JTOW3.mjs +0 -8
  82. package/dist/serialize-JAVOU22E.mjs +0 -7
  83. package/dist/types-DxlMPh-6.d.mts +0 -49
  84. package/dist/types-DxlMPh-6.d.ts +0 -49
package/README.md CHANGED
@@ -63,7 +63,7 @@ export function ClassroomBoard() {
63
63
 
64
64
  ### AI dựng hình học 2D (opt-in)
65
65
 
66
- Textarea AI chỉ xuất hiện khi truyền `generateGeometryFigure`. Callback này chạy từ client nên phải gọi một server boundary của ứng dụng; không đưa `ANTHROPIC_API_KEY` vào component hoặc biến môi trường public.
66
+ Textarea AI chỉ xuất hiện khi truyền `generateGeometryFigure`. Callback chạy từ client nên phải gọi server boundary của ứng dụng; không bao giờ đặt API key vào component / biến môi trường public.
67
67
 
68
68
  ```tsx
69
69
  'use client';
@@ -85,29 +85,102 @@ export function ClassroomBoard() {
85
85
  }
86
86
  ```
87
87
 
88
- dụ route phía server trong Next.js:
88
+ #### Provider backend (chọn 1)
89
+
90
+ Từ phiên bản hỗ trợ multi-provider, có 2 lựa chọn:
91
+
92
+ **A. Local Gemma 3 qua Ollama (mặc định, miễn phí, không cần API key)**
93
+
94
+ Setup máy chạy server:
95
+
96
+ ```bash
97
+ # macOS
98
+ brew install ollama
99
+ ollama serve # chạy nền cổng 11434
100
+
101
+ # Chọn 1 trong 2 model:
102
+ ollama pull gemma3:4b # ~3.3GB Q4 — nhanh ~20s/đề, accuracy 75%
103
+ ollama pull gemma3:12b # ~8GB Q4 — chậm ~60s/đề, accuracy 92% (recommended cho production)
104
+
105
+ # Linux
106
+ curl -fsSL https://ollama.com/install.sh | sh
107
+ ollama serve &
108
+ ollama pull gemma3:12b
109
+ ```
110
+
111
+ **Eval 12 đề THCS/lớp 10** (transpile success rate + dùng đúng primitive):
112
+
113
+ | Model | Transpile OK | Kind đúng | Refuse đúng | Avg latency |
114
+ |-----------|--------------|-----------|-------------|-------------|
115
+ | gemma3:4b | 75% | 63% | 0/1 | 20s |
116
+ | gemma3:12b | 92% | 88% | 1/1 | 62s |
117
+ | Claude Opus 4.7 | ~100% | ~100% | 1/1 | ~5s (cost ~$0.01/đề) |
118
+
119
+ Đề nghị: 12b cho production, 4b cho prototype/máy yếu, Anthropic cho accuracy tuyệt đối.
120
+
121
+ Server-side route Next.js:
89
122
 
90
123
  ```ts
91
124
  import { generateFigure } from '@xom11/whiteboard/ai';
92
125
 
93
126
  export async function POST(request: Request) {
94
127
  const { problem } = await request.json();
95
- const result = await generateFigure(problem, {
96
- apiKey: process.env.ANTHROPIC_API_KEY ?? '',
97
- });
128
+ // Default: provider=ollama, model=gemma3:4b, baseUrl=http://localhost:11434
129
+ const result = await generateFigure(problem);
98
130
  return Response.json(
99
- result.ok
100
- ? { ok: true, state: result.state }
101
- : { ok: false, message: result.message },
131
+ result.ok ? { ok: true, state: result.state } : { ok: false, message: result.message },
102
132
  );
103
133
  }
104
134
  ```
105
135
 
106
- Trong repo package, chạy smoke/eval với API key chỉ ở local shell:
136
+ Env override (optional):
137
+
138
+ ```bash
139
+ WHITEBOARD_AI_PROVIDER=ollama # default
140
+ OLLAMA_BASE_URL=http://localhost:11434 # default
141
+ OLLAMA_DEFAULT_MODEL=gemma3:12b # default gemma3:4b; recommend gemma3:12b cho production
142
+ ```
143
+
144
+ **B. Anthropic Claude (chính xác cao, tốn API cost)**
145
+
146
+ ```ts
147
+ import { generateFigure } from '@xom11/whiteboard/ai';
148
+
149
+ const result = await generateFigure(problem, {
150
+ apiKey: process.env.ANTHROPIC_API_KEY ?? '',
151
+ });
152
+ ```
153
+
154
+ Hoặc qua env:
155
+
156
+ ```bash
157
+ WHITEBOARD_AI_PROVIDER=anthropic
158
+ ANTHROPIC_API_KEY=sk-ant-...
159
+ ```
160
+
161
+ **C. Provider tuỳ biến** (vd OpenAI, OpenRouter, vLLM): implement interface `AIProvider`:
162
+
163
+ ```ts
164
+ import { generateFigure, type AIProvider } from '@xom11/whiteboard/ai';
165
+
166
+ const customProvider: AIProvider = {
167
+ name: 'my-llm',
168
+ defaultModel: 'my-model',
169
+ async call(req) {
170
+ // req.systemPrompt, req.userPrompt, req.schema (JSON Schema cho envelope)
171
+ // ...
172
+ return { kind: 'json', data: envelopeObject };
173
+ },
174
+ };
175
+
176
+ const result = await generateFigure(problem, { provider: customProvider });
177
+ ```
178
+
179
+ #### Smoke test local Ollama
107
180
 
108
181
  ```bash
109
- ANTHROPIC_API_KEY=... npm run ai:smoke
110
- ANTHROPIC_API_KEY=... npm run ai:eval -- --limit 5
182
+ brew install ollama && ollama serve & ollama pull gemma3:4b
183
+ OLLAMA_SMOKE=1 npx jest ollama.smoke
111
184
  ```
112
185
 
113
186
  ## Migration to v0.8.0 (geometry-3d redesign)