loki-mode 5.20.8 → 5.20.10

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/Dockerfile CHANGED
@@ -30,10 +30,10 @@ RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
30
30
  && rm -rf /var/lib/apt/lists/* \
31
31
  && npm cache clean --force
32
32
 
33
- # Install GitHub CLI directly from releases (latest version, not from apt)
33
+ # Install GitHub CLI directly from releases (pinned version for reliability)
34
34
  # This avoids CVE-2024-52308 in older Ubuntu-packaged versions
35
+ ARG GH_VERSION=2.65.0
35
36
  RUN ARCH=$(dpkg --print-architecture) && \
36
- GH_VERSION=$(curl -s https://api.github.com/repos/cli/cli/releases/latest | jq -r .tag_name | sed 's/v//') && \
37
37
  curl -fsSL "https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_${ARCH}.tar.gz" -o /tmp/gh.tar.gz && \
38
38
  tar -xzf /tmp/gh.tar.gz -C /tmp && \
39
39
  mv /tmp/gh_${GH_VERSION}_linux_${ARCH}/bin/gh /usr/local/bin/gh && \
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: loki-mode
3
3
  description: Multi-agent autonomous startup system. Triggers on "Loki Mode". Takes PRD to deployed product with zero human intervention. Requires --dangerously-skip-permissions flag.
4
4
  ---
5
5
 
6
- # Loki Mode v5.20.8
6
+ # Loki Mode v5.20.10
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -253,4 +253,4 @@ Auto-detected or force with `LOKI_COMPLEXITY`:
253
253
 
254
254
  ---
255
255
 
256
- **v5.20.8 | Dashboard Consolidation, Unified Web Components | ~250 lines core**
256
+ **v5.20.10 | Dashboard Consolidation, Unified Web Components | ~250 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 5.20.8
1
+ 5.20.10
package/autonomy/loki CHANGED
@@ -519,13 +519,17 @@ cmd_start() {
519
519
 
520
520
  # Check if session is running
521
521
  is_session_running() {
522
- if [ -f "$LOKI_DIR/run.pid" ]; then
523
- local pid
524
- pid=$(cat "$LOKI_DIR/run.pid" 2>/dev/null)
525
- if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
526
- return 0
522
+ # Check both possible PID files (loki.pid from run.sh, run.pid legacy)
523
+ local pid_files=("$LOKI_DIR/loki.pid" "$LOKI_DIR/run.pid")
524
+ for pid_file in "${pid_files[@]}"; do
525
+ if [ -f "$pid_file" ]; then
526
+ local pid
527
+ pid=$(cat "$pid_file" 2>/dev/null)
528
+ if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
529
+ return 0
530
+ fi
527
531
  fi
528
- fi
532
+ done
529
533
  return 1
530
534
  }
531
535
 
@@ -547,6 +551,27 @@ cmd_stop() {
547
551
 
548
552
  if is_session_running; then
549
553
  touch "$LOKI_DIR/STOP"
554
+
555
+ # Kill the background process and all its children
556
+ local killed_pid=""
557
+ for pid_file in "$LOKI_DIR/loki.pid" "$LOKI_DIR/run.pid"; do
558
+ if [ -f "$pid_file" ]; then
559
+ local pid
560
+ pid=$(cat "$pid_file" 2>/dev/null)
561
+ if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
562
+ # Kill all child processes first
563
+ pkill -P "$pid" 2>/dev/null || true
564
+ # Then kill the parent
565
+ kill "$pid" 2>/dev/null || true
566
+ killed_pid="$pid"
567
+ fi
568
+ rm -f "$pid_file"
569
+ fi
570
+ done
571
+
572
+ # Also kill any orphaned loki-run temp scripts
573
+ pkill -f "loki-run-" 2>/dev/null || true
574
+
550
575
  # Emit session stop event
551
576
  emit_event session cli stop "reason=user_requested"
552
577
  # Emit success pattern for clean stop (SYN-018)
@@ -557,7 +582,12 @@ cmd_stop() {
557
582
  --action-sequence '["check_session", "send_stop_signal"]' \
558
583
  --outcome success \
559
584
  --confidence 0.9
560
- echo -e "${RED}STOP signal sent. Execution will halt immediately.${NC}"
585
+
586
+ if [ -n "$killed_pid" ]; then
587
+ echo -e "${RED}Stopped Loki Mode (PID: $killed_pid)${NC}"
588
+ else
589
+ echo -e "${RED}STOP signal sent. Execution will halt immediately.${NC}"
590
+ fi
561
591
  else
562
592
  echo -e "${YELLOW}No active session running.${NC}"
563
593
  if [ -f "$LOKI_DIR/STOP" ]; then
@@ -1007,24 +1007,72 @@ except ImportError as e:
1007
1007
  # =============================================================================
1008
1008
  # Must be configured AFTER all API routes to avoid conflicts
1009
1009
 
1010
- STATIC_DIR = os.path.join(os.path.dirname(__file__), "static")
1011
- if os.path.isdir(STATIC_DIR):
1010
+ from fastapi.responses import FileResponse, HTMLResponse
1011
+
1012
+ # Find static files in multiple possible locations
1013
+ DASHBOARD_DIR = os.path.dirname(__file__)
1014
+ PROJECT_ROOT = os.path.dirname(DASHBOARD_DIR)
1015
+
1016
+ # Possible static file locations (in order of preference)
1017
+ STATIC_LOCATIONS = [
1018
+ os.path.join(DASHBOARD_DIR, "static"), # dashboard/static/ (production)
1019
+ os.path.join(PROJECT_ROOT, "dashboard-ui", "dist"), # dashboard-ui/dist/ (development)
1020
+ ]
1021
+
1022
+ STATIC_DIR = None
1023
+ for loc in STATIC_LOCATIONS:
1024
+ if os.path.isdir(loc):
1025
+ STATIC_DIR = loc
1026
+ logger.info(f"Static files found at: {loc}")
1027
+ break
1028
+
1029
+ if STATIC_DIR:
1012
1030
  from fastapi.staticfiles import StaticFiles
1013
- from fastapi.responses import FileResponse
1014
1031
 
1015
1032
  # Check if assets directory exists (built frontend)
1016
1033
  ASSETS_DIR = os.path.join(STATIC_DIR, "assets")
1017
1034
  if os.path.isdir(ASSETS_DIR):
1018
1035
  app.mount("/assets", StaticFiles(directory=ASSETS_DIR), name="assets")
1019
1036
 
1020
- # Serve index.html for root
1021
- @app.get("/", include_in_schema=False)
1022
- async def serve_index():
1023
- """Serve the frontend SPA."""
1024
- index_path = os.path.join(STATIC_DIR, "index.html")
1037
+ # Serve index.html or standalone HTML for root
1038
+ @app.get("/", include_in_schema=False)
1039
+ async def serve_index():
1040
+ """Serve the frontend SPA or standalone HTML."""
1041
+ # Try multiple index file locations
1042
+ index_candidates = []
1043
+ if STATIC_DIR:
1044
+ index_candidates.append(os.path.join(STATIC_DIR, "index.html"))
1045
+ index_candidates.append(os.path.join(STATIC_DIR, "loki-dashboard-standalone.html"))
1046
+
1047
+ # Also check dashboard-ui directly for standalone
1048
+ standalone_path = os.path.join(PROJECT_ROOT, "dashboard-ui", "dist", "loki-dashboard-standalone.html")
1049
+ if standalone_path not in index_candidates:
1050
+ index_candidates.append(standalone_path)
1051
+
1052
+ for index_path in index_candidates:
1025
1053
  if os.path.isfile(index_path):
1026
- return FileResponse(index_path)
1027
- raise HTTPException(status_code=404, detail="Frontend not built")
1054
+ return FileResponse(index_path, media_type="text/html")
1055
+
1056
+ # Return helpful error message
1057
+ return HTMLResponse(
1058
+ content="""
1059
+ <html>
1060
+ <head><title>Loki Dashboard</title></head>
1061
+ <body style="font-family: system-ui; padding: 40px; max-width: 600px; margin: 0 auto;">
1062
+ <h1>Dashboard Frontend Not Found</h1>
1063
+ <p>The dashboard API is running, but the frontend files were not found.</p>
1064
+ <p>To fix this, run:</p>
1065
+ <pre style="background: #f5f5f5; padding: 15px; border-radius: 5px;">cd dashboard-ui && npm run build</pre>
1066
+ <p><strong>API Endpoints:</strong></p>
1067
+ <ul>
1068
+ <li><a href="/health">/health</a> - Health check</li>
1069
+ <li><a href="/docs">/docs</a> - API documentation</li>
1070
+ </ul>
1071
+ </body>
1072
+ </html>
1073
+ """,
1074
+ status_code=200
1075
+ )
1028
1076
 
1029
1077
 
1030
1078
  def run_server(host: str = None, port: int = None) -> None:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loki-mode",
3
- "version": "5.20.8",
3
+ "version": "5.20.10",
4
4
  "description": "Multi-agent autonomous startup system for Claude Code, Codex CLI, and Gemini CLI",
5
5
  "keywords": [
6
6
  "claude",