feat: Introduce a comprehensive set of AI agent skills, agents, and workflows, along with new UI components and application structure.

This commit is contained in:
Evandro Fonseca Junior committed 2026-03-04 05:01:34 -03:00
1 parent a2a512d41d
commit 93df87d7e9
317 files changed
+63716 -8727

No files matched your search

+1
View File
@@ -0,0 +1 @@
export { useColorScheme } from 'react-native';
+21
View File
@@ -0,0 +1,21 @@
import { useEffect, useState } from 'react';
import { useColorScheme as useRNColorScheme } from 'react-native';
/**
* To support static rendering, this value needs to be re-calculated on the client side for web
*/
export function useColorScheme() {
const [hasHydrated, setHasHydrated] = useState(false);
useEffect(() => {
setHasHydrated(true);
}, []);
const colorScheme = useRNColorScheme();
if (hasHydrated) {
return colorScheme;
}
return 'light';
}
+21
View File
@@ -0,0 +1,21 @@
/**
* Learn more about light and dark modes:
* https://docs.expo.dev/guides/color-schemes/
*/
import { Colors } from '@/constants/theme';
import { useColorScheme } from '@/hooks/use-color-scheme';
export function useThemeColor(
props: { light?: string; dark?: string },
colorName: keyof typeof Colors.light & keyof typeof Colors.dark
) {
const theme = useColorScheme() ?? 'light';
const colorFromProps = props[theme];
if (colorFromProps) {
return colorFromProps;
} else {
return Colors[theme][colorName];
}
}
+5
View File
@@ -0,0 +1,5 @@
import { useColorScheme as useNativeColorScheme } from 'react-native';
export function useColorScheme() {
return useNativeColorScheme() ?? 'light';
}
+165
View File
@@ -0,0 +1,165 @@
import { useCallback, useRef } from 'react';
import * as api from '../services/lmStudioApi';
import { ChatMessage as ApiMessage } from '../services/types';
import { useAppStore } from '../store/useAppStore';
export function useLMStudio() {
const serverConfig = useAppStore((s) => s.serverConfig);
const isConnected = useAppStore((s) => s.isConnected);
const setIsConnected = useAppStore((s) => s.setIsConnected);
const availableModels = useAppStore((s) => s.availableModels);
const setAvailableModels = useAppStore((s) => s.setAvailableModels);
const activeModelId = useAppStore((s) => s.activeModelId);
const setActiveModelId = useAppStore((s) => s.setActiveModelId);
const messages = useAppStore((s) => s.messages);
const addMessage = useAppStore((s) => s.addMessage);
const appendToMessage = useAppStore((s) => s.appendToMessage);
const isStreaming = useAppStore((s) => s.isStreaming);
const setIsStreaming = useAppStore((s) => s.setIsStreaming);
const abortRef = useRef<{ abort: () => void } | null>(null);
const checkConnection = useCallback(async () => {
const ok = await api.testConnection(serverConfig);
setIsConnected(ok);
return ok;
}, [serverConfig, setIsConnected]);
const fetchModels = useCallback(async () => {
try {
const models = await api.getModels(serverConfig);
setAvailableModels(models);
setIsConnected(true);
if (!activeModelId && models.length > 0) {
setActiveModelId(models[0].id);
}
return models;
} catch {
setIsConnected(false);
setAvailableModels([]);
return [];
}
}, [serverConfig, activeModelId, setAvailableModels, setIsConnected, setActiveModelId]);
const sendMessage = useCallback(async (text: string) => {
if (isStreaming) return;
addMessage({ role: 'user', content: text });
const currentMessages = useAppStore.getState().messages;
const apiMessages: ApiMessage[] = currentMessages.map((m) => ({
role: m.role,
content: m.content,
}));
const modelId = useAppStore.getState().activeModelId;
if (!modelId) {
addMessage({
role: 'assistant',
content: '⚠️ No model selected. Please select a model first.',
});
return;
}
const assistantId = addMessage({ role: 'assistant', content: '' });
setIsStreaming(true);
try {
abortRef.current = api.chatCompletionStream(
serverConfig,
modelId,
apiMessages,
(chunk) => {
appendToMessage(assistantId, chunk);
},
() => {
setIsStreaming(false);
abortRef.current = null;
},
(error) => {
const errorMsg = `\n\n⚠️ Error: ${error.message}`;
appendToMessage(assistantId, errorMsg);
setIsStreaming(false);
abortRef.current = null;
},
);
} catch (err) {
const errorMsg = `⚠️ Connection failed: ${(err as Error).message}`;
appendToMessage(assistantId, errorMsg);
setIsStreaming(false);
}
}, [isStreaming, serverConfig, addMessage, appendToMessage, setIsStreaming]);
const regenerateResponse = useCallback(async () => {
if (isStreaming) return;
const msgs = useAppStore.getState().messages;
// Find the last user message
let lastUserIdx = -1;
for (let i = msgs.length - 1; i >= 0; i--) {
if (msgs[i].role === 'user') {
lastUserIdx = i;
break;
}
}
if (lastUserIdx === -1) return;
const lastUserMsg = msgs[lastUserIdx];
// Remove messages after the last user message
const store = useAppStore.getState();
store.deleteMessagesAfter(lastUserMsg.id);
// Build API messages from remaining
const remaining = useAppStore.getState().messages;
const apiMessages: ApiMessage[] = remaining.map((m) => ({
role: m.role,
content: m.content,
}));
const modelId = useAppStore.getState().activeModelId;
if (!modelId) return;
const assistantId = addMessage({ role: 'assistant', content: '' });
setIsStreaming(true);
try {
abortRef.current = api.chatCompletionStream(
serverConfig,
modelId,
apiMessages,
(chunk) => appendToMessage(assistantId, chunk),
() => { setIsStreaming(false); abortRef.current = null; },
(error) => {
appendToMessage(assistantId, `\n\n⚠️ Error: ${error.message}`);
setIsStreaming(false);
abortRef.current = null;
},
);
} catch (err) {
appendToMessage(assistantId, `⚠️ Connection failed: ${(err as Error).message}`);
setIsStreaming(false);
}
}, [isStreaming, serverConfig, addMessage, appendToMessage, setIsStreaming]);
const stopStreaming = useCallback(() => {
if (abortRef.current) {
abortRef.current.abort();
abortRef.current = null;
setIsStreaming(false);
}
}, [setIsStreaming]);
return {
isConnected,
isStreaming,
availableModels,
activeModelId,
messages,
sendMessage,
stopStreaming,
fetchModels,
checkConnection,
regenerateResponse,
};
}