From 3381967164eada0cf7c64cdd088feabb0ae93474 Mon Sep 17 00:00:00 2001 From: Priyanka Punukollu Date: Wed, 25 Feb 2026 22:18:08 -0600 Subject: [PATCH] feat: add persistent chat history and clear button - ngOnInit restores conversation from sessionStorage on mount - saveHistory() persists every message exchange automatically - clearHistory() resets to welcome message and wipes stored history - Clear button added to panel header (small, subtle, matches dark theme) - welcomeMessage getter adapts copy based on enableRealEstate flag Made-with: Cursor --- agent/scripts/seed_portfolio.py | 87 ++++++++ .../components/ai-chat/ai-chat.component.html | 159 ++++++++++--- .../components/ai-chat/ai-chat.component.scss | 136 +++++++++++- .../components/ai-chat/ai-chat.component.ts | 208 ++++++++++++++---- .../components/ai-chat/ai-markdown.pipe.ts | 2 +- .../components/header/header.component.html | 21 ++ .../app/components/header/header.component.ts | 16 +- .../src/app/services/ai-chat.service.ts | 20 ++ .../src/environments/environment.prod.ts | 1 + apps/client/src/environments/environment.ts | 1 + .../lib/environment/environment.interface.ts | 1 + 11 files changed, 577 insertions(+), 75 deletions(-) create mode 100644 agent/scripts/seed_portfolio.py create mode 100644 apps/client/src/app/services/ai-chat.service.ts diff --git a/agent/scripts/seed_portfolio.py b/agent/scripts/seed_portfolio.py new file mode 100644 index 000000000..5e4e3de4d --- /dev/null +++ b/agent/scripts/seed_portfolio.py @@ -0,0 +1,87 @@ +""" +seed_portfolio.py — Seed a Ghostfolio account with demo holdings. + +Usage: + python scripts/seed_portfolio.py + +Environment variables: + GHOSTFOLIO_BASE_URL (default: http://localhost:3333) + GHOSTFOLIO_BEARER_TOKEN (required) +""" + +import asyncio +import os +import sys + +import httpx + +GHOSTFOLIO_URL = os.getenv("GHOSTFOLIO_BASE_URL", "http://localhost:3333") +TOKEN = os.getenv("GHOSTFOLIO_BEARER_TOKEN", "") + + +async def seed() -> None: + if not TOKEN: + print("ERROR: GHOSTFOLIO_BEARER_TOKEN is not set.", file=sys.stderr) + sys.exit(1) + + holdings = [ + { + "symbol": "AAPL", + "quantity": 10, + "unitPrice": 150.00, + "date": "2024-01-15T00:00:00.000Z", + "type": "BUY", + "currency": "USD", + "dataSource": "YAHOO", + "fee": 4.95, + }, + { + "symbol": "MSFT", + "quantity": 5, + "unitPrice": 300.00, + "date": "2024-03-10T00:00:00.000Z", + "type": "BUY", + "currency": "USD", + "dataSource": "YAHOO", + "fee": 4.95, + }, + { + "symbol": "NVDA", + "quantity": 3, + "unitPrice": 400.00, + "date": "2024-06-01T00:00:00.000Z", + "type": "BUY", + "currency": "USD", + "dataSource": "YAHOO", + "fee": 4.95, + }, + { + "symbol": "TSLA", + "quantity": 2, + "unitPrice": 200.00, + "date": "2024-09-20T00:00:00.000Z", + "type": "BUY", + "currency": "USD", + "dataSource": "YAHOO", + "fee": 4.95, + }, + ] + + async with httpx.AsyncClient(timeout=30) as client: + resp = await client.post( + f"{GHOSTFOLIO_URL}/api/v1/import", + headers={"Authorization": f"Bearer {TOKEN}"}, + json={"activities": holdings}, + ) + print(f"Seed result: {resp.status_code}") + if resp.status_code == 201: + print(f"SUCCESS — imported {len(holdings)} transactions.") + for h in holdings: + print(f" ✓ {h['type']} {h['quantity']} {h['symbol']} @ ${h['unitPrice']}") + else: + print(f"RESPONSE: {resp.text}") + sys.exit(1) + + +if __name__ == "__main__": + asyncio.run(seed()) diff --git a/apps/client/src/app/components/ai-chat/ai-chat.component.html b/apps/client/src/app/components/ai-chat/ai-chat.component.html index 67a03a4dc..6888f00fd 100644 --- a/apps/client/src/app/components/ai-chat/ai-chat.component.html +++ b/apps/client/src/app/components/ai-chat/ai-chat.component.html @@ -1,17 +1,23 @@ -