Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions src/commands/do.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { Command, Option } from "commander";

Check failure on line 1 in src/commands/do.ts

View workflow job for this annotation

GitHub Actions / build

Run autofix to sort these imports!
import { z } from "zod";
import axios from "axios";

import { handleError } from "@zetachain/toolkit/utils";

const DEFAULT_API_URL = "https://docs-v2-git-mcp-server.zetachain.app/api/mcp";

const doOptionsSchema = z.object({
instruction: z.string().min(1),
model: z.string().default("gpt-4o"),
apiUrl: z.string().url().default(DEFAULT_API_URL),

Check failure on line 12 in src/commands/do.ts

View workflow job for this annotation

GitHub Actions / build

Expected object keys to be in ascending order. 'apiUrl' should be before 'model'
raw: z.boolean().default(false),
});

type DoOptions = z.infer<typeof doOptionsSchema>;

const main = async (options: DoOptions) => {
try {
const response = await axios.post(
options.apiUrl,
{ prompt: options.instruction, model: options.model },

Check failure on line 22 in src/commands/do.ts

View workflow job for this annotation

GitHub Actions / build

Expected object keys to be in ascending order. 'model' should be before 'prompt'
{ headers: { "Content-Type": "application/json" }, timeout: 120000 }

Check failure on line 23 in src/commands/do.ts

View workflow job for this annotation

GitHub Actions / build

Insert `,`
);

const data = response.data;

if (options.raw) {
// eslint-disable-next-line no-console
console.log(
typeof data === "string" ? data : JSON.stringify(data, null, 2)

Check failure on line 31 in src/commands/do.ts

View workflow job for this annotation

GitHub Actions / build

Insert `,`
);
return;
}

if (typeof data === "string") {
// eslint-disable-next-line no-console
console.log(data);
return;
}

if (
data &&
typeof data === "object" &&
Array.isArray((data as any).content)

Check failure on line 45 in src/commands/do.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type
) {
const content = (data as any).content as Array<any>;

Check failure on line 47 in src/commands/do.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type

Check failure on line 47 in src/commands/do.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type
const lines = content
.map((c) => {
if (typeof c === "string") return c;
if (c && typeof c === "object") {
if (
(c as any).type === "text" &&

Check failure on line 53 in src/commands/do.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type
typeof (c as any).text === "string"

Check failure on line 54 in src/commands/do.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type
)
return (c as any).text;
if (typeof (c as any).text === "string") return (c as any).text;
}
return undefined;
})
.filter((v): v is string => Boolean(v));

if (lines.length > 0) {
// eslint-disable-next-line no-console
console.log(lines.join("\n"));
return;
}
}

// Fallback to JSON
// eslint-disable-next-line no-console
console.log(JSON.stringify(data, null, 2));
} catch (error) {
handleError({
context: "Error executing AI command",
error,
shouldThrow: false,
});
}
};

export const doCommand = new Command()
.name("do")
.summary("Natural-language command via ZetaChain Docs MCP route")
.argument("<instruction...>", "What you want to do, in natural language")
.addOption(
new Option("--model <model>", "Model name for the server route").default(
"gpt-4o"
)
)
.addOption(
new Option("--api-url <url>", "MCP API route URL").default(DEFAULT_API_URL)
)
.addOption(new Option("--raw", "Print raw response body").default(false))
.action(async (instructionParts: string[], options: any) => {
const parsed = doOptionsSchema.safeParse({
instruction: instructionParts.join(" "),
model: options.model,
apiUrl: options.apiUrl,
raw: options.raw,
});

if (!parsed.success) {
handleError({
context: "Invalid options for do command",
error: parsed.error,
shouldThrow: false,
});
return;
}

await main(parsed.data);
});
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Command } from "commander";

import { setupAnalytics } from "./analytics";
import { askCommand } from "./commands/ask";
import { doCommand } from "./commands/do";
import { docsCommand } from "./commands/docs";
import { newCommand } from "./commands/new";
import config from "./config.json";
Expand All @@ -41,6 +42,7 @@ program.addCommand(bitcoinCommand);
program.addCommand(localnetCommand);
program.addCommand(docsCommand);
program.addCommand(askCommand);
program.addCommand(doCommand);

setupAnalytics(program);

Expand Down
Loading