13 Commits
Author SHA1 Message Date
arc53-machine f6269c483f Add execution-trace settings and declare opentelemetry-api
TRACES_* settings for the per-request trace timeline and its GenAI OTel
export. opentelemetry-api was only transitive; the tracing package
imports it directly.
2026-09-23 17:14:51 +01:00
arc53-machine 53facb460c chore: add Zed project config, .editorconfig and shared pyright settings
- .zed/settings.json: ruff + basedpyright for Python (no format on save, the
  tree is not ruff-format clean), ESLint fixes then Prettier for the frontend,
  scan exclusions for caches and build outputs, .jwt_secret_key as private
- .zed/tasks.json: dev services, API, worker, frontend, pytest/vitest for the
  current file or test, linting, uv lock + requirements export
- .zed/debug.json: debugpy targets matching .vscode/launch.json
- .editorconfig: whitespace rules for every editor
- [tool.pyright] in pyproject.toml: venv, import root and excludes shared by
  pyright, basedpyright and Pylance
- .gitignore: track only the shared files under .zed/
- CONTRIBUTING: editor setup section; fix the stale ESLint config path
2026-09-21 16:10:31 +01:00
Alex aa0e4ea280 feat: docsgpt up runs and manages DocsGPT on Docker
`docsgpt up` copies the standalone Compose file shipped with this package
version into the stack directory (~/.docsgpt/server by default), writes its
.env and starts the stack on the images of the same version. A first run
asks who should reach DocsGPT (this computer, the network with a token, or a
domain with HTTPS) and which model provider to use; flags answer the same
questions for scripts. Re-running keeps secrets and settings and moves the
image tag, and the database password is only generated for a new database.

Also: down, status, logs, token, open, env, upgrade (uv tool installs
upgrade themselves and run `up` again) and uninstall (keeps settings and
data unless --purge). The commands import no Flask, Celery or settings.

The wheel carries deployment/docker-compose-standalone.yaml as
docsgpt/deploy/docker-compose.yaml; the sdist includes the source file.
2026-09-15 22:57:00 +01:00
Alex 762686b520 chore(deps): torch 2.14, transformers 5.17, tokenizers 0.23 (docling extra)
Lifts the deliberate `transformers<5.9` cap. The cap existed because 5.9
broke docling's PDF layout model on Apple Silicon; 5.17 does not. Checked by
converting a four-document benchmark (two papers, a 30-page table corpus, a
10-page report) on this machine with both stacks: the Markdown is
byte-identical on three, and the fourth differs only by one dropped
`<!-- image -->` placeholder on a figure. Tables still render as GFM tables
and no text is lost.

With that cap gone tokenizers can move too — transformers 5.8.1 pinned it at
<=0.23.0 and no such release exists, which is what held it at 0.22.2.
torchvision follows torch.

Linux still resolves torch and torchvision from the CPU-only PyTorch index,
so the docling Docker variant does not pick up the CUDA stack.
2026-09-12 18:15:03 +01:00
Alex 108b8fd56b chore(deps): fastmcp 4 (mcp 2.2)
No code change needed: the server side (`FastMCP`, `@mcp.tool`,
`get_http_headers`, `http_app`) and the client side (`Client`, `BearerAuth`,
the three transports, and the `mcp.client.auth` / `mcp.shared.auth` OAuth
types imported directly) all kept their signatures.

Verified beyond the suite by driving the real `/mcp` mount over a live
uvicorn socket with the fastmcp client: tool discovery, a `search_docs` call
and bearer-token extraction all round-trip, with the token reaching
`search()` intact.

fastmcp 4 and mcp 2.2 also moved to httpx2, so the retry tuple's comment now
places them on that side of the split.
2026-09-12 17:54:18 +01:00
Alex f7baa1952f chore(deps): anthropic 1.5, openai 3.13, and the move to httpx2
Both SDKs' 1.x/3.x majors run on httpx2 (the maintained fork of httpx by its
original author, published by Pydantic at github.com/pydantic/httpx2, version
line 2.x) instead of httpx, which is what makes these two bumps one change.
httpx2 is now a declared dependency because two modules import it directly.
Everything else in the 0.x -> 1.x / 2.x -> 3.x change lists is absent here:
no Text Completions, no `with_raw_response`, no raw `output_format` dicts, no
Bedrock client, and `requires-python` is already 3.12.

Three code changes, all forced by the bump:

The BYOM DNS-pinning client in `docsgpt/security/safe_url.py` is handed to
`OpenAI(http_client=...)`, and the SDK rejects an old-httpx client at
construction — which would have taken the SSRF guard offline. It is built on
httpx2 now, and its `sni_hostname` extension carries a `str` rather than
ascii bytes: httpcore passes the value straight to
`ssl.SSLContext.wrap_socket`, and the truststore backend httpx2 uses for the
default system trust store encodes it instead of accepting bytes. Bytes
therefore failed every real handshake while passing the existing tests, which
stub the transport out; the test now pins the type and says why.

