loki-mode 4.2.0 → 5.1.2

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.
@@ -0,0 +1,184 @@
1
+ #!/bin/bash
2
+ # Provider Loader for loki-mode
3
+ # Sources the appropriate provider configuration based on LOKI_PROVIDER
4
+
5
+ PROVIDERS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+
7
+ # List of supported providers
8
+ SUPPORTED_PROVIDERS=("claude" "codex" "gemini")
9
+
10
+ # Default provider
11
+ DEFAULT_PROVIDER="claude"
12
+
13
+ # Validate provider name
14
+ validate_provider() {
15
+ local provider="$1"
16
+ for p in "${SUPPORTED_PROVIDERS[@]}"; do
17
+ if [[ "$p" == "$provider" ]]; then
18
+ return 0
19
+ fi
20
+ done
21
+ return 1
22
+ }
23
+
24
+ # Load provider configuration
25
+ load_provider() {
26
+ local provider="${1:-$DEFAULT_PROVIDER}"
27
+
28
+ # SECURITY: Validate provider name before sourcing to prevent path traversal
29
+ if ! validate_provider "$provider"; then
30
+ echo "ERROR: Unknown provider: $provider" >&2
31
+ echo "Supported providers: ${SUPPORTED_PROVIDERS[*]}" >&2
32
+ return 1
33
+ fi
34
+
35
+ local config_file="$PROVIDERS_DIR/${provider}.sh"
36
+
37
+ if [[ ! -f "$config_file" ]]; then
38
+ echo "ERROR: Provider config not found: $config_file" >&2
39
+ return 1
40
+ fi
41
+
42
+ # Before sourcing, validate syntax
43
+ if ! bash -n "$config_file" 2>/dev/null; then
44
+ echo "ERROR: Syntax error in provider config: $config_file" >&2
45
+ return 1
46
+ fi
47
+
48
+ # Source the config file (cannot use subshell or variables will be lost)
49
+ # shellcheck source=/dev/null
50
+ if ! source "$config_file"; then
51
+ echo "ERROR: Failed to source provider config: $config_file" >&2
52
+ return 1
53
+ fi
54
+
55
+ # Validate required variables are set
56
+ if ! validate_provider_config; then
57
+ echo "ERROR: Provider config incomplete: $provider" >&2
58
+ return 1
59
+ fi
60
+
61
+ return 0
62
+ }
63
+
64
+ # Validate that required provider variables are set
65
+ validate_provider_config() {
66
+ local required_vars=(
67
+ PROVIDER_NAME
68
+ PROVIDER_DISPLAY_NAME
69
+ PROVIDER_CLI
70
+ PROVIDER_AUTONOMOUS_FLAG
71
+ PROVIDER_PROMPT_POSITIONAL
72
+ PROVIDER_HAS_SUBAGENTS
73
+ PROVIDER_HAS_PARALLEL
74
+ PROVIDER_DEGRADED
75
+ )
76
+
77
+ # Variables that must be defined but can be empty string
78
+ local allow_empty_vars=(
79
+ PROVIDER_PROMPT_FLAG
80
+ )
81
+
82
+ for var in "${required_vars[@]}"; do
83
+ if [[ -z "${!var+x}" ]]; then
84
+ echo "ERROR: Provider config missing required variable: $var" >&2
85
+ return 1
86
+ fi
87
+ # Also check for empty string (must have meaningful value)
88
+ if [[ -z "${!var}" ]]; then
89
+ echo "ERROR: Provider config variable is empty: $var" >&2
90
+ return 1
91
+ fi
92
+ done
93
+
94
+ for var in "${allow_empty_vars[@]}"; do
95
+ if [[ -z "${!var+x}" ]]; then
96
+ echo "ERROR: Provider config missing required variable: $var (can be empty string for positional prompts)" >&2
97
+ return 1
98
+ fi
99
+ done
100
+
101
+ return 0
102
+ }
103
+
104
+ # Check if provider CLI is installed
105
+ check_provider_installed() {
106
+ local provider="${1:-$PROVIDER_NAME}"
107
+
108
+ # Source provider to get provider_detect function
109
+ local config_file="$PROVIDERS_DIR/${provider}.sh"
110
+ if [[ -f "$config_file" ]]; then
111
+ ( source "$config_file" && provider_detect )
112
+ else
113
+ return 1
114
+ fi
115
+ }
116
+
117
+ # Get list of installed providers
118
+ get_installed_providers() {
119
+ local installed=()
120
+ for p in "${SUPPORTED_PROVIDERS[@]}"; do
121
+ if check_provider_installed "$p"; then
122
+ installed+=("$p")
123
+ fi
124
+ done
125
+ echo "${installed[@]}"
126
+ }
127
+
128
+ # Print provider info
129
+ print_provider_info() {
130
+ echo "Provider: $PROVIDER_DISPLAY_NAME ($PROVIDER_NAME)"
131
+ echo "CLI: $PROVIDER_CLI"
132
+ echo "Degraded Mode: $PROVIDER_DEGRADED"
133
+ if [[ "$PROVIDER_DEGRADED" == "true" ]]; then
134
+ echo "Limitations:"
135
+ for reason in "${PROVIDER_DEGRADED_REASONS[@]}"; do
136
+ echo " - $reason"
137
+ done
138
+ fi
139
+ echo "Capabilities:"
140
+ echo " - Subagents: $PROVIDER_HAS_SUBAGENTS"
141
+ echo " - Parallel: $PROVIDER_HAS_PARALLEL"
142
+ echo " - Task Tool: $PROVIDER_HAS_TASK_TOOL"
143
+ echo " - MCP: $PROVIDER_HAS_MCP"
144
+ echo " - Max Parallel: $PROVIDER_MAX_PARALLEL"
145
+ echo "Context Window: $PROVIDER_CONTEXT_WINDOW tokens"
146
+ }
147
+
148
+ # Print capability comparison matrix
149
+ print_capability_matrix() {
150
+ echo "Provider Capability Matrix"
151
+ echo "=========================="
152
+ printf "%-15s %-10s %-10s %-10s %-10s %-10s\n" \
153
+ "Provider" "Subagents" "Parallel" "Task Tool" "MCP" "Degraded"
154
+ echo "--------------------------------------------------------------"
155
+
156
+ for p in "${SUPPORTED_PROVIDERS[@]}"; do
157
+ local config_file="$PROVIDERS_DIR/${p}.sh"
158
+ if [[ -f "$config_file" ]]; then
159
+ (
160
+ source "$config_file"
161
+ printf "%-15s %-10s %-10s %-10s %-10s %-10s\n" \
162
+ "$PROVIDER_NAME" \
163
+ "$PROVIDER_HAS_SUBAGENTS" \
164
+ "$PROVIDER_HAS_PARALLEL" \
165
+ "$PROVIDER_HAS_TASK_TOOL" \
166
+ "$PROVIDER_HAS_MCP" \
167
+ "$PROVIDER_DEGRADED"
168
+ )
169
+ fi
170
+ done
171
+ }
172
+
173
+ # Auto-detect best available provider
174
+ auto_detect_provider() {
175
+ # Prefer Claude (full features), then Codex, then Gemini
176
+ for p in claude codex gemini; do
177
+ if check_provider_installed "$p"; then
178
+ echo "$p"
179
+ return 0
180
+ fi
181
+ done
182
+ echo ""
183
+ return 1
184
+ }
@@ -0,0 +1,423 @@
1
+ # Multi-Provider Architecture Reference
2
+
3
+ > **Version:** 5.1.0 | **Status:** Production | **Last Updated:** 2026-01-24
4
+
5
+ Loki Mode supports three AI CLI providers with a unified abstraction layer. This document provides detailed technical reference for the multi-provider system.
6
+
7
+ ---
8
+
9
+ ## Provider Overview
10
+
11
+ | Provider | CLI | Status | Features |
12
+ |----------|-----|--------|----------|
13
+ | **Claude Code** | `claude` | Full | Subagents, Parallel, Task Tool, MCP |
14
+ | **OpenAI Codex** | `codex` | Degraded | Sequential, Effort Parameter |
15
+ | **Google Gemini** | `gemini` | Degraded | Sequential, Thinking Level |
16
+
17
+ ---
18
+
19
+ ## Provider Configuration Files
20
+
21
+ Located in `providers/` directory:
22
+
23
+ ```
24
+ providers/
25
+ claude.sh # Full-featured provider
26
+ codex.sh # Degraded mode, effort parameter
27
+ gemini.sh # Degraded mode, thinking_level parameter
28
+ loader.sh # Provider loader utility
29
+ ```
30
+
31
+ ### Configuration Variables
32
+
33
+ Each provider config exports these variables:
34
+
35
+ #### Identity Variables
36
+ ```bash
37
+ PROVIDER_NAME="claude" # Internal identifier
38
+ PROVIDER_DISPLAY_NAME="Claude Code" # Human-readable name
39
+ PROVIDER_CLI="claude" # CLI binary name
40
+ ```
41
+
42
+ #### CLI Invocation Variables
43
+ ```bash
44
+ PROVIDER_AUTONOMOUS_FLAG="--dangerously-skip-permissions"
45
+ PROVIDER_PROMPT_FLAG="-p" # Empty for positional prompt
46
+ PROVIDER_PROMPT_POSITIONAL=false # true if prompt is positional arg
47
+ ```
48
+
49
+ #### Capability Flags
50
+ ```bash
51
+ PROVIDER_HAS_SUBAGENTS=true # Can spawn Task tool subagents
52
+ PROVIDER_HAS_PARALLEL=true # Supports parallel execution
53
+ PROVIDER_HAS_TASK_TOOL=true # Has Task tool for agent spawning
54
+ PROVIDER_HAS_MCP=true # Supports MCP server integration
55
+ PROVIDER_MAX_PARALLEL=10 # Maximum concurrent agents
56
+ ```
57
+
58
+ #### Model Configuration
59
+ ```bash
60
+ PROVIDER_MODEL_PLANNING="claude-opus-4-5-20251101"
61
+ PROVIDER_MODEL_DEVELOPMENT="claude-sonnet-4-5-20251101"
62
+ PROVIDER_MODEL_FAST="claude-haiku-4-5-20251101"
63
+ ```
64
+
65
+ #### Rate Limiting
66
+ ```bash
67
+ PROVIDER_RATE_LIMIT_RPM=50 # Requests per minute
68
+ PROVIDER_CONTEXT_WINDOW=200000 # Max context tokens
69
+ PROVIDER_MAX_OUTPUT_TOKENS=64000
70
+ ```
71
+
72
+ #### Degraded Mode
73
+ ```bash
74
+ PROVIDER_DEGRADED=false # true for Codex/Gemini
75
+ PROVIDER_DEGRADED_REASONS=() # Array of limitation descriptions
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Abstract Model Tiers
81
+
82
+ Loki Mode uses abstract tiers that map to provider-specific configurations:
83
+
84
+ | Abstract Tier | Purpose | Claude | Codex | Gemini |
85
+ |---------------|---------|--------|-------|--------|
86
+ | `planning` | Architecture, PRD analysis | opus | xhigh effort | high thinking |
87
+ | `development` | Implementation, tests | sonnet | high effort | medium thinking |
88
+ | `fast` | Simple tasks, docs | haiku | low effort | low thinking |
89
+
90
+ ### Tier Selection by RARV Phase
91
+
92
+ ```
93
+ RARV Phase -> Abstract Tier -> Provider-Specific
94
+ ─────────────────────────────────────────────────────
95
+ REASON -> planning -> opus/xhigh/high
96
+ ACT -> development -> sonnet/high/medium
97
+ REFLECT -> development -> sonnet/high/medium
98
+ VERIFY -> fast -> haiku/low/low
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Provider Loader API
104
+
105
+ ### Functions
106
+
107
+ ```bash
108
+ # Load a provider configuration
109
+ load_provider "claude" # Returns 0 on success, 1 on failure
110
+
111
+ # Check if provider is valid
112
+ validate_provider "codex" # Returns 0 if valid
113
+
114
+ # Check if provider CLI is installed
115
+ check_provider_installed "gemini" # Returns 0 if installed
116
+
117
+ # Auto-detect first available provider
118
+ auto_detect_provider # Echoes provider name or returns 1
119
+
120
+ # Print provider info
121
+ print_provider_info # Displays loaded provider details
122
+
123
+ # Print capability matrix
124
+ print_capability_matrix # Shows all providers comparison
125
+ ```
126
+
127
+ ### Usage Example
128
+
129
+ ```bash
130
+ source providers/loader.sh
131
+
132
+ # Load specific provider
133
+ if load_provider "codex"; then
134
+ echo "Loaded: $PROVIDER_DISPLAY_NAME"
135
+ echo "CLI: $PROVIDER_CLI"
136
+ echo "Degraded: $PROVIDER_DEGRADED"
137
+ fi
138
+
139
+ # Auto-detect
140
+ if provider=$(auto_detect_provider); then
141
+ load_provider "$provider"
142
+ fi
143
+ ```
144
+
145
+ ---
146
+
147
+ ## Provider Invocation Functions
148
+
149
+ Each provider exports these functions:
150
+
151
+ ```bash
152
+ # Check if CLI is installed
153
+ provider_detect() # Returns 0 if installed
154
+
155
+ # Get CLI version
156
+ provider_version() # Echoes version string
157
+
158
+ # Invoke with prompt (autonomous mode)
159
+ provider_invoke "Your prompt here"
160
+
161
+ # Invoke with tier-specific configuration
162
+ provider_invoke_with_tier "planning" "Your prompt here"
163
+
164
+ # Get tier parameter value
165
+ provider_get_tier_param "development" # Returns: opus/sonnet/haiku or xhigh/high/low
166
+ ```
167
+
168
+ ---
169
+
170
+ ## Degraded Mode Behavior
171
+
172
+ When running with Codex or Gemini:
173
+
174
+ 1. **RARV Cycle executes sequentially** - No parallel agents
175
+ 2. **Task tool calls are skipped** - Main thread handles all work
176
+ 3. **Model tier maps to provider configuration:**
177
+ - Codex: `CODEX_MODEL_REASONING_EFFORT` environment variable
178
+ - Gemini: `~/.gemini/settings.json` thinkingMode
179
+ 4. **Quality gates run sequentially** - No 3-reviewer parallel review
180
+ 5. **Git worktree parallelism disabled** - `--parallel` flag has no effect
181
+
182
+ ### Degraded Mode Detection
183
+
184
+ ```bash
185
+ if [ "$PROVIDER_DEGRADED" = "true" ]; then
186
+ echo "Running in degraded mode"
187
+ echo "Limitations:"
188
+ for reason in "${PROVIDER_DEGRADED_REASONS[@]}"; do
189
+ echo " - $reason"
190
+ done
191
+ fi
192
+ ```
193
+
194
+ ---
195
+
196
+ ## Rate Limit Detection
197
+
198
+ The rate limiting system is provider-agnostic:
199
+
200
+ ### Detection Patterns
201
+
202
+ ```bash
203
+ # Generic patterns (all providers)
204
+ - HTTP 429 status code
205
+ - "rate limit" / "rate-limit" / "ratelimit" (case insensitive)
206
+ - "too many requests"
207
+ - "quota exceeded"
208
+ - "request limit"
209
+ - "retry-after" header
210
+
211
+ # Claude-specific
212
+ - "resets Xam/pm" format
213
+ ```
214
+
215
+ ### Fallback Chain
216
+
217
+ ```
218
+ 1. Provider-specific parsing (Claude's reset time)
219
+ |
220
+ v (if no result)
221
+ 2. Generic Retry-After header parsing
222
+ |
223
+ v (if no result)
224
+ 3. Calculated backoff based on PROVIDER_RATE_LIMIT_RPM
225
+ ```
226
+
227
+ ### Rate Limit Functions
228
+
229
+ ```bash
230
+ # Check if output contains rate limit indicators
231
+ is_rate_limited "$log_file" # Returns 0 if rate limited
232
+
233
+ # Get wait time from rate limit response
234
+ detect_rate_limit "$log_file" # Echoes seconds to wait
235
+
236
+ # Parse Retry-After header
237
+ parse_retry_after "$log_file" # Echoes seconds
238
+
239
+ # Calculate default backoff
240
+ calculate_rate_limit_backoff # Uses PROVIDER_RATE_LIMIT_RPM
241
+ ```
242
+
243
+ ---
244
+
245
+ ## CLI Integration
246
+
247
+ ### Provider Selection
248
+
249
+ ```bash
250
+ # Via CLI flag
251
+ ./autonomy/run.sh --provider codex ./prd.md
252
+ loki start --provider gemini ./prd.md
253
+
254
+ # Via environment variable
255
+ export LOKI_PROVIDER=codex
256
+ ./autonomy/run.sh ./prd.md
257
+
258
+ # Precedence: flag > env > default (claude)
259
+ ```
260
+
261
+ ### Help Output
262
+
263
+ ```
264
+ $ loki start --help
265
+
266
+ Provider Options:
267
+ --provider PROVIDER Select AI provider (claude, codex, gemini)
268
+ Default: claude (auto-detect if not installed)
269
+
270
+ Provider Capability Matrix:
271
+ Provider Features Parallel Task Tool MCP
272
+ ──────────────────────────────────────────────────
273
+ claude Full Yes (10) Yes Yes
274
+ codex Degraded No No No
275
+ gemini Degraded No No No
276
+ ```
277
+
278
+ ---
279
+
280
+ ## Verified CLI Flags
281
+
282
+ All CLI flags have been verified against actual CLI help output:
283
+
284
+ | Provider | Flag | Verified Version | Notes |
285
+ |----------|------|------------------|-------|
286
+ | Claude | `--dangerously-skip-permissions` | v2.1.19 | Autonomous mode |
287
+ | Codex | `exec --dangerously-bypass-approvals-and-sandbox` | v0.89.0 | Requires `exec` subcommand |
288
+ | Gemini | `--yolo` | v0.25.2 | `-p` flag is DEPRECATED |
289
+
290
+ ### Gemini Note
291
+
292
+ The `-p` prompt flag is deprecated in Gemini CLI v0.25.2. Loki Mode uses positional prompts instead:
293
+
294
+ ```bash
295
+ # Correct (v5.1.0+)
296
+ gemini --yolo "$prompt"
297
+
298
+ # Deprecated (do not use)
299
+ gemini --yolo -p "$prompt"
300
+ ```
301
+
302
+ ---
303
+
304
+ ## Test Coverage
305
+
306
+ The multi-provider system has 180 tests across 5 test suites:
307
+
308
+ | Test Suite | Tests | Coverage |
309
+ |------------|-------|----------|
310
+ | `test-provider-loader.sh` | 12 | Provider loading, validation |
311
+ | `test-provider-invocation.sh` | 24 | Invoke functions, tier params |
312
+ | `test-provider-degraded-mode.sh` | 19 | Degraded flags, capabilities |
313
+ | `test-cli-provider-flag.sh` | 39 | CLI flag parsing, precedence |
314
+ | `test-rate-limiting.sh` | 27 | Rate limit detection, backoff |
315
+
316
+ Run tests:
317
+ ```bash
318
+ for test in tests/test-provider-*.sh tests/test-cli-provider-flag.sh tests/test-rate-limiting.sh; do
319
+ bash "$test"
320
+ done
321
+ ```
322
+
323
+ ---
324
+
325
+ ## Adding New Providers
326
+
327
+ To add a new provider:
328
+
329
+ 1. Create `providers/<name>.sh` with all required variables
330
+ 2. Implement the four provider functions:
331
+ - `provider_detect()`
332
+ - `provider_version()`
333
+ - `provider_invoke()`
334
+ - `provider_invoke_with_tier()`
335
+ - `provider_get_tier_param()`
336
+ 3. Add to `SUPPORTED_PROVIDERS` array in `loader.sh`
337
+ 4. Update `validate_provider()` regex
338
+ 5. Add provider case in `run.sh` invocation switch
339
+ 6. Add tests for new provider
340
+
341
+ ### Provider Template
342
+
343
+ ```bash
344
+ #!/bin/bash
345
+ # <Provider Name> CLI Provider Configuration
346
+
347
+ # Provider Identity
348
+ PROVIDER_NAME="<name>"
349
+ PROVIDER_DISPLAY_NAME="<Display Name>"
350
+ PROVIDER_CLI="<cli-binary>"
351
+
352
+ # CLI Invocation
353
+ PROVIDER_AUTONOMOUS_FLAG="<autonomous-flag>"
354
+ PROVIDER_PROMPT_FLAG="" # or "-p" etc
355
+ PROVIDER_PROMPT_POSITIONAL=true
356
+
357
+ # Capability Flags
358
+ PROVIDER_HAS_SUBAGENTS=false
359
+ PROVIDER_HAS_PARALLEL=false
360
+ PROVIDER_HAS_TASK_TOOL=false
361
+ PROVIDER_HAS_MCP=false
362
+ PROVIDER_MAX_PARALLEL=1
363
+
364
+ # Model Configuration
365
+ PROVIDER_MODEL_PLANNING="<model>"
366
+ PROVIDER_MODEL_DEVELOPMENT="<model>"
367
+ PROVIDER_MODEL_FAST="<model>"
368
+
369
+ # Context and Limits
370
+ PROVIDER_CONTEXT_WINDOW=128000
371
+ PROVIDER_MAX_OUTPUT_TOKENS=32000
372
+ PROVIDER_RATE_LIMIT_RPM=60
373
+
374
+ # Degraded Mode
375
+ PROVIDER_DEGRADED=true
376
+ PROVIDER_DEGRADED_REASONS=(
377
+ "Reason 1"
378
+ "Reason 2"
379
+ )
380
+
381
+ # Provider Functions
382
+ provider_detect() {
383
+ command -v <cli-binary> >/dev/null 2>&1
384
+ }
385
+
386
+ provider_version() {
387
+ <cli-binary> --version 2>/dev/null | head -1
388
+ }
389
+
390
+ provider_invoke() {
391
+ local prompt="$1"
392
+ shift
393
+ <cli-binary> <autonomous-flag> "$prompt" "$@"
394
+ }
395
+
396
+ provider_get_tier_param() {
397
+ local tier="$1"
398
+ case "$tier" in
399
+ planning) echo "<planning-param>" ;;
400
+ development) echo "<dev-param>" ;;
401
+ fast) echo "<fast-param>" ;;
402
+ *) echo "<default-param>" ;;
403
+ esac
404
+ }
405
+
406
+ provider_invoke_with_tier() {
407
+ local tier="$1"
408
+ local prompt="$2"
409
+ shift 2
410
+ local param=$(provider_get_tier_param "$tier")
411
+ # Provider-specific tier invocation
412
+ <cli-binary> <autonomous-flag> "$prompt" "$@"
413
+ }
414
+ ```
415
+
416
+ ---
417
+
418
+ ## Related Documentation
419
+
420
+ - `skills/providers.md` - User-facing provider guide
421
+ - `skills/model-selection.md` - Model tier selection patterns
422
+ - `references/core-workflow.md` - RARV cycle documentation
423
+ - `docs/INSTALLATION.md` - Installation instructions per provider
@@ -26,6 +26,7 @@
26
26
  | Parallel features, git worktrees | `parallel-workflows.md` |
27
27
  | Scale patterns (50+ agents) | `parallel-workflows.md` + `references/cursor-learnings.md` |
28
28
  | GitHub issues, PRs, syncing | `github-integration.md` |
29
+ | Multi-provider (Codex, Gemini) | `providers.md` |
29
30
 
30
31
  ## Module Descriptions
31
32
 
@@ -107,6 +108,14 @@
107
108
  - Filter by labels, milestone, assignee
108
109
  - Requires `gh` CLI authenticated
109
110
 
111
+ ### providers.md (v5.0.0)
112
+ **When:** Using non-Claude providers (Codex, Gemini), understanding degraded mode
113
+ - Provider comparison matrix
114
+ - Claude (full features) vs Codex/Gemini (degraded mode)
115
+ - Provider selection via CLI flag or environment variable
116
+ - Model tier mapping (planning/development/fast)
117
+ - Degraded mode limitations and behavior
118
+
110
119
  ## How to Load
111
120
 
112
121
  ```python