Skip to content

Commit 4526958

Browse files
committed
wip
Signed-off-by: Tyler Slaton <[email protected]>
1 parent 2554a8d commit 4526958

File tree

8 files changed

+381
-25
lines changed

8 files changed

+381
-25
lines changed

typescript-sdk/apps/client-cli-example/package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,30 @@
99
"clean": "rm -rf dist"
1010
},
1111
"dependencies": {
12+
"@ag-ui/agno": "workspace:*",
1213
"@ag-ui/client": "workspace:*",
1314
"@ag-ui/core": "workspace:*",
15+
"@ag-ui/crewai": "workspace:*",
16+
"@ag-ui/langgraph": "workspace:*",
17+
"@ag-ui/llamaindex": "workspace:*",
1418
"@ag-ui/mastra": "workspace:*",
19+
"@ag-ui/pydantic-ai": "workspace:*",
20+
"@ag-ui/vercel-ai-sdk": "workspace:*",
1521
"@ai-sdk/openai": "^1.3.22",
1622
"@mastra/client-js": "^0.10.9",
1723
"@mastra/core": "^0.10.10",
1824
"@mastra/libsql": "^0.11.0",
1925
"@mastra/loggers": "^0.10.3",
2026
"@mastra/memory": "^0.11.1",
27+
"inquirer": "^12.6.3",
2128
"open": "^10.1.2",
29+
"yargs": "^18.0.0",
2230
"zod": "^3.22.4"
2331
},
2432
"devDependencies": {
33+
"@types/inquirer": "^9.0.8",
2534
"@types/node": "^20",
35+
"@types/yargs": "^17.0.33",
2636
"tsx": "^4.7.0",
2737
"typescript": "^5"
2838
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { agentRegistry } from "./registry";
2+
import yargs from "yargs";
3+
import { hideBin } from "yargs/helpers";
4+
import inquirer from "inquirer";
5+
6+
export async function loadAgentFromCLI() {
7+
// 1. Parse CLI args
8+
const argv = yargs(hideBin(process.argv))
9+
.option("agent", { type: "string", describe: "Agent/framework to use" })
10+
// Do not add all possible config fields as yargs options; we'll check argv directly
11+
.help()
12+
.parseSync();
13+
14+
// 2. Determine agent type
15+
let agentType = argv.agent;
16+
if (!agentType) {
17+
agentType = (
18+
await inquirer.prompt([
19+
{
20+
type: "list",
21+
name: "agentType",
22+
message: "Select an agent/framework:",
23+
choices: Object.keys(agentRegistry).map((key) => ({
24+
name: agentRegistry[key].label,
25+
value: key,
26+
})),
27+
},
28+
])
29+
).agentType;
30+
}
31+
32+
const agentEntry = agentRegistry[agentType as keyof typeof agentRegistry];
33+
if (!agentEntry) throw new Error(`Unknown agent type: ${agentType}`);
34+
35+
// 3. Gather config (from CLI args or prompt for missing)
36+
const config: Record<string, any> = {};
37+
for (const field of agentEntry.required) {
38+
if (argv[field]) {
39+
config[field] = argv[field];
40+
} else {
41+
config[field] = (
42+
await inquirer.prompt([
43+
{ type: "input", name: field, message: `Enter value for ${field}:` },
44+
])
45+
)[field];
46+
}
47+
}
48+
// Optionally gather optional fields if provided via CLI
49+
if (agentEntry.optional) {
50+
for (const field of agentEntry.optional) {
51+
if (argv[field]) {
52+
config[field] = argv[field];
53+
}
54+
}
55+
}
56+
57+
// 4. Instantiate agent
58+
const agent = new agentEntry.AgentClass(config);
59+
return agent;
60+
}

typescript-sdk/apps/client-cli-example/src/agent.ts renamed to typescript-sdk/apps/client-cli-example/src/agents/mastraLocal/index.ts

File renamed without changes.

typescript-sdk/apps/client-cli-example/src/tools/browser.tool.ts renamed to typescript-sdk/apps/client-cli-example/src/agents/mastraLocal/tools/browser.tool.ts

File renamed without changes.

typescript-sdk/apps/client-cli-example/src/tools/weather.tool.ts renamed to typescript-sdk/apps/client-cli-example/src/agents/mastraLocal/tools/weather.tool.ts

File renamed without changes.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { LangGraphAgent } from "@ag-ui/langgraph";
2+
import { CrewAIAgent } from "@ag-ui/crewai";
3+
import { AgnoAgent } from "@ag-ui/agno";
4+
import { LlamaIndexAgent } from "@ag-ui/llamaindex";
5+
import { MastraAgent } from "@ag-ui/mastra";
6+
import { PydanticAIAgent } from "@ag-ui/pydantic-ai";
7+
// import { VercelAISDKAgent } from "@ag-ui/vercel-ai-sdk";
8+
9+
// Type for agent registry entries
10+
export interface AgentRegistryEntry {
11+
label: string;
12+
AgentClass: any;
13+
required: string[];
14+
optional?: string[];
15+
description: string;
16+
}
17+
18+
export const agentRegistry: Record<string, AgentRegistryEntry> = {
19+
langgraph: {
20+
label: "LangGraph",
21+
AgentClass: LangGraphAgent,
22+
required: ["graphId", "deploymentUrl"],
23+
optional: ["langsmithApiKey"],
24+
description: "Connects to a LangGraph deployment.",
25+
},
26+
crewai: {
27+
label: "CrewAI",
28+
AgentClass: CrewAIAgent,
29+
required: ["url"],
30+
optional: ["headers"],
31+
description: "Connects to a CrewAI FastAPI server.",
32+
},
33+
agno: {
34+
label: "Agno",
35+
AgentClass: AgnoAgent,
36+
required: ["url"],
37+
optional: ["headers"],
38+
description: "Connects to an Agno agent server.",
39+
},
40+
llamaindex: {
41+
label: "LlamaIndex",
42+
AgentClass: LlamaIndexAgent,
43+
required: ["url"],
44+
optional: ["headers"],
45+
description: "Connects to a LlamaIndex FastAPI server.",
46+
},
47+
mastra: {
48+
label: "Mastra",
49+
AgentClass: MastraAgent,
50+
required: ["agent"],
51+
optional: ["resourceId"],
52+
description: "Connects to a local or remote Mastra agent.",
53+
},
54+
pydanticai: {
55+
label: "PydanticAI",
56+
AgentClass: PydanticAIAgent,
57+
required: ["model"],
58+
optional: ["maxSteps", "toolChoice"],
59+
description: "Connects to a PydanticAI model.",
60+
},
61+
// vercelai: {
62+
// label: "Vercel AI SDK",
63+
// AgentClass: VercelAISDKAgent,
64+
// required: ["model"],
65+
// optional: ["maxSteps", "toolChoice"],
66+
// description: "Connects to a Vercel AI SDK model.",
67+
// },
68+
};

typescript-sdk/apps/client-cli-example/src/index.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import * as readline from "readline";
2-
import { agent } from "./agent";
32
import { randomUUID } from "node:crypto";
3+
import { loadAgentFromCLI } from "./agents/loadAgent";
4+
import { AbstractAgent } from "@ag-ui/client";
45

5-
const rl = readline.createInterface({
6-
input: process.stdin,
7-
output: process.stdout,
8-
});
6+
async function chatLoop(agent: AbstractAgent) {
7+
const rl = readline.createInterface({
8+
input: process.stdin,
9+
output: process.stdout,
10+
});
911

10-
async function chatLoop() {
1112
console.log("🤖 AG-UI chat started! Type your messages and press Enter. Press Ctrl+D to quit.\n");
1213

1314
return new Promise<void>((resolve) => {
@@ -75,7 +76,8 @@ async function chatLoop() {
7576
}
7677

7778
async function main() {
78-
await chatLoop();
79+
const agent = await loadAgentFromCLI();
80+
await chatLoop(agent);
7981
}
8082

81-
main().catch(console.error);
83+
main();

0 commit comments

Comments
 (0)