The stream-retry error tuple in `docsgpt/llm/base.py` named `httpx`
exceptions only. The two libraries' exception classes are unrelated types, so
after the bump the retry silently stopped firing for openai and anthropic
while still working for google-genai and elevenlabs. It now covers both
stacks, with a parametrized test over each.

anthropic 1.x dropped temperature/top_p/top_k from `messages.create`'s
signature (passing one raises TypeError) without dropping them from the API,
so the provider forwards them through `extra_body`. The wire request is
unchanged and a model that rejects them 400s exactly as before.
2026-09-12 17:44:18 +01:00
Alex b3326b3c33 chore(deps): redis 8, tiktoken 0.14, openapi3-parser 2, daytona 0.211, reportlab 5
Major bumps whose ceilings had to move. redis 8.1.0, tiktoken 0.14.0 and
daytona 0.211.2 needed no code change (the Daytona client, filesystem and
process signatures the sandbox calls are unchanged; redis 8 was checked
against a live server through the app's own sync and async clients).
reportlab 5.0.1 is test-only.

openapi-parser 2.0.0 is a rewrite onto pydantic spec models: `paths` is now
a dict keyed by URL rather than a list of objects carrying their own `url`,
and a path item exposes one field per HTTP method instead of an `operations`
list. `OpenAPI3Parser` reads both accordingly, iterating methods in the
order the spec declares them, and its rendered output is byte-identical to
before. The rewrite also drops prance, openapi-spec-validator and five more
transitive packages.

tokenizers stays at 0.22.2: transformers 5.8.1 caps it at <=0.23.0 and no
such release exists, so it moves with the transformers cap or not at all.
2026-09-12 17:28:58 +01:00
Alex 7e00197678 chore(deps): upgrade backend deps within their declared ranges
`uv lock --upgrade` plus the two code changes the new versions need.

firecrawl-anydoc 0.2.4 raises a dedicated `NeedsOcrError` where 0.2.3 raised
`UnsupportedError("... OCR is required")`, so the anydoc parser no longer
recognised a scanned PDF: the fallback still ran, but a near-empty result was
stored as an empty document instead of failing with the OCR_ENABLED hint.
`_needs_ocr` now accepts both spellings and looks the class up lazily, so an
older anydoc keeps working. 0.2.4 also refuses the CID-font NDA fixture
outright rather than dropping its Chinese column silently, so the PDF
trust-check tests stub that dropped output against the fixture's real bytes
(the check's own inputs) and a new test pins the refusal path.

ruff 0.16 widened its implicit default rule set, turning the dev-group bump
into 7131 findings across the tree. `.ruff.toml` now states the historical
selection (E4, E7, E9, F) explicitly and the CI pin moves to the locked
0.16.7, so lint no longer drifts with the version.
2026-09-12 17:16:59 +01:00
Alex 43f493b926 feat(package): ship the web UI in the wheel and serve it from the API
pip install docsgpt now brings the web UI with it: `docsgpt api` serves the
API and the UI on one port.

- scripts/build_frontend.sh builds the frontend into docsgpt/static
  (gitignored) the way the frontend image does: .env.development as the
  production baseline, and index.html loading /config.js ahead of the
  bundle. hatch admits the directory into the wheel and the sdist through
  `artifacts`; the package workflows run the script before `uv build` and
  fail if the wheel lacks the UI. The backend image keeps ignoring it.
- docsgpt/ui.py serves the build in front of Flask: files as they are,
  hashed assets immutable, Flask's own path prefixes (taken from its URL map,
  so new blueprints need no registration) passed through, every other GET
  rendered as index.html for the client-side router. /config.js is generated
  per request with VITE_API_HOST and VITE_BASE_URL set to the page's origin,
  VITE_* environment variables winning. SERVE_UI=false leaves the API alone.
- docsgpt api configures gunicorn in code (gunicorn.app.base.Application)
  instead of rewriting sys.argv, so the SIGUSR2 re-exec that gunicorn uses
  for zero-downtime upgrades runs the docsgpt console script again and
  works; verified with a live handover.
- Docs: the pip page says the UI is included, that DOCSGPT_HOME and
  DOCSGPT_ENV_FILE are process environment variables rather than .env
  entries, and the settings page describes SERVE_UI.
2026-09-09 11:09:09 +01:00
Alex ae9348bb2a fix(package): review pass on the PyPI package
- docsgpt api binds 127.0.0.1 by default, like gunicorn and uvicorn do;
  --host 0.0.0.0 exposes it. The docs say so.
- The embedded Milvus and LanceDB defaults derive from the data home, so
  they follow DOCSGPT_HOME like the faiss indexes and uploads do. A checkout
  run from its root and the Docker image resolve to the same paths as before.
- The docs and the pyproject comment describe the CPU torch install as two
  steps (torch and torchvision from the PyTorch CPU index first, then the
  docling extra): pip picks the highest version across indexes, so
  --extra-index-url only yields the CPU build while that index keeps pace
  with PyPI.
- AGENTS.md separates DOCSGPT_HOME (moves the data home) from
  DOCSGPT_ENV_FILE (selects the .env file); the docs example uses a password
  placeholder.
2026-09-07 15:25:30 +01:00
Alex bea26336f8 feat: publish the backend to PyPI as docsgpt
pip install docsgpt (extras: docling, milvus) installs the backend with a
docsgpt command: api, worker, migrate, prefetch-models, verify-offline,
reembed. Second step of the PyPI work after the package rename.

- hatchling build; the version comes from docsgpt/version.py. The wheel is
  the docsgpt package with the data it reads at runtime (prompts, model
  catalogs, seed config, alembic.ini and migrations) and without the
  Dockerfile, the exported requirements, the sample index and local runtime
  data. The application import alias stays checkout-only. uv sync installs
  the package editable now that [tool.uv] package = false is gone.
- docsgpt/cli.py: api (gunicorn + BoundedDrainUvicornWorker with the image's
  flags, --reload for uvicorn), worker (Celery worker with beat embedded,
  --no-beat/-Q/--concurrency/--pool, solo pool on macOS), migrate, and
  argument pass-through to the maintenance scripts. --help imports no app.
- docsgpt/core/paths.py: runtime data lives in a data home (DOCSGPT_HOME,
  else the checkout, else cwd); DOCSGPT_ENV_FILE overrides the env file.
  Settings, the dotenv load, LocalStorage and the internal upload route use
  it instead of "three directories above this file", which is site-packages
  for an installed package. A checkout and the Docker image behave as before.
- [project] dependencies are compatible ranges so the package installs next
  to other packages; uv.lock resolves to the same versions and the exported
  requirements files are unchanged.
- package-build.yml builds and checks the wheel on PRs and installs it into
  a clean venv; pypi-publish.yml publishes on a published release through
  trusted publishing (environment pypi), or to TestPyPI on a manual run.
- Docs: Deploying -> Install with pip. AGENTS.md notes the package.
2026-09-07 14:40:35 +01:00
Alex 574f96341e refactor: rename the application package to docsgpt
The backend import package is now docsgpt, the name it will carry on PyPI;
application was far too generic to install into anyone's site-packages.
git mv plus a mechanical rewrite of every import, dotted string and path
reference: 734 Python files, the compose files, Dockerfile, workflows, docs,
setup scripts, devcontainer, k8s manifests, vscode config, pytest and coverage
config, .gitignore. Behaviour is unchanged.

Kept for one release:
- A top-level application package whose meta-path finder resolves
  application.x.y to the already-imported docsgpt.x.y object, so old imports
  and entry points (celery -A application.app.celery,
  uvicorn application.asgi:asgi_app) keep working with a FutureWarning.
- Celery registers every application.* task name as an alias of its
  docsgpt.* task on start-up, so messages queued by the previous release still
  run. The redbeat key prefix moves to redbeat:docsgpt:v2: so schedule entries
  the previous release wrote are left unread instead of firing twice.

The backend image builds from the repository root (docker build -f
docsgpt/Dockerfile .) so it can ship the alias package; a root .dockerignore
allow-lists docsgpt/ and application/ and keeps caches, local data, .env
files, the sample index files and the Dockerfile out. Compose and the image
workflows point at the new context.
2026-09-07 10:20:43 +01:00
Alex 196865846c build(deps): declare dependencies in pyproject.toml with docling and milvus extras
requirements.txt pinned torch and transformers in core although only docling
needs them, and on Linux torch pulls the CUDA 13 stack: 2.7 GB of the 3.0 GB
wheel download. Direct dependencies now live in pyproject.toml, uv.lock pins
everything, and application/requirements*.txt are exported from the lock by
scripts/export_requirements.sh (each file is the core set plus one extra).

The docling extra pins torch/torchvision/transformers itself and, on Linux,
resolves torch from the CPU-only PyTorch index (no nvidia packages). milvus
(pymilvus + milvus-lite, which pulls pyarrow) is the second extra.

application/core/optional_deps.py is the one place install hints come from;
the milvus store and the docling call sites use it so a missing extra fails
with the exact command to run.
2026-09-05 15:50:20 +01:00