nsUpdateCamera, the voice pacer, or any shipped call controls. Every phase is flag-gated + reversible. |---
1. The "F" browser-view tool — Does not exist in the fleet. No Firecrawl, Puppeteer, Playwright, or any visual/screenshot browser. The "starts with F, browser view" is almost certainly Firecrawl (a hosted scrape/screenshot API) — which is NOT installed. What Leo *does* have today is open_page (fetches the raw text of a URL) and web_search (Google-grounded answer + source links). Both are text-only; neither renders or screenshots a page, and neither is wired to the live call UI.
2. Camera vision — Exists, real, flag-gated OFF. Leo can literally see the call camera via Gemini Live multimodal video (KAI_VIDEO_MODE=1), plus an optional face-recognition tap (KAI_FACE_RECOGNITION=1). What's missing is the *chain*: "capture what the camera sees → identify it → search it → show the results," and a surface to show them on.
3. Image generation — Exists, real. shared/gemi-image.mjs calls Google gemini-2.5-flash-image and is exposed as the generate_image tool; Leo already has a handler for it. Today it's text→image only. The same model is image-to-image capable, so restyling a camera frame into a t-shirt design is a small additive change (feed the frame as an input image). Needs GEMINI_API_KEY and has its own image quota.
4. "The CAD thing" — Does not exist as a garment/product/CAD viewer. The only 3D-model viewer in the repo is visualizer/ — a *BrainVisualizer* (loads brain.glb to show lattice metrics). BUT the ingredients for a 3D t-shirt mockup viewer are already here: Three.js r128 (kaiverse.js), the GLTFLoader (three-gltfloader-r128.js) is already vendored and already <script>-loaded in oracle.html, and a working OrbitControls+GLTFLoader viewer pattern is proven in the visualizer. So "the cad thing" = a to-be-built orbitable 3D t-shirt mockup that maps the generated design onto a shirt model. Pure browser WebGL — cheap on this box.
---
Tools that exist (defined in tools/oracle-discord/shared/native-tools.mjs, BASE_TOOLS_SCHEMA):
open_page | schema 232, handler 718 | readUrlContent(url) from url-reader.mjs — fetches a URL and returns raw text (title + first 15k chars). Handles GitHub raw/repo specially, else generic page text. No JS render, no screenshot, no images. |web_search | schema 246, handler 724 | webSearch(query) → google-search.mjs askGoogle(). Uses Gemini google_search grounding (a live Google search summarized by gemini-2.5-flash) and returns an answer plus source titles/URLs. Text-only. Needs a Gemini key. |query_wayback_machine | schema 125, handler 607 | Stub — returns a canned string, not a real archive fetch. |arxiv_search | schema 139, handler 611 | Stub — canned string. |No F-named browser tool anywhere. Repo-wide search for firecrawl|puppeteer|playwright|browser_view|browserless|screenshot_url|surf_web found zero hits in the fleet (tools/oracle-discord/**). The only firecrawl string in the whole tree is inside src-donated/ (an unrelated donated TS codebase, not wired into KAI). The only tool whose name starts with "F" is find_place (Google Maps), which is not a browser view.
Conclusion: the owner's "F… browser view option" is not a current KAI tool. Best interpretation: Firecrawl (hosted crawl/scrape/screenshot API — fits "look it up and *show* me" because it can return a rendered page screenshot). It would be a new dependency + API key. Cheaper non-Firecrawl option: reuse the existing web_search + open_page for the *content*, and add a small rendered "show" panel (link cards, or an <iframe> of the page where the site's CSP allows, or a one-shot screenshot).
The frame path is fully built and traceable end-to-end:
oracle.html, ~L3043 vrCam()): getUserMedia({video}) → self-preview tile → every 2 s grabs a canvas toDataURL('image/jpeg', 0.6) and sends {type:'frame', data:<base64>} over the existing /ws/voice socket. The camera button only renders when the server announces video is enabled (m.event==='video', L3025)./ws/voice forwards the frame to oracle-live-voice.sendFrame() (shared/oracle-live-voice.mjs L333).sendFrame() → gemini-live-bridge.sendVideoFrame() (shared/gemini-live-bridge.mjs L1391) → realtimeInput.video on the Gemini Live socket. Gated by KAI_VIDEO_MODE=1 (default OFF; the bridge bounces frames when off).KAI_FACE_RECOGNITION=1, default OFF): oracle-live-voice._recognizeFrame() (L351) → person-recognition.ingestFrame() → embeds/matches against a shared person store and injects a non-spoken [WHO YOU SEE] context line so Leo greets a known person by name.What this means: with KAI_VIDEO_MODE=1, Leo *already sees* the camera and can talk about what's in front of it. What's missing for the owner's ask: there is no "grab this frame → identify the object → web_search it → show the owner the results" chain, and no display surface in the call to show anything (the call UI is audio + camera tiles only). Note the Live-video model streams frames for conversational awareness; a reliable "identify + search" step is better done by capturing one still and sending it to gemini-2.5-flash (vision) for a labelled identification, then feeding that into the existing web_search.
shared/gemi-image.mjs: generateImage(prompt) → POST to gemini-2.5-flash-image :generateContent with responseModalities:['TEXT','IMAGE'], reads image bytes from candidates[].content.parts[].inlineData, returns a Buffer. Requires GEMINI_API_KEY (or GOOGLE_API_KEY). Header note in the file: image gen has its own free-tier quota.generate_image tool (native-tools.mjs schema L54, handler L583) which emits a generate_image ToolEvent; Leo already consumes it (bots/leo.mjs L750, posts the image to Discord).gemini-2.5-flash-image also accepts an input image part, so image-to-image restyle (camera frame + "make this a bold single-color t-shirt graphic, vector, transparent bg") is a small additive function alongside generateImage() — not a new service.Conclusion: image-gen is the one genuinely paid/quota-bound dependency in this chain, but it's already integrated and keyed. Restyle needs only a new "pass an input image" code path.
visualizer/src/main.js L97 — class BrainVisualizer, which loads a brain.glb (drei-assets) with OrbitControls + UnrealBloomPass and drives it from kai_ticks.csv lattice metrics. That's a metrics visualizer, not a product viewer.kaiverse.js.three-gltfloader-r128.js (a GLTFLoader build) is vendored at repo root and already <script src>-loaded in oracle.html (L2465) — so a GLTF model viewer can run inside the dashboard today.visualizer/.test_fetch.glb at repo root shows GLB loading has been exercised before.Conclusion: "the cad thing" is best read as a 3D t-shirt/product mockup viewer to be built — an orbitable shirt model with the generated design applied as a texture/decal. It is pure in-browser WebGL (no server compute), so it's cheap on this box. It needs a CC0 t-shirt .glb/.obj and texture-mapping/decal code. This is build effort, not a compute or licensing problem.
---
web_search (Gemini-grounded) + open_page (raw text), both working with a Gemini key | The "show" surface in the call; optionally a *visual* page render/screenshot (Firecrawl or headless browser) |KAI_VIDEO_MODE), face-recog tap | Still-frame capture-on-demand → identify → search → show chain |gemi-image.mjs + generate_image tool + Leo handler (text→image) | Image-to-image restyle path (feed input frame); render result on the call, not just Discord |oracle.html, viewer pattern in visualizer/ | The t-shirt mockup viewer itself (model + texture/decal mapping + orbit UI) |Feasibility on this Windows/CPU box:
gemini-2.5-flash-image, no local compute — but its own image quota; heavy use likely needs a paid tier. This is the main cost item.---
Cross-cutting first (enables P1/P2/P3/P4 to "show"): add a SHOW panel to the vr-room call UI in oracle.html — a flag-gated (window.KAI_SHOW_PANEL / server-announced) region that can render: text/source cards, an image, an <iframe>, or a <canvas> (for the 3D viewer). Additive DOM only; does not touch audio scheduling, VAD, the pacer, or the camera tiles.
web_search + open_page results (and grounding source links) into the new SHOW panel as titled cards./scrape with screenshot) behind a new KAI_FIRECRAWL_KEY, or an <iframe> fallback for CSP-friendly sites. Decide before building (cost/dependency).oracle.html (panel), a small server route to relay results to /ws/voice. No control changes.gemini-2.5-flash (vision) for a short identification label → feed the label into the existing web_search → render results in the SHOW panel (P1 surface).KAI_VIDEO_MODE Live-video stream (that stays for conversational sight); this is a discrete capture→identify→search→show action, flag-gated (e.g. KAI_VISION_SEARCH).oracle-live-voice.mjs (a captureAndIdentify seam), server relay, oracle.html panel. No pacer/VAD changes.generateImage() in gemi-image.mjs that accepts an input frame + a restyle prompt (t-shirt graphic: bold, vectorized, limited palette, transparent/flat bg).KAI_IMAGE_RESTYLE). Reuses the existing key + tool-event plumbing.gemi-image.mjs (additive fn), native-tools.mjs (optional new restyle_image tool or an arg on generate_image), panel. Cost note: image quota — see below..glb, maps the P3 design as a texture/decal, and gives OrbitControls (rotate/zoom). Render into the SHOW panel <canvas>.three-gltfloader-r128.js and the visualizer/ pattern; keep it isolated from kaiverse.js (do not share the KAIVERSE scene/camera).KAI_MOCKUP_VIEWER). Needs a shirt model asset (CC0) added to kaiverse_assets/ or similar.Suggested order: SHOW panel → P1 → P2 → P3 → P4. Each ships behind its own flag so the owner can A/B and revert, and none of them alter the working first-person KAIVERSE controls, nsUpdateCamera, the voice pacer, or the existing call audio/camera behavior.
---
GEMINI_API_KEY (already in .env): powers web_search, vision identify, and image-gen. Image generation (gemini-2.5-flash-image) has its own quota — P3 is the most likely to need a paid tier under real use.---
No shipped code was edited, no server/fleet restart, no Codex/Cargo version bump. This document is discovery + plan only. Building begins only after the owner confirms scope (especially: Firecrawl yes/no for P1, and image-gen quota/paid tier for P3).