forked from farhoodlabs/paperclip
9578dc3da7
> **Stacked PR.** Sits on top of the e2b sandbox chain — #5278 (stdin staging) and #5279 (honest-resolvability + login-profiles). The cumulative diff against `master` includes both of those PRs' content; the files touched by *this* PR's commit are the new `maybeRunSandboxInstallCommand` helper in `packages/adapter-utils/src/execution-target.ts` and the per-adapter `index.ts`/`server/test.ts`/`server/execute.ts` wiring under `packages/adapters/{claude,codex,cursor,gemini,opencode,pi}-local/`. The honest resolvability check from #5279 is what gives this PR's install command a meaningful "did it actually land on PATH" follow-up. ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Sandbox execution targets are ephemeral — each fresh lease starts from a template image that may or may not have the agent CLIs preinstalled > - When a CLI isn't preinstalled, the resolvability probe fails at `command -v` and the hello probe never runs > - There's no shared mechanism for "before you probe or provision, install the CLI on this sandbox" > - This pull request adds a `SANDBOX_INSTALL_COMMAND` constant per adapter and a `maybeRunSandboxInstallCommand` helper that runs it via the existing sandbox login shell, captures structured output, and never throws (so the resolvability + hello probe still run after); each adapter's `test()` and `execute()` share the constant so the two callsites can't drift > - The benefit is a fresh sandbox lease without a preinstalled CLI now installs it once via `sh -lc` before the resolvability probe and before managed-runtime provisioning, with a uniform `<adapter>_install_command_run` check on the test report ## What Changed - `packages/adapter-utils/src/execution-target.ts`: add `AdapterSandboxInstallCommandCheck` and `maybeRunSandboxInstallCommand` (runs the install via existing sandbox shell, captures exit/stdout/stderr, returns a structured info/warn check, never throws) - Add `SANDBOX_INSTALL_COMMAND` to each adapter's `index.ts` so `test()` and `execute()` share a single source of truth - Wire each of the 6 affected adapter `testEnvironment()`s to call `maybeRunSandboxInstallCommand` before `ensureAdapterExecutionTargetCommandResolvable` - Pass `installCommand: SANDBOX_INSTALL_COMMAND` through `prepareAdapterExecutionTargetRuntime` in each adapter's `execute()` - Per-adapter install commands use npm globals where possible so binaries land on a PATH segment the template already exports: - claude → `npm install -g @anthropic-ai/claude-code` - codex → `npm install -g @openai/codex` - cursor → `curl https://cursor.com/install -fsS | bash` - gemini → `npm install -g @google/gemini-cli` - opencode → `npm install -g opencode-ai` - pi → `npm install -g @mariozechner/pi-coding-agent` SSH and local targets ignore `installCommand` (SSH runtime takes no such param; local short-circuits before runtime prep), so this is a no-op for non-sandbox environments. ## Verification - `pnpm typecheck` clean - `pnpm vitest run --no-coverage --project @paperclipai/adapter-utils` and per-adapter projects pass - Manual sandbox matrix (claude, codex, cursor, gemini, opencode, pi) — each goes `install_command_run → resolvable → hello_probe_passed` (Codex and Pi land on `hello_probe_auth_required`, which is the configured-credentials problem, not an install issue) - SSH no-regression: SSH Claude still passes; the helper short-circuits on non-sandbox targets ## Risks Medium — adds a network/CPU cost (npm install / curl) on every fresh sandbox lease. Cost is bounded (one-time per lease, typically tens of seconds for npm globals), and the helper never throws so a failing install still lets the report run resolvability and hello probes. If a sandbox image already has the CLI, the install is an idempotent reinstall. ## Model Used Claude Opus 4.7 (1M context) ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots — N/A (no UI) - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge
65 lines
2.7 KiB
TypeScript
65 lines
2.7 KiB
TypeScript
import type { AdapterModelProfileDefinition } from "@paperclipai/adapter-utils";
|
|
|
|
export const type = "gemini_local";
|
|
export const label = "Gemini CLI (local)";
|
|
|
|
export const SANDBOX_INSTALL_COMMAND = "npm install -g @google/gemini-cli";
|
|
|
|
export const DEFAULT_GEMINI_LOCAL_MODEL = "auto";
|
|
|
|
export const models = [
|
|
{ id: DEFAULT_GEMINI_LOCAL_MODEL, label: "Auto" },
|
|
{ id: "gemini-2.5-pro", label: "Gemini 2.5 Pro" },
|
|
{ id: "gemini-2.5-flash", label: "Gemini 2.5 Flash" },
|
|
{ id: "gemini-2.5-flash-lite", label: "Gemini 2.5 Flash Lite" },
|
|
{ id: "gemini-2.0-flash", label: "Gemini 2.0 Flash" },
|
|
{ id: "gemini-2.0-flash-lite", label: "Gemini 2.0 Flash Lite" },
|
|
];
|
|
|
|
export const modelProfiles: AdapterModelProfileDefinition[] = [
|
|
{
|
|
key: "cheap",
|
|
label: "Cheap",
|
|
description: "Use Gemini Flash Lite as the budget Gemini CLI lane while preserving the primary model.",
|
|
adapterConfig: {
|
|
model: "gemini-2.5-flash-lite",
|
|
},
|
|
source: "adapter_default",
|
|
},
|
|
];
|
|
|
|
export const agentConfigurationDoc = `# gemini_local agent configuration
|
|
|
|
Adapter: gemini_local
|
|
|
|
Use when:
|
|
- You want Paperclip to run the Gemini CLI locally on the host machine
|
|
- You want Gemini chat sessions resumed across heartbeats with --resume
|
|
- You want Paperclip skills injected locally without polluting the global environment
|
|
|
|
Don't use when:
|
|
- You need webhook-style external invocation (use http or openclaw_gateway)
|
|
- You only need a one-shot script without an AI coding agent loop (use process)
|
|
- Gemini CLI is not installed on the machine that runs Paperclip
|
|
|
|
Core fields:
|
|
- cwd (string, optional): default absolute working directory fallback for the agent process (created if missing when possible)
|
|
- instructionsFilePath (string, optional): absolute path to a markdown instructions file prepended to the run prompt
|
|
- promptTemplate (string, optional): run prompt template
|
|
- model (string, optional): Gemini model id. Defaults to auto.
|
|
- sandbox (boolean, optional): run in sandbox mode (default: false, passes --sandbox=none)
|
|
- command (string, optional): defaults to "gemini"
|
|
- extraArgs (string[], optional): additional CLI args
|
|
- env (object, optional): KEY=VALUE environment variables
|
|
|
|
Operational fields:
|
|
- timeoutSec (number, optional): run timeout in seconds
|
|
- graceSec (number, optional): SIGTERM grace period in seconds
|
|
|
|
Notes:
|
|
- Runs use positional prompt arguments, not stdin.
|
|
- Sessions resume with --resume when stored session cwd matches the current cwd.
|
|
- Paperclip auto-injects local skills into \`~/.gemini/skills/\` via symlinks, so the CLI can discover both credentials and skills in their natural location.
|
|
- Authentication can use GEMINI_API_KEY / GOOGLE_API_KEY or local Gemini CLI login.
|
|
`;
|