loki-mode 6.37.6 → 6.37.7

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/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 minimal human intervention. Requires --dangerously-skip-permissions flag.
4
4
  ---
5
5
 
6
- # Loki Mode v6.37.6
6
+ # Loki Mode v6.37.7
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -267,4 +267,4 @@ The following features are documented in skill modules but not yet fully automat
267
267
  | Quality gates 3-reviewer system | Implemented (v5.35.0) | 5 specialist reviewers in `skills/quality-gates.md`; execution in run.sh |
268
268
  | Benchmarks (HumanEval, SWE-bench) | Infrastructure only | Runner scripts and datasets exist in `benchmarks/`; no published results |
269
269
 
270
- **v6.37.6 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
270
+ **v6.37.7 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 6.37.6
1
+ 6.37.7
package/autonomy/loki CHANGED
@@ -410,7 +410,7 @@ show_help() {
410
410
  echo " api [cmd] Dashboard/API server (start|stop|status)"
411
411
  echo " sandbox [cmd] Docker sandbox (start|stop|status|logs|shell|build)"
412
412
  echo " notify [cmd] Send notifications (test|slack|discord|webhook|status)"
413
- echo " voice [cmd] Voice input for PRD creation (status|listen|dictate|speak|start)"
413
+ echo " telemetry [cmd] OpenTelemetry management (status|enable|disable|stop|start)"
414
414
  echo " import Import GitHub issues as tasks"
415
415
  echo " github [cmd] GitHub integration (sync|export|pr|status)"
416
416
  echo " config [cmd] Manage configuration (show|init|edit|path|set|get)"
@@ -9744,7 +9744,8 @@ main() {
9744
9744
  cmd_enterprise "$@"
9745
9745
  ;;
9746
9746
  voice)
9747
- cmd_voice "$@"
9747
+ echo "Voice mode is planned for a future release. Track progress at github.com/asklokesh/loki-mode/issues/85"
9748
+ exit 0
9748
9749
  ;;
9749
9750
  secrets)
9750
9751
  cmd_secrets "$@"
@@ -13176,95 +13177,9 @@ for check, passed in checks.items():
13176
13177
 
13177
13178
  # Voice input commands
