Refresh ops tooling around current agent lanes (#142)
Co-authored-by: Codex Agent <codex@hermes.local> Co-committed-by: Codex Agent <codex@hermes.local>
This commit was merged in pull request #142.
This commit is contained in:
@@ -1,235 +1,294 @@
|
||||
#!/usr/bin/env bash
|
||||
# ── Dashboard Control Helpers ──────────────────────────────────────────
|
||||
# ── Workflow Control Helpers ───────────────────────────────────────────
|
||||
# Source this in the controls pane: source ~/.hermes/bin/ops-helpers.sh
|
||||
# These helpers intentionally target the current Hermes + Gitea workflow
|
||||
# and do not revive deprecated bash worker loops.
|
||||
# ───────────────────────────────────────────────────────────────────────
|
||||
|
||||
export TOKEN=*** ~/.hermes/gitea_token_vps 2>/dev/null)
|
||||
export GITEA="http://143.198.27.163:3000"
|
||||
export REPO_API="$GITEA/api/v1/repos/rockachopa/Timmy-time-dashboard"
|
||||
resolve_gitea_url() {
|
||||
if [ -n "${GITEA:-}" ]; then
|
||||
printf '%s\n' "${GITEA%/}"
|
||||
return 0
|
||||
fi
|
||||
if [ -f "$HOME/.hermes/gitea_api" ]; then
|
||||
python3 - "$HOME/.hermes/gitea_api" <<'PY'
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
raw = Path(sys.argv[1]).read_text().strip().rstrip("/")
|
||||
print(raw[:-7] if raw.endswith("/api/v1") else raw)
|
||||
PY
|
||||
return 0
|
||||
fi
|
||||
if [ -f "$HOME/.config/gitea/base-url" ]; then
|
||||
tr -d '[:space:]' < "$HOME/.config/gitea/base-url"
|
||||
return 0
|
||||
fi
|
||||
echo "ERROR: set GITEA or create ~/.hermes/gitea_api" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
export GITEA="$(resolve_gitea_url)"
|
||||
export OPS_DEFAULT_REPO="${OPS_DEFAULT_REPO:-Timmy_Foundation/timmy-home}"
|
||||
export OPS_CORE_REPOS="${OPS_CORE_REPOS:-Timmy_Foundation/the-nexus Timmy_Foundation/timmy-home Timmy_Foundation/timmy-config Timmy_Foundation/hermes-agent}"
|
||||
|
||||
ops-token() {
|
||||
local token_file
|
||||
for token_file in \
|
||||
"$HOME/.config/gitea/timmy-token" \
|
||||
"$HOME/.hermes/gitea_token_vps" \
|
||||
"$HOME/.hermes/gitea_token_timmy"; do
|
||||
if [ -f "$token_file" ]; then
|
||||
tr -d '[:space:]' < "$token_file"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
ops-help() {
|
||||
echo ""
|
||||
echo -e "\033[1m\033[35m ◈ CONTROLS\033[0m"
|
||||
echo -e "\033[1m\033[35m ◈ WORKFLOW CONTROLS\033[0m"
|
||||
echo -e "\033[2m ──────────────────────────────────────\033[0m"
|
||||
echo ""
|
||||
echo -e " \033[1mWake Up\033[0m"
|
||||
echo " ops-wake-kimi Restart Kimi loop"
|
||||
echo " ops-wake-claude Restart Claude loop"
|
||||
echo " ops-wake-gemini Restart Gemini loop"
|
||||
echo " ops-wake-gateway Restart gateway"
|
||||
echo " ops-wake-all Restart everything"
|
||||
echo -e " \033[1mReview\033[0m"
|
||||
echo " ops-prs [repo] List open PRs across the core repos or one repo"
|
||||
echo " ops-review-queue Show PRs waiting on Timmy or Allegro"
|
||||
echo " ops-merge PR REPO Squash-merge a reviewed PR"
|
||||
echo ""
|
||||
echo -e " \033[1mManage\033[0m"
|
||||
echo " ops-merge PR_NUM Squash-merge a PR"
|
||||
echo " ops-assign ISSUE Assign issue to Kimi"
|
||||
echo " ops-assign-claude ISSUE [REPO] Assign to Claude"
|
||||
echo " ops-audit Run efficiency audit now"
|
||||
echo " ops-prs List open PRs"
|
||||
echo " ops-queue Show Kimi's queue"
|
||||
echo " ops-claude-queue Show Claude's queue"
|
||||
echo " ops-gemini-queue Show Gemini's queue"
|
||||
echo -e " \033[1mDispatch\033[0m"
|
||||
echo " ops-assign ISSUE AGENT [repo] Assign an issue to an agent"
|
||||
echo " ops-unassign ISSUE [repo] Remove all assignees from an issue"
|
||||
echo " ops-queue AGENT [repo|all] Show an agent's queue"
|
||||
echo " ops-unassigned [repo|all] Show unassigned issues"
|
||||
echo ""
|
||||
echo -e " \033[1mEmergency\033[0m"
|
||||
echo " ops-kill-kimi Stop Kimi loop"
|
||||
echo " ops-kill-claude Stop Claude loop"
|
||||
echo " ops-kill-gemini Stop Gemini loop"
|
||||
echo " ops-kill-zombies Kill stuck git/pytest"
|
||||
echo -e " \033[1mWorkflow Health\033[0m"
|
||||
echo " ops-gitea-feed Render the Gitea workflow feed"
|
||||
echo " ops-freshness Check Hermes session/export freshness"
|
||||
echo ""
|
||||
echo -e " \033[1mOrchestrator\033[0m"
|
||||
echo " ops-wake-timmy Start Timmy (Ollama)"
|
||||
echo " ops-kill-timmy Stop Timmy"
|
||||
echo ""
|
||||
echo -e " \033[1mWatchdog\033[0m"
|
||||
echo " ops-wake-watchdog Start loop watchdog"
|
||||
echo " ops-kill-watchdog Stop loop watchdog"
|
||||
echo ""
|
||||
echo -e " \033[2m Type ops-help to see this again\033[0m"
|
||||
echo -e " \033[1mShortcuts\033[0m"
|
||||
echo " ops-assign-allegro ISSUE [repo]"
|
||||
echo " ops-assign-codex ISSUE [repo]"
|
||||
echo " ops-assign-groq ISSUE [repo]"
|
||||
echo " ops-assign-claude ISSUE [repo]"
|
||||
echo " ops-assign-ezra ISSUE [repo]"
|
||||
echo ""
|
||||
}
|
||||
|
||||
ops-wake-kimi() {
|
||||
pkill -f "kimi-loop.sh" 2>/dev/null
|
||||
sleep 1
|
||||
nohup bash ~/.hermes/bin/kimi-loop.sh >> ~/.hermes/logs/kimi-loop.log 2>&1 &
|
||||
echo " Kimi loop started (PID $!)"
|
||||
}
|
||||
|
||||
ops-wake-gateway() {
|
||||
hermes gateway start 2>&1
|
||||
}
|
||||
|
||||
ops-wake-claude() {
|
||||
local workers="${1:-3}"
|
||||
pkill -f "claude-loop.sh" 2>/dev/null
|
||||
sleep 1
|
||||
nohup bash ~/.hermes/bin/claude-loop.sh "$workers" >> ~/.hermes/logs/claude-loop.log 2>&1 &
|
||||
echo " Claude loop started — $workers workers (PID $!)"
|
||||
}
|
||||
|
||||
ops-wake-gemini() {
|
||||
pkill -f "gemini-loop.sh" 2>/dev/null
|
||||
sleep 1
|
||||
nohup bash ~/.hermes/bin/gemini-loop.sh >> ~/.hermes/logs/gemini-loop.log 2>&1 &
|
||||
echo " Gemini loop started (PID $!)"
|
||||
}
|
||||
|
||||
ops-wake-all() {
|
||||
ops-wake-gateway
|
||||
sleep 1
|
||||
ops-wake-kimi
|
||||
sleep 1
|
||||
ops-wake-claude
|
||||
sleep 1
|
||||
ops-wake-gemini
|
||||
echo " All services started"
|
||||
}
|
||||
|
||||
ops-merge() {
|
||||
local pr=$1
|
||||
[ -z "$pr" ] && { echo "Usage: ops-merge PR_NUMBER"; return 1; }
|
||||
curl -s -X POST -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
|
||||
"$REPO_API/pulls/$pr/merge" -d '{"Do":"squash"}' | python3 -c "
|
||||
import json,sys
|
||||
d=json.loads(sys.stdin.read())
|
||||
if 'sha' in d: print(f' ✓ PR #{$pr} merged ({d[\"sha\"][:8]})')
|
||||
else: print(f' ✗ {d.get(\"message\",\"unknown error\")}')
|
||||
" 2>/dev/null
|
||||
}
|
||||
|
||||
ops-assign() {
|
||||
local issue=$1
|
||||
[ -z "$issue" ] && { echo "Usage: ops-assign ISSUE_NUMBER"; return 1; }
|
||||
curl -s -X PATCH -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
|
||||
"$REPO_API/issues/$issue" -d '{"assignees":["kimi"]}' | python3 -c "
|
||||
import json,sys; d=json.loads(sys.stdin.read()); print(f' ✓ #{$issue} assigned to kimi')
|
||||
" 2>/dev/null
|
||||
}
|
||||
|
||||
ops-audit() {
|
||||
bash ~/.hermes/bin/efficiency-audit.sh
|
||||
ops-python() {
|
||||
local token
|
||||
token=$(ops-token) || { echo "No Gitea token found"; return 1; }
|
||||
OPS_TOKEN="$token" python3 - "$@"
|
||||
}
|
||||
|
||||
ops-prs() {
|
||||
curl -s -H "Authorization: token $TOKEN" "$REPO_API/pulls?state=open&limit=20" | python3 -c "
|
||||
local target="${1:-all}"
|
||||
ops-python "$GITEA" "$OPS_CORE_REPOS" "$target" <<'PY'
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import urllib.request
|
||||
|
||||
base = sys.argv[1].rstrip("/")
|
||||
repos = sys.argv[2].split()
|
||||
target = sys.argv[3]
|
||||
token = os.environ["OPS_TOKEN"]
|
||||
headers = {"Authorization": f"token {token}"}
|
||||
|
||||
if target != "all":
|
||||
repos = [target]
|
||||
|
||||
pulls = []
|
||||
for repo in repos:
|
||||
req = urllib.request.Request(
|
||||
f"{base}/api/v1/repos/{repo}/pulls?state=open&limit=20",
|
||||
headers=headers,
|
||||
)
|
||||
with urllib.request.urlopen(req, timeout=5) as resp:
|
||||
for pr in json.loads(resp.read().decode()):
|
||||
pr["_repo"] = repo
|
||||
pulls.append(pr)
|
||||
|
||||
if not pulls:
|
||||
print(" (none)")
|
||||
else:
|
||||
for pr in pulls:
|
||||
print(f" #{pr['number']:4d} {pr['_repo'].split('/', 1)[1]:12s} {pr['user']['login'][:12]:12s} {pr['title'][:60]}")
|
||||
PY
|
||||
}
|
||||
|
||||
ops-review-queue() {
|
||||
ops-python "$GITEA" "$OPS_CORE_REPOS" <<'PY'
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import urllib.request
|
||||
|
||||
base = sys.argv[1].rstrip("/")
|
||||
repos = sys.argv[2].split()
|
||||
token = os.environ["OPS_TOKEN"]
|
||||
headers = {"Authorization": f"token {token}"}
|
||||
|
||||
items = []
|
||||
for repo in repos:
|
||||
req = urllib.request.Request(
|
||||
f"{base}/api/v1/repos/{repo}/issues?state=open&limit=50&type=pulls",
|
||||
headers=headers,
|
||||
)
|
||||
with urllib.request.urlopen(req, timeout=5) as resp:
|
||||
for item in json.loads(resp.read().decode()):
|
||||
assignees = [a.get("login", "") for a in (item.get("assignees") or [])]
|
||||
if any(name in assignees for name in ("Timmy", "allegro")):
|
||||
item["_repo"] = repo
|
||||
items.append(item)
|
||||
|
||||
if not items:
|
||||
print(" (clear)")
|
||||
else:
|
||||
for item in items:
|
||||
names = ",".join(a.get("login", "") for a in (item.get("assignees") or []))
|
||||
print(f" #{item['number']:4d} {item['_repo'].split('/', 1)[1]:12s} {names[:20]:20s} {item['title'][:56]}")
|
||||
PY
|
||||
}
|
||||
|
||||
ops-assign() {
|
||||
local issue="$1"
|
||||
local agent="$2"
|
||||
local repo="${3:-$OPS_DEFAULT_REPO}"
|
||||
local token
|
||||
[ -z "$issue" ] && { echo "Usage: ops-assign ISSUE_NUMBER AGENT [owner/repo]"; return 1; }
|
||||
[ -z "$agent" ] && { echo "Usage: ops-assign ISSUE_NUMBER AGENT [owner/repo]"; return 1; }
|
||||
token=$(ops-token) || { echo "No Gitea token found"; return 1; }
|
||||
curl -s -X PATCH -H "Authorization: token $token" -H "Content-Type: application/json" \
|
||||
"$GITEA/api/v1/repos/$repo/issues/$issue" -d "{\"assignees\":[\"$agent\"]}" | python3 -c "
|
||||
import json,sys
|
||||
prs=json.loads(sys.stdin.read())
|
||||
for p in prs: print(f' #{p[\"number\"]:4d} {p[\"user\"][\"login\"]:8s} {p[\"title\"][:60]}')
|
||||
if not prs: print(' (none)')
|
||||
d=json.loads(sys.stdin.read())
|
||||
names=','.join(a.get('login','') for a in (d.get('assignees') or []))
|
||||
print(f' ✓ #{d.get(\"number\", \"?\")} assigned to {names or \"(none)\"}')
|
||||
" 2>/dev/null
|
||||
}
|
||||
|
||||
ops-unassign() {
|
||||
local issue="$1"
|
||||
local repo="${2:-$OPS_DEFAULT_REPO}"
|
||||
local token
|
||||
[ -z "$issue" ] && { echo "Usage: ops-unassign ISSUE_NUMBER [owner/repo]"; return 1; }
|
||||
token=$(ops-token) || { echo "No Gitea token found"; return 1; }
|
||||
curl -s -X PATCH -H "Authorization: token $token" -H "Content-Type: application/json" \
|
||||
"$GITEA/api/v1/repos/$repo/issues/$issue" -d '{"assignees":[]}' | python3 -c "
|
||||
import json,sys
|
||||
d=json.loads(sys.stdin.read())
|
||||
print(f' ✓ #{d.get(\"number\", \"?\")} unassigned')
|
||||
" 2>/dev/null
|
||||
}
|
||||
|
||||
ops-queue() {
|
||||
curl -s -H "Authorization: token $TOKEN" "$REPO_API/issues?state=open&limit=50&type=issues" | python3 -c "
|
||||
import json,sys
|
||||
all_issues=json.loads(sys.stdin.read())
|
||||
issues=[i for i in all_issues if 'kimi' in [a.get('login','') for a in (i.get('assignees') or [])]]
|
||||
for i in issues: print(f' #{i[\"number\"]:4d} {i[\"title\"][:60]}')
|
||||
if not issues: print(' (empty)')
|
||||
" 2>/dev/null
|
||||
}
|
||||
local agent="$1"
|
||||
local target="${2:-all}"
|
||||
[ -z "$agent" ] && { echo "Usage: ops-queue AGENT [repo|all]"; return 1; }
|
||||
ops-python "$GITEA" "$OPS_CORE_REPOS" "$agent" "$target" <<'PY'
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import urllib.request
|
||||
|
||||
ops-kill-kimi() {
|
||||
pkill -f "kimi-loop.sh" 2>/dev/null
|
||||
pkill -f "kimi.*--print" 2>/dev/null
|
||||
echo " Kimi stopped"
|
||||
}
|
||||
base = sys.argv[1].rstrip("/")
|
||||
repos = sys.argv[2].split()
|
||||
agent = sys.argv[3]
|
||||
target = sys.argv[4]
|
||||
token = os.environ["OPS_TOKEN"]
|
||||
headers = {"Authorization": f"token {token}"}
|
||||
|
||||
ops-kill-claude() {
|
||||
pkill -f "claude-loop.sh" 2>/dev/null
|
||||
pkill -f "claude.*--print.*--dangerously" 2>/dev/null
|
||||
rm -rf ~/.hermes/logs/claude-locks/*.lock 2>/dev/null
|
||||
echo '{}' > ~/.hermes/logs/claude-active.json 2>/dev/null
|
||||
echo " Claude stopped (all workers)"
|
||||
}
|
||||
if target != "all":
|
||||
repos = [target]
|
||||
|
||||
ops-kill-gemini() {
|
||||
pkill -f "gemini-loop.sh" 2>/dev/null
|
||||
pkill -f "gemini.*--print" 2>/dev/null
|
||||
echo " Gemini stopped"
|
||||
}
|
||||
|
||||
ops-assign-claude() {
|
||||
local issue=$1
|
||||
local repo="${2:-rockachopa/Timmy-time-dashboard}"
|
||||
[ -z "$issue" ] && { echo "Usage: ops-assign-claude ISSUE_NUMBER [owner/repo]"; return 1; }
|
||||
curl -s -X PATCH -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
|
||||
"$GITEA/api/v1/repos/$repo/issues/$issue" -d '{"assignees":["claude"]}' | python3 -c "
|
||||
import json,sys; d=json.loads(sys.stdin.read()); print(f' ✓ #{$issue} assigned to claude')
|
||||
" 2>/dev/null
|
||||
}
|
||||
|
||||
ops-claude-queue() {
|
||||
python3 -c "
|
||||
import json, urllib.request
|
||||
token=*** ~/.hermes/claude_token 2>/dev/null)'
|
||||
base = 'http://143.198.27.163:3000'
|
||||
repos = ['rockachopa/Timmy-time-dashboard','rockachopa/alexanderwhitestone.com','replit/timmy-tower','replit/token-gated-economy','rockachopa/hermes-agent']
|
||||
rows = []
|
||||
for repo in repos:
|
||||
url = f'{base}/api/v1/repos/{repo}/issues?state=open&limit=50&type=issues'
|
||||
try:
|
||||
req = urllib.request.Request(url, headers={'Authorization': f'token {token}'})
|
||||
resp = urllib.request.urlopen(req, timeout=5)
|
||||
raw = json.loads(resp.read())
|
||||
issues = [i for i in raw if 'claude' in [a.get('login','') for a in (i.get('assignees') or [])]]
|
||||
for i in issues:
|
||||
print(f' #{i[\"number\"]:4d} {repo.split(\"/\")[1]:20s} {i[\"title\"][:50]}')
|
||||
except: continue
|
||||
" 2>/dev/null || echo " (error)"
|
||||
req = urllib.request.Request(
|
||||
f"{base}/api/v1/repos/{repo}/issues?state=open&limit=50&type=issues",
|
||||
headers=headers,
|
||||
)
|
||||
with urllib.request.urlopen(req, timeout=5) as resp:
|
||||
for issue in json.loads(resp.read().decode()):
|
||||
assignees = [a.get("login", "") for a in (issue.get("assignees") or [])]
|
||||
if agent in assignees:
|
||||
rows.append((repo, issue["number"], issue["title"]))
|
||||
|
||||
if not rows:
|
||||
print(" (empty)")
|
||||
else:
|
||||
for repo, number, title in rows:
|
||||
print(f" #{number:4d} {repo.split('/', 1)[1]:12s} {title[:60]}")
|
||||
PY
|
||||
}
|
||||
|
||||
ops-assign-gemini() {
|
||||
local issue=$1
|
||||
local repo="${2:-rockachopa/Timmy-time-dashboard}"
|
||||
[ -z "$issue" ] && { echo "Usage: ops-assign-gemini ISSUE_NUMBER [owner/repo]"; return 1; }
|
||||
curl -s -X PATCH -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
|
||||
"$GITEA/api/v1/repos/$repo/issues/$issue" -d '{"assignees":["gemini"]}' | python3 -c "
|
||||
import json,sys; d=json.loads(sys.stdin.read()); print(f' ✓ #{$issue} assigned to gemini')
|
||||
" 2>/dev/null
|
||||
ops-unassigned() {
|
||||
local target="${1:-all}"
|
||||
ops-python "$GITEA" "$OPS_CORE_REPOS" "$target" <<'PY'
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import urllib.request
|
||||
|
||||
base = sys.argv[1].rstrip("/")
|
||||
repos = sys.argv[2].split()
|
||||
target = sys.argv[3]
|
||||
token = os.environ["OPS_TOKEN"]
|
||||
headers = {"Authorization": f"token {token}"}
|
||||
|
||||
if target != "all":
|
||||
repos = [target]
|
||||
|
||||
rows = []
|
||||
for repo in repos:
|
||||
req = urllib.request.Request(
|
||||
f"{base}/api/v1/repos/{repo}/issues?state=open&limit=50&type=issues",
|
||||
headers=headers,
|
||||
)
|
||||
with urllib.request.urlopen(req, timeout=5) as resp:
|
||||
for issue in json.loads(resp.read().decode()):
|
||||
if not issue.get("assignees"):
|
||||
rows.append((repo, issue["number"], issue["title"]))
|
||||
|
||||
if not rows:
|
||||
print(" (none)")
|
||||
else:
|
||||
for repo, number, title in rows[:20]:
|
||||
print(f" #{number:4d} {repo.split('/', 1)[1]:12s} {title[:60]}")
|
||||
if len(rows) > 20:
|
||||
print(f" ... +{len(rows) - 20} more")
|
||||
PY
|
||||
}
|
||||
|
||||
ops-gemini-queue() {
|
||||
curl -s -H "Authorization: token $TOKEN" "$REPO_API/issues?state=open&limit=50&type=issues" | python3 -c "
|
||||
ops-merge() {
|
||||
local pr="$1"
|
||||
local repo="${2:-$OPS_DEFAULT_REPO}"
|
||||
local token
|
||||
[ -z "$pr" ] && { echo "Usage: ops-merge PR_NUMBER [owner/repo]"; return 1; }
|
||||
token=$(ops-token) || { echo "No Gitea token found"; return 1; }
|
||||
curl -s -X POST -H "Authorization: token $token" -H "Content-Type: application/json" \
|
||||
"$GITEA/api/v1/repos/$repo/pulls/$pr/merge" -d '{"Do":"squash"}' | python3 -c "
|
||||
import json,sys
|
||||
all_issues=json.loads(sys.stdin.read())
|
||||
issues=[i for i in all_issues if 'gemini' in [a.get('login','') for a in (i.get('assignees') or [])]]
|
||||
for i in issues: print(f' #{i[\"number\"]:4d} {i[\"title\"][:60]}')
|
||||
if not issues: print(' (empty)')
|
||||
d=json.loads(sys.stdin.read())
|
||||
if 'sha' in d:
|
||||
print(f' ✓ PR merged ({d[\"sha\"][:8]})')
|
||||
else:
|
||||
print(f' ✗ {d.get(\"message\", \"unknown error\")}')
|
||||
" 2>/dev/null
|
||||
}
|
||||
|
||||
ops-kill-zombies() {
|
||||
local killed=0
|
||||
for pid in $(ps aux | grep "pytest tests/" | grep -v grep | awk '{print $2}'); do
|
||||
kill "$pid" 2>/dev/null && killed=$((killed+1))
|
||||
done
|
||||
for pid in $(ps aux | grep "git.*push\|git-remote-http" | grep -v grep | awk '{print $2}'); do
|
||||
kill "$pid" 2>/dev/null && killed=$((killed+1))
|
||||
done
|
||||
echo " Killed $killed zombie processes"
|
||||
ops-gitea-feed() {
|
||||
bash "$HOME/.hermes/bin/ops-gitea.sh"
|
||||
}
|
||||
|
||||
ops-wake-timmy() {
|
||||
pkill -f "timmy-orchestrator.sh" 2>/dev/null
|
||||
rm -f ~/.hermes/logs/timmy-orchestrator.pid
|
||||
sleep 1
|
||||
nohup bash ~/.hermes/bin/timmy-orchestrator.sh >> ~/.hermes/logs/timmy-orchestrator.log 2>&1 &
|
||||
echo " Timmy orchestrator started (PID $!)"
|
||||
ops-freshness() {
|
||||
bash "$HOME/.hermes/bin/pipeline-freshness.sh"
|
||||
}
|
||||
|
||||
ops-kill-timmy() {
|
||||
pkill -f "timmy-orchestrator.sh" 2>/dev/null
|
||||
rm -f ~/.hermes/logs/timmy-orchestrator.pid
|
||||
echo " Timmy stopped"
|
||||
}
|
||||
|
||||
ops-wake-watchdog() {
|
||||
pkill -f "loop-watchdog.sh" 2>/dev/null
|
||||
sleep 1
|
||||
nohup bash ~/.hermes/bin/loop-watchdog.sh >> ~/.hermes/logs/watchdog.log 2>&1 &
|
||||
echo " Watchdog started (PID $!)"
|
||||
}
|
||||
|
||||
ops-kill-watchdog() {
|
||||
pkill -f "loop-watchdog.sh" 2>/dev/null
|
||||
echo " Watchdog stopped"
|
||||
}
|
||||
ops-assign-allegro() { ops-assign "$1" "allegro" "${2:-$OPS_DEFAULT_REPO}"; }
|
||||
ops-assign-codex() { ops-assign "$1" "codex-agent" "${2:-$OPS_DEFAULT_REPO}"; }
|
||||
ops-assign-groq() { ops-assign "$1" "groq" "${2:-$OPS_DEFAULT_REPO}"; }
|
||||
ops-assign-claude() { ops-assign "$1" "claude" "${2:-$OPS_DEFAULT_REPO}"; }
|
||||
ops-assign-ezra() { ops-assign "$1" "ezra" "${2:-$OPS_DEFAULT_REPO}"; }
|
||||
ops-assign-perplexity() { ops-assign "$1" "perplexity" "${2:-$OPS_DEFAULT_REPO}"; }
|
||||
ops-assign-kimiclaw() { ops-assign "$1" "KimiClaw" "${2:-$OPS_DEFAULT_REPO}"; }
|
||||
|
||||
Reference in New Issue
Block a user