Skip to content

feat: Azure billing + PR pricing, agent multi-turn memory, dashboard chat - #33

Merged
Cro22 merged 6 commits into
mainfrom
feat/azure-billing
Sep 1, 2026
Merged

feat: Azure billing + PR pricing, agent multi-turn memory, dashboard chat#33
Cro22 merged 6 commits into
mainfrom
feat/azure-billing

Conversation

@Cro22

@Cro22 Cro22 commented Sep 1, 2026

Copy link
Copy Markdown
Owner

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)

CostManagementSource against the Azure Cost Management Query API, closing multi-cloud billing alongside AWS Cost Explorer and GCP BigQuery. Same injectable-interface + normalized Report + SourceError shape as the siblings.

  • Enable with CLOUDORACLE_BILLING_PROVIDER=azure_cost_management + AZURE_SUBSCRIPTION_ID; noisy snapshot fallback on init failure.
  • Skipped: NextLink pagination (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).

  • New internal/iac/azure extractor for azurerm_linux_virtual_machine and azurerm_managed_disk; estimators in internal/pricing.
  • Unpriced sizes/SKUs and Windows VMs surface as Skipped, not errors. Premium/Ultra disks are approximated (they bill by tier, not linearly) — flagged in-code.

3. Agent multi-turn memory (LangGraph PostgresSaver)

POST /ask takes an optional thread_id; when DATABASE_URL is set the supervisor graph compiles with AsyncPostgresSaver so a thread's prior messages carry into follow-ups ("and the month before?").

  • Per-run accounting channels (tool_calls/observations/hops) are plain 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 /ask with a per-conversation thread_id, surfacing the whole insights-agent to dashboard users. Dev proxies /ask to :8099; VITE_AGENT_BASE_URL / VITE_AGENT_API_KEY for prod.

Tests

  • Go: go test ./... green (new billing, pricing, iac/azure, and change-dispatch tests).
  • Python: 143 passed, 89% coverage (multi-turn thread test proves context persists and caps reset per turn; API thread_id forwarding).
  • Web: eslint clean on new code, vite build succeeds.

New deps: armcostmanagement (Go), langgraph-checkpoint-postgres (Python).

🤖 Generated with Claude Code

Cro22 added 4 commits August 31, 2026 20:08
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.
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

💰 Cloud Cost Impact

Net monthly change: +$630.11 🔴

This plan adds 4 resources, with a net monthly cost increase of +$630.11.

Top movers by cost impact

Resource Action Δ Monthly Confidence
google_compute_instance.batch 🆕 create +$231.96 low
google_sql_database_instance.main 🆕 create +$219.36 medium
google_compute_instance.web 🆕 create +$158.79 medium
google_compute_disk.data 🆕 create +$20.00 medium
📋 Full breakdown (4 priced, 1 skipped)

Created (4)

  • google_compute_instance.batch — +$231.96
    • Compute: +$226.96
    • BootDisk: +$5.00
  • google_sql_database_instance.main — +$219.36
    • Compute: +$202.36
    • Storage: +$17.00
  • google_compute_instance.web — +$158.79
    • Compute: +$141.79
    • BootDisk: +$17.00
  • google_compute_disk.data — +$20.00
    • Disk: +$20.00

Skipped (1)

  • google_storage_bucket.assets (google_storage_bucket) — unsupported resource type: google_storage_bucket
⚠️ Assumptions and caveats
  • 1 resources skipped (1 unsupported types, 0 estimation failures)
  • Net cost increase this plan
  • Priced from a static GCP price table (may drift from current list price) (applies to: google_compute_instance.batch, google_compute_instance.web, google_compute_disk.data)
  • Spot/preemptible VM priced at on-demand rate (real cost is 60–91% lower) (applies to: google_compute_instance.batch)
  • Priced from a static GCP price table at US rates (may drift; other regions differ) (applies to: google_sql_database_instance.main)
  • REGIONAL (HA) availability doubles compute and storage (applies to: google_sql_database_instance.main)

Generated by CloudOracle · Confidence: low

Cro22 added 2 commits August 31, 2026 20:46
- 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.
@Cro22
Cro22 merged commit 08223df into main Sep 1, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant