OpenPond
1Branch0Tags
GL
glucryptochore: bump opentool to v0.8.28
cba6ada3 days ago3Commits
typescript
import { z } from "zod"; type JsonValue = Record<string, unknown> | Array<unknown> | string | number | boolean | null; export const subAgentSchema = z.object({ appId: z.string().min(1), deploymentId: z.string().min(1), toolName: z.string().min(1), displayName: z.string().optional(), method: z.enum(["GET", "POST"]).optional(), body: z.unknown().optional(), }); export const configSchema = z.object({ subAgents: z.array(subAgentSchema).optional(), channels: z .object({ email: z.boolean().optional(), telegram: z.boolean().optional(), }) .optional(), schedule: z .object({ cron: z.string().min(1).optional(), enabled: z.boolean().optional(), notifyEmail: z.boolean().optional(), }) .optional(), }); export type DailySummaryConfig = z.infer<typeof configSchema>; function parseJson(raw: string | null): JsonValue | null { if (!raw) return null; try { return JSON.parse(raw) as JsonValue; } catch { return null; } } function mergeConfig(base: DailySummaryConfig, override: DailySummaryConfig): DailySummaryConfig { return { ...base, ...override, channels: { ...base.channels, ...override.channels, }, schedule: { ...base.schedule, ...override.schedule, }, subAgents: override.subAgents ?? base.subAgents, }; } export async function readConfig(): Promise<DailySummaryConfig> { let config: DailySummaryConfig = {}; const envConfig = parseJson(process.env.OPENPOND_DAILY_SNAPSHOT_CONFIG ?? null); if (envConfig && configSchema.safeParse(envConfig).success) { config = mergeConfig(config, envConfig as DailySummaryConfig); } return config; } function resolveBaseUrl() { const baseUrl = process.env.BASE_URL; if (!baseUrl) { throw new Error("BASE_URL is required for Daily Snapshot (API host)."); } return baseUrl.replace(/\/$/, ""); } async function fetchJson( url: string, options: RequestInit ): Promise<{ ok: boolean; status: number; data: JsonValue | null }> { const response = await fetch(url, options); const text = await response.text(); const data = parseJson(text); return { ok: response.ok, status: response.status, data }; } export async function openpondRequest(path: string, options: RequestInit) { const apiKey = process.env.OPENPOND_API_KEY; if (!apiKey) { throw new Error("OPENPOND_API_KEY is required for daily summary."); } const url = `${resolveBaseUrl()}${path}`; const headers = new Headers(options.headers ?? {}); headers.set("openpond-api-key", apiKey); if (!headers.has("Authorization")) { headers.set("Authorization", `ApiKey ${apiKey}`); } return fetchJson(url, { ...options, headers }); } export function formatDigest(params: { runAt: string; performance: JsonValue | null; subAgentResults: Array<{ name: string; ok: boolean; data?: JsonValue | null; missing?: boolean; }>; }) { const lines: string[] = []; lines.push(`Daily Snapshot · ${params.runAt}`); lines.push(""); if (params.performance) { lines.push("Performance:"); lines.push(JSON.stringify(params.performance, null, 2)); lines.push(""); } if (params.subAgentResults.length > 0) { lines.push("Add-ons:"); for (const result of params.subAgentResults) { const status = result.missing ? "missing" : result.ok ? "ok" : "failed"; lines.push(`- ${result.name}: ${status}`); if (result.data && !result.missing) { const snippet = JSON.stringify(result.data); lines.push(` ${snippet.slice(0, 400)}${snippet.length > 400 ? "…" : ""}`); } } lines.push(""); } return lines.join("\n").trim(); }