Commit Graph
45 Commits
Author SHA1 Message Date
Robby ManihaniandGitHub 8e6bc343d8 fix(connectors): validate credentials before persisting + populate Gmail URLs (#410) 2026-05-25 11:07:35 -07:00
Robby ManihaniandGitHub 363bdbfa41 feat: Deep Research Granola integration + citation fixes (#366) 2026-05-20 15:56:42 -07:00
Robby ManihaniandGitHub 855ed51780 feat: Deep Research Slack integration (#365) 2026-05-20 12:02:05 -07:00
Tanvir BhathalandGitHub 4652b6e8a8 [FEAT] Proactive Agents (#364) 2026-05-20 12:00:19 -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
Jack HamiltonandGitHub 9e7366fc05 Close KnowledgeStore connections in connectors_router endpoints (#209)
* fix: close KnowledgeStore connections in connectors_router endpoints

KnowledgeStore opens a persistent SQLite connection in __init__ but was
never closed at the three instantiation sites in connectors_router.py,
leaking one file descriptor (plus its WAL handle) per call. The worst
offender is _connector_summary(), which is invoked per-connector on
every GET /connectors poll from the frontend — after ~100 polls the
backend hits the default macOS per-process FD limit (256) and asyncio's
accept() starts failing with OSError: [Errno 24] Too many open files.

Add __enter__/__exit__ to KnowledgeStore (close() already existed) and
wrap all three instantiation sites in `with` blocks so the connection
is released deterministically when the scope exits.

- connectors/store.py: add context manager protocol
- server/connectors_router.py: use `with KnowledgeStore() as store:`
  in _connector_summary, _ingest, and _run_sync

* test: cover KnowledgeStore context manager + connectors_router close leak

- test_store.py: add two tests for the new __enter__/__exit__ protocol
  verifying the connection closes on normal exit and on exceptions.
- test_connectors_router.py: add a regression test that monkeypatches
  KnowledgeStore.close to count invocations and asserts every store
  opened by GET /v1/connectors is paired with a close.

Also fix a pre-existing bug in the test_connectors_router fixture: the
router is created with prefix="/v1/connectors" internally (line 92 of
connectors_router.py), and the fixture was wrapping it again with
prefix="/v1", producing "/v1/v1/connectors". All 6 existing router
tests were failing with 404 before this fix. 5 of them now pass; the
remaining failure (test_trigger_sync) is an unrelated KeyError on a
missing response field and is out of scope for this PR.

* test: drop connectors_router regression test — skipped in CI anyway

The regression test added in the previous commit relies on FastAPI
being importable, but CI's dev-extra install does not include fastapi
(it lives in the `server` optional group). All tests in
test_connectors_router.py silently skip on CI with "fastapi not
installed", so the regression test would never actually execute there.

Revert test_connectors_router.py to the upstream main version. The
fixture bug I fixed (double prefix) and the connection-leak regression
test both deserve a separate PR scoped to test infrastructure — that
PR should either add fastapi to dev deps, split server tests into
their own CI job, or both.

The KnowledgeStore context manager tests in test_store.py are kept
because they have no fastapi dependency and will run in CI.
2026-05-06 23:44:43 -07:00
Andrew ParkandGitHub 88a7ebcaa3 test: add live marker, CI coverage gate, rust bridge boundary tests (#256) 2026-04-17 11:02:21 -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
Tanvir BhathalandGitHub 0e122cd776 DGX Spark Fix (#231) 2026-04-10 11:40:03 -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
krypticmouseandClaude Opus 4.6 caf0e59f16 fix: remove unused imports flagged by ruff across 5 files
Pre-existing lint errors that caused CI failures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 23:39:35 +00:00
Jon Saad-FalconandClaude Opus 4.6 1add224599 test: add 59 tests for system prompt, Slack messaging, and connector health
- test_deep_research_prompt.py (8 tests): date injection, time, day of week,
  dynamic generation, response types, tool descriptions, /no_think, Jarvis name
- test_slack_messaging.py (7 tests): connect with/without tokens, error state,
  disconnect, handler registration, send without token
- test_connector_health.py (44 tests): all 11 connectors instantiate, have
  required methods, report not-connected without creds, have metadata.
  Plus KnowledgeStore data presence checks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 14:35:58 -07:00
Jon Saad-FalconandClaude Opus 4.6 62b98d903b feat: add proper Google OAuth flow with localhost callback server
Add exchange_google_token() and run_oauth_flow() to oauth.py for the
full authorization code exchange. Update gdrive, gcalendar, and
gcontacts connectors to trigger the browser-based OAuth flow when a
client_id:client_secret pair is provided, prefer access_token over raw
token, and require an actual access_token for is_connected(). auth_url()
now returns the Cloud Console credentials page when no client_id is
stored.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 16:45:03 -07:00
Jon Saad-FalconandClaude Opus 4.6 258feff64e fix: skip torch-dependent tests when torch not installed in CI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 14:01:30 -07:00
Jon Saad-FalconandClaude Opus 4.6 869d9256fd fix: resolve all lint errors after merge with main
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:33:42 -07:00
Jon Saad-FalconandClaude Sonnet 4.6 0f03059eec feat: add Outlook connector as IMAP subclass
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 17:16:46 -07:00
Jon Saad-FalconandClaude Sonnet 4.6 744da567db fix: Apple Notes protobuf extraction handles HTML too, fix ZTITLE1 column
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 16:15:58 -07:00
krypticmouseandClaude Sonnet 4.6 bfa5132d1d feat: add SyncScheduler for periodic incremental sync
Implements SyncScheduler that runs a daemon background thread to call
SyncEngine.sync() on all registered connectors at a configurable interval.
Provides run_once() as a synchronous helper for testing.  Disconnected
connectors are skipped each cycle; errors are logged without stopping the
loop.  4 tests covering run_once, disconnected skip, start/stop, and
per-connector chunk counts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 21:29:50 +00:00
krypticmouseandClaude Sonnet 4.6 526cd4d3fb feat: add WhatsApp chat export connector
Implements WhatsAppConnector that reads exported .txt chat files from a
directory, parses the standard WhatsApp export line format with regex,
and yields one Document per chat file with participants, timestamps, and
since filtering.  Registers under "whatsapp" in ConnectorRegistry with
MCP tools for whatsapp_search_messages and whatsapp_get_chat.  10 tests
covering parsing, multi-file, since filtering, is_connected, and registry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 21:29:44 +00:00
krypticmouseandClaude Sonnet 4.6 b776c40507 feat: add Dropbox connector with file listing and download
Implements DropboxConnector using the Dropbox API v2 (list_folder +
download endpoints). Module-level API functions (_dropbox_api_list_folder,
_dropbox_api_download) are kept mockable. Downloads text-extractable
file types (.txt, .md, .csv, .py, etc.) and stores binary/unknown files
as metadata-only Documents.
Includes 6 tests covering not_connected, auth_url, sync (mocked),
disconnect, mcp_tools (dropbox_search_files / dropbox_get_file /
dropbox_list_recent), and registry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 21:23:45 +00:00
krypticmouseandClaude Sonnet 4.6 b4a1e824d8 feat: add Apple Notes connector with gzipped HTML extraction
Reads from the macOS NoteStore.sqlite database using read-only SQLite.
Decompresses ZDATA blobs (gzip + HTML) to yield plain-text Documents.
Includes 9 tests covering sync, decompression, doc_type, disconnect,
mcp_tools (notes_search / notes_get_note), and registry.
Updates connectors/__init__.py auto-import block.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 21:23:38 +00:00
krypticmouseandClaude Sonnet 4.6 dc4c773316 feat: wire Gmail since param to after: search operator
Remove the ARG002 noqa suppression and translate the `since` datetime
parameter into a Gmail `after:<epoch>` query string passed to
`_gmail_api_list_messages`, so incremental syncs only fetch messages
newer than the requested cutoff.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 21:18:52 +00:00
krypticmouseandClaude Sonnet 4.6 ee1805ceaf feat: wire attachment text extraction into IngestionPipeline
Add optional `attachment_store` parameter to IngestionPipeline. When
provided, attachments are stored as blobs in AttachmentStore and their
text (plain/markdown/csv via decode, PDF via pdfplumber) is chunked and
indexed in the KnowledgeStore with attachment provenance metadata.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 21:18:47 +00:00
krypticmouseandClaude Opus 4.6 ef859e6a17 feat: add EmbeddingStore for ColBERTv2 disk persistence
Add disk-persistent storage for ColBERT token-level embeddings so the
reranker can reuse pre-computed embeddings across queries instead of
re-encoding every document on every search.

- EmbeddingStore: individual .pt files per chunk with SQLite index for
  O(1) lookup, graceful degradation when torch is not installed
- ColBERTReranker: checks EmbeddingStore for cached embeddings before
  falling back to docFromText(), stores newly computed embeddings
- KnowledgeStore: ensures chunk_id is always present in retrieval
  metadata (both at store time and as a backfill in retrieve)
- 18 tests covering round-trip persistence, deletion, torch-absent
  degradation, and reranker cache-hit/miss behavior

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 20:48:17 +00:00
krypticmouseandClaude Sonnet 4.6 99d2013d51 feat: add content-addressed AttachmentStore with SHA-256 dedup
Implements AttachmentStore that writes blobs to {base_dir}/{sha[:2]}/{sha}
with a SQLite metadata index tracking filename, MIME type, size, and the
accumulated list of source_doc_ids for each content-identical blob.
Includes 7 unit tests covering SHA-256 return, file path layout,
idempotent dedup, multi-source tracking, metadata retrieval, content
round-trip, and missing-blob None return.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 19:41:35 +00:00
krypticmouseandClaude Sonnet 4.6 25d6a66d68 feat: wire incremental sync via since param in SyncEngine
Parse the last_sync checkpoint timestamp into a datetime and pass it as
the `since` argument to connector.sync(), enabling subsequent syncs to
fetch only new items rather than a full re-fetch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 18:28:18 +00:00
krypticmouseandClaude Sonnet 4.6 2967419691 feat: add TwoStageRetriever with BM25 recall and pluggable ColBERT reranking
Introduces Reranker ABC, ColBERTReranker (lazy-loads colbert-ai with graceful
fallback), and TwoStageRetriever that composes KnowledgeStore BM25 recall with
optional semantic reranking. Includes 8 tests covering filters, top_k limits,
mock reranker invocation, and recall_k sizing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 03:03:48 +00:00
krypticmouseandClaude Opus 4.6 ad2f6cc03c fix: Granola connector uses correct API response key and speaker format
Two bugs found via live API testing:
- List notes API returns "notes" key, not "data" (was returning 0 results)
- Transcript speaker field is a dict {"source": "microphone"}, not a string

Verified: 112 real meeting notes synced, 2,226 chunks indexed and searchable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 02:25:39 +00:00
krypticmouseandClaude Opus 4.6 20d132ff4a fix: add bot message filtering to Slack connector, add live smoke test
Slack connector now skips bot_id messages and non-content subtypes
(message_changed, message_deleted, bot_message, channel_join, channel_leave).
Found by comparing against hermes-agent reference implementation.

Live smoke test indexes 4,467 chunks from real docs/ markdown files and
verifies the full pipeline: Obsidian → SyncEngine → KnowledgeStore → search.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 02:06:43 +00:00
krypticmouseandClaude Sonnet 4.6 e3e9a70181 style: fix line length violations in connector tests
Break long lines in test_notion.py, test_store.py, and test_sync_engine.py
to comply with the 88-character E501 limit enforced by ruff.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 01:45:18 +00:00
krypticmouseandClaude Sonnet 4.6 506bcd88bd feat: add iMessage connector reading from macOS Messages database
Implements IMessageConnector (auth_type='local') that opens ~/Library/Messages/chat.db
read-only, converts Apple nanosecond timestamps to UTC datetimes, and yields one
Document per message with handle-based author resolution and chat display names.
Includes 8 tests using a temporary SQLite DB and 2 MCP tools (search + get conversation).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 01:43:02 +00:00
krypticmouseandClaude Sonnet 4.6 eb339294cb feat: add Google Contacts connector with People API sync
Implements GContactsConnector using the People API v1 to paginate
contacts (names, emails, phones, orgs) and yield them as Documents
with doc_type="contact". Includes 6 unit tests and auto-registration
in the connectors __init__.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 01:40:01 +00:00
krypticmouseandClaude Sonnet 4.6 79616c9da4 feat: add Google Calendar connector with event sync
Implements GCalendarConnector (registered as "gcalendar") following the
gmail.py pattern: module-level API functions for calendarList and events.list,
_format_event helper for human-readable content, paginated sync across all
calendars, and three MCP tools (get_events_today, search_events, next_meeting).
Includes 6 tests covering not_connected, auth_url scope, sync document fields,
disconnect, mcp_tools, and registry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 01:37:28 +00:00
krypticmouseandClaude Sonnet 4.6 89e757adba feat: add Google Drive connector with file export and sync
Implements GDriveConnector using the Drive API v3 with OAuth, paginated
file listing, Google Workspace export (Docs→text/plain, Sheets→text/csv,
Slides→text/plain), and 3 MCP tools. Adds auto-registration in __init__.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 01:34:43 +00:00
krypticmouseandClaude Sonnet 4.6 0d9c25c6f9 feat: add Slack data source connector with channel history sync
Implements SlackConnector that syncs channel message history via the Slack
Web API, with OAuth credential storage, user-map resolution, and 3 MCP tools.
Includes 7 tests covering connectivity, auth, sync document correctness,
disconnect, MCP tools, and registry registration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 01:32:05 +00:00
krypticmouseandClaude Sonnet 4.6 1257303cd4 feat: add Granola meeting notes connector with transcript support
Implements GranolaConnector that syncs meeting notes from the Granola
public API, combining AI-generated summaries with full speaker transcripts
into searchable Documents. Includes cursor-based pagination, created_after
filtering, 2 MCP tools, and 8 tests covering all connector behaviours.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 01:20:12 +00:00
krypticmouseandClaude Sonnet 4.6 547b6ba734 feat: add Notion connector with block-to-markdown rendering
Implements NotionConnector that syncs pages via the Notion REST API,
renders block content (paragraph, headings, lists, code, quote, divider,
to_do) to markdown, and registers with ConnectorRegistry. Includes 8
tests covering auth, sync, rendering, disconnect, MCP tools, and registry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 01:17:16 +00:00
krypticmouseandClaude Sonnet 4.6 138fb8a3d0 feat: add integration test and auto-registration for built-in connectors
Wire up ObsidianConnector and GmailConnector via auto-import in the
connectors __init__.py so they register on package import. Add a full
end-to-end integration test covering the Obsidian vault → SyncEngine →
KnowledgeStore → knowledge_search pipeline.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 00:09:36 +00:00
krypticmouseandClaude Opus 4.6 56554c481a feat: add Gmail connector with OAuth and mocked API sync
Implements GmailConnector registered under 'gmail' in ConnectorRegistry,
a shared oauth.py helper (build_google_auth_url, load/save/delete_tokens)
reusable by Drive/Calendar/Contacts, and 7 fully mocked pytest tests
covering auth state, sync document extraction, disconnect, mcp_tools,
and registry lookup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 23:56:29 +00:00
krypticmouseandClaude Opus 4.6 5e0e8965d7 feat: add Obsidian/Markdown vault connector with frontmatter parsing
Implements ObsidianConnector (filesystem auth, no OAuth) that walks a vault
directory for .md/.markdown/.txt files, parses YAML frontmatter via a
dependency-free parser, skips hidden dirs and binary files, and yields
Document objects with doc_type="note" and obsidian:// deep-link URLs.
Exposes an obsidian_search_notes MCP ToolSpec.  9 tests cover connection
state, vault traversal, hidden-dir/binary filtering, frontmatter extraction,
and registry wiring.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 23:52:49 +00:00
krypticmouseandClaude Sonnet 4.6 af7d0db518 feat: add SyncEngine with checkpoint/resume for connector orchestration
Introduces SyncEngine that wraps IngestionPipeline with a SQLite state
database (sync_state.db) for checkpoint/resume: cursors and item counts
are persisted after every 100-document batch and on completion/error.
Adds 4 tests covering single-connector ingestion, checkpoint accuracy,
unsynced-connector None return, and multi-connector source filtering.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 23:49:54 +00:00
krypticmouseandClaude Sonnet 4.6 1a713e66fe feat: add ingestion pipeline with dedup, type-aware chunking, and indexed storage
Implements IngestionPipeline that deduplicates Documents by doc_id (both
in-memory and by loading existing doc_ids from the store on init), chunks
content via SemanticChunker, and persists all chunks with full provenance
metadata to KnowledgeStore. 8 tests cover single-doc ingestion, dedup across
calls and batches, persistence across pipeline instances, long-doc multi-chunk
splitting, atomic event chunking, multi-source filtering, and return-value accuracy.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 23:47:59 +00:00
krypticmouseandClaude Opus 4.6 efc979edf0 feat: add type-aware semantic chunker with section/paragraph/sentence splitting
Implements SemanticChunker that splits text based on doc_type (event/contact
as single chunks, email on reply boundaries, message on double-newlines,
document/note on ## headings → paragraphs → sentences). ChunkResult carries
sequential 0-based indexes and inherits parent metadata; section headings are
added as chunk metadata. 16 tests covering all splitting strategies.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 23:45:38 +00:00
krypticmouseandClaude Sonnet 4.6 8d3505f8f3 feat: add KnowledgeStore with source-aware SQLite schema and filtered BM25 retrieval
Implements KnowledgeStore (extends MemoryBackend) for Deep Research with a
rich SQLite/FTS5 schema supporting source, doc_type, author, participants,
timestamp, thread_id, url, and chunk_index columns; BM25 ranking via FTS5
with porter unicode61 tokenizer; filtered retrieval by source, doc_type,
author, since, and until; MEMORY_STORE/MEMORY_RETRIEVE event emission; WAL
journal mode; and 15 isolated tests using tmp_path fixtures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 23:42:39 +00:00
krypticmouseandClaude Sonnet 4.6 29d275fe4e feat: add ConnectorRegistry and base connector types (Document, SyncStatus, BaseConnector)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 23:35:01 +00:00