@agentforge-ai/cli 0.4.3 → 0.5.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 (67) hide show
  1. package/dist/default/convex/agents.ts +204 -0
  2. package/dist/default/convex/apiKeys.ts +133 -0
  3. package/dist/default/convex/cronJobs.ts +224 -0
  4. package/dist/default/convex/files.ts +103 -0
  5. package/dist/default/convex/folders.ts +110 -0
  6. package/dist/default/convex/heartbeat.ts +371 -0
  7. package/dist/default/convex/logs.ts +66 -0
  8. package/dist/default/convex/mastraIntegration.ts +185 -0
  9. package/dist/default/convex/mcpConnections.ts +127 -0
  10. package/dist/default/convex/messages.ts +90 -0
  11. package/dist/default/convex/projects.ts +114 -0
  12. package/dist/default/convex/schema.ts +150 -83
  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 +397 -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 +256 -49
  34. package/dist/index.js.map +1 -1
  35. package/package.json +1 -1
  36. package/templates/default/convex/agents.ts +204 -0
  37. package/templates/default/convex/apiKeys.ts +133 -0
  38. package/templates/default/convex/cronJobs.ts +224 -0
  39. package/templates/default/convex/files.ts +103 -0
  40. package/templates/default/convex/folders.ts +110 -0
  41. package/templates/default/convex/heartbeat.ts +371 -0
  42. package/templates/default/convex/logs.ts +66 -0
  43. package/templates/default/convex/mastraIntegration.ts +185 -0
  44. package/templates/default/convex/mcpConnections.ts +127 -0
  45. package/templates/default/convex/messages.ts +90 -0
  46. package/templates/default/convex/projects.ts +114 -0
  47. package/templates/default/convex/schema.ts +150 -83
  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 +397 -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
