mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-28 12:04:41 +01:00
<!-- entire-trail-link-start --> https://entire.com/gh/paperclipai/-/trails/26/changes/paperclip/26 <!-- entire-trail-link-end --> ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agents run on coding harnesses. Each adapter has a model catalog, and sandboxes contain pinned CLIs. > - Upstream providers released new CLI versions and new models. OpenAI retired some Codex models for ChatGPT sign-in. > - A stale catalog hides valid models. A misleading error makes operators upgrade a CLI that is already current. > - This pull request adds verified OpenCode model IDs, names Codex ChatGPT retirements in the environment Test, and refreshes the sandbox CLI pins. > - The benefit is that operators can select current models and get the correct reason when a retired model fails. ## Linked Issues or Issue Description Refs #16708 (adds Claude Haiku 5.5 to `claude_local`; this PR does not duplicate it). Refs #17245 (moves the Codex runtime to 0.163.0; this PR does not change Codex pins). **What happened?** OpenAI retired `gpt-5.5` (October 14, 2026) and `gpt-5.4` / `gpt-5.4-mini` (August 31, 2026) from Codex with ChatGPT sign-in. A saved agent with one of these models and ChatGPT sign-in now fails. The legacy environment Test says that the plan, the rollout, or an old CLI can be the cause. The Paperclip Runner Test gives generic account and runtime advice. The real cause is the retirement. **Expected behavior** Both Tests give the retirement date and the documented replacement. API-key users keep the models. **Proposed change** Record the verified retirements. Add the new verified OpenCode IDs. Refresh the sandbox CLI pins with verified digests. Record the audit. ## What Changed - Codex: add a table of models retired from Codex with ChatGPT sign-in (`gpt-5.5` → `gpt-6.1-sol`, or `gpt-6-luna` on Free and Go; `gpt-5.4` → `gpt-6-sol`; `gpt-5.4-mini` → `gpt-6-luna`). The shared `codexChatGptRetirementHint` builds the hint. The legacy CLI Test (`codexHelloProbeModelRejectionCheck`) and the Paperclip Runner Test (`testNativeRunnerAuthentication`) both use it when the backend rejects one of these models. For other failures, the Paperclip Runner Test hint stays the same. The picker keeps the models for API-key users. - OpenCode: add `anthropic/claude-haiku-5-5` and `google/gemini-4-argon` to the remote fallback catalog. The Paperclip Runner OpenCode picker also uses this catalog. - Evaluation image sandbox layer (`docker/daytona-runner`): | CLI | Before | After | | --- | --- | --- | | Grok CLI | 1.0.46 | 1.0.70 | | Gemini CLI | 0.62.0 | 0.65.0 | | Kimi Code | 2.1.1 | 2.3.3 | | Cursor CLI | 2026.10.01-e373342 | 2026.10.22-27dcf5f | | GitHub CLI | 2.102.0 | 2.103.3 | - Add `doc/adapter-model-audit-2026-10-23.md` with sources, compatibility findings, and deferred items. No model in this PR needs a newer Codex, Claude, or OpenCode runtime than the current pins. Claude Haiku 5.5 needs Claude Code 2.1.293 or later; #16708 records that floor, and this PR does not add it. ## Verification - `vitest run src/index.test.ts src/server/test.remote.test.ts src/server/acp.cli-version.test.ts` in `packages/adapters/codex-local`: 41 passed. - `vitest run src/services/native-runtime/setup-readiness.test.ts` in `server`: 98 passed. These include the two new Paperclip Runner Test cases: a retired model shows the retirement hint, and a model that is not retired keeps the generic hint. The retirement case fails on the earlier code. Run with the host's empty `ANTHROPIC_BASE_URL` unset; see the baseline note in the audit doc. - `vitest run` in `packages/adapters/opencode-local`: 87 passed. - `vitest run src/__tests__/adapter-models.test.ts` in `server`: 27 passed. - `tsc --noEmit` in `packages/adapters/codex-local` and `packages/adapters/opencode-local`: passed. - Cursor archive SHA-256 `85296944e4600a83c4b764f578d1502bf9c416db200d33a593e8f3ecabfdc294` is computed from the versioned Linux x64 tarball. The extracted binary reports `2026.10.22-27dcf5f`. On October 26, 2026, `https://cursor.com/install` still resolves this version. - GitHub CLI SHA-256 `4c806978ffce1cec70853302a56d70ac6da4f19bae7adca4e1a8ab00633dd91d` matches `gh_2.103.3_checksums.txt`. - Grok CLI 1.0.70 and Kimi Code 2.3.3 installed from npm report those versions. The flags that Paperclip uses (`-m`, `--effort`, `grok models`; `-m`, `-p`, `--output-format`, `acp`) are present in `--help`. - `git merge-tree` with #16708 (head `3a06740e9`) and #17245 (head `41f9c611f`): this PR shares no files with either PR. The two PRs can merge in any order. - Not run in the authoring environment: the full `pnpm -r typecheck` and `pnpm build` (no Rust toolchain), the full server `tsc` (memory limit), and the image build. CI runs these. ## Risks - Low risk for catalogs: the IDs are additive suggestions. No saved selection, default, or spending setting changes. - The Paperclip Runner Test changes only the hint text, and only for a ChatGPT rejection of a retired model. Check codes and pass/fail results do not change. - Sandbox CLI pins: - Kimi Code 2.2.0 and 2.3.0 remove the `kaos` MCP executor and require qualified plugin skill names. Paperclip uses neither. Kimi Code 2.3.2 stops automatic swarms in `kimi -p` and ACP sessions. - Gemini CLI 0.65.0 makes workspace settings read-only in untrusted folders. Paperclip writes home settings and sets `GEMINI_CLI_TRUST_WORKSPACE` for remote runs. - xAI publishes no Grok CLI changelog. Grok 1.0.70 behavior changes are verified only against the CLI reference and `--help`. - The pins apply only after a new image is built and promoted. The fleet sandbox image definition must get the same pins. - Rollback: revert this PR. ## Model Used - Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, with tool use (shell, web research, repository search). ## 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 searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Paperclip <noreply@paperclip.ing>
122 lines
6.7 KiB
TypeScript
122 lines
6.7 KiB
TypeScript
export const type = "opencode_local";
|
|
export const label = "OpenCode";
|
|
|
|
// Use OpenCode's official installer instead of `npm install -g opencode-ai`.
|
|
// The npm package reifies four large Linux x64 prebuilt-binary subpackages
|
|
// (linux-x64, linux-x64-musl, linux-x64-baseline, linux-x64-baseline-musl) in
|
|
// parallel even though only one matches the sandbox; on bandwidth-constrained
|
|
// sandboxes (e.g. Cloudflare) that exceeded the 240s install budget. The
|
|
// official installer fetches a single arch-specific binary into
|
|
// `$HOME/.opencode/bin` and tries to add it to PATH via `~/.bashrc`. That
|
|
// rc-file path is only sourced by interactive/login shells, so non-login
|
|
// `sh -c` probe invocations (used by the runtime PATH check) cannot find the
|
|
// binary. We fix that by symlinking the installed binary into a directory on
|
|
// the non-login `sh -c` PATH: prefer `/usr/local/bin` (universally on the
|
|
// default PATH on Linux distros) when root or passwordless sudo is available,
|
|
// otherwise fall back to `$HOME/.local/bin` (which is on the default PATH on
|
|
// the exe.dev sandbox image and most modern home-managed Linux images).
|
|
//
|
|
// Security tradeoff: this is `curl | bash` without a SHA-256 verification of
|
|
// the install script. We accept this because:
|
|
// 1. The install runs inside an isolated, ephemeral sandbox — blast radius
|
|
// is bounded to that sandbox's secrets and disk.
|
|
// 2. The prior `npm install -g opencode-ai` is also unverified code
|
|
// execution from a third-party registry; this is not strictly worse.
|
|
// 3. OpenCode does not publish per-release SHA-256 checksums in a stable
|
|
// location, and pinning a version + hash here would require manual
|
|
// version bumps on every OpenCode release.
|
|
// The `set -e` (implied by Bash's default with `-fsSL` upstream of a piped
|
|
// shell) and `curl -fsSL` give us fail-fast behavior on HTTP errors. If
|
|
// OpenCode starts publishing a stable checksum/signature, switch to fetching
|
|
// a versioned tarball + verifying the digest before exec.
|
|
export const SANDBOX_INSTALL_COMMAND =
|
|
'curl -fsSL https://opencode.ai/install | bash && ' +
|
|
'if [ -x "$HOME/.opencode/bin/opencode" ]; then ' +
|
|
'if [ "$(id -u)" -eq 0 ]; then ' +
|
|
'ln -sf "$HOME/.opencode/bin/opencode" /usr/local/bin/opencode; ' +
|
|
'elif command -v sudo >/dev/null 2>&1 && sudo -n true >/dev/null 2>&1; then ' +
|
|
'sudo ln -sf "$HOME/.opencode/bin/opencode" /usr/local/bin/opencode; ' +
|
|
'else ' +
|
|
'mkdir -p "$HOME/.local/bin" && ' +
|
|
'ln -sf "$HOME/.opencode/bin/opencode" "$HOME/.local/bin/opencode"; ' +
|
|
'fi; ' +
|
|
'fi';
|
|
|
|
export const DEFAULT_OPENCODE_LOCAL_MODEL = "openai/gpt-5.2-codex";
|
|
|
|
export function isValidOpenCodeModelId(value: unknown): value is string {
|
|
if (typeof value !== "string") return false;
|
|
const trimmed = value.trim();
|
|
const slashIndex = trimmed.indexOf("/");
|
|
return Boolean(trimmed) && slashIndex > 0 && slashIndex !== trimmed.length - 1;
|
|
}
|
|
|
|
export const models: Array<{ id: string; label: string }> = [
|
|
{ id: DEFAULT_OPENCODE_LOCAL_MODEL, label: DEFAULT_OPENCODE_LOCAL_MODEL },
|
|
{ id: "openai/gpt-6-astra", label: "openai/gpt-6-astra" },
|
|
{ id: "openai/gpt-6.1-sol", label: "openai/gpt-6.1-sol" },
|
|
{ id: "openai/gpt-6-sol", label: "openai/gpt-6-sol" },
|
|
{ id: "openai/gpt-6-luna", label: "openai/gpt-6-luna" },
|
|
{ id: "openai/gpt-5.6-sol", label: "openai/gpt-5.6-sol" },
|
|
{ id: "openai/gpt-5.6-terra", label: "openai/gpt-5.6-terra" },
|
|
{ id: "openai/gpt-5.6-luna", label: "openai/gpt-5.6-luna" },
|
|
{ id: "anthropic/claude-opus-5-5", label: "anthropic/claude-opus-5-5" },
|
|
{ id: "anthropic/claude-opus-5", label: "anthropic/claude-opus-5" },
|
|
{ id: "anthropic/claude-fable-5-1", label: "anthropic/claude-fable-5-1" },
|
|
{ id: "anthropic/claude-sonnet-5-5", label: "anthropic/claude-sonnet-5-5" },
|
|
{ id: "anthropic/claude-sonnet-5", label: "anthropic/claude-sonnet-5" },
|
|
{ id: "anthropic/claude-haiku-5-5", label: "anthropic/claude-haiku-5-5" },
|
|
{ id: "google/gemini-4-argon", label: "google/gemini-4-argon" },
|
|
{ id: "google/gemini-3.8-flash", label: "google/gemini-3.8-flash" },
|
|
{ id: "xai/grok-4.7", label: "xai/grok-4.7" },
|
|
{ id: "openai/gpt-5.5", label: "openai/gpt-5.5" },
|
|
{ id: "openai/gpt-5.4", label: "openai/gpt-5.4" },
|
|
{ id: "openai/gpt-5.4-mini", label: "openai/gpt-5.4-mini" },
|
|
{ id: "openai/gpt-5.2", label: "openai/gpt-5.2" },
|
|
{ id: "openai/gpt-5.1-codex-max", label: "openai/gpt-5.1-codex-max" },
|
|
{ id: "openai/gpt-5.1-codex-mini", label: "openai/gpt-5.1-codex-mini" },
|
|
];
|
|
|
|
export const agentConfigurationDoc = `# opencode_local agent configuration
|
|
|
|
Adapter: opencode_local
|
|
|
|
Use when:
|
|
- You want Paperclip to run OpenCode locally as the agent runtime
|
|
- You want provider/model routing in OpenCode format (provider/model)
|
|
- You want OpenCode session resume across heartbeats via --session
|
|
|
|
Don't use when:
|
|
- You need webhook-style external invocation (use openclaw_gateway or http)
|
|
- You only need one-shot shell commands (use process)
|
|
- OpenCode CLI is not installed on the machine
|
|
|
|
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
|
|
- model (string, required): OpenCode model id in provider/model format (for example anthropic/claude-sonnet-4-5)
|
|
- variant (string, optional): provider-specific reasoning/profile variant passed as --variant (for example minimal|low|medium|high|xhigh|max)
|
|
- dangerouslySkipPermissions (boolean, optional): inject a runtime OpenCode config with \`permission=allow\` for all tools and connections; defaults to true for unattended Paperclip runs
|
|
- promptTemplate (string, optional): run prompt template
|
|
- command (string, optional): defaults to "opencode"
|
|
- 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:
|
|
- OpenCode supports multiple providers and models. Use \
|
|
\`opencode models\` to list available options in provider/model format.
|
|
- Paperclip requires an explicit \`model\` value for \`opencode_local\` agents.
|
|
- Runs are executed with: opencode run --format json ...
|
|
- Sessions are resumed with --session when stored session cwd matches current cwd.
|
|
- The adapter sets OPENCODE_DISABLE_PROJECT_CONFIG=true to prevent OpenCode from \
|
|
writing an opencode.json config file into the project working directory. Model \
|
|
selection is passed via the --model CLI flag instead.
|
|
- When \`dangerouslySkipPermissions\` is enabled, Paperclip injects a temporary \
|
|
runtime config with \`permission=allow\` so headless runs do \
|
|
not stall on approval prompts.
|
|
`;
|