Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d75e1e5740 |
@@ -0,0 +1,4 @@
|
|||||||
|
OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1
|
||||||
|
PWD=/Users/MWsatwareAG/internal/mw-macbook-pro
|
||||||
|
OLDPWD=/Users/MWsatwareAG/internal/mw-macbook-pro/imsg
|
||||||
|
</dev/null: line 6: 80354 Terminated: 15 export OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1 && export OPENCLAW_GATEWAY_TOKEN=skt3_W8A5AVp__o_d9okfPjIwxjKjcOpLQz3SoUG5XU && openclaw node run --host 100.64.0.39 --port 18789 --display-name 'satware AG MacBook Pro'
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# Environment Template
|
|
||||||
OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1
|
|
||||||
PWD=/Users/MWsatwareAG/internal/mw-macbook-pro
|
|
||||||
OLDPWD=/Users/MWsatwareAG/internal/mw-macbook-pro/imsg
|
|
||||||
ELEVENLABS_API_KEY=
|
|
||||||
HOMEBREW_CELLAR=/usr/local/Cellar
|
|
||||||
INFOPATH=/usr/local/share/info
|
|
||||||
KITTY_PUBLIC_KEY=
|
|
||||||
COLORTERM=truecolor
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
.env
|
|
||||||
node_debug.log
|
|
||||||
node_foreground.log
|
|
||||||
@@ -1,10 +1,5 @@
|
|||||||
# MacBook Pro Node - OpenClaw Gateway Integration
|
# MacBook Pro Node - OpenClaw Gateway Integration
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
- [OpenClaw Architecture](docs/OPENCLAW_ARCHITECTURE.md)
|
|
||||||
- [OpenClaw Health Monitoring](docs/OPENCLAW_HEALTH_MONITORING.md)
|
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
This repository documents the OpenClaw gateway integration for the satware AG MacBook Pro, configured as a remote tool node controlled by the agent-zero Docker container running on the Manjaro PC.
|
This repository documents the OpenClaw gateway integration for the satware AG MacBook Pro, configured as a remote tool node controlled by the agent-zero Docker container running on the Manjaro PC.
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
# OpenClaw Architecture: satware AG MacBook Pro Node
|
|
||||||
|
|
||||||
## Hub-and-Spoke System
|
|
||||||
|
|
||||||
The satware AG MacBook Pro operates as a **Remote Tool Node** in a hub-and-spoke configuration, where the Hub (Gateway) resides inside a Docker container on the "Luca" Manjaro server.
|
|
||||||
|
|
||||||
### 1. Connection Chain (The "Extreme Details")
|
|
||||||
|
|
||||||
The connection from this MacBook to the gateway uses a multi-layered tunnel to ensure secure communications over the Tailscale network while bypassing various Docker isolation barriers.
|
|
||||||
|
|
||||||
#### A. Layer 1: Tailscale Mesh (IP: 100.64.0.x)
|
|
||||||
The underlying transport is the Tailscale mesh network. This MacBook (`100.64.0.12`) sees the Luca server at `100.64.0.39`.
|
|
||||||
|
|
||||||
#### B. Layer 2: SSH Tunnel (Container Entry)
|
|
||||||
* **Service**: `ai.openclaw.ssh-tunnel.plist`
|
|
||||||
* **Command**: `ssh -N -L 18789:172.18.0.2:18789 root@100.64.0.39 -p 2222`
|
|
||||||
* **How it works**:
|
|
||||||
1. The MacBook initiates an SSH connection to port `2222` on Luca's Tailscale IP. Port `2222` is the SSH server running **inside** the `agent-zero` Docker container.
|
|
||||||
2. The `-L 18789:172.18.0.2:18789` switch creates a local loopback listener on this MacBook (`127.0.0.1:18789`).
|
|
||||||
3. Traffic sent to `127.0.0.1:18789` is forwarded through the encrypted SSH tunnel directly to the container's internal IP and port (`172.18.0.2:18789`).
|
|
||||||
4. Since the SSH server is inside the container, `172.18.0.2` is the container's internal interface IP, which the OpenClaw gateway is listening on.
|
|
||||||
|
|
||||||
#### C. Layer 3: WebSocket Node Connection
|
|
||||||
* **Service**: `ai.openclaw.node.plist`
|
|
||||||
* **Command**: `openclaw node run --host 127.0.0.1 --port 18789`
|
|
||||||
* **How it works**:
|
|
||||||
1. The node process starts on the MacBook.
|
|
||||||
2. It connects to `ws://127.0.0.1:18789`. Because of the SSH tunnel above, this connects it to the remote gateway on Luca.
|
|
||||||
3. It authenticates using the `OPENCLAW_GATEWAY_TOKEN` provided in the environment variables.
|
|
||||||
|
|
||||||
### 2. Component Layout
|
|
||||||
|
|
||||||
| Component | Role | Runtime | Host |
|
|
||||||
|-----------|------|---------|------|
|
|
||||||
| **Gateway Hub** | Primary agent orchestrator | Node.js (inside Docker) | Luca (Manjaro) |
|
|
||||||
| **Node Runner** | Secondary tool executor | Node.js (native) | MacBook Pro |
|
|
||||||
| **Llama Server** | LLM Inference (122B Qwen) | ROCm / HIP | evox2-js (AMD Strix Halo) |
|
|
||||||
|
|
||||||
### 3. Permissions and Sandboxing
|
|
||||||
|
|
||||||
* **Gateway Sandbox**: Disabled (`mode: off`) inside the `agent-zero` container. The container *is* the security boundary.
|
|
||||||
* **Node Permissions**: The MacBook Node requires **full disk access**, **accessibility**, and **screen recording** permissions granted to the Node.js binary (located at `/usr/local/opt/node/bin/node` or cellar equivalent).
|
|
||||||
* **Executive Approvals**: Controlled on the Gateway side in `openclaw-data/exec-approvals.json`. The MacBook node is currently granted a set of allowed commands (see status in README).
|
|
||||||
|
|
||||||
### 4. Why 127.0.0.1?
|
|
||||||
|
|
||||||
The MacBook's node configures the gateway URL as `ws://127.0.0.1:18789` because OpenClaw's security policy prohibits sending operator/node tokens over unencrypted (`ws://`) connections to **remote** IP addresses. However, `127.0.0.1` is considered "local" and always trusted. The SSH tunnel transparently wraps the local connection in encryption for its journey over the network.
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
# OpenClaw Health Monitoring: MacBook Pro Node
|
|
||||||
|
|
||||||
## 1. Quick Service Status (Launchd)
|
|
||||||
|
|
||||||
Check if the node and tunnel services are reported as running by macOS:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
launchctl list | grep ai.openclaw
|
|
||||||
```
|
|
||||||
* `ai.openclaw.node`: The node runner.
|
|
||||||
* `ai.openclaw.ssh-tunnel`: The SSH entry tunnel.
|
|
||||||
|
|
||||||
A status of `0` in the middle column usually indicates success. A positive number is the PID.
|
|
||||||
|
|
||||||
## 2. Testing Connectivity (The "Curl" Test)
|
|
||||||
|
|
||||||
Since the tunnel maps the gateway to your local loopback, you can probe the gateway's health endpoint directly from the MacBook terminal:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -i http://127.0.0.1:18789/health
|
|
||||||
```
|
|
||||||
* **Success**: Returns `HTTP/1.1 200 OK` with a JSON body `{"ok":true,...}`.
|
|
||||||
* **Failure (Tunnel Down)**: `curl: (7) Failed to connect to 127.0.0.1 port 18789: Connection refused`.
|
|
||||||
* **Failure (Gateway Down)**: `curl: (52) Empty reply from server` or timeout (if SSH connected but gateway is dead).
|
|
||||||
|
|
||||||
## 3. Log Inspection
|
|
||||||
|
|
||||||
The LaunchAgents are configured to log to `~/.openclaw/logs/`.
|
|
||||||
|
|
||||||
* **Node Logs**: `tail -f ~/.openclaw/logs/node.err.log`
|
|
||||||
* Look for: `[node] connected to gateway`, `[node] authenticated`.
|
|
||||||
* Errors like `Device identity required` indicate a pairing/token issue.
|
|
||||||
* **Tunnel Logs**: `tail -f ~/.openclaw/logs/ssh-tunnel.err.log`
|
|
||||||
* Look for: `Permission denied`, `Connection refused`, or `channel 0: open failed: connect failed`.
|
|
||||||
* `Forwarding port 18789 to 172.18.0.2:18789` should be present.
|
|
||||||
|
|
||||||
## 4. Using the Local CLI
|
|
||||||
|
|
||||||
You can use the `openclaw` CLI directly on the MacBook to interact with the gateway through the tunnel.
|
|
||||||
|
|
||||||
### Check Node Status
|
|
||||||
```bash
|
|
||||||
openclaw node status
|
|
||||||
```
|
|
||||||
|
|
||||||
### Manual Node Run (Foreground)
|
|
||||||
If the background service is acting up, stop it and run in the foreground to see real-time output:
|
|
||||||
```bash
|
|
||||||
launchctl unload ~/Library/LaunchAgents/ai.openclaw.node.plist
|
|
||||||
openclaw node run --host 127.0.0.1 --port 18789 --display-name "Debug Node"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 5. Advanced RPC Diagnostics
|
|
||||||
|
|
||||||
If you need to verify specific gateway states (e.g., if the node is actually visible in the `node.list`), you can use the RPC protocol. Since the `openclaw` CLI sometimes has scope issues, you can use a simple Node.js script (similar to the one on Luca) to send signed requests.
|
|
||||||
|
|
||||||
**Example: Check Gateway Health via RPC**
|
|
||||||
```bash
|
|
||||||
OPENCLAW_WS_URL=ws://127.0.0.1:18789 \
|
|
||||||
OPENCLAW_TOKEN=$(grep OPENCLAW_GATEWAY_TOKEN ~/Library/LaunchAgents/ai.openclaw.node.plist | sed -E 's/.*<string>(.*)<\/string>.*/\1/') \
|
|
||||||
node -e "
|
|
||||||
const WebSocket = require('ws');
|
|
||||||
const ws = new WebSocket(process.env.OPENCLAW_WS_URL);
|
|
||||||
ws.on('open', () => {
|
|
||||||
ws.send(JSON.stringify({
|
|
||||||
type: 'req', id: '1', method: 'connect',
|
|
||||||
params: { auth: { token: process.env.OPENCLAW_TOKEN }, role: 'operator', scopes: ['operator.read'] }
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
ws.on('message', (data) => {
|
|
||||||
const msg = JSON.parse(data);
|
|
||||||
if (msg.method === 'connect') {
|
|
||||||
ws.send(JSON.stringify({ type: 'req', id: '2', method: 'health' }));
|
|
||||||
} else if (msg.id === '2') {
|
|
||||||
console.log(JSON.stringify(msg.payload, null, 2));
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 6. Restarting Services
|
|
||||||
|
|
||||||
If things get stuck, the "Standard Restart" is:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. Restart Tunnel
|
|
||||||
launchctl unload ~/Library/LaunchAgents/ai.openclaw.ssh-tunnel.plist
|
|
||||||
launchctl load ~/Library/LaunchAgents/ai.openclaw.ssh-tunnel.plist
|
|
||||||
|
|
||||||
# 2. Restart Node
|
|
||||||
launchctl unload ~/Library/LaunchAgents/ai.openclaw.node.plist
|
|
||||||
launchctl load ~/Library/LaunchAgents/ai.openclaw.node.plist
|
|
||||||
```
|
|
||||||
|
|
||||||
Wait ~5 seconds between steps for the port to bind.
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
# Shell Standardization Plan
|
|
||||||
|
|
||||||
To ensure a consistent development environment across local machines and remote servers (within the satware AG infrastructure), we are standardizing on `bash` with `starship` as the prompt.
|
|
||||||
|
|
||||||
## Deployment Guide
|
|
||||||
|
|
||||||
### Prerequisites
|
|
||||||
- Access to the target environment.
|
|
||||||
- `curl` installed (for prompt installation).
|
|
||||||
|
|
||||||
### Execution
|
|
||||||
Run the provided bootstrap script:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/path/to/inner/repo/scripts/bootstrap-shell.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### Manual Verification
|
|
||||||
After running the script, initiate the shell switch:
|
|
||||||
1. Ensure the new login shell is available in `/etc/shells` (if on Linux).
|
|
||||||
2. Run `chsh -s /bin/bash`.
|
|
||||||
3. Restart your terminal session.
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Standardize shell configuration (bash)
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
echo "Standardizing shell configuration to bash..."
|
|
||||||
|
|
||||||
# Ensure we are in home
|
|
||||||
cd "$HOME"
|
|
||||||
|
|
||||||
# Install starship if missing
|
|
||||||
if ! command -v starship &> /dev/null; then
|
|
||||||
echo "Installing starship prompt..."
|
|
||||||
curl -sS https://starship.rs/install.sh | sh
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Apply .bashrc
|
|
||||||
cat << 'EOF' > .bashrc
|
|
||||||
# Starship prompt
|
|
||||||
if command -v starship &> /dev/null; then
|
|
||||||
eval "$(starship init bash)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Basic Coder Tools
|
|
||||||
alias ll='ls -la'
|
|
||||||
alias gs='git status'
|
|
||||||
alias gp='git pull'
|
|
||||||
alias gco='git checkout'
|
|
||||||
|
|
||||||
# AI Agent Friendly Aliases
|
|
||||||
alias ai-logs='tail -f mcp_keepalive.log'
|
|
||||||
alias node-logs='tail -f node_debug.log'
|
|
||||||
alias edit-bash='${EDITOR:-nano} ~/.bashrc'
|
|
||||||
alias source-bash='source ~/.bashrc'
|
|
||||||
|
|
||||||
# Path fixes
|
|
||||||
export PATH="$HOME/.local/bin:$PATH"
|
|
||||||
export PATH="$HOME/bin:$PATH"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Apply .bash_profile
|
|
||||||
cat << 'EOF' > .bash_profile
|
|
||||||
if [ -f ~/.bashrc ]; then
|
|
||||||
source ~/.bashrc
|
|
||||||
fi
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo "Bash standardized. Restart your terminal."
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# OpenClaw Health Check Utility
|
|
||||||
|
|
||||||
echo "--- Service Status ---"
|
|
||||||
launchctl list | grep ai.openclaw
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "--- Connectivity Check ---"
|
|
||||||
curl -i http://127.0.0.1:18789/health
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "--- Node Logs (Last 10 lines) ---"
|
|
||||||
tail -n 10 ~/.openclaw/logs/node.err.log
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "--- Tunnel Logs (Last 10 lines) ---"
|
|
||||||
tail -n 10 ~/.openclaw/logs/ssh-tunnel.err.log
|
|
||||||
echo ""
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# vision-bridge.sh: Bridge Peekaboo screenshots to Ollama Vision
|
|
||||||
# Usage: ./vision-bridge.sh "Describe this screen" [app_name]
|
|
||||||
|
|
||||||
PROMPT="${1:-Describe this image}"
|
|
||||||
APP="${2:-}"
|
|
||||||
RETINA="${3:-true}"
|
|
||||||
|
|
||||||
TMP_IMG=$(mktemp /tmp/openclaw-vision-XXXXXX.png)
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
rm -f "$TMP_IMG"
|
|
||||||
}
|
|
||||||
trap cleanup EXIT
|
|
||||||
|
|
||||||
# Capture
|
|
||||||
PEEKABOO_ARGS=(image --path "$TMP_IMG")
|
|
||||||
if [ -n "$APP" ]; then
|
|
||||||
PEEKABOO_ARGS+=(--app "$APP")
|
|
||||||
fi
|
|
||||||
if [ "$RETINA" = "true" ]; then
|
|
||||||
PEEKABOO_ARGS+=(--retina)
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "[vision] Capturing screen..." >&2
|
|
||||||
peekaboo "${PEEKABOO_ARGS[@]}" >/dev/null
|
|
||||||
|
|
||||||
# Analyze
|
|
||||||
echo "[vision] Analyzing with llama3.2-vision..." >&2
|
|
||||||
ollama run llama3.2-vision "$PROMPT" "$TMP_IMG"
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
---
|
|
||||||
name: ollama-vision
|
|
||||||
description: Automated Vision pipeline using Peekaboo for capture and Ollama (llama3.2-vision) for analysis.
|
|
||||||
homepage: https://ollama.com
|
|
||||||
metadata: { "openclaw": { "emoji": "👁️", "requires": { "bins": ["peekaboo", "ollama"] } } }
|
|
||||||
---
|
|
||||||
|
|
||||||
# Ollama Vision
|
|
||||||
|
|
||||||
Bridge macOS screen capture directly to local vision models.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# General screen description
|
|
||||||
./scripts/vision-bridge.sh "What's on my screen?"
|
|
||||||
|
|
||||||
# Focus on a specific app
|
|
||||||
./scripts/vision-bridge.sh "Describe this window" "Slack"
|
|
||||||
|
|
||||||
# Higher detail (retina)
|
|
||||||
./scripts/vision-bridge.sh "Read the text in this terminal" "iTerm2" true
|
|
||||||
```
|
|
||||||
|
|
||||||
## Tools
|
|
||||||
|
|
||||||
### vision.see
|
|
||||||
Capture the screen or a specific app and describe what is visible using Ollama Llama 3.2 Vision.
|
|
||||||
|
|
||||||
**Run configuration:**
|
|
||||||
- `command`: `/Users/MWsatwareAG/internal/mw-macbook-pro/scripts/vision-bridge.sh`
|
|
||||||
- `args`: ["{{prompt}}", "{{app}}", "{{retina}}"]
|
|
||||||
|
|
||||||
**Arguments:**
|
|
||||||
- `prompt`: (string) What to look for or ask about the image.
|
|
||||||
- `app`: (optional string) Name or bundle ID of the app to focus on.
|
|
||||||
- `retina`: (optional boolean, default true) Capture at high resolution.
|
|
||||||
Reference in New Issue
Block a user