[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "langstage" version = "0.13.65" description = "The web stage for your LangGraph agent — AI-powered workspace with streaming, file browser, and canvas" readme = "README.md" license = "MIT" requires-python = ">=3.11" dependencies = [ "fastapi>=0.115", "uvicorn[standard]>=0.30", # Since core 1.0 (ADR 0003) the SessionAdapter streams every turn ONLY through # the in-process AG-UI adapter, so the AG-UI runtime (ag-ui-langgraph[fastapi], # via core's [agui] extra) is a HARD dep. fastapi + uvicorn are already base # deps above, so [agui] mainly adds ag-ui-langgraph itself. # >=1.0.6 for the shared preflight primitive core.verify() used by `check --live`. # >=1.0.9 for the relative-workspace idempotency fix (#66): _enter_workspace() # chdirs into the workspace, and pre-1.0.9 workspace_root() doubled a relative root. # >=1.0.32 for per-file TOML source provenance in resolve() (a global-config value is # no longer mislabeled as coming from the project langstage.toml, gh #119) and for # HostConfig.unknown_toml_keys() + describe() surfacing typo'd/unknown keys (gh #120). # >=1.0.33 for the resolver's port-range validator: an out-of-range port (70000) from # env / TOML / a Python override now degrades to the default + a note instead of being # silently masked to 16 bits by uvicorn at bind time (gh #123). # >=1.0.36 for: a file.py:attr agent importing its sibling modules (gh #167); # load_agent_spec(stdout_to_stderr=) so `check --json` / `chat --json` stay pure JSON # (gh #140); config_dict()/config_issues() reporting a malformed langstage.toml and # every degraded value (gh #170, #138); langstage_core.console.safe_print (gh #146); # the DEEPAGENTS_CONFIG_HOME legacy notice (gh #136); a resolved-debug traceback on the # error frame (gh #134); stdlib typing.TypedDict state on 3.11 (gh #166); and a real # tool duration_ms on tool_end (gh #160). # >=1.0.37 for node attribution taken from each step's own update, so tool_start / # content carry the right node under the async SQLite checkpointer (gh #173). "langstage-core[agui]>=1.0.60", # Any real use of langstage already has langgraph in the env (it is the # thing being hosted); declaring it makes `run --demo` work on a bare install. "langgraph>=1.0", # CanvasMiddleware subclasses langchain.agents.middleware on import, and # langstage.middleware is imported on hot paths (app, cli `check`, default # agent) — so langchain is a HARD dep, not incidental via [deepagents]. "langchain>=1.0", "watchfiles>=1.0", "click>=8.0", "python-dotenv>=1.0", "pydantic>=2.0", "python-multipart>=0.0.12", "croniter>=2.0", # Durable task store for the async task board (TaskRunner persistence). "aiosqlite>=0.19", # Durable agent checkpointer (auto-attached) so conversation/interrupt state # and the task review gate survive restarts. "langgraph-checkpoint-sqlite>=2.0", ] [project.optional-dependencies] deepagents = [ # <1.0: deepagents 1.0 changes the create_deep_agent model contract (gh #169). "deepagents>=0.3,<1.0", ] # Redundant since AG-UI moved into base deps (core 1.0); kept as a no-op alias so # existing `pip install langstage[agui]` scripts/READMEs still resolve. agui = [ "langstage-core[agui]>=1.0.60", ] dev = [ "pytest>=8", "pytest-asyncio>=0.24", "httpx>=0.27", "ruff>=0.5", # AG-UI runtime for the SessionAdapter's only streaming path (base deps pull # this via core's [agui] extra; pinned here too so the test env is explicit). "ag-ui-langgraph>=0.0.41", ] [project.scripts] langstage = "langstage.cli:main" # Deprecated alias command — kept for one transition window. cowork-dash = "langstage.cli:main" [tool.hatch.build] artifacts = ["langstage/static/**"] # Build the React/Vite SPA into langstage/static/ before the wheel is assembled, so a # published wheel actually ships the web UI (gh #94). Without this, `artifacts` above only # re-includes the git-ignored static/ tree *if it already exists* — a plain `uv build` # never built it, so 0.13.20–0.13.23 shipped no frontend. See hatch_build.py. The hook is # a no-op for editable installs (`pip install -e`) and skips when the SPA is already built, # so Node is only needed to cut a real release wheel. `uv build` builds the wheel from the # sdist, and both hatch_build.py and frontend/ (needed by the hook) are VCS-tracked and so # ship in the default sdist. [tool.hatch.build.targets.wheel.hooks.custom] path = "hatch_build.py" [tool.hatch.build.targets.wheel] packages = ["langstage", "cowork_dash"] [tool.pytest.ini_options] asyncio_mode = "auto"