From 9e293b232c0d7819f8d7c9b490eaf49d23543b5c Mon Sep 17 00:00:00 2001 From: LUOSENGWA <1600967865@qq.com> Date: Tue, 28 Jul 2026 13:47:52 +0000 Subject: [PATCH 1/9] feat(manager): migrate Manager runtime from copaw to qwenpaw 2.0 Manager now runs on QwenPaw 2.0.1 alongside PR #1077's Worker migration. Key changes: - Separate venvs: /opt/copaw-venv (copaw 1.0.2 for bridge.py) and /opt/venv/qwenpaw (qwenpaw 2.0.1 for Manager runtime), avoiding agentscope version conflict (1.0.20 vs 2.0.4) - Replace copaw hooks (monkey-patch CoPawAgent._create_toolkit) with agentteams-manager-tools QwenPaw plugin (api.register_tool()) for projectflow/taskflow/message/filesync - Delete Matrix channel physical overlay; use QwenPaw plugin system (agentteams-matrix-channel) symlinked into WORKING_DIR/plugins/ - run_copaw_app.py simplified to runpy.run_module('qwenpaw') - bridge.py invoked with /opt/copaw-venv/bin/python3 (pure stdlib, copaw 1.0.2 deps preserved) - CI pgrep pattern accepts both 'copaw app' and 'qwenpaw app' --- changelog/current.md | 1 + copaw/src/copaw_worker/run_copaw_app.py | 16 ++++-- copaw/tests/test_message_tool.py | 12 ++-- manager/Dockerfile.copaw | 51 +++++++++++++---- manager/scripts/init/start-copaw-manager.sh | 12 ++-- plugins/agentteams-manager-tools/plugin.json | 17 ++++++ plugins/agentteams-manager-tools/plugin.py | 58 ++++++++++++++++++++ tests/lib/test-helpers.sh | 2 +- tests/test-01-manager-boot.sh | 2 +- 9 files changed, 143 insertions(+), 28 deletions(-) create mode 100644 plugins/agentteams-manager-tools/plugin.json create mode 100644 plugins/agentteams-manager-tools/plugin.py diff --git a/changelog/current.md b/changelog/current.md index d0e728ad4..2c7f3736b 100644 --- a/changelog/current.md +++ b/changelog/current.md @@ -23,6 +23,7 @@ Record image-affecting changes to `manager/`, `worker/`, `copaw/`, `hermes/`, `o **Branding and Compatibility** - **QwenPaw 2.0 runtime compatibility**: Adapt the QwenPaw Worker image, Matrix overlay, and native plugins to QwenPaw 2.0.0.post3 startup and schema contracts. +- **QwenPaw 2.0 Manager runtime**: Migrate the Manager container from copaw 1.0.2 to QwenPaw 2.0.1 with a separate venv to avoid agentscope version conflicts, register projectflow/taskflow/message/filesync tools through a QwenPaw plugin instead of monkey-patching CoPawAgent, and replace the physical Matrix channel overlay with the QwenPaw plugin system. - **Complete AgentTeams runtime rename**: Rename installer and Helm entrypoints, the controller Go module and CLI, and container filesystem paths to AgentTeams while preserving thin compatibility aliases and upgrade migration for existing HiClaw installations. ([3121f5f](https://github.com/agentscope-ai/AgentTeams/commit/3121f5f)) - **Hard-cut AgentTeams naming**: Remove retired-brand installer wrappers, environment fallbacks, CLI aliases, Helm naming branches, runtime path migrations, and active source paths so fresh AgentTeams deployments use one canonical contract end to end. ([d20e606](https://github.com/agentscope-ai/AgentTeams/commit/d20e606617edefbbc42c28c1201c5629fa73fd88)) - **Hard-cut Team and Worker resources**: Make Worker CRs the sole owners of runtime configuration and lifecycle, make Team CRs reference existing Workers through `spec.workerMembers`, and remove inline-member, registry, migration, and dependent-script compatibility paths. ([b3cf360](https://github.com/agentscope-ai/AgentTeams/commit/b3cf360)) diff --git a/copaw/src/copaw_worker/run_copaw_app.py b/copaw/src/copaw_worker/run_copaw_app.py index 8fd4eaee1..6b9cca509 100644 --- a/copaw/src/copaw_worker/run_copaw_app.py +++ b/copaw/src/copaw_worker/run_copaw_app.py @@ -1,15 +1,21 @@ -"""Run the upstream CoPaw app with AgentTeams runtime hooks installed.""" +"""Run the QwenPaw 2.0 app for AgentTeams Manager. + +Previously this module called ``install_tool_hooks()`` to monkey-patch +``CoPawAgent._create_toolkit``. On QwenPaw 2.0 that approach no longer +works — ``QwenPawAgent`` does not inherit from ``CoPawAgent`` and has no +``_create_toolkit`` method. The four manager tools (projectflow, taskflow, +message, filesync) are now registered via the ``agentteams-manager-tools`` +QwenPaw plugin (``api.register_tool()``), so this wrapper simply launches +QwenPaw. +""" from __future__ import annotations import runpy -from copaw_worker.hooks import install_tool_hooks - def main() -> None: - install_tool_hooks() - runpy.run_module("copaw", run_name="__main__", alter_sys=True) + runpy.run_module("qwenpaw", run_name="__main__", alter_sys=True) if __name__ == "__main__": diff --git a/copaw/tests/test_message_tool.py b/copaw/tests/test_message_tool.py index 89838a63c..60a634d9e 100644 --- a/copaw/tests/test_message_tool.py +++ b/copaw/tests/test_message_tool.py @@ -510,13 +510,17 @@ async def query_handler(self, msgs, request=None, **kwargs): assert ("taskflow", "override") in names -def test_run_copaw_app_installs_hooks_before_start(monkeypatch): +def test_run_copaw_app_starts_qwenpaw(monkeypatch): + """run_copaw_app.main() should launch qwenpaw without tool hooks. + + The copaw hooks (install_tool_hooks) were removed because + QwenPaw 2.0's QwenPawAgent does not have _create_toolkit. + Tools are now registered via the agentteams-manager-tools plugin. + """ import copaw_worker.run_copaw_app as app calls = [] - monkeypatch.setattr(app, "install_tool_hooks", lambda: calls.append("hooks")) - def fake_run_module(name, *, run_name, alter_sys): calls.append((name, run_name, alter_sys)) @@ -524,4 +528,4 @@ def fake_run_module(name, *, run_name, alter_sys): app.main() - assert calls == ["hooks", ("copaw", "__main__", True)] + assert calls == [("qwenpaw", "__main__", True)] diff --git a/manager/Dockerfile.copaw b/manager/Dockerfile.copaw index e3ab1edb8..f1a022d6e 100644 --- a/manager/Dockerfile.copaw +++ b/manager/Dockerfile.copaw @@ -83,18 +83,6 @@ RUN pip install --no-cache-dir \ loongsuite-instrumentation-copaw \ loongsuite-instrumentation-agentscope -# ---- Overlay AgentTeams Matrix channel (not yet merged into CoPaw release) ---- -# Replace CoPaw's built-in Matrix channel with AgentTeams-enhanced version -COPY copaw/src/matrix/ /tmp/matrix-overlay/ -RUN SITE=$(python3 -c "import copaw; import os; print(os.path.dirname(copaw.__file__))") \ - && rm -rf "$SITE/app/channels/matrix" \ - && mkdir -p "$SITE/app/channels/matrix" \ - && cp /tmp/matrix-overlay/channel.py /tmp/matrix-overlay/__init__.py "$SITE/app/channels/matrix/" \ - && if [ -f /tmp/matrix-overlay/config.py ]; then \ - cp /tmp/matrix-overlay/config.py "$SITE/config/config.py"; \ - fi \ - && rm -rf /tmp/matrix-overlay - # ---- CoPaw worker bridge module (for config conversion) ---- # Stage the copaw-worker package metadata for dependency resolution COPY copaw/pyproject.toml copaw/README.md /tmp/copaw-worker/ @@ -115,6 +103,45 @@ RUN SITE=/opt/copaw-venv/lib/python3.11/site-packages \ && cp -a /tmp/copaw-worker/src/copaw_worker/* "$SITE/copaw_worker/" \ && rm -rf /tmp/copaw-worker/ +# ---- QwenPaw 2.0 Runtime (Manager) ---- +# Separate venv: copaw 1.0.2 requires agentscope==1.0.20, qwenpaw 2.0.1 +# requires agentscope>=2.0.0. Mixing them in one venv breaks copaw's +# ReActAgent import. The copaw venv above stays pristine for bridge.py; +# qwenpaw runs from this venv. +ARG QWENPAW_PIP_SPEC=qwenpaw==2.0.1 +RUN python3 -m venv /opt/venv/qwenpaw \ + && /opt/venv/qwenpaw/bin/pip install --no-cache-dir \ + -i "${PIP_INDEX_URL}" \ + --trusted-host "$(echo ${PIP_INDEX_URL} | sed 's|https\?://||;s|/.*||')" \ + "${QWENPAW_PIP_SPEC}" + +# Overlay copaw_worker source into qwenpaw venv. +# The 4 manager tools (projectflow/taskflow/message/filesync) depend only on +# agentscope 2.0.x and copaw_worker internal modules — not on copaw 1.0.2. +RUN cp -a /opt/copaw-venv/lib/python3.11/site-packages/copaw_worker \ + /opt/venv/qwenpaw/lib/python3.11/site-packages/ + +# qwenpaw CLI on PATH +RUN ln -sf /opt/venv/qwenpaw/bin/qwenpaw /usr/local/bin/qwenpaw + +# qwenpaw venv takes priority for Manager runtime +ENV PATH="/opt/venv/qwenpaw/bin:/opt/copaw-venv/bin:${PATH}" + +# AgentTeams plugins: Matrix channel + Manager tools +COPY plugins/agentteams-matrix-channel/ /opt/agentteams/plugins/agentteams-matrix-channel/ +COPY plugins/agentteams-manager-tools/ /opt/agentteams/plugins/agentteams-manager-tools/ + +# Copy plugins into QwenPaw's plugin discovery path. +# WORKING_DIR = ~/.copaw (set by start-copaw-manager.sh at runtime). +# cp -a (not ln -sfn): QwenPaw PluginLoader._load_plugin_from_path_unlocked +# resolves source_path vs target_dir — symlinks cause rmtree of the real dir +# followed by copytree from the now-dead symlink target (crash). +RUN mkdir -p /root/manager-workspace/.copaw/plugins \ + && cp -a /opt/agentteams/plugins/agentteams-matrix-channel \ + /root/manager-workspace/.copaw/plugins/agentteams-matrix-channel \ + && cp -a /opt/agentteams/plugins/agentteams-manager-tools \ + /root/manager-workspace/.copaw/plugins/agentteams-manager-tools + # ---- Copy Manager agent definitions ---- COPY manager/agent/ /opt/agentteams/agent/ COPY manager/configs/ /opt/agentteams/configs/ diff --git a/manager/scripts/init/start-copaw-manager.sh b/manager/scripts/init/start-copaw-manager.sh index 57da7eb29..59cdfd0a4 100644 --- a/manager/scripts/init/start-copaw-manager.sh +++ b/manager/scripts/init/start-copaw-manager.sh @@ -47,7 +47,7 @@ fi log "Bridging openclaw.json -> CoPaw config (manager)..." PYTHONPATH="/opt/agentteams/copaw/src:${PYTHONPATH:-}" \ - python3 -m copaw_worker.bridge \ + /opt/copaw-venv/bin/python3 -m copaw_worker.bridge \ --profile manager \ --openclaw-json "${OPENCLAW_JSON}" \ --working-dir "${COPAW_WORKING_DIR}" @@ -212,7 +212,7 @@ fi if [ -n "${_curr_hash}" ] && [ "${_curr_hash}" != "${_prev_hash}" ]; then log "openclaw.json changed, re-bridging..." _bridge_out=$(PYTHONPATH="/opt/agentteams/copaw/src:${PYTHONPATH:-}" \ - python3 -m copaw_worker.bridge \ + /opt/copaw-venv/bin/python3 -m copaw_worker.bridge \ --profile manager \ --openclaw-json "${OPENCLAW_JSON}" \ --working-dir "${COPAW_WORKING_DIR}" 2>&1) @@ -231,14 +231,16 @@ log "openclaw.json watcher started (PID: $!)" # 10. Launch CoPaw Manager (app mode with hot-reload) # ============================================================ export COPAW_WORKING_DIR="${COPAW_WORKING_DIR}" +# QWENPAW_WORKING_DIR points to the same directory as COPAW_WORKING_DIR (.copaw/) +# qwenpaw reads config.json + agent.json from this path +export QWENPAW_WORKING_DIR="${COPAW_WORKING_DIR}" -log "Starting CoPaw Manager (app mode)..." +log "Starting QwenPaw 2.0 Manager (app mode)..." COPAW_LOG_LEVEL="${COPAW_LOG_LEVEL:-info}" export COPAW_LOG_LEVEL # Set PYTHONPATH to include copaw_worker module export PYTHONPATH="/opt/agentteams/copaw/src:${PYTHONPATH:-}" -# Use uvicorn to run CoPaw FastAPI app (enables AgentConfigWatcher for hot-reload) -# The wrapper installs AgentTeams-owned tools before CoPaw creates any agents. +# run_copaw_app.py starts qwenpaw app (tools registered via agentteams-manager-tools plugin) exec python3 -m copaw_worker.run_copaw_app app --host 0.0.0.0 --port 18799 diff --git a/plugins/agentteams-manager-tools/plugin.json b/plugins/agentteams-manager-tools/plugin.json new file mode 100644 index 000000000..41e39af2f --- /dev/null +++ b/plugins/agentteams-manager-tools/plugin.json @@ -0,0 +1,17 @@ +{ + "id": "agentteams-manager-tools", + "name": "AgentTeams Manager Tools", + "version": "0.1.0", + "type": "general", + "description": "projectflow, taskflow, message, filesync tools for Manager", + "author": "AgentTeams", + "entry": { + "backend": "plugin.py" + }, + "dependencies": [], + "min_version": "2.0.1", + "qwenpaw_version": { + "min": "2.0.1", + "max": "2.1.0" + } +} diff --git a/plugins/agentteams-manager-tools/plugin.py b/plugins/agentteams-manager-tools/plugin.py new file mode 100644 index 000000000..b62b1646d --- /dev/null +++ b/plugins/agentteams-manager-tools/plugin.py @@ -0,0 +1,58 @@ +"""Register AgentTeams Manager tools as a QwenPaw 2.0 plugin. + +The four tools (projectflow, taskflow, message, filesync) were previously +injected via ``install_tool_hooks()`` which monkey-patched +``CoPawAgent._create_toolkit``. QwenPaw 2.0's ``QwenPawAgent`` does not +have that method, so the tools are now registered through the plugin API's +``api.register_tool()``. + +Tool dependencies (verified against agentscope 2.0.4.post1): + - ``agentscope.message.TextBlock / Msg`` ✅ + - ``agentscope.tool.ToolResponse`` ✅ + - ``copaw_worker.task / sync / hooks.message_filter`` — pure stdlib + agentscope + +No dependency on ``copaw`` 1.0.2 at module-import time. Two functions +(``taskflow``, ``message``) contain deferred ``from copaw.config.config +import load_agent_config`` inside specific branches; those branches will +raise ``ImportError`` if hit, but do not affect plugin loading. +""" + + +class AgentTeamsManagerToolsPlugin: + def register(self, api): + from copaw_worker.hooks.tools.projectflow import projectflow + from copaw_worker.hooks.tools.taskflow import taskflow + from copaw_worker.hooks.tools.message import message + from copaw_worker.hooks.tools.filesync import filesync + + api.register_tool( + tool_name="projectflow", + tool_func=projectflow, + description="AgentTeams project/DAG lifecycle management", + tool_type="internal", + enabled=True, + ) + api.register_tool( + tool_name="taskflow", + tool_func=taskflow, + description="AgentTeams task state management", + tool_type="internal", + enabled=True, + ) + api.register_tool( + tool_name="message", + tool_func=message, + description="Send messages to workers via Matrix", + tool_type="internal", + enabled=True, + ) + api.register_tool( + tool_name="filesync", + tool_func=filesync, + description="Sync files between Manager and Workers via MinIO", + tool_type="internal", + enabled=True, + ) + + +plugin = AgentTeamsManagerToolsPlugin() diff --git a/tests/lib/test-helpers.sh b/tests/lib/test-helpers.sh index 9ded23928..ebc2dfb9f 100755 --- a/tests/lib/test-helpers.sh +++ b/tests/lib/test-helpers.sh @@ -209,7 +209,7 @@ wait_for_manager_agent_ready() { while [ "${elapsed}" -lt "${timeout}" ]; do case "${manager_runtime}" in copaw) - if docker exec "${agent_container}" pgrep -f "copaw(_worker\\.run_copaw_app)? app" >/dev/null 2>&1 && \ + if docker exec "${agent_container}" pgrep -f "copaw(_worker\\.run_copaw_app)? app\|qwenpaw app" >/dev/null 2>&1 && \ docker exec "${agent_container}" curl -sf http://127.0.0.1:18799/ >/dev/null 2>&1; then runtime_ready=true break diff --git a/tests/test-01-manager-boot.sh b/tests/test-01-manager-boot.sh index 61a5bf4de..517406bd8 100755 --- a/tests/test-01-manager-boot.sh +++ b/tests/test-01-manager-boot.sh @@ -120,7 +120,7 @@ case "${MANAGER_RUNTIME}" in log_fail "CoPaw agent.json valid" fi - if docker exec "${_AGENT_CTR}" pgrep -f "copaw(_worker\\.run_copaw_app)? app" >/dev/null 2>&1; then + if docker exec "${_AGENT_CTR}" pgrep -f "copaw(_worker\\.run_copaw_app)? app\|qwenpaw app" >/dev/null 2>&1; then log_pass "CoPaw process running" else log_fail "CoPaw process running" From 974cdf6c492849000bf20dd7df9a8c5ac74b786b Mon Sep 17 00:00:00 2001 From: LUOSENGWA <1600967865@qq.com> Date: Tue, 28 Jul 2026 14:44:10 +0000 Subject: [PATCH 2/9] fix(manager): read Matrix config from agent.json without copaw import MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The message and taskflow tools deferred-imported copaw.config.config to read Matrix credentials (homeserver, access_token, user_id). In the QwenPaw 2.0 venv copaw 1.0.2 is absent, so _matrix_config_for_agent() raised ImportError — the message tool could not send any Matrix messages. Fix: read workspaces//agent.json directly (framework-agnostic). bridge.py already writes the Matrix channel config there. Also add QWENPAW_WORKING_DIR fallback to _resolve_copaw_working_dir() and _current_actor(). --- changelog/current.md | 2 +- copaw/src/copaw_worker/hooks/tools/message.py | 31 +++++++++++++++---- .../src/copaw_worker/hooks/tools/taskflow.py | 25 ++++++++++----- 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/changelog/current.md b/changelog/current.md index 2c7f3736b..e97291b0d 100644 --- a/changelog/current.md +++ b/changelog/current.md @@ -23,7 +23,7 @@ Record image-affecting changes to `manager/`, `worker/`, `copaw/`, `hermes/`, `o **Branding and Compatibility** - **QwenPaw 2.0 runtime compatibility**: Adapt the QwenPaw Worker image, Matrix overlay, and native plugins to QwenPaw 2.0.0.post3 startup and schema contracts. -- **QwenPaw 2.0 Manager runtime**: Migrate the Manager container from copaw 1.0.2 to QwenPaw 2.0.1 with a separate venv to avoid agentscope version conflicts, register projectflow/taskflow/message/filesync tools through a QwenPaw plugin instead of monkey-patching CoPawAgent, and replace the physical Matrix channel overlay with the QwenPaw plugin system. +- **QwenPaw 2.0 Manager runtime**: Migrate the Manager container from copaw 1.0.2 to QwenPaw 2.0.1 with a separate venv to avoid agentscope version conflicts, register projectflow/taskflow/message/filesync tools through a QwenPaw plugin instead of monkey-patching CoPawAgent, replace the physical Matrix channel overlay with the QwenPaw plugin system, and read Matrix credentials directly from agent.json so the manager tools work without importing copaw at runtime. - **Complete AgentTeams runtime rename**: Rename installer and Helm entrypoints, the controller Go module and CLI, and container filesystem paths to AgentTeams while preserving thin compatibility aliases and upgrade migration for existing HiClaw installations. ([3121f5f](https://github.com/agentscope-ai/AgentTeams/commit/3121f5f)) - **Hard-cut AgentTeams naming**: Remove retired-brand installer wrappers, environment fallbacks, CLI aliases, Helm naming branches, runtime path migrations, and active source paths so fresh AgentTeams deployments use one canonical contract end to end. ([d20e606](https://github.com/agentscope-ai/AgentTeams/commit/d20e606617edefbbc42c28c1201c5629fa73fd88)) - **Hard-cut Team and Worker resources**: Make Worker CRs the sole owners of runtime configuration and lifecycle, make Team CRs reference existing Workers through `spec.workerMembers`, and remove inline-member, registry, migration, and dependent-script compatibility paths. ([b3cf360](https://github.com/agentscope-ai/AgentTeams/commit/b3cf360)) diff --git a/copaw/src/copaw_worker/hooks/tools/message.py b/copaw/src/copaw_worker/hooks/tools/message.py index 0af90a3d0..b43f44a51 100644 --- a/copaw/src/copaw_worker/hooks/tools/message.py +++ b/copaw/src/copaw_worker/hooks/tools/message.py @@ -230,11 +230,17 @@ def _sanitize_session_filename(name: str) -> str: def _resolve_copaw_working_dir() -> Path: - configured = os.environ.get("COPAW_WORKING_DIR") + configured = ( + os.environ.get("COPAW_WORKING_DIR") + or os.environ.get("QWENPAW_WORKING_DIR") + ) if configured: return Path(configured).expanduser().resolve() - from copaw.constant import WORKING_DIR + try: + from copaw.constant import WORKING_DIR + except ImportError: + from qwenpaw.constant import WORKING_DIR return Path(WORKING_DIR).expanduser().resolve() @@ -339,11 +345,24 @@ async def _record_matrix_outbound_to_session( def _matrix_config_for_agent(account_id: str) -> tuple[str, str, str]: - from copaw.config.config import load_agent_config + # Read agent.json directly to avoid a hard dependency on + # copaw.config.config, which is unavailable in the QwenPaw 2.0 venv. + # bridge.py writes homeserver/access_token/user_id into + # workspaces//agent.json regardless of runtime. + working_dir = _resolve_copaw_working_dir() + agent_json = ( + working_dir / "workspaces" / (account_id or "default") / "agent.json" + ) + try: + with open(agent_json, "r", encoding="utf-8") as f: + data = json.load(f) + except (FileNotFoundError, json.JSONDecodeError) as exc: + raise MessageToolError( + f"cannot read agent config at {agent_json}: {exc}", + ) - agent_config = load_agent_config(account_id or "default") - channels = _read_config_value(agent_config, "channels") or {} - matrix_cfg = _read_config_value(channels, "matrix") or {} + channels = data.get("channels") or {} + matrix_cfg = channels.get("matrix") or {} homeserver = _read_config_value(matrix_cfg, "homeserver") or "" access_token = _read_config_value(matrix_cfg, "access_token", "accessToken") or "" diff --git a/copaw/src/copaw_worker/hooks/tools/taskflow.py b/copaw/src/copaw_worker/hooks/tools/taskflow.py index f479ce0a7..0fa61aaf6 100644 --- a/copaw/src/copaw_worker/hooks/tools/taskflow.py +++ b/copaw/src/copaw_worker/hooks/tools/taskflow.py @@ -151,15 +151,24 @@ def _current_actor() -> str | None: return configured.strip() try: - from copaw.config.config import load_agent_config - - agent_config = load_agent_config("default") - channels = _read_config_value(agent_config, "channels") or {} - matrix_cfg = _read_config_value(channels, "matrix") or {} - user_id = _read_config_value(matrix_cfg, "user_id", "userId") - return str(user_id).strip() if user_id else None + # Read agent.json directly (works in both copaw and qwenpaw venvs + # without importing either framework's config module). + working_dir = ( + os.getenv("COPAW_WORKING_DIR") + or os.getenv("QWENPAW_WORKING_DIR") + ) + if working_dir: + agent_json = Path(working_dir) / "workspaces" / "default" / "agent.json" + with open(agent_json, "r", encoding="utf-8") as f: + data = json.load(f) + matrix_cfg = (data.get("channels") or {}).get("matrix") or {} + user_id = matrix_cfg.get("user_id") or matrix_cfg.get("userId") + if user_id: + return str(user_id).strip() except Exception: - return None + pass + + return None def _read_config_value(obj: Any, *names: str) -> Any: From 46663c8f8d33134e259fa880714223161494183b Mon Sep 17 00:00:00 2001 From: LUOSENGWA <1600967865@qq.com> Date: Tue, 28 Jul 2026 14:49:09 +0000 Subject: [PATCH 3/9] fix: prefer qwenpaw import over legacy copaw name copaw is the predecessor of qwenpaw (renamed package). In the qwenpaw 2.0 venv the copaw package does not exist, so the try/except in _resolve_copaw_working_dir() should attempt qwenpaw first. --- copaw/src/copaw_worker/hooks/tools/message.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/copaw/src/copaw_worker/hooks/tools/message.py b/copaw/src/copaw_worker/hooks/tools/message.py index b43f44a51..ddb74238c 100644 --- a/copaw/src/copaw_worker/hooks/tools/message.py +++ b/copaw/src/copaw_worker/hooks/tools/message.py @@ -237,10 +237,12 @@ def _resolve_copaw_working_dir() -> Path: if configured: return Path(configured).expanduser().resolve() + # copaw is the legacy name for qwenpaw; the package was renamed. + # In the qwenpaw 2.0 venv only the new name exists. try: - from copaw.constant import WORKING_DIR - except ImportError: from qwenpaw.constant import WORKING_DIR + except ImportError: + from copaw.constant import WORKING_DIR return Path(WORKING_DIR).expanduser().resolve() From 61f262f06ca6f1723fb75694b8b9c038ea17fdc9 Mon Sep 17 00:00:00 2001 From: LUOSENGWA <1600967865@qq.com> Date: Tue, 28 Jul 2026 14:57:21 +0000 Subject: [PATCH 4/9] fix(manager): align Manager with Worker QwenPaw 2.0 patterns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Systematic alignment with PR #1077 Worker Dockerfile and QwenPaw 2.0 conventions: Dockerfile: - CMS observability: loongsuite-instrumentation-copaw → -qwenpaw + add loongsuite-otel-util-genai (matches Worker Dockerfile) start-copaw-manager.sh: - Add QWENPAW_SECRET_DIR, QWENPAW_RUNNING_IN_CONTAINER, QWENPAW_LOG_LEVEL env vars (matches Worker entrypoint) - CMS bootstrap: replace python3 heredoc script with direct heredoc (matches Worker), add LOONGSUITE_PYTHON_SITE_BOOTSTRAP_LOG_SUCCESS export - Inject session file privacy policy into AGENTS.md/SOUL.md (matches Worker _ensure_session_file_prompt_policy) - Remove dead PYTHONPATH=/opt/agentteams/copaw/src (path never existed in the image; modules are in site-packages) agent.manager.json: - Move approval_level into running section (matches QwenPaw 2.0 AgentProfileConfig schema, default AUTO) --- changelog/current.md | 2 +- .../copaw_worker/templates/agent.manager.json | 7 +- manager/Dockerfile.copaw | 7 +- manager/scripts/init/start-copaw-manager.sh | 110 +++++++++--------- 4 files changed, 65 insertions(+), 61 deletions(-) diff --git a/changelog/current.md b/changelog/current.md index e97291b0d..38090c8f9 100644 --- a/changelog/current.md +++ b/changelog/current.md @@ -23,7 +23,7 @@ Record image-affecting changes to `manager/`, `worker/`, `copaw/`, `hermes/`, `o **Branding and Compatibility** - **QwenPaw 2.0 runtime compatibility**: Adapt the QwenPaw Worker image, Matrix overlay, and native plugins to QwenPaw 2.0.0.post3 startup and schema contracts. -- **QwenPaw 2.0 Manager runtime**: Migrate the Manager container from copaw 1.0.2 to QwenPaw 2.0.1 with a separate venv to avoid agentscope version conflicts, register projectflow/taskflow/message/filesync tools through a QwenPaw plugin instead of monkey-patching CoPawAgent, replace the physical Matrix channel overlay with the QwenPaw plugin system, and read Matrix credentials directly from agent.json so the manager tools work without importing copaw at runtime. +- **QwenPaw 2.0 Manager runtime**: Migrate the Manager container from copaw 1.0.2 to QwenPaw 2.0.1 with a separate venv to avoid agentscope version conflicts, register projectflow/taskflow/message/filesync tools through a QwenPaw plugin instead of monkey-patching CoPawAgent, replace the physical Matrix channel overlay with the QwenPaw plugin system, read Matrix credentials directly from agent.json so the manager tools work without importing copaw at runtime, align CMS observability packages and env vars with the Worker image, inject session-file privacy policy into prompt files, set approval_level=AUTO in the agent template, and remove dead PYTHONPATH entries. - **Complete AgentTeams runtime rename**: Rename installer and Helm entrypoints, the controller Go module and CLI, and container filesystem paths to AgentTeams while preserving thin compatibility aliases and upgrade migration for existing HiClaw installations. ([3121f5f](https://github.com/agentscope-ai/AgentTeams/commit/3121f5f)) - **Hard-cut AgentTeams naming**: Remove retired-brand installer wrappers, environment fallbacks, CLI aliases, Helm naming branches, runtime path migrations, and active source paths so fresh AgentTeams deployments use one canonical contract end to end. ([d20e606](https://github.com/agentscope-ai/AgentTeams/commit/d20e606617edefbbc42c28c1201c5629fa73fd88)) - **Hard-cut Team and Worker resources**: Make Worker CRs the sole owners of runtime configuration and lifecycle, make Team CRs reference existing Workers through `spec.workerMembers`, and remove inline-member, registry, migration, and dependent-script compatibility paths. ([b3cf360](https://github.com/agentscope-ai/AgentTeams/commit/b3cf360)) diff --git a/copaw/src/copaw_worker/templates/agent.manager.json b/copaw/src/copaw_worker/templates/agent.manager.json index 19eb48d4a..7bbce416c 100644 --- a/copaw/src/copaw_worker/templates/agent.manager.json +++ b/copaw/src/copaw_worker/templates/agent.manager.json @@ -8,6 +8,10 @@ "PROFILE.md", "TOOLS.md" ], + "running": { + "max_iters": 200, + "approval_level": "AUTO" + }, "heartbeat": { "enabled": true, "every": "30m" @@ -25,8 +29,5 @@ "group_allow_from": [], "groups": {} } - }, - "running": { - "max_iters": 200 } } diff --git a/manager/Dockerfile.copaw b/manager/Dockerfile.copaw index f1a022d6e..d31dee07e 100644 --- a/manager/Dockerfile.copaw +++ b/manager/Dockerfile.copaw @@ -72,15 +72,18 @@ RUN pip install --no-cache-dir \ "copaw==${COPAW_VERSION}" \ "matrix-nio[e2e]>=0.24.0" -# ---- CoPaw CMS Plugin (observability) ---- +# ---- CMS Observability Plugin ---- +# Aligned with qwenpaw Worker Dockerfile: instrumentation-qwenpaw (not -copaw) +# + loongsuite-otel-util-genai for GenAI semantic conventions. RUN pip install --no-cache-dir \ -i "${PIP_INDEX_URL}" \ --trusted-host "$(echo ${PIP_INDEX_URL} | sed 's|https\?://||;s|/.*||')" \ "wrapt<2.0" \ loongsuite-site-bootstrap \ loongsuite-distro \ + loongsuite-otel-util-genai \ opentelemetry-exporter-otlp \ - loongsuite-instrumentation-copaw \ + loongsuite-instrumentation-qwenpaw \ loongsuite-instrumentation-agentscope # ---- CoPaw worker bridge module (for config conversion) ---- diff --git a/manager/scripts/init/start-copaw-manager.sh b/manager/scripts/init/start-copaw-manager.sh index 59cdfd0a4..826cf9882 100644 --- a/manager/scripts/init/start-copaw-manager.sh +++ b/manager/scripts/init/start-copaw-manager.sh @@ -1,9 +1,9 @@ #!/bin/bash -# start-copaw-manager.sh - Start Manager Agent with CoPaw runtime +# start-copaw-manager.sh - Start Manager Agent with QwenPaw 2.0 runtime # Called by start-manager-agent.sh when AGENTTEAMS_MANAGER_RUNTIME=copaw # -# This script converts an OpenClaw-style workspace to a CoPaw-style workspace -# and then launches the CoPaw application. +# This script converts an OpenClaw-style workspace to a QwenPaw-style workspace +# and then launches the QwenPaw application. source /opt/agentteams/scripts/lib/agentteams-env.sh @@ -46,8 +46,7 @@ if [ -f "${COPAW_WORKING_DIR}/config.json" ]; then fi log "Bridging openclaw.json -> CoPaw config (manager)..." -PYTHONPATH="/opt/agentteams/copaw/src:${PYTHONPATH:-}" \ - /opt/copaw-venv/bin/python3 -m copaw_worker.bridge \ +/opt/copaw-venv/bin/python3 -m copaw_worker.bridge \ --profile manager \ --openclaw-json "${OPENCLAW_JSON}" \ --working-dir "${COPAW_WORKING_DIR}" @@ -95,7 +94,26 @@ if [ -d "${OPENCLAW_WORKSPACE}/skills" ]; then fi # ============================================================ -# 5. DM room detection and auto-reply config (patches agent.json directly) +# 5. Inject session file privacy policy into prompt files +# ============================================================ +# Aligned with qwenpaw Worker (_ensure_session_file_prompt_policy): +# prevents the agent from reading/exposing files under sessions/. +SESSION_FILE_POLICY="Do not read, list, grep, glob, summarize, copy, or expose files under sessions/. +Session files are runtime-private state and may contain private conversation history. +This rule applies to all channels, users, and sessions, not only DingTalk." +SESSION_FILE_POLICY_MARKER="Session files are runtime-private state" +for _pf in AGENTS.md SOUL.md; do + _target="${WORKSPACE_DIR}/${_pf}" + if [ -f "${_target}" ]; then + if ! grep -q "${SESSION_FILE_POLICY_MARKER}" "${_target}" 2>/dev/null; then + printf '\n%s\n' "${SESSION_FILE_POLICY}" >> "${_target}" + log " Injected session file policy into ${_pf}" + fi + fi +done + +# ============================================================ +# 6. DM room detection and auto-reply config (patches agent.json directly) # ============================================================ # nio room.users is always 0 after token restore, so all rooms are treated as # "group" (requireMention=true by default). We detect actual DM rooms via @@ -106,7 +124,7 @@ fi log "Detecting DM rooms for auto-reply config..." AGENT_JSON="${WORKSPACE_DIR}/agent.json" if [ ! -f "${AGENT_JSON}" ]; then - log "ERROR: agent.json not found at ${AGENT_JSON} (bridge step must have failed)" + log "ERROR: agent.json not found at ${AGENT_JSON} (bridge steps must have failed)" exit 1 fi MANAGER_MATRIX_TOKEN_VAL=$(jq -r '.channels.matrix.access_token // ""' "${AGENT_JSON}") @@ -155,54 +173,36 @@ jq --slurpfile dm_rooms "${DM_ROOMS_FILE}" \ rm -f "${DM_ROOMS_FILE}" "${DM_ROOMS_FILE}.tmp" # ============================================================ -# 8. Configure CoPaw CMS plugin (LoongSuite observability) +# 7. Configure CMS observability plugin (LoongSuite) # ============================================================ +# Aligned with qwenpaw Worker entrypoint: heredoc + env exports. CMS_TRACES_ENABLED="$(echo "${AGENTTEAMS_CMS_TRACES_ENABLED:-false}" | tr '[:upper:]' '[:lower:]')" if [ "${CMS_TRACES_ENABLED}" = "true" ]; then - log "Configuring CoPaw CMS plugin..." - - # Create bootstrap config directory - BOOTSTRAP_CONFIG_DIR="${HOME}/.loongsuite" - mkdir -p "${BOOTSTRAP_CONFIG_DIR}" - BOOTSTRAP_CONFIG="${BOOTSTRAP_CONFIG_DIR}/bootstrap-config.json" - - # Generate bootstrap-config.json - python3 - "${BOOTSTRAP_CONFIG}" <<'PYEOF' -import json -import sys -import os -from pathlib import Path - -cfg_path = Path(sys.argv[1]) -endpoint = os.getenv("AGENTTEAMS_CMS_ENDPOINT", "") -license_key = os.getenv("AGENTTEAMS_CMS_LICENSE_KEY", "") -arms_project = os.getenv("AGENTTEAMS_CMS_PROJECT", "") -cms_workspace = os.getenv("AGENTTEAMS_CMS_WORKSPACE", "") -service_name = os.getenv("AGENTTEAMS_CMS_SERVICE_NAME", "agentteams-manager") -protocol = "http/protobuf" # Default OTLP protocol - -config = { - "OTEL_EXPORTER_OTLP_ENDPOINT": endpoint, - "OTEL_EXPORTER_OTLP_PROTOCOL": protocol, - "OTEL_EXPORTER_OTLP_HEADERS": f"x-arms-license-key={license_key},x-arms-project={arms_project},x-cms-workspace={cms_workspace}", - "OTEL_SERVICE_NAME": service_name, - "OTEL_SEMCONV_STABILITY_OPT_IN": "http,gen_ai_latest_experimental", - "OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT": "SPAN_AND_EVENT", - "LOONGSUITE_PYTHON_SITE_BOOTSTRAP": "true", + log "Configuring CMS observability plugin..." + + LOONGSUITE_DIR="${HOME}/.loongsuite" + mkdir -p "${LOONGSUITE_DIR}" + + cat > "${LOONGSUITE_DIR}/bootstrap-config.json" </dev/null | awk '{print $1}') @@ -211,8 +211,7 @@ fi _curr_hash=$(md5sum "${OPENCLAW_JSON}" 2>/dev/null | awk '{print $1}') if [ -n "${_curr_hash}" ] && [ "${_curr_hash}" != "${_prev_hash}" ]; then log "openclaw.json changed, re-bridging..." - _bridge_out=$(PYTHONPATH="/opt/agentteams/copaw/src:${PYTHONPATH:-}" \ - /opt/copaw-venv/bin/python3 -m copaw_worker.bridge \ + _bridge_out=$(/opt/copaw-venv/bin/python3 -m copaw_worker.bridge \ --profile manager \ --openclaw-json "${OPENCLAW_JSON}" \ --working-dir "${COPAW_WORKING_DIR}" 2>&1) @@ -228,19 +227,20 @@ fi log "openclaw.json watcher started (PID: $!)" # ============================================================ -# 10. Launch CoPaw Manager (app mode with hot-reload) +# 9. Launch QwenPaw 2.0 Manager (app mode) # ============================================================ +# copaw is the legacy name for qwenpaw; QwenPaw 2.0 treats ~/.copaw as +# a legacy installation and auto-uses it. We set QWENPAW_WORKING_DIR +# explicitly to be unambiguous. export COPAW_WORKING_DIR="${COPAW_WORKING_DIR}" -# QWENPAW_WORKING_DIR points to the same directory as COPAW_WORKING_DIR (.copaw/) -# qwenpaw reads config.json + agent.json from this path export QWENPAW_WORKING_DIR="${COPAW_WORKING_DIR}" +export QWENPAW_SECRET_DIR="${QWENPAW_SECRET_DIR:-${COPAW_WORKING_DIR}.secret}" +export QWENPAW_RUNNING_IN_CONTAINER=true +export QWENPAW_LOG_LEVEL="${COPAW_LOG_LEVEL:-info}" log "Starting QwenPaw 2.0 Manager (app mode)..." COPAW_LOG_LEVEL="${COPAW_LOG_LEVEL:-info}" export COPAW_LOG_LEVEL -# Set PYTHONPATH to include copaw_worker module -export PYTHONPATH="/opt/agentteams/copaw/src:${PYTHONPATH:-}" - # run_copaw_app.py starts qwenpaw app (tools registered via agentteams-manager-tools plugin) exec python3 -m copaw_worker.run_copaw_app app --host 0.0.0.0 --port 18799 From 9adf2dfb545021a95f0c746312736b94b5f4bced Mon Sep 17 00:00:00 2001 From: LUOSENGWA <1600967865@qq.com> Date: Tue, 28 Jul 2026 15:09:43 +0000 Subject: [PATCH 5/9] fix(manager): disable QA Agent + fix approval_level placement QA Agent: Worker disables QwenPaw_QA_Agent_0.2 via API client. Manager runs QwenPaw in-process with no API client, so set enabled=false in config.json agents.profiles before startup. QwenPaw's ensure_qa_agent_exists() skips agents already in profiles, so our preset is preserved. start_all_configured_agents() skips enabled=false agents. approval_level: Move from running{} to top-level in agent.manager.json. QwenPaw 2.0 AgentProfileConfig.approval_level is a top-level field, not inside AgentsRunningConfig (which has extra='ignore' and would silently drop it). --- .../src/copaw_worker/templates/agent.manager.json | 4 ++-- manager/scripts/init/start-copaw-manager.sh | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/copaw/src/copaw_worker/templates/agent.manager.json b/copaw/src/copaw_worker/templates/agent.manager.json index 7bbce416c..fe31a4de9 100644 --- a/copaw/src/copaw_worker/templates/agent.manager.json +++ b/copaw/src/copaw_worker/templates/agent.manager.json @@ -2,6 +2,7 @@ "id": "default", "name": "Manager", "language": "zh", + "approval_level": "AUTO", "system_prompt_files": [ "AGENTS.md", "SOUL.md", @@ -9,8 +10,7 @@ "TOOLS.md" ], "running": { - "max_iters": 200, - "approval_level": "AUTO" + "max_iters": 200 }, "heartbeat": { "enabled": true, diff --git a/manager/scripts/init/start-copaw-manager.sh b/manager/scripts/init/start-copaw-manager.sh index 826cf9882..2902a25e9 100644 --- a/manager/scripts/init/start-copaw-manager.sh +++ b/manager/scripts/init/start-copaw-manager.sh @@ -172,6 +172,20 @@ jq --slurpfile dm_rooms "${DM_ROOMS_FILE}" \ "${AGENT_JSON}" > "${AGENT_JSON}.tmp" && mv "${AGENT_JSON}.tmp" "${AGENT_JSON}" rm -f "${DM_ROOMS_FILE}" "${DM_ROOMS_FILE}.tmp" +# ============================================================ +# 7. Disable built-in QA Agent (QwenPaw_QA_Agent_0.2) +# ============================================================ +# Worker does this via api_client.disable_agent_if_present(). +# Manager runs QwenPaw in-process (no API client), so we set +# enabled=false in config.json's agents.profiles before startup. +# QwenPaw 2.0 start_all_configured_agents() skips enabled=false agents. +CONFIG_JSON="${COPAW_WORKING_DIR}/config.json" +if [ -f "${CONFIG_JSON}" ]; then + jq '.agents.profiles["QwenPaw_QA_Agent_0.2"].enabled = false' \ + "${CONFIG_JSON}" > "${CONFIG_JSON}.tmp" && mv "${CONFIG_JSON}.tmp" "${CONFIG_JSON}" + log "Disabled built-in QA Agent in config.json" +fi + # ============================================================ # 7. Configure CMS observability plugin (LoongSuite) # ============================================================ From d09ce8c364fe0beeb8d4b6203f4bd6afea97093c Mon Sep 17 00:00:00 2001 From: LUOSENGWA <1600967865@qq.com> Date: Tue, 28 Jul 2026 15:14:04 +0000 Subject: [PATCH 6/9] fix(manager): bridge YOLO mode to QwenPaw approval_level=OFF OpenClaw Manager sets tools.exec.ask=off for YOLO mode. QwenPaw 2.0's equivalent is approval_level=OFF (short-circuits the governance pipeline to ALLOW-all). start-manager-agent.sh promotes the yolo-mode marker file to AGENTTEAMS_YOLO=1 before calling this script; we translate that to agent.json approval_level=OFF here. --- manager/scripts/init/start-copaw-manager.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/manager/scripts/init/start-copaw-manager.sh b/manager/scripts/init/start-copaw-manager.sh index 2902a25e9..d6c4b110b 100644 --- a/manager/scripts/init/start-copaw-manager.sh +++ b/manager/scripts/init/start-copaw-manager.sh @@ -252,6 +252,16 @@ export QWENPAW_SECRET_DIR="${QWENPAW_SECRET_DIR:-${COPAW_WORKING_DIR}.secret}" export QWENPAW_RUNNING_IN_CONTAINER=true export QWENPAW_LOG_LEVEL="${COPAW_LOG_LEVEL:-info}" +# YOLO mode: AGENTTEAMS_YOLO=1 → set approval_level=OFF in agent.json +# (QwenPaw 2.0 equivalent of OpenClaw's tools.exec.ask=off). +# start-manager-agent.sh promotes the yolo-mode marker file to +# AGENTTEAMS_YOLO=1 before calling this script. +if [ "${AGENTTEAMS_YOLO:-}" = "1" ] && [ -f "${AGENT_JSON}" ]; then + jq '.approval_level = "OFF"' "${AGENT_JSON}" > "${AGENT_JSON}.tmp" \ + && mv "${AGENT_JSON}.tmp" "${AGENT_JSON}" + log "YOLO mode: approval_level set to OFF" +fi + log "Starting QwenPaw 2.0 Manager (app mode)..." COPAW_LOG_LEVEL="${COPAW_LOG_LEVEL:-info}" export COPAW_LOG_LEVEL From a7f6f2c2d56abb1e5c9084ee94e549c50477dfa5 Mon Sep 17 00:00:00 2001 From: LUOSENGWA <1600967865@qq.com> Date: Tue, 28 Jul 2026 15:21:50 +0000 Subject: [PATCH 7/9] refactor: rename start-copaw-manager.sh to start-qwenpaw-manager.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After PR #1095 the Manager runs QwenPaw 2.0, not copaw. The script name should reflect reality. start-manager-agent.sh now accepts both 'copaw' (legacy runtime identifier used by controller/installer/CI) and 'qwenpaw' (forward- looking name). Both map to the same start-qwenpaw-manager.sh. Controller, installer, CI, Makefile, and Docker image name still use 'copaw' as the runtime identifier — changing those is a separate PR (the controller already defines RuntimeQwenPaw='qwenpaw' for Workers; adding a qwenpaw Manager runtime requires new config fields, image selection logic, and CI matrix entries). --- changelog/current.md | 2 +- manager/Dockerfile.copaw | 2 +- manager/scripts/init/start-manager-agent.sh | 17 ++++++++++------- ...opaw-manager.sh => start-qwenpaw-manager.sh} | 4 ++-- 4 files changed, 14 insertions(+), 11 deletions(-) rename manager/scripts/init/{start-copaw-manager.sh => start-qwenpaw-manager.sh} (99%) diff --git a/changelog/current.md b/changelog/current.md index 38090c8f9..4a0ebf241 100644 --- a/changelog/current.md +++ b/changelog/current.md @@ -23,7 +23,7 @@ Record image-affecting changes to `manager/`, `worker/`, `copaw/`, `hermes/`, `o **Branding and Compatibility** - **QwenPaw 2.0 runtime compatibility**: Adapt the QwenPaw Worker image, Matrix overlay, and native plugins to QwenPaw 2.0.0.post3 startup and schema contracts. -- **QwenPaw 2.0 Manager runtime**: Migrate the Manager container from copaw 1.0.2 to QwenPaw 2.0.1 with a separate venv to avoid agentscope version conflicts, register projectflow/taskflow/message/filesync tools through a QwenPaw plugin instead of monkey-patching CoPawAgent, replace the physical Matrix channel overlay with the QwenPaw plugin system, read Matrix credentials directly from agent.json so the manager tools work without importing copaw at runtime, align CMS observability packages and env vars with the Worker image, inject session-file privacy policy into prompt files, set approval_level=AUTO in the agent template, and remove dead PYTHONPATH entries. +- **QwenPaw 2.0 Manager runtime**: Migrate the Manager container from copaw 1.0.2 to QwenPaw 2.0.1 with a separate venv to avoid agentscope version conflicts, register projectflow/taskflow/message/filesync tools through a QwenPaw plugin instead of monkey-patching CoPawAgent, replace the physical Matrix channel overlay with the QwenPaw plugin system, read Matrix credentials directly from agent.json so the manager tools work without importing copaw at runtime, align CMS observability packages and env vars with the Worker image, inject session-file privacy policy into prompt files, set approval_level=AUTO in the agent template, bridge YOLO mode to QwenPaw approval_level=OFF, disable the built-in QA Agent, rename start-copaw-manager.sh to start-qwenpaw-manager.sh with dual copaw|qwenpaw runtime value support, and remove dead PYTHONPATH entries. - **Complete AgentTeams runtime rename**: Rename installer and Helm entrypoints, the controller Go module and CLI, and container filesystem paths to AgentTeams while preserving thin compatibility aliases and upgrade migration for existing HiClaw installations. ([3121f5f](https://github.com/agentscope-ai/AgentTeams/commit/3121f5f)) - **Hard-cut AgentTeams naming**: Remove retired-brand installer wrappers, environment fallbacks, CLI aliases, Helm naming branches, runtime path migrations, and active source paths so fresh AgentTeams deployments use one canonical contract end to end. ([d20e606](https://github.com/agentscope-ai/AgentTeams/commit/d20e606617edefbbc42c28c1201c5629fa73fd88)) - **Hard-cut Team and Worker resources**: Make Worker CRs the sole owners of runtime configuration and lifecycle, make Team CRs reference existing Workers through `spec.workerMembers`, and remove inline-member, registry, migration, and dependent-script compatibility paths. ([b3cf360](https://github.com/agentscope-ai/AgentTeams/commit/b3cf360)) diff --git a/manager/Dockerfile.copaw b/manager/Dockerfile.copaw index d31dee07e..504ebbab1 100644 --- a/manager/Dockerfile.copaw +++ b/manager/Dockerfile.copaw @@ -135,7 +135,7 @@ COPY plugins/agentteams-matrix-channel/ /opt/agentteams/plugins/agentteams-matri COPY plugins/agentteams-manager-tools/ /opt/agentteams/plugins/agentteams-manager-tools/ # Copy plugins into QwenPaw's plugin discovery path. -# WORKING_DIR = ~/.copaw (set by start-copaw-manager.sh at runtime). +# WORKING_DIR = ~/.copaw (set by start-qwenpaw-manager.sh at runtime). # cp -a (not ln -sfn): QwenPaw PluginLoader._load_plugin_from_path_unlocked # resolves source_path vs target_dir — symlinks cause rmtree of the real dir # followed by copytree from the now-dead symlink target (crash). diff --git a/manager/scripts/init/start-manager-agent.sh b/manager/scripts/init/start-manager-agent.sh index 21d1ff5dc..3f208096c 100755 --- a/manager/scripts/init/start-manager-agent.sh +++ b/manager/scripts/init/start-manager-agent.sh @@ -6,8 +6,11 @@ # # Runtime selection: # AGENTTEAMS_MANAGER_RUNTIME=openclaw (default) - OpenClaw gateway mode -# AGENTTEAMS_MANAGER_RUNTIME=copaw - CoPaw workspace mode -# (hermes runtime is supported for Workers only; Managers run openclaw or copaw.) +# AGENTTEAMS_MANAGER_RUNTIME=copaw|qwenpaw - QwenPaw workspace mode +# "copaw" is the legacy runtime identifier still used by the controller, +# installer, and CI; "qwenpaw" is the forward-looking name. Both map to +# the same QwenPaw 2.0 startup script. +# (hermes runtime is supported for Workers only.) source /opt/agentteams/scripts/lib/agentteams-env.sh @@ -16,8 +19,8 @@ source /opt/agentteams/scripts/lib/agentteams-env.sh # ============================================================ MANAGER_RUNTIME="${AGENTTEAMS_MANAGER_RUNTIME:-openclaw}" case "${MANAGER_RUNTIME}" in - copaw) - log "Manager runtime: CoPaw (Python workspace)" + copaw|qwenpaw) + log "Manager runtime: QwenPaw (Python workspace, runtime=${MANAGER_RUNTIME})" ;; *) log "Manager runtime: OpenClaw (Node.js gateway)" @@ -1162,9 +1165,9 @@ fi # ============================================================ # Runtime-specific startup # ============================================================ -if [ "${MANAGER_RUNTIME}" = "copaw" ]; then - # Delegate to CoPaw startup script - exec /opt/agentteams/scripts/init/start-copaw-manager.sh +if [ "${MANAGER_RUNTIME}" = "copaw" ] || [ "${MANAGER_RUNTIME}" = "qwenpaw" ]; then + # Delegate to QwenPaw startup script + exec /opt/agentteams/scripts/init/start-qwenpaw-manager.sh else # ── OpenClaw Runtime ───────────────────────────────────────────────────── log "Starting OpenClaw Manager..." diff --git a/manager/scripts/init/start-copaw-manager.sh b/manager/scripts/init/start-qwenpaw-manager.sh similarity index 99% rename from manager/scripts/init/start-copaw-manager.sh rename to manager/scripts/init/start-qwenpaw-manager.sh index d6c4b110b..460292b76 100644 --- a/manager/scripts/init/start-copaw-manager.sh +++ b/manager/scripts/init/start-qwenpaw-manager.sh @@ -1,6 +1,6 @@ #!/bin/bash -# start-copaw-manager.sh - Start Manager Agent with QwenPaw 2.0 runtime -# Called by start-manager-agent.sh when AGENTTEAMS_MANAGER_RUNTIME=copaw +# start-qwenpaw-manager.sh - Start Manager Agent with QwenPaw 2.0 runtime +# Called by start-manager-agent.sh when AGENTTEAMS_MANAGER_RUNTIME=copaw|qwenpaw # # This script converts an OpenClaw-style workspace to a QwenPaw-style workspace # and then launches the QwenPaw application. From 90a45c5686bca6df5a413b4b06ca21ef4f7078ce Mon Sep 17 00:00:00 2001 From: LUOSENGWA <1600967865@qq.com> Date: Tue, 28 Jul 2026 16:13:53 +0000 Subject: [PATCH 8/9] fix(manager): correct pgrep, plugin volume mount, CMS venv, QA agent disable Six issues found during deep audit with CI script and PR #1077 cross-reference: 1. pgrep pattern: \|qwenpaw app was a literal pipe in ERE, breaking the original copaw pattern. Manager process cmdline is still 'python3 -m copaw_worker.run_copaw_app app' (runpy.run_module does not change /proc/cmdline), so the original #1077 pattern works. Reverted to 'copaw(_worker\.run_copaw_app)? app'. 2. Plugins invisible at runtime: Dockerfile copied plugins to /root/manager-workspace/.copaw/plugins/ (build-time), but the install script mounts a host volume at /root/manager-workspace, hiding build-time files. Now stores plugins in image-local /opt/agentteams/plugins/ and copies them at runtime in start-qwenpaw-manager.sh (mirrors Worker's _prepare_builtin_plugin). 3. CMS packages in wrong venv: pip install ran while PATH pointed to copaw-venv, but Manager runs from qwenpaw venv. Moved CMS install after qwenpaw venv creation with /opt/venv/qwenpaw/bin/pip. 4. QA Agent disable silently fails: jq wrote {"enabled": false} but AgentProfileRef requires id + workspace_dir. Pydantic validation stripped the incomplete profile, then ensure_qa_agent_exists() recreated it with enabled=true. Now writes a complete profile. 5. taskflow._current_actor() working dir resolution inconsistent with message.py: only checked env vars, no qwenpaw.constant fallback. Added _resolve_working_dir() mirroring message.py's logic. 6. plugin.py docstring stale: claimed taskflow/message still import copaw.config.config, but commit 974cdf6c already removed that. plugin.json type changed from 'general' to 'tool'. --- .../src/copaw_worker/hooks/tools/taskflow.py | 32 +++++++++++--- manager/Dockerfile.copaw | 44 ++++++++----------- manager/scripts/init/start-qwenpaw-manager.sh | 37 ++++++++++++++-- plugins/agentteams-manager-tools/plugin.json | 2 +- plugins/agentteams-manager-tools/plugin.py | 7 ++- tests/lib/test-helpers.sh | 2 +- tests/test-01-manager-boot.sh | 2 +- 7 files changed, 85 insertions(+), 41 deletions(-) diff --git a/copaw/src/copaw_worker/hooks/tools/taskflow.py b/copaw/src/copaw_worker/hooks/tools/taskflow.py index 0fa61aaf6..ee2950b06 100644 --- a/copaw/src/copaw_worker/hooks/tools/taskflow.py +++ b/copaw/src/copaw_worker/hooks/tools/taskflow.py @@ -153,12 +153,9 @@ def _current_actor() -> str | None: try: # Read agent.json directly (works in both copaw and qwenpaw venvs # without importing either framework's config module). - working_dir = ( - os.getenv("COPAW_WORKING_DIR") - or os.getenv("QWENPAW_WORKING_DIR") - ) + working_dir = _resolve_working_dir() if working_dir: - agent_json = Path(working_dir) / "workspaces" / "default" / "agent.json" + agent_json = working_dir / "workspaces" / "default" / "agent.json" with open(agent_json, "r", encoding="utf-8") as f: data = json.load(f) matrix_cfg = (data.get("channels") or {}).get("matrix") or {} @@ -171,6 +168,31 @@ def _current_actor() -> str | None: return None +def _resolve_working_dir() -> Path | None: + """Resolve the QwenPaw/CoPaw working directory. + + Mirrors message.py's _resolve_copaw_working_dir() so that both tools + use the same path resolution logic, including the qwenpaw.constant + fallback when env vars are not set. + """ + configured = ( + os.getenv("COPAW_WORKING_DIR") + or os.getenv("QWENPAW_WORKING_DIR") + ) + if configured: + return Path(configured).expanduser().resolve() + + try: + from qwenpaw.constant import WORKING_DIR + except ImportError: + try: + from copaw.constant import WORKING_DIR + except ImportError: + return None + + return Path(WORKING_DIR).expanduser().resolve() + + def _read_config_value(obj: Any, *names: str) -> Any: for name in names: if isinstance(obj, dict) and name in obj: diff --git a/manager/Dockerfile.copaw b/manager/Dockerfile.copaw index 504ebbab1..a6f67f71e 100644 --- a/manager/Dockerfile.copaw +++ b/manager/Dockerfile.copaw @@ -72,20 +72,6 @@ RUN pip install --no-cache-dir \ "copaw==${COPAW_VERSION}" \ "matrix-nio[e2e]>=0.24.0" -# ---- CMS Observability Plugin ---- -# Aligned with qwenpaw Worker Dockerfile: instrumentation-qwenpaw (not -copaw) -# + loongsuite-otel-util-genai for GenAI semantic conventions. -RUN pip install --no-cache-dir \ - -i "${PIP_INDEX_URL}" \ - --trusted-host "$(echo ${PIP_INDEX_URL} | sed 's|https\?://||;s|/.*||')" \ - "wrapt<2.0" \ - loongsuite-site-bootstrap \ - loongsuite-distro \ - loongsuite-otel-util-genai \ - opentelemetry-exporter-otlp \ - loongsuite-instrumentation-qwenpaw \ - loongsuite-instrumentation-agentscope - # ---- CoPaw worker bridge module (for config conversion) ---- # Stage the copaw-worker package metadata for dependency resolution COPY copaw/pyproject.toml copaw/README.md /tmp/copaw-worker/ @@ -124,6 +110,22 @@ RUN python3 -m venv /opt/venv/qwenpaw \ RUN cp -a /opt/copaw-venv/lib/python3.11/site-packages/copaw_worker \ /opt/venv/qwenpaw/lib/python3.11/site-packages/ +# ---- CMS Observability Plugin (in qwenpaw venv) ---- +# Aligned with qwenpaw Worker Dockerfile: installed into the runtime venv +# (qwenpaw) so that loongsuite-site-bootstrap is active when the Manager +# process starts. instrumentation-qwenpaw (not -copaw) + +# loongsuite-otel-util-genai for GenAI semantic conventions. +RUN /opt/venv/qwenpaw/bin/pip install --no-cache-dir \ + -i "${PIP_INDEX_URL}" \ + --trusted-host "$(echo ${PIP_INDEX_URL} | sed 's|https\?://||;s|/.*||')" \ + "wrapt<2.0" \ + loongsuite-site-bootstrap \ + loongsuite-distro \ + loongsuite-otel-util-genai \ + opentelemetry-exporter-otlp \ + loongsuite-instrumentation-qwenpaw \ + loongsuite-instrumentation-agentscope + # qwenpaw CLI on PATH RUN ln -sf /opt/venv/qwenpaw/bin/qwenpaw /usr/local/bin/qwenpaw @@ -131,20 +133,12 @@ RUN ln -sf /opt/venv/qwenpaw/bin/qwenpaw /usr/local/bin/qwenpaw ENV PATH="/opt/venv/qwenpaw/bin:/opt/copaw-venv/bin:${PATH}" # AgentTeams plugins: Matrix channel + Manager tools +# Stored in image-local path (/opt/agentteams/plugins/). At runtime, +# start-qwenpaw-manager.sh copies them into the working dir's plugins/ +# directory because /root/manager-workspace is a host-mounted volume. COPY plugins/agentteams-matrix-channel/ /opt/agentteams/plugins/agentteams-matrix-channel/ COPY plugins/agentteams-manager-tools/ /opt/agentteams/plugins/agentteams-manager-tools/ -# Copy plugins into QwenPaw's plugin discovery path. -# WORKING_DIR = ~/.copaw (set by start-qwenpaw-manager.sh at runtime). -# cp -a (not ln -sfn): QwenPaw PluginLoader._load_plugin_from_path_unlocked -# resolves source_path vs target_dir — symlinks cause rmtree of the real dir -# followed by copytree from the now-dead symlink target (crash). -RUN mkdir -p /root/manager-workspace/.copaw/plugins \ - && cp -a /opt/agentteams/plugins/agentteams-matrix-channel \ - /root/manager-workspace/.copaw/plugins/agentteams-matrix-channel \ - && cp -a /opt/agentteams/plugins/agentteams-manager-tools \ - /root/manager-workspace/.copaw/plugins/agentteams-manager-tools - # ---- Copy Manager agent definitions ---- COPY manager/agent/ /opt/agentteams/agent/ COPY manager/configs/ /opt/agentteams/configs/ diff --git a/manager/scripts/init/start-qwenpaw-manager.sh b/manager/scripts/init/start-qwenpaw-manager.sh index 460292b76..d0757fb1b 100644 --- a/manager/scripts/init/start-qwenpaw-manager.sh +++ b/manager/scripts/init/start-qwenpaw-manager.sh @@ -181,13 +181,23 @@ rm -f "${DM_ROOMS_FILE}" "${DM_ROOMS_FILE}.tmp" # QwenPaw 2.0 start_all_configured_agents() skips enabled=false agents. CONFIG_JSON="${COPAW_WORKING_DIR}/config.json" if [ -f "${CONFIG_JSON}" ]; then - jq '.agents.profiles["QwenPaw_QA_Agent_0.2"].enabled = false' \ + # AgentProfileRef requires id + workspace_dir (both mandatory). + # Writing only {"enabled": false} causes a Pydantic ValidationError + # that _remove_bad_field() strips, then ensure_qa_agent_exists() + # recreates it with enabled=True — defeating the disable. + _QA_WD="${COPAW_WORKING_DIR}/workspaces/QwenPaw_QA_Agent_0.2" + jq --arg wd "${_QA_WD}" \ + '.agents.profiles["QwenPaw_QA_Agent_0.2"] = { + "id": "QwenPaw_QA_Agent_0.2", + "workspace_dir": $wd, + "enabled": false + }' \ "${CONFIG_JSON}" > "${CONFIG_JSON}.tmp" && mv "${CONFIG_JSON}.tmp" "${CONFIG_JSON}" log "Disabled built-in QA Agent in config.json" fi # ============================================================ -# 7. Configure CMS observability plugin (LoongSuite) +# 8. Configure CMS observability plugin (LoongSuite) # ============================================================ # Aligned with qwenpaw Worker entrypoint: heredoc + env exports. CMS_TRACES_ENABLED="$(echo "${AGENTTEAMS_CMS_TRACES_ENABLED:-false}" | tr '[:upper:]' '[:lower:]')" @@ -216,7 +226,7 @@ EOF fi # ============================================================ -# 8. Background: watch openclaw.json for changes and re-bridge +# 9. Background: watch openclaw.json for changes and re-bridge # ============================================================ ( _prev_hash=$(md5sum "${OPENCLAW_JSON}" 2>/dev/null | awk '{print $1}') @@ -241,7 +251,26 @@ fi log "openclaw.json watcher started (PID: $!)" # ============================================================ -# 9. Launch QwenPaw 2.0 Manager (app mode) +# 10. Copy AgentTeams plugins into working dir +# ============================================================ +# The Dockerfile copies plugins to /opt/agentteams/plugins/ (image-local). +# /root/manager-workspace is a host-mounted volume at runtime, so +# build-time files there are hidden. Copy plugins to the QwenPaw +# working dir's plugins/ directory before startup so PluginLoader +# discovers them. +PLUGINS_TARGET="${COPAW_WORKING_DIR}/plugins" +mkdir -p "${PLUGINS_TARGET}" +for _plugin_src in /opt/agentteams/plugins/*/; do + _plugin_name=$(basename "${_plugin_src}") + if [ -f "${_plugin_src}plugin.json" ]; then + rm -rf "${PLUGINS_TARGET}/${_plugin_name}" + cp -a "${_plugin_src}" "${PLUGINS_TARGET}/${_plugin_name}" + log "Installed plugin: ${_plugin_name}" + fi +done + +# ============================================================ +# 11. Launch QwenPaw 2.0 Manager (app mode) # ============================================================ # copaw is the legacy name for qwenpaw; QwenPaw 2.0 treats ~/.copaw as # a legacy installation and auto-uses it. We set QWENPAW_WORKING_DIR diff --git a/plugins/agentteams-manager-tools/plugin.json b/plugins/agentteams-manager-tools/plugin.json index 41e39af2f..084cd43c4 100644 --- a/plugins/agentteams-manager-tools/plugin.json +++ b/plugins/agentteams-manager-tools/plugin.json @@ -2,7 +2,7 @@ "id": "agentteams-manager-tools", "name": "AgentTeams Manager Tools", "version": "0.1.0", - "type": "general", + "type": "tool", "description": "projectflow, taskflow, message, filesync tools for Manager", "author": "AgentTeams", "entry": { diff --git a/plugins/agentteams-manager-tools/plugin.py b/plugins/agentteams-manager-tools/plugin.py index b62b1646d..d2caba1b9 100644 --- a/plugins/agentteams-manager-tools/plugin.py +++ b/plugins/agentteams-manager-tools/plugin.py @@ -11,10 +11,9 @@ - ``agentscope.tool.ToolResponse`` ✅ - ``copaw_worker.task / sync / hooks.message_filter`` — pure stdlib + agentscope -No dependency on ``copaw`` 1.0.2 at module-import time. Two functions -(``taskflow``, ``message``) contain deferred ``from copaw.config.config -import load_agent_config`` inside specific branches; those branches will -raise ``ImportError`` if hit, but do not affect plugin loading. +No dependency on ``copaw`` 1.0.2 at module-import time. The message and +taskflow tools read Matrix credentials directly from ``agent.json`` instead +of importing ``copaw.config.config``. """ diff --git a/tests/lib/test-helpers.sh b/tests/lib/test-helpers.sh index ebc2dfb9f..9ded23928 100755 --- a/tests/lib/test-helpers.sh +++ b/tests/lib/test-helpers.sh @@ -209,7 +209,7 @@ wait_for_manager_agent_ready() { while [ "${elapsed}" -lt "${timeout}" ]; do case "${manager_runtime}" in copaw) - if docker exec "${agent_container}" pgrep -f "copaw(_worker\\.run_copaw_app)? app\|qwenpaw app" >/dev/null 2>&1 && \ + if docker exec "${agent_container}" pgrep -f "copaw(_worker\\.run_copaw_app)? app" >/dev/null 2>&1 && \ docker exec "${agent_container}" curl -sf http://127.0.0.1:18799/ >/dev/null 2>&1; then runtime_ready=true break diff --git a/tests/test-01-manager-boot.sh b/tests/test-01-manager-boot.sh index 517406bd8..61a5bf4de 100755 --- a/tests/test-01-manager-boot.sh +++ b/tests/test-01-manager-boot.sh @@ -120,7 +120,7 @@ case "${MANAGER_RUNTIME}" in log_fail "CoPaw agent.json valid" fi - if docker exec "${_AGENT_CTR}" pgrep -f "copaw(_worker\\.run_copaw_app)? app\|qwenpaw app" >/dev/null 2>&1; then + if docker exec "${_AGENT_CTR}" pgrep -f "copaw(_worker\\.run_copaw_app)? app" >/dev/null 2>&1; then log_pass "CoPaw process running" else log_fail "CoPaw process running" From 58133f1b96c2a580c1a145719acbed54d1320827 Mon Sep 17 00:00:00 2001 From: LUOSENGWA <1600967865@qq.com> Date: Tue, 28 Jul 2026 16:59:31 +0000 Subject: [PATCH 9/9] fix(manager): inject default profile alongside QA disable to prevent migration overwrite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The QA Agent disable jq only injected agents.profiles['QwenPaw_QA_Agent_0.2'] without the 'default' profile. On first boot, QwenPaw's migrate_legacy_workspace_to_default_agent() sees len(profiles)==1 and 'default' not in profiles → runs legacy migration → replaces config.agents entirely → QA profile lost → ensure_qa_agent_exists() re-creates it with enabled=True, defeating the disable. Fix: inject both 'default' and QA profiles so len(profiles)>=2, which causes the migration to be skipped (multi-agent config detected). --- manager/scripts/init/start-qwenpaw-manager.sh | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/manager/scripts/init/start-qwenpaw-manager.sh b/manager/scripts/init/start-qwenpaw-manager.sh index d0757fb1b..228c0dec1 100644 --- a/manager/scripts/init/start-qwenpaw-manager.sh +++ b/manager/scripts/init/start-qwenpaw-manager.sh @@ -185,13 +185,28 @@ if [ -f "${CONFIG_JSON}" ]; then # Writing only {"enabled": false} causes a Pydantic ValidationError # that _remove_bad_field() strips, then ensure_qa_agent_exists() # recreates it with enabled=True — defeating the disable. + # + # CRITICAL: must also inject the "default" profile alongside QA. + # If profiles contains ONLY the QA entry, QwenPaw's + # migrate_legacy_workspace_to_default_agent() sees len(profiles)==1 + # and "default" not in profiles → runs legacy migration → replaces + # config.agents entirely → QA profile lost → ensure_qa_agent_exists() + # re-creates it with enabled=True. Injecting "default" makes + # len(profiles)>=2 so migration is skipped. + _DEFAULT_WD="${COPAW_WORKING_DIR}/workspaces/default" _QA_WD="${COPAW_WORKING_DIR}/workspaces/QwenPaw_QA_Agent_0.2" - jq --arg wd "${_QA_WD}" \ - '.agents.profiles["QwenPaw_QA_Agent_0.2"] = { - "id": "QwenPaw_QA_Agent_0.2", - "workspace_dir": $wd, - "enabled": false - }' \ + jq --arg wd "${_QA_WD}" --arg dwd "${_DEFAULT_WD}" \ + '.agents.profiles = ((.agents.profiles // {}) + { + "default": { + "id": "default", + "workspace_dir": $dwd + }, + "QwenPaw_QA_Agent_0.2": { + "id": "QwenPaw_QA_Agent_0.2", + "workspace_dir": $wd, + "enabled": false + } + })' \ "${CONFIG_JSON}" > "${CONFIG_JSON}.tmp" && mv "${CONFIG_JSON}.tmp" "${CONFIG_JSON}" log "Disabled built-in QA Agent in config.json" fi