Chat cwd
This commit is contained in:
@@ -29,7 +29,7 @@ piRestRouter.get('/pi/models', async (ctx: Context) => {
|
|||||||
providerNames[`officer-local-${lp.id}`] = lp.name;
|
providerNames[`officer-local-${lp.id}`] = lp.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx.json({ models, providerNames });
|
return ctx.json({ models, providerNames, hostHome: process.env.HOME ?? '' });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Failed to list models', { error: String(err) });
|
logger.error('Failed to list models', { error: String(err) });
|
||||||
return ctx.json({ models: [], providerNames: {} });
|
return ctx.json({ models: [], providerNames: {} });
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
import { useLocation } from 'react-router';
|
import { useLocation } from 'react-router';
|
||||||
import { Trash2 } from 'lucide-react';
|
import { Trash2, Home, Monitor } from 'lucide-react';
|
||||||
import { usePanelChannel } from 'hooks/usePanelChannel';
|
import { usePanelChannel } from 'hooks/usePanelChannel';
|
||||||
import { useChatSessions } from 'state/useChatSessions';
|
import { useChatSessions } from 'state/useChatSessions';
|
||||||
|
import { getHostHome } from 'state/useModels';
|
||||||
import { usePiChat, EmbeddableChat } from '../Chat';
|
import { usePiChat, EmbeddableChat } from '../Chat';
|
||||||
|
|
||||||
export type SelectedSession = {
|
export type SelectedSession = {
|
||||||
@@ -91,12 +93,48 @@ function SessionChat({ sessionId, model }: SessionChatProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function CwdToggle({ cwdMode, onChange }: { cwdMode: 'user' | 'host'; onChange: (mode: 'user' | 'host') => void }) {
|
||||||
|
const hostHome = getHostHome();
|
||||||
|
if (!hostHome) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="shrink-0 flex items-center gap-1 px-4 py-1.5 border-b border-duck-dark/10 dark:border-foreground/10 bg-background/40">
|
||||||
|
<span className="text-xs text-duck-dark/50 dark:text-foreground/50 mr-1">cwd</span>
|
||||||
|
<button
|
||||||
|
onClick={() => onChange('user')}
|
||||||
|
className={`inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs transition-colors cursor-pointer ${
|
||||||
|
cwdMode === 'user'
|
||||||
|
? 'bg-duck-teal/15 text-duck-teal font-medium'
|
||||||
|
: 'text-duck-dark/40 dark:text-foreground/40 hover:text-duck-dark/60 dark:hover:text-foreground/60'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<Home className="h-3 w-3" />
|
||||||
|
User Home
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => onChange('host')}
|
||||||
|
className={`inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs transition-colors cursor-pointer ${
|
||||||
|
cwdMode === 'host'
|
||||||
|
? 'bg-duck-teal/15 text-duck-teal font-medium'
|
||||||
|
: 'text-duck-dark/40 dark:text-foreground/40 hover:text-duck-dark/60 dark:hover:text-foreground/60'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<Monitor className="h-3 w-3" />
|
||||||
|
Host Home
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function NewChat() {
|
function NewChat() {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const locationState = location.state as ChatLocationState;
|
const locationState = location.state as ChatLocationState;
|
||||||
|
const [cwdMode, setCwdMode] = useState<'user' | 'host'>('user');
|
||||||
|
|
||||||
const chat = usePiChat(undefined, locationState?.model);
|
const chat = usePiChat(undefined, locationState?.model);
|
||||||
|
|
||||||
|
const cwd = cwdMode === 'host' ? { path: getHostHome() } : locationState?.cwd;
|
||||||
|
|
||||||
const initialMessage = locationState?.initialMessage
|
const initialMessage = locationState?.initialMessage
|
||||||
? {
|
? {
|
||||||
text: locationState.initialMessage,
|
text: locationState.initialMessage,
|
||||||
@@ -114,13 +152,14 @@ function NewChat() {
|
|||||||
isGenerating={chat.isGenerating}
|
isGenerating={chat.isGenerating}
|
||||||
onDelete={undefined}
|
onDelete={undefined}
|
||||||
/>
|
/>
|
||||||
|
{!chat.hasStarted && <CwdToggle cwdMode={cwdMode} onChange={setCwdMode} />}
|
||||||
<EmbeddableChat
|
<EmbeddableChat
|
||||||
chat={chat}
|
chat={chat}
|
||||||
sessionId={undefined}
|
sessionId={undefined}
|
||||||
initialModel={locationState?.model ?? undefined}
|
initialModel={locationState?.model ?? undefined}
|
||||||
initialMessage={initialMessage}
|
initialMessage={initialMessage}
|
||||||
defaultInput={locationState?.prefillInput ?? ''}
|
defaultInput={locationState?.prefillInput ?? ''}
|
||||||
cwd={locationState?.cwd}
|
cwd={cwd}
|
||||||
className="flex-1 min-h-0"
|
className="flex-1 min-h-0"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,11 +12,16 @@ export function modelKey(m: ModelOption): string {
|
|||||||
|
|
||||||
// Store provider names globally for display
|
// Store provider names globally for display
|
||||||
let globalProviderNames: Record<string, string> = {};
|
let globalProviderNames: Record<string, string> = {};
|
||||||
|
let globalHostHome = '';
|
||||||
|
|
||||||
export function getProviderDisplayName(providerId: string): string {
|
export function getProviderDisplayName(providerId: string): string {
|
||||||
return globalProviderNames[providerId] || providerId;
|
return globalProviderNames[providerId] || providerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getHostHome(): string {
|
||||||
|
return globalHostHome;
|
||||||
|
}
|
||||||
|
|
||||||
export function usePiModels() {
|
export function usePiModels() {
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const { isAuthenticated } = useAuth();
|
const { isAuthenticated } = useAuth();
|
||||||
@@ -25,7 +30,7 @@ export function usePiModels() {
|
|||||||
queryKey: ['PI_MODELS'],
|
queryKey: ['PI_MODELS'],
|
||||||
enabled: isAuthenticated,
|
enabled: isAuthenticated,
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const data = await client.get<{ models: ModelOption[]; providerNames?: Record<string, string> }>('/pi/models');
|
const data = await client.get<{ models: ModelOption[]; providerNames?: Record<string, string>; hostHome?: string }>('/pi/models');
|
||||||
|
|
||||||
console.log('[usePiModels] Fetched models:', {
|
console.log('[usePiModels] Fetched models:', {
|
||||||
modelCount: data.models.length,
|
modelCount: data.models.length,
|
||||||
@@ -38,6 +43,10 @@ export function usePiModels() {
|
|||||||
globalProviderNames = data.providerNames;
|
globalProviderNames = data.providerNames;
|
||||||
console.log('[usePiModels] Stored provider names:', globalProviderNames);
|
console.log('[usePiModels] Stored provider names:', globalProviderNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.hostHome) {
|
||||||
|
globalHostHome = data.hostHome;
|
||||||
|
}
|
||||||
|
|
||||||
return data.models;
|
return data.models;
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user