openpondai/agents/my-openpond
OpenTool app
typescript
import type { DailySummaryConfig } from "./config";
import { readConfig } from "./config";
import { openpondRequest } from "./openpond";
export type JsonValue =
| Record<string, unknown>
| Array<unknown>
| string
| number
| boolean
| null;
export type DailySummarySubAgentResult = {
name: string;
ok: boolean;
data?: JsonValue | null;
missing?: boolean;
};
export type DailyNewsSection = {
summary?: string;
stories: Array<{
title: string;
link: string;
source?: string;
reason?: string;
}>;
};
export type DailyImportantDatesSection = {
summary?: string;
events: Array<{
id?: string;
series: string;
category?: string;
referencePeriod?: string;
releaseAt: string;
source?: string;
sourceUrl?: string;
reason?: string;
}>;
};
export type StrategySnapshot = {
name: string;
netPnl?: number | null;
trades?: number | null;
lastFilledAt?: string | null;
};
export type StrategyChangeItem = {
name: string;
status: "new" | "updated" | "removed";
netPnlDelta?: number | null;
tradesDelta?: number | null;
};
export type StrategyChangeSummary = {
summary: string;
items: StrategyChangeItem[];
};
export type DailyDigestBriefing = {
headline: string;
overview?: string | null;
changes: string[];
previousRunAt?: string | null;
};
type DailyPerformanceSummary = {
netPnl?: number | null;
trades?: number | null;
winRate?: number | null;
lastFilledAt?: string | null;
};
export type DailyDigestHistoryItem = {
messageId: string;
content: string;
runAt: string;
createdAt: string;
updatedAt: string;
metadata?: Record<string, unknown>;
};
type DailyDigestHistoryContext = {
item: DailyDigestHistoryItem | null;
strategies: StrategySnapshot[];
performance: JsonValue | null;
};
const MAX_NEWS_STORIES = 3;
const MAX_IMPORTANT_DATES = 3;
const STRATEGY_DELTA_EPSILON = 0.005;
function isRecord(value: unknown): value is Record<string, unknown> {
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
}
function mapLegacyNewsStories(topStories: unknown[]): DailyNewsSection["stories"] {
return topStories.slice(0, MAX_NEWS_STORIES).map((story) => {
const record = isRecord(story) ? story : {};
return {
title: typeof record.title === "string" ? record.title : "Untitled story",
link: typeof record.link === "string" ? record.link : "",
source: typeof record.source === "string" ? record.source : undefined,
reason: typeof record.reason === "string" ? record.reason : undefined,
};
});
}
function collectWindowTopArticles(summary: Record<string, unknown>): unknown[] {
const windowSummaries = Array.isArray(summary.windowSummaries)
? summary.windowSummaries
: [];
const collected: unknown[] = [];
for (const windowSummary of windowSummaries) {
if (!isRecord(windowSummary) || !Array.isArray(windowSummary.topArticles)) {
continue;
}
for (const article of windowSummary.topArticles) {
collected.push(article);
if (collected.length >= MAX_NEWS_STORIES) {
return collected;
}
}
}
return collected;
}
function mapRoundupNewsStories(topArticles: unknown[]): DailyNewsSection["stories"] {
return topArticles.slice(0, MAX_NEWS_STORIES).map((article) => {
const record = isRecord(article) ? article : {};
return {
title: typeof record.title === "string" ? record.title : "Untitled story",
link:
typeof record.canonicalUrl === "string" ? record.canonicalUrl : "",
source:
typeof record.sourceName === "string" ? record.sourceName : undefined,
reason: typeof record.reason === "string" ? record.reason : undefined,
};
});
}
function hasMechanicalRoundupSummary(value: string | undefined) {
const summary = value?.trim();
if (!summary) return false;
return (
/^Fetched \d+ items from .+ across \d+ lookback windows\.$/i.test(summary) ||
/^No relevant items were found from .+ in the requested windows\.$/i.test(summary)
);
}
function joinLabelList(values: string[]) {
if (values.length === 0) return "";
if (values.length === 1) return values[0]!;
if (values.length === 2) return `${values[0]} and ${values[1]}`;
return `${values.slice(0, -1).join(", ")}, and ${values[values.length - 1]}`;
}
function buildFallbackNewsSummary(stories: DailyNewsSection["stories"]) {
if (stories.length === 0) return undefined;
const sources = Array.from(
new Set(
stories
.map((story) => story.source?.trim())
.filter((source): source is string => Boolean(source)),
),
).slice(0, 3);
if (sources.length === 0) {
return `${stories.length} recent geopolitical ${stories.length === 1 ? "story is" : "stories are"} in focus.`;
}
return `Recent geopolitical context is coming from ${joinLabelList(sources)}.`;
}
export function extractNewsSection(
subAgentResults: DailySummarySubAgentResult[],
): DailyNewsSection | undefined {
for (const result of subAgentResults) {
if (!isRecord(result.data)) continue;
const summary = isRecord(result.data.summary) ? result.data.summary : null;
if (!summary) continue;
const hasLegacyShape = Array.isArray(summary.topStories);
if (hasLegacyShape) {
return {
summary: typeof summary.summary === "string" ? summary.summary : undefined,
stories: mapLegacyNewsStories(summary.topStories as unknown[]),
};
}
const hasRoundupShape =
Array.isArray(summary.topArticles) || Array.isArray(summary.windowSummaries);
if (hasRoundupShape) {
const topArticles = Array.isArray(summary.topArticles)
? summary.topArticles
: collectWindowTopArticles(summary);
const stories = mapRoundupNewsStories(topArticles);
const overallSummary =
typeof summary.overallSummary === "string"
? summary.overallSummary
: undefined;
return {
summary: hasMechanicalRoundupSummary(overallSummary)
? buildFallbackNewsSummary(stories)
: overallSummary,
stories,
};
}
}
return undefined;
}
function mapImportantDateEvent(value: unknown): DailyImportantDatesSection["events"][number] | null {
if (!isRecord(value)) return null;
const series = typeof value.series === "string" ? value.series : "";
const releaseAt = typeof value.releaseAt === "string" ? value.releaseAt : "";
if (!series || !releaseAt) {
return null;
}
return {
id: typeof value.id === "string" ? value.id : undefined,
series,
category: typeof value.category === "string" ? value.category : undefined,
referencePeriod:
typeof value.referencePeriod === "string" ? value.referencePeriod : undefined,
releaseAt,
source: typeof value.source === "string" ? value.source : undefined,
sourceUrl: typeof value.sourceUrl === "string" ? value.sourceUrl : undefined,
reason: typeof value.reason === "string" ? value.reason : undefined,
};
}
function hasImportantDateEvents(value: unknown) {
return Array.isArray(value) && value.some((event) => mapImportantDateEvent(event) !== null);
}
function isImportantDatesResult(result: DailySummarySubAgentResult) {
const normalizedName = result.name.trim().toLowerCase();
if (
normalizedName.includes("important-dates") ||
normalizedName.includes("important dates")
) {
return true;
}
if (!isRecord(result.data)) return false;
const summary = isRecord(result.data.summary) ? result.data.summary : null;
return (
typeof result.data.daysAhead === "number" &&
(hasImportantDateEvents(result.data.events) || hasImportantDateEvents(summary?.topEvents))
);
}
export function extractImportantDatesSection(
subAgentResults: DailySummarySubAgentResult[],
): DailyImportantDatesSection | undefined {
for (const result of subAgentResults) {
if (!isImportantDatesResult(result)) continue;
if (!isRecord(result.data)) continue;
const summary = isRecord(result.data.summary) ? result.data.summary : null;
const topEvents: unknown[] = hasImportantDateEvents(summary?.topEvents)
? (summary?.topEvents as unknown[])
: hasImportantDateEvents(result.data.events)
? (result.data.events as unknown[])
: [];
const events = topEvents
.map((event: unknown) => mapImportantDateEvent(event))
.filter(
(event): event is DailyImportantDatesSection["events"][number] =>
event !== null,
)
.slice(0, MAX_IMPORTANT_DATES);
const summaryText =
typeof summary?.overallSummary === "string" && summary.overallSummary.trim().length > 0
? summary.overallSummary.trim()
: undefined;
if (summaryText || events.length > 0) {
return {
...(events.length === 0 && summaryText ? { summary: summaryText } : {}),
events,
};
}
}
return undefined;
}
export function extractStrategies(performance: JsonValue | null): StrategySnapshot[] {
if (!isRecord(performance)) return [];
const strategies = Array.isArray(performance.strategies)
? performance.strategies
: [];
return strategies
.map((strategy) => ({
name: typeof strategy?.name === "string" ? strategy.name : "Unnamed strategy",
netPnl: typeof strategy?.netPnl === "number" ? strategy.netPnl : undefined,
trades: typeof strategy?.trades === "number" ? strategy.trades : undefined,
lastFilledAt:
typeof strategy?.lastFilledAt === "string" ? strategy.lastFilledAt : null,
}))
.slice(0, 8);
}
function extractPerformanceSummary(performance: JsonValue | null): DailyPerformanceSummary | null {
if (!isRecord(performance) || !isRecord(performance.summary)) {
return null;
}
return {
netPnl:
typeof performance.summary.netPnl === "number"
? performance.summary.netPnl
: null,
trades:
typeof performance.summary.trades === "number"
? performance.summary.trades
: null,
winRate:
typeof performance.summary.winRate === "number"
? performance.summary.winRate
: null,
lastFilledAt:
typeof performance.summary.lastFilledAt === "string"
? performance.summary.lastFilledAt
: null,
};
}
function normalizeStrategyName(name: string): string {
return name.trim().toLowerCase();
}
function normalizeTimestamp(value?: string | null): number | null {
if (!value) return null;
const timestamp = Date.parse(value);
return Number.isFinite(timestamp) ? timestamp : null;
}
function formatStrategyCount(count: number): string {
return `${count} ${count === 1 ? "strategy" : "strategies"}`;
}
function summarizeStrategyChangeCount(params: {
newCount: number;
updatedCount: number;
removedCount: number;
}): string {
const parts: string[] = [];
if (params.newCount > 0) {
parts.push(`${params.newCount} new`);
}
if (params.updatedCount > 0) {
parts.push(`${params.updatedCount} updated`);
}
if (params.removedCount > 0) {
parts.push(`${params.removedCount} removed`);
}
if (parts.length === 0) {
return "No strategy changes since the previous snapshot.";
}
const total = params.newCount + params.updatedCount + params.removedCount;
return `${total} strategy change${total === 1 ? "" : "s"}: ${parts.join(", ")}.`;
}
export function buildStrategyChanges(params: {
currentStrategies: StrategySnapshot[];
previousStrategies: StrategySnapshot[];
}): StrategyChangeSummary | undefined {
const currentStrategies = params.currentStrategies;
const previousStrategies = params.previousStrategies;
if (currentStrategies.length === 0 && previousStrategies.length === 0) {
return undefined;
}
if (previousStrategies.length === 0) {
return {
summary: `Initial snapshot with ${formatStrategyCount(currentStrategies.length)}.`,
items: currentStrategies.map((strategy) => ({
name: strategy.name,
status: "new" as const,
})),
};
}
const previousByName = new Map(
previousStrategies.map((strategy) => [
normalizeStrategyName(strategy.name),
strategy,
]),
);
const currentByName = new Map(
currentStrategies.map((strategy) => [
normalizeStrategyName(strategy.name),
strategy,
]),
);
const items: StrategyChangeItem[] = [];
for (const strategy of currentStrategies) {
const previous = previousByName.get(normalizeStrategyName(strategy.name));
if (!previous) {
items.push({
name: strategy.name,
status: "new",
});
continue;
}
const netPnlDelta =
typeof strategy.netPnl === "number" && typeof previous.netPnl === "number"
? strategy.netPnl - previous.netPnl
: null;
const tradesDelta =
typeof strategy.trades === "number" && typeof previous.trades === "number"
? strategy.trades - previous.trades
: null;
const lastFilledAtChanged =
normalizeTimestamp(strategy.lastFilledAt) !==
normalizeTimestamp(previous.lastFilledAt);
if (
(netPnlDelta != null && Math.abs(netPnlDelta) >= STRATEGY_DELTA_EPSILON) ||
(tradesDelta != null && tradesDelta !== 0) ||
lastFilledAtChanged
) {
items.push({
name: strategy.name,
status: "updated",
...(netPnlDelta != null ? { netPnlDelta } : {}),
...(tradesDelta != null ? { tradesDelta } : {}),
});
}
}
for (const strategy of previousStrategies) {
if (currentByName.has(normalizeStrategyName(strategy.name))) continue;
items.push({
name: strategy.name,
status: "removed",
});
}
const newCount = items.filter((item) => item.status === "new").length;
const updatedCount = items.filter((item) => item.status === "updated").length;
const removedCount = items.filter((item) => item.status === "removed").length;
return {
summary: summarizeStrategyChangeCount({
newCount,
updatedCount,
removedCount,
}),
items,
};
}
function formatUsd(value: number): string {
const sign = value < 0 ? "-" : "";
return `${sign}$${Math.abs(value).toFixed(2)}`;
}
function formatUsdDelta(value: number): string {
return `${value >= 0 ? "+" : "-"}$${Math.abs(value).toFixed(2)}`;
}
function formatTradesDelta(value: number): string {
return `${value >= 0 ? "+" : ""}${value}`;
}
function describeStrategyChange(item: StrategyChangeItem): string {
if (item.status === "new") {
return `${item.name} was added to the snapshot.`;
}
if (item.status === "removed") {
return `${item.name} dropped out of the snapshot.`;
}
const parts: string[] = [];
if (typeof item.netPnlDelta === "number" && Math.abs(item.netPnlDelta) >= STRATEGY_DELTA_EPSILON) {
parts.push(`${formatUsdDelta(item.netPnlDelta)} net PnL`);
}
if (typeof item.tradesDelta === "number" && item.tradesDelta !== 0) {
parts.push(`${item.tradesDelta >= 0 ? "+" : ""}${item.tradesDelta} trades`);
}
if (parts.length === 0) {
return `${item.name} changed since the prior snapshot.`;
}
return `${item.name}: ${parts.join(", ")}.`;
}
function buildFallbackBriefing(params: {
currentStrategies: StrategySnapshot[];
strategyChanges?: StrategyChangeSummary;
news?: DailyNewsSection;
importantDates?: DailyImportantDatesSection;
previousRunAt?: string | null;
}): DailyDigestBriefing {
const strategyCount = params.currentStrategies.length;
const headline =
params.strategyChanges?.summary ??
(strategyCount > 0
? `Active snapshot with ${formatStrategyCount(strategyCount)}.`
: "No active strategies were detected in this snapshot.");
const changes =
params.strategyChanges?.items.slice(0, 4).map(describeStrategyChange) ?? [];
return {
headline,
overview: null,
changes,
previousRunAt: params.previousRunAt ?? null,
};
}
function normalizeHistoryItem(value: unknown): DailyDigestHistoryItem | null {
if (!isRecord(value)) return null;
const messageId = typeof value.messageId === "string" ? value.messageId : "";
const content = typeof value.content === "string" ? value.content : "";
const runAt = typeof value.runAt === "string" ? value.runAt : "";
const createdAt = typeof value.createdAt === "string" ? value.createdAt : "";
const updatedAt = typeof value.updatedAt === "string" ? value.updatedAt : "";
if (!messageId || !runAt || !createdAt || !updatedAt) {
return null;
}
return {
messageId,
content,
runAt,
createdAt,
updatedAt,
metadata: isRecord(value.metadata) ? value.metadata : undefined,
};
}
function normalizeStoredStrategySnapshot(value: unknown): StrategySnapshot | null {
if (!isRecord(value)) {
return null;
}
return {
name: typeof value.name === "string" ? value.name : "Unnamed strategy",
netPnl: typeof value.netPnl === "number" ? value.netPnl : null,
trades: typeof value.trades === "number" ? value.trades : null,
lastFilledAt:
typeof value.lastFilledAt === "string" ? value.lastFilledAt : null,
};
}
export async function fetchDigestHistory(limit: number): Promise<DailyDigestHistoryItem[]> {
const response = await openpondRequest(`/apps/agent/history?limit=${limit}`, {
method: "GET",
});
if (!response.ok) {
throw new Error(`Daily summary history request failed (${response.status})`);
}
const items = isRecord(response.data) && Array.isArray(response.data.items)
? response.data.items
: [];
return items
.map((item) => normalizeHistoryItem(item))
.filter((item): item is DailyDigestHistoryItem => item !== null);
}
function extractHistoryContext(
historyItems: DailyDigestHistoryItem[],
): DailyDigestHistoryContext {
const item = historyItems[0] ?? null;
if (!item?.metadata) {
return { item, strategies: [], performance: null };
}
const strategies = Array.isArray(item.metadata.strategies)
? item.metadata.strategies
.map((strategy) => normalizeStoredStrategySnapshot(strategy))
.filter((strategy): strategy is StrategySnapshot => strategy !== null)
: extractStrategies(
isRecord(item.metadata.performance) ? item.metadata.performance as JsonValue : null,
);
return {
item,
strategies,
performance: isRecord(item.metadata.performance)
? (item.metadata.performance as JsonValue)
: null,
};
}
export async function buildDigestBriefing(params: {
runAt: string;
config: DailySummaryConfig;
performance: JsonValue | null;
currentStrategies: StrategySnapshot[];
subAgentResults: DailySummarySubAgentResult[];
news?: DailyNewsSection;
importantDates?: DailyImportantDatesSection;
historyItems: DailyDigestHistoryItem[];
}): Promise<{
briefing: DailyDigestBriefing;
previousStrategies: StrategySnapshot[];
strategyChanges?: StrategyChangeSummary;
}> {
const historyContext = extractHistoryContext(params.historyItems);
const previousRunAt = historyContext.item?.runAt ?? null;
const previousStrategies = historyContext.strategies;
const strategyChanges = buildStrategyChanges({
currentStrategies: params.currentStrategies,
previousStrategies,
});
return {
briefing: buildFallbackBriefing({
currentStrategies: params.currentStrategies,
strategyChanges,
news: params.news,
importantDates: params.importantDates,
previousRunAt,
}),
previousStrategies,
strategyChanges,
};
}
function formatWinRate(value?: number | null): string | null {
if (typeof value !== "number") return null;
return `${value.toFixed(1)}%`;
}
function formatStrategyLine(
strategy: StrategySnapshot,
strategyChange?: StrategyChangeItem,
): string {
const parts = [strategy.name];
if (typeof strategy.netPnl === "number") {
parts.push(`net PnL ${formatUsd(strategy.netPnl)}`);
}
if (
typeof strategyChange?.netPnlDelta === "number" &&
Math.abs(strategyChange.netPnlDelta) >= STRATEGY_DELTA_EPSILON
) {
parts.push(`Δ ${formatUsdDelta(strategyChange.netPnlDelta)}`);
}
if (typeof strategy.trades === "number") {
parts.push(`${strategy.trades} trades`);
}
if (typeof strategyChange?.tradesDelta === "number" && strategyChange.tradesDelta !== 0) {
parts.push(`Δ ${formatTradesDelta(strategyChange.tradesDelta)} trades`);
}
return `- ${parts.join(" | ")}`;
}
function formatReleaseAt(value: string): string {
const timestamp = Date.parse(value);
if (!Number.isFinite(timestamp)) return value;
return new Intl.DateTimeFormat("en-US", {
timeZone: "America/New_York",
month: "short",
day: "numeric",
hour: "numeric",
minute: "2-digit",
timeZoneName: "short",
}).format(new Date(timestamp));
}
export function formatDigest(params: {
runAt: string;
briefing: DailyDigestBriefing;
performance: JsonValue | null;
strategies: StrategySnapshot[];
strategyChanges?: StrategyChangeSummary;
subAgentResults: DailySummarySubAgentResult[];
news?: DailyNewsSection;
importantDates?: DailyImportantDatesSection;
}) {
const lines: string[] = [];
const strategyChangesByName = new Map(
(params.strategyChanges?.items ?? []).map((item) => [
normalizeStrategyName(item.name),
item,
]),
);
lines.push(`Daily Snapshot - ${params.runAt}`);
lines.push("");
if (params.news) {
lines.push("News:");
if (params.news.summary) {
lines.push(params.news.summary);
}
for (const story of params.news.stories) {
const parts = [story.title];
if (story.source) {
parts.push(story.source);
}
if (story.link) {
parts.push(story.link);
}
lines.push(`- ${parts.join(" | ")}`);
}
lines.push("");
}
if (params.importantDates && params.importantDates.events.length > 0) {
lines.push("Upcoming dates:");
for (const event of params.importantDates.events.slice(0, MAX_IMPORTANT_DATES)) {
const title = event.referencePeriod
? `${event.series} (${event.referencePeriod})`
: event.series;
const parts = [title, formatReleaseAt(event.releaseAt)];
if (event.sourceUrl) {
parts.push(event.sourceUrl);
}
lines.push(`- ${parts.join(" | ")}`);
}
lines.push("");
}
if (params.strategies.length > 0) {
lines.push("Strategies:");
for (const strategy of params.strategies) {
lines.push(
formatStrategyLine(
strategy,
strategyChangesByName.get(normalizeStrategyName(strategy.name)),
),
);
}
lines.push("");
}
return lines.join("\n").trim();
}