refactor(cli): convert agent / providers / mcp to effectCmd (#25525)
This commit is contained in:
@@ -9,8 +9,7 @@ import path from "path"
|
|||||||
import fs from "fs/promises"
|
import fs from "fs/promises"
|
||||||
import { Filesystem } from "@/util/filesystem"
|
import { Filesystem } from "@/util/filesystem"
|
||||||
import matter from "gray-matter"
|
import matter from "gray-matter"
|
||||||
import { Instance } from "../../project/instance"
|
import { InstanceRef } from "@/effect/instance-ref"
|
||||||
import { WithInstance } from "../../project/with-instance"
|
|
||||||
import { EOL } from "os"
|
import { EOL } from "os"
|
||||||
import type { Argv } from "yargs"
|
import type { Argv } from "yargs"
|
||||||
import { Effect } from "effect"
|
import { Effect } from "effect"
|
||||||
@@ -35,7 +34,7 @@ const AVAILABLE_PERMISSIONS = [
|
|||||||
"skill",
|
"skill",
|
||||||
]
|
]
|
||||||
|
|
||||||
const AgentCreateCommand = cmd({
|
const AgentCreateCommand = effectCmd({
|
||||||
command: "create",
|
command: "create",
|
||||||
describe: "create a new agent",
|
describe: "create a new agent",
|
||||||
builder: (yargs: Argv) =>
|
builder: (yargs: Argv) =>
|
||||||
@@ -63,10 +62,11 @@ const AgentCreateCommand = cmd({
|
|||||||
alias: ["m"],
|
alias: ["m"],
|
||||||
describe: "model to use in the format of provider/model",
|
describe: "model to use in the format of provider/model",
|
||||||
}),
|
}),
|
||||||
async handler(args) {
|
handler: Effect.fn("Cli.agent.create")(function* (args) {
|
||||||
await WithInstance.provide({
|
const maybeCtx = yield* InstanceRef
|
||||||
directory: process.cwd(),
|
if (!maybeCtx) return yield* Effect.die("InstanceRef not provided")
|
||||||
async fn() {
|
const ctx = maybeCtx
|
||||||
|
yield* Effect.promise(async () => {
|
||||||
const cliPath = args.path
|
const cliPath = args.path
|
||||||
const cliDescription = args.description
|
const cliDescription = args.description
|
||||||
const cliMode = args.mode as AgentMode | undefined
|
const cliMode = args.mode as AgentMode | undefined
|
||||||
@@ -79,7 +79,7 @@ const AgentCreateCommand = cmd({
|
|||||||
prompts.intro("Create agent")
|
prompts.intro("Create agent")
|
||||||
}
|
}
|
||||||
|
|
||||||
const project = Instance.project
|
const project = ctx.project
|
||||||
|
|
||||||
// Determine scope/path
|
// Determine scope/path
|
||||||
let targetPath: string
|
let targetPath: string
|
||||||
@@ -94,7 +94,7 @@ const AgentCreateCommand = cmd({
|
|||||||
{
|
{
|
||||||
label: "Current project",
|
label: "Current project",
|
||||||
value: "project" as const,
|
value: "project" as const,
|
||||||
hint: Instance.worktree,
|
hint: ctx.worktree,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Global",
|
label: "Global",
|
||||||
@@ -107,7 +107,7 @@ const AgentCreateCommand = cmd({
|
|||||||
scope = scopeResult
|
scope = scopeResult
|
||||||
}
|
}
|
||||||
targetPath = path.join(
|
targetPath = path.join(
|
||||||
scope === "global" ? Global.Path.config : path.join(Instance.worktree, ".opencode"),
|
scope === "global" ? Global.Path.config : path.join(ctx.worktree, ".opencode"),
|
||||||
"agent",
|
"agent",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -230,9 +230,8 @@ const AgentCreateCommand = cmd({
|
|||||||
prompts.log.success(`Agent created: ${filePath}`)
|
prompts.log.success(`Agent created: ${filePath}`)
|
||||||
prompts.outro("Done")
|
prompts.outro("Done")
|
||||||
}
|
}
|
||||||
},
|
|
||||||
})
|
})
|
||||||
},
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
const AgentListCommand = effectCmd({
|
const AgentListCommand = effectCmd({
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ import { McpAuth } from "../../mcp/auth"
|
|||||||
import { McpOAuthProvider } from "../../mcp/oauth-provider"
|
import { McpOAuthProvider } from "../../mcp/oauth-provider"
|
||||||
import { Config } from "@/config/config"
|
import { Config } from "@/config/config"
|
||||||
import { ConfigMCP } from "../../config/mcp"
|
import { ConfigMCP } from "../../config/mcp"
|
||||||
import { Instance } from "../../project/instance"
|
import { InstanceRef } from "@/effect/instance-ref"
|
||||||
import { WithInstance } from "../../project/with-instance"
|
|
||||||
import { Installation } from "../../installation"
|
import { Installation } from "../../installation"
|
||||||
import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
@@ -433,21 +432,22 @@ async function addMcpToConfig(name: string, mcpConfig: ConfigMCP.Info, configPat
|
|||||||
return configPath
|
return configPath
|
||||||
}
|
}
|
||||||
|
|
||||||
export const McpAddCommand = cmd({
|
export const McpAddCommand = effectCmd({
|
||||||
command: "add",
|
command: "add",
|
||||||
describe: "add an MCP server",
|
describe: "add an MCP server",
|
||||||
async handler() {
|
handler: Effect.fn("Cli.mcp.add")(function* () {
|
||||||
await WithInstance.provide({
|
const maybeCtx = yield* InstanceRef
|
||||||
directory: process.cwd(),
|
if (!maybeCtx) return yield* Effect.die("InstanceRef not provided")
|
||||||
async fn() {
|
const ctx = maybeCtx
|
||||||
|
yield* Effect.promise(async () => {
|
||||||
UI.empty()
|
UI.empty()
|
||||||
prompts.intro("Add MCP server")
|
prompts.intro("Add MCP server")
|
||||||
|
|
||||||
const project = Instance.project
|
const project = ctx.project
|
||||||
|
|
||||||
// Resolve config paths eagerly for hints
|
// Resolve config paths eagerly for hints
|
||||||
const [projectConfigPath, globalConfigPath] = await Promise.all([
|
const [projectConfigPath, globalConfigPath] = await Promise.all([
|
||||||
resolveConfigPath(Instance.worktree),
|
resolveConfigPath(ctx.worktree),
|
||||||
resolveConfigPath(Global.Path.config, true),
|
resolveConfigPath(Global.Path.config, true),
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -592,12 +592,11 @@ export const McpAddCommand = cmd({
|
|||||||
}
|
}
|
||||||
|
|
||||||
prompts.outro("MCP server added successfully")
|
prompts.outro("MCP server added successfully")
|
||||||
},
|
|
||||||
})
|
})
|
||||||
},
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const McpDebugCommand = cmd({
|
export const McpDebugCommand = effectCmd({
|
||||||
command: "debug <name>",
|
command: "debug <name>",
|
||||||
describe: "debug OAuth connection for an MCP server",
|
describe: "debug OAuth connection for an MCP server",
|
||||||
builder: (yargs) =>
|
builder: (yargs) =>
|
||||||
@@ -606,10 +605,8 @@ export const McpDebugCommand = cmd({
|
|||||||
type: "string",
|
type: "string",
|
||||||
demandOption: true,
|
demandOption: true,
|
||||||
}),
|
}),
|
||||||
async handler(args) {
|
handler: Effect.fn("Cli.mcp.debug")(function* (args) {
|
||||||
await WithInstance.provide({
|
yield* Effect.promise(async () => {
|
||||||
directory: process.cwd(),
|
|
||||||
async fn() {
|
|
||||||
UI.empty()
|
UI.empty()
|
||||||
prompts.intro("MCP OAuth Debug")
|
prompts.intro("MCP OAuth Debug")
|
||||||
|
|
||||||
@@ -781,7 +778,6 @@ export const McpDebugCommand = cmd({
|
|||||||
}
|
}
|
||||||
|
|
||||||
prompts.outro("Debug complete")
|
prompts.outro("Debug complete")
|
||||||
},
|
|
||||||
})
|
})
|
||||||
},
|
}),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Auth } from "../../auth"
|
import { Auth } from "../../auth"
|
||||||
import { AppRuntime } from "../../effect/app-runtime"
|
import { AppRuntime } from "../../effect/app-runtime"
|
||||||
import { cmd } from "./cmd"
|
import { cmd } from "./cmd"
|
||||||
|
import { effectCmd } from "../effect-cmd"
|
||||||
import * as prompts from "@clack/prompts"
|
import * as prompts from "@clack/prompts"
|
||||||
import { UI } from "../ui"
|
import { UI } from "../ui"
|
||||||
import { ModelsDev } from "@/provider/models"
|
import { ModelsDev } from "@/provider/models"
|
||||||
@@ -13,7 +14,6 @@ import os from "os"
|
|||||||
import { Config } from "@/config/config"
|
import { Config } from "@/config/config"
|
||||||
import { Global } from "@opencode-ai/core/global"
|
import { Global } from "@opencode-ai/core/global"
|
||||||
import { Plugin } from "../../plugin"
|
import { Plugin } from "../../plugin"
|
||||||
import { WithInstance } from "../../project/with-instance"
|
|
||||||
import type { Hooks } from "@opencode-ai/plugin"
|
import type { Hooks } from "@opencode-ai/plugin"
|
||||||
import { Process } from "@/util/process"
|
import { Process } from "@/util/process"
|
||||||
import { text } from "node:stream/consumers"
|
import { text } from "node:stream/consumers"
|
||||||
@@ -232,11 +232,14 @@ export const ProvidersCommand = cmd({
|
|||||||
async handler() {},
|
async handler() {},
|
||||||
})
|
})
|
||||||
|
|
||||||
export const ProvidersListCommand = cmd({
|
export const ProvidersListCommand = effectCmd({
|
||||||
command: "list",
|
command: "list",
|
||||||
aliases: ["ls"],
|
aliases: ["ls"],
|
||||||
describe: "list providers and credentials",
|
describe: "list providers and credentials",
|
||||||
async handler(_args) {
|
// Lists global credentials + provider env vars; no project instance needed.
|
||||||
|
instance: false,
|
||||||
|
handler: Effect.fn("Cli.providers.list")(function* (_args) {
|
||||||
|
yield* Effect.promise(async () => {
|
||||||
UI.empty()
|
UI.empty()
|
||||||
const authPath = path.join(Global.Path.data, "auth.json")
|
const authPath = path.join(Global.Path.data, "auth.json")
|
||||||
const homedir = os.homedir()
|
const homedir = os.homedir()
|
||||||
@@ -280,10 +283,11 @@ export const ProvidersListCommand = cmd({
|
|||||||
|
|
||||||
prompts.outro(`${activeEnvVars.length} environment variable` + (activeEnvVars.length === 1 ? "" : "s"))
|
prompts.outro(`${activeEnvVars.length} environment variable` + (activeEnvVars.length === 1 ? "" : "s"))
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const ProvidersLoginCommand = cmd({
|
export const ProvidersLoginCommand = effectCmd({
|
||||||
command: "login [url]",
|
command: "login [url]",
|
||||||
describe: "log in to a provider",
|
describe: "log in to a provider",
|
||||||
builder: (yargs) =>
|
builder: (yargs) =>
|
||||||
@@ -302,10 +306,8 @@ export const ProvidersLoginCommand = cmd({
|
|||||||
describe: "login method label (skips method selection)",
|
describe: "login method label (skips method selection)",
|
||||||
type: "string",
|
type: "string",
|
||||||
}),
|
}),
|
||||||
async handler(args) {
|
handler: Effect.fn("Cli.providers.login")(function* (args) {
|
||||||
await WithInstance.provide({
|
yield* Effect.promise(async () => {
|
||||||
directory: process.cwd(),
|
|
||||||
async fn() {
|
|
||||||
UI.empty()
|
UI.empty()
|
||||||
prompts.intro("Add credential")
|
prompts.intro("Add credential")
|
||||||
if (args.url) {
|
if (args.url) {
|
||||||
@@ -487,15 +489,17 @@ export const ProvidersLoginCommand = cmd({
|
|||||||
})
|
})
|
||||||
|
|
||||||
prompts.outro("Done")
|
prompts.outro("Done")
|
||||||
},
|
|
||||||
})
|
})
|
||||||
},
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const ProvidersLogoutCommand = cmd({
|
export const ProvidersLogoutCommand = effectCmd({
|
||||||
command: "logout",
|
command: "logout",
|
||||||
describe: "log out from a configured provider",
|
describe: "log out from a configured provider",
|
||||||
async handler(_args) {
|
// Removes a global auth credential; no project instance needed.
|
||||||
|
instance: false,
|
||||||
|
handler: Effect.fn("Cli.providers.logout")(function* (_args) {
|
||||||
|
yield* Effect.promise(async () => {
|
||||||
UI.empty()
|
UI.empty()
|
||||||
const credentials: Array<[string, Auth.Info]> = await AppRuntime.runPromise(
|
const credentials: Array<[string, Auth.Info]> = await AppRuntime.runPromise(
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
@@ -525,5 +529,6 @@ export const ProvidersLogoutCommand = cmd({
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
prompts.outro("Logout successful")
|
prompts.outro("Logout successful")
|
||||||
},
|
})
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user