diff --git a/admin/app/jobs/run_download_job.ts b/admin/app/jobs/run_download_job.ts index 5fad2b6..8a219e9 100644 --- a/admin/app/jobs/run_download_job.ts +++ b/admin/app/jobs/run_download_job.ts @@ -147,13 +147,40 @@ export class RunDownloadJob { // Only dispatch embedding job if AI Assistant (Ollama) is installed const ollamaUrl = await dockerService.getServiceURL('nomad_ollama') if (ollamaUrl) { - try { - await EmbedFileJob.dispatch({ - fileName: url.split('/').pop() || '', - filePath: filepath, - }) - } catch (error) { - console.error(`[RunDownloadJob] Error dispatching EmbedFileJob for URL ${url}:`, error) + // Respect the global ingest policy. Under Manual, record the file + // as pending_decision so the KB panel surfaces the per-file Index + // affordance (PR #909) instead of silently auto-embedding behind + // the user's back. Unset is treated as Always to preserve legacy + // behavior — mirrors rag_service.ts:1587-1588. + const { default: KVStore } = await import('#models/kv_store') + const { default: KbIngestState } = await import('#models/kb_ingest_state') + const policyRaw = await KVStore.getValue('rag.defaultIngestPolicy') + const policy: 'Always' | 'Manual' = policyRaw === 'Manual' ? 'Manual' : 'Always' + + if (policy === 'Manual') { + try { + // firstOrCreate so a re-download doesn't demote an existing + // indexed/failed row — user keeps prior state and can re-index + // explicitly from the KB panel if they want fresh content. + await KbIngestState.firstOrCreate( + { file_path: filepath }, + { file_path: filepath, state: 'pending_decision', chunks_embedded: 0 } + ) + } catch (error) { + console.error( + `[RunDownloadJob] Error recording pending_decision state for ${filepath}:`, + error + ) + } + } else { + try { + await EmbedFileJob.dispatch({ + fileName: url.split('/').pop() || '', + filePath: filepath, + }) + } catch (error) { + console.error(`[RunDownloadJob] Error dispatching EmbedFileJob for URL ${url}:`, error) + } } } } else if (filetype === 'map') {