mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
5f826f4448
The /context command previously showed only the hard budget compression threshold (contextWindow - maxTokens), which confused users who expected to see the soft summarization trigger from summarize_token_percent. This commit adds SummarizeAtTokens alongside the existing CompressAtTokens so that both thresholds are visible: - Compress at: contextWindow - maxTokens (hard budget, triggers proactive compression when exceeded) - Summarize at: contextWindow * summarizeTokenPercent / 100 (soft trigger, matches maybeSummarize's threshold) The fix updates the /context command output, the Web UI popover, and the pico channel WebSocket payload. Fixes #2968
122 lines
2.9 KiB
TypeScript
122 lines
2.9 KiB
TypeScript
import { atom, getDefaultStore } from "jotai"
|
|
import { atomWithStorage } from "jotai/utils"
|
|
|
|
import {
|
|
ASSISTANT_DETAIL_VISIBILITY_STORAGE_KEY,
|
|
type AssistantDetailVisibility,
|
|
DEFAULT_ASSISTANT_DETAIL_VISIBILITY,
|
|
assistantDetailVisibilityStorage,
|
|
shouldShowAssistantMessage,
|
|
} from "@/features/chat/detail-visibility"
|
|
import {
|
|
getInitialActiveSessionId,
|
|
writeStoredSessionId,
|
|
} from "@/features/chat/state"
|
|
|
|
export interface ChatAttachment {
|
|
type: "image" | "audio" | "video" | "file"
|
|
url: string
|
|
filename?: string
|
|
contentType?: string
|
|
}
|
|
|
|
export interface ChatToolCallFunction {
|
|
name?: string
|
|
arguments?: string
|
|
}
|
|
|
|
export interface ChatToolCallExtraContent {
|
|
toolFeedbackExplanation?: string
|
|
}
|
|
|
|
export interface ChatToolCall {
|
|
id?: string
|
|
type?: string
|
|
function?: ChatToolCallFunction
|
|
extraContent?: ChatToolCallExtraContent
|
|
}
|
|
|
|
export type AssistantMessageKind = "normal" | "thought" | "tool_calls"
|
|
|
|
export interface ChatMessage {
|
|
id: string
|
|
role: "user" | "assistant"
|
|
content: string
|
|
timestamp: number | string
|
|
kind?: AssistantMessageKind
|
|
modelName?: string
|
|
attachments?: ChatAttachment[]
|
|
toolCalls?: ChatToolCall[]
|
|
}
|
|
|
|
export interface ContextUsage {
|
|
used_tokens: number
|
|
total_tokens: number
|
|
compress_at_tokens: number
|
|
summarize_at_tokens?: number
|
|
used_percent: number
|
|
}
|
|
|
|
export type ConnectionState =
|
|
| "disconnected"
|
|
| "connecting"
|
|
| "connected"
|
|
| "error"
|
|
|
|
export interface ChatStoreState {
|
|
messages: ChatMessage[]
|
|
connectionState: ConnectionState
|
|
isTyping: boolean
|
|
activeSessionId: string
|
|
hasHydratedActiveSession: boolean
|
|
contextUsage?: ContextUsage
|
|
}
|
|
|
|
type ChatStorePatch = Partial<ChatStoreState>
|
|
|
|
const DEFAULT_CHAT_STATE: ChatStoreState = {
|
|
messages: [],
|
|
connectionState: "disconnected",
|
|
isTyping: false,
|
|
activeSessionId: getInitialActiveSessionId(),
|
|
hasHydratedActiveSession: false,
|
|
}
|
|
|
|
export const chatAtom = atom<ChatStoreState>(DEFAULT_CHAT_STATE)
|
|
export const assistantDetailVisibilityAtom =
|
|
atomWithStorage<AssistantDetailVisibility>(
|
|
ASSISTANT_DETAIL_VISIBILITY_STORAGE_KEY,
|
|
DEFAULT_ASSISTANT_DETAIL_VISIBILITY,
|
|
assistantDetailVisibilityStorage,
|
|
{ getOnInit: true },
|
|
)
|
|
export const showAssistantDetailsAtom = atom(
|
|
(get) => get(assistantDetailVisibilityAtom) !== "none",
|
|
)
|
|
|
|
const store = getDefaultStore()
|
|
|
|
export function getChatState() {
|
|
return store.get(chatAtom)
|
|
}
|
|
|
|
export function updateChatStore(
|
|
patch:
|
|
| ChatStorePatch
|
|
| ((prev: ChatStoreState) => ChatStorePatch | ChatStoreState),
|
|
) {
|
|
store.set(chatAtom, (prev) => {
|
|
const nextPatch = typeof patch === "function" ? patch(prev) : patch
|
|
const next = { ...prev, ...nextPatch }
|
|
|
|
if (next.activeSessionId !== prev.activeSessionId) {
|
|
writeStoredSessionId(next.activeSessionId)
|
|
}
|
|
|
|
return next
|
|
})
|
|
}
|
|
|
|
export { shouldShowAssistantMessage, DEFAULT_ASSISTANT_DETAIL_VISIBILITY }
|
|
export type { AssistantDetailVisibility }
|