@agentforge-ai/cli 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/default/.env.example +11 -0
  2. package/dist/default/dashboard/app/components/DashboardLayout.tsx +245 -0
  3. package/dist/default/dashboard/app/components/ui/badge.tsx +26 -0
  4. package/dist/default/dashboard/app/components/ui/button.tsx +41 -0
  5. package/dist/default/dashboard/app/components/ui/card.tsx +44 -0
  6. package/dist/default/dashboard/app/components/ui/dialog.tsx +66 -0
  7. package/dist/default/dashboard/app/components/ui/input.tsx +21 -0
  8. package/dist/default/dashboard/app/components/ui/label.tsx +18 -0
  9. package/dist/default/dashboard/app/components/ui/select.tsx +75 -0
  10. package/dist/default/dashboard/app/components/ui/sheet.tsx +73 -0
  11. package/dist/default/dashboard/app/components/ui/switch.tsx +34 -0
  12. package/dist/default/dashboard/app/components/ui/table.tsx +60 -0
  13. package/dist/default/dashboard/app/components/ui/tabs.tsx +50 -0
  14. package/dist/default/dashboard/app/components/ui/tooltip.tsx +23 -0
  15. package/dist/default/dashboard/app/lib/utils.ts +6 -0
  16. package/dist/default/dashboard/app/main.tsx +35 -0
  17. package/dist/default/dashboard/app/routeTree.gen.ts +352 -0
  18. package/dist/default/dashboard/app/routes/__root.tsx +10 -0
  19. package/dist/default/dashboard/app/routes/agents.tsx +255 -0
  20. package/dist/default/dashboard/app/routes/chat.tsx +427 -0
  21. package/dist/default/dashboard/app/routes/connections.tsx +413 -0
  22. package/dist/default/dashboard/app/routes/cron.tsx +322 -0
  23. package/dist/default/dashboard/app/routes/files.tsx +203 -0
  24. package/dist/default/dashboard/app/routes/index.tsx +141 -0
  25. package/dist/default/dashboard/app/routes/projects.tsx +254 -0
  26. package/dist/default/dashboard/app/routes/sessions.tsx +272 -0
  27. package/dist/default/dashboard/app/routes/settings.tsx +583 -0
  28. package/dist/default/dashboard/app/routes/skills.tsx +252 -0
  29. package/dist/default/dashboard/app/routes/usage.tsx +181 -0
  30. package/dist/default/dashboard/app/styles/globals.css +93 -0
  31. package/dist/default/dashboard/index.html +13 -0
  32. package/dist/default/dashboard/package.json +36 -0
  33. package/dist/default/dashboard/postcss.config.js +6 -0
  34. package/dist/default/dashboard/tailwind.config.js +50 -0
  35. package/dist/default/dashboard/tsconfig.json +24 -0
  36. package/dist/default/dashboard/vite.config.ts +16 -0
  37. package/dist/default/package.json +5 -2
  38. package/dist/default/src/agent.ts +42 -2
  39. package/dist/index.js +135 -22
  40. package/dist/index.js.map +1 -1
  41. package/package.json +1 -1
  42. package/templates/default/.env.example +11 -0
  43. package/templates/default/dashboard/app/components/DashboardLayout.tsx +245 -0
  44. package/templates/default/dashboard/app/components/ui/badge.tsx +26 -0
  45. package/templates/default/dashboard/app/components/ui/button.tsx +41 -0
  46. package/templates/default/dashboard/app/components/ui/card.tsx +44 -0
  47. package/templates/default/dashboard/app/components/ui/dialog.tsx +66 -0
  48. package/templates/default/dashboard/app/components/ui/input.tsx +21 -0
  49. package/templates/default/dashboard/app/components/ui/label.tsx +18 -0
  50. package/templates/default/dashboard/app/components/ui/select.tsx +75 -0
  51. package/templates/default/dashboard/app/components/ui/sheet.tsx +73 -0
  52. package/templates/default/dashboard/app/components/ui/switch.tsx +34 -0
  53. package/templates/default/dashboard/app/components/ui/table.tsx +60 -0
  54. package/templates/default/dashboard/app/components/ui/tabs.tsx +50 -0
  55. package/templates/default/dashboard/app/components/ui/tooltip.tsx +23 -0
  56. package/templates/default/dashboard/app/lib/utils.ts +6 -0
  57. package/templates/default/dashboard/app/main.tsx +35 -0
  58. package/templates/default/dashboard/app/routeTree.gen.ts +352 -0
  59. package/templates/default/dashboard/app/routes/__root.tsx +10 -0
  60. package/templates/default/dashboard/app/routes/agents.tsx +255 -0
  61. package/templates/default/dashboard/app/routes/chat.tsx +427 -0
  62. package/templates/default/dashboard/app/routes/connections.tsx +413 -0
  63. package/templates/default/dashboard/app/routes/cron.tsx +322 -0
  64. package/templates/default/dashboard/app/routes/files.tsx +203 -0
  65. package/templates/default/dashboard/app/routes/index.tsx +141 -0
  66. package/templates/default/dashboard/app/routes/projects.tsx +254 -0
  67. package/templates/default/dashboard/app/routes/sessions.tsx +272 -0
  68. package/templates/default/dashboard/app/routes/settings.tsx +583 -0
  69. package/templates/default/dashboard/app/routes/skills.tsx +252 -0
  70. package/templates/default/dashboard/app/routes/usage.tsx +181 -0
  71. package/templates/default/dashboard/app/styles/globals.css +93 -0
  72. package/templates/default/dashboard/index.html +13 -0
  73. package/templates/default/dashboard/package.json +36 -0
  74. package/templates/default/dashboard/postcss.config.js +6 -0
  75. package/templates/default/dashboard/tailwind.config.js +50 -0
  76. package/templates/default/dashboard/tsconfig.json +24 -0
  77. package/templates/default/dashboard/vite.config.ts +16 -0
  78. package/templates/default/package.json +5 -2
  79. package/templates/default/src/agent.ts +42 -2
