Skip to content

feat(nav): ⌘K page-jump + NL layer + agent-commerce worker fetcher - #3195

Open
0motionguy wants to merge 14 commits into
hardening/2026-05-31-wavefrom
feat/navigator-palette-live
Open

0motionguy wants to merge 14 commits into
hardening/2026-05-31-wavefrom
feat/navigator-palette-live

Conversation

@0motionguy

Copy link
Copy Markdown
Owner

What

Three additive features on the live line (hardening @ 8e7fe20):

  1. ⌘K Pages tier (Topbar.tsx + nav-commands.ts) — the global search now jumps to any page, not just repos/LLMs. Reuses the exact .search-row markup.
  2. N1 natural-language layer — 'show me agents', 'go to the funding page' resolve deterministically (no LLM). Homepage category views (?cat=agents/llms/models/...) added as jump targets.
  3. agent-commerce worker fetcher — unfreezes /agent-commerce (its GH-Actions cron died 2026-05-31; Redis key was empty). Re-scores the seed on the live worker plane daily.

Verification

  • Playwright on live worktree: ⌘K search → Pages section, Enter navigates, NL queries resolve, 0 console errors (screenshots attached in-session).
  • Worker fetcher: typecheck-clean; runtime (fresh Redis write) pending worker deploy.

🤖 Generated with Claude Code

0motionguy and others added 14 commits July 4, 2026 21:56
The Topbar ⌘K search already found repos + LLMs; it could not jump to
pages. Adds an instant, client-side 'Pages' section to the existing
search dropdown (src/lib/nav-commands.ts registry + matcher), so ⌘K +
'watch'/'funding'/'compare' surfaces the destination alongside repo hits.

- Additive: repo/LLM search path untouched; PageRow reuses the exact
  .search-row markup so it reads native.
- Pages rank first (instant, deterministic), then repos, then LLMs;
  keyboard activeIdx + navigateToHit extended for the page kind.

Verified on live branch (hardening/2026-05-31-wave @ 8e7fe20):
typecheck clean, dev server, Playwright — Pages section renders,
Enter/click routes to /tools/watchlist, 0 console errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e live plane

/agent-commerce was fed only by cron-agent-commerce.yml (GH-Actions),
which has failed since 2026-05-31. On the worker-owned prod plane nothing
wrote the 'agent-commerce' slug, so the page served the deploy-baked seed
frozen at build time. Redis probe confirmed ss:meta:v1:agent-commerce empty.

Adds a worker fetcher that re-runs the seed assembly (scoring mirrors
scripts/build-agent-commerce-seed.mjs) and publishes a fresh 'agent-commerce'
payload daily (41 4 * * *) with an empty-guard. Breaks the deploy-freeze.

v1: seed re-score + fresh timestamp. v2 (tracked): port the onchain x402 /
CoinGecko / agentic.market source fetchers to the worker for live enrichment.

Verification: TS-clean (my files produce zero errors; worker external-dep
errors are pre-existing missing node_modules in the worktree). Runtime
(fresh Redis write) needs a worker image build + deploy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Deterministic NL: strips leading intent verbs ('show me', 'go to',
'take me to'), articles, and trailing 'page/tab/view' before matching,
so plain-English queries resolve. Adds homepage category views
(Agents/LLMs/Models/Gainers/Discovery via ?cat=) as jump targets.

Verified (Playwright, live worktree):
- 'show me agents'        -> Agents (?cat=agents) + Agent Commerce
- 'go to the funding page'-> Funding
- 0 console errors, native styling (screenshot nav-n1-nl.png)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…gates

The wow the ⌘K tier was only plumbing for: a persistent docked assistant
(bottom-right, terminal-styled, Liquid Lava) you ASK in natural language or
by voice, and it replies + executes against the nav-command registry.

- Voice: Web Speech API, feature-detected (mic renders only where supported).
- Deterministic execution today (instant, no LLM); LLM fall-through for
  multi-step requests is the next tier via /api/navigator (worker Kimi/NanoGPT
  key exists on the box).
- Mounted deferred via IdleMount; native shell.css design vars.

Verified (Playwright, live worktree): launcher renders -> panel opens with
greeting + quick chips + mic; typed 'take me to funding' -> agent navigated
to /funding (title 'Funding Radar'); 0 console errors. Screenshot ask-dock-open.png.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Per direction: kill the corner chat panel. A floating, DRAGGABLE, horizontal
liquid-glass command bar — frosted/translucent, minimal color, compact, drifts
anywhere and persists position. You type/speak; the agent navigates. No
transcript — a single ephemeral status flashes, then you're there.

Design (impeccable lens; glass is purposeful here = a HUD over live content, the
canonical justified case, not a decorative card; restrained color per '≤10%
accent'; ease-out-expo motion + reduced-motion fallback; position:fixed escapes
stacking context; DNA: HyperLiquid precision × Meteora liquid unfurl):
- glass: rgba(12,14,17,0.55) + backdrop-blur(24px) saturate(150%), 1px white/8
  border, inset top-edge light refraction; accent only on caret + focus glow.
- collapsed 42px node ↔ 420x46 bar, radius morphs 999px->14px (fluid unfurl).
- drag via pointer events on grip/node, viewport-clamped, saved to localStorage.

Verified (Playwright, live worktree):
- collapsed node: backdrop-filter blur(24px) saturate(1.5), bg rgba(12,14,17,.55), r999px
- expands to 420x46 glass bar (r14px); 'revenue' -> navigated /revenue
- real mouse-drag on grip moved it 211px/282px and persisted {left,top} to localStorage
- 0 console errors; screenshots ask-glass-bar.png + ask-glass-dragged.png

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rag, send+voice

Per direction: more visible + orange glow borders + bigger + no X (send & voice
icons instead) + drag the whole body, not one tiny grip.

- brighter: bg rgba(17,20,25,0.74) (was .55); top refraction .11; input 14px, brighter placeholder.
- orange glow border: border rgba(255,107,53,0.34) at rest -> 0.55 focused; box-shadow orange bloom.
- bigger: node 48px; bar 500x56 (was 420x46), radius 16.
- whole body draggable: pointer handlers on the bar (guard skips input/buttons); grip removed; cursor grab->grabbing.
- send button (ArrowRight, submit) + voice (Radio); X close removed (Esc still collapses).

Verified (Playwright): bar 500x56, border rgba(255,107,53,0.55), bg rgba(17,20,25,0.74),
cursor grab, buttons [Speak, Send] (no close); body-drag from caret moved it; 0 errors;
screenshot ask-glass-v2.png (bright orange-glowing bar over live content).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…igator)

The final tier. When the deterministic matcher misses, the bar falls through to
POST /api/navigator: a small model maps free text ('get me that claude repo',
'where do people discuss funding') to ONE navigation action against the same
route registry, with an ephemeral 'Thinking…' -> result status. No chat log.

Security: the model's href is hard-validated to an internal path (safeInternalHref)
before it reaches the client — a prompt-injected external URL can't become an open
redirect. Zod-validated, per-IP rate-limited (20/min), provider-flexible
(NanoGPT -> OpenRouter -> Kimi, OpenAI-compatible), graceful NOT_CONFIGURED when no
key so the client keeps deterministic-only behaviour.

Verified (curl + Playwright, live worktree):
- POST valid q, no local key -> {ok:false, NOT_CONFIGURED} HTTP 200 (graceful)
- bad body / malformed JSON -> {ok:false, BAD_REQUEST} HTTP 400
- client: deterministic 'breakout' -> /breakout (flash '→ Opening Breakout');
  miss 'zzqx nonsense' -> fires /api/navigator, shows fallback. 0 console errors.
- Full LLM behaviour needs a key in the app env on the box (worker has Kimi/NanoGPT).

All tiers now live in the bar: page-jump, NL, voice, LLM router.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ation

Per direction: the agent should welcome the user and let them TALK to it, not
only route. Now it does both.

- Greeting on open: a warm welcome appears in a readable glass answer panel
  above the bar (the agent talks first).
- Q&A: /api/navigator becomes an assistant returning {reply, answer?, action}.
  Ask a question -> a 1-3 sentence answer in the answer panel; it can also
  navigate. Deterministic 'help/what can you do/hi' answers work with no LLM key.
- Answer panel: same liquid-glass aesthetic, one message (a reply, not a
  transcript), dismissable; nav commands clear it and route.

Verified (Playwright, live worktree):
- open -> greeting 'Hey, I'm your trendingrepo agent…' in the answer panel
- 'what can you do' -> help answer rendered (screenshot ask-conversational.png)
- 'funding' -> flash '→Opening Funding', greeting cleared, navigated /funding
- endpoint returns {answer?} shape; graceful NOT_CONFIGURED without key; 0 errors
- Full LLM Q&A needs a key in the app env on the box.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ows, flowing orange border

Per correction: the answer opened to the TOP; it should open to the BOTTOM,
inside the box. The bar is now a column container that expands DOWNWARD to hold
the conversation, capped at ~5 rows then scroll, with an animated flowing orange
border.

- input row on top; .ask-body opens downward below it (was a floating panel above).
- box grows to fit content, max-height 240px (~5 rows), overflow-y scroll.
- flowing orange border: conic-gradient arc travels the edge (@Property --ask-spin,
  masked border ring) while the box holds a conversation; reduced-motion disables it.
- greeting + Q&A + nav status all render inside the body now (nothing floats above).

Verified (Playwright): bodyBelowInput=true (downward), box grew to 119px, body
max-height 240px, box.::after animation=ask-spin (flowing border), greeting inside
box; 0 console errors; screenshot ask-box-downward.png.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Per direction: messages were pinned/static; they should TYPE out so the user
sees the agent typing, then the next message. And the greeting should be a CTA.

- Typewriter component types each message char-by-char (10-15ms/char, faster for
  long ones) with a blinking accent caret that clears when done. Restarts when
  the message changes, so the next answer types itself out. Instant under
  prefers-reduced-motion.
- Greeting is now a CTA: 'Hey. Tell me what you're looking for and I'll take you
  right there. A repo, funding, trending agents, or just ask.'

Verified (Playwright): greeting types progressively (13 -> 60 -> 113 chars),
.ask-type-caret present while typing and gone when done, CTA text correct;
0 console errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… + chitchat

Bug: 'how are you' (and any question that missed the shortcut or hit the LLM
with no key) showed a transient status that vanished after ~1.8s — the user's
'thinking then nothing'.

- Every miss now lands as a PERSISTENT typed answer (setAnswer), never a
  status that disappears. So there's always a response.
- Broader conversational replies with no LLM key: greetings/'how are you'/'what's
  up' -> warm reply; 'thanks' -> ack; help/'who are you' -> capabilities.
- Client fetch timeout (12s) so 'Thinking…' can never stick forever.

Verified (Playwright): 'how are you' -> persistent 'Doing great, thanks…' (survives
past the old 1.8s window); 'what is the meaning of life' -> persistent typed
'I couldn't map that to a page yet…' (stable across 6 samples, doesn't vanish).
The lone console error is a pre-existing RepoSparkline hydration mismatch, not this code.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…acklog

Clean pick-up doc: what's live on the box, what's built+verified on PR #3195
(the Ask agent, ⌘K, agent-commerce fetcher), what's blocked on Mirko (deploy,
LLM key, Slack webhook), the deploy runbook, and the remaining plan/audit
backlog. Leads with the branch trap (live = hardening, not main).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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