Skip to content

fix: toml-relative agent spec resolves against toml dir + clean TypeError for wrong-type graph on default path (gh #116, #117) - #118

Merged
dkedar7 merged 1 commit into
mainfrom
fix/116-117-toml-spec-and-wrong-type-graph
Aug 8, 2026
Merged

dkedar7 merged 1 commit into
mainfrom
fix/116-117-toml-spec-and-wrong-type-graph

Conversation

@dkedar7

@dkedar7 dkedar7 commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Ships 0.6.30, fixing two cli-local bugs.

#116 — relative agent.spec in langstage.toml resolved against cwd, not the toml's dir

Config discovery walks UP ancestor dirs to find langstage.toml, but a relative agent.spec in it (what init scaffolds: spec = "my_agent.py:graph") was resolved against the process cwd. So running from a subdirectory crashed Agent file not found even though --show-config reported the spec resolved.

Fix: a relative file spec whose source is a discovered langstage.toml now rebases onto that toml's own directory (the project root) before loading — the same way a path in pyproject.toml / tsconfig.json resolves relative to the config file. A spec from -a / LANGSTAGE_AGENT_SPEC keeps its cwd-relative base (#30 — "the file is where the user typed it"); only toml-sourced relative specs change base. The path:attr split is factored into _split_py_file_spec (Windows drive-letter safe — C:\x.py:graph) and reused by both _absolutize_file_spec (cwd) and the new _rebase_toml_file_spec (toml dir); config.toml_dir_for finds the merged file that actually defines the key.

#117 — wrong-type agent leaked AttributeError: '...' object has no attribute 'checkpointer' on the DEFAULT path

On the default persist-on path, a wrong-type agent object (graph = None, a dict, an int) crashed with a cryptic AttributeError because the durable AsyncSqliteSaver was assigned to graph.checkpointer before build_agent validated the graph. --verify and --no-persist already showed the clean message.

Fix: the durable saver assignment is guarded exactly like the non-durable _ensure_checkpointer (try/except), so a wrong-type object falls through to build_agent's actionable TypeError: build_agent expected a compiled LangGraph graph (CompiledStateGraph) ... but got NoneType. — matching --verify / --no-persist. Valid graphs are unaffected.

Tests

  • test_spec_resolution.py: init-scaffold runs from a subdir (spec resolved against the toml dir); -a stays cwd-relative alongside a langstage.toml (control).
  • test_wrong_type_graph.py: graph = None on the default config shows the clean TypeError, not the checkpointer leak, and exits non-zero.
  • Full suite: 177 passed. ruff check + ruff format --check clean.

Closes #116, closes #117.

🤖 Generated with Claude Code

https://claude.ai/code/session_011HWCfJii6gXd3XL3Gq3W8B

…rror for wrong-type graph on default path (gh #116, #117)

#116: A relative `agent.spec` in a walked-up `langstage.toml` (what `init`
scaffolds) was resolved against the process cwd, so running from a subdir
crashed `Agent file not found` even though `--show-config` reported the spec
resolved. A toml-sourced relative file spec now rebases onto the toml's own
directory (the discovered project root) — like a path in pyproject.toml /
tsconfig — while `-a`/env specs keep their cwd-relative base (#30). The
`path:attr` split is factored into `_split_py_file_spec` (Windows drive-letter
safe) and reused; `config.toml_dir_for` finds the file that defines the key.

#117: On the default persist-on path, a wrong-type agent (`graph = None`, a
dict, an int) leaked `AttributeError: 'X' object has no attribute
'checkpointer'` because the durable saver was assigned before `build_agent`
validated the graph. The assignment is now guarded like `_ensure_checkpointer`,
so the object falls through to `build_agent`'s clean `TypeError: build_agent
expected a compiled LangGraph graph ...` — matching `--verify` / `--no-persist`.

Regression tests: init-scaffold runs from a subdir (spec resolved against toml
dir) + `-a` stays cwd-relative; `graph = None` on the default config shows the
clean TypeError, not the checkpointer leak.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011HWCfJii6gXd3XL3Gq3W8B
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment