Skip to content
Open
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
93 changes: 93 additions & 0 deletions docs/hosting/mirofish-hermes-integration-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# MiroFish Hermes Integration Contract

## Purpose

This document defines the minimum stable contract for Hermes and OpenClaw to use the MiroFish host safely.

## Canonical Paths

- Runtime: `/Users/Shared/OpenClaw/mirofish-runtime`
- Transcribes: `/Users/Shared/OpenClaw/transcribes`
- Source only: `/Users/adrianlat/Library/Mobile Documents/com~apple~CloudDocs/airShare/MiroFish`

## Service Identity

- Service label: `com.openclaw.mirofish`
- Runtime owner: `airstride`
- Access model: LAN + SSH only

## Network Endpoints

- Frontend LAN URL: `http://10.0.0.161:3000`
- Backend LAN URL: `http://10.0.0.161:5001`
- Backend health: `http://10.0.0.161:5001/health`
- Frontend proxy health path: `http://10.0.0.161:3000/api/graph/project/list`

## SSH Access

- SSH alias: `openclaw-mirofish`
- SSH user: `airstride`

Recommended tunnels:

```bash
ssh -L 3000:127.0.0.1:3000 openclaw-mirofish
ssh -L 5001:127.0.0.1:5001 openclaw-mirofish
```

Tunnel-based local URLs:

- Frontend: `http://127.0.0.1:3000`
- Backend: `http://127.0.0.1:5001`

## Required Health Checks

Before Hermes or OpenClaw send operational work to MiroFish, the host should pass:

```bash
sudo launchctl print system/com.openclaw.mirofish
curl -sS http://127.0.0.1:5001/health
curl -sSI http://127.0.0.1:3000/
curl -sS http://127.0.0.1:3000/api/graph/project/list
```

Expected results:

- LaunchDaemon present in `system`
- Backend returns `{"service":"MiroFish Backend","status":"ok"}`
- Frontend returns `HTTP/1.1 200 OK`
- Frontend proxy returns a successful JSON payload

## Smoke Test

Use the canonical smoke test after reboot or maintenance:

```bash
/Users/Shared/OpenClaw/mirofish-runtime/scripts/host-smoke-test.sh
```

## Operational Data Rules

- Do not run MiroFish from iCloud.
- Do not write operational runtime state back into the iCloud source tree.
- Treat `/Users/Shared/OpenClaw/mirofish-runtime/backend/uploads` as persistent operational state.
- Treat `/Users/Shared/OpenClaw/transcribes` as the canonical local operational transcribes dataset.

## Consumption Rules

- Prefer SSH tunnels for operator access from other machines.
- Use LAN URLs only inside the trusted local network.
- Do not expose ports `3000` or `5001` through router forwarding or public internet ingress.
- Hermes and OpenClaw should assume MiroFish is a long-lived host service, not an ephemeral dev process.

## Operational Commands

From `/Users/Shared/OpenClaw/mirofish-runtime`:

```bash
./scripts/host-start.sh
./scripts/host-stop.sh
./scripts/host-status.sh
tail -f runtime/logs/backend.log
tail -f runtime/logs/frontend.log
```
145 changes: 145 additions & 0 deletions docs/hosting/mirofish-host-runbook.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# MiroFish Host Runbook

## Canonical Runtime

- Shared source of truth: `/Users/adrianlat/Library/Mobile Documents/com~apple~CloudDocs/airShare/MiroFish`
- Canonical operational runtime: `/Users/Shared/OpenClaw/mirofish-runtime`
- Canonical operational transcribes: `/Users/Shared/OpenClaw/transcribes`

The runtime should live outside iCloud because always-on services need stable local files, virtual environments, logs, and uploads that are not subject to iCloud eviction or placeholder behavior.

The iCloud source for breathwork transcribes remains:

- `/Users/adrianlat/Library/Mobile Documents/com~apple~CloudDocs/BreathWork/Transcribes`

That iCloud tree should be treated as source only. The shared operational copy should live in `/Users/Shared/OpenClaw/transcribes`.

## Ports

- Frontend: `3000`
- Backend: `5001`

