loki-mode 8.76.0 → 8.78.0
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/loki +132 -1
- package/completions/_loki +2 -1
- package/completions/loki.bash +1 -1
- package/dashboard/__init__.py +1 -1
- 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/skills/providers.md +25 -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.
|
|
6
|
+
# Loki Mode v8.78.0
|
|
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.
|
|
472
|
+
**v8.78.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
8.
|
|
1
|
+
8.78.0
|
package/autonomy/loki
CHANGED
|
@@ -1040,7 +1040,8 @@ show_help() {
|
|
|
1040
1040
|
echo " agent analyze api assets audit bench checkpoint (cp) ci cleanup"
|
|
1041
1041
|
echo " cluster cockpit code compliance completions compound config context (ctx)"
|
|
1042
1042
|
echo " cost council crash dashboard demo deploy docker docs doctor dogfood"
|
|
1043
|
-
echo " enterprise explain export failover github grill heal help
|
|
1043
|
+
echo " enterprise estimate explain export failover github grill heal help"
|
|
1044
|
+
echo " import init"
|
|
1044
1045
|
echo " issue kpis logs magic mcp memory metrics migrate modernize monitor"
|
|
1045
1046
|
echo " next notify onboard open optimize otel own (handoff) pause plan preview"
|
|
1046
1047
|
echo " projects proof (receipt) provider quick quickstart rc remote report reset"
|
|
@@ -19158,6 +19159,9 @@ main() {
|
|
|
19158
19159
|
_deprecated_alias cost "report cost" "$@"
|
|
19159
19160
|
cmd_report cost "$@"
|
|
19160
19161
|
;;
|
|
19162
|
+
estimate)
|
|
19163
|
+
cmd_estimate "$@"
|
|
19164
|
+
;;
|
|
19161
19165
|
trust)
|
|
19162
19166
|
cmd_trust "$@"
|
|
19163
19167
|
;;
|
|
@@ -25310,9 +25314,92 @@ cmd_trust_metrics() {
|
|
|
25310
25314
|
# for the current-run aggregate (single source of truth) and reads .loki/proofs/
|
|
25311
25315
|
# for persistent per-run history. Honest: prints "not recorded" when cost was
|
|
25312
25316
|
# never collected, never a fabricated $0.00.
|
|
25317
|
+
# Forward cost projection. Wraps tools/estimate-run.py.
|
|
25318
|
+
#
|
|
25319
|
+
# --iterations is REQUIRED by that tool by design: no multi-run history exists
|
|
25320
|
+
# to derive a horizon from, so projecting a total without one would be guessing
|
|
25321
|
+
# at the single number the operator asked for. We surface that requirement here
|
|
25322
|
+
# rather than inventing a default, for the same reason cost reports UNKNOWN
|
|
25323
|
+
# instead of $0.00 -- an unearned number is worse than an absent one.
|
|
25324
|
+
cmd_estimate() {
|
|
25325
|
+
local iterations=""
|
|
25326
|
+
local show_json=false
|
|
25327
|
+
|
|
25328
|
+
while [[ $# -gt 0 ]]; do
|
|
25329
|
+
case "$1" in
|
|
25330
|
+
--help|-h)
|
|
25331
|
+
echo -e "${BOLD}loki estimate${NC} - Project what a run is likely to cost"
|
|
25332
|
+
echo ""
|
|
25333
|
+
echo "Usage: loki estimate --iterations N [--json]"
|
|
25334
|
+
echo ""
|
|
25335
|
+
echo "Projects a run cost from this workspace's MEASURED history in"
|
|
25336
|
+
echo ".loki/metrics/efficiency/. With no measured history there is no"
|
|
25337
|
+
echo "basis, and it says so rather than returning a fabricated number."
|
|
25338
|
+
echo ""
|
|
25339
|
+
echo "Options:"
|
|
25340
|
+
echo " --iterations N REQUIRED. How many iterations to project."
|
|
25341
|
+
echo " No multi-run history exists to derive a horizon"
|
|
25342
|
+
echo " from, so there is no honest default."
|
|
25343
|
+
echo " --json Machine-readable JSON output"
|
|
25344
|
+
echo " --help, -h Show this help"
|
|
25345
|
+
echo ""
|
|
25346
|
+
echo "Examples:"
|
|
25347
|
+
echo " loki estimate --iterations 10"
|
|
25348
|
+
echo " loki estimate --iterations 25 --json"
|
|
25349
|
+
echo ""
|
|
25350
|
+
echo "See also: loki cost --detail (what a run ALREADY spent)"
|
|
25351
|
+
return 0
|
|
25352
|
+
;;
|
|
25353
|
+
--json) show_json=true; shift ;;
|
|
25354
|
+
--iterations) iterations="${2:-}"; shift 2 || shift ;;
|
|
25355
|
+
--iterations=*) iterations="${1#*=}"; shift ;;
|
|
25356
|
+
*) echo -e "${RED}Unknown option: $1${NC}" >&2; echo "Run 'loki estimate --help' for usage." >&2; return 1 ;;
|
|
25357
|
+
esac
|
|
25358
|
+
done
|
|
25359
|
+
|
|
25360
|
+
if [ -z "$iterations" ]; then
|
|
25361
|
+
echo -e "${RED}--iterations is required${NC}" >&2
|
|
25362
|
+
echo "" >&2
|
|
25363
|
+
echo "No multi-run history exists to derive a horizon from, so there is no" >&2
|
|
25364
|
+
echo "honest default for how many iterations to project. Say how many you" >&2
|
|
25365
|
+
echo "expect and the projection is scaled from measured per-iteration cost." >&2
|
|
25366
|
+
echo "" >&2
|
|
25367
|
+
echo " loki estimate --iterations 10" >&2
|
|
25368
|
+
echo "" >&2
|
|
25369
|
+
echo "Run 'loki estimate --help' for usage." >&2
|
|
25370
|
+
return 1
|
|
25371
|
+
fi
|
|
25372
|
+
|
|
25373
|
+
case "$iterations" in
|
|
25374
|
+
''|*[!0-9]*)
|
|
25375
|
+
echo -e "${RED}--iterations must be a positive whole number (got: $iterations)${NC}" >&2
|
|
25376
|
+
return 1
|
|
25377
|
+
;;
|
|
25378
|
+
esac
|
|
25379
|
+
|
|
25380
|
+
local estimate_py="$SKILL_DIR/tools/estimate-run.py"
|
|
25381
|
+
if ! command -v python3 >/dev/null 2>&1; then
|
|
25382
|
+
echo -e "${RED}python3 is required for 'loki estimate'${NC}" >&2
|
|
25383
|
+
echo "Install python3 and re-run." >&2
|
|
25384
|
+
return 1
|
|
25385
|
+
fi
|
|
25386
|
+
if [ ! -f "$estimate_py" ]; then
|
|
25387
|
+
echo -e "${RED}Estimate tool not found: $estimate_py${NC}" >&2
|
|
25388
|
+
echo "Your install looks incomplete. Reinstall: loki self-update" >&2
|
|
25389
|
+
return 1
|
|
25390
|
+
fi
|
|
25391
|
+
|
|
25392
|
+
# Same workspace derivation as 'loki cost --detail': the tool takes the
|
|
25393
|
+
# workspace and appends .loki itself, while LOKI_DIR is the .loki path.
|
|
25394
|
+
local est_args=("$(dirname "${LOKI_DIR:-.loki}")" "--iterations" "$iterations")
|
|
25395
|
+
[ "$show_json" = "true" ] && est_args+=("--json")
|
|
25396
|
+
python3 "$estimate_py" "${est_args[@]}"
|
|
25397
|
+
}
|
|
25398
|
+
|
|
25313
25399
|
cmd_cost() {
|
|
25314
25400
|
local show_json=false
|
|
25315
25401
|
local last_n=0
|
|
25402
|
+
local detail=false
|
|
25316
25403
|
|
|
25317
25404
|
while [[ $# -gt 0 ]]; do
|
|
25318
25405
|
case "$1" in
|
|
@@ -25328,23 +25415,67 @@ cmd_cost() {
|
|
|
25328
25415
|
echo "Options:"
|
|
25329
25416
|
echo " --json Machine-readable JSON output"
|
|
25330
25417
|
echo " --last N Show only the last N runs in history (default: all)"
|
|
25418
|
+
echo " --detail Per-iteration breakdown: cache hit ratio, cost trend,"
|
|
25419
|
+
echo " and the measured/found ratio (autonomy/lib/cost-summary.py)"
|
|
25331
25420
|
echo " --help, -h Show this help"
|
|
25332
25421
|
echo ""
|
|
25333
25422
|
echo "Examples:"
|
|
25334
25423
|
echo " loki cost # Cost summary + budget status"
|
|
25335
25424
|
echo " loki cost --json # Machine-readable output"
|
|
25336
25425
|
echo " loki cost --last 10 # Last 10 runs of history"
|
|
25426
|
+
echo " loki cost --detail # Per-iteration cache + trend breakdown"
|
|
25427
|
+
echo " loki cost --detail --json # Same, machine-readable"
|
|
25337
25428
|
echo ""
|
|
25338
25429
|
echo "Budget cap: set LOKI_BUDGET_LIMIT (USD). Warns at 80%, stops at 100%."
|
|
25430
|
+
echo ""
|
|
25431
|
+
echo "An unmeasured iteration reads UNKNOWN and is excluded from totals."
|
|
25432
|
+
echo "Unmeasured is never reported as \$0.00 -- that would be indistinguishable"
|
|
25433
|
+
echo "from a real measurement of zero."
|
|
25339
25434
|
exit 0
|
|
25340
25435
|
;;
|
|
25341
25436
|
--json) show_json=true; shift ;;
|
|
25437
|
+
--detail) detail=true; shift ;;
|
|
25342
25438
|
--last) last_n="${2:-0}"; shift 2 ;;
|
|
25343
25439
|
--last=*) last_n="${1#*=}"; shift ;;
|
|
25344
25440
|
*) echo -e "${RED}Unknown option: $1${NC}" >&2; echo "Run 'loki cost --help' for usage." >&2; exit 1 ;;
|
|
25345
25441
|
esac
|
|
25346
25442
|
done
|
|
25347
25443
|
|
|
25444
|
+
# --detail routes to the per-run summarizer, which reports what the budget
|
|
25445
|
+
# view cannot: cache hit ratio, cost trend, and the measured/found ratio.
|
|
25446
|
+
# It reuses the SAME honesty predicate (efficiency_cost.record_is_measured),
|
|
25447
|
+
# so both views agree on what counts as measured.
|
|
25448
|
+
if [ "$detail" = "true" ]; then
|
|
25449
|
+
# --last filters per-RUN history, which this view does not show (it
|
|
25450
|
+
# breaks down the iterations of ONE run). Rejecting is the honest
|
|
25451
|
+
# move: silently discarding it would make the filter look applied.
|
|
25452
|
+
if [ "$last_n" != "0" ]; then
|
|
25453
|
+
echo -e "${RED}--last is not supported with --detail${NC}" >&2
|
|
25454
|
+
echo "--detail breaks down the iterations of the current run, not per-run history." >&2
|
|
25455
|
+
echo "Use 'loki cost --last N' for the per-run history view." >&2
|
|
25456
|
+
return 1
|
|
25457
|
+
fi
|
|
25458
|
+
local cost_summary_py="$SKILL_DIR/autonomy/lib/cost-summary.py"
|
|
25459
|
+
if ! command -v python3 >/dev/null 2>&1; then
|
|
25460
|
+
echo -e "${RED}python3 is required for 'loki cost --detail'${NC}" >&2
|
|
25461
|
+
echo "Install python3, or run 'loki cost' for the budget view." >&2
|
|
25462
|
+
return 1
|
|
25463
|
+
fi
|
|
25464
|
+
if [ ! -f "$cost_summary_py" ]; then
|
|
25465
|
+
echo -e "${RED}Cost summary tool not found: $cost_summary_py${NC}" >&2
|
|
25466
|
+
echo "Your install looks incomplete. Reinstall: loki self-update" >&2
|
|
25467
|
+
return 1
|
|
25468
|
+
fi
|
|
25469
|
+
# cost-summary.py takes the WORKSPACE (it appends .loki itself), while
|
|
25470
|
+
# LOKI_DIR is the .loki path and is genuinely relocatable
|
|
25471
|
+
# (autonomy/serve.sh exports a non-default). Derive the parent so
|
|
25472
|
+
# --detail describes the same workspace the budget view does.
|
|
25473
|
+
local ws_args=("$(dirname "${LOKI_DIR:-.loki}")")
|
|
25474
|
+
[ "$show_json" = "true" ] && ws_args+=("--json")
|
|
25475
|
+
python3 "$cost_summary_py" "${ws_args[@]}"
|
|
25476
|
+
return $?
|
|
25477
|
+
fi
|
|
25478
|
+
|
|
25348
25479
|
local loki_dir="${LOKI_DIR:-.loki}"
|
|
25349
25480
|
|
|
25350
25481
|
if ! command -v python3 &>/dev/null; then
|
package/completions/_loki
CHANGED
|
@@ -179,7 +179,8 @@ function _loki_commands {
|
|
|
179
179
|
'web:Start the web dashboard'
|
|
180
180
|
'plan:Preview the build plan for a spec'
|
|
181
181
|
'report:Reporting commands (cost, kpis, share)'
|
|
182
|
-
'cost:Show cost of recent runs'
|
|
182
|
+
'cost:Show cost of recent runs (--detail for cache + trend)'
|
|
183
|
+
'estimate:Project run cost (requires --iterations N)'
|
|
183
184
|
'kpis:Key performance indicators'
|
|
184
185
|
'stats:Session statistics'
|
|
185
186
|
'preview:Open the running app preview'
|
package/completions/loki.bash
CHANGED
|
@@ -5,7 +5,7 @@ _loki_completion() {
|
|
|
5
5
|
_init_completion || return
|
|
6
6
|
|
|
7
7
|
# Main subcommands (must match autonomy/loki main case statement)
|
|
8
|
-
local main_commands="start quick monitor demo tour welcome init stop pause resume steer status next ship dashboard web serve api sandbox notify import github issue config provider reset memory compound checkpoint council dogfood projects enterprise secrets cockpit secure own handoff doctor watchdog audit metrics syslog onboard share proof receipt explain plan report cost kpis stats test ci watch telemetry agent context ctx code run export review optimize heal modernize migrate cluster worktree wt trigger failover remote deploy docker mcp magic assets analyze compliance crash open otel preview quickstart rc rollback self-update sentrux setup-skill spec state template trust trust-metrics ultracode update verify voice why wiki bench cleanup logs grill docs cp version completions help"
|
|
8
|
+
local main_commands="start quick monitor demo tour welcome init stop pause resume steer status next ship dashboard web serve api sandbox notify import github issue config provider reset memory compound checkpoint council dogfood projects enterprise secrets cockpit secure own handoff doctor watchdog audit metrics syslog onboard share proof receipt explain plan report cost estimate kpis stats test ci watch telemetry agent context ctx code run export review optimize heal modernize migrate cluster worktree wt trigger failover remote deploy docker mcp magic assets analyze compliance crash open otel preview quickstart rc rollback self-update sentrux setup-skill spec state template trust trust-metrics ultracode update verify voice why wiki bench cleanup logs grill docs cp version completions help"
|
|
9
9
|
|
|
10
10
|
# 1. If we are on the first argument (subcommand)
|
|
11
11
|
if [[ $cword -eq 1 ]]; then
|
package/dashboard/__init__.py
CHANGED
package/loki-ts/dist/loki.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var m_=Object.create;var{getPrototypeOf:u_,defineProperty:eK,getOwnPropertyNames:p_}=Object;var d_=Object.prototype.hasOwnProperty;function c_(Z){return this[Z]}var l_,i_,a_=(Z,X,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=X?l_??=new WeakMap:i_??=new WeakMap,z=J.get(Z);if(z)return z}Q=Z!=null?m_(u_(Z)):{};let K=X||!Z||!Z.__esModule?eK(Q,"default",{value:Z,enumerable:!0}):Q;for(let $ of p_(Z))if(!d_.call(K,$))eK(K,$,{get:c_.bind(Z,$),enumerable:!0});if(Y)J.set(Z,K);return K};var HQ=(Z,X)=>()=>(X||Z((X={exports:{}}).exports,X),X.exports);var s_=(Z)=>Z;function n_(Z,X){this[Z]=s_.bind(null,X)}var l0=(Z,X)=>{for(var Q in X)eK(Z,Q,{get:X[Q],enumerable:!0,configurable:!0,set:n_.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:()=>R4,findRepoRootForVersion:()=>X$,REPO_ROOT:()=>i0});import{resolve as n7,dirname as Z$}from"path";import{fileURLToPath as o_}from"url";import{existsSync as UQ}from"fs";import{homedir as r_}from"os";function t_(){let Z=RO;for(let X=0;X<6;X++){if(UQ(n7(Z,"VERSION"))&&UQ(n7(Z,"autonomy/run.sh")))return Z;let Q=Z$(Z);if(Q===Z)break;Z=Q}return n7(RO,"..","..","..")}function X$(Z){let X=Z;for(let Q=0;Q<6;Q++){if(UQ(n7(X,"VERSION"))&&UQ(n7(X,"autonomy/run.sh")))return X;let Y=Z$(X);if(Y===X)break;X=Y}return n7(Z,"..","..","..")}function j0(){return process.env.LOKI_DIR??n7(process.cwd(),".loki")}function R4(){return n7(r_(),".loki")}var RO,i0;var H8=p(()=>{RO=Z$(o_(import.meta.url));i0=t_()});import{readFileSync as e_}from"fs";import{resolve as Zf,dirname as Xf}from"path";import{fileURLToPath as Qf}from"url";function h3(){if(h5!==null)return h5;let Z="8.
|
|
2
|
+
var m_=Object.create;var{getPrototypeOf:u_,defineProperty:eK,getOwnPropertyNames:p_}=Object;var d_=Object.prototype.hasOwnProperty;function c_(Z){return this[Z]}var l_,i_,a_=(Z,X,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=X?l_??=new WeakMap:i_??=new WeakMap,z=J.get(Z);if(z)return z}Q=Z!=null?m_(u_(Z)):{};let K=X||!Z||!Z.__esModule?eK(Q,"default",{value:Z,enumerable:!0}):Q;for(let $ of p_(Z))if(!d_.call(K,$))eK(K,$,{get:c_.bind(Z,$),enumerable:!0});if(Y)J.set(Z,K);return K};var HQ=(Z,X)=>()=>(X||Z((X={exports:{}}).exports,X),X.exports);var s_=(Z)=>Z;function n_(Z,X){this[Z]=s_.bind(null,X)}var l0=(Z,X)=>{for(var Q in X)eK(Z,Q,{get:X[Q],enumerable:!0,configurable:!0,set:n_.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:()=>R4,findRepoRootForVersion:()=>X$,REPO_ROOT:()=>i0});import{resolve as n7,dirname as Z$}from"path";import{fileURLToPath as o_}from"url";import{existsSync as UQ}from"fs";import{homedir as r_}from"os";function t_(){let Z=RO;for(let X=0;X<6;X++){if(UQ(n7(Z,"VERSION"))&&UQ(n7(Z,"autonomy/run.sh")))return Z;let Q=Z$(Z);if(Q===Z)break;Z=Q}return n7(RO,"..","..","..")}function X$(Z){let X=Z;for(let Q=0;Q<6;Q++){if(UQ(n7(X,"VERSION"))&&UQ(n7(X,"autonomy/run.sh")))return X;let Y=Z$(X);if(Y===X)break;X=Y}return n7(Z,"..","..","..")}function j0(){return process.env.LOKI_DIR??n7(process.cwd(),".loki")}function R4(){return n7(r_(),".loki")}var RO,i0;var H8=p(()=>{RO=Z$(o_(import.meta.url));i0=t_()});import{readFileSync as e_}from"fs";import{resolve as Zf,dirname as Xf}from"path";import{fileURLToPath as Qf}from"url";function h3(){if(h5!==null)return h5;let Z="8.78.0";if(typeof Z==="string"&&Z.length>0)return h5=Z,h5;try{let X=Xf(Qf(import.meta.url)),Q=X$(X);h5=e_(Zf(Q,"VERSION"),"utf-8").trim()}catch{h5="unknown"}return h5}var h5=null;var BQ=p(()=>{H8()});var bO={};l0(bO,{runOrThrow:()=>jf,run:()=>E0,readStreamCapped:()=>NQ,commandVersion:()=>Tf,commandExists:()=>X9,ShellError:()=>Q$,MAX_STDOUT_BYTES:()=>yO});async function NQ(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([NQ(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 jf(Z,X={}){let Q=await E0(Z,X);if(Q.exitCode!==0)throw new Q$(`command failed (${Q.exitCode}): ${Z.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function X9(Z){let X=Mf(Z),Q=await E0(["sh","-c",`command -v ${X}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function Mf(Z){if(!/^[A-Za-z0-9._/-]+$/.test(Z))throw Error(`refused to shell-escape suspect token: ${Z}`);return Z}async function Tf(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,Q$;var x9=p(()=>{Q$=class Q$ 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 wf?"":Z}var wf,L0,F8,p0,zV0,a0,W8,Q9,v;var S6=p(()=>{wf=(process.env.NO_COLOR??"").length>0;L0=o7("\x1B[0;31m"),F8=o7("\x1B[0;32m"),p0=o7("\x1B[1;33m"),zV0=o7("\x1B[0;34m"),a0=o7("\x1B[0;36m"),W8=o7("\x1B[1m"),Q9=o7("\x1B[2m"),v=o7("\x1B[0m")});import{existsSync as bf}from"fs";async function E7(){if(x4!==void 0)return x4;let Z="/opt/homebrew/bin/python3.12";if(bf(Z))return x4=Z,Z;let X=await X9("python3.12");if(X)return x4=X,X;let Q=await X9("python3");return x4=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 x4;var r7=p(()=>{x9()});var ZL={};l0(ZL,{runStatus:()=>Kh});import{existsSync as Y9,readFileSync as g3,readdirSync as iO,statSync as aO}from"fs";import{resolve as h8,basename as rf}from"path";import{homedir as tf}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*LQ/X);if(J>LQ)J=LQ;let z=LQ-J,K=F8;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` ${W8}${Q}${v} ${K}[${$}]${v} ${Y}% (${W} / ${V})`}async function Zh(){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)
|
|
@@ -1232,4 +1232,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
|
|
|
1232
1232
|
`),2}case"start":{let{runStart:Y}=await Promise.resolve().then(() => (h_(),f_));return Y(Q)}default:return process.stderr.write(`Unknown command: ${X}
|
|
1233
1233
|
`),process.stderr.write(v_),2}}cO();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var uW0=await mW0(Bun.argv.slice(2));process.exit(uW0);
|
|
1234
1234
|
|
|
1235
|
-
//# debugId=
|
|
1235
|
+
//# debugId=EB92D509ECECF70F64756E2164756E21
|
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.
|
|
4
|
+
"version": "8.78.0",
|
|
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.
|
|
5
|
+
"version": "8.78.0",
|
|
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",
|
package/skills/providers.md
CHANGED
|
@@ -22,15 +22,39 @@ Loki Mode supports four AI providers for autonomous execution.
|
|
|
22
22
|
|
|
23
23
|
## Provider Selection
|
|
24
24
|
|
|
25
|
+
**You do not have to choose one.** Since v8.64.0, leaving `LOKI_PROVIDER`
|
|
26
|
+
unset auto-detects the first installed provider in this priority order:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
claude > cline > codex > aider > opencode
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
[loki] provider: codex (auto-detected)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The order lives in `auto_detect_provider()` (`providers/loader.sh`), which is
|
|
37
|
+
the single authority. Any other list that names providers must agree with it --
|
|
38
|
+
a second list that had drifted was blocking opencode-only machines from
|
|
39
|
+
starting a build at all until v8.76.0.
|
|
40
|
+
|
|
41
|
+
Set it explicitly only when you want a provider other than the highest-priority
|
|
42
|
+
installed one. An explicit choice always wins, and is never silently
|
|
43
|
+
substituted: naming a provider that is not installed fails immediately with its
|
|
44
|
+
install command rather than quietly running a different model (v8.66.0).
|
|
45
|
+
|
|
25
46
|
```bash
|
|
26
47
|
# Via environment variable
|
|
27
|
-
export LOKI_PROVIDER=claude # or codex,
|
|
48
|
+
export LOKI_PROVIDER=claude # or cline, codex, aider, opencode
|
|
28
49
|
|
|
29
50
|
# Via CLI flag
|
|
30
51
|
./autonomy/run.sh --provider codex ./prd.md
|
|
31
52
|
loki start --provider cline ./prd.md
|
|
32
53
|
```
|
|
33
54
|
|
|
55
|
+
`loki doctor` prints which providers are installed and which one would be
|
|
56
|
+
auto-selected.
|
|
57
|
+
|
|
34
58
|
## Any Model, Any Provider (ANTHROPIC_BASE_URL)
|
|
35
59
|
|
|
36
60
|
Independent of the four CLI providers below. Loki speaks the Anthropic Messages
|