shave and code split (#4630)
This commit is contained in:
@@ -6,7 +6,7 @@ import type { View } from '../utils/navigationUtils';
|
||||
import Stop from './ui/Stop';
|
||||
import { Attach, Send, Close, Microphone } from './icons';
|
||||
import { ChatState } from '../types/chatState';
|
||||
import { debounce } from 'lodash';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { LocalMessageStorage } from '../utils/localMessageStorage';
|
||||
import { Message } from '../types/message';
|
||||
import { DirSwitcher } from './bottom_menu/DirSwitcher';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useState, useRef, KeyboardEvent } from 'react';
|
||||
import { Search as SearchIcon } from 'lucide-react';
|
||||
import { ArrowDown, ArrowUp, Close } from '../icons';
|
||||
import { debounce } from 'lodash';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { Button } from '../ui/button';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect, PropsWithChildren, useCallback, useRef } from 'react';
|
||||
import SearchBar from './SearchBar';
|
||||
import { SearchHighlighter } from '../../utils/searchHighlighter';
|
||||
import { debounce } from 'lodash';
|
||||
import debounce from 'lodash/debounce';
|
||||
import '../../styles/search.css';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import { useTextAnimator } from '../../hooks/use-text-animator';
|
||||
|
||||
interface GreetingProps {
|
||||
className?: string;
|
||||
forceRefresh?: boolean;
|
||||
}
|
||||
|
||||
export function Greeting({
|
||||
className = 'mb-12 mt-8 text-4xl font-light animate-in fade-in slide-in-from-right-8 duration-300',
|
||||
forceRefresh = false,
|
||||
}: GreetingProps) {
|
||||
const prefixes = ['Hello.', 'Welcome.', 'Greetings.', 'Welcome back.', 'Hello there.'];
|
||||
const messages = [
|
||||
' Ready to get started?',
|
||||
' What would you like to work on?',
|
||||
' Ready to build something amazing?',
|
||||
' What would you like to explore?',
|
||||
" What's on your mind?",
|
||||
' What shall we create today?',
|
||||
' What project needs attention?',
|
||||
' What would you like to tackle?',
|
||||
' What would you like to explore?',
|
||||
' What needs to be done?',
|
||||
" What's the plan for today?",
|
||||
' Ready to create something great?',
|
||||
' What can be built today?',
|
||||
" What's the next challenge?",
|
||||
' What progress can be made?',
|
||||
' What would you like to accomplish?',
|
||||
' What task awaits?',
|
||||
" What's the mission today?",
|
||||
' What can be achieved?',
|
||||
' What project is ready to begin?',
|
||||
];
|
||||
|
||||
const greeting = useState(() => {
|
||||
const randomPrefixIndex = Math.floor(Math.random() * prefixes.length);
|
||||
const randomMessageIndex = Math.floor(Math.random() * messages.length);
|
||||
|
||||
return {
|
||||
prefix: prefixes[randomPrefixIndex],
|
||||
message: messages[randomMessageIndex],
|
||||
};
|
||||
})[0];
|
||||
|
||||
const messageRef = useTextAnimator({ text: greeting.message });
|
||||
|
||||
return (
|
||||
<h1 className={className} key={forceRefresh ? Date.now() : undefined}>
|
||||
<span>{greeting.prefix}</span>
|
||||
<span className="text-text-muted" ref={messageRef}>
|
||||
{greeting.message}
|
||||
</span>
|
||||
</h1>
|
||||
);
|
||||
}
|
||||
@@ -28,7 +28,7 @@ export const findAvailablePort = (): Promise<number> => {
|
||||
|
||||
// Goose process manager. Take in the app, port, and directory to start goosed in.
|
||||
// Check if goosed server is ready by polling the status endpoint
|
||||
const checkServerStatus = async (): Promise<boolean> => {
|
||||
export const checkServerStatus = async (): Promise<boolean> => {
|
||||
const interval = 100;
|
||||
const maxAttempts = 200;
|
||||
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
||||
@@ -270,10 +270,6 @@ export const startGoosed = async (
|
||||
},
|
||||
});
|
||||
|
||||
// Wait for the server to be ready
|
||||
const isReady = await checkServerStatus();
|
||||
log.info(`Goosed isReady ${isReady}`);
|
||||
|
||||
const try_kill_goose = () => {
|
||||
try {
|
||||
if (isWindows) {
|
||||
@@ -287,14 +283,7 @@ export const startGoosed = async (
|
||||
}
|
||||
};
|
||||
|
||||
if (!isReady) {
|
||||
log.error(`Goosed server failed to start on port ${port}`);
|
||||
try_kill_goose();
|
||||
throw new Error(`Goosed server failed to start on port ${port}`);
|
||||
}
|
||||
|
||||
// Ensure goosed is terminated when the app quits
|
||||
// TODO will need to do it at tab level next
|
||||
app.on('will-quit', () => {
|
||||
log.info('App quitting, terminating goosed server');
|
||||
try_kill_goose();
|
||||
|
||||
+12
-6
@@ -23,7 +23,7 @@ import path from 'node:path';
|
||||
import os from 'node:os';
|
||||
import { spawn } from 'child_process';
|
||||
import 'dotenv/config';
|
||||
import { startGoosed } from './goosed';
|
||||
import { checkServerStatus, startGoosed } from './goosed';
|
||||
import { expandTilde, getBinaryPath } from './utils/pathUtils';
|
||||
import log from './utils/logger';
|
||||
import { ensureWinShims } from './utils/winShims';
|
||||
@@ -51,6 +51,7 @@ import { UPDATES_ENABLED } from './updates';
|
||||
import { Recipe } from './recipe';
|
||||
import './utils/recipeHash';
|
||||
import { decodeRecipe } from './api/sdk.gen';
|
||||
import { client } from './api/client.gen';
|
||||
|
||||
async function decodeRecipeMain(deeplink: string): Promise<Recipe | null> {
|
||||
try {
|
||||
@@ -697,7 +698,7 @@ const createChat = async (
|
||||
// Goose's react app uses HashRouter, so the path + search params follow a #/
|
||||
url.hash = `${appPath}?${searchParams.toString()}`;
|
||||
let formattedUrl = formatUrl(url);
|
||||
console.log('Opening URL: ', formattedUrl);
|
||||
log.info('Opening URL: ', formattedUrl);
|
||||
mainWindow.loadURL(formattedUrl);
|
||||
|
||||
// Set up local keyboard shortcuts that only work when the window is focused
|
||||
@@ -1016,18 +1017,18 @@ process.on('unhandledRejection', (error) => {
|
||||
});
|
||||
|
||||
ipcMain.on('react-ready', () => {
|
||||
console.log('React ready event received');
|
||||
log.info('React ready event received');
|
||||
|
||||
if (pendingDeepLink) {
|
||||
console.log('Processing pending deep link:', pendingDeepLink);
|
||||
log.info('Processing pending deep link:', pendingDeepLink);
|
||||
handleProtocolUrl(pendingDeepLink);
|
||||
} else {
|
||||
console.log('No pending deep link to process');
|
||||
log.info('No pending deep link to process');
|
||||
}
|
||||
|
||||
// We don't need to handle pending deep links here anymore
|
||||
// since we're handling them in the window creation flow
|
||||
console.log('[main] React ready - window is prepared for deep links');
|
||||
log.info('React ready - window is prepared for deep links');
|
||||
});
|
||||
|
||||
// Handle external URL opening
|
||||
@@ -1060,6 +1061,11 @@ ipcMain.handle('get-secret-key', () => {
|
||||
return SERVER_SECRET;
|
||||
});
|
||||
|
||||
ipcMain.handle('get-goosed-host-port', async () => {
|
||||
await checkServerStatus();
|
||||
return client.getConfig().baseUrl || null;
|
||||
});
|
||||
|
||||
ipcMain.handle('set-scheduling-engine', async (_event, engine: string) => {
|
||||
try {
|
||||
const settings = loadSettings();
|
||||
|
||||
@@ -78,6 +78,7 @@ type ElectronAPI = {
|
||||
getDockIconState: () => Promise<boolean>;
|
||||
getSettings: () => Promise<unknown | null>;
|
||||
getSecretKey: () => Promise<string>;
|
||||
getGoosedHostPort: () => Promise<string | null>;
|
||||
setSchedulingEngine: (engine: string) => Promise<boolean>;
|
||||
setWakelock: (enable: boolean) => Promise<boolean>;
|
||||
getWakelockState: () => Promise<boolean>;
|
||||
@@ -168,6 +169,7 @@ const electronAPI: ElectronAPI = {
|
||||
getDockIconState: () => ipcRenderer.invoke('get-dock-icon-state'),
|
||||
getSettings: () => ipcRenderer.invoke('get-settings'),
|
||||
getSecretKey: () => ipcRenderer.invoke('get-secret-key'),
|
||||
getGoosedHostPort: () => ipcRenderer.invoke('get-goosed-host-port'),
|
||||
setSchedulingEngine: (engine: string) => ipcRenderer.invoke('set-scheduling-engine', engine),
|
||||
setWakelock: (enable: boolean) => ipcRenderer.invoke('set-wakelock', enable),
|
||||
getWakelockState: () => ipcRenderer.invoke('get-wakelock-state'),
|
||||
|
||||
@@ -8,8 +8,15 @@ import { client } from './api/client.gen';
|
||||
const App = lazy(() => import('./App'));
|
||||
|
||||
(async () => {
|
||||
console.log('window created, getting goosed connection info');
|
||||
const baseUrl = await window.electron.getGoosedHostPort();
|
||||
if (baseUrl === null) {
|
||||
window.alert('failed to start goose backend process');
|
||||
return;
|
||||
}
|
||||
console.log('connecting at', baseUrl);
|
||||
client.setConfig({
|
||||
baseUrl: window.appConfig.get('GOOSE_API_HOST') + ':' + window.appConfig.get('GOOSE_PORT'),
|
||||
baseUrl,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Secret-Key': await window.electron.getSecretKey(),
|
||||
|
||||
Reference in New Issue
Block a user