diff --git a/index.html b/index.html
index c909032..8710248 100644
--- a/index.html
+++ b/index.html
@@ -10,7 +10,7 @@
-
+
DASFAD
diff --git a/src/diagram/diagramManager.ts b/src/diagram/diagramManager.ts
index 7406954..a2e10ea 100644
--- a/src/diagram/diagramManager.ts
+++ b/src/diagram/diagramManager.ts
@@ -102,6 +102,74 @@ export class DiagramManager {
}
});
+
+ // Chat event listeners for AI-powered diagram creation
+ document.addEventListener('chatCreateEntity', (event: CustomEvent) => {
+ const {entity} = event.detail;
+ this._logger.debug('chatCreateEntity', entity);
+ const object = new DiagramObject(this._scene, this.onDiagramEventObservable, {
+ diagramEntity: entity,
+ actionManager: this._diagramEntityActionManager
+ });
+ this._diagramObjects.set(entity.id, object);
+ this.onDiagramEventObservable.notifyObservers({
+ type: DiagramEventType.ADD,
+ entity: entity
+ }, DiagramEventObserverMask.TO_DB);
+ });
+
+ document.addEventListener('chatRemoveEntity', (event: CustomEvent) => {
+ const {target} = event.detail;
+ this._logger.debug('chatRemoveEntity', target);
+ const entity = this.findEntityByIdOrLabel(target);
+ if (entity) {
+ const diagramObject = this._diagramObjects.get(entity.id);
+ if (diagramObject) {
+ diagramObject.dispose();
+ this._diagramObjects.delete(entity.id);
+ this.onDiagramEventObservable.notifyObservers({
+ type: DiagramEventType.REMOVE,
+ entity: entity
+ }, DiagramEventObserverMask.TO_DB);
+ }
+ }
+ });
+
+ document.addEventListener('chatModifyEntity', (event: CustomEvent) => {
+ const {target, updates} = event.detail;
+ this._logger.debug('chatModifyEntity', target, updates);
+ const entity = this.findEntityByIdOrLabel(target);
+ if (entity) {
+ const diagramObject = this._diagramObjects.get(entity.id);
+ if (diagramObject) {
+ if (updates.text !== undefined) {
+ diagramObject.text = updates.text;
+ }
+ // Note: color and position updates would require additional DiagramObject methods
+ const updatedEntity = {...entity, ...updates};
+ this.onDiagramEventObservable.notifyObservers({
+ type: DiagramEventType.MODIFY,
+ entity: updatedEntity
+ }, DiagramEventObserverMask.TO_DB);
+ }
+ }
+ });
+
+ document.addEventListener('chatListEntities', () => {
+ this._logger.debug('chatListEntities');
+ const entities = Array.from(this._diagramObjects.values()).map(obj => ({
+ id: obj.diagramEntity.id,
+ template: obj.diagramEntity.template,
+ text: obj.diagramEntity.text || '',
+ position: obj.diagramEntity.position
+ }));
+ const responseEvent = new CustomEvent('chatListEntitiesResponse', {
+ detail: {entities},
+ bubbles: true
+ });
+ document.dispatchEvent(responseEvent);
+ });
+
this._logger.debug("DiagramManager constructed");
}
@@ -135,6 +203,21 @@ export class DiagramManager {
return appConfigInstance;
}
+ private findEntityByIdOrLabel(target: string): DiagramEntity | null {
+ // First try direct ID match
+ const byId = this._diagramObjects.get(target);
+ if (byId) {
+ return byId.diagramEntity;
+ }
+ // Then try label match (case-insensitive)
+ const targetLower = target.toLowerCase();
+ for (const [, obj] of this._diagramObjects) {
+ if (obj.diagramEntity.text?.toLowerCase() === targetLower) {
+ return obj.diagramEntity;
+ }
+ }
+ return null;
+ }
private onDiagramEvent(event: DiagramEvent) {
let diagramObject = this._diagramObjects.get(event?.entity?.id);
diff --git a/src/react/pages/vrExperience.tsx b/src/react/pages/vrExperience.tsx
index 7191cf8..a67e2fe 100644
--- a/src/react/pages/vrExperience.tsx
+++ b/src/react/pages/vrExperience.tsx
@@ -2,7 +2,7 @@ import VrApp from '../../vrApp';
import React, {useEffect, useState} from "react";
import {Affix, Burger, Group, Menu, Alert, Button, Text} from "@mantine/core";
import VrTemplate from "../vrTemplate";
-import {IconStar, IconInfoCircle} from "@tabler/icons-react";
+import {IconStar, IconInfoCircle, IconMessageCircle} from "@tabler/icons-react";
import VrMenuItem from "../components/vrMenuItem";
import CreateDiagramModal from "./createDiagramModal";
import ManageDiagramsModal from "./manageDiagramsModal";
@@ -19,6 +19,7 @@ import {DefaultScene} from "../../defaultScene";
import VREntryPrompt from "../components/VREntryPrompt";
import ComingSoonBadge from "../components/ComingSoonBadge";
import UpgradeBadge from "../components/UpgradeBadge";
+import ChatPanel from "../components/ChatPanel";
let vrApp: VrApp = null;
@@ -118,6 +119,7 @@ export default function VrExperience() {
const [rerender, setRerender] = useState(0);
const [dbName, setDbName] = useState(params.db);
const [showVRPrompt, setShowVRPrompt] = useState(false);
+ const [chatOpen, setChatOpen] = useState(!isMobileVRDevice()); // Show chat by default on desktop
useEffect(() => {
const canvas = document.getElementById('vrCanvas');
@@ -340,10 +342,30 @@ export default function VrExperience() {
onClick={getClickHandler(configState, openConfig)}
availableIcon={getFeatureIndicator(configState)}/>
)}
+
+
+ setChatOpen(!chatOpen)}
+ availableIcon={}/>
-
+
+
+
+
+
+ {chatOpen &&
setChatOpen(false)}/>}
+
{/* VR Entry Prompt - Rendered AFTER canvas to ensure it's on top in DOM order */}
-import {defineConfig} from "vite";
+import {defineConfig, loadEnv} from "vite";
/** @type {import('vite').UserConfig} */
-export default defineConfig({
+export default defineConfig(({mode}) => {
+ const env = loadEnv(mode, process.cwd(), '');
+ return {
test: {},
define: {},
build: {
@@ -23,6 +25,7 @@ export default defineConfig({
}
},
server: {
+ allowedHosts: true,
port: 3001,
proxy: {
'^/sync/.*': {
@@ -36,6 +39,22 @@ export default defineConfig({
'^/api/images': {
target: 'https://www.deepdiagram.com/',
changeOrigin: true,
+ },
+ '^/api/claude': {
+ target: 'https://api.anthropic.com',
+ changeOrigin: true,
+ rewrite: (path) => path.replace(/^\/api\/claude/, ''),
+ configure: (proxy) => {
+ proxy.on('proxyReq', (proxyReq) => {
+
+ const apiKey = env.ANTHROPIC_API_KEY;
+ console.log(` API KEY: ${apiKey}`);
+ if (apiKey) {
+ proxyReq.setHeader('x-api-key', apiKey);
+ proxyReq.setHeader('anthropic-version', '2023-06-01');
+ }
+ });
+ }
}
}
@@ -54,9 +73,24 @@ export default defineConfig({
'^/api/images': {
target: 'https://www.deepdiagram.com/',
changeOrigin: true,
+ },
+ '^/api/claude': {
+ target: 'https://api.anthropic.com',
+ changeOrigin: true,
+ rewrite: (path) => path.replace(/^\/api\/claude/, ''),
+ configure: (proxy) => {
+ proxy.on('proxyReq', (proxyReq) => {
+ const apiKey = env.ANTHROPIC_API_KEY;
+ console.log(` API KEY: ${apiKey}`);
+ if (apiKey) {
+ proxyReq.setHeader('x-api-key', apiKey);
+ proxyReq.setHeader('anthropic-version', '2023-06-01');
+ }
+ });
+ }
}
}
},
base: "/"
-
-})
\ No newline at end of file
+ };
+});
\ No newline at end of file