Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ The execution model, in this repo's own terms (`emrg/server/daemon.py`):

- **Tool loop** — the whole process triggered by one user message: LLM requests and tool calls repeat until a round produces no new tool calls (`_run_tool_loop`).
- **Round** — one iteration inside a tool loop: one LLM request + zero or more tool calls + their execution (`round_num`, bounded by `max_tool_rounds`).
- **Evolution cycle** — one full self-evolution run (Prepare → Review → Discover → Improve → Submit → Record). Never call it a "round".
- **Evolution cycle** — one full self-evolution run (Preparation → Look → Think → Act → Record). Never call it a "round".

## Capabilities

Expand Down
12 changes: 7 additions & 5 deletions README.cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ EMRG 是一个关于*自主进化*的实验:一个能帮你写代码的 AI 智
|---|---|
| **Electron GUI(主入口)** | 安装即用:首次启动引导配置 API Key;全部 `/` 指令可用;结果面板、Ask/Auto 模式、自进化可见化。GUI 配好即 TUI 可用 |
| **全功能 TUI + 守护进程** | 流式 Markdown、`/` 自动补全、会话管理、快捷键——跑在常驻的 `emrgd` 守护进程上,随时重连 |
| **定时任务** | 内置 + 自定义任务类型(提示词模板存 `~/.emrg/task-templates/`)、GUI 设置页增删改 + 热加载、`/trigger` 随时手动触发 |
| **定时任务** | 内置任务类型(`evolution`、`paper`、`open-source`、`promote`、`journal`、`competition`、`ios-app`、`feishu`)加自定义类型(提示词模板存 `~/.emrg/task-templates/`)、GUI 设置页增删改 + 热加载、`/trigger` 随时手动触发 |
| **100% 开源** | MIT 协议——没有围墙,没有厂商锁定。默认英文,提供中文版 |

