loki-mode 5.34.0 → 5.35.0

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.
@@ -56,7 +56,7 @@ SANDBOX_MEMORY="${LOKI_SANDBOX_MEMORY:-4g}"
56
56
  SANDBOX_READONLY="${LOKI_SANDBOX_READONLY:-false}"
57
57
 
58
58
  # API ports
59
- API_PORT="${LOKI_API_PORT:-9898}"
59
+ API_PORT="${LOKI_DASHBOARD_PORT:-57374}"
60
60
  DASHBOARD_PORT="${LOKI_DASHBOARD_PORT:-57374}"
61
61
 
62
62
  # Security: Prompt injection disabled by default for enterprise security
@@ -766,12 +766,7 @@ start_sandbox() {
766
766
  validate_project_dir || return 1
767
767
  ensure_image
768
768
 
769
- # Check port availability
770
- if ! check_port_available "$API_PORT"; then
771
- log_error "Port $API_PORT is already in use"
772
- log_info "Set LOKI_API_PORT to use a different port"
773
- return 1
774
- fi
769
+ # Check port availability (unified dashboard/API port)
775
770
  if ! check_port_available "$DASHBOARD_PORT"; then
776
771
  log_error "Port $DASHBOARD_PORT is already in use"
777
772
  log_info "Set LOKI_DASHBOARD_PORT to use a different port"
@@ -898,8 +893,7 @@ start_sandbox() {
898
893
 
899
894
  # Expose ports
900
895
  docker_args+=(
901
- "--publish" "$API_PORT:9898"
902
- "--publish" "$DASHBOARD_PORT:57374"
896
+ "--publish" "$API_PORT:57374"
903
897
  )
904
898
 
905
899
  # Expose additional ports for testing (e.g., LOKI_EXTRA_PORTS="3000:3000,8080:8080")
package/autonomy/serve.sh CHANGED
@@ -9,15 +9,15 @@
9
9
  # loki serve [OPTIONS]
10
10
  #
11
11
  # Options:
12
- # --port, -p <port> Port to listen on (default: 8420)
12
+ # --port, -p <port> Port to listen on (default: 57374)
13
13
  # --host, -h <host> Host to bind to (default: localhost)
14
14
  # --no-cors Disable CORS
15
15
  # --no-auth Disable authentication
16
16
  # --help Show help message
17
17
  #
18
18
  # Environment Variables:
19
- # LOKI_API_PORT Port (default: 8420)
20
- # LOKI_API_HOST Host (default: localhost)
19
+ # LOKI_DASHBOARD_PORT Port (default: 57374)
20
+ # LOKI_DASHBOARD_HOST Host (default: localhost)
21
21
  # LOKI_API_TOKEN API token for remote access
22
22
  #===============================================================================
23
23
 
@@ -28,8 +28,8 @@ PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
28
28
  API_DIR="$PROJECT_DIR/api"
29
29
 
30
30
  # Default configuration
31
- PORT="${LOKI_API_PORT:-8420}"
32
- HOST="${LOKI_API_HOST:-localhost}"
31
+ PORT="${LOKI_DASHBOARD_PORT:-57374}"
32
+ HOST="${LOKI_DASHBOARD_HOST:-localhost}"
33
33
  CORS="true"
34
34
  AUTH="true"
35
35
 
@@ -63,7 +63,7 @@ Usage:
63
63
  loki serve [OPTIONS]
64
64
 
65
65
  Options:
66
- --port, -p <port> Port to listen on (default: 8420)
66
+ --port, -p <port> Port to listen on (default: 57374)
67
67
  --host <host> Host to bind to (default: localhost)
68
68
  --no-cors Disable CORS
69
69
  --no-auth Disable authentication
@@ -71,14 +71,14 @@ Options:
71
71
  --help Show this help message
72
72
 
73
73
  Environment Variables:
74
- LOKI_API_PORT Port (overridden by --port)
75
- LOKI_API_HOST Host (overridden by --host)
74
+ LOKI_DASHBOARD_PORT Port (overridden by --port)
75
+ LOKI_DASHBOARD_HOST Host (overridden by --host)
76
76
  LOKI_API_TOKEN API token for remote access
77
77
  LOKI_DIR Loki installation directory
78
78
  LOKI_DEBUG Enable debug output
79
79
 
80
80
  Examples:
81
- # Start with defaults (localhost:8420)
81
+ # Start with defaults (localhost:57374)
82
82
  loki serve
83
83
 
84
84
  # Custom port
@@ -89,7 +89,7 @@ Examples:
89
89
  loki serve --host 0.0.0.0
90
90
 
91
91
  # Connect from another machine
92
- curl -H "Authorization: Bearer \$TOKEN" http://server:8420/health
92
+ curl -H "Authorization: Bearer \$TOKEN" http://server:57374/health
93
93
 
94
94
  EOF
95
95
  }
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "5.34.0"
10
+ __version__ = "5.35.0"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -188,7 +188,7 @@ class ConnectionManager:
188
188
 
189
189
 
190
190
  manager = ConnectionManager()
191
- start_time = datetime.now()
191
+ start_time = datetime.now(timezone.utc)
192
192
 
193
193
 
194
194
  @asynccontextmanager
@@ -217,8 +217,8 @@ app.add_middleware(
217
217
  CORSMiddleware,
218
218
  allow_origins=[o.strip() for o in _cors_origins if o.strip()],
219
219
  allow_credentials=True,
220
- allow_methods=["*"],
221
- allow_headers=["*"],
220
+ allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
221
+ allow_headers=["Content-Type", "Authorization", "X-Requested-With"],
222
222
  )
223
223
 
224
224
  # Static file serving is configured at the end of the file (after all API routes)
@@ -236,7 +236,7 @@ async def health_check() -> dict[str, str]:
236
236
  async def get_status() -> StatusResponse:
237
237
  """Get system status from .loki/ session files."""
238
238
  loki_dir = _get_loki_dir()
239
- uptime = (datetime.now() - start_time).total_seconds()
239
+ uptime = (datetime.now(timezone.utc) - start_time).total_seconds()
240
240
 
241
241
  # Read dashboard-state.json (written by run.sh every 2 seconds)
242
242
  state_file = loki_dir / "dashboard-state.json"
@@ -681,7 +681,7 @@ async def update_task(
681
681
 
682
682
  # Handle status change to completed
683
683
  if "status" in update_data and update_data["status"] == TaskStatus.DONE:
684
- update_data["completed_at"] = datetime.now()
684
+ update_data["completed_at"] = datetime.now(timezone.utc)
685
685
 
686
686
  for field, value in update_data.items():
687
687
  setattr(task, field, value)
@@ -748,7 +748,7 @@ async def move_task(
748
748
 
749
749
  # Set completed_at if moving to completed
750
750
  if move.status == TaskStatus.DONE and old_status != TaskStatus.DONE:
751
- task.completed_at = datetime.now()
751
+ task.completed_at = datetime.now(timezone.utc)
752
752
  elif move.status != TaskStatus.DONE:
753
753
  task.completed_at = None
754
754
 
@@ -1135,10 +1135,10 @@ _SAFE_ID_RE = re.compile(r'^[a-zA-Z0-9_-]+$')
1135
1135
 
1136
1136
  def _sanitize_agent_id(agent_id: str) -> str:
1137
1137
  """Validate agent_id contains only safe characters for file paths."""
1138
- if not agent_id or ".." in agent_id or not _SAFE_ID_RE.match(agent_id):
1138
+ if not agent_id or len(agent_id) > 128 or ".." in agent_id or not _SAFE_ID_RE.match(agent_id):
1139
1139
  raise HTTPException(
1140
1140
  status_code=400,
1141
- detail="Invalid agent_id: must contain only alphanumeric characters, hyphens, and underscores",
1141
+ detail="Invalid agent_id: must be 1-128 chars of alphanumeric, hyphens, and underscores",
1142
1142
  )
1143
1143
  return agent_id
1144
1144
 
@@ -1611,7 +1611,7 @@ async def pause_session():
1611
1611
  """Pause the current session by creating PAUSE file."""
1612
1612
  pause_file = _get_loki_dir() / "PAUSE"
1613
1613
  pause_file.parent.mkdir(parents=True, exist_ok=True)
1614
- pause_file.write_text(datetime.now().isoformat())
1614
+ pause_file.write_text(datetime.now(timezone.utc).isoformat())
1615
1615
  return {"success": True, "message": "Session paused"}
1616
1616
 
1617
1617
 
@@ -1632,7 +1632,7 @@ async def stop_session():
1632
1632
  """Stop the session by creating STOP file and sending SIGTERM."""
1633
1633
  stop_file = _get_loki_dir() / "STOP"
1634
1634
  stop_file.parent.mkdir(parents=True, exist_ok=True)
1635
- stop_file.write_text(datetime.now().isoformat())
1635
+ stop_file.write_text(datetime.now(timezone.utc).isoformat())
1636
1636
 
1637
1637
  # Try to kill the process
1638
1638
  pid_file = _get_loki_dir() / "loki.pid"
@@ -1979,7 +1979,7 @@ async def force_council_review():
1979
1979
  signal_dir = _get_loki_dir() / "signals"
1980
1980
  signal_dir.mkdir(parents=True, exist_ok=True)
1981
1981
  (signal_dir / "COUNCIL_REVIEW_REQUESTED").write_text(
1982
- datetime.now().isoformat()
1982
+ datetime.now(timezone.utc).isoformat()
1983
1983
  )
1984
1984
  return {"success": True, "message": "Council review requested"}
1985
1985
 
@@ -1990,15 +1990,15 @@ async def force_council_review():
1990
1990
 
1991
1991
  class CheckpointCreate(BaseModel):
1992
1992
  """Schema for creating a checkpoint."""
1993
- message: Optional[str] = Field(None, description="Optional description for the checkpoint")
1993
+ message: Optional[str] = Field(None, max_length=500, description="Optional description for the checkpoint")
1994
1994
 
1995
1995
 
1996
1996
  def _sanitize_checkpoint_id(checkpoint_id: str) -> str:
1997
1997
  """Validate checkpoint_id contains only safe characters for file paths."""
1998
- if not checkpoint_id or ".." in checkpoint_id or not _SAFE_ID_RE.match(checkpoint_id):
1998
+ if not checkpoint_id or len(checkpoint_id) > 128 or ".." in checkpoint_id or not _SAFE_ID_RE.match(checkpoint_id):
1999
1999
  raise HTTPException(
2000
2000
  status_code=400,
2001
- detail="Invalid checkpoint_id: must contain only alphanumeric characters, hyphens, and underscores",
2001
+ detail="Invalid checkpoint_id: must be 1-128 chars of alphanumeric, hyphens, and underscores",
2002
2002
  )
2003
2003
  return checkpoint_id
2004
2004
 
@@ -2241,7 +2241,7 @@ async def pause_agent(agent_id: str):
2241
2241
  signal_dir = _get_loki_dir() / "signals"
2242
2242
  signal_dir.mkdir(parents=True, exist_ok=True)
2243
2243
  (signal_dir / f"PAUSE_AGENT_{agent_id}").write_text(
2244
- datetime.now().isoformat()
2244
+ datetime.now(timezone.utc).isoformat()
2245
2245
  )
2246
2246
  return {"success": True, "message": f"Pause signal sent to agent {agent_id}"}
2247
2247
 
@@ -2290,7 +2290,7 @@ async def get_logs(lines: int = 100):
2290
2290
  for log_file in log_files[:1]:
2291
2291
  try:
2292
2292
  # Use file mtime as fallback timestamp
2293
- file_mtime = datetime.fromtimestamp(log_file.stat().st_mtime).strftime(
2293
+ file_mtime = datetime.fromtimestamp(log_file.stat().st_mtime, tz=timezone.utc).strftime(
2294
2294
  "%Y-%m-%dT%H:%M:%S"
2295
2295
  )
2296
2296
  content = log_file.read_text()