From c750df3e86d180c3f6b3fcd936d9133e878166d8 Mon Sep 17 00:00:00 2001 From: Shoubhit Dash Date: Fri, 24 Apr 2026 18:58:28 +0530 Subject: [PATCH] fix(scout): use effect schema tool params --- packages/opencode/src/tool/repo_clone.ts | 28 ++++++------- packages/opencode/src/tool/repo_overview.ts | 46 +++++++++------------ 2 files changed, 32 insertions(+), 42 deletions(-) diff --git a/packages/opencode/src/tool/repo_clone.ts b/packages/opencode/src/tool/repo_clone.ts index 1d3c80a413..41fd2c5fd1 100644 --- a/packages/opencode/src/tool/repo_clone.ts +++ b/packages/opencode/src/tool/repo_clone.ts @@ -1,6 +1,5 @@ import path from "path" -import z from "zod" -import { Effect } from "effect" +import { Effect, Schema } from "effect" import { AppFileSystem } from "@opencode-ai/shared/filesystem" import { Flock } from "@opencode-ai/shared/util/flock" import { Git } from "@/git" @@ -8,16 +7,13 @@ import DESCRIPTION from "./repo_clone.txt" import * as Tool from "./tool" import { parseRepositoryReference, repositoryCachePath, sameRepositoryReference } from "@/util/repository" -type Parameters = { - repository: string - refresh?: boolean -} - -const parameters: z.ZodType = z.object({ - repository: z - .string() - .describe("Repository to clone, as a git URL, host/path reference, or GitHub owner/repo shorthand"), - refresh: z.boolean().optional().describe("When true, fetches the latest remote state into the managed cache"), +export const Parameters = Schema.Struct({ + repository: Schema.String.annotate({ + description: "Repository to clone, as a git URL, host/path reference, or GitHub owner/repo shorthand", + }), + refresh: Schema.optional(Schema.Boolean).annotate({ + description: "When true, fetches the latest remote state into the managed cache", + }), }) type Metadata = { @@ -49,7 +45,7 @@ function resetTarget(input: { return "HEAD" } -export const RepoCloneTool = Tool.define( +export const RepoCloneTool = Tool.define( "repo_clone", Effect.gen(function* () { const fs = yield* AppFileSystem.Service @@ -57,8 +53,8 @@ export const RepoCloneTool = Tool.define) => + parameters: Parameters, + execute: (params: Schema.Schema.Type, ctx: Tool.Context) => Effect.gen(function* () { const reference = parseRepositoryReference(params.repository) if (!reference) throw new Error("Repository must be a git URL, host/path reference, or GitHub owner/repo shorthand") @@ -152,6 +148,6 @@ export const RepoCloneTool = Tool.define Effect.promise(() => lock.release()).pipe(Effect.ignore), ) }).pipe(Effect.orDie), - } satisfies Tool.DefWithoutID + } satisfies Tool.DefWithoutID }), ) diff --git a/packages/opencode/src/tool/repo_overview.ts b/packages/opencode/src/tool/repo_overview.ts index f991a2e0fa..fcdd1e7da3 100644 --- a/packages/opencode/src/tool/repo_overview.ts +++ b/packages/opencode/src/tool/repo_overview.ts @@ -1,6 +1,5 @@ import path from "path" -import z from "zod" -import { Effect } from "effect" +import { Effect, Schema } from "effect" import { AppFileSystem } from "@opencode-ai/shared/filesystem" import { Git } from "@/git" import { assertExternalDirectoryEffect } from "./external-directory" @@ -9,24 +8,17 @@ import * as Tool from "./tool" import { parseRepositoryReference, repositoryCachePath } from "@/util/repository" import { Instance } from "@/project/instance" -type Parameters = { - repository?: string - path?: string - depth?: number -} - -const parameters: z.ZodType = z - .object({ - repository: z - .string() - .optional() - .describe("Cached repository to inspect, as a git URL, host/path reference, or GitHub owner/repo shorthand"), - path: z.string().optional().describe("Directory path to inspect instead of a cached repository"), - depth: z.number().int().positive().max(6).optional().describe("Maximum structure depth to include. Defaults to 3."), - }) - .refine((input) => Boolean(input.repository || input.path), { - message: "Either repository or path is required", +export const Parameters = Schema.Struct({ + repository: Schema.optional(Schema.String).annotate({ + description: "Cached repository to inspect, as a git URL, host/path reference, or GitHub owner/repo shorthand", + }), + path: Schema.optional(Schema.String).annotate({ + description: "Directory path to inspect instead of a cached repository", + }), + depth: Schema.optional(Schema.Number).annotate({ + description: "Maximum structure depth to include. Defaults to 3.", }) +}) type Metadata = { path: string @@ -84,19 +76,21 @@ function commonEntrypoints(files: Set) { return ["index.ts", "index.tsx", "index.js", "index.mjs", "main.ts", "main.js", "src/index.ts", "src/index.tsx", "src/index.js", "src/main.ts", "src/main.js"].filter((file) => files.has(file)) } -export const RepoOverviewTool = Tool.define( +export const RepoOverviewTool = Tool.define( "repo_overview", Effect.gen(function* () { const fs = yield* AppFileSystem.Service const git = yield* Git.Service - const resolveTarget = Effect.fn("RepoOverviewTool.resolveTarget")(function* (params: Parameters) { + const resolveTarget = Effect.fn("RepoOverviewTool.resolveTarget")(function* (params: Schema.Schema.Type) { if (params.path) { const full = path.isAbsolute(params.path) ? params.path : path.resolve(Instance.directory, params.path) return { path: full, repository: params.repository } } - const parsed = parseRepositoryReference(params.repository!) + if (!params.repository) throw new Error("Either repository or path is required") + + const parsed = parseRepositoryReference(params.repository) if (!parsed) throw new Error("Repository must be a git URL, host/path reference, or GitHub owner/repo shorthand") const repository = parsed.label @@ -152,11 +146,11 @@ export const RepoOverviewTool = Tool.define) => + parameters: Parameters, + execute: (params: Schema.Schema.Type, ctx: Tool.Context) => Effect.gen(function* () { const target = yield* resolveTarget(params) - const depth = params.depth ?? 3 + const depth = !params.depth || !Number.isInteger(params.depth) || params.depth < 1 || params.depth > 6 ? 3 : params.depth yield* assertExternalDirectoryEffect(ctx, target.path, { kind: "directory" }) yield* ctx.ask({ @@ -239,6 +233,6 @@ export const RepoOverviewTool = Tool.define + } satisfies Tool.DefWithoutID }), )