kin: KIN-083 Healthcheck claude CLI auth: перед запуском pipeline проверять что claude залогинен (быстрый claude -p 'ok' --output-format json, проверить is_error и 'Not logged in'). Если не залогинен — не запускать pipeline, а показать ошибку 'Claude CLI requires login' в GUI с инструкцией.

This commit is contained in:
Gros Frumos 2026-03-16 15:48:09 +02:00
parent a80679ae72
commit bfc8f1c0bb
18 changed files with 1390 additions and 57 deletions

View file

@ -1,7 +1,7 @@
<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { api, type TaskFull, type PipelineStep, type PendingAction, type DeployResult } from '../api'
import { api, ApiError, type TaskFull, type PipelineStep, type PendingAction, type DeployResult } from '../api'
import Badge from '../components/Badge.vue'
import Modal from '../components/Modal.vue'
@ -12,6 +12,7 @@ const router = useRouter()
const task = ref<TaskFull | null>(null)
const loading = ref(true)
const error = ref('')
const claudeLoginError = ref(false)
const selectedStep = ref<PipelineStep | null>(null)
const polling = ref(false)
let pollTimer: ReturnType<typeof setInterval> | null = null
@ -206,12 +207,17 @@ async function revise() {
}
async function runPipeline() {
claudeLoginError.value = false
try {
await api.runTask(props.id)
startPolling()
await load()
} catch (e: any) {
error.value = e.message
if (e instanceof ApiError && e.code === 'claude_auth_required') {
claudeLoginError.value = true
} else {
error.value = e.message
}
}
}
@ -521,6 +527,19 @@ async function saveEdit() {
</button>
</div>
<!-- Claude login error banner -->
<div v-if="claudeLoginError" class="mt-3 px-4 py-3 border border-yellow-700 bg-yellow-950/30 rounded">
<div class="flex items-start justify-between gap-2">
<div>
<p class="text-sm font-semibold text-yellow-300">&#9888; Claude CLI requires login</p>
<p class="text-xs text-yellow-200/80 mt-1">Откройте терминал и выполните:</p>
<code class="text-xs text-yellow-400 font-mono bg-black/30 px-2 py-0.5 rounded mt-1 inline-block">claude login</code>
<p class="text-xs text-gray-500 mt-1">После входа повторите запуск pipeline.</p>
</div>
<button @click="claudeLoginError = false" class="text-gray-600 hover:text-gray-400 bg-transparent border-none cursor-pointer text-xs shrink-0"></button>
</div>
</div>
<!-- Deploy result inline block -->
<div v-if="deployResult" class="mx-0 mt-2 p-3 rounded border text-xs font-mono"
:class="deployResult.success ? 'border-teal-800 bg-teal-950/30 text-teal-300' : 'border-red-800 bg-red-950/30 text-red-300'">