## Commands

Run from the runtime root:

```bash
./scripts/host-start.sh
./scripts/host-stop.sh
./scripts/host-status.sh
tail -f runtime/logs/backend.log
tail -f runtime/logs/frontend.log
./scripts/host-smoke-test.sh
```

Sync transcribes from iCloud source to the shared operational path:

```bash
./scripts/sync-transcribes.sh
```

## SSH Tunnels

```bash
ssh -L 3000:127.0.0.1:3000 openclaw-mirofish
ssh -L 5001:127.0.0.1:5001 openclaw-mirofish
```

## Suggested SSH Alias

```sshconfig
Host openclaw-mirofish
HostName 10.0.0.161
User airstride
ServerAliveInterval 30
ServerAliveCountMax 3
StrictHostKeyChecking accept-new
```

## Legacy LaunchAgent Template

The current persistent service is the system LaunchDaemon below, running as `airstride`.
Use this LaunchAgent template only for a user-session fallback.

The validated plist is:

- `/Users/adrianlat/Library/Mobile Documents/com~apple~CloudDocs/airShare/MiroFish/ops/launchd/airshare.mirofish.plist`

It should be installed by a privileged shell or by a shell already running as `airstride`. If you are running as `airstride`, use:

```bash
cp /Users/adrianlat/Library/Mobile\ Documents/com~apple~CloudDocs/airShare/MiroFish/ops/launchd/airshare.mirofish.plist ~/Library/LaunchAgents/airshare.mirofish.plist
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/airshare.mirofish.plist
launchctl kickstart -k gui/$(id -u)/airshare.mirofish
```

If you are running from another admin account, bootstrap into `airstride` requires root privileges or an interactive `airstride` session.

Template:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>airshare.mirofish</string>
<key>ProgramArguments</key>
<array>
<string>/bin/zsh</string>
<string>/Users/Shared/OpenClaw/mirofish-runtime/scripts/host-start.sh</string>
<string>/Users/Shared/OpenClaw/mirofish-runtime</string>
</array>
<key>WorkingDirectory</key>
<string>/Users/Shared/OpenClaw/mirofish-runtime</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>AbandonProcessGroup</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/Shared/OpenClaw/mirofish-runtime/runtime/logs/launchd.log</string>
<key>StandardErrorPath</key>
<string>/Users/Shared/OpenClaw/mirofish-runtime/runtime/logs/launchd.err.log</string>
</dict>
</plist>
```

## Validated Constraints

- MiroFish is not run from iCloud.
- Runtime path is local and shared.
- SSH is LAN-only and should not be published through router/NAT.
- Docker was not available during validation, so source deployment is the active path.

## LaunchDaemon Migration

For a true always-on host, prefer the system LaunchDaemon:

- Source plist: `/Users/Shared/OpenClaw/mirofish-runtime/ops/launchd/com.openclaw.mirofish.plist`
- Installed plist: `/Library/LaunchDaemons/com.openclaw.mirofish.plist`
- Label: `com.openclaw.mirofish`
- User: `airstride`

Install with:

```bash
sudo /Users/Shared/OpenClaw/mirofish-runtime/scripts/install-mirofish-launchdaemon.sh
```

Validate with:

```bash
sudo launchctl print system/com.openclaw.mirofish
curl -sS http://127.0.0.1:5001/health
curl -sSI http://127.0.0.1:3000/
curl -sS http://127.0.0.1:3000/api/graph/project/list
```

## Hermes Integration

The canonical integration contract for Hermes and OpenClaw lives at:

- `/Users/adrianlat/Library/Mobile Documents/com~apple~CloudDocs/airShare/MiroFish/docs/hosting/mirofish-hermes-integration-contract.md`
- `/Users/Shared/OpenClaw/mirofish-runtime/docs/hosting/mirofish-hermes-integration-contract.md`
47 changes: 47 additions & 0 deletions docs/hosting/mirofish-ops-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# MiroFish Ops Contract

## Canonical Paths

- Runtime: `/Users/Shared/OpenClaw/mirofish-runtime`
- Transcribes: `/Users/Shared/OpenClaw/transcribes`
- Source only: `/Users/adrianlat/Library/Mobile Documents/com~apple~CloudDocs/airShare/MiroFish`

## Ownership

- Service owner: `airstride`
- LaunchDaemon label: `com.openclaw.mirofish`

## Local Health Checks

```bash
sudo launchctl print system/com.openclaw.mirofish
curl -sS http://127.0.0.1:5001/health
curl -sSI http://127.0.0.1:3000/
curl -sS http://127.0.0.1:3000/api/graph/project/list
```

## Post-Reboot Smoke Test

```bash
/Users/Shared/OpenClaw/mirofish-runtime/scripts/host-smoke-test.sh
```

## LAN + SSH Access

- Frontend: `http://10.0.0.161:3000`
- Backend: `http://10.0.0.161:5001`
- SSH alias: `openclaw-mirofish`
- SSH user: `airstride`

