Drop Zed/ACP binary lookup. Devin CLI is the only requirement.
This commit is contained in:
@@ -11,7 +11,7 @@ src/credentials.ts # ~/.local/share/devin/credentials.toml
|
|||||||
src/models.ts # `devin models list --format json` → ProviderModelConfig[]
|
src/models.ts # `devin models list --format json` → ProviderModelConfig[]
|
||||||
src/stream.ts # streamSimple via GetChatMessage (Connect/protobuf)
|
src/stream.ts # streamSimple via GetChatMessage (Connect/protobuf)
|
||||||
src/jwt.ts # GetUserJwt cache
|
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/wire.ts # protobuf + Connect framing
|
||||||
src/context-map.ts # Pi Context → Cognition chat history
|
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.
|
- `/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.
|
- 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`.
|
- Package must stay installable as a Pi package: `keywords: ["pi-package"]` and `pi.extensions`.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
A [Pi](https://pi.dev) package that uses **Devin Local** models inside Pi.
|
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
|
## 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.
|
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
|
## Requirements
|
||||||
|
|
||||||
@@ -24,9 +24,8 @@ The CLI binary is resolved in this order:
|
|||||||
|
|
||||||
1. `$DEVIN_CLI`
|
1. `$DEVIN_CLI`
|
||||||
2. `~/.local/bin/devin`, Homebrew, `/usr/local/bin/devin`
|
2. `~/.local/bin/devin`, Homebrew, `/usr/local/bin/devin`
|
||||||
3. Devin.app
|
3. Devin.app's bundled `devin` binary
|
||||||
4. Zed's ACP registry install (`~/Library/Application Support/Zed/external_agents/registry/devin/.../bin/devin`)
|
4. `which devin`
|
||||||
5. `which devin`
|
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
@@ -59,7 +58,7 @@ Restart Pi or run `/reload`.
|
|||||||
/model devin/gpt-5-6-sol-high
|
/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:
|
Commands:
|
||||||
|
|
||||||
@@ -70,10 +69,10 @@ Commands:
|
|||||||
|
|
||||||
| This package | Not this package |
|
| 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 |
|
| Devin CLI for auth + catalog | Fake Windsurf OAuth paste flow |
|
||||||
| Live CLI families (Opus 5, Fable 5, Sol, …) | Hardcoded 11-model cloud allowlist |
|
| 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
|
## Publish
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pi-devin",
|
"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.",
|
"description": "Pi provider for Devin Local models. Auth and catalog come from the local Devin CLI; Pi stays the harness.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
+2
-33
@@ -1,4 +1,4 @@
|
|||||||
import { existsSync, readdirSync, statSync } from "node:fs";
|
import { existsSync } from "node:fs";
|
||||||
import { homedir } from "node:os";
|
import { homedir } from "node:os";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
import { execFile, spawn } from "node:child_process";
|
import { execFile, spawn } from "node:child_process";
|
||||||
@@ -6,12 +6,6 @@ import { promisify } from "node:util";
|
|||||||
|
|
||||||
const execFileAsync = promisify(execFile);
|
const execFileAsync = promisify(execFile);
|
||||||
|
|
||||||
const ZED_DEVIN =
|
|
||||||
join(
|
|
||||||
homedir(),
|
|
||||||
"Library/Application Support/Zed/external_agents/registry/devin",
|
|
||||||
);
|
|
||||||
|
|
||||||
const KNOWN_BINS = [
|
const KNOWN_BINS = [
|
||||||
process.env.DEVIN_CLI,
|
process.env.DEVIN_CLI,
|
||||||
join(homedir(), ".local/bin/devin"),
|
join(homedir(), ".local/bin/devin"),
|
||||||
@@ -23,26 +17,6 @@ const KNOWN_BINS = [
|
|||||||
|
|
||||||
let cachedBin: string | null | undefined;
|
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 {
|
export function findDevinBin(): string | null {
|
||||||
if (cachedBin !== undefined) return cachedBin;
|
if (cachedBin !== undefined) return cachedBin;
|
||||||
for (const bin of KNOWN_BINS) {
|
for (const bin of KNOWN_BINS) {
|
||||||
@@ -51,11 +25,6 @@ export function findDevinBin(): string | null {
|
|||||||
return bin;
|
return bin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const zed = newestZedDevin();
|
|
||||||
if (zed) {
|
|
||||||
cachedBin = zed;
|
|
||||||
return zed;
|
|
||||||
}
|
|
||||||
cachedBin = null;
|
cachedBin = null;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -87,7 +56,7 @@ export async function runDevin(
|
|||||||
const bin = await whichDevin();
|
const bin = await whichDevin();
|
||||||
if (!bin) {
|
if (!bin) {
|
||||||
throw new Error(
|
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.",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user