langstage-cli 0.6.6__tar.gz → 0.6.8__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.
- {langstage_cli-0.6.6/langstage_cli.egg-info → langstage_cli-0.6.8}/PKG-INFO +4 -2
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/README.md +3 -1
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/langstage_cli/agui_stream.py +8 -3
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/langstage_cli/cli.py +14 -4
- {langstage_cli-0.6.6 → langstage_cli-0.6.8/langstage_cli.egg-info}/PKG-INFO +4 -2
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/langstage_cli.egg-info/SOURCES.txt +1 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/pyproject.toml +1 -1
- langstage_cli-0.6.8/tests/test_configurable.py +37 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_quiet_output.py +8 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/LICENSE +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/deepagent_code/__init__.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/langstage_cli/__init__.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/langstage_cli/config.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/langstage_cli.egg-info/dependency_links.txt +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/langstage_cli.egg-info/entry_points.txt +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/langstage_cli.egg-info/requires.txt +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/langstage_cli.egg-info/top_level.txt +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/setup.cfg +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_agui_stream.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_checkpointer.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_cli.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_cli_help.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_codeconfig.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_config.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_help_render.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_no_interactive_approve.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_rename_shim.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_show_config.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_spec_resolution.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_stream_mode.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_streaming_marker.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_turn_exit_and_render.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_unicode_console.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_verify_flag.py +0 -0
- {langstage_cli-0.6.6 → langstage_cli-0.6.8}/tests/test_workspace.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langstage-cli
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.8
|
|
4
4
|
Summary: The terminal stage for your LangGraph agent — Claude Code-style CLI for any CompiledGraph
|
|
5
5
|
Author-email: Kedar Dabhadkar <kdabhadk@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -41,7 +41,9 @@ Dynamic: license-file
|
|
|
41
41
|
|
|
42
42
|
> Renamed from **deepagent-code** (the old package name now just installs this one, and the `deepagent-code` command still works). Not to be confused with LangChain's **`deepagents-code`** (`dcode`) — that's a separate project; `langstage-cli` is the terminal stage of the [LangStage family](#every-stage-for-your-langgraph-agent).
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
<p align="center">
|
|
45
|
+
<img src="assets/header.svg" alt="langstage-cli — the terminal stage for your LangGraph agent" width="100%" />
|
|
46
|
+
</p>
|
|
45
47
|
|
|
46
48
|
## Every stage for your LangGraph agent
|
|
47
49
|
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
> Renamed from **deepagent-code** (the old package name now just installs this one, and the `deepagent-code` command still works). Not to be confused with LangChain's **`deepagents-code`** (`dcode`) — that's a separate project; `langstage-cli` is the terminal stage of the [LangStage family](#every-stage-for-your-langgraph-agent).
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
<p align="center">
|
|
8
|
+
<img src="assets/header.svg" alt="langstage-cli — the terminal stage for your LangGraph agent" width="100%" />
|
|
9
|
+
</p>
|
|
8
10
|
|
|
9
11
|
## Every stage for your LangGraph agent
|
|
10
12
|
|
|
@@ -30,13 +30,18 @@ def ensure_agui_available() -> None:
|
|
|
30
30
|
raise RuntimeError(_IMPORT_HINT) from e
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
def build_session_agent(graph: Any, *, name: str = "langstage-cli") -> Any:
|
|
33
|
+
def build_session_agent(graph: Any, *, name: str = "langstage-cli", config: Any = None) -> Any:
|
|
34
34
|
"""Wrap a compiled graph once per session (checkpointer attached by the core
|
|
35
|
-
bridge), so multi-turn memory persists across turns.
|
|
35
|
+
bridge), so multi-turn memory persists across turns.
|
|
36
|
+
|
|
37
|
+
``config`` (a ``RunnableConfig``, e.g. ``{"configurable": {...}}`` seeded from
|
|
38
|
+
``langstage.toml``'s ``[configurable]`` table) is forwarded to the graph on
|
|
39
|
+
every turn, so keys beyond ``thread_id`` actually reach the agent. (gh #57)
|
|
40
|
+
"""
|
|
36
41
|
ensure_agui_available()
|
|
37
42
|
from langstage_core.agui import build_agent
|
|
38
43
|
|
|
39
|
-
return build_agent(graph, name=name)
|
|
44
|
+
return build_agent(graph, name=name, config=config)
|
|
40
45
|
|
|
41
46
|
|
|
42
47
|
async def agui_stream_updates(
|
|
@@ -173,12 +173,13 @@ def rl_wrap(code: str) -> str:
|
|
|
173
173
|
return code
|
|
174
174
|
|
|
175
175
|
|
|
176
|
-
def make_prompt(text: str = "❯", color: str =
|
|
176
|
+
def make_prompt(text: str = "❯", color: str | None = None) -> str:
|
|
177
177
|
"""Create a prompt string with proper readline escaping for ANSI codes.
|
|
178
178
|
|
|
179
179
|
This prevents line wrapping issues on Windows and other terminals.
|
|
180
180
|
"""
|
|
181
|
-
|
|
181
|
+
prompt_color = BRIGHT_BLUE if color is None else color
|
|
182
|
+
return f"{rl_wrap(BOLD)}{rl_wrap(prompt_color)}{text}{rl_wrap(RESET)} "
|
|
182
183
|
|
|
183
184
|
|
|
184
185
|
def register_command(
|
|
@@ -1328,12 +1329,21 @@ def run_conversation_loop(
|
|
|
1328
1329
|
# the core bridge) so multi-turn memory persists. Since langstage-core 1.0 the
|
|
1329
1330
|
# AG-UI adapter is the only streaming path.
|
|
1330
1331
|
thread_id = ""
|
|
1332
|
+
configurable: Dict[str, Any] = {}
|
|
1331
1333
|
if isinstance(config, dict):
|
|
1332
|
-
|
|
1334
|
+
configurable = dict(config.get("configurable", {}))
|
|
1335
|
+
thread_id = configurable.get("thread_id", "") or ""
|
|
1333
1336
|
from langstage_cli.agui_stream import build_session_agent
|
|
1334
1337
|
|
|
1338
|
+
# Forward the resolved `[configurable]` table (minus thread_id, which the
|
|
1339
|
+
# adapter sets per-run) to the graph, so keys beyond thread_id — the documented
|
|
1340
|
+
# way to parameterize an agent — actually reach it instead of being silently
|
|
1341
|
+
# dropped while /config advertises them. (gh #57)
|
|
1342
|
+
configurable.pop("thread_id", None)
|
|
1343
|
+
session_config = {"configurable": configurable} if configurable else None
|
|
1344
|
+
|
|
1335
1345
|
try:
|
|
1336
|
-
agui_agent = build_session_agent(graph, name=agent_name)
|
|
1346
|
+
agui_agent = build_session_agent(graph, name=agent_name, config=session_config)
|
|
1337
1347
|
except RuntimeError as e:
|
|
1338
1348
|
_status(f"{RED}⏺ {e}{RESET}")
|
|
1339
1349
|
return
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langstage-cli
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.8
|
|
4
4
|
Summary: The terminal stage for your LangGraph agent — Claude Code-style CLI for any CompiledGraph
|
|
5
5
|
Author-email: Kedar Dabhadkar <kdabhadk@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -41,7 +41,9 @@ Dynamic: license-file
|
|
|
41
41
|
|
|
42
42
|
> Renamed from **deepagent-code** (the old package name now just installs this one, and the `deepagent-code` command still works). Not to be confused with LangChain's **`deepagents-code`** (`dcode`) — that's a separate project; `langstage-cli` is the terminal stage of the [LangStage family](#every-stage-for-your-langgraph-agent).
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
<p align="center">
|
|
45
|
+
<img src="assets/header.svg" alt="langstage-cli — the terminal stage for your LangGraph agent" width="100%" />
|
|
46
|
+
</p>
|
|
45
47
|
|
|
46
48
|
## Every stage for your LangGraph agent
|
|
47
49
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "langstage-cli"
|
|
7
|
-
version = "0.6.
|
|
7
|
+
version = "0.6.8"
|
|
8
8
|
description = "The terminal stage for your LangGraph agent — Claude Code-style CLI for any CompiledGraph"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""The langstage.toml [configurable] table reaches the graph (gh #57).
|
|
2
|
+
|
|
3
|
+
`/config` and `--show-config` advertise that `[configurable]` seeds LangGraph's
|
|
4
|
+
`RunnableConfig.configurable`, but the AG-UI streaming path used to forward only
|
|
5
|
+
`thread_id` — every other key was silently dropped. The session agent now carries
|
|
6
|
+
the resolved configurable, so a node's `config["configurable"]` sees it.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from click.testing import CliRunner
|
|
10
|
+
|
|
11
|
+
from langstage_cli.cli import main
|
|
12
|
+
|
|
13
|
+
_CFG_AGENT = (
|
|
14
|
+
"from langgraph.graph import StateGraph, START, END\n"
|
|
15
|
+
"from langgraph.graph.message import MessagesState\n"
|
|
16
|
+
"from langchain_core.messages import AIMessage\n"
|
|
17
|
+
"def respond(state, config):\n"
|
|
18
|
+
" c = (config or {}).get('configurable', {})\n"
|
|
19
|
+
" return {'messages': [AIMessage(content='custom_key=' + str(c.get('custom_key')))]}\n"
|
|
20
|
+
"g = StateGraph(MessagesState)\n"
|
|
21
|
+
"g.add_node('respond', respond)\n"
|
|
22
|
+
"g.add_edge(START, 'respond')\n"
|
|
23
|
+
"g.add_edge('respond', END)\n"
|
|
24
|
+
"graph = g.compile()\n"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_configurable_toml_reaches_the_graph(tmp_path, monkeypatch):
|
|
29
|
+
monkeypatch.chdir(tmp_path)
|
|
30
|
+
(tmp_path / "langstage.toml").write_text('[configurable]\ncustom_key = "from-toml"\n')
|
|
31
|
+
agent = tmp_path / "cfg_agent.py"
|
|
32
|
+
agent.write_text(_CFG_AGENT)
|
|
33
|
+
|
|
34
|
+
r = CliRunner().invoke(main, ["-a", f"{agent}:graph", "hi"])
|
|
35
|
+
assert r.exit_code == 0, r.output
|
|
36
|
+
# The node saw the [configurable] value, not None.
|
|
37
|
+
assert "custom_key=from-toml" in r.output, r.output
|
|
@@ -36,6 +36,14 @@ def test_quiet_flag_forces_clean_output(tmp_path, monkeypatch):
|
|
|
36
36
|
assert "\x1b[" not in r.output and "⏺" not in r.output, r.output
|
|
37
37
|
|
|
38
38
|
|
|
39
|
+
def test_make_prompt_uses_disabled_color_globals_after_ansi_is_disabled():
|
|
40
|
+
c._disable_ansi()
|
|
41
|
+
|
|
42
|
+
prompt = c.make_prompt()
|
|
43
|
+
|
|
44
|
+
assert "\x1b[" not in prompt, repr(prompt)
|
|
45
|
+
|
|
46
|
+
|
|
39
47
|
def test_errors_go_to_stderr_not_stdout(tmp_path, monkeypatch):
|
|
40
48
|
# A failed single-shot run must keep stdout clean so a scripted caller can
|
|
41
49
|
# consume the (empty) reply and read the diagnostic off stderr / the exit code.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|