continue scaffolding and refine the basic foundation
This commit is contained in:
@@ -3,18 +3,16 @@ import type { Agent } from '~~/types'
|
||||
|
||||
export const useAgents = async () => {
|
||||
const { addTask, completeTask } = useTasks()
|
||||
const appState = useAppState()
|
||||
|
||||
const fetchingAgents = ref(false);
|
||||
const agents: Ref<Agent[] | null> = useState('agents', () => null);
|
||||
|
||||
const activeAgent = computed(() => {
|
||||
if (agents.value === null) return;
|
||||
if (!appState.activeAgentId.value) return;
|
||||
|
||||
const routeId = useRoute().params.id;
|
||||
if (routeId === undefined) return;
|
||||
|
||||
const agent = agents.value.find(agent => agent.id === routeId);
|
||||
if (agent === undefined) return;
|
||||
|
||||
const agent = agents.value.find(agent => agent.id === appState.activeAgentId.value);
|
||||
return agent;
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
import type { User, Session } from 'better-auth/types';
|
||||
|
||||
/**
|
||||
* Central application state composable
|
||||
* Manages navigation context and critical app-level state
|
||||
* This is the single source of truth for "what am I viewing"
|
||||
*/
|
||||
export const useAppState = () => {
|
||||
// Current navigation context
|
||||
const activeAgentId = useState<string | null>('appState:activeAgentId', () => null);
|
||||
const activeTopicId = useState<string | null>('appState:activeTopicId', () => null);
|
||||
|
||||
// User data
|
||||
const user = useState<User | null>('appState:user', () => null);
|
||||
const session = useState<Session | null>('appState:session', () => null);
|
||||
|
||||
// Loading states
|
||||
const isInitializing = useState<boolean>('appState:isInitializing', () => true);
|
||||
const generationInProgress = useState<{ generationId: string } | null>('appState:generationInProgress', () => null);
|
||||
|
||||
/**
|
||||
* Set the active agent and clear the topic
|
||||
*/
|
||||
const setActiveAgent = (agentId: string | null | undefined) => {
|
||||
activeAgentId.value = agentId || null;
|
||||
// Clear topic when switching agents
|
||||
activeTopicId.value = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the active topic
|
||||
*/
|
||||
const setActiveTopic = (topicId: string | null | undefined) => {
|
||||
activeTopicId.value = topicId || null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set user session data
|
||||
*/
|
||||
const setUser = (userData: User | null) => {
|
||||
user.value = userData;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set session
|
||||
*/
|
||||
const setSession = (sessionData: Session | null) => {
|
||||
session.value = sessionData;
|
||||
};
|
||||
|
||||
/**
|
||||
* Mark initialization complete
|
||||
*/
|
||||
const markInitialized = () => {
|
||||
isInitializing.value = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Start a generation
|
||||
*/
|
||||
const startGeneration = (generationId: string) => {
|
||||
generationInProgress.value = { generationId };
|
||||
};
|
||||
|
||||
/**
|
||||
* End current generation
|
||||
*/
|
||||
const endGeneration = () => {
|
||||
generationInProgress.value = null;
|
||||
};
|
||||
|
||||
return {
|
||||
// State
|
||||
activeAgentId,
|
||||
activeTopicId,
|
||||
user,
|
||||
session,
|
||||
isInitializing,
|
||||
generationInProgress,
|
||||
|
||||
// Actions
|
||||
setActiveAgent,
|
||||
setActiveTopic,
|
||||
setUser,
|
||||
setSession,
|
||||
markInitialized,
|
||||
startGeneration,
|
||||
endGeneration
|
||||
};
|
||||
};
|
||||
@@ -1,17 +1,23 @@
|
||||
import type { Topic } from "~~/types";
|
||||
|
||||
export const useTopics = async () => {
|
||||
const appState = useAppState()
|
||||
const fetchingTopics = ref(false);
|
||||
const topics: Ref<Topic[] | null> = useState('topics', () => null);
|
||||
const topics: Ref<any[] | null> = useState('topics', () => null);
|
||||
|
||||
/**
|
||||
* Compute topics for the currently active agent
|
||||
*/
|
||||
const topicsForActiveAgent = computed(() => {
|
||||
if (topics.value === null || !appState.activeAgentId.value) return [];
|
||||
return topics.value.filter(topic => topic.agentId === appState.activeAgentId.value);
|
||||
});
|
||||
|
||||
const activeTopic = computed(() => {
|
||||
if (topics.value === null) return;
|
||||
|
||||
const routeId = useRoute().query.topicId;
|
||||
if (routeId === undefined) return;
|
||||
|
||||
const topic = topics.value.find(topic => topic.id === routeId);
|
||||
if (topic === undefined) return;
|
||||
if (topicsForActiveAgent.value.length === 0) return;
|
||||
if (!appState.activeTopicId.value) return;
|
||||
|
||||
const topic = topicsForActiveAgent.value.find(topic => topic.id === appState.activeTopicId.value);
|
||||
return topic;
|
||||
});
|
||||
|
||||
@@ -19,16 +25,17 @@ export const useTopics = async () => {
|
||||
if (fetchingTopics.value) return;
|
||||
fetchingTopics.value = true;
|
||||
|
||||
const { data, error } = await useFetch('/api/topics');
|
||||
if (error.value) throw error;
|
||||
topics.value = data.value!;
|
||||
|
||||
fetchingTopics.value = false;
|
||||
try {
|
||||
const { data, error } = await useFetch('/api/topics');
|
||||
if (error.value) throw error;
|
||||
topics.value = data.value!;
|
||||
} finally {
|
||||
fetchingTopics.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (topics.value === null) await refreshTopics();
|
||||
|
||||
|
||||
const createTopic = async (name: string, agentId: string) => {
|
||||
const res = await fetch('/api/topics', {
|
||||
method: 'POST',
|
||||
@@ -42,8 +49,11 @@ export const useTopics = async () => {
|
||||
throw new Error('Failed to create topic')
|
||||
}
|
||||
|
||||
return res.json()
|
||||
const newTopic = await res.json()
|
||||
if (topics.value === null) topics.value = []
|
||||
topics.value.push(newTopic)
|
||||
return newTopic
|
||||
}
|
||||
|
||||
return { createTopic, activeTopic, topics }
|
||||
return { createTopic, activeTopic, topics, topicsForActiveAgent, fetchingTopics, refreshTopics }
|
||||
}
|
||||
Reference in New Issue
Block a user