# NODE1 File Tool Sync Runbook ## Scope This runbook documents: - how NODE1 runtime drift was identified and synchronized, - how universal `file_tool` was introduced into the **actual** NODE1 router stack, - how to deploy and rollback safely. ## Canonical Runtime (NODE1) - Host: `144.76.224.179` - Runtime repo: `/opt/microdao-daarion` - Compose: `/opt/microdao-daarion/docker-compose.node1.yml` - Router container: `dagi-router-node1` - Gateway container: `dagi-gateway-node1` - Router API contract: `POST /v1/agents/{agent_id}/infer` (not `/route`) ## Drift Findings (before sync) The laptop had multiple repos; only this repo matches NODE1 architecture: - `/Users/apple/github-projects/microdao-daarion` Critical files were drifted against NODE1 runtime (15 files): - `docker-compose.node1.yml` - `gateway-bot/agent_registry.json` - `gateway-bot/http_api.py` - `gateway-bot/router_client.py` - `gateway-bot/senpai_prompt.txt` - `http_api.py` - `services/router/agent_tools_config.py` - `services/router/main.py` - `services/router/memory_retrieval.py` - `services/router/requirements.txt` - `services/router/router-config.yml` - `services/router/tool_manager.py` - `services/senpai-md-consumer/senpai/md_consumer/main.py` - `services/senpai-md-consumer/senpai/md_consumer/publisher.py` - `services/swapper-service/requirements.txt` ## Sync Procedure (NODE1 -> Laptop) 1. Snapshot and compare hashes: - compute SHA256 for the critical file list on laptop and NODE1. 2. Backup local copies: - `rollback_backups/node1_sync_/...` 3. Copy runtime files from NODE1 to laptop: - `scp root@144.76.224.179:/opt/microdao-daarion/ ...` 4. Verify 1:1 hash match. ## File Tool Implementation Implemented in actual NODE1 stack (`services/router/*` + gateway): ### Added actions - `excel_create` - `excel_update` - `csv_create` - `csv_update` - `json_export` - `yaml_export` - `zip_bundle` - `docx_create` - `docx_update` - `pptx_create` - `pptx_update` - `ods_create` - `ods_update` - `parquet_create` - `parquet_update` - `pdf_merge` - `pdf_split` - `pdf_fill` - `pdf_update` - `djvu_to_pdf` - `djvu_extract_text` - `text_create` - `text_update` - `markdown_create` - `markdown_update` - `xml_export` - `html_export` - `image_create` - `image_edit` - `image_convert` - `image_bundle` - `svg_export` - `svg_to_png` ### Standard output contract For file-producing tool calls, router now propagates: - `file_base64` - `file_name` - `file_mime` - `message` (inside tool result payload) ### Gateway behavior `gateway-bot/http_api.py` now sends Telegram `sendDocument` when file fields are present. ## Changed Files - `services/router/requirements.txt` - `services/router/agent_tools_config.py` - `services/router/tool_manager.py` - `services/router/main.py` - `services/router/Dockerfile` - `gateway-bot/router_client.py` - `gateway-bot/http_api.py` ## Deployment Steps (NODE1) 1. Backup target files on NODE1 before each step. 2. Sync updated files to `/opt/microdao-daarion`. 3. Compile checks: - `python3 -m py_compile services/router/tool_manager.py services/router/main.py services/router/agent_tools_config.py gateway-bot/router_client.py gateway-bot/http_api.py` 4. Rebuild/restart runtime services: - `docker compose -f docker-compose.node1.yml up -d --build --no-deps router gateway` 5. Health checks: - `curl http://127.0.0.1:9102/health` - `curl http://127.0.0.1:9300/health` ## Smoke Tests Run inside `dagi-router-node1` to validate actions deterministically: - Excel create/update - Text/Markdown create/update - XML/HTML export - PPTX create/update - ODS create/update - Parquet create/update - CSV create/update - JSON/YAML export - ZIP bundle - DOCX create/update - PDF merge/split/fill - PDF update (rotate/reorder/remove/extract/metadata) - DJVU to PDF conversion - DJVU text extraction - Image create/edit/convert - Image bundle (zip) - SVG export + SVG->PNG convert (rect/circle/ellipse/line/polyline/polygon/text) Also verify infer endpoint still works: - `POST http://127.0.0.1:9102/v1/agents/devtools/infer` ## Backups Created During This Work - `rollback_backups/file_tool_step1_20260215_011637/...` - `rollback_backups/file_tool_step2_tool_manager.py.bak_20260215_012029` - `rollback_backups/file_tool_step3_tool_manager.py.bak_20260215_012200` - `rollback_backups/file_tool_step4_tool_manager.py.bak_20260215_012309` - `services/router/tool_manager.py.bak_20260215_020902` - `services/router/tool_manager.py.bak_20260215_112313` - `services/router/tool_manager.py.bak_20260215_112459` - `services/router/requirements.txt.bak_20260215_112459` - `services/router/tool_manager.py.bak_20260215_112652` - `services/router/requirements.txt.bak_20260215_112652` - `services/router/tool_manager.py.bak_20260215_112841` - `services/router/tool_manager.py.bak_20260215_112912` - `services/router/tool_manager.py.bak_20260215_113301` - `services/router/tool_manager.py.bak_20260215_114512` - `services/router/tool_manager.py.bak_20260215_114740` - `services/router/tool_manager.py.bak_20260215_120912` - `services/router/Dockerfile.bak_20260215_120912` - `services/router/tool_manager.py.bak_20260215_121116` ## Rollback (NODE1) ```bash cd /opt/microdao-daarion cp rollback_backups/file_tool_step1_20260215_011637/services/router/requirements.txt services/router/requirements.txt cp rollback_backups/file_tool_step1_20260215_011637/services/router/agent_tools_config.py services/router/agent_tools_config.py cp rollback_backups/file_tool_step1_20260215_011637/services/router/tool_manager.py services/router/tool_manager.py cp rollback_backups/file_tool_step1_20260215_011637/services/router/main.py services/router/main.py cp rollback_backups/file_tool_step1_20260215_011637/gateway-bot/router_client.py gateway-bot/router_client.py cp rollback_backups/file_tool_step1_20260215_011637/gateway-bot/http_api.py gateway-bot/http_api.py docker compose -f docker-compose.node1.yml up -d --build --no-deps router gateway ``` ## Notes - `docker-compose.node1.yml` may warn about deprecated `version` key; this is non-blocking. - Avoid `--remove-orphans` unless explicitly intended. - Use `--no-deps` for targeted router/gateway rollout to avoid unrelated service churn.