@sales-bot-llm/sdk 0.2.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 (54) hide show
  1. package/biome.json +36 -0
  2. package/docs/superpowers/plans/2026-05-08-sales-bot-sdk-plan.md +258 -0
  3. package/docs/superpowers/plans/2026-05-11-w3-sales-tool-polish-plan.md +476 -0
  4. package/docs/superpowers/specs/2026-05-08-sales-bot-sdk-design.md +587 -0
  5. package/example/.env.example +5 -0
  6. package/example/README.md +90 -0
  7. package/example/index.html +12 -0
  8. package/example/package.json +27 -0
  9. package/example/public/vanilla.global.js +345 -0
  10. package/example/src/App.tsx +50 -0
  11. package/example/src/main.tsx +16 -0
  12. package/example/src/routes/HookDemo.tsx +174 -0
  13. package/example/src/routes/VanillaDemo.tsx +67 -0
  14. package/example/src/routes/WidgetDemo.tsx +55 -0
  15. package/example/src/styles.css +18 -0
  16. package/example/tsconfig.json +19 -0
  17. package/example/tsconfig.tsbuildinfo +1 -0
  18. package/example/vite.config.ts +4 -0
  19. package/package.json +106 -0
  20. package/pnpm-workspace.yaml +3 -0
  21. package/src/core/client.ts +245 -0
  22. package/src/core/conversation.ts +34 -0
  23. package/src/core/index.ts +6 -0
  24. package/src/core/sse-parser.ts +87 -0
  25. package/src/core/storage.ts +72 -0
  26. package/src/core/transport.ts +271 -0
  27. package/src/core/types.ts +314 -0
  28. package/src/core/visitor.ts +21 -0
  29. package/src/react/index.ts +2 -0
  30. package/src/react/use-sales-bot.tsx +182 -0
  31. package/src/vanilla/index.ts +38 -0
  32. package/src/vue/index.ts +2 -0
  33. package/src/vue/use-sales-bot.ts +152 -0
  34. package/src/widget/index.ts +3 -0
  35. package/src/widget/markdown.ts +69 -0
  36. package/src/widget/styles.ts +350 -0
  37. package/src/widget/widget.ts +442 -0
  38. package/tests/contract/wire-format.test.ts +158 -0
  39. package/tests/core/client.test.ts +292 -0
  40. package/tests/core/conversation.test.ts +41 -0
  41. package/tests/core/sse-parser.test.ts +142 -0
  42. package/tests/core/storage.test.ts +78 -0
  43. package/tests/core/transport.test.ts +204 -0
  44. package/tests/core/visitor.test.ts +42 -0
  45. package/tests/react/use-sales-bot.test.tsx +188 -0
  46. package/tests/sales-tool-discriminator.test.ts +45 -0
  47. package/tests/setup.ts +3 -0
  48. package/tests/vanilla/vanilla.test.ts +37 -0
  49. package/tests/vue/use-sales-bot.test.ts +163 -0
  50. package/tests/widget/markdown.test.ts +113 -0
  51. package/tests/widget/widget.test.ts +388 -0
  52. package/tsconfig.json +28 -0
  53. package/tsup.config.ts +38 -0
  54. package/vitest.config.ts +26 -0
