diff --git a/AGENTS.md b/AGENTS.md index c4698c3..941af32 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,7 +11,7 @@ src/credentials.ts # ~/.local/share/devin/credentials.toml src/models.ts # `devin models list --format json` → ProviderModelConfig[] src/stream.ts # streamSimple via GetChatMessage (Connect/protobuf) src/jwt.ts # GetUserJwt cache -src/metadata.ts # Metadata proto (ide_name=devin) +src/metadata.ts # Metadata proto (Windsurf/Devin Desktop version gate) src/wire.ts # protobuf + Connect framing src/context-map.ts # Pi Context → Cognition chat history ``` @@ -20,5 +20,5 @@ src/context-map.ts # Pi Context → Cognition chat history - `/login devin` must call `devin auth login` when credentials are missing, not a custom Windsurf paste flow. - Model IDs must come from `devin models list`, not a hardcoded cloud allowlist. -- Do not spawn `devin acp` as the session owner. Pi keeps tools, permissions, and the session tree. +- Do not depend on Zed or ACP. Pi keeps tools, permissions, and the session tree. - Package must stay installable as a Pi package: `keywords: ["pi-package"]` and `pi.extensions`. diff --git a/README.md b/README.md index d1eaf4f..9d57e62 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A [Pi](https://pi.dev) package that uses **Devin Local** models inside Pi. -Pi stays the harness. The local [Devin CLI](https://docs.devin.ai/cli) owns login and the live model catalog (`devin auth`, `devin models list`). This package does **not** wrap Devin as an ACP agent and does **not** use the old `pi-devin-auth` cloud-only shim. +Pi stays the harness. The [Devin CLI](https://docs.devin.ai/cli) owns login and the live model catalog (`devin auth`, `devin models list`). This is not an ACP integration and does not use Zed. ## Why this exists @@ -12,7 +12,7 @@ Pi stays the harness. The local [Devin CLI](https://docs.devin.ai/cli) owns logi This model is only in Devin Local. ``` -Zed works because it launches `devin acp` — Devin Local. This package uses that same local CLI for auth + catalog, then streams completions into Pi so Pi's tools, sessions, and UI stay in charge. +Those models are available through the local Devin CLI. This package uses that CLI for auth + catalog, then streams completions into Pi so Pi's tools, sessions, and UI stay in charge. ## Requirements @@ -24,9 +24,8 @@ The CLI binary is resolved in this order: 1. `$DEVIN_CLI` 2. `~/.local/bin/devin`, Homebrew, `/usr/local/bin/devin` -3. Devin.app -4. Zed's ACP registry install (`~/Library/Application Support/Zed/external_agents/registry/devin/.../bin/devin`) -5. `which devin` +3. Devin.app's bundled `devin` binary +4. `which devin` ## Install @@ -59,7 +58,7 @@ Restart Pi or run `/reload`. /model devin/gpt-5-6-sol-high ``` -`/login devin` runs `devin auth login` if `~/.local/share/devin/credentials.toml` is missing. If you already signed in through Devin Desktop, the CLI, or Zed, that file is reused. +`/login devin` runs `devin auth login` if `~/.local/share/devin/credentials.toml` is missing. If you already signed in through the Devin CLI or Devin Desktop, that file is reused. Commands: @@ -70,10 +69,10 @@ Commands: | This package | Not this package | |---|---| -| Pi is the agent | Devin ACP taking over the session | +| Pi is the agent | Devin taking over the session | | Devin CLI for auth + catalog | Fake Windsurf OAuth paste flow | | Live CLI families (Opus 5, Fable 5, Sol, …) | Hardcoded 11-model cloud allowlist | -| Completions streamed into Pi tools | `devin acp` as the editor host | +| Completions streamed into Pi tools | An editor host for Devin | ## Publish diff --git a/package.json b/package.json index b8b0f00..f108db7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pi-devin", - "version": "0.1.1", + "version": "0.1.2", "description": "Pi provider for Devin Local models. Auth and catalog come from the local Devin CLI; Pi stays the harness.", "type": "module", "keywords": [ diff --git a/src/cli.ts b/src/cli.ts index 2eb0e95..f8627ba 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -1,4 +1,4 @@ -import { existsSync, readdirSync, statSync } from "node:fs"; +import { existsSync } from "node:fs"; import { homedir } from "node:os"; import { join } from "node:path"; import { execFile, spawn } from "node:child_process"; @@ -6,12 +6,6 @@ import { promisify } from "node:util"; const execFileAsync = promisify(execFile); -const ZED_DEVIN = - join( - homedir(), - "Library/Application Support/Zed/external_agents/registry/devin", - ); - const KNOWN_BINS = [ process.env.DEVIN_CLI, join(homedir(), ".local/bin/devin"), @@ -23,26 +17,6 @@ const KNOWN_BINS = [ let cachedBin: string | null | undefined; -function newestZedDevin(): string | null { - try { - if (!existsSync(ZED_DEVIN)) return null; - const versions = readdirSync(ZED_DEVIN) - .map((name) => { - const bin = join(ZED_DEVIN, name, "bin/devin"); - try { - return { bin, mtime: statSync(bin).mtimeMs }; - } catch { - return null; - } - }) - .filter((row): row is { bin: string; mtime: number } => Boolean(row)) - .sort((a, b) => b.mtime - a.mtime); - return versions[0]?.bin ?? null; - } catch { - return null; - } -} - export function findDevinBin(): string | null { if (cachedBin !== undefined) return cachedBin; for (const bin of KNOWN_BINS) { @@ -51,11 +25,6 @@ export function findDevinBin(): string | null { return bin; } } - const zed = newestZedDevin(); - if (zed) { - cachedBin = zed; - return zed; - } cachedBin = null; return null; } @@ -87,7 +56,7 @@ export async function runDevin( const bin = await whichDevin(); if (!bin) { throw new Error( - "Devin CLI not found. Install Devin, or set DEVIN_CLI to the `devin` binary (Zed ACP registry and Devin.app are also checked).", + "Devin CLI not found. Install the Devin CLI, or set DEVIN_CLI to the `devin` binary.", ); }