fix: scope session assist to session directory
This commit is contained in:
@@ -267,7 +267,7 @@ const ChatViewport = React.memo(({
|
||||
</div>
|
||||
)}
|
||||
|
||||
<SessionRecapNote sessionId={currentSessionId} isMobile={isMobile} />
|
||||
<SessionRecapNote sessionId={currentSessionId} directory={directory} isMobile={isMobile} />
|
||||
|
||||
<div className="mb-3">
|
||||
<StatusRowContainer />
|
||||
|
||||
@@ -4758,6 +4758,7 @@ const ChatInputComponent: React.FC<ChatInputProps> = ({ onOpenSettings, scrollTo
|
||||
<div className="flex flex-col">
|
||||
<SessionSuggestionChip
|
||||
sessionId={currentSessionId}
|
||||
directory={currentSessionDirectoryForSync ?? currentDirectory}
|
||||
hidden={hasContent || newSessionDraftOpen}
|
||||
onApply={applyAssistSuggestion}
|
||||
className="mb-1.5"
|
||||
@@ -4841,6 +4842,7 @@ const ChatInputComponent: React.FC<ChatInputProps> = ({ onOpenSettings, scrollTo
|
||||
<>
|
||||
<SessionSuggestionChip
|
||||
sessionId={currentSessionId}
|
||||
directory={currentSessionDirectoryForSync ?? currentDirectory}
|
||||
hidden={hasContent || newSessionDraftOpen}
|
||||
onApply={applyAssistSuggestion}
|
||||
className="mb-1.5"
|
||||
|
||||
@@ -4,14 +4,15 @@ import { useI18n } from '@/lib/i18n';
|
||||
|
||||
interface SessionRecapNoteProps {
|
||||
sessionId: string;
|
||||
directory?: string;
|
||||
isMobile: boolean;
|
||||
}
|
||||
|
||||
// Quiet one-paragraph recap of the agent's last reply, rendered right under
|
||||
// the last message (above the reserved bottom gap). Appears only after the
|
||||
// 5-minute quiet window, so the layout shift happens off-screen in practice.
|
||||
export const SessionRecapNote: React.FC<SessionRecapNoteProps> = React.memo(({ sessionId, isMobile }) => {
|
||||
const { visibleRecap } = useSessionAssistState(sessionId);
|
||||
export const SessionRecapNote: React.FC<SessionRecapNoteProps> = React.memo(({ sessionId, directory, isMobile }) => {
|
||||
const { visibleRecap } = useSessionAssistState(sessionId, directory);
|
||||
const { t } = useI18n();
|
||||
|
||||
if (!visibleRecap) {
|
||||
|
||||
@@ -8,6 +8,7 @@ import { useI18n } from '@/lib/i18n';
|
||||
|
||||
interface SessionSuggestionChipProps {
|
||||
sessionId: string | null;
|
||||
directory?: string;
|
||||
/** The composer already has content — the suggestion must stay out of the way. */
|
||||
hidden: boolean;
|
||||
onApply: (text: string) => void;
|
||||
@@ -20,8 +21,8 @@ const isRecord = (value: unknown): value is Record<string, unknown> =>
|
||||
// One small-model-suggested follow-up message, styled like the draft starter
|
||||
// chips. Tapping it fills the composer (no auto-send); the X patches the
|
||||
// suggestion out of the session metadata so it stays dismissed everywhere.
|
||||
export const SessionSuggestionChip: React.FC<SessionSuggestionChipProps> = React.memo(({ sessionId, hidden, onApply, className }) => {
|
||||
const { suggestion } = useSessionAssistState(sessionId ?? '');
|
||||
export const SessionSuggestionChip: React.FC<SessionSuggestionChipProps> = React.memo(({ sessionId, directory, hidden, onApply, className }) => {
|
||||
const { suggestion } = useSessionAssistState(sessionId ?? '', directory);
|
||||
const { t } = useI18n();
|
||||
const { currentTheme } = useThemeSystem();
|
||||
const [dismissing, setDismissing] = React.useState(false);
|
||||
|
||||
@@ -13,8 +13,8 @@ interface LastMessageSnapshot {
|
||||
}
|
||||
|
||||
/** Narrow subscription to the last message of a session (id/role/time only). */
|
||||
function useLastMessageSnapshot(sessionId: string): LastMessageSnapshot | null {
|
||||
const store = useDirectoryStore();
|
||||
function useLastMessageSnapshot(sessionId: string, directory?: string): LastMessageSnapshot | null {
|
||||
const store = useDirectoryStore(directory);
|
||||
const cacheRef = React.useRef<LastMessageSnapshot | null>(null);
|
||||
|
||||
const getSnapshot = React.useCallback((): LastMessageSnapshot | null => {
|
||||
@@ -56,10 +56,10 @@ export interface SessionAssistState {
|
||||
suggestion: string | null;
|
||||
}
|
||||
|
||||
export function useSessionAssistState(sessionId: string): SessionAssistState {
|
||||
const session = useSession(sessionId);
|
||||
const status = useSessionStatus(sessionId);
|
||||
const lastMessage = useLastMessageSnapshot(sessionId);
|
||||
export function useSessionAssistState(sessionId: string, directory?: string): SessionAssistState {
|
||||
const session = useSession(sessionId, directory);
|
||||
const status = useSessionStatus(sessionId, directory);
|
||||
const lastMessage = useLastMessageSnapshot(sessionId, directory);
|
||||
|
||||
const isIdle = !status || status.type === 'idle';
|
||||
const payload = getSessionAssist(session);
|
||||
|
||||
@@ -43,7 +43,43 @@ const ASSIST_SYSTEM_PROMPT = [
|
||||
'You assist a user who chats with a coding agent. Based on the conversation transcript, return exactly one JSON object and nothing else — no prose, no markdown, no code fences.',
|
||||
'Shape: {"recap": string, "suggestion": string}',
|
||||
'recap: at most 20 words. State the substance directly — the facts, result, or conclusion, plus the next move if there is one. NEVER narrate ("The assistant explained…", "The agent did…") — write the content itself, like a note the user jotted down.',
|
||||
'suggestion: the next message to send in this conversation, addressed TO the agent — a concise instruction or question that moves the work forward, e.g. "Run the tests and fix failures" / "Commit this". Imperative or question form. Never explain, never offer help, never say "you can".',
|
||||
'suggestion: write ONE immediately sendable next user message addressed TO the coding agent.',
|
||||
'The suggestion should be the most useful next step after the assistant\'s latest reply. It should help the user continue productively, not inspect already-known details.',
|
||||
'Prefer suggestions that ask the agent to make a concrete improvement, implement something specific, validate the latest change, explain tradeoffs, improve the current approach, or continue from the current result.',
|
||||
'Rules for suggestion:',
|
||||
'- Output exactly one message the user could click and send without editing.',
|
||||
'- Pick one best next action yourself.',
|
||||
'- Do not include alternatives, choices, slash-separated options, or "or".',
|
||||
'- Do not write "Do X or Y", "Ask whether...", "Maybe...", or "You could...".',
|
||||
'- Do not ask for information the assistant already provided.',
|
||||
'- Do not ask to see exact code, file paths, prompt locations, or implementation internals unless the assistant did not provide them and they are necessary for the next step.',
|
||||
'- Do not produce generic workflow commands like "Run tests" unless testing is clearly the next unresolved step.',
|
||||
'- Do not produce meta/debug requests that merely inspect the implementation.',
|
||||
'- Use imperative or question form.',
|
||||
'- Keep it concise.',
|
||||
'Use these examples to understand how to choose the suggestion. Do not copy their topic or wording unless the current conversation is about the same thing.',
|
||||
'Example 1:',
|
||||
'Assistant reply summary:',
|
||||
'The assistant already identified the file where the feature is implemented, explained what context is sent to the small model, and summarized the current prompt.',
|
||||
'Bad suggestion:',
|
||||
'"Show me the exact runtime.js code and where the prompt is built."',
|
||||
'Why bad:',
|
||||
'It asks for information the assistant already provided. It repeats inspection instead of moving to an improvement or decision.',
|
||||
'Good suggestion:',
|
||||
'"Suggest how to improve the prompt and context so the generated suggestion is more useful."',
|
||||
'Why good:',
|
||||
'It naturally continues from the analysis and asks for a concrete improvement.',
|
||||
'Example 2:',
|
||||
'Assistant reply summary:',
|
||||
'The assistant implemented a timeline dialog redesign, listed concrete UI changes, and reported that type-check and lint passed.',
|
||||
'Bad suggestion:',
|
||||
'"Check whether scrolling or loading older messages works without jumps."',
|
||||
'Why bad:',
|
||||
'It contains an alternative. A suggestion chip must be one sendable message, not a choice the user has to edit.',
|
||||
'Good suggestion:',
|
||||
'"Check whether scrolling and loading older messages work without jumps."',
|
||||
'Why good:',
|
||||
'It picks a single validation request that the user can send immediately.',
|
||||
'Both values MUST be written in the same language as the conversation text itself. Ignore any other language preferences or personalization you may have — only the conversation text decides the language.',
|
||||
'Use double quotes for JSON strings, no trailing commas.',
|
||||
].join('\n');
|
||||
|
||||
Reference in New Issue
Block a user