Some checks are pending
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / preflight (push) Waiting to run
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / vps-smoke (push) Waiting to run
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:frustration-matrix,kei-frustration-loop,kei-skill-importer,kei-projects-index,kei-projects-watcher,kei-gdrive-import,kei-leak-matrix,kei-skills,kei-gateway,kei-cron-scheduler,kei-export-trajectories,kei-backend-daytona,kei-d… (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-compute-baremetal,kei-compute-vultr,kei-compute-linode,kei-compute-digitalocean,kei-svc-systemd,kei-llm-bridge-mlx name:hosted-sleep-compute]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-diff,kei-scheduler,kei-watch,kei-prune,kei-discover,kei-brain-view,kei-hibernate,kei-ledger-sign,kei-fork name:wave13-15]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-git-gitea,kei-git-forgejo,kei-git-gitlab,kei-git-bitbucket,kei-memory-sled,kei-memory-redis,kei-memory-postgres,kei-memory-sqlite,kei-auth-google,kei-auth-apple,kei-auth-magiclink,kei-auth-webauthn,kei-notify-slack,kei-n… (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-ledger,kei-migrate,kei-changelog,kei-memory,kei-store,kei-conflict-scan,kei-refactor-engine,kei-graph-check,kei-shared,kei-dna-index,kei-pet name:core]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-machine-probe,kei-llm-ollama,kei-llm-llamacpp,kei-llm-mlx,kei-llm-router,kei-model name:llm-stack]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-router,kei-sage,kei-task,kei-chat-store,kei-crossdomain,kei-search-core,kei-content-store,kei-social-store,kei-curator,kei-auth,kei-artifact name:mcp-lbm]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:keisei,kei-forge,kei-runtime,kei-runtime-core,kei-atom-discovery,kei-agent-runtime,kei-capability,kei-provision,kei-entity-store,kei-pipe,kei-cache,kei-spawn,kei-replay name:atom-substrate]) (push) Blocked by required conditions
1. lib-onboarding.sh раскидан на 3 куба (Constructor Pattern <200 LOC):
- lib-onboarding-registry.sh (79 LOC) — парсеры providers/models.toml
+ onboarding_fallback_providers (14 провайдеров)
+ onboarding_auth_env_for_provider helper (был inline в collect_auth)
- lib-onboarding-ui.sh (189 LOC) — pick_language/transport/provider/model
+ collect_auth (whiptail/bash select)
- lib-onboarding-state.sh (57 LOC) — write_secrets + write_config
+ user-model-override.toml для kei-model-router
- lib-onboarding.sh (95 LOC) — тонкий оркестратор: should_run + run
Сам lib-onboarding.sh source'ит 3 подкуба автоматически. Глобалы
(ONBOARDING_*, REGISTRY_*, ONBOARDED_FLAG, etc.) объявлены в
оркестраторе, подкубы их используют через имена.
2. lib-menu.sh локализован:
- whiptail title + radiolist prompt через ${STR_MENU_TITLE} +
${STR_MENU_SUBSTRATE} + ${STR_MENU_PROFILE_PROMPT}.
- Plain heading тоже использует словарь.
- 12 коротких имён профилей (minimal/core/dev/...) — оставлены EN
как стабильные id (не переводятся).
3. _blocks/build-index.sh — детерминированная регенерация INDEX.md.
Группировка по 14 категорийным префиксам + "Прочие" для остальных.
Безопасно перезапускать. INDEX.md обновлён через этот скрипт
(минимальный diff — добавлена ссылка на build-index.sh в шапке).
Проверено: bash -n чисто, unit тесты onboarding_list_providers/
transports/models OK, non-TTY smoke ./install.sh --profile=minimal
--no-execute проходит.
189 lines
6.6 KiB
Bash
189 lines
6.6 KiB
Bash
# shellcheck shell=bash
|
||
# lib-onboarding-ui.sh — pick_* функции мастера (whiptail / bash select).
|
||
#
|
||
# Constructor Pattern: 1 файл = UI слой. Парсеры реестров — в registry.sh,
|
||
# state-запись — в state.sh.
|
||
#
|
||
# Заполняет глобалы:
|
||
# ONBOARDING_LANG, ONBOARDING_TRANSPORT, ONBOARDING_PROVIDER, ONBOARDING_MODEL
|
||
# ONBOARDING_AUTH_ENV_KEYS[] + ONBOARDING_AUTH_ENV_VALUES[]
|
||
#
|
||
# Использует:
|
||
# - lib-i18n.sh: STR_* словарь + i18n_available_languages + i18n_load_lang
|
||
# - lib-onboarding-registry.sh: списки провайдеров/моделей
|
||
|
||
onboarding_pick_language() {
|
||
local langs
|
||
langs="$(i18n_available_languages 2>/dev/null)"
|
||
if [ -z "$langs" ]; then
|
||
langs="$(printf 'en\tEnglish\nru\tРусский\n')"
|
||
fi
|
||
|
||
if command -v whiptail >/dev/null 2>&1; then
|
||
local args=() first=1
|
||
while IFS=$'\t' read -r code name; do
|
||
[ -z "$code" ] && continue
|
||
if [ "$first" = "1" ]; then
|
||
args+=("$code" "$name" "ON"); first=0
|
||
else
|
||
args+=("$code" "$name" "OFF")
|
||
fi
|
||
done <<< "$langs"
|
||
ONBOARDING_LANG=$(whiptail --title "KeiSei · Language / Язык / 语言 / 言語 / ..." --radiolist \
|
||
"Choose interface language / Выберите язык:" 22 70 16 \
|
||
"${args[@]}" 3>&1 1>&2 2>&3) || ONBOARDING_LANG="en"
|
||
else
|
||
echo "" >&2
|
||
echo "Choose language / Выберите язык / 选择语言 / 言語選択:" >&2
|
||
declare -a codes=()
|
||
local i=1
|
||
while IFS=$'\t' read -r code name; do
|
||
[ -z "$code" ] && continue
|
||
codes+=("$code")
|
||
printf " %2d) %s — %s\n" "$i" "$code" "$name" >&2
|
||
i=$((i+1))
|
||
done <<< "$langs"
|
||
read -r -p "[1-${#codes[@]}, default 1=en]: " ans
|
||
ans="${ans:-1}"
|
||
ONBOARDING_LANG="${codes[$((ans-1))]:-en}"
|
||
fi
|
||
command -v i18n_load_lang >/dev/null 2>&1 && i18n_load_lang "$ONBOARDING_LANG"
|
||
}
|
||
|
||
onboarding_pick_transport() {
|
||
local transports
|
||
transports=$(onboarding_list_transports)
|
||
local prompt="${STR_PICK_TRANSPORT:-Choose connection transport:}"
|
||
|
||
if command -v whiptail >/dev/null 2>&1; then
|
||
local args=()
|
||
while IFS= read -r tr; do
|
||
local desc
|
||
case "$tr" in
|
||
direct-api) desc="${STR_TR_DIRECT_API:-Direct provider API}" ;;
|
||
aws-bedrock) desc="${STR_TR_AWS_BEDROCK:-AWS Bedrock}" ;;
|
||
azure-openai) desc="${STR_TR_AZURE_OPENAI:-Azure OpenAI}" ;;
|
||
google-vertex) desc="${STR_TR_GOOGLE_VERTEX:-Google Vertex AI}" ;;
|
||
local) desc="${STR_TR_LOCAL:-Local}" ;;
|
||
proxy) desc="${STR_TR_PROXY:-Proxy}" ;;
|
||
subscription) desc="${STR_TR_SUBSCRIPTION:-OAuth subscription}" ;;
|
||
*) desc="$tr" ;;
|
||
esac
|
||
args+=("$tr" "$desc" "OFF")
|
||
done <<< "$transports"
|
||
ONBOARDING_TRANSPORT=$(whiptail --title "KeiSei · Transport" --radiolist \
|
||
"$prompt" 18 70 7 "${args[@]}" 3>&1 1>&2 2>&3) || ONBOARDING_TRANSPORT="direct-api"
|
||
else
|
||
echo "" >&2
|
||
echo "$prompt" >&2
|
||
local i=1
|
||
declare -a opts=()
|
||
while IFS= read -r tr; do
|
||
opts+=("$tr")
|
||
echo " $i) $tr" >&2
|
||
i=$((i+1))
|
||
done <<< "$transports"
|
||
read -r -p "[1-${#opts[@]}, default 1]: " ans
|
||
ans="${ans:-1}"
|
||
ONBOARDING_TRANSPORT="${opts[$((ans-1))]:-direct-api}"
|
||
fi
|
||
}
|
||
|
||
onboarding_pick_provider() {
|
||
local rows; rows=$(onboarding_providers_in_transport "$ONBOARDING_TRANSPORT")
|
||
local count; count=$(echo "$rows" | wc -l | tr -d ' ')
|
||
|
||
# Если провайдер один на транспорт — авто-выбор.
|
||
if [ "$count" = "1" ]; then
|
||
ONBOARDING_PROVIDER=$(echo "$rows" | awk -F'\t' '{print $1}')
|
||
return
|
||
fi
|
||
|
||
if command -v whiptail >/dev/null 2>&1; then
|
||
local args=()
|
||
while IFS=$'\t' read -r id dn ae; do
|
||
args+=("$id" "$dn" "OFF")
|
||
done <<< "$rows"
|
||
local prompt="${STR_PICK_PROVIDER:-Provider within} $ONBOARDING_TRANSPORT:"
|
||
ONBOARDING_PROVIDER=$(whiptail --title "KeiSei · Provider" --radiolist \
|
||
"$prompt" 16 70 8 "${args[@]}" 3>&1 1>&2 2>&3) \
|
||
|| ONBOARDING_PROVIDER=$(echo "$rows" | head -1 | awk -F'\t' '{print $1}')
|
||
else
|
||
echo "" >&2
|
||
echo "${STR_PICK_PROVIDER:-Provider within} $ONBOARDING_TRANSPORT:" >&2
|
||
declare -a ids=()
|
||
local i=1
|
||
while IFS=$'\t' read -r id dn ae; do
|
||
ids+=("$id")
|
||
echo " $i) $id — $dn" >&2
|
||
i=$((i+1))
|
||
done <<< "$rows"
|
||
read -r -p "[1-${#ids[@]}, default 1]: " ans
|
||
ans="${ans:-1}"
|
||
ONBOARDING_PROVIDER="${ids[$((ans-1))]:-${ids[0]}}"
|
||
fi
|
||
}
|
||
|
||
onboarding_pick_model() {
|
||
# Для AWS/Azure/Vertex модели идут под parent-провайдером — мапим.
|
||
local lookup="$ONBOARDING_PROVIDER"
|
||
case "$ONBOARDING_PROVIDER" in
|
||
anthropic-bedrock) lookup="anthropic" ;;
|
||
openai-azure) lookup="openai" ;;
|
||
google-vertex) lookup="google" ;;
|
||
esac
|
||
local rows; rows=$(onboarding_models_for_provider "$lookup")
|
||
[ -z "$rows" ] && rows=$(printf "claude-sonnet-4-6\tClaude Sonnet 4.6 (fallback)\n")
|
||
|
||
if command -v whiptail >/dev/null 2>&1; then
|
||
local args=()
|
||
while IFS=$'\t' read -r id dn; do
|
||
args+=("$id" "$dn" "OFF")
|
||
done <<< "$rows"
|
||
ONBOARDING_MODEL=$(whiptail --title "KeiSei · Model" --radiolist \
|
||
"${STR_PICK_MODEL:-Default model:}" 16 70 8 "${args[@]}" 3>&1 1>&2 2>&3) \
|
||
|| ONBOARDING_MODEL=$(echo "$rows" | head -1 | awk -F'\t' '{print $1}')
|
||
else
|
||
echo "" >&2
|
||
echo "${STR_PICK_MODEL:-Models for} $lookup:" >&2
|
||
declare -a ids=()
|
||
local i=1
|
||
while IFS=$'\t' read -r id dn; do
|
||
ids+=("$id")
|
||
echo " $i) $id — $dn" >&2
|
||
i=$((i+1))
|
||
done <<< "$rows"
|
||
read -r -p "[1-${#ids[@]}, default 1]: " ans
|
||
ans="${ans:-1}"
|
||
ONBOARDING_MODEL="${ids[$((ans-1))]:-${ids[0]}}"
|
||
fi
|
||
}
|
||
|
||
onboarding_collect_auth() {
|
||
ONBOARDING_AUTH_ENV_KEYS=()
|
||
ONBOARDING_AUTH_ENV_VALUES=()
|
||
local ae; ae=$(onboarding_auth_env_for_provider "$ONBOARDING_PROVIDER")
|
||
[ -z "$ae" ] || [ "$ae" = "_" ] && return # local / subscription — нет ключей
|
||
|
||
echo "" >&2
|
||
echo "${STR_AUTH_INTRO:-Auth for} $ONBOARDING_PROVIDER ($ae):" >&2
|
||
echo "${STR_AUTH_PROMPT:-Enter values (Enter — leave empty, fill later).}" >&2
|
||
|
||
local IFS_old="$IFS"; IFS=','
|
||
for key in $ae; do
|
||
IFS="$IFS_old"
|
||
local cur="${!key:-}"
|
||
local prompt_msg="$key"
|
||
[ -n "$cur" ] && prompt_msg="$key ${STR_AUTH_CURRENT_HINT:-(current: <hidden>)}"
|
||
read -r -s -p " $prompt_msg = " val
|
||
echo "" >&2
|
||
if [ -n "$val" ]; then
|
||
ONBOARDING_AUTH_ENV_KEYS+=("$key")
|
||
ONBOARDING_AUTH_ENV_VALUES+=("$val")
|
||
elif [ -n "$cur" ]; then
|
||
ONBOARDING_AUTH_ENV_KEYS+=("$key")
|
||
ONBOARDING_AUTH_ENV_VALUES+=("$cur")
|
||
fi
|
||
done
|
||
IFS="$IFS_old"
|
||
}
|