Commit graph

16 commits

Author SHA1 Message Date
cd226689da
docs: one README (root canonical) — the two had cross-drifted (#152)
* docs(readme): reconcile root README as the single source of truth

/README.md (renders on GitHub) and work/README.md (packaged by
work/pyproject.toml's readme = "README.md") had cross-drifted: each
had two of four correct lines. Root had the correct `cd meshai/work`
path and work/-prefixed curl URLs; work/README.md had the correct
gemini-3.1-flash-lite model (google retired the gemini-2.x lite tier
on this project's API key).

Pull the one missing fix (model name) into root/README.md. Verified
via diff that these were the only 4 lines (8 diff lines) that ever
differed between the two files.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* build(work): eliminate work/README.md as a second source of truth

The hand-maintained duplicate is what caused the cross-drift fixed in
the previous commit. Replace work/README.md with a symlink to
../README.md so there is exactly one file to edit.

This required unhooking work/'s packaging from a physical README.md:

- setuptools' pyproject reader hard-rejects readme paths outside the
  project dir (`_assert_local` in setuptools/config/expand.py) — so
  `readme = "../README.md"` is not an option, tested and confirmed.
- The symlink resolves fine for local packaging (pip install -e .,
  python -m build --sdist/--wheel all tested passing, PKG-INFO
  correctly carries the root content through the symlink).
- It does NOT resolve for the Docker image build: work/Dockerfile's
  `COPY README.md .` and both work/docker-compose.yml (context: .)
  and .github/workflows/docker-publish.yml (context: work) pin the
  build context to work/, which does not contain the symlink's
  target. Confirmed with an isolated repro: Docker COPY on a symlink
  whose target is outside the build context fails with "too many
  links". Repointing the build context at the repo root would touch
  every COPY path in the Dockerfile plus CI — out of scope here and
  not worth it for a README.

Chose the minimal fix instead: drop `readme = "README.md"` from
work/pyproject.toml (meshai isn't published to PyPI — no publish
workflow exists, only GHCR image publishing — so there's no
long_description to lose in practice) and drop the now-unnecessary
`COPY README.md .` from work/Dockerfile. Confirmed a dangling
same-named symlink left in the build context, never COPYed, does not
break context transfer.

Tested end-to-end: a full `docker build -f work/Dockerfile work`
against the real Dockerfile succeeded (frontend build, apt deps, pip
install -e ., fastembed model fetch), and the resulting image imports
meshai and reports correct `pip show` metadata with no README
involved.

Note for docs/onboarding-via-gui (PR #147) and
chore/untrack-dashboard-static: both edited work/README.md, the file
GitHub never rendered. That target is gone; their Quick-start content
needs to be re-applied to root README.md when those branches rebase.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Matt Johnson <mj@k7zvx.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 14:15:39 -06:00
18e9ae9127
chore: untrack dashboard build output (stale by 13 commits on the pip path) (#151)
* chore(dashboard): untrack committed frontend build output

work/meshai/dashboard/static/ held committed vite build artifacts
(index.html + hashed assets/*.js|css + copied public/ images) that were
last built 2026-07-07 (PR #87), 13 frontend commits ago. Docker builds
the frontend fresh and overwrites these on every image build, but the
pip install -e . path (documented in README Quick start) ships this
stale directory verbatim via [tool.setuptools.packages.find] include.

The root .gitignore already had a rule for this
("meshai/dashboard/static/") but it silently stopped matching when
2e1fb325 moved the source tree into work/ -- gitignore patterns
containing a "/" are anchored to the .gitignore's own directory, so the
unprefixed pattern only ever matched a repo-root meshai/dashboard/static/
that hasn't existed since that move. Fixed by prefixing with work/,
matching the existing work/data/secrets/.env convention elsewhere in
the file.

Every file under static/ is generated: assets/* and index.html come
from `vite build` (outDir: ../meshai/dashboard/static, emptyOutDir:
true, confirmed in dashboard-frontend/vite.config.ts), and the two
PNGs are vite's copy of dashboard-frontend/public/*.png (byte-identical
to the source). None of it is hand-authored, so the whole directory is
untracked rather than partially.

Blobs remain in git history; files remain on disk, just untracked.

* docs(readme): document the required frontend build for pip installs

work/meshai/dashboard/static/ is no longer committed (previous commit),
so the pip install -e . Quick start path now needs an explicit frontend
build step or the dashboard UI silently doesn't exist. Add it, with a
note clarifying the bot/API still work without it -- only the web UI is
affected. Docker is unaffected (already builds the frontend in its own
stage).

* fix(dashboard): log clearly when the built frontend is missing

Previously, if meshai/dashboard/static/ (or its index.html) was absent,
create_app() silently skipped mounting /assets and registering the
root/catch-all routes -- no log, no error. Any request to "/" would
just 404 with FastAPI's generic "Not Found", giving no clue why.

This was latent before (Docker always builds the frontend, and a git
checkout with the artifacts committed always had the directory), but
now that static/ is untracked, a fresh pip install without the frontend
build step will hit this path as its first real-world trigger. Add a
warning log naming the missing path and the exact build command, and
make clear the bot/API are unaffected -- only the dashboard UI is
absent.

* docs(readme): move frontend-build note to root README

work/README.md is about to become a symlink to root README.md on
docs/single-readme. Retarget the frontend-build documentation added in
56eba0f7 from work/README.md to root README.md so it isn't silently
dropped when that symlink lands.

---------

Co-authored-by: Matt Johnson <mj@k7zvx.com>
2026-07-17 14:14:16 -06:00
3c900091d7
docs: point onboarding at the dashboard; drop 3 phantom keys from the seeded default (#147)
* fix(entrypoint): drop three phantom history keys from the seeded default

The config written on first boot -- what EVERY fresh Docker install starts
from -- seeded three keys that do not exist on HistoryConfig and are
silently discarded on load:

    auto_cleanup: true
    cleanup_interval_hours: 24
    max_age_days: 30

HistoryConfig has only `database`, `max_messages_per_user`, and
`conversation_timeout`.

To be precise about the impact: history cleanup DOES work -- cleanup_expired()
is wired at main.py:237 and _prune_history() honours max_messages_per_user.
What never existed is the time-based retention model these keys describe (a
30-day age cutoff on a 24h interval). An operator setting max_age_days: 90
expecting 90-day retention was silently ignored.

Not implemented here -- whether time-based retention should exist is a
product decision, not a cleanup. This only stops the default config
promising it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: point onboarding at the dashboard, not the legacy example config

The documented setup path was `cp config.example.yaml config.yaml`, but that
file is ~40% incomplete: of the 20 top-level Config fields it covers 15,
omitting coverage (the universal bbox), danger_zones, generic_sources,
meshcore_context, commands, and the current notification model
(toggles/destinations/region_routes). Its own notifications header still says
the schema "will be replaced in v0.3 by the 8-toggle model" -- which shipped
long ago. Anyone following the project's own instructions landed on a
degraded surface with no signal a richer config existed.

It is also read by NOTHING at runtime: docker-entrypoint.sh sets
MESHAI_CONFIG=/data/config.yaml and writes its own inline default on first
boot. The Dockerfile still COPYs config.example.yaml into the image, so it is
kept and now labelled reference-only rather than a starting point.

- README: Docker quick-start seeds itself; configure via the dashboard. The
  pip path still uses config.example.yaml (nothing seeds one there) but now
  carries an honest note that it is a minimal bootstrap, not a reference.
  Adds an Advanced section for the split /data/config/ layout and the
  migrate_config_v03 path into it.
- docker-compose.yml: the comment claimed config lives at /data/config.yaml
  as though that were the only layout; corrected to describe both, and note
  secrets live in /data/secrets/.env.
- Dockerfile: document why config.example.yaml is still shipped.

Not done deliberately: config.example.yaml is NOT expanded to cover all 20
sections. A second hand-maintained schema is what caused this drift; the
dashboard is the authoritative surface. The legacy single-file loader is
untouched and still fully supported.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(readme): move dashboard-first onboarding rewrite to root README

work/README.md is about to become a symlink to root README.md on
docs/single-readme. Retarget the Docker/dashboard-first quick start
and config.example.yaml honesty note added in be867d23 from
work/README.md to root README.md, adapted to the root file's own
Quick start structure (cd meshai/work, /work/-prefixed curl URLs), so
none of it is silently dropped when that symlink lands.

---------

Co-authored-by: Matt Johnson <mj@k7zvx.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 14:07:31 -06:00
4f31abc593
chore: remove duplicate top-level source tree (build only from work/) (#125)
Commit 2e1fb325 ("refactor: move source tree into work/, multi-stage Docker
build") COPIED the source tree into work/ but never removed the top-level
originals, so main has been tracking two full copies of the app ever since.

Only work/ is live:

  - CI (.github/workflows/docker-publish.yml, the sole workflow) builds with
    `context: work` / `file: work/Dockerfile`. It never references the
    top-level meshai/, Dockerfile, tests/, or pyproject.toml.
  - Production (CT 108) runs work/docker-compose.yml, whose build context is
    work/ and whose Dockerfile does `COPY meshai/ ./meshai/` relative to it.
  - work/ is self-contained: its own Dockerfile, docker-compose.yml,
    pyproject.toml, requirements.txt, config.example.yaml, dashboard-frontend/
    and tests/.

The top-level copy carried ZERO unique content. work/ is strictly newer
everywhere (migrations v19-v28 vs top-level's v18; whole subsystems the top
level never had: coverage, generic_http, satpass, wzdx, notifications/gating,
notifications/formatters, transport/). Every file that existed ONLY at the top
level is legacy code that work/ deliberately removed after the fork:

  - meshai/cli/configurator.py            removed from work/ in 5de683f7 (#45, legacy TUI configurator)
  - meshai/commands/subscribe.py          removed from work/ in 9e6a3715 / 04604624 (subscription backend)
  - meshai/subscriptions.py               removed from work/ in 9e6a3715 / 04604624 (subscription backend)
  - meshai/notifications/scheduled/fire_digest.py
                                          removed from work/ in b0b0697b (#107, fire digest feature)
  - meshai/notifications/pipeline/severity_router.py
                                          never existed in work/; superseded by notifications/gating + formatters
  - tests/test_fire_digest_recency.py     tests the removed fire digest
  - tests/test_meshcore_per_family_routing.py
                                          tests the top-level-only meshcore_channel impl, superseded in work/ by transport/
  - dashboard-frontend/src/pages/Alerts.tsx
                                          removed from work/ in 9e6a3715 (subscription backend)
  - dashboard-frontend/src/pages/Environment.tsx.bak
                                          stray backup file, never in any build

The duplication is an ACTIVE HAZARD, not just dead weight: a fix applied to the
top-level meshai/ passes review, gets merged, and then silently does nothing,
because neither CI nor prod ever reads that tree. This already happened --
ff3ded8c (#9, "independent per-family MeshCore channel") landed its config.py /
connector.py / channels.py / dispatcher.py changes in the DEAD top-level copy
while work/ got only the transport-layer half. (Nothing was lost there: work/
carries a full, later-generation implementation of the same feature wired
through config.py, connector.py, transport/base.py, transport/composite_transport.py,
transport/meshcore_transport.py and the dashboard routes.) Deleting the copy
makes that class of mistake impossible.

Removed (280 files): meshai/, tests/, dashboard-frontend/, config/, Dockerfile,
docker-compose.yml, docker-entrypoint.sh, config.example.yaml, pyproject.toml,
requirements.txt.

Also fixes README Quick start, which pointed at the now-deleted root paths
(main/docker-compose.yml, main/config.example.yaml -> main/work/...) and still
advertised `meshai --config`, the interactive TUI removed from work/ in 5de683f7.

Verification: work/ test suite unchanged before and after --
20 failed, 2240 passed, 72 skipped (identical failure list; all pre-existing).

Co-authored-by: Matt Johnson <mj@k7zvx.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 10:37:40 -06:00
d117a3ea72
docs: update Central caveat — boot no longer requires Central (graceful + retry) (#27)
Co-authored-by: Matt Johnson <mj@k7zvx.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 01:15:45 -06:00
09c6425caf
docs: document meshai <-> Central (NATS firehose) + native/central feed_source (#25)
Add a "Native adapters vs. Central" subsection: each hazard feed chooses its
data path with feed_source (native = direct public-API fetch, the default and
original path; central = subscribe to Central's pre-aggregated NATS JetStream
firehose). Documents the environmental.central config, mutual exclusivity,
the satpass (central-only) / ducting (native-only) exceptions, runtime
auto-reconnect behavior, and the startup-needs-Central caveat.

Co-authored-by: Matt Johnson <mj@k7zvx.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 00:56:27 -06:00
fbb4fa0e94
docs: refresh README for dual-mesh (Meshtastic + MeshCore) + dashboard (#24)
Rewrite the README to reflect the current project: dual-transport
(Meshtastic base + MeshCore auto-on via meshcore_host), the web dashboard
(with live screenshots), per-mesh routing, the conversational bot with
per-mesh scoped context + three privacy lanes, environmental/hazard
broadcasts, mesh-health scoring, and the RAG knowledge base. Removes the
retired subscription backend/commands, updates the LLM model + architecture,
and adds live dashboard screenshots under docs/images/.

For transparency, documents that the project was vibecoded (built with LLM
coding assistants).

Co-authored-by: Matt Johnson <mj@k7zvx.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 00:47:11 -06:00
9eb40b597c docs: comprehensive README with full setup guide
- Installation (Docker, manual, LXC)
- Configuration guide for all settings
- Environmental feeds setup with API key links
- Command reference
- API reference
- Architecture overview
- Deployment notes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-12 21:02:17 -06:00
MeshAI Claude
1d97854319 docs: Update README — Qdrant/RECON knowledge backend, alert engine, architecture 2026-05-06 16:29:03 +00:00
MeshAI Claude
d5fc69e9a0 docs: Complete README rewrite — mesh intelligence, data sources, updated architecture 2026-05-06 01:28:59 +00:00
root
584d1b199d docs: Update advBBS link to zvx-echo6/advbbs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-04 14:29:43 +00:00
root
0e36869a5f feat: Hybrid RAG knowledge base, sentence-aware chunking, MeshMonitor HTTP sync
Knowledge Base:
- Hybrid FTS5 + vector search using sqlite-vec and bge-small-en-v1.5
- Reciprocal Rank Fusion for result merging
- Domain-aware query construction handles typos
- Configurable weights for keyword vs semantic matching

Message Chunking:
- Sentence-aware splitting respects message boundaries
- Continuation prompts for long responses
- Natural follow-up detection (yes, ok, continue, more, etc.)
- Per-user continuation state management

MeshMonitor Integration:
- HTTP API trigger sync (replaces file-based triggers.json)
- Dynamic refresh interval
- Trigger injection into LLM prompt

Other:
- Updated system prompt for better response length control
- Simplified responder to handle message lists
- Updated README with new features and architecture diagram
- Cleaned up config.example.yaml

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-04 07:44:12 +00:00
root
e65a558c6f docs: Add MeshMonitor integration section and credit to README
- Add MeshMonitor Integration section with features and configuration
- Add credit line in Features list
- Link to github.com/Yeraze/meshmonitor

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-03 07:10:21 +00:00
Ubuntu
8c2c4d2aef Add GHCR publishing workflow and update docker-compose for registry pull
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:39:23 +00:00
Ubuntu
05a8f8659d Document advBBS compatibility in README
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:29:59 +00:00
fd3f995ebb Initial commit: MeshAI - LLM-powered Meshtastic assistant
Features:
- Multi-backend LLM support (OpenAI, Anthropic, Google)
- Rolling summary memory for token optimization (~70-80% reduction)
- Per-user conversation history with SQLite persistence
- Bang commands (!help, !ping, !reset, !status, !weather)
- Meshtastic integration via serial or TCP
- Message chunking for mesh network constraints (150 char limit)
- Rate limiting to prevent network congestion
- Rich TUI configurator
- Docker support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 11:53:46 -07:00