loki-mode 5.4.5 → 5.4.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 zero human intervention. Requires --dangerously-skip-permissions flag.
4
4
  ---
5
5
 
6
- # Loki Mode v5.4.5
6
+ # Loki Mode v5.4.7
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -241,4 +241,4 @@ Auto-detected or force with `LOKI_COMPLEXITY`:
241
241
 
242
242
  ---
243
243
 
244
- **v5.4.5 | Dashboard fix + Gemini stdin fix | ~245 lines core**
244
+ **v5.4.7 | Gemini rate limit fallback to flash model | ~245 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 5.4.5
1
+ 5.4.7
package/autonomy/run.sh CHANGED
@@ -1378,10 +1378,9 @@ spawn_worktree_session() {
1378
1378
  ;;
1379
1379
  gemini)
1380
1380
  # Note: -p flag is DEPRECATED per gemini --help. Using positional prompt.
1381
- # Note: < /dev/null prevents Gemini from pausing on stdin
1382
- gemini --yolo --model "${PROVIDER_MODEL:-gemini-3-pro-preview}" \
1383
- "Loki Mode: $task_prompt. Read .loki/CONTINUITY.md for context." \
1384
- < /dev/null >> "$log_file" 2>&1
1381
+ # Uses invoke_gemini helper for rate limit fallback to flash model
1382
+ invoke_gemini "Loki Mode: $task_prompt. Read .loki/CONTINUITY.md for context." \
1383
+ >> "$log_file" 2>&1
1385
1384
  ;;
1386
1385
  *)
1387
1386
  log_error "Unknown provider: ${PROVIDER_NAME}"
@@ -1471,8 +1470,8 @@ Output ONLY the resolved file content with no conflict markers. No explanations.
1471
1470
  resolution=$(codex exec --dangerously-bypass-approvals-and-sandbox "$conflict_prompt" 2>/dev/null)
1472
1471
  ;;
1473
1472
  gemini)
1474
- # Note: -p flag is DEPRECATED per gemini --help. Using positional prompt.
1475
- resolution=$(gemini --yolo --model "${PROVIDER_MODEL:-gemini-3-pro-preview}" "$conflict_prompt" < /dev/null 2>/dev/null)
1473
+ # Uses invoke_gemini_capture for rate limit fallback to flash model
1474
+ resolution=$(invoke_gemini_capture "$conflict_prompt" 2>/dev/null)
1476
1475
  ;;
1477
1476
  *)
1478
1477
  log_error "Unknown provider: ${PROVIDER_NAME}"
@@ -1864,6 +1863,112 @@ EOF
1864
1863
  log_info "Loki directory initialized: .loki/"
1865
1864
  }
1866
1865
 
