@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.
- package/dist/default/README.md +81 -81
- package/dist/default/convex/agents.ts +204 -0
- package/dist/default/convex/apiKeys.ts +133 -0
- package/dist/default/convex/cronJobs.ts +224 -0
- package/dist/default/convex/files.ts +103 -0
- package/dist/default/convex/folders.ts +110 -0
- package/dist/default/convex/heartbeat.ts +371 -0
- package/dist/default/convex/logs.ts +66 -0
- package/dist/default/convex/mastraIntegration.ts +184 -0
- package/dist/default/convex/mcpConnections.ts +127 -0
- package/dist/default/convex/messages.ts +90 -0
- package/dist/default/convex/projects.ts +114 -0
- package/dist/default/convex/sessions.ts +174 -0
- package/dist/default/convex/settings.ts +79 -0
- package/dist/default/convex/skills.ts +178 -0
- package/dist/default/convex/threads.ts +100 -0
- package/dist/default/convex/usage.ts +195 -0
- package/dist/default/convex/vault.ts +383 -0
- package/dist/default/dashboard/app/main.tsx +7 -3
- package/dist/default/dashboard/app/routes/agents.tsx +103 -161
- package/dist/default/dashboard/app/routes/chat.tsx +163 -317
- package/dist/default/dashboard/app/routes/connections.tsx +247 -386
- package/dist/default/dashboard/app/routes/cron.tsx +127 -286
- package/dist/default/dashboard/app/routes/files.tsx +184 -167
- package/dist/default/dashboard/app/routes/index.tsx +63 -96
- package/dist/default/dashboard/app/routes/projects.tsx +106 -225
- package/dist/default/dashboard/app/routes/sessions.tsx +87 -253
- package/dist/default/dashboard/app/routes/settings.tsx +316 -532
- package/dist/default/dashboard/app/routes/skills.tsx +329 -216
- package/dist/default/dashboard/app/routes/usage.tsx +107 -150
- package/dist/default/dashboard/tsconfig.json +3 -2
- package/dist/default/dashboard/vite.config.ts +6 -0
- package/dist/index.js +279 -50
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/default/README.md +81 -81
- package/templates/default/convex/agents.ts +204 -0
- package/templates/default/convex/apiKeys.ts +133 -0
- package/templates/default/convex/cronJobs.ts +224 -0
- package/templates/default/convex/files.ts +103 -0
- package/templates/default/convex/folders.ts +110 -0
- package/templates/default/convex/heartbeat.ts +371 -0
- package/templates/default/convex/logs.ts +66 -0
- package/templates/default/convex/mastraIntegration.ts +184 -0
- package/templates/default/convex/mcpConnections.ts +127 -0
- package/templates/default/convex/messages.ts +90 -0
- package/templates/default/convex/projects.ts +114 -0
- package/templates/default/convex/sessions.ts +174 -0
- package/templates/default/convex/settings.ts +79 -0
- package/templates/default/convex/skills.ts +178 -0
- package/templates/default/convex/threads.ts +100 -0
- package/templates/default/convex/usage.ts +195 -0
- package/templates/default/convex/vault.ts +383 -0
- package/templates/default/dashboard/app/main.tsx +7 -3
- package/templates/default/dashboard/app/routes/agents.tsx +103 -161
- package/templates/default/dashboard/app/routes/chat.tsx +163 -317
- package/templates/default/dashboard/app/routes/connections.tsx +247 -386
- package/templates/default/dashboard/app/routes/cron.tsx +127 -286
- package/templates/default/dashboard/app/routes/files.tsx +184 -167
- package/templates/default/dashboard/app/routes/index.tsx +63 -96
- package/templates/default/dashboard/app/routes/projects.tsx +106 -225
- package/templates/default/dashboard/app/routes/sessions.tsx +87 -253
- package/templates/default/dashboard/app/routes/settings.tsx +316 -532
- package/templates/default/dashboard/app/routes/skills.tsx +329 -216
- package/templates/default/dashboard/app/routes/usage.tsx +107 -150
- package/templates/default/dashboard/tsconfig.json +3 -2
- package/templates/default/dashboard/vite.config.ts +6 -0
|
@@ -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
|
+
.take(100).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
|
+
.take(100).collect();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return await ctx.db.query("mcpConnections").take(100).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("by_thread", (q) => q.eq("threadId", args.threadId))
|
|
61
|
+
.take(100).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("by_thread", (q) => q.eq("threadId", args.threadId))
|
|
82
|
+
.take(100).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
|
+
.take(100).collect();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return await ctx.db.query("projects").take(100).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
|
+
.take(100).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
|
+
.take(100).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
|
+
.take(100).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
|
+
.take(100).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
|
+
});
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { v } from "convex/values";
|
|
2
|
+
import { mutation, query } from "./_generated/server";
|
|
3
|
+
|
|
4
|
+
// Query: Get all sessions
|
|
5
|
+
export const list = query({
|
|
6
|
+
args: {
|
|
7
|
+
userId: v.optional(v.string()),
|
|
8
|
+
agentId: v.optional(v.string()),
|
|
9
|
+
status: v.optional(v.string()),
|
|
10
|
+
},
|
|
11
|
+
handler: async (ctx, args) => {
|
|
12
|
+
if (args.status) {
|
|
13
|
+
const sessions = await ctx.db
|
|
14
|
+
.query("sessions")
|
|
15
|
+
.withIndex("byStatus", (q) => q.eq("status", args.status as any))
|
|
16
|
+
.take(100).collect();
|
|
17
|
+
|
|
18
|
+
if (args.userId) {
|
|
19
|
+
return sessions.filter((s) => s.userId === args.userId);
|
|
20
|
+
}
|
|
21
|
+
if (args.agentId) {
|
|
22
|
+
return sessions.filter((s) => s.agentId === args.agentId);
|
|
23
|
+
}
|
|
24
|
+
return sessions;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (args.agentId) {
|
|
28
|
+
return await ctx.db
|
|
29
|
+
.query("sessions")
|
|
30
|
+
.withIndex("byAgentId", (q) => q.eq("agentId", args.agentId))
|
|
31
|
+
.take(100).collect();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (args.userId) {
|
|
35
|
+
return await ctx.db
|
|
36
|
+
.query("sessions")
|
|
37
|
+
.withIndex("byUserId", (q) => q.eq("userId", args.userId))
|
|
38
|
+
.take(100).collect();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return await ctx.db.query("sessions").take(100).collect();
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Query: Get session by ID
|
|
46
|
+
export const get = query({
|
|
47
|
+
args: { sessionId: v.string() },
|
|
48
|
+
handler: async (ctx, args) => {
|
|
49
|
+
return await ctx.db
|
|
50
|
+
.query("sessions")
|
|
51
|
+
.withIndex("bySessionId", (q) => q.eq("sessionId", args.sessionId))
|
|
52
|
+
.first();
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Query: Get active sessions
|
|
57
|
+
export const listActive = query({
|
|
58
|
+
args: {
|
|
59
|
+
userId: v.optional(v.string()),
|
|
60
|
+
},
|
|
61
|
+
handler: async (ctx, args) => {
|
|
62
|
+
const sessions = await ctx.db
|
|
63
|
+
.query("sessions")
|
|
64
|
+
.withIndex("byStatus", (q) => q.eq("status", "active"))
|
|
65
|
+
.take(100).collect();
|
|
66
|
+
|
|
67
|
+
if (args.userId) {
|
|
68
|
+
return sessions.filter((s) => s.userId === args.userId);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return sessions;
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Mutation: Create a new session
|
|
76
|
+
export const create = mutation({
|
|
77
|
+
args: {
|
|
78
|
+
sessionId: v.string(),
|
|
79
|
+
threadId: v.id("threads"),
|
|
80
|
+
agentId: v.string(),
|
|
81
|
+
userId: v.optional(v.string()),
|
|
82
|
+
channel: v.optional(v.string()),
|
|
83
|
+
metadata: v.optional(v.any()),
|
|
84
|
+
},
|
|
85
|
+
handler: async (ctx, args) => {
|
|
86
|
+
const now = Date.now();
|
|
87
|
+
const sessionId = await ctx.db.insert("sessions", {
|
|
88
|
+
...args,
|
|
89
|
+
status: "active",
|
|
90
|
+
startedAt: now,
|
|
91
|
+
lastActivityAt: now,
|
|
92
|
+
});
|
|
93
|
+
return sessionId;
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Mutation: Update session activity
|
|
98
|
+
export const updateActivity = mutation({
|
|
99
|
+
args: {
|
|
100
|
+
sessionId: v.string(),
|
|
101
|
+
metadata: v.optional(v.any()),
|
|
102
|
+
},
|
|
103
|
+
handler: async (ctx, args) => {
|
|
104
|
+
const session = await ctx.db
|
|
105
|
+
.query("sessions")
|
|
106
|
+
.withIndex("bySessionId", (q) => q.eq("sessionId", args.sessionId))
|
|
107
|
+
.first();
|
|
108
|
+
|
|
109
|
+
if (!session) {
|
|
110
|
+
throw new Error(`Session ${args.sessionId} not found`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
await ctx.db.patch(session._id, {
|
|
114
|
+
lastActivityAt: Date.now(),
|
|
115
|
+
...(args.metadata && { metadata: args.metadata }),
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
return session._id;
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Mutation: Update session status
|
|
123
|
+
export const updateStatus = mutation({
|
|
124
|
+
args: {
|
|
125
|
+
sessionId: v.string(),
|
|
126
|
+
status: v.union(
|
|
127
|
+
v.literal("active"),
|
|
128
|
+
v.literal("paused"),
|
|
129
|
+
v.literal("completed"),
|
|
130
|
+
v.literal("error")
|
|
131
|
+
),
|
|
132
|
+
},
|
|
133
|
+
handler: async (ctx, args) => {
|
|
134
|
+
const session = await ctx.db
|
|
135
|
+
.query("sessions")
|
|
136
|
+
.withIndex("bySessionId", (q) => q.eq("sessionId", args.sessionId))
|
|
137
|
+
.first();
|
|
138
|
+
|
|
139
|
+
if (!session) {
|
|
140
|
+
throw new Error(`Session ${args.sessionId} not found`);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const updates: any = {
|
|
144
|
+
status: args.status,
|
|
145
|
+
lastActivityAt: Date.now(),
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
if (args.status === "completed" || args.status === "error") {
|
|
149
|
+
updates.completedAt = Date.now();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
await ctx.db.patch(session._id, updates);
|
|
153
|
+
|
|
154
|
+
return session._id;
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Mutation: Delete session
|
|
159
|
+
export const remove = mutation({
|
|
160
|
+
args: { sessionId: v.string() },
|
|
161
|
+
handler: async (ctx, args) => {
|
|
162
|
+
const session = await ctx.db
|
|
163
|
+
.query("sessions")
|
|
164
|
+
.withIndex("bySessionId", (q) => q.eq("sessionId", args.sessionId))
|
|
165
|
+
.first();
|
|
166
|
+
|
|
167
|
+
if (!session) {
|
|
168
|
+
throw new Error(`Session ${args.sessionId} not found`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
await ctx.db.delete(session._id);
|
|
172
|
+
return { success: true };
|
|
173
|
+
},
|
|
174
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { v } from "convex/values";
|
|
2
|
+
import { mutation, query } from "./_generated/server";
|
|
3
|
+
|
|
4
|
+
// Query: Get a setting by key
|
|
5
|
+
export const get = query({
|
|
6
|
+
args: { userId: v.string(), key: v.string() },
|
|
7
|
+
handler: async (ctx, args) => {
|
|
8
|
+
const setting = await ctx.db
|
|
9
|
+
.query("settings")
|
|
10
|
+
.withIndex("byUserIdAndKey", (q) =>
|
|
11
|
+
q.eq("userId", args.userId).eq("key", args.key)
|
|
12
|
+
)
|
|
13
|
+
.first();
|
|
14
|
+
return setting;
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// Query: List all settings for a user
|
|
19
|
+
export const list = query({
|
|
20
|
+
args: { userId: v.optional(v.string()) },
|
|
21
|
+
handler: async (ctx, args) => {
|
|
22
|
+
if (args.userId) {
|
|
23
|
+
return await ctx.db
|
|
24
|
+
.query("settings")
|
|
25
|
+
.withIndex("byUserId", (q) => q.eq("userId", args.userId!))
|
|
26
|
+
.collect();
|
|
27
|
+
}
|
|
28
|
+
return await ctx.db.query("settings").collect();
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Mutation: Set a setting (upsert)
|
|
33
|
+
export const set = mutation({
|
|
34
|
+
args: {
|
|
35
|
+
userId: v.string(),
|
|
36
|
+
key: v.string(),
|
|
37
|
+
value: v.any(),
|
|
38
|
+
},
|
|
39
|
+
handler: async (ctx, args) => {
|
|
40
|
+
const existing = await ctx.db
|
|
41
|
+
.query("settings")
|
|
42
|
+
.withIndex("byUserIdAndKey", (q) =>
|
|
43
|
+
q.eq("userId", args.userId).eq("key", args.key)
|
|
44
|
+
)
|
|
45
|
+
.first();
|
|
46
|
+
|
|
47
|
+
if (existing) {
|
|
48
|
+
await ctx.db.patch(existing._id, {
|
|
49
|
+
value: args.value,
|
|
50
|
+
updatedAt: Date.now(),
|
|
51
|
+
});
|
|
52
|
+
return existing._id;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return await ctx.db.insert("settings", {
|
|
56
|
+
userId: args.userId,
|
|
57
|
+
key: args.key,
|
|
58
|
+
value: args.value,
|
|
59
|
+
updatedAt: Date.now(),
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Mutation: Delete a setting
|
|
65
|
+
export const remove = mutation({
|
|
66
|
+
args: { userId: v.string(), key: v.string() },
|
|
67
|
+
handler: async (ctx, args) => {
|
|
68
|
+
const existing = await ctx.db
|
|
69
|
+
.query("settings")
|
|
70
|
+
.withIndex("byUserIdAndKey", (q) =>
|
|
71
|
+
q.eq("userId", args.userId).eq("key", args.key)
|
|
72
|
+
)
|
|
73
|
+
.first();
|
|
74
|
+
|
|
75
|
+
if (existing) {
|
|
76
|
+
await ctx.db.delete(existing._id);
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
});
|