loki-mode 7.28.1 → 7.29.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/README.md +30 -19
- package/SKILL.md +8 -2
- package/VERSION +1 -1
- package/autonomy/loki +273 -30
- package/autonomy/provider-offer.sh +249 -0
- package/autonomy/quickstart.sh +584 -0
- package/dashboard/__init__.py +1 -1
- package/docs/INSTALLATION.md +10 -1
- package/docs/alternative-installations.md +1 -1
- package/loki-ts/dist/loki.js +208 -208
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/templates/simple-todo-app.md +13 -144
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# provider-offer.sh -- shared, self-contained provider install offer (v7.29.0).
|
|
3
|
+
#
|
|
4
|
+
# Single source of truth for "no AI provider CLI found" handling, used by BOTH
|
|
5
|
+
# the bash CLI (autonomy/loki, sourced) and the Bun-routed doctor
|
|
6
|
+
# (loki-ts/src/commands/doctor.ts, via child_process). Parity is by
|
|
7
|
+
# construction: there is exactly one prompt + npm install + login handoff
|
|
8
|
+
# implementation, and both routes call it.
|
|
9
|
+
#
|
|
10
|
+
# Self-containment contract (load-bearing for parity): this file depends ONLY
|
|
11
|
+
# on bash builtins + npm/claude on PATH. It defines its own colors and never
|
|
12
|
+
# reads $RED/$NC or any other variable owned by autonomy/loki, because when
|
|
13
|
+
# doctor.ts spawns it standalone those variables are unset. If this file ever
|
|
14
|
+
# starts depending on loki's environment, the bash-route and Bun-route bytes
|
|
15
|
+
# diverge and the bun-parity matrix breaks.
|
|
16
|
+
#
|
|
17
|
+
# Security posture (design 1.7): the ONLY command ever executed on the user's
|
|
18
|
+
# behalf is `npm install -g @anthropic-ai/claude-code`, only after explicit
|
|
19
|
+
# consent, with the exact command printed first. No sudo. No curl-pipe-bash.
|
|
20
|
+
# Non-interactive / CI contexts never run an install.
|
|
21
|
+
|
|
22
|
+
# Guard against double-source (loki may source this more than once via reloads).
|
|
23
|
+
if [ -n "${_LOKI_PROVIDER_OFFER_SOURCED:-}" ]; then
|
|
24
|
+
return 0 2>/dev/null || true
|
|
25
|
+
fi
|
|
26
|
+
_LOKI_PROVIDER_OFFER_SOURCED=1
|
|
27
|
+
|
|
28
|
+
# --- Self-contained colors (honor NO_COLOR; no dependency on loki) ----------
|
|
29
|
+
if [ -n "${NO_COLOR:-}" ] || [ ! -t 1 ]; then
|
|
30
|
+
_PO_RED=''; _PO_YELLOW=''; _PO_BOLD=''; _PO_DIM=''; _PO_NC=''
|
|
31
|
+
else
|
|
32
|
+
_PO_RED=$'\033[0;31m'
|
|
33
|
+
_PO_YELLOW=$'\033[1;33m'
|
|
34
|
+
_PO_BOLD=$'\033[1m'
|
|
35
|
+
_PO_NC=$'\033[0m'
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
# The one canonical install command. Quoted everywhere; never re-derived.
|
|
39
|
+
_PO_INSTALL_CMD="npm install -g @anthropic-ai/claude-code"
|
|
40
|
+
|
|
41
|
+
# detect_any_provider: true (0) if any supported provider CLI is on PATH.
|
|
42
|
+
# Extracted verbatim from the loki doctor detection loop (design 1.2).
|
|
43
|
+
detect_any_provider() {
|
|
44
|
+
local _dp
|
|
45
|
+
for _dp in claude codex cline aider; do
|
|
46
|
+
command -v "$_dp" >/dev/null 2>&1 && return 0
|
|
47
|
+
done
|
|
48
|
+
return 1
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# _po_assume_yes: true when the user has opted into unattended confirmation.
|
|
52
|
+
# Honors --yes (LOKI_AUTO_CONFIRM, set by loki:1013) and LOKI_ASSUME_YES.
|
|
53
|
+
_po_assume_yes() {
|
|
54
|
+
[ "${LOKI_ASSUME_YES:-}" = "1" ] && return 0
|
|
55
|
+
[ "${LOKI_AUTO_CONFIRM:-}" = "true" ] && return 0
|
|
56
|
+
return 1
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
# _po_non_interactive: true when we must NEVER prompt (non-TTY or CI).
|
|
60
|
+
# Mirrors cmd_welcome_maybe_firstrun (loki:4286) and maybe_show_auto_plan.
|
|
61
|
+
_po_non_interactive() {
|
|
62
|
+
[ ! -t 1 ] && return 0
|
|
63
|
+
[ ! -t 0 ] && return 0
|
|
64
|
+
[ -n "${CI:-}" ] && return 0
|
|
65
|
+
return 1
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
# _po_run_login: offer (or auto-accept) the claude auth login handoff after a
|
|
69
|
+
# successful install. Inherited stdio; Loki never handles credentials.
|
|
70
|
+
_po_run_login() {
|
|
71
|
+
# claude must actually be on PATH for login to make sense.
|
|
72
|
+
if ! command -v claude >/dev/null 2>&1; then
|
|
73
|
+
printf "%sInstalled, but 'claude' is not on your PATH yet. You may need to restart your shell or add npm's global bin to PATH (npm config get prefix). Run 'loki doctor' to recheck.%s\n" "$_PO_YELLOW" "$_PO_NC"
|
|
74
|
+
return 0
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
local do_login=""
|
|
78
|
+
if _po_assume_yes; then
|
|
79
|
+
do_login="y"
|
|
80
|
+
else
|
|
81
|
+
printf 'Claude Code installed.\n'
|
|
82
|
+
printf '\n'
|
|
83
|
+
printf 'You still need to authenticate. Run the login flow now? [Y/n] '
|
|
84
|
+
read -r do_login || do_login="n"
|
|
85
|
+
fi
|
|
86
|
+
case "$do_login" in
|
|
87
|
+
""|y|Y|yes|YES)
|
|
88
|
+
if claude auth login; then
|
|
89
|
+
# Do not trust the exit code alone: verify the session is
|
|
90
|
+
# actually authenticated before claiming readiness (council
|
|
91
|
+
# HIGH: the old path could falsely report success).
|
|
92
|
+
if claude auth status 2>/dev/null | grep -q '"loggedIn"[[:space:]]*:[[:space:]]*true'; then
|
|
93
|
+
printf "%sProvider ready. Run 'loki doctor' to confirm, or 'loki quickstart' to build.%s\n" "$_PO_BOLD" "$_PO_NC"
|
|
94
|
+
return 0
|
|
95
|
+
fi
|
|
96
|
+
printf "Login finished but authentication could not be confirmed. Run 'claude auth status' to check, then 'loki doctor'.\n"
|
|
97
|
+
return 0
|
|
98
|
+
fi
|
|
99
|
+
printf "Login not completed. Run 'claude auth login' when ready, then 'loki doctor'.\n"
|
|
100
|
+
return 0
|
|
101
|
+
;;
|
|
102
|
+
*)
|
|
103
|
+
printf "Login not completed. Run 'claude auth login' when ready, then 'loki doctor'.\n"
|
|
104
|
+
return 0
|
|
105
|
+
;;
|
|
106
|
+
esac
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
# _po_do_install: run the one consented command, print it first, handle result.
|
|
110
|
+
# Returns 0 on success, non-zero on failure (caller decides exit behavior).
|
|
111
|
+
_po_do_install() {
|
|
112
|
+
printf 'Installing Claude Code (%s) ...\n' "$_PO_INSTALL_CMD"
|
|
113
|
+
# The exact, fixed argv. No interpolation, no extra flags. (design 1.7)
|
|
114
|
+
# Capture npm's exit code directly (not via `if`, whose statement status is
|
|
115
|
+
# 0 when the condition is false with no else, masking the real npm code).
|
|
116
|
+
local code=0
|
|
117
|
+
npm install -g @anthropic-ai/claude-code || code=$?
|
|
118
|
+
if [ "$code" -eq 0 ]; then
|
|
119
|
+
printf '\n'
|
|
120
|
+
_po_run_login
|
|
121
|
+
return 0
|
|
122
|
+
fi
|
|
123
|
+
printf '%sInstall failed (npm exited %s). You can retry manually:%s\n' "$_PO_RED" "$code" "$_PO_NC"
|
|
124
|
+
printf ' %s\n' "$_PO_INSTALL_CMD"
|
|
125
|
+
printf 'If this is a permissions error, see https://docs.npmjs.com/resolving-eacces-permissions-errors\n'
|
|
126
|
+
return "$code"
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
# offer_provider_install <mode>
|
|
130
|
+
# mode = "report" -> doctor: append the offer on a TTY; on non-TTY/CI do
|
|
131
|
+
# NOTHING (doctor already printed the FAIL + install line,
|
|
132
|
+
# and we must keep non-TTY/json bytes identical for parity).
|
|
133
|
+
# Never exits the process.
|
|
134
|
+
# mode = "gate" -> start/demo/quick pre-flight: on non-TTY/CI print the
|
|
135
|
+
# honest one-liner to stderr and return 2. On a TTY, prompt;
|
|
136
|
+
# on decline return 2. On accept install + login.
|
|
137
|
+
#
|
|
138
|
+
# Honors:
|
|
139
|
+
# LOKI_NO_INSTALL_OFFER=1 -> never prompt; print manual command (1.4)
|
|
140
|
+
# --yes / LOKI_ASSUME_YES -> auto-accept install + login (1.4)
|
|
141
|
+
offer_provider_install() {
|
|
142
|
+
local mode="${1:-gate}"
|
|
143
|
+
|
|
144
|
+
# Opt-out: never offer, just surface the manual command.
|
|
145
|
+
if [ "${LOKI_NO_INSTALL_OFFER:-}" = "1" ]; then
|
|
146
|
+
if [ "$mode" = "gate" ]; then
|
|
147
|
+
printf 'No AI provider CLI found. Install one when ready:\n' >&2
|
|
148
|
+
printf ' %s (then: claude auth login)\n' "$_PO_INSTALL_CMD" >&2
|
|
149
|
+
return 2
|
|
150
|
+
fi
|
|
151
|
+
printf '\n'
|
|
152
|
+
printf 'Install a provider when ready:\n'
|
|
153
|
+
printf ' %s (then: claude auth login)\n' "$_PO_INSTALL_CMD"
|
|
154
|
+
printf ' Other supported providers: codex, cline, aider.\n'
|
|
155
|
+
return 0
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
# Non-interactive / CI: NEVER prompt, NEVER install.
|
|
159
|
+
#
|
|
160
|
+
# gate (start/demo/quick): print the honest one-liner to stderr and return 2
|
|
161
|
+
# so the caller exits with an actionable message before any spend.
|
|
162
|
+
# report (doctor): stay SILENT. doctor has already printed the FAIL line and
|
|
163
|
+
# the install command on stdout, so no information is lost. Silence here is
|
|
164
|
+
# load-bearing for parity: doctor.ts gates its child_process bridge on
|
|
165
|
+
# process.stdout.isTTY, so on a non-TTY/CI run the Bun route emits nothing
|
|
166
|
+
# extra. If report-mode printed a stderr line, the bash route would diverge
|
|
167
|
+
# from Bun in exactly the no-provider/non-TTY case the bun-parity matrix
|
|
168
|
+
# captures (2>&1) on CI runners, which have no provider installed.
|
|
169
|
+
if _po_non_interactive; then
|
|
170
|
+
if [ "$mode" = "gate" ]; then
|
|
171
|
+
printf 'No AI provider CLI found; cannot prompt to install in a non-interactive shell. Run: %s\n' "$_PO_INSTALL_CMD" >&2
|
|
172
|
+
return 2
|
|
173
|
+
fi
|
|
174
|
+
return 0
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
# npm missing: degraded path, never attempt a non-npm install.
|
|
178
|
+
if ! command -v npm >/dev/null 2>&1; then
|
|
179
|
+
printf '\n'
|
|
180
|
+
printf '%sNo AI provider CLI was found, and npm is not installed either, so Loki%s\n' "$_PO_BOLD" "$_PO_NC"
|
|
181
|
+
printf 'cannot install one for you.\n'
|
|
182
|
+
printf '\n'
|
|
183
|
+
printf 'Install Node.js + npm first (https://nodejs.org), then run:\n'
|
|
184
|
+
printf ' %s\n' "$_PO_INSTALL_CMD"
|
|
185
|
+
printf ' claude auth login\n'
|
|
186
|
+
printf '\n'
|
|
187
|
+
printf "Already have a provider via another method? Make sure 'claude' (or codex,\n"
|
|
188
|
+
printf "cline, aider) is on your PATH, then run 'loki doctor'.\n"
|
|
189
|
+
[ "$mode" = "gate" ] && return 2
|
|
190
|
+
return 0
|
|
191
|
+
fi
|
|
192
|
+
|
|
193
|
+
# TTY, npm present: the interactive offer.
|
|
194
|
+
printf '\n'
|
|
195
|
+
printf 'No AI provider CLI was found. Loki needs one agent CLI to run a build.\n'
|
|
196
|
+
printf '\n'
|
|
197
|
+
printf 'Claude Code is the recommended provider (full feature support).\n'
|
|
198
|
+
printf ' Install: %s\n' "$_PO_INSTALL_CMD"
|
|
199
|
+
printf ' Then: claude auth login\n'
|
|
200
|
+
printf '\n'
|
|
201
|
+
|
|
202
|
+
local answer=""
|
|
203
|
+
if _po_assume_yes; then
|
|
204
|
+
answer="y"
|
|
205
|
+
else
|
|
206
|
+
printf 'Install Claude Code now? [Y/n] '
|
|
207
|
+
read -r answer || answer="n"
|
|
208
|
+
fi
|
|
209
|
+
|
|
210
|
+
case "$answer" in
|
|
211
|
+
""|y|Y|yes|YES)
|
|
212
|
+
if _po_do_install; then
|
|
213
|
+
return 0
|
|
214
|
+
fi
|
|
215
|
+
# Install failed: honest failure already printed by _po_do_install.
|
|
216
|
+
[ "$mode" = "gate" ] && return 2
|
|
217
|
+
return 1
|
|
218
|
+
;;
|
|
219
|
+
*)
|
|
220
|
+
printf 'Skipped. Install a provider when ready:\n'
|
|
221
|
+
printf ' %s (then: claude auth login)\n' "$_PO_INSTALL_CMD"
|
|
222
|
+
printf 'Other supported providers: codex, cline, aider.\n'
|
|
223
|
+
[ "$mode" = "gate" ] && return 2
|
|
224
|
+
return 0
|
|
225
|
+
;;
|
|
226
|
+
esac
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
# provider_offer_gate: convenience wrapper for the start/demo/quick pre-flight.
|
|
230
|
+
# Returns 0 if a provider is present (or one was just installed); returns 2 to
|
|
231
|
+
# signal the caller should `exit 2` (no provider, declined or non-interactive).
|
|
232
|
+
provider_offer_gate() {
|
|
233
|
+
detect_any_provider && return 0
|
|
234
|
+
offer_provider_install gate || return 2
|
|
235
|
+
# After an accepted install, re-detect; if still absent, fail the gate.
|
|
236
|
+
detect_any_provider && return 0
|
|
237
|
+
return 2
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
# Executed directly (doctor.ts child_process bridge, or manual): run the offer.
|
|
241
|
+
# When sourced by autonomy/loki, this block does not run.
|
|
242
|
+
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
|
|
243
|
+
case "${1:-report}" in
|
|
244
|
+
offer|report) offer_provider_install report ;;
|
|
245
|
+
gate) offer_provider_install gate ;;
|
|
246
|
+
detect) detect_any_provider ;;
|
|
247
|
+
*) offer_provider_install report ;;
|
|
248
|
+
esac
|
|
249
|
+
fi
|