loki-mode 7.9.1 → 7.10.1

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: Autonomous spec-to-product system. Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product via the RARV-C closure loop, with minimal human intervention. Provider-agnostic. Requires --dangerously-skip-permissions flag.
4
4
  ---
5
5
 
6
- # Loki Mode v7.9.1
6
+ # Loki Mode v7.10.1
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -381,4 +381,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
381
381
 
382
382
  ---
383
383
 
384
- **v7.9.1 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
384
+ **v7.10.1 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 7.9.1
1
+ 7.10.1
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env python3
2
+ """Shared efficiency + cost collection for Loki Mode.
3
+
4
+ This module is the single source of truth for reading per-iteration
5
+ efficiency records out of .loki/metrics/efficiency/ and turning them into a
6
+ cost dict. It was extracted from autonomy/lib/proof-generator.py (R1) so that
7
+ both the proof generator and the R2 benchmark adapters compute cost the same
8
+ way ("bench cost == proof cost"). proof-generator.py has a hyphen in its name
9
+ and is therefore not importable as a module, which is why the logic lives
10
+ here instead.
11
+
12
+ Behavior contract (preserved from the R1 proof generator):
13
+ - cost.usd is None when NO valid efficiency record was read (cost was never
14
+ collected for this run). A skeptic seeing "$0.00" assumes the artifact is
15
+ fake; "cost not recorded" is the honest signal.
16
+ - A genuine 0.0 (records existed but summed to zero) is preserved as 0.0.
17
+ - usd is rounded to 4 decimals only when records were collected.
18
+
19
+ The token->USD pricing helper (price_from_tokens) lives here too so that
20
+ adapters and the report compute uniform cost from a single dated price table
21
+ (benchmarks/bench/prices.json) when a tool reports tokens but no native
22
+ cost_usd. This is additive: the proof generator does not use it.
23
+ """
24
+
25
+ import json
26
+ import os
27
+
28
+ __all__ = [
29
+ "collect_efficiency",
30
+ "load_prices",
31
+ "price_from_tokens",
32
+ "DEFAULT_PRICES_PATH",
33
+ ]
34
+
35
+ # benchmarks/bench/prices.json relative to the repo root. Resolved lazily so
36
+ # importing this module never depends on cwd or on the file existing.
37
+ _HERE = os.path.dirname(os.path.abspath(__file__))
38
+ _REPO_ROOT = os.path.dirname(os.path.dirname(_HERE)) # autonomy/lib -> repo
39
+ DEFAULT_PRICES_PATH = os.path.join(
40
+ _REPO_ROOT, "benchmarks", "bench", "prices.json"
41
+ )
42
+
43
+
44
+ # ---------------------------------------------------------------------------
45
+ # small helpers (self-contained copies; proof-generator.py keeps its own)
46
+ # ---------------------------------------------------------------------------
47
+
48
+ def _read_json(path, default=None):
49
+ try:
50
+ with open(path, "r") as f:
51
+ return json.load(f)
52
+ except Exception:
53
+ return default
54
+
55
+
56
+ def _to_int(v, default=0):
57
+ try:
58
+ return int(v)
59
+ except Exception:
60
+ return default
61
+
62
+
63
+ def _to_float(v, default=0.0):
64
+ try:
65
+ return float(v)
66
+ except Exception:
67
+ return default
68
+
69
+
70
+ # ---------------------------------------------------------------------------
71
+ # efficiency collection (extracted verbatim from proof-generator.py)
72
+ # ---------------------------------------------------------------------------
73
+
74
+ def collect_efficiency(loki_dir):
75
+ """Sum cost + tokens across .loki/metrics/efficiency/iteration-*.json.
76
+
77
+ Returns (cost dict, best-effort model name (last non-empty seen)).
78
+
79
+ Credibility: cost.usd is set to None when NO valid efficiency record was
80
+ read (cost was never collected for this run). A skeptic seeing "$0.00" on
81
+ HN assumes the artifact is fake; "cost not recorded" is the honest signal.
82
+ A genuine 0.0 (records existed but summed to zero) is preserved as 0.0.
83
+ """
84
+ cost = {
85
+ "usd": 0.0,
86
+ "input_tokens": 0,
87
+ "output_tokens": 0,
88
+ "cache_read_tokens": 0,
89
+ "cache_creation_tokens": 0,
90
+ }
91
+ model = ""
92
+ collected = False
93
+ eff_dir = os.path.join(loki_dir, "metrics", "efficiency")
94
+ try:
95
+ names = sorted(os.listdir(eff_dir))
96
+ except Exception:
97
+ names = []
98
+ for name in names:
99
+ if not (name.startswith("iteration-") and name.endswith(".json")):
100
+ continue
101
+ rec = _read_json(os.path.join(eff_dir, name), default=None)
102
+ if not isinstance(rec, dict):
103
+ continue
104
+ collected = True
105
+ cost["usd"] += _to_float(rec.get("cost_usd"))
106
+ cost["input_tokens"] += _to_int(rec.get("input_tokens"))
107
+ cost["output_tokens"] += _to_int(rec.get("output_tokens"))
108
+ cost["cache_read_tokens"] += _to_int(rec.get("cache_read_tokens"))
109
+ cost["cache_creation_tokens"] += _to_int(rec.get("cache_creation_tokens"))
110
+ if rec.get("model"):
111
+ model = str(rec.get("model"))
112
+ if collected:
113
+ # Round usd to a sane precision but keep it precise (anti-pattern:
114
+ # round suspiciously-clean numbers). 4 decimals preserves odd values.
115
+ cost["usd"] = round(cost["usd"], 4)
116
+ else:
117
+ # No efficiency files were read: cost was not collected for this run.
118
+ cost["usd"] = None
119
+ return cost, model
120
+
121
+
122
+ # ---------------------------------------------------------------------------
123
+ # uniform token -> USD pricing (R2 benchmark; not used by the proof generator)
124
+ # ---------------------------------------------------------------------------
125
+
126
+ def load_prices(path=None):
127
+ """Load the shared dated price table. Returns {} if missing/unreadable.
128
+
129
+ Never raises: a missing price table means we cannot price tokens, which is
130
+ an honest null, not a fabricated zero.
131
+ """
132
+ p = path or DEFAULT_PRICES_PATH
133
+ data = _read_json(p, default=None)
134
+ if not isinstance(data, dict):
135
+ return {}
136
+ return data
137
+
138
+
139
+ def price_from_tokens(model, input_tokens, output_tokens,
140
+ cache_read_tokens=0, prices=None, prices_path=None):
141
+ """Compute a USD cost from raw token counts and the shared price table.
142
+
143
+ Returns a float (rounded to 6 decimals) when the model is present in the
144
+ price table, else None. None means "cannot price" (honest), never 0.0.
145
+
146
+ Pricing is per million tokens (mtok). cache_read is priced separately from
147
+ fresh input tokens. Used for tools that expose token counts but not a
148
+ native cost_usd; keeps cross-tool cost comparison on one pricing basis.
149
+ """
150
+ table = prices if prices is not None else load_prices(prices_path)
151
+ models = table.get("models") if isinstance(table, dict) else None
152
+ if not isinstance(models, dict):
153
+ return None
154
+ entry = models.get(model)
155
+ if not isinstance(entry, dict):
156
+ return None
157
+ in_rate = _to_float(entry.get("input_per_mtok"), None)
158
+ out_rate = _to_float(entry.get("output_per_mtok"), None)
159
+ cache_rate = _to_float(entry.get("cache_read_per_mtok"), 0.0)
160
+ if in_rate is None or out_rate is None:
161
+ return None
162
+ it = _to_int(input_tokens)
163
+ ot = _to_int(output_tokens)
164
+ ct = _to_int(cache_read_tokens)
165
+ usd = (
166
+ (it / 1_000_000.0) * in_rate
167
+ + (ot / 1_000_000.0) * out_rate
168
+ + (ct / 1_000_000.0) * cache_rate
169
+ )
170
+ return round(usd, 6)
@@ -35,6 +35,7 @@ if _HERE not in sys.path:
35
35
  sys.path.insert(0, _HERE)
