Dax Raad 8 месяцев назад
Родитель
Сommit
af892e5432

+ 41 - 23
README.md

@@ -2,39 +2,57 @@
 
 AI coding agent, built for the terminal.
 
-Note: version 0.1.x is a full rewrite and we do not have proper documentation for it yet. Should have this out week of June 17th 2025
+⚠️ **Note:** version 0.1.x is a full rewrite and we do not have proper documentation for it yet. Should have this out week of June 17th 2025 📚
 
-## Installation
+### Installation
 
-If you have a previous version of opencode < 0.1.x installed you might have to remove it first.
-
-### Curl
-
-```
+```bash
+# YOLO
 curl -fsSL https://opencode.ai/install | bash
+
+# Package managers
+npm i -g opencode-ai@latest        # or bun/pnpm/yarn
+brew install sst/tap/opencode      # macOS
+paru -S opencode-bin               # Arch Linux
 ```
 
-### NPM
+> **Note:** Remove previous versions < 0.1.x first if installed
 
-```
-npm i -g opencode-ai@latest
-bun i -g opencode-ai@latest
-pnpm i -g opencode-ai@latest
-yarn global add opencode-ai@latest
-```
+### Providers
 
-### Brew
+The recommended approach is to sign up for claude pro or max and do `opencode auth login` and select Anthropic. It is the most cost effective way to use this tool.
 
-```
-brew install sst/tap/opencode
-```
+Additionally opencode is powered by the provider list at [models.dev](https://models.dev) so you can use `opencode auth login` to configure api keys for any provider you'd like to use. This is stored in `~/.local/share/opencode/auth.json`
 
-### AUR
+```bash
+$ opencode auth login
 
+┌  Add credential
+│
+◆  Select provider
+│  ● Anthropic (recommended)
+│  ○ OpenAI
+│  ○ Google
+│  ○ Amazon Bedrock
+│  ○ Azure
+│  ○ DeepSeek
+│  ○ Groq
+│  ...
+└
 ```
-paru -S opencode-bin
-```
 
-## Usage
+The models.dev dataset is also used to detect common environment variables like `OPENAI_API_KEY` to autoload that provider.
+
+If there are additional providers you want to use you can submit a PR to the [models.dev repo](https://github.com/sst/models.dev). If configuring just for yourself check out the Config section below
+
+### Project Config
+
+Project configuration is optional. You can place an `opencode.json` file in the root of your repo and it will be loaded.
+
+```json title="opencode.json"
+{
+  "$schema": "https://opencode.ai/schemas/opencode.json"
+}
+```
 
-We are working on proper keybinds - right now it's the various function keys press F1 to see them
+#### MCP

+ 1 - 0
bun.lock

@@ -50,6 +50,7 @@
         "@types/turndown": "5.0.5",
         "@types/yargs": "17.0.33",
         "typescript": "catalog:",
+        "zod-to-json-schema": "3.24.5",
       },
     },
     "packages/web": {

+ 139 - 0
packages/opencode/config.schema.json

@@ -0,0 +1,139 @@
+{
+  "type": "object",
+  "properties": {
+    "provider": {
+      "type": "object",
+      "additionalProperties": {
+        "type": "object",
+        "properties": {
+          "name": {
+            "type": "string"
+          },
+          "env": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            }
+          },
+          "id": {
+            "type": "string"
+          },
+          "models": {
+            "type": "object",
+            "additionalProperties": {
+              "type": "object",
+              "properties": {
+                "name": {
+                  "type": "string"
+                },
+                "attachment": {
+                  "type": "boolean"
+                },
+                "reasoning": {
+                  "type": "boolean"
+                },
+                "temperature": {
+                  "type": "boolean"
+                },
+                "cost": {
+                  "type": "object",
+                  "properties": {
+                    "input": {
+                      "type": "number"
+                    },
+                    "output": {
+                      "type": "number"
+                    },
+                    "inputCached": {
+                      "type": "number"
+                    },
+                    "outputCached": {
+                      "type": "number"
+                    }
+                  },
+                  "required": [
+                    "input",
+                    "output",
+                    "inputCached",
+                    "outputCached"
+                  ],
+                  "additionalProperties": false
+                },
+                "limit": {
+                  "type": "object",
+                  "properties": {
+                    "context": {
+                      "type": "number"
+                    },
+                    "output": {
+                      "type": "number"
+                    }
+                  },
+                  "required": ["context", "output"],
+                  "additionalProperties": false
+                },
+                "id": {
+                  "type": "string"
+                }
+              },
+              "additionalProperties": false
+            }
+          },
+          "options": {
+            "type": "object",
+            "additionalProperties": {}
+          }
+        },
+        "required": ["models"],
+        "additionalProperties": false
+      }
+    },
+    "mcp": {
+      "type": "object",
+      "additionalProperties": {
+        "anyOf": [
+          {
+            "type": "object",
+            "properties": {
+              "type": {
+                "type": "string",
+                "const": "local"
+              },
+              "command": {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              "environment": {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "string"
+                }
+              }
+            },
+            "required": ["type", "command"],
+            "additionalProperties": false
+          },
+          {
+            "type": "object",
+            "properties": {
+              "type": {
+                "type": "string",
+                "const": "remote"
+              },
+              "url": {
+                "type": "string"
+              }
+            },
+            "required": ["type", "url"],
+            "additionalProperties": false
+          }
+        ]
+      }
+    }
+  },
+  "additionalProperties": false,
+  "$schema": "http://json-schema.org/draft-07/schema#"
+}
+

