mirror of
https://github.com/dtzp555-max/memory-continuity.git
synced 2026-07-19 09:42:42 +00:00
294 lines
8.6 KiB
Bash
Executable File
294 lines
8.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# post-install.sh — Install memory-continuity as an OpenClaw lifecycle plugin
|
|
#
|
|
# This script:
|
|
# 1. Copies the plugin to ~/.openclaw/extensions/memory-continuity/
|
|
# 2. Adds the plugin entry to openclaw.json (if not present)
|
|
# 3. Detects OpenClaw agents and installs SKILL.md to selected workspaces
|
|
#
|
|
# Usage:
|
|
# bash scripts/post-install.sh
|
|
#
|
|
# Safe to run multiple times (idempotent).
|
|
|
|
set -euo pipefail
|
|
|
|
OPENCLAW_DIR="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}"
|
|
EXTENSIONS_DIR="$OPENCLAW_DIR/extensions"
|
|
PLUGIN_DIR="$EXTENSIONS_DIR/memory-continuity"
|
|
CONFIG_FILE="$OPENCLAW_DIR/openclaw.json"
|
|
|
|
# Resolve the repo root (parent of scripts/)
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
echo "=== memory-continuity plugin installer ==="
|
|
echo ""
|
|
|
|
# Step 1: Copy plugin files to extensions directory
|
|
echo "[1/3] Installing plugin to $PLUGIN_DIR ..."
|
|
mkdir -p "$EXTENSIONS_DIR"
|
|
|
|
# Remove old installation if exists
|
|
if [[ -d "$PLUGIN_DIR" || -L "$PLUGIN_DIR" ]]; then
|
|
rm -rf "$PLUGIN_DIR"
|
|
echo " Removed previous installation"
|
|
fi
|
|
|
|
# Copy essential plugin files (not the entire repo)
|
|
mkdir -p "$PLUGIN_DIR"
|
|
for f in index.js openclaw.plugin.json package.json SKILL.md; do
|
|
if [[ -f "$REPO_DIR/$f" ]]; then
|
|
cp "$REPO_DIR/$f" "$PLUGIN_DIR/"
|
|
fi
|
|
done
|
|
echo " Copied plugin files"
|
|
|
|
# Step 2: Add plugin entry to openclaw.json
|
|
echo "[2/3] Configuring openclaw.json ..."
|
|
if [[ ! -f "$CONFIG_FILE" ]]; then
|
|
echo " WARNING: $CONFIG_FILE not found. Skipping config update."
|
|
echo " You'll need to manually add the plugin entry."
|
|
else
|
|
python3 -c "
|
|
import json
|
|
path = '$CONFIG_FILE'
|
|
with open(path) as f:
|
|
data = json.load(f)
|
|
if 'plugins' not in data:
|
|
data['plugins'] = {}
|
|
allow_list = data['plugins'].get('allow', [])
|
|
if 'memory-continuity' not in allow_list:
|
|
allow_list.append('memory-continuity')
|
|
data['plugins']['allow'] = allow_list
|
|
if 'entries' not in data['plugins']:
|
|
data['plugins']['entries'] = {}
|
|
data['plugins']['entries']['memory-continuity'] = {
|
|
'enabled': True,
|
|
'hooks': {
|
|
'allowPromptInjection': True
|
|
},
|
|
'config': {
|
|
'maxStateLines': 50,
|
|
'archiveOnNew': True,
|
|
'autoExtract': True
|
|
}
|
|
}
|
|
if 'installs' not in data['plugins']:
|
|
data['plugins']['installs'] = {}
|
|
data['plugins']['installs']['memory-continuity'] = {
|
|
'source': 'path',
|
|
'installPath': '~/.openclaw/extensions/memory-continuity',
|
|
'sourcePath': '$REPO_DIR'
|
|
}
|
|
with open(path, 'w') as f:
|
|
json.dump(data, f, indent=2)
|
|
print(' Added plugin entry, trust config, and install record')
|
|
" 2>/dev/null || echo " WARNING: Could not update config automatically. Add manually."
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Step 3: Detect agents and install SKILL.md to selected workspaces
|
|
# ---------------------------------------------------------------------------
|
|
echo "[3/3] Detecting OpenClaw agents ..."
|
|
|
|
GRAY='\033[0;90m'
|
|
RST='\033[0m'
|
|
|
|
# detect_agents outputs lines of: INDEX|ID|DISPLAY_NAME|WORKSPACE_PATH
|
|
# Uses python3 to parse openclaw.json; falls back gracefully if unavailable.
|
|
detect_agents() {
|
|
if [[ ! -f "$CONFIG_FILE" ]]; then
|
|
return 1
|
|
fi
|
|
|
|
python3 - "$CONFIG_FILE" "$OPENCLAW_DIR" <<'PYEOF'
|
|
import json, sys, os
|
|
|
|
config_file = sys.argv[1]
|
|
openclaw_dir = sys.argv[2]
|
|
|
|
with open(config_file) as f:
|
|
data = json.load(f)
|
|
|
|
default_ws = data.get('agents', {}).get('defaults', {}).get('workspace', os.path.join(openclaw_dir, 'workspace', 'main'))
|
|
|
|
agents = data.get('agents', {}).get('list', [])
|
|
seen = set()
|
|
idx = 1
|
|
|
|
for agent in agents:
|
|
agent_id = agent.get('id', '')
|
|
if not agent_id or agent_id in seen:
|
|
continue
|
|
seen.add(agent_id)
|
|
|
|
name = agent.get('name', agent_id)
|
|
workspace = agent.get('workspace', default_ws)
|
|
|
|
# Expand ~ in path
|
|
workspace = os.path.expanduser(workspace)
|
|
|
|
print('{}|{}|{}|{}'.format(idx, agent_id, name, workspace))
|
|
idx += 1
|
|
|
|
PYEOF
|
|
}
|
|
|
|
# Collect ALL detected agents (including non-alive) into arrays
|
|
ALL_AGENT_IDS=()
|
|
ALL_AGENT_NAMES=()
|
|
ALL_AGENT_WORKSPACES=()
|
|
|
|
if command -v python3 &>/dev/null && [[ -f "$CONFIG_FILE" ]]; then
|
|
while IFS='|' read -r idx agent_id agent_name workspace; do
|
|
ALL_AGENT_IDS+=("$agent_id")
|
|
ALL_AGENT_NAMES+=("$agent_name")
|
|
ALL_AGENT_WORKSPACES+=("$workspace")
|
|
done < <(detect_agents 2>/dev/null || true)
|
|
fi
|
|
|
|
# Filter to alive agents (workspace directory exists)
|
|
AGENT_IDS=()
|
|
AGENT_NAMES=()
|
|
AGENT_WORKSPACES=()
|
|
SKIPPED=0
|
|
|
|
for i in "${!ALL_AGENT_IDS[@]}"; do
|
|
if [[ -d "${ALL_AGENT_WORKSPACES[$i]}" ]]; then
|
|
AGENT_IDS+=("${ALL_AGENT_IDS[$i]}")
|
|
AGENT_NAMES+=("${ALL_AGENT_NAMES[$i]}")
|
|
AGENT_WORKSPACES+=("${ALL_AGENT_WORKSPACES[$i]}")
|
|
else
|
|
SKIPPED=$((SKIPPED + 1))
|
|
fi
|
|
done
|
|
|
|
install_skill_to_workspace() {
|
|
local workspace="$1"
|
|
local skill_dest="${workspace}/skills/memory-continuity"
|
|
mkdir -p "$skill_dest"
|
|
cp "$REPO_DIR/SKILL.md" "$skill_dest/SKILL.md"
|
|
echo " Installed → ${skill_dest}/SKILL.md"
|
|
}
|
|
|
|
if [[ ${#AGENT_IDS[@]} -eq 0 && ${#ALL_AGENT_IDS[@]} -gt 0 ]]; then
|
|
# Config has agents but none are alive
|
|
echo ""
|
|
echo " Found ${#ALL_AGENT_IDS[@]} agent(s) in config but their workspace directories don't exist yet."
|
|
echo " You may need to initialize them first."
|
|
echo ""
|
|
printf " Enter workspace path to install SKILL.md (or press Enter to skip): "
|
|
read -r FALLBACK_WS
|
|
if [[ -n "$FALLBACK_WS" ]]; then
|
|
FALLBACK_WS="${FALLBACK_WS/#\~/$HOME}"
|
|
install_skill_to_workspace "$FALLBACK_WS"
|
|
else
|
|
echo " Skipped SKILL.md installation."
|
|
fi
|
|
elif [[ ${#AGENT_IDS[@]} -eq 0 ]]; then
|
|
# No agents at all — ask user for a workspace path
|
|
echo " No agents detected in openclaw.json (file missing or parse error)."
|
|
echo ""
|
|
printf " Enter workspace path to install SKILL.md (or press Enter to skip): "
|
|
read -r FALLBACK_WS
|
|
if [[ -n "$FALLBACK_WS" ]]; then
|
|
FALLBACK_WS="${FALLBACK_WS/#\~/$HOME}"
|
|
install_skill_to_workspace "$FALLBACK_WS"
|
|
else
|
|
echo " Skipped SKILL.md installation."
|
|
fi
|
|
else
|
|
# Show numbered list — alive agents first, then skipped summary
|
|
echo ""
|
|
echo " Found ${#AGENT_IDS[@]} alive agent(s):"
|
|
for i in "${!AGENT_IDS[@]}"; do
|
|
num=$((i + 1))
|
|
printf " [%d] %s (%s)\n" "$num" "${AGENT_NAMES[$i]}" "${AGENT_WORKSPACES[$i]}"
|
|
done
|
|
|
|
# Show skipped (non-alive) agents in gray
|
|
if [[ $SKIPPED -gt 0 ]]; then
|
|
echo ""
|
|
printf " ${GRAY}Skipped %d agent(s) with missing workspace directories:${RST}\n" "$SKIPPED"
|
|
for i in "${!ALL_AGENT_IDS[@]}"; do
|
|
if [[ ! -d "${ALL_AGENT_WORKSPACES[$i]}" ]]; then
|
|
printf " ${GRAY} %s (%s)${RST}\n" "${ALL_AGENT_NAMES[$i]}" "${ALL_AGENT_WORKSPACES[$i]}"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
echo ""
|
|
echo " Install to: [A]ll alive agents (default) / [1,2,...] specific / [Q]uit"
|
|
printf " > (20s timeout, Enter or no input = All) "
|
|
|
|
# Auto-select All if stdin is not a tty (pipe/CI) or on timeout
|
|
if [[ ! -t 0 ]]; then
|
|
SELECTION="A"
|
|
echo "(non-interactive: auto-selecting All)"
|
|
elif read -t 20 -r SELECTION; then
|
|
# User provided input (possibly empty = Enter)
|
|
: # SELECTION is set
|
|
else
|
|
# Timeout — default to All
|
|
echo ""
|
|
echo " (timeout — defaulting to All)"
|
|
SELECTION=""
|
|
fi
|
|
|
|
# Empty input (Enter or timeout) defaults to All
|
|
if [[ -z "$SELECTION" ]]; then
|
|
SELECTION="A"
|
|
fi
|
|
|
|
SELECTION_UPPER="$(echo "$SELECTION" | tr '[:lower:]' '[:upper:]')"
|
|
case "$SELECTION_UPPER" in
|
|
A|ALL)
|
|
for i in "${!AGENT_IDS[@]}"; do
|
|
install_skill_to_workspace "${AGENT_WORKSPACES[$i]}"
|
|
done
|
|
;;
|
|
Q|QUIT)
|
|
echo " Skipped SKILL.md installation."
|
|
;;
|
|
*)
|
|
# Parse comma-separated numbers
|
|
IFS=',' read -ra PICKS <<< "$SELECTION"
|
|
INSTALLED=0
|
|
for pick in "${PICKS[@]}"; do
|
|
pick="${pick// /}" # trim spaces
|
|
if [[ "$pick" =~ ^[0-9]+$ ]]; then
|
|
idx=$((pick - 1))
|
|
if [[ $idx -ge 0 && $idx -lt ${#AGENT_IDS[@]} ]]; then
|
|
install_skill_to_workspace "${AGENT_WORKSPACES[$idx]}"
|
|
INSTALLED=$((INSTALLED + 1))
|
|
else
|
|
echo " WARNING: No agent at index $pick — skipped."
|
|
fi
|
|
else
|
|
echo " WARNING: Invalid selection '$pick' — skipped."
|
|
fi
|
|
done
|
|
if [[ $INSTALLED -eq 0 ]]; then
|
|
echo " No valid selections — SKILL.md not installed."
|
|
fi
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
echo ""
|
|
echo "🧙 启动配置向导..."
|
|
python3 "$(dirname "$0")/setup_wizard.py" || true
|
|
|
|
echo ""
|
|
echo "=== Installation complete ==="
|
|
echo ""
|
|
echo "Verify with:"
|
|
echo " bash scripts/verify.sh"
|
|
echo " bash scripts/verify.sh --all-agents"
|
|
echo ""
|
|
echo "Test with:"
|
|
echo " 1. Tell your agent something memorable"
|
|
echo " 2. Send /new"
|
|
echo " 3. Ask what you told it"
|