comate-cli 0.1.11__tar.gz → 0.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.
- {comate_cli-0.1.11 → comate_cli-0.2.1}/PKG-INFO +1 -1
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/mcp_cli.py +30 -23
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/animations.py +21 -20
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/app.py +13 -8
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/custom_slash_commands.py +13 -7
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/event_renderer.py +149 -133
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/logging_adapter.py +94 -15
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/logo.py +7 -2
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/question_view.py +22 -14
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/rpc_protocol.py +12 -5
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/rpc_stdio.py +105 -10
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/status_bar.py +1 -2
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/tool_view.py +36 -4
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/tui.py +155 -105
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/tui_parts/history_sync.py +2 -2
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/tui_parts/key_bindings.py +51 -18
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/tui_parts/render_panels.py +53 -3
- {comate_cli-0.1.11 → comate_cli-0.2.1}/pyproject.toml +1 -1
- comate_cli-0.2.1/tests/test_app_mcp_preload.py +48 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_completion_status_panel.py +88 -4
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_custom_slash_commands.py +39 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_event_renderer.py +108 -52
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_history_sync.py +5 -5
- comate_cli-0.2.1/tests/test_interrupt_exit_semantics.py +300 -0
- comate_cli-0.2.1/tests/test_logging_adapter.py +68 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_logo.py +14 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_mcp_cli.py +58 -0
- comate_cli-0.2.1/tests/test_question_key_bindings.py +181 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_question_view.py +117 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_rpc_protocol.py +7 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_rpc_stdio_bridge.py +83 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_status_bar.py +22 -0
- comate_cli-0.2.1/tests/test_task_panel_key_bindings.py +195 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_tool_view.py +1 -1
- comate_cli-0.2.1/uv.lock +2243 -0
- comate_cli-0.1.11/uv.lock +0 -2259
- {comate_cli-0.1.11 → comate_cli-0.2.1}/.gitignore +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/README.md +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/__init__.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/__main__.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/main.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/__init__.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/assistant_render.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/env_utils.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/error_display.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/fragment_utils.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/history_printer.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/input_geometry.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/layout_coordinator.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/markdown_render.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/mention_completer.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/message_style.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/models.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/preflight.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/resume_selector.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/rewind_store.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/selection_menu.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/session_view.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/slash_commands.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/startup.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/text_effects.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/tips.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/tui_parts/__init__.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/tui_parts/commands.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/tui_parts/input_behavior.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/tui_parts/slash_command_registry.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/comate_cli/terminal_agent/tui_parts/ui_mode.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/test_memory.md +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/conftest.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_app_preflight_gate.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_app_shutdown.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_app_usage_line.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_cli_project_root.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_compact_command_semantics.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_completion_context_activation.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_context_command.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_input_behavior.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_layout_coordinator.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_main_args.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_mcp_slash_command.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_mention_completer.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_preflight.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_preflight_copilot.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_resume_selector.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_rewind_command_semantics.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_rewind_store.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_selection_menu.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_skills_slash_command.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_slash_argument_hint.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_slash_completer.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_slash_registry.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_tui_elapsed_status.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_tui_mcp_init_gate.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_tui_paste_placeholder.py +0 -0
- {comate_cli-0.1.11 → comate_cli-0.2.1}/tests/test_tui_split_invariance.py +0 -0
|
@@ -3,7 +3,6 @@ from __future__ import annotations
|
|
|
3
3
|
import argparse
|
|
4
4
|
import asyncio
|
|
5
5
|
import sys
|
|
6
|
-
from pathlib import Path
|
|
7
6
|
from typing import Any
|
|
8
7
|
|
|
9
8
|
from comate_agent_sdk.mcp import (
|
|
@@ -15,6 +14,7 @@ from comate_agent_sdk.mcp import (
|
|
|
15
14
|
write_mcp_servers_to_path,
|
|
16
15
|
)
|
|
17
16
|
from comate_agent_sdk.mcp.types import McpServerConfig
|
|
17
|
+
from comate_agent_sdk.utils.paths import PathInput
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class McpCliError(ValueError):
|
|
@@ -23,8 +23,13 @@ class McpCliError(ValueError):
|
|
|
23
23
|
self.exit_code = int(exit_code)
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
class _McpArgumentParser(argparse.ArgumentParser):
|
|
27
|
+
def error(self, message: str) -> None:
|
|
28
|
+
raise McpCliError(message)
|
|
29
|
+
|
|
30
|
+
|
|
26
31
|
def _build_parser() -> argparse.ArgumentParser:
|
|
27
|
-
parser =
|
|
32
|
+
parser = _McpArgumentParser(
|
|
28
33
|
prog="comate mcp",
|
|
29
34
|
description="Configure and manage MCP servers",
|
|
30
35
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
@@ -143,11 +148,11 @@ def _parse_env_entries(entries: list[str]) -> dict[str, str]:
|
|
|
143
148
|
return env
|
|
144
149
|
|
|
145
150
|
|
|
146
|
-
def
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return
|
|
151
|
+
def _split_trailing_command_args(argv: list[str]) -> tuple[list[str], list[str]]:
|
|
152
|
+
if "--" not in argv:
|
|
153
|
+
return list(argv), []
|
|
154
|
+
separator_index = argv.index("--")
|
|
155
|
+
return list(argv[:separator_index]), list(argv[separator_index + 1 :])
|
|
151
156
|
|
|
152
157
|
|
|
153
158
|
def _build_add_server_config(args: argparse.Namespace) -> McpServerConfig:
|
|
@@ -155,9 +160,7 @@ def _build_add_server_config(args: argparse.Namespace) -> McpServerConfig:
|
|
|
155
160
|
header_entries = [str(item) for item in list(args.header or [])]
|
|
156
161
|
env_entries = [str(item) for item in list(args.env or [])]
|
|
157
162
|
command_or_url = str(args.command_or_url or "").strip()
|
|
158
|
-
remainder =
|
|
159
|
-
[str(item) for item in list(getattr(args, "extra_args", []) or [])]
|
|
160
|
-
)
|
|
163
|
+
remainder = [str(item) for item in list(getattr(args, "extra_args", []) or [])]
|
|
161
164
|
|
|
162
165
|
if transport == "http":
|
|
163
166
|
if env_entries:
|
|
@@ -177,6 +180,9 @@ def _build_add_server_config(args: argparse.Namespace) -> McpServerConfig:
|
|
|
177
180
|
|
|
178
181
|
if header_entries:
|
|
179
182
|
raise McpCliError("--header is only supported for http transport")
|
|
183
|
+
stdio_args = list(remainder)
|
|
184
|
+
if not command_or_url and stdio_args:
|
|
185
|
+
command_or_url = stdio_args.pop(0)
|
|
180
186
|
if not command_or_url:
|
|
181
187
|
raise McpCliError("stdio transport requires command after <name>")
|
|
182
188
|
|
|
@@ -184,14 +190,14 @@ def _build_add_server_config(args: argparse.Namespace) -> McpServerConfig:
|
|
|
184
190
|
cfg = {
|
|
185
191
|
"command": command_or_url,
|
|
186
192
|
}
|
|
187
|
-
if
|
|
188
|
-
cfg["args"] =
|
|
193
|
+
if stdio_args:
|
|
194
|
+
cfg["args"] = stdio_args
|
|
189
195
|
if env:
|
|
190
196
|
cfg["env"] = env
|
|
191
197
|
return cfg # type: ignore[return-value]
|
|
192
198
|
|
|
193
199
|
|
|
194
|
-
def _load_servers_by_scope(*, scope: str, project_root:
|
|
200
|
+
def _load_servers_by_scope(*, scope: str, project_root: PathInput | None) -> dict[str, McpServerConfig]:
|
|
195
201
|
if scope == "effective":
|
|
196
202
|
return load_effective_servers(project_root=project_root)
|
|
197
203
|
return load_scope_servers(scope=scope, project_root=project_root) # type: ignore[arg-type]
|
|
@@ -200,7 +206,7 @@ def _load_servers_by_scope(*, scope: str, project_root: Path | None) -> dict[str
|
|
|
200
206
|
def _read_effective_server_with_source(
|
|
201
207
|
*,
|
|
202
208
|
name: str,
|
|
203
|
-
project_root:
|
|
209
|
+
project_root: PathInput | None,
|
|
204
210
|
) -> tuple[McpServerConfig, str] | None:
|
|
205
211
|
user_servers = load_scope_servers(scope="user", project_root=project_root)
|
|
206
212
|
project_servers = load_scope_servers(scope="project", project_root=project_root)
|
|
@@ -230,7 +236,7 @@ def _format_server_endpoint(cfg: McpServerConfig) -> str:
|
|
|
230
236
|
return " ".join([command, *str_args]).strip()
|
|
231
237
|
|
|
232
238
|
|
|
233
|
-
def _cmd_add(args: argparse.Namespace, *, project_root:
|
|
239
|
+
def _cmd_add(args: argparse.Namespace, *, project_root: PathInput | None) -> None:
|
|
234
240
|
scope = str(args.scope)
|
|
235
241
|
name = str(args.name).strip()
|
|
236
242
|
if not name:
|
|
@@ -250,7 +256,7 @@ def _cmd_add(args: argparse.Namespace, *, project_root: Path | None) -> None:
|
|
|
250
256
|
)
|
|
251
257
|
|
|
252
258
|
|
|
253
|
-
def _cmd_remove(args: argparse.Namespace, *, project_root:
|
|
259
|
+
def _cmd_remove(args: argparse.Namespace, *, project_root: PathInput | None) -> None:
|
|
254
260
|
scope = str(args.scope)
|
|
255
261
|
name = str(args.name).strip()
|
|
256
262
|
if not name:
|
|
@@ -271,7 +277,7 @@ def _cmd_remove(args: argparse.Namespace, *, project_root: Path | None) -> None:
|
|
|
271
277
|
)
|
|
272
278
|
|
|
273
279
|
|
|
274
|
-
def _cmd_list(args: argparse.Namespace, *, project_root:
|
|
280
|
+
def _cmd_list(args: argparse.Namespace, *, project_root: PathInput | None) -> None:
|
|
275
281
|
scope = str(args.scope)
|
|
276
282
|
servers = _load_servers_by_scope(scope=scope, project_root=project_root)
|
|
277
283
|
if not servers:
|
|
@@ -295,7 +301,7 @@ def _cmd_list(args: argparse.Namespace, *, project_root: Path | None) -> None:
|
|
|
295
301
|
sys.stdout.write(f"{alias}: {endpoint} ({server_type}) - {status}\n")
|
|
296
302
|
|
|
297
303
|
|
|
298
|
-
def _cmd_get(args: argparse.Namespace, *, project_root:
|
|
304
|
+
def _cmd_get(args: argparse.Namespace, *, project_root: PathInput | None) -> None:
|
|
299
305
|
name = str(args.name).strip()
|
|
300
306
|
scope = str(args.scope)
|
|
301
307
|
if not name:
|
|
@@ -363,18 +369,19 @@ def _cmd_get(args: argparse.Namespace, *, project_root: Path | None) -> None:
|
|
|
363
369
|
sys.stdout.write("\n".join(lines) + "\n")
|
|
364
370
|
|
|
365
371
|
|
|
366
|
-
def run_mcp_command(argv: list[str], *, project_root:
|
|
372
|
+
def run_mcp_command(argv: list[str], *, project_root: PathInput | None = None) -> None:
|
|
367
373
|
parser = _build_parser()
|
|
368
|
-
|
|
374
|
+
parser_argv, trailing_args = _split_trailing_command_args(argv)
|
|
375
|
+
parsed = parser.parse_args(parser_argv)
|
|
369
376
|
command = str(getattr(parsed, "command", "") or "").strip()
|
|
370
377
|
if not command:
|
|
371
378
|
parser.print_help(sys.stdout)
|
|
372
379
|
return
|
|
373
|
-
if command != "add" and
|
|
374
|
-
joined = " ".join(
|
|
380
|
+
if command != "add" and trailing_args:
|
|
381
|
+
joined = " ".join(["--", *trailing_args])
|
|
375
382
|
raise McpCliError(f"Unrecognized arguments: {joined}")
|
|
376
383
|
if command == "add":
|
|
377
|
-
setattr(parsed, "extra_args", list(
|
|
384
|
+
setattr(parsed, "extra_args", list(trailing_args))
|
|
378
385
|
|
|
379
386
|
handlers = {
|
|
380
387
|
"add": _cmd_add,
|
|
@@ -11,26 +11,27 @@ from rich.text import Text
|
|
|
11
11
|
from comate_agent_sdk.agent.events import StopEvent, TextEvent, ToolCallEvent, ToolResultEvent, UserQuestionEvent
|
|
12
12
|
|
|
13
13
|
DEFAULT_STATUS_PHRASES: tuple[str, ...] = (
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
14
|
+
"Embellishing…",
|
|
15
|
+
"Vibing…",
|
|
16
|
+
"Thinking…",
|
|
17
|
+
"Reasoning…",
|
|
18
|
+
"Planning next move…",
|
|
19
|
+
"Reading context…",
|
|
20
|
+
"Connecting dots…",
|
|
21
|
+
"Synthesizing signal…",
|
|
22
|
+
"Spotting edge cases…",
|
|
23
|
+
"Checking assumptions…",
|
|
24
|
+
"Tracing dependencies…",
|
|
25
|
+
"Drafting response…",
|
|
26
|
+
"Polishing details…",
|
|
27
|
+
"Validating flow…",
|
|
28
|
+
"Cross-checking facts…",
|
|
29
|
+
"Refining intent…",
|
|
30
|
+
"Mapping tools…",
|
|
31
|
+
"Building confidence…",
|
|
32
|
+
"Stitching answer…",
|
|
33
|
+
"Finalizing output…",
|
|
34
|
+
"Almost there…",
|
|
34
35
|
)
|
|
35
36
|
|
|
36
37
|
BREATH_DOT_COLORS: tuple[str, ...] = (
|
|
@@ -69,8 +69,8 @@ async def _check_update() -> str | None:
|
|
|
69
69
|
return None
|
|
70
70
|
|
|
71
71
|
if _is_chinese_locale():
|
|
72
|
-
url = f"https://mirrors.
|
|
73
|
-
source_label = "
|
|
72
|
+
url = f"https://mirrors.tuna.tsinghua.edu.cn/pypi/{package}/json"
|
|
73
|
+
source_label = "tuna"
|
|
74
74
|
else:
|
|
75
75
|
url = f"https://pypi.org/pypi/{package}/json"
|
|
76
76
|
source_label = "pypi"
|
|
@@ -90,9 +90,9 @@ async def _check_update() -> str | None:
|
|
|
90
90
|
from packaging.version import Version
|
|
91
91
|
if Version(latest) > Version(current):
|
|
92
92
|
return (
|
|
93
|
-
f"[dim]
|
|
93
|
+
f"[dim] New version available: [bold cyan]{latest}[/] "
|
|
94
94
|
f"(current: {current}) "
|
|
95
|
-
f"Run [bold]uv tool upgrade {package}[/] to upgrade.[/]"
|
|
95
|
+
f"Run [bold green]uv tool upgrade {package}[/] to upgrade.[/]"
|
|
96
96
|
)
|
|
97
97
|
except Exception:
|
|
98
98
|
pass
|
|
@@ -230,16 +230,20 @@ def _format_resume_hint(session_id: str | None) -> str | None:
|
|
|
230
230
|
|
|
231
231
|
async def _preload_mcp_in_tui(session: ChatSession) -> None:
|
|
232
232
|
"""在 TUI 内异步加载 MCP,初始化阶段不输出 scrollback 文案。"""
|
|
233
|
-
|
|
233
|
+
runtime = session.runtime
|
|
234
|
+
if not bool(runtime.options.mcp_enabled):
|
|
234
235
|
return
|
|
235
236
|
|
|
236
237
|
try:
|
|
237
|
-
|
|
238
|
+
preload_task = runtime.start_mcp_preload()
|
|
239
|
+
if preload_task is None:
|
|
240
|
+
return
|
|
241
|
+
await preload_task
|
|
238
242
|
except Exception as e:
|
|
239
243
|
logger.warning(f"MCP init failed: {e}", exc_info=True)
|
|
240
244
|
return
|
|
241
245
|
|
|
242
|
-
mgr =
|
|
246
|
+
mgr = runtime._mcp_manager
|
|
243
247
|
if mgr is None:
|
|
244
248
|
return
|
|
245
249
|
|
|
@@ -311,7 +315,7 @@ async def run(
|
|
|
311
315
|
|
|
312
316
|
# 配置 TUI logging handler(将 SDK 日志输出到 TUI)
|
|
313
317
|
from comate_cli.terminal_agent.logging_adapter import setup_tui_logging
|
|
314
|
-
setup_tui_logging(renderer)
|
|
318
|
+
logging_session = setup_tui_logging(renderer)
|
|
315
319
|
|
|
316
320
|
tui = TerminalAgentTUI(session, status_bar, renderer)
|
|
317
321
|
tui.add_resume_history(mode)
|
|
@@ -333,6 +337,7 @@ async def run(
|
|
|
333
337
|
exc_info=True,
|
|
334
338
|
)
|
|
335
339
|
finally:
|
|
340
|
+
logging_session.close()
|
|
336
341
|
if active_session is session:
|
|
337
342
|
await _graceful_shutdown(active_session)
|
|
338
343
|
else:
|
|
@@ -10,6 +10,8 @@ from typing import Literal
|
|
|
10
10
|
|
|
11
11
|
import yaml
|
|
12
12
|
|
|
13
|
+
from comate_agent_sdk.utils.paths import PathInput, normalize_path_input
|
|
14
|
+
|
|
13
15
|
logger = logging.getLogger(__name__)
|
|
14
16
|
|
|
15
17
|
DEFAULT_ITEM_MAX_BYTES = 32 * 1024
|
|
@@ -55,12 +57,15 @@ class CustomSlashLoadResult:
|
|
|
55
57
|
|
|
56
58
|
def discover_custom_slash_commands(
|
|
57
59
|
*,
|
|
58
|
-
project_root:
|
|
60
|
+
project_root: PathInput,
|
|
59
61
|
builtin_names: set[str],
|
|
60
|
-
user_root:
|
|
62
|
+
user_root: PathInput | None = None,
|
|
61
63
|
) -> CustomSlashLoadResult:
|
|
62
|
-
resolved_project_root = project_root
|
|
63
|
-
resolved_user_root = (
|
|
64
|
+
resolved_project_root = normalize_path_input(project_root, field_name="project_root")
|
|
65
|
+
resolved_user_root = normalize_path_input(
|
|
66
|
+
user_root if user_root is not None else Path.home(),
|
|
67
|
+
field_name="user_root",
|
|
68
|
+
)
|
|
64
69
|
|
|
65
70
|
project_dir = resolved_project_root / ".agent" / "commands"
|
|
66
71
|
user_dir = resolved_user_root / ".agent" / "commands"
|
|
@@ -188,11 +193,12 @@ async def render_custom_slash_prompt(
|
|
|
188
193
|
*,
|
|
189
194
|
command: CustomSlashCommand,
|
|
190
195
|
raw_args: str,
|
|
191
|
-
project_root:
|
|
196
|
+
project_root: PathInput,
|
|
192
197
|
item_max_bytes: int = DEFAULT_ITEM_MAX_BYTES,
|
|
193
198
|
total_max_bytes: int = DEFAULT_TOTAL_MAX_BYTES,
|
|
194
199
|
bash_timeout_seconds: float = DEFAULT_BASH_TIMEOUT_SECONDS,
|
|
195
200
|
) -> str:
|
|
201
|
+
resolved_project_root = normalize_path_input(project_root, field_name="project_root")
|
|
196
202
|
normalized_args = raw_args.strip()
|
|
197
203
|
try:
|
|
198
204
|
arg_tokens = shlex.split(normalized_args) if normalized_args else []
|
|
@@ -213,7 +219,7 @@ async def render_custom_slash_prompt(
|
|
|
213
219
|
after_bash = await _replace_bash_markers(
|
|
214
220
|
text=replaced_text,
|
|
215
221
|
marker_map=marker_map,
|
|
216
|
-
project_root=
|
|
222
|
+
project_root=resolved_project_root,
|
|
217
223
|
item_max_bytes=item_max_bytes,
|
|
218
224
|
total_max_bytes=total_max_bytes,
|
|
219
225
|
total_inserted_bytes=total_inserted_bytes,
|
|
@@ -224,7 +230,7 @@ async def render_custom_slash_prompt(
|
|
|
224
230
|
after_file_ref = _replace_file_reference_markers(
|
|
225
231
|
text=after_bash,
|
|
226
232
|
marker_map=marker_map,
|
|
227
|
-
project_root=
|
|
233
|
+
project_root=resolved_project_root,
|
|
228
234
|
item_max_bytes=item_max_bytes,
|
|
229
235
|
total_max_bytes=total_max_bytes,
|
|
230
236
|
total_inserted_bytes=total_inserted_bytes,
|