@_davideast/stitch-mcp 0.5.5 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-0xbbvsve.js +370 -0
- package/dist/chunk-0xbbvsve.js.map +16 -0
- package/dist/chunk-11ab03kg.js +137 -0
- package/dist/chunk-11ab03kg.js.map +10 -0
- package/dist/chunk-17cs61t4.js +270 -0
- package/dist/chunk-17cs61t4.js.map +10 -0
- package/dist/chunk-1mz7188j.js +20 -0
- package/dist/chunk-1mz7188j.js.map +9 -0
- package/dist/chunk-1txb8kjb.js +17 -0
- package/dist/chunk-1txb8kjb.js.map +9 -0
- package/dist/chunk-1v5q6d3n.js +17 -0
- package/dist/chunk-1v5q6d3n.js.map +9 -0
- package/dist/chunk-1wcg0pjg.js +94 -0
- package/dist/chunk-1wcg0pjg.js.map +10 -0
- package/dist/chunk-2zp03jky.js +19 -0
- package/dist/chunk-2zp03jky.js.map +9 -0
- package/dist/chunk-441ntz7a.js +137 -0
- package/dist/chunk-441ntz7a.js.map +10 -0
- package/dist/chunk-543135qd.js +43679 -0
- package/dist/chunk-543135qd.js.map +234 -0
- package/dist/chunk-564wpgj7.js +246 -0
- package/dist/chunk-564wpgj7.js.map +14 -0
- package/dist/chunk-5jbenaez.js +19185 -0
- package/dist/chunk-5jbenaez.js.map +115 -0
- package/dist/chunk-633ma50k.js +371 -0
- package/dist/chunk-633ma50k.js.map +16 -0
- package/dist/chunk-7ryqstaa.js +7065 -0
- package/dist/chunk-7ryqstaa.js.map +115 -0
- package/dist/chunk-7z5z40ar.js +165 -0
- package/dist/chunk-7z5z40ar.js.map +10 -0
- package/dist/chunk-86gwwcyr.js +46325 -0
- package/dist/chunk-86gwwcyr.js.map +261 -0
- package/dist/chunk-8gegrmmt.js +256 -0
- package/dist/chunk-8gegrmmt.js.map +11 -0
- package/dist/chunk-8hgrrc49.js +17 -0
- package/dist/chunk-8hgrrc49.js.map +9 -0
- package/dist/chunk-8w97w2wa.js +50 -0
- package/dist/chunk-8w97w2wa.js.map +9 -0
- package/dist/chunk-8yfetpqq.js +19132 -0
- package/dist/chunk-8yfetpqq.js.map +115 -0
- package/dist/chunk-94knm2sw.js +1495 -0
- package/dist/chunk-94knm2sw.js.map +23 -0
- package/dist/chunk-9ckyz47q.js +518 -0
- package/dist/chunk-9ckyz47q.js.map +12 -0
- package/dist/chunk-appd0sxm.js +5217 -0
- package/dist/chunk-appd0sxm.js.map +67 -0
- package/dist/chunk-b9atzag0.js +67 -0
- package/dist/chunk-b9atzag0.js.map +10 -0
- package/dist/chunk-c08qy4ty.js +67 -0
- package/dist/chunk-c08qy4ty.js.map +10 -0
- package/dist/chunk-c5dtqvff.js +11 -0
- package/dist/chunk-c5dtqvff.js.map +9 -0
- package/dist/chunk-d1ea3tmp.js +17 -0
- package/dist/chunk-d1ea3tmp.js.map +9 -0
- package/dist/chunk-ecn1ca83.js +34253 -0
- package/dist/chunk-ecn1ca83.js.map +261 -0
- package/dist/chunk-ef1c6gq5.js +947 -0
- package/dist/chunk-ef1c6gq5.js.map +28 -0
- package/dist/chunk-ef355a3f.js +20 -0
- package/dist/chunk-ef355a3f.js.map +9 -0
- package/dist/chunk-f0dt9hv8.js +680 -0
- package/dist/chunk-f0dt9hv8.js.map +17 -0
- package/dist/chunk-f2aj8ff8.js +11 -0
- package/dist/chunk-f2aj8ff8.js.map +9 -0
- package/dist/chunk-f3wp07zw.js +24 -0
- package/dist/chunk-f3wp07zw.js.map +9 -0
- package/dist/chunk-f5wqd3z3.js +10 -0
- package/dist/chunk-f5wqd3z3.js.map +9 -0
- package/dist/chunk-g8hwy0wx.js +504 -0
- package/dist/chunk-g8hwy0wx.js.map +21 -0
- package/dist/chunk-gcx3c3yc.js +680 -0
- package/dist/chunk-gcx3c3yc.js.map +17 -0
- package/dist/chunk-gq6vxp70.js +202 -0
- package/dist/chunk-gq6vxp70.js.map +13 -0
- package/dist/chunk-gw64p5pg.js +164 -0
- package/dist/chunk-gw64p5pg.js.map +10 -0
- package/dist/chunk-hgv5frj1.js +256 -0
- package/dist/chunk-hgv5frj1.js.map +11 -0
- package/dist/chunk-hst78da7.js +87 -0
- package/dist/chunk-hst78da7.js.map +13 -0
- package/dist/chunk-hsxpgjyd.js +256 -0
- package/dist/chunk-hsxpgjyd.js.map +11 -0
- package/dist/chunk-j1v44zzm.js +109 -0
- package/dist/chunk-j1v44zzm.js.map +10 -0
- package/dist/chunk-jfd5md63.js +736 -0
- package/dist/chunk-jfd5md63.js.map +16 -0
- package/dist/chunk-jn5pcnz9.js +270 -0
- package/dist/chunk-jn5pcnz9.js.map +10 -0
- package/dist/chunk-jvhzgyhy.js +62 -0
- package/dist/chunk-jvhzgyhy.js.map +10 -0
- package/dist/chunk-k86st2r8.js +7 -0
- package/dist/chunk-k86st2r8.js.map +9 -0
- package/dist/chunk-kztccppz.js +606 -0
- package/dist/chunk-kztccppz.js.map +15 -0
- package/dist/chunk-m2vk15q9.js +503 -0
- package/dist/chunk-m2vk15q9.js.map +21 -0
- package/dist/chunk-mk40f3ka.js +31529 -0
- package/dist/chunk-mk40f3ka.js.map +245 -0
- package/dist/chunk-mp1sf8x6.js +264 -0
- package/dist/chunk-mp1sf8x6.js.map +12 -0
- package/dist/chunk-mzyqavzd.js +736 -0
- package/dist/chunk-mzyqavzd.js.map +16 -0
- package/dist/chunk-n9fs543g.js +94 -0
- package/dist/chunk-n9fs543g.js.map +10 -0
- package/dist/chunk-nbbwjw90.js +165 -0
- package/dist/chunk-nbbwjw90.js.map +10 -0
- package/dist/chunk-nh14pn95.js +137 -0
- package/dist/chunk-nh14pn95.js.map +10 -0
- package/dist/chunk-qnd877d5.js +947 -0
- package/dist/chunk-qnd877d5.js.map +28 -0
- package/dist/chunk-rng2ypf7.js +538 -0
- package/dist/chunk-rng2ypf7.js.map +15 -0
- package/dist/chunk-sjq10wbw.js +39 -0
- package/dist/chunk-sjq10wbw.js.map +9 -0
- package/dist/chunk-snv6a65k.js +759 -0
- package/dist/chunk-snv6a65k.js.map +19 -0
- package/dist/chunk-sqhdg0mf.js +2138 -0
- package/dist/chunk-sqhdg0mf.js.map +44 -0
- package/dist/chunk-tebher8z.js +514 -0
- package/dist/chunk-tebher8z.js.map +12 -0
- package/dist/chunk-v0wtyr4k.js +66 -0
- package/dist/chunk-v0wtyr4k.js.map +10 -0
- package/dist/chunk-v20274k8.js +246 -0
- package/dist/chunk-v20274k8.js.map +14 -0
- package/dist/chunk-vcp9fp2w.js +839 -0
- package/dist/chunk-vcp9fp2w.js.map +11 -0
- package/dist/chunk-vz737k5f.js +269 -0
- package/dist/chunk-vz737k5f.js.map +10 -0
- package/dist/chunk-x6bsgeqa.js +736 -0
- package/dist/chunk-x6bsgeqa.js.map +16 -0
- package/dist/chunk-xg9kcbp1.js +371 -0
- package/dist/chunk-xg9kcbp1.js.map +16 -0
- package/dist/chunk-xhad5b8x.js +110 -0
- package/dist/chunk-xhad5b8x.js.map +10 -0
- package/dist/chunk-xkwa1mn5.js +203 -0
- package/dist/chunk-xkwa1mn5.js.map +13 -0
- package/dist/chunk-xtcg74kf.js +50 -0
- package/dist/chunk-xtcg74kf.js.map +9 -0
- package/dist/chunk-xzjkaqe9.js +759 -0
- package/dist/chunk-xzjkaqe9.js.map +19 -0
- package/dist/chunk-y65xgj69.js +1495 -0
- package/dist/chunk-y65xgj69.js.map +23 -0
- package/dist/commands/doctor/command.js +1 -1
- package/dist/commands/init/command.js +1 -1
- package/dist/commands/logout/command.js +1 -1
- package/dist/commands/proxy/LoggingCallToolHandler.d.ts +11 -0
- package/dist/commands/proxy/command.js +1 -1
- package/dist/commands/screens/command.js +4 -4
- package/dist/commands/serve/command.js +5 -5
- package/dist/commands/site/command.js +1 -1
- package/dist/commands/snapshot/command.js +1 -1
- package/dist/commands/tool/command.js +1 -1
- package/dist/commands/tool/steps/LogExecuteToolStep.d.ts +19 -0
- package/dist/commands/upload/command.d.ts +2 -0
- package/dist/commands/upload/command.js +77 -0
- package/dist/commands/upload/command.js.map +11 -0
- package/dist/commands/upload/handler.d.ts +20 -0
- package/dist/commands/upload/spec.d.ts +38 -0
- package/dist/commands/view/command.js +1 -1
- package/dist/index.js +9 -9
- package/dist/index.js.map +1 -1
- package/dist/lib/log/append.d.ts +12 -0
- package/dist/lib/log/blob-store/handler.d.ts +10 -0
- package/dist/lib/log/blob-store/spec.d.ts +251 -0
- package/dist/lib/log/capture/handler.d.ts +10 -0
- package/dist/lib/log/capture/spec.d.ts +1504 -0
- package/dist/lib/log/factory.d.ts +4 -0
- package/package.json +2 -2
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/ui/InteractiveViewer.tsx", "../src/ui/JsonTree.tsx", "../src/ui/copy-behaviors/handlers.ts", "../src/ui/copy-behaviors/registry.ts", "../src/ui/navigation-behaviors/handler.ts", "../src/ui/serve-behaviors/server.ts", "../src/ui/serve-behaviors/handlers.ts", "../src/ui/serve-behaviors/registry.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Interactive viewer with navigation support.\n * Wraps JsonTree to handle drill-down navigation and back navigation.\n */\nimport React, { useState, useCallback } from 'react';\nimport { Box, Text } from 'ink';\nimport { JsonTree } from './JsonTree.js';\nimport type { NavigationResult } from './navigation-behaviors/handler.js';\n\nexport interface ViewerState {\n data: any;\n rootLabel?: string;\n resourcePath?: string;\n}\n\ninterface InteractiveViewerProps {\n initialData: any;\n initialRootLabel?: string;\n /** Pre-populated navigation history (for back navigation from deep links) */\n initialHistory?: ViewerState[];\n /** Fetch function to load new resource data */\n onFetch: (resourceName: string) => Promise<any>;\n /** Called when exiting the viewer */\n onExit?: () => void;\n}\n\nexport const InteractiveViewer = ({\n initialData,\n initialRootLabel,\n initialHistory,\n onFetch,\n onExit,\n}: InteractiveViewerProps) => {\n // Use initialHistory if provided, otherwise start with just the initial data\n const [history, setHistory] = useState<ViewerState[]>(() => {\n if (initialHistory && initialHistory.length > 0) {\n return [...initialHistory, { data: initialData, rootLabel: initialRootLabel }];\n }\n return [{ data: initialData, rootLabel: initialRootLabel }];\n });\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const currentState = history[history.length - 1];\n\n const handleNavigate = useCallback(async (result: NavigationResult) => {\n if (!result.target) return;\n\n setIsLoading(true);\n setError(null);\n\n try {\n const data = await onFetch(result.target);\n\n // Determine rootLabel based on navigation type\n let rootLabel: string | undefined;\n if (result.type === 'screen') {\n rootLabel = 'screen';\n } else if (result.type === 'project') {\n rootLabel = 'project';\n } else {\n rootLabel = 'resource';\n }\n\n setHistory(prev => [...prev, { data, rootLabel, resourcePath: result.target }]);\n } catch (err) {\n setError(`Navigation failed: ${err}`);\n } finally {\n setIsLoading(false);\n }\n }, [onFetch]);\n\n const handleBack = useCallback(() => {\n if (history.length > 1) {\n setHistory(prev => prev.slice(0, -1));\n setError(null);\n }\n }, [history.length]);\n\n if (isLoading) {\n return (\n <Box flexDirection=\"column\">\n <Text color=\"blue\">Loading...</Text>\n </Box>\n );\n }\n\n // Should never happen since we initialize with one item, but satisfies TypeScript\n if (!currentState) {\n return <Text color=\"red\">No data to display</Text>;\n }\n\n return (\n <Box flexDirection=\"column\">\n {history.length > 1 && (\n <Text color=\"gray\" dimColor>\n ← Press Backspace to go back ({history.length - 1} level{history.length > 2 ? 's' : ''} deep)\n </Text>\n )}\n {error && <Text color=\"red\">{error}</Text>}\n <JsonTree\n key={history.length}\n data={currentState.data}\n rootLabel={currentState.rootLabel}\n onNavigate={handleNavigate}\n onBack={history.length > 1 ? handleBack : undefined}\n />\n </Box>\n );\n};\n",
|
|
6
|
+
"import React, { useState, useMemo, useEffect, useRef } from 'react';\nimport { Box, Text, useInput, useApp } from 'ink';\nimport { openUrl } from '../platform/browser.js';\nimport { getHandler } from './copy-behaviors/registry.js';\nimport type { CopyResult } from './copy-behaviors/types.js';\nimport { getNavigationTarget, type NavigationResult } from './navigation-behaviors/handler.js';\nimport { getServeHandler } from './serve-behaviors/registry.js';\nimport type { ServeResult } from './serve-behaviors/types.js';\n\ntype TreeNode = {\n id: string; // Unique path identifier\n key: string;\n value: any;\n depth: number;\n isLeaf: boolean;\n isExpanded: boolean;\n hasChildren: boolean;\n};\n\nfunction getType(value: any): string {\n if (value === null) return 'null';\n if (Array.isArray(value)) return 'array';\n return typeof value;\n}\n\nfunction buildVisibleTree(\n data: any,\n expandedIds: Set<string>,\n prefix: string = '',\n depth: number = 0,\n rootLabel?: string\n): TreeNode[] {\n const nodes: TreeNode[] = [];\n const type = getType(data);\n\n // If rootLabel is provided and we're at the root level, add a root node\n if (rootLabel && prefix === '' && depth === 0) {\n const isExpanded = expandedIds.has(rootLabel);\n nodes.push({\n id: rootLabel,\n key: rootLabel,\n value: data,\n depth: 0,\n isLeaf: false,\n isExpanded,\n hasChildren: true,\n });\n\n if (isExpanded) {\n nodes.push(...buildVisibleTree(data, expandedIds, rootLabel, 1));\n }\n return nodes;\n }\n\n if (type === 'object' || type === 'array') {\n const keys = Object.keys(data);\n\n for (const key of keys) {\n const value = data[key];\n const id = prefix ? `${prefix}.${key}` : key;\n const valueType = getType(value);\n const isLeaf = valueType !== 'object' && valueType !== 'array';\n const hasChildren = !isLeaf && Object.keys(value).length > 0;\n const isExpanded = expandedIds.has(id);\n\n nodes.push({\n id,\n key,\n value,\n depth,\n isLeaf,\n isExpanded,\n hasChildren,\n });\n\n if (hasChildren && isExpanded) {\n nodes.push(...buildVisibleTree(value, expandedIds, id, depth + 1));\n }\n }\n }\n\n return nodes;\n}\n\ninterface JsonTreeProps {\n data: any;\n /** Optional label for root object - when set, root is selectable for copying */\n rootLabel?: string;\n /** Called when user navigates into a resource (Enter on screenInstances) */\n onNavigate?: (result: NavigationResult) => void;\n /** Called when user wants to go back (Backspace/Delete) */\n onBack?: () => void;\n}\n\nexport const JsonTree = ({ data, rootLabel, onNavigate, onBack }: JsonTreeProps) => {\n const [expandedIds, setExpandedIds] = useState<Set<string>>(() => {\n const ids = new Set<string>();\n if (rootLabel) {\n ids.add(rootLabel);\n } else if (data && typeof data === 'object') {\n Object.keys(data).forEach((key) => ids.add(key));\n }\n return ids;\n });\n\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [feedbackMessage, setFeedbackMessage] = useState<string | null>(null);\n const lastCPressTime = useRef<number>(0);\n const feedbackTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const visibleNodes = useMemo(() => {\n return buildVisibleTree(data, expandedIds, '', 0, rootLabel);\n }, [data, expandedIds, rootLabel]);\n\n const { exit } = useApp();\n\n useInput((input, key) => {\n if (input === 'q') {\n exit();\n }\n\n // Handle 'c' key for copy\n if (input === 'c') {\n const node = visibleNodes[selectedIndex];\n if (!node) return;\n\n const now = Date.now();\n const timeSinceLastC = now - lastCPressTime.current;\n lastCPressTime.current = now;\n\n // Double-tap detection (within 300ms = 'cc')\n const isDoubleTap = timeSinceLastC < 300;\n\n const handler = getHandler(node.id);\n\n // Progress callback for immediate feedback during async operations\n const onProgress = (message: string) => {\n if (feedbackTimeout.current) clearTimeout(feedbackTimeout.current);\n setFeedbackMessage(message);\n };\n\n const ctx = { key: node.key, value: node.value, path: node.id, onProgress };\n\n const showFeedback = (result: CopyResult) => {\n if (feedbackTimeout.current) clearTimeout(feedbackTimeout.current);\n setFeedbackMessage(result.message);\n feedbackTimeout.current = setTimeout(() => setFeedbackMessage(null), 3000);\n };\n\n if (isDoubleTap) {\n handler.copyExtended(ctx).then(showFeedback);\n } else {\n // Wait briefly to see if it's a double-tap\n setTimeout(() => {\n if (Date.now() - lastCPressTime.current >= 280) {\n handler.copy(ctx).then(showFeedback);\n }\n }, 300);\n }\n return;\n }\n\n // Handle 's' key to serve/preview HTML\n if (input === 's') {\n const node = visibleNodes[selectedIndex];\n if (!node) return;\n\n const handler = getServeHandler(node.id);\n if (!handler) {\n if (feedbackTimeout.current) clearTimeout(feedbackTimeout.current);\n setFeedbackMessage('⚠️ No preview available for this path');\n feedbackTimeout.current = setTimeout(() => setFeedbackMessage(null), 3000);\n return;\n }\n\n const onProgress = (message: string) => {\n if (feedbackTimeout.current) clearTimeout(feedbackTimeout.current);\n setFeedbackMessage(message);\n };\n\n const ctx = { key: node.key, value: node.value, path: node.id, onProgress };\n handler.serve(ctx).then((result: ServeResult) => {\n if (feedbackTimeout.current) clearTimeout(feedbackTimeout.current);\n setFeedbackMessage(result.message);\n feedbackTimeout.current = setTimeout(() => setFeedbackMessage(null), 10000);\n });\n return;\n }\n\n // Handle 'o' key to open project in Stitch web app\n if (input === 'o') {\n const node = visibleNodes[selectedIndex];\n if (!node) return;\n\n // Try to extract project ID from various sources\n let projectId: string | undefined;\n\n // Check if path contains 'projects' and extract the ID\n const projectsMatch = node.id.match(/projects\\.(\\d+)/);\n if (projectsMatch && projectsMatch[1]) {\n // We're somewhere inside a project in the list view\n // Need to find the actual project name from the data\n const projectIndex = parseInt(projectsMatch[1], 10);\n const project = data.projects?.[projectIndex];\n if (project?.name) {\n projectId = project.name.replace('projects/', '');\n }\n }\n\n // Check if we're in a single project/resource view\n if (!projectId && typeof node.value === 'object' && node.value?.name) {\n const nameMatch = node.value.name.match(/projects\\/(\\d+)/);\n if (nameMatch) {\n projectId = nameMatch[1];\n }\n }\n\n // Check if the node's name property contains a project ID\n if (!projectId && node.key === 'name' && typeof node.value === 'string') {\n const nameMatch = node.value.match(/projects\\/(\\d+)/);\n if (nameMatch) {\n projectId = nameMatch[1];\n }\n }\n\n // Check if rootLabel is 'screen' or 'resource' and data has a name\n if (!projectId && (rootLabel === 'screen' || rootLabel === 'resource')) {\n const nameMatch = data.name?.match(/projects\\/(\\d+)/);\n if (nameMatch) {\n projectId = nameMatch[1];\n }\n }\n\n if (projectId) {\n const url = `https://stitch.withgoogle.com/projects/${projectId}`;\n // Open in browser using platform command\n openUrl(url);\n\n if (feedbackTimeout.current) clearTimeout(feedbackTimeout.current);\n setFeedbackMessage(`🔗 Opened project in browser`);\n feedbackTimeout.current = setTimeout(() => setFeedbackMessage(null), 3000);\n } else {\n if (feedbackTimeout.current) clearTimeout(feedbackTimeout.current);\n setFeedbackMessage(`⚠️ No project found at this path`);\n feedbackTimeout.current = setTimeout(() => setFeedbackMessage(null), 3000);\n }\n return;\n }\n\n if (key.upArrow) {\n setSelectedIndex(Math.max(0, selectedIndex - 1));\n }\n\n if (key.downArrow) {\n setSelectedIndex(Math.min(visibleNodes.length - 1, selectedIndex + 1));\n }\n\n if (key.rightArrow || key.return) {\n const node = visibleNodes[selectedIndex];\n if (node && node.hasChildren) {\n if (!node.isExpanded) {\n const newExpanded = new Set(expandedIds);\n newExpanded.add(node.id);\n setExpandedIds(newExpanded);\n }\n }\n\n // Check for navigation on Enter (not rightArrow)\n if (key.return && node && onNavigate) {\n const navResult = getNavigationTarget({ path: node.id, value: node.value, key: node.key });\n if (navResult.shouldNavigate) {\n onNavigate(navResult);\n return;\n }\n }\n }\n\n // Backspace/Delete for back navigation\n if ((key.delete || key.backspace) && onBack) {\n onBack();\n return;\n }\n\n if (key.leftArrow) {\n const node = visibleNodes[selectedIndex];\n if (node) {\n if (node.isExpanded) {\n const newExpanded = new Set(expandedIds);\n newExpanded.delete(node.id);\n setExpandedIds(newExpanded);\n } else {\n // Move to parent\n // Find parent ID by removing last segment\n const lastDot = node.id.lastIndexOf('.');\n if (lastDot !== -1) {\n const parentId = node.id.substring(0, lastDot);\n const parentIndex = visibleNodes.findIndex(n => n.id === parentId);\n if (parentIndex !== -1) {\n setSelectedIndex(parentIndex);\n // Optional: Collapse parent when moving back to it?\n // Usually Left arrow on a collapsed node moves to parent.\n }\n } else {\n // Top level, do nothing?\n }\n }\n }\n }\n });\n\n // Adjust scroll/window logic if list is long?\n // For simplicity, we render a slice around the cursor if needed, or rely on terminal scrolling.\n // Ink handles output, but if it's longer than screen height, it might be weird.\n // Let's just render all for now, typical terminals scroll.\n // But a static UI at bottom is better.\n // \"Arrow through\" implies a viewport.\n\n // Let's implement a simple viewport\n const viewportHeight = 20; // Configurable?\n const startRow = Math.max(0, Math.min(selectedIndex - 2, visibleNodes.length - viewportHeight));\n const endRow = Math.min(startRow + viewportHeight, visibleNodes.length);\n const viewportNodes = visibleNodes.slice(startRow, endRow);\n\n if (!data || typeof data !== 'object') {\n return <Text>Invalid data: {String(data)}</Text>;\n }\n\n if (Object.keys(data).length === 0) {\n return <Text>Empty object</Text>;\n }\n\n return (\n <Box flexDirection=\"column\">\n <Text color=\"blue\" bold>JSON Viewer (Use Arrows to Navigate, 'q' to Quit)</Text>\n <Box flexDirection=\"column\" borderStyle=\"single\">\n {viewportNodes.map((node, index) => {\n const absoluteIndex = startRow + index;\n const isSelected = absoluteIndex === selectedIndex;\n const indentation = ' '.repeat(node.depth);\n\n let prefixChar = ' ';\n if (node.hasChildren) {\n prefixChar = node.isExpanded ? '▼' : '▶';\n }\n\n let valueDisplay = '';\n if (node.isLeaf) {\n const valType = getType(node.value);\n if (valType === 'string') valueDisplay = `\"${node.value}\"`;\n else valueDisplay = String(node.value);\n } else {\n const type = Array.isArray(node.value) ? '[]' : '{}';\n const itemCount = Object.keys(node.value).length;\n // Try to show a meaningful label for objects (title, name, id, etc.)\n const label = node.value.title || node.value.name || node.value.displayName || node.value.id || null;\n if (label && typeof label === 'string') {\n valueDisplay = `${type} \"${label}\" (${itemCount})`;\n } else {\n valueDisplay = `${type} ${itemCount} items`;\n }\n }\n\n return (\n <Box key={node.id}>\n <Text backgroundColor={isSelected ? 'blue' : undefined} color={isSelected ? 'white' : undefined} wrap=\"truncate\">\n {indentation}\n <Text color=\"green\">{prefixChar} {node.key}</Text>\n <Text>: </Text>\n <Text color=\"yellow\">{valueDisplay}</Text>\n </Text>\n </Box>\n );\n })}\n {visibleNodes.length > viewportHeight && (\n <Text color=\"gray\">... {visibleNodes.length - endRow} more items ...</Text>\n )}\n </Box>\n <Text color=\"gray\">\n Selected Path: {visibleNodes[selectedIndex]?.id || 'none'} | 'c' copy, 'cc' extended, 's' preview\n </Text>\n {feedbackMessage && (\n <Text color=\"cyan\" bold>{feedbackMessage}</Text>\n )}\n </Box>\n );\n};\n",
|
|
7
|
+
"/**\n * Copy handlers - isolated behavior implementations.\n */\nimport type { CopyHandler, CopyContext, CopyResult } from './types.js';\nimport { copyJson, copyText, downloadAndCopyImage, downloadAndCopyText } from './clipboard.js';\n\n/**\n * Default handler: copies value on \"c\", copies {key: value} on \"cc\"\n */\nexport const defaultCopyHandler: CopyHandler = {\n async copy(ctx: CopyContext): Promise<CopyResult> {\n try {\n await copyJson(ctx.value);\n const preview = typeof ctx.value === 'string'\n ? `\"${ctx.value.slice(0, 50)}${ctx.value.length > 50 ? '...' : ''}\"`\n : JSON.stringify(ctx.value).slice(0, 50);\n return { success: true, message: `Copied: ${preview}` };\n } catch (error) {\n return { success: false, message: `Copy failed: ${error}` };\n }\n },\n\n async copyExtended(ctx: CopyContext): Promise<CopyResult> {\n try {\n const obj = { [ctx.key]: ctx.value };\n await copyJson(obj);\n return { success: true, message: `Copied: { ${ctx.key}: ... }` };\n } catch (error) {\n return { success: false, message: `Copy failed: ${error}` };\n }\n },\n};\n\n/**\n * Image URL handler: copies URL on \"c\", downloads and copies image on \"cc\"\n */\nexport const imageUrlCopyHandler: CopyHandler = {\n async copy(ctx: CopyContext): Promise<CopyResult> {\n try {\n if (typeof ctx.value !== 'string') {\n return { success: false, message: 'Value is not a URL string' };\n }\n await copyText(ctx.value);\n return { success: true, message: `Copied URL: ${ctx.value.slice(0, 60)}...` };\n } catch (error) {\n return { success: false, message: `Copy failed: ${error}` };\n }\n },\n\n async copyExtended(ctx: CopyContext): Promise<CopyResult> {\n try {\n if (typeof ctx.value !== 'string') {\n return { success: false, message: 'Value is not a URL string' };\n }\n // Show immediate progress feedback\n ctx.onProgress?.('📷 Downloading image...');\n await downloadAndCopyImage(ctx.value);\n return { success: true, message: '📷 Image copied to clipboard!' };\n } catch (error) {\n return { success: false, message: `Image copy failed: ${error}` };\n }\n },\n};\n\n/**\n * HTML code URL handler: copies URL on \"c\", downloads and copies HTML code on \"cc\"\n */\nexport const htmlCodeCopyHandler: CopyHandler = {\n async copy(ctx: CopyContext): Promise<CopyResult> {\n try {\n if (typeof ctx.value !== 'string') {\n return { success: false, message: 'Value is not a URL string' };\n }\n await copyText(ctx.value);\n return { success: true, message: `Copied URL: ${ctx.value.slice(0, 60)}...` };\n } catch (error) {\n return { success: false, message: `Copy failed: ${error}` };\n }\n },\n\n async copyExtended(ctx: CopyContext): Promise<CopyResult> {\n try {\n if (typeof ctx.value !== 'string') {\n return { success: false, message: 'Value is not a URL string' };\n }\n ctx.onProgress?.('📝 Downloading HTML code...');\n await downloadAndCopyText(ctx.value);\n return { success: true, message: '📝 HTML code copied to clipboard!' };\n } catch (error) {\n return { success: false, message: `HTML copy failed: ${error}` };\n }\n },\n};\n",
|
|
8
|
+
"/**\n * Registry for path-based copy handler selection.\n */\nimport type { CopyHandler, PathMatcher } from './types.js';\nimport { defaultCopyHandler, imageUrlCopyHandler, htmlCodeCopyHandler } from './handlers.js';\n\ninterface HandlerRegistration {\n matcher: PathMatcher;\n handler: CopyHandler;\n}\n\nconst registrations: HandlerRegistration[] = [];\n\n/**\n * Register a handler for paths matching the given pattern.\n * Later registrations take precedence over earlier ones.\n */\nexport function registerHandler(matcher: PathMatcher, handler: CopyHandler): void {\n registrations.push({ matcher, handler });\n}\n\n/**\n * Get the appropriate handler for a given path.\n * Returns the most recently registered matching handler, or default.\n */\nexport function getHandler(path: string): CopyHandler {\n // Check in reverse order (most recent first)\n for (let i = registrations.length - 1; i >= 0; i--) {\n const registration = registrations[i];\n if (registration && registration.matcher(path)) {\n return registration.handler;\n }\n }\n return defaultCopyHandler;\n}\n\n/**\n * Create a matcher that checks if path ends with the given suffix.\n */\nexport function endsWith(suffix: string): PathMatcher {\n return (path: string) => path.endsWith(suffix);\n}\n\n/**\n * Create a matcher that checks if path contains the given segment.\n */\nexport function contains(segment: string): PathMatcher {\n return (path: string) => path.includes(segment);\n}\n\n// ============================================================================\n// Default registrations\n// ============================================================================\n\n// Register image URL handler for thumbnailScreenshot.downloadUrl\nregisterHandler(endsWith('.thumbnailScreenshot.downloadUrl'), imageUrlCopyHandler);\n\n// Register image URL handler for screenshot.downloadUrl (in screen view)\nregisterHandler(endsWith('.screenshot.downloadUrl'), imageUrlCopyHandler);\n\n// Register HTML code handler for htmlCode.downloadUrl\nregisterHandler(endsWith('.htmlCode.downloadUrl'), htmlCodeCopyHandler);\n\n// Export for convenience\nexport { defaultCopyHandler, imageUrlCopyHandler, htmlCodeCopyHandler };\n",
|
|
9
|
+
"/**\n * Navigation behaviors for the JSON viewer.\n * Handles drill-down navigation into screens and back navigation.\n */\n\nexport interface NavigationContext {\n /** Current selected path */\n path: string;\n /** Current node value */\n value: any;\n /** The key of the node */\n key: string;\n}\n\nexport interface NavigationResult {\n /** Whether navigation should occur */\n shouldNavigate: boolean;\n /** Target resource to navigate to */\n target?: string;\n /** Type of navigation (e.g., 'screen', 'project') */\n type?: string;\n}\n\nexport type NavigationHandler = (ctx: NavigationContext) => NavigationResult;\n\n/**\n * Detects if the current node is within screenInstances and can navigate to a screen.\n * When on screenInstances[x] or screenInstances[x].sourceScreen, extract the sourceScreen value.\n */\nexport function screenInstanceNavigationHandler(ctx: NavigationContext): NavigationResult {\n // Check if we're in a screenInstances path\n if (!ctx.path.includes('screenInstances')) {\n return { shouldNavigate: false };\n }\n\n // If value is an object with sourceScreen, use that\n if (ctx.value && typeof ctx.value === 'object' && ctx.value.sourceScreen) {\n return {\n shouldNavigate: true,\n target: ctx.value.sourceScreen,\n type: 'screen',\n };\n }\n\n // If we're on the sourceScreen property itself\n if (ctx.key === 'sourceScreen' && typeof ctx.value === 'string') {\n return {\n shouldNavigate: true,\n target: ctx.value,\n type: 'screen',\n };\n }\n\n return { shouldNavigate: false };\n}\n\n/**\n * Registry of navigation handlers.\n * Handlers are checked in order, first match wins.\n */\nconst navigationHandlers: NavigationHandler[] = [\n screenInstanceNavigationHandler,\n];\n\n/**\n * Get navigation result for a given context.\n */\nexport function getNavigationTarget(ctx: NavigationContext): NavigationResult {\n for (const handler of navigationHandlers) {\n const result = handler(ctx);\n if (result.shouldNavigate) {\n return result;\n }\n }\n return { shouldNavigate: false };\n}\n\n/**\n * Register a custom navigation handler.\n */\nexport function registerNavigationHandler(handler: NavigationHandler): void {\n navigationHandlers.unshift(handler); // Add at start for priority\n}\n",
|
|
10
|
+
"/**\n * In-memory HTTP server using node:http for cross-runtime compatibility.\n */\nimport { createServer, type Server } from 'node:http';\nimport { randomBytes } from 'node:crypto';\nimport { openUrl } from '../../platform/browser.js';\n\nexport interface ServeInstance {\n url: string;\n stop: () => void;\n}\n\nexport async function serveHtmlInMemory(\n html: string,\n options?: { timeout?: number; openBrowser?: boolean }\n): Promise<ServeInstance> {\n const timeout = options?.timeout ?? 5 * 60 * 1000;\n const openBrowser = options?.openBrowser ?? true;\n\n return new Promise((resolve, reject) => {\n const server: Server = createServer((req, res) => {\n const nonce = randomBytes(16).toString('base64');\n const csp = [\n \"default-src 'self' data: https:;\",\n `script-src 'self' 'nonce-${nonce}';`,\n \"style-src 'self' 'unsafe-inline';\",\n \"object-src 'none';\",\n \"base-uri 'self';\",\n ].join(' ');\n\n res.writeHead(200, {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Content-Security-Policy': csp,\n 'X-Content-Type-Options': 'nosniff',\n 'Referrer-Policy': 'no-referrer',\n });\n\n // Inject nonce into all script tags in the HTML\n const htmlWithNonces = html.replace(/<script(\\b[^>]*)>/gi, `<script$1 nonce=\"${nonce}\">`);\n res.end(htmlWithNonces);\n });\n\n server.listen(0, '127.0.0.1', () => {\n const address = server.address();\n if (!address || typeof address === 'string') {\n reject(new Error('Failed to get server address'));\n return;\n }\n\n const url = `http://127.0.0.1:${address.port}`;\n const timer = setTimeout(() => server.close(), timeout);\n const stop = () => { clearTimeout(timer); server.close(); };\n\n if (openBrowser) {\n openUrl(url);\n }\n\n resolve({ url, stop });\n });\n\n server.on('error', reject);\n });\n}\n",
|
|
11
|
+
"/**\n * Serve handlers - isolated behavior implementations.\n */\nimport type { ServeHandler, ServeContext, ServeResult } from './types.js';\nimport { serveHtmlInMemory } from './server.js';\n\n// Export dependencies for testing\nexport const deps = {\n serveHtmlInMemory\n};\n\nexport const htmlCodeServeHandler: ServeHandler = {\n async serve(ctx: ServeContext): Promise<ServeResult> {\n try {\n // Extract URL - either from value directly or from value.downloadUrl\n let url: string;\n if (typeof ctx.value === 'string') {\n url = ctx.value;\n } else if (typeof ctx.value === 'object' && ctx.value?.downloadUrl) {\n url = ctx.value.downloadUrl;\n } else {\n return { success: false, message: 'No download URL found' };\n }\n\n ctx.onProgress?.('📥 Downloading HTML...');\n const response = await fetch(url);\n if (!response.ok) {\n return { success: false, message: `Download failed: ${response.status} ${response.statusText}` };\n }\n const html = await response.text();\n\n ctx.onProgress?.('🚀 Starting local server...');\n const { url: serveUrl } = await deps.serveHtmlInMemory(html);\n\n ctx.onProgress?.('🌐 Opening browser...');\n return { success: true, message: `🌐 Preview at ${serveUrl} (auto-closes in 5 min)`, url: serveUrl };\n } catch (error) {\n return { success: false, message: `Serve failed: ${error instanceof Error ? error.message : String(error)}` };\n }\n },\n};\n",
|
|
12
|
+
"/**\n * Registry for path-based serve handler selection.\n */\nimport type { ServeHandler, PathMatcher } from './types.js';\nimport { htmlCodeServeHandler } from './handlers.js';\n\ninterface HandlerRegistration { matcher: PathMatcher; handler: ServeHandler; }\nconst registrations: HandlerRegistration[] = [];\n\nexport function registerServeHandler(matcher: PathMatcher, handler: ServeHandler): void {\n registrations.push({ matcher, handler });\n}\n\nexport function getServeHandler(path: string): ServeHandler | null {\n for (let i = registrations.length - 1; i >= 0; i--) {\n const reg = registrations[i];\n if (reg && reg.matcher(path)) return reg.handler;\n }\n return null;\n}\n\nexport function endsWith(suffix: string): PathMatcher {\n return (path: string) => path.endsWith(suffix);\n}\n\nexport function contains(segment: string): PathMatcher {\n return (path: string) => path.includes(segment);\n}\n\n// Default registrations\nregisterServeHandler(endsWith('.htmlCode'), htmlCodeServeHandler);\nregisterServeHandler(endsWith('.htmlCode.downloadUrl'), htmlCodeServeHandler);\n\nexport { htmlCodeServeHandler };\n"
|
|
13
|
+
],
|
|
14
|
+
"mappings": "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",
|
|
15
|
+
"debugId": "5616FED4529C741864756E2164756E21",
|
|
16
|
+
"names": []
|
|
17
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createCaptureHandler,
|
|
3
|
+
isLogEnabled
|
|
4
|
+
} from "./chunk-rng2ypf7.js";
|
|
5
|
+
import {
|
|
6
|
+
CallToolRequestSchema,
|
|
7
|
+
JSONRPCMessageSchema,
|
|
8
|
+
StitchProxy
|
|
9
|
+
} from "./chunk-mk40f3ka.js";
|
|
10
|
+
import"./chunk-c6ge431q.js";
|
|
11
|
+
import"./chunk-9wyra8hs.js";
|
|
12
|
+
|
|
13
|
+
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
14
|
+
import process2 from "node:process";
|
|
15
|
+
|
|
16
|
+
// node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
|
|
17
|
+
class ReadBuffer {
|
|
18
|
+
append(chunk) {
|
|
19
|
+
this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
|
|
20
|
+
}
|
|
21
|
+
readMessage() {
|
|
22
|
+
if (!this._buffer) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const index = this._buffer.indexOf(`
|
|
26
|
+
`);
|
|
27
|
+
if (index === -1) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
const line = this._buffer.toString("utf8", 0, index).replace(/\r$/, "");
|
|
31
|
+
this._buffer = this._buffer.subarray(index + 1);
|
|
32
|
+
return deserializeMessage(line);
|
|
33
|
+
}
|
|
34
|
+
clear() {
|
|
35
|
+
this._buffer = undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function deserializeMessage(line) {
|
|
39
|
+
return JSONRPCMessageSchema.parse(JSON.parse(line));
|
|
40
|
+
}
|
|
41
|
+
function serializeMessage(message) {
|
|
42
|
+
return JSON.stringify(message) + `
|
|
43
|
+
`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
47
|
+
class StdioServerTransport {
|
|
48
|
+
constructor(_stdin = process2.stdin, _stdout = process2.stdout) {
|
|
49
|
+
this._stdin = _stdin;
|
|
50
|
+
this._stdout = _stdout;
|
|
51
|
+
this._readBuffer = new ReadBuffer;
|
|
52
|
+
this._started = false;
|
|
53
|
+
this._ondata = (chunk) => {
|
|
54
|
+
this._readBuffer.append(chunk);
|
|
55
|
+
this.processReadBuffer();
|
|
56
|
+
};
|
|
57
|
+
this._onerror = (error) => {
|
|
58
|
+
this.onerror?.(error);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
async start() {
|
|
62
|
+
if (this._started) {
|
|
63
|
+
throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");
|
|
64
|
+
}
|
|
65
|
+
this._started = true;
|
|
66
|
+
this._stdin.on("data", this._ondata);
|
|
67
|
+
this._stdin.on("error", this._onerror);
|
|
68
|
+
}
|
|
69
|
+
processReadBuffer() {
|
|
70
|
+
while (true) {
|
|
71
|
+
try {
|
|
72
|
+
const message = this._readBuffer.readMessage();
|
|
73
|
+
if (message === null) {
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
this.onmessage?.(message);
|
|
77
|
+
} catch (error) {
|
|
78
|
+
this.onerror?.(error);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async close() {
|
|
83
|
+
this._stdin.off("data", this._ondata);
|
|
84
|
+
this._stdin.off("error", this._onerror);
|
|
85
|
+
const remainingDataListeners = this._stdin.listenerCount("data");
|
|
86
|
+
if (remainingDataListeners === 0) {
|
|
87
|
+
this._stdin.pause();
|
|
88
|
+
}
|
|
89
|
+
this._readBuffer.clear();
|
|
90
|
+
this.onclose?.();
|
|
91
|
+
}
|
|
92
|
+
send(message) {
|
|
93
|
+
return new Promise((resolve) => {
|
|
94
|
+
const json = serializeMessage(message);
|
|
95
|
+
if (this._stdout.write(json)) {
|
|
96
|
+
resolve();
|
|
97
|
+
} else {
|
|
98
|
+
this._stdout.once("drain", resolve);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/commands/proxy/LoggingCallToolHandler.ts
|
|
105
|
+
var DEFAULT_STITCH_MCP_URL = "https://stitch.googleapis.com/mcp";
|
|
106
|
+
function installLoggingCallToolHandler(proxy, capture, opts) {
|
|
107
|
+
const apiKey = opts?.apiKey ?? process.env.STITCH_API_KEY;
|
|
108
|
+
const url = opts?.url ?? process.env.STITCH_MCP_URL ?? DEFAULT_STITCH_MCP_URL;
|
|
109
|
+
if (!apiKey)
|
|
110
|
+
throw new Error("logging proxy requires STITCH_API_KEY");
|
|
111
|
+
const server = proxy?.server?.server;
|
|
112
|
+
if (!server || typeof server.setRequestHandler !== "function") {
|
|
113
|
+
throw new Error("cannot install logging handler: proxy.server.server.setRequestHandler missing");
|
|
114
|
+
}
|
|
115
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
116
|
+
const { name, arguments: args } = request.params;
|
|
117
|
+
const startedAt = new Date().toISOString();
|
|
118
|
+
const t0 = Date.now();
|
|
119
|
+
let result;
|
|
120
|
+
try {
|
|
121
|
+
result = await forwardToStitch({ apiKey, url }, name, args ?? {});
|
|
122
|
+
} catch (err) {
|
|
123
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
124
|
+
result = { content: [{ type: "text", text: `Error calling ${name}: ${message}` }], isError: true };
|
|
125
|
+
}
|
|
126
|
+
const finishedAt = new Date().toISOString();
|
|
127
|
+
const durationMs = Date.now() - t0;
|
|
128
|
+
try {
|
|
129
|
+
await capture.capture({
|
|
130
|
+
tool: name,
|
|
131
|
+
args: args ?? {},
|
|
132
|
+
result,
|
|
133
|
+
duration_ms: durationMs,
|
|
134
|
+
started_at: startedAt,
|
|
135
|
+
finished_at: finishedAt
|
|
136
|
+
});
|
|
137
|
+
} catch (err) {
|
|
138
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
139
|
+
console.error(`[stitch-mcp log] capture failed: ${msg}`);
|
|
140
|
+
}
|
|
141
|
+
return result;
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
async function forwardToStitch(opts, name, args) {
|
|
145
|
+
const body = {
|
|
146
|
+
jsonrpc: "2.0",
|
|
147
|
+
method: "tools/call",
|
|
148
|
+
params: { name, arguments: args },
|
|
149
|
+
id: Date.now()
|
|
150
|
+
};
|
|
151
|
+
const res = await globalThis.fetch(opts.url, {
|
|
152
|
+
method: "POST",
|
|
153
|
+
headers: {
|
|
154
|
+
"Content-Type": "application/json",
|
|
155
|
+
Accept: "application/json",
|
|
156
|
+
"X-Goog-Api-Key": opts.apiKey
|
|
157
|
+
},
|
|
158
|
+
body: JSON.stringify(body)
|
|
159
|
+
});
|
|
160
|
+
if (!res.ok)
|
|
161
|
+
throw new Error(`Stitch API error (${res.status}): ${await res.text()}`);
|
|
162
|
+
const json = await res.json();
|
|
163
|
+
if (json.error)
|
|
164
|
+
throw new Error(`Stitch RPC error: ${json.error.message}`);
|
|
165
|
+
return json.result;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// src/commands/proxy/handler.ts
|
|
169
|
+
class ProxyCommandHandler {
|
|
170
|
+
createProxy;
|
|
171
|
+
createTransport;
|
|
172
|
+
constructor(deps) {
|
|
173
|
+
this.createProxy = deps?.createProxy ?? ((opts) => new StitchProxy(opts));
|
|
174
|
+
this.createTransport = deps?.createTransport ?? (() => new StdioServerTransport);
|
|
175
|
+
}
|
|
176
|
+
async execute(input) {
|
|
177
|
+
try {
|
|
178
|
+
const proxy = this.createProxy({
|
|
179
|
+
apiKey: process.env.STITCH_API_KEY
|
|
180
|
+
});
|
|
181
|
+
const transport = this.createTransport();
|
|
182
|
+
await proxy.start(transport);
|
|
183
|
+
if (isLogEnabled()) {
|
|
184
|
+
try {
|
|
185
|
+
installLoggingCallToolHandler(proxy, createCaptureHandler());
|
|
186
|
+
} catch (err) {
|
|
187
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
188
|
+
console.error(`[stitch-mcp log] failed to install capture handler: ${msg}`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
await transport.onclose;
|
|
192
|
+
return { success: true, data: { status: "running" } };
|
|
193
|
+
} catch (e) {
|
|
194
|
+
return { success: false, error: { code: "PROXY_START_ERROR", message: e.message, recoverable: false } };
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
export {
|
|
199
|
+
ProxyCommandHandler
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
//# debugId=AB5D43359F304DEA64756E2164756E21
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js", "../node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js", "../src/commands/proxy/LoggingCallToolHandler.ts", "../src/commands/proxy/handler.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import process from 'node:process';\nimport { ReadBuffer, serializeMessage } from '../shared/stdio.js';\n/**\n * Server transport for stdio: this communicates with an MCP client by reading from the current process' stdin and writing to stdout.\n *\n * This transport is only available in Node.js environments.\n */\nexport class StdioServerTransport {\n constructor(_stdin = process.stdin, _stdout = process.stdout) {\n this._stdin = _stdin;\n this._stdout = _stdout;\n this._readBuffer = new ReadBuffer();\n this._started = false;\n // Arrow functions to bind `this` properly, while maintaining function identity.\n this._ondata = (chunk) => {\n this._readBuffer.append(chunk);\n this.processReadBuffer();\n };\n this._onerror = (error) => {\n this.onerror?.(error);\n };\n }\n /**\n * Starts listening for messages on stdin.\n */\n async start() {\n if (this._started) {\n throw new Error('StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.');\n }\n this._started = true;\n this._stdin.on('data', this._ondata);\n this._stdin.on('error', this._onerror);\n }\n processReadBuffer() {\n while (true) {\n try {\n const message = this._readBuffer.readMessage();\n if (message === null) {\n break;\n }\n this.onmessage?.(message);\n }\n catch (error) {\n this.onerror?.(error);\n }\n }\n }\n async close() {\n // Remove our event listeners first\n this._stdin.off('data', this._ondata);\n this._stdin.off('error', this._onerror);\n // Check if we were the only data listener\n const remainingDataListeners = this._stdin.listenerCount('data');\n if (remainingDataListeners === 0) {\n // Only pause stdin if we were the only listener\n // This prevents interfering with other parts of the application that might be using stdin\n this._stdin.pause();\n }\n // Clear the buffer and notify closure\n this._readBuffer.clear();\n this.onclose?.();\n }\n send(message) {\n return new Promise(resolve => {\n const json = serializeMessage(message);\n if (this._stdout.write(json)) {\n resolve();\n }\n else {\n this._stdout.once('drain', resolve);\n }\n });\n }\n}\n//# sourceMappingURL=stdio.js.map",
|
|
6
|
+
"import { JSONRPCMessageSchema } from '../types.js';\n/**\n * Buffers a continuous stdio stream into discrete JSON-RPC messages.\n */\nexport class ReadBuffer {\n append(chunk) {\n this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;\n }\n readMessage() {\n if (!this._buffer) {\n return null;\n }\n const index = this._buffer.indexOf('\\n');\n if (index === -1) {\n return null;\n }\n const line = this._buffer.toString('utf8', 0, index).replace(/\\r$/, '');\n this._buffer = this._buffer.subarray(index + 1);\n return deserializeMessage(line);\n }\n clear() {\n this._buffer = undefined;\n }\n}\nexport function deserializeMessage(line) {\n return JSONRPCMessageSchema.parse(JSON.parse(line));\n}\nexport function serializeMessage(message) {\n return JSON.stringify(message) + '\\n';\n}\n//# sourceMappingURL=stdio.js.map",
|
|
7
|
+
"import { CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';\nimport type { CaptureSpec } from '../../lib/log/capture/spec.js';\n\nconst DEFAULT_STITCH_MCP_URL = 'https://stitch.googleapis.com/mcp';\n\ninterface ForwardOptions {\n apiKey: string;\n url: string;\n}\n\n/**\n * Replace the SDK proxy's tools/call handler with a capture-wrapped variant.\n * Must be called AFTER {@link StitchProxy.start} (which registers the original).\n */\nexport function installLoggingCallToolHandler(proxy: any, capture: CaptureSpec, opts?: Partial<ForwardOptions>): void {\n const apiKey = opts?.apiKey ?? process.env.STITCH_API_KEY;\n const url = opts?.url ?? process.env.STITCH_MCP_URL ?? DEFAULT_STITCH_MCP_URL;\n if (!apiKey) throw new Error('logging proxy requires STITCH_API_KEY');\n\n // The SDK exposes McpServer at proxy.server, whose underlying Server is at .server.\n const server = proxy?.server?.server;\n if (!server || typeof server.setRequestHandler !== 'function') {\n throw new Error('cannot install logging handler: proxy.server.server.setRequestHandler missing');\n }\n\n server.setRequestHandler(CallToolRequestSchema, async (request: any) => {\n const { name, arguments: args } = request.params;\n const startedAt = new Date().toISOString();\n const t0 = Date.now();\n\n let result: any;\n try {\n result = await forwardToStitch({ apiKey, url }, name, args ?? {});\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n result = { content: [{ type: 'text', text: `Error calling ${name}: ${message}` }], isError: true };\n }\n const finishedAt = new Date().toISOString();\n const durationMs = Date.now() - t0;\n\n // best-effort capture — never propagate failures to the MCP client\n try {\n await capture.capture({\n tool: name,\n args: (args ?? {}) as Record<string, unknown>,\n result,\n duration_ms: durationMs,\n started_at: startedAt,\n finished_at: finishedAt,\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n // eslint-disable-next-line no-console\n console.error(`[stitch-mcp log] capture failed: ${msg}`);\n }\n\n return result;\n });\n}\n\n/** Minimal JSON-RPC forwarder, mirroring the SDK's private forwardToStitch. */\nasync function forwardToStitch(opts: ForwardOptions, name: string, args: Record<string, unknown>): Promise<any> {\n const body = {\n jsonrpc: '2.0',\n method: 'tools/call',\n params: { name, arguments: args },\n id: Date.now(),\n };\n const res = await globalThis.fetch(opts.url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n 'X-Goog-Api-Key': opts.apiKey,\n },\n body: JSON.stringify(body),\n });\n if (!res.ok) throw new Error(`Stitch API error (${res.status}): ${await res.text()}`);\n const json = (await res.json()) as { result?: unknown; error?: { message: string } };\n if (json.error) throw new Error(`Stitch RPC error: ${json.error.message}`);\n return json.result;\n}\n",
|
|
8
|
+
"import { StitchProxy } from '@google/stitch-sdk';\nimport type { StitchProxy as StitchProxyType } from '@google/stitch-sdk';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { createCaptureHandler, isLogEnabled } from '../../lib/log/factory.js';\nimport { installLoggingCallToolHandler } from './LoggingCallToolHandler.js';\n\ninterface ProxyCommandInput {\n port?: number;\n debug?: boolean;\n}\n\ninterface ProxyCommandResult {\n success: boolean;\n data?: { status: string };\n error?: { code: string; message: string; recoverable: boolean };\n}\n\nexport class ProxyCommandHandler {\n private createProxy: (opts: { apiKey?: string }) => StitchProxyType;\n private createTransport: () => StdioServerTransport;\n\n constructor(deps?: {\n createProxy?: (opts: { apiKey?: string }) => StitchProxyType;\n createTransport?: () => StdioServerTransport;\n }) {\n this.createProxy = deps?.createProxy ?? ((opts) => new StitchProxy(opts));\n this.createTransport = deps?.createTransport ?? (() => new StdioServerTransport());\n }\n\n async execute(input: ProxyCommandInput): Promise<ProxyCommandResult> {\n try {\n const proxy = this.createProxy({\n apiKey: process.env.STITCH_API_KEY,\n });\n const transport = this.createTransport();\n await proxy.start(transport);\n\n // Override the SDK's tools/call handler with a capture-wrapped variant.\n // Must run AFTER proxy.start() (which registers the original handler).\n if (isLogEnabled()) {\n try {\n installLoggingCallToolHandler(proxy, createCaptureHandler());\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n // eslint-disable-next-line no-console\n console.error(`[stitch-mcp log] failed to install capture handler: ${msg}`);\n }\n }\n\n await transport.onclose;\n return { success: true, data: { status: 'running' } };\n } catch (e: any) {\n return { success: false, error: { code: 'PROXY_START_ERROR', message: e.message, recoverable: false } };\n }\n }\n}\n"
|
|
9
|
+
],
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "AB5D43359F304DEA64756E2164756E21",
|
|
12
|
+
"names": []
|
|
13
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import {
|
|
2
|
+
openUrl,
|
|
3
|
+
require_jsx_dev_runtime
|
|
4
|
+
} from "./chunk-x1tt02n9.js";
|
|
5
|
+
import {
|
|
6
|
+
StitchViteServer
|
|
7
|
+
} from "./chunk-86gwwcyr.js";
|
|
8
|
+
import"./chunk-7vdj1qwb.js";
|
|
9
|
+
import {
|
|
10
|
+
Box_default,
|
|
11
|
+
Text,
|
|
12
|
+
use_app_default,
|
|
13
|
+
use_input_default
|
|
14
|
+
} from "./chunk-8yfetpqq.js";
|
|
15
|
+
import {
|
|
16
|
+
require_react
|
|
17
|
+
} from "./chunk-b43pzs3z.js";
|
|
18
|
+
import {
|
|
19
|
+
downloadText
|
|
20
|
+
} from "./chunk-fkzq5m59.js";
|
|
21
|
+
import"./chunk-q6sv0243.js";
|
|
22
|
+
import"./chunk-3sfn889r.js";
|
|
23
|
+
import {
|
|
24
|
+
__toESM
|
|
25
|
+
} from "./chunk-9wyra8hs.js";
|
|
26
|
+
|
|
27
|
+
// src/commands/serve/ServeView.tsx
|
|
28
|
+
var import_react = __toESM(require_react(), 1);
|
|
29
|
+
var jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
|
|
30
|
+
function ServeView({ projectId, projectTitle, screens }) {
|
|
31
|
+
const { exit } = use_app_default();
|
|
32
|
+
const [selectedIndex, setSelectedIndex] = import_react.useState(0);
|
|
33
|
+
const [serverUrl, setServerUrl] = import_react.useState(null);
|
|
34
|
+
const [status, setStatus] = import_react.useState("Starting server...");
|
|
35
|
+
const [server, setServer] = import_react.useState(null);
|
|
36
|
+
import_react.useEffect(() => {
|
|
37
|
+
const srv = new StitchViteServer;
|
|
38
|
+
setServer(srv);
|
|
39
|
+
let mounted = true;
|
|
40
|
+
async function init() {
|
|
41
|
+
try {
|
|
42
|
+
const url = await srv.start(0);
|
|
43
|
+
if (mounted)
|
|
44
|
+
setServerUrl(url);
|
|
45
|
+
await Promise.all(screens.map(async (screen) => {
|
|
46
|
+
try {
|
|
47
|
+
const html = await downloadText(screen.codeUrl);
|
|
48
|
+
srv.mount(`/screens/${screen.screenId}`, html);
|
|
49
|
+
} catch (e) {
|
|
50
|
+
console.error(`Failed to load ${screen.screenId}`);
|
|
51
|
+
}
|
|
52
|
+
}));
|
|
53
|
+
const indexHtml = `<!DOCTYPE html>
|
|
54
|
+
<html>
|
|
55
|
+
<head>
|
|
56
|
+
<title>${projectTitle}</title>
|
|
57
|
+
<style>
|
|
58
|
+
body { font-family: system-ui, sans-serif; max-width: 800px; margin: 40px auto; padding: 20px; background: #1a1a1a; color: #fff; }
|
|
59
|
+
ul { list-style: none; padding: 0; }
|
|
60
|
+
li { margin: 12px 0; padding: 16px; background: #252525; border-radius: 8px; }
|
|
61
|
+
a { color: #4fc3f7; text-decoration: none; font-size: 18px; display: block; }
|
|
62
|
+
a:hover { text-decoration: underline; }
|
|
63
|
+
</style>
|
|
64
|
+
</head>
|
|
65
|
+
<body>
|
|
66
|
+
<h1>${projectTitle}</h1>
|
|
67
|
+
<ul>
|
|
68
|
+
${screens.map((s) => `<li>
|
|
69
|
+
<a href="/screens/${s.screenId}">${s.title}</a>
|
|
70
|
+
</li>`).join(`
|
|
71
|
+
`)}
|
|
72
|
+
</ul>
|
|
73
|
+
</body>
|
|
74
|
+
</html>`;
|
|
75
|
+
srv.mount("/", indexHtml);
|
|
76
|
+
if (mounted)
|
|
77
|
+
setStatus("Ready");
|
|
78
|
+
} catch (e) {
|
|
79
|
+
if (mounted)
|
|
80
|
+
setStatus(`Error: ${e.message}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
init();
|
|
84
|
+
return () => {
|
|
85
|
+
mounted = false;
|
|
86
|
+
srv.stop();
|
|
87
|
+
};
|
|
88
|
+
}, []);
|
|
89
|
+
use_input_default((input, key) => {
|
|
90
|
+
if (input === "q") {
|
|
91
|
+
exit();
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (key.upArrow || input === "k") {
|
|
95
|
+
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
96
|
+
}
|
|
97
|
+
if (key.downArrow || input === "j") {
|
|
98
|
+
setSelectedIndex((prev) => Math.min(screens.length, prev + 1));
|
|
99
|
+
}
|
|
100
|
+
if (key.return && serverUrl) {
|
|
101
|
+
let target = serverUrl;
|
|
102
|
+
if (selectedIndex > 0) {
|
|
103
|
+
const screen = screens[selectedIndex - 1];
|
|
104
|
+
if (screen) {
|
|
105
|
+
target = `${serverUrl}/screens/${screen.screenId}`;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
openUrl(target);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
112
|
+
flexDirection: "column",
|
|
113
|
+
padding: 1,
|
|
114
|
+
children: [
|
|
115
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
116
|
+
bold: true,
|
|
117
|
+
children: projectTitle
|
|
118
|
+
}, undefined, false, undefined, this),
|
|
119
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
120
|
+
color: "green",
|
|
121
|
+
children: serverUrl || "Starting..."
|
|
122
|
+
}, undefined, false, undefined, this),
|
|
123
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
124
|
+
children: status
|
|
125
|
+
}, undefined, false, undefined, this),
|
|
126
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
127
|
+
marginTop: 1,
|
|
128
|
+
flexDirection: "column",
|
|
129
|
+
children: [
|
|
130
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
131
|
+
color: selectedIndex === 0 ? "cyan" : undefined,
|
|
132
|
+
children: [
|
|
133
|
+
selectedIndex === 0 ? "> " : " ",
|
|
134
|
+
" Index (/)"
|
|
135
|
+
]
|
|
136
|
+
}, undefined, true, undefined, this),
|
|
137
|
+
screens.map((s, i) => /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
138
|
+
color: selectedIndex === i + 1 ? "cyan" : undefined,
|
|
139
|
+
children: [
|
|
140
|
+
selectedIndex === i + 1 ? "> " : " ",
|
|
141
|
+
" ",
|
|
142
|
+
s.title,
|
|
143
|
+
" (/screens/",
|
|
144
|
+
s.screenId,
|
|
145
|
+
")"
|
|
146
|
+
]
|
|
147
|
+
}, s.screenId, true, undefined, this))
|
|
148
|
+
]
|
|
149
|
+
}, undefined, true, undefined, this),
|
|
150
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
151
|
+
marginTop: 1,
|
|
152
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
153
|
+
dimColor: true,
|
|
154
|
+
children: "[Enter] Open | [q] Quit"
|
|
155
|
+
}, undefined, false, undefined, this)
|
|
156
|
+
}, undefined, false, undefined, this)
|
|
157
|
+
]
|
|
158
|
+
}, undefined, true, undefined, this);
|
|
159
|
+
}
|
|
160
|
+
export {
|
|
161
|
+
ServeView
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
//# debugId=9F5B92ED2A4E429F64756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/commands/serve/ServeView.tsx"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import React, { useState, useEffect } from 'react';\nimport { Box, Text, useInput, useApp } from 'ink';\nimport { StitchViteServer } from '../../lib/server/vite/StitchViteServer.js';\nimport { downloadText } from '../../ui/copy-behaviors/clipboard.js';\nimport { openUrl } from '../../platform/browser.js';\n\ninterface CodeScreen {\n screenId: string;\n title: string;\n codeUrl: string;\n}\n\ninterface ServeViewProps {\n projectId: string;\n projectTitle: string;\n screens: CodeScreen[];\n}\n\nexport function ServeView({ projectId, projectTitle, screens }: ServeViewProps) {\n const { exit } = useApp();\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [serverUrl, setServerUrl] = useState<string | null>(null);\n const [status, setStatus] = useState('Starting server...');\n const [server, setServer] = useState<StitchViteServer | null>(null);\n\n useEffect(() => {\n const srv = new StitchViteServer();\n setServer(srv);\n let mounted = true;\n\n async function init() {\n try {\n const url = await srv.start(0);\n if (mounted) setServerUrl(url);\n\n // Fetch and mount screens\n await Promise.all(screens.map(async (screen) => {\n try {\n const html = await downloadText(screen.codeUrl);\n srv.mount(`/screens/${screen.screenId}`, html);\n } catch (e) {\n console.error(`Failed to load ${screen.screenId}`);\n }\n }));\n\n // Generate Index\n const indexHtml = `<!DOCTYPE html>\n<html>\n<head>\n <title>${projectTitle}</title>\n <style>\n body { font-family: system-ui, sans-serif; max-width: 800px; margin: 40px auto; padding: 20px; background: #1a1a1a; color: #fff; }\n ul { list-style: none; padding: 0; }\n li { margin: 12px 0; padding: 16px; background: #252525; border-radius: 8px; }\n a { color: #4fc3f7; text-decoration: none; font-size: 18px; display: block; }\n a:hover { text-decoration: underline; }\n </style>\n</head>\n<body>\n <h1>${projectTitle}</h1>\n <ul>\n ${screens.map(s => `<li>\n <a href=\"/screens/${s.screenId}\">${s.title}</a>\n </li>`).join('\\n')}\n </ul>\n</body>\n</html>`;\n srv.mount('/', indexHtml);\n\n if (mounted) setStatus('Ready');\n } catch (e: any) {\n if (mounted) setStatus(`Error: ${e.message}`);\n }\n }\n\n init();\n\n return () => {\n mounted = false;\n srv.stop();\n };\n }, []);\n\n useInput((input, key) => {\n if (input === 'q') {\n exit();\n return;\n }\n\n if (key.upArrow || input === 'k') {\n setSelectedIndex(prev => Math.max(0, prev - 1));\n }\n if (key.downArrow || input === 'j') {\n setSelectedIndex(prev => Math.min(screens.length, prev + 1));\n }\n\n if (key.return && serverUrl) {\n let target = serverUrl;\n if (selectedIndex > 0) {\n const screen = screens[selectedIndex - 1];\n if (screen) {\n target = `${serverUrl}/screens/${screen.screenId}`;\n }\n }\n openUrl(target);\n }\n });\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text bold>{projectTitle}</Text>\n <Text color=\"green\">{serverUrl || 'Starting...'}</Text>\n <Text>{status}</Text>\n <Box marginTop={1} flexDirection=\"column\">\n <Text color={selectedIndex === 0 ? 'cyan' : undefined}>\n {selectedIndex === 0 ? '> ' : ' '} Index (/)\n </Text>\n {screens.map((s, i) => (\n <Text key={s.screenId} color={selectedIndex === i + 1 ? 'cyan' : undefined}>\n {selectedIndex === i + 1 ? '> ' : ' '} {s.title} (/screens/{s.screenId})\n </Text>\n ))}\n </Box>\n <Box marginTop={1}>\n <Text dimColor>[Enter] Open | [q] Quit</Text>\n </Box>\n </Box>\n );\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "9F5B92ED2A4E429F64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|