feat(corpus): add save-to-corpus + private corpus search scope
- POST /api/save-to-corpus.php — saves tool output text to user's default CaveauAI corpus via ClientRagPipeline
- api/case/upload.php — dual-writes uploaded PDFs to CaveauAI client_documents (best-effort)
- assets/js/corpus-save.js — shared <dialog> handler for .js-save-corpus buttons on all tool pages
- includes/layout_footer.php — injects corpus-save.js + shared save dialog markup
- korrespond/deep-research/barnevernet/discrepancy JS — save-to-corpus buttons on output sections
- api/search.php + LegalTools::search() — corpus_scope param ('shared'|'private'|'both'), merges personal CaveauAI corpus with shared legal library when 'both'
- includes/tool_form.php + assets/js/tools.js — corpus scope radio toggle shown on search tab
- api/user-docs.php — add POST upload method for non-SSO authenticated users
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+45
-5
@@ -40,11 +40,51 @@ if (strncmp($head, '%PDF-', 5) !== 0) {
|
||||
try {
|
||||
$doc = CaseStore::registerUpload($userId, $name, $tmp, $size);
|
||||
CaseStore::caseEnqueueIngest((int)$doc['doc_id'], $userId);
|
||||
dbnToolsRespond([
|
||||
'ok' => true,
|
||||
'doc_id' => $doc['doc_id'],
|
||||
'filename' => $doc['filename'],
|
||||
]);
|
||||
} catch (Throwable $e) {
|
||||
dbnToolsError($e->getMessage(), 400, 'upload_failed');
|
||||
}
|
||||
|
||||
// Dual-write to CaveauAI corpus (best-effort — never fails the upload)
|
||||
$caveauDocId = null;
|
||||
$clientId = (int)($_SESSION['dbn_tools_client_id'] ?? 0);
|
||||
if ($clientId > 0 && !empty($doc['storage_path'])) {
|
||||
try {
|
||||
dbnToolsBootCaveau();
|
||||
$aiPortalRoot = dbnToolsAiPortalRoot();
|
||||
$textExtractFile = $aiPortalRoot . '/platform/includes/text_extract.php';
|
||||
if (is_file($textExtractFile)) {
|
||||
require_once $textExtractFile;
|
||||
$content = extractPdfText($doc['storage_path']);
|
||||
if ($content !== '' && strlen($content) > 30) {
|
||||
$caveauDb = getDb();
|
||||
$corpusSt = $caveauDb->prepare(
|
||||
'SELECT id FROM client_corpora WHERE client_id = ? AND is_default = 1 LIMIT 1'
|
||||
);
|
||||
$corpusSt->execute([$clientId]);
|
||||
$corpusId = (int)($corpusSt->fetchColumn() ?: 0);
|
||||
if ($corpusId > 0) {
|
||||
$title = pathinfo($doc['filename'], PATHINFO_FILENAME);
|
||||
$caveauDb->prepare("
|
||||
INSERT INTO client_documents
|
||||
(client_id, corpus_id, title, source_type, content, category,
|
||||
import_method, word_count, status)
|
||||
VALUES (?, ?, ?, 'pdf', ?, 'user-upload', 'dbn_upload', ?, 'pending')
|
||||
")->execute([$clientId, $corpusId, $title, $content, str_word_count($content)]);
|
||||
$caveauDocId = (int)$caveauDb->lastInsertId();
|
||||
$rag = new ClientRagPipeline($clientId);
|
||||
$rag->ingestDocument($caveauDocId);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
// Non-fatal: log and continue
|
||||
error_log('[upload] CaveauAI dual-write failed for doc ' . ($doc['doc_id'] ?? '?') . ': ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
dbnToolsRespond([
|
||||
'ok' => true,
|
||||
'doc_id' => $doc['doc_id'],
|
||||
'filename' => $doc['filename'],
|
||||
'caveau_doc_id' => $caveauDocId,
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user