1866
+ #===============================================================================
1867
+ # Gemini Invocation with Rate Limit Fallback
1868
+ #===============================================================================
1869
+
1870
+ # Invoke Gemini with automatic fallback to flash model on rate limit
1871
+ # Usage: invoke_gemini "prompt" [additional args...]
1872
+ # Returns: exit code from gemini CLI
1873
+ invoke_gemini() {
1874
+ local prompt="$1"
1875
+ shift
1876
+
1877
+ local model="${PROVIDER_MODEL:-gemini-3-pro-preview}"
1878
+ local fallback="${PROVIDER_MODEL_FALLBACK:-gemini-3-flash-preview}"
1879
+
1880
+ # Create temp file for output to preserve streaming while checking for rate limit
1881
+ local tmp_output
1882
+ tmp_output=$(mktemp)
1883
+
1884
+ # Try primary model first
1885
+ gemini --yolo --model "$model" "$prompt" "$@" < /dev/null 2>&1 | tee "$tmp_output"
1886
+ local exit_code=${PIPESTATUS[0]}
1887
+
1888
+ # Check for rate limit in output
1889
+ if [[ $exit_code -ne 0 ]] && grep -qiE "(rate.?limit|429|quota|resource.?exhausted)" "$tmp_output"; then
1890
+ log_warn "Rate limit hit on $model, falling back to $fallback"
1891
+ rm -f "$tmp_output"
1892
+ gemini --yolo --model "$fallback" "$prompt" "$@" < /dev/null
1893
+ exit_code=$?
1894
+ else
1895
+ rm -f "$tmp_output"
1896
+ fi
1897
+
1898
+ return $exit_code
1899
+ }
1900
+
1901
+ # Invoke Gemini and capture output (for variable assignment)
1902
+ # Usage: result=$(invoke_gemini_capture "prompt")
1903
+ # Falls back to flash model on rate limit
1904
+ invoke_gemini_capture() {
1905
+ local prompt="$1"
1906
+ shift
1907
+
1908
+ local model="${PROVIDER_MODEL:-gemini-3-pro-preview}"
1909
+ local fallback="${PROVIDER_MODEL_FALLBACK:-gemini-3-flash-preview}"
1910
+ local output
1911
+
1912
+ # Try primary model first
1913
+ output=$(gemini --yolo --model "$model" "$prompt" "$@" < /dev/null 2>&1)
1914
+ local exit_code=$?
1915
+
1916
+ # Check for rate limit in output
1917
+ if [[ $exit_code -ne 0 ]] && echo "$output" | grep -qiE "(rate.?limit|429|quota|resource.?exhausted)"; then
1918
+ log_warn "Rate limit hit on $model, falling back to $fallback" >&2
1919
+ output=$(gemini --yolo --model "$fallback" "$prompt" "$@" < /dev/null 2>&1)
1920
+ fi
1921
+
1922
+ echo "$output"
1923
+ }
1924
+
1925
+ #===============================================================================
1926
+ # Copy Skill Files to Project Directory
1927
+ #===============================================================================
1928
+
1929
+ copy_skill_files() {
1930
+ # Copy skill files from the CLI package to the project's .loki/ directory.
1931
+ # This makes the CLI self-contained - no need to install Claude Code skill separately.
1932
+ # All providers (Claude, Gemini, Codex) use the same .loki/skills/ location.
1933
+
1934
+ local skills_src="$PROJECT_DIR/skills"
1935
+ local skills_dst=".loki/skills"
1936
+
1937
+ if [ ! -d "$skills_src" ]; then
1938
+ log_warn "Skills directory not found at $skills_src"
1939
+ return 1
1940
+ fi
1941
+
1942
+ # Create destination and copy skill files
1943
+ mkdir -p "$skills_dst"
1944
+
1945
+ # Copy all skill markdown files
1946
+ local copied=0
1947
+ for skill_file in "$skills_src"/*.md; do
1948
+ if [ -f "$skill_file" ]; then
1949
+ cp "$skill_file" "$skills_dst/"
1950
+ ((copied++))
1951
+ fi
1952
+ done
1953
+
1954
+ # Also copy SKILL.md to .loki/ and rewrite paths for workspace access
1955
+ if [ -f "$PROJECT_DIR/SKILL.md" ]; then
1956
+ # Rewrite skill paths from skills/ to .loki/skills/
1957
+ sed -e 's|skills/00-index\.md|.loki/skills/00-index.md|g' \
1958
+ -e 's|skills/model-selection\.md|.loki/skills/model-selection.md|g' \
1959
+ -e 's|skills/quality-gates\.md|.loki/skills/quality-gates.md|g' \
1960
+ -e 's|skills/testing\.md|.loki/skills/testing.md|g' \
1961
+ -e 's|skills/troubleshooting\.md|.loki/skills/troubleshooting.md|g' \
1962
+ -e 's|skills/production\.md|.loki/skills/production.md|g' \
1963
+ -e 's|skills/parallel-workflows\.md|.loki/skills/parallel-workflows.md|g' \
1964
+ -e 's|skills/providers\.md|.loki/skills/providers.md|g' \
1965
+ -e 's|Read skills/|Read .loki/skills/|g' \
1966
+ "$PROJECT_DIR/SKILL.md" > ".loki/SKILL.md"
1967
+ fi
1968
+
1969
+ log_info "Copied $copied skill files to .loki/skills/"
1970
+ }
1971
+
1867
1972
  #===============================================================================
1868
1973
  # Task Status Monitor
1869
1974
  #===============================================================================
@@ -3415,7 +3520,8 @@ build_prompt() {
3415
3520
  # Core autonomous instructions - NO questions, NO waiting, NEVER say done
3416
3521
  local autonomous_suffix="CRITICAL AUTONOMY RULES: 1) NEVER ask questions - just decide. 2) NEVER wait for confirmation - just act. 3) NEVER say 'done' or 'complete' - there's always more to improve. 4) NEVER stop voluntarily - if out of tasks, create new ones (add tests, optimize, refactor, add features). 5) Work continues PERPETUALLY. Even if PRD is implemented, find bugs, add tests, improve UX, optimize performance."
3417
3522
 
3418
- local sdlc_instruction="SDLC_PHASES_ENABLED: [$phases]. Execute ALL enabled phases. Log results to .loki/logs/. See SKILL.md for phase details."
3523
+ # Skill files are always copied to .loki/skills/ for all providers
3524
+ local sdlc_instruction="SDLC_PHASES_ENABLED: [$phases]. Execute ALL enabled phases. Log results to .loki/logs/. See .loki/SKILL.md for phase details. Skill modules at .loki/skills/."
3419
3525
 
3420
3526
  # Codebase Analysis Mode - when no PRD provided
3421
3527
  local analysis_instruction="CODEBASE_ANALYSIS_MODE: No PRD. FIRST: Analyze codebase - scan structure, read package.json/requirements.txt, examine README. THEN: Generate PRD at .loki/generated-prd.md. FINALLY: Execute SDLC phases."
@@ -3830,13 +3936,25 @@ if __name__ == "__main__":
3830
3936
 
3831
3937
  gemini)
3832
3938
  # Gemini: Degraded mode - no stream-json, no agent tracking
3833
- # Using --model flag to specify model
3834
- # Note: < /dev/null prevents Gemini from pausing on stdin
3835
- echo "[loki] Gemini model: ${PROVIDER_MODEL:-gemini-3-pro-preview}, tier: $tier_param" >> "$log_file"
3836
- echo "[loki] Gemini model: ${PROVIDER_MODEL:-gemini-3-pro-preview}, tier: $tier_param" >> "$agent_log"
3837
- gemini --yolo --model "${PROVIDER_MODEL:-gemini-3-pro-preview}" \
3838
- "$prompt" < /dev/null 2>&1 | tee -a "$log_file" "$agent_log"
3939
+ # Uses invoke_gemini helper for rate limit fallback to flash model
3940
+ local model="${PROVIDER_MODEL:-gemini-3-pro-preview}"
3941
+ local fallback="${PROVIDER_MODEL_FALLBACK:-gemini-3-flash-preview}"
3942
+ echo "[loki] Gemini model: $model (fallback: $fallback), tier: $tier_param" >> "$log_file"
3943
+ echo "[loki] Gemini model: $model (fallback: $fallback), tier: $tier_param" >> "$agent_log"
3944
+
3945
+ # Try primary model, fallback on rate limit
3946
+ local tmp_output
3947
+ tmp_output=$(mktemp)
3948
+ gemini --yolo --model "$model" "$prompt" < /dev/null 2>&1 | tee "$tmp_output" | tee -a "$log_file" "$agent_log"
3839
3949
  local exit_code=${PIPESTATUS[0]}
3950
+
3951
+ if [[ $exit_code -ne 0 ]] && grep -qiE "(rate.?limit|429|quota|resource.?exhausted)" "$tmp_output"; then
3952
+ log_warn "Rate limit hit on $model, falling back to $fallback"
3953
+ echo "[loki] Fallback to $fallback due to rate limit" >> "$log_file"
3954
+ gemini --yolo --model "$fallback" "$prompt" < /dev/null 2>&1 | tee -a "$log_file" "$agent_log"
3955
+ exit_code=${PIPESTATUS[0]}
3956
+ fi
3957
+ rm -f "$tmp_output"
3840
3958
  ;;
3841
3959
 
3842
3960
  *)
@@ -4276,6 +4394,10 @@ main() {
4276
4394
  # Initialize .loki directory
4277
4395
  init_loki_dir
4278
4396
 
4397
+ # Copy skill files to .loki/skills/ - makes CLI self-contained
4398
+ # No need to install Claude Code skill separately
4399
+ copy_skill_files
4400
+
4279
4401
  # Import GitHub issues if enabled (v4.1.0)
4280
4402
  if [ "$GITHUB_IMPORT" = "true" ]; then
4281
4403
  import_github_issues
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loki-mode",
3
- "version": "5.4.5",
3
+ "version": "5.4.7",
4
4
  "description": "Multi-agent autonomous startup system for Claude Code, Codex CLI, and Gemini CLI",
5
5
  "keywords": [
6
6
  "claude",
@@ -49,11 +49,13 @@ PROVIDER_MAX_PARALLEL=1
49
49
 
50
50
  # Model Configuration
51
51
  # Gemini CLI supports --model flag to specify model
52
- # Using gemini-3-pro-preview (latest as of Jan 2026)
52
+ # Primary: gemini-3-pro-preview (latest as of Jan 2026)
53
+ # Fallback: gemini-3-flash-preview (for rate limit scenarios)
53
54
  PROVIDER_MODEL="gemini-3-pro-preview"
55
+ PROVIDER_MODEL_FALLBACK="gemini-3-flash-preview"
54
56
  PROVIDER_MODEL_PLANNING="gemini-3-pro-preview"
55
57
  PROVIDER_MODEL_DEVELOPMENT="gemini-3-pro-preview"
56
- PROVIDER_MODEL_FAST="gemini-3-pro-preview"
58
+ PROVIDER_MODEL_FAST="gemini-3-flash-preview"
57
59
 
58
60
  # Thinking levels (Gemini-specific: maps to reasoning depth)
59
61
  PROVIDER_THINKING_PLANNING="high"
@@ -96,14 +98,28 @@ provider_version() {
96
98
  gemini --version 2>/dev/null | head -1
97
99
  }
98
100
 
99
- # Invocation function
101
+ # Invocation function with rate limit fallback
100
102
  # Uses --model flag to specify model, --yolo for autonomous mode
101
- # Using positional prompt (not deprecated -p flag)
103
+ # Falls back to flash model if pro hits rate limit
102
104
  # Note: < /dev/null prevents Gemini from pausing on stdin
103
105
  provider_invoke() {
104
106
  local prompt="$1"
105
107
  shift
106
- gemini --yolo --model "$PROVIDER_MODEL" "$prompt" "$@" < /dev/null
108
+ local output
109
+ local exit_code
110
+
111
+ # Try primary model first
112
+ output=$(gemini --yolo --model "$PROVIDER_MODEL" "$prompt" "$@" < /dev/null 2>&1)
113
+ exit_code=$?
114
+
115
+ # Check for rate limit (429) or quota exceeded
116
+ if [[ $exit_code -ne 0 ]] && echo "$output" | grep -qiE "(rate.?limit|429|quota|resource.?exhausted)"; then
117
+ echo "[loki] Rate limit hit on $PROVIDER_MODEL, falling back to $PROVIDER_MODEL_FALLBACK" >&2
118
+ gemini --yolo --model "$PROVIDER_MODEL_FALLBACK" "$prompt" "$@" < /dev/null
119
+ else
120
+ echo "$output"
121
+ return $exit_code
122
+ fi
107
123
  }
108
124
 
109
125
  # Model tier to thinking level parameter
@@ -117,14 +133,34 @@ provider_get_tier_param() {
117
133
  esac
118
134
  }
119
135
 
120
- # Tier-aware invocation
136
+ # Tier-aware invocation with rate limit fallback
121
137
  # Uses --model flag to specify model
122
- # Using positional prompt (not deprecated -p flag)
138
+ # Falls back to flash model if pro hits rate limit
123
139
  # Note: < /dev/null prevents Gemini from pausing on stdin
124
140
  provider_invoke_with_tier() {
125
141
  local tier="$1"
126
142
  local prompt="$2"
127
143
  shift 2
128
- echo "[loki] Using tier: $tier, model: $PROVIDER_MODEL" >&2
129
- gemini --yolo --model "$PROVIDER_MODEL" "$prompt" "$@" < /dev/null
144
+
145
+ # Select model based on tier
146
+ local model="$PROVIDER_MODEL"
147
+ [[ "$tier" == "fast" ]] && model="$PROVIDER_MODEL_FAST"
148
+
149
+ echo "[loki] Using tier: $tier, model: $model" >&2
150
+
151
+ local output
152
+ local exit_code
153
+
154
+ # Try selected model first
155
+ output=$(gemini --yolo --model "$model" "$prompt" "$@" < /dev/null 2>&1)
156
+ exit_code=$?
157
+
158
+ # Check for rate limit (429) or quota exceeded - fallback to flash
159
+ if [[ $exit_code -ne 0 ]] && echo "$output" | grep -qiE "(rate.?limit|429|quota|resource.?exhausted)"; then
160
+ echo "[loki] Rate limit hit on $model, falling back to $PROVIDER_MODEL_FALLBACK" >&2
161
+ gemini --yolo --model "$PROVIDER_MODEL_FALLBACK" "$prompt" "$@" < /dev/null
162
+ else
163
+ echo "$output"
164
+ return $exit_code
165
+ fi
130
166
  }