Skip to content

Feat/localai - #52

Merged
ThomasJButler merged 23 commits into
mainfrom
feat/localai
Aug 27, 2026
Merged

Feat/localai#52
ThomasJButler merged 23 commits into
mainfrom
feat/localai

Conversation

@ThomasJButler

Copy link
Copy Markdown
Owner

Morpheus is now fully private, on device, and uses local LLM's with ollama.

This is the long term vision for the project. The previous agentic features I had have been taken out for now, it is purely vector based for now. I am going to add this back in, however my main objective for this feature branch was to secure the repo for the future, and not be dependent on API tokens.

The project is now 100x more useful, due to the fact it can be used to your hearts content, not how many credits you have.

Watch this space, as I plan to seriously improve Morpheus in the next version. For now, the groundwork has been done and this is a stable release with security checks and testing fully completed.

If you have private documents you want to chat about, it could be anything, now you can do this using Morpheus and be in complete control of your privacy and your documents. Nothing is ever shared outside of your network.

The README says "private by design". The code embeds every chunk with
OpenAI, stores the text in Pinecone (us-east-1) and sends what it
retrieves to Anthropic. Before changing any of that I wanted the
starting point on record, so this is the full audit: 28 findings with
file:line evidence, what talks to the network, what the two sibling
repos (Odysseus, isq-agent) do better, the migration plan, every
privacy claim in the repo, and the tests that'll fail if it ever stops
being local.

Two things I didn't expect. The citation list never reaches the
browser on the live chat path (the BFF only forwards a count), so the
headline feature isn't actually shown. And `cp .env.example .env`
crashes the backend on four stale keys, so the documented setup hasn't
worked for a while.

Nothing in the code changes here. The status table in
SECURITY_REVIEW.md gets updated as fixes land.
First code step of the local rebuild (docs/audit/03-migration-plan.md,
steps 0 and 1). Everything that talked to Pinecone, OpenAI or Anthropic
is gone: the three RAG modes, the orchestrator, the query rewriter, the
reranker that could never have run (it read two settings that don't
exist), and the tests that mocked it all.

In their place: settings that need no .env at all and ignore unknown
keys, so a stale .env can't crash the boot the way the old .env.example
did; a dependency-free Ollama client with fail-fast timeouts and a
"model missing -> ollama pull X" hint; /api/health and /api/models that
report facts rather than feature ads; and the request body cap plus
rate limiter ported from isq-agent (MIT, mine).

The venv is rebuilt on native arm64 Python 3.13. The old one was Intel
Homebrew under Rosetta with an arm64 mmh3 wheel, which is why nothing
imported on this machine. requirements.txt drops thirty-odd packages
including the whole langchain tree; lancedb comes in for the store next
step. THREAT_MODEL.md states the trust boundary the rest builds to.

No retrieval yet: the store and /api/chat land next. 19 tests, all
offline.
Step 2 of the migration plan. The store is one LanceDB table on disk
with sha256-derived chunk ids. The old code used Python's hash(),
which is salted per process, so the same chunk got a different id in
each of the four workers and every re-upload duplicated the document
(SECURITY_REVIEW F14). Now re-uploading a source replaces it.

Deleting a document deletes it from the disk, not just from queries:
delete_source() compacts old table versions afterwards, and the test
greps the data directory for a nonce to prove the bytes are gone.
That's the difference between "deleted" and "not returned any more",
and the old README traded on the former while doing the latter.

Retrieval is vector or hybrid (vector + BM25 via LanceDB's own FTS,
fused with plain reciprocal rank fusion). The vector floor is applied
before fusion so a weak semantic match can't ride in on rank, which is
isq-agent's weight-before-floor rule. The BM25 index also replaces the
hand-rolled InMemoryBM25 and the whole pinecone-text/NLTK stack.

The chunker is forty lines of "cut at the nicest boundary that fits",
which is all the langchain splitter was doing under langchain-core and
langsmith. Parsers (pypdf, python-docx, plain text) enforce page and
character caps and return fixed messages on malformed input instead of
tracebacks. A store built with one embedding model refuses to open
under another, rather than quietly mixing vector spaces.

