agent-brain-cli 10.2.0__tar.gz → 10.2.1__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.
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/PKG-INFO +3 -3
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/__init__.py +1 -1
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/client/api_client.py +16 -2
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/client/transport.py +10 -4
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/init.py +31 -2
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/start.py +6 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/config.py +52 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/pyproject.toml +3 -3
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/README.md +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/cli.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/client/__init__.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/__init__.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/cache.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/config.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/doctor.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/folders.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/index.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/inject.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/install_agent.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/jobs.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/list_cmd.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/query.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/reset.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/status.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/stop.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/types.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/commands/uninstall.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/config_migrate.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/config_schema.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/diagnostics.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/migration.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/runtime/__init__.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/runtime/claude_converter.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/runtime/codex_converter.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/runtime/converter_base.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/runtime/gemini_converter.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/runtime/opencode_converter.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/runtime/parser.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/runtime/skill_runtime_converter.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/runtime/tool_maps.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/runtime/types.py +0 -0
- {agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/xdg_paths.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: agent-brain-cli
|
|
3
|
-
Version: 10.2.
|
|
3
|
+
Version: 10.2.1
|
|
4
4
|
Summary: Agent Brain CLI - Command-line interface for managing AI agent memory and knowledge retrieval
|
|
5
5
|
Home-page: https://github.com/SpillwaveSolutions/agent-brain
|
|
6
6
|
License: MIT
|
|
@@ -15,8 +15,8 @@ Classifier: Programming Language :: Python :: 3
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
-
Requires-Dist: agent-brain-rag (>=10.2.
|
|
19
|
-
Requires-Dist: agent-brain-uds (>=10.2.
|
|
18
|
+
Requires-Dist: agent-brain-rag (>=10.2.1,<11.0.0)
|
|
19
|
+
Requires-Dist: agent-brain-uds (>=10.2.1,<11.0.0)
|
|
20
20
|
Requires-Dist: click (>=8.1.0,<9.0.0)
|
|
21
21
|
Requires-Dist: httpx (>=0.28.0,<0.29.0)
|
|
22
22
|
Requires-Dist: pydantic (>=2.10.0,<3.0.0)
|
|
@@ -159,6 +159,7 @@ class DocServeClient:
|
|
|
159
159
|
self,
|
|
160
160
|
base_url: str = "http://127.0.0.1:8000",
|
|
161
161
|
timeout: float = 30.0,
|
|
162
|
+
api_key: str | None = None,
|
|
162
163
|
):
|
|
163
164
|
"""
|
|
164
165
|
Initialize the client.
|
|
@@ -166,13 +167,21 @@ class DocServeClient:
|
|
|
166
167
|
Args:
|
|
167
168
|
base_url: Server base URL.
|
|
168
169
|
timeout: Request timeout in seconds.
|
|
170
|
+
api_key: Optional X-API-Key value (Issue #179). When supplied,
|
|
171
|
+
every outbound request carries the header. ``None`` means
|
|
172
|
+
no auth (legacy single-user loopback dev path).
|
|
169
173
|
"""
|
|
170
174
|
self.base_url = base_url.rstrip("/")
|
|
171
175
|
self.timeout = timeout
|
|
172
|
-
|
|
176
|
+
headers = {"X-API-Key": api_key} if api_key else None
|
|
177
|
+
self._client = httpx.Client(timeout=timeout, headers=headers)
|
|
173
178
|
|
|
174
179
|
@classmethod
|
|
175
|
-
def from_httpx(
|
|
180
|
+
def from_httpx(
|
|
181
|
+
cls,
|
|
182
|
+
client: httpx.Client,
|
|
183
|
+
api_key: str | None = None,
|
|
184
|
+
) -> "DocServeClient":
|
|
176
185
|
"""Build a DocServeClient that uses a pre-constructed httpx.Client.
|
|
177
186
|
|
|
178
187
|
Used by the transport selector to inject a UDS-backed client
|
|
@@ -183,6 +192,9 @@ class DocServeClient:
|
|
|
183
192
|
Args:
|
|
184
193
|
client: An already-configured ``httpx.Client``. The wrapper
|
|
185
194
|
takes ownership and will close it on ``__exit__``.
|
|
195
|
+
api_key: Optional X-API-Key to merge into the client's
|
|
196
|
+
default headers (Issue #179). Caller may also have set
|
|
197
|
+
the header on ``client`` directly; both paths work.
|
|
186
198
|
|
|
187
199
|
Returns:
|
|
188
200
|
A DocServeClient backed by ``client``.
|
|
@@ -191,6 +203,8 @@ class DocServeClient:
|
|
|
191
203
|
instance.base_url = "" # inner client carries the real base_url
|
|
192
204
|
timeout = client.timeout
|
|
193
205
|
instance.timeout = timeout.read or 30.0
|
|
206
|
+
if api_key:
|
|
207
|
+
client.headers["X-API-Key"] = api_key
|
|
194
208
|
instance._client = client
|
|
195
209
|
return instance
|
|
196
210
|
|
|
@@ -17,7 +17,7 @@ from pathlib import Path
|
|
|
17
17
|
|
|
18
18
|
import click
|
|
19
19
|
|
|
20
|
-
from ..config import resolve_transport
|
|
20
|
+
from ..config import resolve_api_key, resolve_transport
|
|
21
21
|
from .api_client import DocServeClient
|
|
22
22
|
|
|
23
23
|
|
|
@@ -41,14 +41,20 @@ def open_client(ctx: click.Context, *, timeout: float = 30.0) -> DocServeClient:
|
|
|
41
41
|
base_url_override=obj.get("base_url_override"),
|
|
42
42
|
socket_path_override=obj.get("socket_path_override"),
|
|
43
43
|
)
|
|
44
|
+
# Issue #179: resolve the API key alongside the transport so the same
|
|
45
|
+
# CLI invocation works against an authed and an unauthed server.
|
|
46
|
+
api_key = resolve_api_key()
|
|
44
47
|
if obj.get("debug_transport"):
|
|
45
|
-
|
|
48
|
+
auth_marker = "with X-API-Key" if api_key else "no auth"
|
|
49
|
+
click.echo(
|
|
50
|
+
f"[debug-transport] {transport} -> {target} ({auth_marker})", err=True
|
|
51
|
+
)
|
|
46
52
|
|
|
47
53
|
if transport == "http":
|
|
48
|
-
return DocServeClient(base_url=target, timeout=timeout)
|
|
54
|
+
return DocServeClient(base_url=target, timeout=timeout, api_key=api_key)
|
|
49
55
|
|
|
50
56
|
# UDS: import lazily so HTTP-only invocations don't pay the cost.
|
|
51
57
|
from agent_brain_uds import make_client
|
|
52
58
|
|
|
53
59
|
inner = make_client(socket_path=Path(target), timeout=timeout)
|
|
54
|
-
return DocServeClient.from_httpx(inner)
|
|
60
|
+
return DocServeClient.from_httpx(inner, api_key=api_key)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Init command for initializing an Agent Brain project."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
import secrets
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
|
|
6
7
|
import click
|
|
@@ -69,6 +70,14 @@ STATE_DIR_NAME = ".agent-brain"
|
|
|
69
70
|
type=click.Path(file_okay=False, resolve_path=True),
|
|
70
71
|
help="Custom state directory for index data (default: .agent-brain)",
|
|
71
72
|
)
|
|
73
|
+
@click.option(
|
|
74
|
+
"--no-api-key",
|
|
75
|
+
is_flag=True,
|
|
76
|
+
help=(
|
|
77
|
+
"Skip auto-generating an API key (Issue #179). Use for single-user "
|
|
78
|
+
"loopback dev when no auth is desired. Server still starts without auth."
|
|
79
|
+
),
|
|
80
|
+
)
|
|
72
81
|
def init_command(
|
|
73
82
|
path: str | None,
|
|
74
83
|
host: str,
|
|
@@ -76,6 +85,7 @@ def init_command(
|
|
|
76
85
|
force: bool,
|
|
77
86
|
json_output: bool,
|
|
78
87
|
state_dir: str | None,
|
|
88
|
+
no_api_key: bool,
|
|
79
89
|
) -> None:
|
|
80
90
|
"""Initialize a new Agent Brain project.
|
|
81
91
|
|
|
@@ -145,8 +155,21 @@ def init_command(
|
|
|
145
155
|
config["port"] = port
|
|
146
156
|
config["auto_port"] = False
|
|
147
157
|
|
|
148
|
-
#
|
|
158
|
+
# Issue #179: auto-generate an API key so the server boots with auth
|
|
159
|
+
# by default. Stored in config.json (project-local); the `start`
|
|
160
|
+
# command exports it as AGENT_BRAIN_API_KEY for the server
|
|
161
|
+
# subprocess, and `resolve_api_key` reads it for the CLI side. Opt
|
|
162
|
+
# out with --no-api-key for single-user loopback workflows.
|
|
163
|
+
if not no_api_key:
|
|
164
|
+
config["api_key"] = secrets.token_urlsafe(32)
|
|
165
|
+
|
|
166
|
+
# Write configuration with mode 0o600 since it may carry a secret.
|
|
149
167
|
config_path.write_text(json.dumps(config, indent=2))
|
|
168
|
+
try:
|
|
169
|
+
config_path.chmod(0o600)
|
|
170
|
+
except OSError:
|
|
171
|
+
# Best-effort; filesystems without POSIX modes (FAT) still work.
|
|
172
|
+
pass
|
|
150
173
|
|
|
151
174
|
if json_output:
|
|
152
175
|
click.echo(
|
|
@@ -162,12 +185,18 @@ def init_command(
|
|
|
162
185
|
)
|
|
163
186
|
)
|
|
164
187
|
else:
|
|
188
|
+
api_key_note = (
|
|
189
|
+
f"[bold]API Key:[/] generated ({config_path.name}, mode 0o600)"
|
|
190
|
+
if not no_api_key
|
|
191
|
+
else "[bold]API Key:[/] [yellow]disabled[/] (--no-api-key)"
|
|
192
|
+
)
|
|
165
193
|
console.print(
|
|
166
194
|
Panel(
|
|
167
195
|
f"[green]Project initialized successfully![/]\n\n"
|
|
168
196
|
f"[bold]Project Root:[/] {project_root}\n"
|
|
169
197
|
f"[bold]State Directory:[/] {resolved_state_dir}\n"
|
|
170
|
-
f"[bold]Configuration:[/] {config_path}"
|
|
198
|
+
f"[bold]Configuration:[/] {config_path}\n"
|
|
199
|
+
f"{api_key_note}",
|
|
171
200
|
title="Agent Brain Initialized",
|
|
172
201
|
border_style="green",
|
|
173
202
|
)
|
|
@@ -368,6 +368,12 @@ def start_command(
|
|
|
368
368
|
env = os.environ.copy()
|
|
369
369
|
env["AGENT_BRAIN_PROJECT_ROOT"] = str(project_root)
|
|
370
370
|
env["AGENT_BRAIN_STATE_DIR"] = str(state_dir)
|
|
371
|
+
# Issue #179: propagate the project-local API key from config.json
|
|
372
|
+
# into the server subprocess. Existing env value wins so operators
|
|
373
|
+
# can override the file-stored key without re-running init.
|
|
374
|
+
config_api_key = config.get("api_key")
|
|
375
|
+
if config_api_key and not env.get("AGENT_BRAIN_API_KEY"):
|
|
376
|
+
env["AGENT_BRAIN_API_KEY"] = str(config_api_key)
|
|
371
377
|
if strict:
|
|
372
378
|
env["AGENT_BRAIN_STRICT_MODE"] = "true"
|
|
373
379
|
if enable_uds:
|
|
@@ -414,6 +414,58 @@ def get_server_url(config: AgentBrainConfig | None = None) -> str:
|
|
|
414
414
|
return config.server.url
|
|
415
415
|
|
|
416
416
|
|
|
417
|
+
def resolve_api_key(state_dir: Path | None = None) -> str | None:
|
|
418
|
+
"""Resolve the X-API-Key value the CLI should send (Issue #179).
|
|
419
|
+
|
|
420
|
+
Precedence (first non-empty wins):
|
|
421
|
+
1. ``AGENT_BRAIN_API_KEY`` environment variable
|
|
422
|
+
2. ``runtime.json::api_key`` for the resolved state directory
|
|
423
|
+
(set by the running server)
|
|
424
|
+
3. ``config.json::api_key`` for the resolved state directory
|
|
425
|
+
(set by ``agent-brain init``, used when the server hasn't
|
|
426
|
+
started yet)
|
|
427
|
+
|
|
428
|
+
Returns ``None`` when no source provides a value, which is the
|
|
429
|
+
correct behavior for a server running in default no-auth loopback
|
|
430
|
+
mode — the client sends no header and the server's no-op dependency
|
|
431
|
+
accepts the request.
|
|
432
|
+
|
|
433
|
+
Args:
|
|
434
|
+
state_dir: Optional state directory to read from. Defaults to
|
|
435
|
+
``get_state_dir()`` so callers in CLI commands don't need
|
|
436
|
+
to thread the path through.
|
|
437
|
+
|
|
438
|
+
Returns:
|
|
439
|
+
The resolved API key or ``None``.
|
|
440
|
+
"""
|
|
441
|
+
import json
|
|
442
|
+
|
|
443
|
+
env_key = os.getenv("AGENT_BRAIN_API_KEY")
|
|
444
|
+
if env_key:
|
|
445
|
+
return env_key
|
|
446
|
+
|
|
447
|
+
if state_dir is None:
|
|
448
|
+
try:
|
|
449
|
+
state_dir = get_state_dir()
|
|
450
|
+
except Exception:
|
|
451
|
+
return None
|
|
452
|
+
|
|
453
|
+
for filename in ("runtime.json", "config.json"):
|
|
454
|
+
candidate = state_dir / filename
|
|
455
|
+
if not candidate.exists():
|
|
456
|
+
continue
|
|
457
|
+
try:
|
|
458
|
+
with open(candidate) as f:
|
|
459
|
+
payload = json.load(f)
|
|
460
|
+
except (json.JSONDecodeError, OSError):
|
|
461
|
+
continue
|
|
462
|
+
api_key = payload.get("api_key")
|
|
463
|
+
if api_key:
|
|
464
|
+
return str(api_key)
|
|
465
|
+
|
|
466
|
+
return None
|
|
467
|
+
|
|
468
|
+
|
|
417
469
|
def resolve_transport(
|
|
418
470
|
*,
|
|
419
471
|
transport_hint: str | None = None,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "agent-brain-cli"
|
|
3
|
-
version = "10.2.
|
|
3
|
+
version = "10.2.1"
|
|
4
4
|
description = "Agent Brain CLI - Command-line interface for managing AI agent memory and knowledge retrieval"
|
|
5
5
|
authors = ["Spillwave Solutions"]
|
|
6
6
|
readme = "README.md"
|
|
@@ -27,8 +27,8 @@ httpx = "^0.28.0"
|
|
|
27
27
|
rich = "^13.9.0"
|
|
28
28
|
pyyaml = "^6.0.0"
|
|
29
29
|
pydantic = "^2.10.0"
|
|
30
|
-
agent-brain-rag = "^10.2.
|
|
31
|
-
agent-brain-uds = "^10.2.
|
|
30
|
+
agent-brain-rag = "^10.2.1"
|
|
31
|
+
agent-brain-uds = "^10.2.1"
|
|
32
32
|
|
|
33
33
|
[tool.poetry.group.dev.dependencies]
|
|
34
34
|
pytest = "^8.3.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/runtime/claude_converter.py
RENAMED
|
File without changes
|
{agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/runtime/codex_converter.py
RENAMED
|
File without changes
|
|
File without changes
|
{agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/runtime/gemini_converter.py
RENAMED
|
File without changes
|
{agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/runtime/opencode_converter.py
RENAMED
|
File without changes
|
|
File without changes
|
{agent_brain_cli-10.2.0 → agent_brain_cli-10.2.1}/agent_brain_cli/runtime/skill_runtime_converter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|