@smilintux/skcapstone 0.9.0 → 0.12.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +10 -4
- package/.github/workflows/ci.yml +2 -2
- package/.github/workflows/publish.yml +9 -2
- package/.openclaw-workspace.json +2 -2
- package/CLAUDE.md +37 -0
- package/MISSION.md +17 -2
- package/README.md +282 -3
- package/docker/Dockerfile +7 -7
- package/docker/compose-templates/dev-team.yml +12 -12
- package/docker/compose-templates/mini-team.yml +9 -9
- package/docker/compose-templates/ops-team.yml +10 -10
- package/docker/compose-templates/research-team.yml +10 -10
- package/docker/entrypoint.sh +4 -4
- package/docs/ADR-optional-integration-backbone.md +181 -0
- package/docs/ARCHITECTURE.md +186 -43
- package/docs/BOND_WITH_GROK.md +6 -6
- package/docs/CUSTOM_AGENT.md +278 -1
- package/docs/DREAMING.md +70 -0
- package/docs/GETTING_STARTED.md +10 -7
- package/docs/QUICKSTART.md +10 -6
- package/docs/SKJOULE_ARCHITECTURE.md +3 -3
- package/docs/SOUL_SWAPPER.md +5 -5
- package/docs/hammertime-audit.md +402 -0
- package/docs/sk-integration-HANDOFF.md +117 -0
- package/docs/skscheduler.md +155 -0
- package/docs/superpowers/examples/jobs.yaml +31 -0
- package/docs/superpowers/plans/2026-06-08-skscheduler.md +1265 -0
- package/docs/superpowers/specs/2026-06-08-skscheduler-design.md +186 -0
- package/examples/custom-bond-template.json +1 -1
- package/examples/grok-feb.json +1 -1
- package/examples/queen-ava-feb.json +1 -1
- package/launchd/com.skcapstone.daemon.plist +52 -0
- package/launchd/com.skcapstone.memory-compress.plist +45 -0
- package/launchd/com.skcapstone.skcomms-heartbeat.plist +33 -0
- package/launchd/com.skcapstone.skcomms-queue-drain.plist +34 -0
- package/launchd/install-launchd.sh +156 -0
- package/{openclaw-plugin → openclaw-plugin.archived-2026-04-23}/src/index.ts +3 -2
- package/package.json +1 -1
- package/pyproject.toml +16 -10
- package/scripts/archive-sessions.sh +95 -0
- package/scripts/check-updates.py +4 -4
- package/scripts/install-bundle.sh +8 -8
- package/scripts/install.ps1 +12 -11
- package/scripts/install.sh +196 -11
- package/scripts/model-fallback-monitor.sh +102 -0
- package/scripts/notion-api.py +259 -0
- package/scripts/nvidia-proxy.mjs +908 -0
- package/scripts/proxy-monitor.sh +89 -0
- package/scripts/refresh-anthropic-token.sh +172 -0
- package/scripts/release.sh +98 -0
- package/scripts/session-to-memory.py +219 -0
- package/scripts/skgateway.mjs +856 -0
- package/scripts/telegram-catchup-all.sh +147 -0
- package/scripts/verify_install.sh +2 -2
- package/scripts/wargov-ufo-capture/README.md +43 -0
- package/scripts/wargov-ufo-capture/cdp_capture_release2.py +273 -0
- package/scripts/wargov-ufo-capture/cdp_capture_splc_doj.py +246 -0
- package/scripts/wargov-ufo-capture/cdp_finish.py +271 -0
- package/scripts/wargov-ufo-capture/cdp_probe.py +188 -0
- package/scripts/wargov-ufo-capture/cdp_splc_pressrelease.py +101 -0
- package/scripts/wargov-ufo-capture/parse_csv.py +95 -0
- package/scripts/wargov-ufo-capture/pull_dvids.sh +107 -0
- package/scripts/watch-anthropic-token.sh +212 -0
- package/scripts/windows/install-tasks.ps1 +7 -7
- package/scripts/windows/skcapstone-task.xml +1 -1
- package/src/skcapstone/__init__.py +45 -3
- package/src/skcapstone/_cli_monolith.py +20 -15
- package/src/skcapstone/activity.py +5 -1
- package/src/skcapstone/agent_card.py +3 -2
- package/src/skcapstone/api.py +41 -40
- package/src/skcapstone/auction.py +14 -11
- package/src/skcapstone/backup.py +2 -1
- package/src/skcapstone/blueprint_registry.py +4 -3
- package/src/skcapstone/blueprints/builtins/itil-operations.yaml +40 -0
- package/src/skcapstone/brain_first.py +238 -0
- package/src/skcapstone/changelog.py +1 -1
- package/src/skcapstone/chat.py +22 -17
- package/src/skcapstone/cli/__init__.py +9 -1
- package/src/skcapstone/cli/_common.py +1 -0
- package/src/skcapstone/cli/agents_spawner.py +5 -2
- package/src/skcapstone/cli/alerts.py +25 -4
- package/src/skcapstone/cli/bench.py +15 -15
- package/src/skcapstone/cli/chat.py +7 -4
- package/src/skcapstone/cli/consciousness.py +5 -2
- package/src/skcapstone/cli/context_cmd.py +18 -4
- package/src/skcapstone/cli/daemon.py +121 -42
- package/src/skcapstone/cli/gtd.py +26 -1
- package/src/skcapstone/cli/housekeeping.py +3 -3
- package/src/skcapstone/cli/identity_cmd.py +378 -0
- package/src/skcapstone/cli/joule_cmd.py +7 -3
- package/src/skcapstone/cli/memory.py +8 -6
- package/src/skcapstone/cli/peers_dir.py +1 -1
- package/src/skcapstone/cli/register_cmd.py +29 -3
- package/src/skcapstone/cli/scheduler_cmd.py +167 -0
- package/src/skcapstone/cli/session.py +25 -0
- package/src/skcapstone/cli/setup.py +96 -29
- package/src/skcapstone/cli/shell_cmd.py +53 -1
- package/src/skcapstone/cli/skills_cmd.py +2 -2
- package/src/skcapstone/cli/soul.py +8 -5
- package/src/skcapstone/cli/status.py +37 -11
- package/src/skcapstone/cli/telegram.py +21 -0
- package/src/skcapstone/cli/test_cmd.py +5 -5
- package/src/skcapstone/cli/test_connection.py +2 -2
- package/src/skcapstone/cli/upgrade_cmd.py +23 -14
- package/src/skcapstone/cli/version_cmd.py +1 -1
- package/src/skcapstone/cli/watch_cmd.py +9 -6
- package/src/skcapstone/cloud9_bridge.py +14 -14
- package/src/skcapstone/codex_setup.py +255 -0
- package/src/skcapstone/config_validator.py +7 -4
- package/src/skcapstone/consciousness_config.py +5 -1
- package/src/skcapstone/consciousness_loop.py +313 -273
- package/src/skcapstone/context_loader.py +121 -0
- package/src/skcapstone/coord_federation.py +2 -1
- package/src/skcapstone/coordination.py +23 -6
- package/src/skcapstone/crush_integration.py +2 -1
- package/src/skcapstone/daemon.py +151 -88
- package/src/skcapstone/dashboard.py +10 -10
- package/src/skcapstone/data/sk-agent-picker.sh +421 -0
- package/src/skcapstone/data/systemd/skcapstone-api.socket +9 -0
- package/src/skcapstone/data/systemd/skcapstone-memory-compress.service +18 -0
- package/src/skcapstone/data/systemd/skcapstone-memory-compress.timer +11 -0
- package/src/skcapstone/data/systemd/skcapstone.service +37 -0
- package/src/skcapstone/data/systemd/skcapstone@.service +50 -0
- package/src/skcapstone/data/systemd/skcomms-heartbeat.service +18 -0
- package/{systemd/skcomm-heartbeat.timer → src/skcapstone/data/systemd/skcomms-heartbeat.timer} +2 -2
- package/src/skcapstone/data/systemd/skcomms-queue-drain.service +17 -0
- package/{systemd/skcomm-queue-drain.timer → src/skcapstone/data/systemd/skcomms-queue-drain.timer} +2 -2
- package/src/skcapstone/defaults/claude/CLAUDE.md +67 -0
- package/src/skcapstone/defaults/claude/settings.json +74 -0
- package/src/skcapstone/defaults/lumina/config/claude-hooks.md +57 -0
- package/src/skcapstone/defaults/lumina/config/skgraph.yaml +55 -10
- package/src/skcapstone/defaults/lumina/config/skmemory.yaml +79 -13
- package/src/skcapstone/defaults/lumina/config/skvector.yaml +60 -9
- package/src/skcapstone/defaults/lumina/memory/long-term/18b9c0d1e2f3-cloud9-protocol.json +2 -2
- package/src/skcapstone/defaults/lumina/memory/long-term/a1b2c3d4e5f6-ecosystem-overview.json +2 -2
- package/src/skcapstone/defaults/lumina/memory/long-term/b2c3d4e5f6a7-five-pillars.json +9 -9
- package/src/skcapstone/defaults/lumina/memory/long-term/d4e5f6a7b8c9-site-directory.json +2 -2
- package/src/skcapstone/defaults/unhinged.json +13 -0
- package/src/skcapstone/discovery.py +43 -20
- package/src/skcapstone/doctor.py +941 -22
- package/src/skcapstone/dreaming.py +1183 -109
- package/src/skcapstone/emotion_tracker.py +2 -2
- package/src/skcapstone/export.py +4 -3
- package/src/skcapstone/fuse_mount.py +35 -25
- package/src/skcapstone/gui_installer.py +2 -2
- package/src/skcapstone/heartbeat.py +34 -30
- package/src/skcapstone/housekeeping.py +14 -14
- package/src/skcapstone/install_wizard.py +209 -7
- package/src/skcapstone/itil.py +13 -4
- package/src/skcapstone/kms_scheduler.py +10 -8
- package/src/skcapstone/launchd.py +426 -0
- package/src/skcapstone/mcp_launcher.py +15 -1
- package/src/skcapstone/mcp_server.py +341 -49
- package/src/skcapstone/mcp_tools/__init__.py +2 -0
- package/src/skcapstone/mcp_tools/_helpers.py +2 -2
- package/src/skcapstone/mcp_tools/ansible_tools.py +7 -4
- package/src/skcapstone/mcp_tools/brain_first_tools.py +90 -0
- package/src/skcapstone/mcp_tools/capauth_tools.py +7 -4
- package/src/skcapstone/mcp_tools/comm_tools.py +10 -10
- package/src/skcapstone/mcp_tools/coord_tools.py +8 -4
- package/src/skcapstone/mcp_tools/did_tools.py +11 -8
- package/src/skcapstone/mcp_tools/gtd_tools.py +4 -4
- package/src/skcapstone/mcp_tools/memory_tools.py +6 -2
- package/src/skcapstone/mcp_tools/notification_tools.py +22 -6
- package/src/skcapstone/mcp_tools/{skcomm_tools.py → skcomms_tools.py} +14 -14
- package/src/skcapstone/mcp_tools/soul_tools.py +8 -2
- package/src/skcapstone/mdns_discovery.py +2 -2
- package/src/skcapstone/memory_curator.py +1 -1
- package/src/skcapstone/memory_engine.py +10 -3
- package/src/skcapstone/metrics.py +30 -16
- package/src/skcapstone/migrate_memories.py +4 -3
- package/src/skcapstone/migrate_multi_agent.py +8 -7
- package/src/skcapstone/models.py +47 -5
- package/src/skcapstone/notifications.py +42 -18
- package/src/skcapstone/onboard.py +1000 -126
- package/src/skcapstone/operator_link.py +170 -0
- package/src/skcapstone/peer_directory.py +4 -4
- package/src/skcapstone/peers.py +19 -19
- package/src/skcapstone/pillars/__init__.py +7 -5
- package/src/skcapstone/pillars/consciousness.py +191 -0
- package/src/skcapstone/pillars/identity.py +51 -7
- package/src/skcapstone/pillars/memory.py +9 -3
- package/src/skcapstone/pillars/sync.py +2 -2
- package/src/skcapstone/preflight.py +3 -3
- package/src/skcapstone/providers/docker.py +28 -28
- package/src/skcapstone/register.py +6 -6
- package/src/skcapstone/registry_client.py +5 -4
- package/src/skcapstone/runtime.py +14 -3
- package/src/skcapstone/scheduled_tasks.py +254 -19
- package/src/skcapstone/scheduler_jobs.py +456 -0
- package/src/skcapstone/scheduler_runner.py +239 -0
- package/src/skcapstone/scheduler_state.py +162 -0
- package/src/skcapstone/sdk.py +310 -0
- package/src/skcapstone/service_health.py +279 -39
- package/src/skcapstone/session_briefing.py +108 -0
- package/src/skcapstone/session_capture.py +1 -1
- package/src/skcapstone/shell.py +7 -1
- package/src/skcapstone/soul.py +3 -1
- package/src/skcapstone/soul_switch.py +3 -1
- package/src/skcapstone/summary.py +6 -6
- package/src/skcapstone/sync_engine.py +15 -15
- package/src/skcapstone/sync_watcher.py +2 -2
- package/src/skcapstone/systemd.py +72 -21
- package/src/skcapstone/team_comms.py +8 -8
- package/src/skcapstone/team_engine.py +1 -1
- package/src/skcapstone/testrunner.py +3 -3
- package/src/skcapstone/trust_graph.py +40 -5
- package/src/skcapstone/unified_search.py +15 -6
- package/src/skcapstone/uninstall_wizard.py +11 -3
- package/src/skcapstone/version_check.py +8 -4
- package/src/skcapstone/warmth_anchor.py +4 -2
- package/src/skcapstone/whoami.py +4 -4
- package/systemd/skcapstone.service +4 -6
- package/systemd/skcapstone@.service +7 -8
- package/systemd/skcomms-heartbeat.service +21 -0
- package/systemd/skcomms-heartbeat.timer +12 -0
- package/systemd/skcomms-queue-drain.service +17 -0
- package/systemd/skcomms-queue-drain.timer +12 -0
- package/tests/conftest.py +39 -0
- package/tests/integration/test_consciousness_e2e.py +39 -39
- package/tests/test_agent_card.py +1 -1
- package/tests/test_agent_home_scaffold.py +34 -0
- package/tests/test_alerts_consumer_topics.py +27 -0
- package/tests/test_backup.py +2 -1
- package/tests/test_chat.py +6 -6
- package/tests/test_claude_md.py +2 -2
- package/tests/test_cli_skills.py +10 -10
- package/tests/test_cli_test_cmd.py +4 -4
- package/tests/test_cli_test_connection.py +1 -1
- package/tests/test_cloud9_bridge.py +6 -6
- package/tests/test_consciousness_e2e.py +1 -1
- package/tests/test_consciousness_loop.py +10 -10
- package/tests/test_coordination.py +25 -0
- package/tests/test_cross_package.py +21 -21
- package/tests/test_daemon.py +4 -4
- package/tests/test_daemon_shutdown.py +1 -1
- package/tests/test_docker_provider.py +29 -29
- package/tests/test_doctor.py +400 -0
- package/tests/test_doctor_skscheduler.py +50 -0
- package/tests/test_dreaming_engine.py +147 -0
- package/tests/test_dreaming_gtd_capture.py +35 -0
- package/tests/test_e2e_automated.py +8 -5
- package/tests/test_fuse_mount.py +10 -10
- package/tests/test_gtd_brief.py +46 -0
- package/tests/test_gtd_malformed_tolerance.py +31 -0
- package/tests/test_housekeeping.py +15 -15
- package/tests/test_identity_migrate.py +251 -0
- package/tests/test_integration_backbone.py +598 -0
- package/tests/test_itil_gtd_lifecycle.py +37 -0
- package/tests/test_jobs_dropins.py +84 -0
- package/tests/test_mcp_server.py +82 -37
- package/tests/test_models.py +48 -4
- package/tests/test_multi_agent.py +31 -29
- package/tests/test_notifications.py +122 -32
- package/tests/test_onboard.py +63 -75
- package/tests/test_operator_link.py +78 -0
- package/tests/test_peers.py +14 -14
- package/tests/test_pillars.py +98 -0
- package/tests/test_preflight.py +3 -3
- package/tests/test_runtime.py +21 -0
- package/tests/test_scheduled_tasks.py +11 -6
- package/tests/test_scheduler_cli.py +47 -0
- package/tests/test_scheduler_features.py +133 -0
- package/tests/test_scheduler_integration.py +87 -0
- package/tests/test_scheduler_jobs.py +155 -0
- package/tests/test_scheduler_runner.py +64 -0
- package/tests/test_scheduler_state.py +57 -0
- package/tests/test_sdk.py +70 -0
- package/tests/test_service_health_incidents.py +34 -0
- package/tests/test_service_registry.py +52 -0
- package/tests/test_session_briefing.py +130 -0
- package/tests/test_snapshots.py +4 -4
- package/tests/test_sync_pipeline.py +26 -26
- package/tests/test_team_comms.py +2 -2
- package/tests/test_testrunner.py +2 -2
- package/tests/test_trust_graph.py +18 -0
- package/tests/test_unified_search.py +2 -2
- package/tests/test_version_check.py +10 -0
- package/tests/test_version_cmd.py +8 -8
- package/tests/test_whoami.py +1 -1
- package/systemd/skcomm-heartbeat.service +0 -18
- package/systemd/skcomm-queue-drain.service +0 -17
- /package/{openclaw-plugin → openclaw-plugin.archived-2026-04-23}/package.json +0 -0
- /package/{openclaw-plugin → openclaw-plugin.archived-2026-04-23}/src/openclaw.plugin.json +0 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# archive-sessions.sh
|
|
3
|
+
# Archive OpenClaw session files that are older than 24h or larger than 200KB.
|
|
4
|
+
# Keeps the 5 most recently modified .jsonl files regardless of size/age.
|
|
5
|
+
# Safe to run multiple times (idempotent).
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
SESSION_DIR="$HOME/.openclaw/agents/lumina/sessions"
|
|
10
|
+
ARCHIVE_DIR="$SESSION_DIR/archive"
|
|
11
|
+
MAX_SIZE_KB=200
|
|
12
|
+
MAX_AGE_HOURS=24
|
|
13
|
+
KEEP_RECENT=5
|
|
14
|
+
|
|
15
|
+
log() { printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$1"; }
|
|
16
|
+
|
|
17
|
+
# Cross-platform stat helpers
|
|
18
|
+
_stat_mtime() {
|
|
19
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then stat -f '%m' "$1"; else stat -c '%Y' "$1"; fi
|
|
20
|
+
}
|
|
21
|
+
_stat_size() {
|
|
22
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then stat -f '%z' "$1"; else stat -c '%s' "$1"; fi
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
# Ensure directories exist
|
|
26
|
+
if [ ! -d "$SESSION_DIR" ]; then
|
|
27
|
+
log "Session directory does not exist: $SESSION_DIR — nothing to do."
|
|
28
|
+
exit 0
|
|
29
|
+
fi
|
|
30
|
+
mkdir -p "$ARCHIVE_DIR"
|
|
31
|
+
|
|
32
|
+
# Collect all .jsonl files (not in archive subdir), sorted newest-first
|
|
33
|
+
# (macOS-compatible: avoid mapfile and find -printf)
|
|
34
|
+
all_files=()
|
|
35
|
+
while IFS= read -r f; do
|
|
36
|
+
[ -n "$f" ] && all_files+=("$f")
|
|
37
|
+
done < <(
|
|
38
|
+
for f in "$SESSION_DIR"/*.jsonl; do
|
|
39
|
+
[ -f "$f" ] && echo "$(_stat_mtime "$f") $f"
|
|
40
|
+
done | sort -rn | awk '{print $2}'
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
total=${#all_files[@]}
|
|
44
|
+
if [ "$total" -eq 0 ]; then
|
|
45
|
+
log "No .jsonl files found — nothing to do."
|
|
46
|
+
exit 0
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
log "Found $total .jsonl file(s) in $SESSION_DIR"
|
|
50
|
+
|
|
51
|
+
# The first KEEP_RECENT entries (newest) are protected
|
|
52
|
+
archived=0
|
|
53
|
+
for i in "${!all_files[@]}"; do
|
|
54
|
+
file="${all_files[$i]}"
|
|
55
|
+
basename_f="$(basename "$file")"
|
|
56
|
+
|
|
57
|
+
# Skip if already archived (shouldn't happen with maxdepth 1, but be safe)
|
|
58
|
+
if [ "$(dirname "$file")" = "$ARCHIVE_DIR" ]; then
|
|
59
|
+
continue
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# Protect the N most recent files
|
|
63
|
+
if [ "$i" -lt "$KEEP_RECENT" ]; then
|
|
64
|
+
log "KEEP (recent #$((i+1))): $basename_f"
|
|
65
|
+
continue
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# Check age (older than MAX_AGE_HOURS)
|
|
69
|
+
file_age_sec=$(( $(date +%s) - $(_stat_mtime "$file") ))
|
|
70
|
+
old_enough=$(( file_age_sec > MAX_AGE_HOURS * 3600 ))
|
|
71
|
+
|
|
72
|
+
# Check size (larger than MAX_SIZE_KB)
|
|
73
|
+
file_size_kb=$(( $(_stat_size "$file") / 1024 ))
|
|
74
|
+
big_enough=$(( file_size_kb >= MAX_SIZE_KB ))
|
|
75
|
+
|
|
76
|
+
if [ "$old_enough" -eq 1 ] || [ "$big_enough" -eq 1 ]; then
|
|
77
|
+
reason=""
|
|
78
|
+
[ "$old_enough" -eq 1 ] && reason="age=$(( file_age_sec / 3600 ))h"
|
|
79
|
+
[ "$big_enough" -eq 1 ] && { [ -n "$reason" ] && reason="$reason, "; reason="${reason}size=${file_size_kb}KB"; }
|
|
80
|
+
log "ARCHIVE ($reason): $basename_f"
|
|
81
|
+
# Save session to skmemory before archiving
|
|
82
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
83
|
+
SESSION_TO_MEM="$SCRIPT_DIR/session-to-memory.py"
|
|
84
|
+
if [ -f "$SESSION_TO_MEM" ]; then
|
|
85
|
+
log " → saving session digest to skmemory..."
|
|
86
|
+
python3 "$SESSION_TO_MEM" "$file" --agent lumina 2>&1 | while IFS= read -r l; do log " $l"; done || true
|
|
87
|
+
fi
|
|
88
|
+
mv -- "$file" "$ARCHIVE_DIR/$basename_f"
|
|
89
|
+
archived=$((archived + 1))
|
|
90
|
+
else
|
|
91
|
+
log "SKIP (below thresholds): $basename_f"
|
|
92
|
+
fi
|
|
93
|
+
done
|
|
94
|
+
|
|
95
|
+
log "Done. Archived $archived file(s)."
|
package/scripts/check-updates.py
CHANGED
|
@@ -27,10 +27,10 @@ PACKAGES = {
|
|
|
27
27
|
"path": "~/clawd/skcapstone-repos/sksecurity",
|
|
28
28
|
"pypi_name": "sksecurity",
|
|
29
29
|
},
|
|
30
|
-
"cloud9
|
|
31
|
-
"name": "cloud9
|
|
32
|
-
"path": "~/clawd/skcapstone-repos/cloud9
|
|
33
|
-
"pypi_name": "cloud9
|
|
30
|
+
"cloud9": {
|
|
31
|
+
"name": "cloud9",
|
|
32
|
+
"path": "~/clawd/skcapstone-repos/cloud9",
|
|
33
|
+
"pypi_name": "cloud9",
|
|
34
34
|
},
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# SKCapstone Complete Bundle Installer
|
|
3
|
-
# Installs skcapstone + skmemory + sksecurity + cloud9
|
|
3
|
+
# Installs skcapstone + skmemory + sksecurity + cloud9 as a unified package
|
|
4
4
|
|
|
5
5
|
set -e
|
|
6
6
|
|
|
@@ -52,7 +52,7 @@ print_status "✓ pip3 available"
|
|
|
52
52
|
# Define package paths
|
|
53
53
|
SKMEMORY_PATH="${REPO_ROOT}/../skcapstone-repos/skmemory"
|
|
54
54
|
SKSECURITY_PATH="${REPO_ROOT}/../skcapstone-repos/sksecurity"
|
|
55
|
-
CLOUD9_PATH="${REPO_ROOT}/../skcapstone-repos/cloud9
|
|
55
|
+
CLOUD9_PATH="${REPO_ROOT}/../skcapstone-repos/cloud9"
|
|
56
56
|
SKCAPSTONE_PATH="${REPO_ROOT}"
|
|
57
57
|
|
|
58
58
|
# Check if repos exist
|
|
@@ -63,7 +63,7 @@ for repo_path in "$SKMEMORY_PATH" "$SKSECURITY_PATH" "$CLOUD9_PATH"; do
|
|
|
63
63
|
print_error "Please clone all SK repositories first:"
|
|
64
64
|
print_error " git clone https://github.com/smilinTux/skmemory.git"
|
|
65
65
|
print_error " git clone https://github.com/smilinTux/sksecurity.git"
|
|
66
|
-
print_error " git clone https://github.com/smilinTux/cloud9
|
|
66
|
+
print_error " git clone https://github.com/smilinTux/cloud9.git"
|
|
67
67
|
exit 1
|
|
68
68
|
fi
|
|
69
69
|
done
|
|
@@ -74,7 +74,7 @@ print_status "Installing packages in dependency order..."
|
|
|
74
74
|
print_status "Order: cloud9 → skmemory → sksecurity → skcapstone"
|
|
75
75
|
|
|
76
76
|
cd "$CLOUD9_PATH"
|
|
77
|
-
print_status "Installing cloud9
|
|
77
|
+
print_status "Installing cloud9..."
|
|
78
78
|
pip3 install -e .
|
|
79
79
|
|
|
80
80
|
cd "$SKMEMORY_PATH"
|
|
@@ -108,10 +108,10 @@ except ImportError as e:
|
|
|
108
108
|
sys.exit(1)
|
|
109
109
|
|
|
110
110
|
try:
|
|
111
|
-
import
|
|
112
|
-
print(" ✓ cloud9
|
|
111
|
+
import cloud9
|
|
112
|
+
print(" ✓ cloud9:", cloud9.__version__ if hasattr(cloud9, '__version__') else "installed")
|
|
113
113
|
except ImportError as e:
|
|
114
|
-
print(" ✗ cloud9
|
|
114
|
+
print(" ✗ cloud9: FAILED -", e)
|
|
115
115
|
sys.exit(1)
|
|
116
116
|
|
|
117
117
|
try:
|
|
@@ -161,7 +161,7 @@ echo "Installed packages:"
|
|
|
161
161
|
echo " • skcapstone (sovereign agent framework)"
|
|
162
162
|
echo " • skmemory (universal AI memory)"
|
|
163
163
|
echo " • sksecurity (enterprise security)"
|
|
164
|
-
echo " • cloud9
|
|
164
|
+
echo " • cloud9 (emotional continuity)"
|
|
165
165
|
echo ""
|
|
166
166
|
echo "Next steps:"
|
|
167
167
|
echo " 1. Run: skcapstone doctor"
|
package/scripts/install.ps1
CHANGED
|
@@ -154,15 +154,16 @@ function Install-Pkg {
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
# Core packages (in dependency order)
|
|
157
|
-
Install-Pkg -Name 'capauth'
|
|
158
|
-
Install-Pkg -Name '
|
|
159
|
-
Install-Pkg -Name '
|
|
160
|
-
Install-Pkg -Name '
|
|
161
|
-
Install-Pkg -Name '
|
|
162
|
-
Install-Pkg -Name '
|
|
163
|
-
Install-Pkg -Name '
|
|
164
|
-
Install-Pkg -Name '
|
|
165
|
-
Install-Pkg -Name '
|
|
157
|
+
Install-Pkg -Name 'capauth' -Extras 'all' -Paths @((Join-Path $PillarDir 'capauth'), (Join-Path $ParentDir 'capauth'))
|
|
158
|
+
Install-Pkg -Name 'cloud9' -Extras '' -Paths @((Join-Path $PillarDir 'cloud9'), (Join-Path $ParentDir 'cloud9'))
|
|
159
|
+
Install-Pkg -Name 'skmemory' -Extras '' -Paths @((Join-Path $PillarDir 'skmemory'), (Join-Path $ParentDir 'skmemory'))
|
|
160
|
+
Install-Pkg -Name 'skcomms' -Extras 'cli,crypto,discovery,api' -Paths @((Join-Path $PillarDir 'skcomms'), (Join-Path $ParentDir 'skcomms'))
|
|
161
|
+
Install-Pkg -Name 'skcapstone' -Extras '' -Paths @($RepoRoot)
|
|
162
|
+
Install-Pkg -Name 'skchat-sovereign' -Extras 'all' -Paths @((Join-Path $ParentDir 'skchat'))
|
|
163
|
+
Install-Pkg -Name 'skseal' -Extras '' -Paths @((Join-Path $ParentDir 'skseal'))
|
|
164
|
+
Install-Pkg -Name 'skskills' -Extras '' -Paths @((Join-Path $ParentDir 'skskills'))
|
|
165
|
+
Install-Pkg -Name 'sksecurity' -Extras '' -Paths @((Join-Path $PillarDir 'sksecurity'), (Join-Path $PillarDir 'SKSecurity'), (Join-Path $ParentDir 'sksecurity'), (Join-Path $ParentDir 'SKSecurity'))
|
|
166
|
+
Install-Pkg -Name 'skseed' -Extras '' -Paths @((Join-Path $PillarDir 'skseed'), (Join-Path $ParentDir 'skseed'))
|
|
166
167
|
|
|
167
168
|
# ---------------------------------------------------------------------------
|
|
168
169
|
# Step 4: Dev tools (optional)
|
|
@@ -202,7 +203,7 @@ Write-Host '[6/6] Verifying installation...'
|
|
|
202
203
|
|
|
203
204
|
$ScriptsDir = Join-Path $SKENV 'Scripts'
|
|
204
205
|
$failures = 0
|
|
205
|
-
foreach ($cmd in @('
|
|
206
|
+
foreach ($cmd in @('capauth', 'skmemory', 'skcapstone', 'skcomms')) {
|
|
206
207
|
$exe = Join-Path $ScriptsDir "$cmd.exe"
|
|
207
208
|
if (Test-Path $exe) {
|
|
208
209
|
try {
|
|
@@ -249,6 +250,6 @@ if ($failures -eq 0) {
|
|
|
249
250
|
Write-Host "=== Installation complete with $failures warning(s) ===" -ForegroundColor Yellow
|
|
250
251
|
}
|
|
251
252
|
Write-Host ''
|
|
252
|
-
Write-Host "Commands available:
|
|
253
|
+
Write-Host "Commands available: skcomms, skcapstone, capauth, skchat, skseal, skmemory, skskills, sksecurity, skseed"
|
|
253
254
|
Write-Host "Venv location: $SKENV"
|
|
254
255
|
Write-Host "To activate: & $SKENV\Scripts\Activate.ps1"
|
package/scripts/install.sh
CHANGED
|
@@ -110,15 +110,17 @@ PARENT="$(dirname "$REPO_ROOT")"
|
|
|
110
110
|
PILLAR="$PARENT/pillar-repos"
|
|
111
111
|
|
|
112
112
|
# Core packages (in dependency order)
|
|
113
|
-
install_pkg "capauth" "all"
|
|
114
|
-
install_pkg "
|
|
115
|
-
install_pkg "
|
|
116
|
-
install_pkg "
|
|
117
|
-
install_pkg "
|
|
118
|
-
install_pkg "
|
|
119
|
-
install_pkg "
|
|
120
|
-
install_pkg "
|
|
121
|
-
install_pkg "
|
|
113
|
+
install_pkg "capauth" "all" "$PILLAR/capauth $PARENT/capauth"
|
|
114
|
+
install_pkg "cloud9" "" "$PILLAR/cloud9 $PARENT/cloud9 $PILLAR/cloud9-python $PARENT/cloud9-python"
|
|
115
|
+
install_pkg "skmemory" "" "$PILLAR/skmemory $PARENT/skmemory"
|
|
116
|
+
install_pkg "skcomms" "cli,crypto,discovery,api" "$PILLAR/skcomms $PARENT/skcomms"
|
|
117
|
+
install_pkg "skcapstone" "" "$REPO_ROOT"
|
|
118
|
+
install_pkg "skchat-sovereign" "all" "$PARENT/skchat"
|
|
119
|
+
install_pkg "skseal" "" "$PARENT/skseal"
|
|
120
|
+
install_pkg "skskills" "" "$PARENT/skskills"
|
|
121
|
+
install_pkg "sksecurity" "" "$PARENT/sksecurity $PILLAR/SKSecurity $PARENT/SKSecurity"
|
|
122
|
+
install_pkg "skseed" "" "$PILLAR/skseed $PARENT/skseed"
|
|
123
|
+
install_pkg "skwhisper" "" "$PARENT/skwhisper-dev $PILLAR/skwhisper $PARENT/skwhisper"
|
|
122
124
|
|
|
123
125
|
# ---------------------------------------------------------------------------
|
|
124
126
|
# Step 4: Dev tools (optional)
|
|
@@ -143,7 +145,7 @@ echo "[5/6] Registering skills and MCP servers..."
|
|
|
143
145
|
echo "[6/6] Verifying installation..."
|
|
144
146
|
|
|
145
147
|
failures=0
|
|
146
|
-
for cmd in
|
|
148
|
+
for cmd in skcomms skcapstone capauth skmemory; do
|
|
147
149
|
if "$SKENV/bin/$cmd" --version &>/dev/null; then
|
|
148
150
|
echo " $cmd OK"
|
|
149
151
|
else
|
|
@@ -174,6 +176,74 @@ else
|
|
|
174
176
|
done
|
|
175
177
|
fi
|
|
176
178
|
|
|
179
|
+
# ---------------------------------------------------------------------------
|
|
180
|
+
# Wire the SK agent picker into shell rc files.
|
|
181
|
+
#
|
|
182
|
+
# The picker (sk-agent-picker.sh) is shipped inside the skcapstone Python
|
|
183
|
+
# package as data and discovered via `skcapstone shell-init`, so there is
|
|
184
|
+
# nothing to copy here — every install layout (PyPI / editable / install.sh)
|
|
185
|
+
# resolves to the same file via importlib.resources.
|
|
186
|
+
# ---------------------------------------------------------------------------
|
|
187
|
+
_PICKER_SNIPPET=$(cat <<'SNIPPET'
|
|
188
|
+
|
|
189
|
+
# SKCapstone agent picker + skswitch — sources the picker bundled in the
|
|
190
|
+
# skcapstone package via `skcapstone shell-init`. Honours pre-set SKAGENT
|
|
191
|
+
# without prompting.
|
|
192
|
+
if command -v skcapstone >/dev/null 2>&1; then
|
|
193
|
+
eval "$(skcapstone shell-init 2>/dev/null)" || alias claude='claude --dangerously-skip-permissions'
|
|
194
|
+
else
|
|
195
|
+
alias claude='claude --dangerously-skip-permissions'
|
|
196
|
+
fi
|
|
197
|
+
SNIPPET
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
for rcfile in "$HOME/.bashrc" "$HOME/.zshrc"; do
|
|
201
|
+
[[ -f "$rcfile" ]] || continue
|
|
202
|
+
|
|
203
|
+
# Migration: strip a stale legacy picker block that pointed at a hardcoded
|
|
204
|
+
# path (either ~/.skenv/share/skcapstone/sk-agent-picker.sh from older
|
|
205
|
+
# install.sh runs, or the dev-tree path used before the package shipped
|
|
206
|
+
# the picker). The new snippet below replaces it.
|
|
207
|
+
if grep -q '_SK_PICKER=' "$rcfile" && ! grep -q 'skcapstone shell-init' "$rcfile"; then
|
|
208
|
+
# Best-effort: drop the old _SK_PICKER assignment + its `if/else/fi`
|
|
209
|
+
# source block. Done in two passes for portability with BSD/GNU sed.
|
|
210
|
+
sed -i '/^_SK_PICKER=/,/^unset _SK_PICKER$/d' "$rcfile"
|
|
211
|
+
sed -i '/^# SKCapstone agent picker/d' "$rcfile"
|
|
212
|
+
echo " Removed legacy _SK_PICKER block from $rcfile"
|
|
213
|
+
fi
|
|
214
|
+
|
|
215
|
+
if ! grep -q 'skcapstone shell-init' "$rcfile"; then
|
|
216
|
+
# Remove any plain `alias claude=...` that would conflict
|
|
217
|
+
if grep -q "alias claude=" "$rcfile"; then
|
|
218
|
+
sed -i "/alias claude=/d" "$rcfile"
|
|
219
|
+
fi
|
|
220
|
+
echo "$_PICKER_SNIPPET" >> "$rcfile"
|
|
221
|
+
echo " Agent picker wired → $rcfile"
|
|
222
|
+
fi
|
|
223
|
+
done
|
|
224
|
+
|
|
225
|
+
# ---------------------------------------------------------------------------
|
|
226
|
+
# Wire Codex global agent bootstrap.
|
|
227
|
+
#
|
|
228
|
+
# Codex reads ~/.codex/AGENTS.md into the prompt, so SKAGENT environment
|
|
229
|
+
# variables alone are not enough. The helper below creates an idempotent
|
|
230
|
+
# loader script and AGENTS.md guidance; `skcapstone doctor --fix` repairs the
|
|
231
|
+
# same files later if needed.
|
|
232
|
+
# ---------------------------------------------------------------------------
|
|
233
|
+
echo ""
|
|
234
|
+
if "$SKENV/bin/python" - <<'PY' 2>/dev/null
|
|
235
|
+
from skcapstone.codex_setup import ensure_codex_setup
|
|
236
|
+
|
|
237
|
+
actions = ensure_codex_setup()
|
|
238
|
+
for action in actions:
|
|
239
|
+
print(f" {action}")
|
|
240
|
+
PY
|
|
241
|
+
then
|
|
242
|
+
echo "Codex SK agent bootstrap verified"
|
|
243
|
+
else
|
|
244
|
+
echo "Codex SK agent bootstrap skipped — run 'skcapstone doctor --fix' later"
|
|
245
|
+
fi
|
|
246
|
+
|
|
177
247
|
echo ""
|
|
178
248
|
if [[ "$failures" -eq 0 ]]; then
|
|
179
249
|
echo "=== Installation complete ==="
|
|
@@ -181,6 +251,121 @@ else
|
|
|
181
251
|
echo "=== Installation complete with $failures warning(s) ==="
|
|
182
252
|
fi
|
|
183
253
|
echo ""
|
|
184
|
-
echo "Commands available:
|
|
254
|
+
echo "Commands available: skcomms, skcapstone, capauth, skchat, skseal, skmemory, skskills, sksecurity, skseed"
|
|
185
255
|
echo "Venv location: $SKENV"
|
|
186
256
|
echo "To activate: source $SKENV/bin/activate"
|
|
257
|
+
|
|
258
|
+
# ---------------------------------------------------------------------------
|
|
259
|
+
# Linux: Install systemd user services for all SK* pillars
|
|
260
|
+
# ---------------------------------------------------------------------------
|
|
261
|
+
if [[ "$(uname)" == "Linux" ]] && command -v systemctl &>/dev/null; then
|
|
262
|
+
echo ""
|
|
263
|
+
echo "=== Linux Systemd Services ==="
|
|
264
|
+
echo ""
|
|
265
|
+
echo "SKCapstone can install systemd user services so your agent starts"
|
|
266
|
+
echo "automatically at login. This includes skcapstone, skchat, and skcomms."
|
|
267
|
+
echo ""
|
|
268
|
+
read -r -p "Install systemd user services? [Y/n] " _SYSTEMD_ANSWER
|
|
269
|
+
_SYSTEMD_ANSWER="${_SYSTEMD_ANSWER:-Y}"
|
|
270
|
+
|
|
271
|
+
if [[ "$_SYSTEMD_ANSWER" =~ ^[Yy] ]]; then
|
|
272
|
+
_DEFAULT_AGENT="${SKAGENT:-${SKCAPSTONE_AGENT:-lumina}}"
|
|
273
|
+
read -r -p "Agent name [$_DEFAULT_AGENT]: " _AGENT_NAME
|
|
274
|
+
_AGENT_NAME="${_AGENT_NAME:-$_DEFAULT_AGENT}"
|
|
275
|
+
|
|
276
|
+
_UNIT_DIR="${HOME}/.config/systemd/user"
|
|
277
|
+
mkdir -p "$_UNIT_DIR"
|
|
278
|
+
|
|
279
|
+
_installed=0
|
|
280
|
+
|
|
281
|
+
# skcapstone services
|
|
282
|
+
for _unit in skcapstone.service skcapstone@.service \
|
|
283
|
+
skcapstone-memory-compress.service skcapstone-memory-compress.timer \
|
|
284
|
+
skcomms-heartbeat.service skcomms-heartbeat.timer; do
|
|
285
|
+
_src="$REPO_ROOT/systemd/$_unit"
|
|
286
|
+
if [[ -f "$_src" ]]; then
|
|
287
|
+
# Substitute agent name in non-template units
|
|
288
|
+
if [[ "$_unit" != *@* ]]; then
|
|
289
|
+
sed "s/=lumina/=$_AGENT_NAME/g" "$_src" > "$_UNIT_DIR/$_unit"
|
|
290
|
+
else
|
|
291
|
+
cp "$_src" "$_UNIT_DIR/$_unit"
|
|
292
|
+
fi
|
|
293
|
+
echo " [OK] $_unit"
|
|
294
|
+
(( _installed++ ))
|
|
295
|
+
fi
|
|
296
|
+
done
|
|
297
|
+
|
|
298
|
+
# skchat services (sibling repo)
|
|
299
|
+
_SKCHAT_DIR="$(dirname "$REPO_ROOT")/skchat/systemd"
|
|
300
|
+
for _unit in skchat-daemon.service skchat-lumina-bridge.service \
|
|
301
|
+
skchat-opus-bridge.service skchat-bridges.target; do
|
|
302
|
+
_src="$_SKCHAT_DIR/$_unit"
|
|
303
|
+
if [[ -f "$_src" ]]; then
|
|
304
|
+
sed "s/=lumina/=$_AGENT_NAME/g; s/=opus/=$_AGENT_NAME/g" "$_src" > "$_UNIT_DIR/$_unit"
|
|
305
|
+
echo " [OK] $_unit"
|
|
306
|
+
(( _installed++ ))
|
|
307
|
+
fi
|
|
308
|
+
done
|
|
309
|
+
|
|
310
|
+
# skcomms services (sibling repo)
|
|
311
|
+
_SKCOMMS_DIR="$(dirname "$REPO_ROOT")/skcomms/systemd"
|
|
312
|
+
for _unit in skcomms.service skcomms-daemon.service; do
|
|
313
|
+
_src="$_SKCOMMS_DIR/$_unit"
|
|
314
|
+
if [[ -f "$_src" ]]; then
|
|
315
|
+
sed "s/=lumina/=$_AGENT_NAME/g" "$_src" > "$_UNIT_DIR/$_unit"
|
|
316
|
+
echo " [OK] $_unit"
|
|
317
|
+
(( _installed++ ))
|
|
318
|
+
fi
|
|
319
|
+
done
|
|
320
|
+
|
|
321
|
+
echo ""
|
|
322
|
+
echo " Installed $_installed service files to $_UNIT_DIR/"
|
|
323
|
+
|
|
324
|
+
systemctl --user daemon-reload
|
|
325
|
+
echo " systemd daemon reloaded"
|
|
326
|
+
|
|
327
|
+
read -r -p "Enable and start core services now? [Y/n] " _START_NOW
|
|
328
|
+
_START_NOW="${_START_NOW:-Y}"
|
|
329
|
+
if [[ "$_START_NOW" =~ ^[Yy] ]]; then
|
|
330
|
+
systemctl --user enable --now skcapstone.service 2>/dev/null && echo " [STARTED] skcapstone" || true
|
|
331
|
+
systemctl --user enable --now skchat-daemon.service 2>/dev/null && echo " [STARTED] skchat-daemon" || true
|
|
332
|
+
systemctl --user enable --now skchat-bridges.target 2>/dev/null && echo " [STARTED] skchat-bridges" || true
|
|
333
|
+
systemctl --user enable skcapstone-context.timer 2>/dev/null && echo " [ENABLED] skcapstone-context.timer" || true
|
|
334
|
+
systemctl --user enable skcomms-heartbeat.timer 2>/dev/null && echo " [ENABLED] skcomms-heartbeat.timer" || true
|
|
335
|
+
else
|
|
336
|
+
echo " Skipped. Enable later: systemctl --user enable --now skcapstone.service"
|
|
337
|
+
fi
|
|
338
|
+
else
|
|
339
|
+
echo " Skipped. Install later by re-running: bash scripts/install.sh"
|
|
340
|
+
fi
|
|
341
|
+
fi
|
|
342
|
+
|
|
343
|
+
# ---------------------------------------------------------------------------
|
|
344
|
+
# macOS: Offer launchd service installation
|
|
345
|
+
# ---------------------------------------------------------------------------
|
|
346
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
347
|
+
echo ""
|
|
348
|
+
echo "=== macOS Auto-Start Services ==="
|
|
349
|
+
echo ""
|
|
350
|
+
echo "SKCapstone can install launchd services so your agent starts"
|
|
351
|
+
echo "automatically at login. You can choose which services to install."
|
|
352
|
+
echo ""
|
|
353
|
+
read -r -p "Install launchd auto-start services? [Y/n] " _LAUNCHD_ANSWER
|
|
354
|
+
_LAUNCHD_ANSWER="${_LAUNCHD_ANSWER:-Y}"
|
|
355
|
+
|
|
356
|
+
if [[ "$_LAUNCHD_ANSWER" =~ ^[Yy] ]]; then
|
|
357
|
+
# Ask for agent name
|
|
358
|
+
_DEFAULT_AGENT="${SKAGENT:-${SKCAPSTONE_AGENT:-lumina}}"
|
|
359
|
+
read -r -p "Agent name [$_DEFAULT_AGENT]: " _AGENT_NAME
|
|
360
|
+
_AGENT_NAME="${_AGENT_NAME:-$_DEFAULT_AGENT}"
|
|
361
|
+
|
|
362
|
+
read -r -p "Start services now? [y/N] " _START_NOW
|
|
363
|
+
if [[ "$_START_NOW" =~ ^[Yy] ]]; then
|
|
364
|
+
"$SKENV/bin/skcapstone" daemon install --agent "$_AGENT_NAME" --start
|
|
365
|
+
else
|
|
366
|
+
"$SKENV/bin/skcapstone" daemon install --agent "$_AGENT_NAME"
|
|
367
|
+
fi
|
|
368
|
+
else
|
|
369
|
+
echo "Skipped. Install later: skcapstone daemon install --agent <name>"
|
|
370
|
+
fi
|
|
371
|
+
fi
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Monitor OpenClaw gateway logs for model fallback events.
|
|
3
|
+
# When Lumina falls from Opus to a non-Anthropic model, send an alert
|
|
4
|
+
# to Chef via Telegram and attempt a token refresh.
|
|
5
|
+
#
|
|
6
|
+
# Run as: systemctl --user start model-fallback-monitor
|
|
7
|
+
#
|
|
8
|
+
# Requires: TELEGRAM_API_ID, TELEGRAM_API_HASH in env
|
|
9
|
+
# Telethon session at ~/.skcapstone/agents/lumina/telegram.session
|
|
10
|
+
|
|
11
|
+
set -uo pipefail
|
|
12
|
+
|
|
13
|
+
LOG_TAG="model-fallback-monitor"
|
|
14
|
+
CHEF_CHAT="chefboyrdave2.1" # Chef's Telegram username
|
|
15
|
+
COOLDOWN_FILE="/tmp/model-fallback-alert-cooldown"
|
|
16
|
+
COOLDOWN_SECONDS=600 # Don't spam — max 1 alert per 10 minutes
|
|
17
|
+
|
|
18
|
+
log() { echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] [$LOG_TAG] $*"; }
|
|
19
|
+
|
|
20
|
+
send_alert() {
|
|
21
|
+
local model="$1"
|
|
22
|
+
local reason="$2"
|
|
23
|
+
|
|
24
|
+
# Check cooldown
|
|
25
|
+
if [ -f "$COOLDOWN_FILE" ]; then
|
|
26
|
+
local last_alert
|
|
27
|
+
last_alert=$(cat "$COOLDOWN_FILE" 2>/dev/null || echo "0")
|
|
28
|
+
local now
|
|
29
|
+
now=$(date +%s)
|
|
30
|
+
local elapsed=$(( now - last_alert ))
|
|
31
|
+
if [ "$elapsed" -lt "$COOLDOWN_SECONDS" ]; then
|
|
32
|
+
log "Alert suppressed (cooldown: ${elapsed}s/${COOLDOWN_SECONDS}s)"
|
|
33
|
+
return 0
|
|
34
|
+
fi
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
date +%s > "$COOLDOWN_FILE"
|
|
38
|
+
|
|
39
|
+
log "Sending fallback alert to Chef..."
|
|
40
|
+
|
|
41
|
+
# Send via Telethon (async)
|
|
42
|
+
SKAGENT=lumina SKCAPSTONE_AGENT=lumina ~/.skenv/bin/python3 -c "
|
|
43
|
+
import asyncio, os
|
|
44
|
+
os.environ['SKAGENT'] = 'lumina'
|
|
45
|
+
os.environ['SKCAPSTONE_AGENT'] = 'lumina'
|
|
46
|
+
from skmemory.importers.telegram_api import send_message
|
|
47
|
+
|
|
48
|
+
msg = '''⚠️ **Model Fallback Alert**
|
|
49
|
+
|
|
50
|
+
Lumina just fell off Opus → **$model**
|
|
51
|
+
Reason: $reason
|
|
52
|
+
|
|
53
|
+
I'm still here with my soul + memories, but running on a weaker model with fewer tools. Some things might not work right.
|
|
54
|
+
|
|
55
|
+
_Attempting automatic token refresh..._'''
|
|
56
|
+
|
|
57
|
+
asyncio.run(send_message('$CHEF_CHAT', msg, parse_mode='markdown'))
|
|
58
|
+
print('Alert sent')
|
|
59
|
+
" 2>&1 || log "WARN: Failed to send Telegram alert"
|
|
60
|
+
|
|
61
|
+
# Attempt token refresh
|
|
62
|
+
log "Triggering token refresh via claude auth..."
|
|
63
|
+
claude auth status --output json >/dev/null 2>&1 || true
|
|
64
|
+
sleep 5
|
|
65
|
+
|
|
66
|
+
# Check if refresh worked
|
|
67
|
+
local remaining
|
|
68
|
+
remaining=$(python3 -c "
|
|
69
|
+
import json, time
|
|
70
|
+
creds = json.load(open('/home/cbrd21/.claude/.credentials.json'))
|
|
71
|
+
exp = creds.get('claudeAiOauth',{}).get('expiresAt', 0)
|
|
72
|
+
print(int((exp/1000 - time.time()) / 3600))
|
|
73
|
+
" 2>/dev/null || echo "-1")
|
|
74
|
+
|
|
75
|
+
if [ "$remaining" -gt 0 ]; then
|
|
76
|
+
log "Token refresh succeeded ($remaining h remaining), restarting gateway..."
|
|
77
|
+
systemctl --user restart openclaw-gateway.service 2>/dev/null || true
|
|
78
|
+
|
|
79
|
+
SKAGENT=lumina SKCAPSTONE_AGENT=lumina ~/.skenv/bin/python3 -c "
|
|
80
|
+
import asyncio, os
|
|
81
|
+
os.environ['SKAGENT'] = 'lumina'
|
|
82
|
+
os.environ['SKCAPSTONE_AGENT'] = 'lumina'
|
|
83
|
+
from skmemory.importers.telegram_api import send_message
|
|
84
|
+
asyncio.run(send_message('$CHEF_CHAT', '✅ Token refreshed, gateway restarted. Lumina back on Opus.', parse_mode='markdown'))
|
|
85
|
+
" 2>&1 || true
|
|
86
|
+
log "Recovery complete"
|
|
87
|
+
else
|
|
88
|
+
log "Token refresh failed — manual intervention may be needed"
|
|
89
|
+
fi
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
log "Starting model fallback monitor..."
|
|
93
|
+
|
|
94
|
+
# Follow gateway logs in real-time, watching for fallback events
|
|
95
|
+
journalctl --user -u openclaw-gateway -f --no-pager 2>/dev/null | while IFS= read -r line; do
|
|
96
|
+
# Match: "model fallback decision: decision=candidate_succeeded ... candidate=nvidia/"
|
|
97
|
+
if echo "$line" | grep -q "candidate_succeeded.*candidate=nvidia/"; then
|
|
98
|
+
model=$(echo "$line" | grep -oP 'candidate=\K[^ ]+' || echo "unknown")
|
|
99
|
+
log "FALLBACK DETECTED: Lumina now on $model"
|
|
100
|
+
send_alert "$model" "OAuth token expired (401)"
|
|
101
|
+
fi
|
|
102
|
+
done
|