Files
mnote/wolai-frontend/convex/agentActions.ts
T
2026-04-13 19:21:42 +08:00

132 lines
3.5 KiB
TypeScript

import { mutation, query } from "./_generated/server";
import { v } from "convex/values";
import { nowIso } from "./_utils/time";
import type { MutationCtx, QueryCtx } from "./_generated/server";
async function assertWorkspaceMember(
ctx: QueryCtx | MutationCtx,
userId: string,
workspaceId: string,
) {
const membership = await ctx.db
.query("workspace_members")
.withIndex("by_workspace_user", (q) =>
q.eq("workspace_id", workspaceId).eq("user_id", userId),
)
.first();
if (!membership) {
throw new Error("无权访问该工作空间");
}
return membership;
}
export const getById = query({
args: {
userId: v.string(),
workspaceId: v.string(),
actionId: v.string(),
},
handler: async (ctx, args) => {
await assertWorkspaceMember(ctx, args.userId, args.workspaceId);
return await ctx.db
.query("agent_actions")
.withIndex("by_action_id", (q) => q.eq("id", args.actionId))
.first();
},
});
export const listBySession = query({
args: {
userId: v.string(),
workspaceId: v.string(),
sessionId: v.string(),
},
handler: async (ctx, args) => {
await assertWorkspaceMember(ctx, args.userId, args.workspaceId);
return await ctx.db
.query("agent_actions")
.withIndex("by_workspace_session", (q) =>
q.eq("workspace_id", args.workspaceId).eq("session_id", args.sessionId),
)
.collect();
},
});
export const createStarted = mutation({
args: {
userId: v.string(),
workspaceId: v.string(),
actionId: v.string(),
sessionId: v.string(),
actionType: v.string(),
actor: v.union(v.literal("human"), v.literal("agent"), v.literal("automation")),
input: v.any(),
startedAt: v.string(),
},
handler: async (ctx, args) => {
await assertWorkspaceMember(ctx, args.userId, args.workspaceId);
await ctx.db.insert("agent_actions", {
id: args.actionId,
workspace_id: args.workspaceId,
session_id: args.sessionId,
action_type: args.actionType,
status: "running",
actor: args.actor,
input: args.input,
output: null,
error: null,
started_at: args.startedAt,
finished_at: null,
});
return { ok: true, actionId: args.actionId };
},
});
export const markSucceeded = mutation({
args: {
userId: v.string(),
workspaceId: v.string(),
actionId: v.string(),
output: v.any(),
finishedAt: v.string(),
},
handler: async (ctx, args) => {
await assertWorkspaceMember(ctx, args.userId, args.workspaceId);
const row = await ctx.db
.query("agent_actions")
.withIndex("by_action_id", (q) => q.eq("id", args.actionId))
.first();
if (!row) throw new Error("action log not found");
await ctx.db.patch(row._id, {
status: "succeeded",
output: args.output,
finished_at: args.finishedAt,
});
return { ok: true };
},
});
export const markFailed = mutation({
args: {
userId: v.string(),
workspaceId: v.string(),
actionId: v.string(),
error: v.string(),
finishedAt: v.string(),
},
handler: async (ctx, args) => {
await assertWorkspaceMember(ctx, args.userId, args.workspaceId);
const row = await ctx.db
.query("agent_actions")
.withIndex("by_action_id", (q) => q.eq("id", args.actionId))
.first();
if (!row) throw new Error("action log not found");
await ctx.db.patch(row._id, {
status: "failed",
error: args.error,
finished_at: args.finishedAt,
});
return { ok: true };
},
});