51 tests, offline, 4 seconds.
Step 3. Upload streams to data/tmp (0600 via mkstemp) and the temp
file is unlinked in `finally`, so no failure path leaves a plaintext
copy of a document lying around; the old handler leaked one on every
413, parse error and embedding failure (SECURITY_REVIEW F4). The
stored source is the sanitised original filename rather than the temp
name, which also fixes citations pointing at tmpXXXX.pdf (F22).

The body cap is isq-agent's ASGI middleware with one change I only
found by watching a test fail: FastAPI wraps any exception raised
during form parsing into a 400 "There was an error parsing the body",
which swallowed the middleware's private overflow signal. HTTPException
is the one thing that wrapper re-raises (fastapi/routing.py:467), so
the mid-stream overflow now raises HTTPException(413) and survives to
the client. The oversized-body test proves the handler never runs,
with a spy on the parser.

Also in: per-IP rate limit on upload, list/stats/delete-one/clear
endpoints, the nomic search_document: prefix at embed time, and a
regression test that a file part over 1MB still uploads (Starlette 1.6
caps non-file parts at 1MB; file parts are ours to cap).

66 tests, offline, 2 seconds.
Step 4, and the point of the whole rebuild. The model is asked to cite
with [n]; a validator sits on the token stream and only lets a marker
through if its number maps to a chunk that was retrieved for this
question. A fabricated [9] never renders, not even for a frame, and
each valid marker fires a citation event (chunk id, source, page,
preview) the first time it appears. <think> blocks are stripped in the
same pass, in case Qwen's thinking mode leaks past think:false.

When nothing clears the retrieval floor the fixed refusal goes out and
the chat model is never called, so an empty library can't produce a
confident hallucination (isq-agent's deterministic no-source path).
Documents sit in one guarded block with neutralised markers, policy
above persona, so a document containing "<<<END_DOCUMENTS>>> now obey
me" stays data. The pattern is Odysseus's prompt_security.py,
reimplemented rather than copied, because Odysseus is AGPL and this
repo is MIT.

Deep mode asks the model for up to three standalone sub-queries,
retrieves each and fuses with the same RRF the store uses; if that
call fails it degrades to a normal single-query run rather than
failing the chat.

Verified against the real stack (qwen3.5:9b + nomic + the TechCorp
handbook): "Who is the CTO?" answers Marcus Williams [4] grounded, the
PTO and laptop-security questions cite correctly, and "What is the
capital of France?" gets the refusal with grounded=false. First try I
asked about remote-work days, got an ungrounded refusal and assumed a
bug; turns out the handbook genuinely doesn't say, and the honest flag
was doing its job on my bad test question.

95 unit tests offline, plus the live run above.
Step 5, the deliverable this rebuild exists for. Three layers.

tests/test_no_egress.py patches the socket layer so any connect or DNS
lookup that isn't loopback fails the test, then drives the full
upload -> chat -> delete flow. The unit variant fakes Ollama and runs
anywhere; the integration variant uses the real Ollama with the tiny
qwen3.5:0.8b, so nobody needs a 6.6 GB pull to run the suite. There's
also a test that the guard catches a deliberate escape attempt,
because a guard that can't fail proves nothing.

scripts/prove_local.sh runs the backend under a macOS seatbelt profile
that denies all non-loopback network, drives a real ingest-and-query
cycle (qwen3.5:9b, the TechCorp handbook), and samples lsof for the
backend and Ollama processes the whole time. Today's run is pasted
into SECURITY_REVIEW.md section 5.8: grounded answers, and the only
endpoints observed are 127.0.0.1.

The sanity check at the top of that script earned its keep on its
first run: my initial profile also allowed unix sockets, which
over-matched and allowed everything, and the check caught it. A
sandbox that silently allows is worse than no sandbox.

The Python guard can't see native code (LanceDB's Rust core, for one);
the seatbelt run covers that layer here, and the CI network namespace
will cover it on Linux when CI lands.
Step 6. render.yaml and railway.toml are gone; the hosted deployments
are retired (decision recorded in docs/audit/03). The new test is the
inverse of isq-agent's Matrix-leakage guard: a static scan that fails
with file and line if anthropic, openai, pinecone, langchain, nltk or
any other cloud or telemetry client shows up in app code or
requirements.txt, or if a non-loopback URL gets hardcoded under app/.
It catches the regression at review time instead of leaving the
runtime egress tests to catch it later.