36
36
 
37
37
  import proof_redact # noqa: E402
38
+ from efficiency_cost import collect_efficiency as _collect_efficiency # noqa: E402
38
39
 
39
40
 
40
41
  # ---------------------------------------------------------------------------
@@ -85,52 +86,10 @@ def _to_float(v, default=0.0):
85
86
  # data collection
86
87
  # ---------------------------------------------------------------------------
87
88
 
88
- def _collect_efficiency(loki_dir):
89
- """Sum cost + tokens across .loki/metrics/efficiency/iteration-*.json.
90
-
91
- Returns cost dict and a best-effort model name (last non-empty seen).
92
-
93
- Credibility: cost.usd is set to None when NO valid efficiency record was
94
- read (cost was never collected for this run). A skeptic seeing "$0.00" on
95
- HN assumes the artifact is fake; "cost not recorded" is the honest signal.
96
- A genuine 0.0 (records existed but summed to zero) is preserved as 0.0.
97
- """
98
- cost = {
99
- "usd": 0.0,
100
- "input_tokens": 0,
101
- "output_tokens": 0,
102
- "cache_read_tokens": 0,
103
- "cache_creation_tokens": 0,
104
- }
105
- model = ""
106
- collected = False
107
- eff_dir = os.path.join(loki_dir, "metrics", "efficiency")
108
- try:
109
- names = sorted(os.listdir(eff_dir))
110
- except Exception:
111
- names = []
112
- for name in names:
113
- if not (name.startswith("iteration-") and name.endswith(".json")):
114
- continue
115
- rec = _read_json(os.path.join(eff_dir, name), default=None)
116
- if not isinstance(rec, dict):
117
- continue
118
- collected = True
119
- cost["usd"] += _to_float(rec.get("cost_usd"))
120
- cost["input_tokens"] += _to_int(rec.get("input_tokens"))
121
- cost["output_tokens"] += _to_int(rec.get("output_tokens"))
122
- cost["cache_read_tokens"] += _to_int(rec.get("cache_read_tokens"))
123
- cost["cache_creation_tokens"] += _to_int(rec.get("cache_creation_tokens"))
124
- if rec.get("model"):
125
- model = str(rec.get("model"))
126
- if collected:
127
- # Round usd to a sane precision but keep it precise (anti-pattern:
128
- # round suspiciously-clean numbers). 4 decimals preserves odd values.
129
- cost["usd"] = round(cost["usd"], 4)
130
- else:
131
- # No efficiency files were read: cost was not collected for this run.
132
- cost["usd"] = None
133
- return cost, model
89
+ # _collect_efficiency was extracted to autonomy/lib/efficiency_cost.py (R2) so
90
+ # the benchmark adapters and this generator compute cost identically. It is
91
+ # imported at the top of this file as _collect_efficiency; the behavior
92
+ # (None usd when uncollected, 0.0 preserved, 4-decimal rounding) is unchanged.
134
93
 
