loki-mode 7.7.9 → 7.7.10
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/run.sh +68 -1
- 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.10
|
|
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.10 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
7.7.
|
|
1
|
+
7.7.10
|
package/autonomy/run.sh
CHANGED
|
@@ -8755,10 +8755,68 @@ _intelligent_usage_regen() {
|
|
|
8755
8755
|
_manifests="${_manifests}=== $f ===\n$(head -50 "$target_dir/$f" 2>/dev/null)\n\n"
|
|
8756
8756
|
fi
|
|
8757
8757
|
done
|
|
8758
|
+
# v7.7.10 F-3 fix: include entrypoint file content so the model can read
|
|
8759
|
+
# the ACTUAL port / host bindings instead of guessing from package.json
|
|
8760
|
+
# scripts (which often imply port 3000 by convention but server.js may
|
|
8761
|
+
# bind a different port like 3001). Without this the regen wrote
|
|
8762
|
+
# "curl http://localhost:3000" for projects where the server bound 3001.
|
|
8763
|
+
local _entrypoints=""
|
|
8764
|
+
local _ep_candidates=""
|
|
8765
|
+
# Detect entrypoint from package.json main field if present
|
|
8766
|
+
if [ -f "$target_dir/package.json" ]; then
|
|
8767
|
+
local _pkg_main
|
|
8768
|
+
_pkg_main=$(python3 -c "import json,sys; d=json.load(open('$target_dir/package.json'));print(d.get('main') or '')" 2>/dev/null)
|
|
8769
|
+
[ -n "$_pkg_main" ] && _ep_candidates="$_ep_candidates $_pkg_main"
|
|
8770
|
+
# Extract files referenced in `scripts.start` and `scripts.dev`
|
|
8771
|
+
local _pkg_scripts
|
|
8772
|
+
_pkg_scripts=$(python3 -c "import json,re,sys; d=json.load(open('$target_dir/package.json'));s=d.get('scripts',{});c=' '.join([s.get('start',''),s.get('dev','')]);[print(t) for t in re.findall(r'[\\w/.-]+\\.(?:js|mjs|cjs|ts|mts|cts|py)\\b',c)]" 2>/dev/null)
|
|
8773
|
+
[ -n "$_pkg_scripts" ] && _ep_candidates="$_ep_candidates $_pkg_scripts"
|
|
8774
|
+
fi
|
|
8775
|
+
# Fallback convention names for common stacks
|
|
8776
|
+
for _ep in server.js server.ts server.mjs index.js index.ts app.js app.ts \
|
|
8777
|
+
main.py app.py server.py manage.py wsgi.py asgi.py \
|
|
8778
|
+
main.go cmd/server/main.go src/main.rs src/index.ts dist/server.js \
|
|
8779
|
+
build/server.js; do
|
|
8780
|
+
_ep_candidates="$_ep_candidates $_ep"
|
|
8781
|
+
done
|
|
8782
|
+
# Read first 80 lines of up to 3 unique existing candidates, scrubbing
|
|
8783
|
+
# common secret-bearing lines before they ship to the haiku endpoint.
|
|
8784
|
+
# v7.7.10 privacy guard: replaces lines matching API_KEY/SECRET/PASSWORD/
|
|
8785
|
+
# TOKEN/PRIVATE_KEY/AUTH/CREDENTIAL/BEARER assignments with [REDACTED]
|
|
8786
|
+
# so default-on regen does not exfiltrate hardcoded secrets. Port-binding
|
|
8787
|
+
# lines (listen/run/ListenAndServe with numeric literals) are preserved.
|
|
8788
|
+
# Opt out entirely with LOKI_INTELLIGENT_USAGE_INCLUDE_SOURCE=0.
|
|
8789
|
+
local _include_source="${LOKI_INTELLIGENT_USAGE_INCLUDE_SOURCE:-1}"
|
|
8790
|
+
local _seen="" _count=0
|
|
8791
|
+
for _ep in $_ep_candidates; do
|
|
8792
|
+
# Skip duplicates and non-existent files
|
|
8793
|
+
case " $_seen " in *" $_ep "*) continue ;; esac
|
|
8794
|
+
_seen="$_seen $_ep"
|
|
8795
|
+
if [ -f "$target_dir/$_ep" ]; then
|
|
8796
|
+
local _ep_body
|
|
8797
|
+
if [ "$_include_source" = "0" ]; then
|
|
8798
|
+
_ep_body="(entrypoint source omitted: LOKI_INTELLIGENT_USAGE_INCLUDE_SOURCE=0)"
|
|
8799
|
+
else
|
|
8800
|
+
# Scrub: any line whose text contains a credential keyword
|
|
8801
|
+
# has its value (everything after the first `:` or `=`)
|
|
8802
|
+
# replaced with [REDACTED]. Then any literal high-entropy
|
|
8803
|
+
# token shape (stripe sk-, github ghp_/ghs_, slack xox, GCP
|
|
8804
|
+
# AIza, AWS AKIA) is replaced inline. Port-binding lines
|
|
8805
|
+
# (no credential keyword) pass through unchanged.
|
|
8806
|
+
_ep_body=$(head -80 "$target_dir/$_ep" 2>/dev/null \
|
|
8807
|
+
| sed -E \
|
|
8808
|
+
-e '/[Aa][Pp][Ii][_-]?[Kk][Ee][Yy]|[Ss][Ee][Cc][Rr][Ee][Tt]|[Pp][Aa][Ss][Ss][Ww][Oo][Rr][Dd]|[Tt][Oo][Kk][Ee][Nn]|[Pp][Rr][Ii][Vv][Aa][Tt][Ee][_-]?[Kk][Ee][Yy]|[Cc][Rr][Ee][Dd][Ee][Nn][Tt][Ii][Aa][Ll]|[Bb][Ee][Aa][Rr][Ee][Rr]/ s/[:=].*$/= [REDACTED]/' \
|
|
8809
|
+
-e 's/(sk-[A-Za-z0-9_-]{16,}|pk_[A-Za-z0-9_-]{16,}|ghp_[A-Za-z0-9]{16,}|ghs_[A-Za-z0-9]{16,}|xox[bpoa]-[A-Za-z0-9-]{16,}|AIza[A-Za-z0-9_-]{32,}|AKIA[A-Z0-9]{12,})/[REDACTED]/g')
|
|
8810
|
+
fi
|
|
8811
|
+
_entrypoints="${_entrypoints}=== Entrypoint: $_ep ===\n${_ep_body}\n\n"
|
|
8812
|
+
_count=$((_count + 1))
|
|
8813
|
+
[ "$_count" -ge 3 ] && break
|
|
8814
|
+
fi
|
|
8815
|
+
done
|
|
8758
8816
|
_commits=$(cd "$target_dir" && git log --oneline -10 2>/dev/null || true)
|
|
8759
8817
|
|
|
8760
8818
|
log_info "Regenerating USAGE.md from final project state (intelligent mode)..."
|
|
8761
|
-
local _ic_prompt="You are writing a USAGE.md for the project below. Detect the stack from the manifest files; emit a concise (under 100 lines) Markdown doc with sections: ## Prerequisites, ## Install, ## Start, ## Verify (2-3 copy-paste curl/browser/CLI commands with expected output), ## Stop. Use the ACTUAL command names from package.json scripts or pyproject entry points -- never generic placeholders. Output ONLY the Markdown body (no code-fence wrapper, no preamble).
|
|
8819
|
+
local _ic_prompt="You are writing a USAGE.md for the project below. Detect the stack from the manifest files; emit a concise (under 100 lines) Markdown doc with sections: ## Prerequisites, ## Install, ## Start, ## Verify (2-3 copy-paste curl/browser/CLI commands with expected output), ## Stop. Use the ACTUAL command names from package.json scripts or pyproject entry points -- never generic placeholders. For ports, read the ENTRYPOINT file contents below (server.listen / app.listen / app.run / http.ListenAndServe / uvicorn.run port arg) -- do NOT infer port from script names or convention. If the entrypoint reads from process.env.PORT with a literal default, use the literal default. Output ONLY the Markdown body (no code-fence wrapper, no preamble).
|
|
8762
8820
|
|
|
8763
8821
|
=== Project tree (max 30 files, 3 levels deep) ===
|
|
8764
8822
|
${_tree}
|
|
@@ -8766,6 +8824,9 @@ ${_tree}
|
|
|
8766
8824
|
=== Manifest files ===
|
|
8767
8825
|
${_manifests}
|
|
8768
8826
|
|
|
8827
|
+
=== Entrypoint file contents (port bindings live here, NOT in package.json) ===
|
|
8828
|
+
${_entrypoints}
|
|
8829
|
+
|
|
8769
8830
|
=== Last 10 commits ===
|
|
8770
8831
|
${_commits}"
|
|
8771
8832
|
|
|
@@ -12136,6 +12197,8 @@ cleanup() {
|
|
|
12136
12197
|
# v7.5.12: Kill any running provider pipeline first, before slow cleanup.
|
|
12137
12198
|
kill_provider_child 2>/dev/null || true
|
|
12138
12199
|
rm -f "$loki_dir/STOP" "$loki_dir/PAUSE" "$loki_dir/PAUSED.md" 2>/dev/null
|
|
12200
|
+
# UT2-13: Clear cli-provider marker on session end.
|
|
12201
|
+
rm -f "$loki_dir/state/cli-provider" 2>/dev/null || true
|
|
12139
12202
|
if type app_runner_cleanup &>/dev/null; then
|
|
12140
12203
|
app_runner_cleanup
|
|
12141
12204
|
fi
|
|
@@ -12183,6 +12246,8 @@ except (json.JSONDecodeError, OSError): pass
|
|
|
12183
12246
|
stop_status_monitor
|
|
12184
12247
|
kill_all_registered
|
|
12185
12248
|
rm -f "$loki_dir/loki.pid" "$loki_dir/PAUSE" 2>/dev/null
|
|
12249
|
+
# UT2-13: Clear cli-provider marker on session end.
|
|
12250
|
+
rm -f "$loki_dir/state/cli-provider" 2>/dev/null || true
|
|
12186
12251
|
# Clean up per-session PID file if running with session ID
|
|
12187
12252
|
if [ -n "${LOKI_SESSION_ID:-}" ]; then
|
|
12188
12253
|
rm -f "$loki_dir/sessions/${LOKI_SESSION_ID}/loki.pid" 2>/dev/null
|
|
@@ -12789,6 +12854,8 @@ main() {
|
|
|
12789
12854
|
stop_status_monitor
|
|
12790
12855
|
local loki_dir="${TARGET_DIR:-.}/.loki"
|
|
12791
12856
|
rm -f "$loki_dir/loki.pid" 2>/dev/null
|
|
12857
|
+
# UT2-13: Clear cli-provider marker on normal session end.
|
|
12858
|
+
rm -f "$loki_dir/state/cli-provider" 2>/dev/null || true
|
|
12792
12859
|
# Clean up per-session PID file if running with session ID
|
|
12793
12860
|
if [ -n "${LOKI_SESSION_ID:-}" ]; then
|
|
12794
12861
|
rm -f "$loki_dir/sessions/${LOKI_SESSION_ID}/loki.pid" 2>/dev/null
|
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.10";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=E665186CA1CB055E64756E2164756E21
|
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.10",
|
|
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",
|