@agentforge-ai/cli 0.4.2 → 0.5.0

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 (67) hide show
  1. package/dist/default/README.md +81 -81
  2. package/dist/default/convex/agents.ts +204 -0
  3. package/dist/default/convex/apiKeys.ts +133 -0
  4. package/dist/default/convex/cronJobs.ts +224 -0
  5. package/dist/default/convex/files.ts +103 -0
  6. package/dist/default/convex/folders.ts +110 -0
  7. package/dist/default/convex/heartbeat.ts +371 -0
  8. package/dist/default/convex/logs.ts +66 -0
  9. package/dist/default/convex/mastraIntegration.ts +184 -0
  10. package/dist/default/convex/mcpConnections.ts +127 -0
  11. package/dist/default/convex/messages.ts +90 -0
  12. package/dist/default/convex/projects.ts +114 -0
  13. package/dist/default/convex/sessions.ts +174 -0
  14. package/dist/default/convex/settings.ts +79 -0
  15. package/dist/default/convex/skills.ts +178 -0
  16. package/dist/default/convex/threads.ts +100 -0
  17. package/dist/default/convex/usage.ts +195 -0
  18. package/dist/default/convex/vault.ts +383 -0
  19. package/dist/default/dashboard/app/main.tsx +7 -3
  20. package/dist/default/dashboard/app/routes/agents.tsx +103 -161
  21. package/dist/default/dashboard/app/routes/chat.tsx +163 -317
  22. package/dist/default/dashboard/app/routes/connections.tsx +247 -386
  23. package/dist/default/dashboard/app/routes/cron.tsx +127 -286
  24. package/dist/default/dashboard/app/routes/files.tsx +184 -167
  25. package/dist/default/dashboard/app/routes/index.tsx +63 -96
  26. package/dist/default/dashboard/app/routes/projects.tsx +106 -225
  27. package/dist/default/dashboard/app/routes/sessions.tsx +87 -253
  28. package/dist/default/dashboard/app/routes/settings.tsx +316 -532
  29. package/dist/default/dashboard/app/routes/skills.tsx +329 -216
  30. package/dist/default/dashboard/app/routes/usage.tsx +107 -150
  31. package/dist/default/dashboard/tsconfig.json +3 -2
  32. package/dist/default/dashboard/vite.config.ts +6 -0
  33. package/dist/index.js +279 -50
  34. package/dist/index.js.map +1 -1
  35. package/package.json +1 -1
  36. package/templates/default/README.md +81 -81
  37. package/templates/default/convex/agents.ts +204 -0
  38. package/templates/default/convex/apiKeys.ts +133 -0
  39. package/templates/default/convex/cronJobs.ts +224 -0
  40. package/templates/default/convex/files.ts +103 -0
  41. package/templates/default/convex/folders.ts +110 -0
  42. package/templates/default/convex/heartbeat.ts +371 -0
  43. package/templates/default/convex/logs.ts +66 -0
  44. package/templates/default/convex/mastraIntegration.ts +184 -0
  45. package/templates/default/convex/mcpConnections.ts +127 -0
  46. package/templates/default/convex/messages.ts +90 -0
  47. package/templates/default/convex/projects.ts +114 -0
  48. package/templates/default/convex/sessions.ts +174 -0
  49. package/templates/default/convex/settings.ts +79 -0
  50. package/templates/default/convex/skills.ts +178 -0
  51. package/templates/default/convex/threads.ts +100 -0
  52. package/templates/default/convex/usage.ts +195 -0
  53. package/templates/default/convex/vault.ts +383 -0
  54. package/templates/default/dashboard/app/main.tsx +7 -3
  55. package/templates/default/dashboard/app/routes/agents.tsx +103 -161
  56. package/templates/default/dashboard/app/routes/chat.tsx +163 -317
  57. package/templates/default/dashboard/app/routes/connections.tsx +247 -386
  58. package/templates/default/dashboard/app/routes/cron.tsx +127 -286
  59. package/templates/default/dashboard/app/routes/files.tsx +184 -167
  60. package/templates/default/dashboard/app/routes/index.tsx +63 -96
  61. package/templates/default/dashboard/app/routes/projects.tsx +106 -225
  62. package/templates/default/dashboard/app/routes/sessions.tsx +87 -253
  63. package/templates/default/dashboard/app/routes/settings.tsx +316 -532
  64. package/templates/default/dashboard/app/routes/skills.tsx +329 -216
  65. package/templates/default/dashboard/app/routes/usage.tsx +107 -150
  66. package/templates/default/dashboard/tsconfig.json +3 -2
  67. package/templates/default/dashboard/vite.config.ts +6 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentforge-ai/cli",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "CLI tool for creating, running, and managing AgentForge projects",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,110 +1,110 @@
