From 37725ac022060b5829bd815988e008e01c82338c Mon Sep 17 00:00:00 2001 From: imrishabh18 Date: Thu, 3 Sep 2026 20:06:46 +0530 Subject: [PATCH] Show TI MCP conversation in subcircuit picker --- system-block-ui/README.md | 7 +- .../src/components/SubcircuitPickerModal.tsx | 184 ++++++++---------- system-block-ui/src/styles.css | 162 ++++++++------- system-block-ui/src/ti-recommendations.ts | 161 +++++---------- 4 files changed, 223 insertions(+), 291 deletions(-) diff --git a/system-block-ui/README.md b/system-block-ui/README.md index 31e48b9..f385bb4 100644 --- a/system-block-ui/README.md +++ b/system-block-ui/README.md @@ -34,9 +34,10 @@ Worker at . No TI credentials are stored in this application. To use a locally running proxy instead, copy `.env.example` to `.env.local` before starting Vite. -In the subcircuit picker, click a recommended TI portfolio part to reveal its -description. Recommendation descriptions stay collapsed until their part is -clicked. +The subcircuit picker keeps the repository's selectable TI subcircuits separate +from the upstream exchange. Expand **TI MCP conversation** to see the exact +request prompt and literal tool-response text. The MCP output is not converted +into selectable parts or recommendation badges. To build the production application and serve that build locally: diff --git a/system-block-ui/src/components/SubcircuitPickerModal.tsx b/system-block-ui/src/components/SubcircuitPickerModal.tsx index c775de6..8f00163 100644 --- a/system-block-ui/src/components/SubcircuitPickerModal.tsx +++ b/system-block-ui/src/components/SubcircuitPickerModal.tsx @@ -2,9 +2,8 @@ import { useEffect, useMemo, useState } from "react"; import type { SubcircuitDefinition } from "../model"; import { - getTiRecommendations, - matchTiRecommendedDefinitionIds, - type TiRecommendedPart, + getTiMcpConversation, + type TiMcpConversation, } from "../ti-recommendations"; export function getSelectableSubcircuitCandidates( @@ -35,16 +34,6 @@ export function SubcircuitPickerModal({ onClose, onSelect, }: SubcircuitPickerModalProps) { - const recommendationDefinitions = useMemo( - () => - definitions.filter( - (definition) => - definition.canInstantiate !== false && - definition.sourcePath.startsWith("lib/subcircuits/") && - definition.category === currentDefinition.category, - ), - [currentDefinition.category, definitions], - ); const candidates = useMemo(() => { const selectable = getSelectableSubcircuitCandidates( definitions, @@ -54,61 +43,42 @@ export function SubcircuitPickerModal({ a.title.localeCompare(b.title, "en"), ); }, [currentDefinition, definitions]); - const [recommendedIds, setRecommendedIds] = useState>( - () => new Set(), - ); - const [recommendedParts, setRecommendedParts] = useState< - readonly TiRecommendedPart[] - >([]); - const [expandedPartNumber, setExpandedPartNumber] = useState( + const [isConversationOpen, setIsConversationOpen] = useState(false); + const [conversation, setConversation] = useState( null, ); - const [isFetchingRecommendations, setIsFetchingRecommendations] = - useState(false); - const widerPortfolioParts = useMemo( - () => - recommendedParts.filter( - (part) => - matchTiRecommendedDefinitionIds( - [part.partNumber], - recommendationDefinitions, - ).size === 0, - ), - [recommendationDefinitions, recommendedParts], - ); + const [isFetchingConversation, setIsFetchingConversation] = useState(false); + const [conversationUnavailable, setConversationUnavailable] = useState(false); + + useEffect(() => { + setIsConversationOpen(false); + setConversation(null); + setIsFetchingConversation(false); + setConversationUnavailable(false); + }, [currentDefinition.category]); useEffect(() => { + if (!isConversationOpen || conversation) return; + let active = true; - setRecommendedIds(new Set()); - setRecommendedParts([]); - setExpandedPartNumber(null); - if (candidates.length === 0) { - setIsFetchingRecommendations(false); - return; - } - setIsFetchingRecommendations(true); - void getTiRecommendations( - currentDefinition.category, - recommendationDefinitions, - ).then( - (recommendations) => { + setConversationUnavailable(false); + setIsFetchingConversation(true); + void getTiMcpConversation(currentDefinition.category).then( + (result) => { if (!active) return; - setRecommendedIds(recommendations.definitionIds); - setRecommendedParts(recommendations.parts); - setIsFetchingRecommendations(false); + setConversation(result); + setIsFetchingConversation(false); }, () => { - if (active) setIsFetchingRecommendations(false); + if (!active) return; + setConversationUnavailable(true); + setIsFetchingConversation(false); }, ); return () => { active = false; }; - }, [ - candidates.length, - currentDefinition.category, - recommendationDefinitions, - ]); + }, [conversation, currentDefinition.category, isConversationOpen]); useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { @@ -147,57 +117,64 @@ export function SubcircuitPickerModal({
Available subcircuits -
- {isFetchingRecommendations && ( - -