feat(agents): add Cursor CLI support and remove Antigravity and Cursor IDE integrations
This commit is contained in:
1 parent
84c29782b0
commit
8901eff9bb
24 files changed
+530
-634
No files matched your search
@@ -0,0 +1,5 @@
|
||||
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M22.8416 1.387C23.4132 1.0062 24.1735 1.44515 24.1295 2.13055L22.6326 25.4656C22.5957 26.0405 21.8646 26.2609 21.5162 25.8022L15.0114 17.2395C14.8429 17.0177 14.5923 16.873 14.316 16.838L3.6481 15.486C3.07656 15.4136 2.9019 14.6703 3.38136 14.3509L22.8416 1.387Z" fill="#1E1E1E"/>
|
||||
<path d="M1.79102 15.2782L24.2386 0.457031L14.6808 17.0116L1.79102 15.2782Z" fill="#000000"/>
|
||||
<path d="M22.6278 27.3078L24.2394 0.457031L14.6816 17.0116L22.6278 27.3078Z" fill="#777777"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 587 B |
+2
-2
@@ -937,9 +937,9 @@ export const jaOverrides = {
|
||||
'agents.description.openclaw': 'CPA モデルプロバイダーと既定モデルを使用',
|
||||
'agents.description.hermes': 'CPA カスタムプロバイダーを使用',
|
||||
'agents.description.deepseekHarness': 'Harness のネイティブ DeepSeek 設定と分離された OpenAI 互換ルートで CPA を使用',
|
||||
'agents.description.antigravityIde': 'CPA の Gemini 互換 API で Antigravity IDE を設定',
|
||||
'agents.description.cursorCli': 'Cursor CLI (cursor-agent) の検出とネイティブ起動に対応',
|
||||
'agents.modify.cursorCliHint': 'Cursor CLI は cursor-agent 経由で起動され、~/.cursor/cli-config.json で設定されます。CPA ではローカルインストールの検出と、任意のディレクトリやターミナル選択からの起動をサポートしています。',
|
||||
'agents.description.antigravityCli': 'CPA の Gemini 互換 API で Antigravity CLI を設定',
|
||||
'agents.modify.antigravityIdeHint': '設定の適用・解除後は IDE を再起動してください。リクエストにはここで選択した CPA モデルが使用され、IDE 内のモデル表示名は変わりません。初回は IDE へのログインが必要です。',
|
||||
'agents.modify.antigravityCliHint': '設定適用後はこのページの起動ボタンを使用してください。CPA が CLI プロセスに接続先とキーを渡します。agy を直接実行する場合は環境変数の設定が必要です。',
|
||||
'agents.description.workbuddy': 'CPA の OpenAI Chat Completions API で WorkBuddy のカスタムモデルを設定',
|
||||
'agents.modify.workbuddyHint': '適用後、WorkBuddy で「CPA:モデル名」を選択してください。表示されない場合は App を再起動してください。既存の会話のモデルは自動で切り替わりません。',
|
||||
|
||||
@@ -937,9 +937,9 @@ export const en: Record<MessageKey, string> = {
|
||||
'agents.description.openclaw': 'Uses the CPA model provider and default model',
|
||||
'agents.description.hermes': 'Uses the CPA custom provider',
|
||||
'agents.description.deepseekHarness': 'Uses CPA through an isolated, OpenAI-compatible Harness route',
|
||||
'agents.description.antigravityIde': 'Configure Antigravity IDE with CPA’s Gemini-compatible API',
|
||||
'agents.description.cursorCli': 'Supports detection and native launch for Cursor CLI (cursor-agent)',
|
||||
'agents.modify.cursorCliHint': 'Cursor CLI runs via cursor-agent and is configured in ~/.cursor/cli-config.json. CPA supports local installation detection and launch with custom terminal and working directory.',
|
||||
'agents.description.antigravityCli': 'Configure Antigravity CLI with CPA’s Gemini-compatible API',
|
||||
'agents.modify.antigravityIdeHint': 'Restart the IDE after applying or disabling configuration. Requests use the CPA model selected here; model labels inside the IDE stay unchanged. Initial IDE sign-in is still required.',
|
||||
'agents.modify.antigravityCliHint': 'Use Launch on this page after applying configuration. CPA supplies the endpoint and key to that CLI process. Running agy directly requires setting the environment variables yourself.',
|
||||
'agents.description.workbuddy': 'Configures a WorkBuddy custom model using the CPA OpenAI Chat Completions API',
|
||||
'agents.modify.workbuddyHint': 'After applying, select “CPA:model name” in WorkBuddy. Restart the app if it is missing; existing conversations keep their selected model.',
|
||||
|
||||
@@ -936,9 +936,9 @@ export const zhCN = {
|
||||
'agents.description.openclaw': '使用 CPA 模型供应商和默认模型',
|
||||
'agents.description.hermes': '使用 CPA 自定义提供方',
|
||||
'agents.description.deepseekHarness': '通过通用 OpenAI 兼容路由使用 CPA,并与 Harness 原生 DeepSeek 配置隔离',
|
||||
'agents.description.antigravityIde': '使用 CPA 的 Gemini 兼容接口配置 Antigravity IDE',
|
||||
'agents.description.cursorCli': '支持 Cursor CLI (cursor-agent) 的检测与原生启动',
|
||||
'agents.modify.cursorCliHint': 'Cursor CLI 通过 cursor-agent 运行,使用 ~/.cursor/cli-config.json 配置。CPA 支持本地安装检测,并支持自定义终端与工作目录启动。',
|
||||
'agents.description.antigravityCli': '使用 CPA 的 Gemini 兼容接口配置 Antigravity CLI',
|
||||
'agents.modify.antigravityIdeHint': '应用或关闭配置后请重启 IDE。模型请求使用此处选择的 CPA 模型;IDE 内的模型标签保持原样。首次使用仍需完成 IDE 登录。',
|
||||
'agents.modify.antigravityCliHint': '应用后请使用此页的启动按钮,CPA 会为本次 CLI 进程注入地址和密钥。直接运行 agy 需要自行设置环境变量。',
|
||||
'agents.description.workbuddy': '使用 CPA 的 OpenAI Chat Completions 接口配置 WorkBuddy 自定义模型',
|
||||
'agents.modify.workbuddyHint': '应用后,在 WorkBuddy 的模型选择器中选择「CPA:模型名」。若未显示,请重启 App;已有会话的模型不会自动切换。',
|
||||
|
||||
+76
-29
@@ -38,6 +38,7 @@ import piIcon from '../assets/icons/pi-logo-on-light.svg';
|
||||
import zcodeIcon from '../assets/icons/zcode.png';
|
||||
import workbuddyIcon from '../assets/icons/workbuddy.png';
|
||||
import antigravityIcon from '../assets/icons/antigravity.svg';
|
||||
import cursorIcon from '../assets/icons/cursor.svg';
|
||||
import {
|
||||
agentModelAlias,
|
||||
filterAgentModels,
|
||||
@@ -82,8 +83,8 @@ type AgentClientId =
|
||||
| 'deepseek-harness'
|
||||
| 'zcode'
|
||||
| 'workbuddy'
|
||||
| 'antigravity-ide'
|
||||
| 'antigravity-cli'
|
||||
| 'cursor-cli'
|
||||
| 'kimi-code'
|
||||
| 'grok-build'
|
||||
| 'pi';
|
||||
@@ -233,7 +234,7 @@ type AgentDefinition = {
|
||||
name: string;
|
||||
icon?: string;
|
||||
Icon?: ComponentType<{ size?: number; 'aria-hidden'?: boolean }>;
|
||||
descriptionKey: 'agents.description.claudeCode' | 'agents.description.claudeDesktop' | 'agents.description.codex' | 'agents.description.opencode' | 'agents.description.openclaw' | 'agents.description.hermes' | 'agents.description.deepseekHarness' | 'agents.description.zcode' | 'agents.description.workbuddy' | 'agents.description.antigravityIde' | 'agents.description.antigravityCli' | 'agents.description.kimiCode' | 'agents.description.grokBuild' | 'agents.description.pi';
|
||||
descriptionKey: 'agents.description.claudeCode' | 'agents.description.claudeDesktop' | 'agents.description.codex' | 'agents.description.opencode' | 'agents.description.openclaw' | 'agents.description.hermes' | 'agents.description.deepseekHarness' | 'agents.description.zcode' | 'agents.description.workbuddy' | 'agents.description.antigravityCli' | 'agents.description.cursorCli' | 'agents.description.kimiCode' | 'agents.description.grokBuild' | 'agents.description.pi';
|
||||
};
|
||||
|
||||
type AgentSubpageId = 'core' | 'management' | 'sessions';
|
||||
@@ -287,8 +288,8 @@ const agentDefinitions: AgentDefinition[] = [
|
||||
icon: grokIcon,
|
||||
descriptionKey: 'agents.description.grokBuild',
|
||||
},
|
||||
{ id: 'antigravity-ide', name: 'Antigravity IDE', icon: antigravityIcon, descriptionKey: 'agents.description.antigravityIde' },
|
||||
{ id: 'antigravity-cli', name: 'Antigravity CLI', icon: antigravityIcon, descriptionKey: 'agents.description.antigravityCli' },
|
||||
{ id: 'cursor-cli', name: 'Cursor CLI', icon: cursorIcon, descriptionKey: 'agents.description.cursorCli' },
|
||||
{
|
||||
id: 'workbuddy',
|
||||
name: 'WorkBuddy',
|
||||
@@ -329,6 +330,21 @@ const agentSubpages: AgentSubpageDefinition[] = [
|
||||
{
|
||||
id: 'management',
|
||||
labelKey: 'agents.tabs.management',
|
||||
clients: [
|
||||
'claude-code',
|
||||
'claude-desktop',
|
||||
'codex',
|
||||
'opencode',
|
||||
'openclaw',
|
||||
'hermes',
|
||||
'deepseek-harness',
|
||||
'zcode',
|
||||
'workbuddy',
|
||||
'antigravity-cli',
|
||||
'kimi-code',
|
||||
'grok-build',
|
||||
'pi',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'sessions',
|
||||
@@ -796,8 +812,11 @@ export function AgentsPage({ embedded = false, onConfigurationApplied }: AgentsP
|
||||
const [viewStateByClient, setViewStateByClient] = useState(() => agentViewStateCache);
|
||||
const viewMode = embedded ? 'embedded' : 'full';
|
||||
const viewState = viewStateByClient[viewMode][selected] ?? DEFAULT_AGENT_VIEW_STATE;
|
||||
const activeSubpage = viewState.subpage === 'sessions' && (embedded || selected !== 'codex')
|
||||
? DEFAULT_AGENT_SUBPAGE : viewState.subpage;
|
||||
const isCursorClient = selected === 'cursor-cli';
|
||||
const activeSubpage = isCursorClient
|
||||
? DEFAULT_AGENT_SUBPAGE
|
||||
: viewState.subpage === 'sessions' && (embedded || selected !== 'codex')
|
||||
? DEFAULT_AGENT_SUBPAGE : viewState.subpage;
|
||||
const updateViewState = (patch: Partial<AgentViewState>) => {
|
||||
setViewStateByClient((current) => {
|
||||
const next = {
|
||||
@@ -919,6 +938,12 @@ export function AgentsPage({ embedded = false, onConfigurationApplied }: AgentsP
|
||||
}, []);
|
||||
|
||||
const loadModels = useCallback(async (client: AgentClientId, preferredModel = '') => {
|
||||
if (client === 'cursor-cli') {
|
||||
setModelLoading(false);
|
||||
setModelError('');
|
||||
setModels([]);
|
||||
return;
|
||||
}
|
||||
const requestId = modelRequestRef.current + 1;
|
||||
modelRequestRef.current = requestId;
|
||||
setModelLoading(true);
|
||||
@@ -1223,7 +1248,6 @@ export function AgentsPage({ embedded = false, onConfigurationApplied }: AgentsP
|
||||
const modificationDescription = activeStatus?.modificationState === 'invalid'
|
||||
? t('agents.modify.invalid')
|
||||
: nativeOauth ? t('agents.nativeOAuth.activeHint')
|
||||
: selected === 'antigravity-ide' ? t('agents.modify.antigravityIdeHint')
|
||||
: selected === 'antigravity-cli' ? t('agents.modify.antigravityCliHint')
|
||||
: selected === 'workbuddy'
|
||||
? t('agents.modify.workbuddyHint')
|
||||
@@ -1748,7 +1772,7 @@ export function AgentsPage({ embedded = false, onConfigurationApplied }: AgentsP
|
||||
};
|
||||
|
||||
const restartDesktopApp = async () => {
|
||||
if (!['codex', 'opencode', 'claude-desktop', 'zcode', 'workbuddy', 'antigravity-ide'].includes(selected)) return;
|
||||
if (!['codex', 'opencode', 'claude-desktop', 'zcode', 'workbuddy'].includes(selected)) return;
|
||||
setBusyAction('restart-app');
|
||||
setLaunchError('');
|
||||
try {
|
||||
@@ -2030,7 +2054,8 @@ export function AgentsPage({ embedded = false, onConfigurationApplied }: AgentsP
|
||||
</aside>
|
||||
|
||||
<section className="panel agent-config-panel">
|
||||
<div className="agent-subpage-tabs" role="tablist" aria-label={t('agents.tabs.label')}>
|
||||
{availableSubpages.length > 1 ? (
|
||||
<div className="agent-subpage-tabs" role="tablist" aria-label={t('agents.tabs.label')}>
|
||||
{availableSubpages.map((subpage) => (
|
||||
<button
|
||||
type="button"
|
||||
@@ -2058,6 +2083,7 @@ export function AgentsPage({ embedded = false, onConfigurationApplied }: AgentsP
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
{embedded && activeSubpage === 'core' ? (
|
||||
<div className="agent-minimal-config" id="agent-subpage-panel-core" role="tabpanel" aria-labelledby="agent-subpage-tab-core">
|
||||
<div className="agent-minimal-client-summary">
|
||||
@@ -2073,7 +2099,13 @@ export function AgentsPage({ embedded = false, onConfigurationApplied }: AgentsP
|
||||
|
||||
<MessageNotice message={activeStatus?.error || activeStatus?.warnings.join(';')} tone={activeStatus?.error ? 'error' : 'info'} />
|
||||
|
||||
{selected === 'claude-desktop' ? desktopModelEditor : <div className="agent-minimal-field">
|
||||
{isCursorClient ? (
|
||||
<div className="agent-unmanaged-notice">
|
||||
<p className="agent-model-hint">
|
||||
{t('agents.modify.cursorCliHint')}
|
||||
</p>
|
||||
</div>
|
||||
) : selected === 'claude-desktop' ? desktopModelEditor : <div className="agent-minimal-field">
|
||||
<label htmlFor="embedded-agent-model">{t(isDeepSeekHarnessClient ? 'agents.harness.defaultModel' : 'agents.useModel')}</label>
|
||||
<AgentModelPicker
|
||||
models={isClaudeModelMappingClient ? claudeMappingModels : models}
|
||||
@@ -2089,23 +2121,25 @@ export function AgentsPage({ embedded = false, onConfigurationApplied }: AgentsP
|
||||
|
||||
{isDeepSeekHarnessClient ? <p className="agent-model-hint">{t('agents.harness.defaultHint')}</p> : null}
|
||||
|
||||
<div className="agent-save-bar">
|
||||
{configurationFeedback}
|
||||
<div className={`agent-save-actions${!isPiClient ? ' agent-codex-save-actions' : ''}`}>
|
||||
{closeConfigurationButton}
|
||||
<button
|
||||
type="button"
|
||||
className="primary-button"
|
||||
onClick={applySelectedConfiguration}
|
||||
disabled={busy || !canEnable || configurationWriteBlocked}
|
||||
>
|
||||
{['apply', 'install-pi', 'repair-pi'].includes(busyAction ?? '') ? <LoaderCircle size={16} className="spin" /> : null}
|
||||
{isPiClient
|
||||
? activeStatus?.pluginInstalled ? configurationActionLabel : t('agents.pi.install')
|
||||
: configurationActionLabel}
|
||||
</button>
|
||||
{!isCursorClient ? (
|
||||
<div className="agent-save-bar">
|
||||
{configurationFeedback}
|
||||
<div className={`agent-save-actions${!isPiClient ? " agent-codex-save-actions" : ""}`}>
|
||||
{closeConfigurationButton}
|
||||
<button
|
||||
type="button"
|
||||
className="primary-button"
|
||||
onClick={applySelectedConfiguration}
|
||||
disabled={busy || !canEnable || configurationWriteBlocked}
|
||||
>
|
||||
{['apply', 'install-pi', 'repair-pi'].includes(busyAction ?? '') ? <LoaderCircle size={16} className="spin" /> : null}
|
||||
{isPiClient
|
||||
? activeStatus?.pluginInstalled ? configurationActionLabel : t('agents.pi.install')
|
||||
: configurationActionLabel}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
</div>
|
||||
) : null}
|
||||
@@ -2158,7 +2192,7 @@ export function AgentsPage({ embedded = false, onConfigurationApplied }: AgentsP
|
||||
</>
|
||||
) : (
|
||||
<div>
|
||||
<span>{t('agents.clientVersion')}</span>
|
||||
<span>{selected === 'cursor-cli' ? t('agents.cliVersion') : t('agents.clientVersion')}</span>
|
||||
<strong title={activeStatus?.version ?? undefined}>{activeStatus?.version ?? t('agents.notFetched')}</strong>
|
||||
</div>
|
||||
)}
|
||||
@@ -2166,7 +2200,18 @@ export function AgentsPage({ embedded = false, onConfigurationApplied }: AgentsP
|
||||
|
||||
<MessageNotice message={activeStatus?.error || activeStatus?.warnings.join(';')} tone={activeStatus?.error ? 'error' : 'info'} />
|
||||
|
||||
{!isClaudeModelMappingClient ? (
|
||||
{isCursorClient ? (
|
||||
<section className="agent-core-setting-section">
|
||||
<div className="agent-section-heading">
|
||||
<div><strong>{t('agents.description.cursorCli')}</strong></div>
|
||||
</div>
|
||||
<p className="agent-model-hint">
|
||||
{t('agents.modify.cursorCliHint')}
|
||||
</p>
|
||||
</section>
|
||||
) : null}
|
||||
|
||||
{!isCursorClient && !isClaudeModelMappingClient ? (
|
||||
<section className="agent-core-setting-section agent-model-section">
|
||||
<div className="agent-section-heading">
|
||||
<div><strong>{t(isDeepSeekHarnessClient ? 'agents.harness.defaultModel' : 'agents.useModel')}</strong></div>
|
||||
@@ -2396,9 +2441,10 @@ export function AgentsPage({ embedded = false, onConfigurationApplied }: AgentsP
|
||||
</section>
|
||||
) : null}
|
||||
|
||||
{!isCursorClient ? (
|
||||
<div className="agent-save-bar">
|
||||
{configurationFeedback}
|
||||
<div className={`agent-save-actions${!isPiClient ? ' agent-codex-save-actions' : ''}`}>
|
||||
<div className={`agent-save-actions${!isPiClient ? " agent-codex-save-actions" : ""}`}>
|
||||
{closeConfigurationButton}
|
||||
<button type="button" className="primary-button" onClick={applySelectedConfiguration}
|
||||
disabled={busy || !canEnable || configurationWriteBlocked}
|
||||
@@ -2408,6 +2454,7 @@ export function AgentsPage({ embedded = false, onConfigurationApplied }: AgentsP
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
</div>
|
||||
) : null}
|
||||
@@ -2443,7 +2490,7 @@ export function AgentsPage({ embedded = false, onConfigurationApplied }: AgentsP
|
||||
<MessageNotice tone="success" message={!configurationErrorMessage ? configurationNotice || clearNotice : null}
|
||||
onDismiss={() => { setConfigurationNotice(''); setClearNotice(''); }} />
|
||||
{activeSubpage === 'core' ? <AgentRunControls name={activeDefinition.name} dualTargets={hasIndependentCliAndApp}
|
||||
desktop={hasIndependentCliAndApp || selected === 'claude-desktop' || selected === 'zcode' || selected === 'workbuddy' || selected === 'antigravity-ide'}
|
||||
desktop={hasIndependentCliAndApp || selected === 'claude-desktop' || selected === 'zcode' || selected === 'workbuddy'}
|
||||
targets={activeLaunchTargets} enabled={launchEnabled} busyAction={busyAction}
|
||||
harness={isDeepSeekHarnessClient ? deepSeekHarnessProcessStatus : null}
|
||||
onLaunch={(target) => void launchAgent(target)} onRestart={() => void restartDesktopApp()}
|
||||
|
||||
Reference in new issue
Block a user