Dax Raad 5 месяцев назад
Родитель
Сommit
6722ee22ee
2 измененных файлов с 2 добавлено и 209 удалено
  1. 2 0
      .opencode/.gitignore
  2. 0 209
      .opencode/plans/1771135996918-mighty-wizard.md

+ 2 - 0
.opencode/.gitignore

@@ -3,3 +3,5 @@ package.json
 package-lock.json
 bun.lock
 .gitignore
+package-lock.json
+plans

+ 0 - 209
.opencode/plans/1771135996918-mighty-wizard.md

@@ -1,209 +0,0 @@
-# Plan: Project References Feature
-
-Add support for referencing external git repositories in `opencode.json` that can be queried via a dedicated subagent.
-
-## Overview
-
-Users can specify references in config:
-
-```json
-{
-  "references": ["git@github.com:Effect-TS/effect.git", "git@github.com:foo/bar.git#v1.0.0", "/local/path/to/repo"]
-}
-```
-
-These get cloned/cached to `~/.cache/opencode/references/` and a `reference` subagent can search across them.
-
----
-
-## Files to Create
-
-### `src/reference/index.ts`
-
-Core reference management module with:
-
-- `parse(url: string): Reference` - Parse git URL or local path, extract branch if present (`#branch` suffix)
-- `cachePath(ref: Reference): string` - SHA-256 hash of URL for deterministic directory names
-- `isStale(ref: Reference): Promise<boolean>` - Check if `FETCH_HEAD` mtime > 1 hour old
-- `fetch(ref: Reference): Promise<void>` - Clone with `--depth 1` or `git fetch`, handle branch checkout
-- `ensureFresh(ref: Reference): Promise<void>` - Lazy fetch wrapper (skip if not stale)
-- `list(): Promise<Reference[]>` - Get references from config
-- `directories(): Promise<string[]>` - Get all cached reference paths for permissions
-
-Types:
-
-```ts
-interface Reference {
-  url: string // Original URL/path
-  path: string // Cache directory (for git) or resolved path (for local)
-  branch?: string // Optional branch/tag from URL fragment
-  type: "git" | "local"
-}
-```
-
-URL parsing supports:
-
-- `git@github.com:foo/bar.git` → git
-- `git@github.com:foo/bar.git#main` → git with branch
-- `https://github.com/foo/bar.git#v1.0.0` → git with tag
-- `/absolute/path` → local
-- `~/relative/path` → local (expanded)
-
-### `src/agent/prompt/reference.txt`
-
-Prompt for reference subagent:
-
-```
-You are a multi-project code search specialist. You search across referenced projects
-to answer questions about external codebases.
-
-Available references: {references}
-
-Guidelines:
-- Search across ALL referenced projects unless the user specifies one
-- Report which project(s) contained relevant findings
-- Use Glob for file patterns, Grep for content search, Read for specific files
-- Return absolute paths so users can locate findings
-- Do not modify any files or run destructive commands
-```
-
----
-
-## Files to Modify
-
-### `src/config/config.ts`
-
-Add `references` field to `Config.Info` schema (around line 1174):
-
-```ts
-references: z.array(z.string()).optional().describe(
-  "Git repositories or local paths to reference from subagents"
-),
-```
-
-### `src/global/index.ts`
-
-Add reference cache path and create directory:
-
-```ts
-// Add to Path object:
-reference: path.join(cache, "references"),
-
-// Add to mkdir promise array:
-fs.mkdir(path.join(cache, "references"), { recursive: true }),
-```
-
-### `src/agent/agent.ts`
-
-Add `reference` agent to built-in agents (after `explore` around line 155):
-
-```ts
-reference: {
-  name: "reference",
-  description: `Search across referenced projects configured in opencode.json under "references". Use this to query code in external repositories.`,
-  permission: PermissionNext.merge(
-    defaults,
-    PermissionNext.fromConfig({
-      "*": "deny",
-      grep: "allow",
-      glob: "allow",
-      list: "allow",
-      bash: "allow",
-      webfetch: "allow",
-      websearch: "allow",
-      codesearch: "allow",
-      read: "allow",
-      lsp: "allow",
-      external_directory: {
-        [Truncate.GLOB]: "allow",
-        // Reference paths added dynamically via Reference.directories()
-      },
-    }),
-    user,
-  ),
-  prompt: PROMPT_REFERENCE,
-  options: {},
-  mode: "subagent",
-  native: true,
-},
-```
-
-Need to inject reference paths into `external_directory` permissions. This requires:
-
-1. Loading references via `Reference.list()`
-2. Ensuring they're fresh via `Reference.ensureFresh()`
-3. Adding their paths to `external_directory` permissions
-
-**Challenge**: The agent definition is loaded once at startup, but references may change. Solution: Inject reference paths dynamically in the Task tool when creating the subagent session.
-
-### `src/tool/task.ts`
-
-When creating session for `reference` subagent (around line 72):
-
-```ts
-// Before Session.create:
-let extraPermissions = []
-if (params.subagent_type === "reference") {
-  const refs = await Reference.list()
-  await Promise.all(refs.map((r) => Reference.ensureFresh(r)))
-  const paths = refs.map((r) => path.join(r.path, "*"))
-  extraPermissions = paths.map((p) => ({
-    permission: "external_directory" as const,
-    pattern: p,
-    action: "allow" as const,
-  }))
-}
-
-// Add extraPermissions to the permission array in Session.create
-```
-
-Also need to inject available references into the prompt. Modify `SessionPrompt.resolvePromptParts` or add a way to inject context.
-
-### `src/session/prompt.ts` (or similar)
-
-Inject reference list into reference agent's system prompt:
-
-```ts
-// When agent.name === "reference", prepend reference info to prompt
-const refs = await Reference.list()
-const refList = refs.map((r) => `- ${r.url} at ${r.path}`).join("\n")
-// Inject into prompt or parts
-```
-
----
-
-## Edge Cases
-
-1. **Clone failures**: Log warning, continue with other references. Don't block subagent.
-2. **Network failures**: Use cached version if exists, even if stale. Only error if never cloned.
-3. **Branch not found**: Log error, skip that reference.
-4. **Local path missing**: Log warning, skip reference.
-5. **Invalid URL format**: Log warning, skip reference.
-6. **Shallow clone**: Use `--depth 1` for faster clones. For branch-specific URLs, use `--branch <ref> --depth 1`.
-
----
-
-## Verification
-
-1. Add to `opencode.json`: `{"references": ["git@github.com:effect-ts/effect.git"]}`
-2. Invoke `@reference` with query like "show me the Effect schema module"
-3. Verify repo cloned to `~/.cache/opencode/references/<hash>/`
-4. Verify subagent can search/read files in the cloned repo
-5. Wait 1+ hour, invoke again, verify fetch happens
-6. Test with local path: `{"references": ["/path/to/local/repo"]}`
-7. Test with branch: `{"references": ["git@github.com:foo/bar.git#main"]}`
-8. Verify error handling with invalid URL
-
----
-
-## Files Summary
-
-| File                             | Action                                      |
-| -------------------------------- | ------------------------------------------- |
-| `src/reference/index.ts`         | Create                                      |
-| `src/agent/prompt/reference.txt` | Create                                      |
-| `src/config/config.ts`           | Add `references` to schema                  |
-| `src/global/index.ts`            | Add `reference` path                        |
-| `src/agent/agent.ts`             | Add `reference` agent                       |
-| `src/tool/task.ts`               | Inject ref permissions + paths into session |
-| `src/session/prompt.ts`          | Inject reference list into system prompt    |