diff --git a/packages/core/src/v1/config/config.ts b/packages/core/src/v1/config/config.ts index 2e773f71e256..ea4b98b2fbd7 100644 --- a/packages/core/src/v1/config/config.ts +++ b/packages/core/src/v1/config/config.ts @@ -53,6 +53,9 @@ export const Info = Schema.Struct({ description: "Enable or disable snapshot tracking. When false, filesystem snapshots are not recorded and undoing or reverting will not undo/redo file changes. Defaults to true.", }), + follow_symlinks: Schema.optional(Schema.Boolean).annotate({ + description: "Follow symbolic links when searching files (default: false)", + }), plugin: Schema.optional(Schema.mutable(Schema.Array(ConfigPluginV1.Spec))), share: Schema.optional(Schema.Literals(["manual", "auto", "disabled"])).annotate({ description: diff --git a/packages/opencode/src/tool/glob.ts b/packages/opencode/src/tool/glob.ts index 40d3a27d3cba..1a52df86dc82 100644 --- a/packages/opencode/src/tool/glob.ts +++ b/packages/opencode/src/tool/glob.ts @@ -1,6 +1,7 @@ import path from "path" -import { Effect, Schema } from "effect" +import { Effect, Option, Schema } from "effect" import { InstanceState } from "@/effect/instance-state" +import { Config } from "@/config/config" import { FSUtil } from "@opencode-ai/core/fs-util" import { Ripgrep } from "@opencode-ai/core/ripgrep" import { assertExternalDirectoryEffect } from "./external-directory" @@ -46,8 +47,14 @@ export const GlobTool = Tool.define( kind: "directory", }) + const configSvc = yield* Effect.serviceOption(Config.Service) + const cfg = Option.isNone(configSvc) + ? undefined + : yield* configSvc.value.get().pipe(Effect.catch(() => Effect.succeed(undefined))) + const follow = cfg?.follow_symlinks ?? false + const limit = 100 - const files = yield* ripgrep.glob({ cwd: search, pattern: params.pattern, limit }) + const files = yield* ripgrep.glob({ cwd: search, pattern: params.pattern, limit, follow }) const truncated = files.length === limit const output = []