feat: Azure billing + PR pricing, agent multi-turn memory, dashboard chat - #33
Merged
Conversation
Implements AzureCostManagementSource against the Azure Cost Management Query API, closing the multi-cloud gap alongside the existing AWS Cost Explorer and GCP BigQuery sources. Wired via CLOUDORACLE_BILLING_PROVIDER=azure_cost_management (requires AZURE_SUBSCRIPTION_ID), with the same noisy snapshot fallback.
Extends the v2 pre-merge Terraform estimator to Azure, closing the gap alongside AWS (live Pricing API) and GCP (static table). Adds an internal/iac/azure extractor for azurerm_linux_virtual_machine and azurerm_managed_disk, and prices them from an embedded static table mirroring the GCP arm (the Azure Retail Prices API is the documented upgrade path). Unpriced sizes/SKUs and Windows VMs surface as Skipped, not errors.
Adds optional conversational memory to the insights agent: POST /ask now takes an optional thread_id, and when DATABASE_URL is set the supervisor graph is compiled with AsyncPostgresSaver so a thread's prior messages carry into later turns (follow-ups like 'and the month before?'). The per-run accounting channels (tool_calls, observations, hops) are plain LastValue rather than accumulating, so the run-wide caps reset each turn instead of tripping on the whole thread's history. The synthesizer now scopes its question + findings to the current turn. No DB configured keeps the previous single-shot behavior.
Floating chat panel on the dashboard that POSTs to the insights-agent's /ask with a per-conversation thread_id, so follow-up questions keep context (multi-turn memory added on the agent side). Dev proxies /ask to the agent on :8099; set VITE_AGENT_BASE_URL for prod and VITE_AGENT_API_KEY when the agent requires X-API-Key. Surfaces the verified-fallback badge when the model's draft failed grounding.
💰 Cloud Cost ImpactNet monthly change: +$630.11 🔴 This plan adds 4 resources, with a net monthly cost increase of +$630.11. Top movers by cost impact
📋 Full breakdown (4 priced, 1 skipped)Created (4)
Skipped (1)
|
- Split RefreshContext into a plain module (context + hook) so the .jsx exports only <RefreshProvider>, satisfying react-refresh/only-export- components; repoint the 6 importers. - Comment the two empty catch blocks (no-empty) in useApi/ChatWidget error parsing. - Annotate the intentional fetch-on-change setState in useApi with a scoped eslint-disable and rationale. npm run lint is now clean.
docs/EXPLICACION-PARA-TODOS.md is a local-only file, not for the repo.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the three high-ROI items from the improvement report ("Hazlo" block), each mirroring an existing pattern in the codebase.
1. Azure Cost Management (real billing)
CostManagementSourceagainst the Azure Cost Management Query API, closing multi-cloud billing alongside AWS Cost Explorer and GCP BigQuery. Same injectable-interface + normalizedReport+SourceErrorshape as the siblings.CLOUDORACLE_BILLING_PROVIDER=azure_cost_management+AZURE_SUBSCRIPTION_ID; noisy snapshot fallback on init failure.NextLinkpagination (a monthly service-grouped query is a few dozen rows).2. Azure in the PR pricing analyzer (v2)
Extends the pre-merge Terraform estimator to Azure via an embedded static price table (the same choice the GCP arm makes; the Azure Retail Prices API is the documented upgrade path).
internal/iac/azureextractor forazurerm_linux_virtual_machineandazurerm_managed_disk; estimators ininternal/pricing.3. Agent multi-turn memory (LangGraph PostgresSaver)
POST /asktakes an optionalthread_id; whenDATABASE_URLis set the supervisor graph compiles withAsyncPostgresSaverso a thread's prior messages carry into follow-ups ("and the month before?").LastValue, not accumulating, so the run-wide caps reset each turn instead of tripping on the whole thread's history; the synthesizer scopes its question+findings to the current turn. No DB configured keeps single-shot behavior.4. Dashboard chat widget
Floating chat panel wired to the agent's
/askwith a per-conversationthread_id, surfacing the whole insights-agent to dashboard users. Dev proxies/askto:8099;VITE_AGENT_BASE_URL/VITE_AGENT_API_KEYfor prod.Tests
go test ./...green (new billing, pricing, iac/azure, and change-dispatch tests).eslintclean on new code,vite buildsucceeds.New deps:
armcostmanagement(Go),langgraph-checkpoint-postgres(Python).🤖 Generated with Claude Code