支持Cline Agent
This commit is contained in:
@@ -5,6 +5,7 @@ import { cn } from "@/lib/utils"
|
||||
import ClaudeColor from "@lobehub/icons/es/Claude/components/Color"
|
||||
import GeminiColor from "@lobehub/icons/es/Gemini/components/Color"
|
||||
import OpenClawColor from "@lobehub/icons/es/OpenClaw/components/Color"
|
||||
import ClineMono from "@lobehub/icons/es/Cline/components/Mono"
|
||||
import { OpenAI, OpenCode } from "@lobehub/icons"
|
||||
|
||||
interface AgentIconProps {
|
||||
@@ -24,6 +25,7 @@ const COLOR_ICONS: Partial<Record<AgentType, AnyIcon>> = {
|
||||
const MONO_ICONS: Partial<Record<AgentType, AnyIcon>> = {
|
||||
codex: OpenAI,
|
||||
open_code: OpenCode,
|
||||
cline: ClineMono,
|
||||
}
|
||||
|
||||
// Text-color versions for Mono icons
|
||||
|
||||
@@ -274,7 +274,10 @@ const ConversationTabView = memo(function ConversationTabView({
|
||||
agentType: selectedAgent,
|
||||
isActive: isActive && canAutoConnect,
|
||||
workingDir: workingDirForConnection,
|
||||
sessionId: dbConversationId != null ? externalId : undefined,
|
||||
sessionId:
|
||||
dbConversationId != null && selectedAgent !== "cline"
|
||||
? externalId
|
||||
: undefined,
|
||||
})
|
||||
const {
|
||||
status: connStatus,
|
||||
|
||||
@@ -878,6 +878,8 @@ function getToolIcon(
|
||||
name === "switch_mode"
|
||||
)
|
||||
return <ListTodoIcon className={ICON_CLASS} />
|
||||
if (name === "attempt_completion")
|
||||
return <CircleCheckIcon className={ICON_CLASS} />
|
||||
return undefined
|
||||
}
|
||||
|
||||
@@ -909,6 +911,16 @@ function deriveToolTitle(
|
||||
return null
|
||||
}
|
||||
|
||||
// Cline: attempt_completion — show result summary as title
|
||||
if (name === "attempt_completion") {
|
||||
const result = getField("result")
|
||||
if (result) {
|
||||
const firstLine = result.split("\n")[0].trim()
|
||||
return `${ellipsis(firstLine, 80)}`
|
||||
}
|
||||
return "Completion"
|
||||
}
|
||||
|
||||
// File-based tools
|
||||
const filePath =
|
||||
getField("file_path") ??
|
||||
@@ -2282,6 +2294,43 @@ const ToolCallPart = memo(function ToolCallPart({
|
||||
toolNameLower === "enterplanmode" ||
|
||||
toolNameLower === "exitplanmode") &&
|
||||
!part.errorText
|
||||
// Cline: attempt_completion — render as an expanded card with result + progress
|
||||
if (toolNameLower === "attempt_completion") {
|
||||
const parsedCompletion = tryParseJson(part.input ?? "")
|
||||
const completionResult =
|
||||
(parsedCompletion?.result as string | undefined)?.trim() ?? null
|
||||
const taskProgress =
|
||||
(parsedCompletion?.task_progress as string | undefined)?.trim() ?? null
|
||||
return (
|
||||
<Tool open onOpenChange={setManualOpen}>
|
||||
<ToolHeader
|
||||
type="dynamic-tool"
|
||||
state={part.state}
|
||||
toolName={normalizedToolName}
|
||||
title={title ?? "Completion"}
|
||||
icon={icon}
|
||||
/>
|
||||
<ToolContent>
|
||||
{completionResult && (
|
||||
<div className="text-sm prose prose-sm dark:prose-invert max-w-none [&_ul]:list-inside [&_ol]:list-inside">
|
||||
<MessageResponse>{completionResult}</MessageResponse>
|
||||
</div>
|
||||
)}
|
||||
{taskProgress && (
|
||||
<div className="mt-2 rounded-md border bg-muted/30 px-3 py-2">
|
||||
<div className="text-[11px] font-medium text-muted-foreground mb-1">
|
||||
Progress
|
||||
</div>
|
||||
<div className="text-xs prose prose-sm dark:prose-invert max-w-none [&_ul]:list-inside [&_ol]:list-inside">
|
||||
<MessageResponse>{taskProgress}</MessageResponse>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</ToolContent>
|
||||
</Tool>
|
||||
)
|
||||
}
|
||||
|
||||
const open = (isRunning && (isCommandTool || hasLiveOutput)) || manualOpen
|
||||
|
||||
return (
|
||||
|
||||
@@ -107,6 +107,10 @@ interface AgentDraft {
|
||||
openClawGatewayUrl: string
|
||||
openClawGatewayToken: string
|
||||
openClawSessionKey: string
|
||||
clineProvider: ClineProvider
|
||||
clineApiKey: string
|
||||
clineModel: string
|
||||
clineBaseUrl: string
|
||||
}
|
||||
|
||||
type RunningActionKind =
|
||||
@@ -250,6 +254,20 @@ const OPENCLAW_ENV_KEYS = {
|
||||
sessionKey: "OPENCLAW_SESSION_KEY",
|
||||
} as const
|
||||
|
||||
const CLINE_PROVIDERS = [
|
||||
{ value: "anthropic", label: "Anthropic" },
|
||||
{ value: "openai-native", label: "OpenAI" },
|
||||
{ value: "openai", label: "OpenAI Compatible" },
|
||||
{ value: "openrouter", label: "OpenRouter" },
|
||||
{ value: "gemini", label: "Gemini" },
|
||||
{ value: "deepseek", label: "DeepSeek" },
|
||||
{ value: "bedrock", label: "AWS Bedrock" },
|
||||
{ value: "vertex", label: "GCP Vertex" },
|
||||
{ value: "ollama", label: "Ollama" },
|
||||
] as const
|
||||
|
||||
type ClineProvider = (typeof CLINE_PROVIDERS)[number]["value"]
|
||||
|
||||
type ClaudeModelKey = keyof typeof CLAUDE_MODEL_ENV_KEYS
|
||||
type ImportantConfigKey = "apiBaseUrl" | "apiKey" | "model" | ClaudeModelKey
|
||||
type ImportantDraftPatch = Partial<Pick<AgentDraft, ImportantConfigKey>>
|
||||
@@ -564,6 +582,26 @@ interface OpenClawImportantValues {
|
||||
sessionKey: string
|
||||
}
|
||||
|
||||
interface ClineImportantValues {
|
||||
provider: ClineProvider
|
||||
apiKey: string
|
||||
model: string
|
||||
baseUrl: string
|
||||
}
|
||||
|
||||
function extractClineImportantValues(configText: string): ClineImportantValues {
|
||||
const parseResult = parseConfigJsonText(configText)
|
||||
const config = parseResult.config
|
||||
return {
|
||||
provider: (typeof config.apiProvider === "string" && config.apiProvider
|
||||
? config.apiProvider
|
||||
: "anthropic") as ClineProvider,
|
||||
apiKey: typeof config.apiKey === "string" ? config.apiKey : "",
|
||||
model: typeof config.model === "string" ? config.model : "",
|
||||
baseUrl: typeof config.apiBaseUrl === "string" ? config.apiBaseUrl : "",
|
||||
}
|
||||
}
|
||||
|
||||
function extractOpenClawImportantValues(
|
||||
env: Record<string, string>,
|
||||
configText: string
|
||||
@@ -1965,6 +2003,7 @@ function buildAgentDraft(agent: AcpAgentInfo): AgentDraft {
|
||||
configText,
|
||||
openCodeAuthJsonText
|
||||
)
|
||||
const clineImportant = extractClineImportantValues(configText)
|
||||
return {
|
||||
enabled: agent.enabled,
|
||||
envText: envMapToText(agent.env),
|
||||
@@ -2014,6 +2053,10 @@ function buildAgentDraft(agent: AcpAgentInfo): AgentDraft {
|
||||
openClawGatewayUrl: openClawImportant.gatewayUrl,
|
||||
openClawGatewayToken: openClawImportant.gatewayToken,
|
||||
openClawSessionKey: openClawImportant.sessionKey,
|
||||
clineProvider: clineImportant.provider,
|
||||
clineApiKey: clineImportant.apiKey,
|
||||
clineModel: clineImportant.model,
|
||||
clineBaseUrl: clineImportant.baseUrl,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3059,6 +3102,19 @@ export function AcpAgentSettings() {
|
||||
return
|
||||
}
|
||||
|
||||
if (selectedAgent.agent_type === "cline") {
|
||||
const cline = extractClineImportantValues(nextText)
|
||||
updateSelectedDraft((current) => ({
|
||||
...current,
|
||||
configText: nextText,
|
||||
clineProvider: cline.provider,
|
||||
clineApiKey: cline.apiKey,
|
||||
clineModel: cline.model,
|
||||
clineBaseUrl: cline.baseUrl,
|
||||
}))
|
||||
return
|
||||
}
|
||||
|
||||
const important = extractImportantConfigValues(
|
||||
selectedAgent.agent_type,
|
||||
parseEnvText(selectedDraft.envText),
|
||||
@@ -3321,6 +3377,37 @@ export function AcpAgentSettings() {
|
||||
[selectedAgent, selectedDraft, updateSelectedDraft]
|
||||
)
|
||||
|
||||
const handleClineFieldChange = useCallback(
|
||||
(
|
||||
key: "clineProvider" | "clineApiKey" | "clineModel" | "clineBaseUrl",
|
||||
value: string
|
||||
) => {
|
||||
if (
|
||||
!selectedAgent ||
|
||||
!selectedDraft ||
|
||||
selectedAgent.agent_type !== "cline"
|
||||
)
|
||||
return
|
||||
|
||||
updateSelectedDraft((current) => {
|
||||
const next = { ...current, [key]: value }
|
||||
// Rebuild config_json from Cline draft fields
|
||||
const config: Record<string, unknown> = {}
|
||||
config.apiProvider =
|
||||
key === "clineProvider" ? value : next.clineProvider
|
||||
const apiKey = key === "clineApiKey" ? value : next.clineApiKey
|
||||
if (apiKey.trim()) config.apiKey = apiKey.trim()
|
||||
const model = key === "clineModel" ? value : next.clineModel
|
||||
if (model.trim()) config.model = model.trim()
|
||||
const baseUrl = key === "clineBaseUrl" ? value : next.clineBaseUrl
|
||||
if (baseUrl.trim()) config.apiBaseUrl = baseUrl.trim()
|
||||
next.configText = JSON.stringify(config, null, 2)
|
||||
return next
|
||||
})
|
||||
},
|
||||
[selectedAgent, selectedDraft, updateSelectedDraft]
|
||||
)
|
||||
|
||||
const handleOpenCodeConfigPatch = useCallback(
|
||||
(mutator: (config: Record<string, unknown>) => void) => {
|
||||
if (
|
||||
@@ -5694,6 +5781,188 @@ supports_websockets = true`}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : selectedAgent.agent_type === "cline" ? (
|
||||
<div className="space-y-3 rounded-md border bg-muted/10 p-3">
|
||||
<div>
|
||||
<label className="text-xs font-medium">Cline</label>
|
||||
<p className="mt-1 text-[11px] text-muted-foreground">
|
||||
{t("cline.configDescription")}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="text-[11px] text-muted-foreground">
|
||||
Provider
|
||||
</label>
|
||||
<Select
|
||||
value={selectedDraft.clineProvider}
|
||||
onValueChange={(value) => {
|
||||
handleClineFieldChange("clineProvider", value)
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="h-8 text-xs">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{CLINE_PROVIDERS.map((p) => (
|
||||
<SelectItem key={p.value} value={p.value}>
|
||||
{p.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="text-[11px] text-muted-foreground">
|
||||
API Key
|
||||
</label>
|
||||
<div className="flex items-center gap-2">
|
||||
<Input
|
||||
type={
|
||||
showApiKeys[selectedAgent.agent_type]
|
||||
? "text"
|
||||
: "password"
|
||||
}
|
||||
value={selectedDraft.clineApiKey}
|
||||
onChange={(event) => {
|
||||
handleClineFieldChange(
|
||||
"clineApiKey",
|
||||
event.target.value
|
||||
)
|
||||
}}
|
||||
placeholder="sk-..."
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setShowApiKeys((prev) => ({
|
||||
...prev,
|
||||
[selectedAgent.agent_type]:
|
||||
!prev[selectedAgent.agent_type],
|
||||
}))
|
||||
}}
|
||||
title={
|
||||
showApiKeys[selectedAgent.agent_type]
|
||||
? t("actions.hideApiKey")
|
||||
: t("actions.showApiKey")
|
||||
}
|
||||
>
|
||||
{showApiKeys[selectedAgent.agent_type] ? (
|
||||
<EyeOff className="h-3.5 w-3.5" />
|
||||
) : (
|
||||
<Eye className="h-3.5 w-3.5" />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="text-[11px] text-muted-foreground">
|
||||
Model
|
||||
</label>
|
||||
<Input
|
||||
value={selectedDraft.clineModel}
|
||||
onChange={(event) => {
|
||||
handleClineFieldChange(
|
||||
"clineModel",
|
||||
event.target.value
|
||||
)
|
||||
}}
|
||||
placeholder="claude-sonnet-4-5-20250514"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{(selectedDraft.clineProvider === "anthropic" ||
|
||||
selectedDraft.clineProvider === "openai-native" ||
|
||||
selectedDraft.clineProvider === "openai" ||
|
||||
selectedDraft.clineProvider === "openrouter" ||
|
||||
selectedDraft.clineProvider === "ollama") && (
|
||||
<div className="space-y-1.5">
|
||||
<label className="text-[11px] text-muted-foreground">
|
||||
API URL
|
||||
</label>
|
||||
<Input
|
||||
value={selectedDraft.clineBaseUrl}
|
||||
onChange={(event) => {
|
||||
handleClineFieldChange(
|
||||
"clineBaseUrl",
|
||||
event.target.value
|
||||
)
|
||||
}}
|
||||
placeholder="https://api.openai.com"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="text-[11px] text-muted-foreground">
|
||||
{t("nativeJsonConfig")} (config)
|
||||
</label>
|
||||
<Textarea
|
||||
value={selectedDraft.configText}
|
||||
onChange={(event) => {
|
||||
handleConfigTextChange(event.target.value)
|
||||
}}
|
||||
className="min-h-24 font-mono text-xs"
|
||||
placeholder={`{
|
||||
"apiProvider": "anthropic",
|
||||
"apiKey": "sk-...",
|
||||
"model": "claude-sonnet-4-5-20250514"
|
||||
}`}
|
||||
/>
|
||||
{selectedConfigError && (
|
||||
<div className="rounded-md border border-red-500/30 bg-red-500/5 px-2.5 py-1.5 text-[11px] text-red-400">
|
||||
{selectedConfigError}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
persistPreferences(
|
||||
selectedAgent.agent_type,
|
||||
selectedDraft.enabled,
|
||||
selectedDraft.envText,
|
||||
selectedDraft.configText
|
||||
)
|
||||
.then(() => {
|
||||
toast.success(t("toasts.clineSaved"), {
|
||||
description: t("toasts.configSavedHint"),
|
||||
})
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(
|
||||
"[Settings] save cline config failed:",
|
||||
err
|
||||
)
|
||||
const message =
|
||||
err instanceof Error ? err.message : String(err)
|
||||
toast.error(t("toasts.saveClineFailed"), {
|
||||
description: message,
|
||||
})
|
||||
})
|
||||
}}
|
||||
disabled={selectedIsSaving}
|
||||
>
|
||||
{selectedIsSaving ? (
|
||||
<>
|
||||
<Loader2 className="h-3.5 w-3.5 animate-spin" />
|
||||
{t("actions.saving")}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Save className="h-3.5 w-3.5" />
|
||||
{t("actions.saveClineConfig")}
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : selectedAgent.agent_type === "open_claw" ? (
|
||||
<div className="space-y-3 rounded-md border bg-muted/10 p-3">
|
||||
<div>
|
||||
|
||||
@@ -486,7 +486,8 @@
|
||||
"delete": "حذف",
|
||||
"deleting": "جارٍ الحذف...",
|
||||
"confirmDelete": "تأكيد الحذف",
|
||||
"confirmUninstall": "تأكيد إزالة التثبيت"
|
||||
"confirmUninstall": "تأكيد إزالة التثبيت",
|
||||
"saveClineConfig": "حفظ تكوين Cline"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "مفعّل",
|
||||
@@ -618,7 +619,9 @@
|
||||
"saveOpenClawFailed": "فشل حفظ إعداد OpenClaw",
|
||||
"configSaved": "تم حفظ الإعداد",
|
||||
"configSavedHint": "يجب إعادة فتح الجلسات الحالية لتطبيق التغييرات",
|
||||
"saveConfigManagementFailed": "فشل حفظ إدارة الإعدادات"
|
||||
"saveConfigManagementFailed": "فشل حفظ إدارة الإعدادات",
|
||||
"clineSaved": "تم حفظ تكوين Cline",
|
||||
"saveClineFailed": "فشل في حفظ تكوين Cline"
|
||||
},
|
||||
"version": {
|
||||
"statusLabel": "حالة الإصدار",
|
||||
@@ -630,6 +633,9 @@
|
||||
"upgradeAvailable": "{versionText}. تتوفر ترقية.",
|
||||
"remoteUnavailable": "{versionText}. الإصدار البعيد غير متاح حاليًا.",
|
||||
"latest": "{versionText}. أنت على أحدث إصدار."
|
||||
},
|
||||
"cline": {
|
||||
"configDescription": "تكوين مزود واجهة برمجة التطبيقات وبيانات اعتماد Cline. يتم حفظ الإعدادات في ~/.cline/data/."
|
||||
}
|
||||
},
|
||||
"SettingsPages": {
|
||||
|
||||
@@ -486,7 +486,8 @@
|
||||
"delete": "Löschen",
|
||||
"deleting": "Löschen...",
|
||||
"confirmDelete": "Löschen bestätigen",
|
||||
"confirmUninstall": "Deinstallation bestätigen"
|
||||
"confirmUninstall": "Deinstallation bestätigen",
|
||||
"saveClineConfig": "Cline-Konfiguration speichern"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "Aktiviert",
|
||||
@@ -618,7 +619,9 @@
|
||||
"saveOpenClawFailed": "Speichern der OpenClaw-Konfiguration fehlgeschlagen",
|
||||
"configSaved": "Konfiguration gespeichert",
|
||||
"configSavedHint": "Bestehende Sitzungen müssen neu geöffnet werden, damit die Änderungen wirksam werden",
|
||||
"saveConfigManagementFailed": "Speichern der Konfigurationsverwaltung fehlgeschlagen"
|
||||
"saveConfigManagementFailed": "Speichern der Konfigurationsverwaltung fehlgeschlagen",
|
||||
"clineSaved": "Cline-Konfiguration gespeichert",
|
||||
"saveClineFailed": "Cline-Konfiguration konnte nicht gespeichert werden"
|
||||
},
|
||||
"version": {
|
||||
"statusLabel": "Versionsstatus",
|
||||
@@ -630,6 +633,9 @@
|
||||
"upgradeAvailable": "{versionText}. Upgrade verfügbar.",
|
||||
"remoteUnavailable": "{versionText}. Remote-Version ist derzeit nicht verfügbar.",
|
||||
"latest": "{versionText}. Bereits aktuell."
|
||||
},
|
||||
"cline": {
|
||||
"configDescription": "Konfigurieren Sie den Cline API-Anbieter und die Anmeldedaten. Einstellungen werden in ~/.cline/data/ gespeichert."
|
||||
}
|
||||
},
|
||||
"SettingsPages": {
|
||||
|
||||
@@ -486,7 +486,8 @@
|
||||
"delete": "Delete",
|
||||
"deleting": "Deleting...",
|
||||
"confirmDelete": "Confirm Delete",
|
||||
"confirmUninstall": "Confirm Uninstall"
|
||||
"confirmUninstall": "Confirm Uninstall",
|
||||
"saveClineConfig": "Save Cline Config"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "Enabled",
|
||||
@@ -618,7 +619,9 @@
|
||||
"saveOpenClawFailed": "Failed to save OpenClaw config",
|
||||
"configSaved": "Config saved",
|
||||
"configSavedHint": "Existing sessions need to be reopened to take effect",
|
||||
"saveConfigManagementFailed": "Failed to save config management"
|
||||
"saveConfigManagementFailed": "Failed to save config management",
|
||||
"clineSaved": "Cline config saved",
|
||||
"saveClineFailed": "Failed to save Cline config"
|
||||
},
|
||||
"version": {
|
||||
"statusLabel": "Version Status",
|
||||
@@ -630,6 +633,9 @@
|
||||
"upgradeAvailable": "{versionText}. Upgrade available.",
|
||||
"remoteUnavailable": "{versionText}. Remote version is currently unavailable.",
|
||||
"latest": "{versionText}. Already latest."
|
||||
},
|
||||
"cline": {
|
||||
"configDescription": "Configure Cline API provider and credentials. Settings are saved to ~/.cline/data/."
|
||||
}
|
||||
},
|
||||
"SettingsPages": {
|
||||
|
||||
@@ -486,7 +486,8 @@
|
||||
"delete": "Eliminar",
|
||||
"deleting": "Eliminando...",
|
||||
"confirmDelete": "Confirmar eliminación",
|
||||
"confirmUninstall": "Confirmar desinstalación"
|
||||
"confirmUninstall": "Confirmar desinstalación",
|
||||
"saveClineConfig": "Guardar configuración de Cline"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "Habilitado",
|
||||
@@ -618,7 +619,9 @@
|
||||
"saveOpenClawFailed": "No se pudo guardar la configuración de OpenClaw",
|
||||
"configSaved": "Configuración guardada",
|
||||
"configSavedHint": "Las sesiones existentes deben reabrirse para que surta efecto",
|
||||
"saveConfigManagementFailed": "No se pudo guardar la gestión de configuración"
|
||||
"saveConfigManagementFailed": "No se pudo guardar la gestión de configuración",
|
||||
"clineSaved": "Configuración de Cline guardada",
|
||||
"saveClineFailed": "Error al guardar la configuración de Cline"
|
||||
},
|
||||
"version": {
|
||||
"statusLabel": "Estado de versión",
|
||||
@@ -630,6 +633,9 @@
|
||||
"upgradeAvailable": "{versionText}. Hay actualización disponible.",
|
||||
"remoteUnavailable": "{versionText}. La versión remota no está disponible por ahora.",
|
||||
"latest": "{versionText}. Ya está en la última versión."
|
||||
},
|
||||
"cline": {
|
||||
"configDescription": "Configure el proveedor de API y las credenciales de Cline. La configuración se guarda en ~/.cline/data/."
|
||||
}
|
||||
},
|
||||
"SettingsPages": {
|
||||
|
||||
@@ -486,7 +486,8 @@
|
||||
"delete": "Supprimer",
|
||||
"deleting": "Suppression...",
|
||||
"confirmDelete": "Confirmer la suppression",
|
||||
"confirmUninstall": "Confirmer la désinstallation"
|
||||
"confirmUninstall": "Confirmer la désinstallation",
|
||||
"saveClineConfig": "Enregistrer la configuration Cline"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "Activé",
|
||||
@@ -618,7 +619,9 @@
|
||||
"saveOpenClawFailed": "Échec de l’enregistrement de la configuration OpenClaw",
|
||||
"configSaved": "Configuration enregistrée",
|
||||
"configSavedHint": "Les sessions existantes doivent être rouvertes pour prendre effet",
|
||||
"saveConfigManagementFailed": "Échec de l’enregistrement de la gestion de configuration"
|
||||
"saveConfigManagementFailed": "Échec de l’enregistrement de la gestion de configuration",
|
||||
"clineSaved": "Configuration Cline enregistrée",
|
||||
"saveClineFailed": "Échec de l'enregistrement de la configuration Cline"
|
||||
},
|
||||
"version": {
|
||||
"statusLabel": "Statut de version",
|
||||
@@ -630,6 +633,9 @@
|
||||
"upgradeAvailable": "{versionText}. Mise à niveau disponible.",
|
||||
"remoteUnavailable": "{versionText}. La version distante est actuellement indisponible.",
|
||||
"latest": "{versionText}. Déjà à jour."
|
||||
},
|
||||
"cline": {
|
||||
"configDescription": "Configurez le fournisseur API et les identifiants Cline. Les paramètres sont enregistrés dans ~/.cline/data/."
|
||||
}
|
||||
},
|
||||
"SettingsPages": {
|
||||
|
||||
@@ -486,7 +486,8 @@
|
||||
"delete": "削除",
|
||||
"deleting": "削除中...",
|
||||
"confirmDelete": "削除を確認",
|
||||
"confirmUninstall": "アンインストールを確認"
|
||||
"confirmUninstall": "アンインストールを確認",
|
||||
"saveClineConfig": "Cline設定を保存"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "有効",
|
||||
@@ -618,7 +619,9 @@
|
||||
"saveOpenClawFailed": "OpenClaw設定の保存に失敗しました",
|
||||
"configSaved": "設定を保存しました",
|
||||
"configSavedHint": "既存のセッションは再度開く必要があります",
|
||||
"saveConfigManagementFailed": "設定管理の保存に失敗しました"
|
||||
"saveConfigManagementFailed": "設定管理の保存に失敗しました",
|
||||
"clineSaved": "Cline設定を保存しました",
|
||||
"saveClineFailed": "Cline設定の保存に失敗しました"
|
||||
},
|
||||
"version": {
|
||||
"statusLabel": "バージョン状態",
|
||||
@@ -630,6 +633,9 @@
|
||||
"upgradeAvailable": "{versionText}。アップグレード可能です。",
|
||||
"remoteUnavailable": "{versionText}。現在リモートバージョンは取得できません。",
|
||||
"latest": "{versionText}。すでに最新です。"
|
||||
},
|
||||
"cline": {
|
||||
"configDescription": "Cline API プロバイダーと認証情報を設定します。設定は ~/.cline/data/ に保存されます。"
|
||||
}
|
||||
},
|
||||
"SettingsPages": {
|
||||
|
||||
@@ -486,7 +486,8 @@
|
||||
"delete": "삭제",
|
||||
"deleting": "삭제 중...",
|
||||
"confirmDelete": "삭제 확인",
|
||||
"confirmUninstall": "제거 확인"
|
||||
"confirmUninstall": "제거 확인",
|
||||
"saveClineConfig": "Cline 설정 저장"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "활성화됨",
|
||||
@@ -618,7 +619,9 @@
|
||||
"saveOpenClawFailed": "OpenClaw 설정 저장 실패",
|
||||
"configSaved": "구성이 저장되었습니다",
|
||||
"configSavedHint": "기존 세션은 다시 열어야 적용됩니다",
|
||||
"saveConfigManagementFailed": "구성 관리 저장 실패"
|
||||
"saveConfigManagementFailed": "구성 관리 저장 실패",
|
||||
"clineSaved": "Cline 설정 저장됨",
|
||||
"saveClineFailed": "Cline 설정 저장 실패"
|
||||
},
|
||||
"version": {
|
||||
"statusLabel": "버전 상태",
|
||||
@@ -630,6 +633,9 @@
|
||||
"upgradeAvailable": "{versionText}. 업그레이드가 가능합니다.",
|
||||
"remoteUnavailable": "{versionText}. 현재 원격 버전을 사용할 수 없습니다.",
|
||||
"latest": "{versionText}. 이미 최신입니다."
|
||||
},
|
||||
"cline": {
|
||||
"configDescription": "Cline API 제공자와 자격 증명을 구성합니다. 설정은 ~/.cline/data/에 저장됩니다."
|
||||
}
|
||||
},
|
||||
"SettingsPages": {
|
||||
|
||||
@@ -486,7 +486,8 @@
|
||||
"delete": "Excluir",
|
||||
"deleting": "Excluindo...",
|
||||
"confirmDelete": "Confirmar exclusão",
|
||||
"confirmUninstall": "Confirmar desinstalação"
|
||||
"confirmUninstall": "Confirmar desinstalação",
|
||||
"saveClineConfig": "Salvar configuração do Cline"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "Habilitado",
|
||||
@@ -618,7 +619,9 @@
|
||||
"saveOpenClawFailed": "Falha ao salvar configuração do OpenClaw",
|
||||
"configSaved": "Configuração salva",
|
||||
"configSavedHint": "Sessões existentes precisam ser reabertas para que as alterações tenham efeito",
|
||||
"saveConfigManagementFailed": "Falha ao salvar o gerenciamento de configuração"
|
||||
"saveConfigManagementFailed": "Falha ao salvar o gerenciamento de configuração",
|
||||
"clineSaved": "Configuração do Cline salva",
|
||||
"saveClineFailed": "Falha ao salvar a configuração do Cline"
|
||||
},
|
||||
"version": {
|
||||
"statusLabel": "Status da versão",
|
||||
@@ -630,6 +633,9 @@
|
||||
"upgradeAvailable": "{versionText}. Atualização disponível.",
|
||||
"remoteUnavailable": "{versionText}. A versão remota está indisponível no momento.",
|
||||
"latest": "{versionText}. Já está na versão mais recente."
|
||||
},
|
||||
"cline": {
|
||||
"configDescription": "Configure o provedor de API e as credenciais do Cline. As configurações são salvas em ~/.cline/data/."
|
||||
}
|
||||
},
|
||||
"SettingsPages": {
|
||||
|
||||
@@ -486,7 +486,8 @@
|
||||
"delete": "删除",
|
||||
"deleting": "删除中...",
|
||||
"confirmDelete": "确认删除",
|
||||
"confirmUninstall": "确认卸载"
|
||||
"confirmUninstall": "确认卸载",
|
||||
"saveClineConfig": "保存 Cline 配置"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "启用",
|
||||
@@ -618,7 +619,9 @@
|
||||
"saveOpenClawFailed": "保存 OpenClaw 配置失败",
|
||||
"configSaved": "配置已保存",
|
||||
"configSavedHint": "已有会话需要重新打开才能生效",
|
||||
"saveConfigManagementFailed": "保存配置管理失败"
|
||||
"saveConfigManagementFailed": "保存配置管理失败",
|
||||
"clineSaved": "Cline 配置已保存",
|
||||
"saveClineFailed": "保存 Cline 配置失败"
|
||||
},
|
||||
"version": {
|
||||
"statusLabel": "版本状态",
|
||||
@@ -630,6 +633,9 @@
|
||||
"upgradeAvailable": "{versionText}。发现可升级版本。",
|
||||
"remoteUnavailable": "{versionText}。远程版本暂不可用。",
|
||||
"latest": "{versionText}。已是最新版本。"
|
||||
},
|
||||
"cline": {
|
||||
"configDescription": "配置 Cline API 提供商和凭证。设置将保存到 ~/.cline/data/。"
|
||||
}
|
||||
},
|
||||
"SettingsPages": {
|
||||
|
||||
@@ -486,7 +486,8 @@
|
||||
"delete": "刪除",
|
||||
"deleting": "刪除中...",
|
||||
"confirmDelete": "確認刪除",
|
||||
"confirmUninstall": "確認卸載"
|
||||
"confirmUninstall": "確認卸載",
|
||||
"saveClineConfig": "儲存 Cline 配置"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "啟用",
|
||||
@@ -618,7 +619,9 @@
|
||||
"saveOpenClawFailed": "儲存 OpenClaw 配置失敗",
|
||||
"configSaved": "配置已儲存",
|
||||
"configSavedHint": "已有會話需要重新打開才能生效",
|
||||
"saveConfigManagementFailed": "儲存配置管理失敗"
|
||||
"saveConfigManagementFailed": "儲存配置管理失敗",
|
||||
"clineSaved": "Cline 配置已儲存",
|
||||
"saveClineFailed": "儲存 Cline 配置失敗"
|
||||
},
|
||||
"version": {
|
||||
"statusLabel": "版本狀態",
|
||||
@@ -630,6 +633,9 @@
|
||||
"upgradeAvailable": "{versionText}。發現可升級版本。",
|
||||
"remoteUnavailable": "{versionText}。遠端版本暫不可用。",
|
||||
"latest": "{versionText}。已是最新版本。"
|
||||
},
|
||||
"cline": {
|
||||
"configDescription": "配置 Cline API 提供商和憑證。設定將儲存到 ~/.cline/data/。"
|
||||
}
|
||||
},
|
||||
"SettingsPages": {
|
||||
|
||||
@@ -38,6 +38,17 @@ const EXACT_TOOL_NAME_ALIASES: Record<string, string> = {
|
||||
search_text: "grep",
|
||||
writefile: "write",
|
||||
editfile: "edit",
|
||||
// Cline
|
||||
attempt_completion: "attempt_completion",
|
||||
ask_followup_question: "question",
|
||||
write_to_file: "write",
|
||||
replace_in_file: "edit",
|
||||
execute_command: "bash",
|
||||
list_files: "glob",
|
||||
search_files: "grep",
|
||||
list_code_definition_names: "grep",
|
||||
browser_action: "webfetch",
|
||||
use_mcp_tool: "tool",
|
||||
// Codex
|
||||
update_plan: "task",
|
||||
request_user_input: "question",
|
||||
|
||||
@@ -4,6 +4,7 @@ export type AgentType =
|
||||
| "open_code"
|
||||
| "gemini"
|
||||
| "open_claw"
|
||||
| "cline"
|
||||
|
||||
export type AppErrorCode =
|
||||
| "invalid_input"
|
||||
@@ -206,6 +207,7 @@ export const AGENT_DISPLAY_ORDER: AgentType[] = [
|
||||
"open_code",
|
||||
"gemini",
|
||||
"open_claw",
|
||||
"cline",
|
||||
]
|
||||
|
||||
const AGENT_DISPLAY_ORDER_INDEX = new Map(
|
||||
@@ -224,6 +226,7 @@ export const AGENT_LABELS: Record<AgentType, string> = {
|
||||
open_code: "OpenCode",
|
||||
gemini: "Gemini CLI",
|
||||
open_claw: "OpenClaw",
|
||||
cline: "Cline",
|
||||
}
|
||||
|
||||
export const AGENT_COLORS: Record<AgentType, string> = {
|
||||
@@ -232,6 +235,7 @@ export const AGENT_COLORS: Record<AgentType, string> = {
|
||||
open_code: "bg-blue-500",
|
||||
gemini: "bg-blue-400",
|
||||
open_claw: "bg-emerald-600",
|
||||
cline: "bg-purple-500",
|
||||
}
|
||||
|
||||
// ACP connection status (matches Rust ConnectionStatus)
|
||||
@@ -461,6 +465,7 @@ export interface AcpAgentInfo {
|
||||
opencode_auth_json: string | null
|
||||
codex_auth_json: string | null
|
||||
codex_config_toml: string | null
|
||||
cline_secrets_json: string | null
|
||||
}
|
||||
|
||||
// Lightweight agent status returned by acp_get_agent_status
|
||||
|
||||
Reference in New Issue
Block a user