135
94
 
136
95
  def _collect_council(loki_dir):
package/autonomy/loki CHANGED
@@ -567,6 +567,7 @@ show_help() {
567
567
  echo " report [opts] Session report generator (--format text|markdown|html, --output)"
568
568
  echo " share [opts] Share session report as GitHub Gist (--private, --format)"
569
569
  echo " proof [cmd] Inspect/share proof-of-run artifacts (list|show|open|share)"
570
+ echo " bench [cmd] Head-to-head benchmark harness (run|vs|list|verify|report)"
570
571
  echo " version Show version"
571
572
  echo " help Show this help"
572
573
  echo ""
@@ -13078,6 +13079,9 @@ main() {
13078
13079
  proof)
13079
13080
  cmd_proof "$@"
13080
13081
  ;;
13082
+ bench)
13083
+ cmd_bench "$@"
13084
+ ;;
13081
13085
  context|ctx)
13082
13086
  cmd_context "$@"
13083
13087
  ;;
@@ -24541,6 +24545,48 @@ _loki_gist_upload() {
24541
24545
  echo -e "${GREEN}Shared: ${gist_url}${NC}"
24542
24546
  }
24543
24547
 
24548
+ # loki bench - head-to-head benchmark harness (R2).
24549
+ # Subcommands: run <task> | vs <task> | list | verify <result.json>.
24550
+ # Thin pass-through to benchmarks/bench/run.sh (shared python core runner.py).
24551
+ # CREDIBILITY: Loki NEVER grades its own success. Success is decided by a
24552
+ # held-out acceptance command run by the grader OUTSIDE the agent (exit code).
24553
+ # No council / RARV-C / LLM-judge participates in scoring. See
24554
+ # benchmarks/SCHEMA-adapter.md and benchmarks/SCHEMA-result.md.
24555
+ cmd_bench() {
24556
+ local bench_sh="$SKILL_DIR/benchmarks/bench/run.sh"
24557
+ if [ ! -f "$bench_sh" ]; then
24558
+ log_error "benchmark harness not found: $bench_sh"
24559
+ return 1
24560
+ fi
24561
+ local sub="${1:-}"
24562
+ case "$sub" in
24563
+ ""|--help|-h|help)
24564
+ echo -e "${BOLD}loki bench${NC} - head-to-head benchmark harness (R2)"
24565
+ echo ""
24566
+ echo "Usage: loki bench <subcommand> [args] [options]"
24567
+ echo ""
24568
+ echo "Subcommands:"
24569
+ echo " run <task> Run Loki only on a task-spec"
24570
+ echo " vs <task> Run all configured tools on a task-spec (head-to-head)"
24571
+ echo " list List available task-specs"
24572
+ echo " verify <file> Recompute task_hash + check tool versions for a result.json"
24573
+ echo " report <files> Build results.json + RESULTS.md from per-tool result-rows"
24574
+ echo ""
24575
+ echo "Options:"
24576
+ echo " --trials N Number of trials per tool (default 3)"
24577
+ echo " --model NAME Override the model"
24578
+ echo " --emit-proof Emit an R1 proof-of-run for the Loki trial(s)"
24579
+ echo " --out-dir DIR (report) output dir for results.json + RESULTS.md"
24580
+ echo ""
24581
+ echo "Loki NEVER grades its own success: a held-out acceptance command run"
24582
+ echo "by the grader OUTSIDE the agent decides success by exit code."
24583
+ [ "$sub" = "" ] && return 1
24584
+ return 0
24585
+ ;;
24586
+ esac
24587
+ bash "$bench_sh" "$@"
24588
+ }
24589
+
24544
24590
  # loki proof - inspect and share proof-of-run artifacts (.loki/proofs/<id>/).
