From b561640494a4eea29c77f4584afa3d2d08d30663 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Sun, 30 Nov 2025 18:38:09 -0800 Subject: [PATCH] feat: add default AI endpoints for all users MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hardcoded fallback values for Ollama and RunPod text endpoints so that all users have access to AI features without needing to configure their own API keys: - Ollama: defaults to https://ai.jeffemmett.com (Netcup AI Orchestrator) - RunPod Text: defaults to pre-configured vLLM endpoint This ensures Mycelial Intelligence works for everyone out of the box. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/components/HolonBrowser.tsx | 74 ++++++++++++++------ src/lib/clientConfig.ts | 24 ++++--- src/shapes/HolonShapeUtil.tsx | 116 +++++++++++++++++++++++--------- 3 files changed, 152 insertions(+), 62 deletions(-) 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 = false
-
-

Coordinates

-

- {holonInfo.latitude.toFixed(6)}, {holonInfo.longitude.toFixed(6)} -

-
-
-

Resolution

-

- {holonInfo.resolutionName} (Level {holonInfo.resolution}) -

-
+ {holonInfo.resolution >= 0 ? ( + <> +
+

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 { }) } - // Validate if input is a valid H3 cell ID - const isValidH3Cell = (id: string): boolean => { + // Validate if input is a valid Holon ID + // Accepts both H3 cell IDs (hexagonal geospatial identifiers like 872a1070bffffff) + // and numeric Holon IDs (workspace/group identifiers like 1002848305066) + const isValidHolonId = (id: string): boolean => { + if (!id || id.trim() === '') return false + const trimmedId = id.trim() + + // Check if it's a valid H3 cell ID + try { + if (h3.isValidCell(trimmedId)) { + return true + } + } catch { + // Not an H3 cell, continue to check other formats + } + + // Check if it's a numeric Holon ID (workspace/group identifier) + // These are typically 10-15 digit numbers + if (/^\d{6,20}$/.test(trimmedId)) { + return true + } + + // Check if it's an alphanumeric identifier (some holons use these) + if (/^[a-zA-Z0-9_-]{3,50}$/.test(trimmedId)) { + return true + } + + return false + } + + // Check if the ID is an H3 cell (for coordinate extraction) + const isH3CellId = (id: string): boolean => { if (!id || id.trim() === '') return false try { return h3.isValidCell(id.trim()) @@ -258,27 +288,36 @@ export class HolonShape extends BaseBoxShapeUtil { return } - // Validate H3 cell ID - if (!isValidH3Cell(trimmedHolonId)) { - setError('Invalid H3 Cell ID. Holon IDs must be valid H3 geospatial cell identifiers (e.g., 872a1070bffffff)') + // Validate Holon ID (accepts H3 cells, numeric IDs, and alphanumeric identifiers) + if (!isValidHolonId(trimmedHolonId)) { + setError('Invalid Holon ID. Enter an H3 cell ID (e.g., 872a1070bffffff) or a numeric Holon ID (e.g., 1002848305066)') return } console.log('🔌 Connecting to Holon:', trimmedHolonId) setError(null) - // Extract H3 cell info (coordinates and resolution) + // Extract H3 cell info if applicable (coordinates and resolution) let cellLatitude = latitude let cellLongitude = longitude let cellResolution = resolution - try { - const [lat, lng] = h3.cellToLatLng(trimmedHolonId) - cellLatitude = lat - cellLongitude = lng - cellResolution = h3.getResolution(trimmedHolonId) - console.log(`📍 H3 Cell Info: lat=${lat}, lng=${lng}, resolution=${cellResolution}`) - } catch (e) { - console.warn('Could not extract H3 cell coordinates:', e) + const isH3 = isH3CellId(trimmedHolonId) + + if (isH3) { + try { + const [lat, lng] = h3.cellToLatLng(trimmedHolonId) + cellLatitude = lat + cellLongitude = lng + cellResolution = h3.getResolution(trimmedHolonId) + console.log(`📍 H3 Cell Info: lat=${lat}, lng=${lng}, resolution=${cellResolution}`) + } catch (e) { + console.warn('Could not extract H3 cell coordinates:', e) + } + } else { + // For numeric/alphanumeric Holon IDs, use default coordinates + // The holon is not geospatially indexed + console.log(`📍 Numeric Holon ID detected: ${trimmedHolonId} (not geospatially indexed)`) + cellResolution = -1 // Indicate non-H3 holon } // Update the shape to mark as connected with trimmed ID and H3 info @@ -766,7 +805,7 @@ export class HolonShape extends BaseBoxShapeUtil { lineHeight: '1.5', width: '100%' }}> - Enter an H3 Cell ID to connect to the Holosphere + Enter a Holon ID to connect to the Holosphere
{ textAlign: 'center', marginBottom: '8px' }}> - H3 Cell IDs are hexagonal geospatial identifiers (e.g., 872a1070bffffff) + Supports numeric IDs (e.g., 1002848305066) or H3 cell IDs (e.g., 872a1070bffffff)
{/* Quick generate button */}
{ handleConnect() } }} - placeholder="872a1070bffffff" + placeholder="1002848305066 or 872a1070bffffff" style={{ flex: 1, height: '48px', @@ -942,7 +981,7 @@ export class HolonShape extends BaseBoxShapeUtil { }} onWheel={handleWheel} > - {/* H3 Cell Information Header */} + {/* Holon Information Header */} {isConnected && (
{ }}>
= 0 ? 'repeat(2, 1fr)' : '1fr', gap: '8px', fontSize: '11px' }}> -
- Resolution:{' '} - - {resolutionInfo.name} (Level {resolution}) - -
-
- Coordinates:{' '} - - {latitude.toFixed(4)}, {longitude.toFixed(4)} - -
+ {resolution >= 0 ? ( + <> +
+ Resolution:{' '} + + {resolutionInfo.name} (Level {resolution}) + +
+
+ Coordinates:{' '} + + {latitude.toFixed(4)}, {longitude.toFixed(4)} + +
+ + ) : ( +
+ Type:{' '} + + Workspace / Group Holon + +
+ )}
- {resolutionInfo.description} + {resolution >= 0 + ? resolutionInfo.description + : 'This holon represents a workspace, organization, or group (not geospatially indexed)'}
)}