|
| 1 | +import type { SpendAnalysisResponse } from "@features/billing/types/spend-analysis"; |
1 | 2 | import { isSupportedReasoningEffort } from "@posthog/agent/adapters/reasoning-effort"; |
2 | 3 | import type { PermissionMode } from "@posthog/agent/execution-mode"; |
3 | 4 | import { |
@@ -2855,4 +2856,35 @@ export class PostHogAPIClient { |
2855 | 2856 | const blob = await response.blob(); |
2856 | 2857 | return URL.createObjectURL(blob); |
2857 | 2858 | } |
| 2859 | + |
| 2860 | + /** |
| 2861 | + * Fetch the requesting user's personal LLM spend analysis. `dateFrom` / `dateTo` |
| 2862 | + * accept absolute dates (`2026-04-23`) or relative strings (`-7d`, `-1m`), and |
| 2863 | + * default to the last 30 days. When `product` is set the tool / model / trace |
| 2864 | + * breakdowns are scoped to that `ai_product` (e.g. `posthog_code`); when omitted |
| 2865 | + * they aggregate across every product. |
| 2866 | + */ |
| 2867 | + async getPersonalSpendAnalysis( |
| 2868 | + options: { dateFrom?: string; dateTo?: string; product?: string } = {}, |
| 2869 | + ): Promise<SpendAnalysisResponse> { |
| 2870 | + const { dateFrom = "-30d", dateTo, product } = options; |
| 2871 | + const urlPath = `/api/llm_analytics/@me/spend/`; |
| 2872 | + const url = new URL(`${this.api.baseUrl}${urlPath}`); |
| 2873 | + url.searchParams.set("date_from", dateFrom); |
| 2874 | + if (dateTo) { |
| 2875 | + url.searchParams.set("date_to", dateTo); |
| 2876 | + } |
| 2877 | + if (product) { |
| 2878 | + url.searchParams.set("product", product); |
| 2879 | + } |
| 2880 | + const response = await this.api.fetcher.fetch({ |
| 2881 | + method: "get", |
| 2882 | + url, |
| 2883 | + path: urlPath, |
| 2884 | + }); |
| 2885 | + if (!response.ok) { |
| 2886 | + throw new Error(`Failed to fetch spend analysis: ${response.status}`); |
| 2887 | + } |
| 2888 | + return (await response.json()) as SpendAnalysisResponse; |
| 2889 | + } |
2858 | 2890 | } |
0 commit comments