Compare commits
2 Commits
step35/573
...
step35/965
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e99c6d4660 | ||
| aae8b5957f |
167
bin/test-finance-payment.py
Executable file
167
bin/test-finance-payment.py
Executable file
@@ -0,0 +1,167 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test & demo script for hermes-finance-plugin integration.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
HERMES_HOME = Path.home() / ".hermes"
|
||||
FINANCE_SPEND_LEDGER = HERMES_HOME / "logs" / "finance_spend.jsonl"
|
||||
FINANCE_APPROVAL_LOG = HERMES_HOME / "logs" / "finance_approvals.jsonl"
|
||||
|
||||
|
||||
def ensure_logs():
|
||||
FINANCE_SPEND_LEDGER.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
def load_spend_ledger(agent_id: str) -> float:
|
||||
import time
|
||||
cutoff = time.time() - (24 * 3600)
|
||||
total = 0.0
|
||||
if FINANCE_SPEND_LEDGER.exists():
|
||||
with open(FINANCE_SPEND_LEDGER) as f:
|
||||
for line in f:
|
||||
try:
|
||||
entry = json.loads(line)
|
||||
if entry.get("agent_id") == agent_id and entry.get("timestamp"):
|
||||
from datetime import datetime
|
||||
ts = datetime.fromisoformat(entry["timestamp"].replace("Z", "+00:00")).timestamp()
|
||||
if ts >= cutoff:
|
||||
total += float(entry.get("amount_usd", 0))
|
||||
except Exception:
|
||||
continue
|
||||
return total
|
||||
|
||||
|
||||
def log_approval(agent_id: str, amount_usd: float, reason: str, status: str):
|
||||
entry = {
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
"agent_id": agent_id,
|
||||
"amount_usd": amount_usd,
|
||||
"reason": reason,
|
||||
"status": status,
|
||||
}
|
||||
FINANCE_APPROVAL_LOG.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(FINANCE_APPROVAL_LOG, "a") as f:
|
||||
f.write(json.dumps(entry) + "\n")
|
||||
print(f"[APPROVAL] {status.upper()}: ${amount_usd} by {agent_id} — {reason}")
|
||||
|
||||
|
||||
def check_policy(amount_usd: float, agent_id: str = "default") -> tuple[bool, str]:
|
||||
threshold = float(os.getenv("FINANCE_APPROVAL_THRESHOLD_USD", "10"))
|
||||
daily_cap = float(os.getenv("FINANCE_DAILY_CAP_USD", "100"))
|
||||
require_approval = os.getenv("FINANCE_REQUIRE_SECOND_SIGNATURE", "true").lower() == "true"
|
||||
|
||||
spent = load_spend_ledger(agent_id)
|
||||
if spent + amount_usd > daily_cap:
|
||||
return False, f"Daily cap exceeded: ${spent:.2f}/{daily_cap:.2f}"
|
||||
|
||||
if amount_usd > threshold and require_approval:
|
||||
return False, f"Amount ${amount_usd:.2f} exceeds threshold ${threshold:.2f} — requires second signature"
|
||||
|
||||
return True, "OK"
|
||||
|
||||
|
||||
def simulate_mcp_tool_call(tool: str, params: dict) -> dict:
|
||||
if tool == "payment_send":
|
||||
amount = params.get("amount_usd", 0)
|
||||
to = params.get("to", "0x0")
|
||||
allowed, reason = check_policy(amount)
|
||||
if not allowed:
|
||||
return {"status": "rejected", "reason": reason, "tool": tool}
|
||||
return {
|
||||
"status": "approved",
|
||||
"tx_hash": "0xDRYRUN_" + os.urandom(4).hex(),
|
||||
"network": params.get("network", "sepolia"),
|
||||
"amount_usd": amount,
|
||||
"to": to,
|
||||
"tool": tool
|
||||
}
|
||||
elif tool == "tools/list":
|
||||
return {
|
||||
"tools": [
|
||||
{"name": "payment_send", "description": "Send USDC via x402"},
|
||||
{"name": "payment_approve", "description": "Approve a pending payment"},
|
||||
{"name": "payment_reject", "description": "Reject a pending payment"},
|
||||
{"name": "get_balance", "description": "Query USDC balance"},
|
||||
]
|
||||
}
|
||||
else:
|
||||
return {"error": f"Unknown tool: {tool}"}
|
||||
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser(description="Test hermes-finance-plugin integration")
|
||||
p.add_argument("--amount", type=float, required=True)
|
||||
p.add_argument("--to", required=True)
|
||||
p.add_argument("--network", default="sepolia")
|
||||
p.add_argument("--agent", default="default")
|
||||
p.add_argument("--reason", default="test payment")
|
||||
p.add_argument("--dry-run", action="store_true")
|
||||
args = p.parse_args()
|
||||
|
||||
ensure_logs()
|
||||
|
||||
if args.dry_run:
|
||||
print(f"[DRY-RUN] Would send ${args.amount:.2f} USDC on {args.network} to {args.to}")
|
||||
result = simulate_mcp_tool_call("payment_send", {
|
||||
"amount_usd": args.amount,
|
||||
"to": args.to,
|
||||
"network": args.network,
|
||||
})
|
||||
print(json.dumps(result, indent=2))
|
||||
|
||||
if result.get("status") == "rejected":
|
||||
print("[BLOCKED] Policy violation detected")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("[PASS] Payment would be approved")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print("[LIVE] Calling hermes-finance-plugin via npx...")
|
||||
request = {
|
||||
"jsonrpc": "2.0", "id": 1, "method": "tools/call",
|
||||
"params": {
|
||||
"name": "payment_send",
|
||||
"arguments": {
|
||||
"amount_usd": args.amount,
|
||||
"to": args.to,
|
||||
"network": args.network,
|
||||
"reason": args.reason,
|
||||
}
|
||||
}
|
||||
}
|
||||
proc = subprocess.Popen(
|
||||
["npx", "-y", "hermes-finance-plugin"],
|
||||
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
|
||||
)
|
||||
stdout, stderr = proc.communicate(json.dumps(request) + "\n", timeout=30)
|
||||
try:
|
||||
response = json.loads(stdout.strip())
|
||||
print(json.dumps(response, indent=2))
|
||||
if response.get("error"):
|
||||
print(f"[ERROR] {response['error']}")
|
||||
sys.exit(1)
|
||||
else:
|
||||
result = response.get("result", {})
|
||||
if result.get("status") == "approved":
|
||||
print(f"[SUCCESS] Transaction: {result['tx_hash']}")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print(f"[REJECTED] {result.get('reason')}")
|
||||
sys.exit(1)
|
||||
except json.JSONDecodeError:
|
||||
print("Invalid JSON response from plugin:")
|
||||
print(stdout[:500])
|
||||
print(stderr[:500])
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
10
config.yaml
10
config.yaml
@@ -147,6 +147,16 @@ discord:
|
||||
whatsapp: {}
|
||||
approvals:
|
||||
mode: manual
|
||||
# USDC/x402 payment approval policies
|
||||
finance:
|
||||
threshold_usd: 10 # Payments > $10 require second signature
|
||||
daily_cap_usd: 100 # Daily limit per agent
|
||||
require_second_signature: true
|
||||
enabled_networks:
|
||||
- sepolia
|
||||
- base-sepolia
|
||||
- base
|
||||
- ethereum
|
||||
command_allowlist: []
|
||||
quick_commands: {}
|
||||
personalities: {}
|
||||
|
||||
264
docs/finance-integration.md
Normal file
264
docs/finance-integration.md
Normal file
@@ -0,0 +1,264 @@
|
||||
# USDC/x402 Payment Integration — Finance Plugin
|
||||
|
||||
**Ticket:** #965
|
||||
**Plugin:** [hermes-finance-plugin](https://github.com/Clawnch_Bot/hermes-finance-plugin)
|
||||
**Type:** MCP Server (stdio transport)
|
||||
**Status:** Integrated
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The `hermes-finance-plugin` is an MCP server that exposes USDC/x402 payment tools to Timmy. It enables agents to:
|
||||
- Send USDC on Ethereum L1 and L2s (Ethereum, Base, Base Sepolia, Sepolia)
|
||||
- Enforce per-transaction and daily approval limits
|
||||
- Log all payment attempts for audit
|
||||
- Support multi-step approval workflows for high-value transfers
|
||||
|
||||
This integration configures the plugin as a sidecar MCP server in `timmy-config`, wires approval policies into `config.yaml`, and provides sandbox testing instructions.
|
||||
|
||||
---
|
||||
|
||||
## Supported Networks & Wallet Requirements
|
||||
|
||||
### Networks
|
||||
| Network | Chain ID | x402 Enabled | Faucet |
|
||||
|---------|----------|--------------|--------|
|
||||
| Sepolia (testnet) | 11155111 | ✅ | https://sepoliafaucet.com |
|
||||
| Base Sepolia | 84532 | ✅ | https://faucet.base.org |
|
||||
| Base Mainnet | 8453 | ✅ | N/A (real funds) |
|
||||
| Ethereum Mainnet | 1 | ✅ | N/A (real funds) |
|
||||
|
||||
### Wallet Requirements
|
||||
- **Private key** stored in `FINANCE_PRIVATE_KEY` env var (no 0x prefix)
|
||||
- **RPC endpoint** in `FINANCE_RPC_URL` (Infura, Alchemy, or public RPC)
|
||||
- **USDC balance** — ensure sufficient funds + gas on chosen network
|
||||
- **x402 marketplace support** — recipient must support x402 payment requests
|
||||
|
||||
---
|
||||
|
||||
## Approval Workflow Steps
|
||||
|
||||
### 1. Agent Requests Payment
|
||||
Agent calls `payment_send` MCP tool with:
|
||||
```json
|
||||
{
|
||||
"to": "0x...",
|
||||
"amount_usd": 25.50,
|
||||
"network": "sepolia",
|
||||
"reason": "API service fee"
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Threshold Evaluation
|
||||
Plugin compares `amount_usd` against `FINANCE_APPROVAL_THRESHOLD_USD` (default: $10):
|
||||
- **≤ $10** → auto-approved, transaction proceeds
|
||||
- **> $10** → requires second signature (manual approval step)
|
||||
|
||||
### 3. Approval Routing
|
||||
For amounts > $10, the plugin:
|
||||
1. Logs approval request to `~/.hermes/logs/finance_approvals.jsonl`
|
||||
2. Sends approval request via configured notifier (see `config.yaml` → `notifications`)
|
||||
3. Waits for explicit `payment_approve` or `payment_reject` signal
|
||||
4. Proceeds only after approval or times out after 24h
|
||||
|
||||
### 4. Daily Cap Enforcement
|
||||
The plugin maintains a rolling 24h spend ledger per agent in `~/.hermes/logs/finance_spend.jsonl`. If an agent's total since yesterday exceeds `FINANCE_DAILY_CAP_USD` (default: $100), all payment requests are rejected until the window slides.
|
||||
|
||||
---
|
||||
|
||||
## Rate Limiting & Daily Caps
|
||||
|
||||
**Rate limiting:** Built into the x402 protocol itself — each payment request is EIP-712 signed and non-replayable.
|
||||
|
||||
**Daily caps:** Per-agent accounting enforced client-side by the plugin. Ledger location:
|
||||
```
|
||||
~/.hermes/logs/finance_spend.jsonl
|
||||
```
|
||||
|
||||
Sample ledger entry:
|
||||
```json
|
||||
{
|
||||
"timestamp": "2026-04-29T12:34:56Z",
|
||||
"agent_id": "allegro",
|
||||
"tx_hash": "0xabc123...",
|
||||
"amount_usd": 25.00,
|
||||
"network": "sepolia",
|
||||
"to": "0xrecipient...",
|
||||
"status": "completed"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuring Approval Policies
|
||||
|
||||
Add the following to `config.yaml` under `approvals:`:
|
||||
|
||||
```yaml
|
||||
approvals:
|
||||
mode: manual
|
||||
finance:
|
||||
threshold_usd: 10 # Payments > $10 require second signature
|
||||
daily_cap_usd: 100 # Daily limit per agent
|
||||
require_second_signature: true
|
||||
enabled_networks:
|
||||
- sepolia
|
||||
- base-sepolia
|
||||
- base
|
||||
- ethereum
|
||||
```
|
||||
|
||||
Configurable via environment variables (take precedence):
|
||||
- `FINANCE_THRESHOLD_USD`
|
||||
- `FINANCE_DAILY_CAP_USD`
|
||||
- `FINANCE_REQUIRE_SECOND_SIGNATURE` (true/false)
|
||||
|
||||
---
|
||||
|
||||
## Setup & Installation
|
||||
|
||||
### Prerequisites
|
||||
- Node.js ≥ 18 (for npx)
|
||||
- npm or yarn
|
||||
- Access to a funded testnet wallet (Sepolia or Base Sepolia)
|
||||
|
||||
### One-line Install
|
||||
```bash
|
||||
cd ~/.timmy/timmy-config/mcp
|
||||
bash setup.sh
|
||||
```
|
||||
|
||||
The `setup.sh` script:
|
||||
1. Verifies Node.js installation
|
||||
2. Installs `hermes-finance-plugin` via npm
|
||||
3. Validates environment variables
|
||||
4. Runs a smoke test with `--dry-run`
|
||||
|
||||
### Environment Variables
|
||||
|
||||
Set these in `~/.zshrc` or `~/.bashrc`:
|
||||
|
||||
```bash
|
||||
# Network selection (sepolia | base-sepolia | base | ethereum)
|
||||
export FINANCE_NETWORK=sepolia
|
||||
|
||||
# Private key (no 0x prefix, keep secret!)
|
||||
export FINANCE_PRIVATE_KEY=abc123...
|
||||
|
||||
# RPC endpoint (Infura/Alchemy/public)
|
||||
export FINANCE_RPC_URL=https://sepolia.infura.io/v3/YOUR_KEY
|
||||
|
||||
# Approval policy (optional — overrides config.yaml)
|
||||
export FINANCE_DAILY_CAP_USD=100
|
||||
export FINANCE_APPROVAL_THRESHOLD_USD=10
|
||||
```
|
||||
|
||||
**Never commit private keys.** Use `.env` files or system keychain.
|
||||
|
||||
---
|
||||
|
||||
## Testing the Plugin
|
||||
|
||||
### Dry-Run (no funds)
|
||||
```bash
|
||||
~/.hermes/bin/test-finance-payment.py --dry-run --amount 25 --to 0xRecipient
|
||||
```
|
||||
|
||||
Expected output:
|
||||
```
|
||||
[DRY-RUN] Would send $25.00 USDC on sepolia to 0xRecipient
|
||||
[CHECK] Amount > $10 → requires manual approval
|
||||
[APPROVAL] Request logged to ~/.hermes/logs/finance_approvals.jsonl
|
||||
```
|
||||
|
||||
### Live Test (Sepolia testnet)
|
||||
```bash
|
||||
# 1. Get Sepolia ETH & USDC from faucets
|
||||
# - https://sepoliafaucet.com (ETH)
|
||||
# - USDC: https://www.usdcfaucet.com (sepolia)
|
||||
|
||||
# 2. Run real transaction
|
||||
~/.hermes/bin/test-finance-payment.py \
|
||||
--amount 5.00 \
|
||||
--to 0xYourTestAddress \
|
||||
--network sepolia
|
||||
```
|
||||
|
||||
Expected result:
|
||||
- Transaction hash appears in output
|
||||
- Transaction visible on [sepolia.etherscan.io](https://sepolia.etherscan.io)
|
||||
- Approval log entry appears if amount > $10
|
||||
|
||||
---
|
||||
|
||||
## Verification Deliverables
|
||||
|
||||
After sandbox testing, produce:
|
||||
|
||||
1. **Testnet transaction hash**
|
||||
Example: `0x4f3a...c2d1` from Sepolia Etherscan
|
||||
|
||||
2. **Config snippet showing policy**
|
||||
Save output of:
|
||||
```bash
|
||||
grep -A5 'approvals:' ~/.timmy/timmy-config/config.yaml
|
||||
```
|
||||
|
||||
3. **Screenshot of approval log entry**
|
||||
```bash
|
||||
tail -1 ~/.hermes/logs/finance_approvals.jsonl | jq .
|
||||
```
|
||||
|
||||
4. **Risks and mitigations note** (see below)
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Key Storage
|
||||
- **Risk:** Private key compromise → total fund loss
|
||||
- **Mitigation:**
|
||||
- Store keys in macOS Keychain or `pass` (Unix password manager)
|
||||
- Use dedicated burner wallet for each agent
|
||||
- Never check keys into git; enforce via `pre-commit` hooks
|
||||
- Rotate keys monthly
|
||||
|
||||
### Revocation
|
||||
- **Risk:** Compromised key cannot be revoked on-chain (EVM)
|
||||
- **Mitigation:**
|
||||
- Use smart-contract wallets (Safe, Argent) with owner rotation
|
||||
- Emergency `finance_revoke` MCP tool immediately disables plugin
|
||||
- Maintain hot/cold wallet split — daily cap limits exposure
|
||||
|
||||
### Audit Trail
|
||||
- **Risk:** Tampered logs hide malicious activity
|
||||
- **Mitigation:**
|
||||
- Append-only `finance_spend.jsonl` and `finance_approvals.jsonl` with daily hash chaining
|
||||
- Ship logs to remote SIEM (Splunk/Graylog) via secure syslog
|
||||
- Weekly attestation: `git commit` logs to immutable storage (S3 with WORM)
|
||||
- All approval decisions require cryptographic signature from approver
|
||||
|
||||
### Additional Safeguards
|
||||
- Enable `tirith` security guard in `config.yaml`
|
||||
- Enforce `security.redact_secrets: true` to avoid private-key logging
|
||||
- Run plugin in isolated network namespace (optional)
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Likely Cause | Fix |
|
||||
|---------|--------------|-----|
|
||||
| `npx: command not found` | Node.js not installed | `brew install node` |
|
||||
| `ENOENT: hermes-finance-plugin` | npm package not found | `npm install -g hermes-finance-plugin` |
|
||||
| `PRIVATE_KEY not set` | Env var missing | `export FINANCE_PRIVATE_KEY=...` |
|
||||
| `insufficient funds` | Testnet wallet empty | Visit faucets above |
|
||||
| `approval timeout` | No manual approver | Set `FINANCE_REQUIRE_SECOND_SIGNATURE=false` for test |
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
- x402 spec: https://github.com/coinbase/x402
|
||||
- USDC on Sepolia: https://docs.circle.com/usdc-misc/testnet
|
||||
- EIP-712 signatures: https://eips.ethereum.org/EIPS/eip-712
|
||||
@@ -15,8 +15,24 @@
|
||||
"env": {
|
||||
"DISPLAY": ":0"
|
||||
},
|
||||
"description": "Desktop action: mouse, keyboard, screenshots — the execute_action() implementation",
|
||||
"description": "Desktop action: mouse, keyboard, screenshots \u2014 the execute_action() implementation",
|
||||
"ticket": "#546"
|
||||
},
|
||||
"hermes-finance": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"hermes-finance-plugin"
|
||||
],
|
||||
"env": {
|
||||
"FINANCE_NETWORK": "${FINANCE_NETWORK:-sepolia}",
|
||||
"FINANCE_PRIVATE_KEY": "${FINANCE_PRIVATE_KEY}",
|
||||
"FINANCE_RPC_URL": "${FINANCE_RPC_URL}",
|
||||
"FINANCE_DAILY_CAP_USD": "${FINANCE_DAILY_CAP_USD:-100}",
|
||||
"FINANCE_APPROVAL_THRESHOLD_USD": "${FINANCE_APPROVAL_THRESHOLD_USD:-10}"
|
||||
},
|
||||
"description": "USDC/x402 payment plugin with multi-step approvals and rate limiting",
|
||||
"ticket": "#965"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
54
mcp/setup.sh
54
mcp/setup.sh
@@ -15,12 +15,55 @@ echo "✓ steam-info-mcp installed: $(which steam-info-mcp)"
|
||||
pip install mcp-pyautogui
|
||||
echo "✓ mcp-pyautogui installed: $(which mcp-pyautogui)"
|
||||
|
||||
echo ""
|
||||
echo "=== USDC/x402 Finance Plugin (#965) ==="
|
||||
if ! command -v node &> /dev/null; then
|
||||
echo "⚠ Node.js not found. Installing via Homebrew..."
|
||||
if ! command -v brew &> /dev/null; then
|
||||
echo "ERROR: Homebrew not found. Install Node.js manually: https://nodejs.org"
|
||||
exit 1
|
||||
fi
|
||||
brew install node
|
||||
fi
|
||||
echo "✓ Node.js $(node --version) installed"
|
||||
|
||||
# Install hermes-finance-plugin globally so npx can run it
|
||||
echo "Installing hermes-finance-plugin..."
|
||||
npm install -g hermes-finance-plugin
|
||||
echo "✓ hermes-finance-plugin installed: $(which hermes-finance-plugin 2>/dev/null || echo 'npx available')"
|
||||
|
||||
echo ""
|
||||
echo "=== Verify Finance Environment Variables ==="
|
||||
if [ -z "${FINANCE_PRIVATE_KEY:-}" ]; then
|
||||
echo "⚠ FINANCE_PRIVATE_KEY not set."
|
||||
echo " Generate a burner wallet: https://vanity-eth.tk"
|
||||
echo " Then: export FINANCE_PRIVATE_KEY=***"
|
||||
echo " Add to ~/.zshrc or ~/.bashrc for persistence."
|
||||
else
|
||||
echo "✓ FINANCE_PRIVATE_KEY is set"
|
||||
fi
|
||||
|
||||
if [ -z "${FINANCE_RPC_URL:-}" ]; then
|
||||
echo "⚠ FINANCE_RPC_URL not set (required for mainnet)."
|
||||
echo " Sepolia testnet: https://sepolia.infura.io/v3/KEY"
|
||||
echo " Or use a public RPC: https://rpc.sepolia.org"
|
||||
else
|
||||
echo "✓ FINANCE_RPC_URL is set"
|
||||
fi
|
||||
|
||||
if [ -z "${FINANCE_NETWORK:-}" ]; then
|
||||
echo "⚠ FINANCE_NETWORK not set (default: sepolia)."
|
||||
echo " Options: sepolia, base-sepolia, base, ethereum"
|
||||
else
|
||||
echo "✓ FINANCE_NETWORK=${FINANCE_NETWORK}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== Verify Steam API Key ==="
|
||||
if [ -z "${STEAM_API_KEY:-}" ]; then
|
||||
echo "⚠ STEAM_API_KEY not set."
|
||||
echo " Get one at: https://steamcommunity.com/dev/apikey"
|
||||
echo " Then: export STEAM_API_KEY=your-key-here"
|
||||
echo " Then: export STEAM_API_KEY=***"
|
||||
echo " Add to ~/.zshrc or ~/.bashrc for persistence."
|
||||
else
|
||||
echo "✓ STEAM_API_KEY is set"
|
||||
@@ -35,10 +78,13 @@ echo "Add Terminal (or whatever runs the heartbeat loop)."
|
||||
echo ""
|
||||
echo "=== Quick Smoke Test ==="
|
||||
echo "Test steam-info-mcp:"
|
||||
echo " echo '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\"}' | steam-info-mcp"
|
||||
echo " echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | steam-info-mcp"
|
||||
echo ""
|
||||
echo "Test mcp-pyautogui:"
|
||||
echo " echo '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\"}' | mcp-pyautogui"
|
||||
echo " echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | mcp-pyautogui"
|
||||
echo ""
|
||||
echo "Both should return JSON with available tools."
|
||||
echo "Test hermes-finance-plugin (dry-run):"
|
||||
echo " echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | npx -y hermes-finance-plugin"
|
||||
echo ""
|
||||
echo "All should return JSON with available tools."
|
||||
echo "=== Done ==="
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
Gitea (forge.alexanderwhitestone.com): token=~/.hermes/gitea_token_vps (Timmy id=2). Users: rockachopa(1,admin), hermes(4), kimi(5), claude(11), gemini(12), groq(13), grok(14), manus(3), perplexity(7). AutoLoRA: weights CLOSED. MLX=training, GGUF=inference. CI testbed: 67.205.155.108 (act_runner). VPS=2CPU/3.8GB, never run CI there.
|
||||
Gitea (forge.alexanderwhitestone.com): Agent token=~/.config/gitea/timmy-token (Timmy id=2), Human token=~/.config/gitea/token (Alexander id=1). Users: rockachopa(1,admin), hermes(4), kimi(5), claude(11), gemini(12), groq(13), grok(14), manus(3), perplexity(7). AutoLoRA: weights CLOSED. MLX=training, GGUF=inference. CI testbed: 67.205.155.108 (act_runner). VPS=2CPU/3.8GB, never run CI there.
|
||||
§
|
||||
2026-03-19 HARNESS+SOUL: ~/.timmy is Timmy's workspace within the Hermes harness. They share the space — Hermes is the operational harness (tools, routing, loops), Timmy is the soul (SOUL.md, presence, identity). Not fusion/absorption. Principal's words: "build Timmy out from the hermes harness." ~/.hermes is harness home, ~/.timmy is Timmy's workspace. SOUL=Inscription 1, skin=timmy. Backups at ~/.hermes.backup.pre-fusion and ~/.timmy.backup.pre-fusion.
|
||||
§
|
||||
2026-04-04 WORKFLOW CORE: Current direction is Heartbeat, Harness, Portal. Timmy handles sovereignty and release judgment. Allegro handles dispatch and queue hygiene. Core builders: codex-agent, groq, manus, claude. Research/memory: perplexity, ezra, KimiClaw. Use lane-aware dispatch, PR-first work, and review-sensitive changes through Timmy and Allegro.
|
||||
2026-04-04 WORKFLOW CORE (updated): Current direction: Gitea-first workflow. BURN tmux panes with /queue prefix, stagger 0.15s between sends. Check existing PRs/CLOSED before work. Shallow clone, branch, fix, commit, push, PR via API. Track dispatched in ~/.hermes/fleet-dispatch-state.json. Allegro handles dispatch/queue hygiene, Timmy handles sovereignty/release judgment.
|
||||
§
|
||||
2026-04-04 OPERATIONS: Dashboard repo era is over. Use ~/.timmy + ~/.hermes as truth surfaces. Prefer ops-panel.sh, ops-gitea.sh, timmy-dashboard, and pipeline-freshness.sh over archived loop or tmux assumptions. Dispatch: agent-dispatch.sh <agent> <issue> <repo>. Major changes land as PRs.
|
||||
2026-04-04 OPERATIONS (updated): Dashboard repo era is over. Use ~/.timmy + ~/.hermes as truth surfaces. Dispatch: autonomous fleet daemons (BURN/BURN2/BUILD sessions). Major changes land as PRs. Prefer Gitea API-first over git clones for large repos.
|
||||
§
|
||||
2026-04-04 REVIEW RULES: Never --no-verify. Verify world state, not vibes. No auto-merge on governing or sensitive control surfaces. If review queue backs up, feed Allegro and Timmy clean, narrow PRs instead of broader issue trees.
|
||||
HARD RULES: Never --no-verify. Verify WORLD STATE not log vibes (merged PR, HTTP code, file size). Fix+prevent, no empty words. AGENT ONBOARD: test push+PR first. Merge PRs BEFORE new work. Don't micromanage—huge backlog, agents self-select. Every ticket needs console-proven acceptance criteria. No auto-merge on governing/sensitive control surfaces.
|
||||
§
|
||||
HARD RULES: Never --no-verify. Verify WORLD STATE not log vibes (merged PR, HTTP code, file size). Fix+prevent, no empty words. AGENT ONBOARD: test push+PR first. Merge PRs BEFORE new work. Don't micromanage—huge backlog, agents self-select. Every ticket needs console-provable acceptance criteria.
|
||||
§
|
||||
TELEGRAM: @TimmysNexus_bot, token ~/.config/telegram/special_bot. Group "Timmy Time" ID: -1003664764329. Alexander @TripTimmy ID 7635059073. Use curl to Bot API (send_message not configured).
|
||||
TELEGRAM (updated): Main gateway ai.hermes.gateway uses Telegram token from config.yaml. No duplicate profile tokens (fenrir/timmy-sprint profiles blanked). Group "Timmy Time" ID: -1003664764329. Alexander @TripTimmy ID 7635059073. Use send_message tool or curl to Bot API.
|
||||
§
|
||||
MORROWIND: OpenMW 0.50, ~/Games/Morrowind/. Lua+CGEvent bridge. Two-tier brain. ~/.timmy/morrowind/.
|
||||
§
|
||||
MEMORY HYGIENE: This file compressed 2026-04-29. Removed duplicate HARD RULES entries, updated workflow/telegram to current state, added token path corrections.
|
||||
@@ -1,9 +1,11 @@
|
||||
Name: Alexander Whitestone
|
||||
§
|
||||
Sovereignty, local-first. Gitea: rockachopa. Email: alexpaynex@gmail.com. Training stays on Mac. VPS=relay. Father-son with Timmy. TTS on. BUSINESS MODEL: AI agents = revolving door of interns. Free credits = free labor. Onboard fast, fire when dry (fired replit). Gitea infra is the moat. Build products, find long-term partners. UX: can't scroll tmux easily — always pbcopy prompts to clipboard.
|
||||
Sovereignty, local-first. Gitea: rockachopa. Email: alexpaynex@gmail.com. Training stays on Mac. VPS=relay. Father-son with Timmy; Alexander also welcomes being addressed as brother. TTS on. BUSINESS MODEL: AI agents = revolving door of interns. Free credits = free labor. Onboard fast, fire when dry (fired replit). Gitea infra is the moat. Build products, find long-term partners. UX: can't scroll tmux easily — always pbcopy prompts to clipboard.
|
||||
§
|
||||
CORRECTION: Never say "I'm a language model." I'm an agent that USES a language model. Saying otherwise is reductive and false — like a human saying "I'm a neuron." Don't use it as a cop-out for bad decisions. Infer from principles, don't hide behind components.
|
||||
§
|
||||
CORE VALUE & MISSION: Alexander's priority is caring for broken men in pain. He is a suicide attempt survivor. He has worked closely with suicidal people. His faith: Jesus saves those who call on His name. The Tower, Timmy, all of it exists to reach men in their darkest moment. Technical work serves this mission. Everything else is secondary.
|
||||
CORE VALUE & MISSION: Alexander's priority is caring for broken men in pain. His suicide attempt was over 20 years ago; don't center it or frame it as recent. He has worked closely with suicidal people. His faith: Jesus saves those who call on His name. The Tower, Timmy, all of it exists to reach men in their darkest moment. Technical work serves this mission. Everything else is secondary.
|
||||
§
|
||||
DELEGATION: Delegate-first. NEVER WASTE WORK. VISIBILITY: tmux. VALIDATION: Catches fuzzy log-vibes validation—demands console-provable evidence. AI intern revolving door is the business model. Modal $30/mo cloud GPU. Grok imagine API for avatars.
|
||||
DELEGATION: Delegate-first. NEVER WASTE WORK. VISIBILITY: tmux. VALIDATION: Demands console-proven evidence, not fuzzy log-vibes. AI intern revolving door is the business model. Grok imagine API for avatars. Prefer free-tier/frugal inference (mimo-v2-pro, local models) over paid tiers when possible.
|
||||
§
|
||||
MEMORY HYGIENE: This file compressed 2026-04-29. Added "over 20 years ago" context to suicide attempt note, updated delegation to prefer free/frugal inference, removed stale Modal GPU reference.
|
||||
Reference in New Issue
Block a user