diff --git a/src/commands/embed.ts b/src/commands/embed.ts index e43c5582f..d0214111e 100644 --- a/src/commands/embed.ts +++ b/src/commands/embed.ts @@ -4,6 +4,8 @@ import type { ChunkInput } from '../core/types.ts'; import { chunkText } from '../core/chunkers/recursive.ts'; import { createProgress, type ProgressReporter } from '../core/progress.ts'; import { getCliOptions, cliOptsToProgressOptions } from '../core/cli-options.ts'; +import { assertEmbeddingEnabled } from '../core/embedding-dim-check.ts'; +import { loadConfig } from '../core/config.ts'; export interface EmbedOpts { /** Embed ALL pages (every chunk). */ @@ -67,6 +69,12 @@ export interface EmbedResult { * auto-embed step) can report embeddings in their own structured output. */ export async function runEmbedCore(engine: BrainEngine, opts: EmbedOpts): Promise { + // T7 (D9): refuse cleanly when init persisted the deferred-setup sentinel. + // Skipped in dryRun mode so plan-mode introspection still works. + if (!opts.dryRun) { + assertEmbeddingEnabled(loadConfig()); + } + const result: EmbedResult = { embedded: 0, skipped: 0, diff --git a/src/commands/import.ts b/src/commands/import.ts index 517c9a50c..e0ed8525d 100644 --- a/src/commands/import.ts +++ b/src/commands/import.ts @@ -49,6 +49,22 @@ export async function runImport( const noEmbed = args.includes('--no-embed'); const fresh = args.includes('--fresh'); const jsonOutput = args.includes('--json'); + + // T7 (D9): refuse cleanly when init persisted the deferred-setup sentinel, + // unless the user is explicitly skipping embedding via `--no-embed` (in + // which case the chunks land without vectors and the user can backfill + // later with `gbrain embed --stale` after configuring a provider). + if (!noEmbed) { + const { assertEmbeddingEnabled } = await import('../core/embedding-dim-check.ts'); + const { loadConfig } = await import('../core/config.ts'); + try { + assertEmbeddingEnabled(loadConfig()); + } catch (e) { + console.error(`\n${e instanceof Error ? e.message : e}`); + console.error('Tip: run `gbrain import --no-embed` to import without embedding now.'); + process.exit(1); + } + } // v0.30.x follow-up to PR #707: programmatic sourceId support so internal // callers (performFullSync, future Step 6 paths) can route to a named // source. The CLI `gbrain import` deliberately has no --source flag per