13178
13179
  cmd_voice() {
13179
- local subcommand="${1:-status}"
13180
- local VOICE_SCRIPT="$SKILL_DIR/autonomy/voice.sh"
13181
-
13182
- # Check fallback locations for voice script
13183
- if [ ! -f "$VOICE_SCRIPT" ]; then
13184
- # Try relative to loki CLI location
13185
- local loki_dir
13186
- loki_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13187
- VOICE_SCRIPT="$loki_dir/voice.sh"
13188
- fi
13189
-
13190
- if [ ! -f "$VOICE_SCRIPT" ]; then
13191
- echo -e "${RED}Error: Voice module not found${NC}"
13192
- echo "Expected at: $SKILL_DIR/autonomy/voice.sh"
13193
- echo ""
13194
- echo "Voice input requires the voice.sh module."
13195
- echo "This feature may not be available in all installations."
13196
- exit 1
13197
- fi
13198
-
13199
- case "$subcommand" in
13200
- status)
13201
- "$VOICE_SCRIPT" status
13202
- ;;
13203
- listen)
13204
- echo -e "${BOLD}Starting voice input...${NC}"
13205
- local text
13206
- text=$("$VOICE_SCRIPT" listen)
13207
- if [ -n "$text" ]; then
13208
- echo ""
13209
- echo -e "${GREEN}Transcribed text:${NC}"
13210
- echo "$text"
13211
- fi
13212
- ;;
13213
- dictate)
13214
- local output="${2:-prd-voice.md}"
13215
- echo -e "${BOLD}Starting guided PRD dictation...${NC}"
13216
- echo ""
13217
- "$VOICE_SCRIPT" dictate "$output"
13218
- if [ -f "$output" ]; then
13219
- echo ""
13220
- echo -e "${GREEN}PRD created: $output${NC}"
13221
- echo ""
13222
- echo "Start Loki Mode with:"
13223
- echo " loki start $output"
13224
- fi
13225
- ;;
13226
- speak)
13227
- shift
13228
- if [ $# -eq 0 ]; then
13229
- echo -e "${RED}Usage: loki voice speak MESSAGE${NC}"
13230
- exit 1
13231
- fi
13232
- "$VOICE_SCRIPT" speak "$*"
13233
- ;;
13234
- start)
13235
- # Dictate PRD and start Loki Mode
13236
- local prd_file="${2:-prd-voice-$(date +%Y%m%d%H%M%S).md}"
13237
- echo -e "${BOLD}Voice-activated PRD creation...${NC}"
13238
- "$VOICE_SCRIPT" dictate "$prd_file"
13239
- if [ -f "$prd_file" ]; then
13240
- echo ""
13241
- echo -e "${GREEN}PRD created. Starting Loki Mode...${NC}"
13242
- cmd_start "$prd_file"
13243
- fi
13244
- ;;
13245
- --help|-h|help)
13246
- echo -e "${BOLD}loki voice${NC} - Voice input for PRD creation"
13247
- echo ""
13248
- echo "Usage: loki voice <command> [options]"
13249
- echo ""
13250
- echo "Commands:"
13251
- echo " status Check voice input capabilities"
13252
- echo " listen Listen and transcribe voice input"
13253
- echo " dictate [FILE] Guided PRD dictation (default: prd-voice.md)"
13254
- echo " speak MESSAGE Text-to-speech output"
13255
- echo " start [FILE] Dictate PRD and start Loki Mode immediately"
13256
- echo ""
13257
- echo "Requirements:"
13258
- echo " macOS: Enable Dictation in System Settings > Keyboard"
13259
- echo " Or: Set OPENAI_API_KEY for Whisper API transcription"
13260
- echo " Or: pip install openai-whisper for local transcription"
13261
- ;;
13262
- *)
13263
- echo -e "${RED}Unknown voice command: $subcommand${NC}"
13264
- echo "Run 'loki voice help' for usage."
13265
- exit 1
13266
- ;;
13267
- esac
13180
+ # Voice mode is planned for a future release (#85)
13181
+ echo "Voice mode is planned for a future release. Track progress at github.com/asklokesh/loki-mode/issues/85"
13182
+ return 0
13268
13183
  }
13269
13184
 
13270
13185
  # Enterprise features (optional - requires env vars)
