fix node npm detection (#1163)
This commit is contained in:
@@ -24,6 +24,7 @@ export interface CodingAgentMutationResult extends CodingAgentsStatus {
|
||||
success: boolean
|
||||
tool: CodingAgentToolStatus
|
||||
message?: string
|
||||
code?: string
|
||||
}
|
||||
|
||||
export interface CodingAgentConfigFileContent {
|
||||
|
||||
@@ -35,6 +35,7 @@ export interface PreviewStatus {
|
||||
export interface PreviewActionResponse extends PreviewStatus {
|
||||
success: boolean
|
||||
message?: string
|
||||
code?: string
|
||||
}
|
||||
|
||||
// Config-based model types
|
||||
|
||||
@@ -42,6 +42,23 @@ function applyErrorStatus(err: any) {
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function errorCodeMessage(code?: string, fallback?: string): string {
|
||||
if (code === 'node_environment_missing') return t('githubPreview.nodeEnvironmentMissing')
|
||||
return fallback || t('githubPreview.actionFailed')
|
||||
}
|
||||
|
||||
function parseErrorPayload(err: any): { message?: string; code?: string } | null {
|
||||
const messageText = String(err?.message || '')
|
||||
const jsonStart = messageText.indexOf('{')
|
||||
if (jsonStart < 0) return null
|
||||
try {
|
||||
const parsed = JSON.parse(messageText.slice(jsonStart))
|
||||
return parsed && typeof parsed === 'object' ? parsed : null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async function loadStatus() {
|
||||
status.value = await fetchPreviewStatus()
|
||||
if (!selectedTag.value && status.value.current_tag) {
|
||||
@@ -71,19 +88,20 @@ async function handleRefresh() {
|
||||
}
|
||||
}
|
||||
|
||||
async function runAction(action: string, fn: () => Promise<PreviewStatus & { success?: boolean; message?: string }>, successKey: string) {
|
||||
async function runAction(action: string, fn: () => Promise<PreviewStatus & { success?: boolean; message?: string; code?: string }>, successKey: string) {
|
||||
actionLoading.value = action
|
||||
try {
|
||||
const res = await fn()
|
||||
status.value = res
|
||||
if (res.success === false) {
|
||||
message.warning(res.message || t('githubPreview.actionFailed'))
|
||||
message.warning(errorCodeMessage(res.code, res.message))
|
||||
return
|
||||
}
|
||||
message.success(t(successKey))
|
||||
} catch (err: any) {
|
||||
applyErrorStatus(err)
|
||||
message.error(err?.message || t('githubPreview.actionFailed'))
|
||||
const payload = parseErrorPayload(err)
|
||||
message.error(errorCodeMessage(payload?.code, payload?.message || err?.message))
|
||||
} finally {
|
||||
actionLoading.value = ''
|
||||
}
|
||||
|
||||
@@ -1015,6 +1015,7 @@ jobTriggered: 'Job ausgelost',
|
||||
yes: "Ja",
|
||||
no: "Nein",
|
||||
actionFailed: "Aktion fehlgeschlagen",
|
||||
nodeEnvironmentMissing: "Node/npm wurde nicht erkannt. Bitte installiere Node.js und versuche es erneut.",
|
||||
prepareSuccess: "Vorschaucode ist bereit",
|
||||
installSuccess: "Abhängigkeiten installiert",
|
||||
startSuccess: "Vorschau gestartet",
|
||||
@@ -1038,6 +1039,7 @@ jobTriggered: 'Job ausgelost',
|
||||
installing: "Installiere",
|
||||
installSuccess: "Installiert",
|
||||
installFailed: "Installation fehlgeschlagen",
|
||||
nodeEnvironmentMissing: "Node/npm wurde nicht erkannt. Bitte installiere Node.js und versuche es erneut.",
|
||||
deleteNow: "Loschen",
|
||||
deleting: "Losche",
|
||||
deleteSuccess: "Gelöscht",
|
||||
|
||||
@@ -1117,6 +1117,7 @@ export default {
|
||||
yes: "Yes",
|
||||
no: "No",
|
||||
actionFailed: "Action failed",
|
||||
nodeEnvironmentMissing: "Node/npm was not detected. Please install Node.js and try again.",
|
||||
prepareSuccess: "Preview code is ready",
|
||||
installSuccess: "Dependencies installed",
|
||||
startSuccess: "Preview started",
|
||||
@@ -1140,6 +1141,7 @@ export default {
|
||||
installing: "Installing",
|
||||
installSuccess: "Installed",
|
||||
installFailed: "Install failed",
|
||||
nodeEnvironmentMissing: "Node/npm was not detected. Please install Node.js and try again.",
|
||||
deleteNow: "Delete",
|
||||
deleting: "Deleting",
|
||||
deleteSuccess: "Deleted",
|
||||
|
||||
@@ -1015,6 +1015,7 @@ jobTriggered: 'Job ejecutado',
|
||||
yes: "Sí",
|
||||
no: "No",
|
||||
actionFailed: "Acción fallida",
|
||||
nodeEnvironmentMissing: "No se detectó Node/npm. Instala Node.js y vuelve a intentarlo.",
|
||||
prepareSuccess: "Código de vista previa listo",
|
||||
installSuccess: "Dependencias instaladas",
|
||||
startSuccess: "Vista previa iniciada",
|
||||
@@ -1038,6 +1039,7 @@ jobTriggered: 'Job ejecutado',
|
||||
installing: "Instalando",
|
||||
installSuccess: "Instalado",
|
||||
installFailed: "Error de instalación",
|
||||
nodeEnvironmentMissing: "No se detectó Node/npm. Instala Node.js y vuelve a intentarlo.",
|
||||
deleteNow: "Eliminar",
|
||||
deleting: "Eliminando",
|
||||
deleteSuccess: "Eliminado",
|
||||
|
||||
@@ -1015,6 +1015,7 @@ jobTriggered: 'Job declenche',
|
||||
yes: "Oui",
|
||||
no: "Non",
|
||||
actionFailed: "Échec de l’action",
|
||||
nodeEnvironmentMissing: "Node/npm n’a pas été détecté. Installez Node.js puis réessayez.",
|
||||
prepareSuccess: "Code de prévisualisation prêt",
|
||||
installSuccess: "Dépendances installées",
|
||||
startSuccess: "Prévisualisation démarrée",
|
||||
@@ -1038,6 +1039,7 @@ jobTriggered: 'Job declenche',
|
||||
installing: "Installation",
|
||||
installSuccess: "Installé",
|
||||
installFailed: "Échec de l’installation",
|
||||
nodeEnvironmentMissing: "Node/npm n’a pas été détecté. Installez Node.js puis réessayez.",
|
||||
deleteNow: "Supprimer",
|
||||
deleting: "Suppression",
|
||||
deleteSuccess: "Supprimé",
|
||||
|
||||
@@ -1015,6 +1015,7 @@ export default {
|
||||
yes: "はい",
|
||||
no: "いいえ",
|
||||
actionFailed: "操作に失敗しました",
|
||||
nodeEnvironmentMissing: "Node/npm が検出されませんでした。Node.js をインストールしてから再試行してください。",
|
||||
prepareSuccess: "プレビューコードの準備が完了しました",
|
||||
installSuccess: "依存関係をインストールしました",
|
||||
startSuccess: "プレビューを起動しました",
|
||||
@@ -1038,6 +1039,7 @@ export default {
|
||||
installing: "インストール中",
|
||||
installSuccess: "インストールしました",
|
||||
installFailed: "インストールに失敗しました",
|
||||
nodeEnvironmentMissing: "Node/npm が検出されませんでした。Node.js をインストールしてから再試行してください。",
|
||||
deleteNow: "削除",
|
||||
deleting: "削除中",
|
||||
deleteSuccess: "削除しました",
|
||||
|
||||
@@ -1015,6 +1015,7 @@ export default {
|
||||
yes: "예",
|
||||
no: "아니요",
|
||||
actionFailed: "작업 실패",
|
||||
nodeEnvironmentMissing: "Node/npm 환경을 찾을 수 없습니다. Node.js를 설치한 뒤 다시 시도하세요.",
|
||||
prepareSuccess: "미리보기 코드가 준비되었습니다",
|
||||
installSuccess: "의존성이 설치되었습니다",
|
||||
startSuccess: "미리보기가 시작되었습니다",
|
||||
@@ -1038,6 +1039,7 @@ export default {
|
||||
installing: "설치 중",
|
||||
installSuccess: "설치됨",
|
||||
installFailed: "설치 실패",
|
||||
nodeEnvironmentMissing: "Node/npm 환경을 찾을 수 없습니다. Node.js를 설치한 뒤 다시 시도하세요.",
|
||||
deleteNow: "삭제",
|
||||
deleting: "삭제 중",
|
||||
deleteSuccess: "삭제됨",
|
||||
|
||||
@@ -1015,6 +1015,7 @@ jobTriggered: 'Job acionado',
|
||||
yes: "Sim",
|
||||
no: "Não",
|
||||
actionFailed: "Ação falhou",
|
||||
nodeEnvironmentMissing: "Node/npm não foi detectado. Instale o Node.js e tente novamente.",
|
||||
prepareSuccess: "Código de prévia pronto",
|
||||
installSuccess: "Dependências instaladas",
|
||||
startSuccess: "Prévia iniciada",
|
||||
@@ -1038,6 +1039,7 @@ jobTriggered: 'Job acionado',
|
||||
installing: "Instalando",
|
||||
installSuccess: "Instalado",
|
||||
installFailed: "Falha na instalação",
|
||||
nodeEnvironmentMissing: "Node/npm não foi detectado. Instale o Node.js e tente novamente.",
|
||||
deleteNow: "Excluir",
|
||||
deleting: "Excluindo",
|
||||
deleteSuccess: "Excluído",
|
||||
|
||||
@@ -1109,6 +1109,7 @@ export default {
|
||||
yes: "是",
|
||||
no: "否",
|
||||
actionFailed: "操作失敗",
|
||||
nodeEnvironmentMissing: "未偵測到可用的 Node/npm 環境,請先安裝 Node.js 後重試。",
|
||||
prepareSuccess: "預覽程式碼已準備好",
|
||||
installSuccess: "依賴安裝完成",
|
||||
startSuccess: "預覽已啟動",
|
||||
@@ -1132,6 +1133,7 @@ export default {
|
||||
installing: "安裝中",
|
||||
installSuccess: "安裝完成",
|
||||
installFailed: "安裝失敗",
|
||||
nodeEnvironmentMissing: "未偵測到可用的 Node/npm 環境,請先安裝 Node.js 後重試。",
|
||||
deleteNow: "刪除",
|
||||
deleting: "刪除中",
|
||||
deleteSuccess: "刪除完成",
|
||||
|
||||
@@ -1109,6 +1109,7 @@ export default {
|
||||
yes: "是",
|
||||
no: "否",
|
||||
actionFailed: "操作失败",
|
||||
nodeEnvironmentMissing: "未检测到可用的 Node/npm 环境,请先安装 Node.js 后重试。",
|
||||
prepareSuccess: "预览代码已准备好",
|
||||
installSuccess: "依赖安装完成",
|
||||
startSuccess: "预览已启动",
|
||||
@@ -1132,6 +1133,7 @@ export default {
|
||||
installing: "安装中",
|
||||
installSuccess: "安装完成",
|
||||
installFailed: "安装失败",
|
||||
nodeEnvironmentMissing: "未检测到可用的 Node/npm 环境,请先安装 Node.js 后重试。",
|
||||
deleteNow: "删除",
|
||||
deleting: "删除中",
|
||||
deleteSuccess: "删除完成",
|
||||
|
||||
@@ -307,6 +307,23 @@ function currentLaunchRequest() {
|
||||
}
|
||||
}
|
||||
|
||||
function codingAgentMessage(code?: string, fallback?: string, fallbackKey = 'codingAgents.installFailed'): string {
|
||||
if (code === 'node_environment_missing') return t('codingAgents.nodeEnvironmentMissing')
|
||||
return fallback || t(fallbackKey)
|
||||
}
|
||||
|
||||
function parseErrorPayload(err: any): { message?: string; code?: string } | null {
|
||||
const messageText = String(err?.message || '')
|
||||
const jsonStart = messageText.indexOf('{')
|
||||
if (jsonStart < 0) return null
|
||||
try {
|
||||
const parsed = JSON.parse(messageText.slice(jsonStart))
|
||||
return parsed && typeof parsed === 'object' ? parsed : null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async function launchBuiltInTerminal() {
|
||||
if (!useGlobalLaunchConfig.value && (!launchProvider.value || !launchModel.value)) {
|
||||
message.error(t('codingAgents.selectProviderModel'))
|
||||
@@ -352,10 +369,11 @@ async function handleInstall(id: CodingAgentId) {
|
||||
if (result.success) {
|
||||
message.success(t('codingAgents.installSuccess'))
|
||||
} else {
|
||||
message.error(result.message || t('codingAgents.installFailed'))
|
||||
message.error(codingAgentMessage(result.code, result.message, 'codingAgents.installFailed'))
|
||||
}
|
||||
} catch (err: any) {
|
||||
message.error(err?.message || t('codingAgents.installFailed'))
|
||||
const payload = parseErrorPayload(err)
|
||||
message.error(codingAgentMessage(payload?.code, payload?.message || err?.message, 'codingAgents.installFailed'))
|
||||
} finally {
|
||||
installing.value[id] = false
|
||||
}
|
||||
@@ -369,10 +387,11 @@ async function handleDelete(id: CodingAgentId) {
|
||||
if (result.success) {
|
||||
message.success(t('codingAgents.deleteSuccess'))
|
||||
} else {
|
||||
message.error(result.message || t('codingAgents.deleteFailed'))
|
||||
message.error(codingAgentMessage(result.code, result.message, 'codingAgents.deleteFailed'))
|
||||
}
|
||||
} catch (err: any) {
|
||||
message.error(err?.message || t('codingAgents.deleteFailed'))
|
||||
const payload = parseErrorPayload(err)
|
||||
message.error(codingAgentMessage(payload?.code, payload?.message || err?.message, 'codingAgents.deleteFailed'))
|
||||
} finally {
|
||||
deleting.value[id] = false
|
||||
}
|
||||
|
||||
@@ -77,6 +77,9 @@ async function loadRecommendations() {
|
||||
const response = await fetch(recommendationsPath.value)
|
||||
if (!response.ok) throw new Error(`HTTP ${response.status}`)
|
||||
const text = await response.text()
|
||||
if (/^\s*<!doctype html/i.test(text) || /^\s*<html[\s>]/i.test(text)) {
|
||||
throw new Error('Skill recommendations file was not found')
|
||||
}
|
||||
if (requestSeq === recommendationsRequestSeq) {
|
||||
recommendations.value = text
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user