Recommended tunnels:

```bash
ssh -L 3000:127.0.0.1:3000 openclaw-mirofish
ssh -L 5001:127.0.0.1:5001 openclaw-mirofish
```

## Operational Rule

- Do not run MiroFish from iCloud.
- Do not change canonical runtime or transcribes paths without migration.
- Treat `backend/uploads` and shared transcribes as operational state.
2 changes: 1 addition & 1 deletion frontend/src/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import i18n from '../i18n'

// 创建axios实例
const service = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:5001',
baseURL: import.meta.env.VITE_API_BASE_URL || '/api',
timeout: 300000, // 5分钟超时(本体生成可能需要较长时间)
headers: {
'Content-Type': 'application/json'
Expand Down
14 changes: 13 additions & 1 deletion frontend/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,20 @@ export default defineConfig({
}
},
server: {
host: '0.0.0.0',
port: 3000,
open: false,
proxy: {
'/api': {
target: 'http://localhost:5001',
changeOrigin: true,
secure: false
}
}
},
preview: {
host: '0.0.0.0',
port: 3000,
open: true,
proxy: {
'/api': {
target: 'http://localhost:5001',
Expand Down
26 changes: 26 additions & 0 deletions ops/launchd/airshare.mirofish.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>airshare.mirofish</string>
<key>ProgramArguments</key>
<array>
<string>/bin/zsh</string>
<string>/Users/Shared/OpenClaw/mirofish-runtime/scripts/host-start.sh</string>
<string>/Users/Shared/OpenClaw/mirofish-runtime</string>
</array>
<key>WorkingDirectory</key>
<string>/Users/Shared/OpenClaw/mirofish-runtime</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>AbandonProcessGroup</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/Shared/OpenClaw/mirofish-runtime/runtime/logs/launchd.log</string>
<key>StandardErrorPath</key>
<string>/Users/Shared/OpenClaw/mirofish-runtime/runtime/logs/launchd.err.log</string>
</dict>
</plist>
41 changes: 41 additions & 0 deletions ops/launchd/com.openclaw.mirofish.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.openclaw.mirofish</string>
<key>ProgramArguments</key>
<array>
<string>/bin/zsh</string>
<string>/Users/Shared/OpenClaw/mirofish-runtime/scripts/host-start.sh</string>
<string>/Users/Shared/OpenClaw/mirofish-runtime</string>
</array>
<key>UserName</key>
<string>airstride</string>
<key>WorkingDirectory</key>
<string>/Users/Shared/OpenClaw/mirofish-runtime</string>
<key>EnvironmentVariables</key>
<dict>
<key>HOME</key>
<string>/Users/airstride</string>
<key>CODEX_HOME</key>
<string>/Users/airstride/.codex-openclaw</string>
<key>PATH</key>
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
</dict>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>ProcessType</key>
<string>Background</string>
<key>AbandonProcessGroup</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/Shared/OpenClaw/mirofish-runtime/runtime/logs/launchd.log</string>
<key>StandardErrorPath</key>
<string>/Users/Shared/OpenClaw/mirofish-runtime/runtime/logs/launchd.err.log</string>
<key>ThrottleInterval</key>
<integer>15</integer>
</dict>
</plist>
Loading