loki-mode 7.5.17 → 7.5.27
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/README.md +10 -9
- package/SKILL.md +14 -14
- package/VERSION +1 -1
- package/autonomy/completion-council.sh +26 -3
- package/autonomy/lib/claude-flags.sh +132 -0
- package/autonomy/lib/mcp-config.sh +160 -0
- package/autonomy/lib/project-graph.sh +675 -0
- package/autonomy/lib/voter-agents.sh +356 -0
- package/autonomy/loki +61 -96
- package/autonomy/run.sh +95 -186
- package/bin/loki +10 -0
- package/dashboard/__init__.py +1 -1
- package/dashboard/requirements.txt +13 -8
- package/dashboard/server.py +33 -15
- package/dashboard/static/index.html +298 -299
- package/docs/INSTALLATION.md +54 -21
- package/docs/retrospectives/v7.5.15-fleet-postmortem.md +325 -0
- package/docs/retrospectives/v7.5.15-honesty-audit.md +136 -0
- package/docs/retrospectives/v7.5.15-llm-failure-modes.md +49 -0
- package/loki-ts/data/finding-schema.json +74 -0
- package/loki-ts/data/model-pricing.json +12 -0
- package/loki-ts/dist/loki.js +109 -108
- package/mcp/__init__.py +1 -1
- package/mcp/lsp_proxy.py +713 -0
- package/mcp/requirements.txt +9 -3
- package/mcp/tests/__init__.py +0 -0
- package/mcp/tests/test_lsp_proxy.py +377 -0
- package/memory/app_graph.py +153 -0
- package/memory/storage.py +6 -1
- package/memory/tests/test_app_graph.py +134 -0
- package/package.json +4 -3
- package/providers/claude.sh +115 -4
- package/providers/codex.sh +2 -2
- package/providers/loader.sh +4 -4
- package/providers/model_catalog.json +0 -9
- package/providers/models.sh +1 -2
- package/references/multi-provider.md +26 -35
- package/references/prompt-repetition.md +1 -1
- package/references/quality-control.md +1 -1
- package/skills/00-index.md +3 -3
- package/skills/model-selection.md +11 -14
- package/skills/providers.md +17 -57
- package/skills/quality-gates.md +2 -2
- package/skills/troubleshooting.md +1 -1
- package/src/integrations/github/action-handler.js +3 -2
- package/src/protocols/tools/start-project.js +1 -1
- package/providers/gemini.sh +0 -343
package/dashboard/server.py
CHANGED
|
@@ -810,7 +810,7 @@ async def agent_card() -> dict:
|
|
|
810
810
|
"agents": 41,
|
|
811
811
|
"swarms": 8,
|
|
812
812
|
"quality_gates": 9,
|
|
813
|
-
"providers": ["claude", "codex", "
|
|
813
|
+
"providers": ["claude", "codex", "cline", "aider"],
|
|
814
814
|
"streaming": True,
|
|
815
815
|
"pushNotifications": False,
|
|
816
816
|
"stateTransitionHistory": True,
|
|
@@ -3168,8 +3168,17 @@ def _parse_time_range(time_range: str) -> Optional[datetime]:
|
|
|
3168
3168
|
return datetime.now(timezone.utc) - delta
|
|
3169
3169
|
|
|
3170
3170
|
|
|
3171
|
-
def _read_events(time_range: str = "7d", max_events: int = 10000) -> list:
|
|
3172
|
-
"""Read events from .loki/events.jsonl with time filter and size limits.
|
|
3171
|
+
def _read_events(time_range: str = "7d", max_events: int = 10000, type_prefix: Optional[str] = None) -> list:
|
|
3172
|
+
"""Read events from .loki/events.jsonl with time filter and size limits.
|
|
3173
|
+
|
|
3174
|
+
Args:
|
|
3175
|
+
time_range: e.g. "7d", "24h", "30m". Events older than the cutoff are dropped.
|
|
3176
|
+
max_events: hard cap on the number of returned events.
|
|
3177
|
+
type_prefix: when set (non-empty), only return events whose ``type`` field
|
|
3178
|
+
starts with this prefix. Backward compatible: when None or empty,
|
|
3179
|
+
no type filtering is applied. Used by v7.5.22 Phase D for filtering
|
|
3180
|
+
``claude_hook_*`` events without adding a new endpoint.
|
|
3181
|
+
"""
|
|
3173
3182
|
events_file = _get_loki_dir() / "events.jsonl"
|
|
3174
3183
|
if not events_file.exists():
|
|
3175
3184
|
return []
|
|
@@ -3208,6 +3217,10 @@ def _read_events(time_range: str = "7d", max_events: int = 10000) -> list:
|
|
|
3208
3217
|
continue
|
|
3209
3218
|
except (ValueError, TypeError):
|
|
3210
3219
|
pass # Keep events with unparseable timestamps
|
|
3220
|
+
# Optional type-prefix filter (v7.5.22 Phase D).
|
|
3221
|
+
if type_prefix:
|
|
3222
|
+
if not str(event.get("type", "")).startswith(type_prefix):
|
|
3223
|
+
continue
|
|
3211
3224
|
events.append(event)
|
|
3212
3225
|
except json.JSONDecodeError:
|
|
3213
3226
|
pass
|
|
@@ -3401,9 +3414,6 @@ _DEFAULT_PRICING = {
|
|
|
3401
3414
|
"haiku": {"input": 1.00, "output": 5.00},
|
|
3402
3415
|
# OpenAI Codex
|
|
3403
3416
|
"gpt-5.3-codex": {"input": 1.50, "output": 12.00},
|
|
3404
|
-
# Google Gemini
|
|
3405
|
-
"gemini-3-pro": {"input": 1.25, "output": 10.00},
|
|
3406
|
-
"gemini-3-flash": {"input": 0.10, "output": 0.40},
|
|
3407
3417
|
}
|
|
3408
3418
|
|
|
3409
3419
|
# Active pricing - starts with defaults, updated from .loki/pricing.json
|
|
@@ -3616,8 +3626,6 @@ _PROVIDER_LABELS = {
|
|
|
3616
3626
|
"sonnet": "Sonnet 4.5",
|
|
3617
3627
|
"haiku": "Haiku 4.5",
|
|
3618
3628
|
"gpt-5.3-codex": "GPT-5.3 Codex",
|
|
3619
|
-
"gemini-3-pro": "Gemini 3 Pro",
|
|
3620
|
-
"gemini-3-flash": "Gemini 3 Flash",
|
|
3621
3629
|
}
|
|
3622
3630
|
|
|
3623
3631
|
_MODEL_PROVIDERS = {
|
|
@@ -3625,8 +3633,6 @@ _MODEL_PROVIDERS = {
|
|
|
3625
3633
|
"sonnet": "claude",
|
|
3626
3634
|
"haiku": "claude",
|
|
3627
3635
|
"gpt-5.3-codex": "codex",
|
|
3628
|
-
"gemini-3-pro": "gemini",
|
|
3629
|
-
"gemini-3-flash": "gemini",
|
|
3630
3636
|
"cline-default": "cline",
|
|
3631
3637
|
"aider-default": "aider",
|
|
3632
3638
|
}
|
|
@@ -3787,13 +3793,18 @@ async def get_council_transcripts(
|
|
|
3787
3793
|
limit: int = Query(default=20, ge=1, le=200),
|
|
3788
3794
|
since: Optional[str] = Query(default=None),
|
|
3789
3795
|
iter_min: Optional[int] = Query(default=None, ge=0),
|
|
3796
|
+
type_prefix: Optional[str] = Query(default=None),
|
|
3790
3797
|
):
|
|
3791
3798
|
"""List council transcript records, sorted descending by iteration number.
|
|
3792
3799
|
|
|
3793
3800
|
Query params:
|
|
3794
|
-
limit
|
|
3795
|
-
since
|
|
3796
|
-
iter_min
|
|
3801
|
+
limit int, default=20, max=200
|
|
3802
|
+
since ISO8601 string (optional), filter to transcripts after this time
|
|
3803
|
+
iter_min int (optional), filter to iteration >= N
|
|
3804
|
+
type_prefix str (optional), v7.5.22 Phase D. When set, the response also
|
|
3805
|
+
includes a ``hook_events`` array of matching .loki/events.jsonl
|
|
3806
|
+
entries whose ``type`` starts with this prefix (e.g.
|
|
3807
|
+
``claude_hook_``). Unset -> behavior unchanged.
|
|
3797
3808
|
"""
|
|
3798
3809
|
# Validate query params before any early-return so invalid inputs always get 400.
|
|
3799
3810
|
since_dt = None
|
|
@@ -3805,7 +3816,10 @@ async def get_council_transcripts(
|
|
|
3805
3816
|
|
|
3806
3817
|
transcripts_dir = _get_loki_dir() / "council" / "transcripts"
|
|
3807
3818
|
if not transcripts_dir.exists():
|
|
3808
|
-
|
|
3819
|
+
response: dict = {"transcripts": [], "total": 0, "latest_id": None}
|
|
3820
|
+
if type_prefix:
|
|
3821
|
+
response["hook_events"] = _read_events(type_prefix=type_prefix)
|
|
3822
|
+
return response
|
|
3809
3823
|
|
|
3810
3824
|
records = []
|
|
3811
3825
|
for f in sorted(transcripts_dir.glob("iter-*.json"), reverse=True):
|
|
@@ -3834,11 +3848,15 @@ async def get_council_transcripts(
|
|
|
3834
3848
|
if len(records) >= limit:
|
|
3835
3849
|
break
|
|
3836
3850
|
|
|
3837
|
-
|
|
3851
|
+
response = {
|
|
3838
3852
|
"transcripts": records,
|
|
3839
3853
|
"total": len(records),
|
|
3840
3854
|
"latest_id": records[0].get("iteration_id") if records else None,
|
|
3841
3855
|
}
|
|
3856
|
+
# v7.5.22 Phase D: opt-in hook-event passthrough via _read_events filter.
|
|
3857
|
+
if type_prefix:
|
|
3858
|
+
response["hook_events"] = _read_events(type_prefix=type_prefix)
|
|
3859
|
+
return response
|
|
3842
3860
|
|
|
3843
3861
|
|
|
3844
3862
|
@app.get("/api/council/transcripts/{iteration_id}")
|