24545
24591
  # Subcommands: list | show <id> | open <id> | share <id>.
24546
24592
  # The proof.json schema is frozen (R1 spec). Reads are tolerant of missing
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "7.9.1"
10
+ __version__ = "7.10.1"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -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:** v7.9.1
5
+ **Version:** v7.10.1
6
6
 
7
7
  ---
8
8
 
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- var N7=Object.defineProperty;var k7=(K)=>K;function D7(K,$){this[K]=k7.bind(null,$)}var v=(K,$)=>{for(var Q in $)N7(K,Q,{get:$[Q],enumerable:!0,configurable:!0,set:D7.bind($,Q)})};var E=(K,$)=>()=>(K&&($=K(K=0)),$);var $1=import.meta.require;var z0={};v(z0,{lokiDir:()=>R,homeLokiDir:()=>v1,findRepoRootForVersion:()=>y1,REPO_ROOT:()=>c});import{resolve as p,dirname as b1}from"path";import{fileURLToPath as C7}from"url";import{existsSync as O1}from"fs";import{homedir as h7}from"os";function b7(){let K=Z0;for(let $=0;$<6;$++){if(O1(p(K,"VERSION"))&&O1(p(K,"autonomy/run.sh")))return K;let Q=b1(K);if(Q===K)break;K=Q}return p(Z0,"..","..","..")}function y1(K){let $=K;for(let Q=0;Q<6;Q++){if(O1(p($,"VERSION"))&&O1(p($,"autonomy/run.sh")))return $;let X=b1($);if(X===$)break;$=X}return p(K,"..","..","..")}function R(){return process.env.LOKI_DIR??p(process.cwd(),".loki")}function v1(){return p(h7(),".loki")}var Z0,c;var g=E(()=>{Z0=b1(C7(import.meta.url));c=b7()});import{readFileSync as y7}from"fs";import{resolve as v7,dirname as g7}from"path";import{fileURLToPath as m7}from"url";function T1(){if(r!==null)return r;let K="7.9.1";if(typeof K==="string"&&K.length>0)return r=K,r;try{let $=g7(m7(import.meta.url)),Q=y1($);r=y7(v7(Q,"VERSION"),"utf-8").trim()}catch{r="unknown"}return r}var r=null;var g1=E(()=>{g()});var U0={};v(U0,{runOrThrow:()=>f7,run:()=>N,commandVersion:()=>p7,commandExists:()=>y,ShellError:()=>m1});async function N(K,$={}){let Q=Bun.spawn({cmd:[...K],stdout:"pipe",stderr:"pipe",env:$.env?{...process.env,...$.env}:process.env,cwd:$.cwd}),X,Z;if($.timeoutMs&&$.timeoutMs>0)X=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}Z=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},$.timeoutMs);try{let[z,H,V]=await Promise.all([new Response(Q.stdout).text(),new Response(Q.stderr).text(),Q.exited]);return{stdout:z,stderr:H,exitCode:V}}finally{if(X)clearTimeout(X);if(Z)clearTimeout(Z)}}async function f7(K,$={}){let Q=await N(K,$);if(Q.exitCode!==0)throw new m1(`command failed (${Q.exitCode}): ${K.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function y(K){let $=u7(K),Q=await N(["sh","-c",`command -v ${$}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function u7(K){if(!/^[A-Za-z0-9._/-]+$/.test(K))throw Error(`refused to shell-escape suspect token: ${K}`);return K}async function p7(K,$="--version"){if(!await y(K))return null;let X=await N([K,$],{timeoutMs:5000});if(X.exitCode!==0)return null;return((X.stdout||X.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var m1;var l=E(()=>{m1=class m1 extends Error{message;exitCode;stdout;stderr;constructor(K,$,Q,X){super(K);this.message=K;this.exitCode=$;this.stdout=Q;this.stderr=X;this.name="ShellError"}}});function d(K){return c7?"":K}var c7,A,h,w,u6,_,k,D,U;var o=E(()=>{c7=(process.env.NO_COLOR??"").length>0;A=d("\x1B[0;31m"),h=d("\x1B[0;32m"),w=d("\x1B[1;33m"),u6=d("\x1B[0;34m"),_=d("\x1B[0;36m"),k=d("\x1B[1m"),D=d("\x1B[2m"),U=d("\x1B[0m")});import{existsSync as e7}from"fs";async function Q1(){if(V1!==void 0)return V1;let K="/opt/homebrew/bin/python3.12";if(e7(K))return V1=K,K;let $=await y("python3.12");if($)return V1=$,$;let Q=await y("python3");return V1=Q,Q}async function t(K,$={}){let Q=await Q1();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return N([Q,"-c",K],$)}var V1;var W1=E(()=>{l()});var A0={};v(A0,{runStatus:()=>B5});import{existsSync as C,readFileSync as Z1,readdirSync as G0,statSync as B0}from"fs";import{resolve as S,basename as Z5}from"path";import{homedir as z5}from"os";async function U5(){if(await y("jq"))return!0;return process.stdout.write(`${A}Error: jq is required but not installed.${U}
2
+ var N7=Object.defineProperty;var k7=(K)=>K;function D7(K,$){this[K]=k7.bind(null,$)}var v=(K,$)=>{for(var Q in $)N7(K,Q,{get:$[Q],enumerable:!0,configurable:!0,set:D7.bind($,Q)})};var E=(K,$)=>()=>(K&&($=K(K=0)),$);var $1=import.meta.require;var z0={};v(z0,{lokiDir:()=>R,homeLokiDir:()=>v1,findRepoRootForVersion:()=>y1,REPO_ROOT:()=>c});import{resolve as p,dirname as b1}from"path";import{fileURLToPath as C7}from"url";import{existsSync as O1}from"fs";import{homedir as h7}from"os";function b7(){let K=Z0;for(let $=0;$<6;$++){if(O1(p(K,"VERSION"))&&O1(p(K,"autonomy/run.sh")))return K;let Q=b1(K);if(Q===K)break;K=Q}return p(Z0,"..","..","..")}function y1(K){let $=K;for(let Q=0;Q<6;Q++){if(O1(p($,"VERSION"))&&O1(p($,"autonomy/run.sh")))return $;let X=b1($);if(X===$)break;$=X}return p(K,"..","..","..")}function R(){return process.env.LOKI_DIR??p(process.cwd(),".loki")}function v1(){return p(h7(),".loki")}var Z0,c;var g=E(()=>{Z0=b1(C7(import.meta.url));c=b7()});import{readFileSync as y7}from"fs";import{resolve as v7,dirname as g7}from"path";import{fileURLToPath as m7}from"url";function T1(){if(r!==null)return r;let K="7.10.1";if(typeof K==="string"&&K.length>0)return r=K,r;try{let $=g7(m7(import.meta.url)),Q=y1($);r=y7(v7(Q,"VERSION"),"utf-8").trim()}catch{r="unknown"}return r}var r=null;var g1=E(()=>{g()});var U0={};v(U0,{runOrThrow:()=>f7,run:()=>N,commandVersion:()=>p7,commandExists:()=>y,ShellError:()=>m1});async function N(K,$={}){let Q=Bun.spawn({cmd:[...K],stdout:"pipe",stderr:"pipe",env:$.env?{...process.env,...$.env}:process.env,cwd:$.cwd}),X,Z;if($.timeoutMs&&$.timeoutMs>0)X=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}Z=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},$.timeoutMs);try{let[z,H,V]=await Promise.all([new Response(Q.stdout).text(),new Response(Q.stderr).text(),Q.exited]);return{stdout:z,stderr:H,exitCode:V}}finally{if(X)clearTimeout(X);if(Z)clearTimeout(Z)}}async function f7(K,$={}){let Q=await N(K,$);if(Q.exitCode!==0)throw new m1(`command failed (${Q.exitCode}): ${K.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function y(K){let $=u7(K),Q=await N(["sh","-c",`command -v ${$}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function u7(K){if(!/^[A-Za-z0-9._/-]+$/.test(K))throw Error(`refused to shell-escape suspect token: ${K}`);return K}async function p7(K,$="--version"){if(!await y(K))return null;let X=await N([K,$],{timeoutMs:5000});if(X.exitCode!==0)return null;return((X.stdout||X.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var m1;var l=E(()=>{m1=class m1 extends Error{message;exitCode;stdout;stderr;constructor(K,$,Q,X){super(K);this.message=K;this.exitCode=$;this.stdout=Q;this.stderr=X;this.name="ShellError"}}});function d(K){return c7?"":K}var c7,A,h,w,u6,_,k,D,U;var o=E(()=>{c7=(process.env.NO_COLOR??"").length>0;A=d("\x1B[0;31m"),h=d("\x1B[0;32m"),w=d("\x1B[1;33m"),u6=d("\x1B[0;34m"),_=d("\x1B[0;36m"),k=d("\x1B[1m"),D=d("\x1B[2m"),U=d("\x1B[0m")});import{existsSync as e7}from"fs";async function Q1(){if(V1!==void 0)return V1;let K="/opt/homebrew/bin/python3.12";if(e7(K))return V1=K,K;let $=await y("python3.12");if($)return V1=$,$;let Q=await y("python3");return V1=Q,Q}async function t(K,$={}){let Q=await Q1();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return N([Q,"-c",K],$)}var V1;var W1=E(()=>{l()});var A0={};v(A0,{runStatus:()=>B5});import{existsSync as C,readFileSync as Z1,readdirSync as G0,statSync as B0}from"fs";import{resolve as S,basename as Z5}from"path";import{homedir as z5}from"os";async function U5(){if(await y("jq"))return!0;return process.stdout.write(`${A}Error: jq is required but not installed.${U}
3
3
  `),process.stdout.write(`Install with:
4
4
  `),process.stdout.write(` brew install jq (macOS)
5
5
  `),process.stdout.write(` apt install jq (Debian/Ubuntu)
@@ -667,4 +667,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
667
667
  `),2}default:return process.stderr.write(`Unknown command: ${$}
668
668
  `),process.stderr.write(S7),2}}process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var x6=await w6(Bun.argv.slice(2));process.exit(x6);
669
669
 
670
- //# debugId=7022BA0BF583F56764756E2164756E21
670
+ //# debugId=DA55407B6698C64C64756E2164756E21
package/mcp/__init__.py CHANGED
@@ -57,4 +57,4 @@ try:
57
57
  except ImportError:
58
58
  __all__ = ['mcp']
59
59
 
60
- __version__ = '7.9.1'
60
+ __version__ = '7.10.1'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loki-mode",
3
- "version": "7.9.1",
3
+ "version": "7.10.1",
4
4
  "description": "Loki Mode by Autonomi. Autonomous spec-to-product system: takes a PRD, GitHub issue, OpenAPI/JSON/YAML, or one-line brief to a deployed app via the RARV-C closure loop with 11 quality gates. Provider-agnostic (Claude Code, OpenAI Codex, Cline, Aider).",
5
5
  "keywords": [
6
6
  "agent",