loki-mode 7.36.0 → 7.37.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/lib/claude-flags.sh +75 -0
- package/autonomy/run.sh +66 -3
- package/dashboard/__init__.py +1 -1
- package/dashboard/server.py +12 -0
- 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: 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, 11 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 v7.
|
|
6
|
+
# Loki Mode v7.37.0
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -398,4 +398,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
398
398
|
|
|
399
399
|
---
|
|
400
400
|
|
|
401
|
-
**v7.
|
|
401
|
+
**v7.37.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
7.
|
|
1
|
+
7.37.0
|
|
@@ -378,3 +378,78 @@ loki_ultrareview_supported() {
|
|
|
378
378
|
loki_ultrareview_enabled() {
|
|
379
379
|
[ "${LOKI_ULTRAREVIEW:-0}" = "1" ]
|
|
380
380
|
}
|
|
381
|
+
|
|
382
|
+
# ---------------------------------------------------------------------------
|
|
383
|
+
# Session-continuity Phase 2 (GitHub #165) -- LOKI_RESUME_SESSION recovery resume
|
|
384
|
+
#
|
|
385
|
+
# NAMING COLLISION WARNING: Loki already has a user-facing `loki heal --resume`
|
|
386
|
+
# / `loki migrate --resume` CHECKPOINT flag (autonomy/loki). LOKI_RESUME_SESSION
|
|
387
|
+
# governs the CLAUDE-CLI session-resume layer (claude --resume <uuid>), NOT the
|
|
388
|
+
# Loki checkpoint resume. They are unrelated.
|
|
389
|
+
#
|
|
390
|
+
# SCOPE (minimum useful, design s2): on a RESTARTED run (the prior run was
|
|
391
|
+
# interrupted -- crash / rate limit / --max-budget cutoff -- so its non-terminal
|
|
392
|
+
# autonomy-state.json persisted iterationCount>0), the FIRST main-loop claude
|
|
393
|
+
# call of the restarted run emits `claude --resume <stored-uuid>` (the stable
|
|
394
|
+
# per-run uuid from .loki/state/claude-session.json) instead of a fresh
|
|
395
|
+
# stateless call, reattaching the prior Claude context. After that single
|
|
396
|
+
# resumed call the run reverts to normal per-iteration stateless behavior
|
|
397
|
+
# (injected memory carries forward as today). This is a RECOVERY feature, NOT a
|
|
398
|
+
# per-iteration resume chain -- so transcript growth cannot accumulate.
|
|
399
|
+
#
|
|
400
|
+
# CONSERVATIVE DEFAULT OFF: with the knob unset the default claude argv is
|
|
401
|
+
# byte-identical to v7.34 (no --resume ever emitted). Opt IN with
|
|
402
|
+
# LOKI_RESUME_SESSION=1. Gated on CLI support so an older claude degrades.
|
|
403
|
+
#
|
|
404
|
+
# MUTUAL EXCLUSION: --session-id and --resume are mutually exclusive on one
|
|
405
|
+
# claude invocation (claude rejects a session-id already in use, and resume
|
|
406
|
+
# replaces the fresh-session intent). The run.sh main-loop block emits the
|
|
407
|
+
# resume slice INSTEAD of the stamp slice on the one resumed call, never both.
|
|
408
|
+
# ---------------------------------------------------------------------------
|
|
409
|
+
|
|
410
|
+
# Predicate: is recovery resume enabled AND supported? CONSERVATIVE DEFAULT OFF.
|
|
411
|
+
# Opt IN with LOKI_RESUME_SESSION=1; gated on `claude --resume` support so an
|
|
412
|
+
# older CLI degrades to normal stateless behavior (no flag emitted).
|
|
413
|
+
loki_resume_session_enabled() {
|
|
414
|
+
[ "${LOKI_RESUME_SESSION:-0}" = "1" ] || return 1
|
|
415
|
+
loki_claude_flag_supported "--resume"
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
# Predicate: when resuming, also fork into a NEW session id (leaving the parent
|
|
419
|
+
# transcript untouched)? Only honored together with LOKI_RESUME_SESSION=1.
|
|
420
|
+
# DEFAULT OFF. Gated on `claude --fork-session` support.
|
|
421
|
+
loki_session_fork_enabled() {
|
|
422
|
+
[ "${LOKI_SESSION_FORK:-0}" = "1" ] || return 1
|
|
423
|
+
loki_resume_session_enabled || return 1
|
|
424
|
+
loki_claude_flag_supported "--fork-session"
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
# The stable per-run claude session uuid to resume, read from the run-start
|
|
428
|
+
# metadata file .loki/state/claude-session.json (written on the FRESH run, so it
|
|
429
|
+
# survives into a restart). Emits the stored uuid on stdout, or nothing when the
|
|
430
|
+
# file is absent / unreadable / has no uuid (caller then skips resume and runs a
|
|
431
|
+
# normal fresh call -- safe degrade). Pure read, no side effects. Honors LOKI_DIR
|
|
432
|
+
# / TARGET_DIR exactly like the rest of run.sh.
|
|
433
|
+
_loki_resume_target_uuid() {
|
|
434
|
+
local loki_dir="${LOKI_DIR:-${TARGET_DIR:-.}/.loki}"
|
|
435
|
+
local cs_file="$loki_dir/state/claude-session.json"
|
|
436
|
+
[ -s "$cs_file" ] || return 0
|
|
437
|
+
command -v python3 >/dev/null 2>&1 || return 0
|
|
438
|
+
_LOKI_CS_FILE="$cs_file" python3 - <<'RESUME_UUID_PY' 2>/dev/null || true
|
|
439
|
+
import json, os, re
|
|
440
|
+
try:
|
|
441
|
+
with open(os.environ["_LOKI_CS_FILE"]) as f:
|
|
442
|
+
d = json.load(f)
|
|
443
|
+
if not isinstance(d, dict):
|
|
444
|
+
raise ValueError
|
|
445
|
+
u = d.get("claude_session_uuid", "")
|
|
446
|
+
# RFC-4122 shape check: only print a well-formed uuid so a corrupt file
|
|
447
|
+
# never injects a bogus --resume argument.
|
|
448
|
+
if isinstance(u, str) and re.match(
|
|
449
|
+
r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", u
|
|
450
|
+
):
|
|
451
|
+
print(u, end="")
|
|
452
|
+
except Exception:
|
|
453
|
+
pass
|
|
454
|
+
RESUME_UUID_PY
|
|
455
|
+
}
|
package/autonomy/run.sh
CHANGED
|
@@ -12390,6 +12390,25 @@ except Exception:
|
|
|
12390
12390
|
fi
|
|
12391
12391
|
fi
|
|
12392
12392
|
|
|
12393
|
+
# Session-continuity Phase 2 (GitHub #165): snapshot whether THIS run is a
|
|
12394
|
+
# RESTARTED run BEFORE the main loop mutates ITERATION_COUNT. load_state
|
|
12395
|
+
# (called above) restored ITERATION_COUNT from .loki/autonomy-state.json's
|
|
12396
|
+
# iterationCount, resetting to 0 after a terminal prior run. So at this point
|
|
12397
|
+
# ITERATION_COUNT>0 means "the prior run was interrupted (non-terminal) and
|
|
12398
|
+
# is being restarted"; ==0 means fresh. The main loop increments
|
|
12399
|
+
# ITERATION_COUNT at the top of each pass, so the resume decision MUST key on
|
|
12400
|
+
# this run-start snapshot, never the live counter. _LOKI_RESUME_CONSUMED is
|
|
12401
|
+
# the once-only latch so the recovery resume fires on exactly the FIRST
|
|
12402
|
+
# main-loop call of a restarted run, then the run reverts to normal stateless
|
|
12403
|
+
# iterations (no resume chain -- transcript growth cannot accumulate).
|
|
12404
|
+
if [ "${ITERATION_COUNT:-0}" -gt 0 ]; then
|
|
12405
|
+
_LOKI_RESTARTED_RUN=1
|
|
12406
|
+
else
|
|
12407
|
+
_LOKI_RESTARTED_RUN=0
|
|
12408
|
+
fi
|
|
12409
|
+
_LOKI_RESUME_CONSUMED=0
|
|
12410
|
+
export _LOKI_RESTARTED_RUN _LOKI_RESUME_CONSUMED
|
|
12411
|
+
|
|
12393
12412
|
# Trust-metrics instrumentation marker: record one run_start event per
|
|
12394
12413
|
# fresh run so the trust-metrics denominator counts ONLY instrumented runs.
|
|
12395
12414
|
# This is what lets the aggregator distinguish "0 blocks measured" from
|
|
@@ -12415,9 +12434,22 @@ except Exception:
|
|
|
12415
12434
|
if [ -n "$_loki_session_uuid" ]; then
|
|
12416
12435
|
local _loki_session_created
|
|
12417
12436
|
_loki_session_created="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
12437
|
+
# mode reflects the active session-continuity layer for this run,
|
|
12438
|
+
# surfaced on the dashboard: "resume" when Phase 2 recovery resume
|
|
12439
|
+
# is enabled (GitHub #165), else "stamp" (Phase 1 correlation-only,
|
|
12440
|
+
# v7.34). DEFAULT (no knobs) stays "stamp" so existing behavior +
|
|
12441
|
+
# dashboard output are unchanged. The uuid is the SAME stable
|
|
12442
|
+
# per-run uuid either way -- it is the resume anchor a later
|
|
12443
|
+
# restart reads back. The "stamp" vs "resume" label only records
|
|
12444
|
+
# intent; the actual argv decision is gated again at call time.
|
|
12445
|
+
local _loki_session_mode="stamp"
|
|
12446
|
+
if type loki_resume_session_enabled >/dev/null 2>&1 \
|
|
12447
|
+
&& loki_resume_session_enabled; then
|
|
12448
|
+
_loki_session_mode="resume"
|
|
12449
|
+
fi
|
|
12418
12450
|
mkdir -p ".loki/state" 2>/dev/null || true
|
|
12419
|
-
printf '{"run_id":"%s","claude_session_uuid":"%s","mode":"
|
|
12420
|
-
"$LOKI_TRUST_RUN_ID" "$_loki_session_uuid" "$_loki_session_created" \
|
|
12451
|
+
printf '{"run_id":"%s","claude_session_uuid":"%s","mode":"%s","created_at":"%s"}\n' \
|
|
12452
|
+
"$LOKI_TRUST_RUN_ID" "$_loki_session_uuid" "$_loki_session_mode" "$_loki_session_created" \
|
|
12421
12453
|
> ".loki/state/claude-session.json" 2>/dev/null || true
|
|
12422
12454
|
fi
|
|
12423
12455
|
fi
|
|
@@ -12816,6 +12848,34 @@ except Exception as exc:
|
|
|
12816
12848
|
&& loki_claude_flag_supported "--include-partial-messages"; then
|
|
12817
12849
|
_loki_claude_argv+=("--include-partial-messages")
|
|
12818
12850
|
fi
|
|
12851
|
+
# Session-continuity Phase 2 (GitHub #165): on the FIRST main-loop call of
|
|
12852
|
+
# a RESTARTED run (snapshot _LOKI_RESTARTED_RUN==1, latch
|
|
12853
|
+
# _LOKI_RESUME_CONSUMED==0) with LOKI_RESUME_SESSION=1, emit
|
|
12854
|
+
# `--resume <stored-uuid>` INSTEAD of the per-iteration --session-id stamp
|
|
12855
|
+
# (the two are mutually exclusive on one invocation). This reattaches the
|
|
12856
|
+
# prior Claude context once, then the latch flips so every later iteration
|
|
12857
|
+
# reverts to normal stateless behavior. Optional --fork-session
|
|
12858
|
+
# (LOKI_SESSION_FORK=1) writes the resumed turn to a new id, leaving the
|
|
12859
|
+
# parent transcript untouched. DEFAULT OFF: with no knobs neither --resume
|
|
12860
|
+
# nor --session-id is emitted (argv byte-identical to v7.34).
|
|
12861
|
+
local _loki_did_resume=0
|
|
12862
|
+
if [ "${_LOKI_RESTARTED_RUN:-0}" = "1" ] && [ "${_LOKI_RESUME_CONSUMED:-0}" = "0" ] \
|
|
12863
|
+
&& type loki_resume_session_enabled >/dev/null 2>&1 \
|
|
12864
|
+
&& loki_resume_session_enabled; then
|
|
12865
|
+
local _loki_resume_uuid
|
|
12866
|
+
_loki_resume_uuid="$(_loki_resume_target_uuid)"
|
|
12867
|
+
if [ -n "$_loki_resume_uuid" ]; then
|
|
12868
|
+
_loki_claude_argv+=("--resume" "$_loki_resume_uuid")
|
|
12869
|
+
if type loki_session_fork_enabled >/dev/null 2>&1 \
|
|
12870
|
+
&& loki_session_fork_enabled; then
|
|
12871
|
+
_loki_claude_argv+=("--fork-session")
|
|
12872
|
+
fi
|
|
12873
|
+
_loki_did_resume=1
|
|
12874
|
+
_LOKI_RESUME_CONSUMED=1
|
|
12875
|
+
export _LOKI_RESUME_CONSUMED
|
|
12876
|
+
log_info "LOKI_RESUME_SESSION=1: resuming Claude session $_loki_resume_uuid (recovery resume, first call of restarted run)"
|
|
12877
|
+
fi
|
|
12878
|
+
fi
|
|
12819
12879
|
# v7.34.0 Phase 1 (correlation-only): per-iteration --session-id. OPT-IN
|
|
12820
12880
|
# via LOKI_SESSION_STAMP=1 (CONSERVATIVE DEFAULT is OFF so the default
|
|
12821
12881
|
# argv stays byte-identical to v7.33 -- the UX-monotonicity requirement).
|
|
@@ -12824,7 +12884,10 @@ except Exception as exc:
|
|
|
12824
12884
|
# and accumulate transcript (Phase 2 continuity, out of scope). This keeps
|
|
12825
12885
|
# each iteration a fresh stateless session while making its ~/.claude
|
|
12826
12886
|
# JSONL name predictable for dashboard correlation. Gated on CLI support.
|
|
12827
|
-
|
|
12887
|
+
# MUTUAL EXCLUSION: skip the stamp on the call that emitted --resume above
|
|
12888
|
+
# (claude rejects --session-id + --resume together).
|
|
12889
|
+
if [ "$_loki_did_resume" = "0" ] \
|
|
12890
|
+
&& type loki_session_stamp_enabled >/dev/null 2>&1 \
|
|
12828
12891
|
&& loki_session_stamp_enabled; then
|
|
12829
12892
|
local _loki_iter_session_uuid
|
|
12830
12893
|
_loki_iter_session_uuid="$(_loki_claude_iteration_session_uuid "${LOKI_TRUST_RUN_ID:-}" "$ITERATION_COUNT")"
|
package/dashboard/__init__.py
CHANGED
package/dashboard/server.py
CHANGED
|
@@ -392,6 +392,11 @@ class StatusResponse(BaseModel):
|
|
|
392
392
|
# user can correlate the run with its Claude session JSONL (in ~/.claude/projects). Empty when
|
|
393
393
|
# the run predates this field or no claude session was stamped.
|
|
394
394
|
claude_session_id: str = ""
|
|
395
|
+
# Session-continuity Phase 2 (#165): the active session-continuity layer for
|
|
396
|
+
# the current run, read from claude-session.json. "stamp" = Phase 1
|
|
397
|
+
# correlation-only (v7.34); "resume" = LOKI_RESUME_SESSION recovery resume.
|
|
398
|
+
# Empty when the run predates this field or no claude session was stamped.
|
|
399
|
+
claude_session_mode: str = ""
|
|
395
400
|
# Concurrent sessions (v6.4.0)
|
|
396
401
|
sessions: list[SessionInfo] = []
|
|
397
402
|
|
|
@@ -963,6 +968,7 @@ async def get_status() -> StatusResponse:
|
|
|
963
968
|
# run-start by run.sh (correlation-only). Best-effort read; empty when the
|
|
964
969
|
# file is absent (run predates the field, or a non-claude provider).
|
|
965
970
|
claude_session_id = ""
|
|
971
|
+
claude_session_mode = ""
|
|
966
972
|
claude_session_file = loki_dir / "state" / "claude-session.json"
|
|
967
973
|
if claude_session_file.exists():
|
|
968
974
|
try:
|
|
@@ -976,6 +982,11 @@ async def get_status() -> StatusResponse:
|
|
|
976
982
|
if isinstance(_cs, dict):
|
|
977
983
|
_v = _cs.get("claude_session_uuid", "")
|
|
978
984
|
claude_session_id = _v if isinstance(_v, str) else ""
|
|
985
|
+
# Phase 2 (#165): "stamp" (Phase 1 correlation-only) or "resume"
|
|
986
|
+
# (LOKI_RESUME_SESSION recovery resume). Empty when the run
|
|
987
|
+
# predates the field. Same non-string guard as the uuid.
|
|
988
|
+
_m = _cs.get("mode", "")
|
|
989
|
+
claude_session_mode = _m if isinstance(_m, str) else ""
|
|
979
990
|
except (json.JSONDecodeError, OSError, KeyError, AttributeError):
|
|
980
991
|
pass
|
|
981
992
|
|
|
@@ -1232,6 +1243,7 @@ async def get_status() -> StatusResponse:
|
|
|
1232
1243
|
provider=provider,
|
|
1233
1244
|
current_task=current_task,
|
|
1234
1245
|
claude_session_id=claude_session_id,
|
|
1246
|
+
claude_session_mode=claude_session_mode,
|
|
1235
1247
|
sessions=active_session_list,
|
|
1236
1248
|
)
|
|
1237
1249
|
|
package/docs/INSTALLATION.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The flagship product of [Autonomi](https://www.autonomi.dev/). Loki Mode is a spec-driven autonomous builder with a built-in trust layer that takes any spec to a deployed product and verifies completion with evidence (quality gates plus a completion council), not just a "done" claim. Complete installation instructions for all platforms and use cases.
|
|
4
4
|
|
|
5
|
-
**Version:** v7.
|
|
5
|
+
**Version:** v7.37.0
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
package/loki-ts/dist/loki.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var n6=Object.defineProperty;var a6=($)=>$;function s6($,Q){this[$]=a6.bind(null,Q)}var h=($,Q)=>{for(var Z in Q)n6($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:s6.bind(Q,Z)})};var L=($,Q)=>()=>($&&(Q=$($=0)),Q);var K$=import.meta.require;var S1={};h(S1,{lokiDir:()=>P,homeLokiDir:()=>o$,findRepoRootForVersion:()=>d$,REPO_ROOT:()=>m});import{resolve as n,dirname as l$}from"path";import{fileURLToPath as t6}from"url";import{existsSync as P$}from"fs";import{homedir as r6}from"os";function i6(){let $=N1;for(let Q=0;Q<6;Q++){if(P$(n($,"VERSION"))&&P$(n($,"autonomy/run.sh")))return $;let Z=l$($);if(Z===$)break;$=Z}return n(N1,"..","..","..")}function d$($){let Q=$;for(let Z=0;Z<6;Z++){if(P$(n(Q,"VERSION"))&&P$(n(Q,"autonomy/run.sh")))return Q;let z=l$(Q);if(z===Q)break;Q=z}return n($,"..","..","..")}function P(){return process.env.LOKI_DIR??n(process.cwd(),".loki")}function o$(){return n(r6(),".loki")}var N1,m;var C=L(()=>{N1=l$(t6(import.meta.url));m=i6()});import{readFileSync as e6}from"fs";import{resolve as $Q,dirname as QQ}from"path";import{fileURLToPath as ZQ}from"url";function F$(){if($$!==null)return $$;let $="7.
|
|
2
|
+
var n6=Object.defineProperty;var a6=($)=>$;function s6($,Q){this[$]=a6.bind(null,Q)}var h=($,Q)=>{for(var Z in Q)n6($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:s6.bind(Q,Z)})};var L=($,Q)=>()=>($&&(Q=$($=0)),Q);var K$=import.meta.require;var S1={};h(S1,{lokiDir:()=>P,homeLokiDir:()=>o$,findRepoRootForVersion:()=>d$,REPO_ROOT:()=>m});import{resolve as n,dirname as l$}from"path";import{fileURLToPath as t6}from"url";import{existsSync as P$}from"fs";import{homedir as r6}from"os";function i6(){let $=N1;for(let Q=0;Q<6;Q++){if(P$(n($,"VERSION"))&&P$(n($,"autonomy/run.sh")))return $;let Z=l$($);if(Z===$)break;$=Z}return n(N1,"..","..","..")}function d$($){let Q=$;for(let Z=0;Z<6;Z++){if(P$(n(Q,"VERSION"))&&P$(n(Q,"autonomy/run.sh")))return Q;let z=l$(Q);if(z===Q)break;Q=z}return n($,"..","..","..")}function P(){return process.env.LOKI_DIR??n(process.cwd(),".loki")}function o$(){return n(r6(),".loki")}var N1,m;var C=L(()=>{N1=l$(t6(import.meta.url));m=i6()});import{readFileSync as e6}from"fs";import{resolve as $Q,dirname as QQ}from"path";import{fileURLToPath as ZQ}from"url";function F$(){if($$!==null)return $$;let $="7.37.0";if(typeof $==="string"&&$.length>0)return $$=$,$$;try{let Q=QQ(ZQ(import.meta.url)),Z=d$(Q);$$=e6($Q(Z,"VERSION"),"utf-8").trim()}catch{$$="unknown"}return $$}var $$=null;var n$=L(()=>{C()});var C1={};h(C1,{runOrThrow:()=>zQ,run:()=>j,commandVersion:()=>KQ,commandExists:()=>f,ShellError:()=>a$});async function j($,Q={}){let Z=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:Q.env?{...process.env,...Q.env}:process.env,cwd:Q.cwd}),z,X;if(Q.timeoutMs&&Q.timeoutMs>0)z=setTimeout(()=>{try{Z.kill("SIGTERM")}catch{}X=setTimeout(()=>{try{Z.kill("SIGKILL")}catch{}},2000)},Q.timeoutMs);try{let[W,K,U]=await Promise.all([new Response(Z.stdout).text(),new Response(Z.stderr).text(),Z.exited]);return{stdout:W,stderr:K,exitCode:U}}finally{if(z)clearTimeout(z);if(X)clearTimeout(X)}}async function zQ($,Q={}){let Z=await j($,Q);if(Z.exitCode!==0)throw new a$(`command failed (${Z.exitCode}): ${$.join(" ")}`,Z.exitCode,Z.stdout,Z.stderr);return Z}async function f($){let Q=XQ($),Z=await j(["sh","-c",`command -v ${Q}`],{timeoutMs:5000});if(Z.exitCode===0)return Z.stdout.trim()||null;return null}function XQ($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function KQ($,Q="--version"){if(!await f($))return null;let z=await j([$,Q],{timeoutMs:5000});if(z.exitCode!==0)return null;return((z.stdout||z.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var a$;var d=L(()=>{a$=class a$ extends Error{message;exitCode;stdout;stderr;constructor($,Q,Z,z){super($);this.message=$;this.exitCode=Q;this.stdout=Z;this.stderr=z;this.name="ShellError"}}});function a($){return WQ?"":$}var WQ,T,S,I,TZ,w,R,y,q;var c=L(()=>{WQ=(process.env.NO_COLOR??"").length>0;T=a("\x1B[0;31m"),S=a("\x1B[0;32m"),I=a("\x1B[1;33m"),TZ=a("\x1B[0;34m"),w=a("\x1B[0;36m"),R=a("\x1B[1m"),y=a("\x1B[2m"),q=a("\x1B[0m")});import{existsSync as TQ}from"fs";async function Q$(){if(B$!==void 0)return B$;let $="/opt/homebrew/bin/python3.12";if(TQ($))return B$=$,$;let Q=await f("python3.12");if(Q)return B$=Q,Q;let Z=await f("python3");return B$=Z,Z}async function Z$($,Q={}){let Z=await Q$();if(!Z)return{stdout:"",stderr:"python3 not found",exitCode:127};return j([Z,"-c",$],Q)}var B$;var W$=L(()=>{d()});var t1={};h(t1,{runStatus:()=>gQ});import{existsSync as v,readFileSync as U$,readdirSync as l1,statSync as d1}from"fs";import{resolve as D,basename as xQ}from"path";import{homedir as NQ}from"os";async function DQ(){if(await f("jq"))return!0;return process.stdout.write(`${T}Error: jq is required but not installed.${q}
|
|
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)
|
|
@@ -789,4 +789,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
|
|
|
789
789
|
`),2}default:return process.stderr.write(`Unknown command: ${Q}
|
|
790
790
|
`),process.stderr.write(o6),2}}p1();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var ZZ=await QZ(Bun.argv.slice(2));process.exit(ZZ);
|
|
791
791
|
|
|
792
|
-
//# debugId=
|
|
792
|
+
//# debugId=92753F401EF6DED164756E2164756E21
|
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": "7.
|
|
4
|
+
"version": "7.37.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 11 quality gates. Provider-agnostic (Claude Code, OpenAI Codex, Cline, Aider).",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"agent",
|