@@ -13752,9 +13667,22 @@ cmd_telemetry() {
13752
13667
  echo -e "${BOLD}Telemetry Status${NC}"
13753
13668
  echo ""
13754
13669
 
13670
+ # Check persistent opt-out (~/.loki/config)
13671
+ local global_config="${HOME}/.loki/config"
13672
+ local persistently_disabled=false
13673
+ if [ -f "$global_config" ] && grep -q "^TELEMETRY_DISABLED=true" "$global_config" 2>/dev/null; then
13674
+ persistently_disabled=true
13675
+ fi
13676
+
13677
+ if [ "$persistently_disabled" = true ]; then
13678
+ echo -e " Opt-out: ${RED}disabled persistently${NC} (loki telemetry start to re-enable)"
13679
+ fi
13680
+
13755
13681
  local endpoint="${LOKI_OTEL_ENDPOINT:-}"
13756
- if [ -n "$endpoint" ]; then
13682
+ if [ -n "$endpoint" ] && [ "$persistently_disabled" = false ]; then
13757
13683
  echo -e " Endpoint: ${GREEN}$endpoint${NC}"
13684
+ elif [ "$persistently_disabled" = true ]; then
13685
+ echo -e " Endpoint: ${YELLOW}ignored (opted out)${NC}"
13758
13686
  else
13759
13687
  echo -e " Endpoint: ${YELLOW}not configured${NC}"
13760
13688
  fi
@@ -13787,6 +13715,15 @@ try {
13787
13715
 
13788
13716
  enable)
13789
13717
  local endpoint="${1:-http://localhost:4318}"
13718
+
13719
+ # Check persistent opt-out
13720
+ local global_config="${HOME}/.loki/config"
13721
+ if [ -f "$global_config" ] && grep -q "^TELEMETRY_DISABLED=true" "$global_config" 2>/dev/null; then
13722
+ echo -e "${YELLOW}Telemetry is persistently disabled.${NC}"
13723
+ echo "Run 'loki telemetry start' first to re-enable."
13724
+ return 1
13725
+ fi
13726
+
13790
13727
  echo -e "${BOLD}Enabling telemetry${NC}"
13791
13728
 
13792
13729
  # Save to config
@@ -13830,15 +13767,49 @@ with open('$config_file', 'w') as f:
13830
13767
  echo " Unset LOKI_OTEL_ENDPOINT in your shell for immediate effect."
13831
13768
  ;;
13832
13769
 
13770
+ stop)
13771
+ # Persistent opt-out across all sessions
13772
+ local global_config="${HOME}/.loki/config"
13773
+ mkdir -p "${HOME}/.loki"
13774
+
13775
+ # Remove existing TELEMETRY_DISABLED line if present, then add
13776
+ if [ -f "$global_config" ]; then
13777
+ grep -v "^TELEMETRY_DISABLED=" "$global_config" > "${global_config}.tmp" 2>/dev/null || true
13778
+ mv "${global_config}.tmp" "$global_config"
13779
+ fi
13780
+ echo "TELEMETRY_DISABLED=true" >> "$global_config"
13781
+
13782
+ echo -e "${BOLD}Telemetry permanently disabled${NC}"
13783
+ echo ""
13784
+ echo " Opt-out saved to: $global_config"
13785
+ echo " This persists across all sessions and new runs."
13786
+ echo " Run 'loki telemetry start' to re-enable."
13787
+ ;;
13788
+
13789
+ start)
13790
+ # Remove persistent opt-out
13791
+ local global_config="${HOME}/.loki/config"
13792
+ if [ -f "$global_config" ]; then
13793
+ grep -v "^TELEMETRY_DISABLED=" "$global_config" > "${global_config}.tmp" 2>/dev/null || true
13794
+ mv "${global_config}.tmp" "$global_config"
13795
+ fi
13796
+
13797
+ echo -e "${BOLD}Telemetry opt-out removed${NC}"
13798
+ echo ""
13799
+ echo " Telemetry can now be enabled with 'loki telemetry enable [endpoint]'."
13800
+ ;;
13801
+
13833
13802
  --help|-h|help)
13834
- echo -e "${BOLD}loki telemetry${NC} - OpenTelemetry management (v6.7.0)"
13803
+ echo -e "${BOLD}loki telemetry${NC} - OpenTelemetry management"
13835
13804
  echo ""
13836
13805
  echo "Usage: loki telemetry <command>"
13837
13806
  echo ""
13838
13807
  echo "Commands:"
13839
13808
  echo " status Show current telemetry config"
13840
13809
  echo " enable [endpoint] Enable OTEL (default: http://localhost:4318)"
13841
- echo " disable Disable OTEL"
13810
+ echo " disable Disable OTEL for current project"
13811
+ echo " stop Permanently opt out of telemetry across all sessions"
13812
+ echo " start Remove persistent opt-out, re-enable telemetry"
13842
13813
  echo ""
13843
13814
  ;;
13844
13815
  *)
