| name | ai-foundation |
| description | Implement or extend optional, review-first AI infrastructure for numpad without compromising deterministic engine authority. |
ai-foundation skill
Use this skill for work in src/features/ai/, src-tauri/src/services/ai_*.rs, src-tauri/src/commands/ai.rs, or any AI settings/provider/streaming work.
Companion files — read these too
.codex/skills/ai-foundation/ai-file-map.md — every AI file with its role and key types
Core rules — never violate
- AI is always optional —
aiEnabled in settings.store.ts gates all AI features.
- AI is assistive, not authoritative — AI drafts are previews only.
- Deterministic engine validates AI output —
validateAiNumpadDraft() must run before any AI text is inserted.
- No hidden remote calls — all AI calls are user-triggered.
- Settings and API key are explicit — user must configure before any remote call happens.
Complete AI data flow
User triggers AI request (AiAssistantPanel)
→ build AiRequestContext (ai.context.ts)
→ build AiProviderMessage[] (ai.prompts.ts)
→ call streamAiAssistant() (ai.native.ts)
→ Tauri: stream_ai_assistant command (commands/ai.rs)
→ ai_service.rs: enabled check → model check → key resolution → provider
→ openrouter_provider.rs: SSE stream to OpenRouter
→ emits AiStreamEvent { type: "token" | "done" | "error" }
→ Tauri events received in AiAssistantPanel
→ accumulate streaming text
→ parseAiAssistantOutput() (ai.response.ts) → { responseText, draft }
→ validateAiNumpadDraft() (ai.validation.ts) → { status, issues }
→ user reviews → clicks "Insert" → applyAiDraftToNote() (ai.validation.ts)
→ onRawTextChange() callback → workspace store → engine projection
TypeScript AI file map
| File | Role |
|---|
src/features/ai/ai.types.ts | All types: AiAssistantAction, AiContextScope, AiThinkingMode, AiSettingsSnapshot, AiStreamEvent, AiModelSummary, AiDraftValidationResult, etc. |
src/features/ai/ai.constants.ts | AI_ACTIONS, AI_CONTEXT_SCOPES, AI_THINKING_OPTIONS arrays |
src/features/ai/ai.native.ts | Typed invoke wrappers: getAiSettings(), saveAiSettings(), listAiModels(), streamAiAssistant(), etc. |
src/features/ai/ai.context.ts | buildAiRequestContext() — packages editor state into context payload |
src/features/ai/ai.prompts.ts | buildAiMessages() — constructs system + user messages for OpenRouter |
src/features/ai/ai.response.ts | parseAiAssistantOutput() — splits AI response into responseText + draft |
src/features/ai/ai.validation.ts | validateAiNumpadDraft(), applyAiDraftToNote() |
src/features/ai/AiAssistantSheet.tsx | Chat panel UI — review-first, streaming display, Insert button |
src/features/settings/SettingsDialog.tsx | Global settings dialog — AI section owns API key, model, temperature, etc. |
Rust AI file map
| File | Role |
|---|
src-tauri/src/commands/ai.rs | Thin command handlers for all AI IPC |
src-tauri/src/services/ai_service.rs | Orchestration: enable check → key → provider → stream |
src-tauri/src/services/ai_settings_service.rs | Load/save AI settings from SQLite |
src-tauri/src/services/ai_secret_service.rs | OS keychain for OpenRouter API key |
src-tauri/src/services/ai_key_resolution.rs | Key precedence: user → env var → error |
src-tauri/src/services/ai_provider.rs | AiProvider trait |
src-tauri/src/services/openrouter_provider.rs | OpenRouter HTTP + SSE client |
Required workflow
- Read
ai-file-map.md for the complete type and file inventory.
- Read
docs/AI_SPEC.md for the current declared AI contracts.
- Inspect the specific files you will change.
- For new AI actions: add to
AI_ACTIONS in ai.constants.ts, add type to AiAssistantAction in ai.types.ts, handle in ai.prompts.ts and ai.context.ts.
- For new settings: add to
SaveAiSettingsInput + AiSettingsSnapshot in ai.types.ts, update Rust structs, update settings dialog.
- Run
npm run typecheck && npm run build.
- Update
docs/AI_SPEC.md and docs/API_CONTRACTS.md.
Constraints
- Do not auto-send or auto-insert — always require user confirmation.
- Do not add AI calls to engine code or workspace store.
- Do not skip
validateAiNumpadDraft() before inserting.
- Do not persist chat history between sessions (currently in-memory only).
- Do not add unit tests unless explicitly requested.
- Keep AI easy to disable via the
aiEnabled settings flag.
Docs to update
docs/AI_SPEC.md — for any AI command, type, or behavior changes
docs/API_CONTRACTS.md — for new or changed Tauri AI commands
docs/ARCHITECTURE.md — for structural changes to the AI layer