diff --git a/packages/server/src/server/daemon-client.e2e.test.ts b/packages/server/src/server/daemon-client.e2e.test.ts index c66c8068b..89f66f351 100644 --- a/packages/server/src/server/daemon-client.e2e.test.ts +++ b/packages/server/src/server/daemon-client.e2e.test.ts @@ -892,6 +892,42 @@ test("returns typed relative suggestions within a requested directory", async () } }, 30000); +test("finds workspace files inside the OpenCode directory", async () => { + const cwd = mkdtempSync(path.join(tmpdir(), "paseo-opencode-suggestion-")); + const target = path.join( + cwd, + ".opencode", + "command", + "workflow", + "00-kickoff", + "00-user-stories.md", + ); + + try { + mkdirSync(path.dirname(target), { recursive: true }); + writeFileSync(target, ""); + + const result = await ctx.client.getDirectorySuggestions({ + cwd, + query: "00-user-stories.md", + includeFiles: true, + includeDirectories: false, + limit: 20, + }); + + expect(result.error).toBeNull(); + expect(result.directories).toEqual([]); + expect(result.entries).toEqual([ + { + path: ".opencode/command/workflow/00-kickoff/00-user-stories.md", + kind: "file", + }, + ]); + } finally { + rmSync(cwd, { recursive: true, force: true }); + } +}, 30000); + test("receives server_info on websocket connect", async () => { const client = new DaemonClient({ url: `ws://127.0.0.1:${ctx.daemon.port}/ws`, diff --git a/packages/server/src/server/session.ts b/packages/server/src/server/session.ts index ac2bb1c3f..cc38733b2 100644 --- a/packages/server/src/server/session.ts +++ b/packages/server/src/server/session.ts @@ -174,7 +174,10 @@ import { type AgentUpdatesService, } from "./session/agent-updates/agent-updates-service.js"; import { expandTilde } from "../utils/path.js"; -import { searchDirectoryEntries } from "../utils/directory-suggestions.js"; +import { + searchDirectoryEntries, + WORKSPACE_SEARCH_HIDDEN_DIRECTORIES, +} from "../utils/directory-suggestions.js"; import type { CheckoutDiffManager } from "./checkout-diff-manager.js"; import type { Resolvable } from "./speech/provider-resolver.js"; import type { SpeechReadinessSnapshot } from "./speech/speech-runtime.js"; @@ -224,15 +227,6 @@ import { CreateAgentLifecycleDispatch } from "./agent/create-agent-lifecycle-dis // the entire session message if they encounter an unknown provider. const LEGACY_PROVIDER_IDS = new Set(["claude", "codex", "opencode"]); const MIN_VERSION_ALL_PROVIDERS = "0.1.45"; -const WORKSPACE_SEARCH_HIDDEN_DIRECTORIES = [ - ".agents", - ".claude", - ".codex", - ".github", - ".paseo", - ".vscode", -]; - function errorToFriendlyMessage(error: unknown): string { if (error instanceof Error) return error.message; if (typeof error === "string") return error; diff --git a/packages/server/src/utils/directory-suggestions.test.ts b/packages/server/src/utils/directory-suggestions.test.ts index 810b68a6b..309232814 100644 --- a/packages/server/src/utils/directory-suggestions.test.ts +++ b/packages/server/src/utils/directory-suggestions.test.ts @@ -11,12 +11,13 @@ import { tmpdir } from "node:os"; import path from "node:path"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { isPlatform } from "../test-utils/platform.js"; -import { searchDirectoryEntries } from "./directory-suggestions.js"; +import { + searchDirectoryEntries, + WORKSPACE_SEARCH_HIDDEN_DIRECTORIES, +} from "./directory-suggestions.js"; const isWindows = isPlatform("win32"); const filesystemRootDirectoryName = isWindows ? "Windows" : "usr"; -const workspaceHiddenDirectories = [".agents", ".claude", ".codex", ".github", ".paseo", ".vscode"]; - async function searchAbsoluteDirectoryPaths(options: { homeDir: string; query: string; @@ -60,7 +61,7 @@ async function searchRelativeDirectoryEntries(options: { matchMode: options.matchMode, pathQueryPolicy: "slashes", blankQueryBehavior: "children", - traversableHiddenDirectoryNames: workspaceHiddenDirectories, + traversableHiddenDirectoryNames: WORKSPACE_SEARCH_HIDDEN_DIRECTORIES, limit: options.limit, maxDepth: options.maxDepth, maxEntriesScanned: options.maxEntriesScanned, diff --git a/packages/server/src/utils/directory-suggestions.ts b/packages/server/src/utils/directory-suggestions.ts index 67d95fd4d..081c36ede 100644 --- a/packages/server/src/utils/directory-suggestions.ts +++ b/packages/server/src/utils/directory-suggestions.ts @@ -24,7 +24,7 @@ export interface SearchDirectoryEntriesOptions { pathQueryPolicy?: PathQueryPolicy; rootAliases?: string[]; blankQueryBehavior?: BlankQueryBehavior; - traversableHiddenDirectoryNames?: string[]; + traversableHiddenDirectoryNames?: readonly string[]; limit?: number; maxDepth?: number; maxEntriesScanned?: number; @@ -84,6 +84,15 @@ const NO_SEGMENT_INDEX = Number.MAX_SAFE_INTEGER; const NO_MATCH_OFFSET = Number.MAX_SAFE_INTEGER; const NO_FUZZY_SCORE = Number.MAX_SAFE_INTEGER; const NO_MATCH_TIER = 5; +export const WORKSPACE_SEARCH_HIDDEN_DIRECTORIES = [ + ".agents", + ".claude", + ".codex", + ".github", + ".opencode", + ".paseo", + ".vscode", +] as const; const IGNORED_DIRECTORY_NAMES = new Set([ "node_modules", "venv",