# 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_<timestamp>/...`
3. Copy runtime files from NODE1 to laptop:
   - `scp root@144.76.224.179:/opt/microdao-daarion/<file> ...`
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.