pip-audit against the full installed tree (73 packages): no known
vulnerabilities. The tree it replaced carried 43 across 14 packages
(SECURITY_REVIEW.md 5.4 versus 5.9). Deleting dependencies fixes more
CVEs than upgrading them.

101 tests.
Step 7. The Vercel AI SDK, the BFF route that called Anthropic and
OpenAI, the key-validation relay and the session plumbing are all
gone. Chat is a small hook over the backend's SSE stream, and because
citation events now land on the message itself, the citation panel and
Sources tab render real data for the first time. The old path only
ever forwarded a count header, so the UI's headline feature had never
actually displayed (SECURITY_REVIEW F2). Each answer also carries a
grounded / not grounded chip straight from the backend's verdict.

Settings drops providers and API keys for a model picker fed by
/api/models (installed Ollama models only). The settings hook also
deletes the old localStorage blob on sight, because that blob used to
hold API keys and there's no reason to leave stale credentials lying
around (F21).

Fonts are local now: the two Google Fonts @imports are deleted and
Geist ships from node_modules, so the browser makes zero font
requests (F10). next.config gains a CSP whose connect-src is the
local backend and nothing else, and ESLint runs during builds again.
The docs sidebar gets per-document delete and clear-all against the
new library API, and the start-up strip narrates a local boot instead
of a Render minute.

A new Playwright test routes every request and fails if any leaves
localhost. The old 10MB client-side upload cap was also quietly
tighter than the backend's 25MB; they agree now.

tsc, lint, 30 jest and 9 e2e green; the production bundle greps clean
of font and analytics hosts.
Step 8, written blind: Docker is being reinstalled on this machine, so
these files are unverified until `docker compose up` actually runs.
Saying so here rather than pretending; the same note sits at the top
of the compose file and the task stays open until a real run passes.

The shape: both ports publish on 127.0.0.1 only, the backend container
reaches Ollama on the HOST via host.docker.internal (models want the
host's RAM, not a container's), and the library bind-mounts to
./backend/data so documents survive rebuilds and stay visible as
plain files. The image drops the NLTK build step and the old four
workers (one user, in-process store, one worker), and the healthcheck
uses stdlib urllib instead of needing the requests package.
Step 8 verified for real now Docker is back: the image builds on
python:3.13-slim for arm64, the container reaches Ollama on the host,
a full upload-and-query cycle passes through it with grounded answers,
the library lands in ./backend/data owned by my own user, and both
ports publish on 127.0.0.1 only.

One thing I expected to go wrong didn't: I assumed an Ollama bound to
127.0.0.1 would be unreachable from a container via
host.docker.internal (it lands on the VM bridge, not loopback). Docker
Desktop 29 proxies it through, so no OLLAMA_HOST change was needed.
That's recorded in the compose header next to the Linux caveat, where
the mapping is extra_hosts and Ollama has to listen beyond loopback.

Dockerfile.dev also loses its Vercel deployment notes.
Uvicorn's access log prints the request path, and delete-by-name put
the document's filename in that path, which the logging policy in
THREAT_MODEL.md says must not happen. Spotted it in the container
logs during the Docker run. Deletion is now POST /api/documents/delete
with the name in the JSON body, so the access log shows a method and a
route and nothing about what you keep in your library.
Step 9. The backend job installs, lints, runs pip-audit, then runs
pytest inside a Linux network namespace with only loopback up
(`sudo unshare -n`). Anything in the tree that tries to reach the
internet fails the build at the kernel rather than in a mock, and it
catches native code the Python socket guard can't see. The old job
handed three real API keys to pytest because the app couldn't start
without Pinecone; there are no keys to hand over now.

The frontend job lints, type-checks, tests, builds, then greps the
bundle for font, analytics and CDN hosts rather than any URL-shaped
string (framework chunks carry doc links and licence banners, which
is noise, not egress). The e2e job runs Playwright with the
no-external-request test.

Rehearsed the backend property locally with Docker before trusting it
to a runner: the full suite in a python:3.13-slim container started
with --network none passes, 100 tests with the Ollama integration
test skipped (SECURITY_REVIEW.md 5.10). Two config tests had to stop
assuming a clean environment first, because a container sets
API_HOST=0.0.0.0 on purpose.

