统一command入口
This commit is contained in:
parent
e9cf2e3533
commit
f9ea8b1d6b
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
REPL 内的会话管理命令优先使用 slash command。
|
REPL 内的会话管理命令优先使用 slash command。
|
||||||
|
|
||||||
`/history`、`/resume`、`/new` 由程序直接处理,不进入 agent loop。
|
REPL 内所有 slash command 由程序直接处理,不进入 agent loop。
|
||||||
|
|
||||||
当前项目支持最小 memory:使用 `/remember` 保存长期信息,使用 `/memory` 查看。
|
当前项目支持最小 memory:使用 `/remember` 保存长期信息,使用 `/memory` 查看。
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@
|
|||||||
- 搜索文件内容时,优先使用 `Grep`,而不是 `Bash`
|
- 搜索文件内容时,优先使用 `Grep`,而不是 `Bash`
|
||||||
- 修改已有文件时,优先使用 `Edit`,而不是 `Bash` 或 `Write`
|
- 修改已有文件时,优先使用 `Edit`,而不是 `Bash` 或 `Write`
|
||||||
- 需要创建或覆盖文件时,优先使用 `Write` 工具,而不是 `Bash`
|
- 需要创建或覆盖文件时,优先使用 `Write` 工具,而不是 `Bash`
|
||||||
- 会话管理优先使用 slash command,而不是自然语言或 `Bash` 探查 session 文件
|
- 会话与 memory 管理优先使用 slash command,而不是自然语言或 `Bash` 探查对应文件
|
||||||
- 长期有价值的项目约束或偏好,优先使用 `/remember` 保存
|
- 长期有价值的项目约束或偏好,优先使用 `/remember` 保存
|
||||||
- Windows 下先验证 shell 兼容性,再选择命令写法
|
- Windows 下先验证 shell 兼容性,再选择命令写法
|
||||||
|
|
||||||
|
|||||||
83
src/cc_slim/commands.py
Normal file
83
src/cc_slim/commands.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from rich.console import Console
|
||||||
|
|
||||||
|
from cc_slim.engine import Agent
|
||||||
|
from cc_slim.memory import MemoryStore
|
||||||
|
from cc_slim.session import SessionStore
|
||||||
|
|
||||||
|
|
||||||
|
def parse_command(text: str) -> dict[str, str] | None:
|
||||||
|
command = text.strip()
|
||||||
|
if not command.startswith("/"):
|
||||||
|
return None
|
||||||
|
name, _, args = command.partition(" ")
|
||||||
|
return {"name": name, "args": args.strip()}
|
||||||
|
|
||||||
|
|
||||||
|
def handle_command(
|
||||||
|
text: str,
|
||||||
|
*,
|
||||||
|
console: Console,
|
||||||
|
root: Path,
|
||||||
|
config: Any,
|
||||||
|
store: SessionStore,
|
||||||
|
memory: MemoryStore,
|
||||||
|
agent: Agent,
|
||||||
|
build_agent: Any,
|
||||||
|
render_history: Any,
|
||||||
|
) -> Agent:
|
||||||
|
parsed = parse_command(text)
|
||||||
|
if not parsed:
|
||||||
|
return agent
|
||||||
|
|
||||||
|
name = parsed["name"]
|
||||||
|
args = parsed["args"]
|
||||||
|
|
||||||
|
if name == "/help":
|
||||||
|
console.print("/help - 显示命令帮助")
|
||||||
|
console.print("/clear - 清空当前上下文并创建新 session")
|
||||||
|
console.print("/history - 查看历史 session")
|
||||||
|
console.print("/resume <id-or-index> - 恢复指定 session")
|
||||||
|
console.print("/new - 创建全新 session")
|
||||||
|
console.print("/remember <text> - 保存长期 memory")
|
||||||
|
console.print("/memory - 查看当前项目 memory")
|
||||||
|
return agent
|
||||||
|
|
||||||
|
if name in {"/clear", "/new"}:
|
||||||
|
session_meta = store.create_session(config.model)
|
||||||
|
console.print(f"已创建新 session: {session_meta.get('session_id')}")
|
||||||
|
return build_agent(root, config, store, session_meta, [])
|
||||||
|
|
||||||
|
if name == "/history":
|
||||||
|
render_history(store)
|
||||||
|
return agent
|
||||||
|
|
||||||
|
if name == "/resume":
|
||||||
|
if not args:
|
||||||
|
console.print("[red]error:[/red] 缺少 resume 目标")
|
||||||
|
return agent
|
||||||
|
session_id = store.resolve_session_id(args)
|
||||||
|
session_meta = store.load_meta(session_id)
|
||||||
|
restored_history = store.load_messages(session_id)
|
||||||
|
console.print(f"已恢复 session: {session_meta.get('session_id')}")
|
||||||
|
return build_agent(root, config, store, session_meta, restored_history)
|
||||||
|
|
||||||
|
if name == "/memory":
|
||||||
|
content = memory.read()
|
||||||
|
console.print(content or "当前项目还没有 memory。")
|
||||||
|
return agent
|
||||||
|
|
||||||
|
if name == "/remember":
|
||||||
|
if not args:
|
||||||
|
console.print("[red]error:[/red] 缺少需要保存的 memory 内容")
|
||||||
|
return agent
|
||||||
|
path = memory.append(args)
|
||||||
|
console.print(f"已写入 memory: {path}")
|
||||||
|
return agent
|
||||||
|
|
||||||
|
console.print(f"[red]error:[/red] 不支持的命令: {name},输入 /help 查看帮助")
|
||||||
|
return agent
|
||||||
@ -7,6 +7,7 @@ import typer
|
|||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
from rich.table import Table
|
from rich.table import Table
|
||||||
|
|
||||||
|
from cc_slim.commands import handle_command, parse_command
|
||||||
from cc_slim.engine import Agent, resolve_config
|
from cc_slim.engine import Agent, resolve_config
|
||||||
from cc_slim.memory import MemoryStore
|
from cc_slim.memory import MemoryStore
|
||||||
from cc_slim.session import SessionStore
|
from cc_slim.session import SessionStore
|
||||||
@ -79,52 +80,6 @@ def build_agent(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def handle_repl_command(
|
|
||||||
user_input: str,
|
|
||||||
store: SessionStore,
|
|
||||||
memory: MemoryStore,
|
|
||||||
config: object,
|
|
||||||
root: Path,
|
|
||||||
agent: Agent,
|
|
||||||
) -> Agent:
|
|
||||||
command = user_input.strip()
|
|
||||||
if command in {"--history", "/history"}:
|
|
||||||
render_history(store)
|
|
||||||
return agent
|
|
||||||
|
|
||||||
if command == "/new":
|
|
||||||
session_meta = store.create_session(config.model)
|
|
||||||
console.print(f"已创建新 session: {session_meta.get('session_id')}")
|
|
||||||
return build_agent(root, config, store, session_meta, [])
|
|
||||||
|
|
||||||
if command == "/memory":
|
|
||||||
content = memory.read()
|
|
||||||
console.print(content or "当前项目还没有 memory。")
|
|
||||||
return agent
|
|
||||||
|
|
||||||
if command.startswith("/remember "):
|
|
||||||
text = user_input.split(" ", 1)[1].strip()
|
|
||||||
if not text:
|
|
||||||
console.print("[red]error:[/red] 缺少需要保存的 memory 内容")
|
|
||||||
return agent
|
|
||||||
path = memory.append(text)
|
|
||||||
console.print(f"已写入 memory: {path}")
|
|
||||||
return agent
|
|
||||||
|
|
||||||
if command.startswith("--resume ") or command.startswith("/resume "):
|
|
||||||
target = command.split(maxsplit=1)[1].strip()
|
|
||||||
if not target:
|
|
||||||
console.print("[red]error:[/red] 缺少 resume 目标")
|
|
||||||
return agent
|
|
||||||
session_id = store.resolve_session_id(target)
|
|
||||||
session_meta = store.load_meta(session_id)
|
|
||||||
restored_history = store.load_messages(session_id)
|
|
||||||
console.print(f"已恢复 session: {session_meta.get('session_id')}")
|
|
||||||
return build_agent(root, config, store, session_meta, restored_history)
|
|
||||||
|
|
||||||
return agent
|
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def run(
|
def run(
|
||||||
prompt: Optional[str] = typer.Argument(None, help="单次执行的用户输入"),
|
prompt: Optional[str] = typer.Argument(None, help="单次执行的用户输入"),
|
||||||
@ -183,9 +138,19 @@ def run(
|
|||||||
if not user_input.strip():
|
if not user_input.strip():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if user_input.strip().startswith("/") or user_input.strip().startswith("--history") or user_input.strip().startswith("--resume"):
|
if parse_command(user_input):
|
||||||
try:
|
try:
|
||||||
agent = handle_repl_command(user_input, store, memory, config, root, agent)
|
agent = handle_command(
|
||||||
|
user_input,
|
||||||
|
console=console,
|
||||||
|
root=root,
|
||||||
|
config=config,
|
||||||
|
store=store,
|
||||||
|
memory=memory,
|
||||||
|
agent=agent,
|
||||||
|
build_agent=build_agent,
|
||||||
|
render_history=render_history,
|
||||||
|
)
|
||||||
except Exception as exc: # pragma: no cover
|
except Exception as exc: # pragma: no cover
|
||||||
console.print(f"[red]error:[/red] {exc}")
|
console.print(f"[red]error:[/red] {exc}")
|
||||||
continue
|
continue
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user