mirror of
https://github.com/garrytan/gbrain.git
synced 2026-08-14 08:53:22 +00:00
fix(sync): honor the embedding_disabled sentinel as implicit --no-embed (#2879)
gbrain init --no-embedding writes embedding_disabled: true as a deferred-setup sentinel, and init/import/embed honor it via assertEmbeddingEnabled. sync's embed credential preflight (v0.41.6.0 D1) only checked the --no-embed CLI flag, so every gbrain sync on a keyless deferred-setup brain exited 1 demanding <PROVIDER>_API_KEY — including orchestrated callers (gstack /sync-gbrain) that never pass --no-embed. embed-preflight.ts's own skip protocol documents that the sentinel is owned upstream of the credential check; this wires that contract into sync by deriving noEmbed from CLI args + config in one exported pure helper (resolveNoEmbed), covered by test/sync-no-embed-sentinel.test.ts. Co-authored-by: Gawie van Blerk <gawie.vanblerk@emeraldlife.co.za>
This commit is contained in:
co-authored by
Gawie van Blerk
parent
d21f34e96d
commit
22cb074943
+20
-1
@@ -909,6 +909,25 @@ export function buildAutoEmbedArgs(slugs: string[], sourceId?: string): string[]
|
||||
return sourceId ? ['--source', sourceId, '--slugs', ...slugs] : ['--slugs', ...slugs];
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve sync's effective no-embed mode from CLI args + config.
|
||||
*
|
||||
* The deferred-setup sentinel (`embedding_disabled: true`, written by
|
||||
* `gbrain init --no-embedding`) is an implicit `--no-embed`: without this,
|
||||
* the embed credential preflight demands provider credentials the user
|
||||
* deliberately deferred at init, and every `gbrain sync` on a keyless
|
||||
* brain exits 1. See embed-preflight.ts's skip protocol — the sentinel is
|
||||
* meant to be honored before the credential check ever runs.
|
||||
*
|
||||
* Exported for `test/sync-no-embed-sentinel.test.ts`.
|
||||
*/
|
||||
export function resolveNoEmbed(
|
||||
args: string[],
|
||||
cfg: { embedding_disabled?: boolean } | null,
|
||||
): boolean {
|
||||
return args.includes('--no-embed') || cfg?.embedding_disabled === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shell out to git with a generous maxBuffer.
|
||||
*
|
||||
@@ -4023,7 +4042,7 @@ See also:
|
||||
const dryRun = args.includes('--dry-run');
|
||||
const full = args.includes('--full');
|
||||
const noPull = args.includes('--no-pull');
|
||||
const noEmbed = args.includes('--no-embed');
|
||||
const noEmbed = resolveNoEmbed(args, loadConfig());
|
||||
const noExtract = args.includes('--no-extract'); // v0.42.7 #1696
|
||||
const skipFailed = args.includes('--skip-failed');
|
||||
const retryFailed = args.includes('--retry-failed');
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Deferred-setup sentinel → implicit --no-embed for `gbrain sync`.
|
||||
*
|
||||
* `gbrain init --no-embedding` writes `embedding_disabled: true` to
|
||||
* config.json. init, import, and embed honor that sentinel via
|
||||
* `assertEmbeddingEnabled`, but sync's embed credential preflight
|
||||
* (v0.41.6.0 D1) only checked the `--no-embed` CLI flag — so every
|
||||
* `gbrain sync` on a keyless deferred-setup brain exited 1 with
|
||||
* "Embedding model ... requires <PROVIDER>_API_KEY", even when nothing
|
||||
* needed embedding. embed-preflight.ts's own skip protocol says the
|
||||
* sentinel is owned upstream of the credential check.
|
||||
*
|
||||
* Pure-function tests; no DB, no gateway state.
|
||||
*/
|
||||
import { describe, test, expect } from 'bun:test';
|
||||
import { resolveNoEmbed } from '../src/commands/sync.ts';
|
||||
|
||||
describe('resolveNoEmbed', () => {
|
||||
test('--no-embed flag opts out regardless of config', () => {
|
||||
expect(resolveNoEmbed(['--no-embed'], null)).toBe(true);
|
||||
expect(resolveNoEmbed(['--source', 's1', '--no-embed'], { embedding_disabled: false })).toBe(true);
|
||||
});
|
||||
|
||||
test('embedding_disabled: true (deferred setup) is an implicit --no-embed', () => {
|
||||
expect(resolveNoEmbed([], { embedding_disabled: true })).toBe(true);
|
||||
expect(resolveNoEmbed(['--strategy', 'code', '--source', 's1'], { embedding_disabled: true })).toBe(true);
|
||||
});
|
||||
|
||||
test('embedding-enabled brains still embed by default', () => {
|
||||
expect(resolveNoEmbed([], null)).toBe(false);
|
||||
expect(resolveNoEmbed([], {})).toBe(false);
|
||||
expect(resolveNoEmbed([], { embedding_disabled: false })).toBe(false);
|
||||
});
|
||||
|
||||
test('sentinel must be strictly true — junk config values do not disable embedding', () => {
|
||||
expect(resolveNoEmbed([], { embedding_disabled: 'yes' as unknown as boolean })).toBe(false);
|
||||
expect(resolveNoEmbed([], { embedding_disabled: 1 as unknown as boolean })).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user