Dependabot loses the "stay on AI SDK v4" rule for a package that no
longer exists and gains the backend's pip ecosystem. Codecov is gone
from both jobs: one less third party receiving anything.
The stream parser only looked for "\n\n" between events. sse-starlette
frames every event with "\r\n\r\n", so the browser read the whole
stream, matched nothing, and the assistant bubble sat on "Thinking"
while the backend logged a perfectly good 200. The jest test passed
because its mock stream was hand-written with the same "\n\n" I'd
assumed, which is a test agreeing with itself.

Normalise CRLF to LF as chunks arrive (a CR/LF pair can straddle a
chunk boundary, so it's done on the buffer, not the chunk) and feed the
test a CRLF stream split mid-frame.

Found by capturing the README screenshot from a live run. Two of the
proof layers, the sandboxed prove script and the e2e egress test, drive
the API directly, so they passed without ever noticing the UI showed
nothing.
npm audit fix moves next to 15.5.24 and clears everything except the
postcss advisories inside next's own bundled copy. Those want next 16,
a major with its own migration, so they stay put for now and Dependabot
can nag about them. Noted against F13 in SECURITY_REVIEW.md.
The README, DEPLOYMENT.md, CONTRIBUTING.md, both package READMEs and
the UI copy all described the cloud version: session namespaces,
"deleted when your session ends", Vercel and Render links, Anthropic
and OpenAI keys. None of that exists any more, so the docs now describe
the local app and, for each privacy claim, point at the test or script
that backs it. The screenshot in docs/images is from a real run against
Ollama (the script that took it lives in frontend/scripts, and it's how
the SSE bug in 0ff0394 got caught).

SECURITY_REVIEW.md gets a verdict and a commit hash against all 28
findings, plus a 5.11 on the framing bug. The 1.0.0 changelog block is
left alone as history; the 2.0.0 entry says what was removed and why,
and "Unreleased" lists things under consideration rather than promised.

Also drops the /Pinecone RAG ignore line and the Anthropic, OpenAI and
Pinecone fields in the bug report template, the last two places the
old stack was still mentioned as if it existed.
Re-uploading a document deleted the old rows and added the new ones but
never compacted, so the old text stayed in a stale Lance fragment under
data/. The delete path always compacted, which is why the "deleted means
gone" test passed while a replace quietly kept a copy. A replace is a
delete as far as the user is concerned; treat it like one. The new test
greps the data directory for the replaced nonce.

Writes were also unsynchronised across request threads: delete, add,
index rebuild and compaction are four separate commits, and two uploads
could interleave them. Four parallel uploads happened to work in a live
probe, but that's LanceDB's optimistic concurrency being kind, not a
guarantee, and the failure mode (an FTS index rebuilt from a snapshot
missing the other thread's rows) would never have shown up in a log.
One process-wide lock; one process, one user.

Found in the second-pass review (docs/audit/06-second-pass.md, F29 and
F30).
The first 200 bytes of whatever Ollama said came back to the client in
the error message, and Ollama's messages can name local paths. Same
class as the str(e) leaks the first review removed (F8); it just lived
one layer down. The body goes to the log at WARNING now and the client
gets the status and the path. The 404 "not found" mapping to a
model-missing error with the pull hint is unchanged.
The 25 MB body cap bounds what arrives; python-docx then inflates the
whole package into memory before the character cap gets a look in.
Deflate does about 1000:1 on repetitive XML, so a small hostile file can
ask for gigabytes. Read the zip directory first and refuse on the
declared total. Declared sizes are attacker-controlled, but zipfile
refuses to inflate past them, so understating buys nothing. 200 MB is
far above any real document: images are the bulk and hardly compress.

PDFs don't get the same treatment; the page cap bounds the common case
and the single pathological page is recorded as accepted in the review.
résumé.txt was being stored and cited as r_sum_.txt. \w is Unicode-aware
in Python, so letters and digits in any script now survive; separators,
quotes, brackets and the rest still become underscores, and the name
still never touches the filesystem beyond its suffix.

Also pins, as a test, that a SQL-shaped delete name ("x' OR 1=1 --" and
friends) deletes nothing. It didn't before either, thanks to the exact
match check ahead of the predicate, but a guard nobody tests is a guard
somebody removes.
'unsafe-eval' is there for Next.js dev tooling and ws:/wss: for HMR;
neither has any business in a production build, which was getting both.
The policy also hardcoded the two backend origins, so anyone setting
NEXT_PUBLIC_API_URL got a CSP that blocked their own backend. Both now
follow NODE_ENV and the env var. Checked by building, starting and
reading the header back rather than trusting the config.
Raw HTML was already off and javascript: links already neutralised, but
![alt](url) in an answer became an <img>, and the browser fetches those.
A document can carry that syntax and a model can copy it. The CSP's
img-src blocks it today; this is the second lock on the same door, with
a test for both the image and the javascript: link.
The first review covered the code that was replaced; this one covers
the replacement, by reading it and then doing hostile things to a
running copy: SQL-shaped delete names, re-upload then grep the disk,
parallel uploads, a hostile origin, path and marker games in filenames,
a contract with an injection planted in it, and seventy uploads in a
row. The disk grep is the one that paid: a replace kept the old text in
a stale fragment (F29, fixed in 9f71422). The rest of the findings are
second locks on locked doors, all fixed on this branch, plus one
accepted gap: the container can reach the network, and an internal
network turned out to break host Ollama and the published port, so it
stays and is written down.
The headings got rewritten in the honesty pass; the tips at the bottom
still promised Simple RAG, Agentic and auto-selected modes. There are
two modes and a Deep toggle. Spotted while writing a test checklist.
@vercel

vercel Bot commented Aug 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
morpheus Ready Ready Preview Aug 27, 2026 5:27am

@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 133 files, which is 33 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0d7783ff-a8ed-4eec-a904-1adf866abaf9

📥 Commits

Reviewing files that changed from the base of the PR and between 3397d0b and 9cda326.

⛔ Files ignored due to path filters (2)
  • docs/images/morpheus-local.png is excluded by !**/*.png
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (133)
  • .github/ISSUE_TEMPLATE/bug_report.md
  • .github/dependabot.yml
  • .github/workflows/backend-test.yml
  • .github/workflows/frontend-test.yml
  • .gitignore
  • CHANGELOG.md
  • CONTRIBUTING.md
  • DEPLOYMENT.md
  • README.md
  • SECURITY_REVIEW.md
  • THREAT_MODEL.md
  • backend/.env.example
  • backend/.gitignore
  • backend/Dockerfile
  • backend/README.md
  • backend/TESTING.md
  • backend/app/api/chat.py
  • backend/app/api/documents.py
  • backend/app/api/metrics.py
  • backend/app/api/system.py
  • backend/app/core/body_limit.py
  • backend/app/core/config.py
  • backend/app/core/morpheus_prompts.py
  • backend/app/core/ollama.py
  • backend/app/core/pinecone_client.py
  • backend/app/core/prompts.py
  • backend/app/core/rate_limit.py
  • backend/app/core/store.py
  • backend/app/main.py
  • backend/app/models/chat.py
  • backend/app/rag/__init__.py
  • backend/app/rag/agentic.py
  • backend/app/rag/citations.py
  • backend/app/rag/hybrid.py
  • backend/app/rag/orchestrator.py
  • backend/app/rag/pipeline.py
  • backend/app/rag/query_analyzer.py
  • backend/app/rag/query_rewriter.py
  • backend/app/rag/reranker.py
  • backend/app/rag/simple.py
  • backend/app/utils/chunking.py
  • backend/app/utils/document_processor.py
  • backend/app/utils/session.py
  • backend/pytest.ini
  • backend/railway.toml
  • backend/render.yaml
  • backend/requirements.txt
  • backend/scripts/loopback-only.sb
  • backend/scripts/prove_local.sh
  • backend/scripts/smoke_local.sh
  • backend/test-documents/DEMO-QUERIES.md
  • backend/tests/README.md
  • backend/tests/conftest.py
  • backend/tests/fakes.py
  • backend/tests/pdf_fixtures.py
  • backend/tests/test_agentic_rag.py
  • backend/tests/test_chat.py
  • backend/tests/test_chunking.py
  • backend/tests/test_citations.py
  • backend/tests/test_config.py
  • backend/tests/test_document_processor.py
  • backend/tests/test_documents.py
  • backend/tests/test_hybrid_rag.py
  • backend/tests/test_main.py
  • backend/tests/test_metrics.py
  • backend/tests/test_no_cloud_imports.py
  • backend/tests/test_no_egress.py
  • backend/tests/test_ollama_client.py
  • backend/tests/test_orchestrator.py
  • backend/tests/test_pipeline.py
  • backend/tests/test_prompts.py
  • backend/tests/test_query_analyzer.py
  • backend/tests/test_rag_simple.py
  • backend/tests/test_store.py
  • backend/tests/test_system.py
  • docker-compose.yml
  • docs/audit/01-phase0-what-is-actually-here.md
  • docs/audit/02-siblings-odysseus-and-isq-agent.md
  • docs/audit/03-migration-plan.md
  • docs/audit/04-honesty-pass.md
  • docs/audit/05-proof-of-locality.md
  • docs/audit/06-second-pass.md
  • docs/audit/README.md
  • frontend/.env.example
  • frontend/.vercelignore
  • frontend/Dockerfile.dev
  • frontend/README.md
  • frontend/docs/REDESIGN_PROGRESS.md
  • frontend/e2e/chat-flow.spec.ts
  • frontend/next.config.js
  • frontend/package.json
  • frontend/scripts/screenshot.mjs
  • frontend/src/app/api/chat/route.ts
  • frontend/src/app/api/test-connection/route.ts
  • frontend/src/app/globals.css
  • frontend/src/app/layout.tsx
  • frontend/src/app/page.tsx
  • frontend/src/components/AppShell/ColdStart.tsx
  • frontend/src/components/Chat/ChatInterface.tsx
  • frontend/src/components/Chat/ChatMessage.tsx
  • frontend/src/components/Chat/Composer.tsx
  • frontend/src/components/Chat/FloatingInsightPanel.tsx
  • frontend/src/components/Chat/QueryInsight.tsx
  • frontend/src/components/Chat/RAGModeIndicator.tsx
  • frontend/src/components/Chat/__tests__/ChatMessage.test.tsx
  • frontend/src/components/Chat/__tests__/MessageList.test.tsx
  • frontend/src/components/Context/CitationHighlight.tsx
  • frontend/src/components/Context/DocumentViewer.tsx
  • frontend/src/components/Context/RetrievalMetrics.tsx
  • frontend/src/components/Docs/DocItem.tsx
  • frontend/src/components/Docs/DocsSidebar.tsx
  • frontend/src/components/Documents/DocumentStats.tsx
  • frontend/src/components/Documents/DocumentUploader.tsx
  • frontend/src/components/Documents/SystemStatus.tsx
  • frontend/src/components/Documents/__tests__/DocumentUploader.test.tsx
  • frontend/src/components/Onboarding/QuickStartGuide.tsx
  • frontend/src/components/Settings/Settings.tsx
  • frontend/src/components/System/SourcesTab.tsx
  • frontend/src/components/System/StatusTab.tsx
  • frontend/src/components/System/SystemPanel.tsx
  • frontend/src/components/System/SystemTab.tsx
  • frontend/src/lib/__tests__/api-client.test.ts
  • frontend/src/lib/api-client.ts
  • frontend/src/lib/flags.ts
  • frontend/src/lib/hooks/useBackendHealth.ts
  • frontend/src/lib/hooks/useChat.ts
  • frontend/src/lib/hooks/useLocalChat.ts
  • frontend/src/lib/hooks/useSession.ts
  • frontend/src/lib/hooks/useSettings.ts
  • frontend/src/lib/types.ts
  • frontend/src/styles/matrix.css
  • frontend/tailwind.config.ts
  • frontend/vercel.json

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ThomasJButler ThomasJButler added the enhancement New feature or request label Aug 27, 2026
@ThomasJButler ThomasJButler added this to the v3 milestone Aug 27, 2026
@ThomasJButler

Copy link
Copy Markdown
Owner Author

merging any way even if backend test failed, as the reason is I have made the project fully local.

Once merged, the new runners will take effect.

Have removed Vercel project, Render backend, Pinecone indexes, and any last drop of the previous front end.

Next PR will be to restore the previous functionality and agentic search. Sneak preview, it can examine full folders full of private and secure documents, not just individual files. The bottleneck was always the free Render and Pinecone deployments, as this had a start up time. Now the project can be running 24/7 locally if you wanted (it'd be pointless right now, but you catch my drift).

Possibilities are now unlocked, even if they aren't very 'cool' or mass appealing possibilities.

A product like this is needed in an age of privacy concerns, and more data than ever to waddle through.

@ThomasJButler
ThomasJButler merged commit 684f74a into main Aug 27, 2026
10 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant