Skip to content

A market terminal: live stock and crypto prices and the news - #384

Open
johnfrankowski8-hub wants to merge 2 commits into
AgentSystemLabs:mainfrom
johnfrankowski8-hub:market-terminal
Open

johnfrankowski8-hub wants to merge 2 commits into
AgentSystemLabs:mainfrom
johnfrankowski8-hub:market-terminal

Conversation

@johnfrankowski8-hub

Copy link
Copy Markdown

What it does

J (or Market terminal in the Ctrl+K palette) opens an amber-on-black market window:

  • A watchlist that refreshes every 10 seconds, with rows flashing green or red as prices move. Type a ticker (AAPL) or a coin pair (BTC-USD) and press Enter to add it. The list is kept in the browser.
  • The selected symbol up close: last price, change, open, high and low.
  • Top market headlines, refreshed every minute.

Crypto comes from Coinbase's public prices and needs no key. Stocks and news come from Finnhub and need a free AGENT_OFFICE_FINNHUB_KEY. Without the key, the window says so and links to the sign-up page.

How it plugs in

  • src/server/market.ts holds the data proxy, and src/server/http/routes/market.ts adds /api/market/quotes and /api/market/news, both behind the signed-in session.
  • src/shared/market.ts has the types and symbol validation.
  • src/client/features/market/ has the window. main.ts gets its install line, and the palette and help each get one row.
  • README, docs/features.md, docs/controls.md and docs/configuration.md are updated.

Safety

  • Only two hosts are ever called. Symbols are checked against strict ticker and pair patterns, so a symbol can't change the request path (no SSRF).
  • The Finnhub key goes only in a request header, and only to Finnhub. It never reaches a page or a URL, and the client only learns whether stocks are enabled.
  • News links are limited to http(s) and open with noopener noreferrer. All third-party text is rendered as text, never HTML.
  • The office makes at most 50 Finnhub calls a minute across all users, to stay under the free tier's 60. Prices are cached for 10 seconds and headlines for a minute.
  • The cache is capped at 500 entries, oldest dropped first. Upstream answers are capped at 2 MB, and redirects are refused.
  • No new dependencies.

Verification

  • npm run typecheck passes.
  • npm run build passes.
  • tests/market.test.ts covers symbol validation, the no-key behaviour, the key staying in the header, news-link filtering and the 50-calls-a-minute cap.
  • size, client-structure, client-help and palette tests pass.
  • Headless Chrome screenshot of the built office: the window opens on J with live Coinbase prices, has the top-right ✕, and Esc closes it.
  • On this Windows machine, the clone tests, two client-registry interaction-kind tests and the symlink test fail the same way on a clean origin/main, so they aren't from this change. The full npm test run also hung at the drunk-vision test, so the test files after it were run separately.

🤖 Generated with Claude Code

J (or "Market terminal" in Ctrl+K) opens an amber-on-black window with a
ticking watchlist, the picked symbol up close, and top headlines. Crypto
comes from Coinbase's public prices with no key; stocks and news from
Finnhub with a free AGENT_OFFICE_FINNHUB_KEY that never leaves the server.
The office proxies both behind the sign-in, caps its Finnhub calls at 50 a
minute for everyone, caps its cache and answer sizes, and only follows
http(s) news links.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@johnfrankowski8-hub

Copy link
Copy Markdown
Author

Added a read-only Portfolio panel in 207e377. Type AAPL 10 182.50, or Import CSV with Symbol, Quantity and an optional Average Cost column, and the terminal values each holding live, with today's move and P/L. Holdings stay in the browser's localStorage. The office is only asked for prices by symbol, and there's no broker sign-in. Covered in tests/market.test.ts. Checked with typecheck, build and a headless screenshot.

Type AAPL 10 182.50 or import a positions CSV (Symbol, Quantity and an
optional Average Cost column) and the terminal values each holding live,
with today's move and profit or loss. Holdings stay in localStorage: the
office is only asked for prices by symbol, and nothing signs in to a broker.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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