-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall-suboculo-opencode.sh
More file actions
executable file
·163 lines (141 loc) · 5.4 KB
/
install-suboculo-opencode.sh
File metadata and controls
executable file
·163 lines (141 loc) · 5.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#!/usr/bin/env bash
set -e
# Suboculo Installation Script for OpenCode
# Copies required files and sets up per-project monitoring
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TARGET_DIR=""
PORT=3000
require_cmd() {
if ! command -v "$1" >/dev/null 2>&1; then
echo "❌ Error: Required command not found: $1"
exit 1
fi
}
patch_port_in_file() {
local file="$1"
local pattern="$2"
local replacement="$3"
node -e '
const fs = require("fs");
const [file, pattern, replacement] = process.argv.slice(1);
const input = fs.readFileSync(file, "utf8");
const output = input.split(pattern).join(replacement);
if (input === output) {
console.error(`❌ Error: Failed to patch ${file}; pattern not found: ${pattern}`);
process.exit(1);
}
fs.writeFileSync(file, output);
' "$file" "$pattern" "$replacement"
}
# Parse arguments
while [ $# -gt 0 ]; do
case "$1" in
--port)
PORT="$2"
shift 2
;;
*)
TARGET_DIR="$1"
shift
;;
esac
done
TARGET_DIR="${TARGET_DIR:-.}"
TARGET_ABS_DIR="$(cd "$TARGET_DIR" && pwd)"
SUBOCULO_DB_PATH="$TARGET_ABS_DIR/.suboculo/events.db"
echo "📊 Installing Suboculo for OpenCode to: $TARGET_DIR (port: $PORT)"
echo ""
# Validate target directory
if [ ! -d "$TARGET_DIR" ]; then
echo "❌ Error: Target directory does not exist: $TARGET_DIR"
exit 1
fi
# Preflight checks before mutating target project
require_cmd node
require_cmd npm
require_cmd jq
require_cmd mktemp
# Create .suboculo directory for shared backend/database
SUBOCULO_DIR="$TARGET_ABS_DIR/.suboculo"
mkdir -p "$SUBOCULO_DIR/backend"
mkdir -p "$SUBOCULO_DIR/backend/db"
mkdir -p "$SUBOCULO_DIR/backend/domain"
mkdir -p "$SUBOCULO_DIR/backend/repositories"
mkdir -p "$SUBOCULO_DIR/backend/routes"
mkdir -p "$SUBOCULO_DIR/frontend"
# Create .opencode directory for plugin
OPENCODE_DIR="$TARGET_ABS_DIR/.opencode"
mkdir -p "$OPENCODE_DIR/plugins"
# Build frontend
echo "🔨 Building frontend..."
cd "$SCRIPT_DIR/svelte-app"
npm install --silent 2>/dev/null
if ! npm run build >/dev/null 2>&1; then
echo "❌ Frontend build failed. Running again with output:"
npm run build
exit 1
fi
cd "$TARGET_ABS_DIR"
# Copy backend files (shared with Claude Code integration)
echo "📋 Copying backend files..."
cp "$SCRIPT_DIR/backend/mcp-analytics-server.mjs" "$SUBOCULO_DIR/backend/"
cp "$SCRIPT_DIR/backend/server.js" "$SUBOCULO_DIR/backend/"
cp "$SCRIPT_DIR/backend/app.js" "$SUBOCULO_DIR/backend/"
cp "$SCRIPT_DIR/backend/logger.js" "$SUBOCULO_DIR/backend/"
patch_port_in_file "$SUBOCULO_DIR/backend/server.js" "process.env.SUBOCULO_PORT || 3000" "process.env.SUBOCULO_PORT || $PORT"
cp "$SCRIPT_DIR/backend/cep-processor.js" "$SUBOCULO_DIR/backend/"
cp "$SCRIPT_DIR/backend/db/"*.js "$SUBOCULO_DIR/backend/db/"
cp "$SCRIPT_DIR/backend/domain/"*.js "$SUBOCULO_DIR/backend/domain/"
cp "$SCRIPT_DIR/backend/repositories/"*.js "$SUBOCULO_DIR/backend/repositories/"
cp "$SCRIPT_DIR/backend/routes/"*.js "$SUBOCULO_DIR/backend/routes/"
cp -r "$SCRIPT_DIR/svelte-app/dist/"* "$SUBOCULO_DIR/frontend/" 2>/dev/null || echo "⚠️ Frontend not built yet (run 'cd svelte-app && npm run build')"
if [ -f "$SCRIPT_DIR/.suboculo/thresholds.example.json" ]; then
cp "$SCRIPT_DIR/.suboculo/thresholds.example.json" "$SUBOCULO_DIR/thresholds.example.json"
fi
# Copy OpenCode plugin
echo "📋 Copying OpenCode plugin..."
cp "$SCRIPT_DIR/integrations/opencode/plugins/suboculo.js" "$OPENCODE_DIR/plugins/"
patch_port_in_file "$OPENCODE_DIR/plugins/suboculo.js" "const NOTIFY_PORT = 3000" "const NOTIFY_PORT = $PORT"
# Note: OpenCode uses Bun, and the plugin uses built-in bun:sqlite (no plugin dependencies needed)
# Copy backend package.json
cp "$SCRIPT_DIR/integrations/claude-code/hooks/package.json" "$SUBOCULO_DIR/"
# Install backend dependencies
echo "📦 Installing backend dependencies..."
cd "$SUBOCULO_DIR"
npm install --silent
cd "$TARGET_ABS_DIR"
# Create or merge opencode.json
OPENCODE_CONFIG="$TARGET_ABS_DIR/opencode.json"
SUBOCULO_MCP="{\"type\":\"local\",\"command\":[\"node\",\"./.suboculo/backend/mcp-analytics-server.mjs\"],\"environment\":{\"SUBOCULO_DB_PATH\":\".suboculo/events.db\",\"SUBOCULO_PORT\":\"$PORT\"},\"enabled\":true}"
if [ -f "$OPENCODE_CONFIG" ] && [ -s "$OPENCODE_CONFIG" ]; then
echo "⚙️ Merging suboculo into existing opencode.json..."
TEMP_FILE=$(mktemp)
jq --argjson srv "$SUBOCULO_MCP" '.mcp.suboculo = $srv' "$OPENCODE_CONFIG" > "$TEMP_FILE"
mv "$TEMP_FILE" "$OPENCODE_CONFIG"
else
echo "⚙️ Generating opencode.json..."
jq -n --argjson srv "$SUBOCULO_MCP" '{mcp: {suboculo: $srv}}' > "$OPENCODE_CONFIG"
fi
# Create .gitignore entries
if [ -f "$TARGET_ABS_DIR/.gitignore" ]; then
if ! grep -q "^\.suboculo/$" "$TARGET_ABS_DIR/.gitignore" 2>/dev/null; then
echo "📝 Adding .suboculo/ to .gitignore..."
echo ".suboculo/" >> "$TARGET_ABS_DIR/.gitignore"
fi
fi
echo ""
echo "✅ Suboculo for OpenCode installed successfully!"
echo ""
echo "📌 Next steps:"
echo ""
echo "1. Restart OpenCode"
echo "2. Run any tool to generate events"
echo "3. Query via MCP: 'What tools have I used?'"
echo "4. Start web UI: cd $TARGET_ABS_DIR && node ./.suboculo/backend/server.js"
echo " Then open http://localhost:$PORT"
echo ""
echo "📊 Data stored in: $SUBOCULO_DB_PATH"
echo "🔧 MCP server configured in: opencode.json"
echo "🌐 Web UI available at: .suboculo/backend/server.js"
echo "🔌 Plugin installed at: .opencode/plugins/suboculo.js"
echo ""