agentgraph-server 0.5.0__tar.gz → 0.5.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/.agents/skills/graph/SKILL.md +18 -14
- agentgraph_server-0.5.2/PKG-INFO +175 -0
- agentgraph_server-0.5.2/README.md +135 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/auth/credentials.py +21 -9
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/backends/__init__.py +9 -2
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/backends/sqlite/backend.py +496 -119
- agentgraph_server-0.5.2/agentgraph/backends/sqlite/schema.sql +86 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/cli.py +52 -14
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/cli_query.py +7 -12
- agentgraph_server-0.5.2/agentgraph/config.py +144 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/connectors/base.py +24 -8
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/core/storage.py +30 -13
- agentgraph_server-0.5.2/agentgraph/demo.py +382 -0
- agentgraph_server-0.5.2/agentgraph/demo_fixtures/reliable-webhooks.md +21 -0
- agentgraph_server-0.5.2/agentgraph/demo_fixtures/retry-guidance.md +21 -0
- agentgraph_server-0.5.2/agentgraph/graph/__init__.py +1 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/graph/bookmark.py +1 -1
- agentgraph_server-0.5.2/agentgraph/graph/expiration.py +80 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/graph/fetch.py +48 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/graph/query.py +2 -5
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/mcp/server.py +18 -38
- agentgraph_server-0.5.2/agentgraph/server/app.py +236 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/server/cli_api.py +30 -15
- agentgraph_server-0.5.2/agentgraph/server/observation.py +188 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/server/router.py +5 -4
- agentgraph_server-0.5.2/agentgraph/server/static/viewer.html +2765 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/server/sync.py +20 -5
- agentgraph_server-0.5.2/agentgraph_server.egg-info/PKG-INFO +175 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph_server.egg-info/SOURCES.txt +10 -4
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/pyproject.toml +7 -2
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_auth.py +12 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_browse.py +54 -23
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_cli.py +122 -4
- agentgraph_server-0.5.2/tests/test_config.py +144 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_connectors.py +139 -15
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_docs_build.py +112 -9
- agentgraph_server-0.5.2/tests/test_expiration.py +460 -0
- agentgraph_server-0.5.2/tests/test_launch_demo.py +104 -0
- agentgraph_server-0.5.2/tests/test_observation.py +402 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_query.py +42 -41
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_release_metadata.py +1 -2
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_rss_connector.py +4 -3
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_schema.py +68 -22
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_sync.py +53 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_upsert.py +91 -6
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_viewer_layout_contract.py +73 -19
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_web_connector.py +137 -1
- agentgraph_server-0.5.0/PKG-INFO +0 -286
- agentgraph_server-0.5.0/README.md +0 -246
- agentgraph_server-0.5.0/agentgraph/config.py +0 -90
- agentgraph_server-0.5.0/agentgraph/graph/__init__.py +0 -1
- agentgraph_server-0.5.0/agentgraph/graph/gc.py +0 -26
- agentgraph_server-0.5.0/agentgraph/server/app.py +0 -133
- agentgraph_server-0.5.0/agentgraph/server/dwell.py +0 -79
- agentgraph_server-0.5.0/agentgraph_server.egg-info/PKG-INFO +0 -286
- agentgraph_server-0.5.0/tests/test_config.py +0 -64
- agentgraph_server-0.5.0/tests/test_gc.py +0 -228
- agentgraph_server-0.5.0/tests/test_observe.py +0 -156
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/.agents/skills/slack-auth/SKILL.md +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/LICENSE +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/__init__.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/auth/__init__.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/backends/sqlite/__init__.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/backends/sqlite/vector.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/connectors/__init__.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/connectors/registry.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/connectors/status.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/core/__init__.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/core/context.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/core/runtime.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/graph/delete.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/graph/download.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/graph/embeddings.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/graph/link.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/graph/person.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/graph/upsert.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/logging.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/mcp/__init__.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/perf.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/server/__init__.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/server/graph_api.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph/skills.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph_server.egg-info/dependency_links.txt +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph_server.egg-info/entry_points.txt +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph_server.egg-info/requires.txt +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/agentgraph_server.egg-info/top_level.txt +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/setup.cfg +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_benchmarks.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_discord_attachments.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_embeddings.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_fetch.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_logging.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_registry.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_router.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_server_imports.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_slack_auth_artifacts.py +0 -0
- {agentgraph_server-0.5.0 → agentgraph_server-0.5.2}/tests/test_slack_oauth.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: graph
|
|
3
|
-
description: Use the AgentGraph CLI to
|
|
3
|
+
description: Use the AgentGraph CLI to search and traverse the local knowledge graph, inspect sources, and retrieve evidence for coding-agent tasks.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /graph — AgentGraph CLI skill
|
|
@@ -23,7 +23,7 @@ agentgraph edges <entity-id|platform/ref> [--type <edge-type>] [--direction in|o
|
|
|
23
23
|
agentgraph traverse <entity-id|platform/ref> --resolve [--depth N] [--json]
|
|
24
24
|
|
|
25
25
|
# Filter entities by type and metadata
|
|
26
|
-
agentgraph query --type <entity-type> [--filter key=value] [--since 12h|30m|2d] [--mine] [--has-attachments] [--limit N] [--order-by created_at|updated_at|
|
|
26
|
+
agentgraph query --type <entity-type> [--filter key=value] [--since 12h|30m|2d] [--mine] [--has-attachments] [--limit N] [--order-by created_at|updated_at|source_created_at|source_updated_at|observed_at|synced_at] [--json]
|
|
27
27
|
|
|
28
28
|
# Trigger a connector fetch for a platform entity (by platform + platform-specific ID)
|
|
29
29
|
agentgraph fetch <platform> <resource-id> [--json]
|
|
@@ -46,9 +46,6 @@ agentgraph unify-persons <primary-person-id> <duplicate-person-id>... [--json]
|
|
|
46
46
|
# Queue a background poll for one or all connectors
|
|
47
47
|
agentgraph poll [<source>] [--json] # source: slack, gmail, discord, drive, rss — omit for all; reports already_running and skipped auth failures
|
|
48
48
|
|
|
49
|
-
# Run a one-shot bulk ingest for a connector (all data within the retention window, beyond what poll covers)
|
|
50
|
-
agentgraph ingest <source> [--json] # e.g. gmail, rss
|
|
51
|
-
|
|
52
49
|
# List installed connectors and their sync status; credential fields are null for connectors like RSS/web
|
|
53
50
|
agentgraph connectors [--verify] [--json] # auth_provider, auth_status/auth_detail when applicable, auth_verified, url_patterns, polls, poll_delegates, polled_by, sync, last_synced_at
|
|
54
51
|
|
|
@@ -58,6 +55,7 @@ agentgraph connector <source> --help
|
|
|
58
55
|
agentgraph connector rss add <feed-url> [feed-url...] [--json] # validates feeds, rejects non-feeds without saving, and queues an RSS poll
|
|
59
56
|
agentgraph connector rss remove <feed-url> [feed-url...] [--json] # removes exact configured feed URLs
|
|
60
57
|
agentgraph connector rss import-opml <file.opml> [--all | --select 1,3-5] [--json] # omit flags for checkbox selection
|
|
58
|
+
agentgraph connector gmail ingest [--account <account-id>] [--json] # queue an optional 90-day Gmail historical backfill; omit --account for all authenticated Google accounts
|
|
61
59
|
|
|
62
60
|
# Show credential-backed auth provider state (dedupes shared providers like Google); add --verify for live provider API checks
|
|
63
61
|
agentgraph auth [--verify] [--json] status # provider, connectors[], auth_status/auth_detail, auth_verified, accounts[] including auth_method
|
|
@@ -75,6 +73,9 @@ agentgraph serve [--reload]
|
|
|
75
73
|
agentgraph mcp-serve
|
|
76
74
|
agentgraph mcp-config # stdio config for Claude Desktop/Claude Code; ChatGPT uses a tunneled HTTPS /mcp endpoint
|
|
77
75
|
|
|
76
|
+
# Create the self-contained fictional graph used by the public demo
|
|
77
|
+
agentgraph demo seed --config-dir <directory> [--reset] [--json]
|
|
78
|
+
|
|
78
79
|
# Install the bundled AgentGraph skill into ~/.agents/skills or ./.agents/skills
|
|
79
80
|
agentgraph install-skill [graph] [--target user|project] [--force] [--json]
|
|
80
81
|
```
|
|
@@ -100,7 +101,6 @@ agentgraph fetch ... -> fetch_entity_tool(platform, resource_id)
|
|
|
100
101
|
agentgraph fetch-entity ... -> fetch_entity_by_id_tool(entity_id)
|
|
101
102
|
agentgraph download ... -> download_entity_tool(entity_id, output_path)
|
|
102
103
|
agentgraph poll [source] -> poll_connectors_tool(source) # returns polled, already_running, and skipped lists
|
|
103
|
-
agentgraph ingest <source> -> ingest_connector_tool(source)
|
|
104
104
|
agentgraph bookmark ... -> bookmark_entity_tool(entity_id, bookmarked)
|
|
105
105
|
agentgraph delete ... -> delete_entity_tool(entity_id)
|
|
106
106
|
agentgraph unify-persons ... -> unify_persons_tool(primary_entity_id, duplicate_entity_ids)
|
|
@@ -112,7 +112,8 @@ agentgraph install-skill ... -> install_skill_tool(skill, target, force)
|
|
|
112
112
|
| Type | Contains |
|
|
113
113
|
|---|---|
|
|
114
114
|
| `Message` | Chat messages (Discord, Slack). **Chat images and file uploads are attachments on Message entities** — stored in `metadata.attachments` (JSON array with `url`, `filename`, `content_type`, `width`, `height`). Use `--has-attachments` to filter to messages with files. |
|
|
115
|
-
| `Document` | Text documents (Google Docs, etc.) and Gmail attachment stubs. Gmail attachment stubs are referenced by their owning `
|
|
115
|
+
| `Document` | Text documents (Google Docs, etc.) and Gmail attachment stubs. Gmail attachment stubs are referenced by their owning `Email` and can be downloaded with `agentgraph download`. |
|
|
116
|
+
| `Email` | Gmail email threads. |
|
|
116
117
|
| `Channel` | Chat channels and DM threads. |
|
|
117
118
|
| `Task` | Tasks or to-do items. |
|
|
118
119
|
| `Project` | Project/repository containers. |
|
|
@@ -139,10 +140,12 @@ agentgraph download <attachment-document-entity-id> --output <file-or-dir>
|
|
|
139
140
|
- Delete targets accept: full UUID, UUID prefix, platform ref, or HTTP(S) URL. Connected edges are removed with the entity.
|
|
140
141
|
- Use `agentgraph download` for source files stored behind connector auth, such as Drive PDFs, exported Google Docs/Sheets, or Gmail attachment `Document` stubs
|
|
141
142
|
- `agentgraph fetch` and `agentgraph fetch-entity` persist the connector's complete returned batch before reporting counts; content-rich resources such as RSS feeds may take several minutes
|
|
142
|
-
-
|
|
143
|
+
- Direct fetch is not a browser observation and does not update `observed_at`; use it when a result references missing or stale context, not as evidence that the human viewed the resource
|
|
144
|
+
- Use `agentgraph bookmark` for entities or HTTP(S) URLs that should survive retention-window expiration
|
|
143
145
|
- Use `agentgraph unify-persons` only after confirming two or more `Person` entities are the same human; the first argument is the canonical person to keep. Without `--json`, the command displays the updated canonical Person, including merged identity metadata and duplicate identities.
|
|
144
146
|
- `polls: false` does not always mean stale: check `polled_by` / `sync` for connectors refreshed by another connector, e.g. `gdocs` and `gsheets` are refreshed via the `gdrive` Drive Changes poll
|
|
145
147
|
- Server logs go to stdout unless the process manager redirects them elsewhere
|
|
148
|
+
- `agentgraph demo seed` is an offline CLI fixture; it does not configure or require an MCP client
|
|
146
149
|
|
|
147
150
|
## Stub Entities
|
|
148
151
|
|
|
@@ -151,9 +154,10 @@ An entity is a **stub** when it has no title and no content — it was reference
|
|
|
151
154
|
## Workflow
|
|
152
155
|
|
|
153
156
|
When the user asks about graph data:
|
|
154
|
-
1.
|
|
155
|
-
2.
|
|
156
|
-
3.
|
|
157
|
-
4.
|
|
158
|
-
5.
|
|
159
|
-
6.
|
|
157
|
+
1. Search for the relevant terms with `agentgraph search ... --json`; do not query the SQLite database directly
|
|
158
|
+
2. Open promising results with `agentgraph get ... --json` to read their full content and source metadata
|
|
159
|
+
3. Use `agentgraph edges` or `agentgraph traverse` to follow people, threads, containers, references, and other relationships
|
|
160
|
+
4. Compare source dates and contents, distinguish source facts from inference, and cite the source URLs or entity identifiers used
|
|
161
|
+
5. Inspect `agentgraph connectors --json` and `agentgraph auth --json status` only when the task requires source freshness, a missing resource must be fetched, or a graph command reports a connector or credential problem
|
|
162
|
+
6. If credential validity is uncertain, use `agentgraph auth --verify --json status` or `agentgraph connectors --verify --json`; if Google is invalid or missing, tell the user to run `agentgraph auth google`
|
|
163
|
+
7. When a result links to an unfetched stub or a specific missing resource, use `fetch-entity` for its graph ID or `fetch <platform> <resource-id>`, then continue the investigation with the hydrated context
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentgraph-server
|
|
3
|
+
Version: 0.5.2
|
|
4
|
+
Summary: A local-first CLI and MCP server that turns selected digital sources into a searchable graph for the AI agent you already use.
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: aiosqlite>=0.20.0
|
|
9
|
+
Requires-Dist: agentgraph-connector-web<0.6,>=0.5.0
|
|
10
|
+
Requires-Dist: apscheduler>=3.11.2
|
|
11
|
+
Requires-Dist: click<8.4
|
|
12
|
+
Requires-Dist: fastapi>=0.135.2
|
|
13
|
+
Requires-Dist: fastembed>=0.8.0
|
|
14
|
+
Requires-Dist: httpx>=0.28.1
|
|
15
|
+
Requires-Dist: mcp>=1.26.0
|
|
16
|
+
Requires-Dist: numpy>=2.4.6
|
|
17
|
+
Requires-Dist: pydantic>=2.12.5
|
|
18
|
+
Requires-Dist: pydantic-settings>=2.13.1
|
|
19
|
+
Requires-Dist: rich>=14.3.3
|
|
20
|
+
Requires-Dist: sqlite-vec>=0.1.9
|
|
21
|
+
Requires-Dist: typer>=0.24.1
|
|
22
|
+
Requires-Dist: uvicorn>=0.42.0
|
|
23
|
+
Provides-Extra: google
|
|
24
|
+
Requires-Dist: agentgraph-connector-google<0.6,>=0.5.0; extra == "google"
|
|
25
|
+
Provides-Extra: slack
|
|
26
|
+
Requires-Dist: agentgraph-connector-slack<0.6,>=0.5.0; extra == "slack"
|
|
27
|
+
Provides-Extra: discord
|
|
28
|
+
Requires-Dist: agentgraph-connector-discord<0.6,>=0.5.0; extra == "discord"
|
|
29
|
+
Provides-Extra: rss
|
|
30
|
+
Requires-Dist: agentgraph-connector-rss<0.6,>=0.5.0; extra == "rss"
|
|
31
|
+
Provides-Extra: web
|
|
32
|
+
Requires-Dist: agentgraph-connector-web<0.6,>=0.5.0; extra == "web"
|
|
33
|
+
Provides-Extra: all
|
|
34
|
+
Requires-Dist: agentgraph-connector-web<0.6,>=0.5.0; extra == "all"
|
|
35
|
+
Requires-Dist: agentgraph-connector-google<0.6,>=0.5.0; extra == "all"
|
|
36
|
+
Requires-Dist: agentgraph-connector-slack<0.6,>=0.5.0; extra == "all"
|
|
37
|
+
Requires-Dist: agentgraph-connector-discord<0.6,>=0.5.0; extra == "all"
|
|
38
|
+
Requires-Dist: agentgraph-connector-rss<0.6,>=0.5.0; extra == "all"
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
# AgentGraph
|
|
42
|
+
|
|
43
|
+
**Give the AI agent you already use a searchable world.**
|
|
44
|
+
|
|
45
|
+
AgentGraph is a local-first, self-hosted CLI and MCP server that turns the sources you choose into a searchable graph for the AI agent you already use. Connect Gmail, Google Drive, Slack, Discord, RSS, and web pages; AgentGraph translates them into local entities, people, relationships, and searchable content.
|
|
46
|
+
|
|
47
|
+
> **AgentGraph stores context; your agent reasons over it.** It is not an agent, chatbot, hosted graph service, or replacement for the tools you already use.
|
|
48
|
+
|
|
49
|
+
[See the demo](docs-src/demo.md) · [Quickstart](docs-src/quickstart.md) · [Documentation](https://simonexmachina.github.io/agent-graph/) · [Chrome extension](https://chromewebstore.google.com/detail/agentgraph-extension/iilkfclglabllelhjacijldknapbhidi)
|
|
50
|
+
|
|
51
|
+
<picture>
|
|
52
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs-src/assets/diagrams/architecture-overview-dark.svg">
|
|
53
|
+
<img src="docs-src/assets/diagrams/architecture-overview-light.svg" alt="Selected online services connect to AgentGraph on the user's machine. Browser observation, agent fetches, and background refresh flow through connector packages into a local graph, which is exposed to the user's existing coding agent through MCP.">
|
|
54
|
+
</picture>
|
|
55
|
+
|
|
56
|
+
## Why AgentGraph
|
|
57
|
+
|
|
58
|
+
Coding agents work well because their source of truth is already on disk. They can search files, follow references, inspect history, and build a model of the system without the user pasting every relevant detail.
|
|
59
|
+
|
|
60
|
+
The rest of a person's digital context is fragmented across messages, documents, feeds, and web pages. AgentGraph makes the parts you choose locally searchable and navigable through MCP, so a coding agent can investigate that context instead of starting every conversation blind.
|
|
61
|
+
|
|
62
|
+
## How context enters the graph
|
|
63
|
+
|
|
64
|
+
AgentGraph builds context in three ways:
|
|
65
|
+
|
|
66
|
+
1. **Observe:** the Chrome extension recognizes a supported URL, waits until you have kept it focused for the observation threshold, and reports the resource to your local AgentGraph server. The owning connector fetches it through the source API.
|
|
67
|
+
2. **Fetch:** your agent or the CLI can request a specific resource. The connector adds or refreshes its entities, people, and edges before returning.
|
|
68
|
+
3. **Refresh:** connector polling and ingest keep configured or already-known resources current in the background.
|
|
69
|
+
|
|
70
|
+
Observation is also an attention signal. Browser observation updates `observed_at`; direct fetch, polling, ingest, and source changes do not. Observable entities expire after 90 days by default unless they are observed again or bookmarked. See [How AgentGraph works](docs-src/how-it-works.md) and [Entity retention](docs-src/retention.md).
|
|
71
|
+
|
|
72
|
+
The extension sends recognized URLs, plus the Gmail thread identifier where required, to the local server. It does not upload arbitrary page content to an AgentGraph-operated service.
|
|
73
|
+
|
|
74
|
+
## Trace a decision across sources
|
|
75
|
+
|
|
76
|
+
The launch demo asks an existing coding agent:
|
|
77
|
+
|
|
78
|
+
> Before I reply to Maya, reconstruct the Atlas synchronization decision. What did she require, what did engineering agree, does the Drive plan match, and which research supports the decision? Flag contradictions and link every source.
|
|
79
|
+
|
|
80
|
+
The agent uses the Graph skill and AgentGraph CLI to search a fictional Gmail thread, traverse a Slack discussion and its authors, check a stale Drive plan, and compare two research documents. Everything is included in one deterministic fixture; no provider credentials, browser observation, or MCP setup are required. [Run the demo](docs-src/demo.md).
|
|
81
|
+
|
|
82
|
+
## What each connector makes perceptible
|
|
83
|
+
|
|
84
|
+
| Connector | What it contributes | Context paths |
|
|
85
|
+
| --- | --- | --- |
|
|
86
|
+
| Gmail | Email threads, participants, subjects, bodies, and attachment references | Observe, fetch, poll, ingest |
|
|
87
|
+
| Google Drive, Docs, Sheets | Folders, files, content, ownership, authorship, and containment | Observe, fetch, poll |
|
|
88
|
+
| Slack | Channels and DMs, messages, replies, authors, mentions, and attachments | Observe, fetch, poll |
|
|
89
|
+
| Discord | Channels, DMs, threads, messages, authors, mentions, and attachments | Observe, fetch, poll |
|
|
90
|
+
| RSS | Feeds, posts, dates, authors, and publication relationships | Observe, fetch, poll, ingest |
|
|
91
|
+
| Web | Configured pages and bookmarks with titles, text, metadata, and URLs | Observe, fetch |
|
|
92
|
+
|
|
93
|
+
These connectors are proof of the pattern, not the boundary of the product. A connector can translate an API, export, webhook, local database, browser surface, or structured file into AgentGraph's shared model.
|
|
94
|
+
|
|
95
|
+
**Bring any service into your agent's world.** Teams can keep private connectors for internal systems, individuals can connect niche tools, and open-source contributors can publish integrations for the wider community. See [Connectors](docs-src/connectors.md) and [Extending AgentGraph](docs-src/extending.md).
|
|
96
|
+
|
|
97
|
+
## Quickstart
|
|
98
|
+
|
|
99
|
+
AgentGraph requires Python 3.12+, [`uv`](https://docs.astral.sh/uv/), and Chrome for browser observation.
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
git clone https://github.com/simonexmachina/agent-graph
|
|
103
|
+
cd agent-graph
|
|
104
|
+
uv sync --extra all
|
|
105
|
+
source .venv/bin/activate
|
|
106
|
+
agentgraph onboard
|
|
107
|
+
agentgraph serve
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Install the [AgentGraph Chrome extension](https://chromewebstore.google.com/detail/agentgraph-extension/iilkfclglabllelhjacijldknapbhidi), browse a supported resource, then verify that context landed:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
agentgraph connectors
|
|
114
|
+
agentgraph search "project kickoff notes"
|
|
115
|
+
agentgraph traverse <entity-id> --depth 2
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Connect the agent you already use:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
agentgraph mcp-config
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Use the printed stdio configuration with Claude Desktop, Claude Code, Codex, or another compatible MCP client. ChatGPT developer mode uses the streamable HTTP `/mcp` endpoint through HTTPS. The [Quickstart](docs-src/quickstart.md) covers the complete path and expected result.
|
|
125
|
+
|
|
126
|
+
## What AgentGraph is and is not
|
|
127
|
+
|
|
128
|
+
| AgentGraph is | AgentGraph is not |
|
|
129
|
+
| --- | --- |
|
|
130
|
+
| Local-first infrastructure | An AI agent or autonomous assistant |
|
|
131
|
+
| A CLI and MCP server | A replacement for your agent |
|
|
132
|
+
| A searchable graph of selected context | A chatbot or LLM |
|
|
133
|
+
| An open connector architecture | A hosted integration SaaS |
|
|
134
|
+
| Semantic search plus typed entities and edges | Only a vector database |
|
|
135
|
+
| Self-hosted and open source | A project-operated store for your graph data |
|
|
136
|
+
|
|
137
|
+
## Local data and privacy
|
|
138
|
+
|
|
139
|
+
Indexed content is stored in SQLite on your machine. Provider credentials stay in the AgentGraph config directory, and source API calls run directly from your machine under your credentials. AgentGraph does not operate a hosted graph service or send indexed content to a project-controlled backend.
|
|
140
|
+
|
|
141
|
+
An MCP client you connect can receive content from the local graph, subject to that client's data practices. Read the complete [Privacy Policy](docs-src/privacy.md), [Terms of Service](docs-src/terms.md), and [retention model](docs-src/retention.md).
|
|
142
|
+
|
|
143
|
+
## Interfaces
|
|
144
|
+
|
|
145
|
+
| Surface | Use it for | Entry point |
|
|
146
|
+
| --- | --- | --- |
|
|
147
|
+
| MCP | Let an existing agent search, traverse, fetch, and manage context | `agentgraph mcp-config`, `agentgraph mcp-serve` |
|
|
148
|
+
| CLI | Search, fetch, ingest, debug, and operate the graph | `agentgraph search`, `agentgraph fetch`, `agentgraph serve` |
|
|
149
|
+
| Browser extension | Turn focused browsing on supported URLs into observations | [Chrome Web Store](https://chromewebstore.google.com/detail/agentgraph-extension/iilkfclglabllelhjacijldknapbhidi) |
|
|
150
|
+
| Viewer | Inspect entities, people, relationships, and observation state | `http://127.0.0.1:8765/viewer` |
|
|
151
|
+
|
|
152
|
+
## Documentation
|
|
153
|
+
|
|
154
|
+
- [Install](docs-src/install.md)
|
|
155
|
+
- [Quickstart](docs-src/quickstart.md)
|
|
156
|
+
- [How AgentGraph works](docs-src/how-it-works.md)
|
|
157
|
+
- [Connectors](docs-src/connectors.md)
|
|
158
|
+
- [Configuration](docs-src/configuration.md)
|
|
159
|
+
- [Commands](docs-src/commands/index.md)
|
|
160
|
+
- [MCP tools](docs-src/mcp/index.md)
|
|
161
|
+
- [Extending](docs-src/extending.md)
|
|
162
|
+
|
|
163
|
+
## Contributing
|
|
164
|
+
|
|
165
|
+
See [AGENTS.md](AGENTS.md) for repository-specific development rules. Before opening a change, run:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
uv run pytest tests/ -m "not integration" -q
|
|
169
|
+
uv run pyright
|
|
170
|
+
uv run ruff check agentgraph/ packages/ scripts/ tests/
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## License
|
|
174
|
+
|
|
175
|
+
See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# AgentGraph
|
|
2
|
+
|
|
3
|
+
**Give the AI agent you already use a searchable world.**
|
|
4
|
+
|
|
5
|
+
AgentGraph is a local-first, self-hosted CLI and MCP server that turns the sources you choose into a searchable graph for the AI agent you already use. Connect Gmail, Google Drive, Slack, Discord, RSS, and web pages; AgentGraph translates them into local entities, people, relationships, and searchable content.
|
|
6
|
+
|
|
7
|
+
> **AgentGraph stores context; your agent reasons over it.** It is not an agent, chatbot, hosted graph service, or replacement for the tools you already use.
|
|
8
|
+
|
|
9
|
+
[See the demo](docs-src/demo.md) · [Quickstart](docs-src/quickstart.md) · [Documentation](https://simonexmachina.github.io/agent-graph/) · [Chrome extension](https://chromewebstore.google.com/detail/agentgraph-extension/iilkfclglabllelhjacijldknapbhidi)
|
|
10
|
+
|
|
11
|
+
<picture>
|
|
12
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs-src/assets/diagrams/architecture-overview-dark.svg">
|
|
13
|
+
<img src="docs-src/assets/diagrams/architecture-overview-light.svg" alt="Selected online services connect to AgentGraph on the user's machine. Browser observation, agent fetches, and background refresh flow through connector packages into a local graph, which is exposed to the user's existing coding agent through MCP.">
|
|
14
|
+
</picture>
|
|
15
|
+
|
|
16
|
+
## Why AgentGraph
|
|
17
|
+
|
|
18
|
+
Coding agents work well because their source of truth is already on disk. They can search files, follow references, inspect history, and build a model of the system without the user pasting every relevant detail.
|
|
19
|
+
|
|
20
|
+
The rest of a person's digital context is fragmented across messages, documents, feeds, and web pages. AgentGraph makes the parts you choose locally searchable and navigable through MCP, so a coding agent can investigate that context instead of starting every conversation blind.
|
|
21
|
+
|
|
22
|
+
## How context enters the graph
|
|
23
|
+
|
|
24
|
+
AgentGraph builds context in three ways:
|
|
25
|
+
|
|
26
|
+
1. **Observe:** the Chrome extension recognizes a supported URL, waits until you have kept it focused for the observation threshold, and reports the resource to your local AgentGraph server. The owning connector fetches it through the source API.
|
|
27
|
+
2. **Fetch:** your agent or the CLI can request a specific resource. The connector adds or refreshes its entities, people, and edges before returning.
|
|
28
|
+
3. **Refresh:** connector polling and ingest keep configured or already-known resources current in the background.
|
|
29
|
+
|
|
30
|
+
Observation is also an attention signal. Browser observation updates `observed_at`; direct fetch, polling, ingest, and source changes do not. Observable entities expire after 90 days by default unless they are observed again or bookmarked. See [How AgentGraph works](docs-src/how-it-works.md) and [Entity retention](docs-src/retention.md).
|
|
31
|
+
|
|
32
|
+
The extension sends recognized URLs, plus the Gmail thread identifier where required, to the local server. It does not upload arbitrary page content to an AgentGraph-operated service.
|
|
33
|
+
|
|
34
|
+
## Trace a decision across sources
|
|
35
|
+
|
|
36
|
+
The launch demo asks an existing coding agent:
|
|
37
|
+
|
|
38
|
+
> Before I reply to Maya, reconstruct the Atlas synchronization decision. What did she require, what did engineering agree, does the Drive plan match, and which research supports the decision? Flag contradictions and link every source.
|
|
39
|
+
|
|
40
|
+
The agent uses the Graph skill and AgentGraph CLI to search a fictional Gmail thread, traverse a Slack discussion and its authors, check a stale Drive plan, and compare two research documents. Everything is included in one deterministic fixture; no provider credentials, browser observation, or MCP setup are required. [Run the demo](docs-src/demo.md).
|
|
41
|
+
|
|
42
|
+
## What each connector makes perceptible
|
|
43
|
+
|
|
44
|
+
| Connector | What it contributes | Context paths |
|
|
45
|
+
| --- | --- | --- |
|
|
46
|
+
| Gmail | Email threads, participants, subjects, bodies, and attachment references | Observe, fetch, poll, ingest |
|
|
47
|
+
| Google Drive, Docs, Sheets | Folders, files, content, ownership, authorship, and containment | Observe, fetch, poll |
|
|
48
|
+
| Slack | Channels and DMs, messages, replies, authors, mentions, and attachments | Observe, fetch, poll |
|
|
49
|
+
| Discord | Channels, DMs, threads, messages, authors, mentions, and attachments | Observe, fetch, poll |
|
|
50
|
+
| RSS | Feeds, posts, dates, authors, and publication relationships | Observe, fetch, poll, ingest |
|
|
51
|
+
| Web | Configured pages and bookmarks with titles, text, metadata, and URLs | Observe, fetch |
|
|
52
|
+
|
|
53
|
+
These connectors are proof of the pattern, not the boundary of the product. A connector can translate an API, export, webhook, local database, browser surface, or structured file into AgentGraph's shared model.
|
|
54
|
+
|
|
55
|
+
**Bring any service into your agent's world.** Teams can keep private connectors for internal systems, individuals can connect niche tools, and open-source contributors can publish integrations for the wider community. See [Connectors](docs-src/connectors.md) and [Extending AgentGraph](docs-src/extending.md).
|
|
56
|
+
|
|
57
|
+
## Quickstart
|
|
58
|
+
|
|
59
|
+
AgentGraph requires Python 3.12+, [`uv`](https://docs.astral.sh/uv/), and Chrome for browser observation.
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
git clone https://github.com/simonexmachina/agent-graph
|
|
63
|
+
cd agent-graph
|
|
64
|
+
uv sync --extra all
|
|
65
|
+
source .venv/bin/activate
|
|
66
|
+
agentgraph onboard
|
|
67
|
+
agentgraph serve
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Install the [AgentGraph Chrome extension](https://chromewebstore.google.com/detail/agentgraph-extension/iilkfclglabllelhjacijldknapbhidi), browse a supported resource, then verify that context landed:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
agentgraph connectors
|
|
74
|
+
agentgraph search "project kickoff notes"
|
|
75
|
+
agentgraph traverse <entity-id> --depth 2
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Connect the agent you already use:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
agentgraph mcp-config
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Use the printed stdio configuration with Claude Desktop, Claude Code, Codex, or another compatible MCP client. ChatGPT developer mode uses the streamable HTTP `/mcp` endpoint through HTTPS. The [Quickstart](docs-src/quickstart.md) covers the complete path and expected result.
|
|
85
|
+
|
|
86
|
+
## What AgentGraph is and is not
|
|
87
|
+
|
|
88
|
+
| AgentGraph is | AgentGraph is not |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| Local-first infrastructure | An AI agent or autonomous assistant |
|
|
91
|
+
| A CLI and MCP server | A replacement for your agent |
|
|
92
|
+
| A searchable graph of selected context | A chatbot or LLM |
|
|
93
|
+
| An open connector architecture | A hosted integration SaaS |
|
|
94
|
+
| Semantic search plus typed entities and edges | Only a vector database |
|
|
95
|
+
| Self-hosted and open source | A project-operated store for your graph data |
|
|
96
|
+
|
|
97
|
+
## Local data and privacy
|
|
98
|
+
|
|
99
|
+
Indexed content is stored in SQLite on your machine. Provider credentials stay in the AgentGraph config directory, and source API calls run directly from your machine under your credentials. AgentGraph does not operate a hosted graph service or send indexed content to a project-controlled backend.
|
|
100
|
+
|
|
101
|
+
An MCP client you connect can receive content from the local graph, subject to that client's data practices. Read the complete [Privacy Policy](docs-src/privacy.md), [Terms of Service](docs-src/terms.md), and [retention model](docs-src/retention.md).
|
|
102
|
+
|
|
103
|
+
## Interfaces
|
|
104
|
+
|
|
105
|
+
| Surface | Use it for | Entry point |
|
|
106
|
+
| --- | --- | --- |
|
|
107
|
+
| MCP | Let an existing agent search, traverse, fetch, and manage context | `agentgraph mcp-config`, `agentgraph mcp-serve` |
|
|
108
|
+
| CLI | Search, fetch, ingest, debug, and operate the graph | `agentgraph search`, `agentgraph fetch`, `agentgraph serve` |
|
|
109
|
+
| Browser extension | Turn focused browsing on supported URLs into observations | [Chrome Web Store](https://chromewebstore.google.com/detail/agentgraph-extension/iilkfclglabllelhjacijldknapbhidi) |
|
|
110
|
+
| Viewer | Inspect entities, people, relationships, and observation state | `http://127.0.0.1:8765/viewer` |
|
|
111
|
+
|
|
112
|
+
## Documentation
|
|
113
|
+
|
|
114
|
+
- [Install](docs-src/install.md)
|
|
115
|
+
- [Quickstart](docs-src/quickstart.md)
|
|
116
|
+
- [How AgentGraph works](docs-src/how-it-works.md)
|
|
117
|
+
- [Connectors](docs-src/connectors.md)
|
|
118
|
+
- [Configuration](docs-src/configuration.md)
|
|
119
|
+
- [Commands](docs-src/commands/index.md)
|
|
120
|
+
- [MCP tools](docs-src/mcp/index.md)
|
|
121
|
+
- [Extending](docs-src/extending.md)
|
|
122
|
+
|
|
123
|
+
## Contributing
|
|
124
|
+
|
|
125
|
+
See [AGENTS.md](AGENTS.md) for repository-specific development rules. Before opening a change, run:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
uv run pytest tests/ -m "not integration" -q
|
|
129
|
+
uv run pyright
|
|
130
|
+
uv run ruff check agentgraph/ packages/ scripts/ tests/
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## License
|
|
134
|
+
|
|
135
|
+
See [LICENSE](LICENSE).
|
|
@@ -9,11 +9,20 @@ from __future__ import annotations
|
|
|
9
9
|
import json
|
|
10
10
|
import os
|
|
11
11
|
import tempfile
|
|
12
|
+
from pathlib import Path
|
|
12
13
|
from typing import Any, cast
|
|
13
14
|
|
|
14
15
|
from pydantic import BaseModel
|
|
15
16
|
|
|
16
|
-
from agentgraph.config import CONFIG_DIR, CREDENTIALS_FILE
|
|
17
|
+
from agentgraph.config import CONFIG_DIR, CREDENTIALS_FILE, get_config_paths
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _credential_paths() -> tuple[Path, Path]:
|
|
21
|
+
"""Resolve credentials dynamically while preserving local path overrides."""
|
|
22
|
+
if "AGENTGRAPH_CONFIG_DIR" in os.environ:
|
|
23
|
+
config_dir, _, _, credentials_file, _ = get_config_paths()
|
|
24
|
+
return config_dir, credentials_file
|
|
25
|
+
return CONFIG_DIR, CREDENTIALS_FILE
|
|
17
26
|
|
|
18
27
|
|
|
19
28
|
class CredentialsFileError(ValueError):
|
|
@@ -26,34 +35,36 @@ class PlatformAccounts(BaseModel):
|
|
|
26
35
|
|
|
27
36
|
|
|
28
37
|
def _load_all_credentials() -> dict[str, Any]:
|
|
29
|
-
|
|
38
|
+
_, credentials_file = _credential_paths()
|
|
39
|
+
if not credentials_file.exists():
|
|
30
40
|
return {}
|
|
31
41
|
try:
|
|
32
|
-
data = json.loads(
|
|
42
|
+
data = json.loads(credentials_file.read_text())
|
|
33
43
|
except Exception as exc:
|
|
34
44
|
# Never fall back to "no credentials" here: callers would treat a
|
|
35
45
|
# damaged file as a first-time setup and overwrite every platform.
|
|
36
46
|
raise CredentialsFileError(
|
|
37
|
-
f"Could not parse {
|
|
47
|
+
f"Could not parse {credentials_file}: {exc}. "
|
|
38
48
|
"Fix or move the file aside, then re-run auth for each platform."
|
|
39
49
|
) from exc
|
|
40
50
|
if not isinstance(data, dict):
|
|
41
51
|
raise CredentialsFileError(
|
|
42
|
-
f"Expected a JSON object at the top level of {
|
|
52
|
+
f"Expected a JSON object at the top level of {credentials_file}, got {type(data).__name__}."
|
|
43
53
|
)
|
|
44
54
|
return cast(dict[str, Any], data)
|
|
45
55
|
|
|
46
56
|
|
|
47
57
|
def _write_all_credentials(raw: dict[str, Any]) -> None:
|
|
48
|
-
|
|
58
|
+
config_dir, credentials_file = _credential_paths()
|
|
59
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
|
49
60
|
# Write via a temp file in the same directory and rename, so a concurrent
|
|
50
61
|
# writer can never leave a shorter document overlaid on a longer one.
|
|
51
|
-
fd, tmp_name = tempfile.mkstemp(dir=
|
|
62
|
+
fd, tmp_name = tempfile.mkstemp(dir=config_dir, prefix=".credentials-", suffix=".json")
|
|
52
63
|
try:
|
|
53
64
|
with os.fdopen(fd, "w") as handle:
|
|
54
65
|
json.dump(raw, handle, indent=2, default=str)
|
|
55
66
|
os.chmod(tmp_name, 0o600)
|
|
56
|
-
os.replace(tmp_name,
|
|
67
|
+
os.replace(tmp_name, credentials_file)
|
|
57
68
|
except BaseException:
|
|
58
69
|
if os.path.exists(tmp_name):
|
|
59
70
|
os.unlink(tmp_name)
|
|
@@ -64,8 +75,9 @@ def _validate_accounts(platform: str, val: dict[str, Any]) -> PlatformAccounts:
|
|
|
64
75
|
try:
|
|
65
76
|
return PlatformAccounts.model_validate(val)
|
|
66
77
|
except Exception as exc:
|
|
78
|
+
_, credentials_file = _credential_paths()
|
|
67
79
|
raise CredentialsFileError(
|
|
68
|
-
f"Stored '{platform}' credentials in {
|
|
80
|
+
f"Stored '{platform}' credentials in {credentials_file} are malformed: {exc}. "
|
|
69
81
|
f"Fix the file or re-run auth for {platform}."
|
|
70
82
|
) from exc
|
|
71
83
|
|
|
@@ -15,6 +15,7 @@ from agentgraph.core.storage import StorageBackend
|
|
|
15
15
|
logger = logging.getLogger(__name__)
|
|
16
16
|
|
|
17
17
|
_registry: dict[str, type[StorageBackend]] = {}
|
|
18
|
+
_builtin_import_errors: dict[str, ImportError] = {}
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
def _ensure_loaded() -> None:
|
|
@@ -29,8 +30,9 @@ def _load_builtins() -> None:
|
|
|
29
30
|
from agentgraph.backends.sqlite.backend import SQLiteBackend
|
|
30
31
|
|
|
31
32
|
_registry["sqlite"] = SQLiteBackend
|
|
32
|
-
except ImportError:
|
|
33
|
-
|
|
33
|
+
except ImportError as exc:
|
|
34
|
+
_builtin_import_errors["sqlite"] = exc
|
|
35
|
+
logger.debug("SQLite backend unavailable (aiosqlite not installed)", exc_info=True)
|
|
34
36
|
|
|
35
37
|
|
|
36
38
|
def _load_plugins() -> None:
|
|
@@ -44,6 +46,11 @@ def _load_plugins() -> None:
|
|
|
44
46
|
def get_backend_class(name: str) -> type[StorageBackend]:
|
|
45
47
|
_ensure_loaded()
|
|
46
48
|
if name not in _registry:
|
|
49
|
+
if name in _builtin_import_errors:
|
|
50
|
+
raise ValueError(
|
|
51
|
+
"SQLite backend is unavailable. Run this project with `uv run` or install "
|
|
52
|
+
"the project dependencies."
|
|
53
|
+
) from _builtin_import_errors[name]
|
|
47
54
|
raise ValueError(
|
|
48
55
|
f"Unknown backend {name!r}. Available: {sorted(_registry)}"
|
|
49
56
|
)
|