rlmness-cli 0.2.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.
- rlmagent/__init__.py +1 -0
- rlmagent/__main__.py +8 -0
- rlmagent/acp/__init__.py +1 -0
- rlmagent/acp/runtime.py +71 -0
- rlmagent/acp/server.py +598 -0
- rlmagent/acp/updates.py +128 -0
- rlmagent/agentnet.py +237 -0
- rlmagent/agents/__init__.py +1 -0
- rlmagent/agents/approval.py +90 -0
- rlmagent/agents/bridge.py +109 -0
- rlmagent/agents/budget.py +212 -0
- rlmagent/agents/child_handles.py +46 -0
- rlmagent/agents/child_mailbox.py +30 -0
- rlmagent/agents/kernel_api.py +156 -0
- rlmagent/agents/output.py +34 -0
- rlmagent/agents/patch.py +107 -0
- rlmagent/agents/prompts.py +156 -0
- rlmagent/agents/trace.py +290 -0
- rlmagent/agents/tree.py +682 -0
- rlmagent/agents/wasm_api.py +105 -0
- rlmagent/agents/workspace.py +357 -0
- rlmagent/autopilot.py +447 -0
- rlmagent/backend.py +946 -0
- rlmagent/backend_context.py +74 -0
- rlmagent/cli/__init__.py +5 -0
- rlmagent/cli/config_cmd.py +177 -0
- rlmagent/cli/health.py +156 -0
- rlmagent/cli/main.py +1194 -0
- rlmagent/cli/update.py +188 -0
- rlmagent/clipboard.py +63 -0
- rlmagent/config/__init__.py +37 -0
- rlmagent/config/config.py +297 -0
- rlmagent/config/loader.py +119 -0
- rlmagent/config/prompts.py +124 -0
- rlmagent/config/secure_input.py +213 -0
- rlmagent/config/store.py +275 -0
- rlmagent/context/__init__.py +47 -0
- rlmagent/context/budget.py +557 -0
- rlmagent/contract.py +311 -0
- rlmagent/contract_run.py +232 -0
- rlmagent/conversation.py +2547 -0
- rlmagent/cron.py +77 -0
- rlmagent/directives.py +893 -0
- rlmagent/discovery.py +356 -0
- rlmagent/execution_log.py +66 -0
- rlmagent/factory.py +189 -0
- rlmagent/factory_graph.py +413 -0
- rlmagent/harness/__init__.py +63 -0
- rlmagent/harness/contracts/__init__.py +1 -0
- rlmagent/harness/contracts/stream.py +129 -0
- rlmagent/harness/contracts/tooling.py +127 -0
- rlmagent/harness/contracts/transcript/__init__.py +68 -0
- rlmagent/harness/contracts/transcript/_base.py +29 -0
- rlmagent/harness/contracts/transcript/diagnostics.py +52 -0
- rlmagent/harness/contracts/transcript/entries.py +180 -0
- rlmagent/harness/contracts/transcript/segments.py +64 -0
- rlmagent/harness/contracts/values.py +6 -0
- rlmagent/harness/driver.py +397 -0
- rlmagent/harness/engine.py +489 -0
- rlmagent/harness/mending.py +153 -0
- rlmagent/harness/provider/__init__.py +1 -0
- rlmagent/harness/provider/base.py +27 -0
- rlmagent/harness/provider/wire.py +189 -0
- rlmagent/harness/py.typed +0 -0
- rlmagent/harness/session/__init__.py +5 -0
- rlmagent/harness/session/index.py +218 -0
- rlmagent/harness/session/lease.py +66 -0
- rlmagent/harness/session/records.py +118 -0
- rlmagent/harness/session/replay.py +165 -0
- rlmagent/harness/session/store.py +155 -0
- rlmagent/harness/session/summary.py +46 -0
- rlmagent/hints.py +47 -0
- rlmagent/history.py +92 -0
- rlmagent/hooks/__init__.py +1 -0
- rlmagent/hooks/hooks.py +1 -0
- rlmagent/instructions.py +157 -0
- rlmagent/job_runner.py +117 -0
- rlmagent/jobs.py +365 -0
- rlmagent/kept_agents.py +397 -0
- rlmagent/kernel/__init__.py +5 -0
- rlmagent/kernel/session.py +205 -0
- rlmagent/kernel/wasm.py +169 -0
- rlmagent/logs.py +208 -0
- rlmagent/managed_release.py +368 -0
- rlmagent/mcp.py +411 -0
- rlmagent/mcp_oauth.py +213 -0
- rlmagent/model/__init__.py +29 -0
- rlmagent/model/_claude/__init__.py +1 -0
- rlmagent/model/_claude/courier.py +117 -0
- rlmagent/model/_claude/emitter.py +378 -0
- rlmagent/model/_oai/__init__.py +1 -0
- rlmagent/model/_oai/helpers.py +256 -0
- rlmagent/model/_oai/normalize.py +263 -0
- rlmagent/model/_oai/parsers.py +317 -0
- rlmagent/model/_oai/payloads.py +226 -0
- rlmagent/model/_oai/transport.py +127 -0
- rlmagent/model/claude.py +552 -0
- rlmagent/model/copilot.py +142 -0
- rlmagent/model/correlation.py +21 -0
- rlmagent/model/deadline.py +19 -0
- rlmagent/model/discovery.py +181 -0
- rlmagent/model/external/__init__.py +11 -0
- rlmagent/model/external/acp.py +202 -0
- rlmagent/model/external/acp_install.py +109 -0
- rlmagent/model/external/cli.py +248 -0
- rlmagent/model/external/textcalls.py +57 -0
- rlmagent/model/failover.py +129 -0
- rlmagent/model/google.py +199 -0
- rlmagent/model/limits.py +46 -0
- rlmagent/model/oai_compatible.py +414 -0
- rlmagent/model/preferences.py +56 -0
- rlmagent/model/py.typed +0 -0
- rlmagent/model/registered_oauth.py +195 -0
- rlmagent/model/scripted.py +55 -0
- rlmagent/model/settings.py +271 -0
- rlmagent/model/subscription.py +398 -0
- rlmagent/model/token_bounds.py +15 -0
- rlmagent/model/transport/__init__.py +1 -0
- rlmagent/model/transport/backoff.py +87 -0
- rlmagent/model/transport/client.py +87 -0
- rlmagent/model/transport/faults.py +65 -0
- rlmagent/model/transport/responses_socket.py +223 -0
- rlmagent/model/vertex.py +93 -0
- rlmagent/network.py +123 -0
- rlmagent/packages.py +246 -0
- rlmagent/planning.py +84 -0
- rlmagent/playbook/__init__.py +1 -0
- rlmagent/playbook/apply.py +106 -0
- rlmagent/playbook/digest.py +63 -0
- rlmagent/playbook/improver.py +272 -0
- rlmagent/playbook/plan.py +99 -0
- rlmagent/playbook/store.py +67 -0
- rlmagent/plugins.py +327 -0
- rlmagent/policy.py +105 -0
- rlmagent/prompt_refs.py +57 -0
- rlmagent/prompts.py +331 -0
- rlmagent/prune.py +60 -0
- rlmagent/py.typed +0 -0
- rlmagent/reasoning.py +135 -0
- rlmagent/refinement/__init__.py +1 -0
- rlmagent/refinement/controller.py +448 -0
- rlmagent/refinement/engine.py +220 -0
- rlmagent/refinement/evidence.py +131 -0
- rlmagent/refinement/scoped.py +90 -0
- rlmagent/refinement/store.py +193 -0
- rlmagent/refresh.py +202 -0
- rlmagent/routing.py +52 -0
- rlmagent/runtime.py +575 -0
- rlmagent/safety.py +267 -0
- rlmagent/session_html.py +57 -0
- rlmagent/session_import.py +52 -0
- rlmagent/session_share.py +55 -0
- rlmagent/sessions.py +249 -0
- rlmagent/shell_sandbox.py +88 -0
- rlmagent/skillset.py +320 -0
- rlmagent/steering.py +148 -0
- rlmagent/stops.py +62 -0
- rlmagent/subscriptions.py +219 -0
- rlmagent/tasks.py +98 -0
- rlmagent/toolhost.py +310 -0
- rlmagent/tools/__init__.py +56 -0
- rlmagent/tools/_shared.py +210 -0
- rlmagent/tools/files.py +462 -0
- rlmagent/tools/kernel.py +93 -0
- rlmagent/tools/patch_tool.py +68 -0
- rlmagent/tools/search.py +188 -0
- rlmagent/trust.py +383 -0
- rlmagent/tui/__init__.py +1 -0
- rlmagent/tui/adapter.py +506 -0
- rlmagent/tui/app.py +711 -0
- rlmagent/tui/approval_screen.py +57 -0
- rlmagent/tui/choice_screen.py +47 -0
- rlmagent/tui/completions.py +116 -0
- rlmagent/tui/components.py +25 -0
- rlmagent/tui/composer.py +40 -0
- rlmagent/tui/factory_view.py +86 -0
- rlmagent/tui/inspect.py +193 -0
- rlmagent/tui/messages.py +215 -0
- rlmagent/tui/model_screen.py +307 -0
- rlmagent/tui/prompt.py +98 -0
- rlmagent/tui/question_screen.py +52 -0
- rlmagent/tui/replay.py +141 -0
- rlmagent/tui/rlm_agent.tcss +405 -0
- rlmagent/tui/search_box.py +91 -0
- rlmagent/tui/sidebar.py +182 -0
- rlmagent/tui/status.py +49 -0
- rlmagent/tui/steps.py +283 -0
- rlmagent/tui/suggest.py +778 -0
- rlmagent/tui/transcript.py +172 -0
- rlmagent/tui/trust_dialog.py +58 -0
- rlmagent/tui/worker_attach.py +141 -0
- rlmagent/ui/__init__.py +1 -0
- rlmagent/ui/render.py +211 -0
- rlmagent/undo.py +109 -0
- rlmagent/utils/__init__.py +1 -0
- rlmagent/websearch.py +75 -0
- rlmagent/worker.py +1275 -0
- rlmagent/worker_service.py +203 -0
- rlmness_cli-0.2.0.dist-info/METADATA +882 -0
- rlmness_cli-0.2.0.dist-info/RECORD +203 -0
- rlmness_cli-0.2.0.dist-info/WHEEL +4 -0
- rlmness_cli-0.2.0.dist-info/entry_points.txt +2 -0
- rlmness_cli-0.2.0.dist-info/licenses/LICENSE +21 -0
rlmagent/directives.py
ADDED
|
@@ -0,0 +1,893 @@
|
|
|
1
|
+
"""Slash-command registry: parsing, dispatch, and structured result actions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from typing import Protocol, runtime_checkable
|
|
8
|
+
|
|
9
|
+
# ---------------------------------------------------------------------------
|
|
10
|
+
# Session protocol — the only view commands need of a live session
|
|
11
|
+
# ---------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@runtime_checkable
|
|
15
|
+
class CommandSession(Protocol):
|
|
16
|
+
"""Read-only view of session state consumed by command handlers."""
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def session_id(self) -> str: ...
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def cwd(self) -> str: ...
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def model(self) -> str: ...
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def provider_name(self) -> str: ...
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def title(self) -> str | None: ...
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def thinking_level(self) -> str | None: ...
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def tools(self) -> tuple[object, ...]: ...
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def active(self) -> bool: ...
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# ---------------------------------------------------------------------------
|
|
44
|
+
# CommandResult — structured action descriptor
|
|
45
|
+
# ---------------------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass(frozen=True, slots=True)
|
|
49
|
+
class CommandResult:
|
|
50
|
+
"""Describes what the application should do in response to a slash command."""
|
|
51
|
+
|
|
52
|
+
handled: bool = False
|
|
53
|
+
message: str = ""
|
|
54
|
+
|
|
55
|
+
# ── lifecycle flags ───────────────────────────────────────────────
|
|
56
|
+
exit_requested: bool = False
|
|
57
|
+
new_session_requested: bool = False
|
|
58
|
+
reload_requested: bool = False
|
|
59
|
+
|
|
60
|
+
# ── navigation flags ──────────────────────────────────────────────
|
|
61
|
+
resume_requested: bool = False
|
|
62
|
+
resume_session_id: str = ""
|
|
63
|
+
|
|
64
|
+
# ── picker / interactive flags ────────────────────────────────────
|
|
65
|
+
model_picker_requested: bool = False
|
|
66
|
+
model_value: str = ""
|
|
67
|
+
tools_picker_requested: bool = False
|
|
68
|
+
export_requested: bool = False
|
|
69
|
+
export_format: str = ""
|
|
70
|
+
|
|
71
|
+
# ── provider switching ────────────────────────────────────────────
|
|
72
|
+
provider_switch_requested: bool = False
|
|
73
|
+
provider_value: str = ""
|
|
74
|
+
|
|
75
|
+
# ── thinking mode ─────────────────────────────────────────────────
|
|
76
|
+
thinking_requested: bool = False
|
|
77
|
+
thinking_value: str | None = None
|
|
78
|
+
|
|
79
|
+
# ── session metadata ──────────────────────────────────────────────
|
|
80
|
+
name_requested: bool = False
|
|
81
|
+
name_value: str = ""
|
|
82
|
+
|
|
83
|
+
# ── plan mode ─────────────────────────────────────────────────────
|
|
84
|
+
plan_requested: bool = False
|
|
85
|
+
plan_value: str = ""
|
|
86
|
+
|
|
87
|
+
# ── compaction ────────────────────────────────────────────────────
|
|
88
|
+
compact_requested: bool = False
|
|
89
|
+
|
|
90
|
+
# ── branching / rewind ────────────────────────────────────────────
|
|
91
|
+
branch_requested: bool = False
|
|
92
|
+
branch_summary: str = ""
|
|
93
|
+
rewind_requested: bool = False
|
|
94
|
+
rewind_entry_id: str = ""
|
|
95
|
+
|
|
96
|
+
# ── shell ─────────────────────────────────────────────────────────
|
|
97
|
+
shell_requested: bool = False
|
|
98
|
+
shell_command: str = ""
|
|
99
|
+
|
|
100
|
+
# ── diagnostics ───────────────────────────────────────────────────
|
|
101
|
+
diag_requested: bool = False
|
|
102
|
+
|
|
103
|
+
# ── extensibility ─────────────────────────────────────────────────
|
|
104
|
+
extras: dict[str, object] = field(default_factory=dict)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
# Convenience shortcuts
|
|
108
|
+
_HANDLED = CommandResult(handled=True)
|
|
109
|
+
_NOT_HANDLED = CommandResult()
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _ok(message: str = "", **kwargs: object) -> CommandResult:
|
|
113
|
+
"""Build a handled result with an optional message and extra flags."""
|
|
114
|
+
return CommandResult(handled=True, message=message, **kwargs) # type: ignore[arg-type]
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
# ---------------------------------------------------------------------------
|
|
118
|
+
# CommandContext — everything a handler receives
|
|
119
|
+
# ---------------------------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@dataclass(frozen=True, slots=True)
|
|
123
|
+
class CommandContext:
|
|
124
|
+
"""Bundle passed to every command handler."""
|
|
125
|
+
|
|
126
|
+
session: CommandSession
|
|
127
|
+
registry: CommandRegistry
|
|
128
|
+
raw: str
|
|
129
|
+
name: str
|
|
130
|
+
args: str
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# ---------------------------------------------------------------------------
|
|
134
|
+
# SlashCommand — metadata for a single registered command
|
|
135
|
+
# ---------------------------------------------------------------------------
|
|
136
|
+
|
|
137
|
+
#: Type alias for command handler functions.
|
|
138
|
+
Handler = Callable[[CommandContext], CommandResult]
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@dataclass(frozen=True, slots=True)
|
|
142
|
+
class SlashCommand:
|
|
143
|
+
"""Metadata and handler for a single slash command."""
|
|
144
|
+
|
|
145
|
+
name: str
|
|
146
|
+
description: str
|
|
147
|
+
handler: Handler
|
|
148
|
+
usage: str = ""
|
|
149
|
+
aliases: tuple[str, ...] = ()
|
|
150
|
+
search_terms: tuple[str, ...] = ()
|
|
151
|
+
|
|
152
|
+
@property
|
|
153
|
+
def display_usage(self) -> str:
|
|
154
|
+
"""Human-readable usage string, falling back to ``/<name>``."""
|
|
155
|
+
return self.usage or f"/{self.name}"
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
# ---------------------------------------------------------------------------
|
|
159
|
+
# Parsing utilities
|
|
160
|
+
# ---------------------------------------------------------------------------
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def parse_command(text: str) -> tuple[str, str] | None:
|
|
164
|
+
"""Parse ``/command args`` into ``(name, args)`` or ``None``."""
|
|
165
|
+
if not text.startswith("/"):
|
|
166
|
+
return None
|
|
167
|
+
if text.startswith("//"):
|
|
168
|
+
return None
|
|
169
|
+
body = text[1:]
|
|
170
|
+
if not body or body[0].isspace():
|
|
171
|
+
return None
|
|
172
|
+
parts = body.split(None, 1)
|
|
173
|
+
name = parts[0].lower()
|
|
174
|
+
args = parts[1].strip() if len(parts) > 1 else ""
|
|
175
|
+
return name, args
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# ---------------------------------------------------------------------------
|
|
179
|
+
# CommandRegistry
|
|
180
|
+
# ---------------------------------------------------------------------------
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class CommandRegistry:
|
|
184
|
+
"""Dictionary-based slash command registry with alias support."""
|
|
185
|
+
|
|
186
|
+
def __init__(self) -> None:
|
|
187
|
+
self._commands: dict[str, SlashCommand] = {}
|
|
188
|
+
self._aliases: dict[str, str] = {}
|
|
189
|
+
|
|
190
|
+
# ── registration ──────────────────────────────────────────────────
|
|
191
|
+
|
|
192
|
+
def register(self, command: SlashCommand) -> None:
|
|
193
|
+
"""Add a command to the registry."""
|
|
194
|
+
if command.name in self._commands or command.name in self._aliases:
|
|
195
|
+
raise ValueError(f"Duplicate command name: /{command.name}")
|
|
196
|
+
for alias in command.aliases:
|
|
197
|
+
if alias in self._commands or alias in self._aliases:
|
|
198
|
+
raise ValueError(
|
|
199
|
+
f"Alias /{alias} for /{command.name} collides with "
|
|
200
|
+
f"an existing command or alias"
|
|
201
|
+
)
|
|
202
|
+
self._commands[command.name] = command
|
|
203
|
+
for alias in command.aliases:
|
|
204
|
+
self._aliases[alias] = command.name
|
|
205
|
+
|
|
206
|
+
# ── lookup ────────────────────────────────────────────────────────
|
|
207
|
+
|
|
208
|
+
def get(self, name: str) -> SlashCommand | None:
|
|
209
|
+
"""Look up a command by primary name or alias."""
|
|
210
|
+
if name in self._commands:
|
|
211
|
+
return self._commands[name]
|
|
212
|
+
primary = self._aliases.get(name)
|
|
213
|
+
if primary is not None:
|
|
214
|
+
return self._commands.get(primary)
|
|
215
|
+
return None
|
|
216
|
+
|
|
217
|
+
def all_commands(self) -> list[SlashCommand]:
|
|
218
|
+
"""Return all registered commands in alphabetical order."""
|
|
219
|
+
return sorted(self._commands.values(), key=lambda c: c.name)
|
|
220
|
+
|
|
221
|
+
@property
|
|
222
|
+
def names(self) -> frozenset[str]:
|
|
223
|
+
"""All registered primary names and aliases."""
|
|
224
|
+
return frozenset(self._commands) | frozenset(self._aliases)
|
|
225
|
+
|
|
226
|
+
# ── dispatch ──────────────────────────────────────────────────────
|
|
227
|
+
|
|
228
|
+
def dispatch(self, session: CommandSession, text: str) -> CommandResult:
|
|
229
|
+
"""Parse *text* and dispatch to the matching handler."""
|
|
230
|
+
parsed = parse_command(text)
|
|
231
|
+
if parsed is None:
|
|
232
|
+
return _NOT_HANDLED
|
|
233
|
+
|
|
234
|
+
name, args = parsed
|
|
235
|
+
command = self.get(name)
|
|
236
|
+
if command is None:
|
|
237
|
+
return _NOT_HANDLED
|
|
238
|
+
|
|
239
|
+
ctx = CommandContext(
|
|
240
|
+
session=session,
|
|
241
|
+
registry=self,
|
|
242
|
+
raw=text,
|
|
243
|
+
name=name,
|
|
244
|
+
args=args,
|
|
245
|
+
)
|
|
246
|
+
return command.handler(ctx)
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
# ---------------------------------------------------------------------------
|
|
250
|
+
# Built-in command handlers
|
|
251
|
+
# ---------------------------------------------------------------------------
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def _cmd_help(ctx: CommandContext) -> CommandResult:
|
|
255
|
+
"""List all available commands with descriptions."""
|
|
256
|
+
lines = ["Commands:"]
|
|
257
|
+
for cmd in ctx.registry.all_commands():
|
|
258
|
+
alias_str = ""
|
|
259
|
+
if cmd.aliases:
|
|
260
|
+
alias_str = " (" + " ".join(f"/{a}" for a in cmd.aliases) + ")"
|
|
261
|
+
lines.append(f" {cmd.display_usage:<22}{cmd.description}{alias_str}")
|
|
262
|
+
return _ok("\n".join(lines))
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def _cmd_quit(ctx: CommandContext) -> CommandResult:
|
|
266
|
+
"""Signal that the user wants to exit."""
|
|
267
|
+
return _ok(exit_requested=True)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def _cmd_version(ctx: CommandContext) -> CommandResult:
|
|
271
|
+
"""Show the installed version."""
|
|
272
|
+
return _ok(extras={"version_requested": True})
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def _cmd_new(ctx: CommandContext) -> CommandResult:
|
|
276
|
+
"""Request creation of a fresh session."""
|
|
277
|
+
return _ok("Starting new session.", new_session_requested=True)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def _cmd_model(ctx: CommandContext) -> CommandResult:
|
|
281
|
+
"""Show or switch the active model."""
|
|
282
|
+
if not ctx.args:
|
|
283
|
+
return _ok(f"Current model: {ctx.session.model}", model_picker_requested=True)
|
|
284
|
+
return _ok(
|
|
285
|
+
f"Switching to model: {ctx.args}",
|
|
286
|
+
model_picker_requested=True,
|
|
287
|
+
model_value=ctx.args,
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def _cmd_provider(ctx: CommandContext) -> CommandResult:
|
|
292
|
+
"""Show or switch the active provider."""
|
|
293
|
+
if not ctx.args:
|
|
294
|
+
return _ok(f"Current provider: {ctx.session.provider_name}")
|
|
295
|
+
return _ok(
|
|
296
|
+
f"Switching to provider: {ctx.args}",
|
|
297
|
+
provider_switch_requested=True,
|
|
298
|
+
provider_value=ctx.args,
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def _cmd_tools(ctx: CommandContext) -> CommandResult:
|
|
303
|
+
"""List registered tools or open the tools picker."""
|
|
304
|
+
tools = ctx.session.tools
|
|
305
|
+
if not tools:
|
|
306
|
+
return _ok("No tools registered.")
|
|
307
|
+
lines = [f"Registered tools ({len(tools)}):"]
|
|
308
|
+
for tool in tools:
|
|
309
|
+
name = getattr(tool, "name", str(tool))
|
|
310
|
+
lines.append(f" {name}")
|
|
311
|
+
return _ok("\n".join(lines), tools_picker_requested=True)
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def _cmd_export(ctx: CommandContext) -> CommandResult:
|
|
315
|
+
"""Request a transcript export."""
|
|
316
|
+
fmt = ctx.args or "text"
|
|
317
|
+
if fmt not in {"text", "json", "jsonl"}:
|
|
318
|
+
return _ok(f"Unknown format: {fmt!r}. Use text, json, or jsonl.")
|
|
319
|
+
return _ok(export_requested=True, export_format=fmt)
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def _cmd_reload(ctx: CommandContext) -> CommandResult:
|
|
323
|
+
"""Request a hot reload of tools, extensions, and system prompt."""
|
|
324
|
+
return _ok("Reloading.", reload_requested=True)
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def _cmd_resume(ctx: CommandContext) -> CommandResult:
|
|
328
|
+
"""Resume a previous session by ID."""
|
|
329
|
+
if not ctx.args:
|
|
330
|
+
return _ok("Usage: /resume <session-id>")
|
|
331
|
+
return _ok(
|
|
332
|
+
f"Resuming session: {ctx.args}",
|
|
333
|
+
resume_requested=True,
|
|
334
|
+
resume_session_id=ctx.args,
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def _cmd_session(ctx: CommandContext) -> CommandResult:
|
|
339
|
+
"""Show current session info."""
|
|
340
|
+
title = ctx.session.title or "(untitled)"
|
|
341
|
+
lines = [
|
|
342
|
+
f"Session: {ctx.session.session_id}",
|
|
343
|
+
f"Title: {title}",
|
|
344
|
+
f"Model: {ctx.session.model}",
|
|
345
|
+
f"Provider:{ctx.session.provider_name}",
|
|
346
|
+
f"CWD: {ctx.session.cwd}",
|
|
347
|
+
]
|
|
348
|
+
return _ok("\n".join(lines))
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
def _cmd_think(ctx: CommandContext) -> CommandResult:
|
|
352
|
+
"""Set or disable thinking mode."""
|
|
353
|
+
if not ctx.args or ctx.args.lower() in {"off", "none", "disable"}:
|
|
354
|
+
return _ok("Thinking disabled.", thinking_requested=True, thinking_value=None)
|
|
355
|
+
level = ctx.args.split()[0]
|
|
356
|
+
return _ok(
|
|
357
|
+
f"Thinking set to: {level}",
|
|
358
|
+
thinking_requested=True,
|
|
359
|
+
thinking_value=level,
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def _cmd_plan(ctx: CommandContext) -> CommandResult:
|
|
364
|
+
"""Toggle read-only plan mode, or set it with ``on``/``off``."""
|
|
365
|
+
return _ok(plan_requested=True, plan_value=ctx.args.strip().lower())
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def _cmd_improve(ctx: CommandContext) -> CommandResult:
|
|
369
|
+
"""Handled by the session."""
|
|
370
|
+
return _ok()
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def _cmd_undo(ctx: CommandContext) -> CommandResult:
|
|
374
|
+
"""Handled by the session."""
|
|
375
|
+
return _ok()
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def _cmd_diff(ctx: CommandContext) -> CommandResult:
|
|
379
|
+
"""Handled by the session."""
|
|
380
|
+
return _ok()
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
def _cmd_tasks(ctx: CommandContext) -> CommandResult:
|
|
384
|
+
"""Handled by the session."""
|
|
385
|
+
return _ok()
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def _cmd_mcp(ctx: CommandContext) -> CommandResult:
|
|
389
|
+
"""Handled by the session."""
|
|
390
|
+
return _ok()
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def _cmd_image(ctx: CommandContext) -> CommandResult:
|
|
394
|
+
"""Handled by the session."""
|
|
395
|
+
return _ok()
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def _cmd_tier(ctx: CommandContext) -> CommandResult:
|
|
399
|
+
"""Handled by the session."""
|
|
400
|
+
return _ok()
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
def _cmd_btw(ctx: CommandContext) -> CommandResult:
|
|
404
|
+
"""Handled by the session."""
|
|
405
|
+
return _ok()
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
def _cmd_session_owned(ctx: CommandContext) -> CommandResult:
|
|
409
|
+
"""Handled by the session (/update, /share, /logs, /changelog)."""
|
|
410
|
+
return _ok()
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
def _cmd_goal(ctx: CommandContext) -> CommandResult:
|
|
414
|
+
"""Handled by the session."""
|
|
415
|
+
return _ok()
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def _cmd_autonomous(ctx: CommandContext) -> CommandResult:
|
|
419
|
+
"""Handled by the session."""
|
|
420
|
+
return _ok()
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def _cmd_compact(ctx: CommandContext) -> CommandResult:
|
|
424
|
+
"""Request context compaction."""
|
|
425
|
+
return _ok(compact_requested=True)
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
def _cmd_stats(ctx: CommandContext) -> CommandResult:
|
|
429
|
+
"""Display session statistics (delegated to caller for actual data)."""
|
|
430
|
+
return _ok(extras={"stats_requested": True})
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
def _cmd_name(ctx: CommandContext) -> CommandResult:
|
|
434
|
+
"""Show or set the session title."""
|
|
435
|
+
if not ctx.args:
|
|
436
|
+
title = ctx.session.title or ctx.session.session_id
|
|
437
|
+
return _ok(f"Session: {title}")
|
|
438
|
+
return _ok(
|
|
439
|
+
f"Session named: {ctx.args}",
|
|
440
|
+
name_requested=True,
|
|
441
|
+
name_value=ctx.args,
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
def _cmd_branch(ctx: CommandContext) -> CommandResult:
|
|
446
|
+
"""Fork the conversation at the current point."""
|
|
447
|
+
return _ok(branch_requested=True, branch_summary=ctx.args)
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
def _cmd_rewind(ctx: CommandContext) -> CommandResult:
|
|
451
|
+
"""Rewind to a previous entry, or list the branchable ones."""
|
|
452
|
+
return _ok(rewind_requested=True, rewind_entry_id=ctx.args)
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
def _cmd_branches(ctx: CommandContext) -> CommandResult:
|
|
456
|
+
"""List recorded fork points."""
|
|
457
|
+
return _ok(extras={"branches_requested": True})
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
def _cmd_create_skill(ctx: CommandContext) -> CommandResult:
|
|
461
|
+
"""Save a new project skill."""
|
|
462
|
+
if not ctx.args:
|
|
463
|
+
return _ok("Usage: /create-skill <name> <instructions>")
|
|
464
|
+
return _ok(extras={"create_skill_requested": True, "create_skill_args": ctx.args})
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
def _cmd_continue(ctx: CommandContext) -> CommandResult:
|
|
468
|
+
"""Resume the agent loop without a new user message."""
|
|
469
|
+
return _ok(extras={"continue_requested": True})
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
def _cmd_shell(ctx: CommandContext) -> CommandResult:
|
|
473
|
+
"""Request execution of a shell command."""
|
|
474
|
+
if not ctx.args:
|
|
475
|
+
return _ok("Usage: /shell <command>")
|
|
476
|
+
return _ok(shell_requested=True, shell_command=ctx.args)
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
def _cmd_diag(ctx: CommandContext) -> CommandResult:
|
|
480
|
+
"""Request session diagnostics dump."""
|
|
481
|
+
return _ok(diag_requested=True)
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
def _cmd_system(ctx: CommandContext) -> CommandResult:
|
|
485
|
+
"""Show the active system prompt with each section's source."""
|
|
486
|
+
return _ok(extras={"system_requested": True})
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
def _cmd_skills(ctx: CommandContext) -> CommandResult:
|
|
490
|
+
"""List available skills."""
|
|
491
|
+
return _ok(extras={"skills_requested": True})
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def _cmd_prompts(ctx: CommandContext) -> CommandResult:
|
|
495
|
+
"""List available prompt templates."""
|
|
496
|
+
return _ok(extras={"prompts_requested": True})
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
def _cmd_theme(ctx: CommandContext) -> CommandResult:
|
|
500
|
+
"""Show or switch theme."""
|
|
501
|
+
if not ctx.args:
|
|
502
|
+
return _ok(extras={"theme_requested": True})
|
|
503
|
+
return _ok(extras={"theme_requested": True, "theme_value": ctx.args})
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
def _cmd_login(ctx: CommandContext) -> CommandResult:
|
|
507
|
+
"""Request provider authentication."""
|
|
508
|
+
provider = ctx.args or ""
|
|
509
|
+
return _ok(extras={"login_requested": True, "login_provider": provider})
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
def _cmd_logout(ctx: CommandContext) -> CommandResult:
|
|
513
|
+
"""Request provider deauthentication."""
|
|
514
|
+
provider = ctx.args or ""
|
|
515
|
+
return _ok(extras={"logout_requested": True, "logout_provider": provider})
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
def _cmd_config(ctx: CommandContext) -> CommandResult:
|
|
519
|
+
"""Show or edit configuration."""
|
|
520
|
+
if not ctx.args:
|
|
521
|
+
return _ok(extras={"config_requested": True})
|
|
522
|
+
return _ok(extras={"config_requested": True, "config_args": ctx.args})
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
def _cmd_doctor(ctx: CommandContext) -> CommandResult:
|
|
526
|
+
"""Run environment health checks."""
|
|
527
|
+
return _ok(extras={"doctor_requested": True})
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
# ---------------------------------------------------------------------------
|
|
531
|
+
# Default registry builder
|
|
532
|
+
# ---------------------------------------------------------------------------
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
def build_default_registry() -> CommandRegistry:
|
|
536
|
+
"""Create a ``CommandRegistry`` populated with rlm-agent's built-in commands."""
|
|
537
|
+
reg = CommandRegistry()
|
|
538
|
+
|
|
539
|
+
_BUILTINS: list[SlashCommand] = [
|
|
540
|
+
SlashCommand(
|
|
541
|
+
name="help",
|
|
542
|
+
description="Show available commands",
|
|
543
|
+
handler=_cmd_help,
|
|
544
|
+
usage="/help",
|
|
545
|
+
aliases=("?", "h"),
|
|
546
|
+
search_terms=("commands", "usage"),
|
|
547
|
+
),
|
|
548
|
+
SlashCommand(
|
|
549
|
+
name="quit",
|
|
550
|
+
description="End the session",
|
|
551
|
+
handler=_cmd_quit,
|
|
552
|
+
usage="/quit",
|
|
553
|
+
aliases=("exit", "q"),
|
|
554
|
+
search_terms=("leave", "close", "stop"),
|
|
555
|
+
),
|
|
556
|
+
SlashCommand(
|
|
557
|
+
name="version",
|
|
558
|
+
description="Show version info",
|
|
559
|
+
handler=_cmd_version,
|
|
560
|
+
usage="/version",
|
|
561
|
+
search_terms=("build", "release"),
|
|
562
|
+
),
|
|
563
|
+
SlashCommand(
|
|
564
|
+
name="new",
|
|
565
|
+
description="Start a new session",
|
|
566
|
+
handler=_cmd_new,
|
|
567
|
+
usage="/new",
|
|
568
|
+
search_terms=("fresh", "reset", "clear"),
|
|
569
|
+
),
|
|
570
|
+
SlashCommand(
|
|
571
|
+
name="session",
|
|
572
|
+
description="Show current session info",
|
|
573
|
+
handler=_cmd_session,
|
|
574
|
+
usage="/session",
|
|
575
|
+
search_terms=("info", "status"),
|
|
576
|
+
),
|
|
577
|
+
SlashCommand(
|
|
578
|
+
name="model",
|
|
579
|
+
description="Show or switch model",
|
|
580
|
+
handler=_cmd_model,
|
|
581
|
+
usage="/model [name]",
|
|
582
|
+
aliases=("m",),
|
|
583
|
+
search_terms=("switch", "llm"),
|
|
584
|
+
),
|
|
585
|
+
SlashCommand(
|
|
586
|
+
name="provider",
|
|
587
|
+
description="Show or switch provider",
|
|
588
|
+
handler=_cmd_provider,
|
|
589
|
+
usage="/provider [name]",
|
|
590
|
+
search_terms=("backend", "api"),
|
|
591
|
+
),
|
|
592
|
+
SlashCommand(
|
|
593
|
+
name="tools",
|
|
594
|
+
description="List registered tools",
|
|
595
|
+
handler=_cmd_tools,
|
|
596
|
+
usage="/tools",
|
|
597
|
+
search_terms=("functions", "capabilities"),
|
|
598
|
+
),
|
|
599
|
+
SlashCommand(
|
|
600
|
+
name="export",
|
|
601
|
+
description="Export transcript",
|
|
602
|
+
handler=_cmd_export,
|
|
603
|
+
usage="/export [text|json|jsonl]",
|
|
604
|
+
search_terms=("save", "download", "dump"),
|
|
605
|
+
),
|
|
606
|
+
SlashCommand(
|
|
607
|
+
name="reload",
|
|
608
|
+
description="Reload tools, extensions, and prompt",
|
|
609
|
+
handler=_cmd_reload,
|
|
610
|
+
usage="/reload",
|
|
611
|
+
search_terms=("refresh",),
|
|
612
|
+
),
|
|
613
|
+
SlashCommand(
|
|
614
|
+
name="resume",
|
|
615
|
+
description="Resume a previous session",
|
|
616
|
+
handler=_cmd_resume,
|
|
617
|
+
usage="/resume <session-id>",
|
|
618
|
+
aliases=("r",),
|
|
619
|
+
search_terms=("restore", "continue", "load"),
|
|
620
|
+
),
|
|
621
|
+
SlashCommand(
|
|
622
|
+
name="think",
|
|
623
|
+
description="Set thinking level (off to disable)",
|
|
624
|
+
handler=_cmd_think,
|
|
625
|
+
usage="/think [level|off]",
|
|
626
|
+
aliases=("thinking", "effort"),
|
|
627
|
+
search_terms=("reasoning", "depth"),
|
|
628
|
+
),
|
|
629
|
+
SlashCommand(
|
|
630
|
+
name="tier", description="Set the provider service tier",
|
|
631
|
+
handler=_cmd_tier, usage="/tier auto|default|flex|priority|off",
|
|
632
|
+
search_terms=("priority", "flex"),
|
|
633
|
+
),
|
|
634
|
+
SlashCommand(
|
|
635
|
+
name="fast", description="Use priority service for the current model",
|
|
636
|
+
handler=_cmd_tier, usage="/fast on|off",
|
|
637
|
+
),
|
|
638
|
+
SlashCommand(
|
|
639
|
+
name="plan",
|
|
640
|
+
description="Toggle read-only plan mode",
|
|
641
|
+
handler=_cmd_plan,
|
|
642
|
+
usage="/plan [on|off]",
|
|
643
|
+
search_terms=("planning", "readonly", "research", "propose"),
|
|
644
|
+
),
|
|
645
|
+
SlashCommand(
|
|
646
|
+
name="diff",
|
|
647
|
+
description="Show what this session changed in the project",
|
|
648
|
+
handler=_cmd_diff,
|
|
649
|
+
usage="/diff [last | stat]",
|
|
650
|
+
search_terms=("changes", "patch", "git"),
|
|
651
|
+
),
|
|
652
|
+
SlashCommand(
|
|
653
|
+
name="tasks",
|
|
654
|
+
description="Show or edit the agent's task list",
|
|
655
|
+
handler=_cmd_tasks,
|
|
656
|
+
usage="/tasks [add TEXT | done N | undo N | remove N | clear]",
|
|
657
|
+
search_terms=("todo", "checklist", "plan"),
|
|
658
|
+
),
|
|
659
|
+
SlashCommand(
|
|
660
|
+
name="mcp",
|
|
661
|
+
description="List MCP servers and their tools; /mcp NAME starts one",
|
|
662
|
+
handler=_cmd_mcp,
|
|
663
|
+
usage="/mcp [NAME | login NAME | logout NAME]",
|
|
664
|
+
search_terms=("servers", "connectors", "tools"),
|
|
665
|
+
),
|
|
666
|
+
SlashCommand(
|
|
667
|
+
name="image",
|
|
668
|
+
description="Attach an image to your next message",
|
|
669
|
+
handler=_cmd_image,
|
|
670
|
+
usage="/image PATH | clear",
|
|
671
|
+
search_terms=("picture", "screenshot", "attach", "vision"),
|
|
672
|
+
),
|
|
673
|
+
SlashCommand(
|
|
674
|
+
name="update",
|
|
675
|
+
description="Check for a newer rlm-agent, or install it with /update apply",
|
|
676
|
+
handler=_cmd_session_owned,
|
|
677
|
+
usage="/update [apply]",
|
|
678
|
+
search_terms=("upgrade", "version", "release"),
|
|
679
|
+
),
|
|
680
|
+
SlashCommand(
|
|
681
|
+
name="share",
|
|
682
|
+
description="Preview this session as an unlisted gist; publish with its SHA-256",
|
|
683
|
+
handler=_cmd_session_owned,
|
|
684
|
+
usage="/share [publish SHA256]",
|
|
685
|
+
search_terms=("gist", "link", "publish"),
|
|
686
|
+
),
|
|
687
|
+
SlashCommand(
|
|
688
|
+
name="logs",
|
|
689
|
+
description="Show the end of this session's newest log file",
|
|
690
|
+
handler=_cmd_session_owned,
|
|
691
|
+
usage="/logs [LINES]",
|
|
692
|
+
search_terms=("log", "debug", "trace"),
|
|
693
|
+
),
|
|
694
|
+
SlashCommand(
|
|
695
|
+
name="changelog",
|
|
696
|
+
description="List recent rlm-agent releases",
|
|
697
|
+
handler=_cmd_session_owned,
|
|
698
|
+
usage="/changelog",
|
|
699
|
+
search_terms=("releases", "news", "versions"),
|
|
700
|
+
),
|
|
701
|
+
SlashCommand(
|
|
702
|
+
name="btw",
|
|
703
|
+
description="Ask about the conversation so far; the exchange is not kept",
|
|
704
|
+
handler=_cmd_btw,
|
|
705
|
+
usage="/btw QUESTION",
|
|
706
|
+
search_terms=("aside", "question", "quick"),
|
|
707
|
+
),
|
|
708
|
+
SlashCommand(
|
|
709
|
+
name="goal",
|
|
710
|
+
description="Set, show, pause or clear the goal the agent keeps working toward",
|
|
711
|
+
handler=_cmd_goal,
|
|
712
|
+
usage="/goal [TEXT [--tokens N] | pause | resume | clear]",
|
|
713
|
+
search_terms=("objective", "target", "aim"),
|
|
714
|
+
),
|
|
715
|
+
SlashCommand(
|
|
716
|
+
name="autonomous",
|
|
717
|
+
description="Keep working toward the goal without waiting, within limits",
|
|
718
|
+
handler=_cmd_autonomous,
|
|
719
|
+
usage="/autonomous [off | status | turns N | tokens N | seconds N | gate CMD | gate list | gate add NAME CMD | gate remove NAME]",
|
|
720
|
+
search_terms=("auto", "loop", "unattended"),
|
|
721
|
+
),
|
|
722
|
+
SlashCommand(
|
|
723
|
+
name="undo",
|
|
724
|
+
description="Undo the last turn: its file changes and its messages",
|
|
725
|
+
handler=_cmd_undo,
|
|
726
|
+
usage="/undo [N | list]",
|
|
727
|
+
search_terms=("revert", "restore", "rollback"),
|
|
728
|
+
),
|
|
729
|
+
SlashCommand(
|
|
730
|
+
name="refine",
|
|
731
|
+
description="Review reusable guidance in a background job",
|
|
732
|
+
handler=_cmd_improve,
|
|
733
|
+
usage="/refine [focus] | status | cancel | evidence | rate <change> <verdict>",
|
|
734
|
+
search_terms=("harness", "workflow", "guidance"),
|
|
735
|
+
),
|
|
736
|
+
SlashCommand(
|
|
737
|
+
name="improve",
|
|
738
|
+
description="Update the playbook from this conversation",
|
|
739
|
+
handler=_cmd_improve,
|
|
740
|
+
usage="/improve [--shared] [instructions] | list | undo <id>",
|
|
741
|
+
search_terms=("playbook", "learn", "remember", "lessons"),
|
|
742
|
+
),
|
|
743
|
+
SlashCommand(
|
|
744
|
+
name="compact",
|
|
745
|
+
description="Summarise older context",
|
|
746
|
+
handler=_cmd_compact,
|
|
747
|
+
usage="/compact",
|
|
748
|
+
search_terms=("compress", "summarize", "prune"),
|
|
749
|
+
),
|
|
750
|
+
SlashCommand(
|
|
751
|
+
name="stats",
|
|
752
|
+
description="Show token/turn/cost statistics",
|
|
753
|
+
handler=_cmd_stats,
|
|
754
|
+
usage="/stats",
|
|
755
|
+
search_terms=("tokens", "cost", "usage"),
|
|
756
|
+
),
|
|
757
|
+
SlashCommand(
|
|
758
|
+
name="name",
|
|
759
|
+
description="Show or set session title",
|
|
760
|
+
handler=_cmd_name,
|
|
761
|
+
usage="/name [title]",
|
|
762
|
+
aliases=("title",),
|
|
763
|
+
search_terms=("rename", "label"),
|
|
764
|
+
),
|
|
765
|
+
SlashCommand(
|
|
766
|
+
name="branch",
|
|
767
|
+
description="Fork the conversation here",
|
|
768
|
+
handler=_cmd_branch,
|
|
769
|
+
usage="/branch [summary]",
|
|
770
|
+
aliases=("fork",),
|
|
771
|
+
search_terms=("diverge", "split"),
|
|
772
|
+
),
|
|
773
|
+
SlashCommand(
|
|
774
|
+
name="rewind",
|
|
775
|
+
description="Rewind to a prior entry (no argument lists them)",
|
|
776
|
+
handler=_cmd_rewind,
|
|
777
|
+
usage="/rewind [number]",
|
|
778
|
+
search_terms=("undo", "rollback", "back"),
|
|
779
|
+
),
|
|
780
|
+
SlashCommand(
|
|
781
|
+
name="branches",
|
|
782
|
+
description="List fork points",
|
|
783
|
+
handler=_cmd_branches,
|
|
784
|
+
usage="/branches",
|
|
785
|
+
search_terms=("forks", "tree", "history"),
|
|
786
|
+
),
|
|
787
|
+
SlashCommand(
|
|
788
|
+
name="create-skill",
|
|
789
|
+
description="Save a new skill",
|
|
790
|
+
handler=_cmd_create_skill,
|
|
791
|
+
usage="/create-skill <name> <text>",
|
|
792
|
+
search_terms=("add", "author", "write"),
|
|
793
|
+
),
|
|
794
|
+
SlashCommand(
|
|
795
|
+
name="continue",
|
|
796
|
+
description="Resume the agent loop after a stop",
|
|
797
|
+
handler=_cmd_continue,
|
|
798
|
+
usage="/continue",
|
|
799
|
+
aliases=("cont",),
|
|
800
|
+
search_terms=("carry", "on", "proceed"),
|
|
801
|
+
),
|
|
802
|
+
SlashCommand(
|
|
803
|
+
name="shell",
|
|
804
|
+
description="Run a shell command",
|
|
805
|
+
handler=_cmd_shell,
|
|
806
|
+
usage="/shell <command>",
|
|
807
|
+
aliases=("sh", "!"),
|
|
808
|
+
search_terms=("terminal", "exec", "bash"),
|
|
809
|
+
),
|
|
810
|
+
SlashCommand(
|
|
811
|
+
name="diag",
|
|
812
|
+
description="Dump session diagnostics",
|
|
813
|
+
handler=_cmd_diag,
|
|
814
|
+
usage="/diag",
|
|
815
|
+
aliases=("debug",),
|
|
816
|
+
search_terms=("diagnostics", "inspect"),
|
|
817
|
+
),
|
|
818
|
+
SlashCommand(
|
|
819
|
+
name="system",
|
|
820
|
+
description="Show the system prompt and where each part came from",
|
|
821
|
+
handler=_cmd_system,
|
|
822
|
+
usage="/system",
|
|
823
|
+
search_terms=("prompt", "instructions", "provenance", "agents.md"),
|
|
824
|
+
),
|
|
825
|
+
SlashCommand(
|
|
826
|
+
name="skills",
|
|
827
|
+
description="List available skills",
|
|
828
|
+
handler=_cmd_skills,
|
|
829
|
+
usage="/skills",
|
|
830
|
+
search_terms=("abilities",),
|
|
831
|
+
),
|
|
832
|
+
SlashCommand(
|
|
833
|
+
name="prompts",
|
|
834
|
+
description="List prompt templates",
|
|
835
|
+
handler=_cmd_prompts,
|
|
836
|
+
usage="/prompts",
|
|
837
|
+
aliases=("templates",),
|
|
838
|
+
search_terms=("snippets",),
|
|
839
|
+
),
|
|
840
|
+
SlashCommand(
|
|
841
|
+
name="theme",
|
|
842
|
+
description="Show or switch theme",
|
|
843
|
+
handler=_cmd_theme,
|
|
844
|
+
usage="/theme [name]",
|
|
845
|
+
search_terms=("color", "style", "appearance"),
|
|
846
|
+
),
|
|
847
|
+
SlashCommand(
|
|
848
|
+
name="login",
|
|
849
|
+
description="Authenticate with a provider",
|
|
850
|
+
handler=_cmd_login,
|
|
851
|
+
usage="/login [provider]",
|
|
852
|
+
search_terms=("auth", "authenticate", "key"),
|
|
853
|
+
),
|
|
854
|
+
SlashCommand(
|
|
855
|
+
name="logout",
|
|
856
|
+
description="Deauthenticate from a provider",
|
|
857
|
+
handler=_cmd_logout,
|
|
858
|
+
usage="/logout [provider]",
|
|
859
|
+
search_terms=("deauth", "revoke"),
|
|
860
|
+
),
|
|
861
|
+
SlashCommand(
|
|
862
|
+
name="config",
|
|
863
|
+
description="Show or edit configuration",
|
|
864
|
+
handler=_cmd_config,
|
|
865
|
+
usage="/config [key=value]",
|
|
866
|
+
aliases=("settings",),
|
|
867
|
+
search_terms=("preferences", "options"),
|
|
868
|
+
),
|
|
869
|
+
SlashCommand(
|
|
870
|
+
name="doctor",
|
|
871
|
+
description="Run environment health checks",
|
|
872
|
+
handler=_cmd_doctor,
|
|
873
|
+
usage="/doctor",
|
|
874
|
+
search_terms=("health", "check", "verify"),
|
|
875
|
+
),
|
|
876
|
+
]
|
|
877
|
+
|
|
878
|
+
for cmd in _BUILTINS:
|
|
879
|
+
reg.register(cmd)
|
|
880
|
+
|
|
881
|
+
return reg
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
__all__ = [
|
|
885
|
+
"CommandContext",
|
|
886
|
+
"CommandRegistry",
|
|
887
|
+
"CommandResult",
|
|
888
|
+
"CommandSession",
|
|
889
|
+
"Handler",
|
|
890
|
+
"SlashCommand",
|
|
891
|
+
"build_default_registry",
|
|
892
|
+
"parse_command",
|
|
893
|
+
]
|