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/config/store.py
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"""Persisted user configuration: schema, file location, and TOML read/write."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
import tomllib
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
# ---------------------------------------------------------------------------
|
|
12
|
+
# Provider metadata (plain data — the set of backends rlm-agent can talk to)
|
|
13
|
+
# ---------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True, slots=True)
|
|
17
|
+
class ProviderInfo:
|
|
18
|
+
"""Static facts about a supported provider backend."""
|
|
19
|
+
|
|
20
|
+
key: str
|
|
21
|
+
label: str
|
|
22
|
+
key_env: str
|
|
23
|
+
base_url: str
|
|
24
|
+
models: tuple[str, ...]
|
|
25
|
+
needs_key: bool = True
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
PROVIDERS: tuple[ProviderInfo, ...] = (
|
|
29
|
+
ProviderInfo(key="copilot", label="GitHub Copilot", key_env="COPILOT_GITHUB_TOKEN",
|
|
30
|
+
base_url="", models=("auto",), needs_key=False),
|
|
31
|
+
ProviderInfo(key="claude-subscription", label="Claude Code subscription", key_env="",
|
|
32
|
+
base_url="", models=("cli:claude-code",), needs_key=False),
|
|
33
|
+
ProviderInfo(key="xai", label="xAI", key_env="XAI_API_KEY",
|
|
34
|
+
base_url="https://api.x.ai/v1", models=("grok-4",)),
|
|
35
|
+
ProviderInfo(key="xai-subscription", label="xAI registered OAuth", key_env="",
|
|
36
|
+
base_url="https://api.x.ai/v1", models=("grok-4",), needs_key=False),
|
|
37
|
+
ProviderInfo(key="codex", label="Codex subscription", key_env="",
|
|
38
|
+
base_url="https://api.openai.com/v1", models=("gpt-6.1-sol",), needs_key=False),
|
|
39
|
+
ProviderInfo(key="google", label="Google Gemini", key_env="GOOGLE_API_KEY",
|
|
40
|
+
base_url="https://generativelanguage.googleapis.com/v1beta", models=("gemini-2.5-flash",)),
|
|
41
|
+
ProviderInfo(key="mistral", label="Mistral", key_env="MISTRAL_API_KEY",
|
|
42
|
+
base_url="https://api.mistral.ai/v1", models=("mistral-small-latest",)),
|
|
43
|
+
ProviderInfo(key="azure", label="Azure OpenAI", key_env="AZURE_OPENAI_API_KEY",
|
|
44
|
+
base_url="", models=("deployment-name",)),
|
|
45
|
+
ProviderInfo(
|
|
46
|
+
key="openai",
|
|
47
|
+
label="OpenAI",
|
|
48
|
+
key_env="OPENAI_API_KEY",
|
|
49
|
+
base_url="https://api.openai.com/v1",
|
|
50
|
+
models=("gpt-5", "gpt-5-mini", "gpt-4.1"),
|
|
51
|
+
),
|
|
52
|
+
ProviderInfo(
|
|
53
|
+
key="anthropic",
|
|
54
|
+
label="Anthropic",
|
|
55
|
+
key_env="ANTHROPIC_API_KEY",
|
|
56
|
+
base_url="https://api.anthropic.com",
|
|
57
|
+
models=("claude-opus-5", "claude-sonnet-5", "claude-haiku-4-5"),
|
|
58
|
+
),
|
|
59
|
+
ProviderInfo(
|
|
60
|
+
key="openrouter",
|
|
61
|
+
label="OpenRouter",
|
|
62
|
+
key_env="OPENROUTER_API_KEY",
|
|
63
|
+
base_url="https://openrouter.ai/api/v1",
|
|
64
|
+
models=(
|
|
65
|
+
"anthropic/claude-opus-5",
|
|
66
|
+
"openai/gpt-5",
|
|
67
|
+
"meta-llama/llama-3.3-70b-instruct",
|
|
68
|
+
),
|
|
69
|
+
),
|
|
70
|
+
ProviderInfo(
|
|
71
|
+
key="ollama",
|
|
72
|
+
label="Ollama",
|
|
73
|
+
key_env="OLLAMA_API_KEY",
|
|
74
|
+
base_url="http://localhost:11434/v1",
|
|
75
|
+
models=("llama3.3", "qwen2.5-coder", "deepseek-r1"),
|
|
76
|
+
needs_key=False,
|
|
77
|
+
),
|
|
78
|
+
ProviderInfo(
|
|
79
|
+
key="huggingface",
|
|
80
|
+
label="Hugging Face",
|
|
81
|
+
key_env="HF_TOKEN",
|
|
82
|
+
base_url="https://router.huggingface.co/v1",
|
|
83
|
+
models=(
|
|
84
|
+
"openai/gpt-oss-120b",
|
|
85
|
+
"Qwen/Qwen3-Coder-480B-A35B-Instruct",
|
|
86
|
+
"moonshotai/Kimi-K2-Instruct",
|
|
87
|
+
),
|
|
88
|
+
),
|
|
89
|
+
ProviderInfo(key="vertex", label="Google Vertex", key_env="GOOGLE_CLOUD_PROJECT",
|
|
90
|
+
base_url="", models=("google/gemini-3.5-flash",), needs_key=False),
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def provider_info(key: str) -> ProviderInfo:
|
|
95
|
+
"""Look up provider metadata by key, raising ``KeyError`` when unknown."""
|
|
96
|
+
for info in PROVIDERS:
|
|
97
|
+
if info.key == key:
|
|
98
|
+
return info
|
|
99
|
+
raise KeyError(key)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
PROVIDER_KEYS: tuple[str, ...] = tuple(p.key for p in PROVIDERS)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# ---------------------------------------------------------------------------
|
|
106
|
+
# Config file schema
|
|
107
|
+
# ---------------------------------------------------------------------------
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@dataclass(slots=True)
|
|
111
|
+
class RlmAgentConfig:
|
|
112
|
+
"""Contents of the user's ``config.toml``."""
|
|
113
|
+
|
|
114
|
+
provider: str | None = None
|
|
115
|
+
model: str | None = None
|
|
116
|
+
api_keys: dict[str, str] = field(default_factory=dict)
|
|
117
|
+
base_urls: dict[str, str] = field(default_factory=dict)
|
|
118
|
+
# How folders with no saved trust decision are treated: ask, always, never.
|
|
119
|
+
# Read only from this user-wide file, never from a project.
|
|
120
|
+
project_trust: str | None = None
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# ---------------------------------------------------------------------------
|
|
124
|
+
# Location
|
|
125
|
+
# ---------------------------------------------------------------------------
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
MAX_RECENT = 8
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def recent_models() -> list[dict]:
|
|
132
|
+
"""Models chosen before, newest first: [{"provider", "model"}]. Holds no keys."""
|
|
133
|
+
try:
|
|
134
|
+
saved = json.loads((config_dir() / "recent_models.json").read_text(encoding="utf-8"))
|
|
135
|
+
except (OSError, ValueError):
|
|
136
|
+
return []
|
|
137
|
+
return [r for r in saved if isinstance(r, dict) and r.get("provider") and r.get("model")]
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def remember_model(provider: str, model: str) -> None:
|
|
141
|
+
entry = {"provider": provider, "model": model}
|
|
142
|
+
kept = [entry] + [r for r in recent_models() if r != entry]
|
|
143
|
+
config_dir().mkdir(parents=True, exist_ok=True)
|
|
144
|
+
(config_dir() / "recent_models.json").write_text(
|
|
145
|
+
json.dumps(kept[:MAX_RECENT], indent=2), encoding="utf-8")
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def forget_model(provider: str, model: str) -> None:
|
|
149
|
+
kept = [r for r in recent_models() if r != {"provider": provider, "model": model}]
|
|
150
|
+
(config_dir() / "recent_models.json").write_text(json.dumps(kept, indent=2), encoding="utf-8")
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def config_dir() -> Path:
|
|
154
|
+
"""Directory holding rlm-agent's user configuration."""
|
|
155
|
+
override = os.environ.get("RLM_AGENT_CONFIG_DIR") or os.environ.get("RLM_AGENT_HOME")
|
|
156
|
+
if override:
|
|
157
|
+
return Path(override)
|
|
158
|
+
return Path.home() / ".rlm-agent"
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def config_path() -> Path:
|
|
162
|
+
"""Full path to ``config.toml``."""
|
|
163
|
+
return config_dir() / "config.toml"
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
# ---------------------------------------------------------------------------
|
|
167
|
+
# Read
|
|
168
|
+
# ---------------------------------------------------------------------------
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def load_config() -> RlmAgentConfig:
|
|
172
|
+
"""Read the config file, returning empty defaults when absent or malformed."""
|
|
173
|
+
path = config_path()
|
|
174
|
+
try:
|
|
175
|
+
raw = path.read_bytes()
|
|
176
|
+
except OSError:
|
|
177
|
+
return RlmAgentConfig()
|
|
178
|
+
|
|
179
|
+
try:
|
|
180
|
+
data = tomllib.loads(raw.decode("utf-8"))
|
|
181
|
+
except (tomllib.TOMLDecodeError, UnicodeDecodeError):
|
|
182
|
+
return RlmAgentConfig()
|
|
183
|
+
|
|
184
|
+
providers = data.get("providers")
|
|
185
|
+
api_keys: dict[str, str] = {}
|
|
186
|
+
base_urls: dict[str, str] = {}
|
|
187
|
+
if isinstance(providers, dict):
|
|
188
|
+
for name, section in providers.items():
|
|
189
|
+
if not isinstance(section, dict):
|
|
190
|
+
continue
|
|
191
|
+
key = section.get("api_key")
|
|
192
|
+
if isinstance(key, str) and key:
|
|
193
|
+
api_keys[name] = key
|
|
194
|
+
url = section.get("base_url")
|
|
195
|
+
if isinstance(url, str) and url:
|
|
196
|
+
base_urls[name] = url
|
|
197
|
+
|
|
198
|
+
provider = data.get("provider")
|
|
199
|
+
model = data.get("model")
|
|
200
|
+
trust = data.get("project_trust")
|
|
201
|
+
return RlmAgentConfig(
|
|
202
|
+
provider=provider if isinstance(provider, str) and provider else None,
|
|
203
|
+
model=model if isinstance(model, str) and model else None,
|
|
204
|
+
api_keys=api_keys,
|
|
205
|
+
base_urls=base_urls,
|
|
206
|
+
project_trust=trust if trust in ("ask", "always", "never") else None,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
# ---------------------------------------------------------------------------
|
|
211
|
+
# Write
|
|
212
|
+
# ---------------------------------------------------------------------------
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def _quote(value: str) -> str:
|
|
216
|
+
"""Serialize a string as a TOML basic string."""
|
|
217
|
+
escaped = value.replace("\\", "\\\\").replace('"', '\\"')
|
|
218
|
+
return f'"{escaped}"'
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def render_config(config: RlmAgentConfig) -> str:
|
|
222
|
+
"""Render *config* as TOML text."""
|
|
223
|
+
lines: list[str] = []
|
|
224
|
+
if config.provider:
|
|
225
|
+
lines.append(f"provider = {_quote(config.provider)}")
|
|
226
|
+
if config.model:
|
|
227
|
+
lines.append(f"model = {_quote(config.model)}")
|
|
228
|
+
if config.project_trust:
|
|
229
|
+
lines.append(f"project_trust = {_quote(config.project_trust)}")
|
|
230
|
+
|
|
231
|
+
names = sorted(set(config.api_keys) | set(config.base_urls))
|
|
232
|
+
for name in names:
|
|
233
|
+
lines.append("")
|
|
234
|
+
lines.append(f"[providers.{name}]")
|
|
235
|
+
if name in config.api_keys:
|
|
236
|
+
lines.append(f"api_key = {_quote(config.api_keys[name])}")
|
|
237
|
+
if name in config.base_urls:
|
|
238
|
+
lines.append(f"base_url = {_quote(config.base_urls[name])}")
|
|
239
|
+
return "\n".join(lines) + "\n"
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def save_config(config: RlmAgentConfig) -> Path:
|
|
243
|
+
"""Write *config* to disk with owner-only permissions."""
|
|
244
|
+
path = config_path()
|
|
245
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
246
|
+
path.write_text(render_config(config), encoding="utf-8")
|
|
247
|
+
try:
|
|
248
|
+
path.chmod(0o600)
|
|
249
|
+
except OSError:
|
|
250
|
+
pass # best effort — some filesystems (e.g. FAT) reject chmod
|
|
251
|
+
return path
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def mask_key(value: str) -> str:
|
|
255
|
+
"""Render an API key safe for display: last four characters only."""
|
|
256
|
+
if not value:
|
|
257
|
+
return ""
|
|
258
|
+
if len(value) <= 4:
|
|
259
|
+
return "*" * len(value)
|
|
260
|
+
return "*" * (len(value) - 4) + value[-4:]
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
__all__ = [
|
|
264
|
+
"RlmAgentConfig",
|
|
265
|
+
"PROVIDERS",
|
|
266
|
+
"PROVIDER_KEYS",
|
|
267
|
+
"ProviderInfo",
|
|
268
|
+
"config_dir",
|
|
269
|
+
"config_path",
|
|
270
|
+
"load_config",
|
|
271
|
+
"mask_key",
|
|
272
|
+
"provider_info",
|
|
273
|
+
"render_config",
|
|
274
|
+
"save_config",
|
|
275
|
+
]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""rlm-agent context: token budgeting, threshold detection, and compaction planning."""
|
|
2
|
+
|
|
3
|
+
from rlmagent.context.budget import (
|
|
4
|
+
CHARS_PER_TOKEN,
|
|
5
|
+
DEFAULT_SUMMARY_SYSTEM,
|
|
6
|
+
DEFAULT_WINDOW,
|
|
7
|
+
MODEL_WINDOWS,
|
|
8
|
+
TOOL_SCHEMA_BASELINE,
|
|
9
|
+
CompactionPlan,
|
|
10
|
+
CompactionResult,
|
|
11
|
+
ContextEstimate,
|
|
12
|
+
ContextLimits,
|
|
13
|
+
apply_compaction,
|
|
14
|
+
build_summary_prompts,
|
|
15
|
+
estimate_context,
|
|
16
|
+
estimate_entry_tokens,
|
|
17
|
+
estimate_system_tokens,
|
|
18
|
+
estimate_tool_tokens,
|
|
19
|
+
estimate_transcript_tokens,
|
|
20
|
+
exceeds_threshold,
|
|
21
|
+
plan_compaction,
|
|
22
|
+
resolve_window,
|
|
23
|
+
serialize_for_summary,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"CHARS_PER_TOKEN",
|
|
28
|
+
"CompactionPlan",
|
|
29
|
+
"CompactionResult",
|
|
30
|
+
"ContextEstimate",
|
|
31
|
+
"ContextLimits",
|
|
32
|
+
"DEFAULT_SUMMARY_SYSTEM",
|
|
33
|
+
"DEFAULT_WINDOW",
|
|
34
|
+
"MODEL_WINDOWS",
|
|
35
|
+
"TOOL_SCHEMA_BASELINE",
|
|
36
|
+
"apply_compaction",
|
|
37
|
+
"build_summary_prompts",
|
|
38
|
+
"estimate_context",
|
|
39
|
+
"estimate_entry_tokens",
|
|
40
|
+
"estimate_system_tokens",
|
|
41
|
+
"estimate_tool_tokens",
|
|
42
|
+
"estimate_transcript_tokens",
|
|
43
|
+
"exceeds_threshold",
|
|
44
|
+
"plan_compaction",
|
|
45
|
+
"resolve_window",
|
|
46
|
+
"serialize_for_summary",
|
|
47
|
+
]
|