-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathpyproject.toml
More file actions
221 lines (210 loc) · 8.44 KB
/
Copy pathpyproject.toml
File metadata and controls
221 lines (210 loc) · 8.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
[project]
name = "grapharc"
version = "0.1.5"
description = "A graph engineering toolkit on LangGraph: typed state contracts, per-node write permissions, enforced budgets, and JSONL traces that double as replay points."
readme = "README.md"
license = "MIT"
license-files = ["LICENSE"]
requires-python = ">=3.12"
authors = [{ name = "Shashank Shekhar Singh" }]
keywords = [
"agents",
"agent-runtime",
"ai-agents",
"graph-engineering",
"guardrails",
"langchain",
"langgraph",
"llm",
"multi-agent",
"observability",
"orchestration",
"workflow",
]
# PEP 639 is in use (`license` is an SPDX expression), which forbids a
# `License ::` trove classifier — the expression above is the license metadata.
# The OS classifier is deliberately narrow: the sandboxed tool executor needs
# POSIX fork/setsid/killpg, and Linux is the only platform CI exercises.
classifiers = [
"Development Status :: 3 - Alpha",
"Environment :: Console",
"Intended Audience :: Developers",
"Intended Audience :: Information Technology",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
"Topic :: Software Development :: Libraries :: Python Modules",
]
dependencies = [
"langgraph>=0.4",
"langgraph-checkpoint-sqlite>=2.0",
"langchain-core>=0.3",
"pydantic>=2.7",
]
[project.urls]
Homepage = "https://github.com/CodeGraphContext/GraphARC"
Repository = "https://github.com/CodeGraphContext/GraphARC"
Issues = "https://github.com/CodeGraphContext/GraphARC/issues"
Contributing = "https://github.com/CodeGraphContext/GraphARC/blob/main/CONTRIBUTING.md"
Documentation = "https://github.com/CodeGraphContext/GraphARC/blob/main/README.md"
Roadmap = "https://github.com/CodeGraphContext/GraphARC/blob/main/ROADMAP.md"
# An extra is a dependency declaration, not a feature claim. Each comment says
# whether anything under `grapharc/` imports the dependency today; where it does
# not, the extra exists so the feature being built against it has somewhere to
# declare itself. Check ROADMAP.md before assuming an extra buys you a feature.
[project.optional-dependencies]
# Imported by grapharc/gateway/openai_compat.py, which the openrouter, openai
# and ollama backends all build on. Three extras naming one dependency is not
# duplication: `uv sync --extra ollama` is the instruction the Ollama backend
# and its probe both give, and an extra that did not exist would make that a
# lie.
openrouter = [
"langchain-openai>=0.2",
]
# Imported by grapharc/gateway/openai.py.
openai = [
"langchain-openai>=0.2",
]
# Imported by grapharc/gateway/ollama.py. Ollama speaks the OpenAI wire format,
# so the local backend needs the same client and no ollama-specific package.
ollama = [
"langchain-openai>=0.2",
]
# HTTP API surface (ROADMAP 9.1). `httpx` is in the dev group for the test client.
server = [
"fastapi>=0.115",
"uvicorn>=0.32",
]
# MCP client (ROADMAP 3.5).
mcp = [
"mcp>=1.2",
]
# LadybugDB-backed claim store — grapharc/memory/ladybug_store.py imports this
# one, unlike the `memory` extra above. The distribution is `real-ladybug`, not
# `ladybug`: the latter name belongs to Ladybug Tools, an unrelated
# building-science package.
ladybug = [
"real-ladybug>=0.15.3",
]
# OpenTelemetry export (ROADMAP 10.3).
otel = [
"opentelemetry-api>=1.27",
"opentelemetry-sdk>=1.27",
"opentelemetry-exporter-otlp-proto-http>=1.27",
]
# Direct Anthropic API backend (ROADMAP 2.4). Nothing imports `anthropic` today;
# the shipped Anthropic path is the Claude Code CLI adapter, which needs no SDK.
api = [
"anthropic>=0.40",
]
# Imported (lazily) by grapharc/slack/bot.py: the Socket Mode bot that runs the
# CLI from a Slack workspace. Everything else in grapharc/slack/ is stdlib-only.
slack = [
"slack-bolt>=1.20",
]
# Everything above. Self-referential so it cannot drift out of sync.
all = [
"grapharc[api,ladybug,mcp,ollama,openai,openrouter,otel,server,slack]",
]
[dependency-groups]
dev = [
"httpx>=0.27",
"pytest>=8.2",
"pytest-asyncio>=0.24",
"pytest-timeout>=2.3",
"ruff>=0.5",
]
[project.scripts]
grapharc = "grapharc.cli.main:main"
[build-system]
requires = ["hatchling>=1.27"]
build-backend = "hatchling.build"
# `.gitignore` must not get a vote on what ships. Hatchling's default is to
# treat VCS ignore rules as build exclusions, and that is a silent, total
# failure mode: adding `grapharc/tools/` to .gitignore was verified to drop the
# entire subpackage from the wheel with no error, no warning, and a build that
# reports success. `pip install grapharc` then fails at `import grapharc.tools`.
# With `ignore-vcs = true` the two lists below are the only thing that decides,
# so the junk .gitignore used to keep out has to be named here instead.
[tool.hatch.build]
ignore-vcs = true
exclude = [
"**/__pycache__",
"**/*.py[cod]",
"**/.pytest_cache",
"**/.ruff_cache",
"**/*.sqlite",
"**/*.jsonl",
# An internal working note, not documentation. It carries local paths and
# account details, and `.gitignore` cannot keep it out of a build because
# `ignore-vcs` is on — this line is the only thing that does.
"/HANDOFF.md",
"/.grapharc",
# Demo footage embedded in the README. GitHub renders it; a pip install
# has no use for megabytes of GIF, so it stays out of the sdist.
"/docs/media",
]
# `packages` is recursive: every subpackage under `grapharc/` ships without
# being named. Confirmed against a built wheel, which contains planner, policy,
# server, session and tools; `tests/test_packaging.py` fails if a new one is
# ever added in a way that keeps it out.
[tool.hatch.build.targets.wheel]
packages = ["grapharc"]
# Hatchling does not read MANIFEST.in — that is a setuptools file, and editing
# it alone changes nothing about this build (verified by building with
# directives in it). MANIFEST.in exists anyway, mirrors this list, and ships;
# `tests/test_packaging.py` fails if the two drift, so it cannot become a lie.
# This list is the authority.
#
# Sdist contents are an allowlist rather than a denylist so that a new top-level
# file cannot be published by accident. Add new shipped paths here.
[tool.hatch.build.targets.sdist]
include = [
"/grapharc",
"/tests",
# `/docs` ships because six `tests/test_cookbook_*.py` modules read their
# page at *import* time. Without it `pytest` inside an unpacked sdist dies
# with five collection errors rather than running.
"/docs",
"/*.md",
"/LICENSE",
"/MANIFEST.in",
"/pyproject.toml",
"/uv.lock",
]
[tool.pytest.ini_options]
testpaths = ["tests"]
# Live tests spend real money and real quota, so they are opt-in: run them
# with `pytest -m live`. Without this they ran on every plain `pytest`.
#
# `--strict-markers` is part of that guarantee, not a style preference. An
# unregistered marker is only a warning by default, so `@pytest.mark.lvie` on a
# paid test does not match `-m 'not live'`, is not deselected, and calls the API
# on a plain `pytest`. Reproduced before this flag was added; the CI
# `live-marker-guard` does not catch it either, because a typo'd test is absent
# from *both* selections and so their intersection stays empty. `--strict-config`
# does the same job for a typo in this table.
addopts = "-q -m 'not live' --strict-markers --strict-config"
# Registering a marker below does not install the plugin that gives it meaning.
# `timeout` and `asyncio` come from plugins, and naming them here would make a
# missing plugin silent under `--strict-markers` — tests would collect with no
# timeout at all, or coroutines would never be awaited. `required_plugins` is
# what closes that: pytest refuses to start if either plugin is absent.
required_plugins = ["pytest-asyncio", "pytest-timeout"]
markers = [
"live: calls a real model backend; costs money. Opt in with `-m live`.",
"asyncio: run this coroutine test on an event loop (pytest-asyncio).",
"timeout: cap this test's wall clock in seconds (pytest-timeout).",
]
# Explicit, because the suite marks every coroutine test by hand. Under `auto`
# an unmarked coroutine would silently start running instead of being reported.
asyncio_mode = "strict"
[tool.ruff]
line-length = 100
target-version = "py312"
[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B"]