generated from nhcarrigan/template
4134e11c88
## Summary This PR implements all tickets filed from the CLI v2.1.74 → v2.1.80 changelog audit (issues #223–#232). ### Changes by Issue - **#223** — `feat: handle Elicitation and ElicitationResult hook events` New `ElicitationModal.svelte` component, Rust parsing for `[Elicitation Hook]` and `[ElicitationResult Hook]`, new store methods, and TypeScript event types. - **#224** — `feat: handle StopFailure hook event for API error turns` Rust parsing for `[StopFailure Hook]`; frontend shows error toast + error character state. - **#225** — `feat: handle PostCompact hook event` Rust parsing for `[PostCompact Hook]`; frontend shows info toast + success character state. - **#226** — `feat: expose --name CLI flag as session name at startup` Added `session_name` field to `ClaudeStartOptions`; `StatusBar.doConnect()` passes the conversation name. - **#227** — `fix: tighten startup watchdog and correct misleading comment` Startup watchdog tightened from 60 s → 30 s; corrected a comment that said "5 minutes" whilst the code used 60 seconds. - **#228** — `fix: document cost estimation review and update default model fallback` Default model fallback updated from `claude-sonnet-4-5-20250929` → `claude-sonnet-4-6`; added doc comment explaining why char-based estimation is unaffected by v2.1.75 token overcounting fix. - **#229** — `chore: update supported CLI version constant to 2.1.80` `SUPPORTED_CLI_VERSION` bumped in `CliVersion.svelte`. - **#230** — `feat: surface memory file last-modified timestamps in MemoryBrowserPanel` Backend populates `last_modified` Unix timestamp; frontend formats and displays it per file. - **#231** — `feat: update max_output_tokens upper bound and helper text for 128k` Input max raised to 128 000; placeholder and helper text updated to reflect model-dependent defaults and 128 k ceiling for Opus/Sonnet 4.6. - **#232** — `fix: document non-streaming fallback compatibility with mid-session watchdog` Added doc comment above `STUCK_TIMEOUT` explaining the 5-minute watchdog is intentionally larger than the CLI's 2-minute non-streaming API fallback. --- ✨ This PR was created with help from Hikari~ 🌸 Reviewed-on: #233 Co-authored-by: Hikari <hikari@nhcarrigan.com> Co-committed-by: Hikari <hikari@nhcarrigan.com>
151 lines
6.3 KiB
TypeScript
151 lines
6.3 KiB
TypeScript
import { derived } from "svelte/store";
|
|
import { conversationsStore } from "./conversations";
|
|
import type { TerminalLine } from "$lib/types/messages";
|
|
import { characterState } from "$lib/stores/character";
|
|
import {
|
|
setShouldRestoreHistory,
|
|
setSavedHistory,
|
|
getShouldRestoreHistory,
|
|
getSavedHistory,
|
|
clearHistoryRestore,
|
|
} from "./historyRestore";
|
|
|
|
// Re-export TerminalLine type for backwards compatibility
|
|
export type { TerminalLine };
|
|
|
|
// Re-export from conversations store for backwards compatibility
|
|
export const claudeStore = {
|
|
// Existing subscriptions
|
|
connectionStatus: conversationsStore.connectionStatus,
|
|
sessionId: conversationsStore.sessionId,
|
|
currentWorkingDirectory: conversationsStore.currentWorkingDirectory,
|
|
terminalLines: conversationsStore.terminalLines,
|
|
pendingPermission: conversationsStore.pendingPermission,
|
|
pendingQuestion: conversationsStore.pendingQuestion,
|
|
pendingElicitation: conversationsStore.pendingElicitation,
|
|
isProcessing: conversationsStore.isProcessing,
|
|
grantedTools: conversationsStore.grantedTools,
|
|
pendingRetryMessage: conversationsStore.pendingRetryMessage,
|
|
attachments: conversationsStore.attachments,
|
|
worktreeInfo: conversationsStore.worktreeInfo,
|
|
|
|
// New conversation-aware subscriptions
|
|
conversations: conversationsStore.conversations,
|
|
activeConversationId: conversationsStore.activeConversationId,
|
|
activeConversation: conversationsStore.activeConversation,
|
|
|
|
// Methods
|
|
setConnectionStatus: conversationsStore.setConnectionStatus,
|
|
setConnectionStatusForConversation: conversationsStore.setConnectionStatusForConversation,
|
|
setCharacterStateForConversation: conversationsStore.setCharacterStateForConversation,
|
|
setSessionId: conversationsStore.setSessionId,
|
|
setSessionIdForConversation: conversationsStore.setSessionIdForConversation,
|
|
setWorkingDirectory: conversationsStore.setWorkingDirectory,
|
|
setWorkingDirectoryForConversation: conversationsStore.setWorkingDirectoryForConversation,
|
|
setProcessing: conversationsStore.setProcessing,
|
|
setProcessingForConversation: conversationsStore.setProcessingForConversation,
|
|
addLine: conversationsStore.addLine,
|
|
addLineToConversation: conversationsStore.addLineToConversation,
|
|
updateLine: conversationsStore.updateLine,
|
|
appendToLine: conversationsStore.appendToLine,
|
|
clearTerminal: conversationsStore.clearTerminal,
|
|
getConversationHistory: conversationsStore.getConversationHistory,
|
|
requestPermission: conversationsStore.requestPermission,
|
|
clearPermission: conversationsStore.clearPermission,
|
|
requestPermissionForConversation: conversationsStore.requestPermissionForConversation,
|
|
clearPermissionForConversation: conversationsStore.clearPermissionForConversation,
|
|
requestQuestion: conversationsStore.requestQuestion,
|
|
clearQuestion: conversationsStore.clearQuestion,
|
|
requestQuestionForConversation: conversationsStore.requestQuestionForConversation,
|
|
clearQuestionForConversation: conversationsStore.clearQuestionForConversation,
|
|
requestElicitation: conversationsStore.requestElicitation,
|
|
clearElicitation: conversationsStore.clearElicitation,
|
|
requestElicitationForConversation: conversationsStore.requestElicitationForConversation,
|
|
clearElicitationForConversation: conversationsStore.clearElicitationForConversation,
|
|
grantTool: conversationsStore.grantTool,
|
|
revokeAllTools: conversationsStore.revokeAllTools,
|
|
isToolGranted: conversationsStore.isToolGranted,
|
|
setPendingRetryMessage: conversationsStore.setPendingRetryMessage,
|
|
|
|
// Sound tracking
|
|
resetSoundState: conversationsStore.resetSoundState,
|
|
setTaskStartTime: conversationsStore.setTaskStartTime,
|
|
markSuccessSoundFired: conversationsStore.markSuccessSoundFired,
|
|
markTaskStartSoundFired: conversationsStore.markTaskStartSoundFired,
|
|
|
|
// Draft text (per-tab input persistence)
|
|
setDraftText: conversationsStore.setDraftText,
|
|
|
|
// Worktree info (per-conversation)
|
|
setWorktreeInfo: conversationsStore.setWorktreeInfo,
|
|
|
|
// Conversation management
|
|
createConversation: conversationsStore.createConversation,
|
|
deleteConversation: conversationsStore.deleteConversation,
|
|
switchConversation: conversationsStore.switchConversation,
|
|
renameConversation: conversationsStore.renameConversation,
|
|
saveScrollPosition: conversationsStore.saveScrollPosition,
|
|
getScrollPosition: conversationsStore.getScrollPosition,
|
|
|
|
// Attachment management
|
|
addAttachment: conversationsStore.addAttachment,
|
|
removeAttachment: conversationsStore.removeAttachment,
|
|
clearAttachments: conversationsStore.clearAttachments,
|
|
getAttachments: conversationsStore.getAttachments,
|
|
|
|
getGrantedTools: (): string[] => {
|
|
let tools: string[] = [];
|
|
conversationsStore.grantedTools.subscribe((t) => (tools = Array.from(t)))();
|
|
return tools;
|
|
},
|
|
|
|
// History restoration methods from main branch
|
|
setShouldRestoreHistory: setShouldRestoreHistory,
|
|
setSavedConversationHistory: setSavedHistory,
|
|
getShouldRestoreHistory: getShouldRestoreHistory,
|
|
getSavedConversationHistory: getSavedHistory,
|
|
|
|
reset: () => {
|
|
// Reset only the active conversation
|
|
conversationsStore.clearTerminal();
|
|
conversationsStore.setSessionId(null);
|
|
conversationsStore.setWorkingDirectory("");
|
|
conversationsStore.setProcessing(false);
|
|
conversationsStore.revokeAllTools();
|
|
conversationsStore.clearAttachments();
|
|
// Also clear history restoration
|
|
clearHistoryRestore();
|
|
},
|
|
};
|
|
|
|
export const hasPermissionPending = derived(
|
|
claudeStore.activeConversation,
|
|
($conversation) =>
|
|
$conversation?.pendingPermissions !== null &&
|
|
$conversation?.pendingPermissions !== undefined &&
|
|
$conversation.pendingPermissions.length > 0
|
|
);
|
|
|
|
export const hasQuestionPending = derived(
|
|
claudeStore.activeConversation,
|
|
($conversation) => $conversation?.pendingQuestion !== null
|
|
);
|
|
|
|
export const hasElicitationPending = derived(
|
|
claudeStore.activeConversation,
|
|
($conversation) =>
|
|
$conversation?.pendingElicitation !== null && $conversation?.pendingElicitation !== undefined
|
|
);
|
|
|
|
// Derived store to check if Claude is currently processing (can be interrupted)
|
|
export const isClaudeProcessing = derived(
|
|
[claudeStore.connectionStatus, characterState],
|
|
([$connectionStatus, $characterState]) => {
|
|
// Must be connected and in one of the processing states
|
|
return (
|
|
$connectionStatus === "connected" &&
|
|
["thinking", "typing", "searching", "coding", "mcp"].includes($characterState)
|
|
);
|
|
}
|
|
);
|