refactor: remove handbook sync state and related functionality
All checks were successful
On Push to Main / test (push) Successful in 31s
On Push to Main / publish (push) Successful in 1m4s
On Push to Main / deploy-dev (push) Successful in 1m31s

This commit is contained in:
RaymondVerhoef
2026-05-22 19:45:14 +02:00
parent dc628644b6
commit ca8945ea5b
12 changed files with 159 additions and 552 deletions

View File

@@ -4,8 +4,6 @@ import { Trash2, Edit2, Save, X, RefreshCw, AlertCircle, Plus, Link as LinkIcon
import * as db from '../../lib/db';
import { callLLM } from '../../lib/llm';
import { EMIT_GRAPH_ACTIONS_TOOL } from '../../lib/llmTools';
import { analyzeHandbookDelta } from '../../lib/extractionPipeline';
import { getRepoFolder, getFileContent } from '../../lib/githubService';
import Button from '../ui/Button';
import SuggestionsQueue from './SuggestionsQueue';
@@ -20,10 +18,6 @@ const KnowledgeGraph = () => {
const [analyzeError, setAnalyzeError] = useState(null);
const [newRelData, setNewRelData] = useState({ target: '', type: 'related_to' });
const [isSyncing, setIsSyncing] = useState(false);
const [syncResult, setSyncResult] = useState(null);
const [syncError, setSyncError] = useState(null);
const [syncProgress, setSyncProgress] = useState(null);
const [topics, setTopics] = useState([]);
const [relations, setRelations] = useState([]);
@@ -237,87 +231,6 @@ const KnowledgeGraph = () => {
)));
};
const syncHandbook = async () => {
setIsSyncing(true);
setSyncError(null);
setSyncResult(null);
try {
const files = await getRepoFolder('respellion', 'employee-handbook', 'docs');
const syncStates = await db.getHandbookSyncStates();
const added = [];
const modified = [];
const unchanged = [];
files.forEach(file => {
const state = syncStates.find(s => s.path === file.path);
if (!state) {
added.push(file);
} else if (state.sha !== file.sha) {
modified.push(file);
} else {
unchanged.push(file);
}
});
setSyncResult({ added, modified, unchanged, failed: [] });
const filesToProcess = [...added, ...modified];
if (filesToProcess.length > 0) {
const total = filesToProcess.length;
let done = 0;
const failed = [];
setSyncProgress(`Processing 0 of ${total} files...`);
// Run files in parallel with bounded concurrency. The extractionLimiter
// inside analyzeHandbookDelta still governs the actual API request rate;
// parallelism here just hides GitHub fetch latency and overlaps with the
// limiter's spacing instead of waiting serially.
const CONCURRENCY = 4;
const queue = filesToProcess.slice();
async function worker() {
while (queue.length > 0) {
const file = queue.shift();
if (!file) return;
try {
const rawContent = await getFileContent('respellion', 'employee-handbook', file.path);
// Skip near-empty files — they only burn an LLM call to extract nothing.
if (rawContent.trim().length < 50) {
await db.updateHandbookSyncState(file.path, file.sha);
} else {
await analyzeHandbookDelta(rawContent, file.path);
await db.updateHandbookSyncState(file.path, file.sha);
}
} catch (err) {
console.error('Failed to process file:', file.path, err);
failed.push({ path: file.path, message: err?.message || String(err) });
} finally {
done++;
setSyncProgress(`Processing ${done} of ${total} files (${failed.length} failed)...`);
}
}
}
await Promise.all(Array.from({ length: Math.min(CONCURRENCY, total) }, worker));
setSyncResult({ added, modified, unchanged, failed });
setSyncProgress(
failed.length === 0
? 'Sync Complete! Click "Analyze & Optimize Graph" above to clean up and merge.'
: `Sync finished with ${failed.length} failure(s). See console for details.`
);
reloadKb();
}
} catch (e) {
setSyncError(e.message || 'Failed to check GitHub for updates.');
} finally {
setIsSyncing(false);
setTimeout(() => setSyncProgress(null), 10000); // Clear progress after 10s
}
};
const analyzeGraph = async () => {
if (!confirm('This will send the entire graph to the AI to evaluate content, merge duplicates, and create new logical relations. This may take a moment. Proceed?')) return;
@@ -466,43 +379,6 @@ ${JSON.stringify({ topics: compactTopics, relations: compactRelations })}`;
</p>
)}
</div>
<div>
<Button
onClick={syncHandbook}
disabled={isSyncing}
variant="outline"
className="w-full flex justify-center items-center gap-2"
>
<RefreshCw size={16} className={isSyncing ? "animate-spin" : ""} />
{isSyncing ? 'Checking for updates...' : 'Sync Employee Handbook'}
</Button>
{syncError && (
<p className="mt-2 text-xs text-red-600 flex items-start gap-1">
<AlertCircle size={14} className="shrink-0 mt-0.5" />
{syncError}
</p>
)}
{syncResult && (
<div className="mt-2 text-xs text-fg-muted space-y-1 p-2 bg-bg rounded">
<p className="font-medium text-fg">GitHub Sync Status:</p>
<p>Added files: {syncResult.added.length}</p>
<p>Modified files: {syncResult.modified.length}</p>
<p>Unchanged: {syncResult.unchanged.length}</p>
{syncResult.failed?.length > 0 && (
<p className="text-red-600">Failed: {syncResult.failed.length}</p>
)}
</div>
)}
{syncProgress && (
<div className="mt-2 text-xs text-teal p-2 bg-teal/10 border border-teal/20 rounded">
<p className="font-medium flex items-center gap-2">
{syncProgress !== 'Sync Complete!' && <RefreshCw size={12} className="animate-spin" />}
{syncProgress}
</p>
</div>
)}
</div>
</div>
{/* R42 chatbot suggestions queue */}