---
Expand All @@ -64,8 +64,8 @@ EMRG 不只是一个工具——它是一个**会听吐槽、会自我改进**
- 跨项目学习
|
v
演化循环(每 30 分钟)
(准备 -> 回顾 -> 发现 -> 改进 -> 提交 -> 记录)
演化循环(默认每 10 分钟)
(Preparation -> Look -> Think -> Act -> Record)
|
v
1. pytest + import 检查
Expand Down Expand Up @@ -148,12 +148,14 @@ TUI 内:`Esc` 中断流式输出,`Ctrl+C` / `exit` 退出(配置与 GUI
| `/memory` | 浏览项目和会话记忆 |
| `/rename [标题]` | 给当前会话起个好记的名字 |
| `/model [name]` | 切换 LLM 模型——不带参数进入交互式选择器 |
| `/sandbox [mode]` | 设置本会话的沙箱档位——不带参数弹出选择器;`add`/`remove`/`list` 管理额外可写根 |
| `/rant <反馈> [@<project>]` | 吐槽、建议、夸奖——演化系统会听 |
| `/help` | 查看所有键盘快捷键和命令帮助 |
| `/image` | 从剪贴板插入图片到输入框 |
| `/delete [id]` | 删除会话——不带参数进入交互式选择器 |
| `/rewind` | 回退对话到历史某个节点 |
| `/trigger` | 触发演化任务——交互式选择器(任务管理在 GUI 设置 → 定时任务) |
| `/task-session` | 打开某个定时任务自己的会话——交互式选择器 |
| `/skills` | 列出已加载技能;`/skills available\|install\|update` |
| `/version` | 显示 EMRG 版本和实例信息 |
| `Esc` | 中断正在运行的响应 |
Expand All @@ -166,13 +168,13 @@ TUI 内:`Esc` 中断流式输出,`Ctrl+C` / `exit` 退出(配置与 GUI
| | Claude Code | Codex | DeepSeek Harness | **EMRG** | **Grok Bot** |
|---|---|---|---|---|---|
| AI 驱动编程 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 工具调用 (bash, read, write, edit, glob, grep) | ✅ | ✅ | ✅ | ✅ | ✅ |
| 工具调用 (`bash`/`pwsh`、`read`、`write`、`edit`、`glob`、`grep`、`submit_rant`、`subagent`) | ✅ | ✅ | ✅ | ✅ | ✅ |
| 会话记忆与上下文 | ✅ | ✅ | ✅ | ✅ | ✅ |
| `/` 命令自动补全 | ✅ | ✅ | ✅ | ✅ | ~ *@ mention 建议 + 命令面板* |
| ESC 中断 | ✅ | ✅ | — | ✅ | ✅ |
| 插件化架构 | ❌ | ❌ | ✅ *一切皆插件* | ❌ | ✅ |
| 沙箱执行 | ❌ | ❌ | ✅ | ✅ *read-only / workspace-write / danger-full-access* | ~ *protectedBoxPaths + /workspace* |
| 子代理 | ❌ | ❌ | ✅ | ❌ | ✅ *assistants/automations 生态* |
| 子代理 | ❌ | ❌ | ✅ | ✅ *子会话委派* | ✅ *assistants/automations 生态* |
| Web UI | ❌ | ❌ | ✅ *浏览器* | ✅ *Electron* | ✅ *Electron* |
| **递归自我改进(RSI)** | ❌ | ❌ | ❌ | ✅ *全自动——代码、提示词、工具链* | ❌ |
| **个人智能体** *你的机器、你的 key、你的数据* | ~ *本地 CLI,模型为托管服务,走你的账号* | ~ *本地 CLI,模型为托管服务* | ~ *本地 harness,模型为托管服务* | ✅ *本地智能体,用你的 key,状态在你磁盘上* | ~ *本地应用,托管服务* |
Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ EMRG is an experiment in *autonomous self-improvement*: an AI agent that helps y
|---|---|
| **Electron GUI (main entry)** | Install & go: first-run wizard, all slash commands, results panel, Ask/Auto modes, visible self-evolution. GUI configured = TUI ready |
| **Full-featured TUI + daemon** | Streaming markdown, `/` autocomplete, sessions, shortcuts — on a persistent `emrgd` daemon you can reconnect to anytime |
| **Scheduled tasks** | Built-in + custom task types with prompt templates (`~/.emrg/task-templates/`), CRUD + hot reload from the GUI settings, `/trigger` any task on demand |
| **Scheduled tasks** | Built-in task types (`evolution`, `paper`, `open-source`, `promote`, `journal`, `competition`, `ios-app`, `feishu`) plus custom ones with prompt templates in `~/.emrg/task-templates/`, CRUD + hot reload from the GUI settings, `/trigger` any task on demand |
| **100% open source** | MIT — no walled garden, no vendor lock-in. English default, Chinese version available |

---
Expand All @@ -64,8 +64,8 @@ Inputs:
- Cross-project learning
|
v
Evolution Cycle (every 30 min)
(Prepare -> Review -> Discover -> Improve -> Commit -> Record)
Evolution Cycle (every 10 min by default)
(Preparation -> Look -> Think -> Act -> Record)
|
v
1. pytest + import check
Expand Down Expand Up @@ -150,12 +150,14 @@ In the TUI: `Esc` interrupts streaming, `Ctrl+C` / `exit` quits (config is share
| `/memory` | Browse project & session memories |
| `/rename [title]` | Give your session a memorable name |
| `/model [name]` | Switch LLM model — no args for interactive picker |
| `/sandbox [mode]` | Set this session's sandbox tier — no args for a picker; `add`/`remove`/`list` manage extra writable roots |
| `/rant <feedback> [@<project>]` | Complain, suggest, praise — evolution listens |
| `/help` | Show keyboard shortcuts and command help |
| `/image` | Insert clipboard image into the input field |
| `/delete [id]` | Delete a session — no args for interactive picker |
| `/rewind` | Rewind conversation to a history point |
| `/trigger` | Trigger an evolution task — interactive picker (manage tasks in GUI Settings → Scheduled tasks) |
| `/task-session` | Open a scheduled task's own session — interactive picker |
| `/skills` | List loaded skills; `/skills available\|install\|update` |
| `/version` | Show EMRG version and instance info |
| `Esc` | Interrupt a running response mid-stream |
Expand All @@ -168,13 +170,13 @@ In the TUI: `Esc` interrupts streaming, `Ctrl+C` / `exit` quits (config is share
| | Claude Code | Codex | DeepSeek Harness | **EMRG** | **Grok Bot** |
|---|---|---|---|---|---|
| AI-powered coding | ✅ | ✅ | ✅ | ✅ | ✅ |
| Tool-calling (bash, read, write, edit, glob, grep) | ✅ | ✅ | ✅ | ✅ | ✅ |
| Tool-calling (`bash`/`pwsh`, `read`, `write`, `edit`, `glob`, `grep`, `submit_rant`, `subagent`) | ✅ | ✅ | ✅ | ✅ | ✅ |
| Session memory & context | ✅ | ✅ | ✅ | ✅ | ✅ |
| `/` command autocomplete | ✅ | ✅ | ✅ | ✅ | ~ *@ mention + command palette* |
| ESC interrupt | ✅ | ✅ | — | ✅ | ✅ |
| Plugin architecture | ❌ | ❌ | ✅ *everything is a plugin* | ❌ | ✅ |
| Sandboxed execution | ❌ | ❌ | ✅ | ✅ *read-only / workspace-write / danger-full-access* | ~ *protectedBoxPaths + /workspace* |
| Subagents | ❌ | ❌ | ✅ | ❌ | ✅ *assistants/automations* |
| Subagents | ❌ | ❌ | ✅ | ✅ *delegated child sessions* | ✅ *assistants/automations* |
| Web UI | ❌ | ❌ | ✅ *browser* | ✅ *Electron* | ✅ *Electron* |
| **Recursive self-improvement (RSI)** | ❌ | ❌ | ❌ | ✅ *autonomous — code, prompts, toolchain* | ❌ |
| **Personal agent** *your machine, your key, your data* | ~ *local CLI, hosted model, your account* | ~ *local CLI, hosted model* | ~ *local harness, hosted model* | ✅ *local agent, your key, its state on your disk* | ~ *local app, hosted service* |
Expand Down
61 changes: 45 additions & 16 deletions emrg/server/daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,50 @@ def build_shell_tool(
return BashToolV2()


def build_tool_registry(
sandbox_config: Optional[SandboxConfig] = None,
run_subagent_cb=None,
platform_name: str | None = None,
) -> ToolRegistry:
"""The daemon's tool set, built in one place so that its size is a reading.

The registry is the one fact about this agent that a document cannot restate
by hand and stay true: `README.md` names the tools, and a name added here is a
name that document stops being right about the moment it is added. Something
therefore has to compare the two, and a comparison that lives in a test needs a
producer it can call **without a daemon** — a copy of this block in the test
would be a second list to keep in step, which is the defect
`emrg/tools/shell_dialects.py` exists to name. So the block is here, the daemon
calls it, and `tests/test_readme_matches_code.py` reads the same function.

:param sandbox_config: the ``[sandbox]`` section, passed through to
:func:`build_shell_tool`; a missing one means the defaults.
:param run_subagent_cb: the caller's own runner. The tool has no path to the
session machinery of its own, so everything that owns state stays with the
daemon that supplies it.
:param platform_name: the platform to decide the shell dialect for; defaults to
the host's, which is what the daemon wants and what a test overrides.
:returns: the populated registry.
"""
tools = ToolRegistry()
# Which shell this platform mounts — and, on POSIX, which of the two
# executors answers to the name `bash`. The gate is composition data
# rather than a runtime branch (design §14.2 layer 6): Windows has no
# `bash` tool row at all, so "bash is not found" is not representable
# there. See `build_shell_tool` for the three cases.
tools.register(build_shell_tool(sandbox_config, platform_name))
tools.register(ReadTool())
tools.register(WriteTool())
tools.register(EditTool())
tools.register(GlobTool())
tools.register(GrepTool())
tools.register(SubmitRantTool())
# The runner is the daemon's own method, so the tool has no path to the
# session machinery of its own: everything that owns state stays there.
tools.register(SubagentTool(run_subagent_cb))
return tools


class EmrgServer:
"""EMRG daemon — listens on Unix socket, processes tasks with tool calling."""

Expand Down Expand Up @@ -798,22 +842,7 @@ def __init__(self, llm_config: LlmConfig) -> None:
self._pending_web_auth_proc: Optional[asyncio.subprocess.Process] = None

# Build tool registry
self.tools = ToolRegistry()
# Which shell this platform mounts — and, on POSIX, which of the two
# executors answers to the name `bash`. The gate is composition data
# rather than a runtime branch (design §14.2 layer 6): Windows has no
# `bash` tool row at all, so "bash is not found" is not representable
# there. See `build_shell_tool` for the three cases.
self.tools.register(build_shell_tool(self._sandbox_config))
self.tools.register(ReadTool())
self.tools.register(WriteTool())
self.tools.register(EditTool())
self.tools.register(GlobTool())
self.tools.register(GrepTool())
self.tools.register(SubmitRantTool())
# The runner is the daemon's own method, so the tool has no path to the
# session machinery of its own: everything that owns state stays here.
self.tools.register(SubagentTool(self._run_subagent_tool))
self.tools = build_tool_registry(self._sandbox_config, self._run_subagent_tool)
logger.info("tools registered: %s", self.tools.names)

# Skills are **not** held here. A snapshot taken at startup cannot see a skill
Expand Down
Loading
Loading