loki-mode 7.7.34 → 7.8.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 CHANGED
@@ -3,7 +3,7 @@ name: loki-mode
3
3
  description: Autonomous spec-to-product system. Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product via the RARV-C closure loop, with minimal human intervention. Provider-agnostic. Requires --dangerously-skip-permissions flag.
4
4
  ---
5
5
 
6
- # Loki Mode v7.7.34
6
+ # Loki Mode v7.8.0
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.34 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
384
+ **v7.8.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 7.7.34
1
+ 7.8.0
package/autonomy/run.sh CHANGED
@@ -11222,6 +11222,26 @@ except Exception as exc:
11222
11222
  && loki_claude_flag_supported "--append-system-prompt"; then
11223
11223
  _loki_claude_argv+=("--append-system-prompt" "$(_loki_autonomy_override_text)")
11224
11224
  fi
11225
+ # v7.8.0: explicit settings precedence. Pin the loaded settings sources
11226
+ # so Loki's invocation does not drift if Claude Code changes its implicit
11227
+ # default. Behavior-neutral (these are the standard sources). Gated +
11228
+ # falls back to the implicit default when unsupported. Opt out with
11229
+ # LOKI_SETTING_SOURCES=off.
11230
+ if [ "${LOKI_SETTING_SOURCES:-on}" != "off" ] \
11231
+ && type loki_claude_flag_supported >/dev/null 2>&1 \
11232
+ && loki_claude_flag_supported "--setting-sources"; then
11233
+ _loki_claude_argv+=("--setting-sources" "user,project,local")
11234
+ fi
11235
+ # v7.8.0: stream partial assistant deltas so the dashboard renders the
11236
+ # agent's output in real time instead of only at message boundaries. The
11237
+ # stream-json parser below handles the partial event type additively and
11238
+ # ignores it if unrecognized. Gated + fallback. Opt out with
11239
+ # LOKI_PARTIAL_MESSAGES=off.
11240
+ if [ "${LOKI_PARTIAL_MESSAGES:-on}" != "off" ] \
11241
+ && type loki_claude_flag_supported >/dev/null 2>&1 \
11242
+ && loki_claude_flag_supported "--include-partial-messages"; then
11243
+ _loki_claude_argv+=("--include-partial-messages")
11244
+ fi
11225
11245
  case "${PROVIDER_NAME:-claude}" in
11226
11246
  claude)
11227
11247
  # Claude: Full features with stream-json output and agent tracking
@@ -11365,6 +11385,12 @@ def process_stream():
11365
11385
  init_orchestrator()
11366
11386
  print(f"{MAGENTA}[Orchestrator Active]{NC} Main agent started", flush=True)
11367
11387
 
11388
+ # v7.8.0: track whether the current assistant message text was already
11389
+ # streamed live via --include-partial-messages stream_event deltas, so the
11390
+ # final assistant block does not re-print it. Reset after each assistant
11391
+ # message. Stays False when partial messages are off (no stream_event lines).
11392
+ streamed_text_blocks = False
11393
+
11368
11394
  for line in sys.stdin:
11369
11395
  line = line.strip()
11370
11396
  if not line:
@@ -11373,6 +11399,29 @@ def process_stream():
11373
11399
  data = json.loads(line)
11374
11400
  msg_type = data.get("type", "")
11375
11401
 
11402
+ # v7.8.0: --include-partial-messages emits incremental stream_event
11403
+ # records (content_block_delta) BEFORE the final assistant message.
11404
+ # Render the delta text live so the dashboard/terminal shows progress
11405
+ # in real time, and remember that we streamed it so the final
11406
+ # assistant block does not print the same text again (double-print).
11407
+ # Purely additive: if partial messages are off, no stream_event lines
11408
+ # arrive and this branch never fires.
11409
+ if msg_type == "stream_event":
11410
+ ev = data.get("event", {})
11411
+ ev_type = ev.get("type")
11412
+ if ev_type == "message_start":
11413
+ # New message beginning: reset the streamed-text tracker so
11414
+ # the deltas of this message are tracked independently.
11415
+ streamed_text_blocks = False
11416
+ elif ev_type == "content_block_delta":
11417
+ delta = ev.get("delta", {})
11418
+ if delta.get("type") == "text_delta":
11419
+ dtext = delta.get("text", "")
11420
+ if dtext:
11421
+ print(dtext, end="", flush=True)
11422
+ streamed_text_blocks = True
11423
+ continue
11424
+
11376
11425
  if msg_type == "assistant":
