Dax Raad пре 8 месеци
родитељ
комит
e5b06a2d95

+ 23 - 0
packages/opencode/AGENTS.md

@@ -0,0 +1,23 @@
+# OpenCode Agent Guidelines
+
+## Build/Test Commands
+- **Install**: `bun install`
+- **Run**: `bun run index.ts`
+- **Typecheck**: `bun run typecheck` (npm run typecheck)
+- **Test**: `bun test` (runs all tests)
+- **Single test**: `bun test test/tool/tool.test.ts` (specific test file)
+
+## Code Style
+- **Runtime**: Bun with TypeScript ESM modules
+- **Imports**: Use relative imports for local modules, named imports preferred
+- **Types**: Zod schemas for validation, TypeScript interfaces for structure
+- **Naming**: camelCase for variables/functions, PascalCase for classes/namespaces
+- **Error handling**: Use Result patterns, avoid throwing exceptions in tools
+- **File structure**: Namespace-based organization (e.g., `Tool.define()`, `Session.create()`)
+
+## Architecture
+- **Tools**: Implement `Tool.Info` interface with `execute()` method
+- **Context**: Pass `sessionID` in tool context, use `App.provide()` for DI
+- **Validation**: All inputs validated with Zod schemas
+- **Logging**: Use `Log.create({ service: "name" })` pattern
+- **Storage**: Use `Storage` namespace for persistence

+ 24 - 9
packages/opencode/src/index.ts

@@ -84,17 +84,11 @@ cli
         unsub()
         unsub()
       })
       })
 
 
-      const [provider] = await Provider.active().then((val) =>
-        val.values().toArray(),
-      )
-      if (!provider) throw new Error("no providers found")
-      const model = provider.models[0]
-      if (!model) throw new Error("no models found")
-      console.log("using", provider.id, model.id)
+      const { providerID, modelID } = await Provider.defaultModel()
       const result = await Session.chat({
       const result = await Session.chat({
         sessionID: session.id,
         sessionID: session.id,
-        providerID: provider.id,
-        modelID: model.id,
+        providerID,
+        modelID,
         parts: [
         parts: [
           {
           {
             type: "text",
             type: "text",
@@ -115,6 +109,27 @@ cli
     })
     })
   })
   })
 
 
+cli.command("init", "Run a chat message").action(async () => {
+  await App.provide({ cwd: process.cwd(), version }, async () => {
+    const { modelID, providerID } = await Provider.defaultModel()
+    console.log("Initializing...")
+
+    const session = await Session.create()
+
+    const unsub = Bus.subscribe(Session.Event.Updated, async (message) => {
+      if (message.properties.info.share?.url)
+        console.log("Share:", message.properties.info.share.url)
+      unsub()
+    })
+
+    await Session.initialize({
+      sessionID: session.id,
+      modelID,
+      providerID,
+    })
+  })
+})
+
 cli.version(typeof OPENCODE_VERSION === "string" ? OPENCODE_VERSION : "dev")
 cli.version(typeof OPENCODE_VERSION === "string" ? OPENCODE_VERSION : "dev")
 cli.help()
 cli.help()
 cli.parse()
 cli.parse()

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

@@ -141,6 +141,17 @@ export namespace Provider {
     }
     }
   }
   }
 
 
+  export async function defaultModel() {
+    const [provider] = await active().then((val) => val.values().toArray())
+    if (!provider) throw new Error("no providers found")
+    const model = provider.models[0]
+    if (!model) throw new Error("no models found")
+    return {
+      providerID: provider.id,
+      modelID: model.id,
+    }
+  }
+
   const TOOLS = [
   const TOOLS = [
     BashTool,
     BashTool,
     EditTool,
     EditTool,

+ 29 - 0
packages/opencode/src/server/server.ts

@@ -93,6 +93,35 @@ export namespace Server {
           return c.json(App.info())
           return c.json(App.info())
         },
         },
       )
       )
+      .post(
+        "/session_initialize",
+        describeRoute({
+          description: "Analyze the app and create an AGENTS.md file",
+          responses: {
+            200: {
+              description: "200",
+              content: {
+                "application/json": {
+                  schema: resolver(z.boolean()),
+                },
+              },
+            },
+          },
+        }),
+        zValidator(
+          "json",
+          z.object({
+            sessionID: z.string(),
+            providerID: z.string(),
+            modelID: z.string(),
+          }),
+        ),
+        async (c) => {
+          const body = c.req.valid("json")
+          await Session.initialize(body)
+          return c.json(true)
+        },
+      )
       .post(
       .post(
         "/path_get",
         "/path_get",
         describeRoute({
         describeRoute({

+ 7 - 0
packages/opencode/src/session/prompt/initialize.txt

@@ -0,0 +1,7 @@
+Please analyze this codebase and create an AGENTS.md file containing:
+1. Build/lint/test commands - especially for running a single test
+2. Code style guidelines including imports, formatting, types, naming conventions, error handling, etc.
+
+The file you create will be given to agentic coding agents (such as yourself) that operate in this repository. Make it about 20 lines long.
+If there's already an AGENTS.md, improve it.
+If there are Cursor rules (in .cursor/rules/ or .cursorrules) or Copilot rules (in .github/copilot-instructions.md), make sure to include them.

+ 19 - 0
packages/opencode/src/session/session.ts

@@ -18,6 +18,7 @@ import { Decimal } from "decimal.js"
 import PROMPT_ANTHROPIC from "./prompt/anthropic.txt"
 import PROMPT_ANTHROPIC from "./prompt/anthropic.txt"
 import PROMPT_TITLE from "./prompt/title.txt"
 import PROMPT_TITLE from "./prompt/title.txt"
 import PROMPT_SUMMARIZE from "./prompt/summarize.txt"
 import PROMPT_SUMMARIZE from "./prompt/summarize.txt"
+import PROMPT_INITIALIZE from "../session/prompt/initialize.txt"
 
 
 import { Share } from "../share/share"
 import { Share } from "../share/share"
 import { Message } from "./message"
 import { Message } from "./message"
@@ -531,4 +532,22 @@ export namespace Session {
       super(`Session ${sessionID} is busy`)
       super(`Session ${sessionID} is busy`)
     }
     }
   }
   }
+
+  export async function initialize(input: {
+    sessionID: string
+    modelID: string
+    providerID: string
+  }) {
+    await Session.chat({
+      sessionID: input.sessionID,
+      providerID: input.providerID,
+      modelID: input.modelID,
+      parts: [
+        {
+          type: "text",
+          text: PROMPT_INITIALIZE,
+        },
+      ],
+    })
+  }
 }
 }