@@ -0,0 +1,16 @@
1
+ import { defineConfig } from "vite";
2
+ import react from "@vitejs/plugin-react";
3
+ import tsconfigPaths from "vite-tsconfig-paths";
4
+
5
+ export default defineConfig({
6
+ plugins: [react(), tsconfigPaths()],
7
+ build: {
8
+ outDir: "dist",
9
+ sourcemap: true,
10
+ },
11
+ server: {
12
+ port: 3000,
13
+ host: "0.0.0.0",
14
+ allowedHosts: true,
15
+ },
16
+ });
@@ -8,10 +8,13 @@
8
8
  "build": "tsc",
9
9
  "convex:dev": "npx convex dev",
10
10
  "convex:deploy": "npx convex deploy",
11
- "dashboard": "agentforge dashboard"
11
+ "dashboard": "agentforge dashboard",
12
+ "dashboard:install": "cd dashboard && pnpm install",
13
+ "dashboard:dev": "cd dashboard && pnpm dev",
14
+ "dashboard:build": "cd dashboard && pnpm build"
12
15
  },
13
16
  "dependencies": {
14
- "@agentforge-ai/core": "^0.3.2",
17
+ "@agentforge-ai/core": "^0.4.0",
15
18
  "convex": "^1.17.0",
16
19
  "zod": "^3.23.0"
17
20
  },
@@ -1,11 +1,17 @@
1
1
  import { Agent } from '@agentforge-ai/core';
2
+ import { AgentForgeWorkspace } from '@agentforge-ai/core/workspace';
2
3
 
3
4
  /**
4
5
  * AgentForge — Your First Agent
5
6
  *
6
7
  * This starter agent demonstrates how to configure an AI agent with
7
- * AgentForge's multi-provider support. You can use OpenAI, OpenRouter,
8
- * Anthropic, Google, or xAI as your LLM provider.
8
+ * AgentForge's multi-provider support and Mastra Workspace integration.
9
+ *
10
+ * Workspace gives your agent:
11
+ * - Filesystem: Read, write, list, and delete files
12
+ * - Sandbox: Execute shell commands
13
+ * - Skills: Discover and activate reusable instructions
14
+ * - Search: BM25 keyword search over indexed content
9
15
  *
10
16
  * Set your provider and API key in the .env file:
11
17
  * OPENAI_API_KEY=sk-...
@@ -13,6 +19,20 @@ import { Agent } from '@agentforge-ai/core';
13
19
  * ANTHROPIC_API_KEY=sk-ant-...
14
20
  */
15
21
 
