9958e00abc
Rectification stays optional. Reported minutes can consult and generate reports; date-plus-period uses a declared window instead of a midpoint or 00:00. Updates BUG-341. Co-authored-by: Cursor <cursoragent@cursor.com>
86 lines
3.0 KiB
TypeScript
86 lines
3.0 KiB
TypeScript
import { z } from "zod";
|
|
import type { DeclaredBirthWindowConsultation } from "./consultation-route-service.ts";
|
|
|
|
const clockSchema = z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/);
|
|
|
|
export const declaredWindowChartPacketSchema = z.object({
|
|
declared_range: z.object({
|
|
start: clockSchema,
|
|
end: clockSchema,
|
|
wraps_midnight: z.boolean(),
|
|
}),
|
|
probe_count: z.number().int().min(2).max(4),
|
|
probes: z.array(z.object({
|
|
clock: clockSchema,
|
|
role: z.enum(["range_start", "interior", "range_end"]),
|
|
}).strict()).min(2).max(4),
|
|
stable_layers: z.object({
|
|
planet_signs: z.record(z.string()),
|
|
moon_nakshatra: z.string().optional(),
|
|
ascendant_sign: z.string().optional(),
|
|
house_cusp_signs: z.record(z.string()).optional(),
|
|
}).passthrough(),
|
|
varying_layers: z.object({
|
|
planet_signs: z.record(z.array(z.string())).optional(),
|
|
moon_nakshatra: z.array(z.string()).optional(),
|
|
ascendant_signs: z.array(z.string()).optional(),
|
|
house_cusp_signs: z.record(z.array(z.string())).optional(),
|
|
}).passthrough(),
|
|
blocked_layers: z.array(z.string()),
|
|
answer_policy: z.object({
|
|
can_answer_direction: z.boolean(),
|
|
can_answer_precise_timing: z.literal(false),
|
|
birth_time_confidence: z.literal("declared_window"),
|
|
candidate_is_confirmed: z.literal(false),
|
|
}).passthrough(),
|
|
result_hash: z.string().min(1),
|
|
}).passthrough();
|
|
|
|
export type DeclaredWindowChartPacket = z.infer<typeof declaredWindowChartPacketSchema>;
|
|
|
|
type LoadDeclaredWindowChartInput = Readonly<{
|
|
window: DeclaredBirthWindowConsultation;
|
|
fetchImpl?: typeof fetch;
|
|
apiBase?: string;
|
|
signal?: AbortSignal;
|
|
}>;
|
|
|
|
export async function fetchDeclaredWindowChart(
|
|
input: LoadDeclaredWindowChartInput,
|
|
): Promise<DeclaredWindowChartPacket> {
|
|
const fetchImpl = input.fetchImpl ?? fetch;
|
|
const apiBase = input.apiBase ?? process.env.JYOTISH_API_BASE ?? "http://127.0.0.1:5200";
|
|
const { toolInput } = input.window;
|
|
const response = await fetchImpl(`${apiBase}/api/declared_window_chart`, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({
|
|
year: toolInput.year,
|
|
month: toolInput.month,
|
|
day: toolInput.day,
|
|
lat: toolInput.lat,
|
|
lon: toolInput.lon,
|
|
tz: toolInput.tz,
|
|
range_start: toolInput.rangeStart,
|
|
range_end: toolInput.rangeEnd,
|
|
}),
|
|
cache: "no-store",
|
|
signal: input.signal,
|
|
});
|
|
if (!response.ok) {
|
|
throw new Error("declared_window_chart_unavailable");
|
|
}
|
|
const payload = await response.json().catch(() => null);
|
|
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
throw new Error("declared_window_chart_unavailable");
|
|
}
|
|
const record = payload as Record<string, unknown>;
|
|
if (record.success !== true || record.endpoint !== "declared_window_chart") {
|
|
throw new Error("declared_window_chart_unavailable");
|
|
}
|
|
if ("hour" in record || "minute" in record || "birth_time" in record) {
|
|
throw new Error("declared_window_chart_unavailable");
|
|
}
|
|
return declaredWindowChartPacketSchema.parse(record.packet);
|
|
}
|