fix: restore rectification agent message actions
This commit is contained in:
@@ -8,6 +8,7 @@ import type {
|
||||
import { rectificationAgentV5Protocol, rectificationV4AlgorithmVersion, rectificationV4Protocol } from "./contracts.ts";
|
||||
import { selectRectificationDeploymentMode } from "../rectification-agent/feature-policy.ts";
|
||||
import { CURRENT_RECTIFICATION_PROMPT_VERSION, CURRENT_RECTIFICATION_SKILL_VERSION } from "../rectification-agent/contracts.ts";
|
||||
import { regenerateQuestionRealization } from "../rectification-agent/renderer-agent.ts";
|
||||
import { calculationSpecHash, evidenceSetHash } from "./fingerprints.ts";
|
||||
import { openingQuestion } from "./opening-question.ts";
|
||||
import type { RectificationV4Store } from "./store.ts";
|
||||
@@ -88,6 +89,40 @@ export function createRectificationV4CaseService(store: RectificationV4Store, op
|
||||
return response(input.userId, saved.case, saved.job.id);
|
||||
},
|
||||
|
||||
async regenerateQuestion(input: {
|
||||
readonly userId: string;
|
||||
readonly caseId: string;
|
||||
readonly actionId: string;
|
||||
readonly expectedCaseVersion: number;
|
||||
}) {
|
||||
const current = await store.loadCase(input.userId, input.caseId);
|
||||
if (!current?.currentQuestion || current.deploymentMode !== "v5_agent") return null;
|
||||
const validated = await store.loadLatestValidatedDecision(input.userId, input.caseId);
|
||||
const opportunity = validated?.selectedOpportunity;
|
||||
if (!opportunity) return null;
|
||||
const [events, turns] = await Promise.all([
|
||||
store.loadEvents(input.userId, input.caseId),
|
||||
store.loadTurns(input.userId, input.caseId),
|
||||
]);
|
||||
const prompt = await regenerateQuestionRealization({
|
||||
caseValue: current,
|
||||
currentPrompt: current.currentQuestion.prompt,
|
||||
latestAnswer: turns.at(-1)?.answer ?? "",
|
||||
acceptedEvents: events,
|
||||
opportunity,
|
||||
});
|
||||
const nextQuestion = {
|
||||
...current.currentQuestion,
|
||||
id: randomUUID(),
|
||||
prompt,
|
||||
};
|
||||
return response(input.userId, await store.replaceCurrentQuestion({
|
||||
...input,
|
||||
question: nextQuestion,
|
||||
now: now().toISOString(),
|
||||
}));
|
||||
},
|
||||
|
||||
async reviseEvent(input: {
|
||||
readonly userId: string;
|
||||
readonly caseId: string;
|
||||
|
||||
@@ -63,6 +63,12 @@ export function answerRectificationV4(caseId: string, expectedCaseVersion: numbe
|
||||
});
|
||||
}
|
||||
|
||||
export function regenerateRectificationV4Question(caseId: string, expectedCaseVersion: number) {
|
||||
return post(`/api/rectification/v4/cases/${caseId}/regenerate`, {
|
||||
actionId: globalThis.crypto.randomUUID(), expectedCaseVersion,
|
||||
});
|
||||
}
|
||||
|
||||
export function transitionRectificationV4(
|
||||
caseId: string,
|
||||
expectedCaseVersion: number,
|
||||
|
||||
@@ -69,6 +69,14 @@ export function createRectificationV4MemoryStore(): RectificationV4Store & {
|
||||
.filter((turn) => turn.caseId === caseId)
|
||||
.sort((left, right) => left.caseVersion - right.caseVersion || left.createdAt.localeCompare(right.createdAt));
|
||||
},
|
||||
async loadLatestValidatedDecision(userId, caseId) {
|
||||
const caseValue = cases.get(caseId);
|
||||
if (!caseValue || caseValue.userId !== userId) return null;
|
||||
const latest = [...agentRuns.values()]
|
||||
.filter((run) => run.caseId === caseId)
|
||||
.sort((left, right) => right.caseVersion - left.caseVersion || right.createdAt.localeCompare(left.createdAt))[0];
|
||||
return latest ? validatedDecisions.get(latest.jobId) ?? latest.validatedDecision : null;
|
||||
},
|
||||
async createCase(input) {
|
||||
const replay = actionResults.get(`${input.case.userId}:${input.actionId}`);
|
||||
if (replay) return owned(input.case.userId, replay.caseId);
|
||||
@@ -91,6 +99,29 @@ export function createRectificationV4MemoryStore(): RectificationV4Store & {
|
||||
actionResults.set(`${input.case.userId}:${input.actionId}`, { caseId: input.case.id, jobId: null });
|
||||
return input.case;
|
||||
},
|
||||
async replaceCurrentQuestion(input) {
|
||||
const key = `${input.userId}:${input.actionId}`;
|
||||
const replay = actionResults.get(key);
|
||||
if (replay) return owned(input.userId, replay.caseId);
|
||||
const current = owned(input.userId, input.caseId);
|
||||
if (current.version !== input.expectedCaseVersion) throw new RectificationV4StoreError("stale_version");
|
||||
if (current.deploymentMode !== "v5_agent"
|
||||
|| !["awaiting_answer", "range_ready"].includes(current.status)
|
||||
|| !current.currentQuestion) throw new RectificationV4StoreError("invalid_state");
|
||||
const updated: RectificationV4Case = {
|
||||
...current,
|
||||
version: current.version + 1,
|
||||
currentQuestion: {
|
||||
...input.question,
|
||||
domain: current.currentQuestion.domain,
|
||||
targetEventId: current.currentQuestion.targetEventId,
|
||||
},
|
||||
updatedAt: input.now,
|
||||
};
|
||||
cases.set(current.id, updated);
|
||||
actionResults.set(key, { caseId: current.id, jobId: null });
|
||||
return updated;
|
||||
},
|
||||
async submitAnswer(input) {
|
||||
const key = `${input.userId}:${input.actionId}`;
|
||||
const replay = actionResults.get(key);
|
||||
|
||||
@@ -45,7 +45,16 @@ export interface RectificationV4Store {
|
||||
loadCase(userId: string, caseId: string): Promise<RectificationV4Case | null>;
|
||||
loadEvents(userId: string, caseId: string): Promise<readonly LifeEventRevision[]>;
|
||||
loadTurns(userId: string, caseId: string): Promise<readonly RectificationV4Turn[]>;
|
||||
loadLatestValidatedDecision(userId: string, caseId: string): Promise<ValidatedDecision | null>;
|
||||
createCase(input: { readonly case: RectificationV4Case; readonly actionId: string }): Promise<RectificationV4Case>;
|
||||
replaceCurrentQuestion(input: {
|
||||
readonly userId: string;
|
||||
readonly caseId: string;
|
||||
readonly actionId: string;
|
||||
readonly expectedCaseVersion: number;
|
||||
readonly question: RectificationV4Question;
|
||||
readonly now: string;
|
||||
}): Promise<RectificationV4Case>;
|
||||
submitAnswer(input: {
|
||||
readonly userId: string;
|
||||
readonly caseId: string;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
import { validatedDecisionSchema, type ValidatedDecision } from "../rectification-agent/contracts.ts";
|
||||
import {
|
||||
candidateSnapshotSchema,
|
||||
lifeEventRevisionSchema,
|
||||
@@ -199,6 +200,14 @@ export function createRectificationV4SupabaseStore(supabase: SupabaseClient): Re
|
||||
loadCase: loadCaseById,
|
||||
loadEvents: loadEventsByCase,
|
||||
loadTurns: loadTurnsByCase,
|
||||
async loadLatestValidatedDecision(userId, caseId): Promise<ValidatedDecision | null> {
|
||||
const { data, error } = await supabase.from("birth_time_rectification_agent_runs")
|
||||
.select("validated_decision_json").eq("case_id", caseId).eq("user_id", userId)
|
||||
.order("case_version", { ascending: false }).order("created_at", { ascending: false })
|
||||
.limit(1).maybeSingle();
|
||||
if (error) throw storeError(error);
|
||||
return data ? validatedDecisionSchema.parse((data as Row).validated_decision_json) : null;
|
||||
},
|
||||
async createCase(input) {
|
||||
const id = String(await rpc("create_birth_time_rectification_v5_case", {
|
||||
p_user_id: input.case.userId,
|
||||
@@ -222,6 +231,19 @@ export function createRectificationV4SupabaseStore(supabase: SupabaseClient): Re
|
||||
if (!value) throw new RectificationV4StoreError("not_found");
|
||||
return value;
|
||||
},
|
||||
async replaceCurrentQuestion(input) {
|
||||
const id = String(await rpc("replace_birth_time_rectification_v4_current_question", {
|
||||
p_user_id: input.userId,
|
||||
p_case_id: input.caseId,
|
||||
p_action_id: input.actionId,
|
||||
p_expected_version: input.expectedCaseVersion,
|
||||
p_question: input.question,
|
||||
p_now: input.now,
|
||||
}));
|
||||
const value = await loadCaseById(input.userId, id);
|
||||
if (!value) throw new RectificationV4StoreError("not_found");
|
||||
return value;
|
||||
},
|
||||
async submitAnswer(input) {
|
||||
const jobId = String(await rpc("submit_birth_time_rectification_v4_answer", {
|
||||
p_user_id: input.userId,
|
||||
|
||||
Reference in New Issue
Block a user