loki-mode 7.7.6 → 7.7.7
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 +8 -3
- package/autonomy/run.sh +70 -18
- package/dashboard/__init__.py +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/loki-ts/dist/loki.js +2 -2
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
package/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: loki-mode
|
|
|
3
3
|
description: Multi-agent autonomous startup system. Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product with minimal human intervention. Requires --dangerously-skip-permissions flag.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Loki Mode v7.7.
|
|
6
|
+
# Loki Mode v7.7.7
|
|
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.7.
|
|
384
|
+
**v7.7.7 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
7.7.
|
|
1
|
+
7.7.7
|
package/autonomy/loki
CHANGED
|
@@ -14259,20 +14259,25 @@ except Exception as e:
|
|
|
14259
14259
|
# .loki/metrics/efficiency/iter-*.json. Unify: prefer the
|
|
14260
14260
|
# canonical kpis source; fall back to the legacy file for
|
|
14261
14261
|
# backward compat with pre-v7.6.6 sessions.
|
|
14262
|
+
# v7.7.7 fix: also check iteration-*.json (the canonical filename)
|
|
14263
|
+
# in addition to iter-*.json. Use a portable glob check (no compgen)
|
|
14264
|
+
# so the function works in any POSIX shell, not just bash.
|
|
14262
14265
|
local _eff_dir=".loki/metrics/efficiency"
|
|
14263
14266
|
local _legacy_file=".loki/memory/token_economics.json"
|
|
14264
14267
|
local _have_iters=0
|
|
14265
14268
|
if [ -d "$_eff_dir" ]; then
|
|
14266
|
-
if
|
|
14269
|
+
if ls "$_eff_dir"/iteration-*.json >/dev/null 2>&1 || ls "$_eff_dir"/iter-*.json >/dev/null 2>&1; then
|
|
14267
14270
|
_have_iters=1
|
|
14268
14271
|
fi
|
|
14269
14272
|
fi
|
|
14270
14273
|
if [ "$_have_iters" -eq 1 ]; then
|
|
14271
14274
|
PYTHONPATH="${SKILL_DIR}${PYTHONPATH:+:$PYTHONPATH}" python3 - <<'PYEOF' 2>/dev/null
|
|
14272
14275
|
import json, glob, os, sys
|
|
14273
|
-
|
|
14276
|
+
# v7.7.7 fix: canonical filename is `iteration-N.json`, NOT `iter-N.json`.
|
|
14277
|
+
# We glob both for compat with any older runs.
|
|
14278
|
+
files = sorted(set(glob.glob('.loki/metrics/efficiency/iteration-*.json') + glob.glob('.loki/metrics/efficiency/iter-*.json')))
|
|
14274
14279
|
totals = {
|
|
14275
|
-
'source': '.loki/metrics/efficiency/
|
|
14280
|
+
'source': '.loki/metrics/efficiency/iteration-*.json',
|
|
14276
14281
|
'iterations': len(files),
|
|
14277
14282
|
'total_input_tokens': 0,
|
|
14278
14283
|
'total_output_tokens': 0,
|
package/autonomy/run.sh
CHANGED
|
@@ -8826,35 +8826,87 @@ auto_capture_episode() {
|
|
|
8826
8826
|
# rolled the new files into HEAD. Now diff against the iteration-start
|
|
8827
8827
|
# SHA captured at the top of the retry loop. Falls back to HEAD~1 if the
|
|
8828
8828
|
# start SHA env is unset (older direct callers).
|
|
8829
|
+
# v7.7.7 fix: previously only captured files when target_dir was a git
|
|
8830
|
+
# repo. Real-user test on /tmp/loki-validate (no git init) produced
|
|
8831
|
+
# `files_modified: []` because git rev-parse failed silently and the
|
|
8832
|
+
# fallback also required git. Now: detect git-vs-non-git up front, and
|
|
8833
|
+
# for non-git dirs use a `find` snapshot diff against the timestamp
|
|
8834
|
+
# captured when loki created .loki/ (initialized_at). Skips standard
|
|
8835
|
+
# noise dirs (.loki, node_modules, .git, venv, .venv, dist, build).
|
|
8829
8836
|
local files_modified=""
|
|
8830
8837
|
local _diff_base="${_LOKI_ITER_START_SHA:-}"
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
|
|
8834
|
-
|
|
8835
|
-
|
|
8836
|
-
|
|
8837
|
-
|
|
8838
|
-
|
|
8839
|
-
if [ -n "$
|
|
8840
|
-
files_modified
|
|
8838
|
+
local _is_git=0
|
|
8839
|
+
if (cd "$target_dir" && git rev-parse --is-inside-work-tree >/dev/null 2>&1); then
|
|
8840
|
+
_is_git=1
|
|
8841
|
+
fi
|
|
8842
|
+
if [ "$_is_git" -eq 1 ]; then
|
|
8843
|
+
if [ -z "$_diff_base" ]; then
|
|
8844
|
+
_diff_base=$(cd "$target_dir" && git rev-parse HEAD~1 2>/dev/null || echo "")
|
|
8845
|
+
fi
|
|
8846
|
+
if [ -n "$_diff_base" ]; then
|
|
8847
|
+
files_modified=$(cd "$target_dir" && git diff --name-only "$_diff_base" HEAD 2>/dev/null | head -50 | tr '\n' '|' || true)
|
|
8848
|
+
# Also include unstaged changes (in case auto-commit didn't run)
|
|
8849
|
+
local _unstaged
|
|
8850
|
+
_unstaged=$(cd "$target_dir" && git diff --name-only HEAD 2>/dev/null | head -20 | tr '\n' '|' || true)
|
|
8851
|
+
if [ -n "$_unstaged" ]; then
|
|
8852
|
+
files_modified="${files_modified}${_unstaged}"
|
|
8853
|
+
fi
|
|
8854
|
+
else
|
|
8855
|
+
# Git repo but no prior commit (e.g. fresh init) -- list untracked.
|
|
8856
|
+
files_modified=$(cd "$target_dir" && git ls-files --others --exclude-standard 2>/dev/null | head -50 | tr '\n' '|' || true)
|
|
8841
8857
|
fi
|
|
8842
8858
|
else
|
|
8843
|
-
#
|
|
8844
|
-
|
|
8859
|
+
# NOT a git repo: snapshot diff via find. Use .loki/ mtime as the
|
|
8860
|
+
# iteration-start reference (loki creates .loki/ on session start).
|
|
8861
|
+
# `-newer` on directory mtime gives a rough but useful set of files
|
|
8862
|
+
# modified DURING this session. Skip noise dirs.
|
|
8863
|
+
local _ref_file="${target_dir}/.loki/state/orchestrator.json"
|
|
8864
|
+
if [ ! -f "$_ref_file" ]; then
|
|
8865
|
+
_ref_file="${target_dir}/.loki"
|
|
8866
|
+
fi
|
|
8867
|
+
if [ -e "$_ref_file" ]; then
|
|
8868
|
+
files_modified=$(cd "$target_dir" && find . -type f -newer "$_ref_file" \
|
|
8869
|
+
-not -path './.loki/*' \
|
|
8870
|
+
-not -path './node_modules/*' \
|
|
8871
|
+
-not -path './.git/*' \
|
|
8872
|
+
-not -path './venv/*' \
|
|
8873
|
+
-not -path './.venv/*' \
|
|
8874
|
+
-not -path './dist/*' \
|
|
8875
|
+
-not -path './build/*' \
|
|
8876
|
+
2>/dev/null | head -50 | sed 's|^\./||' | tr '\n' '|' || true)
|
|
8877
|
+
fi
|
|
8878
|
+
# Belt-and-suspenders: if find returned nothing, fall back to a
|
|
8879
|
+
# plain listing of non-noise files (every visible file, capped at 50).
|
|
8880
|
+
if [ -z "$files_modified" ]; then
|
|
8881
|
+
files_modified=$(cd "$target_dir" && find . -maxdepth 3 -type f \
|
|
8882
|
+
-not -path './.loki/*' \
|
|
8883
|
+
-not -path './node_modules/*' \
|
|
8884
|
+
-not -path './.git/*' \
|
|
8885
|
+
2>/dev/null | head -50 | sed 's|^\./||' | tr '\n' '|' || true)
|
|
8886
|
+
fi
|
|
8845
8887
|
fi
|
|
8846
8888
|
|
|
8847
8889
|
# Collect last git commit if any
|
|
8848
8890
|
local git_commit=""
|
|
8849
8891
|
git_commit=$(cd "$target_dir" && git rev-parse --short HEAD 2>/dev/null || true)
|
|
8850
8892
|
|
|
8851
|
-
# v7.6.4 B-3a fix
|
|
8852
|
-
#
|
|
8853
|
-
#
|
|
8854
|
-
#
|
|
8855
|
-
|
|
8893
|
+
# v7.6.4 B-3a fix + v7.7.7 filename fix: the actual filename is
|
|
8894
|
+
# `iteration-N.json` (not `iter-N.json` as v7.6.4 erroneously assumed).
|
|
8895
|
+
# Real-user test on /tmp/loki-validate showed `iteration-1.json` in
|
|
8896
|
+
# .loki/metrics/efficiency/. We now check both the canonical name and
|
|
8897
|
+
# the legacy `iter-N.json` for backward compat with any older runs.
|
|
8898
|
+
local _iter_metrics_file=""
|
|
8899
|
+
for _candidate in \
|
|
8900
|
+
"$target_dir/.loki/metrics/efficiency/iteration-${iteration}.json" \
|
|
8901
|
+
"$target_dir/.loki/metrics/efficiency/iter-${iteration}.json" \
|
|
8902
|
+
; do
|
|
8903
|
+
if [ -f "$_candidate" ]; then
|
|
8904
|
+
_iter_metrics_file="$_candidate"
|
|
8905
|
+
break
|
|
8906
|
+
fi
|
|
8907
|
+
done
|
|
8856
8908
|
local _iter_tokens_in=0 _iter_tokens_out=0 _iter_cost=0
|
|
8857
|
-
if [ -
|
|
8909
|
+
if [ -n "$_iter_metrics_file" ]; then
|
|
8858
8910
|
_iter_tokens_in=$(python3 -c "import json; d=json.load(open('$_iter_metrics_file')); print(int(d.get('input_tokens', 0) or 0))" 2>/dev/null || echo 0)
|
|
8859
8911
|
_iter_tokens_out=$(python3 -c "import json; d=json.load(open('$_iter_metrics_file')); print(int(d.get('output_tokens', 0) or 0))" 2>/dev/null || echo 0)
|
|
8860
8912
|
_iter_cost=$(python3 -c "import json; d=json.load(open('$_iter_metrics_file')); print(float(d.get('cost_usd', 0) or 0))" 2>/dev/null || echo 0)
|
package/dashboard/__init__.py
CHANGED
package/docs/INSTALLATION.md
CHANGED
package/loki-ts/dist/loki.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var _7=Object.defineProperty;var I7=(K)=>K;function P7(K,$){this[K]=I7.bind(null,$)}var b=(K,$)=>{for(var z in $)_7(K,z,{get:$[z],enumerable:!0,configurable:!0,set:P7.bind($,z)})};var R=(K,$)=>()=>(K&&($=K(K=0)),$);var V1=import.meta.require;var e1={};b(e1,{lokiDir:()=>P,homeLokiDir:()=>k1,findRepoRootForVersion:()=>N1,REPO_ROOT:()=>p});import{resolve as u,dirname as S1}from"path";import{fileURLToPath as L7}from"url";import{existsSync as J1}from"fs";import{homedir as R7}from"os";function E7(){let K=i1;for(let $=0;$<6;$++){if(J1(u(K,"VERSION"))&&J1(u(K,"autonomy/run.sh")))return K;let z=S1(K);if(z===K)break;K=z}return u(i1,"..","..","..")}function N1(K){let $=K;for(let z=0;z<6;z++){if(J1(u($,"VERSION"))&&J1(u($,"autonomy/run.sh")))return $;let Q=S1($);if(Q===$)break;$=Q}return u(K,"..","..","..")}function P(){return process.env.LOKI_DIR??u(process.cwd(),".loki")}function k1(){return u(R7(),".loki")}var i1,p;var y=R(()=>{i1=S1(L7(import.meta.url));p=E7()});import{readFileSync as x7}from"fs";import{resolve as F7,dirname as w7}from"path";import{fileURLToPath as S7}from"url";function G1(){if(n!==null)return n;let K="7.7.
|
|
2
|
+
var _7=Object.defineProperty;var I7=(K)=>K;function P7(K,$){this[K]=I7.bind(null,$)}var b=(K,$)=>{for(var z in $)_7(K,z,{get:$[z],enumerable:!0,configurable:!0,set:P7.bind($,z)})};var R=(K,$)=>()=>(K&&($=K(K=0)),$);var V1=import.meta.require;var e1={};b(e1,{lokiDir:()=>P,homeLokiDir:()=>k1,findRepoRootForVersion:()=>N1,REPO_ROOT:()=>p});import{resolve as u,dirname as S1}from"path";import{fileURLToPath as L7}from"url";import{existsSync as J1}from"fs";import{homedir as R7}from"os";function E7(){let K=i1;for(let $=0;$<6;$++){if(J1(u(K,"VERSION"))&&J1(u(K,"autonomy/run.sh")))return K;let z=S1(K);if(z===K)break;K=z}return u(i1,"..","..","..")}function N1(K){let $=K;for(let z=0;z<6;z++){if(J1(u($,"VERSION"))&&J1(u($,"autonomy/run.sh")))return $;let Q=S1($);if(Q===$)break;$=Q}return u(K,"..","..","..")}function P(){return process.env.LOKI_DIR??u(process.cwd(),".loki")}function k1(){return u(R7(),".loki")}var i1,p;var y=R(()=>{i1=S1(L7(import.meta.url));p=E7()});import{readFileSync as x7}from"fs";import{resolve as F7,dirname as w7}from"path";import{fileURLToPath as S7}from"url";function G1(){if(n!==null)return n;let K="7.7.7";if(typeof K==="string"&&K.length>0)return n=K,n;try{let $=w7(S7(import.meta.url)),z=N1($);n=x7(F7(z,"VERSION"),"utf-8").trim()}catch{n="unknown"}return n}var n=null;var D1=R(()=>{y()});var $0={};b($0,{runOrThrow:()=>N7,run:()=>S,commandVersion:()=>D7,commandExists:()=>D,ShellError:()=>C1});async function S(K,$={}){let z=Bun.spawn({cmd:[...K],stdout:"pipe",stderr:"pipe",env:$.env?{...process.env,...$.env}:process.env,cwd:$.cwd}),Q,X;if($.timeoutMs&&$.timeoutMs>0)Q=setTimeout(()=>{try{z.kill("SIGTERM")}catch{}X=setTimeout(()=>{try{z.kill("SIGKILL")}catch{}},2000)},$.timeoutMs);try{let[H,Z,q]=await Promise.all([new Response(z.stdout).text(),new Response(z.stderr).text(),z.exited]);return{stdout:H,stderr:Z,exitCode:q}}finally{if(Q)clearTimeout(Q);if(X)clearTimeout(X)}}async function N7(K,$={}){let z=await S(K,$);if(z.exitCode!==0)throw new C1(`command failed (${z.exitCode}): ${K.join(" ")}`,z.exitCode,z.stdout,z.stderr);return z}async function D(K){let $=k7(K),z=await S(["sh","-c",`command -v ${$}`],{timeoutMs:5000});if(z.exitCode===0)return z.stdout.trim()||null;return null}function k7(K){if(!/^[A-Za-z0-9._/-]+$/.test(K))throw Error(`refused to shell-escape suspect token: ${K}`);return K}async function D7(K,$="--version"){if(!await D(K))return null;let Q=await S([K,$],{timeoutMs:5000});if(Q.exitCode!==0)return null;return((Q.stdout||Q.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var C1;var c=R(()=>{C1=class C1 extends Error{message;exitCode;stdout;stderr;constructor(K,$,z,Q){super(K);this.message=K;this.exitCode=$;this.stdout=z;this.stderr=Q;this.name="ShellError"}}});function l(K){return C7?"":K}var C7,E,C,x,O6,O,k,F,W;var a=R(()=>{C7=(process.env.NO_COLOR??"").length>0;E=l("\x1B[0;31m"),C=l("\x1B[0;32m"),x=l("\x1B[1;33m"),O6=l("\x1B[0;34m"),O=l("\x1B[0;36m"),k=l("\x1B[1m"),F=l("\x1B[2m"),W=l("\x1B[0m")});import{existsSync as c7}from"fs";async function t(){if(z1!==void 0)return z1;let K="/opt/homebrew/bin/python3.12";if(c7(K))return z1=K,K;let $=await D("python3.12");if($)return z1=$,$;let z=await D("python3");return z1=z,z}async function s(K,$={}){let z=await t();if(!z)return{stdout:"",stderr:"python3 not found",exitCode:127};return S([z,"-c",K],$)}var z1;var Q1=R(()=>{c()});var G0={};b(G0,{runStatus:()=>z5});import{existsSync as N,readFileSync as Z1,readdirSync as H0,statSync as W0}from"fs";import{resolve as w,basename as a7}from"path";async function r7(){if(await D("jq"))return!0;return process.stdout.write(`${E}Error: jq is required but not installed.${W}
|
|
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)
|
|
@@ -550,4 +550,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
|
|
|
550
550
|
`),2}default:return process.stderr.write(`Unknown command: ${$}
|
|
551
551
|
`),process.stderr.write(j7),2}}process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var z6=await $6(Bun.argv.slice(2));process.exit(z6);
|
|
552
552
|
|
|
553
|
-
//# debugId=
|
|
553
|
+
//# debugId=A58DDE9430ACC6E964756E2164756E21
|
package/mcp/__init__.py
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "loki-mode",
|
|
3
|
-
"version": "7.7.
|
|
3
|
+
"version": "7.7.7",
|
|
4
4
|
"description": "Loki Mode by Autonomi. Multi-agent autonomous SDLC framework. Spec to deployed app: PRD, GitHub issue, OpenAPI/JSON/YAML, or one-line brief. 4 AI providers (Claude Code, OpenAI Codex, Cline, Aider). 11 quality gates.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|