loki-mode 8.16.0 → 8.16.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.
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/lib/trust_metrics.py +11 -5
- package/dashboard/__init__.py +1 -1
- package/dashboard/server.py +43 -5
- package/loki-ts/dist/loki.js +2 -2
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
package/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: loki-mode
|
|
|
3
3
|
description: Autonomous spec-driven build system with a built-in trust layer. It does not call work done until it is verified (RARV-C closure loop, 8 quality gates, completion council, verified-completion evidence gate). Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product with minimal human intervention. Provider-agnostic. Requires --dangerously-skip-permissions flag.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Loki Mode v8.16.
|
|
6
|
+
# Loki Mode v8.16.2
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -469,4 +469,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
469
469
|
|
|
470
470
|
---
|
|
471
471
|
|
|
472
|
-
**v8.16.
|
|
472
|
+
**v8.16.2 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
8.16.
|
|
1
|
+
8.16.2
|
|
@@ -376,11 +376,17 @@ def _proof_cost(proof):
|
|
|
376
376
|
usd = None
|
|
377
377
|
tokens = cost.get("total_tokens")
|
|
378
378
|
if tokens is None:
|
|
379
|
-
# Some proofs carry
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
379
|
+
# Some proofs carry the components separately. Sum ALL of them,
|
|
380
|
+
# including the cache tiers: the proof generator records
|
|
381
|
+
# cache_read_tokens, and on real traffic they are ~98% of input volume.
|
|
382
|
+
# Adding only input+output reported 16,436 tokens for a proof whose own
|
|
383
|
+
# record totals 893,701 -- a 54x undercount feeding cost-per-verified,
|
|
384
|
+
# which is a published benchmark number.
|
|
385
|
+
parts = [cost.get(k) for k in
|
|
386
|
+
("input_tokens", "output_tokens",
|
|
387
|
+
"cache_read_tokens", "cache_creation_tokens")]
|
|
388
|
+
if any(v is not None for v in parts):
|
|
389
|
+
tokens = sum(_to_int(v, 0) for v in parts)
|
|
384
390
|
try:
|
|
385
391
|
tokens = int(tokens) if tokens is not None else None
|
|
386
392
|
except (TypeError, ValueError):
|
package/dashboard/__init__.py
CHANGED
package/dashboard/server.py
CHANGED
|
@@ -7338,13 +7338,33 @@ def _get_model_pricing() -> dict:
|
|
|
7338
7338
|
return _MODEL_PRICING
|
|
7339
7339
|
|
|
7340
7340
|
|
|
7341
|
-
def _calculate_model_cost(
|
|
7342
|
-
|
|
7341
|
+
def _calculate_model_cost(
|
|
7342
|
+
model: str,
|
|
7343
|
+
input_tokens: int,
|
|
7344
|
+
output_tokens: int,
|
|
7345
|
+
cache_read_tokens: int = 0,
|
|
7346
|
+
cache_creation_tokens: int = 0,
|
|
7347
|
+
) -> float:
|
|
7348
|
+
"""Calculate USD cost for a model's token usage, including cache tiers.
|
|
7349
|
+
|
|
7350
|
+
Cache tokens DOMINATE real traffic -- a measured iteration carried 797,496
|
|
7351
|
+
cache-read against 10,272 plain input tokens. Pricing them at zero, which
|
|
7352
|
+
this did, under-counted a real iteration by roughly 5x. This is the third
|
|
7353
|
+
route to carry that same bug (bash check_budget_limit and the TS budget
|
|
7354
|
+
breaker were fixed in v8.12); the rates match both.
|
|
7355
|
+
|
|
7356
|
+
An unpriced cache tier falls back to the FULL input rate rather than zero:
|
|
7357
|
+
for anything driving a spend display the safe direction on an unknown rate
|
|
7358
|
+
is to over-state, never to silently under-count.
|
|
7359
|
+
"""
|
|
7343
7360
|
pricing_table = _get_model_pricing()
|
|
7344
7361
|
pricing = pricing_table.get(model.lower(), pricing_table.get("sonnet", {}))
|
|
7345
|
-
|
|
7362
|
+
inp_rate = pricing.get("input", 3.00)
|
|
7363
|
+
input_cost = (input_tokens / 1_000_000) * inp_rate
|
|
7346
7364
|
output_cost = (output_tokens / 1_000_000) * pricing.get("output", 15.00)
|
|
7347
|
-
|
|
7365
|
+
cache_read_cost = (cache_read_tokens / 1_000_000) * pricing.get("cache_read", inp_rate * 0.1)
|
|
7366
|
+
cache_write_cost = (cache_creation_tokens / 1_000_000) * pricing.get("cache_write", inp_rate * 1.25)
|
|
7367
|
+
return round(input_cost + output_cost + cache_read_cost + cache_write_cost, 6)
|
|
7348
7368
|
|
|
7349
7369
|
|
|
7350
7370
|
@app.get("/api/cost", dependencies=[Depends(auth.require_scope("read"))])
|
|
@@ -7365,6 +7385,8 @@ def _compute_cost_snapshot() -> dict:
|
|
|
7365
7385
|
|
|
7366
7386
|
total_input = 0
|
|
7367
7387
|
total_output = 0
|
|
7388
|
+
total_cache_read = 0
|
|
7389
|
+
total_cache_creation = 0
|
|
7368
7390
|
estimated_cost = 0.0
|
|
7369
7391
|
by_phase: dict = {}
|
|
7370
7392
|
by_model: dict = {}
|
|
@@ -7390,15 +7412,22 @@ def _compute_cost_snapshot() -> dict:
|
|
|
7390
7412
|
|
|
7391
7413
|
inp = data.get("input_tokens", 0)
|
|
7392
7414
|
out = data.get("output_tokens", 0)
|
|
7415
|
+
# Cache tiers: recorded per iteration since v6.82.0 and
|
|
7416
|
+
# typically ~98% of input volume. Omitting them made this
|
|
7417
|
+
# endpoint report roughly 1% of a run's real token count.
|
|
7418
|
+
cr = data.get("cache_read_tokens", 0) or 0
|
|
7419
|
+
cw = data.get("cache_creation_tokens", 0) or 0
|
|
7393
7420
|
model = data.get("model", "sonnet").lower()
|
|
7394
7421
|
phase = data.get("phase", "unknown")
|
|
7395
7422
|
|
|
7396
7423
|
total_input += inp
|
|
7397
7424
|
total_output += out
|
|
7425
|
+
total_cache_read += cr
|
|
7426
|
+
total_cache_creation += cw
|
|
7398
7427
|
|
|
7399
7428
|
cost = data.get("cost_usd")
|
|
7400
7429
|
if cost is None:
|
|
7401
|
-
cost = _calculate_model_cost(model, inp, out)
|
|
7430
|
+
cost = _calculate_model_cost(model, inp, out, cr, cw)
|
|
7402
7431
|
estimated_cost += cost
|
|
7403
7432
|
|
|
7404
7433
|
# Aggregate by phase
|
|
@@ -7464,9 +7493,18 @@ def _compute_cost_snapshot() -> dict:
|
|
|
7464
7493
|
except (json.JSONDecodeError, KeyError):
|
|
7465
7494
|
pass
|
|
7466
7495
|
|
|
7496
|
+
# Cache hit ratio against everything read IN. Null (not 0.0) when nothing
|
|
7497
|
+
# was read: a zero is a claim about a COLD cache, which is a real and
|
|
7498
|
+
# expensive condition, so reporting it for a run with no data would send
|
|
7499
|
+
# someone hunting a caching problem that does not exist.
|
|
7500
|
+
_read_in = total_input + total_cache_read
|
|
7467
7501
|
return {
|
|
7468
7502
|
"total_input_tokens": total_input,
|
|
7469
7503
|
"total_output_tokens": total_output,
|
|
7504
|
+
"total_cache_read_tokens": total_cache_read,
|
|
7505
|
+
"total_cache_creation_tokens": total_cache_creation,
|
|
7506
|
+
"total_tokens": total_input + total_output + total_cache_read + total_cache_creation,
|
|
7507
|
+
"cache_hit_ratio": round(total_cache_read / _read_in, 4) if _read_in > 0 else None,
|
|
7470
7508
|
"estimated_cost_usd": round(estimated_cost, 6),
|
|
7471
7509
|
"by_phase": {k: {
|
|
7472
7510
|
"input_tokens": v["input_tokens"],
|
package/loki-ts/dist/loki.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var h_=Object.create;var{getPrototypeOf:v_,defineProperty:rK,getOwnPropertyNames:g_}=Object;var m_=Object.prototype.hasOwnProperty;function u_(Z){return this[Z]}var p_,d_,c_=(Z,X,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=X?p_??=new WeakMap:d_??=new WeakMap,z=J.get(Z);if(z)return z}Q=Z!=null?h_(v_(Z)):{};let K=X||!Z||!Z.__esModule?rK(Q,"default",{value:Z,enumerable:!0}):Q;for(let $ of g_(Z))if(!m_.call(K,$))rK(K,$,{get:u_.bind(Z,$),enumerable:!0});if(Y)J.set(Z,K);return K};var qQ=(Z,X)=>()=>(X||Z((X={exports:{}}).exports,X),X.exports);var l_=(Z)=>Z;function i_(Z,X){this[Z]=l_.bind(null,X)}var l0=(Z,X)=>{for(var Q in X)rK(Z,Q,{get:X[Q],enumerable:!0,configurable:!0,set:i_.bind(X,Q)})};var p=(Z,X)=>()=>(Z&&(X=Z(Z=0)),X);var e0=import.meta.require;var kO={};l0(kO,{lokiDir:()=>j0,homeLokiDir:()=>P4,findRepoRootForVersion:()=>eK,REPO_ROOT:()=>r0});import{resolve as n7,dirname as tK}from"path";import{fileURLToPath as a_}from"url";import{existsSync as GQ}from"fs";import{homedir as s_}from"os";function n_(){let Z=RO;for(let X=0;X<6;X++){if(GQ(n7(Z,"VERSION"))&&GQ(n7(Z,"autonomy/run.sh")))return Z;let Q=tK(Z);if(Q===Z)break;Z=Q}return n7(RO,"..","..","..")}function eK(Z){let X=Z;for(let Q=0;Q<6;Q++){if(GQ(n7(X,"VERSION"))&&GQ(n7(X,"autonomy/run.sh")))return X;let Y=tK(X);if(Y===X)break;X=Y}return n7(Z,"..","..","..")}function j0(){return process.env.LOKI_DIR??n7(process.cwd(),".loki")}function P4(){return n7(s_(),".loki")}var RO,r0;var G8=p(()=>{RO=tK(a_(import.meta.url));r0=n_()});import{readFileSync as o_}from"fs";import{resolve as r_,dirname as t_}from"path";import{fileURLToPath as e_}from"url";function f3(){if(h5!==null)return h5;let Z="8.16.
|
|
2
|
+
var h_=Object.create;var{getPrototypeOf:v_,defineProperty:rK,getOwnPropertyNames:g_}=Object;var m_=Object.prototype.hasOwnProperty;function u_(Z){return this[Z]}var p_,d_,c_=(Z,X,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=X?p_??=new WeakMap:d_??=new WeakMap,z=J.get(Z);if(z)return z}Q=Z!=null?h_(v_(Z)):{};let K=X||!Z||!Z.__esModule?rK(Q,"default",{value:Z,enumerable:!0}):Q;for(let $ of g_(Z))if(!m_.call(K,$))rK(K,$,{get:u_.bind(Z,$),enumerable:!0});if(Y)J.set(Z,K);return K};var qQ=(Z,X)=>()=>(X||Z((X={exports:{}}).exports,X),X.exports);var l_=(Z)=>Z;function i_(Z,X){this[Z]=l_.bind(null,X)}var l0=(Z,X)=>{for(var Q in X)rK(Z,Q,{get:X[Q],enumerable:!0,configurable:!0,set:i_.bind(X,Q)})};var p=(Z,X)=>()=>(Z&&(X=Z(Z=0)),X);var e0=import.meta.require;var kO={};l0(kO,{lokiDir:()=>j0,homeLokiDir:()=>P4,findRepoRootForVersion:()=>eK,REPO_ROOT:()=>r0});import{resolve as n7,dirname as tK}from"path";import{fileURLToPath as a_}from"url";import{existsSync as GQ}from"fs";import{homedir as s_}from"os";function n_(){let Z=RO;for(let X=0;X<6;X++){if(GQ(n7(Z,"VERSION"))&&GQ(n7(Z,"autonomy/run.sh")))return Z;let Q=tK(Z);if(Q===Z)break;Z=Q}return n7(RO,"..","..","..")}function eK(Z){let X=Z;for(let Q=0;Q<6;Q++){if(GQ(n7(X,"VERSION"))&&GQ(n7(X,"autonomy/run.sh")))return X;let Y=tK(X);if(Y===X)break;X=Y}return n7(Z,"..","..","..")}function j0(){return process.env.LOKI_DIR??n7(process.cwd(),".loki")}function P4(){return n7(s_(),".loki")}var RO,r0;var G8=p(()=>{RO=tK(a_(import.meta.url));r0=n_()});import{readFileSync as o_}from"fs";import{resolve as r_,dirname as t_}from"path";import{fileURLToPath as e_}from"url";function f3(){if(h5!==null)return h5;let Z="8.16.2";if(typeof Z==="string"&&Z.length>0)return h5=Z,h5;try{let X=t_(e_(import.meta.url)),Q=eK(X);h5=o_(r_(Q,"VERSION"),"utf-8").trim()}catch{h5="unknown"}return h5}var h5=null;var HQ=p(()=>{G8()});var bO={};l0(bO,{runOrThrow:()=>Of,run:()=>E0,readStreamCapped:()=>UQ,commandVersion:()=>Af,commandExists:()=>X9,ShellError:()=>Z$,MAX_STDOUT_BYTES:()=>yO});async function UQ(Z,X=yO){let Q=Z.getReader(),Y=new TextDecoder,J="",z=0;try{while(z<X){let{done:K,value:$}=await Q.read();if(K)break;if(!$)continue;if(z+=$.byteLength,z>X){let W=$.byteLength-(z-X);J+=Y.decode($.subarray(0,W),{stream:!0});break}J+=Y.decode($,{stream:!0})}J+=Y.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return J}async function E0(Z,X={}){let Q=Bun.spawn({cmd:[...Z],stdout:"pipe",stderr:"pipe",env:X.env?{...process.env,...X.env}:process.env,cwd:X.cwd}),Y,J;if(X.timeoutMs&&X.timeoutMs>0)Y=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}J=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},X.timeoutMs);try{let[z,K,$]=await Promise.all([UQ(Q.stdout),new Response(Q.stderr).text(),Q.exited]);return{stdout:z,stderr:K,exitCode:$}}finally{if(Y)clearTimeout(Y);if(J)clearTimeout(J)}}async function Of(Z,X={}){let Q=await E0(Z,X);if(Q.exitCode!==0)throw new Z$(`command failed (${Q.exitCode}): ${Z.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function X9(Z){let X=Lf(Z),Q=await E0(["sh","-c",`command -v ${X}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function Lf(Z){if(!/^[A-Za-z0-9._/-]+$/.test(Z))throw Error(`refused to shell-escape suspect token: ${Z}`);return Z}async function Af(Z,X="--version"){if(!await X9(Z))return null;let Y=await E0([Z,X],{timeoutMs:5000});if(Y.exitCode!==0)return null;return((Y.stdout||Y.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var yO=16777216,Z$;var x9=p(()=>{Z$=class Z$ extends Error{message;exitCode;stdout;stderr;constructor(Z,X,Q,Y){super(Z);this.message=Z;this.exitCode=X;this.stdout=Q;this.stderr=Y;this.name="ShellError"}}});function o7(Z){return jf?"":Z}var jf,L0,k8,p0,ZV0,i0,H8,Q9,v;var S6=p(()=>{jf=(process.env.NO_COLOR??"").length>0;L0=o7("\x1B[0;31m"),k8=o7("\x1B[0;32m"),p0=o7("\x1B[1;33m"),ZV0=o7("\x1B[0;34m"),i0=o7("\x1B[0;36m"),H8=o7("\x1B[1m"),Q9=o7("\x1B[2m"),v=o7("\x1B[0m")});import{existsSync as xf}from"fs";async function E7(){if(k4!==void 0)return k4;let Z="/opt/homebrew/bin/python3.12";if(xf(Z))return k4=Z,Z;let X=await X9("python3.12");if(X)return k4=X,X;let Q=await X9("python3");return k4=Q,Q}async function Y7(Z,X={}){let Q=await E7();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return E0([Q,"-c",Z],X)}var k4;var r7=p(()=>{x9()});var ZL={};l0(ZL,{runStatus:()=>Yh});import{existsSync as Y9,readFileSync as v3,readdirSync as iO,statSync as aO}from"fs";import{resolve as h8,basename as sf}from"path";import{homedir as nf}from"os";function sO(Z){let X=Math.trunc(Z);if(X>=1e6)return`${(Math.trunc(X/1e6*10)/10).toFixed(1)}M`;if(X>=1000)return`${(Math.trunc(X/1000*10)/10).toFixed(1)}K`;return String(X)}function nO(Z,X,Q){if(X===0)return null;let Y=Math.trunc(Z*100/X),J=Math.trunc(Z*NQ/X);if(J>NQ)J=NQ;let z=NQ-J,K=k8;if(Y>=80)K=L0;else if(Y>=50)K=p0;let $="=".repeat(Math.max(0,J))+" ".repeat(Math.max(0,z)),W=sO(Z),V=sO(X);return` ${H8}${Q}${v} ${K}[${$}]${v} ${Y}% (${W} / ${V})`}async function rf(){if(await X9("jq"))return!0;return process.stdout.write(`${L0}Error: jq is required but not installed.${v}
|
|
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)
|
|
@@ -1222,4 +1222,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
|
|
|
1222
1222
|
`),2}case"start":{let{runStart:Y}=await Promise.resolve().then(() => (b_(),y_));return Y(Q)}default:return process.stderr.write(`Unknown command: ${X}
|
|
1223
1223
|
`),process.stderr.write(__),2}}cO();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var fW0=await _W0(Bun.argv.slice(2));process.exit(fW0);
|
|
1224
1224
|
|
|
1225
|
-
//# debugId=
|
|
1225
|
+
//# debugId=F9BF1A9706826A5864756E2164756E21
|
package/mcp/__init__.py
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "loki-mode",
|
|
3
3
|
"mcpName": "io.github.asklokesh/loki-mode",
|
|
4
|
-
"version": "8.16.
|
|
4
|
+
"version": "8.16.2",
|
|
5
5
|
"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 8 quality gates. Provider-agnostic (Claude Code, OpenAI Codex, Cline, Aider).",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"agent",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
3
|
"name": "loki-mode",
|
|
4
4
|
"displayName": "Loki Mode",
|
|
5
|
-
"version": "8.16.
|
|
5
|
+
"version": "8.16.2",
|
|
6
6
|
"description": "Autonomous spec-to-product build system with a built-in trust layer (RARV-C closure loop, 8 quality gates, completion council). Ships Loki's spec-hardening, drift-detection, and deterministic PR verification commands plus the Loki MCP server.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Autonomi",
|