prepare 0.5.25 changelog (#778)
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hermes-web-ui",
|
||||
"version": "0.5.24",
|
||||
"version": "0.5.25",
|
||||
"description": "Self-hosted AI chat dashboard for Hermes Agent — multi-model web UI with multi-platform integration",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -41,22 +41,72 @@ const statusItems = computed(() => {
|
||||
];
|
||||
});
|
||||
|
||||
type DisplayContentFile = {
|
||||
type: 'image' | 'file'
|
||||
name: string
|
||||
path?: string
|
||||
url?: string
|
||||
}
|
||||
|
||||
function getBlockText(block: any): string {
|
||||
if (!block || typeof block !== 'object') return ''
|
||||
if (block.type === 'text' || block.type === 'input_text') {
|
||||
return typeof block.text === 'string' ? block.text : ''
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
function getImageUrlFromBlock(block: any): string | null {
|
||||
if (!block || typeof block !== 'object') return null
|
||||
if (block.type !== 'input_image' && block.type !== 'image_url') return null
|
||||
const raw = block.image_url
|
||||
if (typeof raw === 'string') return raw
|
||||
if (raw && typeof raw === 'object' && typeof raw.url === 'string') return raw.url
|
||||
return null
|
||||
}
|
||||
|
||||
function imageNameFromDataUrl(url: string, index: number): string {
|
||||
const match = url.match(/^data:image\/([^;,]+)/i)
|
||||
const ext = match?.[1] === 'jpeg' ? 'jpg' : match?.[1] || 'png'
|
||||
return `image-${index + 1}.${ext}`
|
||||
}
|
||||
|
||||
function parseContentBlocks(content: string): Array<ContentBlock | Record<string, unknown>> | null {
|
||||
const trimmed = content.trim()
|
||||
if (!trimmed) return null
|
||||
|
||||
const parse = (value: string) => {
|
||||
const parsed = JSON.parse(value)
|
||||
return Array.isArray(parsed) && parsed.length > 0 && 'type' in parsed[0]
|
||||
? parsed as Array<ContentBlock | Record<string, unknown>>
|
||||
: null
|
||||
}
|
||||
|
||||
try {
|
||||
return parse(trimmed)
|
||||
} catch {
|
||||
// Hermes Agent stored some multimodal user messages via Python str(list),
|
||||
// e.g. [{'type': 'text'}, {'type': 'image_url', ...}]. Convert that
|
||||
// legacy repr into JSON for display only.
|
||||
if (!trimmed.startsWith("[{'") && !trimmed.startsWith('[{"')) return null
|
||||
try {
|
||||
return parse(
|
||||
trimmed
|
||||
.replace(/\bNone\b/g, 'null')
|
||||
.replace(/\bTrue\b/g, 'true')
|
||||
.replace(/\bFalse\b/g, 'false')
|
||||
.replace(/'/g, '"'),
|
||||
)
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse ContentBlock[] from JSON string
|
||||
const contentBlocks = computed(() => {
|
||||
const content = props.message.content || '';
|
||||
if (!content.trim()) return null;
|
||||
|
||||
try {
|
||||
// Try to parse as ContentBlock[] array
|
||||
const parsed = JSON.parse(content);
|
||||
if (Array.isArray(parsed) && parsed.length > 0 && 'type' in parsed[0]) {
|
||||
return parsed as ContentBlock[];
|
||||
}
|
||||
} catch {
|
||||
// Not valid JSON, treat as plain text
|
||||
}
|
||||
|
||||
return null;
|
||||
return parseContentBlocks(content);
|
||||
});
|
||||
|
||||
// Check if content is in ContentBlock[] format
|
||||
@@ -70,16 +120,40 @@ const displayText = computed(() => {
|
||||
|
||||
// Extract text from blocks
|
||||
return contentBlocks.value!
|
||||
.filter(block => block.type === 'text')
|
||||
.map(block => block.text)
|
||||
.map(block => getBlockText(block))
|
||||
.filter(Boolean)
|
||||
.join('\n');
|
||||
});
|
||||
|
||||
// Extract files from ContentBlock[]
|
||||
const contentFiles = computed(() => {
|
||||
const contentFiles = computed<DisplayContentFile[] | null>(() => {
|
||||
if (!isContentBlockArray.value) return null;
|
||||
|
||||
return contentBlocks.value!.filter(block => block.type === 'image' || block.type === 'file');
|
||||
return contentBlocks.value!.flatMap<DisplayContentFile>((block, index) => {
|
||||
if (block.type === 'image') {
|
||||
return [{
|
||||
type: 'image' as const,
|
||||
name: String((block as any).name || `image-${index + 1}`),
|
||||
path: String((block as any).path || ''),
|
||||
}].filter(file => file.path)
|
||||
}
|
||||
if (block.type === 'file') {
|
||||
return [{
|
||||
type: 'file' as const,
|
||||
name: String((block as any).name || `file-${index + 1}`),
|
||||
path: String((block as any).path || ''),
|
||||
}].filter(file => file.path)
|
||||
}
|
||||
const imageUrl = getImageUrlFromBlock(block)
|
||||
if (imageUrl?.startsWith('data:image/')) {
|
||||
return [{
|
||||
type: 'image' as const,
|
||||
name: imageNameFromDataUrl(imageUrl, index),
|
||||
url: imageUrl,
|
||||
}]
|
||||
}
|
||||
return []
|
||||
});
|
||||
});
|
||||
|
||||
// Generate download URL with auth token
|
||||
@@ -89,6 +163,11 @@ function getDownloadUrl(path: string, name: string): string {
|
||||
return token ? `${base}&token=${encodeURIComponent(token)}` : base;
|
||||
}
|
||||
|
||||
function getContentFileUrl(file: DisplayContentFile): string {
|
||||
if (file.url) return file.url
|
||||
return file.path ? getDownloadUrl(file.path, file.name) : ''
|
||||
}
|
||||
|
||||
const toolExpanded = ref(false);
|
||||
const previewUrl = ref<string | null>(null);
|
||||
|
||||
@@ -721,16 +800,16 @@ onBeforeUnmount(() => {
|
||||
>
|
||||
<template v-if="file.type === 'image'">
|
||||
<img
|
||||
:src="getDownloadUrl(file.path, file.name)"
|
||||
:src="getContentFileUrl(file)"
|
||||
:alt="file.name"
|
||||
class="msg-attachment-thumb"
|
||||
@click="previewUrl = getDownloadUrl(file.path, file.name)"
|
||||
@click="previewUrl = getContentFileUrl(file)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div
|
||||
class="msg-attachment-file"
|
||||
@click="downloadFile(file.path, file.name).catch(err => toast.error(err.message || t('download.downloadFailed')))"
|
||||
@click="file.path && downloadFile(file.path, file.name).catch(err => toast.error(err.message || t('download.downloadFailed')))"
|
||||
style="cursor: pointer;"
|
||||
:title="t('download.downloadFile')"
|
||||
>
|
||||
|
||||
@@ -5,6 +5,20 @@ export interface ChangelogEntry {
|
||||
}
|
||||
|
||||
export const changelog: ChangelogEntry[] = [
|
||||
{
|
||||
version: '0.5.25',
|
||||
date: '2026-05-16',
|
||||
changes: [
|
||||
'changelog.new_0_5_25_1',
|
||||
'changelog.new_0_5_25_2',
|
||||
'changelog.new_0_5_25_3',
|
||||
'changelog.new_0_5_25_4',
|
||||
'changelog.new_0_5_25_5',
|
||||
'changelog.new_0_5_25_6',
|
||||
'changelog.new_0_5_25_7',
|
||||
'changelog.new_0_5_25_8',
|
||||
],
|
||||
},
|
||||
{
|
||||
version: '0.5.24',
|
||||
date: '2026-05-15',
|
||||
|
||||
@@ -909,6 +909,14 @@ jobTriggered: 'Job ausgelost',
|
||||
new_0_5_23_4: 'Reserve the Web UI port during gateway allocation to avoid startup conflicts',
|
||||
new_0_5_23_5: 'Fix self-update restart handling so successful helper exits are not reported as failures',
|
||||
new_0_5_24_1: 'Align Bridge chat with API Server handling for multimodal input, system prompt, and workspace context',
|
||||
new_0_5_25_1: 'Add group chat room reset and clone actions',
|
||||
new_0_5_25_2: 'Make the Web UI state directory configurable for custom deployment layouts',
|
||||
new_0_5_25_3: 'Add MiMo as a TTS provider in voice settings',
|
||||
new_0_5_25_4: 'Fetch custom provider model lists through the backend to avoid browser CORS failures',
|
||||
new_0_5_25_5: 'Fix tool approval flow for bridge sessions',
|
||||
new_0_5_25_6: 'Remove the forced CLI platform hint from bridge prompts so custom media/file instructions are preserved',
|
||||
new_0_5_25_7: 'Show base64 image content correctly in user message history',
|
||||
new_0_5_25_8: 'Add Playwright browser tests, chat streaming contract coverage, provider model coverage, and coverage baseline',
|
||||
new_0_5_5_1: '🎉 Tag der Arbeit! Heute wird nicht gearbeitet, bitte habt Verständnis',
|
||||
new_0_5_5_2: 'Verlaufsseite für Hermes-Sitzungshistorie hinzugefügt',
|
||||
new_0_5_5_3: 'Verlaufsseite verwaltet Sitzungen unabhängig ohne Störung des aktiven Chats',
|
||||
|
||||
@@ -1192,6 +1192,14 @@ export default {
|
||||
new_0_5_23_4: 'Reserve the Web UI port during gateway allocation to avoid startup conflicts',
|
||||
new_0_5_23_5: 'Fix self-update restart handling so successful helper exits are not reported as failures',
|
||||
new_0_5_24_1: 'Align Bridge chat with API Server handling for multimodal input, system prompt, and workspace context',
|
||||
new_0_5_25_1: 'Add group chat room reset and clone actions',
|
||||
new_0_5_25_2: 'Make the Web UI state directory configurable for custom deployment layouts',
|
||||
new_0_5_25_3: 'Add MiMo as a TTS provider in voice settings',
|
||||
new_0_5_25_4: 'Fetch custom provider model lists through the backend to avoid browser CORS failures',
|
||||
new_0_5_25_5: 'Fix tool approval flow for bridge sessions',
|
||||
new_0_5_25_6: 'Remove the forced CLI platform hint from bridge prompts so custom media/file instructions are preserved',
|
||||
new_0_5_25_7: 'Show base64 image content correctly in user message history',
|
||||
new_0_5_25_8: 'Add Playwright browser tests, chat streaming contract coverage, provider model coverage, and coverage baseline',
|
||||
|
||||
new_0_5_6_1: 'Add voice playback feature with Web Speech API: manual button, auto-play toggle, rainbow border animation, and mobile optimization',
|
||||
new_0_5_6_2: 'Add robust LLM JSON parser with tolerance for Python format and extract text from streaming events',
|
||||
|
||||
@@ -905,6 +905,14 @@ jobTriggered: 'Job ejecutado',
|
||||
new_0_5_23_4: 'Reserve the Web UI port during gateway allocation to avoid startup conflicts',
|
||||
new_0_5_23_5: 'Fix self-update restart handling so successful helper exits are not reported as failures',
|
||||
new_0_5_24_1: 'Align Bridge chat with API Server handling for multimodal input, system prompt, and workspace context',
|
||||
new_0_5_25_1: 'Add group chat room reset and clone actions',
|
||||
new_0_5_25_2: 'Make the Web UI state directory configurable for custom deployment layouts',
|
||||
new_0_5_25_3: 'Add MiMo as a TTS provider in voice settings',
|
||||
new_0_5_25_4: 'Fetch custom provider model lists through the backend to avoid browser CORS failures',
|
||||
new_0_5_25_5: 'Fix tool approval flow for bridge sessions',
|
||||
new_0_5_25_6: 'Remove the forced CLI platform hint from bridge prompts so custom media/file instructions are preserved',
|
||||
new_0_5_25_7: 'Show base64 image content correctly in user message history',
|
||||
new_0_5_25_8: 'Add Playwright browser tests, chat streaming contract coverage, provider model coverage, and coverage baseline',
|
||||
new_0_5_5_1: '🎉 ¡Feliz Día del Trabajo! Hoy no se trabaja, agradezcan su comprensión',
|
||||
new_0_5_5_2: 'Añadida página de historial para sesiones Hermes',
|
||||
new_0_5_5_3: 'La página de historial gestiona sesiones de forma independiente',
|
||||
|
||||
@@ -904,6 +904,14 @@ jobTriggered: 'Job declenche',
|
||||
new_0_5_23_4: 'Reserve the Web UI port during gateway allocation to avoid startup conflicts',
|
||||
new_0_5_23_5: 'Fix self-update restart handling so successful helper exits are not reported as failures',
|
||||
new_0_5_24_1: 'Align Bridge chat with API Server handling for multimodal input, system prompt, and workspace context',
|
||||
new_0_5_25_1: 'Add group chat room reset and clone actions',
|
||||
new_0_5_25_2: 'Make the Web UI state directory configurable for custom deployment layouts',
|
||||
new_0_5_25_3: 'Add MiMo as a TTS provider in voice settings',
|
||||
new_0_5_25_4: 'Fetch custom provider model lists through the backend to avoid browser CORS failures',
|
||||
new_0_5_25_5: 'Fix tool approval flow for bridge sessions',
|
||||
new_0_5_25_6: 'Remove the forced CLI platform hint from bridge prompts so custom media/file instructions are preserved',
|
||||
new_0_5_25_7: 'Show base64 image content correctly in user message history',
|
||||
new_0_5_25_8: 'Add Playwright browser tests, chat streaming contract coverage, provider model coverage, and coverage baseline',
|
||||
new_0_5_5_1: '🎉 Joyeuse Fête du Travail! Pas de travail aujourd\'hui, merci de votre compréhension',
|
||||
new_0_5_5_2: 'Ajout d\'une page d\'historique pour les sessions Hermes',
|
||||
new_0_5_5_3: 'La page d\'historique gère les sessions de manière indépendante',
|
||||
|
||||
@@ -905,6 +905,14 @@ export default {
|
||||
new_0_5_23_4: 'Reserve the Web UI port during gateway allocation to avoid startup conflicts',
|
||||
new_0_5_23_5: 'Fix self-update restart handling so successful helper exits are not reported as failures',
|
||||
new_0_5_24_1: 'Align Bridge chat with API Server handling for multimodal input, system prompt, and workspace context',
|
||||
new_0_5_25_1: 'Add group chat room reset and clone actions',
|
||||
new_0_5_25_2: 'Make the Web UI state directory configurable for custom deployment layouts',
|
||||
new_0_5_25_3: 'Add MiMo as a TTS provider in voice settings',
|
||||
new_0_5_25_4: 'Fetch custom provider model lists through the backend to avoid browser CORS failures',
|
||||
new_0_5_25_5: 'Fix tool approval flow for bridge sessions',
|
||||
new_0_5_25_6: 'Remove the forced CLI platform hint from bridge prompts so custom media/file instructions are preserved',
|
||||
new_0_5_25_7: 'Show base64 image content correctly in user message history',
|
||||
new_0_5_25_8: 'Add Playwright browser tests, chat streaming contract coverage, provider model coverage, and coverage baseline',
|
||||
new_0_5_5_1: '🎉 労働者の日!今日はお休みです、何卒ご理解ください',
|
||||
new_0_5_5_2: 'Hermesセッション履歴ページを追加',
|
||||
new_0_5_5_3: '履歴ページはアクティブチャットに干渉せずにセッション管理',
|
||||
|
||||
@@ -905,6 +905,14 @@ export default {
|
||||
new_0_5_23_4: 'Reserve the Web UI port during gateway allocation to avoid startup conflicts',
|
||||
new_0_5_23_5: 'Fix self-update restart handling so successful helper exits are not reported as failures',
|
||||
new_0_5_24_1: 'Align Bridge chat with API Server handling for multimodal input, system prompt, and workspace context',
|
||||
new_0_5_25_1: 'Add group chat room reset and clone actions',
|
||||
new_0_5_25_2: 'Make the Web UI state directory configurable for custom deployment layouts',
|
||||
new_0_5_25_3: 'Add MiMo as a TTS provider in voice settings',
|
||||
new_0_5_25_4: 'Fetch custom provider model lists through the backend to avoid browser CORS failures',
|
||||
new_0_5_25_5: 'Fix tool approval flow for bridge sessions',
|
||||
new_0_5_25_6: 'Remove the forced CLI platform hint from bridge prompts so custom media/file instructions are preserved',
|
||||
new_0_5_25_7: 'Show base64 image content correctly in user message history',
|
||||
new_0_5_25_8: 'Add Playwright browser tests, chat streaming contract coverage, provider model coverage, and coverage baseline',
|
||||
new_0_5_5_1: '🎉 노동절 감사합니다! 오늘은 쉬니까 양해 부탁드립니다',
|
||||
new_0_5_5_2: 'Hermes 세션 기록 페이지 추가',
|
||||
new_0_5_5_3: '기록 페이지는 독립적으로 세션 관리',
|
||||
|
||||
@@ -905,6 +905,14 @@ jobTriggered: 'Job acionado',
|
||||
new_0_5_23_4: 'Reserve the Web UI port during gateway allocation to avoid startup conflicts',
|
||||
new_0_5_23_5: 'Fix self-update restart handling so successful helper exits are not reported as failures',
|
||||
new_0_5_24_1: 'Align Bridge chat with API Server handling for multimodal input, system prompt, and workspace context',
|
||||
new_0_5_25_1: 'Add group chat room reset and clone actions',
|
||||
new_0_5_25_2: 'Make the Web UI state directory configurable for custom deployment layouts',
|
||||
new_0_5_25_3: 'Add MiMo as a TTS provider in voice settings',
|
||||
new_0_5_25_4: 'Fetch custom provider model lists through the backend to avoid browser CORS failures',
|
||||
new_0_5_25_5: 'Fix tool approval flow for bridge sessions',
|
||||
new_0_5_25_6: 'Remove the forced CLI platform hint from bridge prompts so custom media/file instructions are preserved',
|
||||
new_0_5_25_7: 'Show base64 image content correctly in user message history',
|
||||
new_0_5_25_8: 'Add Playwright browser tests, chat streaming contract coverage, provider model coverage, and coverage baseline',
|
||||
new_0_5_5_1: '🎉 Feliz Dia do Trabalhador! Hoje não se trabalha, obrigado pela compreensão',
|
||||
new_0_5_5_2: 'Adicionada página de histórico para sessões Hermes',
|
||||
new_0_5_5_3: 'Página de histórico gerencia sessões de forma independente',
|
||||
|
||||
@@ -1194,6 +1194,14 @@ export default {
|
||||
new_0_5_23_4: 'gateway 分配連接埠時保留 Web UI 連接埠,避免啟動連接埠衝突',
|
||||
new_0_5_23_5: '修復自更新重啟邏輯,避免將 restart helper 的成功退出誤報為失敗',
|
||||
new_0_5_24_1: '對齊 Bridge 聊天與 API Server 的多模態輸入、系統提示詞和工作區上下文處理',
|
||||
new_0_5_25_1: '新增群聊房間重設和複製操作',
|
||||
new_0_5_25_2: '支援設定 Web UI 狀態目錄,方便自訂部署目錄結構',
|
||||
new_0_5_25_3: '語音設定新增 MiMo TTS 提供商',
|
||||
new_0_5_25_4: '自訂 Provider 模型清單改由後端代理請求,避免瀏覽器跨域失敗',
|
||||
new_0_5_25_5: '修復 Bridge 工作階段的工具授權流程',
|
||||
new_0_5_25_6: '移除 Bridge 強制注入的 CLI 平台提示,保留使用者自訂媒體和檔案輸出規則',
|
||||
new_0_5_25_7: '使用者訊息歷史支援正確展示 base64 圖片內容',
|
||||
new_0_5_25_8: '新增 Playwright 瀏覽器測試、聊天串流契約覆蓋、Provider 模型測試和覆蓋率基線',
|
||||
new_0_5_6_1: '新增語音播放功能:使用 Web Speech API,支援手動播放按鈕、自動播放開關、彩虹邊框動畫和行動端最佳化',
|
||||
new_0_5_6_2: '新增強健的 LLM JSON 解析器,相容 Python 格式並從串流事件中擷取文字',
|
||||
new_0_5_6_3: 'Skills 功能增強:使用統計、來源過濾、封存技能、來源追溯和釘選切換',
|
||||
|
||||
@@ -1194,6 +1194,14 @@ export default {
|
||||
new_0_5_23_4: 'gateway 分配端口时保留 Web UI 端口,避免启动端口冲突',
|
||||
new_0_5_23_5: '修复自更新重启逻辑,避免将 restart helper 的成功退出误报为失败',
|
||||
new_0_5_24_1: '对齐 Bridge 聊天与 API Server 的多模态输入、系统提示词和工作区上下文处理',
|
||||
new_0_5_25_1: '新增群聊房间重置和克隆操作',
|
||||
new_0_5_25_2: '支持配置 Web UI 状态目录,方便自定义部署目录结构',
|
||||
new_0_5_25_3: '语音设置新增 MiMo TTS 提供商',
|
||||
new_0_5_25_4: '自定义 Provider 模型列表改由后端代理请求,避免浏览器跨域失败',
|
||||
new_0_5_25_5: '修复 Bridge 会话的工具授权流程',
|
||||
new_0_5_25_6: '移除 Bridge 强制注入的 CLI 平台提示,保留用户自定义媒体和文件输出规则',
|
||||
new_0_5_25_7: '用户消息历史支持正确展示 base64 图片内容',
|
||||
new_0_5_25_8: '新增 Playwright 浏览器测试、聊天流式契约覆盖、Provider 模型测试和覆盖率基线',
|
||||
|
||||
new_0_5_6_1: '新增语音播放功能:使用 Web Speech API,支持手动播放按钮、自动播放开关、彩虹边框动画和移动端优化',
|
||||
new_0_5_6_2: '新增健壮的 LLM JSON 解析器,兼容 Python 格式并从流式事件中提取文本',
|
||||
|
||||
@@ -280,12 +280,13 @@ export class AgentBridgeClient {
|
||||
conversationHistory?: unknown[],
|
||||
instructions?: string,
|
||||
profile?: string,
|
||||
options: { force_compress?: boolean } = {},
|
||||
options: { force_compress?: boolean; storage_message?: AgentBridgeMessage } = {},
|
||||
): Promise<AgentBridgeChatStarted> {
|
||||
return this.request<AgentBridgeChatStarted>({
|
||||
action: 'chat',
|
||||
session_id: sessionId,
|
||||
message,
|
||||
...(options.storage_message !== undefined ? { storage_message: options.storage_message } : {}),
|
||||
...(conversationHistory ? { conversation_history: conversationHistory } : {}),
|
||||
...(instructions ? { instructions } : {}),
|
||||
...(profile ? { profile } : {}),
|
||||
|
||||
@@ -719,10 +719,12 @@ class AgentPool:
|
||||
self,
|
||||
session: AgentSession,
|
||||
message: Any,
|
||||
storage_message: Any | None,
|
||||
conversation_history: list[dict[str, Any]] | None,
|
||||
profile: str | None,
|
||||
) -> bool:
|
||||
user_content = str(message) if not isinstance(message, dict) else str(message.get("content", message))
|
||||
persist_message = storage_message if storage_message is not None else message
|
||||
user_content = str(persist_message) if not isinstance(persist_message, dict) else str(persist_message.get("content", persist_message))
|
||||
if not user_content.strip():
|
||||
return False
|
||||
|
||||
@@ -839,6 +841,7 @@ class AgentPool:
|
||||
self,
|
||||
session_id: str,
|
||||
message: Any,
|
||||
storage_message: Any | None = None,
|
||||
instructions: str | None = None,
|
||||
conversation_history: list[dict[str, Any]] | None = None,
|
||||
profile: str | None = None,
|
||||
@@ -858,14 +861,14 @@ class AgentPool:
|
||||
|
||||
thread = threading.Thread(
|
||||
target=self._run_chat,
|
||||
args=(session, record, message, instructions, conversation_history, profile, force_compress),
|
||||
args=(session, record, message, storage_message, instructions, conversation_history, profile, force_compress),
|
||||
daemon=True,
|
||||
name=f"hermes-bridge-run-{run_id[:8]}",
|
||||
)
|
||||
thread.start()
|
||||
return record
|
||||
|
||||
def _run_chat(self, session: AgentSession, record: RunRecord, message: Any, instructions: str | None = None, conversation_history: list[dict[str, Any]] | None = None, profile: str | None = None, force_compress: bool = False) -> None:
|
||||
def _run_chat(self, session: AgentSession, record: RunRecord, message: Any, storage_message: Any | None = None, instructions: str | None = None, conversation_history: list[dict[str, Any]] | None = None, profile: str | None = None, force_compress: bool = False) -> None:
|
||||
with self._run_lock:
|
||||
def stream_callback(delta: str) -> None:
|
||||
with self._lock:
|
||||
@@ -888,7 +891,7 @@ class AgentPool:
|
||||
os.environ["HERMES_EXEC_ASK"] = "1"
|
||||
except Exception:
|
||||
previous_approval_callback = None
|
||||
self._prepersist_user_message(session, message, conversation_history, profile)
|
||||
self._prepersist_user_message(session, message, storage_message, conversation_history, profile)
|
||||
db_count_after_prepersist = self._session_db_message_count(session.session_id, profile)
|
||||
if force_compress:
|
||||
compress = getattr(session.agent, "_compress_context", None)
|
||||
@@ -1154,12 +1157,14 @@ class BridgeServer:
|
||||
if action == "chat":
|
||||
session_id = str(req.get("session_id") or "").strip() or uuid.uuid4().hex
|
||||
message = req.get("message", req.get("input", ""))
|
||||
storage_message = req.get("storage_message")
|
||||
instructions = req.get("instructions") or req.get("system_message")
|
||||
conversation_history = req.get("conversation_history")
|
||||
profile = req.get("profile")
|
||||
record = self.pool.start_chat(
|
||||
session_id,
|
||||
message,
|
||||
storage_message,
|
||||
instructions,
|
||||
conversation_history,
|
||||
profile,
|
||||
|
||||
@@ -124,6 +124,9 @@ export async function handleBridgeRun(
|
||||
const bridgeInput = isContentBlockArray(input)
|
||||
? await convertContentBlocksForAgent(input)
|
||||
: input
|
||||
const bridgeStorageInput = isContentBlockArray(input)
|
||||
? inputStr
|
||||
: undefined
|
||||
logger.info('[chat-run-socket] starting CLI bridge run for session %s', session_id)
|
||||
bridgeLogger.info({
|
||||
sessionId: session_id,
|
||||
@@ -133,7 +136,14 @@ export async function handleBridgeRun(
|
||||
hasInstructions: Boolean(fullInstructions),
|
||||
multimodalInput: isContentBlockArray(input),
|
||||
}, '[chat-run-socket] starting CLI bridge run')
|
||||
const started = await bridge.chat(session_id, bridgeInput as AgentBridgeMessage, bridgeHistory, fullInstructions, profile)
|
||||
const started = await bridge.chat(
|
||||
session_id,
|
||||
bridgeInput as AgentBridgeMessage,
|
||||
bridgeHistory,
|
||||
fullInstructions,
|
||||
profile,
|
||||
bridgeStorageInput !== undefined ? { storage_message: bridgeStorageInput } : {},
|
||||
)
|
||||
state.runId = started.run_id
|
||||
bridgeLogger.info({
|
||||
sessionId: session_id,
|
||||
|
||||
Reference in New Issue
Block a user