rlmy 0.1.0__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.
- rlmy-0.1.0/PKG-INFO +114 -0
- rlmy-0.1.0/README.md +92 -0
- rlmy-0.1.0/pyproject.toml +46 -0
- rlmy-0.1.0/setup.cfg +4 -0
- rlmy-0.1.0/src/rlmy/__init__.py +8 -0
- rlmy-0.1.0/src/rlmy/agent/__init__.py +14 -0
- rlmy-0.1.0/src/rlmy/agent/commands.py +155 -0
- rlmy-0.1.0/src/rlmy/agent/main.py +988 -0
- rlmy-0.1.0/src/rlmy/agent/rlm.py +1085 -0
- rlmy-0.1.0/src/rlmy/agent/sandbox.py +290 -0
- rlmy-0.1.0/src/rlmy/agent/trajectory.py +481 -0
- rlmy-0.1.0/src/rlmy/cli.py +142 -0
- rlmy-0.1.0/src/rlmy/config.py +115 -0
- rlmy-0.1.0/src/rlmy/tools/__init__.py +13 -0
- rlmy-0.1.0/src/rlmy/tools/edit.py +503 -0
- rlmy-0.1.0/src/rlmy/tools/mcp.py +343 -0
- rlmy-0.1.0/src/rlmy/tools/shell.py +346 -0
- rlmy-0.1.0/src/rlmy/wizard.py +184 -0
- rlmy-0.1.0/src/rlmy.egg-info/PKG-INFO +114 -0
- rlmy-0.1.0/src/rlmy.egg-info/SOURCES.txt +25 -0
- rlmy-0.1.0/src/rlmy.egg-info/dependency_links.txt +1 -0
- rlmy-0.1.0/src/rlmy.egg-info/entry_points.txt +2 -0
- rlmy-0.1.0/src/rlmy.egg-info/requires.txt +15 -0
- rlmy-0.1.0/src/rlmy.egg-info/top_level.txt +1 -0
- rlmy-0.1.0/tests/test_deep_imports.py +93 -0
- rlmy-0.1.0/tests/test_dspy_upgrade_compatibility.py +132 -0
- rlmy-0.1.0/tests/test_rlmy_core.py +113 -0
rlmy-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rlmy
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: An interactive RLM (Recursive Language Model) agent built on DSPy
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: dspy>=3.2.1
|
|
9
|
+
Requires-Dist: boto3>=1.42.0
|
|
10
|
+
Requires-Dist: nest-asyncio>=1.6.0
|
|
11
|
+
Requires-Dist: mcp>=1.26.0
|
|
12
|
+
Requires-Dist: rich>=14.0.0
|
|
13
|
+
Requires-Dist: markitdown>=0.1.5
|
|
14
|
+
Requires-Dist: prompt-toolkit>=3.0.50
|
|
15
|
+
Requires-Dist: pydantic>=2.12.0
|
|
16
|
+
Requires-Dist: platformdirs>=4.0.0
|
|
17
|
+
Requires-Dist: strands-agents-tools>=0.4.1
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
20
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
21
|
+
Requires-Dist: ruff; extra == "dev"
|
|
22
|
+
|
|
23
|
+
# rlmy
|
|
24
|
+
|
|
25
|
+
An interactive RLM (Recursive Language Model) agent built on DSPy.
|
|
26
|
+
|
|
27
|
+
## What is this?
|
|
28
|
+
|
|
29
|
+
- An AI coding agent that runs in your terminal
|
|
30
|
+
- Uses DSPy's RLM framework — the LLM writes and executes Python code iteratively
|
|
31
|
+
- Connects to MCP servers (Slack, internal tools, etc.) as additional tools
|
|
32
|
+
- Maintains conversation state across turns (trajectory persistence)
|
|
33
|
+
- Supports cooperative interrupt (Ctrl+C pauses gracefully)
|
|
34
|
+
|
|
35
|
+
## Key Features
|
|
36
|
+
|
|
37
|
+
- **Iterative REPL**: LLM writes code, sees output, writes more code — until it solves the problem
|
|
38
|
+
- **MCP Integration**: Connect any MCP-compatible tool server
|
|
39
|
+
- **Filesystem Tools**: Read, write, edit files with safety guards (read-before-write)
|
|
40
|
+
- **Shell Access**: Run shell commands with deny-list safety and approval system
|
|
41
|
+
- **Trajectory Persistence**: Resume sessions where you left off
|
|
42
|
+
- **Conversation Continuity**: Prior context injected into new turns
|
|
43
|
+
- **Configurable Models**: Use any DSPy-compatible LM (Anthropic, Bedrock, OpenAI, Groq, Ollama)
|
|
44
|
+
|
|
45
|
+
## Prerequisites
|
|
46
|
+
|
|
47
|
+
- Valid LLM credentials (Anthropic API key, AWS profile for Bedrock, etc.)
|
|
48
|
+
- Python 3.12+ and Deno are installed automatically by the setup script
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
Recommended (installs Deno + uv + rlmy in one command):
|
|
53
|
+
|
|
54
|
+
curl -LsSf https://raw.githubusercontent.com/diego-lima/rlmy/main/setup_install.sh | bash
|
|
55
|
+
|
|
56
|
+
Alternative (if you already have Deno and uv):
|
|
57
|
+
|
|
58
|
+
uv tool install rlmy
|
|
59
|
+
|
|
60
|
+
## Quick Start
|
|
61
|
+
|
|
62
|
+
rlmy
|
|
63
|
+
|
|
64
|
+
- First run asks which AI model to use (model selection wizard)
|
|
65
|
+
- Workspaces are created in `~/.config/rlmy/sandboxes/`
|
|
66
|
+
- Ctrl+C pauses gracefully (doesn't lose work)
|
|
67
|
+
|
|
68
|
+
To skip the wizard (headless/CI):
|
|
69
|
+
|
|
70
|
+
export RLM_MAIN_MODEL='bedrock/us.anthropic.claude-sonnet-4-6'
|
|
71
|
+
export RLM_SUB_MODEL='bedrock/us.anthropic.claude-sonnet-4-6'
|
|
72
|
+
rlmy
|
|
73
|
+
|
|
74
|
+
## Try It Out
|
|
75
|
+
|
|
76
|
+
If your credentials are set, run `rlmy` and type:
|
|
77
|
+
|
|
78
|
+
> *"curl https://calmcode.io/static/data/pokemon.json and teach me something surprising about it."*
|
|
79
|
+
|
|
80
|
+
Watch it fetch the data, explore it with code, and teach you something you didn't know. This is the RLM loop in action: it'll iterate until it has a neat insight.
|
|
81
|
+
|
|
82
|
+
## Configuration
|
|
83
|
+
|
|
84
|
+
- Priority: env vars > config file > wizard
|
|
85
|
+
- Config file: `~/.config/rlmy/config.toml`
|
|
86
|
+
- Supported model formats: any DSPy model string (e.g., `bedrock/us.anthropic.claude-sonnet-4-6`, `bedrock/us.anthropic.claude-opus-4-6-v1`)
|
|
87
|
+
|
|
88
|
+
## MCP Tools (optional)
|
|
89
|
+
|
|
90
|
+
- Config location: `~/.config/rlmy/mcp_servers.json`
|
|
91
|
+
- The setup script creates an empty template
|
|
92
|
+
- Edit it to connect Slack, internal tools, or any MCP-compatible server
|
|
93
|
+
- Agent starts without MCP if config is empty (no crash)
|
|
94
|
+
|
|
95
|
+
## CLI Options
|
|
96
|
+
|
|
97
|
+
- `--sandbox-root PATH`: Override sandbox directory (default: `~/.config/rlmy/sandboxes/`)
|
|
98
|
+
- `--cache-path PATH`: Override workspace cache file
|
|
99
|
+
|
|
100
|
+
## Architecture
|
|
101
|
+
|
|
102
|
+
- Built on DSPy's experimental RLM module
|
|
103
|
+
- InterruptableRLM: cooperative SIGINT + trajectory injection
|
|
104
|
+
- Sandboxed code execution via Deno + Pyodide (WASM)
|
|
105
|
+
- Tools are plain Python functions registered with DSPy
|
|
106
|
+
|
|
107
|
+
## License
|
|
108
|
+
|
|
109
|
+
MIT
|
|
110
|
+
|
|
111
|
+
## Status
|
|
112
|
+
|
|
113
|
+
- Early release — works well for the author, may have rough edges
|
|
114
|
+
- Feedback welcome via GitHub issues
|
rlmy-0.1.0/README.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# rlmy
|
|
2
|
+
|
|
3
|
+
An interactive RLM (Recursive Language Model) agent built on DSPy.
|
|
4
|
+
|
|
5
|
+
## What is this?
|
|
6
|
+
|
|
7
|
+
- An AI coding agent that runs in your terminal
|
|
8
|
+
- Uses DSPy's RLM framework — the LLM writes and executes Python code iteratively
|
|
9
|
+
- Connects to MCP servers (Slack, internal tools, etc.) as additional tools
|
|
10
|
+
- Maintains conversation state across turns (trajectory persistence)
|
|
11
|
+
- Supports cooperative interrupt (Ctrl+C pauses gracefully)
|
|
12
|
+
|
|
13
|
+
## Key Features
|
|
14
|
+
|
|
15
|
+
- **Iterative REPL**: LLM writes code, sees output, writes more code — until it solves the problem
|
|
16
|
+
- **MCP Integration**: Connect any MCP-compatible tool server
|
|
17
|
+
- **Filesystem Tools**: Read, write, edit files with safety guards (read-before-write)
|
|
18
|
+
- **Shell Access**: Run shell commands with deny-list safety and approval system
|
|
19
|
+
- **Trajectory Persistence**: Resume sessions where you left off
|
|
20
|
+
- **Conversation Continuity**: Prior context injected into new turns
|
|
21
|
+
- **Configurable Models**: Use any DSPy-compatible LM (Anthropic, Bedrock, OpenAI, Groq, Ollama)
|
|
22
|
+
|
|
23
|
+
## Prerequisites
|
|
24
|
+
|
|
25
|
+
- Valid LLM credentials (Anthropic API key, AWS profile for Bedrock, etc.)
|
|
26
|
+
- Python 3.12+ and Deno are installed automatically by the setup script
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
Recommended (installs Deno + uv + rlmy in one command):
|
|
31
|
+
|
|
32
|
+
curl -LsSf https://raw.githubusercontent.com/diego-lima/rlmy/main/setup_install.sh | bash
|
|
33
|
+
|
|
34
|
+
Alternative (if you already have Deno and uv):
|
|
35
|
+
|
|
36
|
+
uv tool install rlmy
|
|
37
|
+
|
|
38
|
+
## Quick Start
|
|
39
|
+
|
|
40
|
+
rlmy
|
|
41
|
+
|
|
42
|
+
- First run asks which AI model to use (model selection wizard)
|
|
43
|
+
- Workspaces are created in `~/.config/rlmy/sandboxes/`
|
|
44
|
+
- Ctrl+C pauses gracefully (doesn't lose work)
|
|
45
|
+
|
|
46
|
+
To skip the wizard (headless/CI):
|
|
47
|
+
|
|
48
|
+
export RLM_MAIN_MODEL='bedrock/us.anthropic.claude-sonnet-4-6'
|
|
49
|
+
export RLM_SUB_MODEL='bedrock/us.anthropic.claude-sonnet-4-6'
|
|
50
|
+
rlmy
|
|
51
|
+
|
|
52
|
+
## Try It Out
|
|
53
|
+
|
|
54
|
+
If your credentials are set, run `rlmy` and type:
|
|
55
|
+
|
|
56
|
+
> *"curl https://calmcode.io/static/data/pokemon.json and teach me something surprising about it."*
|
|
57
|
+
|
|
58
|
+
Watch it fetch the data, explore it with code, and teach you something you didn't know. This is the RLM loop in action: it'll iterate until it has a neat insight.
|
|
59
|
+
|
|
60
|
+
## Configuration
|
|
61
|
+
|
|
62
|
+
- Priority: env vars > config file > wizard
|
|
63
|
+
- Config file: `~/.config/rlmy/config.toml`
|
|
64
|
+
- Supported model formats: any DSPy model string (e.g., `bedrock/us.anthropic.claude-sonnet-4-6`, `bedrock/us.anthropic.claude-opus-4-6-v1`)
|
|
65
|
+
|
|
66
|
+
## MCP Tools (optional)
|
|
67
|
+
|
|
68
|
+
- Config location: `~/.config/rlmy/mcp_servers.json`
|
|
69
|
+
- The setup script creates an empty template
|
|
70
|
+
- Edit it to connect Slack, internal tools, or any MCP-compatible server
|
|
71
|
+
- Agent starts without MCP if config is empty (no crash)
|
|
72
|
+
|
|
73
|
+
## CLI Options
|
|
74
|
+
|
|
75
|
+
- `--sandbox-root PATH`: Override sandbox directory (default: `~/.config/rlmy/sandboxes/`)
|
|
76
|
+
- `--cache-path PATH`: Override workspace cache file
|
|
77
|
+
|
|
78
|
+
## Architecture
|
|
79
|
+
|
|
80
|
+
- Built on DSPy's experimental RLM module
|
|
81
|
+
- InterruptableRLM: cooperative SIGINT + trajectory injection
|
|
82
|
+
- Sandboxed code execution via Deno + Pyodide (WASM)
|
|
83
|
+
- Tools are plain Python functions registered with DSPy
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
MIT
|
|
88
|
+
|
|
89
|
+
## Status
|
|
90
|
+
|
|
91
|
+
- Early release — works well for the author, may have rough edges
|
|
92
|
+
- Feedback welcome via GitHub issues
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "rlmy"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "An interactive RLM (Recursive Language Model) agent built on DSPy"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = {text = "MIT"}
|
|
7
|
+
requires-python = ">=3.11"
|
|
8
|
+
dependencies = [
|
|
9
|
+
"dspy>=3.2.1",
|
|
10
|
+
"boto3>=1.42.0",
|
|
11
|
+
"nest-asyncio>=1.6.0",
|
|
12
|
+
"mcp>=1.26.0",
|
|
13
|
+
"rich>=14.0.0",
|
|
14
|
+
"markitdown>=0.1.5",
|
|
15
|
+
"prompt-toolkit>=3.0.50",
|
|
16
|
+
"pydantic>=2.12.0",
|
|
17
|
+
"platformdirs>=4.0.0",
|
|
18
|
+
"strands-agents-tools>=0.4.1",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[project.scripts]
|
|
22
|
+
rlmy = "rlmy.cli:main"
|
|
23
|
+
|
|
24
|
+
[project.optional-dependencies]
|
|
25
|
+
dev = [
|
|
26
|
+
"pytest>=8.0",
|
|
27
|
+
"pytest-cov",
|
|
28
|
+
"ruff",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[build-system]
|
|
32
|
+
requires = ["setuptools>=68"]
|
|
33
|
+
build-backend = "setuptools.build_meta"
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.packages.find]
|
|
36
|
+
where = ["src"]
|
|
37
|
+
|
|
38
|
+
[tool.pytest.ini_options]
|
|
39
|
+
pythonpath = ["src"]
|
|
40
|
+
testpaths = ["tests"]
|
|
41
|
+
addopts = "-v"
|
|
42
|
+
|
|
43
|
+
[tool.ruff]
|
|
44
|
+
line-length = 88
|
|
45
|
+
target-version = "py311"
|
|
46
|
+
|
rlmy-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""
|
|
2
|
+
RLMY Agent — core agent logic, trajectory, and workspace management.
|
|
3
|
+
|
|
4
|
+
Key exports:
|
|
5
|
+
InterruptableRLM — interrupt-safe RLM subclass with prior trajectory injection
|
|
6
|
+
RLMContext — mutable context passed to contextual tools
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# NOTE: Heavy imports (InterruptableRLM, etc.) are deferred to avoid loading
|
|
10
|
+
# the entire agent stack on `import rlmy`. Import directly from submodules:
|
|
11
|
+
# from rlmy.agent.rlm import InterruptableRLM, RLMContext
|
|
12
|
+
# from rlmy.agent.trajectory import save_trajectory, load_trajectory
|
|
13
|
+
# from rlmy.agent.sandbox import SandboxManager
|
|
14
|
+
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Purpose: Slash command registry — decoupled matching, dispatch signaling, help display.
|
|
3
|
+
Usage:
|
|
4
|
+
from rlmy.agent.commands import REGISTRY, SlashCommandSignal
|
|
5
|
+
cmd = REGISTRY.match(user_text) # returns SlashCommand or None
|
|
6
|
+
raise SlashCommandSignal(cmd) # for context-dependent commands
|
|
7
|
+
Key Components:
|
|
8
|
+
SlashCommand — immutable command descriptor (name, aliases, action key, description)
|
|
9
|
+
SlashCommandSignal — exception raised when a context-dependent command is triggered
|
|
10
|
+
CommandRegistry — register, match, help panel
|
|
11
|
+
REGISTRY — module-level singleton with all commands pre-registered
|
|
12
|
+
Conventions:
|
|
13
|
+
Commands return action keys (strings), NOT callbacks.
|
|
14
|
+
Self-contained commands (exit, help) are handled by prompt_user() directly.
|
|
15
|
+
Context-dependent commands (compact) raise SlashCommandSignal for the caller to handle.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from dataclasses import dataclass, field
|
|
19
|
+
from typing import Optional
|
|
20
|
+
|
|
21
|
+
from rich.panel import Panel
|
|
22
|
+
from rich.text import Text
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(frozen=True)
|
|
26
|
+
class SlashCommand:
|
|
27
|
+
"""
|
|
28
|
+
Purpose: Immutable descriptor for a slash command.
|
|
29
|
+
Attributes:
|
|
30
|
+
name: Primary command string (e.g., "/compact")
|
|
31
|
+
aliases: Alternative triggers (e.g., ["/c"])
|
|
32
|
+
action: Action key dispatched to callers (e.g., "compact"). NOT a callback.
|
|
33
|
+
description: Human-readable description for /help display.
|
|
34
|
+
self_contained: If True, prompt_user() handles it directly (e.g., exit, help).
|
|
35
|
+
If False, SlashCommandSignal is raised for the caller.
|
|
36
|
+
"""
|
|
37
|
+
name: str
|
|
38
|
+
action: str
|
|
39
|
+
description: str
|
|
40
|
+
aliases: list[str] = field(default_factory=list)
|
|
41
|
+
self_contained: bool = False
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class SlashCommandSignal(Exception):
|
|
45
|
+
"""
|
|
46
|
+
Purpose: Raised by prompt_user() when user triggers a context-dependent command.
|
|
47
|
+
|
|
48
|
+
Why an exception: prompt_user() doesn't own the conversation loop or trajectory.
|
|
49
|
+
It can't execute context-dependent commands itself. The exception propagates to
|
|
50
|
+
the caller (contextual_ask_user_guidance or mainmcp's between-turns loop) which
|
|
51
|
+
has the necessary context to dispatch.
|
|
52
|
+
|
|
53
|
+
Attributes:
|
|
54
|
+
command: The matched SlashCommand
|
|
55
|
+
action: Shortcut to command.action for easy dispatch
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
def __init__(self, command: SlashCommand):
|
|
59
|
+
self.command = command
|
|
60
|
+
self.action = command.action
|
|
61
|
+
super().__init__(f"Slash command: {command.name}")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class CommandRegistry:
|
|
65
|
+
"""
|
|
66
|
+
Purpose: Central registry for slash commands. Match user input, render help.
|
|
67
|
+
|
|
68
|
+
Usage Patterns:
|
|
69
|
+
REGISTRY.register(SlashCommand("/foo", "foo", "Do foo"))
|
|
70
|
+
cmd = REGISTRY.match("/foo") # returns SlashCommand
|
|
71
|
+
cmd = REGISTRY.match("hello") # returns None
|
|
72
|
+
panel = REGISTRY.help_panel() # Rich Panel for /help display
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
def __init__(self):
|
|
76
|
+
self._commands: list[SlashCommand] = []
|
|
77
|
+
# Lookup: normalized trigger string → SlashCommand
|
|
78
|
+
self._lookup: dict[str, SlashCommand] = {}
|
|
79
|
+
|
|
80
|
+
def register(self, cmd: SlashCommand) -> None:
|
|
81
|
+
"""Register a command. All triggers (name + aliases) are indexed."""
|
|
82
|
+
self._commands.append(cmd)
|
|
83
|
+
for trigger in [cmd.name] + cmd.aliases:
|
|
84
|
+
key = trigger.strip().lower()
|
|
85
|
+
if key in self._lookup:
|
|
86
|
+
raise ValueError(
|
|
87
|
+
f"Duplicate trigger '{key}': already registered to '{self._lookup[key].name}'"
|
|
88
|
+
)
|
|
89
|
+
self._lookup[key] = cmd
|
|
90
|
+
|
|
91
|
+
def match(self, text: str) -> Optional[SlashCommand]:
|
|
92
|
+
"""
|
|
93
|
+
Match user input against registered commands.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
text: The full user input text (already stripped by prompt_user).
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
SlashCommand if the ENTIRE text matches a trigger, else None.
|
|
100
|
+
Partial matches (e.g., "/comp" for "/compact") do NOT match.
|
|
101
|
+
"""
|
|
102
|
+
return self._lookup.get(text.lower())
|
|
103
|
+
|
|
104
|
+
def help_panel(self) -> Panel:
|
|
105
|
+
"""Build a Rich Panel listing all registered commands."""
|
|
106
|
+
lines = Text()
|
|
107
|
+
for cmd in self._commands:
|
|
108
|
+
triggers = ", ".join([cmd.name] + cmd.aliases)
|
|
109
|
+
lines.append(f" {triggers}", style="bold cyan")
|
|
110
|
+
lines.append(f" — {cmd.description}\n", style="dim")
|
|
111
|
+
return Panel(
|
|
112
|
+
lines,
|
|
113
|
+
title="[bold]Available Commands[/bold]",
|
|
114
|
+
border_style="blue",
|
|
115
|
+
padding=(1, 2),
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
# =============================================================================
|
|
120
|
+
# Module-level singleton — all commands registered here
|
|
121
|
+
# =============================================================================
|
|
122
|
+
|
|
123
|
+
REGISTRY = CommandRegistry()
|
|
124
|
+
|
|
125
|
+
REGISTRY.register(SlashCommand(
|
|
126
|
+
name="/quit",
|
|
127
|
+
action="exit",
|
|
128
|
+
description="Exit the program",
|
|
129
|
+
aliases=["/q"],
|
|
130
|
+
self_contained=True,
|
|
131
|
+
))
|
|
132
|
+
|
|
133
|
+
REGISTRY.register(SlashCommand(
|
|
134
|
+
name="/help",
|
|
135
|
+
action="help",
|
|
136
|
+
description="Show available commands",
|
|
137
|
+
aliases=["/h", "/?"],
|
|
138
|
+
self_contained=True,
|
|
139
|
+
))
|
|
140
|
+
|
|
141
|
+
REGISTRY.register(SlashCommand(
|
|
142
|
+
name="/compact",
|
|
143
|
+
action="compact",
|
|
144
|
+
description="Compact trajectory to free LLM attention (irreversible)",
|
|
145
|
+
aliases=["/c"],
|
|
146
|
+
self_contained=False,
|
|
147
|
+
))
|
|
148
|
+
|
|
149
|
+
REGISTRY.register(SlashCommand(
|
|
150
|
+
name="/reset",
|
|
151
|
+
action="reset",
|
|
152
|
+
description="Clear trajectory and start fresh",
|
|
153
|
+
aliases=[],
|
|
154
|
+
self_contained=False,
|
|
155
|
+
))
|