1e16b0d5d2
- Add packages/ai: AgentController (streaming + budget), SuggestionBuilder, NoteBuilder, AIStore (Dexie/IndexedDB), SuggestionMutation - Fix createUlid to use monotonicFactory for reliable listSessions sort tiebreaker - Extend outline system prompt with setting + characters context - Add dexie dependency to packages/ai - 188 tests passing (core 47, ui 5, editor 30, ai 71, exporters 22, web 13)
48 lines
3.2 KiB
Markdown
48 lines
3.2 KiB
Markdown
# CHUNK #9 — AI Roles & Suggestions
|
|
|
|
**Status:** In progress. Core AI session storage layer implemented and tested.
|
|
|
|
## Progress
|
|
|
|
- [x] **AI session storage layer** (`packages/ai/src/`)
|
|
- [x] `agent.ts` — AgentController: streaming orchestration + token budget enforcement
|
|
- [x] `suggestions.ts` — SuggestionBuilder: AI suggestions across brainstorm/outline/expand/tighten/continue/research/dialogue/worldbuilding
|
|
- [x] `notes.ts` — NoteBuilder: note builders for writing assistance
|
|
- [x] `ai-session.ts` — AIStore: IndexedDB session persistence via Dexie (sessions, messages, suggestions, notes)
|
|
- [x] `suggestion-mutation.ts` — SuggestionMutation: apply/insert/replace/delete logic
|
|
- [x] `index.ts` — package exports
|
|
- [x] `dexie` dependency added to `packages/ai/package.json`
|
|
|
|
## Bug fixes
|
|
|
|
- [x] **`listSessions` sort tiebreaker flaky in full suite** — `packages/core/src/ids.ts` `createUlid` used the non-monotonic `ulid` function, so ULIDs weren't monotonic. The `listSessions` sort uses ULID comparison as a tiebreaker when `updatedAt` timestamps are equal; non-monotonic ULIDs caused the test to pass in isolation but fail in the full suite. Fixed by switching `createUlid` to `monotonicFactory` from the `ulid` package.
|
|
- [x] **`mergeNotes` test used wrong note id** — test used `note2.notes[0]!.id` (same as note1's id) instead of `note2.notes[1]!.id`, causing the merge to combine note1 with itself. Fixed the test.
|
|
- [x] **`outline` system prompt missing context** — test "includes the context in the system prompt" expected the outline prompt to include `setting` and `characters`, but the outline prompt only included `chapterTitle` and `previous`. Added setting and characters to the outline prompt.
|
|
- [x] **Lint errors** — removed unused imports: `createInMemoryPersistence`, `NoteKind`, `AINote`, `AISuggestion`.
|
|
|
|
## Test results
|
|
|
|
- packages/core: 47 tests
|
|
- packages/ui: 5 tests
|
|
- packages/editor: 30 tests
|
|
- packages/ai: 71 tests
|
|
- packages/exporters: 22 tests
|
|
- apps/web: 13 tests
|
|
- **Total: 188 tests passing**
|
|
|
|
## Key facts
|
|
|
|
- Chunk #9 builds `packages/ai` as a self-contained SSE-based provider layer (NOT the Vercel AI SDK). The SDK moved v5→v4 and `@ai-sdk/openrouter` doesn't exist (404); a hand-rolled SSE client directly exercises the real deliverable (streaming orchestration, thinking-param mapping, usage tracking, 429 retry) in the mocked integration test that is the CI gate.
|
|
- The Vercel AI SDK remains the intended transport for Chunk #11 (tools).
|
|
- `packages/core/src/tokens.ts` provides `countTokens`/`allocateBudget`/`DEFAULT_BUDGET` (re-exported by `packages/ai/budget.ts`).
|
|
- `packages/ai` re-exports core's token-budget types as `Budget` (NOT `TokenBudget`).
|
|
- `packages/ai` uses Dexie for IndexedDB AI session persistence, coordinating `AIStore`, `SuggestionBuilder`, `NoteBuilder`, and `AgentController`.
|
|
|
|
## Remaining (per CHUNK#9.md)
|
|
|
|
- Base role prompts (`packages/ai/src/roles/`): editor/reader/publisher/co-author
|
|
- Context builder (`packages/ai/src/context.ts`)
|
|
- Tools (`packages/ai/src/tools/`): applySuggestion, updateEntity, addNote, draftChapter, queryProject
|
|
- Suggestion protocol: structured output + inline rendering in editor decorations
|
|
- Session UI (`apps/web/src/features/ai/`): AiPanel, AiSessionsView, feedback loop
|