mirror of
http://10.0.2.1:3031/sauer/claude-code.git
synced 2026-06-30 11:36:57 +10:00
151 lines
19 KiB
TypeScript
151 lines
19 KiB
TypeScript
|
|
import { c as _c } from "react/compiler-runtime";
|
||
|
|
import axios from 'axios';
|
||
|
|
import React, { useEffect, useState } from 'react';
|
||
|
|
import { logEvent } from 'src/services/analytics/index.js';
|
||
|
|
import { Spinner } from '../components/Spinner.js';
|
||
|
|
import { getOauthConfig } from '../constants/oauth.js';
|
||
|
|
import { useTimeout } from '../hooks/useTimeout.js';
|
||
|
|
import { Box, Text } from '../ink.js';
|
||
|
|
import { getSSLErrorHint } from '../services/api/errorUtils.js';
|
||
|
|
import { getUserAgent } from './http.js';
|
||
|
|
import { logError } from './log.js';
|
||
|
|
export interface PreflightCheckResult {
|
||
|
|
success: boolean;
|
||
|
|
error?: string;
|
||
|
|
sslHint?: string;
|
||
|
|
}
|
||
|
|
async function checkEndpoints(): Promise<PreflightCheckResult> {
|
||
|
|
try {
|
||
|
|
const oauthConfig = getOauthConfig();
|
||
|
|
const tokenUrl = new URL(oauthConfig.TOKEN_URL);
|
||
|
|
const endpoints = [`${oauthConfig.BASE_API_URL}/api/hello`, `${tokenUrl.origin}/v1/oauth/hello`];
|
||
|
|
const checkEndpoint = async (url: string): Promise<PreflightCheckResult> => {
|
||
|
|
try {
|
||
|
|
const response = await axios.get(url, {
|
||
|
|
headers: {
|
||
|
|
'User-Agent': getUserAgent()
|
||
|
|
}
|
||
|
|
});
|
||
|
|
if (response.status !== 200) {
|
||
|
|
const hostname = new URL(url).hostname;
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
error: `Failed to connect to ${hostname}: Status ${response.status}`
|
||
|
|
};
|
||
|
|
}
|
||
|
|
return {
|
||
|
|
success: true
|
||
|
|
};
|
||
|
|
} catch (error) {
|
||
|
|
const hostname = new URL(url).hostname;
|
||
|
|
const sslHint = getSSLErrorHint(error);
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
error: `Failed to connect to ${hostname}: ${error instanceof Error ? (error as ErrnoException).code || error.message : String(error)}`,
|
||
|
|
sslHint: sslHint ?? undefined
|
||
|
|
};
|
||
|
|
}
|
||
|
|
};
|
||
|
|
const results = await Promise.all(endpoints.map(checkEndpoint));
|
||
|
|
const failedResult = results.find(result => !result.success);
|
||
|
|
if (failedResult) {
|
||
|
|
// Log failure to Statsig
|
||
|
|
logEvent('tengu_preflight_check_failed', {
|
||
|
|
isConnectivityError: false,
|
||
|
|
hasErrorMessage: !!failedResult.error,
|
||
|
|
isSSLError: !!failedResult.sslHint
|
||
|
|
});
|
||
|
|
}
|
||
|
|
return failedResult || {
|
||
|
|
success: true
|
||
|
|
};
|
||
|
|
} catch (error) {
|
||
|
|
logError(error as Error);
|
||
|
|
|
||
|
|
// Log to Statsig
|
||
|
|
logEvent('tengu_preflight_check_failed', {
|
||
|
|
isConnectivityError: true
|
||
|
|
});
|
||
|
|
return {
|
||
|
|
success: false,
|
||
|
|
error: `Connectivity check error: ${error instanceof Error ? (error as ErrnoException).code || error.message : String(error)}`
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
interface PreflightStepProps {
|
||
|
|
onSuccess: () => void;
|
||
|
|
}
|
||
|
|
export function PreflightStep(t0) {
|
||
|
|
const $ = _c(12);
|
||
|
|
const {
|
||
|
|
onSuccess
|
||
|
|
} = t0;
|
||
|
|
const [result, setResult] = useState(null);
|
||
|
|
const [isChecking, setIsChecking] = useState(true);
|
||
|
|
const showSpinner = useTimeout(1000) && isChecking;
|
||
|
|
let t1;
|
||
|
|
let t2;
|
||
|
|
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||
|
|
t1 = () => {
|
||
|
|
const run = async function run() {
|
||
|
|
const checkResult = await checkEndpoints();
|
||
|
|
setResult(checkResult);
|
||
|
|
setIsChecking(false);
|
||
|
|
};
|
||
|
|
run();
|
||
|
|
};
|
||
|
|
t2 = [];
|
||
|
|
$[0] = t1;
|
||
|
|
$[1] = t2;
|
||
|
|
} else {
|
||
|
|
t1 = $[0];
|
||
|
|
t2 = $[1];
|
||
|
|
}
|
||
|
|
useEffect(t1, t2);
|
||
|
|
let t3;
|
||
|
|
let t4;
|
||
|
|
if ($[2] !== onSuccess || $[3] !== result) {
|
||
|
|
t3 = () => {
|
||
|
|
if (result?.success) {
|
||
|
|
onSuccess();
|
||
|
|
} else {
|
||
|
|
if (result && !result.success) {
|
||
|
|
const timer = setTimeout(_temp, 100);
|
||
|
|
return () => clearTimeout(timer);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
t4 = [result, onSuccess];
|
||
|
|
$[2] = onSuccess;
|
||
|
|
$[3] = result;
|
||
|
|
$[4] = t3;
|
||
|
|
$[5] = t4;
|
||
|
|
} else {
|
||
|
|
t3 = $[4];
|
||
|
|
t4 = $[5];
|
||
|
|
}
|
||
|
|
useEffect(t3, t4);
|
||
|
|
let t5;
|
||
|
|
if ($[6] !== isChecking || $[7] !== result || $[8] !== showSpinner) {
|
||
|
|
t5 = isChecking && showSpinner ? <Box paddingLeft={1}><Spinner /><Text>Checking connectivity...</Text></Box> : !result?.success && !isChecking && <Box flexDirection="column" gap={1}><Text color="error">Unable to connect to Anthropic services</Text><Text color="error">{result?.error}</Text>{result?.sslHint ? <Box flexDirection="column" gap={1}><Text>{result.sslHint}</Text><Text color="suggestion">See https://code.claude.com/docs/en/network-config</Text></Box> : <Box flexDirection="column" gap={1}><Text>Please check your internet connection and network settings.</Text><Text>Note: Claude Code might not be available in your country. Check supported countries at{" "}<Text color="suggestion">https://anthropic.com/supported-countries</Text></Text></Box>}</Box>;
|
||
|
|
$[6] = isChecking;
|
||
|
|
$[7] = result;
|
||
|
|
$[8] = showSpinner;
|
||
|
|
$[9] = t5;
|
||
|
|
} else {
|
||
|
|
t5 = $[9];
|
||
|
|
}
|
||
|
|
let t6;
|
||
|
|
if ($[10] !== t5) {
|
||
|
|
t6 = <Box flexDirection="column" gap={1} paddingLeft={1}>{t5}</Box>;
|
||
|
|
$[10] = t5;
|
||
|
|
$[11] = t6;
|
||
|
|
} else {
|
||
|
|
t6 = $[11];
|
||
|
|
}
|
||
|
|
return t6;
|
||
|
|
}
|
||
|
|
function _temp() {
|
||
|
|
return process.exit(1);
|
||
|
|
}
|
||
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJheGlvcyIsIlJlYWN0IiwidXNlRWZmZWN0IiwidXNlU3RhdGUiLCJsb2dFdmVudCIsIlNwaW5uZXIiLCJnZXRPYXV0aENvbmZpZyIsInVzZVRpbWVvdXQiLCJCb3giLCJUZXh0IiwiZ2V0U1NMRXJyb3JIaW50IiwiZ2V0VXNlckFnZW50IiwibG9nRXJyb3IiLCJQcmVmbGlnaHRDaGVja1Jlc3VsdCIsInN1Y2Nlc3MiLCJlcnJvciIsInNzbEhpbnQiLCJjaGVja0VuZHBvaW50cyIsIlByb21pc2UiLCJvYXV0aENvbmZpZyIsInRva2VuVXJsIiwiVVJMIiwiVE9LRU5fVVJMIiwiZW5kcG9pbnRzIiwiQkFTRV9BUElfVVJMIiwib3JpZ2luIiwiY2hlY2tFbmRwb2ludCIsInVybCIsInJlc3BvbnNlIiwiZ2V0IiwiaGVhZGVycyIsInN0YXR1cyIsImhvc3RuYW1lIiwiRXJyb3IiLCJFcnJub0V4Y2VwdGlvbiIsImNvZGUiLCJtZXNzYWdlIiwiU3RyaW5nIiwidW5kZWZpbmVkIiwicmVzdWx0cyIsImFsbCIsIm1hcCIsImZhaWxlZFJlc3VsdCIsImZpbmQiLCJyZXN1bHQiLCJpc0Nvbm5lY3Rpdml0eUVycm9yIiwiaGFzRXJyb3JNZXNzYWdlIiwiaXNTU0xFcnJvciIsIlByZWZsaWdodFN0ZXBQcm9wcyIsIm9uU3VjY2VzcyIsIlByZWZsaWdodFN0ZXAiLCJ0MCIsIiQiLCJfYyIsInNldFJlc3VsdCIsImlzQ2hlY2tpbmciLCJzZXRJc0NoZWNraW5nIiwic2hvd1NwaW5uZXIiLCJ0MSIsInQyIiwiU3ltYm9sIiwiZm9yIiwicnVuIiwiY2hlY2tSZXN1bHQiLCJ0MyIsInQ0IiwidGltZXIiLCJzZXRUaW1lb3V0IiwiX3RlbXAiLCJjbGVhclRpbWVvdXQiLCJ0NSIsInQ2IiwicHJvY2VzcyIsImV4aXQiXSwic291cmNlcyI6WyJwcmVmbGlnaHRDaGVja3MudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBheGlvcyBmcm9tICdheGlvcydcbmltcG9ydCBSZWFjdCwgeyB1c2VFZmZlY3QsIHVzZVN0YXRlIH0gZnJvbSAncmVhY3QnXG5pbXBvcnQgeyBsb2dFdmVudCB9IGZyb20gJ3NyYy9zZXJ2aWNlcy9hbmFseXRpY3MvaW5kZXguanMnXG5pbXBvcnQgeyBTcGlubmVyIH0gZnJvbSAnLi4vY29tcG9uZW50cy9TcGlubmVyLmpzJ1xuaW1wb3J0IHsgZ2V0T2F1dGhDb25maWcgfSBmcm9tICcuLi9jb25zdGFudHMvb2F1dGguanMnXG5pbXBvcnQgeyB1c2VUaW1lb3V0IH0gZnJvbSAnLi4vaG9va3MvdXNlVGltZW91dC5qcydcbmltcG9ydCB7IEJveCwgVGV4dCB9IGZyb20gJy4uL2luay5qcydcbmltcG9ydCB7IGdldFNTTEVycm9ySGludCB9IGZyb20gJy4uL3NlcnZpY2VzL2FwaS9lcnJvclV0aWxzLmpzJ1xuaW1wb3J0IHsgZ2V0VXNlckFnZW50IH0gZnJvbSAnLi9odHRwLmpzJ1xuaW1wb3J0IHsgbG9nRXJyb3IgfSBmcm9tICcuL2xvZy5qcydcblxuZXhwb3J0IGludGVyZmFjZSBQcmVmbGlnaHRDaGVja1Jlc3VsdCB7XG4gIHN1Y2Nlc3M6IGJvb2xlYW5cbiAgZXJyb3I/OiBzdHJpbmdcbiAgc3NsSGludD86IHN0cmluZ1xufVxuXG5hc3luYyBmdW5jdGlvbiBjaGVja0VuZHBvaW50cygpOiBQcm9taXNlPFByZWZsaWdodENoZWNrUmVzdWx0PiB7XG4gIHRyeSB7XG4gICAgY29uc3Qgb2F1dGhDb25maWcgPSBnZXRPYXV0aENvbmZpZygpXG4gICAgY29uc3QgdG9rZW5VcmwgPSBuZXcgVVJMKG9hdXRoQ29uZmlnLlRPS0VOX1VSTClcbiAgICBjb25zdCBlbmRwb2ludHMgPSBbXG4gICAgICBgJHtvYXV0aENvbmZpZy5CQVNFX0FQSV9VUkx9L2FwaS9oZWxsb2AsXG4gICAgICBgJHt0b2tlblVybC5vcmlnaW59L3YxL29hdXRoL2hlbGxvYCxcbiAgICBdXG5cbiAgICBjb25zdCBjaGVja0VuZHBvaW50ID0gYXN5bmMgKFxuICAgICAgdXJsOiBzdHJpbmcsXG4gICAgKTogUHJvbWlzZTxQcmVmbGlnaHRDaGVja1Jlc3VsdD4gPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBheGlvcy5nZXQodXJsLCB7XG4gICAgICAgICAgaGVhZGVyczogeyAnVXNlci1BZ2VudCc6IGdldFVzZXJBZ2VudCgpIH0sXG4gICAgICAgIH0pXG4gICAgICAgIGlmIChyZXNwb25zZS5zdGF0dXMgIT09IDIwMCkge1xuICAgICAgICAgIGNvbnN0IGhvc3RuYW1lID0gbmV3IFVSTCh1cmwpLmhvc3RuYW1lXG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICAgICAgZXJyb3I6IGBGYWlsZWQgdG8gY29ubmVjdCB0byAke2hvc3RuYW1lfTogU3RhdHVzICR7cmVzcG9uc2Uuc3RhdHVzfWAsXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IHRydWUgfVxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgY29uc3QgaG9zdG5hbWUgPSBuZXcgVVJMKHVybCkuaG9zdG5hbWVcbiAgICAgICAgY29uc3Qgc3NsSGludCA9IGdldFNTTEVycm9ySGludChlcnJvcilcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgICBlcnJvcjogYEZhaWxlZCB0byBjb25uZWN0IHRvICR7aG9zdG5hbWV9OiAke2Vycm9yIGluc3RhbmNlb2YgRXJyb3IgPyAoZXJyb3IgYXMgRXJybm9FeGNlcHRpb24pLmNvZGUgfHwgZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcil9YCxcbiAgICAgICAgICBzc2xIaW50OiBzc2xIaW50ID8/IHVuZGVmaW5lZCxcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChlbmRwb2ludHMubWFwKGNoZWNrRW5kcG9pbnQpKVxuICAgIGNvbnN0IGZhaWxlZFJlc3VsdCA9IHJlc3VsdHMuZmluZChyZXN1bHQgPT4gIXJlc3VsdC5zdWNjZXNzKVxuXG4gICAgaWYgKGZhaWxlZFJlc3VsdCkge1xuICAgICAgLy8gTG9nIGZhaWx1cmUgdG8gU3RhdHNpZ1xuICAgICAgbG9nRXZlbnQoJ3Rlbmd1X3ByZWZsaWdodF9jaGVja19mYWlsZWQnLCB7XG4gICAgICAgIGlzQ29ubmVjdGl2aXR5RXJyb3I6IGZhbHNlLFxuICAgICAgICBoYXNFcnJvck1lc3NhZ2U6ICEhZmFpbGVkUmVzdWx0LmVycm9yLFxuICAgICAgICBpc1NTTEVycm9yOiAhIWZhaWxlZFJlc3VsdC5zc2xIaW50LFxuICAgICAgfSlcbiA
|