meridian-cli 0.0.25__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.
- meridian/__init__.py +5 -0
- meridian/__main__.py +6 -0
- meridian/cli/__init__.py +5 -0
- meridian/cli/app_cmd.py +48 -0
- meridian/cli/config_cmd.py +41 -0
- meridian/cli/doctor_cmd.py +34 -0
- meridian/cli/format_helpers.py +35 -0
- meridian/cli/main.py +1323 -0
- meridian/cli/models_cmd.py +31 -0
- meridian/cli/output.py +227 -0
- meridian/cli/registration.py +115 -0
- meridian/cli/report_cmd.py +117 -0
- meridian/cli/session_cmd.py +133 -0
- meridian/cli/spawn.py +747 -0
- meridian/cli/spawn_inject.py +112 -0
- meridian/cli/streaming_serve.py +175 -0
- meridian/cli/utils.py +52 -0
- meridian/cli/work_cmd.py +228 -0
- meridian/dev/__init__.py +1 -0
- meridian/dev/pytests.py +50 -0
- meridian/lib/__init__.py +6 -0
- meridian/lib/adapters/__init__.py +15 -0
- meridian/lib/app/__init__.py +3 -0
- meridian/lib/app/agui_mapping/__init__.py +26 -0
- meridian/lib/app/agui_mapping/base.py +25 -0
- meridian/lib/app/agui_mapping/claude.py +380 -0
- meridian/lib/app/agui_mapping/codex.py +257 -0
- meridian/lib/app/agui_mapping/extensions.py +37 -0
- meridian/lib/app/agui_mapping/opencode.py +247 -0
- meridian/lib/app/agui_types.py +80 -0
- meridian/lib/app/server.py +271 -0
- meridian/lib/app/ws_endpoint.py +243 -0
- meridian/lib/catalog/__init__.py +1 -0
- meridian/lib/catalog/agent.py +227 -0
- meridian/lib/catalog/model_aliases.py +368 -0
- meridian/lib/catalog/model_policy.py +196 -0
- meridian/lib/catalog/models.py +556 -0
- meridian/lib/catalog/skill.py +233 -0
- meridian/lib/config/__init__.py +3 -0
- meridian/lib/config/settings.py +863 -0
- meridian/lib/core/__init__.py +1 -0
- meridian/lib/core/codec.py +91 -0
- meridian/lib/core/context.py +86 -0
- meridian/lib/core/conversation.py +36 -0
- meridian/lib/core/domain.py +128 -0
- meridian/lib/core/logging.py +41 -0
- meridian/lib/core/overrides.py +240 -0
- meridian/lib/core/sink.py +90 -0
- meridian/lib/core/spawn_lifecycle.py +60 -0
- meridian/lib/core/types.py +19 -0
- meridian/lib/core/util.py +42 -0
- meridian/lib/harness/__init__.py +0 -0
- meridian/lib/harness/adapter.py +274 -0
- meridian/lib/harness/claude.py +424 -0
- meridian/lib/harness/codex.py +512 -0
- meridian/lib/harness/common.py +610 -0
- meridian/lib/harness/connections/__init__.py +37 -0
- meridian/lib/harness/connections/base.py +117 -0
- meridian/lib/harness/connections/claude_ws.py +403 -0
- meridian/lib/harness/connections/codex_ws.py +535 -0
- meridian/lib/harness/connections/opencode_http.py +621 -0
- meridian/lib/harness/direct.py +226 -0
- meridian/lib/harness/launch_types.py +26 -0
- meridian/lib/harness/opencode.py +271 -0
- meridian/lib/harness/registry.py +86 -0
- meridian/lib/harness/session_detection.py +29 -0
- meridian/lib/harness/transcript.py +48 -0
- meridian/lib/launch/__init__.py +105 -0
- meridian/lib/launch/artifact_io.py +11 -0
- meridian/lib/launch/command.py +77 -0
- meridian/lib/launch/cwd.py +26 -0
- meridian/lib/launch/default_agent_policy.py +103 -0
- meridian/lib/launch/env.py +143 -0
- meridian/lib/launch/errors.py +110 -0
- meridian/lib/launch/extract.py +123 -0
- meridian/lib/launch/heartbeat.py +59 -0
- meridian/lib/launch/plan.py +378 -0
- meridian/lib/launch/process.py +482 -0
- meridian/lib/launch/prompt.py +310 -0
- meridian/lib/launch/reference.py +175 -0
- meridian/lib/launch/report.py +142 -0
- meridian/lib/launch/resolve.py +336 -0
- meridian/lib/launch/runner.py +1100 -0
- meridian/lib/launch/session_ids.py +53 -0
- meridian/lib/launch/session_scope.py +69 -0
- meridian/lib/launch/signals.py +237 -0
- meridian/lib/launch/stream_capture.py +144 -0
- meridian/lib/launch/terminal.py +150 -0
- meridian/lib/launch/timeout.py +85 -0
- meridian/lib/launch/types.py +142 -0
- meridian/lib/launch/written_files.py +137 -0
- meridian/lib/ops/__init__.py +0 -0
- meridian/lib/ops/catalog.py +348 -0
- meridian/lib/ops/config.py +888 -0
- meridian/lib/ops/diag.py +239 -0
- meridian/lib/ops/manifest.py +702 -0
- meridian/lib/ops/mars.py +180 -0
- meridian/lib/ops/reference.py +205 -0
- meridian/lib/ops/report.py +227 -0
- meridian/lib/ops/runtime.py +126 -0
- meridian/lib/ops/session_log.py +605 -0
- meridian/lib/ops/session_search.py +188 -0
- meridian/lib/ops/spawn/__init__.py +61 -0
- meridian/lib/ops/spawn/api.py +777 -0
- meridian/lib/ops/spawn/context_ref.py +140 -0
- meridian/lib/ops/spawn/execute.py +887 -0
- meridian/lib/ops/spawn/log.py +281 -0
- meridian/lib/ops/spawn/models.py +526 -0
- meridian/lib/ops/spawn/plan.py +67 -0
- meridian/lib/ops/spawn/prepare.py +400 -0
- meridian/lib/ops/spawn/query.py +250 -0
- meridian/lib/ops/work_attachment.py +33 -0
- meridian/lib/ops/work_dashboard.py +543 -0
- meridian/lib/ops/work_lifecycle.py +458 -0
- meridian/lib/safety/__init__.py +0 -0
- meridian/lib/safety/budget.py +121 -0
- meridian/lib/safety/guardrails.py +127 -0
- meridian/lib/safety/permissions.py +303 -0
- meridian/lib/safety/redaction.py +65 -0
- meridian/lib/state/__init__.py +57 -0
- meridian/lib/state/artifact_store.py +109 -0
- meridian/lib/state/atomic.py +73 -0
- meridian/lib/state/event_store.py +105 -0
- meridian/lib/state/paths.py +228 -0
- meridian/lib/state/reaper.py +492 -0
- meridian/lib/state/reaper_config.py +16 -0
- meridian/lib/state/session_store.py +671 -0
- meridian/lib/state/spawn_store.py +605 -0
- meridian/lib/state/work_store.py +420 -0
- meridian/lib/streaming/__init__.py +13 -0
- meridian/lib/streaming/control_socket.py +107 -0
- meridian/lib/streaming/spawn_manager.py +420 -0
- meridian/lib/streaming/types.py +45 -0
- meridian/lib/utils/__init__.py +1 -0
- meridian/lib/utils/time.py +11 -0
- meridian/py.typed +0 -0
- meridian/server/__init__.py +10 -0
- meridian/server/main.py +79 -0
- meridian_cli-0.0.25.dist-info/METADATA +367 -0
- meridian_cli-0.0.25.dist-info/RECORD +143 -0
- meridian_cli-0.0.25.dist-info/WHEEL +4 -0
- meridian_cli-0.0.25.dist-info/entry_points.txt +4 -0
- meridian_cli-0.0.25.dist-info/licenses/LICENSE +201 -0
meridian/__init__.py
ADDED
meridian/__main__.py
ADDED
meridian/cli/__init__.py
ADDED
meridian/cli/app_cmd.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""CLI command for the meridian app web UI server."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import importlib
|
|
6
|
+
import threading
|
|
7
|
+
import time
|
|
8
|
+
import webbrowser
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def run_app(
|
|
12
|
+
port: int = 8420,
|
|
13
|
+
no_browser: bool = False,
|
|
14
|
+
host: str = "127.0.0.1",
|
|
15
|
+
) -> None:
|
|
16
|
+
"""Start the Meridian app server."""
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
importlib.import_module("fastapi")
|
|
20
|
+
uvicorn_module = importlib.import_module("uvicorn")
|
|
21
|
+
except ModuleNotFoundError:
|
|
22
|
+
print("Missing app dependencies. Install with: uv sync --extra app")
|
|
23
|
+
raise SystemExit(1) from None
|
|
24
|
+
|
|
25
|
+
from meridian.lib.app.server import create_app
|
|
26
|
+
from meridian.lib.ops.runtime import resolve_runtime_root_and_config, resolve_state_root
|
|
27
|
+
from meridian.lib.streaming.spawn_manager import SpawnManager
|
|
28
|
+
|
|
29
|
+
repo_root, _ = resolve_runtime_root_and_config(None)
|
|
30
|
+
state_root = resolve_state_root(repo_root)
|
|
31
|
+
|
|
32
|
+
manager = SpawnManager(state_root=state_root, repo_root=repo_root)
|
|
33
|
+
app = create_app(manager)
|
|
34
|
+
|
|
35
|
+
if not no_browser:
|
|
36
|
+
url = f"http://{host}:{port}"
|
|
37
|
+
|
|
38
|
+
def _open_browser() -> None:
|
|
39
|
+
time.sleep(1.5)
|
|
40
|
+
webbrowser.open(url)
|
|
41
|
+
|
|
42
|
+
threading.Thread(target=_open_browser, daemon=True).start()
|
|
43
|
+
|
|
44
|
+
print(f"Starting meridian app at http://{host}:{port}")
|
|
45
|
+
uvicorn_module.run(app, host=host, port=port, log_level="info")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
__all__ = ["run_app"]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""CLI command handlers for config.* operations."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
from functools import partial
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from cyclopts import App
|
|
8
|
+
|
|
9
|
+
from meridian.cli.registration import register_manifest_cli_group
|
|
10
|
+
from meridian.lib.ops.config import (
|
|
11
|
+
ConfigGetInput,
|
|
12
|
+
ConfigResetInput,
|
|
13
|
+
ConfigSetInput,
|
|
14
|
+
config_get_sync,
|
|
15
|
+
config_reset_sync,
|
|
16
|
+
config_set_sync,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
Emitter = Callable[[Any], None]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _config_set(emit: Emitter, key: str, value: str) -> None:
|
|
23
|
+
emit(config_set_sync(ConfigSetInput(key=key, value=value)))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _config_get(emit: Emitter, key: str) -> None:
|
|
27
|
+
emit(config_get_sync(ConfigGetInput(key=key)))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _config_reset(emit: Emitter, key: str) -> None:
|
|
31
|
+
emit(config_reset_sync(ConfigResetInput(key=key)))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def register_config_commands(app: App, emit: Emitter) -> tuple[set[str], dict[str, str]]:
|
|
35
|
+
handlers: dict[str, Callable[[], Callable[..., None]]] = {
|
|
36
|
+
# config.init and config.show are auto-generated (no required CLI args).
|
|
37
|
+
"config.set": lambda: partial(_config_set, emit),
|
|
38
|
+
"config.get": lambda: partial(_config_get, emit),
|
|
39
|
+
"config.reset": lambda: partial(_config_reset, emit),
|
|
40
|
+
}
|
|
41
|
+
return register_manifest_cli_group(app, group="config", handlers=handlers, emit=emit)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""CLI command handler for standalone doctor operation."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from cyclopts import App
|
|
7
|
+
|
|
8
|
+
from meridian.cli.registration import register_manifest_cli_group
|
|
9
|
+
|
|
10
|
+
Emitter = Callable[[Any], None]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def register_doctor_command(app: App, emit: Emitter) -> tuple[set[str], dict[str, str]]:
|
|
14
|
+
# doctor has no required CLI args — handler is auto-generated.
|
|
15
|
+
return register_manifest_cli_group(
|
|
16
|
+
app,
|
|
17
|
+
group="doctor",
|
|
18
|
+
command_help_epilogues={
|
|
19
|
+
"doctor": (
|
|
20
|
+
"Health check and auto-repair for meridian state.\n\n"
|
|
21
|
+
"Reconciles orphaned spawns (dead PIDs, stale heartbeats, missing\n"
|
|
22
|
+
"spawn directories), cleans stale session locks, and warns about\n"
|
|
23
|
+
"missing or malformed configuration.\n\n"
|
|
24
|
+
"Doctor is idempotent - re-running converges on the same result.\n"
|
|
25
|
+
"It is safe (and intended) to run after a crash, after a force-kill,\n"
|
|
26
|
+
"or any time `meridian spawn show` reports a status that doesn't match\n"
|
|
27
|
+
"reality.\n\n"
|
|
28
|
+
"Examples:\n\n"
|
|
29
|
+
" meridian doctor # check and repair, JSON output\n\n"
|
|
30
|
+
" meridian doctor --format text # human-readable summary\n"
|
|
31
|
+
)
|
|
32
|
+
},
|
|
33
|
+
emit=emit,
|
|
34
|
+
)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Shared text formatting primitives for CLI output.
|
|
2
|
+
|
|
3
|
+
Centralizes column alignment and key-value rendering so that all
|
|
4
|
+
format_text() implementations produce consistent output.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def tabular(rows: list[list[str]], sep: str = " ") -> str:
|
|
9
|
+
"""Align columns by max width per column.
|
|
10
|
+
|
|
11
|
+
>>> tabular([["r1", "done", "5.0s"], ["r20", "failed", "21.6s"]])
|
|
12
|
+
'r1 done 5.0s\\nr20 failed 21.6s'
|
|
13
|
+
"""
|
|
14
|
+
if not rows:
|
|
15
|
+
return ""
|
|
16
|
+
col_count = max(len(row) for row in rows)
|
|
17
|
+
col_widths = [
|
|
18
|
+
max((len(row[col]) if col < len(row) else 0) for row in rows) for col in range(col_count)
|
|
19
|
+
]
|
|
20
|
+
lines: list[str] = []
|
|
21
|
+
for row in rows:
|
|
22
|
+
cells = [
|
|
23
|
+
(row[col] if col < len(row) else "").ljust(col_widths[col]) for col in range(col_count)
|
|
24
|
+
]
|
|
25
|
+
lines.append(sep.join(cells).rstrip())
|
|
26
|
+
return "\n".join(lines)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def kv_block(pairs: list[tuple[str, str | None]]) -> str:
|
|
30
|
+
"""Render key: value pairs, skipping None values.
|
|
31
|
+
|
|
32
|
+
>>> kv_block([("Spawn", "r1"), ("Status", "done"), ("Cost", None)])
|
|
33
|
+
'Spawn: r1\\nStatus: done'
|
|
34
|
+
"""
|
|
35
|
+
return "\n".join(f"{k}: {v}" for k, v in pairs if v is not None)
|