Mastra intermediate text-delta was published as answer.delta, then set-focus domain errors reset the attempt and replayed evidence. Publish only the terminal no-tool step, persist the next probe on the server, and ground batch quotes in the source turn. Co-authored-by: Cursor <cursoragent@cursor.com>
231 lines
6.6 KiB
TypeScript
231 lines
6.6 KiB
TypeScript
/**
|
|
* V9 public execution receipts and activity event allowlists.
|
|
*
|
|
* The web client may only ever see allowlisted phases, tool names and
|
|
* activity events. Raw provider reasoning payloads, tool payloads, internal
|
|
* scores, birth data and provider metadata must never reach the client.
|
|
* Chain-of-thought is never a public event. Coarse `activity.changed`
|
|
* replaces token-level thinking on the browser stream.
|
|
*/
|
|
|
|
export const PUBLIC_RECTIFICATION_PHASES = [
|
|
"run.started",
|
|
"skill.started",
|
|
"skill.loaded",
|
|
"skill.bound",
|
|
"case.loaded",
|
|
"intent.classified",
|
|
"evidence.proposed",
|
|
"evidence.confirmed",
|
|
"candidates.comparing",
|
|
"candidates.updated",
|
|
"diagnostics.completed",
|
|
"candidate.accepted",
|
|
"birth_time.confirmed",
|
|
"answer.composed",
|
|
"billing.settled",
|
|
"answer.delta",
|
|
"activity.changed",
|
|
"choice.applied",
|
|
"attempt.reset",
|
|
"run.completed",
|
|
"run.failed",
|
|
] as const;
|
|
|
|
export type PublicRectificationPhase =
|
|
(typeof PUBLIC_RECTIFICATION_PHASES)[number];
|
|
|
|
export const PUBLIC_RECTIFICATION_TOOLS = [
|
|
"rectification-read-case",
|
|
"rectification-set-focus",
|
|
"rectification-resolve-focus",
|
|
"rectification-record-evidence-batch",
|
|
"rectification-propose-evidence",
|
|
"rectification-confirm-evidence",
|
|
"rectification-revise-evidence",
|
|
"rectification-compare-candidates",
|
|
"rectification-read-diagnostics",
|
|
"rectification-offer-candidates",
|
|
"rectification-accept-candidate",
|
|
"rectification-confirm-birth-time",
|
|
"rectification-close-case",
|
|
] as const;
|
|
|
|
export type PublicRectificationTool =
|
|
(typeof PUBLIC_RECTIFICATION_TOOLS)[number];
|
|
|
|
export const RECTIFICATION_AGENT_TOOLS = PUBLIC_RECTIFICATION_TOOLS.filter(
|
|
(tool) => tool !== "rectification-set-focus",
|
|
);
|
|
|
|
export const PUBLIC_RECTIFICATION_METHODS = [
|
|
"d1-rashi",
|
|
"d2-hora",
|
|
"d3-drekkana",
|
|
"d4-chaturthamsha",
|
|
"d5-panchamsha",
|
|
"d7-saptamsha",
|
|
"d9-navamsa",
|
|
"d10-dashamsa",
|
|
"d11-labhamsha",
|
|
"d12-dwadashamsha",
|
|
"d24-chaturvimshamsha",
|
|
"d30-trimshamsha",
|
|
"vimshottari-dasha",
|
|
"narayana-dasha",
|
|
"gochara",
|
|
"ashtakavarga",
|
|
"shadbala",
|
|
"arudha-pada",
|
|
"functional-benefic-malefic",
|
|
] as const;
|
|
|
|
export type PublicRectificationMethod =
|
|
(typeof PUBLIC_RECTIFICATION_METHODS)[number];
|
|
|
|
export const RECTIFICATION_ACTIVITY_STATUSES = [
|
|
"started",
|
|
"completed",
|
|
"failed",
|
|
] as const;
|
|
|
|
export type RectificationActivityStatus =
|
|
(typeof RECTIFICATION_ACTIVITY_STATUSES)[number];
|
|
|
|
export const PUBLIC_RECTIFICATION_ACTIVITIES = [
|
|
"reading_case",
|
|
"recording_answer",
|
|
"updating_candidates",
|
|
"checking_stability",
|
|
"preparing_question",
|
|
"preparing_result",
|
|
] as const;
|
|
|
|
export type PublicRectificationActivity =
|
|
(typeof PUBLIC_RECTIFICATION_ACTIVITIES)[number];
|
|
|
|
export type RectificationActivityChangedEvent = Readonly<{
|
|
type: "activity.changed";
|
|
activity: PublicRectificationActivity;
|
|
}>;
|
|
|
|
export type RectificationChoiceAppliedEvent = Readonly<{
|
|
type: "choice.applied";
|
|
questionId: string;
|
|
}>;
|
|
|
|
export type RectificationActivityEvent = Readonly<{
|
|
type: "tool.activity";
|
|
tool: PublicRectificationTool;
|
|
status: RectificationActivityStatus;
|
|
methods?: readonly PublicRectificationMethod[];
|
|
code?: string;
|
|
}>;
|
|
|
|
export const RECEIPT_STATUSES = [
|
|
"completed",
|
|
"degraded",
|
|
"blocked",
|
|
"failed",
|
|
] as const;
|
|
|
|
export type RectificationReceiptStatus =
|
|
(typeof RECEIPT_STATUSES)[number];
|
|
|
|
export type RectificationExecutionReceipt = Readonly<{
|
|
turnId: string;
|
|
skillName: string;
|
|
skillVersion: string;
|
|
engineVersion: string | null;
|
|
phases: readonly PublicRectificationPhase[];
|
|
toolsUsed: readonly PublicRectificationTool[];
|
|
methods: readonly PublicRectificationMethod[];
|
|
status: RectificationReceiptStatus;
|
|
startedAt: string;
|
|
completedAt: string;
|
|
}>;
|
|
|
|
const PHASE_SET = new Set<string>(PUBLIC_RECTIFICATION_PHASES);
|
|
const TOOL_SET = new Set<string>(PUBLIC_RECTIFICATION_TOOLS);
|
|
const METHOD_SET = new Set<string>(PUBLIC_RECTIFICATION_METHODS);
|
|
const ACTIVITY_STATUS_SET = new Set<string>(RECTIFICATION_ACTIVITY_STATUSES);
|
|
const ACTIVITY_SET = new Set<string>(PUBLIC_RECTIFICATION_ACTIVITIES);
|
|
|
|
export function isPublicRectificationPhase(
|
|
value: unknown,
|
|
): value is PublicRectificationPhase {
|
|
return typeof value === "string" && PHASE_SET.has(value);
|
|
}
|
|
|
|
export function isPublicRectificationTool(
|
|
value: unknown,
|
|
): value is PublicRectificationTool {
|
|
return typeof value === "string" && TOOL_SET.has(value);
|
|
}
|
|
|
|
export function isPublicRectificationMethod(
|
|
value: unknown,
|
|
): value is PublicRectificationMethod {
|
|
return typeof value === "string" && METHOD_SET.has(value);
|
|
}
|
|
|
|
export function isRectificationActivityStatus(
|
|
value: unknown,
|
|
): value is RectificationActivityStatus {
|
|
return typeof value === "string" && ACTIVITY_STATUS_SET.has(value);
|
|
}
|
|
|
|
export function isPublicRectificationActivity(
|
|
value: unknown,
|
|
): value is PublicRectificationActivity {
|
|
return typeof value === "string" && ACTIVITY_SET.has(value);
|
|
}
|
|
|
|
const TOOL_ACTIVITY: Readonly<Partial<Record<PublicRectificationTool, PublicRectificationActivity>>> = {
|
|
"rectification-read-case": "reading_case",
|
|
"rectification-record-evidence-batch": "recording_answer",
|
|
"rectification-propose-evidence": "recording_answer",
|
|
"rectification-confirm-evidence": "recording_answer",
|
|
"rectification-revise-evidence": "recording_answer",
|
|
"rectification-resolve-focus": "recording_answer",
|
|
"rectification-compare-candidates": "updating_candidates",
|
|
"rectification-read-diagnostics": "checking_stability",
|
|
"rectification-set-focus": "preparing_question",
|
|
"rectification-offer-candidates": "preparing_result",
|
|
"rectification-accept-candidate": "preparing_result",
|
|
"rectification-confirm-birth-time": "preparing_result",
|
|
"rectification-close-case": "preparing_result",
|
|
};
|
|
|
|
export function activityForRectificationTool(
|
|
tool: PublicRectificationTool,
|
|
): PublicRectificationActivity {
|
|
return TOOL_ACTIVITY[tool] ?? "preparing_question";
|
|
}
|
|
|
|
/**
|
|
* The exact NDJSON activity stream events the API is allowed to emit.
|
|
* Anything not in this list must be dropped before it reaches the browser.
|
|
*/
|
|
export const PUBLIC_ACTIVITY_EVENTS = PUBLIC_RECTIFICATION_PHASES;
|
|
|
|
export function safeActivityEvent(
|
|
value: unknown,
|
|
): PublicRectificationPhase | null {
|
|
return isPublicRectificationPhase(value) ? value : null;
|
|
}
|
|
|
|
/**
|
|
* Denied content that must never appear in any public projection.
|
|
* The working candidate range is user-visible (BUG-074), but the baseline
|
|
* birth snapshot, raw scores and internal identifiers are not.
|
|
*/
|
|
export const DENIED_PUBLIC_CONTENT = [
|
|
"raw provider chain-of-thought payload",
|
|
"unsanitized reasoning",
|
|
"tool payload",
|
|
"baseline birth snapshot",
|
|
"user_id",
|
|
"engine score",
|
|
] as const;
|