1
- # My AgentForge Project
1
+ # AgentForge Project
2
2
 
3
- Built with [AgentForge](https://github.com/Agentic-Engineering-Agency/agentforge) a NanoClaw made with Mastra.
3
+ Welcome to your new AgentForge project! This project was scaffolded by the `@agentforge-ai/cli`.
4
4
 
5
- ## Quick Start
5
+ ## 🚀 Quick Start
6
+
7
+ ### 1. Install Dependencies
8
+
9
+ If this wasn't done automatically during project creation, install the dependencies for the root project and the dashboard:
6
10
 
7
11
  ```bash
8
- # 1. Install dependencies
9
- npm install
12
+ # Install root dependencies
13
+ pnpm install
14
+
15
+ # Install dashboard dependencies
16
+ cd dashboard
17
+ pnpm install
18
+ cd ..
19
+ ```
10
20
 
11
- # 2. Set up your environment
12
- cp .env.example .env
13
- # Edit .env and add your API key (OpenAI, OpenRouter, Anthropic, etc.)
21
+ ### 2. Configure Your Environment
22
+
23
+ Copy the example environment file and add your API keys. You only need to configure one LLM provider to get started.
24
+
25
+ ```bash
26
+ cp .env.example .env.local
27
+ ```
14
28
 
15
- # 3. Start the Convex dev server
29
+ Edit `.env.local` with your keys:
30
+
31
+ ```dotenv
32
+ # Convex URL will be set automatically by `npx convex dev`
33
+ CONVEX_URL=
34
+
35
+ # Add your preferred LLM provider API key
36
+ OPENAI_API_KEY=sk-...
37
+ ```
38
+
39
+ ### 3. Start the Development Servers
40
+
41
+ AgentForge requires two concurrent processes for local development:
42
+
43
+ ```bash
44
+ # Terminal 1: Start the Convex backend
16
45
  npx convex dev
17
46
 
18
- # 4. Start building!
19
- npm run dev
47
+ # Terminal 2: Launch the web dashboard
48
+ agentforge dashboard
49
+ ```
50
+
51
+ - The **Convex backend** syncs your database schema and functions, providing a dashboard at `http://localhost:8187`.
52
+ - The **web dashboard** provides a UI for managing your agents, available at `http://localhost:3000`.
53
+
54
+ ## 🤖 Your First Agent
55
+
56
+ Your default agent is defined in `src/agent.ts`. You can customize its instructions, model, and tools.
57
+
58
+ ```typescript
59
+ // src/agent.ts
60
+ import { Agent } from '@agentforge-ai/core';
61
+
62
+ const myAgent = new Agent({
63
+ id: 'my-first-agent',
64
+ name: 'My First Agent',
65
+ instructions: 'You are a helpful AI assistant...',
66
+ model: 'openai:gpt-4o-mini',
67
+ });
68
+
69
+ export default myAgent;
20
70
  ```
21
71
 
22
72
  ## Project Structure
23
73
 
24
74
  ```
25
- ├── convex/ # Convex schema and functions
26
- │ └── schema.ts # Database schema (agents, threads, messages, etc.)
75
+ /my-agent-project
76
+ ├── convex/ # Convex backend (database schema, functions)
77
+ ├── dashboard/ # Web dashboard frontend (Vite + React)
78
+ ├── skills/ # Custom agent skills
79
+ ├── workspace/ # Default local file storage for agents
27
80
  ├── src/
28
- │ └── agent.ts # Your agent definition
29
- ├── skills/ # Custom skills directory
30
- ├── .env.example # Environment variable template
81
+ │ └── agent.ts # Your main agent definition
82
+ ├── .env.local # Your local environment variables
31
83
  ├── package.json
32
84
  └── tsconfig.json
33
85
  ```
34
86
 
35
- ## CLI Commands
87
+ ## CLI Commands
88
+
89
+ Use the `agentforge` CLI to manage your project from the terminal.
36
90
 
37
91
  ```bash
38
- # Agent Management
39
- agentforge agents list # List all agents
40
- agentforge agents create # Create a new agent (interactive)
41
- agentforge agents inspect <id> # Show agent details
42
- agentforge agents edit <id> # Edit an agent
43
- agentforge agents delete <id> # Delete an agent
44
-
45
- # Chat
46
- agentforge chat <agent-id> # Start chatting with an agent
47
- agentforge chat --session <id> # Resume a session
48
-
49
- # Sessions & Threads
50
- agentforge sessions list # List all sessions
51
- agentforge threads list # List all threads
52
-
53
- # Skills
54
- agentforge skills list # List installed skills
55
- agentforge skills install <name> # Install a skill
56
- agentforge skills search <query> # Search available skills
57
-
58
- # Cron Jobs
59
- agentforge cron list # List cron jobs
60
- agentforge cron create # Create a cron job (interactive)
61
-
62
- # MCP Connections
63
- agentforge mcp list # List MCP connections
64
- agentforge mcp add # Add a connection (interactive)
65
- agentforge mcp test <id> # Test connection health
66
-
67
- # Files & Projects
68
- agentforge files list # List files
69
- agentforge files upload <path> # Upload a file
70
- agentforge projects list # List projects
71
- agentforge projects create <name> # Create a project
72
-
73
- # Configuration & Vault
74
- agentforge config list # List all config
75
- agentforge vault list # List secrets (masked)
76
- agentforge vault add <name> <value> # Store a secret
77
-
78
- # Utilities
79
- agentforge status # Show system health
80
- agentforge logs # Tail recent logs
81
- agentforge dashboard # Open the web dashboard
82
- agentforge deploy # Deploy to production
83
- ```
92
+ # List all agents
93
+ agentforge agents list
84
94
 
85
- ## Providers
95
+ # Chat with your agent
96
+ agentforge chat my-first-agent
86
97
 
87
- AgentForge supports multiple LLM providers. Set your preferred provider in `.env`:
98
+ # See all available commands
99
+ agentforge --help
100
+ ```
88
101
 
89
- | Provider | Model Format | API Key Variable |
90
- |----------|-------------|-----------------|
91
- | OpenAI | `openai:gpt-4o-mini` | `OPENAI_API_KEY` |
92
- | OpenRouter | `openrouter:anthropic/claude-3.5-sonnet` | `OPENROUTER_API_KEY` |
93
- | Anthropic | `anthropic:claude-3-5-sonnet-20241022` | `ANTHROPIC_API_KEY` |
94
- | Google | `google:gemini-2.0-flash` | `GOOGLE_API_KEY` |
95
- | xAI | `xai:grok-2` | `XAI_API_KEY` |
96
102
 
97
- ## Web Dashboard
98
103
 
99
- Launch the dashboard for a visual interface:
100
104
 
101
- ```bash
102
- agentforge dashboard
103
- ```
104
105
 
105
106
  ## Learn More
106
107
 
107
- - [AgentForge Documentation](https://github.com/Agentic-Engineering-Agency/agentforge)
108
- - [CLI Reference](https://github.com/Agentic-Engineering-Agency/agentforge/blob/main/docs/cli-reference.md)
109
- - [Convex Docs](https://docs.convex.dev)
110
- - [Mastra Docs](https://mastra.ai/docs)
108
+ - **[AgentForge Documentation](https://github.com/Agentic-Engineering-Agency/agentforge)**: Main project repository and documentation.
109
+ - **[Convex Docs](https://docs.convex.dev)**: Learn more about the real-time backend.
110
+ - **[Mastra Docs](https://mastra.ai/docs)**: Understand the core AI engine.
@@ -0,0 +1,204 @@
1
+ import { v } from "convex/values";
2
+ import { mutation, query, action } from "./_generated/server";
3
+ import { api } from "./_generated/api";
4
+
5
+ // Query: Get all agents
6
+ export const list = query({
7
+ args: {
8
+ userId: v.optional(v.string()),
9
+ },
10
+ handler: async (ctx, args) => {
11
+ if (args.userId) {
12
+ return await ctx.db
13
+ .query("agents")
14
+ .withIndex("byUserId", (q) => q.eq("userId", args.userId))
15
+ .take(100).collect();
16
+ }
17
+ return await ctx.db.query("agents").take(100).collect();
18
+ },
19
+ });
20
+
21
+ // Query: Get agent by ID
22
+ export const get = query({
23
+ args: { id: v.string() },
24
+ handler: async (ctx, args) => {
25
+ return await ctx.db
26
+ .query("agents")
27
+ .withIndex("byAgentId", (q) => q.eq("id", args.id))
28
+ .first();
29
+ },
30
+ });
31
+
32
+ // Query: Get active agents
33
+ export const listActive = query({
34
+ args: {
35
+ userId: v.optional(v.string()),
36
+ },
37
+ handler: async (ctx, args) => {
38
+ let query = ctx.db
39
+ .query("agents")
40
+ .withIndex("byIsActive", (q) => q.eq("isActive", true));
41
+
42
+ const agents = await query.take(100).collect();
43
+
44
+ if (args.userId) {
45
+ return agents.filter((agent) => agent.userId === args.userId);
46
+ }
47
+
48
+ return agents;
49
+ },
50
+ });
51
+
52
+ // Mutation: Create a new agent
53
+ export const create = mutation({
54
+ args: {
55
+ id: v.string(),
56
+ name: v.string(),
57
+ description: v.optional(v.string()),
58
+ instructions: v.string(),
59
+ model: v.string(),
60
+ provider: v.string(),
61
+ tools: v.optional(v.any()),
62
+ temperature: v.optional(v.number()),
63
+ maxTokens: v.optional(v.number()),
64
+ topP: v.optional(v.number()),
65
+ userId: v.optional(v.string()),
66
+ },
67
+ handler: async (ctx, args) => {
68
+ const now = Date.now();
69
+ const agentId = await ctx.db.insert("agents", {
70
+ ...args,
71
+ isActive: true,
72
+ createdAt: now,
73
+ updatedAt: now,
74
+ });
75
+ return agentId;
76
+ },
77
+ });
78
+
79
+ // Mutation: Update an agent
80
+ export const update = mutation({
81
+ args: {
82
+ id: v.string(),
83
+ name: v.optional(v.string()),
84
+ description: v.optional(v.string()),
85
+ instructions: v.optional(v.string()),
86
+ model: v.optional(v.string()),
87
+ provider: v.optional(v.string()),
88
+ tools: v.optional(v.any()),
89
+ temperature: v.optional(v.number()),
90
+ maxTokens: v.optional(v.number()),
91
+ topP: v.optional(v.number()),
92
+ isActive: v.optional(v.boolean()),
93
+ },
94
+ handler: async (ctx, args) => {
95
+ const { id, ...updates } = args;
96
+ const agent = await ctx.db
97
+ .query("agents")
98
+ .withIndex("byAgentId", (q) => q.eq("id", id))
99
+ .first();
100
+
101
+ if (!agent) {
102
+ throw new Error(`Agent with id ${id} not found`);
103
+ }
104
+
105
+ await ctx.db.patch(agent._id, {
106
+ ...updates,
107
+ updatedAt: Date.now(),
108
+ });
109
+
110
+ return agent._id;
111
+ },
112
+ });
113
+
114
+ // Mutation: Delete an agent
115
+ export const remove = mutation({
116
+ args: { id: v.string() },
117
+ handler: async (ctx, args) => {
118
+ const agent = await ctx.db
119
+ .query("agents")
120
+ .withIndex("byAgentId", (q) => q.eq("id", args.id))
121
+ .first();
122
+
123
+ if (!agent) {
124
+ throw new Error(`Agent with id ${args.id} not found`);
125
+ }
126
+
127
+ await ctx.db.delete(agent._id);
128
+ return { success: true };
129
+ },
130
+ });
131
+
132
+ // Mutation: Toggle agent active status
133
+ export const toggleActive = mutation({
134
+ args: { id: v.string() },
135
+ handler: async (ctx, args) => {
136
+ const agent = await ctx.db
137
+ .query("agents")
138
+ .withIndex("byAgentId", (q) => q.eq("id", args.id))
139
+ .first();
140
+
141
+ if (!agent) {
142
+ throw new Error(`Agent with id ${args.id} not found`);
143
+ }
144
+
145
+ await ctx.db.patch(agent._id, {
146
+ isActive: !agent.isActive,
147
+ updatedAt: Date.now(),
148
+ });
149
+
150
+ return { success: true, isActive: !agent.isActive };
151
+ },
152
+ });
153
+
154
+ // Action: Run agent with Mastra (to be implemented with Mastra integration)
155
+ export const run = action({
156
+ args: {
157
+ agentId: v.string(),
158
+ prompt: v.string(),
159
+ threadId: v.optional(v.id("threads")),
160
+ userId: v.optional(v.string()),
161
+ },
162
+ handler: async (ctx, args) => {
163
+ // Get agent configuration
164
+ const agent = await ctx.runQuery(api.agents.get, { id: args.agentId });
165
+
166
+ if (!agent) {
167
+ throw new Error(`Agent with id ${args.agentId} not found`);
168
+ }
169
+
170
+ // Create or get thread
171
+ let threadId = args.threadId;
172
+ if (!threadId) {
173
+ threadId = await ctx.runMutation(api.threads.create, {
174
+ agentId: args.agentId,
175
+ userId: args.userId,
176
+ });
177
+ }
178
+
179
+ // Add user message
180
+ await ctx.runMutation(api.messages.add, {
181
+ threadId,
182
+ role: "user",
183
+ content: args.prompt,
184
+ });
185
+
186
+ // TODO: Integrate with Mastra to run the agent
187
+ // This will be implemented in the Mastra integration phase
188
+ // For now, return a placeholder response
189
+ const response = {
190
+ threadId,
191
+ message: "Agent execution will be implemented with Mastra integration",
192
+ agentId: args.agentId,
193
+ };
194
+
195
+ // Add assistant message placeholder
196
+ await ctx.runMutation(api.messages.add, {
197
+ threadId,
198
+ role: "assistant",
199
+ content: response.message,
200
+ });
201
+
202
+ return response;
203
+ },
204
+ });
@@ -0,0 +1,133 @@
1
+ import { v } from "convex/values";
2
+ import { mutation, query } from "./_generated/server";
3
+
4
+ // Query: List API keys
5
+ export const list = query({
6
+ args: {
7
+ userId: v.optional(v.string()),
8
+ provider: v.optional(v.string()),
9
+ },
10
+ handler: async (ctx, args) => {
11
+ if (args.provider) {
12
+ const keys = await ctx.db
13
+ .query("apiKeys")
14
+ .withIndex("byProvider", (q) => q.eq("provider", args.provider))
15
+ .take(100).collect();
16
+
17
+ if (args.userId) {
18
+ return keys.filter((k) => k.userId === args.userId);
19
+ }
20
+ return keys;
21
+ }
22
+
23
+ if (args.userId) {
24
+ return await ctx.db
25
+ .query("apiKeys")
26
+ .withIndex("byUserId", (q) => q.eq("userId", args.userId))
27
+ .take(100).collect();
28
+ }
29
+
30
+ return await ctx.db.query("apiKeys").take(100).collect();
31
+ },
32
+ });
33
+
34
+ // Query: Get API key by ID
35
+ export const get = query({
36
+ args: { id: v.id("apiKeys") },
37
+ handler: async (ctx, args) => {
38
+ return await ctx.db.get(args.id);
39
+ },
40
+ });
41
+
42
+ // Query: Get active API key for provider
43
+ export const getActiveForProvider = query({
44
+ args: {
45
+ provider: v.string(),
46
+ userId: v.optional(v.string()),
47
+ },
48
+ handler: async (ctx, args) => {
49
+ const keys = await ctx.db
50
+ .query("apiKeys")
51
+ .withIndex("byProvider", (q) => q.eq("provider", args.provider))
52
+ .take(100).collect();
53
+
54
+ const activeKeys = keys.filter((k) => k.isActive);
55
+
56
+ if (args.userId) {
57
+ return activeKeys.find((k) => k.userId === args.userId);
58
+ }
59
+
60
+ return activeKeys[0];
61
+ },
62
+ });
63
+
64
+ // Mutation: Create API key
65
+ export const create = mutation({
66
+ args: {
67
+ provider: v.string(),
68
+ keyName: v.string(),
69
+ encryptedKey: v.string(),
70
+ userId: v.optional(v.string()),
71
+ },
72
+ handler: async (ctx, args) => {
73
+ const keyId = await ctx.db.insert("apiKeys", {
74
+ ...args,
75
+ isActive: true,
76
+ createdAt: Date.now(),
77
+ });
78
+ return keyId;
79
+ },
80
+ });
81
+
82
+ // Mutation: Update API key
83
+ export const update = mutation({
84
+ args: {
85
+ id: v.id("apiKeys"),
86
+ keyName: v.optional(v.string()),
87
+ encryptedKey: v.optional(v.string()),
88
+ isActive: v.optional(v.boolean()),
89
+ },
90
+ handler: async (ctx, args) => {
91
+ const { id, ...updates } = args;
92
+ await ctx.db.patch(id, updates);
93
+ return id;
94
+ },
95
+ });
96
+
97
+ // Mutation: Toggle API key active status
98
+ export const toggleActive = mutation({
99
+ args: { id: v.id("apiKeys") },
100
+ handler: async (ctx, args) => {
101
+ const key = await ctx.db.get(args.id);
102
+
103
+ if (!key) {
104
+ throw new Error(`API key not found`);
105
+ }
106
+
107
+ await ctx.db.patch(args.id, {
108
+ isActive: !key.isActive,
109
+ });
110
+
111
+ return { success: true, isActive: !key.isActive };
112
+ },
113
+ });
114
+
115
+ // Mutation: Update last used timestamp
116
+ export const updateLastUsed = mutation({
117
+ args: { id: v.id("apiKeys") },
118
+ handler: async (ctx, args) => {
119
+ await ctx.db.patch(args.id, {
120
+ lastUsedAt: Date.now(),
121
+ });
122
+ return args.id;
123
+ },
124
+ });
125
+
126
+ // Mutation: Delete API key
127
+ export const remove = mutation({
128
+ args: { id: v.id("apiKeys") },
129
+ handler: async (ctx, args) => {
130
+ await ctx.db.delete(args.id);
131
+ return { success: true };
132
+ },
133
+ });