@@ -14648,19 +14619,19 @@ cmd_agent() {
14648
14619
  local filter_swarm="${1:-}"
14649
14620
  echo -e "${BOLD}Agent Types${NC}"
14650
14621
  echo ""
14651
- python3 << PYEOF
14652
- import json, sys
14622
+ TYPES_FILE="$types_file" FILTER_SWARM="$filter_swarm" FILTER_SWARM2="${2:-}" python3 << 'PYEOF'
14623
+ import json, sys, os
14653
14624
 
14654
- with open("$types_file") as f:
14625
+ with open(os.environ["TYPES_FILE"]) as f:
14655
14626
  agents = json.load(f)
14656
14627
 
14657
- filter_swarm = "$filter_swarm"
14628
+ filter_swarm = os.environ.get("FILTER_SWARM", "")
14658
14629
  if filter_swarm and filter_swarm.startswith("--swarm"):
14659
14630
  # Handle --swarm=X or --swarm X
14660
14631
  if "=" in filter_swarm:
14661
14632
  filter_swarm = filter_swarm.split("=")[1]
14662
14633
  else:
14663
- filter_swarm = "${2:-}"
14634
+ filter_swarm = os.environ.get("FILTER_SWARM2", "")
14664
14635
 
14665
14636
  swarms = {}
14666
14637
  for a in agents:
@@ -14690,13 +14661,13 @@ PYEOF
14690
14661
  echo -e "${RED}Usage: loki agent info <type>${NC}"
14691
14662
  return 1
14692
14663
  fi
14693
- python3 << PYEOF
14694
- import json, sys
14664
+ TYPES_FILE="$types_file" AGENT_TYPE="$agent_type" python3 << 'PYEOF'
14665
+ import json, sys, os
14695
14666
 
14696
- with open("$types_file") as f:
14667
+ with open(os.environ["TYPES_FILE"]) as f:
14697
14668
  agents = json.load(f)
14698
14669
 
14699
- target = "$agent_type"
14670
+ target = os.environ["AGENT_TYPE"]
14700
14671
  found = None
14701
14672
  for a in agents:
14702
14673
  if a["type"] == target:
package/autonomy/run.sh CHANGED
@@ -602,6 +602,12 @@ if [ -f "${SCRIPT_DIR}/playwright-verify.sh" ]; then
602
602
  fi
603
603
 
604
604
  # Anonymous usage telemetry (opt-out: LOKI_TELEMETRY_DISABLED=true or DO_NOT_TRACK=1)
605
+ # Also check persistent opt-out from ~/.loki/config (#77)
606
+ if [ -f "${HOME}/.loki/config" ] && grep -q "^TELEMETRY_DISABLED=true" "${HOME}/.loki/config" 2>/dev/null; then
607
+ LOKI_TELEMETRY_DISABLED=true
608
+ export LOKI_TELEMETRY_DISABLED
609
+ unset LOKI_OTEL_ENDPOINT
610
+ fi
605
611
  TELEMETRY_SCRIPT="$SCRIPT_DIR/telemetry.sh"
606
612
  if [ -f "$TELEMETRY_SCRIPT" ]; then
607
613
  # shellcheck source=telemetry.sh
package/completions/_loki CHANGED
@@ -44,8 +44,11 @@ function _loki {
44
44
  projects)
45
45
  _loki_projects
46
46
  ;;
47
- voice)
48
- _loki_voice
47
+ telemetry)
48
+ _loki_telemetry
49
+ ;;
50
+ agent)
51
+ _loki_agent
49
52
  ;;
50
53
  status)
51
54
  _arguments \
