Files
2026-11-14 09:56:45 +00:00

48 lines
2.2 KiB
TypeScript

// The proposals subscriber that sends a reviewer's decision on a platform-extracted line back to the
// platform as Document Items feedback (core/item-feedback.ts).
//
// It reads the proposal the event names in the delivery's own scope (the relay rebuilt it from the
// outbox record, so another organization's proposal is not found), and does nothing for a proposal of
// another target, a line the platform did not extract, or a worker that bound no `DOCUMENT_ITEMS`.
// Feedback improves the platform's profile; it never decides anything here, so a delivery whose
// platform call fails is retried by the relay and a decision is never undone by it.
import { type EventContext, internal } from "@conusai-kit/core"
import { DATA_SOURCE } from "@conusai-kit/data"
import { FILES_SCOPE } from "@conusai-kit/files"
import { proposals } from "@conusai-kit/proposals"
import { LINE_TARGET_KEY } from "../contract/index.js"
import { feedbackOf } from "../core/item-feedback.js"
import { DOCUMENT_ITEMS } from "./platform-items-extractor.js"
interface Decided {
readonly orgId: string
readonly proposalId: string
readonly targetKey: string
}
async function forward(
decision: "approved" | "edited" | "rejected",
payload: Decided,
ctx: EventContext,
): Promise<void> {
if (payload.targetKey !== LINE_TARGET_KEY || !ctx.container.has(DOCUMENT_ITEMS)) return
const items = ctx.container.resolve(DOCUMENT_ITEMS)
const scope = ctx.container.resolve(FILES_SCOPE)
if (scope.orgId !== payload.orgId) {
throw internal(`a proposals event of organization ${payload.orgId} was delivered in ${scope.orgId}`)
}
const proposal = await ctx.container.resolve(DATA_SOURCE).forScope(scope).of(proposals).get(payload.proposalId)
if (!proposal) return
const sent = feedbackOf(decision, proposal.change)
if (!sent) return
await items.feedback(sent.runId, [sent.feedback])
}
export const onLineApproved = (event: { name: string; payload: Decided }, ctx: EventContext) =>
forward("approved", event.payload, ctx)
export const onLineRejected = (event: { name: string; payload: Decided }, ctx: EventContext) =>
forward("rejected", event.payload, ctx)
export const onLineEdited = (event: { name: string; payload: Decided }, ctx: EventContext) =>
forward("edited", event.payload, ctx)