fix(cli): route gbrain capture through put_page on thin-client installs#2266
Open
spinsirr wants to merge 1 commit into
Open
fix(cli): route gbrain capture through put_page on thin-client installs#2266spinsirr wants to merge 1 commit into
gbrain capture through put_page on thin-client installs#2266spinsirr wants to merge 1 commit into
Conversation
…alls
On a thin-client install (config has `remote_mcp`, no `database_url`),
`gbrain capture "..."` failed with:
No database URL: database_url is missing from config.
Fix: Run gbrain init --supabase or gbrain init --url
even though `gbrain put`, `gbrain whoami`, and `gbrain search` all routed
remote correctly on the exact same config.
Root cause: `capture` is a CLI_ONLY command, so it is dispatched through
`handleCliOnly()` rather than the shared-op routing seam in `main()` that
sends non-localOnly ops through `runThinClientRouted` on thin-client
installs. `handleCliOnly` already has thin-client bypasses for `status`
and `eval whoknows` (both pass `engine=null` and return before connect),
but not for `capture` — so capture fell through to the unconditional
`connectEngine()`, which throws "No database URL" from src/core/db.ts
before capture's own thin-client branch (callRemoteTool('put_page', ...))
could ever run.
capture.ts itself was already correct: `runCapture` accepts `engine=null`
and guards every local-engine use behind `isThinClient(cfg)` (the source
resolver at ~L426, the put_page-op fallback at ~L506). The only thing
missing was the dispatch-time bypass so the engine is never opened.
Fix: add a thin-client bypass for `capture` in `handleCliOnly`, mirroring
the existing `status` / `eval whoknows` guards. `capture` is intentionally
NOT added to THIN_CLIENT_REFUSED_COMMANDS because it CAN run remotely (the
server exposes put_page) — matching the documented contract: "thin-client
installs route through callRemoteTool('put_page', ...). Same UX both ways."
Test: adds a regression test in test/cli-dispatch-thin-client.test.ts that
seeds a thin-client config, runs `gbrain capture`, and asserts it never
emits "No database URL" and instead surfaces the remote put_page path
(the "remote put_page failed:" prefix is unique to capture's thin-client
catch and cannot appear on the local-engine path).
Verified: `tsc --noEmit` clean; `bun run verify` (30 checks) all green;
cli-dispatch-thin-client + thin-client-routing-audit + capture-runcapture +
commands/capture + ingestion/ingest-capture suites pass (97 tests, 0 fail).
Co-Authored-By: Zypher Agent <zypher@corespeed.io>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
On a thin-client install (config has
remote_mcp, no localdatabase_url),gbrain capture "..."errors out:…even though
gbrain put,gbrain whoami, andgbrain searchall route remote correctly on the exact same config. Onlycapturebreaks.This violates the documented contract (README + CHANGELOG):
Reproduce
gbrain put inbox/xon the same config routes remote correctly (it only fails on reaching the server), proving the issue is specific tocapture.Root cause
captureis aCLI_ONLYcommand, so it is dispatched throughhandleCliOnly()rather than the shared-op routing seam inmain()that sends non-localOnlyops throughrunThinClientRoutedon thin-client installs.handleCliOnlyalready has thin-client bypasses forstatusandeval whoknows(both passengine=nulland return before connecting) — but not forcapture. Socapturefalls through to the unconditionalconnectEngine(), which throwsNo database URLfromsrc/core/db.tsbefore capture's own thin-client branch (callRemoteTool('put_page', ...)) can ever run.src/commands/capture.tswas already correct:runCaptureacceptsengine=nulland guards every local-engine use behindisThinClient(cfg)(the source resolver at ~L426, theput_page-op fallback at ~L506). The only thing missing was the dispatch-time bypass so the local engine is never opened on a thin-client.put/whoami/searchwork because they are registered ops (notCLI_ONLY) and hit themain()routing seam.Fix
Add a thin-client bypass for
captureinhandleCliOnly, mirroring the existingstatus/eval whoknowsguards:captureis intentionally not added toTHIN_CLIENT_REFUSED_COMMANDSbecause it can run remotely (the server exposesput_page).Test
Adds a regression test to
test/cli-dispatch-thin-client.test.tsthat seeds a thin-client config, spawnsgbrain capture, and asserts it never emitsNo database URLand instead surfaces the remoteput_pagepath. The"remote put_page failed:"prefix is unique to capture's thin-clientcatchand cannot appear on the local-engine path, so it is precise proof of remote routing. Watched it fail before the fix (RED) and pass after (GREEN).Verification
tsc --noEmit— cleanbun run verify(30 checks) — all greenbun testoncli-dispatch-thin-client,thin-client-routing-audit,capture-runcapture,commands/capture,ingestion/ingest-capture— 97 pass, 0 failNotes
isThinClient(cfg), so local-engine capture takes the existing path untouched.src/commands/capture.tsis unchanged from v0.42.36 through current master, so this bug is present on master too.