@@ -0,0 +1,185 @@
1
+ import { action } from "./_generated/server";
2
+ import { v } from "convex/values";
3
+ import { api } from "./_generated/api";
4
+
5
+ /**
6
+ * Mastra Integration Actions for Convex
7
+ *
8
+ * These actions run in the Node.js runtime and can use Mastra
9
+ * to execute agents and manage workflows.
10
+ */
11
+
12
+ // Action: Execute agent with Mastra
13
+ export const executeAgent = action({
14
+ args: {
15
+ agentId: v.string(),
16
+ prompt: v.string(),
17
+ threadId: v.optional(v.id("threads")),
18
+ userId: v.optional(v.string()),
19
+ stream: v.optional(v.boolean()),
20
+ },
21
+ handler: async (ctx, args) => {
22
+ // Get agent configuration from database
23
+ const agent = await ctx.runQuery(api.agents.get, { id: args.agentId });
24
+
25
+ if (!agent) {
26
+ throw new Error(`Agent ${args.agentId} not found`);
27
+ }
28
+
29
+ // Create or get thread
30
+ let threadId = args.threadId;
31
+ if (!threadId) {
32
+ threadId = await ctx.runMutation(api.threads.create, {
33
+ agentId: args.agentId,
34
+ userId: args.userId,
35
+ });
36
+ }
37
+
38
+ // Add user message to thread
39
+ await ctx.runMutation(api.messages.add, {
40
+ threadId,
41
+ role: "user",
42
+ content: args.prompt,
43
+ });
44
+
45
+ // Create session
46
+ const sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
47
+ await ctx.runMutation(api.sessions.create, {
48
+ sessionId,
49
+ threadId,
50
+ agentId: args.agentId,
51
+ userId: args.userId,
52
+ channel: "dashboard",
53
+ });
54
+
55
+ try {
56
+ // Import Mastra dynamically (Node.js runtime)
57
+ // @ts-expect-error - Mastra is installed at runtime in the user's project
58
+ const { Agent } = await import("@mastra/core/agent");
59
+
60
+ // Format model string for Mastra
61
+ const modelString = agent.model.includes("/")
62
+ ? agent.model
63
+ : `${agent.provider}/${agent.model}`;
64
+
65
+ // Create Mastra agent
66
+ const mastraAgent = new Agent({
67
+ id: agent.id,
68
+ name: agent.name,
69
+ instructions: agent.instructions,
70
+ model: modelString,
71
+ tools: agent.tools || {},
72
+ ...(agent.temperature && { temperature: agent.temperature }),
73
+ ...(agent.maxTokens && { maxTokens: agent.maxTokens }),
74
+ ...(agent.topP && { topP: agent.topP }),
75
+ });
76
+
77
+ // Get conversation history for context
78
+ const messages = await ctx.runQuery(api.messages.list, { threadId });
79
+
80
+ // Build context from message history
81
+ const context = messages
82
+ .slice(-10) // Last 10 messages for context
83
+ .map((m) => `${m.role}: ${m.content}`)
84
+ .join("\n");
85
+
86
+ // Execute agent
87
+ const result: any = await mastraAgent.generate(args.prompt, {
88
+ ...(args.stream && { stream: args.stream }),
89
+ context: context || undefined,
90
+ });
91
+
92
+ // Extract response content
93
+ const responseContent = typeof result === "string"
94
+ ? result
95
+ : result.text || result.content || JSON.stringify(result);
96
+
97
+ // Add assistant message to thread
98
+ await ctx.runMutation(api.messages.add, {
99
+ threadId,
100
+ role: "assistant",
101
+ content: responseContent,
102
+ });
103
+
104
+ // Update session status
105
+ await ctx.runMutation(api.sessions.updateStatus, {
106
+ sessionId,
107
+ status: "completed",
108
+ });
109
+
110
+ // Record usage (if available in result)
111
+ if (result.usage) {
112
+ await ctx.runMutation(api.usage.record, {
113
+ agentId: args.agentId,
114
+ sessionId,
115
+ provider: agent.provider,
116
+ model: agent.model,
117
+ promptTokens: result.usage.promptTokens || 0,
118
+ completionTokens: result.usage.completionTokens || 0,
119
+ totalTokens: result.usage.totalTokens || 0,
120
+ cost: result.usage.cost,
121
+ userId: args.userId,
122
+ });
123
+ }
124
+
125
+ return {
126
+ success: true,
127
+ threadId,
128
+ sessionId,
129
+ response: responseContent,
130
+ usage: result.usage,
131
+ };
132
+ } catch (error: any) {
133
+ // Update session status to error
134
+ await ctx.runMutation(api.sessions.updateStatus, {
135
+ sessionId,
136
+ status: "error",
137
+ });
138
+
139
+ // Add error message
140
+ await ctx.runMutation(api.messages.add, {
141
+ threadId,
142
+ role: "assistant",
143
+ content: `Error: ${error.message}`,
144
+ });
145
+
146
+ throw error;
147
+ }
148
+ },
149
+ });
150
+
151
+ // Action: Stream agent response
152
+ export const streamAgent = action({
153
+ args: {
154
+ agentId: v.string(),
155
+ prompt: v.string(),
156
+ threadId: v.id("threads"),
157
+ userId: v.optional(v.string()),
158
+ },
159
+ handler: async (ctx, args) => {
160
+ // Similar to executeAgent but with streaming support
161
+ // This would require WebSocket or SSE implementation
162
+ // For now, return a placeholder
163
+ return {
164
+ success: true,
165
+ message: "Streaming support coming soon",
166
+ };
167
+ },
168
+ });
169
+
170
+ // Action: Execute workflow with multiple agents
171
+ export const executeWorkflow = action({
172
+ args: {
173
+ workflowId: v.string(),
174
+ input: v.any(),
175
+ userId: v.optional(v.string()),
176
+ },
177
+ handler: async (ctx, args) => {
178
+ // Placeholder for workflow execution
179
+ // This would orchestrate multiple agents in sequence or parallel
180
+ return {
181
+ success: true,
182
+ message: "Workflow execution coming soon",
183
+ };
184
+ },
185
+ });
@@ -0,0 +1,127 @@
1
+ import { v } from "convex/values";
2
+ import { mutation, query } from "./_generated/server";
3
+
4
+ // Query: List MCP connections
5
+ export const list = query({
6
+ args: {
7
+ userId: v.optional(v.string()),
8
+ isEnabled: v.optional(v.boolean()),
9
+ },
10
+ handler: async (ctx, args) => {
11
+ if (args.isEnabled !== undefined) {
12
+ const connections = await ctx.db
13
+ .query("mcpConnections")
14
+ .withIndex("byIsEnabled", (q) => q.eq("isEnabled", args.isEnabled!))
15
+ .collect();
16
+
17
+ if (args.userId) {
18
+ return connections.filter((c) => c.userId === args.userId);
19
+ }
20
+ return connections;
21
+ }
22
+
23
+ if (args.userId) {
24
+ return await ctx.db
25
+ .query("mcpConnections")
26
+ .withIndex("byUserId", (q) => q.eq("userId", args.userId!))
27
+ .collect();
28
+ }
29
+
30
+ return await ctx.db.query("mcpConnections").collect();
31
+ },
32
+ });
33
+
34
+ // Query: Get MCP connection by ID
35
+ export const get = query({
36
+ args: { id: v.id("mcpConnections") },
37
+ handler: async (ctx, args) => {
38
+ return await ctx.db.get(args.id);
39
+ },
40
+ });
41
+
42
+ // Mutation: Create MCP connection
43
+ export const create = mutation({
44
+ args: {
45
+ name: v.string(),
46
+ serverUrl: v.string(),
47
+ protocol: v.string(),
48
+ credentials: v.optional(v.any()),
49
+ capabilities: v.optional(v.any()),
50
+ userId: v.optional(v.string()),
51
+ },
52
+ handler: async (ctx, args) => {
53
+ const now = Date.now();
54
+ const connectionId = await ctx.db.insert("mcpConnections", {
55
+ ...args,
56
+ isConnected: false,
57
+ isEnabled: true,
58
+ createdAt: now,
59
+ updatedAt: now,
60
+ });
61
+ return connectionId;
62
+ },
63
+ });
64
+
65
+ // Mutation: Update MCP connection
66
+ export const update = mutation({
67
+ args: {
68
+ id: v.id("mcpConnections"),
69
+ name: v.optional(v.string()),
70
+ serverUrl: v.optional(v.string()),
71
+ credentials: v.optional(v.any()),
72
+ capabilities: v.optional(v.any()),
73
+ isEnabled: v.optional(v.boolean()),
74
+ },
75
+ handler: async (ctx, args) => {
76
+ const { id, ...updates } = args;
77
+ await ctx.db.patch(id, {
78
+ ...updates,
79
+ updatedAt: Date.now(),
80
+ });
81
+ return id;
82
+ },
83
+ });
84
+
85
+ // Mutation: Update connection status
86
+ export const updateStatus = mutation({
87
+ args: {
88
+ id: v.id("mcpConnections"),
89
+ isConnected: v.boolean(),
90
+ },
91
+ handler: async (ctx, args) => {
92
+ await ctx.db.patch(args.id, {
93
+ isConnected: args.isConnected,
94
+ lastConnectedAt: args.isConnected ? Date.now() : undefined,
95
+ updatedAt: Date.now(),
96
+ });
97
+ return args.id;
98
+ },
99
+ });
100
+
101
+ // Mutation: Toggle MCP connection enabled status
102
+ export const toggleEnabled = mutation({
103
+ args: { id: v.id("mcpConnections") },
104
+ handler: async (ctx, args) => {
105
+ const connection = await ctx.db.get(args.id);
106
+
107
+ if (!connection) {
108
+ throw new Error(`MCP connection not found`);
109
+ }
110
+
111
+ await ctx.db.patch(args.id, {
112
+ isEnabled: !connection.isEnabled,
113
+ updatedAt: Date.now(),
114
+ });
115
+
116
+ return { success: true, isEnabled: !connection.isEnabled };
117
+ },
118
+ });
119
+
120
+ // Mutation: Delete MCP connection
121
+ export const remove = mutation({
122
+ args: { id: v.id("mcpConnections") },
123
+ handler: async (ctx, args) => {
124
+ await ctx.db.delete(args.id);
125
+ return { success: true };
126
+ },
127
+ });
@@ -0,0 +1,90 @@
1
+ import { mutation, query } from "./_generated/server";
2
+ import { v } from "convex/values";
3
+
4
+ // Mutation: Add a message to a thread
5
+ export const add = mutation({
6
+ args: {
7
+ threadId: v.id("threads"),
8
+ role: v.union(
9
+ v.literal("user"),
10
+ v.literal("assistant"),
11
+ v.literal("system"),
12
+ v.literal("tool")
13
+ ),
14
+ content: v.string(),
15
+ tool_calls: v.optional(v.any()),
16
+ },
17
+ handler: async (ctx, args) => {
18
+ const messageId = await ctx.db.insert("messages", {
19
+ ...args,
20
+ createdAt: Date.now(),
21
+ });
22
+
23
+ // Update thread's updatedAt timestamp
24
+ await ctx.db.patch(args.threadId, {
25
+ updatedAt: Date.now(),
26
+ });
27
+
28
+ return messageId;
29
+ },
30
+ });
31
+
32
+ // Mutation: Create a message (alias for add)
33
+ export const create = mutation({
34
+ args: {
35
+ threadId: v.id("threads"),
36
+ role: v.union(
37
+ v.literal("user"),
38
+ v.literal("assistant"),
39
+ v.literal("system"),
40
+ v.literal("tool")
41
+ ),
42
+ content: v.string(),
43
+ tool_calls: v.optional(v.any()),
44
+ },
45
+ handler: async (ctx, args) => {
46
+ const messageId = await ctx.db.insert("messages", {
47
+ ...args,
48
+ createdAt: Date.now(),
49
+ });
50
+ return messageId;
51
+ },
52
+ });
53
+
54
+ // Query: Get messages by thread
55
+ export const list = query({
56
+ args: { threadId: v.id("threads") },
57
+ handler: async (ctx, args) => {
58
+ const messages = await ctx.db
59
+ .query("messages")
60
+ .withIndex("byThread", (q) => q.eq("threadId", args.threadId!))
61
+ .collect();
62
+ return messages;
63
+ },
64
+ });
65
+
66
+ // Mutation: Delete a message
67
+ export const remove = mutation({
68
+ args: { id: v.id("messages") },
69
+ handler: async (ctx, args) => {
70
+ await ctx.db.delete(args.id);
71
+ return { success: true };
72
+ },
73
+ });
74
+
75
+ // Mutation: Clear all messages in a thread
76
+ export const clearThread = mutation({
77
+ args: { threadId: v.id("threads") },
78
+ handler: async (ctx, args) => {
79
+ const messages = await ctx.db
80
+ .query("messages")
81
+ .withIndex("byThread", (q) => q.eq("threadId", args.threadId!))
82
+ .collect();
83
+
84
+ for (const message of messages) {
85
+ await ctx.db.delete(message._id);
86
+ }
87
+
88
+ return { success: true, deleted: messages.length };
89
+ },
90
+ });
@@ -0,0 +1,114 @@
1
+ import { v } from "convex/values";
2
+ import { mutation, query } from "./_generated/server";
3
+
4
+ // Query: List projects
5
+ export const list = query({
6
+ args: {
7
+ userId: v.optional(v.string()),
8
+ },
9
+ handler: async (ctx, args) => {
10
+ if (args.userId) {
11
+ return await ctx.db
12
+ .query("projects")
13
+ .withIndex("byUserId", (q) => q.eq("userId", args.userId!))
14
+ .collect();
15
+ }
16
+
17
+ return await ctx.db.query("projects").collect();
18
+ },
19
+ });
20
+
21
+ // Query: Get project by ID
22
+ export const get = query({
23
+ args: { id: v.id("projects") },
24
+ handler: async (ctx, args) => {
25
+ return await ctx.db.get(args.id);
26
+ },
27
+ });
28
+
29
+ // Mutation: Create project
30
+ export const create = mutation({
31
+ args: {
32
+ name: v.string(),
33
+ description: v.optional(v.string()),
34
+ userId: v.optional(v.string()),
35
+ settings: v.optional(v.any()),
36
+ },
37
+ handler: async (ctx, args) => {
38
+ const now = Date.now();
39
+ const projectId = await ctx.db.insert("projects", {
40
+ ...args,
41
+ createdAt: now,
42
+ updatedAt: now,
43
+ });
44
+ return projectId;
45
+ },
46
+ });
47
+
48
+ // Mutation: Update project
49
+ export const update = mutation({
50
+ args: {
51
+ id: v.id("projects"),
52
+ name: v.optional(v.string()),
53
+ description: v.optional(v.string()),
54
+ settings: v.optional(v.any()),
55
+ },
56
+ handler: async (ctx, args) => {
57
+ const { id, ...updates } = args;
58
+ await ctx.db.patch(id, {
59
+ ...updates,
60
+ updatedAt: Date.now(),
61
+ });
62
+ return id;
63
+ },
64
+ });
65
+
66
+ // Mutation: Delete project
67
+ export const remove = mutation({
68
+ args: { id: v.id("projects") },
69
+ handler: async (ctx, args) => {
70
+ // Delete all threads in the project
71
+ const threads = await ctx.db
72
+ .query("threads")
73
+ .withIndex("byProjectId", (q) => q.eq("projectId", args.id!))
74
+ .collect();
75
+
76
+ for (const thread of threads) {
77
+ // Delete messages in thread
78
+ const messages = await ctx.db
79
+ .query("messages")
80
+ .withIndex("byThread", (q) => q.eq("threadId", thread._id))
81
+ .collect();
82
+
83
+ for (const message of messages) {
84
+ await ctx.db.delete(message._id);
85
+ }
86
+
87
+ await ctx.db.delete(thread._id);
88
+ }
89
+
90
+ // Delete all files in the project
91
+ const files = await ctx.db
92
+ .query("files")
93
+ .withIndex("byProjectId", (q) => q.eq("projectId", args.id!))
94
+ .collect();
95
+
96
+ for (const file of files) {
97
+ await ctx.db.delete(file._id);
98
+ }
99
+
100
+ // Delete all folders in the project
101
+ const folders = await ctx.db
102
+ .query("folders")
103
+ .withIndex("byProjectId", (q) => q.eq("projectId", args.id!))
104
+ .collect();
105
+
106
+ for (const folder of folders) {
107
+ await ctx.db.delete(folder._id);
108
+ }
109
+
110
+ // Delete the project itself
111
+ await ctx.db.delete(args.id);
112
+ return { success: true };
113
+ },
114
+ });