refactor: Business logic and dependencies updates
- 核心服务代码更新 (db, server, auth, proxy) - Agent 相关模块更新 (mindspace, experience) - 前端组件和 hooks 更新 - 数据库 schema 更新 - 依赖版本更新
This commit is contained in:
@@ -305,6 +305,7 @@ export function createMindSpaceAgentRunner({
|
||||
apiSecret,
|
||||
userAuth,
|
||||
agentJobService,
|
||||
experienceService = null,
|
||||
executeSessionReply = defaultExecuteSessionReply,
|
||||
apiFetchImpl = null,
|
||||
}) {
|
||||
@@ -324,11 +325,15 @@ export function createMindSpaceAgentRunner({
|
||||
});
|
||||
});
|
||||
|
||||
const runJob = async (jobId) => {
|
||||
// preClaimed lets a polling worker that already atomically claimed the job
|
||||
// (via claimNextJob + SKIP LOCKED) hand the claim payload straight in, instead
|
||||
// of claiming a second time. The HTTP-triggered path calls runJob(jobId) with
|
||||
// no preClaimed and claims here as before.
|
||||
const runJob = async (jobId, preClaimed = null) => {
|
||||
let claim = null;
|
||||
let sessionId = null;
|
||||
try {
|
||||
claim = await agentJobService.claimJob(jobId);
|
||||
claim = preClaimed ?? (await agentJobService.claimJob(jobId));
|
||||
const gate = await userAuth.canUseChat(claim.userId);
|
||||
if (!gate.ok) {
|
||||
throw runnerError(gate.message || '当前用户无法执行 Agent 任务', 'worker_unavailable');
|
||||
@@ -377,7 +382,11 @@ export function createMindSpaceAgentRunner({
|
||||
const localAsset = await agentJobService.getAssetForJob(jobId, claim.jobToken, asset.assetId);
|
||||
assetContexts.push(await readAssetContext(localAsset));
|
||||
}
|
||||
const prompt = buildAgentJobPrompt(claim, assetContexts);
|
||||
let prompt = buildAgentJobPrompt(claim, assetContexts);
|
||||
// Inject shared experience (etat C): relevant lessons all instances learned.
|
||||
// Best-effort — retrieval must never block or fail a job.
|
||||
const relevant = await retrieveExperience(claim.instruction);
|
||||
if (relevant) prompt = `${relevant}\n\n${prompt}`;
|
||||
const requestId = crypto.randomUUID();
|
||||
const reply = await executeSessionReply(apiFetch, sessionId, requestId, prompt);
|
||||
const parsed = normalizeStructuredResult(extractJsonObject(reply.text));
|
||||
@@ -386,7 +395,7 @@ export function createMindSpaceAgentRunner({
|
||||
await userAuth.billSessionUsage(claim.userId, sessionId, reply.tokenState, requestId);
|
||||
}
|
||||
|
||||
return agentJobService.completeJob(jobId, claim.jobToken, {
|
||||
const completed = await agentJobService.completeJob(jobId, claim.jobToken, {
|
||||
title: parsed.title,
|
||||
summary: parsed.summary,
|
||||
content: parsed.content,
|
||||
@@ -395,6 +404,9 @@ export function createMindSpaceAgentRunner({
|
||||
templateId: parsed.templateId,
|
||||
sourceAssetIds: claim.allowedAssets.map((asset) => asset.assetId),
|
||||
});
|
||||
// Record the outcome as shared experience so other instances benefit.
|
||||
await recordExperience(claim, sessionId, parsed);
|
||||
return completed;
|
||||
} catch (error) {
|
||||
if (claim?.jobToken) {
|
||||
await agentJobService
|
||||
@@ -409,6 +421,39 @@ export function createMindSpaceAgentRunner({
|
||||
}
|
||||
};
|
||||
|
||||
// Returns a prompt-ready block of relevant prior experience, or '' if none /
|
||||
// disabled / on any error. Never throws.
|
||||
async function retrieveExperience(instruction) {
|
||||
if (!experienceService || !instruction) return '';
|
||||
try {
|
||||
const hits = await experienceService.search(instruction, { limit: 3 });
|
||||
if (!hits.length) return '';
|
||||
const lines = hits.map((h) => `- ${h.title}: ${h.body}`).join('\n');
|
||||
return `# 相关经验(供参考,来自历史任务)\n${lines}`;
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
// Persists a one-line lesson from a completed job. Best-effort; never throws.
|
||||
async function recordExperience(claim, sessionId, parsed) {
|
||||
if (!experienceService) return;
|
||||
try {
|
||||
const title = String(parsed?.title ?? claim.instruction ?? '').slice(0, 200);
|
||||
const summary = String(parsed?.summary ?? '').trim();
|
||||
if (!title || !summary) return;
|
||||
await experienceService.record({
|
||||
kind: 'task_outcome',
|
||||
title,
|
||||
body: summary,
|
||||
sourceSessionId: sessionId,
|
||||
sourceUserId: claim.userId,
|
||||
});
|
||||
} catch {
|
||||
// swallow — experience recording is non-critical
|
||||
}
|
||||
}
|
||||
|
||||
return { runJob };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user