From bf5c0c36ad70ac40d0933d8025cd1b992905050a Mon Sep 17 00:00:00 2001 From: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com> Date: Fri, 10 Apr 2026 01:37:38 -0700 Subject: [PATCH 1/3] fix: resolve all lint errors and warnings Fix 46 no-explicit-any errors, unused imports/params, require-yield, useless escapes, and useless fallback spreads across 32 files. Exclude generated .astro/ directory from linting. --- .oxlintrc.jsonc | 1 + apps/cli/src/build.ts | 5 +-- apps/cli/src/main.ts | 19 ++++++---- apps/cloud/src/auth/workos.ts | 6 ++-- apps/cloud/src/mcp.ts | 2 -- apps/cloud/src/routes/__root.tsx | 2 +- apps/cloud/src/web/shell.tsx | 9 ++--- apps/desktop/scripts/bundle-cli.js | 2 +- apps/local/src/routes/__root.tsx | 2 +- packages/core/api/src/handlers/secrets.ts | 4 +-- packages/core/api/src/handlers/sources.ts | 4 +-- packages/core/api/src/handlers/tools.ts | 2 +- packages/core/config/src/config-store.ts | 35 +++++++++++++++---- packages/core/env/src/index.test.ts | 1 + packages/core/execution/src/engine.ts | 12 +++---- packages/core/sdk/src/index.test.ts | 1 - .../core/sdk/src/plugins/in-memory-tools.ts | 3 +- packages/core/sdk/src/promise-executor.ts | 17 ++++----- packages/core/sdk/src/runtime-tools.ts | 3 ++ packages/core/sdk/src/schema-types.ts | 4 +-- .../core/storage-postgres/src/index.test.ts | 1 - packages/core/storage-postgres/src/types.ts | 1 + .../plugins/graphql/src/sdk/extract.test.ts | 25 +++++++------ packages/plugins/graphql/src/sdk/extract.ts | 1 + packages/plugins/mcp/src/sdk/invoke.ts | 4 +-- packages/plugins/mcp/src/sdk/plugin.ts | 8 ++--- .../plugins/onepassword/src/sdk/service.ts | 2 +- packages/react/src/components/combobox.tsx | 2 +- .../react/src/components/schema-explorer.tsx | 1 + packages/react/src/components/tool-detail.tsx | 4 +-- packages/react/src/pages/secrets.tsx | 1 - tests/presets-reachable.test.ts | 2 +- 32 files changed, 110 insertions(+), 76 deletions(-) diff --git a/.oxlintrc.jsonc b/.oxlintrc.jsonc index 56cbf3c9d1..d52e4b6610 100644 --- a/.oxlintrc.jsonc +++ b/.oxlintrc.jsonc @@ -1,4 +1,5 @@ { + "ignorePatterns": [".astro/"], "rules": { "typescript/no-explicit-any": "error", }, diff --git a/apps/cli/src/build.ts b/apps/cli/src/build.ts index 72cfd3f911..30dfdd69b4 100644 --- a/apps/cli/src/build.ts +++ b/apps/cli/src/build.ts @@ -280,6 +280,7 @@ const buildBinaries = async (targets: Target[], mode: BuildMode) => { entrypoints: [join(cliRoot, "src/main.ts")], minify: mode === "production", compile: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Bun compile target string is dynamically constructed target: bunTarget(target) as any, outfile: join(binDir, binaryName(target)), }, @@ -554,8 +555,8 @@ const repositoryUrl = typeof packageJson.repository === "string" ? packageJson.repository : packageJson.repository && packageJson.repository.url; const githubBase = String(packageJson.homepage || repositoryUrl || "https://github.com/RhysSullivan/executor") - .replace(/^git\+/, "") - .replace(/\.git$/, ""); + .replace(/^git[+]/, "") + .replace(/.git$/, ""); const version = packageJson.version; const platformMap = { darwin: "darwin", linux: "linux", win32: "windows" }; diff --git a/apps/cli/src/main.ts b/apps/cli/src/main.ts index 658f2a8304..82f9053680 100644 --- a/apps/cli/src/main.ts +++ b/apps/cli/src/main.ts @@ -14,13 +14,19 @@ if (typeof Bun !== "undefined" && (await Bun.file(wasmOnDisk).exists())) { const variant = { type: "sync" as const, importFFI: () => - import("@jitl/quickjs-wasmfile-release-sync/ffi").then((m: any) => m.QuickJSFFI), + import("@jitl/quickjs-wasmfile-release-sync/ffi").then( + (m: Record) => m.QuickJSFFI, + ), importModuleLoader: () => - import("@jitl/quickjs-wasmfile-release-sync/emscripten-module").then((m: any) => { - const original = m.default; - return (moduleArg: any = {}) => original({ ...moduleArg, wasmBinary }); - }), + import("@jitl/quickjs-wasmfile-release-sync/emscripten-module").then( + (m: Record) => { + const original = m.default as (...args: unknown[]) => unknown; + return (moduleArg: Record = {}) => + original({ ...moduleArg, wasmBinary }); + }, + ), }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- quickjs-emscripten variant type is not publicly exported const mod = await newQuickJSWASMModule(variant as any); setQuickJSModule(mod); } @@ -200,7 +206,8 @@ const callCommand = Command.make( } } else { console.log(result.text); - const executionId = (result.structured as any)?.executionId; + const executionId = (result.structured as Record | undefined) + ?.executionId; if (executionId) { console.log( `\nTo resume:\n ${cliPrefix} resume --execution-id ${executionId} --action accept`, diff --git a/apps/cloud/src/auth/workos.ts b/apps/cloud/src/auth/workos.ts index 1b7a92b81c..f4ba4a0a59 100644 --- a/apps/cloud/src/auth/workos.ts +++ b/apps/cloud/src/auth/workos.ts @@ -40,7 +40,7 @@ const make = Effect.gen(function* () { cookiePassword, }); - const result = yield* use((wos) => session.authenticate()); + const result = yield* use((_wos) => session.authenticate()); if (result.authenticated) { return { @@ -58,7 +58,7 @@ const make = Effect.gen(function* () { if (result.reason === "no_session_cookie_provided") return null; // Try refreshing - const refreshed = yield* use((wos) => session.refresh()).pipe( + const refreshed = yield* use((_wos) => session.refresh()).pipe( Effect.orElseSucceed(() => ({ authenticated: false as const })), ); @@ -117,7 +117,7 @@ const make = Effect.gen(function* () { sessionData, cookiePassword, }); - const refreshed = yield* use((wos) => + const refreshed = yield* use((_wos) => session.refresh(organizationId ? { organizationId } : undefined), ); if (!refreshed.authenticated || !("sealedSession" in refreshed)) return null; diff --git a/apps/cloud/src/mcp.ts b/apps/cloud/src/mcp.ts index a3f23adeeb..8a39bc8ee2 100644 --- a/apps/cloud/src/mcp.ts +++ b/apps/cloud/src/mcp.ts @@ -5,8 +5,6 @@ import { env } from "cloudflare:workers"; import { createRemoteJWKSet, jwtVerify } from "jose"; -import type { McpSessionInit } from "./mcp-session"; - // --------------------------------------------------------------------------- // Constants // --------------------------------------------------------------------------- diff --git a/apps/cloud/src/routes/__root.tsx b/apps/cloud/src/routes/__root.tsx index 544103a6b7..3bd8fd460b 100644 --- a/apps/cloud/src/routes/__root.tsx +++ b/apps/cloud/src/routes/__root.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { HeadContent, Outlet, Scripts, createRootRoute } from "@tanstack/react-router"; +import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router"; import { AutumnProvider } from "autumn-js/react"; import { ExecutorProvider } from "@executor/react/api/provider"; import { AuthProvider, useAuth } from "../web/auth"; diff --git a/apps/cloud/src/web/shell.tsx b/apps/cloud/src/web/shell.tsx index f30d23c61e..4586fae377 100644 --- a/apps/cloud/src/web/shell.tsx +++ b/apps/cloud/src/web/shell.tsx @@ -1,9 +1,9 @@ import { Link, Outlet, useLocation } from "@tanstack/react-router"; import { useEffect, useRef, useState } from "react"; -import { useAtomRefresh, useAtomValue, Result } from "@effect-atom/atom-react"; -import { sourcesAtom, toolsAtom } from "@executor/react/api/atoms"; +import { useAtomValue, Result } from "@effect-atom/atom-react"; +import { sourcesAtom } from "@executor/react/api/atoms"; import { useScope } from "@executor/react/api/scope-context"; -import { Button } from "@executor/react/components/button"; + import { AUTH_PATHS } from "../auth/api"; import { useAuth } from "./auth"; @@ -169,9 +169,6 @@ function SidebarContent(props: { pathname: string; onNavigate?: () => void; show export function Shell() { const location = useLocation(); const pathname = location.pathname; - const scopeId = useScope(); - const refreshSources = useAtomRefresh(sourcesAtom(scopeId)); - const refreshTools = useAtomRefresh(toolsAtom(scopeId)); const lastPathname = useRef(pathname); const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false); if (lastPathname.current !== pathname) { diff --git a/apps/desktop/scripts/bundle-cli.js b/apps/desktop/scripts/bundle-cli.js index 9c860eecd7..8e6836b53a 100644 --- a/apps/desktop/scripts/bundle-cli.js +++ b/apps/desktop/scripts/bundle-cli.js @@ -2,7 +2,7 @@ * Builds the executor CLI binary and copies it into the desktop app's * resources/ folder so electron-builder can bundle it as a sidecar. */ -const { execSync, spawnSync } = require("node:child_process"); +const { spawnSync } = require("node:child_process"); const { existsSync, mkdirSync, cpSync, chmodSync } = require("node:fs"); const { resolve, join } = require("node:path"); diff --git a/apps/local/src/routes/__root.tsx b/apps/local/src/routes/__root.tsx index e4e627fc1b..c03afcc63b 100644 --- a/apps/local/src/routes/__root.tsx +++ b/apps/local/src/routes/__root.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { Outlet, createRootRoute } from "@tanstack/react-router"; +import { createRootRoute } from "@tanstack/react-router"; import { ExecutorProvider } from "@executor/react/api/provider"; import { Shell } from "../web/shell"; diff --git a/packages/core/api/src/handlers/secrets.ts b/packages/core/api/src/handlers/secrets.ts index 4c9f38b227..e72aba233c 100644 --- a/packages/core/api/src/handlers/secrets.ts +++ b/packages/core/api/src/handlers/secrets.ts @@ -23,7 +23,7 @@ const refToResponse = (ref: { export const SecretsHandlers = HttpApiBuilder.group(ExecutorApi, "secrets", (handlers) => handlers - .handle("list", ({ path }) => + .handle("list", ({ path: _path }) => Effect.gen(function* () { const executor = yield* ExecutorService; const refs = yield* executor.secrets.list(); @@ -37,7 +37,7 @@ export const SecretsHandlers = HttpApiBuilder.group(ExecutorApi, "secrets", (han return { secretId: path.secretId, status }; }), ) - .handle("set", ({ path, payload }) => + .handle("set", ({ path: _path, payload }) => Effect.gen(function* () { const executor = yield* ExecutorService; const ref = yield* executor.secrets.set({ diff --git a/packages/core/api/src/handlers/sources.ts b/packages/core/api/src/handlers/sources.ts index f5712c7703..806ea59adc 100644 --- a/packages/core/api/src/handlers/sources.ts +++ b/packages/core/api/src/handlers/sources.ts @@ -6,7 +6,7 @@ import { ExecutorService } from "../services"; export const SourcesHandlers = HttpApiBuilder.group(ExecutorApi, "sources", (handlers) => handlers - .handle("list", ({ path }) => + .handle("list", ({ path: _path }) => Effect.gen(function* () { const executor = yield* ExecutorService; const sources = yield* executor.sources.list(); @@ -49,7 +49,7 @@ export const SourcesHandlers = HttpApiBuilder.group(ExecutorApi, "sources", (han })); }), ) - .handle("detect", ({ path, payload }) => + .handle("detect", ({ path: _path, payload }) => Effect.gen(function* () { const executor = yield* ExecutorService; const results = yield* executor.sources.detect(payload.url); diff --git a/packages/core/api/src/handlers/tools.ts b/packages/core/api/src/handlers/tools.ts index 5f984e7edc..4c7dedca28 100644 --- a/packages/core/api/src/handlers/tools.ts +++ b/packages/core/api/src/handlers/tools.ts @@ -6,7 +6,7 @@ import { ExecutorService } from "../services"; export const ToolsHandlers = HttpApiBuilder.group(ExecutorApi, "tools", (handlers) => handlers - .handle("list", ({ path }) => + .handle("list", ({ path: _path }) => Effect.gen(function* () { const executor = yield* ExecutorService; const tools = yield* executor.tools.list(); diff --git a/packages/core/config/src/config-store.ts b/packages/core/config/src/config-store.ts index 37776f4ae6..f3d3ddfb0e 100644 --- a/packages/core/config/src/config-store.ts +++ b/packages/core/config/src/config-store.ts @@ -157,41 +157,64 @@ interface StoreWithSource { removeSource: (namespace: string) => Effect.Effect; } +interface OpenApiSource { + namespace: string; + name: string; + config: { spec: string; baseUrl?: string; namespace?: string; headers?: Record }; +} + +interface GraphqlSource { + namespace: string; + name: string; + config: { + endpoint: string; + introspectionJson?: string; + namespace?: string; + headers?: Record; + }; +} + +interface McpSource { + namespace: string; + name: string; + config: { transport: string; [key: string]: unknown }; +} + /** * Wrap a plugin store so putSource/removeSource also write to executor.jsonc. * Preserves the full store type — only the two methods are intercepted. */ export const withConfigFile = { - openapi: >( + openapi: >( inner: TStore, configPath: string, fsLayer: Layer.Layer, ): TStore => ({ ...inner, - putSource: wrapPutSource(inner.putSource, configPath, openApiToSourceConfig as any, fsLayer), + putSource: wrapPutSource(inner.putSource, configPath, openApiToSourceConfig, fsLayer), removeSource: wrapRemoveSource(inner.removeSource, configPath, fsLayer), }) as TStore, - graphql: >( + graphql: >( inner: TStore, configPath: string, fsLayer: Layer.Layer, ): TStore => ({ ...inner, - putSource: wrapPutSource(inner.putSource, configPath, graphqlToSourceConfig as any, fsLayer), + putSource: wrapPutSource(inner.putSource, configPath, graphqlToSourceConfig, fsLayer), removeSource: wrapRemoveSource(inner.removeSource, configPath, fsLayer), }) as TStore, - mcp: >( + mcp: >( inner: TStore, configPath: string, fsLayer: Layer.Layer, ): TStore => ({ ...inner, - putSource: wrapPutSource(inner.putSource, configPath, mcpToSourceConfig as any, fsLayer), + putSource: wrapPutSource(inner.putSource, configPath, mcpToSourceConfig, fsLayer), removeSource: wrapRemoveSource(inner.removeSource, configPath, fsLayer), }) as TStore, }; diff --git a/packages/core/env/src/index.test.ts b/packages/core/env/src/index.test.ts index b2cda1a1de..7cd8828237 100644 --- a/packages/core/env/src/index.test.ts +++ b/packages/core/env/src/index.test.ts @@ -287,6 +287,7 @@ describe("createEnv", () => { }, ); + // oxlint-disable-next-line no-constant-condition -- compile-time-only type check if (false) { createEnv( { diff --git a/packages/core/execution/src/engine.ts b/packages/core/execution/src/engine.ts index 5223250279..0c8d59659a 100644 --- a/packages/core/execution/src/engine.ts +++ b/packages/core/execution/src/engine.ts @@ -103,14 +103,14 @@ export const formatPausedExecution = ( structured: Record; } => { const req = paused.elicitationContext.request; - const lines: string[] = [`Execution paused: ${(req as any).message}`]; + const lines: string[] = [`Execution paused: ${req.message}`]; if (req._tag === "UrlElicitation") { - lines.push(`\nOpen this URL in a browser:\n${(req as any).url}`); + lines.push(`\nOpen this URL in a browser:\n${req.url}`); lines.push("\nAfter the browser flow, resume with the executionId below:"); } else { lines.push("\nResume with the executionId below and a response matching the requested schema:"); - const schema = (req as any).requestedSchema; + const schema = req.requestedSchema; if (schema && Object.keys(schema).length > 0) { lines.push(`\nRequested schema:\n${JSON.stringify(schema, null, 2)}`); } @@ -125,10 +125,10 @@ export const formatPausedExecution = ( executionId: paused.id, interaction: { kind: req._tag === "UrlElicitation" ? "url" : "form", - message: (req as any).message, - ...(req._tag === "UrlElicitation" ? { url: (req as any).url } : {}), + message: req.message, + ...(req._tag === "UrlElicitation" ? { url: req.url } : {}), ...(req._tag === "FormElicitation" - ? { requestedSchema: (req as any).requestedSchema } + ? { requestedSchema: req.requestedSchema } : {}), }, }, diff --git a/packages/core/sdk/src/index.test.ts b/packages/core/sdk/src/index.test.ts index 0809be9e3a..c0081292ef 100644 --- a/packages/core/sdk/src/index.test.ts +++ b/packages/core/sdk/src/index.test.ts @@ -12,7 +12,6 @@ import { ElicitationResponse, Source, type MemoryToolContext, - type ToolId, type InvokeOptions, SecretId, } from "./index"; diff --git a/packages/core/sdk/src/plugins/in-memory-tools.ts b/packages/core/sdk/src/plugins/in-memory-tools.ts index cf790dfe62..927a55d1cc 100644 --- a/packages/core/sdk/src/plugins/in-memory-tools.ts +++ b/packages/core/sdk/src/plugins/in-memory-tools.ts @@ -267,9 +267,9 @@ export function tool( // Plugin factory // --------------------------------------------------------------------------- -// eslint-disable-next-line @typescript-eslint/no-explicit-any export const inMemoryToolsPlugin = (config: { readonly namespace?: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Schema.Schema is invariant; `any` required to accept arbitrary MemoryToolDefinition types readonly tools: readonly MemoryToolDefinition[]; }) => { const ns = config.namespace ?? "memory"; @@ -303,6 +303,7 @@ export const inMemoryToolsPlugin = (config: { return { extension: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Schema.Schema is invariant; `any` required to accept arbitrary MemoryToolDefinition types addTools: (newTools: readonly MemoryToolDefinition[]) => Effect.gen(function* () { const newResults = newTools.map((t) => buildRegistration(ns, t)); diff --git a/packages/core/sdk/src/promise-executor.ts b/packages/core/sdk/src/promise-executor.ts index 3af8aca2ee..4e83c54eac 100644 --- a/packages/core/sdk/src/promise-executor.ts +++ b/packages/core/sdk/src/promise-executor.ts @@ -18,6 +18,7 @@ import { type ExecutorConfig as EffectExecutorConfig, type ExecutorPlugin, type PluginContext as EffectPluginContext, + type PluginHandle as EffectPluginHandle, type ElicitationContext, type InvokeOptions as EffectInvokeOptions, type ToolInvocationResult, @@ -26,8 +27,6 @@ import { type ToolSchema, type ToolInvoker as EffectToolInvoker, type RuntimeToolHandler as EffectRuntimeToolHandler, - type Source, - type SourceDetectionResult, type SourceManager as EffectSourceManager, type Policy, type SecretRef, @@ -44,6 +43,8 @@ import { type SecretResolutionError, type PolicyDeniedError, type ElicitationDeclinedError, + ToolListFilter, + PolicyCheckInput, } from "./index"; // --------------------------------------------------------------------------- @@ -432,7 +433,7 @@ export interface PolicyEngine extends Omit ({ scope: ctx.scope, tools: { - list: (filter?) => run(ctx.tools.list(filter as any)), + list: (filter?) => run(ctx.tools.list(filter ? new ToolListFilter(filter) : undefined)), schema: (toolId) => run(ctx.tools.schema(ToolId.make(toolId))), invoke: (toolId, args, options) => run(ctx.tools.invoke(ToolId.make(toolId), args, toEffectInvokeOptions(options))), @@ -475,7 +476,7 @@ const wrapPluginContext = (ctx: EffectPluginContext): PluginContext => ({ }, policies: { list: (scopeId) => run(ctx.policies.list(ScopeId.make(scopeId))), - check: (input) => run(ctx.policies.check(input as any)), + check: (input) => run(ctx.policies.check(new PolicyCheckInput({ scopeId: ScopeId.make(input.scopeId), toolId: ToolId.make(input.toolId) }))), add: (policy) => run(ctx.policies.add(policy)), remove: (policyId) => run(ctx.policies.remove(PolicyId.make(policyId))), }, @@ -516,7 +517,7 @@ const toEffectPlugin = ( ? () => fromPromise(() => handle.close!()) as Effect.Effect : undefined, }; - }) as Effect.Effect, + }) as Effect.Effect, PromiseAdapterError>, }); // --------------------------------------------------------------------------- @@ -616,7 +617,7 @@ export const createExecutor = async = {}, ): Promise> => { const effectPlugins = (config.plugins ?? []).map((p) => - isPromisePlugin(p as any) + isPromisePlugin(p as { _promise?: boolean }) ? toEffectPlugin(p as Plugin) : (p as unknown as ExecutorPlugin), ); @@ -640,7 +641,7 @@ export const createExecutor = async - run(executor.tools.list(filter as any)), + run(executor.tools.list(filter ? new ToolListFilter(filter) : undefined)), schema: (toolId: string) => run(executor.tools.schema(toolId)), definitions: () => run(executor.tools.definitions()), invoke: (toolId: string, args: unknown, options: InvokeOptions) => @@ -667,7 +668,7 @@ export const createExecutor = async run(executor.secrets.set(input as any)), + }) => run(executor.secrets.set({ ...input, id: SecretId.make(input.id) })), remove: (secretId: string) => run(executor.secrets.remove(SecretId.make(secretId))), addProvider: (provider: SecretProvider) => run(executor.secrets.addProvider(toEffectSecretProvider(provider))), diff --git a/packages/core/sdk/src/runtime-tools.ts b/packages/core/sdk/src/runtime-tools.ts index 7afda46ac8..a44d9019db 100644 --- a/packages/core/sdk/src/runtime-tools.ts +++ b/packages/core/sdk/src/runtime-tools.ts @@ -11,7 +11,9 @@ export interface RuntimeToolDefinition { readonly sourceId?: string; readonly name: string; readonly description?: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Schema.Schema is invariant in Encoded; `any` is the only way to accept arbitrary encodings readonly inputSchema: Schema.Schema; + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Schema.Schema is invariant in Encoded; `any` is the only way to accept arbitrary encodings readonly outputSchema?: Schema.Schema; readonly handler: (args: TInput) => Effect.Effect; } @@ -95,6 +97,7 @@ const toRuntimeHandler = (toolId: ToolId, entry: RuntimeHandlerEntry): RuntimeTo }); export const registerRuntimeTools = < + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- RuntimeToolDefinition requires `any` for Schema invariant Encoded param const TTools extends readonly RuntimeToolDefinition[], >(input: { readonly registry: { diff --git a/packages/core/sdk/src/schema-types.ts b/packages/core/sdk/src/schema-types.ts index 69331ba3af..30a01d1c5e 100644 --- a/packages/core/sdk/src/schema-types.ts +++ b/packages/core/sdk/src/schema-types.ts @@ -384,8 +384,8 @@ export const buildToolTypeScriptPreview = (input: { : null; const mergedDefinitions = { - ...(inputPreview?.definitions ?? {}), - ...(outputPreview?.definitions ?? {}), + ...inputPreview?.definitions, + ...outputPreview?.definitions, }; return { diff --git a/packages/core/storage-postgres/src/index.test.ts b/packages/core/storage-postgres/src/index.test.ts index d3f8daff15..c84f6de50d 100644 --- a/packages/core/storage-postgres/src/index.test.ts +++ b/packages/core/storage-postgres/src/index.test.ts @@ -16,7 +16,6 @@ import { SecretId, ToolRegistration, scopeKv, - type Executor, } from "@executor/sdk"; import { makePgConfig } from "./index"; diff --git a/packages/core/storage-postgres/src/types.ts b/packages/core/storage-postgres/src/types.ts index 24d14b738f..05287cde24 100644 --- a/packages/core/storage-postgres/src/types.ts +++ b/packages/core/storage-postgres/src/types.ts @@ -4,4 +4,5 @@ import type { PgDatabase } from "drizzle-orm/pg-core"; +// eslint-disable-next-line @typescript-eslint/no-explicit-any export type DrizzleDb = PgDatabase; diff --git a/packages/plugins/graphql/src/sdk/extract.test.ts b/packages/plugins/graphql/src/sdk/extract.test.ts index 7f4478a23e..bd2931dd06 100644 --- a/packages/plugins/graphql/src/sdk/extract.test.ts +++ b/packages/plugins/graphql/src/sdk/extract.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from "@effect/vitest"; -import { Effect } from "effect"; +import { Effect, Option } from "effect"; import { extract } from "./extract"; import type { IntrospectionResult } from "./introspect"; @@ -182,11 +182,11 @@ describe("extract", () => { const createUser = result.fields.find((f) => f.fieldName === "createUser"); expect(createUser).toBeDefined(); - const inputSchema = createUser!.inputSchema as any; - expect(inputSchema.value).toBeDefined(); - const schema = inputSchema.value; + expect(Option.isSome(createUser!.inputSchema)).toBe(true); + const schema = Option.getOrThrow(createUser!.inputSchema) as Record; expect(schema.type).toBe("object"); - expect(schema.properties.name.type).toBe("string"); + const properties = schema.properties as Record>; + expect(properties.name.type).toBe("string"); expect(schema.required).toContain("name"); expect(schema.required).not.toContain("email"); }); @@ -311,15 +311,18 @@ describe("extract", () => { expect(issuesField.fieldName).toBe("issues"); // The filter arg should use a $ref, not inline the full type - const schema = (issuesField.inputSchema as any).value; - expect(schema.properties.filter.$ref).toBe("#/$defs/IssueFilter"); + const schema = Option.getOrThrow(issuesField.inputSchema) as Record; + const schemaProps = schema.properties as Record>; + expect(schemaProps.filter.$ref).toBe("#/$defs/IssueFilter"); // The definition should exist with proper fields - const filterDef = definitions["IssueFilter"] as any; + const filterDef = definitions["IssueFilter"] as Record; expect(filterDef.type).toBe("object"); - expect(filterDef.properties.title.type).toBe("string"); + const filterProps = filterDef.properties as Record>; + expect(filterProps.title.type).toBe("string"); // Self-referential "and" field uses $ref back to itself - expect(filterDef.properties.and.type).toBe("array"); - expect(filterDef.properties.and.items.$ref).toBe("#/$defs/IssueFilter"); + expect(filterProps.and.type).toBe("array"); + const andItems = filterProps.and.items as Record; + expect(andItems.$ref).toBe("#/$defs/IssueFilter"); }); }); diff --git a/packages/plugins/graphql/src/sdk/extract.ts b/packages/plugins/graphql/src/sdk/extract.ts index ad634f696d..0666d907c7 100644 --- a/packages/plugins/graphql/src/sdk/extract.ts +++ b/packages/plugins/graphql/src/sdk/extract.ts @@ -81,6 +81,7 @@ const buildDefinitions = ( const typeRefToJsonSchema = ( ref: IntrospectionTypeRef, + // oxlint-disable-next-line only-used-in-recursion types: ReadonlyMap, ): Record => { switch (ref.kind) { diff --git a/packages/plugins/mcp/src/sdk/invoke.ts b/packages/plugins/mcp/src/sdk/invoke.ts index c0f656ff1e..dbff96ef36 100644 --- a/packages/plugins/mcp/src/sdk/invoke.ts +++ b/packages/plugins/mcp/src/sdk/invoke.ts @@ -153,7 +153,7 @@ const resolveConnectorInput = ( } return Effect.gen(function* () { - const headers: Record = { ...(sourceData.headers ?? {}) }; + const headers: Record = { ...sourceData.headers }; let authProvider: OAuthClientProvider | undefined; const auth = sourceData.auth; @@ -317,7 +317,7 @@ export const makeMcpInvoker = (opts: { elicitationHandler, ).pipe( // On failure, invalidate the cached connection and retry once - Effect.catchAll((err) => + Effect.catchAll((_err) => Effect.gen(function* () { yield* connectionCache.invalidate(cacheKey); pendingConnectors.set(cacheKey, connector); diff --git a/packages/plugins/mcp/src/sdk/plugin.ts b/packages/plugins/mcp/src/sdk/plugin.ts index 158354b8dc..5afe795a80 100644 --- a/packages/plugins/mcp/src/sdk/plugin.ts +++ b/packages/plugins/mcp/src/sdk/plugin.ts @@ -308,14 +308,14 @@ export const mcpPlugin = (options?: { return Effect.gen(function* () { const headers: Record = { - ...(sd.headers ?? {}), + ...sd.headers, }; let authProvider: OAuthClientProvider | undefined; const auth = sd.auth; if (auth.kind === "header") { const val = yield* ctx.secrets - .resolve(auth.secretId as any, ctx.scope.id) + .resolve(SecretId.make(auth.secretId), ctx.scope.id) .pipe( Effect.mapError(() => remoteConnectionError(`Failed to resolve secret "${auth.secretId}"`), @@ -324,7 +324,7 @@ export const mcpPlugin = (options?: { headers[auth.headerName] = auth.prefix ? `${auth.prefix}${val}` : val; } else if (auth.kind === "oauth2") { const accessToken = yield* ctx.secrets - .resolve(auth.accessTokenSecretId as any, ctx.scope.id) + .resolve(SecretId.make(auth.accessTokenSecretId), ctx.scope.id) .pipe( Effect.mapError(() => remoteConnectionError("Failed to resolve OAuth access token"), @@ -334,7 +334,7 @@ export const mcpPlugin = (options?: { let refreshToken: string | undefined; if (auth.refreshTokenSecretId) { refreshToken = yield* ctx.secrets - .resolve(auth.refreshTokenSecretId as any, ctx.scope.id) + .resolve(SecretId.make(auth.refreshTokenSecretId), ctx.scope.id) .pipe( Effect.option, Effect.map((o) => (o._tag === "Some" ? o.value : undefined)), diff --git a/packages/plugins/onepassword/src/sdk/service.ts b/packages/plugins/onepassword/src/sdk/service.ts index 9dd204fd68..1f9bba915c 100644 --- a/packages/plugins/onepassword/src/sdk/service.ts +++ b/packages/plugins/onepassword/src/sdk/service.ts @@ -152,7 +152,7 @@ export const makeNativeSdkService = ( export const makeCliService = ( auth: ResolvedAuth, ): Effect.Effect => - Effect.gen(function* () { + Effect.sync(() => { // Configure auth if (auth.kind === "service-account") { op.setServiceAccount(auth.token); diff --git a/packages/react/src/components/combobox.tsx b/packages/react/src/components/combobox.tsx index 0bb2bdf695..cd575183cb 100644 --- a/packages/react/src/components/combobox.tsx +++ b/packages/react/src/components/combobox.tsx @@ -243,7 +243,7 @@ function ComboboxChip({ ); } -function ComboboxChipsInput({ className, children, ...props }: ComboboxPrimitive.Input.Props) { +function ComboboxChipsInput({ className, ...props }: ComboboxPrimitive.Input.Props) { return ( { // Type label — human readable, shows ref names // --------------------------------------------------------------------------- +// oxlint-disable-next-line only-used-in-recursion const getTypeLabel = (schema: JsonSchema, root: JsonSchema): string => { if (schema.$ref) { return getRefName(schema.$ref) ?? "ref"; diff --git a/packages/react/src/components/tool-detail.tsx b/packages/react/src/components/tool-detail.tsx index 39762a2f71..c95c7d3b64 100644 --- a/packages/react/src/components/tool-detail.tsx +++ b/packages/react/src/components/tool-detail.tsx @@ -2,9 +2,7 @@ import { useMemo, useState } from "react"; import { useAtomValue, Result } from "@effect-atom/atom-react"; import { toolSchemaAtom } from "../api/atoms"; import { ScopeId, ToolId } from "@executor/sdk"; -import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "./accordion"; -import { Badge } from "./badge"; -import { CodeBlock } from "./code-block"; + import { Markdown } from "./markdown"; import { SchemaExplorer } from "./schema-explorer"; import { ExpandableCodeBlock } from "./expandable-code-block"; diff --git a/packages/react/src/pages/secrets.tsx b/packages/react/src/pages/secrets.tsx index faad3dfa3e..05306ab096 100644 --- a/packages/react/src/pages/secrets.tsx +++ b/packages/react/src/pages/secrets.tsx @@ -16,7 +16,6 @@ import { import { Button } from "../components/button"; import { Input } from "../components/input"; import { Label } from "../components/label"; -import { Badge } from "../components/badge"; import { DropdownMenu, DropdownMenuContent, diff --git a/tests/presets-reachable.test.ts b/tests/presets-reachable.test.ts index ac9347938f..b31d5d21eb 100644 --- a/tests/presets-reachable.test.ts +++ b/tests/presets-reachable.test.ts @@ -151,7 +151,7 @@ const publicPresets = allPresets.filter( // Skip auth-required endpoints that won't pass detection without credentials !["github-graphql", "linear", "monday", "stripe"].includes(p.id) && // Skip stdio presets (not HTTP-reachable) - !("transport" in p && (p as any).transport === "stdio") && + !("transport" in p && (p as Record).transport === "stdio") && // Skip host-scoped Google Discovery URLs (forms.googleapis.com/$discovery/...) // — the detector only recognises the central directory pattern today !["google-forms", "google-keep"].includes(p.id) && From d44a97b80692031eb69acdb1ef18f5826ca73f20 Mon Sep 17 00:00:00 2001 From: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com> Date: Fri, 10 Apr 2026 02:04:17 -0700 Subject: [PATCH 2/3] fix: remove unused _ prefixed parameters instead of dangling them --- apps/cloud/src/auth/workos.ts | 6 +++--- apps/cloud/src/routes/billing_.plans.tsx | 1 - packages/core/api/src/handlers/secrets.ts | 4 ++-- packages/core/api/src/handlers/sources.ts | 4 ++-- packages/core/api/src/handlers/tools.ts | 2 +- packages/plugins/mcp/src/sdk/invoke.ts | 2 +- 6 files changed, 9 insertions(+), 10 deletions(-) diff --git a/apps/cloud/src/auth/workos.ts b/apps/cloud/src/auth/workos.ts index f4ba4a0a59..cfee30ed80 100644 --- a/apps/cloud/src/auth/workos.ts +++ b/apps/cloud/src/auth/workos.ts @@ -40,7 +40,7 @@ const make = Effect.gen(function* () { cookiePassword, }); - const result = yield* use((_wos) => session.authenticate()); + const result = yield* use(() => session.authenticate()); if (result.authenticated) { return { @@ -58,7 +58,7 @@ const make = Effect.gen(function* () { if (result.reason === "no_session_cookie_provided") return null; // Try refreshing - const refreshed = yield* use((_wos) => session.refresh()).pipe( + const refreshed = yield* use(() => session.refresh()).pipe( Effect.orElseSucceed(() => ({ authenticated: false as const })), ); @@ -117,7 +117,7 @@ const make = Effect.gen(function* () { sessionData, cookiePassword, }); - const refreshed = yield* use((_wos) => + const refreshed = yield* use(() => session.refresh(organizationId ? { organizationId } : undefined), ); if (!refreshed.authenticated || !("sealedSession" in refreshed)) return null; diff --git a/apps/cloud/src/routes/billing_.plans.tsx b/apps/cloud/src/routes/billing_.plans.tsx index f9b304a18a..359a07929b 100644 --- a/apps/cloud/src/routes/billing_.plans.tsx +++ b/apps/cloud/src/routes/billing_.plans.tsx @@ -95,7 +95,6 @@ function PlansPage() { const isCanceling = eligibility?.canceling ?? false; const isCurrent = status === "active" && !isCanceling; const isScheduled = status === "scheduled"; - const isActionable = action !== "none"; const label = isCanceling ? "Resume" : (ACTION_LABELS[action] ?? "Select"); const isUpgradeAction = action === "upgrade" || action === "activate"; diff --git a/packages/core/api/src/handlers/secrets.ts b/packages/core/api/src/handlers/secrets.ts index e72aba233c..c9eb8a8070 100644 --- a/packages/core/api/src/handlers/secrets.ts +++ b/packages/core/api/src/handlers/secrets.ts @@ -23,7 +23,7 @@ const refToResponse = (ref: { export const SecretsHandlers = HttpApiBuilder.group(ExecutorApi, "secrets", (handlers) => handlers - .handle("list", ({ path: _path }) => + .handle("list", () => Effect.gen(function* () { const executor = yield* ExecutorService; const refs = yield* executor.secrets.list(); @@ -37,7 +37,7 @@ export const SecretsHandlers = HttpApiBuilder.group(ExecutorApi, "secrets", (han return { secretId: path.secretId, status }; }), ) - .handle("set", ({ path: _path, payload }) => + .handle("set", ({ payload }) => Effect.gen(function* () { const executor = yield* ExecutorService; const ref = yield* executor.secrets.set({ diff --git a/packages/core/api/src/handlers/sources.ts b/packages/core/api/src/handlers/sources.ts index 806ea59adc..cacbdd4f01 100644 --- a/packages/core/api/src/handlers/sources.ts +++ b/packages/core/api/src/handlers/sources.ts @@ -6,7 +6,7 @@ import { ExecutorService } from "../services"; export const SourcesHandlers = HttpApiBuilder.group(ExecutorApi, "sources", (handlers) => handlers - .handle("list", ({ path: _path }) => + .handle("list", () => Effect.gen(function* () { const executor = yield* ExecutorService; const sources = yield* executor.sources.list(); @@ -49,7 +49,7 @@ export const SourcesHandlers = HttpApiBuilder.group(ExecutorApi, "sources", (han })); }), ) - .handle("detect", ({ path: _path, payload }) => + .handle("detect", ({ payload }) => Effect.gen(function* () { const executor = yield* ExecutorService; const results = yield* executor.sources.detect(payload.url); diff --git a/packages/core/api/src/handlers/tools.ts b/packages/core/api/src/handlers/tools.ts index 4c7dedca28..99676fe3ca 100644 --- a/packages/core/api/src/handlers/tools.ts +++ b/packages/core/api/src/handlers/tools.ts @@ -6,7 +6,7 @@ import { ExecutorService } from "../services"; export const ToolsHandlers = HttpApiBuilder.group(ExecutorApi, "tools", (handlers) => handlers - .handle("list", ({ path: _path }) => + .handle("list", () => Effect.gen(function* () { const executor = yield* ExecutorService; const tools = yield* executor.tools.list(); diff --git a/packages/plugins/mcp/src/sdk/invoke.ts b/packages/plugins/mcp/src/sdk/invoke.ts index dbff96ef36..5ff11c8cb4 100644 --- a/packages/plugins/mcp/src/sdk/invoke.ts +++ b/packages/plugins/mcp/src/sdk/invoke.ts @@ -317,7 +317,7 @@ export const makeMcpInvoker = (opts: { elicitationHandler, ).pipe( // On failure, invalidate the cached connection and retry once - Effect.catchAll((_err) => + Effect.catchAll(() => Effect.gen(function* () { yield* connectionCache.invalidate(cacheKey); pendingConnectors.set(cacheKey, connector); From bce0a0786d88fbf93b504e4205dc65f6417cf76e Mon Sep 17 00:00:00 2001 From: RhysSullivan <39114868+RhysSullivan@users.noreply.github.com> Date: Fri, 10 Apr 2026 09:05:10 +0000 Subject: [PATCH 3/3] style: format --- apps/cli/src/main.ts | 3 +-- packages/core/execution/src/engine.ts | 4 +--- packages/core/sdk/src/promise-executor.ts | 10 +++++++++- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/apps/cli/src/main.ts b/apps/cli/src/main.ts index 82f9053680..d59f06fe27 100644 --- a/apps/cli/src/main.ts +++ b/apps/cli/src/main.ts @@ -206,8 +206,7 @@ const callCommand = Command.make( } } else { console.log(result.text); - const executionId = (result.structured as Record | undefined) - ?.executionId; + const executionId = (result.structured as Record | undefined)?.executionId; if (executionId) { console.log( `\nTo resume:\n ${cliPrefix} resume --execution-id ${executionId} --action accept`, diff --git a/packages/core/execution/src/engine.ts b/packages/core/execution/src/engine.ts index 0c8d59659a..20350b0da5 100644 --- a/packages/core/execution/src/engine.ts +++ b/packages/core/execution/src/engine.ts @@ -127,9 +127,7 @@ export const formatPausedExecution = ( kind: req._tag === "UrlElicitation" ? "url" : "form", message: req.message, ...(req._tag === "UrlElicitation" ? { url: req.url } : {}), - ...(req._tag === "FormElicitation" - ? { requestedSchema: req.requestedSchema } - : {}), + ...(req._tag === "FormElicitation" ? { requestedSchema: req.requestedSchema } : {}), }, }, }; diff --git a/packages/core/sdk/src/promise-executor.ts b/packages/core/sdk/src/promise-executor.ts index 4e83c54eac..ea40c72e49 100644 --- a/packages/core/sdk/src/promise-executor.ts +++ b/packages/core/sdk/src/promise-executor.ts @@ -476,7 +476,15 @@ const wrapPluginContext = (ctx: EffectPluginContext): PluginContext => ({ }, policies: { list: (scopeId) => run(ctx.policies.list(ScopeId.make(scopeId))), - check: (input) => run(ctx.policies.check(new PolicyCheckInput({ scopeId: ScopeId.make(input.scopeId), toolId: ToolId.make(input.toolId) }))), + check: (input) => + run( + ctx.policies.check( + new PolicyCheckInput({ + scopeId: ScopeId.make(input.scopeId), + toolId: ToolId.make(input.toolId), + }), + ), + ), add: (policy) => run(ctx.policies.add(policy)), remove: (policyId) => run(ctx.policies.remove(PolicyId.make(policyId))), },