deep-agent-cli 0.1.0__py3-none-any.whl
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.
- agent/__init__.py +42 -0
- agent/attachments.py +303 -0
- agent/bootstrap.py +44 -0
- agent/cancel.py +107 -0
- agent/cli/__init__.py +5 -0
- agent/cli/app.py +1768 -0
- agent/cli/clipboard.py +224 -0
- agent/cli/commands.py +94 -0
- agent/cli/gitinfo.py +84 -0
- agent/cli/input.py +65 -0
- agent/cli/interactions.py +187 -0
- agent/cli/main.py +124 -0
- agent/cli/previews.py +710 -0
- agent/cli/rendering.py +770 -0
- agent/cli/session_controller.py +221 -0
- agent/cli/state.py +326 -0
- agent/config.example.yaml +76 -0
- agent/config.py +528 -0
- agent/control.py +171 -0
- agent/factory.py +232 -0
- agent/file_mutation.py +5 -0
- agent/llm.py +339 -0
- agent/middleware/__init__.py +9 -0
- agent/middleware/attachments.py +31 -0
- agent/middleware/cancel_tools.py +39 -0
- agent/middleware/pause.py +18 -0
- agent/middleware/recovery.py +65 -0
- agent/middleware/steering.py +35 -0
- agent/middleware/tool_arg_hints.py +128 -0
- agent/middleware/workspace_filesystem.py +38 -0
- agent/middleware/write_operation.py +60 -0
- agent/network.py +30 -0
- agent/permission.py +80 -0
- agent/runner.py +1393 -0
- agent/sandbox.py +699 -0
- agent/session.py +431 -0
- agent/session_lock.py +223 -0
- agent/session_runtime.py +209 -0
- agent/stream.py +168 -0
- agent/tools/__init__.py +9 -0
- agent/tools/examples.py +30 -0
- agent/tools/execute.py +73 -0
- agent/tools/human_input.py +170 -0
- agent/tools/human_interaction.py +101 -0
- agent/tools/web_search.py +131 -0
- deep_agent_cli-0.1.0.dist-info/METADATA +408 -0
- deep_agent_cli-0.1.0.dist-info/RECORD +50 -0
- deep_agent_cli-0.1.0.dist-info/WHEEL +4 -0
- deep_agent_cli-0.1.0.dist-info/entry_points.txt +2 -0
- deep_agent_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
agent/cli/main.py
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Installed entry point for the interactive Deep Agent CLI."""
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
from dataclasses import replace
|
|
7
|
+
from prompt_toolkit import PromptSession
|
|
8
|
+
from prompt_toolkit.validation import Validator
|
|
9
|
+
from rich.console import Console
|
|
10
|
+
from rich.panel import Panel
|
|
11
|
+
|
|
12
|
+
from agent.cli import CliApplication
|
|
13
|
+
from agent.cli.app import default_config_dir
|
|
14
|
+
from agent.bootstrap import initialize_user_files
|
|
15
|
+
from agent.config import ConfigError, Settings, require_keybindings_outside_workspace
|
|
16
|
+
from agent.runner import AgentRunner
|
|
17
|
+
from agent.sandbox import ExecutionMode, SandboxUnavailableError, UNSANDBOXED_WARNING
|
|
18
|
+
from agent.session import SessionStore
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def create_runner(settings: Settings) -> AgentRunner:
|
|
22
|
+
session_store = SessionStore.for_workspace(
|
|
23
|
+
settings.sandbox.workspace,
|
|
24
|
+
override=settings.state_path,
|
|
25
|
+
)
|
|
26
|
+
try:
|
|
27
|
+
runner = AgentRunner(
|
|
28
|
+
settings=settings,
|
|
29
|
+
sandbox_config=settings.sandbox,
|
|
30
|
+
session_store=session_store,
|
|
31
|
+
enable_sessions=True,
|
|
32
|
+
workspace=settings.sandbox.workspace,
|
|
33
|
+
)
|
|
34
|
+
except SandboxUnavailableError as exc:
|
|
35
|
+
if not sys.stdin.isatty():
|
|
36
|
+
raise SystemExit(
|
|
37
|
+
"Non-interactive startup refused UNSANDBOXED fallback. Install bwrap or set "
|
|
38
|
+
"sandbox.allow_unsandboxed: true in ~/.deep-agent/config.yaml。"
|
|
39
|
+
) from exc
|
|
40
|
+
_confirm_unsandboxed(str(exc))
|
|
41
|
+
runner = AgentRunner(
|
|
42
|
+
settings=settings,
|
|
43
|
+
sandbox_config=replace(settings.sandbox, allow_unsandboxed=True),
|
|
44
|
+
session_store=session_store,
|
|
45
|
+
enable_sessions=True,
|
|
46
|
+
workspace=settings.sandbox.workspace,
|
|
47
|
+
)
|
|
48
|
+
return runner
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _confirm_unsandboxed(error: str) -> None:
|
|
52
|
+
Console(stderr=True).print(Panel(
|
|
53
|
+
f"[bold red]{error}[/bold red]\n\n{UNSANDBOXED_WARNING}\n\n"
|
|
54
|
+
"Type [bold]UNSANDBOXED[/bold] to accept the risk. Escape/Ctrl+C cancels startup.",
|
|
55
|
+
title="Sandbox unavailable",
|
|
56
|
+
border_style="red",
|
|
57
|
+
))
|
|
58
|
+
validator = Validator.from_callable(
|
|
59
|
+
lambda value: value == "UNSANDBOXED",
|
|
60
|
+
error_message="Enter UNSANDBOXED exactly, or press Ctrl+C to cancel.",
|
|
61
|
+
move_cursor_to_end=True,
|
|
62
|
+
)
|
|
63
|
+
try:
|
|
64
|
+
PromptSession().prompt("Confirm: ", validator=validator, validate_while_typing=False)
|
|
65
|
+
except (EOFError, KeyboardInterrupt) as exc:
|
|
66
|
+
raise SystemExit("Startup cancelled.") from exc
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def parse_startup_args(argv: list[str]) -> tuple[str | None, bool]:
|
|
70
|
+
if not argv:
|
|
71
|
+
return None, False
|
|
72
|
+
if argv[0] in {"-h", "--help"}:
|
|
73
|
+
print("Usage: deep-agent [resume [session-id]]")
|
|
74
|
+
raise SystemExit(0)
|
|
75
|
+
if argv[0] != "resume" or len(argv) > 2:
|
|
76
|
+
raise SystemExit(f"Unknown command: {argv[0]}\nUsage: deep-agent [resume [session-id]]")
|
|
77
|
+
return (argv[1] if len(argv) > 1 else None), True
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def main(argv: list[str] | None = None) -> None:
|
|
81
|
+
resume_id, open_picker = parse_startup_args(sys.argv[1:] if argv is None else argv)
|
|
82
|
+
created = initialize_user_files()
|
|
83
|
+
if created is not None:
|
|
84
|
+
Console(stderr=True).print(
|
|
85
|
+
f"Created {created} and ~/.deep-agent/skills/.\n"
|
|
86
|
+
"Edit the model endpoint and API key in the config, then run deep-agent again."
|
|
87
|
+
)
|
|
88
|
+
return
|
|
89
|
+
try:
|
|
90
|
+
settings = Settings.load()
|
|
91
|
+
except (ConfigError, FileNotFoundError) as exc:
|
|
92
|
+
print(f"Configuration error: {exc}", file=sys.stderr)
|
|
93
|
+
raise SystemExit(2) from None
|
|
94
|
+
config_dir = settings.config_dir or default_config_dir()
|
|
95
|
+
require_keybindings_outside_workspace(config_dir, settings.sandbox.workspace)
|
|
96
|
+
runner = create_runner(settings)
|
|
97
|
+
if runner.prepared.execution_mode is ExecutionMode.UNSANDBOXED:
|
|
98
|
+
Console(stderr=True).print(f"[bold red]UNSANDBOXED: {runner.prepared.security_warning}[/bold red]")
|
|
99
|
+
Console(stderr=True).print(f"[dim]workspace={settings.sandbox.workspace}[/dim]")
|
|
100
|
+
app = CliApplication(runner, config_dir=config_dir)
|
|
101
|
+
# Startup resume shares the controller workflow: a busy session waits
|
|
102
|
+
# inside the TUI (Esc cancels) instead of aborting the launch.
|
|
103
|
+
if resume_id:
|
|
104
|
+
app.sessions.startup_session_id = resume_id
|
|
105
|
+
elif open_picker:
|
|
106
|
+
app.sessions.open_picker_on_start = True
|
|
107
|
+
try:
|
|
108
|
+
app.run()
|
|
109
|
+
finally:
|
|
110
|
+
message = app.continue_session_message()
|
|
111
|
+
if message:
|
|
112
|
+
Console().print(message)
|
|
113
|
+
try:
|
|
114
|
+
runner.close()
|
|
115
|
+
except RuntimeError as exc:
|
|
116
|
+
print(
|
|
117
|
+
f"{exc}\nThe session lock is not released early; the operating "
|
|
118
|
+
"system releases it when this process actually exits.",
|
|
119
|
+
file=sys.stderr,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
if __name__ == "__main__":
|
|
124
|
+
main()
|