0.3 增加登录模块
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
import { internalAction, internalMutation, internalQuery, mutation, query } from "./_generated/server";
|
||||
import { v } from "convex/values";
|
||||
import { nowIso } from "./_utils/time";
|
||||
import { internal } from "./_generated/api";
|
||||
import { api, internal } from "./_generated/api";
|
||||
import { lightragIngestText } from "./_utils/lightrag";
|
||||
import { extractTextFromDocumentContent, extractTextFromMindmapData } from "./_utils/text";
|
||||
import { enqueueIngestDocumentJob, enqueueIngestMediaAssetJob, enqueueIngestMindmapJob } from "./_utils/ingestJobs";
|
||||
|
||||
export const get = query({
|
||||
args: { userId: v.string(), id: v.string() },
|
||||
@@ -52,6 +55,35 @@ export const enqueueDemo = mutation({
|
||||
},
|
||||
});
|
||||
|
||||
export const enqueueRagIndexDocument = mutation({
|
||||
args: { userId: v.string(), documentId: v.string() },
|
||||
handler: async (ctx, args) => {
|
||||
const { id } = await enqueueIngestDocumentJob(ctx, { userId: args.userId, documentId: args.documentId, debounceMs: 0 });
|
||||
return { ok: true, id };
|
||||
},
|
||||
});
|
||||
|
||||
export const enqueueRagIndexMindmap = mutation({
|
||||
args: { userId: v.string(), docId: v.string(), mindmapId: v.string() },
|
||||
handler: async (ctx, args) => {
|
||||
const { id } = await enqueueIngestMindmapJob(ctx, {
|
||||
userId: args.userId,
|
||||
docId: args.docId,
|
||||
mindmapId: args.mindmapId,
|
||||
debounceMs: 0,
|
||||
});
|
||||
return { ok: true, id };
|
||||
},
|
||||
});
|
||||
|
||||
export const enqueueRagIndexMediaAsset = mutation({
|
||||
args: { userId: v.string(), assetId: v.string() },
|
||||
handler: async (ctx, args) => {
|
||||
const { id } = await enqueueIngestMediaAssetJob(ctx, { userId: args.userId, assetId: args.assetId, debounceMs: 0 });
|
||||
return { ok: true, id };
|
||||
},
|
||||
});
|
||||
|
||||
export const start = internalMutation({
|
||||
args: { id: v.string() },
|
||||
handler: async (ctx, args) => {
|
||||
@@ -85,6 +117,88 @@ export const run = internalAction({
|
||||
return;
|
||||
}
|
||||
|
||||
if (job.type === "ingest.rag_index_document") {
|
||||
const documentId = String(job.payload?.documentId ?? "").trim();
|
||||
if (!documentId) throw new Error("缺少 documentId");
|
||||
|
||||
const [meta, contentRes] = await Promise.all([
|
||||
ctx.runQuery(api.documents.getMeta, { userId: job.user_id, id: documentId }),
|
||||
ctx.runQuery(api.documents.getContent, { userId: job.user_id, id: documentId }),
|
||||
]);
|
||||
|
||||
if (!meta) throw new Error("页面不存在或无权限");
|
||||
|
||||
const title = meta.title ?? "无标题";
|
||||
const text = extractTextFromDocumentContent(contentRes?.content ?? null);
|
||||
const fileSource = `document:${documentId}`;
|
||||
const { trackId } = await lightragIngestText({ fileSource, text: `# ${title}\n\n${text}` });
|
||||
|
||||
await ctx.runMutation(internal.jobs.finishSuccess, {
|
||||
id: args.id,
|
||||
result: { ok: true, kind: "document", documentId, trackId },
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (job.type === "ingest.rag_index_mindmap") {
|
||||
const docId = String(job.payload?.docId ?? "").trim();
|
||||
const mindmapId = String(job.payload?.mindmapId ?? "").trim();
|
||||
if (!docId) throw new Error("缺少 docId");
|
||||
if (!mindmapId) throw new Error("缺少 mindmapId");
|
||||
|
||||
const [docMeta, mindmapRes] = await Promise.all([
|
||||
ctx.runQuery(api.documents.getMeta, { userId: job.user_id, id: docId }),
|
||||
ctx.runQuery(api.mindmaps.get, { userId: job.user_id, docId, mindmapId }),
|
||||
]);
|
||||
|
||||
if (!docMeta) throw new Error("页面不存在或无权限");
|
||||
if (!mindmapRes?.ok) throw new Error("导图读取失败");
|
||||
if (!mindmapRes.meta?.exists) {
|
||||
await ctx.runMutation(internal.jobs.finishSuccess, {
|
||||
id: args.id,
|
||||
result: { ok: true, kind: "mindmap", docId, mindmapId, skipped: true, reason: "mindmap_not_exists" },
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const title = docMeta.title ?? "无标题";
|
||||
const text = extractTextFromMindmapData(mindmapRes.data ?? null);
|
||||
const fileSource = `mindmap:${docId}:${mindmapId}`;
|
||||
const { trackId } = await lightragIngestText({ fileSource, text: `# ${title}\n\n${text}` });
|
||||
|
||||
await ctx.runMutation(internal.jobs.finishSuccess, {
|
||||
id: args.id,
|
||||
result: { ok: true, kind: "mindmap", docId, mindmapId, trackId },
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (job.type === "ingest.rag_index_media_asset") {
|
||||
const assetId = String(job.payload?.assetId ?? "").trim();
|
||||
if (!assetId) throw new Error("缺少 assetId");
|
||||
|
||||
const asset = await ctx.runQuery(api.mediaAssets.getById, { userId: job.user_id, id: assetId });
|
||||
if (!asset) throw new Error("资源不存在或无权限");
|
||||
|
||||
const title = asset.file_name ?? asset.id;
|
||||
const text = String(asset.ocr_text ?? "").trim();
|
||||
if (!text) {
|
||||
await ctx.runMutation(internal.jobs.finishSuccess, {
|
||||
id: args.id,
|
||||
result: { ok: true, kind: "media_asset", assetId, skipped: true, reason: "empty_ocr_text" },
|
||||
});
|
||||
return;
|
||||
}
|
||||
const fileSource = `media:${assetId}`;
|
||||
const { trackId } = await lightragIngestText({ fileSource, text: `# ${title}\n\n${text}` });
|
||||
|
||||
await ctx.runMutation(internal.jobs.finishSuccess, {
|
||||
id: args.id,
|
||||
result: { ok: true, kind: "media_asset", assetId, trackId },
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error(`未知任务类型:${job.type}`);
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
@@ -103,6 +217,7 @@ export const _getInternal = internalQuery({
|
||||
if (!job) return null;
|
||||
return {
|
||||
id: job.id,
|
||||
user_id: job.user_id,
|
||||
type: job.type,
|
||||
status: job.status,
|
||||
payload: job.payload,
|
||||
|
||||
Reference in New Issue
Block a user