@shakudo/opencode-mattermost-control 0.3.45

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.
Files changed (69) hide show
  1. package/.opencode/command/mattermost-connect.md +5 -0
  2. package/.opencode/command/mattermost-disconnect.md +5 -0
  3. package/.opencode/command/mattermost-monitor.md +12 -0
  4. package/.opencode/command/mattermost-status.md +5 -0
  5. package/.opencode/command/speckit.analyze.md +184 -0
  6. package/.opencode/command/speckit.checklist.md +294 -0
  7. package/.opencode/command/speckit.clarify.md +181 -0
  8. package/.opencode/command/speckit.constitution.md +82 -0
  9. package/.opencode/command/speckit.implement.md +135 -0
  10. package/.opencode/command/speckit.plan.md +89 -0
  11. package/.opencode/command/speckit.specify.md +258 -0
  12. package/.opencode/command/speckit.tasks.md +137 -0
  13. package/.opencode/command/speckit.taskstoissues.md +30 -0
  14. package/.opencode/plugin/mattermost-control/event-handlers/compaction.ts +61 -0
  15. package/.opencode/plugin/mattermost-control/event-handlers/file.ts +36 -0
  16. package/.opencode/plugin/mattermost-control/event-handlers/index.ts +14 -0
  17. package/.opencode/plugin/mattermost-control/event-handlers/message.ts +124 -0
  18. package/.opencode/plugin/mattermost-control/event-handlers/permission.ts +34 -0
  19. package/.opencode/plugin/mattermost-control/event-handlers/question.ts +92 -0
  20. package/.opencode/plugin/mattermost-control/event-handlers/session.ts +100 -0
  21. package/.opencode/plugin/mattermost-control/event-handlers/todo.ts +33 -0
  22. package/.opencode/plugin/mattermost-control/event-handlers/tool.ts +76 -0
  23. package/.opencode/plugin/mattermost-control/formatters.ts +202 -0
  24. package/.opencode/plugin/mattermost-control/index.ts +964 -0
  25. package/.opencode/plugin/mattermost-control/package.json +12 -0
  26. package/.opencode/plugin/mattermost-control/state.ts +180 -0
  27. package/.opencode/plugin/mattermost-control/timers.ts +96 -0
  28. package/.opencode/plugin/mattermost-control/tools/connect.ts +563 -0
  29. package/.opencode/plugin/mattermost-control/tools/file.ts +41 -0
  30. package/.opencode/plugin/mattermost-control/tools/index.ts +12 -0
  31. package/.opencode/plugin/mattermost-control/tools/monitor.ts +183 -0
  32. package/.opencode/plugin/mattermost-control/tools/schedule.ts +253 -0
  33. package/.opencode/plugin/mattermost-control/tools/session.ts +120 -0
  34. package/.opencode/plugin/mattermost-control/types.ts +107 -0
  35. package/LICENSE +21 -0
  36. package/README.md +1280 -0
  37. package/opencode-shared +359 -0
  38. package/opencode-shared-restart +495 -0
  39. package/opencode-shared-stop +90 -0
  40. package/package.json +65 -0
  41. package/src/clients/mattermost-client.ts +221 -0
  42. package/src/clients/websocket-client.ts +199 -0
  43. package/src/command-handler.ts +1035 -0
  44. package/src/config.ts +170 -0
  45. package/src/context-builder.ts +309 -0
  46. package/src/file-completion-handler.ts +521 -0
  47. package/src/file-handler.ts +242 -0
  48. package/src/guest-approval-handler.ts +223 -0
  49. package/src/logger.ts +73 -0
  50. package/src/merge-handler.ts +335 -0
  51. package/src/message-router.ts +151 -0
  52. package/src/models/index.ts +197 -0
  53. package/src/models/routing.ts +50 -0
  54. package/src/models/thread-mapping.ts +40 -0
  55. package/src/monitor-service.ts +222 -0
  56. package/src/notification-service.ts +118 -0
  57. package/src/opencode-session-registry.ts +370 -0
  58. package/src/persistence/team-store.ts +396 -0
  59. package/src/persistence/thread-mapping-store.ts +258 -0
  60. package/src/question-handler.ts +401 -0
  61. package/src/reaction-handler.ts +111 -0
  62. package/src/response-streamer.ts +364 -0
  63. package/src/scheduler/schedule-store.ts +261 -0
  64. package/src/scheduler/scheduler-service.ts +349 -0
  65. package/src/session-manager.ts +142 -0
  66. package/src/session-ownership-handler.ts +253 -0
  67. package/src/status-indicator.ts +279 -0
  68. package/src/thread-manager.ts +231 -0
  69. package/src/todo-manager.ts +162 -0
