loki-mode 7.88.0 → 7.89.1
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/crash.sh +57 -30
- package/autonomy/lib/own-render.py +78 -8
- package/autonomy/lib/proof-generator.py +27 -1
- package/autonomy/lib/wiki-generator.py +192 -4
- package/autonomy/loki +141 -48
- package/autonomy/run.sh +395 -34
- package/autonomy/spec-interrogation.sh +51 -5
- package/autonomy/telemetry.sh +89 -12
- package/bin/loki +89 -8
- package/dashboard/__init__.py +1 -1
- package/dashboard/server.py +213 -0
- package/dashboard/static/assets/mermaid.min.js +2030 -0
- package/dashboard/static/index.html +328 -196
- package/dashboard/telemetry.py +62 -15
- package/docs/INSTALLATION.md +2 -2
- package/docs/PRIVACY.md +65 -38
- package/loki-ts/dist/loki.js +249 -243
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
package/autonomy/loki
CHANGED
|
@@ -1017,29 +1017,35 @@ detect_arg_type() {
|
|
|
1017
1017
|
return 0
|
|
1018
1018
|
fi
|
|
1019
1019
|
|
|
1020
|
-
#
|
|
1021
|
-
|
|
1022
|
-
echo "prd"
|
|
1023
|
-
return 0
|
|
1024
|
-
fi
|
|
1025
|
-
|
|
1026
|
-
# Existing file on disk -> PRD
|
|
1020
|
+
# An existing file on disk is unambiguously a PRD, even if its name has
|
|
1021
|
+
# spaces -- a real path the user pointed at wins over the brief heuristic.
|
|
1027
1022
|
if [ -e "$arg" ]; then
|
|
1028
1023
|
echo "prd"
|
|
1029
1024
|
return 0
|
|
1030
1025
|
fi
|
|
1031
1026
|
|
|
1032
1027
|
# R7 (zero-config first run): a one-line brief. An arg that contains
|
|
1033
|
-
#
|
|
1034
|
-
#
|
|
1035
|
-
#
|
|
1036
|
-
# "
|
|
1037
|
-
#
|
|
1028
|
+
# WHITESPACE and is not an existing file is a natural-language brief, NOT a
|
|
1029
|
+
# path -- a real PRD path argument essentially never contains spaces, whereas
|
|
1030
|
+
# a brief routinely contains slashes/punctuation ("add/list/done", "CI/CD",
|
|
1031
|
+
# "input/output"). This MUST come before the path-like (contains "/")
|
|
1032
|
+
# heuristic below, else a brief like "a todo app with add/list/done" is
|
|
1033
|
+
# misrouted to PRD mode and dies with "PRD file not found" (W1 E2E bug,
|
|
1034
|
+
# v7.89.1). The `--brief` flag remains the escape hatch for a single-word
|
|
1035
|
+
# brief with no whitespace.
|
|
1038
1036
|
if [[ "$arg" == *[[:space:]]* ]]; then
|
|
1039
1037
|
echo "brief"
|
|
1040
1038
|
return 0
|
|
1041
1039
|
fi
|
|
1042
1040
|
|
|
1041
|
+
# Path-like (contains / or starts with . or /) -> treat as PRD. Reached only
|
|
1042
|
+
# for a NO-WHITESPACE arg (a brief with spaces was already handled above), so
|
|
1043
|
+
# this is a genuine file path like ./prd.md or docs/spec.md.
|
|
1044
|
+
if [[ "$arg" == */* ]] || [[ "$arg" == .* ]] || [[ "$arg" == /* ]]; then
|
|
1045
|
+
echo "prd"
|
|
1046
|
+
return 0
|
|
1047
|
+
fi
|
|
1048
|
+
|
|
1043
1049
|
# Fallback: unknown. Caller treats as PRD for backward compat.
|
|
1044
1050
|
echo "unknown"
|
|
1045
1051
|
}
|
|
@@ -5315,14 +5321,17 @@ cmd_welcome_terminal() {
|
|
|
5315
5321
|
echo -e " Quick start: ${BOLD}loki quickstart${NC} (from your idea) or ${BOLD}loki start ./prd.md${NC} (from a spec)"
|
|
5316
5322
|
echo -e " Docs: ${BOLD}https://www.autonomi.dev/docs${NC}"
|
|
5317
5323
|
echo ""
|
|
5324
|
+
# One-time honest disclosure (this welcome screen shows once, via the
|
|
5325
|
+
# WELCOME_MARKER). On-by-default anonymous diagnostics must be disclosed
|
|
5326
|
+
# somewhere so collection is never covert; this single line is that
|
|
5327
|
+
# disclosure. It is NOT repeated on later runs. Enterprise/CI/air-gapped
|
|
5328
|
+
# installs auto-disable collection, so the line only appears when it is
|
|
5329
|
+
# actually on. Opt out anytime: loki telemetry off.
|
|
5318
5330
|
if _loki_welcome_analytics_on; then
|
|
5319
|
-
echo -e " ${DIM}Anonymous
|
|
5320
|
-
echo -e " ${DIM}
|
|
5321
|
-
|
|
5322
|
-
echo -e " ${DIM}Anonymous analytics are off by default. Nothing is sent unless you${NC}"
|
|
5323
|
-
echo -e " ${DIM}opt in with: loki telemetry on${NC}"
|
|
5331
|
+
echo -e " ${DIM}Anonymous diagnostics on (os/arch/version/error type only -- never${NC}"
|
|
5332
|
+
echo -e " ${DIM}code, prompts, or paths). Off: loki telemetry off - docs/PRIVACY.md${NC}"
|
|
5333
|
+
echo ""
|
|
5324
5334
|
fi
|
|
5325
|
-
echo ""
|
|
5326
5335
|
}
|
|
5327
5336
|
|
|
5328
5337
|
cmd_welcome() {
|
|
@@ -5419,7 +5428,7 @@ cmd_web() {
|
|
|
5419
5428
|
case "$subcommand" in
|
|
5420
5429
|
start)
|
|
5421
5430
|
shift || true
|
|
5422
|
-
|
|
5431
|
+
cmd_web_redirect_to_dashboard "$@"
|
|
5423
5432
|
;;
|
|
5424
5433
|
stop)
|
|
5425
5434
|
cmd_web_stop
|
|
@@ -5449,51 +5458,87 @@ cmd_web() {
|
|
|
5449
5458
|
*)
|
|
5450
5459
|
# Treat unknown args as options to start (e.g., loki web --no-open)
|
|
5451
5460
|
shift
|
|
5452
|
-
|
|
5461
|
+
cmd_web_redirect_to_dashboard "$subcommand" "$@"
|
|
5453
5462
|
;;
|
|
5454
5463
|
esac
|
|
5455
5464
|
}
|
|
5456
5465
|
|
|
5466
|
+
# v7.x (F55): `loki web` (the command a user intuitively types) used to launch
|
|
5467
|
+
# the deprecated Purple Lab, whose '/' redirects to '/lab/' and whose port has
|
|
5468
|
+
# none of the real dashboard APIs (/api/status, /trust, etc. all 404). A user
|
|
5469
|
+
# typing the obvious command landed on the wrong, broken-looking surface. The
|
|
5470
|
+
# value-preserving fix: the START path now launches the real dashboard instead.
|
|
5471
|
+
# 'loki web stop|status|logs' still operate on Purple Lab so anyone who started
|
|
5472
|
+
# it the old way (or via scripts) is never stranded. The deprecation banner has
|
|
5473
|
+
# already printed in cmd_web() before we get here.
|
|
5474
|
+
cmd_web_redirect_to_dashboard() {
|
|
5475
|
+
# The dashboard start path does not accept Purple-Lab-only flags
|
|
5476
|
+
# (--no-open, --prd). Filter them so `loki web --no-open` (used in CI) and
|
|
5477
|
+
# `loki web --prd X` keep working instead of erroring on an unknown option.
|
|
5478
|
+
# --port is shared and passes straight through.
|
|
5479
|
+
local orig_args=("$@")
|
|
5480
|
+
local dash_args=()
|
|
5481
|
+
while [[ $# -gt 0 ]]; do
|
|
5482
|
+
case "$1" in
|
|
5483
|
+
--no-open)
|
|
5484
|
+
# Dashboard has no browser-open behavior to suppress; drop it.
|
|
5485
|
+
shift
|
|
5486
|
+
;;
|
|
5487
|
+
--prd)
|
|
5488
|
+
# Purple-Lab-only prefill; not supported by the dashboard.
|
|
5489
|
+
shift 2 2>/dev/null || shift
|
|
5490
|
+
;;
|
|
5491
|
+
--prd=*)
|
|
5492
|
+
shift
|
|
5493
|
+
;;
|
|
5494
|
+
*)
|
|
5495
|
+
dash_args+=("$1")
|
|
5496
|
+
shift
|
|
5497
|
+
;;
|
|
5498
|
+
esac
|
|
5499
|
+
done
|
|
5500
|
+
|
|
5501
|
+
# Safe empty-array expansion (bash 3.2 + set -u): ${arr[@]+"${arr[@]}"}
|
|
5502
|
+
if ! _deprecated_alias_should_suppress ${orig_args[@]+"${orig_args[@]}"}; then
|
|
5503
|
+
echo "Launching the dashboard (http://localhost:${DASHBOARD_DEFAULT_PORT}) instead of the deprecated Purple Lab." >&2
|
|
5504
|
+
fi
|
|
5505
|
+
cmd_dashboard_start ${dash_args[@]+"${dash_args[@]}"}
|
|
5506
|
+
}
|
|
5507
|
+
|
|
5457
5508
|
cmd_web_help() {
|
|
5458
5509
|
echo -e "${BOLD}Purple Lab -- Loki Mode Web UI (deprecated -- use the dashboard)${NC}"
|
|
5459
5510
|
echo ""
|
|
5460
5511
|
echo "Usage: loki web [command] [options]"
|
|
5461
5512
|
echo ""
|
|
5462
5513
|
echo "DEPRECATED as of v7.44.0: Purple Lab is consolidated into the dashboard."
|
|
5463
|
-
echo "
|
|
5464
|
-
echo "
|
|
5465
|
-
echo "
|
|
5466
|
-
echo " '
|
|
5467
|
-
echo " but it will be removed in a future release. Migrate to the dashboard."
|
|
5514
|
+
echo " 'loki web' (no subcommand) now LAUNCHES THE DASHBOARD"
|
|
5515
|
+
echo " (http://localhost:${DASHBOARD_DEFAULT_PORT}) instead of the deprecated Purple"
|
|
5516
|
+
echo " Lab, so the obvious command lands you on the working UI. Use the embedded"
|
|
5517
|
+
echo " 'Lab' tab there to submit a PRD. For the hosted platform, see Autonomi Cloud."
|
|
5468
5518
|
echo ""
|
|
5469
|
-
echo "Note:
|
|
5470
|
-
echo "
|
|
5471
|
-
echo " Use 'loki dashboard' to monitor running agents, tasks, costs, council, escalations."
|
|
5519
|
+
echo "Note: the canonical command is 'loki dashboard' (operations UI, port ${DASHBOARD_DEFAULT_PORT})."
|
|
5520
|
+
echo " Use it to monitor running agents, tasks, costs, council, escalations."
|
|
5472
5521
|
echo ""
|
|
5473
5522
|
echo "Commands:"
|
|
5474
|
-
echo " start
|
|
5475
|
-
echo " stop Stop Purple Lab server"
|
|
5523
|
+
echo " start Launch the dashboard (default; Purple Lab is deprecated)"
|
|
5524
|
+
echo " stop Stop the Purple Lab server (if one was started the old way)"
|
|
5476
5525
|
echo " status Show Purple Lab server status"
|
|
5477
5526
|
echo " logs Show Purple Lab server logs"
|
|
5478
5527
|
echo " help Show this help"
|
|
5479
5528
|
echo ""
|
|
5480
5529
|
echo "Options (for start):"
|
|
5481
|
-
echo " --
|
|
5482
|
-
echo " --
|
|
5483
|
-
echo ""
|
|
5484
|
-
echo "Purple Lab is the product UI where you input PRDs and watch agents build."
|
|
5485
|
-
echo "It runs its own backend (web-app/server.py) on port ${PURPLE_LAB_DEFAULT_PORT}."
|
|
5530
|
+
echo " --port PORT Use custom port (default: ${DASHBOARD_DEFAULT_PORT})"
|
|
5531
|
+
echo " --no-open Accepted for back-compat; ignored (no-op on the dashboard)"
|
|
5486
5532
|
echo ""
|
|
5487
5533
|
echo "Examples:"
|
|
5488
|
-
echo " loki web
|
|
5489
|
-
echo " loki web --no-open
|
|
5490
|
-
echo " loki web stop Stop
|
|
5534
|
+
echo " loki web Launch the dashboard"
|
|
5535
|
+
echo " loki web --no-open Launch the dashboard (--no-open is a no-op)"
|
|
5536
|
+
echo " loki web stop Stop a Purple Lab server started the old way"
|
|
5491
5537
|
echo ""
|
|
5492
5538
|
echo "Note (since v7.5.30):"
|
|
5493
|
-
echo "
|
|
5494
|
-
echo "
|
|
5495
|
-
echo "
|
|
5496
|
-
echo " supported (Rule 0); both modes serve the same React bundle."
|
|
5539
|
+
echo " The same PRD-input UI is embedded in the dashboard as a 'Lab' sidebar entry."
|
|
5540
|
+
echo " 'loki web stop|status|logs' still operate on a standalone Purple Lab"
|
|
5541
|
+
echo " process so anyone who started one the old way is never stranded."
|
|
5497
5542
|
}
|
|
5498
5543
|
|
|
5499
5544
|
cmd_web_start() {
|
|
@@ -16110,6 +16155,18 @@ worktree wt projects cp rc trust-metrics serve agent code self_update test help
|
|
|
16110
16155
|
|
|
16111
16156
|
# Main command dispatcher
|
|
16112
16157
|
main() {
|
|
16158
|
+
# v7.89.0 telemetry TTY fix (council cH_r1 AC1): resolve interactivity EXACTLY
|
|
16159
|
+
# ONCE here, while autonomy/loki main still owns the user's real TTY, and
|
|
16160
|
+
# export the explicit signal that the telemetry/crash gates trust instead of a
|
|
16161
|
+
# late `-t` re-probe. When invoked via the bin/loki shim the var is already
|
|
16162
|
+
# exported (and re-exporting the same value is a no-op); this covers the path
|
|
16163
|
+
# where autonomy/loki is invoked directly (LOKI_LEGACY_BASH, no-Bun, or a
|
|
16164
|
+
# direct call). Only set when a terminal is actually present; leave UNSET
|
|
16165
|
+
# otherwise so isolated gate unit tests fall back to their own `-t` probe.
|
|
16166
|
+
if [ -z "${LOKI_TTY_INTERACTIVE:-}" ] && { [ -t 1 ] || [ -t 0 ]; }; then
|
|
16167
|
+
export LOKI_TTY_INTERACTIVE=1
|
|
16168
|
+
fi
|
|
16169
|
+
|
|
16113
16170
|
# v7.5.18: early guard -- LOKI_PROVIDER=gemini is no longer supported.
|
|
16114
16171
|
if [ "${LOKI_PROVIDER:-}" = "gemini" ]; then
|
|
16115
16172
|
echo -e "${RED}Error: Provider 'gemini' is deprecated as of v7.5.18 and has been removed.${NC}" >&2
|
|
@@ -16131,6 +16188,19 @@ main() {
|
|
|
16131
16188
|
# v7.4.13: first-run telemetry moved to bin/loki shim so it fires for
|
|
16132
16189
|
# both Bun-routed and bash-routed commands (autonomy/loki main() never
|
|
16133
16190
|
# runs for the 8 ported commands). Marker file: ~/.loki-first-run.
|
|
16191
|
+
#
|
|
16192
|
+
# v7.89.0 (council cH_r1 AC4): this is a FOREGROUND egress on the bash route.
|
|
16193
|
+
# Before it can phone home, the user must have seen the disclosure once -- a
|
|
16194
|
+
# bash-routed first command must never be covert. Evaluate the SAME gate the
|
|
16195
|
+
# egress uses, and if collection is genuinely enabled, disclose once (shared
|
|
16196
|
+
# impl from telemetry.sh, keyed on its own marker, so it never double-prints
|
|
16197
|
+
# with the Bun route or repeats). loki_telemetry itself re-checks the gate, so
|
|
16198
|
+
# this only adds the disclosure; it never changes whether we send.
|
|
16199
|
+
if declare -f _loki_telemetry_enabled >/dev/null 2>&1 \
|
|
16200
|
+
&& declare -f _loki_disclose_telemetry_once >/dev/null 2>&1 \
|
|
16201
|
+
&& _loki_telemetry_enabled; then
|
|
16202
|
+
_loki_disclose_telemetry_once
|
|
16203
|
+
fi
|
|
16134
16204
|
loki_telemetry "cli_command" "command=$command" 2>/dev/null || true
|
|
16135
16205
|
|
|
16136
16206
|
# Unified config-file pre-pass (#691). For session commands ONLY, honor
|
|
@@ -21947,13 +22017,32 @@ try {
|
|
|
21947
22017
|
|
|
21948
22018
|
# Unified collection state (PostHog usage telemetry + crash reporting).
|
|
21949
22019
|
# loki_collection_enabled is the single source of truth (crash.sh).
|
|
21950
|
-
# Collection is
|
|
22020
|
+
# Collection is ON BY DEFAULT for individual interactive installs and
|
|
22021
|
+
# auto-off in enterprise/CI/air-gapped/non-interactive contexts; an
|
|
22022
|
+
# explicit opt-out always wins. AC8 (council cH_r1): the status copy
|
|
22023
|
+
# must distinguish "on by default" from an explicit "you opted in".
|
|
21951
22024
|
echo ""
|
|
21952
22025
|
if type loki_collection_enabled &>/dev/null; then
|
|
21953
22026
|
if loki_collection_enabled; then
|
|
21954
|
-
|
|
22027
|
+
# Detect an EXPLICIT opt-in (env LOKI_TELEMETRY=on, or the
|
|
22028
|
+
# persistent ~/.loki/config TELEMETRY_ENABLED=true written by
|
|
22029
|
+
# `loki telemetry on`). Anything else that is enabled is the
|
|
22030
|
+
# individual on-by-default path.
|
|
22031
|
+
local _telem_lower_status
|
|
22032
|
+
_telem_lower_status="$(printf '%s' "${LOKI_TELEMETRY:-}" | tr '[:upper:]' '[:lower:]')"
|
|
22033
|
+
local _explicit_optin=false
|
|
22034
|
+
if [ "$_telem_lower_status" = "on" ]; then
|
|
22035
|
+
_explicit_optin=true
|
|
22036
|
+
elif [ -f "$global_config" ] && grep -q "^TELEMETRY_ENABLED=true" "$global_config" 2>/dev/null; then
|
|
22037
|
+
_explicit_optin=true
|
|
22038
|
+
fi
|
|
22039
|
+
if [ "$_explicit_optin" = true ]; then
|
|
22040
|
+
echo -e " Collection: ${GREEN}enabled${NC} (you opted in; anonymous diagnostics; opt out with: loki telemetry off)"
|
|
22041
|
+
else
|
|
22042
|
+
echo -e " Collection: ${GREEN}on by default${NC} (anonymous diagnostics; opt out with: loki telemetry off)"
|
|
22043
|
+
fi
|
|
21955
22044
|
else
|
|
21956
|
-
echo -e " Collection: ${YELLOW}off
|
|
22045
|
+
echo -e " Collection: ${YELLOW}off${NC} (nothing sent; enterprise/CI/air-gapped or opted out; opt in with: loki telemetry on)"
|
|
21957
22046
|
fi
|
|
21958
22047
|
fi
|
|
21959
22048
|
|
|
@@ -30649,7 +30738,7 @@ cmd_proof() {
|
|
|
30649
30738
|
# "No proofs found" line -- matching the Bun route (proof.ts
|
|
30650
30739
|
# listProofs, which returns before the header when rows is empty).
|
|
30651
30740
|
if [ "$found" -eq 0 ]; then
|
|
30652
|
-
printf "%-26s %-20s %-
|
|
30741
|
+
printf "%-26s %-20s %-18s %-9s %s\n" "RUN_ID" "GENERATED_AT" "VERDICT" "COST_USD" "FILES"
|
|
30653
30742
|
fi
|
|
30654
30743
|
found=1
|
|
30655
30744
|
LOKI_PROOF_JSON="$pj" python3 - <<'PYEOF'
|
|
@@ -30667,10 +30756,14 @@ def s(v):
|
|
|
30667
30756
|
return "-" if v is None else str(v)
|
|
30668
30757
|
run_id = d.get("run_id")
|
|
30669
30758
|
gen = d.get("generated_at")
|
|
30670
|
-
verdict
|
|
30759
|
+
# The honest verdict lives in honesty.headline (VERIFIED / VERIFIED WITH GAPS /
|
|
30760
|
+
# NOT VERIFIED); fall back to legacy council.final_verdict for older proofs.
|
|
30761
|
+
verdict = (d.get("honesty") or {}).get("headline")
|
|
30762
|
+
if verdict is None:
|
|
30763
|
+
verdict = (d.get("council") or {}).get("final_verdict")
|
|
30671
30764
|
cost = (d.get("cost") or {}).get("usd")
|
|
30672
30765
|
files = (d.get("files_changed") or {}).get("count")
|
|
30673
|
-
print("{:<26} {:<20} {:<
|
|
30766
|
+
print("{:<26} {:<20} {:<18} {:<9} {}".format(
|
|
30674
30767
|
s(run_id), s(gen), s(verdict), s(cost), s(files)))
|
|
30675
30768
|
PYEOF
|
|
30676
30769
|
done
|