feat: KB Accelerator — convert KB articles into interactive flows

Full-stack implementation of the KB Accelerator feature that converts
static MSP knowledge base articles into interactive troubleshooting
and procedural flows using AI.

Backend:
- Migrations 054/055: kb_imports, kb_import_nodes tables + plan_limits KB columns
- SQLAlchemy models with relationships and self-referential node hierarchy
- Text extraction service (txt, paste, docx with structural metadata)
- AI conversion service with MSP-specialist prompts for both flow types
- 8 API endpoints: upload, get, list, convert, edit node, commit, delete, quota
- Tier-gated access via plan_limits (free: 3 lifetime, pro/team: unlimited)
- 8 integration tests covering upload, get/list, quota, commit, delete

Frontend:
- TypeScript types and API client for all KB Accelerator endpoints
- Multi-step wizard page: upload → processing → review → success
- Upload screen with paste/file tabs, drag-drop, target type selector
- Two-panel review screen with source highlighting and node cards
- Per-node actions: approve, edit, regenerate, insert, delete
- Confidence color indicators (green/amber/red)
- Sidebar navigation with Sparkles icon
- Code-split lazy-loaded route at /kb-accelerator

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-03-10 20:56:28 -04:00
parent c65aa4f0b7
commit 71ff4a8c35
27 changed files with 4426 additions and 2 deletions

View File

@@ -73,3 +73,17 @@ export type {
ContextMenuPosition,
SuggestionMarker,
} from './editor-ai'
export type {
KBUploadTextRequest,
KBNodeEditRequest,
KBCommitRequest,
KBListParams,
KBImportNode,
KBUploadResponse,
KBImport,
KBImportSummary,
KBImportListResponse,
KBCommitResponse,
KBQuotaResponse,
} from './kbAccelerator'

View File

@@ -0,0 +1,108 @@
/**
* KB Accelerator types — converts KB articles into interactive flows.
*/
// ── Requests ──
export interface KBUploadTextRequest {
content: string
title?: string
target_type?: 'troubleshooting' | 'procedural'
}
export interface KBNodeEditRequest {
operation: 'approve' | 'reject' | 'edit' | 'delete' | 'regenerate' | 'insert_after'
content?: Record<string, unknown>
guidance?: string
}
export interface KBCommitRequest {
name?: string
description?: string
category_id?: string
}
export interface KBListParams {
skip?: number
limit?: number
status?: string
}
// ── Responses ──
export interface KBImportNode {
id: string
kb_import_id: string
node_order: number
node_type: string
content: Record<string, unknown>
parent_node_id: string | null
source_excerpt: string | null
confidence_score: number
user_edited: boolean
user_approved: boolean
}
export interface KBUploadResponse {
id: string
status: string
source_format: string
}
export interface KBImport {
id: string
account_id: string
created_by: string
source_filename: string | null
source_format: string
source_text: string
source_metadata: Record<string, unknown> | null
target_type: string
status: string
confidence_avg: number | null
error_message: string | null
processing_time_ms: number | null
ai_tokens_input: number | null
ai_tokens_output: number | null
tree_id: string | null
nodes: KBImportNode[]
created_at: string
updated_at: string
}
export interface KBImportSummary {
id: string
source_filename: string | null
source_format: string
target_type: string
status: string
confidence_avg: number | null
node_count: number
created_at: string
}
export interface KBImportListResponse {
items: KBImportSummary[]
total: number
skip: number
limit: number
}
export interface KBCommitResponse {
tree_id: string
import_id: string
tree_type: string
}
export interface KBQuotaResponse {
plan: string
kb_accelerator_enabled: boolean
lifetime_conversions_used: number
lifetime_conversions_limit: number | null
allowed_formats: string[]
detailed_analysis: boolean
conversational_refinement: boolean
step_library_matching: boolean
history_limit: number | null
can_convert: boolean
}