mirror of
https://github.com/block/goose.git
synced 2026-07-17 12:56:20 +02:00
Show setup instructions for ACP providers in settings modal (#8065)
Signed-off-by: Michael Neale <michael.neale@gmail.com>
This commit is contained in:
@@ -25,12 +25,18 @@ impl ProviderDef for ClaudeAcpProvider {
|
||||
ProviderMetadata::new(
|
||||
CLAUDE_ACP_PROVIDER_NAME,
|
||||
"Claude Code",
|
||||
"ACP wrapper for Anthropic's Claude. Install: npm install -g @zed-industries/claude-agent-acp",
|
||||
"Use goose with your Claude Code subscription via the claude-agent-acp adapter.",
|
||||
ACP_CURRENT_MODEL,
|
||||
vec![],
|
||||
CLAUDE_ACP_DOC_URL,
|
||||
vec![],
|
||||
)
|
||||
.with_setup_steps(vec![
|
||||
"Install the ACP adapter: `npm install -g @zed-industries/claude-agent-acp`",
|
||||
"Ensure your Claude CLI is authenticated (run `claude` to verify)",
|
||||
"Set in your goose config file (`~/.config/goose/config.yaml` on macOS/Linux):\n GOOSE_PROVIDER: claude-acp\n GOOSE_MODEL: current",
|
||||
"Restart goose for changes to take effect",
|
||||
])
|
||||
}
|
||||
|
||||
fn from_env(
|
||||
|
||||
@@ -24,12 +24,18 @@ impl ProviderDef for CodexAcpProvider {
|
||||
ProviderMetadata::new(
|
||||
CODEX_ACP_PROVIDER_NAME,
|
||||
"Codex CLI",
|
||||
"ACP adapter for OpenAI's coding assistant. Install: npm install -g @zed-industries/codex-acp",
|
||||
"Use goose with your ChatGPT Plus/Pro subscription via the codex-acp adapter.",
|
||||
ACP_CURRENT_MODEL,
|
||||
vec![],
|
||||
CODEX_ACP_DOC_URL,
|
||||
vec![],
|
||||
)
|
||||
.with_setup_steps(vec![
|
||||
"Install the ACP adapter: `npm install -g @zed-industries/codex-acp`",
|
||||
"Run `codex` once to authenticate with your OpenAI account",
|
||||
"Set in your goose config file (`~/.config/goose/config.yaml` on macOS/Linux):\n GOOSE_PROVIDER: codex-acp\n GOOSE_MODEL: current",
|
||||
"Restart goose for changes to take effect",
|
||||
])
|
||||
}
|
||||
|
||||
fn from_env(
|
||||
|
||||
@@ -24,12 +24,18 @@ impl ProviderDef for GeminiAcpProvider {
|
||||
ProviderMetadata::new(
|
||||
GEMINI_ACP_PROVIDER_NAME,
|
||||
"Gemini CLI (ACP)",
|
||||
"ACP provider for Google's Gemini CLI. Install: npm install -g @google/gemini-cli",
|
||||
"Use goose with your Google Gemini subscription via the Gemini CLI.",
|
||||
ACP_CURRENT_MODEL,
|
||||
vec![],
|
||||
GEMINI_ACP_DOC_URL,
|
||||
vec![],
|
||||
)
|
||||
.with_setup_steps(vec![
|
||||
"Install the Gemini CLI: `npm install -g @google/gemini-cli`",
|
||||
"Run `gemini` once to authenticate with your Google account",
|
||||
"Set in your goose config file (`~/.config/goose/config.yaml` on macOS/Linux):\n GOOSE_PROVIDER: gemini-acp\n GOOSE_MODEL: current",
|
||||
"Restart goose for changes to take effect",
|
||||
])
|
||||
}
|
||||
|
||||
fn from_env(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import { useState, Fragment } from 'react';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -26,6 +26,36 @@ import {
|
||||
import { Button } from '../../../../components/ui/button';
|
||||
import { errorMessage } from '../../../../utils/conversionUtils';
|
||||
|
||||
/** Render a setup step string, turning `backtick` spans into <code> and newlines into <br/>. */
|
||||
function renderSetupStep(text: string) {
|
||||
// Split on backtick-wrapped segments
|
||||
const parts = text.split(/(`[^`]+`)/g);
|
||||
return parts.map((part, i) => {
|
||||
if (part.startsWith('`') && part.endsWith('`')) {
|
||||
return (
|
||||
<code
|
||||
key={i}
|
||||
className="px-1 py-0.5 rounded bg-background-secondary text-xs font-mono break-all"
|
||||
>
|
||||
{part.slice(1, -1)}
|
||||
</code>
|
||||
);
|
||||
}
|
||||
// Handle newlines within text
|
||||
const lines = part.split('\n');
|
||||
return (
|
||||
<Fragment key={i}>
|
||||
{lines.map((line, j) => (
|
||||
<Fragment key={j}>
|
||||
{j > 0 && <br />}
|
||||
{line}
|
||||
</Fragment>
|
||||
))}
|
||||
</Fragment>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
interface ProviderConfigurationModalProps {
|
||||
provider: ProviderDetails;
|
||||
onClose: () => void;
|
||||
@@ -59,13 +89,20 @@ export default function ProviderConfigurationModal({
|
||||
? `Delete configuration for ${provider.metadata.display_name}`
|
||||
: `Configure ${provider.metadata.display_name}`;
|
||||
|
||||
const isExternalSetup =
|
||||
provider.metadata.config_keys.length === 0 &&
|
||||
provider.metadata.setup_steps &&
|
||||
provider.metadata.setup_steps.length > 0;
|
||||
|
||||
const descriptionText = showDeleteConfirmation
|
||||
? isActiveProvider
|
||||
? `You cannot delete this provider while it's currently in use. Please switch to a different model first.`
|
||||
: 'This will permanently delete the current provider configuration.'
|
||||
: isOAuthProvider
|
||||
? `Sign in with your ${provider.metadata.display_name} account to use this provider`
|
||||
: `Add your API key(s) for this provider to integrate into goose`;
|
||||
: isExternalSetup
|
||||
? provider.metadata.description
|
||||
: `Add your API key(s) for this provider to integrate into goose`;
|
||||
|
||||
const handleOAuthLogin = async () => {
|
||||
setIsOAuthLoading(true);
|
||||
@@ -241,6 +278,35 @@ export default function ProviderConfigurationModal({
|
||||
A browser window will open for you to complete the login.
|
||||
</p>
|
||||
</div>
|
||||
) : provider.metadata.config_keys.length === 0 &&
|
||||
provider.metadata.setup_steps &&
|
||||
provider.metadata.setup_steps.length > 0 ? (
|
||||
<div className="space-y-3">
|
||||
<p className="text-sm text-text-secondary">
|
||||
This provider is configured outside of goose. Follow these steps:
|
||||
</p>
|
||||
<ol className="ml-5 list-decimal text-sm text-text-primary space-y-2">
|
||||
{provider.metadata.setup_steps.map((step, i) => (
|
||||
<li key={i}>{renderSetupStep(step)}</li>
|
||||
))}
|
||||
</ol>
|
||||
{provider.metadata.model_doc_link && (
|
||||
<p className="text-sm text-text-secondary mt-4">
|
||||
See the{' '}
|
||||
<a
|
||||
href="#"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
window.electron.openExternal(provider.metadata.model_doc_link);
|
||||
}}
|
||||
className="underline hover:text-text-primary"
|
||||
>
|
||||
documentation
|
||||
</a>{' '}
|
||||
for more details.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{/* Contains information used to set up each provider */}
|
||||
@@ -271,6 +337,20 @@ export default function ProviderConfigurationModal({
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
) : provider.metadata.config_keys.length === 0 &&
|
||||
provider.metadata.setup_steps &&
|
||||
provider.metadata.setup_steps.length > 0 &&
|
||||
!showDeleteConfirmation ? (
|
||||
<div className="w-full">
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
onClick={handleCancel}
|
||||
className="w-full h-[60px] rounded-none border-t border-border-primary text-md hover:bg-background-secondary text-text-primary font-medium"
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<ProviderSetupActions
|
||||
primaryParameters={primaryParameters}
|
||||
|
||||
Reference in New Issue
Block a user