Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 52 additions & 3 deletions libs/code/deepagents_code/client/commands/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,15 @@ def setup_config_parser(
help="Show the effective value and source for one option",
add_help=False,
)
get_parser.add_argument("key", help="Option key (e.g. interpreter.memory_limit_mb)")
# Optional so a bare `config get` reaches our handler with a useful hint
# (available keys + examples) instead of argparse's terse "the following
# arguments are required: key".
get_parser.add_argument(
"key",
nargs="?",
default=None,
help="Option key (e.g. interpreter.memory_limit_mb)",
)
get_parser.add_argument(
"-h",
"--help",
Expand Down Expand Up @@ -512,12 +520,53 @@ def _print_config_verbose(
console.print()


def _run_get(key: str, output_format: OutputFormat) -> int:
_GET_KEY_EXAMPLE = "interpreter.memory_limit_mb"
"""Illustrative key shown in the missing-key hint.

A unit test asserts this stays a real manifest key so the hint never points at a
key that `config get` would reject.
"""


def _report_missing_get_key(output_format: OutputFormat) -> int:
"""Explain that `config get` needs a key, and point at how to find one.

Reached when the user runs a bare `config get` (the `key` positional is
optional so this handler can render a useful hint instead of argparse's
terse usage error).

Returns:
Exit code `2`, matching argparse's convention for a usage error so
existing scripts see the same code they did before.
"""
from deepagents_code.config_manifest import option_keys

if output_format == "json":
write_json(
"config get",
{"error": "missing key", "keys": list(option_keys())},
)
return 2

print( # noqa: T201
f"`dcode config get` needs an option key, e.g. `dcode config get "
f"{_GET_KEY_EXAMPLE}`. Run `dcode config` to list options and their "
"effective values, or `dcode config --verbose` to see every key.",
file=sys.stderr,
)
return 2


def _run_get(key: str | None, output_format: OutputFormat) -> int:
"""Resolve and print a single option by key.

Returns:
Process exit code (`0` on success, `1` for an unknown key).
Process exit code (`0` on success, `1` for an unknown key, `2` when no
key was given).
"""
if key is None:
return _report_missing_get_key(output_format)

from deepagents_code.config_manifest import get_option

option = get_option(key)
Expand Down
27 changes: 27 additions & 0 deletions libs/code/tests/unit_tests/test_config_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1266,6 +1266,33 @@ def test_run_get_unknown_key_returns_error_code(capsys) -> None:
assert "config --verbose" in err


def test_run_get_missing_key_hints_available_keys(capsys) -> None:
"""Bare `config get` explains it needs a key and where to find one."""
args = argparse.Namespace(config_command="get", key=None, output_format="text")
assert run_config_command(args) == 2
err = capsys.readouterr().err
assert "needs an option key" in err
assert "dcode config" in err


def test_run_get_missing_key_json_lists_keys(capsys) -> None:
"""JSON output for a bare `config get` returns the full key list for tools."""
import json

args = argparse.Namespace(config_command="get", key=None, output_format="json")
assert run_config_command(args) == 2
payload = json.loads(capsys.readouterr().out)
assert payload["data"]["error"] == "missing key"
assert payload["data"]["keys"] == list(option_keys())


def test_missing_key_example_is_a_real_option() -> None:
"""The hint's example key must stay a resolvable manifest key."""
from deepagents_code.client.commands.config import _GET_KEY_EXAMPLE

assert get_option(_GET_KEY_EXAMPLE) is not None


def test_config_registered_as_bare_action_group() -> None:
"""Bare `config` must run its action instead of startup-fast-path help."""
from deepagents_code import ui
Expand Down