Merge pull request #452 from aaaaron/feat/gemini-adapter-improvements

feat(adapters/gemini-local): Gemini CLI adapter with auth, skills, and sandbox support
This commit is contained in:
Dotta
2026-03-11 13:43:28 -05:00
committed by GitHub
40 changed files with 2295 additions and 27 deletions

View File

@@ -16,6 +16,7 @@ import {
DEFAULT_CODEX_LOCAL_MODEL,
} from "@paperclipai/adapter-codex-local";
import { DEFAULT_CURSOR_LOCAL_MODEL } from "@paperclipai/adapter-cursor-local";
import { DEFAULT_GEMINI_LOCAL_MODEL } from "@paperclipai/adapter-gemini-local";
import {
Popover,
PopoverContent,
@@ -282,6 +283,7 @@ export function AgentConfigForm(props: AgentConfigFormProps) {
const isLocal =
adapterType === "claude_local" ||
adapterType === "codex_local" ||
adapterType === "gemini_local" ||
adapterType === "opencode_local" ||
adapterType === "cursor";
const uiAdapter = useMemo(() => getUIAdapter(adapterType), [adapterType]);
@@ -374,9 +376,10 @@ export function AgentConfigForm(props: AgentConfigFormProps) {
)
: adapterType === "cursor"
? eff("adapterConfig", "mode", String(config.mode ?? ""))
: adapterType === "opencode_local"
? eff("adapterConfig", "variant", String(config.variant ?? ""))
: adapterType === "opencode_local"
? eff("adapterConfig", "variant", String(config.variant ?? ""))
: eff("adapterConfig", "effort", String(config.effort ?? ""));
const showThinkingEffort = adapterType !== "gemini_local";
const codexSearchEnabled = adapterType === "codex_local"
? (isCreate ? Boolean(val!.search) : eff("adapterConfig", "search", Boolean(config.search)))
: false;
@@ -494,6 +497,8 @@ export function AgentConfigForm(props: AgentConfigFormProps) {
nextValues.model = DEFAULT_CODEX_LOCAL_MODEL;
nextValues.dangerouslyBypassSandbox =
DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX;
} else if (t === "gemini_local") {
nextValues.model = DEFAULT_GEMINI_LOCAL_MODEL;
} else if (t === "cursor") {
nextValues.model = DEFAULT_CURSOR_LOCAL_MODEL;
} else if (t === "opencode_local") {
@@ -510,6 +515,8 @@ export function AgentConfigForm(props: AgentConfigFormProps) {
model:
t === "codex_local"
? DEFAULT_CODEX_LOCAL_MODEL
: t === "gemini_local"
? DEFAULT_GEMINI_LOCAL_MODEL
: t === "cursor"
? DEFAULT_CURSOR_LOCAL_MODEL
: "",
@@ -615,6 +622,8 @@ export function AgentConfigForm(props: AgentConfigFormProps) {
placeholder={
adapterType === "codex_local"
? "codex"
: adapterType === "gemini_local"
? "gemini"
: adapterType === "cursor"
? "agent"
: adapterType === "opencode_local"
@@ -646,24 +655,28 @@ export function AgentConfigForm(props: AgentConfigFormProps) {
</p>
)}
<ThinkingEffortDropdown
value={currentThinkingEffort}
options={thinkingEffortOptions}
onChange={(v) =>
isCreate
? set!({ thinkingEffort: v })
: mark("adapterConfig", thinkingEffortKey, v || undefined)
}
open={thinkingEffortOpen}
onOpenChange={setThinkingEffortOpen}
/>
{adapterType === "codex_local" &&
codexSearchEnabled &&
currentThinkingEffort === "minimal" && (
<p className="text-xs text-amber-400">
Codex may reject `minimal` thinking when search is enabled.
</p>
)}
{showThinkingEffort && (
<>
<ThinkingEffortDropdown
value={currentThinkingEffort}
options={thinkingEffortOptions}
onChange={(v) =>
isCreate
? set!({ thinkingEffort: v })
: mark("adapterConfig", thinkingEffortKey, v || undefined)
}
open={thinkingEffortOpen}
onOpenChange={setThinkingEffortOpen}
/>
{adapterType === "codex_local" &&
codexSearchEnabled &&
currentThinkingEffort === "minimal" && (
<p className="text-xs text-amber-400">
Codex may reject `minimal` thinking when search is enabled.
</p>
)}
</>
)}
<Field label="Bootstrap prompt (first run)" hint={help.bootstrapPrompt}>
<MarkdownEditor
value={
@@ -898,7 +911,7 @@ function AdapterEnvironmentResult({ result }: { result: AdapterEnvironmentTestRe
/* ---- Internal sub-components ---- */
const ENABLED_ADAPTER_TYPES = new Set(["claude_local", "codex_local", "opencode_local", "cursor"]);
const ENABLED_ADAPTER_TYPES = new Set(["claude_local", "codex_local", "gemini_local", "opencode_local", "cursor"]);
/** Display list includes all real adapter types plus UI-only coming-soon entries. */
const ADAPTER_DISPLAY_LIST: { value: string; label: string; comingSoon: boolean }[] = [