Files
PubScript/CHUNK#9_PROGRESS.md
T
Schwitzz 1e16b0d5d2 CHUNK #9: AI session storage layer (AgentController, AIStore, builders)
- 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)
2026-10-29 07:31:25 -05:00

3.2 KiB

CHUNK #9 — AI Roles & Suggestions

Status: In progress. Core AI session storage layer implemented and tested.

Progress

  • AI session storage layer (packages/ai/src/)
    • agent.ts — AgentController: streaming orchestration + token budget enforcement
    • suggestions.ts — SuggestionBuilder: AI suggestions across brainstorm/outline/expand/tighten/continue/research/dialogue/worldbuilding
    • notes.ts — NoteBuilder: note builders for writing assistance
    • ai-session.ts — AIStore: IndexedDB session persistence via Dexie (sessions, messages, suggestions, notes)
    • suggestion-mutation.ts — SuggestionMutation: apply/insert/replace/delete logic
    • index.ts — package exports
    • dexie dependency added to packages/ai/package.json

Bug fixes

  • 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.
  • 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.
  • 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.
  • 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