package/biome.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
3
+ "vcs": {
4
+ "enabled": true,
5
+ "clientKind": "git",
6
+ "useIgnoreFile": true
7
+ },
8
+ "formatter": {
9
+ "enabled": true,
10
+ "indentStyle": "space",
11
+ "indentWidth": 2,
12
+ "lineWidth": 100
13
+ },
14
+ "linter": {
15
+ "enabled": true,
16
+ "rules": {
17
+ "recommended": true,
18
+ "complexity": {
19
+ "noForEach": "off"
20
+ },
21
+ "suspicious": {
22
+ "noExplicitAny": "warn"
23
+ }
24
+ }
25
+ },
26
+ "javascript": {
27
+ "formatter": {
28
+ "quoteStyle": "single",
29
+ "trailingCommas": "all",
30
+ "semicolons": "always"
31
+ }
32
+ },
33
+ "files": {
34
+ "ignore": ["dist/**", "node_modules/**", "coverage/**"]
35
+ }
36
+ }
@@ -0,0 +1,258 @@
1
+ # Sales Bot SDK — Implementation Plan
2
+
3
+ **Date:** 2026-05-08
4
+ **Status:** Active
5
+ **Author:** Claude (autonomous)
6
+
7
+ Each phase is TDD: write the failing test(s) first, implement to make them pass, commit.
8
+
9
+ ---
10
+
11
+ ## Phase 0 — Bootstrap (package.json, tsconfig, tooling)
12
+
13
+ ### Tasks
14
+ - [ ] 0.1 Create `package.json` with name `@sales-bot/sdk`, TypeScript, tsup, vitest, biome, React/Vue as peerDeps
15
+ - [ ] 0.2 Create `tsconfig.json` — strict mode, ESNext, bundler module resolution
16
+ - [ ] 0.3 Create `tsup.config.ts` — ESM+CJS for core/react/vue/widget; IIFE for vanilla
17
+ - [ ] 0.4 Create `vitest.config.ts` — happy-dom environment, coverage
18
+ - [ ] 0.5 Create `biome.json` — formatting + lint rules
19
+ - [ ] 0.6 Install dependencies
20
+
21
+ **Commit:** `chore: bootstrap package — tsup, vitest, biome, tsconfig`
22
+
23
+ ---
24
+
25
+ ## Phase 1 — Core types
26
+
27
+ ### Tasks
28
+ - [ ] 1.1 Write `tests/contract/wire-format.test.ts` — imports types, asserts shape assignability
29
+ - [ ] 1.2 Create `src/core/types.ts` — verbatim event interfaces from backend, `SalesBotEvent` union, `SalesBotErrorCode`, `IdentifyInput`, `AskOptions`, `PostTurnInput`, `StorageAdapter`, `Unsubscribe`
30
+ - [ ] 1.3 Make contract test pass (compile-time + runtime shape assertions)
31
+
32
+ **Commit:** `feat(core): wire-format types + contract tests`
33
+
34
+ ---
35
+
36
+ ## Phase 2 — SSE parser
37
+
38
+ ### TDD steps
39
+ 1. Write `tests/core/sse-parser.test.ts`:
40
+ - parse single `turn_started` frame
41
+ - parse multiple frames in one chunk
42
+ - parse frames split across chunk boundaries
43
+ - parse `error` frame
44
+ - handle malformed frame → `SalesBotError({ code: 'parse_error' })`
45
+ - handle empty stream
46
+ 2. Implement `src/core/sse-parser.ts`
47
+ 3. All tests pass
48
+
49
+ **Commit:** `feat(core): SSE parser with boundary-spanning chunk handling`
50
+
51
+ ---
52
+
53
+ ## Phase 3 — Storage adapters
54
+
55
+ ### TDD steps
56
+ 1. Write `tests/core/storage.test.ts`:
57
+ - `LocalStorageAdapter` get/set/remove (happy-dom has localStorage)
58
+ - `MemoryStorageAdapter` get/set/remove
59
+ - `MemoryStorageAdapter` isolation between instances
60
+ 2. Implement `src/core/storage.ts`
61
+ 3. All tests pass
62
+
63
+ **Commit:** `feat(core): LocalStorageAdapter + MemoryStorageAdapter`
64
+
65
+ ---
66
+
67
+ ## Phase 4 — Visitor token
68
+
69
+ ### TDD steps
70
+ 1. Write `tests/core/visitor.test.ts`:
71
+ - generates UUID on first call
72
+ - returns same UUID on subsequent calls (same storage)
73
+ - namespaces key by embedKey
74
+ - uses injected storage adapter
75
+ 2. Implement `src/core/visitor.ts`
76
+ 3. All tests pass
77
+
78
+ **Commit:** `feat(core): visitor token generation + persistence`
79
+
80
+ ---
81
+
82
+ ## Phase 5 — SalesBotError
83
+
84
+ ### Tasks
85
+ - [ ] 5.1 Add `SalesBotError` class to `src/core/types.ts`
86
+ - [ ] 5.2 Write test asserting it extends `Error`, has `.code`, `.retryable`, `.details`
87
+ - [ ] 5.3 Make test pass
88
+
89
+ **Commit:** `feat(core): SalesBotError class`
90
+
91
+ ---
92
+
93
+ ## Phase 6 — HTTP transport
94
+
95
+ ### TDD steps
96
+ 1. Write `tests/core/transport.test.ts`:
97
+ - sets `Authorization: Bearer <embedKey>` header
98
+ - sets `Idempotency-Key` header
99
+ - sets `Accept: text/event-stream`
100
+ - sets `Content-Type: application/json`
101
+ - sends correct JSON body
102
+ - returns `ReadableStream` on 200
103
+ - maps 401 → `SalesBotError({ code: 'invalid_embed_key' })` when body has that code
104
+ - maps 402 → `out_of_credits`
105
+ - maps 429 → `rate_limited`
106
+ - maps 500 → `internal`
107
+ - maps fetch throw → `network_error`
108
+ - `getResumeStream` calls `GET /api/chat/turns/:turnId/stream`
109
+ - merges `customHeaders`
110
+ 2. Implement `src/core/transport.ts`
111
+ 3. All tests pass
112
+
113
+ **Commit:** `feat(core): fetch-based HTTP transport with error mapping`
114
+
115
+ ---
116
+
117
+ ## Phase 7 — SalesBotClient class
118
+
119
+ ### TDD steps
120
+ 1. Write `tests/core/client.test.ts`:
121
+ - constructor stores embedKey, creates storage, generates visitor token
122
+ - `identify()` stores traits for next ask
123
+ - `ask()` calls postTurn with correct body (visitorToken, message, identify, conversationId)
124
+ - `ask()` yields events from the SSE stream
125
+ - `ask()` emits events on the event bus simultaneously
126
+ - `ask()` auto-updates conversationId from `turn_started`
127
+ - `resume(turnId)` calls getResumeStream
128
+ - `on()` returns unsubscribe function that actually unsubscribes
129
+ - `getVisitorToken()` returns stable UUID
130
+ - `getConversationId()` / `setConversationId()`
131
+ 2. Implement `src/core/client.ts`
132
+ 3. Implement `src/core/index.ts` re-exports
133
+ 4. All tests pass
134
+
135
+ **Commit:** `feat(core): SalesBotClient with ask/identify/resume/on API`
136
+
137
+ ---
138
+
139
+ ## Phase 8 — React adapter
140
+
141
+ ### TDD steps
142
+ 1. Write `tests/react/use-sales-bot.test.tsx`:
143
+ - `renderHook(() => useSalesBot({ embedKey }))` returns stable shape
144
+ - `ask()` appends user message to `messages`
145
+ - `isStreaming` becomes true during ask, false after done
146
+ - `messages` accumulates assistant deltas
147
+ - `error` is set on SalesBotError
148
+ - `reset()` clears messages and conversationId
149
+ - client is not re-created on re-render
150
+ 2. Implement `src/react/use-sales-bot.tsx`
151
+ 3. Implement `src/react/index.ts`
152
+ 4. All tests pass
153
+
154
+ **Commit:** `feat(react): useSalesBot hook`
155
+
156
+ ---
157
+
158
+ ## Phase 9 — Vue adapter
159
+
160
+ ### TDD steps
161
+ 1. Write `tests/vue/use-sales-bot.test.ts`:
162
+ - composable returns reactive refs
163
+ - `ask()` updates `messages` ref
164
+ - `isStreaming` ref transitions correctly
165
+ - `error` ref set on failure
166
+ - `reset()` clears state
167
+ - handlers unsubscribed on unmount
168
+ 2. Implement `src/vue/use-sales-bot.ts`
169
+ 3. Implement `src/vue/index.ts`
170
+ 4. All tests pass
171
+
172
+ **Commit:** `feat(vue): useSalesBot composable`
173
+
174
+ ---
175
+
176
+ ## Phase 10 — Widget UI
177
+
178
+ ### Tasks
179
+ - [ ] 10.1 Write `tests/widget/widget.test.ts`:
180
+ - `createWidget(opts)` appends `<sales-bot-widget>` to body
181
+ - shadow root contains launcher button and panel
182
+ - clicking launcher opens/closes panel
183
+ - `destroy()` removes element from DOM
184
+ - basic message rendering in shadow DOM
185
+ - [ ] 10.2 Implement `src/widget/styles.ts` — CSS string for shadow root
186
+ - [ ] 10.3 Implement `src/widget/widget.ts` — shadow DOM, message rendering, event wiring
187
+ - [ ] 10.4 Implement `src/widget/index.ts`
188
+ - [ ] 10.5 All tests pass
189
+
190
+ **Commit:** `feat(widget): shadow-DOM floating chat widget`
191
+
192
+ ---
193
+
194
+ ## Phase 11 — Vanilla / IIFE bundle entry
195
+
196
+ ### Tasks
197
+ - [ ] 11.1 Implement `src/vanilla/index.ts` — `window.SalesBot = { init, widget }`
198
+ - [ ] 11.2 Write a smoke test asserting `init()` returns a `SalesBotClient`
199
+ - [ ] 11.3 All tests pass
200
+
201
+ **Commit:** `feat(vanilla): IIFE entry with window.SalesBot`
202
+
203
+ ---
204
+
205
+ ## Phase 12 — Build pipeline
206
+
207
+ ### Tasks
208
+ - [ ] 12.1 Finalize `tsup.config.ts` with all entry points
209
+ - [ ] 12.2 Finalize `package.json` exports map
210
+ - [ ] 12.3 Run `pnpm build` and verify `dist/` contains expected files
211
+ - [ ] 12.4 Spot-check each bundle imports cleanly
212
+
213
+ **Commit:** `build: finalize tsup config + exports map`
214
+
215
+ ---
216
+
217
+ ## Phase 13 — size-limit
218
+
219
+ ### Tasks
220
+ - [ ] 13.1 Add `size-limit` config to `package.json`
221
+ - [ ] 13.2 Run `size-limit` and verify budgets pass (core <8KB, react/vue <12KB, widget <25KB, vanilla <20KB)
222
+
223
+ **Commit:** `ci: add size-limit bundle budget checks`
224
+
225
+ ---
226
+
227
+ ## Phase 14 — Final review + cleanup
228
+
229
+ ### Tasks
230
+ - [ ] 14.1 Run full test suite — all pass
231
+ - [ ] 14.2 Run biome check — no errors
232
+ - [ ] 14.3 Verify builds produce correct output
233
+ - [ ] 14.4 Review public API surface for consistency
234
+
235
+ **Commit:** `chore: final cleanup and verification`
236
+
237
+ ---
238
+
239
+ ## Dependency matrix
240
+
241
+ | Package | Role | Dev/Peer/Prod |
242
+ |---|---|---|
243
+ | `typescript` | Language | dev |
244
+ | `tsup` | Bundler | dev |
245
+ | `vitest` | Test runner | dev |
246
+ | `happy-dom` | DOM env | dev |
247
+ | `@testing-library/react` | React test utils | dev |
248
+ | `@testing-library/user-event` | User interaction | dev |
249
+ | `@vue/test-utils` | Vue test utils | dev |
250
+ | `@vitejs/plugin-react` | React support in vitest | dev |
251
+ | `biome` | Lint + format | dev |
252
+ | `size-limit` | Bundle budget | dev |
253
+ | `@size-limit/preset-small-lib` | size-limit preset | dev |
254
+ | `react` | React framework | peerDep |
255
+ | `react-dom` | React DOM | peerDep |
256
+ | `vue` | Vue framework | peerDep |
257
+
258
+ **Zero runtime dependencies.** All helpers (SSE parser, markdown renderer, storage) are hand-rolled and tree-shakeable.