20 Commits

Author SHA1 Message Date
dependabot[bot]
bf8113b65c Bump mobx-state-tree from 6.0.1 to 7.0.2
Bumps [mobx-state-tree](https://github.com/mobxjs/mobx-state-tree) from 6.0.1 to 7.0.2.
- [Release notes](https://github.com/mobxjs/mobx-state-tree/releases)
- [Changelog](https://github.com/mobxjs/mobx-state-tree/blob/master/changelog.md)
- [Commits](https://github.com/mobxjs/mobx-state-tree/compare/v6.0.1...v7.0.2)

---
updated-dependencies:
- dependency-name: mobx-state-tree
  dependency-version: 7.0.2
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-17 17:48:58 +00:00
Geoff Seemueller
4edee1e191 Potential fix for code scanning alert no. 5: Shell command built from environment values
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Signed-off-by: Geoff Seemueller <28698553+geoffsee@users.noreply.github.com>
2025-07-17 13:47:50 -04:00
geoffsee
734f48d4a7 remove webhost in assistant prompt 2025-07-17 13:47:50 -04:00
geoffsee
66363cdf39 set ai as the default landing 2025-07-17 13:47:50 -04:00
geoffsee
36f8fcee87 Integrate PWA service worker registration using virtual:pwa-register. 2025-07-17 13:47:50 -04:00
geoffsee
f055cd39fe Update InputMenu to use clientChatStore.reset() instead of setActiveConversation when closing. 2025-07-17 13:47:50 -04:00
geoffsee
0183503425 Refactored layout components and styling: removed unused imports, adjusted positioning and padding for consistency. 2025-07-17 13:47:50 -04:00
geoffsee
a7ad06093a simplify landing page for my peace 2025-07-17 13:47:50 -04:00
geoffsee
c26d2467f4 sweet lander 2025-07-17 13:47:50 -04:00
geoffsee
818e0e672a chat + maps + ai + tools 2025-07-17 13:47:50 -04:00
geoffsee
48655474e3 mirror error handling behavior in cloudflare worker 2025-07-17 13:47:50 -04:00
geoffsee
ffabfd4ce5 add top level error handler to the router 2025-07-17 13:47:50 -04:00
geoffsee
fa5b7466bc Optimize WASM handling and integrate service worker caching.
Removed unused pointer events in BevyScene, updated Vite config with Workbox for service worker caching, and adjusted file paths in generate-bevy-bundle.js. Added WASM size optimization to ensure smaller and efficient builds, skipping optimization for files below 30MB.
2025-07-17 13:47:50 -04:00
geoffsee
6cc5e038a7 Add visible prop to toggle components and simplify conditional rendering 2025-07-17 13:47:50 -04:00
geoffsee
e72198628c Add "Install App" button to the toolbar using react-use-pwa-install library 2025-07-17 13:47:50 -04:00
geoffsee
c0428094c8 **Integrate PWA asset generator and update favicon and manifest configuration** 2025-07-17 13:47:50 -04:00
geoffsee
3901337163 - Refactor BevyScene to replace script injection with dynamic import.
- Update `NavItem` to provide fallback route for invalid `path`.
- Temporarily stub metric API endpoints with placeholders.
2025-07-17 13:47:50 -04:00
geoffsee
0ff8b5c03e * Introduced BevyScene React component in landing-component for rendering a 3D cockpit visualization.
* Included WebAssembly asset `yachtpit.js` for cockpit functionality.
* Added Bevy MIT license file.
* Implemented a service worker to cache assets locally instead of fetching them remotely.
* Added collapsible functionality to **Tweakbox** and included the `@chakra-ui/icons` dependency.
* Applied the `hidden` prop to the Tweakbox Heading for better accessibility.
* Refactored **Particles** component for improved performance, clarity, and maintainability.

  * Introduced helper functions for particle creation and count management.
  * Added responsive resizing with particle repositioning.
  * Optimized animation updates, including velocity adjustments for speed changes.
  * Ensured canvas size and particle state are cleanly managed on component unmount.
2025-07-17 13:47:50 -04:00
geoffsee
858282929c Refactor chat-stream-provider to simplify tool structure. Optimize WeatherTool implementation with enriched function schema. 2025-07-17 13:47:50 -04:00
geoffsee
06b6a68b9b Enable tool-based message generation in chat-stream-provider and add BasicValueTool and WeatherTool.
Updated dependencies to latest versions in `bun.lock`. Modified development script in `package.json` to include watch mode.
2025-07-17 13:47:50 -04:00
21 changed files with 54 additions and 79 deletions

View File

@@ -46,7 +46,6 @@ describe('AssistantSdk', () => {
expect(prompt).toContain('# Assistant Knowledge');
expect(prompt).toContain('### Date: ');
expect(prompt).toContain('### Web Host: ');
expect(prompt).toContain('### User Location: ');
expect(prompt).toContain('### Timezone: ');
});

View File

@@ -23,7 +23,7 @@ export class AssistantSdk {
return `# Assistant Knowledge
## Assistant Name
### yachtpit-ai
### open-gsio
## Current Context
### Date: ${currentDate} ${currentTime}
${maxTokens ? `### Max Response Length: ${maxTokens} tokens (maximum)` : ''}

View File

@@ -50,7 +50,7 @@
"marked-katex-extension": "^5.1.4",
"mobx": "^6.13.5",
"mobx-react-lite": "^4.0.7",
"mobx-state-tree": "^6.0.1",
"mobx-state-tree": "^7.0.2",
"qrcode.react": "^4.1.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",

View File

@@ -1,4 +1,4 @@
import { execSync } from 'node:child_process';
import { execSync, execFileSync } from 'node:child_process';
import {
existsSync,
readdirSync,
@@ -175,7 +175,7 @@ function optimizeWasmSize() {
if (sizeInMb > 30) {
logger.info(`WASM size is ${sizeInMb.toFixed(2)}MB, optimizing...`);
execSync(`wasm-opt -Oz -o ${wasmPath} ${wasmPath}`, {
execFileSync('wasm-opt', ['-Oz', '-o', wasmPath, wasmPath], {
encoding: 'utf-8',
});
logger.info(`✅ WASM size optimized`);

View File

@@ -171,7 +171,7 @@ const InputMenu: React.FC<{ isDisabled?: boolean }> = observer(({ isDisabled })
bg="background.tertiary"
color="text.primary"
onClick={() => {
clientChatStore.setActiveConversation('conversation:new');
clientChatStore.reset();
onClose();
}}
_hover={{ bg: 'rgba(0, 0, 0, 0.05)' }}

View File

@@ -49,7 +49,7 @@ const InputTextArea: React.FC<InputTextAreaProps> = observer(
color="text.primary"
borderRadius="20px"
border="none"
placeholder="To Gilligan's island!"
placeholder="Free my mind..."
_placeholder={{
color: 'gray.400',
textWrap: 'nowrap',

View File

@@ -9,7 +9,7 @@ export function formatConversationMarkdown(messages: Instance<typeof IMessage>[]
if (message.role === 'user') {
return `**You**: ${message.content}`;
} else if (message.role === 'assistant') {
return `**yachtpit-ai**: ${message.content}`;
return `**open-gsio**: ${message.content}`;
}
return '';
})

View File

@@ -51,7 +51,7 @@ const MessageBubble = observer(({ msg, scrollRef }) => {
const [isEditing, setIsEditing] = useState(false);
const [isHovered, setIsHovered] = useState(false);
const isUser = msg.role === 'user';
const senderName = isUser ? 'You' : 'yachtpit-ai';
const senderName = isUser ? 'You' : 'open-gsio';
const isLoading = !msg.content || !(msg.content.trim().length > 0);
const messageRef = useRef();

View File

@@ -104,7 +104,7 @@ describe('MessageBubble', () => {
it('should render assistant message correctly', () => {
render(<MessageBubble msg={mockAssistantMessage} scrollRef={mockScrollRef} />);
expect(screen.getByText('yachtpit-ai')).toBeInTheDocument();
expect(screen.getByText('open-gsio')).toBeInTheDocument();
expect(screen.getByTestId('message-content')).toHaveTextContent('Assistant response');
});

View File

@@ -3,16 +3,13 @@ import React, { useEffect, useState } from 'react';
import { useComponent } from '../contexts/ComponentContext.tsx';
import { BevyScene } from './BevyScene.tsx';
// import { BevyScene } from './BevyScene.tsx';
import Tweakbox from './Tweakbox.tsx';
export const LandingComponent: React.FC = () => {
const [speed, setSpeed] = useState(0.2);
const [intensity, setIntensity] = useState(0.99);
const [glow, setGlow] = useState(false);
const [bevyScene, setBevyScene] = useState(true);
const [mapActive, setMapActive] = useState(true);
const [aiActive, setAiActive] = useState(false);
const [mapActive, setMapActive] = useState(false);
const [aiActive, setAiActive] = useState(true);
const component = useComponent();
const { setEnabledComponent } = component;
@@ -27,22 +24,8 @@ export const LandingComponent: React.FC = () => {
}, []);
return (
<Box
as="section"
bg="background.primary"
w="100%"
h="100vh"
overflow="hidden"
position="relative"
>
<Box
position="fixed"
bottom="100x"
right="12px"
maxWidth="300px"
minWidth="200px"
zIndex={1000}
>
<Box as="section" bg="background.primary" overflow="hidden">
<Box position="fixed" right={0} maxWidth="300px" minWidth="200px" zIndex={1000}>
<Tweakbox
sliders={{
intensity: {
@@ -56,13 +39,6 @@ export const LandingComponent: React.FC = () => {
},
}}
switches={{
bevyScene: {
value: bevyScene,
onChange(enabled) {
setBevyScene(enabled);
},
label: 'Instruments',
},
GpsMap: {
value: mapActive,
onChange(enabled) {
@@ -74,7 +50,7 @@ export const LandingComponent: React.FC = () => {
}
setMapActive(enabled);
},
label: 'Map',
label: 'GPS',
},
AI: {
value: aiActive,
@@ -92,7 +68,7 @@ export const LandingComponent: React.FC = () => {
}}
/>
</Box>
<BevyScene speed={speed} intensity={intensity} glow={glow} visible={bevyScene} />
{/*<BevyScene speed={speed} intensity={intensity} glow={glow} visible={bevyScene} />*/}
</Box>
);
};

View File

@@ -37,7 +37,7 @@ const key =
function Map(props: { visible: boolean }) {
return (
/* Full-screen wrapper — fills the viewport and becomes the positioning context */
<Box w="100%" h="100vh" position="relative" overflow="hidden">
<Box position={'absolute'} top={0} w="100vw" h={'100vh'} overflow="hidden">
{/* Button bar — absolutely positioned inside the wrapper */}
<MapNext mapboxPublicKey={atob(key)} />

View File

@@ -1,4 +1,4 @@
import { Box, Button, HStack, Input } from '@chakra-ui/react';
import { Box } from '@chakra-ui/react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import Map, {
FullscreenControl,
@@ -118,11 +118,10 @@ Type '{ city: string; population: string; image: string; state: string; latitude
right: 0,
}}
>
<GeolocateControl position="top-left" />
<GeolocateControl position="top-left" style={{ marginTop: '6rem' }} />
<FullscreenControl position="top-left" />
<NavigationControl position="top-left" />
<ScaleControl position="top-left" />
{pins}
{popupInfo && (

View File

@@ -6,7 +6,7 @@ import { useIsMobile } from '../components/contexts/MobileContext';
function Content({ children }) {
const isMobile = useIsMobile();
return (
<Flex flexDirection="column" w="100%" h="100vh" p={!isMobile ? 4 : 1}>
<Flex flexDirection="column" w="100%" h="100vh">
{children}
</Flex>
);

View File

@@ -1,4 +1,6 @@
// runs before anything else
import { registerSW } from 'virtual:pwa-register';
import UserOptionsStore from '../stores/UserOptionsStore';
UserOptionsStore.initialize();
@@ -6,7 +8,11 @@ UserOptionsStore.initialize();
try {
const isLocal = window.location.hostname.includes('localhost');
if (!isLocal) {
navigator.serviceWorker.register('/service-worker.js');
if ('serviceWorker' in navigator) {
// && !/localhost/.test(window.location)) {
registerSW();
}
// navigator.serviceWorker.register('/service-worker.js');
} else {
(async () => {
await navigator.serviceWorker.getRegistrations().then(registrations => {

View File

@@ -1,4 +1,4 @@
import { Box, Grid, GridItem, Stack } from '@chakra-ui/react';
import { Box } from '@chakra-ui/react';
import React, { useEffect } from 'react';
import Chat from '../../components/chat/Chat.tsx';
@@ -22,27 +22,26 @@ export default function IndexPage() {
const component = useComponent();
return (
<Grid templateColumns="repeat(2, 1fr)" height="100%" width="100%" gap={0}>
<GridItem>
<LandingComponent />
</GridItem>
<GridItem p={2}>
<Box
display={component.enabledComponent === 'ai' ? undefined : 'none'}
width="100%"
height="100%"
overflowY="scroll"
>
<Chat />
</Box>
<Box
display={component.enabledComponent === 'gpsmap' ? undefined : 'none'}
width="100%"
height="100%"
>
<ReactMap visible={component.enabledComponent === 'gpsmap'} />
</Box>
</GridItem>
</Grid>
<Box height="100%" width="100%">
<LandingComponent />
<Box
display={component.enabledComponent === 'ai' ? undefined : 'none'}
width="100%"
height="100%"
overflowY="scroll"
padding={'unset'}
>
<Chat />
</Box>
<Box
display={component.enabledComponent === 'gpsmap' ? undefined : 'none'}
width="100%"
height="100%"
padding={'unset'}
>
<ReactMap visible={component.enabledComponent === 'gpsmap'} />
</Box>
</Box>
);
}

View File

@@ -1,5 +1,5 @@
export const welcome_home_text = `
# yachtpit-ai
# open-gsio
---
<br/>

View File

@@ -22,10 +22,6 @@ const prebuildPlugin = () => ({
console.log('Generated robots.txt -> public/robots.txt');
child_process.execSync('bun run generate:fonts');
console.log('Copied fonts -> public/static/fonts');
child_process.execSync('bun run generate:bevy:bundle', {
stdio: 'inherit',
});
console.log('Bundled bevy app -> public/yachtpit.html');
}
},
});

View File

@@ -10,7 +10,7 @@
"@open-gsio/services": "workspace:*",
"itty-router": "^5.0.18",
"mobx": "^6.13.5",
"mobx-state-tree": "^6.0.1",
"mobx-state-tree": "^7.0.2",
"vitest": "^3.1.4",
"vite": "^6.3.5"
}

View File

@@ -20,6 +20,6 @@
},
"devDependencies": {
"typescript": "^5.7.2",
"mobx-state-tree": "^6.0.1"
"mobx-state-tree": "^7.0.2"
}
}

View File

@@ -21,7 +21,7 @@
"itty-router": "^5.0.18",
"jsdom": "^24.0.0",
"mobx": "^6.13.5",
"mobx-state-tree": "^6.0.1",
"mobx-state-tree": "^7.0.2",
"moo": "^0.5.2",
"typescript": "^5.7.2",
"vike": "0.4.235",

View File

@@ -30,7 +30,7 @@
"itty-router": "^5.0.18",
"jsdom": "^24.0.0",
"mobx": "^6.13.5",
"mobx-state-tree": "^6.0.1",
"mobx-state-tree": "^7.0.2",
"moo": "^0.5.2",
"openai": "^5.0.1",
"typescript": "^5.7.2",