22
+ // ─── Workspace Setup ──────────────────────────────────────────────────
23
+ // The workspace provides persistent file storage, command execution,
24
+ // skill discovery, and content search for your agents.
25
+ const workspace = AgentForgeWorkspace.local({
26
+ basePath: './workspace',
27
+ skills: ['/skills'],
28
+ search: true,
29
+ autoIndexPaths: ['/skills'],
30
+ sandbox: true,
31
+ });
32
+
33
+ // Initialize workspace (triggers auto-indexing)
34
+ await workspace.init();
35
+
16
36
  // ─── Main Agent ────────────────────────────────────────────────────────
17
37
  const myAgent = new Agent({
18
38
  id: 'my-first-agent',
@@ -21,6 +41,9 @@ const myAgent = new Agent({
21
41
  You can help users with a variety of tasks.
22
42
  Be concise, accurate, and friendly.
23
43
 
44
+ You have access to a workspace with file management, command execution,
45
+ and skill discovery capabilities. Use them when appropriate.
46
+
24
47
  When you don't know something, say so honestly.
25
48
  When asked about your capabilities, mention that you're powered by AgentForge.`,
26
49
 
@@ -33,8 +56,21 @@ When asked about your capabilities, mention that you're powered by AgentForge.`,
33
56
  model: 'openai:gpt-4o-mini',
34
57
  });
35
58
 
59
+ export { workspace };
36
60
  export default myAgent;
37
61
 
62
+ // ─── Example: Cloud Workspace (Cloudflare R2) ─────────────────────────
63
+ // For production deployment on Cloudflare, use a cloud workspace:
64
+ //
65
+ // const cloudWorkspace = AgentForgeWorkspace.cloud({
66
+ // bucket: 'my-agent-files',
67
+ // region: 'auto',
68
+ // endpoint: process.env.R2_ENDPOINT,
69
+ // accessKeyId: process.env.R2_ACCESS_KEY_ID,
70
+ // secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
71
+ // skills: ['/skills'],
72
+ // });
73
+
38
74
  // ─── Example: Agent with Custom Tools ──────────────────────────────────
39
75
  // import { z } from 'zod';
40
76
  //
@@ -60,3 +96,7 @@ export default myAgent;
60
96
  // ─── Example: Using the Agent ──────────────────────────────────────────
61
97
  // const response = await myAgent.generate('Hello, what can you do?');
62
98
  // console.log(response.text);
99
+ //
100
+ // ─── Example: Searching Workspace Content ──────────────────────────────
101
+ // const results = await workspace.search('code review');
102
+ // console.log(results);
package/dist/index.js CHANGED
@@ -19,15 +19,25 @@ async function createProject(projectName, options) {
19
19
  console.log(`
20
20
  \u{1F528} Creating AgentForge project: ${projectName}
21
21
  `);
22
- const templateDir = path.resolve(
23
- __dirname,
24
- "..",
25
- // from dist/commands to dist
26
- "templates",
27
- options.template
28
- );
29
- if (!await fs.pathExists(templateDir)) {
22
+ const searchDirs = [
23
+ path.resolve(__dirname, options.template),
24
+ // dist/default (built)
25
+ path.resolve(__dirname, "..", "templates", options.template),
26
+ // packages/cli/templates/default (dev)
27
+ path.resolve(__dirname, "..", "..", "templates", options.template)
28
+ // fallback
29
+ ];
30
+ let templateDir = "";
31
+ for (const dir of searchDirs) {
32
+ if (await fs.pathExists(path.join(dir, "package.json"))) {
33
+ templateDir = dir;
34
+ break;
35
+ }
36
+ }
37
+ if (!templateDir) {
30
38
  console.error(`Error: Template "${options.template}" not found.`);
39
+ console.error(`Searched in:`);
40
+ searchDirs.forEach((d) => console.error(` - ${d}`));
31
41
  process.exit(1);
32
42
  }
33
43
  await fs.copy(templateDir, targetDir);
@@ -37,6 +47,12 @@ async function createProject(projectName, options) {
37
47
  pkg2.name = projectName;
38
48
  await fs.writeJson(pkgPath, pkg2, { spaces: 2 });
39
49
  }
50
+ const dashPkgPath = path.join(targetDir, "dashboard", "package.json");
51
+ if (await fs.pathExists(dashPkgPath)) {
52
+ const dashPkg = await fs.readJson(dashPkgPath);
53
+ dashPkg.name = `${projectName}-dashboard`;
54
+ await fs.writeJson(dashPkgPath, dashPkg, { spaces: 2 });
55
+ }
40
56
  console.log(` \u2705 Project scaffolded at ./${projectName}`);
41
57
  console.log(`
42
58
  \u{1F4E6} Installing dependencies...
@@ -54,12 +70,58 @@ async function createProject(projectName, options) {
54
70
  \u26A0\uFE0F Could not install dependencies. Run "cd ${projectName} && pnpm install" manually.`
55
71
  );
56
72
  }
73
+ const dashDir = path.join(targetDir, "dashboard");
74
+ if (await fs.pathExists(dashDir)) {
75
+ console.log(`
76
+ \u{1F4E6} Installing dashboard dependencies...
77
+ `);
78
+ try {
79
+ execSync("pnpm install", {
80
+ cwd: dashDir,
81
+ stdio: "inherit"
82
+ });
83
+ console.log(`
84
+ \u2705 Dashboard dependencies installed`);
85
+ } catch {
86
+ console.warn(
87
+ `
88
+ \u26A0\uFE0F Could not install dashboard dependencies. Run "cd ${projectName}/dashboard && pnpm install" manually.`
89
+ );
90
+ }
91
+ }
92
+ console.log(`
93
+ \u26A1 Initializing Convex...
94
+ `);
95
+ try {
96
+ execSync("npx convex dev --once", {
97
+ cwd: targetDir,
98
+ stdio: "inherit"
99
+ });
100
+ console.log(`
101
+ \u2705 Convex initialized`);
102
+ } catch {
103
+ console.warn(
104
+ `
105
+ \u26A0\uFE0F Convex initialization skipped. Run "npx convex dev" to set up your backend.`
106
+ );
107
+ }
57
108
  console.log(`
58
109
  \u{1F389} AgentForge project "${projectName}" created successfully!
59
110
 
60
111
  Next steps:
61
112
  cd ${projectName}
62
- agentforge run
113
+
114
+ # Start the Convex backend
115
+ npx convex dev
116
+
117
+ # In another terminal, launch the dashboard
118
+ agentforge dashboard
119
+
120
+ # Or chat with your agent from the CLI
121
+ agentforge chat
122
+
123
+ # Check system status
124
+ agentforge status
63
125
 
64
126
  Documentation: https://github.com/Agentic-Engineering-Agency/agentforge
65
127
  `);
@@ -1545,6 +1607,7 @@ function registerStatusCommand(program2) {
1545
1607
  checks["Project Root"] = fs8.existsSync(path8.join(cwd, "package.json")) ? "\u2714 Found" : "\u2716 Not found";
1546
1608
  checks["Convex Dir"] = fs8.existsSync(path8.join(cwd, "convex")) ? "\u2714 Found" : "\u2716 Not found";
1547
1609
  checks["Skills Dir"] = fs8.existsSync(path8.join(cwd, "skills")) ? "\u2714 Found" : "\u2716 Not configured";
1610
+ checks["Dashboard Dir"] = fs8.existsSync(path8.join(cwd, "dashboard")) ? "\u2714 Found" : "\u2716 Not found";
1548
1611
  checks["Env Config"] = fs8.existsSync(path8.join(cwd, ".env.local")) || fs8.existsSync(path8.join(cwd, ".env")) ? "\u2714 Found" : "\u2716 Not found";
1549
1612
  try {
1550
1613
  const client = createClient();
@@ -1577,24 +1640,75 @@ function registerStatusCommand(program2) {
1577
1640
  checks["LLM Provider"] = provider !== "Not configured" ? `\u2714 ${provider}` : "\u2716 Not configured";
1578
1641
  details(checks);
1579
1642
  });
1580
- program2.command("dashboard").description("Launch the web dashboard").option("-p, --port <port>", "Port for the dashboard", "3000").action(async (opts) => {
1643
+ program2.command("dashboard").description("Launch the web dashboard").option("-p, --port <port>", "Port for the dashboard", "3000").option("--install", "Install dashboard dependencies before starting").action(async (opts) => {
1581
1644
  const cwd = process.cwd();
1582
- const webDir = path8.join(cwd, "node_modules", "@agentforge-ai", "web");
1583
- const localWebDir = path8.join(cwd, "packages", "web");
1645
+ const searchPaths = [
1646
+ path8.join(cwd, "dashboard"),
1647
+ // 1. Bundled in project (agentforge create)
1648
+ path8.join(cwd, "packages", "web"),
1649
+ // 2. Monorepo structure
1650
+ path8.join(cwd, "node_modules", "@agentforge-ai", "web")
1651
+ // 3. Installed as dependency
1652
+ ];
1584
1653
  let dashDir = "";
1585
- if (fs8.existsSync(localWebDir)) {
1586
- dashDir = localWebDir;
1587
- } else if (fs8.existsSync(webDir)) {
1588
- dashDir = webDir;
1589
- } else {
1590
- info("Dashboard not found locally. Starting from the built-in dashboard...");
1591
- info("Install the dashboard: pnpm add @agentforge-ai/web");
1592
- info("Or clone the repo: git clone https://github.com/Agentic-Engineering-Agency/agentforge");
1654
+ for (const p of searchPaths) {
1655
+ if (fs8.existsSync(path8.join(p, "package.json"))) {
1656
+ dashDir = p;
1657
+ break;
1658
+ }
1659
+ }
1660
+ if (!dashDir) {
1661
+ error("Dashboard not found!");
1662
+ console.log();
1663
+ info("The dashboard should be in your project's ./dashboard/ directory.");
1664
+ info("If you created this project with an older version of AgentForge,");
1665
+ info("you can add it manually:");
1666
+ console.log();
1667
+ console.log(` ${colors.cyan}# Option 1: Recreate the project${colors.reset}`);
1668
+ console.log(` agentforge create my-project`);
1669
+ console.log();
1670
+ console.log(` ${colors.cyan}# Option 2: Clone the dashboard from the repo${colors.reset}`);
1671
+ console.log(` git clone https://github.com/Agentic-Engineering-Agency/agentforge /tmp/af`);
1672
+ console.log(` cp -r /tmp/af/packages/web ./dashboard`);
1673
+ console.log(` cd dashboard && pnpm install`);
1674
+ console.log();
1593
1675
  return;
1594
1676
  }
1677
+ const nodeModulesExists = fs8.existsSync(path8.join(dashDir, "node_modules"));
1678
+ if (!nodeModulesExists || opts.install) {
1679
+ header("AgentForge Dashboard \u2014 Installing Dependencies");
1680
+ info(`Installing in ${path8.relative(cwd, dashDir) || "."}...`);
1681
+ console.log();
1682
+ const installChild = spawn2("pnpm", ["install"], {
1683
+ cwd: dashDir,
1684
+ stdio: "inherit",
1685
+ shell: true
1686
+ });
1687
+ await new Promise((resolve2, reject) => {
1688
+ installChild.on("close", (code) => {
1689
+ if (code === 0) resolve2();
1690
+ else reject(new Error(`pnpm install exited with code ${code}`));
1691
+ });
1692
+ installChild.on("error", reject);
1693
+ });
1694
+ console.log();
1695
+ success("Dependencies installed.");
1696
+ console.log();
1697
+ }
1698
+ const envPath = path8.join(cwd, ".env.local");
1699
+ if (fs8.existsSync(envPath)) {
1700
+ const envContent = fs8.readFileSync(envPath, "utf-8");
1701
+ const convexUrlMatch = envContent.match(/CONVEX_URL=(.+)/);
1702
+ if (convexUrlMatch) {
1703
+ const dashEnvPath = path8.join(dashDir, ".env.local");
1704
+ const dashEnvContent = `VITE_CONVEX_URL=${convexUrlMatch[1].trim()}
1705
+ `;
1706
+ fs8.writeFileSync(dashEnvPath, dashEnvContent);
1707
+ }
1708
+ }
1595
1709
  header("AgentForge Dashboard");
1596
1710
  info(`Starting dashboard on port ${opts.port}...`);
1597
- info(`Open http://localhost:${opts.port} in your browser.`);
1711
+ info(`Open ${colors.cyan}http://localhost:${opts.port}${colors.reset} in your browser.`);
1598
1712
  console.log();
1599
1713
  const child = spawn2("pnpm", ["dev", "--port", opts.port], {
1600
1714
  cwd: dashDir,
@@ -1653,7 +1767,6 @@ function registerStatusCommand(program2) {
1653
1767
  });
1654
1768
  console.log();
1655
1769
  const rl = readline9.createInterface({ input: process.stdin, output: process.stdout });
1656
- const { createInterface } = await import("readline");
1657
1770
  const answer = await new Promise((r) => rl.question("Resume pending tasks? (y/N): ", (a) => {
1658
1771
  rl.close();
1659
1772
  r(a.trim());