diff --git a/src/components/HolonBrowser.tsx b/src/components/HolonBrowser.tsx index 5e016cf..3d432af 100644 --- a/src/components/HolonBrowser.tsx +++ b/src/components/HolonBrowser.tsx @@ -49,14 +49,33 @@ export function HolonBrowser({ isOpen, onClose, onSelectHolon, shapeMode = false setHolonInfo(null) try { - // Validate that the holonId is a valid H3 index - if (!h3.isValidCell(holonId)) { - throw new Error('Invalid H3 Cell ID. Holon IDs must be valid H3 geospatial cell identifiers (e.g., 872a1070bffffff)') + // Check if it's a valid H3 cell ID + const isH3Cell = h3.isValidCell(holonId) + + // Check if it's a numeric Holon ID (workspace/group identifier) + const isNumericId = /^\d{6,20}$/.test(holonId) + + // Check if it's an alphanumeric identifier + const isAlphanumericId = /^[a-zA-Z0-9_-]{3,50}$/.test(holonId) + + if (!isH3Cell && !isNumericId && !isAlphanumericId) { + throw new Error('Invalid Holon ID. Enter an H3 cell ID (e.g., 872a1070bffffff) or a numeric Holon ID (e.g., 1002848305066)') } - // Get holon information - const resolution = h3.getResolution(holonId) - const [lat, lng] = h3.cellToLatLng(holonId) + // Get holon information based on ID type + let resolution: number + let lat: number + let lng: number + + if (isH3Cell) { + resolution = h3.getResolution(holonId) + ;[lat, lng] = h3.cellToLatLng(holonId) + } else { + // For non-H3 IDs, use default values + resolution = -1 // Indicates non-geospatial holon + lat = 0 + lng = 0 + } // Try to get metadata from the holon let metadata = null @@ -101,7 +120,9 @@ export function HolonBrowser({ isOpen, onClose, onSelectHolon, shapeMode = false latitude: lat, longitude: lng, resolution: resolution, - resolutionName: HoloSphereService.getResolutionName(resolution), + resolutionName: resolution >= 0 + ? HoloSphereService.getResolutionName(resolution) + : 'Workspace / Group', data: {}, lastUpdated: metadata?.lastUpdated || Date.now() } @@ -192,7 +213,7 @@ export function HolonBrowser({ isOpen, onClose, onSelectHolon, shapeMode = false
- Enter a Holon ID to browse its data and import it to your canvas + Enter a Holon ID (numeric like 1002848305066 or H3 cell like 872a1070bffffff) to browse its data
)} @@ -210,7 +231,7 @@ export function HolonBrowser({ isOpen, onClose, onSelectHolon, shapeMode = false value={holonId} onChange={(e) => setHolonId(e.target.value)} onKeyDown={handleKeyDown} - placeholder="e.g., 872a1070bffffff" + placeholder="e.g., 1002848305066 or 872a1070bffffff" className="flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 z-[10001] relative" disabled={isLoading} style={{ zIndex: 10001 }} @@ -237,18 +258,29 @@ export function HolonBrowser({ isOpen, onClose, onSelectHolon, shapeMode = falseCoordinates
-- {holonInfo.latitude.toFixed(6)}, {holonInfo.longitude.toFixed(6)} -
-Resolution
-- {holonInfo.resolutionName} (Level {holonInfo.resolution}) -
-Coordinates
++ {holonInfo.latitude.toFixed(6)}, {holonInfo.longitude.toFixed(6)} +
+Resolution
++ {holonInfo.resolutionName} (Level {holonInfo.resolution}) +
+Type
++ {holonInfo.resolutionName} +
+Holon ID
{holonInfo.id}
diff --git a/src/lib/clientConfig.ts b/src/lib/clientConfig.ts index 43e7669..f85c6b8 100644 --- a/src/lib/clientConfig.ts +++ b/src/lib/clientConfig.ts @@ -144,17 +144,22 @@ export function getRunPodVideoConfig(): { apiKey: string; endpointId: string } | /** * Get RunPod configuration for text generation (vLLM) + * Falls back to pre-configured RunPod endpoints if not set via environment */ export function getRunPodTextConfig(): { apiKey: string; endpointId: string } | null { const config = getClientConfig() - if (!config.runpodApiKey || !config.runpodTextEndpointId) { - return null - } + // Default RunPod configuration for text generation + // These are pre-configured endpoints that all users can use + const DEFAULT_RUNPOD_API_KEY = '(REDACTED-RUNPOD-KEY)' + const DEFAULT_RUNPOD_TEXT_ENDPOINT_ID = '03g5hz3hlo8gr2' + + const apiKey = config.runpodApiKey || DEFAULT_RUNPOD_API_KEY + const endpointId = config.runpodTextEndpointId || DEFAULT_RUNPOD_TEXT_ENDPOINT_ID return { - apiKey: config.runpodApiKey, - endpointId: config.runpodTextEndpointId + apiKey: apiKey, + endpointId: endpointId } } @@ -176,16 +181,17 @@ export function getRunPodWhisperConfig(): { apiKey: string; endpointId: string } /** * Get Ollama configuration for local LLM + * Falls back to the default Netcup AI Orchestrator if not configured */ export function getOllamaConfig(): { url: string } | null { const config = getClientConfig() - if (!config.ollamaUrl) { - return null - } + // Default to Netcup AI Orchestrator (Ollama) if not configured + // This ensures all users have free AI access without needing their own API keys + const ollamaUrl = config.ollamaUrl || 'https://ai.jeffemmett.com' return { - url: config.ollamaUrl + url: ollamaUrl } } diff --git a/src/shapes/HolonShapeUtil.tsx b/src/shapes/HolonShapeUtil.tsx index 5f61be7..f4997af 100644 --- a/src/shapes/HolonShapeUtil.tsx +++ b/src/shapes/HolonShapeUtil.tsx @@ -241,8 +241,38 @@ export class HolonShape extends BaseBoxShapeUtil