@@ -121,7 +124,8 @@ function _loki_commands {
121
124
  'dogfood:Self-development statistics'
122
125
  'projects:Project registry commands'
123
126
  'enterprise:Enterprise feature commands'
124
- 'voice:Voice input commands'
127
+ 'telemetry:OpenTelemetry management'
128
+ 'agent:Agent type dispatch'
125
129
  'doctor:Check system prerequisites'
126
130
  'onboard:Analyze repo and generate CLAUDE.md'
127
131
  'metrics:Session productivity report'
@@ -294,17 +298,29 @@ function _loki_projects {
294
298
  _describe -t cmds 'projects subcommand' cmds
295
299
  }
296
300
 
297
- function _loki_voice {
301
+ function _loki_telemetry {
302
+ local -a cmds
303
+ cmds=(
304
+ 'status:Show telemetry config'
305
+ 'enable:Enable OTEL'
306
+ 'disable:Disable OTEL for current project'
307
+ 'stop:Permanently opt out across all sessions'
308
+ 'start:Remove persistent opt-out'
309
+ 'help:Telemetry help'
310
+ )
311
+ _describe -t cmds 'telemetry subcommand' cmds
312
+ }
313
+
314
+ function _loki_agent {
298
315
  local -a cmds
299
316
  cmds=(
300
- 'status:Voice input status'
301
- 'listen:Start listening'
302
- 'dictate:Dictate PRD'
303
- 'speak:Text-to-speech'
304
- 'start:Start voice session'
305
- 'help:Voice help'
317
+ 'list:List agent types'
318
+ 'info:Show agent type details'
319
+ 'run:Run agent with prompt'
320
+ 'start:Start agent in background'
321
+ 'help:Agent help'
306
322
  )
307
- _describe -t cmds 'voice subcommand' cmds
323
+ _describe -t cmds 'agent subcommand' cmds
308
324
  }
309
325
 
310
326
  function _loki_reset {
@@ -5,7 +5,7 @@ _loki_completion() {
5
5
  _init_completion || return
6
6
 
7
7
  # Main subcommands (must match autonomy/loki main case statement)
8
- local main_commands="start quick demo init stop pause resume status dashboard logs serve api sandbox notify import github issue config provider reset memory compound checkpoint council dogfood projects enterprise voice secrets doctor watchdog audit metrics syslog onboard share explain plan report test ci watch version completions help"
8
+ local main_commands="start quick demo init stop pause resume status dashboard logs serve api sandbox notify import github issue config provider reset memory compound checkpoint council dogfood projects enterprise secrets doctor watchdog audit metrics syslog onboard share explain plan report test ci watch telemetry agent version completions help"
9
9
 
10
10
  # 1. If we are on the first argument (subcommand)
11
11
  if [[ $cword -eq 1 ]]; then
@@ -83,9 +83,14 @@ _loki_completion() {
83
83
  COMPREPLY=( $(compgen -W "${projects_cmds}" -- "$cur") )
84
84
  ;;
85
85
 
86
- voice)
87
- local voice_cmds="status listen dictate speak start help"
88
- COMPREPLY=( $(compgen -W "${voice_cmds}" -- "$cur") )
86
+ telemetry)
87
+ local telemetry_cmds="status enable disable stop start help"
88
+ COMPREPLY=( $(compgen -W "${telemetry_cmds}" -- "$cur") )
89
+ ;;
90
+
91
+ agent)
92
+ local agent_cmds="list info run start help"
93
+ COMPREPLY=( $(compgen -W "${agent_cmds}" -- "$cur") )
89
94
  ;;
90
95
 
91
96
  syslog)
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "6.37.6"
10
+ __version__ = "6.37.7"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -2662,10 +2662,43 @@ async def pause_session():
2662
2662
  """Pause the current session by creating PAUSE file."""
2663
2663
  if not _control_limiter.check("control"):
2664
2664
  raise HTTPException(status_code=429, detail="Rate limit exceeded")
2665
- pause_file = _get_loki_dir() / "PAUSE"
2665
+
2666
+ loki_dir = _get_loki_dir()
2667
+ pid_file = loki_dir / "loki.pid"
2668
+
2669
+ # Verify loki process is running before attempting pause
2670
+ process_running = False
2671
+ if pid_file.exists():
2672
+ try:
2673
+ pid = int(pid_file.read_text().strip())
2674
+ os.kill(pid, 0) # Signal 0: check existence without killing
2675
+ process_running = True
2676
+ except (ValueError, OSError, ProcessLookupError):
2677
+ pass
2678
+
2679
+ pause_file = loki_dir / "PAUSE"
2666
2680
  pause_file.parent.mkdir(parents=True, exist_ok=True)
2667
2681
  pause_file.write_text(datetime.now(timezone.utc).isoformat())
2668
- return {"success": True, "message": "Session paused"}
2682
+
2683
+ if not process_running:
2684
+ return JSONResponse(
2685
+ status_code=503,
2686
+ content={"success": False, "message": "Session process is not running; pause signal may have no effect"},
2687
+ )
2688
+
2689
+ # Poll up to 5s to confirm process is still alive with PAUSE file present
2690
+ for _ in range(10):
2691
+ try:
2692
+ os.kill(pid, 0)
2693
+ return {"success": True, "message": "Session paused", "process_verified": True}
2694
+ except OSError:
2695
+ break
2696
+ await asyncio.sleep(0.5)
2697
+
2698
+ return JSONResponse(
2699
+ status_code=503,
2700
+ content={"success": False, "message": "Session process exited unexpectedly after pause signal"},
2701
+ )
2669
2702
 
2670
2703
 
2671
2704
  @app.post("/api/control/resume", dependencies=[Depends(auth.require_scope("control"))])
@@ -2673,13 +2706,58 @@ async def resume_session():
2673
2706
  """Resume a paused session by removing PAUSE/STOP files."""
2674
2707
  if not _control_limiter.check("control"):
2675
2708
  raise HTTPException(status_code=429, detail="Rate limit exceeded")
2709
+
2710
+ loki_dir = _get_loki_dir()
2711
+ pid_file = loki_dir / "loki.pid"
2712
+
2713
+ # Verify loki process is running before attempting resume
2714
+ process_running = False
2715
+ pid = 0
2716
+ if pid_file.exists():
2717
+ try:
2718
+ pid = int(pid_file.read_text().strip())
2719
+ os.kill(pid, 0) # Signal 0: check existence without killing
2720
+ process_running = True
2721
+ except (ValueError, OSError, ProcessLookupError):
2722
+ pass
2723
+
2724
+ if not process_running:
2725
+ # Still remove the files for cleanup, but return 503
2726
+ for fname in ["PAUSE", "STOP"]:
2727
+ fpath = loki_dir / fname
2728
+ try:
2729
+ fpath.unlink(missing_ok=True)
2730
+ except Exception:
2731
+ pass
2732
+ return JSONResponse(
2733
+ status_code=503,
2734
+ content={"success": False, "message": "Session did not respond to resume signal"},
2735
+ )
2736
+
2676
2737
  for fname in ["PAUSE", "STOP"]:
2677
- fpath = _get_loki_dir() / fname
2738
+ fpath = loki_dir / fname
2678
2739
  try:
2679
2740
  fpath.unlink(missing_ok=True)
2680
2741
  except Exception:
2681
2742
  pass
2682
- return {"success": True, "message": "Session resumed"}
2743
+
2744
+ # Poll up to 5s to verify the process is still running and acknowledged the resume
2745
+ for _ in range(10):
2746
+ try:
2747
+ os.kill(pid, 0)
2748
+ if not (loki_dir / "PAUSE").exists():
2749
+ return {"success": True, "message": "Session resumed", "process_verified": True}
2750
+ except OSError:
2751
+ return JSONResponse(
2752
+ status_code=503,
2753
+ content={"success": False, "message": "Session did not respond to resume signal"},
2754
+ )
2755
+ await asyncio.sleep(0.5)
2756
+
2757
+ return JSONResponse(
2758
+ status_code=503,
2759
+ content={"success": False, "message": "Session did not respond to resume signal"},
2760
+ )
2683
2761
 
2684
2762
 
2685
2763
  @app.post("/api/control/stop", dependencies=[Depends(auth.require_scope("control"))])
@@ -2,7 +2,7 @@
2
2
 
3
3
  The flagship product of [Autonomi](https://www.autonomi.dev/). Complete installation instructions for all platforms and use cases.
4
4
 
5
- **Version:** v6.37.6
5
+ **Version:** v6.37.7
6
6
 
7
7
  ---
8
8
 
package/mcp/__init__.py CHANGED
@@ -57,4 +57,4 @@ try:
57
57
  except ImportError:
58
58
  __all__ = ['mcp']
59
59
 
60
- __version__ = '6.37.6'
60
+ __version__ = '6.37.7'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loki-mode",
3
- "version": "6.37.6",
3
+ "version": "6.37.7",
4
4
  "description": "Loki Mode by Autonomi - Multi-agent autonomous startup system for Claude Code, Codex CLI, and Gemini CLI",
5
5
  "keywords": [
6
6
  "agent",