@@ -0,0 +1,359 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # opencode-shared - Start or attach to a shared OpenCode server
4
+ #
5
+ # Usage:
6
+ # ./opencode-shared [options]
7
+ #
8
+ # Options are passed through to 'opencode attach' (e.g., --session <id>)
9
+ #
10
+ # Environment variables:
11
+ # OPENCODE_SERVER_PORT - Port for the shared server (default: 4096)
12
+ # OPENCODE_SERVER_PASSWORD - Password for server authentication (optional)
13
+ # OPENCODE_SERVER_LOG - Log file path (default: /tmp/opencode-server.log)
14
+ #
15
+ # Auto-restart configuration:
16
+ # OPENCODE_AUTO_RESTART - Enable auto-restart (default: true)
17
+ # OPENCODE_MONITOR_INTERVAL - Health check interval in seconds (default: 2)
18
+ # OPENCODE_RESTART_MAX_ATTEMPTS - Max restarts in window before backoff (default: 5)
19
+ # OPENCODE_RESTART_WINDOW - Time window for counting restarts in seconds (default: 300)
20
+ # OPENCODE_RESTART_BACKOFF_BASE - Base backoff time in seconds (default: 1)
21
+ # OPENCODE_RESTART_BACKOFF_MAX - Maximum backoff time in seconds (default: 60)
22
+ # OPENCODE_HEALTH_TIMEOUT - Health check timeout in seconds (default: 2)
23
+ # OPENCODE_HEALTH_FAIL_THRESHOLD - Consecutive health failures before restart (default: 3)
24
+ # OPENCODE_STARTUP_TIMEOUT - Server startup timeout in seconds (default: 15)
25
+ #
26
+
27
+ set -euo pipefail
28
+
29
+ # =============================================================================
30
+ # Configuration
31
+ # =============================================================================
32
+
33
+ PORT="${OPENCODE_SERVER_PORT:-4096}"
34
+ SERVER_URL="http://localhost:${PORT}"
35
+
36
+ # Log files
37
+ SERVER_LOG="${OPENCODE_SERVER_LOG:-/tmp/opencode-server.log}"
38
+ SUPERVISOR_LOG="${OPENCODE_SUPERVISOR_LOG:-/tmp/opencode-server.supervisor.log}"
39
+
40
+ # State files
41
+ PIDFILE="/tmp/opencode-server.pid"
42
+ SUPERVISOR_PIDFILE="/tmp/opencode-server.supervisor.pid"
43
+ STOP_FLAG="/tmp/opencode-server.stop"
44
+ LOCKDIR="/tmp/opencode-server.supervisor.lock"
45
+
46
+ # Auto-restart settings
47
+ AUTO_RESTART="${OPENCODE_AUTO_RESTART:-true}"
48
+ MONITOR_INTERVAL="${OPENCODE_MONITOR_INTERVAL:-2}"
49
+ STARTUP_TIMEOUT="${OPENCODE_STARTUP_TIMEOUT:-15}"
50
+
51
+ # Health check settings
52
+ HEALTH_PATH="${OPENCODE_HEALTH_PATH:-/global/health}"
53
+ HEALTH_TIMEOUT="${OPENCODE_HEALTH_TIMEOUT:-2}"
54
+ HEALTH_FAIL_THRESHOLD="${OPENCODE_HEALTH_FAIL_THRESHOLD:-3}"
55
+
56
+ # Restart/backoff settings
57
+ RESTART_MAX="${OPENCODE_RESTART_MAX_ATTEMPTS:-5}"
58
+ RESTART_WINDOW="${OPENCODE_RESTART_WINDOW:-300}"
59
+ BACKOFF_BASE="${OPENCODE_RESTART_BACKOFF_BASE:-1}"
60
+ BACKOFF_MAX="${OPENCODE_RESTART_BACKOFF_MAX:-60}"
61
+
62
+ # =============================================================================
63
+ # Utility Functions
64
+ # =============================================================================
65
+
66
+ # Timestamp for logging
67
+ ts() { date -Iseconds 2>/dev/null || date '+%Y-%m-%dT%H:%M:%S'; }
68
+
69
+ # Log to supervisor log file
70
+ log_supervisor() {
71
+ printf '%s [supervisor] %s\n' "$(ts)" "$*" >> "$SUPERVISOR_LOG"
72
+ }
73
+
74
+ # Log to stdout
75
+ log_info() {
76
+ echo "$*"
77
+ }
78
+
79
+ # =============================================================================
80
+ # Server Health & Status Functions
81
+ # =============================================================================
82
+
83
+ # Check if server PID is alive
84
+ pid_alive() {
85
+ [[ -f "$PIDFILE" ]] || return 1
86
+ local pid
87
+ pid="$(cat "$PIDFILE" 2>/dev/null || true)"
88
+ [[ -n "${pid:-}" ]] || return 1
89
+ kill -0 "$pid" 2>/dev/null
90
+ }
91
+
92
+ # Check server health via HTTP endpoint
93
+ health_ok() {
94
+ curl -fsS --max-time "$HEALTH_TIMEOUT" "${SERVER_URL}${HEALTH_PATH}" >/dev/null 2>&1 || \
95
+ curl -fsS --max-time "$HEALTH_TIMEOUT" "${SERVER_URL}/health" >/dev/null 2>&1 || \
96
+ curl -fsS --max-time "$HEALTH_TIMEOUT" "${SERVER_URL}" >/dev/null 2>&1
97
+ }
98
+
99
+ # Check if server is running (PID alive + responding)
100
+ is_server_running() {
101
+ if [[ -f "$PIDFILE" ]]; then
102
+ local pid
103
+ pid=$(cat "$PIDFILE" 2>/dev/null || true)
104
+ if [[ -n "${pid:-}" ]] && kill -0 "$pid" 2>/dev/null; then
105
+ # Process exists, verify it's actually responding
106
+ if health_ok || nc -z localhost "$PORT" 2>/dev/null; then
107
+ return 0
108
+ fi
109
+ fi
110
+ # Stale PID file, remove it
111
+ rm -f "$PIDFILE"
112
+ fi
113
+
114
+ # No PID file, but check if something is listening on the port anyway
115
+ if nc -z localhost "$PORT" 2>/dev/null; then
116
+ return 0
117
+ fi
118
+
119
+ return 1
120
+ }
121
+
122
+ # =============================================================================
123
+ # Server Lifecycle Functions
124
+ # =============================================================================
125
+
126
+ # Start the server in the background
127
+ start_server() {
128
+ log_info "Starting OpenCode shared server on port ${PORT}..."
129
+
130
+ rm -f "$PIDFILE"
131
+ nohup opencode serve --port "$PORT" >> "$SERVER_LOG" 2>&1 &
132
+ local server_pid=$!
133
+ echo "$server_pid" > "$PIDFILE"
134
+
135
+ log_info "Server process started (PID: ${server_pid})"
136
+ log_info "Server logs: ${SERVER_LOG}"
137
+ }
138
+
139
+ # Wait for server to become ready
140
+ wait_server_ready() {
141
+ local max_attempts=$((STARTUP_TIMEOUT * 2)) # Check every 0.5s
142
+ local attempt=0
143
+
144
+ while [[ $attempt -lt $max_attempts ]]; do
145
+ if nc -z localhost "$PORT" 2>/dev/null; then
146
+ return 0
147
+ fi
148
+
149
+ # Check if process is still running
150
+ if ! pid_alive; then
151
+ return 1
152
+ fi
153
+
154
+ sleep 0.5
155
+ attempt=$((attempt + 1))
156
+ done
157
+
158
+ return 1
159
+ }
160
+
161
+ # Start server and wait for it to be ready
162
+ start_server_and_wait() {
163
+ start_server
164
+
165
+ if wait_server_ready; then
166
+ local pid
167
+ pid=$(cat "$PIDFILE" 2>/dev/null || echo "unknown")
168
+ log_info "Server ready (PID: ${pid})"
169
+ return 0
170
+ else
171
+ log_info "Error: Server failed to start within ${STARTUP_TIMEOUT} seconds. Check logs: ${SERVER_LOG}"
172
+ rm -f "$PIDFILE"
173
+ return 1
174
+ fi
175
+ }
176
+
177
+ # =============================================================================
178
+ # Supervisor Functions
179
+ # =============================================================================
180
+
181
+ # Calculate exponential backoff time
182
+ calc_backoff() {
183
+ local n="$1"
184
+ local backoff=$((BACKOFF_BASE * (2 ** (n - 1))))
185
+ if [[ $backoff -gt $BACKOFF_MAX ]]; then
186
+ backoff="$BACKOFF_MAX"
187
+ fi
188
+ echo "$backoff"
189
+ }
190
+
191
+ # The supervisor loop - monitors and restarts server
192
+ supervise() {
193
+ # Acquire lock (only one supervisor allowed)
194
+ if ! mkdir "$LOCKDIR" 2>/dev/null; then
195
+ # Another supervisor is running
196
+ exit 0
197
+ fi
198
+
199
+ # Save our PID
200
+ echo "$$" > "$SUPERVISOR_PIDFILE"
201
+ log_supervisor "supervisor started pid=$$"
202
+
203
+ # Cleanup on exit
204
+ trap 'rm -f "$SUPERVISOR_PIDFILE"; rmdir "$LOCKDIR" 2>/dev/null || true; log_supervisor "supervisor stopped"' EXIT
205
+
206
+ # Track restart times for backoff calculation
207
+ local -a restart_times=()
208
+ local health_fail_count=0
209
+
210
+ while true; do
211
+ # Check for stop flag
212
+ if [[ -f "$STOP_FLAG" ]]; then
213
+ log_supervisor "stop flag detected, exiting"
214
+ break
215
+ fi
216
+
217
+ # Check server health
218
+ if pid_alive && health_ok; then
219
+ # Server is healthy
220
+ health_fail_count=0
221
+ sleep "$MONITOR_INTERVAL"
222
+ continue
223
+ fi
224
+
225
+ # Server might be unhealthy or down
226
+ if pid_alive && ! health_ok; then
227
+ # Process alive but not responding to health checks
228
+ health_fail_count=$((health_fail_count + 1))
229
+ log_supervisor "health check failed (${health_fail_count}/${HEALTH_FAIL_THRESHOLD})"
230
+
231
+ if [[ $health_fail_count -lt $HEALTH_FAIL_THRESHOLD ]]; then
232
+ sleep "$MONITOR_INTERVAL"
233
+ continue
234
+ fi
235
+
236
+ # Threshold exceeded, kill and restart
237
+ log_supervisor "health threshold exceeded, killing server"
238
+ local pid
239
+ pid=$(cat "$PIDFILE" 2>/dev/null || true)
240
+ if [[ -n "${pid:-}" ]]; then
241
+ kill "$pid" 2>/dev/null || true
242
+ sleep 1
243
+ kill -9 "$pid" 2>/dev/null || true
244
+ fi
245
+ rm -f "$PIDFILE"
246
+ health_fail_count=0
247
+ else
248
+ # Server is down
249
+ log_supervisor "server down, preparing restart"
250
+ fi
251
+
252
+ # Re-check stop flag before restart
253
+ if [[ -f "$STOP_FLAG" ]]; then
254
+ log_supervisor "stop flag detected before restart, exiting"
255
+ break
256
+ fi
257
+
258
+ # Calculate restarts in window for backoff
259
+ local now
260
+ now="$(date +%s)"
261
+ local -a recent=()
262
+ for t in "${restart_times[@]:-}"; do
263
+ if [[ $((now - t)) -lt $RESTART_WINDOW ]]; then
264
+ recent+=("$t")
265
+ fi
266
+ done
267
+ restart_times=("${recent[@]}")
268
+ restart_times+=("$now")
269
+
270
+ local restart_count="${#restart_times[@]}"
271
+
272
+ # Apply backoff if too many restarts
273
+ if [[ $restart_count -gt 1 ]]; then
274
+ local backoff
275
+ backoff="$(calc_backoff "$restart_count")"
276
+ log_supervisor "backoff ${backoff}s (restart #${restart_count} in ${RESTART_WINDOW}s window)"
277
+ sleep "$backoff"
278
+
279
+ # Re-check stop flag after backoff
280
+ if [[ -f "$STOP_FLAG" ]]; then
281
+ log_supervisor "stop flag detected after backoff, exiting"
282
+ break
283
+ fi
284
+ fi
285
+
286
+ # Restart the server
287
+ log_supervisor "restarting server..."
288
+ start_server
289
+
290
+ if wait_server_ready; then
291
+ local pid
292
+ pid=$(cat "$PIDFILE" 2>/dev/null || echo "unknown")
293
+ log_supervisor "server restarted successfully (PID: ${pid})"
294
+ else
295
+ log_supervisor "server failed to start, will retry"
296
+ rm -f "$PIDFILE"
297
+ fi
298
+
299
+ sleep "$MONITOR_INTERVAL"
300
+ done
301
+ }
302
+
303
+ # Ensure supervisor is running (spawn if needed)
304
+ ensure_supervisor_running() {
305
+ [[ "$AUTO_RESTART" == "true" ]] || return 0
306
+
307
+ # Check if supervisor is already running
308
+ if [[ -f "$SUPERVISOR_PIDFILE" ]]; then
309
+ local spid
310
+ spid="$(cat "$SUPERVISOR_PIDFILE" 2>/dev/null || true)"
311
+ if [[ -n "${spid:-}" ]] && kill -0 "$spid" 2>/dev/null; then
312
+ # Supervisor already running
313
+ return 0
314
+ fi
315
+ fi
316
+
317
+ # Clear stale stop flag from previous runs
318
+ rm -f "$STOP_FLAG"
319
+
320
+ # Spawn supervisor as background process
321
+ log_info "Starting auto-restart supervisor..."
322
+ nohup "$0" --supervise >> "$SUPERVISOR_LOG" 2>&1 &
323
+
324
+ # Give it a moment to start
325
+ sleep 0.2
326
+ }
327
+
328
+ # =============================================================================
329
+ # Main Entry Point
330
+ # =============================================================================
331
+
332
+ main() {
333
+ # Handle supervisor mode
334
+ if [[ "${1:-}" == "--supervise" ]]; then
335
+ supervise
336
+ exit 0
337
+ fi
338
+
339
+ # Normal launcher mode
340
+
341
+ # Clear any stale stop flag
342
+ rm -f "$STOP_FLAG"
343
+
344
+ if is_server_running; then
345
+ log_info "Connecting to existing OpenCode server at ${SERVER_URL}"
346
+ else
347
+ if ! start_server_and_wait; then
348
+ exit 1
349
+ fi
350
+ fi
351
+
352
+ # Ensure supervisor is running for auto-restart
353
+ ensure_supervisor_running
354
+
355
+ # Attach to the server, passing through any additional arguments
356
+ exec opencode attach "$SERVER_URL" "$@"
357
+ }
358
+
359
+ main "$@"