Commit Graph
139 Commits
Author SHA1 Message Date
7ba334b5f0 fix(gui): inject bearer token into streaming chat/research routes (#499)
Ensures that the desktop GUI correctly sends the Authorization header
when an API key is configured. This resolves the 'Failed to get response'
bug on Windows systems with enabled authentication.

Ref: #266

Co-authored-by: sanjayravit <sanjay@example.com>
2026-06-14 17:32:43 -07:00
8eaeb3a754 fix(windows): desktop backend spawn + model-aware engine selection (#533)
* fix(windows): desktop backend spawn (#531) + model-aware engine selection (#532)

Two runtime bugs found during end-to-end testing on a clean Windows 11
24H2 Azure VM.

#531 - Desktop "Failed to get response": run_jarvis_command spawned the
backend with .output(), which waits for the process to exit. `jarvis
serve` never exits, so the Tauri command hung forever (the Start button
never resolved); and it ran `uv run jarvis` with no cwd, so in a packaged
install -- where the cwd isn't the checkout -- `jarvis` wasn't found and
the server never started. Now: run from find_project_root(), and for
`serve` spawn detached (.spawn()), drain stderr, and poll /health for
readiness (mirrors start_backend); short commands keep .output().

The server layer itself was verified healthy on Windows (/health and
/v1/chat/completions both 200, localhost included) -- the fault was the
Tauri spawn path.

#532 - "OpenAI client not available" after reboot: when the local engine
is down, get_engine's fallback selected CloudEngine because health() is
True if ANY provider client exists -- without checking the resolved
model's provider has a client. A user with e.g. OPENROUTER_API_KEY and a
gpt-* model then hit the OpenAI path with no client. Add
CloudEngine.can_serve(model) (checks the specific provider client via the
same routing generate()/stream() use) + a default can_serve->True on the
base engine, and make get_engine model-aware so it skips an engine that
can't serve the model -- the user falls through to the helpful "no engine
available / start ollama" message instead.

Tests: engine discovery/cloud/model-matrix + cli serve/ask suites pass
(the one ask_e2e failure is a pre-existing version-banner flake, fails
identically on main). The Tauri crate couldn't be compiled locally (no
GTK/webkit sys-libs in this env); relies on CI.

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

* test(engine): cover model-aware engine selection + CloudEngine.can_serve (#532)

#533 added a `model` arg to get_engine and a can_serve() gate but shipped no
tests. Add them:
- get_engine skips a healthy engine that can't serve the requested model
  (the cloud-fallback-for-unservable-model case behind #532),
- model=None preserves the legacy model-agnostic selection,
- CloudEngine.can_serve gates on the per-provider client (gpt->OpenAI,
  claude->Anthropic, ...), verified empirically.

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

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Jon Saad-Falcon <jonsaadfalcon@gmail.com>
2026-06-10 19:52:36 -07:00
bc9fa6b3c8 fix(memory): surface clear error when openjarvis_rust missing instead of silent no-op (#527)
Memory tools degraded silently and misleadingly when the mandatory
`openjarvis_rust` extension was absent from the *serving* venv:

- `POST /v1/memory/store` returned HTTP 200 `{"status":"stored","note":
  "no backend available"}` and stored nothing (silent data loss).
- `POST /v1/memory/index` returned a generic "No memory backend available",
  and the desktop frontend discarded the server `detail` and threw a blanket
  "Failed to index path", blaming the path instead of the real cause.
- `GET /v1/memory/config` reported `backend_type: sqlite` even though no
  backend could be constructed.

Root cause: `SQLiteMemory.__init__` calls `get_rust_module()` (which raises
ImportError by design — the Rust ext is mandatory, no Python fallback), and
`_get_memory_backend` swallowed that ImportError and returned `None`,
conflating "native extension missing" (a hard install error) with "memory
intentionally disabled" (benign). A chunking floor also silently dropped whole
short documents, and the installer never verified the extension imported from
the serving venv before writing its success marker.

Fix (no fake Python fallback — the Rust ext stays mandatory by design):

- Add `MemoryBackendUnavailable` + `RUST_MISSING_HINT` in tools/storage/_stubs.
  `SQLiteMemory.__init__` translates the bridge ImportError into this clear,
  actionable error ("run `uv run maturin develop ...`").
- `_get_memory_backend` distinguishes the two cases: a missing native ext
  raises HTTP 503 with the actionable hint; a benign unconfigured backend
  still returns `None` (graceful path preserved for search/stats).
- `/store` now returns 503 instead of a 200 silent no-op.
- `/config` reports `available: false` + `detail` instead of falsely claiming
  a healthy `backend_type`.
- `/index` adds a `note` when `chunks_indexed == 0` so "indexed" never
  silently means "stored nothing".
- chunk_text no longer drops an entire short document below `min_chunk_size`
  (the floor only discards tiny *trailing* fragments now).
- Frontend `storeMemory`/`indexMemoryPath` surface the server `detail` instead
  of blanket strings; `MemoryConfig` gains optional `available`/`detail`.
  (Left the pre-existing `backend` vs `backend_type` mismatch untouched.)
- build-extension.sh verifies `import openjarvis_rust` succeeds in the serving
  venv before writing the `extension-built` marker.

Regression tests: tests/server/test_api_routes.py::TestMemoryRustMissing mocks
`get_rust_module` to raise ImportError and asserts /store (503, not 200 no-op),
/index (actionable detail, not "Failed to index path"), and /config
(available:false) all surface the clear error; tests/memory/test_chunking.py
asserts short-only docs are kept while tiny trailing fragments are still
filtered.

Fixes #502

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 13:25:10 -07:00
f72abadf68 fix(desktop): AppImage env-strip + attach to existing healthy server (#496)
Closes #455. @wishwanto on Linux Mint hit two distinct bugs in the desktop launcher that ship together because they share the same boot_backend code path.

Bug A — AppImage hang on "starting server":
When the desktop is shipped as an AppImage on Linux, the AppImage runtime sets LD_LIBRARY_PATH to its temp-extracted lib dir. Children we spawn (uv, ollama) inherit that env, then Python's numpy/cryptography extensions dlopen the AppImage's mismatched libstdc++/libssl versions and python dies silently. Stderr drainer sees immediate EOF → GUI hangs forever.

Fix: new helper prepare_subprocess_for_appimage strips LD_LIBRARY_PATH, LD_PRELOAD, APPIMAGE, APPIMAGE_UUID, APPDIR, ARGV0 when $APPIMAGE is set. Linux-only via #[cfg(target_os = "linux")] — true no-op on macOS/Windows. Called at all 3 spawn sites: ollama sidecar, uv sync, uv run jarvis serve.

Bug B — Desktop force-kills the user's already-running `jarvis serve`:
Old code (post #437) ran fuser -k 8000/tcp / taskkill /PID /F on ANY HTTP response from :8000/health — including 200 OK from a healthy user-launched serve.

Fix: replace the indiscriminate kill with a health-aware decision tree:
  * 2xx /health → confirm with a 500ms-apart second probe, then attach (set server/model/ollama ready, return without spawning)
  * 503 → user-facing error "wait for engine or stop it"
  * other 4xx/5xx → user-facing error with lsof -i :8000 (unix) / netstat (windows) hint
  * Err → fall through to normal spawn (unchanged)

Adversarial review caught and fixed 5 real issues pre-commit:
  - HIGH: parallel cargo-test env mutation race → APPIMAGE_ENV_LOCK Mutex
  - HIGH: 2xx attach left model_ready/ollama_ready false → set both true before return
  - MEDIUM: #[allow(unused_variables)] suppressed lint on Linux too → cfg_attr
  - MEDIUM: single-probe attach trusted a 2s snapshot → confirmatory second probe
  - MEDIUM: /bin/true would silently mislead on Windows → HARMLESS_BIN const per platform

2 new unit tests; CI green on all gates including rust.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 19:54:06 -07:00
4b4fd587b2 fix(frontend): send local API key as Bearer on /v1 + /api requests (#471)
When `jarvis serve` runs with an API key configured, AuthMiddleware 401s
every /v1 and /api request that lacks a Bearer token. The frontend never
sent one, so telemetry, managed-agents, savings, etc. all failed (#266).

- Add getApiKey() (reads settings.apiKey, with optional
  VITE_OPENJARVIS_API_KEY build-time override) and authHeaders() to
  api.ts, plus an apiFetch() wrapper that prepends getBase() and injects
  the Bearer header on every local-server call. Route all /v1 + /api
  fetches through it so none can omit auth.
- Add `apiKey` to the Settings model (store.ts) and a password field in
  Settings → Connection so users can enter it.

Keyless local servers are unaffected: with no key, no Authorization
header is sent (byte-for-byte unchanged). The Supabase savings path keeps
its own anon key — not conflated with the local key.

Bootstraps vitest (no prior frontend test runner) + a `test` script, and
adds api.auth.test.ts covering getApiKey/authHeaders. Verified: tsc
--noEmit clean, vitest 6/6, vite build succeeds.

Deferred (not in scope): WebSocket auth (browsers can't set WS headers)
and Tauri auto-injecting a generated key.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 13:25:14 -07:00
Jon Saad-FalconandGitHub 21f1becb4d feat(desktop): single default model + custom OpenAI-compatible endpoints (#453) 2026-05-30 19:34:51 -07:00
Jon Saad-FalconandGitHub d9af1eca45 fix(desktop): stop auto-pulling the entire Qwen3.5 model ladder (#446) 2026-05-30 19:31:22 -07:00
b6a8280d68 fix(desktop): detect early child exit + drain stderr to avoid pipe stall (#437)
Closes #309.

Three root-cause fixes in `frontend/src-tauri/src/lib.rs`:

1. **Background stderr drainer.** `jarvis serve` was spawned with `stderr(Stdio::piped())` but its 4 KB Windows pipe buffer would fill from the startup log volume before the child could bind its HTTP port — hanging the process mid-startup. Now a tokio task drains stderr from the moment of spawn into a rolling 16 KB tail buffer; the pipe never fills.
2. **`try_wait()` early-exit detection.** The old `wait_for_url` was blind to child crashes — uv-not-on-PATH or extension-import failures would silently waste the full 10-minute timeout. The new `wait_for_jarvis_health` checks the child's exit status each iteration and surfaces the stderr tail with the exit code.
3. **HTTP 503 distinguished from connection-refused.** A 503 means the server bound but the inference engine failed to load (terminal); we now surface the body text immediately rather than polling for 10 minutes.

Adversarially reviewed before commit — caught and fixed a stderr-pipe back-pressure regression on the Ready path before push.

Huge thanks to @xoomarx for the careful #309 repro — without that exact symptom signature ("stuck on Starting api server" on Windows) the pipe-buffer deadlock would have been very hard to identify from the user-visible behavior alone.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 16:36:49 -07:00
Andrew ParkandGitHub 48dcb40be4 fix(desktop): surface backend error frames in Deep Research stream (#428) 2026-05-29 09:48:59 -07:00
Robby ManihaniandGitHub 26285e56fa fix(agents): wire continuous-agent Interact tab end-to-end + CLI workflow polish (#425) 2026-05-28 12:07:03 -07:00
Andrew ParkandGitHub c6448f7cf2 fix(desktop): preselect model in onboarding so first chat doesn't 400 (#427) 2026-05-28 11:19:52 -07:00
Tanvir BhathalandGitHub 0702f2793c (bug): telemetry fixes (#421) 2026-05-27 09:36:26 -07:00
krypticmouseandClaude Opus 4.7 658effb964 refactor(desktop): extract testable uv-sync error helpers + unit tests (#331)
The uv-sync failure handling added in #398 was inline in the async
`boot_backend` GUI path, so its logic — exit-code rendering and the
stderr "tail" extraction — could only be verified by running the
desktop app. This extracts the pure logic into three free functions
and adds unit tests, so the message formatting is now covered by
`cargo test` with no GUI / webview runtime needed.

Extracted:
- `uv_sync_stderr_tail(stderr, max_chars)` — last N chars of stderr,
  trimmed, on char boundaries. The original inline version used
  `.rev().take(N).collect().chars().rev().collect()`; the new version
  is `skip(count - N)` which is clearer and equally UTF-8-safe (matters
  because Windows consoles emit non-ASCII cp9xx bytes — a byte slice
  could split a codepoint).
- `format_uv_sync_failure(root, exit_code, stderr)` — the non-zero-exit
  message. Now renders a missing exit code (signal-terminated process)
  as "unknown" instead of a misleading "-1".
- `format_uv_sync_spawn_error(root, uv_bin, err)` — the can't-spawn
  message.

`boot_backend` now calls these instead of formatting inline.

Tests (7, in `#[cfg(test)] mod tests`):
- tail returns whole string when shorter than the limit
- tail keeps the END (the actionable line), not the spinner-noise start
- tail trims surrounding whitespace
- tail never splits a multi-byte codepoint (500×"é", limit 100 → exactly
  100 chars, all "é")
- failure message includes exit code + stderr tail + the actionable
  "run uv sync manually" hint
- missing exit code renders as "exit unknown", never "exit -1"
- spawn-error names the uv binary path and repo root

Verified the logic standalone via `rustc --test` (7/7 pass). In CI they
run via `cargo test` in desktop.yml's `validate` job, which already
builds the Tauri crate with the webkit deps and runs on every PR that
touches `frontend/**` — so this changes the existing `cargo check` step
to `cargo test` (a superset: same build coverage, plus the tests).

This doesn't verify the GUI *behavior* (that still needs a human running
the app, or the windows-latest empirical path) — but the error-message
logic that was previously untestable now has automated coverage.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 15:26:07 +00:00
krypticmouseandClaude Opus 4.7 612d3e1f88 fix(install): make Windows install path discoverable + bail early on Git Bash
Addresses the second half of the Discord support thread on the
"Jarvis server did not become healthy in time" issue (PR #398 fixed
the diagnostic gap; this fixes discoverability of the right install
path so users don't end up there in the first place).

Three changes, all surface improvements:

1. **`README.md`** — explicit Windows section in the Installation
   block. Previously, the only Windows mention was a footnote
   ("Platforms: ... WSL2 on Windows") that came AFTER the `curl … |
   bash` install command. Users on PowerShell would copy/paste the
   command, get a syntax error, then try to debug bash on Windows.
   Now the README clearly says: bash installer is macOS/Linux only;
   Windows users have two paths (WSL2 with one-time `wsl --install`
   setup, or the desktop .exe from Releases). Both link to the
   relevant docs.

2. **`scripts/install/install.sh`** — early bail when running under
   Git Bash / MSYS2 / Cygwin (MINGW*, MSYS*, CYGWIN* per `uname -s`).
   These environments aren't WSL — `uv` and `git` will install to
   Windows-side paths that OpenJarvis can't reach, Ollama integration
   silently breaks, and the user gets to debug it 3 minutes into a
   doomed install. The bail message points at both the WSL2 setup
   command (`wsl --install -d Ubuntu-24.04`) and the desktop .exe
   download as alternatives.

   Verified the case-match doesn't fire on Linux (`uname -s` →
   `Linux`, matches the wildcard fall-through, not the MINGW patterns).

3. **`frontend/src-tauri/src/lib.rs`** — when `resolve_bin("uv")`
   can't find uv, the per-OS error message now contains the exact
   install command for the user's OS, ready to copy/paste. On Windows
   that's the `irm https://astral.sh/uv/install.ps1 | iex` command
   Marc kept reposting on the Discord support thread (5/12-5/14).
   On macOS/Linux it's the standard `curl | sh` installer.

   The previous generic "Install it from https://astral.sh/uv" left
   users guessing whether to use winget, scoop, pip, or the official
   installer — which is exactly the confusion the Discord thread
   captured.

None of these are root-cause code fixes (Discord users' uv installs
fail for environment-specific reasons we can't diagnose remotely),
but together they remove the three biggest friction sources we saw:
copy-paste install command that can't possibly work, doomed git-bash
installs that fail mysteriously, and missing exact install commands
when uv isn't found.

The Tauri change ships in the desktop binary; the README change is
visible immediately on the repo page; the install.sh change reaches
users via openjarvis.ai (when it's restored) and via the GitHub-raw
fallback from PR #398.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 15:48:13 +00:00
krypticmouseandClaude Opus 4.7 158fc83feb fix(desktop): surface uv sync errors so users aren't stuck waiting for health check
Addresses #331 (multiple Windows users hit "Jarvis server did not
become healthy in time" with no actionable detail).

The boot sequence ran `uv sync` with **both** stdout AND stderr piped
to `/dev/null` and discarded the exit code (`let _ = …`). When
`uv sync` failed for any reason — Windows PATH/permission issues,
network problems, lockfile conflicts, stale `.venv/` — the user saw
nothing useful. The boot proceeded to `uv run jarvis serve` in an
under-provisioned venv, then waited the full 600-second health-check
window before showing a generic "did not start" message with no
hint of what actually went wrong.

Fix: capture stderr, check the exit status, and surface a useful
error to the user **before** the long server-start wait, including:
- The exit code
- The last ~800 chars of `uv sync` stderr (where the diagnostic
  message usually lives)
- A concrete next step (open a terminal and run `uv sync --extra server`
  manually for full output)

Also updated the status detail message to "Installing dependencies
(uv sync — may take 1-2 min on first boot)..." so users on slow
connections don't restart the app thinking it's stuck.

Discord support thread (5/12-5/14) shows the same pattern across
multiple Windows users (@ItsVoyage, @Mystic_irl, @doevud, @Sainthood):
all stuck on "Starting api server" / "did not become healthy in time"
for 4+ minutes, with the actual root cause turning out to be a uv
installation issue that the discarded stderr would have surfaced
immediately. The community workaround (uninstall, install Feb
pre-release, run a magic PowerShell `irm` command for uv) is the
right diagnosis applied without diagnostic output — this commit
makes that diagnostic output visible.

Note: this fix lands in the desktop binary's source (`frontend/src-tauri/src/lib.rs`).
Users running the v1.0.1 desktop binary won't see the improved
error message until the desktop release is re-cut from this branch.
Until then, the workaround documented in this PR's `openjarvis.ai`
fallback section (curl the install.sh from GitHub raw) gets new
users past the install step.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 15:31:17 +00:00
Tanvir BhathalandGitHub c84f1fddee feat: proactive agent approval bell with approve/deny UI (#370) 2026-05-22 17:38:48 -07:00
Robby ManihaniandGitHub 855ed51780 feat: Deep Research Slack integration (#365) 2026-05-20 12:02:05 -07:00
Tanvir BhathalandGitHub a58d6b6c48 Auto Update (#358) 2026-05-19 11:57:10 -07:00
Jon Saad-FalconandGitHub fea8d3e872 release: v1.0.1 (#357) 2026-05-18 20:19:37 -07:00
Robby ManihaniandGitHub 9af0dfe336 feat: Deep Research — personal deep research over Gmail with hybrid retrieval and agentic synthesis (#354) 2026-05-18 17:46:12 -07:00
Tanvir BhathalandGitHub 7081be7bd3 [FEAT] Telemetry (#351) 2026-05-17 13:07:05 -07:00
Andrew ParkandGitHub 64d0f7ab02 feat(frontend): cleaner UI pass — consistent layout, tokens, skeleton loading (#258) 2026-04-17 12:33:29 -07:00
Andrew ParkandGitHub 28e913f706 fix(agents): bind built-in tools, live tool-call UI, Markdown streaming (#255) 2026-04-17 11:01:50 -07:00
Andrew ParkandGitHub 48c23d87df perf: replace agents polling with WebSocket, fix workbox prod mode (#254) 2026-04-17 11:00:50 -07:00
f339c1c2d6 feat: memory UI, settings, and API fixes (#247)
* refactor: merge desktop/ into frontend/, eliminate duplicate Tauri scaffolding

The project had two overlapping directories: desktop/ (Tauri Rust backend +
stale React components) and frontend/ (real React app + dead Tauri stub).
This consolidates everything under frontend/:

- Move desktop/src-tauri/ → frontend/src-tauri/ (the real 1,720-line Rust
  backend with Ollama sidecar, backend lifecycle, cloud keys, overlay, etc.)
- Preserve 9 old desktop React components in frontend/src/components/Desktop/
  (excluded from TS build — APIs have drifted, kept for future integration)
- Delete the old frontend/src-tauri/ stub (246 lines, never compiled)
- Delete desktop/ entirely
- Fix tauri.conf.json frontendDist path (../../frontend/dist → ../dist)
- Update CI workflow, bump script, .gitignore, and docs paths
- Rename setup/ → Setup/ for consistent PascalCase component directories

* feat: add memory UI, settings, and fix memory API routes

- Add Memory tab to Data Sources page with stats, search, index path,
  and manual store functionality
- Add Memory section to Settings page with backend picker, context
  injection toggle, and parameter sliders (top_k, min_score, max_tokens)
- Add memory API functions to frontend (getMemoryStats, searchMemory,
  storeMemory, indexMemoryPath, getMemoryConfig)
- Fix backend /v1/memory/* routes to use app-level memory backend
  instead of creating fresh SQLiteMemory instances per request
- Add GET /v1/memory/config and POST /v1/memory/index endpoints
- Gracefully handle missing Rust backend (return defaults instead of 500)
- Fix nested scroll in Agents Interact tab (use viewport-relative height)

* fix: memory API routes, dialog plugin, and UI polish

- Fix memory API: use backend.retrieve() not .search(), .count() not
  .stats() to match actual SQLiteMemory interface
- Handle None backend gracefully in index endpoint (503 instead of crash)
- Expand ~ in index path (expanduser + resolve)
- Install @tauri-apps/plugin-dialog for native folder picker in Tauri
- Browse button only shows in Tauri (browser can't get absolute paths)
- Redesign Memory tab: proper cards, color-coded search scores, two-column
  layout for index/store, loading spinners, accent gradient on stats card

---------

Co-authored-by: Jon Saad-Falcon <41205309+jonsaadfalcon@users.noreply.github.com>
2026-04-14 09:53:14 -07:00
Andrew ParkandGitHub 54d79ef235 feat: add Apple Contacts connector (macOS AddressBook) (#248)
* feat: add Apple Contacts connector (macOS AddressBook)

Reads directly from ~/Library/Application Support/AddressBook/AddressBook-v22.abcddb
in read-only mode. Extracts names, phone numbers, emails, postal addresses, URLs,
social profiles, and notes for each contact. Requires Full Disk Access like
iMessage and Apple Notes connectors.

- New connector: src/openjarvis/connectors/apple_contacts.py
- Registered in connectors/__init__.py
- Added frontend catalog entry (PIM category) and icon mapping
- MCP tools: contacts_search, contacts_get_contact

* test: add comprehensive tests for Apple Contacts connector

15 tests covering: is_connected (exists/missing), sync yields all real
contacts (skips system rows), extracts all field types (phone, email,
address, URL, social, notes), cleans Apple label markup, org-only
contacts, minimal contacts, since filter, sync_status tracking,
structured metadata, disconnect, mcp_tools, registry, empty DB,
missing DB. Uses fake SQLite database — no real Contacts DB needed.

* fix: scan iCloud/Exchange source databases for all contacts

The main AddressBook database only contains locally-created contacts.
Synced contacts (iCloud, Exchange, etc.) live under
Sources/<UUID>/AddressBook-v22.abcddb. Now scans all source databases
and deduplicates by ZUNIQUEID across sources.

Adds tests for multi-source scanning and cross-source deduplication.
2026-04-14 09:49:08 -07:00
Andrew ParkandGitHub 55662fc426 refactor: merge desktop/ into frontend/, eliminate duplicate Tauri scaffolding (#246)
The project had two overlapping directories: desktop/ (Tauri Rust backend +
stale React components) and frontend/ (real React app + dead Tauri stub).
This consolidates everything under frontend/:

- Move desktop/src-tauri/ → frontend/src-tauri/ (the real 1,720-line Rust
  backend with Ollama sidecar, backend lifecycle, cloud keys, overlay, etc.)
- Preserve 9 old desktop React components in frontend/src/components/Desktop/
  (excluded from TS build — APIs have drifted, kept for future integration)
- Delete the old frontend/src-tauri/ stub (246 lines, never compiled)
- Delete desktop/ entirely
- Fix tauri.conf.json frontendDist path (../../frontend/dist → ../dist)
- Update CI workflow, bump script, .gitignore, and docs paths
- Rename setup/ → Setup/ for consistent PascalCase component directories
2026-04-14 09:48:12 -07:00
Tanvir BhathalandGitHub 9c15b25f90 [FEAT] New Interaction Interface UI (#237) 2026-04-13 14:23:15 -07:00
Jon Saad-FalconandGitHub a009646071 feat: Morning Digest with Voice Mode + unified OAuth + Apple connectors (#174) 2026-04-03 11:05:41 -07:00
mrTSB 2feaa10d97 fix local 2026-04-01 22:13:00 -07:00
3ea727fc43 fix: match template instruction keys to server template IDs (underscores)
Server returns template IDs with underscores (code_reviewer, research_monitor)
but TEMPLATE_INSTRUCTIONS used hyphens. Added both formats + prompts for
personal_deep_research and inbox_triager templates.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 21:24:36 -07:00
608ed7531c feat: add Models, API Keys, and Web Search sections to Settings
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 21:24:36 -07:00
370be96565 feat: add document import via paste text or file upload
Adds a new Upload / Paste data source that lets users paste text or upload
documents (.txt, .md, .pdf, .docx, .csv) directly into the knowledge base.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 21:24:36 -07:00
1100057b90 fix: improve Gmail connect instructions and add troubleshooting
Clarify that Gmail uses App Passwords (not OAuth login popup), emphasize
2-Step Verification prerequisite, and add a collapsible troubleshooting
section for common issues. Also improve the error message when Gmail
auth fails to specifically mention App Password requirements.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 21:24:36 -07:00
beb5c0fb6c feat: reorder agent tabs (Interact first), add strategy tooltips
Move the Interact tab to the first position in agent detail view and
default to it when opening an agent. Add "(optional)" hint to Advanced
Settings and add (?) tooltips to Memory Extraction, Observation
Compression, Retrieval Strategy, and Task Decomposition labels.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 21:24:36 -07:00
aaab50ffcf feat: add pre-filled instruction prompts to agent templates
Add TEMPLATE_INSTRUCTIONS map with sensible defaults for daily-briefing,
research-monitor, code-reviewer, and meeting-prep templates so users get
a starting prompt when selecting a template. Show a warning hint when the
instruction contains [bracketed placeholders] that need to be replaced.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 21:24:36 -07:00
5c1990b7ae feat: add daily/weekly/hourly schedule presets for agents
Replace the manual/interval/cron schedule picker with friendlier presets
(Daily, Weekly, Every N hours, Custom cron) that generate the correct
cron expressions or interval values behind the scenes. Update
formatSchedule() to render human-readable labels like "Daily at 9:00 AM"
and "Weekly on Mon, Wed, Fri at 9:00 AM".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 21:24:36 -07:00
579ff50256 feat: add chat/edit/delete buttons and model status to agent cards
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 21:24:36 -07:00
dc2a2edbcd fix: data source connect flow UX, obsidian/gcalendar sync bugs, agent timeout
- Frontend: add progress stages (Connecting → Authenticating → Connected →
  Syncing) with spinner and progress bar to the data source connect flow.
  Previously sources would silently stay "Not connected" after setup.
  Show error message on failure instead of swallowing exceptions.

- Obsidian connector: use timezone-aware datetime (tz=timezone.utc) in
  fromtimestamp() to fix "can't compare offset-naive and offset-aware
  datetimes" crash during incremental sync.

- Google Calendar connector: catch HTTPStatusError when listing events
  for individual calendars (e.g. US Holidays returning 404) so one
  inaccessible calendar doesn't crash the entire sync.

- Agent SSE timeout: increase progress queue timeout from 120s to 600s
  so complex multi-hop deep research queries aren't killed mid-execution
  on slower local models.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 21:24:36 -07:00
mrTSB 59dcbb9cc4 make cloud models on desktop app work 2026-04-01 21:22:39 -07:00
mrTSB f8c37fe85e make cloud models on desktop app work 2026-04-01 21:22:25 -07:00
Jon Saad-FalconandClaude Opus 4.6 a57813fcfa feat: overhaul install + setup UX for data sources, messaging, and desktop app
- Skip SetupWizard on launch, go straight to Chat page
- Add Data Sources page with sidebar nav (separate tabs for data sources + messaging channels)
- Add "Connect your data" banner + quick-action buttons on Chat empty state
- Add hint on deep research agent pointing to Data Sources + Messaging tabs
- Consistent naming: "Data Sources" and "Messaging Channels" everywhere
- Fix Apple Notes / iMessage setup (remove broken system prefs link)
- Fix Slack data source: auto-join public channels, rate limit retry, is_member filter
- Add channels:join scope to all Slack manifests + docs
- Fix Gmail: use gmail_imap connector (IMAP + app password), increase limit to 5000
- Fix sync endpoint: run in background thread, return immediately
- Show sync progress with progress bar, error messages, Sync Now / Re-sync / Retry buttons
- Add triggerSync() API + SyncStatusDisplay component
- Rewrite all connector setup instructions with precise click-by-click steps
- Notion: share all pages at once via top-level page sharing
- Obsidian: show how to find vault path via Obsidian UI or Finder
- SendBlue: add link to API Credentials page, add ngrok webhook step
- Slack messaging: add Copy button for JSON manifest
- Add OpenJarvis Slack icon asset
- Shorten deep research template description
- Fix desktop app port (8222 → 8000 to match server default)
- Disable auto-updater for local dev builds
- Register Slack, Outlook, GCalendar connectors in __init__.py
- Auto-create default agent when setting up messaging channels

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 22:44:59 -07:00
ANarayanandClaude Opus 4.6 bbcda62ed4 fix: add Node >= 20 engine requirement to frontend package.json
Tailwind CSS v4.2 (@tailwindcss/oxide) requires Node >= 20 for native
bindings. Without this, `npm install` succeeds but `vite` fails at
runtime with a missing native binding error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 18:51:37 -07:00
Jon Saad-FalconandClaude Opus 4.6 bc31cce732 feat: simplify Messaging tab to iMessage/SMS (SendBlue) + Slack only
Removed WhatsApp (Baileys blocked by WhatsApp servers) and Twilio SMS
(SendBlue handles SMS as fallback automatically). Updated Slack setup
instructions with the App Manifest JSON for one-step configuration.

Three channels: iMessage + SMS (SendBlue), Slack (Socket Mode)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 17:17:51 -07:00
Jon Saad-FalconandClaude Opus 4.6 9825daa334 feat: complete SendBlue integration — auto-restore, CLI, health check, docs
- Register sendblue in channels/__init__.py so ChannelRegistry works
- Auto-restore SendBlue bindings on server startup from database,
  re-creating ChannelBridge + DeepResearchAgent so webhooks survive
  server restarts
- Add sendblue to CLI channel_cmd.py (_get_channel, help text) and
  SystemBuilder._resolve_channel() for config.toml support
- Health check endpoint GET /v1/channels/sendblue/health returns
  channel_connected, bridge_wired, ready status
- Frontend: SendBlueWizard checks health on mount, shows
  "Disconnected" badge with "Reconnect" button when bridge is dead
- Docs: CLI usage, server restart behavior, ngrok re-registration,
  troubleshooting table, health check endpoint

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 22:33:12 -07:00
Jon Saad-FalconandClaude Opus 4.6 bfcc90866c fix: make Slack App Token required, fix CLI prompt label
App Token (xapp-) is required for Socket Mode DMs, not optional.
Removed xoxe- from CLI prompt since session tokens don't work.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 22:21:04 -07:00
Jon Saad-FalconandClaude Opus 4.6 6e57379018 fix: handle SendBlue free tier (shared line) in setup wizard
When /api/lines returns no numbers (free/shared line tier), the wizard
now shows a manual input with instructions to copy the phone number
from the "Send from" field in the SendBlue dashboard, instead of
showing an error.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 21:40:57 -07:00
Jon Saad-FalconandClaude Opus 4.6 0508056903 fix: correct SendBlue signup URL to dashboard.sendblue.com/company-signup
The old sendblue.co/getblue URL causes ERR_TOO_MANY_REDIRECTS.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 21:22:13 -07:00
Jon Saad-FalconandClaude Opus 4.6 1adab5d849 feat: SendBlue guided wizard with auto-verify, auto-register, test msg
Backend:
- POST /v1/channels/sendblue/verify — validates API keys, auto-fetches
  assigned phone numbers from SendBlue GET /api/lines
- POST /v1/channels/sendblue/register-webhook — auto-registers the
  /webhooks/sendblue callback URL with SendBlue
- POST /v1/channels/sendblue/test — sends a test iMessage to verify setup

Frontend:
- SendBlueWizard component with multi-step guided flow:
  Step 1: "Open SendBlue signup" button (opens in new tab)
  Step 2: Paste API Key + Secret → "Verify & Find Number" auto-fetches
  Step 3: Shows discovered phone number → "Activate Phone Number"
  Step 4: Success state with "Send Test" button
- Active state shows agent's number + test message sender
- Generic channels (Slack, WhatsApp, SMS, local iMessage) listed below

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 21:18:02 -07:00
Jon Saad-FalconandClaude Opus 4.6 7fd247be7e feat: wire Slack Socket Mode listener to channel bind/unbind
When user connects Slack in the Messaging tab, the backend now creates
a SlackChannel with Socket Mode, registers a handler that routes incoming
DMs to DeepResearchAgent, and starts listening. Unbinding disconnects
the Socket Mode client.

Requires slack-sdk installed and both bot_token (xoxb-) + app_token (xapp-).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 20:44:55 -07:00