+ 4 - 2
packages/opencode/package.json

@@ -5,7 +5,8 @@
   "type": "module",
   "private": true,
   "scripts": {
-    "typecheck": "tsc --noEmit"
+    "typecheck": "tsc --noEmit",
+    "dev": "bun run ./src/index.ts"
   },
   "exports": {
     "./*": [
@@ -18,7 +19,8 @@
     "@types/bun": "latest",
     "@types/turndown": "5.0.5",
     "@types/yargs": "17.0.33",
-    "typescript": "catalog:"
+    "typescript": "catalog:",
+    "zod-to-json-schema": "3.24.5"
   },
   "dependencies": {
     "@clack/prompts": "0.11.0",

+ 8 - 0
packages/opencode/script/schema.ts

@@ -0,0 +1,8 @@
+#!/usr/bin/env bun
+
+import "zod-openapi/extend"
+import { Config } from "../src/config/config"
+import { zodToJsonSchema } from "zod-to-json-schema"
+
+const result = zodToJsonSchema(Config.Info)
+await Bun.write("config.schema.json", JSON.stringify(result, null, 2))

+ 1 - 0
packages/opencode/src/cli/cmd/generate.ts

@@ -2,6 +2,7 @@ import { Server } from "../../server/server"
 import fs from "fs/promises"
 import path from "path"
 import type { CommandModule } from "yargs"
+import { Config } from "../../config/config"
 
 export const GenerateCommand = {
   command: "generate",

+ 0 - 5
packages/opencode/src/config/config.ts

@@ -58,11 +58,6 @@ export namespace Config {
           }),
         )
         .optional(),
-      tool: z
-        .object({
-          provider: z.record(z.string(), z.string().array()).optional(),
-        })
-        .optional(),
       mcp: z.record(z.string(), Mcp).optional(),
     })
     .strict()

+ 2 - 0
packages/opencode/src/provider/provider.ts

@@ -289,11 +289,13 @@ export namespace Provider {
     google: TOOLS,
   }
   export async function tools(providerID: string) {
+    /*
     const cfg = await Config.get()
     if (cfg.tool?.provider?.[providerID])
       return cfg.tool.provider[providerID].map(
         (id) => TOOLS.find((t) => t.id === id)!,
       )
+        */
     return TOOL_MAPPING[providerID] ?? TOOLS
   }