diff --git a/README.md b/README.md
index 4c91f1cf..4978a30c 100644
--- a/README.md
+++ b/README.md
@@ -48,7 +48,7 @@ CowAgent is lightweight, easy to deploy, and built to extend. Plug in any major
## 🏗️ Architecture
-
+
CowAgent is a complete **Agent Harness**: messages flow in through **Channels**; the **Agent Core** plans and reasons over memory, knowledge, and the available tools and skills; **Models** generate the response, which is sent back through the originating channel. Every layer is decoupled and independently extensible.
diff --git a/agent/memory/summarizer.py b/agent/memory/summarizer.py
index 9da349d1..066549dc 100644
--- a/agent/memory/summarizer.py
+++ b/agent/memory/summarizer.py
@@ -462,13 +462,12 @@ class MemoryFlushManager:
daily_content=daily_content or "(no recent daily records)",
)
from agent.protocol.models import LLMRequest
- # Scale max_tokens based on input size to avoid truncating large MEMORY.md
- input_chars = len(memory_content) + len(daily_content)
- dream_max_tokens = max(2000, min(input_chars, 8000))
+ # No output cap: the prompt already keeps MEMORY.md concise (~50
+ # items), so a hard max_tokens would only risk truncating a large
+ # rewrite. Let the model use its default output budget.
request = LLMRequest(
messages=[{"role": "user", "content": user_msg}],
temperature=0.3,
- max_tokens=dream_max_tokens,
stream=False,
system=_dream_system_prompt(),
)
diff --git a/cli/cli.py b/cli/cli.py
index 99b837ab..b266b372 100644
--- a/cli/cli.py
+++ b/cli/cli.py
@@ -3,7 +3,7 @@
import click
from cli import __version__
from cli.commands.skill import skill
-from cli.commands.process import start, stop, restart, update, status, logs
+from cli.commands.process import start, stop, restart, self_restart, update, status, logs
from cli.commands.context import context
from cli.commands.install import install_browser
from cli.commands.knowledge import knowledge
@@ -68,6 +68,7 @@ main.add_command(skill)
main.add_command(start)
main.add_command(stop)
main.add_command(restart)
+main.add_command(self_restart)
main.add_command(update)
main.add_command(status)
main.add_command(logs)
diff --git a/cli/commands/process.py b/cli/commands/process.py
index d6b1aaf4..c7f98448 100644
--- a/cli/commands/process.py
+++ b/cli/commands/process.py
@@ -195,6 +195,120 @@ def restart(ctx, no_logs):
ctx.invoke(start, no_logs=no_logs)
+# Detached relay that survives the caller's process tree. Run via `python -c`
+# with start_new_session=True so it keeps going after the agent's bash child
+# (and the main app it kills) both die. Flow: self-check the new code FIRST
+# (import app); abort without touching the old process if it fails. Only when
+# the new code is loadable does it SIGTERM the old PID, wait for exit (SIGKILL
+# fallback), then start a fresh app.py and write the pid.
+_RELAY_SCRIPT = r"""
+import os, sys, time, signal, subprocess
+
+root, python, app_py, pid_file, log_file = sys.argv[1:6]
+old_pid = int(sys.argv[6]) if len(sys.argv) > 6 and sys.argv[6] else 0
+
+
+def alive(pid):
+ if not pid:
+ return False
+ try:
+ os.kill(pid, 0)
+ return True
+ except OSError:
+ return False
+
+
+def log(msg):
+ try:
+ with open(log_file, "a") as f:
+ f.write("[self-restart] " + msg + "\n")
+ except OSError:
+ pass
+
+
+# 0) Self-check: make sure the new code actually loads BEFORE killing anything.
+# `import app` exercises top-level imports / syntax of the entry module. If it
+# fails, abort and leave the running service untouched — never end up with the
+# old process killed and the new one unable to start.
+check = subprocess.run(
+ [python, "-c", "import app"], cwd=root,
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+)
+if check.returncode != 0:
+ detail = (check.stdout or b"").decode("utf-8", "replace").strip()
+ log("self-check FAILED, aborting restart; service left running:\n" + detail)
+ sys.exit(1)
+log("self-check passed")
+
+# 1) Ask the old process to exit gracefully (its SIGTERM handler persists state).
+if alive(old_pid):
+ try:
+ os.kill(old_pid, signal.SIGTERM)
+ except OSError:
+ pass
+ # 2) Wait up to ~15s for it to go, then force-kill as a backstop.
+ for _ in range(150):
+ if not alive(old_pid):
+ break
+ time.sleep(0.1)
+ else:
+ try:
+ os.kill(old_pid, signal.SIGKILL)
+ except OSError:
+ pass
+ time.sleep(0.5)
+
+# 3) Start a fresh instance, detached, logging to the same file.
+with open(log_file, "a") as f:
+ proc = subprocess.Popen(
+ [python, app_py], cwd=root,
+ stdout=f, stderr=f, start_new_session=True,
+ )
+with open(pid_file, "w") as f:
+ f.write(str(proc.pid))
+log("restarted, new pid=" + str(proc.pid))
+"""
+
+
+@click.command(name="self-restart", hidden=True)
+def self_restart():
+ """Restart from inside the running agent (detached; survives parent death).
+
+ Intended to be invoked by the agent itself (e.g. via bash after editing its
+ own code), not by users — so it is hidden from `cow help`. Unlike `restart`,
+ the actual stop+start runs in a detached relay process that outlives the
+ agent's bash child, which would otherwise die together with the main app it
+ kills.
+ """
+ if _IS_WIN:
+ click.echo("self-restart is not supported on Windows; use `cow restart`.", err=True)
+ sys.exit(1)
+
+ root = get_project_root()
+ app_py = os.path.join(root, "app.py")
+ if not os.path.exists(app_py):
+ click.echo("Error: app.py not found in project root.", err=True)
+ sys.exit(1)
+
+ python = sys.executable
+ pid = _read_pid() or 0
+
+ subprocess.Popen(
+ [
+ python, "-c", _RELAY_SCRIPT,
+ root, python, app_py, _get_pid_file(), _get_log_file(), str(pid),
+ ],
+ cwd=root,
+ start_new_session=True,
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL,
+ )
+ click.echo(click.style(
+ "✓ Restart scheduled. The service will stop and come back in a few seconds.",
+ fg="green",
+ ))
+
+
@click.command()
@click.pass_context
def update(ctx):
diff --git a/docs/intro/architecture.mdx b/docs/intro/architecture.mdx
index a9797bf1..77fdbc8a 100644
--- a/docs/intro/architecture.mdx
+++ b/docs/intro/architecture.mdx
@@ -9,7 +9,7 @@ CowAgent 2.0 has evolved from a simple chatbot into a super intelligent assistan
CowAgent's architecture consists of the following core modules:
-
+
| Module | Description |
| --- | --- |
diff --git a/docs/ja/README.md b/docs/ja/README.md
index afe51342..1ae5cb84 100644
--- a/docs/ja/README.md
+++ b/docs/ja/README.md
@@ -48,7 +48,7 @@ CowAgent は軽量でデプロイしやすく、拡張性に優れています
## 🏗️ アーキテクチャ
-
+
CowAgent は完全な **Agent Harness** です:メッセージは各種**チャネル**から流入し、**Agent Core** が記憶・知識・利用可能なツール/Skill を組み合わせてタスクを計画・判断、**モデル**が応答を生成し、結果は元のチャネルに返されます。各レイヤーは疎結合で、独立して拡張可能です。
diff --git a/docs/ja/intro/architecture.mdx b/docs/ja/intro/architecture.mdx
index 5e8b202b..682b407e 100644
--- a/docs/ja/intro/architecture.mdx
+++ b/docs/ja/intro/architecture.mdx
@@ -9,7 +9,7 @@ CowAgent 2.0 は、シンプルなチャットボットから、自律的な思
CowAgent のアーキテクチャは以下のコアモジュールで構成されています:
-
+
| モジュール | 説明 |
| --- | --- |