updated files related to chat-dev page, added onSend function to handle sending questions, and updated the button's onClick handler to call this function. Also added new types in code-graph store for handling results from opencode AI SDK.
This commit is contained in:
@@ -32,6 +32,7 @@
|
|||||||
"@tanstack/react-router": "^1.166.7",
|
"@tanstack/react-router": "^1.166.7",
|
||||||
"@uiw/codemirror-theme-vscode": "^4.25.8",
|
"@uiw/codemirror-theme-vscode": "^4.25.8",
|
||||||
"@uiw/react-codemirror": "^4.25.8",
|
"@uiw/react-codemirror": "^4.25.8",
|
||||||
|
"ai": "^6.0.116",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cmdk": "^1.1.1",
|
"cmdk": "^1.1.1",
|
||||||
@@ -62,6 +63,7 @@
|
|||||||
"@kevisual/kv-login": "^0.1.17",
|
"@kevisual/kv-login": "^0.1.17",
|
||||||
"@kevisual/query": "0.0.53",
|
"@kevisual/query": "0.0.53",
|
||||||
"@kevisual/types": "^0.0.12",
|
"@kevisual/types": "^0.0.12",
|
||||||
|
"@opencode-ai/sdk": "^1.2.26",
|
||||||
"@tailwindcss/vite": "^4.2.1",
|
"@tailwindcss/vite": "^4.2.1",
|
||||||
"@tanstack/react-router-devtools": "^1.166.7",
|
"@tanstack/react-router-devtools": "^1.166.7",
|
||||||
"@tanstack/router-plugin": "^1.166.7",
|
"@tanstack/router-plugin": "^1.166.7",
|
||||||
|
|||||||
123
src/pages/chat-dev/page.tsx
Normal file
123
src/pages/chat-dev/page.tsx
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useSearch } from '@tanstack/react-router';
|
||||||
|
import { useShallow } from 'zustand/react/shallow';
|
||||||
|
import { BotIcon, FileIcon, FolderIcon } from 'lucide-react';
|
||||||
|
import { useChatDevStore } from './store';
|
||||||
|
import { BOT_KEYS, BotKey } from '@/pages/code-graph/store/bot-helper';
|
||||||
|
import openclawSvg from '@/pages/code-graph/assets/openclaw.svg';
|
||||||
|
import opencodePng from '@/pages/code-graph/assets/opencode.png';
|
||||||
|
import { useCodeGraphStore } from '../code-graph/store';
|
||||||
|
import { useLayoutStore } from '../auth/store';
|
||||||
|
|
||||||
|
const BOT_ICONS: Record<BotKey, string> = {
|
||||||
|
openclaw: openclawSvg,
|
||||||
|
opencode: opencodePng,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const App = () => {
|
||||||
|
const { timestamp } = useSearch({ from: '/chat-dev' });
|
||||||
|
const { question, engine, projectInfo, initFromTimestamp, setData } = useChatDevStore(
|
||||||
|
useShallow((s) => ({
|
||||||
|
question: s.question,
|
||||||
|
engine: s.engine,
|
||||||
|
projectInfo: s.projectInfo,
|
||||||
|
initFromTimestamp: s.initFromTimestamp,
|
||||||
|
setData: s.setData,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
const layoutStore = useLayoutStore(useShallow((s) => ({
|
||||||
|
me: s.me,
|
||||||
|
})));
|
||||||
|
const codeGraphStore = useCodeGraphStore(useShallow((s) => ({
|
||||||
|
createQuestion: s.createQuestion,
|
||||||
|
init: s.init,
|
||||||
|
})));
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!layoutStore.me?.username) return;
|
||||||
|
codeGraphStore.init(layoutStore.me, { load: false });
|
||||||
|
}, [layoutStore.me]);
|
||||||
|
useEffect(() => {
|
||||||
|
if (timestamp) {
|
||||||
|
initFromTimestamp(timestamp);
|
||||||
|
}
|
||||||
|
}, [timestamp]);
|
||||||
|
|
||||||
|
const relativePath = projectInfo
|
||||||
|
? (projectInfo.filepath || '').replace((projectInfo.projectPath || '') + '/', '') || '/'
|
||||||
|
: null;
|
||||||
|
const onSend = async () => {
|
||||||
|
if (projectInfo) {
|
||||||
|
const res = await codeGraphStore.createQuestion({
|
||||||
|
question,
|
||||||
|
projectPath: projectInfo.projectPath,
|
||||||
|
engine,
|
||||||
|
});
|
||||||
|
console.log(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className='h-full bg-slate-950 text-slate-100 flex flex-col items-center py-10 px-4'>
|
||||||
|
<div className='w-full max-w-2xl rounded-xl border border-white/10 bg-slate-900 shadow-2xl flex flex-col'>
|
||||||
|
{/* 标题栏 */}
|
||||||
|
<div className='flex items-center gap-2 px-4 py-3 border-b border-white/10'>
|
||||||
|
<BotIcon className='size-4 text-emerald-400' />
|
||||||
|
<span className='text-sm font-medium text-slate-100'>AI 助手</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 内容区 */}
|
||||||
|
<div className='px-4 py-4 flex flex-col gap-4'>
|
||||||
|
{/* 节点信息 + Bot 切换 */}
|
||||||
|
<div className='flex items-center gap-2'>
|
||||||
|
{relativePath && (
|
||||||
|
<div className='flex-1 flex items-center gap-2 px-3 py-2 rounded-lg bg-slate-800/60 border border-white/5 min-w-0'>
|
||||||
|
<FileIcon className='size-4 shrink-0 text-slate-400' />
|
||||||
|
<span className='text-xs text-slate-300 font-mono truncate' title={relativePath}>
|
||||||
|
{relativePath}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{projectInfo?.projectPath && !relativePath && (
|
||||||
|
<div className='flex-1 flex items-center gap-2 px-3 py-2 rounded-lg bg-slate-800/60 border border-white/5 min-w-0'>
|
||||||
|
<FolderIcon className='size-4 shrink-0 text-slate-400' />
|
||||||
|
<span className='text-xs text-slate-300 font-mono truncate'>
|
||||||
|
{projectInfo.projectPath}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{/* Bot 切换按钮组 */}
|
||||||
|
<div className='flex items-center gap-1 shrink-0 ml-auto'>
|
||||||
|
{BOT_KEYS.map((key) => (
|
||||||
|
<button
|
||||||
|
key={key}
|
||||||
|
title={key}
|
||||||
|
onClick={() => setData({ engine: key })}
|
||||||
|
className={`p-1.5 rounded-lg border transition-colors ${engine === key
|
||||||
|
? 'border-emerald-500/60 bg-emerald-500/10'
|
||||||
|
: 'border-white/5 bg-slate-800/60 opacity-40 hover:opacity-70'
|
||||||
|
}`}>
|
||||||
|
<img src={BOT_ICONS[key]} alt={key} className='size-5 object-contain' />
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 问题输入区 */}
|
||||||
|
<textarea
|
||||||
|
className='w-full rounded-lg border border-white/10 bg-slate-800 px-3 py-2 text-sm text-slate-200 placeholder:text-slate-500 focus:outline-none focus:ring-1 focus:ring-emerald-500 resize-none'
|
||||||
|
rows={6}
|
||||||
|
placeholder='请输入内容...'
|
||||||
|
value={question}
|
||||||
|
onChange={(e) => setData({ question: e.target.value })}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<button className='w-full rounded-lg bg-emerald-600 hover:bg-emerald-500 active:bg-emerald-700 text-white text-sm font-medium py-2 transition-colors' onClick={onSend}>
|
||||||
|
发送
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default App;
|
||||||
64
src/pages/chat-dev/store/index.ts
Normal file
64
src/pages/chat-dev/store/index.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import { create } from 'zustand';
|
||||||
|
import { BotKey } from '@/pages/code-graph/store/bot-helper';
|
||||||
|
export type ChatDevData = {
|
||||||
|
question: string;
|
||||||
|
engine: BotKey;
|
||||||
|
projectInfo: {
|
||||||
|
filepath: string;
|
||||||
|
projectPath: string;
|
||||||
|
} | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ChatDevState = {
|
||||||
|
question: string;
|
||||||
|
engine: BotKey;
|
||||||
|
projectInfo: {
|
||||||
|
filepath: string;
|
||||||
|
projectPath: string;
|
||||||
|
} | null;
|
||||||
|
setData: (data: Partial<ChatDevData>) => void;
|
||||||
|
initFromTimestamp: (timestamp: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const SESSION_KEY_PREFIX = 'chat-dev-';
|
||||||
|
const SESSION_KEY = 'chat-dev';
|
||||||
|
|
||||||
|
export const useChatDevStore = create<ChatDevState>()((set) => ({
|
||||||
|
question: '',
|
||||||
|
engine: 'opencode',
|
||||||
|
projectInfo: null,
|
||||||
|
|
||||||
|
setData: (data) => set((s) => ({ ...s, ...data })),
|
||||||
|
|
||||||
|
initFromTimestamp: (timestamp: string) => {
|
||||||
|
const key = SESSION_KEY_PREFIX + timestamp;
|
||||||
|
|
||||||
|
// 优先从 localStorage 读取(首次打开)
|
||||||
|
const localRaw = localStorage.getItem(key);
|
||||||
|
if (localRaw) {
|
||||||
|
try {
|
||||||
|
const data: ChatDevData = JSON.parse(localRaw);
|
||||||
|
// 持久化到 sessionStorage,供刷新页面使用(不带 timestamp)
|
||||||
|
sessionStorage.setItem(SESSION_KEY, localRaw);
|
||||||
|
// 清除 localStorage
|
||||||
|
localStorage.removeItem(key);
|
||||||
|
set({ question: data.question, engine: data.engine, projectInfo: data.projectInfo });
|
||||||
|
return;
|
||||||
|
} catch {
|
||||||
|
localStorage.removeItem(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新页面时从 sessionStorage 读取(固定 key,不带 timestamp)
|
||||||
|
const sessionRaw = sessionStorage.getItem(SESSION_KEY);
|
||||||
|
if (sessionRaw) {
|
||||||
|
try {
|
||||||
|
const data: ChatDevData = JSON.parse(sessionRaw);
|
||||||
|
set({ question: data.question, engine: data.engine, projectInfo: data.projectInfo });
|
||||||
|
return;
|
||||||
|
} catch {
|
||||||
|
sessionStorage.removeItem(SESSION_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}));
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { BotIcon, XIcon, FileIcon, FolderIcon, DatabaseIcon, MoreHorizontalIcon } from 'lucide-react';
|
import { BotIcon, XIcon, FileIcon, FolderIcon, DatabaseIcon, MoreHorizontalIcon } from 'lucide-react';
|
||||||
import { getDynamicBasename, wrapBasename } from '@/modules/basename';
|
import { useNavigate, useLocation } from '@tanstack/react-router';
|
||||||
import { useBotHelperStore, BOT_KEYS, BotKey } from '../store/bot-helper';
|
import { useBotHelperStore, BOT_KEYS, BotKey } from '../store/bot-helper';
|
||||||
import { useShallow } from 'zustand/react/shallow';
|
import { useShallow } from 'zustand/react/shallow';
|
||||||
import { useCodeGraphStore, NodeInfoData } from '../store';
|
import { useCodeGraphStore, NodeInfoData } from '../store';
|
||||||
@@ -27,13 +27,16 @@ export function BotHelperModal() {
|
|||||||
closeModal: s.closeModal,
|
closeModal: s.closeModal,
|
||||||
activeKey: s.activeKey,
|
activeKey: s.activeKey,
|
||||||
setActiveKey: s.setActiveKey,
|
setActiveKey: s.setActiveKey,
|
||||||
|
projectInfo: s.projectInfo,
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
const { nodeInfoData, createQuestion } = useCodeGraphStore(useShallow((s) => ({
|
const { nodeInfoData, createQuestion } = useCodeGraphStore(useShallow((s) => ({
|
||||||
nodeInfoData: s.nodeInfoData,
|
nodeInfoData: s.nodeInfoData,
|
||||||
createQuestion: s.createQuestion,
|
createQuestion: s.createQuestion,
|
||||||
})));
|
})));
|
||||||
|
const location = useLocation();
|
||||||
|
console.log('BotHelperModal render', location);
|
||||||
|
const basename = location.publicHref.replace(location.href, '');
|
||||||
const relativePath = nodeInfoData
|
const relativePath = nodeInfoData
|
||||||
? nodeInfoData.fullPath.replace((nodeInfoData.projectPath || '') + '/', '') || '/'
|
? nodeInfoData.fullPath.replace((nodeInfoData.projectPath || '') + '/', '') || '/'
|
||||||
: null;
|
: null;
|
||||||
@@ -67,7 +70,12 @@ export function BotHelperModal() {
|
|||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const timestamp = Date.now();
|
const timestamp = Date.now();
|
||||||
window.open(`/code-graph?timestamp=${timestamp}`, '_blank');
|
localStorage.setItem('chat-dev-' + timestamp, JSON.stringify({
|
||||||
|
question: botHelperStore.input,
|
||||||
|
engine: botHelperStore.activeKey,
|
||||||
|
projectInfo: botHelperStore.projectInfo,
|
||||||
|
}));
|
||||||
|
window.open(`${basename}/chat-dev?timestamp=${timestamp}`, '_blank');
|
||||||
}}
|
}}
|
||||||
className='text-slate-500 hover:text-slate-200 transition-colors p-1 rounded hover:bg-white/10'
|
className='text-slate-500 hover:text-slate-200 transition-colors p-1 rounded hover:bg-white/10'
|
||||||
title='新窗口打开'>
|
title='新窗口打开'>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { toast } from 'sonner';
|
|||||||
import { FileProjectData } from '../modules/tree';
|
import { FileProjectData } from '../modules/tree';
|
||||||
import { UserInfo } from '@/pages/auth/store';
|
import { UserInfo } from '@/pages/auth/store';
|
||||||
import { Result } from '@kevisual/query';
|
import { Result } from '@kevisual/query';
|
||||||
|
import { AssistantMessage, Part } from '@opencode-ai/sdk'
|
||||||
export type ProjectItem = {
|
export type ProjectItem = {
|
||||||
path: string;
|
path: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
@@ -25,6 +25,10 @@ export type NodeInfoData = {
|
|||||||
fileId?: string;
|
fileId?: string;
|
||||||
nodeSize?: number;
|
nodeSize?: number;
|
||||||
};
|
};
|
||||||
|
export type OpencodeResult = {
|
||||||
|
info: AssistantMessage;
|
||||||
|
parts: Array<Part>;
|
||||||
|
}
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
codePodOpen: boolean;
|
codePodOpen: boolean;
|
||||||
@@ -52,7 +56,7 @@ type State = {
|
|||||||
setNodeInfo: (data: NodeInfoData | null, pos?: { x: number; y: number }) => void;
|
setNodeInfo: (data: NodeInfoData | null, pos?: { x: number; y: number }) => void;
|
||||||
closeNodeInfo: () => void;
|
closeNodeInfo: () => void;
|
||||||
url?: string;
|
url?: string;
|
||||||
init(user: UserInfo): Promise<void>;
|
init(user: UserInfo, opts?: { load?: boolean }): Promise<void>;
|
||||||
fetchProjects: () => Promise<void>;
|
fetchProjects: () => Promise<void>;
|
||||||
getFiles: (opts?: {
|
getFiles: (opts?: {
|
||||||
filepath?: string; // 可选的目录路径,默认为根目录
|
filepath?: string; // 可选的目录路径,默认为根目录
|
||||||
@@ -194,13 +198,16 @@ export const useCodeGraphStore = create<State>()((set, get) => ({
|
|||||||
}),
|
}),
|
||||||
closeNodeInfo: () => set({ nodeInfoOpen: false, nodeInfoData: null }),
|
closeNodeInfo: () => set({ nodeInfoOpen: false, nodeInfoData: null }),
|
||||||
url: API_URL,
|
url: API_URL,
|
||||||
init: async (user) => {
|
init: async (user, opts = {}) => {
|
||||||
// 可以在这里根据用户信息初始化一些数据,比如权限相关的设置等
|
// 可以在这里根据用户信息初始化一些数据,比如权限相关的设置等
|
||||||
console.log('CodeGraphStore initialized for user:', user.username);
|
console.log('CodeGraphStore initialized for user:', user.username);
|
||||||
const username = user.username;
|
const username = user.username;
|
||||||
const url = username ? `/${username}/v1/cnb-dev` : API_URL;
|
const url = username ? `/${username}/v1/cnb-dev` : API_URL;
|
||||||
set({ url });
|
set({ url });
|
||||||
await get().fetchProjects();
|
const load = opts.load ?? true;
|
||||||
|
if (load) {
|
||||||
|
await get().fetchProjects();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
fetchProjects: async () => {
|
fetchProjects: async () => {
|
||||||
get().loadProjects();
|
get().loadProjects();
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { Route as rootRouteImport } from './routes/__root'
|
|||||||
import { Route as LoginRouteImport } from './routes/login'
|
import { Route as LoginRouteImport } from './routes/login'
|
||||||
import { Route as DemoRouteImport } from './routes/demo'
|
import { Route as DemoRouteImport } from './routes/demo'
|
||||||
import { Route as CodeGraphRouteImport } from './routes/code-graph'
|
import { Route as CodeGraphRouteImport } from './routes/code-graph'
|
||||||
|
import { Route as ChatDevRouteImport } from './routes/chat-dev'
|
||||||
import { Route as IndexRouteImport } from './routes/index'
|
import { Route as IndexRouteImport } from './routes/index'
|
||||||
|
|
||||||
const LoginRoute = LoginRouteImport.update({
|
const LoginRoute = LoginRouteImport.update({
|
||||||
@@ -29,6 +30,11 @@ const CodeGraphRoute = CodeGraphRouteImport.update({
|
|||||||
path: '/code-graph',
|
path: '/code-graph',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => rootRouteImport,
|
||||||
} as any)
|
} as any)
|
||||||
|
const ChatDevRoute = ChatDevRouteImport.update({
|
||||||
|
id: '/chat-dev',
|
||||||
|
path: '/chat-dev',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
const IndexRoute = IndexRouteImport.update({
|
const IndexRoute = IndexRouteImport.update({
|
||||||
id: '/',
|
id: '/',
|
||||||
path: '/',
|
path: '/',
|
||||||
@@ -37,12 +43,14 @@ const IndexRoute = IndexRouteImport.update({
|
|||||||
|
|
||||||
export interface FileRoutesByFullPath {
|
export interface FileRoutesByFullPath {
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
|
'/chat-dev': typeof ChatDevRoute
|
||||||
'/code-graph': typeof CodeGraphRoute
|
'/code-graph': typeof CodeGraphRoute
|
||||||
'/demo': typeof DemoRoute
|
'/demo': typeof DemoRoute
|
||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
}
|
}
|
||||||
export interface FileRoutesByTo {
|
export interface FileRoutesByTo {
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
|
'/chat-dev': typeof ChatDevRoute
|
||||||
'/code-graph': typeof CodeGraphRoute
|
'/code-graph': typeof CodeGraphRoute
|
||||||
'/demo': typeof DemoRoute
|
'/demo': typeof DemoRoute
|
||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
@@ -50,20 +58,22 @@ export interface FileRoutesByTo {
|
|||||||
export interface FileRoutesById {
|
export interface FileRoutesById {
|
||||||
__root__: typeof rootRouteImport
|
__root__: typeof rootRouteImport
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
|
'/chat-dev': typeof ChatDevRoute
|
||||||
'/code-graph': typeof CodeGraphRoute
|
'/code-graph': typeof CodeGraphRoute
|
||||||
'/demo': typeof DemoRoute
|
'/demo': typeof DemoRoute
|
||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
}
|
}
|
||||||
export interface FileRouteTypes {
|
export interface FileRouteTypes {
|
||||||
fileRoutesByFullPath: FileRoutesByFullPath
|
fileRoutesByFullPath: FileRoutesByFullPath
|
||||||
fullPaths: '/' | '/code-graph' | '/demo' | '/login'
|
fullPaths: '/' | '/chat-dev' | '/code-graph' | '/demo' | '/login'
|
||||||
fileRoutesByTo: FileRoutesByTo
|
fileRoutesByTo: FileRoutesByTo
|
||||||
to: '/' | '/code-graph' | '/demo' | '/login'
|
to: '/' | '/chat-dev' | '/code-graph' | '/demo' | '/login'
|
||||||
id: '__root__' | '/' | '/code-graph' | '/demo' | '/login'
|
id: '__root__' | '/' | '/chat-dev' | '/code-graph' | '/demo' | '/login'
|
||||||
fileRoutesById: FileRoutesById
|
fileRoutesById: FileRoutesById
|
||||||
}
|
}
|
||||||
export interface RootRouteChildren {
|
export interface RootRouteChildren {
|
||||||
IndexRoute: typeof IndexRoute
|
IndexRoute: typeof IndexRoute
|
||||||
|
ChatDevRoute: typeof ChatDevRoute
|
||||||
CodeGraphRoute: typeof CodeGraphRoute
|
CodeGraphRoute: typeof CodeGraphRoute
|
||||||
DemoRoute: typeof DemoRoute
|
DemoRoute: typeof DemoRoute
|
||||||
LoginRoute: typeof LoginRoute
|
LoginRoute: typeof LoginRoute
|
||||||
@@ -92,6 +102,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof CodeGraphRouteImport
|
preLoaderRoute: typeof CodeGraphRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
|
'/chat-dev': {
|
||||||
|
id: '/chat-dev'
|
||||||
|
path: '/chat-dev'
|
||||||
|
fullPath: '/chat-dev'
|
||||||
|
preLoaderRoute: typeof ChatDevRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
'/': {
|
'/': {
|
||||||
id: '/'
|
id: '/'
|
||||||
path: '/'
|
path: '/'
|
||||||
@@ -104,6 +121,7 @@ declare module '@tanstack/react-router' {
|
|||||||
|
|
||||||
const rootRouteChildren: RootRouteChildren = {
|
const rootRouteChildren: RootRouteChildren = {
|
||||||
IndexRoute: IndexRoute,
|
IndexRoute: IndexRoute,
|
||||||
|
ChatDevRoute: ChatDevRoute,
|
||||||
CodeGraphRoute: CodeGraphRoute,
|
CodeGraphRoute: CodeGraphRoute,
|
||||||
DemoRoute: DemoRoute,
|
DemoRoute: DemoRoute,
|
||||||
LoginRoute: LoginRoute,
|
LoginRoute: LoginRoute,
|
||||||
|
|||||||
9
src/routes/chat-dev.tsx
Normal file
9
src/routes/chat-dev.tsx
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { createFileRoute } from '@tanstack/react-router'
|
||||||
|
import {App} from '../pages/chat-dev/page'
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/chat-dev')({
|
||||||
|
validateSearch: (search: Record<string, unknown>) => ({
|
||||||
|
timestamp: search.timestamp as string | undefined,
|
||||||
|
}),
|
||||||
|
component: App,
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user