feat: ACP base provider, Copilot integration, eliminate hardcoded provider unions (#170)
* feat(server): add ACP base provider with Claude ACP integration Implement a generic Agent Client Protocol (ACP) base provider that any ACP-compatible agent can extend with minimal code. Includes a concrete Claude ACP implementation via @agentclientprotocol/claude-agent-acp with full parity to the existing Claude Code provider. The base handles subprocess lifecycle, streaming translation, permission bridging, terminal/fs callbacks, listModels, loadSession/resume, and mode/model management. The concrete class only specifies the command, modes, and availability check. * fix: update lockfile signatures and Nix hash * feat: add Copilot ACP provider, eliminate hardcoded provider unions, fix ACP streaming bugs Add Copilot as an ACP provider (copilot --acp), with real modes and models discovered from the ACP server. Fix two ACP base bugs: duplicate assistant text (emit deltas not cumulative) and idle→running→stuck (fire-and-return startTurn). Replace all hardcoded provider string unions with string/manifest- derived values so adding a provider only requires: impl class, manifest entry, registry factory, icon, and E2E config. Add provider docs and Copilot icon. * fix: update lockfile signatures and Nix hash * feat(app): add OpenCode provider icon --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
github-actions[bot] <github-actions[bot]@users.noreply.github.com>
parent
5d89f9444a
commit
a854096c35
@@ -11,9 +11,8 @@ import { AgentInputArea } from "@/components/agent-input-area";
|
||||
import { ArchivedAgentCallout } from "@/components/archived-agent-callout";
|
||||
import { FileDropZone } from "@/components/file-drop-zone";
|
||||
import type { ImageAttachment } from "@/components/message-input";
|
||||
import { getProviderIcon } from "@/components/provider-icons";
|
||||
import { ToastViewport, useToastHost } from "@/components/toast-host";
|
||||
import { ClaudeIcon } from "@/components/icons/claude-icon";
|
||||
import { CodexIcon } from "@/components/icons/codex-icon";
|
||||
import { useAgentAttentionClear } from "@/hooks/use-agent-attention-clear";
|
||||
import { useAgentInitialization } from "@/hooks/use-agent-initialization";
|
||||
import {
|
||||
@@ -51,16 +50,14 @@ import {
|
||||
} from "@/screens/agent/agent-ready-screen-bottom-anchor";
|
||||
|
||||
function formatProviderLabel(provider: Agent["provider"]): string {
|
||||
if (provider === "claude") {
|
||||
return "Claude";
|
||||
}
|
||||
if (provider === "codex") {
|
||||
return "Codex";
|
||||
}
|
||||
if (!provider) {
|
||||
return "Agent";
|
||||
}
|
||||
return provider.charAt(0).toUpperCase() + provider.slice(1);
|
||||
return provider
|
||||
.split(/[-_\s]+/)
|
||||
.filter((part) => part.length > 0)
|
||||
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
||||
.join(" ");
|
||||
}
|
||||
|
||||
function resolveWorkspaceAgentTabLabel(title: string | null | undefined): string | null {
|
||||
@@ -96,7 +93,7 @@ function useAgentPanelDescriptor(
|
||||
);
|
||||
const provider = descriptorState.provider;
|
||||
const label = resolveWorkspaceAgentTabLabel(descriptorState.title);
|
||||
const icon = provider === "claude" ? ClaudeIcon : provider === "codex" ? CodexIcon : Bot;
|
||||
const icon = getProviderIcon(provider) ?? Bot;
|
||||
|
||||
return {
|
||||
label: label ?? "",
|
||||
|
||||
Reference in New Issue
Block a user