11377
11426
  # Extract and print assistant text
11378
11427
  message = data.get("message", {})
@@ -11380,7 +11429,9 @@ def process_stream():
11380
11429
  for item in content:
11381
11430
  if item.get("type") == "text":
11382
11431
  text = item.get("text", "")
11383
- if text:
11432
+ # Skip if we already streamed this text via stream_event
11433
+ # deltas (avoids printing the full message a second time).
11434
+ if text and not streamed_text_blocks:
11384
11435
  print(text, end="", flush=True)
11385
11436
  elif item.get("type") == "tool_use":
11386
11437
  tool = item.get("name", "unknown")
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "7.7.34"
10
+ __version__ = "7.8.0"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -2,7 +2,7 @@
2
2
 
3
3
  The flagship product of [Autonomi](https://www.autonomi.dev/). Complete installation instructions for all platforms and use cases.
4
4
 
5
- **Version:** v7.7.34
5
+ **Version:** v7.8.0
6
6
 
7
7
  ---
8
8
 
@@ -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 v=(K,$)=>{for(var Q in $)_7(K,Q,{get:$[Q],enumerable:!0,configurable:!0,set:P7.bind($,Q)})};var w=(K,$)=>()=>(K&&($=K(K=0)),$);var t=import.meta.require;var e1={};v(e1,{lokiDir:()=>L,homeLokiDir:()=>k1,findRepoRootForVersion:()=>S1,REPO_ROOT:()=>p});import{resolve as u,dirname as N1}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 Q=N1(K);if(Q===K)break;K=Q}return u(i1,"..","..","..")}function S1(K){let $=K;for(let Q=0;Q<6;Q++){if(J1(u($,"VERSION"))&&J1(u($,"autonomy/run.sh")))return $;let X=N1($);if(X===$)break;$=X}return u(K,"..","..","..")}function L(){return process.env.LOKI_DIR??u(process.cwd(),".loki")}function k1(){return u(R7(),".loki")}var i1,p;var g=w(()=>{i1=N1(L7(import.meta.url));p=E7()});import{readFileSync as w7}from"fs";import{resolve as x7,dirname as F7}from"path";import{fileURLToPath as N7}from"url";function G1(){if(o!==null)return o;let K="7.7.34";if(typeof K==="string"&&K.length>0)return o=K,o;try{let $=F7(N7(import.meta.url)),Q=S1($);o=w7(x7(Q,"VERSION"),"utf-8").trim()}catch{o="unknown"}return o}var o=null;var C1=w(()=>{g()});var $0={};v($0,{runOrThrow:()=>S7,run:()=>C,commandVersion:()=>C7,commandExists:()=>b,ShellError:()=>D1});async function C(K,$={}){let Q=Bun.spawn({cmd:[...K],stdout:"pipe",stderr:"pipe",env:$.env?{...process.env,...$.env}:process.env,cwd:$.cwd}),X,Z;if($.timeoutMs&&$.timeoutMs>0)X=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}Z=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},$.timeoutMs);try{let[W,z,q]=await Promise.all([new Response(Q.stdout).text(),new Response(Q.stderr).text(),Q.exited]);return{stdout:W,stderr:z,exitCode:q}}finally{if(X)clearTimeout(X);if(Z)clearTimeout(Z)}}async function S7(K,$={}){let Q=await C(K,$);if(Q.exitCode!==0)throw new D1(`command failed (${Q.exitCode}): ${K.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function b(K){let $=k7(K),Q=await C(["sh","-c",`command -v ${$}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.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 C7(K,$="--version"){if(!await b(K))return null;let X=await C([K,$],{timeoutMs:5000});if(X.exitCode!==0)return null;return((X.stdout||X.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var D1;var n=w(()=>{D1=class D1 extends Error{message;exitCode;stdout;stderr;constructor(K,$,Q,X){super(K);this.message=K;this.exitCode=$;this.stdout=Q;this.stderr=X;this.name="ShellError"}}});function c(K){return D7?"":K}var D7,F,y,N,A6,A,D,S,H;var a=w(()=>{D7=(process.env.NO_COLOR??"").length>0;F=c("\x1B[0;31m"),y=c("\x1B[0;32m"),N=c("\x1B[1;33m"),A6=c("\x1B[0;34m"),A=c("\x1B[0;36m"),D=c("\x1B[1m"),S=c("\x1B[2m"),H=c("\x1B[0m")});import{existsSync as c7}from"fs";async function i(){if(Z1!==void 0)return Z1;let K="/opt/homebrew/bin/python3.12";if(c7(K))return Z1=K,K;let $=await b("python3.12");if($)return Z1=$,$;let Q=await b("python3");return Z1=Q,Q}async function s(K,$={}){let Q=await i();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return C([Q,"-c",K],$)}var Z1;var z1=w(()=>{n()});var G0={};v(G0,{runStatus:()=>X5});import{existsSync as k,readFileSync as K1,readdirSync as W0,statSync as H0}from"fs";import{resolve as R,basename as a7}from"path";import{homedir as s7}from"os";async function t7(){if(await b("jq"))return!0;return process.stdout.write(`${F}Error: jq is required but not installed.${H}
2
+ var _7=Object.defineProperty;var I7=(K)=>K;function P7(K,$){this[K]=I7.bind(null,$)}var v=(K,$)=>{for(var Q in $)_7(K,Q,{get:$[Q],enumerable:!0,configurable:!0,set:P7.bind($,Q)})};var w=(K,$)=>()=>(K&&($=K(K=0)),$);var t=import.meta.require;var e1={};v(e1,{lokiDir:()=>L,homeLokiDir:()=>k1,findRepoRootForVersion:()=>S1,REPO_ROOT:()=>p});import{resolve as u,dirname as N1}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 Q=N1(K);if(Q===K)break;K=Q}return u(i1,"..","..","..")}function S1(K){let $=K;for(let Q=0;Q<6;Q++){if(J1(u($,"VERSION"))&&J1(u($,"autonomy/run.sh")))return $;let X=N1($);if(X===$)break;$=X}return u(K,"..","..","..")}function L(){return process.env.LOKI_DIR??u(process.cwd(),".loki")}function k1(){return u(R7(),".loki")}var i1,p;var g=w(()=>{i1=N1(L7(import.meta.url));p=E7()});import{readFileSync as w7}from"fs";import{resolve as x7,dirname as F7}from"path";import{fileURLToPath as N7}from"url";function G1(){if(o!==null)return o;let K="7.8.0";if(typeof K==="string"&&K.length>0)return o=K,o;try{let $=F7(N7(import.meta.url)),Q=S1($);o=w7(x7(Q,"VERSION"),"utf-8").trim()}catch{o="unknown"}return o}var o=null;var C1=w(()=>{g()});var $0={};v($0,{runOrThrow:()=>S7,run:()=>C,commandVersion:()=>C7,commandExists:()=>b,ShellError:()=>D1});async function C(K,$={}){let Q=Bun.spawn({cmd:[...K],stdout:"pipe",stderr:"pipe",env:$.env?{...process.env,...$.env}:process.env,cwd:$.cwd}),X,Z;if($.timeoutMs&&$.timeoutMs>0)X=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}Z=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},$.timeoutMs);try{let[W,z,q]=await Promise.all([new Response(Q.stdout).text(),new Response(Q.stderr).text(),Q.exited]);return{stdout:W,stderr:z,exitCode:q}}finally{if(X)clearTimeout(X);if(Z)clearTimeout(Z)}}async function S7(K,$={}){let Q=await C(K,$);if(Q.exitCode!==0)throw new D1(`command failed (${Q.exitCode}): ${K.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function b(K){let $=k7(K),Q=await C(["sh","-c",`command -v ${$}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.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 C7(K,$="--version"){if(!await b(K))return null;let X=await C([K,$],{timeoutMs:5000});if(X.exitCode!==0)return null;return((X.stdout||X.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var D1;var n=w(()=>{D1=class D1 extends Error{message;exitCode;stdout;stderr;constructor(K,$,Q,X){super(K);this.message=K;this.exitCode=$;this.stdout=Q;this.stderr=X;this.name="ShellError"}}});function c(K){return D7?"":K}var D7,F,y,N,A6,A,D,S,H;var a=w(()=>{D7=(process.env.NO_COLOR??"").length>0;F=c("\x1B[0;31m"),y=c("\x1B[0;32m"),N=c("\x1B[1;33m"),A6=c("\x1B[0;34m"),A=c("\x1B[0;36m"),D=c("\x1B[1m"),S=c("\x1B[2m"),H=c("\x1B[0m")});import{existsSync as c7}from"fs";async function i(){if(Z1!==void 0)return Z1;let K="/opt/homebrew/bin/python3.12";if(c7(K))return Z1=K,K;let $=await b("python3.12");if($)return Z1=$,$;let Q=await b("python3");return Z1=Q,Q}async function s(K,$={}){let Q=await i();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return C([Q,"-c",K],$)}var Z1;var z1=w(()=>{n()});var G0={};v(G0,{runStatus:()=>X5});import{existsSync as k,readFileSync as K1,readdirSync as W0,statSync as H0}from"fs";import{resolve as R,basename as a7}from"path";import{homedir as s7}from"os";async function t7(){if(await b("jq"))return!0;return process.stdout.write(`${F}Error: jq is required but not installed.${H}
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)
@@ -604,4 +604,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
604
604
  `),2}default:return process.stderr.write(`Unknown command: ${$}
605
605
  `),process.stderr.write(j7),2}}process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var Z6=await X6(Bun.argv.slice(2));process.exit(Z6);
606
606
 
607
- //# debugId=4E748539D57C6D2864756E2164756E21
607
+ //# debugId=289BCE83EBB8514D64756E2164756E21
package/mcp/__init__.py CHANGED
@@ -57,4 +57,4 @@ try:
57
57
  except ImportError:
58
58
  __all__ = ['mcp']
59
59
 
60
- __version__ = '7.7.34'
60
+ __version__ = '7.8.0'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loki-mode",
3
- "version": "7.7.34",
3
+ "version": "7.8.0",
4
4
  "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).",
5
5
  "keywords": [
6
6
  "agent",
@@ -216,6 +216,23 @@ _loki_build_claude_auto_flags() {
216
216
  && loki_claude_flag_supported "--append-system-prompt"; then
217
217
  _LOKI_CLAUDE_AUTO_FLAGS+=("--append-system-prompt" "$(_loki_autonomy_override_text)")
218
218
  fi
219
+
220
+ # --setting-sources (v7.8.0): pin the settings precedence so the invocation
221
+ # does not drift with Claude Code's implicit default. Behavior-neutral.
222
+ # Default-on; opt out with LOKI_SETTING_SOURCES=off.
223
+ if [ "${LOKI_SETTING_SOURCES:-on}" != "off" ] \
224
+ && loki_claude_flag_supported "--setting-sources"; then
225
+ _LOKI_CLAUDE_AUTO_FLAGS+=("--setting-sources" "user,project,local")
226
+ fi
227
+
228
+ # --include-partial-messages (v7.8.0): stream incremental assistant deltas
229
+ # for real-time dashboard/terminal output. The stream-json parser handles
230
+ # the stream_event type additively and de-dupes against the final message.
231
+ # Default-on; opt out with LOKI_PARTIAL_MESSAGES=off.
232
+ if [ "${LOKI_PARTIAL_MESSAGES:-on}" != "off" ] \
233
+ && loki_claude_flag_supported "--include-partial-messages"; then
234
+ _LOKI_CLAUDE_AUTO_FLAGS+=("--include-partial-messages")
235
+ fi
219
236
  }
220
237
 
221
238
  # The system-prompt text that authorizes autonomous operation and resolves