diff --git a/api/agent_sessions.py b/api/agent_sessions.py index 91664f5e..bc0e1431 100644 --- a/api/agent_sessions.py +++ b/api/agent_sessions.py @@ -32,6 +32,7 @@ SOURCE_LABELS = { 'telegram': 'Telegram', 'tool': 'Tool', 'tui': 'TUI', + 'webhook': 'Webhook', 'webui': 'WebUI', 'weixin': 'Weixin', } @@ -54,6 +55,8 @@ def normalize_agent_session_source(raw_source: str | None) -> dict: session_source = 'messaging' elif raw == 'cron': session_source = 'cron' + elif raw == 'webhook': + session_source = 'webhook' elif raw == 'tool': session_source = 'tool' elif raw == 'api_server': @@ -173,7 +176,7 @@ def is_cli_session_row(row: dict) -> bool: source_label = _safe_lower(row.get("source_label")) if "webui" in {source, source_tag, raw_source, source_name, source_label}: return False - non_cli_sources = MESSAGING_SOURCES | {"cron", "tool", "api", "api_server"} + non_cli_sources = MESSAGING_SOURCES | {"cron", "webhook", "tool", "api", "api_server"} if {source, source_tag, raw_source, source_name, source_label} & non_cli_sources: return False if source == "messaging": diff --git a/api/config.py b/api/config.py index 51b6e507..b22ec075 100644 --- a/api/config.py +++ b/api/config.py @@ -7802,6 +7802,7 @@ _SETTINGS_DEFAULTS = { "fade_text_effect": False, # animate newly streamed words with a lightweight fade-in effect "show_cli_sessions": True, # merge CLI/TUI/messaging sessions from state.db into the sidebar by default (#3988); established installs are grandfathered OFF by the load_settings backfill "show_cron_sessions": False, # surface cron sessions in the sidebar (subordinate to show_cli_sessions) + "show_webhook_sessions": False, # surface webhook sessions in the sidebar (subordinate to show_cli_sessions) "show_previous_messaging_sessions": False, # show older Telegram/Discord/etc. reset segments "sync_to_insights": False, # mirror WebUI token usage to state.db for /insights "check_for_updates": True, # check if webui/agent repos are behind upstream @@ -8046,6 +8047,7 @@ _SETTINGS_BOOL_KEYS = { "fade_text_effect", "show_cli_sessions", "show_cron_sessions", + "show_webhook_sessions", "show_previous_messaging_sessions", "sync_to_insights", "check_for_updates", diff --git a/api/models.py b/api/models.py index 3668b5d2..a0b9f9bd 100644 --- a/api/models.py +++ b/api/models.py @@ -37,6 +37,7 @@ CLI_VISIBLE_SESSION_LIMIT = 20 # addressable even when many newer non-cron sessions dominate the default # sidebar window (#3172). CRON_PROJECT_CHIP_LIMIT = 200 +WEBHOOK_PROJECT_CHIP_LIMIT = 200 _CLI_SESSIONS_CACHE_TTL_SECONDS = 5.0 # While a turn is actively streaming, hold the CLI/cron projection longer than # one poll interval (mirrors the route-level #4808 hold-down). The frontend @@ -2906,12 +2907,19 @@ def new_session(workspace=None, model=None, profile=None, model_provider=None, p s.save() return s -def _hide_from_default_sidebar(session: dict, *, show_cron: bool = False) -> bool: +def _hide_from_default_sidebar(session: dict, *, show_cron: bool = False, show_webhook: bool = False) -> bool: """Return True for internal/background sessions hidden from the default list.""" sid = str(session.get('session_id') or '') - source = session.get('source_tag') or session.get('source') + source = ( + session.get('source_tag') + or session.get('source') + or session.get('raw_source') + or session.get('session_source') + ) if not show_cron and (source == 'cron' or sid.startswith('cron_')): return True + if not show_webhook and source == 'webhook': + return True if bool(session.get('pre_compression_snapshot')): return not bool(session.get('_show_pre_compression_snapshot')) return False @@ -2959,8 +2967,13 @@ def _has_live_sidebar_state(session: dict) -> bool: def _is_intentionally_background_sidebar_session(session: dict) -> bool: sid = str(session.get('session_id') or '') - source = session.get('source_tag') or session.get('source') - return source == 'cron' or sid.startswith('cron_') + source = ( + session.get('source_tag') + or session.get('source') + or session.get('raw_source') + or session.get('session_source') + ) + return source in {'cron', 'webhook'} or sid.startswith('cron_') def _include_project_hidden_background_sidebar_sessions( @@ -2969,9 +2982,9 @@ def _include_project_hidden_background_sidebar_sessions( ) -> list[dict]: """Keep project-assigned background sessions addressable by project chips. - Cron sessions stay hidden from the default sidebar, but if they have a - project assignment they must still be present in the client cache so the - dedicated project chip can reveal them (#3019). + Cron and webhook sessions stay hidden from the default sidebar, but if they + have a project assignment they must still be present in the client cache so + their dedicated project chips can reveal them (#3019). """ visible_ids = { str(session.get('session_id')) @@ -4149,7 +4162,43 @@ def ensure_cron_project() -> str: return project_id -def is_cron_session(session_id: str, source_tag: str = None) -> bool: +WEBHOOK_PROJECT_NAME = 'Webhooks' +_WEBHOOK_PROJECT_LOCK = threading.Lock() + + +def ensure_webhook_project() -> str: + """Return the project_id of the system "Webhooks" project for the active profile.""" + from api.profiles import get_active_profile_name, _is_root_profile + + active = get_active_profile_name() or 'default' + with _WEBHOOK_PROJECT_LOCK: + projects = load_projects() + for p in projects: + if p.get('name') != WEBHOOK_PROJECT_NAME: + continue + row_profile = p.get('profile') + if row_profile == active: + return p['project_id'] + if _is_root_profile(row_profile or 'default') and _is_root_profile(active): + return p['project_id'] + for p in projects: + if p.get('name') == WEBHOOK_PROJECT_NAME and not p.get('profile'): + p['profile'] = active + save_projects(projects) + return p['project_id'] + project_id = uuid.uuid4().hex[:12] + projects.append({ + 'project_id': project_id, + 'name': WEBHOOK_PROJECT_NAME, + 'color': '#0ea5e9', + 'profile': active, + 'created_at': time.time(), + }) + save_projects(projects) + return project_id + + +def is_cron_session(session_id: str, source_tag: str | None = None) -> bool: """Return True if a session originates from a cron job.""" if source_tag == 'cron': return True @@ -4157,6 +4206,11 @@ def is_cron_session(session_id: str, source_tag: str = None) -> bool: return sid.startswith('cron_') +def is_webhook_session(session_id: str, source_tag: str | None = None) -> bool: + """Return True if a session originates from a webhook route.""" + return str(source_tag or '').strip().lower() == 'webhook' + + def import_cli_session( session_id: str, @@ -4994,6 +5048,7 @@ def _load_cli_sessions_uncached( *, visible_session_limit: int | None = None, cron_project_limit: int | None | bool = CRON_PROJECT_CHIP_LIMIT, + webhook_project_limit: int | None | bool = WEBHOOK_PROJECT_CHIP_LIMIT, include_claude_code: bool = True, ) -> list: cli_sessions = [] @@ -5061,12 +5116,29 @@ def _load_cli_sessions_uncached( _cli_workspace_cache[0] = str(get_last_workspace()) return _cli_workspace_cache[0] + _webhook_pid_cache: list[str | None] = [None] + def _webhook_pid(): + if _webhook_pid_cache[0] is None: + _webhook_pid_cache[0] = ensure_webhook_project() + return _webhook_pid_cache[0] + + def _state_row_project_id(sid: str, source: str | None) -> str | None: + if is_cron_session(sid, source): + return _cron_pid() + if is_webhook_session(sid, source): + return _webhook_pid() + return None + profile_value = _cli_profile or 'default' for row in read_importable_agent_session_rows( db_path, - limit=visible_session_limit if visible_session_limit is not None else (CRON_PROJECT_CHIP_LIMIT if source_filter == 'cron' else CLI_VISIBLE_SESSION_LIMIT), + limit=visible_session_limit if visible_session_limit is not None else ( + CRON_PROJECT_CHIP_LIMIT if source_filter == 'cron' + else WEBHOOK_PROJECT_CHIP_LIMIT if source_filter == 'webhook' + else CLI_VISIBLE_SESSION_LIMIT + ), log=logger, - exclude_sources=("cron",) if source_filter is None else None, + exclude_sources=("cron", "webhook") if source_filter is None else None, include_sources=None if source_filter is None else (source_filter,), ): sid = row['id'] @@ -5076,6 +5148,7 @@ def _load_cli_sessions_uncached( profile = profile_value # CLI DB has no profile column; use active profile _source = row['source'] or 'cli' + _source_meta = normalize_agent_session_source(_source) _title = row['title'] if not _title and _source == 'cron': # Look up the human-friendly cron job name (cron_{job_id}_{ts}) from @@ -5101,18 +5174,18 @@ def _load_cli_sessions_uncached( 'updated_at': raw_ts, 'pinned': False, 'archived': _archived, - 'project_id': _cron_pid() if is_cron_session(sid, _source) else None, + 'project_id': _state_row_project_id(sid, _source), 'profile': profile, 'source_tag': _source, - 'raw_source': row.get('raw_source'), + 'raw_source': row.get('raw_source') or _source_meta.get('raw_source'), 'user_id': row.get('user_id'), 'chat_id': row.get('chat_id') or row.get('origin_chat_id'), 'chat_type': row.get('chat_type'), 'thread_id': row.get('thread_id'), 'session_key': row.get('session_key'), 'platform': row.get('platform'), - 'session_source': row.get('session_source'), - 'source_label': row.get('source_label'), + 'session_source': row.get('session_source') or _source_meta.get('session_source'), + 'source_label': row.get('source_label') or _source_meta.get('source_label'), 'parent_session_id': row.get('parent_session_id'), 'parent_title': row.get('parent_title'), 'parent_source': row.get('parent_source'), @@ -5124,7 +5197,7 @@ def _load_cli_sessions_uncached( '_lineage_root_id': row.get('_lineage_root_id'), '_lineage_tip_id': row.get('_lineage_tip_id'), '_compression_segment_count': row.get('_compression_segment_count'), - 'is_cli_session': is_cli_session_row(row), + 'is_cli_session': is_cli_session_row({**row, **_source_meta}), }) if source_filter is not None: @@ -5202,6 +5275,72 @@ def _load_cli_sessions_uncached( except Exception: logger.debug("Cron project-chip second pass failed", exc_info=True) + # --- Second pass: fetch webhook sessions that may have been squeezed out + # of the default window. They stay hidden from the default sidebar but must + # remain addressable under the Webhooks project chip. + if webhook_project_limit is not False: + existing_sids = {s['session_id'] for s in cli_sessions} + try: + for row in read_importable_agent_session_rows( + db_path, + limit=webhook_project_limit, + log=logger, + exclude_sources=None, + include_sources=("webhook",), + ): + sid = row['id'] + if sid in existing_sids: + continue + _source = row['source'] or 'webhook' + if _source != 'webhook': + continue + _source_meta = normalize_agent_session_source(_source) + raw_ts = row['last_activity'] or row['started_at'] + _title = row['title'] + _sidecar_meta = _state_projection_sidecar_metadata(sid) + if _sidecar_meta.get('title'): + _title = _sidecar_meta['title'] + _archived = bool(_sidecar_meta.get('archived')) + _display_title = _title or 'Webhook Session' + cli_sessions.append({ + 'session_id': sid, + 'title': _display_title, + 'workspace': str(get_last_workspace()), + 'model': row['model'] or None, + 'message_count': row['message_count'] or row['actual_message_count'] or 0, + 'created_at': row['started_at'], + 'updated_at': raw_ts, + 'pinned': False, + 'archived': _archived, + 'project_id': _webhook_pid(), + 'profile': profile_value, + 'source_tag': 'webhook', + 'raw_source': row.get('raw_source') or _source_meta.get('raw_source'), + 'user_id': row.get('user_id'), + 'chat_id': row.get('chat_id') or row.get('origin_chat_id'), + 'chat_type': row.get('chat_type'), + 'thread_id': row.get('thread_id'), + 'session_key': row.get('session_key'), + 'platform': row.get('platform'), + 'session_source': row.get('session_source') or _source_meta.get('session_source'), + 'source_label': row.get('source_label') or _source_meta.get('source_label'), + 'parent_session_id': row.get('parent_session_id'), + 'parent_title': row.get('parent_title'), + 'parent_source': row.get('parent_source'), + 'relationship_type': row.get('relationship_type'), + '_parent_lineage_root_id': row.get('_parent_lineage_root_id'), + 'end_reason': row.get('end_reason'), + 'actual_message_count': row.get('actual_message_count'), + 'user_message_count': row.get('actual_user_message_count'), + '_lineage_root_id': row.get('_lineage_root_id'), + '_lineage_tip_id': row.get('_lineage_tip_id'), + '_compression_segment_count': row.get('_compression_segment_count'), + 'is_cli_session': is_cli_session_row({**row, **_source_meta}), + }) + existing_sids.add(sid) + except Exception: + logger.debug("Webhook project-chip second pass failed", exc_info=True) + return cli_sessions @@ -5247,6 +5386,7 @@ def get_cli_sessions(source_filter=None, *, all_profiles: bool = False) -> list: source_filter=source_filter, visible_session_limit=None, cron_project_limit=None, + webhook_project_limit=None, include_claude_code=(idx == 0), ) ) diff --git a/api/route_session_list_cache.py b/api/route_session_list_cache.py index 67978d72..82b42467 100644 --- a/api/route_session_list_cache.py +++ b/api/route_session_list_cache.py @@ -125,6 +125,7 @@ def _session_list_cache_key( include_archived: bool = False, exclude_hidden: bool = False, visible_only: bool = False, + show_webhook_sessions: bool = False, source_filter: str | None = None, sidebar_source: str | None = None, archived_limit: int | None = None, @@ -149,6 +150,7 @@ def _session_list_cache_key( bool(include_archived), bool(exclude_hidden), bool(visible_only), + bool(show_webhook_sessions), source_filter, sidebar_source, normalized_archived_limit, diff --git a/api/routes.py b/api/routes.py index 138ab59d..b0e84eac 100644 --- a/api/routes.py +++ b/api/routes.py @@ -1802,6 +1802,7 @@ def _build_session_list_cache_payload( include_archived: bool = False, exclude_hidden: bool = False, visible_only: bool = False, + show_webhook_sessions: bool = False, source_filter: str | None = None, sidebar_source: str | None = None, archived_limit: int | None = None, @@ -1859,6 +1860,7 @@ def _build_session_list_cache_payload( show_cli_sessions = bool(show_cli_sessions) show_previous_messaging_sessions = bool(show_previous_messaging_sessions) show_cron_sessions = bool(show_cron_sessions) + show_webhook_sessions = bool(show_webhook_sessions) webui_sessions = [_normalize_sidebar_source_flags(s) for s in webui_sessions] if show_cli_sessions: diag_stage("get_cli_sessions") @@ -1948,6 +1950,7 @@ def _build_session_list_cache_payload( cli, represented_webui_ids, show_cron_sessions=show_cron_sessions, + show_webhook_sessions=show_webhook_sessions, ) else: diag_stage("filter_webui_sessions") @@ -2081,6 +2084,7 @@ def _build_session_list_cache_payload( "show_cli_sessions": show_cli_sessions, "show_previous_messaging_sessions": show_previous_messaging_sessions, "show_cron_sessions": show_cron_sessions, + "show_webhook_sessions": show_webhook_sessions, }, } @@ -7389,16 +7393,22 @@ def _is_duplicate_webui_state_projection(session: dict, represented_webui_ids: s return bool(_session_lineage_ids(session) & represented_webui_ids) -def _dedupe_cli_sidebar_sessions_for_api(cli: list[dict], represented_webui_ids: set[str], *, show_cron_sessions: bool = False) -> list[dict]: - """Return CLI/state sidebar rows while preserving project-hidden cron rows. +def _dedupe_cli_sidebar_sessions_for_api( + cli: list[dict], + represented_webui_ids: set[str], + *, + show_cron_sessions: bool = False, + show_webhook_sessions: bool = False, +) -> list[dict]: + """Return state sidebar rows while preserving project-hidden background rows. - Agent-side cron sessions come from state.db rather than the WebUI session - store. They should stay hidden from the default sidebar, but project-assigned - messageful rows must remain in the `/api/sessions` payload with - `default_hidden` so the matching project chip can reveal them (#3134). + Agent-side cron and webhook sessions come from state.db rather than the WebUI + session store. They should stay hidden from the default sidebar, but + project-assigned messageful rows must remain in the `/api/sessions` payload + with `default_hidden` so the matching project chip can reveal them (#3134). """ from api.models import ( - _hide_from_default_sidebar as _cron_hide, + _hide_from_default_sidebar as _hide_background, _include_project_hidden_background_sidebar_sessions, ) @@ -7408,7 +7418,14 @@ def _dedupe_cli_sidebar_sessions_for_api(cli: list[dict], represented_webui_ids: and not _is_duplicate_webui_state_projection(s, represented_webui_ids) and is_cli_session_row_visible(s) ] - visible = [s for s in candidates if not _cron_hide(s, show_cron=show_cron_sessions)] + visible = [ + s for s in candidates + if not _hide_background( + s, + show_cron=show_cron_sessions, + show_webhook=show_webhook_sessions, + ) + ] return _include_project_hidden_background_sidebar_sessions(candidates, visible) @@ -10917,6 +10934,7 @@ def handle_get(handler, parsed) -> bool: settings.get("show_previous_messaging_sessions") ) show_cron_sessions = bool(settings.get("show_cron_sessions")) + show_webhook_sessions = bool(settings.get("show_webhook_sessions")) agent_session_source_filter = settings.get("agent_session_source_filter") active_profile = get_active_profile_name() all_profiles = _all_profiles_enabled(parsed) @@ -10938,6 +10956,7 @@ def handle_get(handler, parsed) -> bool: include_archived=include_archived, exclude_hidden=exclude_hidden, visible_only=True, + show_webhook_sessions=show_webhook_sessions, source_filter=agent_session_source_filter, sidebar_source=sidebar_source, archived_limit=archived_limit, @@ -10958,6 +10977,7 @@ def handle_get(handler, parsed) -> bool: include_archived=include_archived, exclude_hidden=exclude_hidden, visible_only=True, + show_webhook_sessions=show_webhook_sessions, source_filter=agent_session_source_filter, sidebar_source=sidebar_source, archived_limit=archived_limit, @@ -13140,6 +13160,7 @@ def handle_post(handler, parsed) -> bool: for k in ( "show_cli_sessions", "show_cron_sessions", + "show_webhook_sessions", "show_previous_messaging_sessions", ) ): diff --git a/static/i18n.js b/static/i18n.js index 433ec157..4b92d80f 100644 --- a/static/i18n.js +++ b/static/i18n.js @@ -827,6 +827,7 @@ const LOCALES = { cmd_reasoning: 'Toggle thinking visibility (show/hide), set effort level, or check current status', settings_label_external_sessions: 'Show non-WebUI sessions', settings_label_cron_sessions: 'Show cron sessions', + settings_label_webhook_sessions: 'Show webhook sessions', settings_label_previous_messaging_sessions: 'Show previous messaging sessions', settings_label_sync_insights: 'Sync to insights', settings_label_check_updates: 'Check for updates', @@ -1145,6 +1146,7 @@ const LOCALES = { settings_desc_auto_title_refresh: 'Automatically re-generates the session title based on the latest exchange, keeping it relevant as the conversation evolves. Requires an LLM title generation model to be configured.', settings_desc_external_sessions: 'Show conversations from CLI, Telegram, Discord, Slack, and other channels in the session list. Click to import and continue.', settings_desc_cron_sessions: 'Surface cron job output as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-frequency jobs can flood the sidebar.', + settings_desc_webhook_sessions: 'Surface webhook runs as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-volume routes can flood the sidebar.', settings_desc_previous_messaging_sessions: 'Show older Discord, Telegram, Slack, and Weixin sessions that were replaced by reset or compression.', settings_desc_sync_insights: 'Mirrors WebUI token usage to state.db so hermes /insights includes browser session data. Off by default.', settings_desc_check_updates: 'Show a banner when newer versions of the WebUI or Agent are available. Runs a background git fetch periodically.', @@ -2468,6 +2470,7 @@ const LOCALES = { cmd_reasoning: 'Mostra/nascondi ragionamento, imposta livello sforzo o controlla stato attuale', settings_label_external_sessions: 'Mostra sessioni non-WebUI', settings_label_cron_sessions: 'Show cron sessions', + settings_label_webhook_sessions: 'Show webhook sessions', settings_label_previous_messaging_sessions: 'Mostra sessioni di messaggistica precedenti', settings_label_sync_insights: 'Sincronizza con insights', settings_label_check_updates: 'Verifica aggiornamenti', @@ -2774,6 +2777,7 @@ const LOCALES = { settings_desc_auto_title_refresh: 'Rigenera automaticamente il titolo della sessione in base all\'ultimo scambio, mantenendolo pertinente mentre la conversazione evolve. Richiede un modello LLM per la generazione titoli.', settings_desc_external_sessions: 'Mostra conversazioni da CLI, Telegram, Discord, Slack e altri canali nella lista sessioni. Clicca per importare e continuare.', settings_desc_cron_sessions: 'Surface cron job output as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-frequency jobs can flood the sidebar.', + settings_desc_webhook_sessions: 'Surface webhook runs as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-volume routes can flood the sidebar.', settings_desc_previous_messaging_sessions: 'Mostra sessioni Discord, Telegram, Slack e Weixin più vecchie sostituite da reset o compressione.', settings_desc_sync_insights: 'Rispecchia l\'uso token WebUI su state.db così hermes /insights include i dati delle sessioni browser. Disattivato per impostazione predefinita.', settings_desc_check_updates: 'Mostra un banner quando sono disponibili versioni più recenti della WebUI o dell\'Agente. Esegue un git fetch in background periodicamente.', @@ -4100,6 +4104,7 @@ const LOCALES = { cmd_reasoning: '思考表示の切り替え (表示/非表示)、努力レベル設定、現在状態の確認', settings_label_external_sessions: '非WebUIセッションを表示', settings_label_cron_sessions: 'Cronセッションを表示', + settings_label_webhook_sessions: 'Webhookセッションを表示', settings_label_previous_messaging_sessions: '以前のメッセージングセッションを表示', settings_label_sync_insights: 'インサイトに同期', settings_label_check_updates: 'アップデートを確認', @@ -4411,6 +4416,7 @@ const LOCALES = { settings_desc_auto_title_refresh: '最新のやり取りに基づいてセッションタイトルを自動再生成し、会話の進行に合わせて適切に保ちます。LLM タイトル生成モデルの設定が必要です。', settings_desc_external_sessions: 'CLI、Telegram、Discord、Slack その他のチャネルからの会話をセッション一覧に表示します。クリックでインポートして続行できます。', settings_desc_cron_sessions: 'Cronジョブの出力をサイドバーの会話として表示します。WebUI以外のセッションが有効な場合のみ機能します。デフォルトはオフ。高頻度のジョブはサイドバーを溢れさせる可能性があります。', + settings_desc_webhook_sessions: 'Webhook実行をサイドバーの会話として表示します。WebUI以外のセッションが有効な場合のみ機能します。デフォルトはオフ。高頻度のルートはサイドバーを溢れさせる可能性があります。', settings_desc_previous_messaging_sessions: 'reset または compression によって置き換えられた以前の Discord、Telegram、Slack、Weixin セッションを表示します。', settings_desc_sync_insights: 'WebUI のトークン使用量を state.db にミラーし、hermes /insights にブラウザセッションのデータを含めます。デフォルトはオフ。', settings_desc_check_updates: 'WebUI または Agent の新しいバージョンが利用可能な時にバナーを表示します。バックグラウンドで定期的に git fetch を実行します。', @@ -5444,6 +5450,7 @@ const LOCALES = { cmd_reasoning: 'Toggle thinking visibility (show/hide), set effort level, or check current status', settings_label_external_sessions: 'Показывать внешние сеансы', settings_label_cron_sessions: 'Show cron sessions', + settings_label_webhook_sessions: 'Show webhook sessions', settings_label_previous_messaging_sessions: 'Показывать предыдущие сеансы обмена сообщениями', settings_label_sync_insights: 'Синхронизировать с Insights', settings_label_check_updates: 'Проверять обновления', @@ -5680,6 +5687,7 @@ const LOCALES = { settings_desc_auto_title_refresh: 'Автоматически переформулирует заголовок сессии на основе последнего обмена, чтобы он оставался актуальным по мере развития беседы. Требует настроенную модель генерации заголовков.', settings_desc_external_sessions: 'Показать беседы из CLI, Telegram, Discord, Slack и других каналов в списке сеансов. Нажмите для импорта и продолжения.', settings_desc_cron_sessions: 'Surface cron job output as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-frequency jobs can flood the sidebar.', + settings_desc_webhook_sessions: 'Surface webhook runs as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-volume routes can flood the sidebar.', settings_desc_previous_messaging_sessions: 'Показывать предыдущие сеансы Discord, Telegram, Slack и Weixin, замененные сбросом или сжатием.', settings_desc_sync_insights: 'Синхронизирует использование токенов WebUI в state.db, чтобы Hermes /insights включал данные браузерных сеансов. Выключено по умолчанию.', settings_desc_check_updates: 'Показывает баннер, когда доступны более новые версии WebUI или Agent. Периодически выполняет git fetch в фоне.', @@ -7003,6 +7011,7 @@ const LOCALES = { cmd_reasoning: 'Toggle thinking visibility (show/hide), set effort level, or check current status', settings_label_external_sessions: 'Mostrar sesiones externas', settings_label_cron_sessions: 'Show cron sessions', + settings_label_webhook_sessions: 'Show webhook sessions', settings_label_previous_messaging_sessions: 'Mostrar sesiones de mensajería anteriores', settings_label_sync_insights: 'Sincronizar con insights', settings_label_check_updates: 'Buscar actualizaciones', @@ -7250,6 +7259,7 @@ const LOCALES = { settings_desc_auto_title_refresh: 'Regenera automáticamente el título de la sesión basándose en el último intercambio, manteniéndolo relevante a medida que evoluciona la conversación. Requiere un modelo LLM de generación de títulos configurado.', settings_desc_external_sessions: 'Mostrar conversaciones de CLI, Telegram, Discord, Slack y otros canales en la lista de sesiones. Haz clic para importar y continuar.', settings_desc_cron_sessions: 'Surface cron job output as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-frequency jobs can flood the sidebar.', + settings_desc_webhook_sessions: 'Surface webhook runs as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-volume routes can flood the sidebar.', settings_desc_previous_messaging_sessions: 'Mostrar sesiones antiguas de Discord, Telegram, Slack y Weixin reemplazadas por reset o compresión.', settings_desc_sync_insights: 'Refleja el uso de tokens de la WebUI en state.db para que hermes /insights incluya datos de sesiones del navegador. Desactivado por defecto.', settings_desc_check_updates: 'Muestra un banner cuando haya versiones más nuevas de la WebUI o del Agent. Ejecuta periódicamente un git fetch en segundo plano.', @@ -8550,6 +8560,7 @@ const LOCALES = { cmd_reasoning: 'Toggle thinking visibility (show/hide), set effort level, or check current status', settings_label_external_sessions: 'Externe Sitzungen anzeigen', settings_label_cron_sessions: 'Show cron sessions', + settings_label_webhook_sessions: 'Show webhook sessions', settings_label_previous_messaging_sessions: 'Vorherige Messaging-Sitzungen anzeigen', settings_label_sync_insights: 'Mit Insights synchronisieren', settings_label_check_updates: 'Nach Updates suchen', @@ -8787,6 +8798,7 @@ const LOCALES = { settings_desc_auto_title_refresh: 'Generiert den Sitzungstitel automatisch anhand des letzten Austauschs neu und hält ihn so aktuell, während sich das Gespräch entwickelt. Erfordert ein konfiguriertes LLM-Titelgenerierungsmodell.', settings_desc_external_sessions: 'Zeigt Gespräche von CLI, Telegram, Discord, Slack und anderen Kanälen in der Sitzungsliste an. Klicken zum Importieren und Fortsetzen.', settings_desc_cron_sessions: 'Surface cron job output as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-frequency jobs can flood the sidebar.', + settings_desc_webhook_sessions: 'Surface webhook runs as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-volume routes can flood the sidebar.', settings_desc_previous_messaging_sessions: 'Zeigt ältere Discord-, Telegram-, Slack- und Weixin-Sitzungen, die durch Reset oder Compression ersetzt wurden.', settings_desc_sync_insights: 'Spiegelt den WebUI-Token-Verbrauch in die state.db, sodass hermes /insights Browser-Sitzungsdaten enthält. Standardmäßig aus.', settings_desc_check_updates: 'Zeigt ein Banner an, wenn neuere Versionen der WebUI oder des Agenten verfügbar sind. Führt regelmäßig einen Git-Fetch im Hintergrund aus.', @@ -10162,6 +10174,7 @@ const LOCALES = { cmd_reasoning: '切换思维可见性(显示/隐藏)、设置工作强度或查看当前状态', settings_label_external_sessions: '显示外部会话', settings_label_cron_sessions: 'Show cron sessions', + settings_label_webhook_sessions: 'Show webhook sessions', settings_label_previous_messaging_sessions: '显示以前的消息会话', settings_label_sync_insights: '同步到 insights', settings_label_check_updates: '检查更新', @@ -10484,6 +10497,7 @@ const LOCALES = { settings_desc_auto_title_refresh: '基于最新对话自动重新生成会话标题,使其随对话发展保持相关。需要配置 LLM 标题生成模型。', settings_desc_external_sessions: '在会话列表中显示来自 CLI、Telegram、Discord、Slack 等渠道的对话。点击可导入并继续对话。', settings_desc_cron_sessions: 'Surface cron job output as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-frequency jobs can flood the sidebar.', + settings_desc_webhook_sessions: 'Surface webhook runs as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-volume routes can flood the sidebar.', settings_desc_previous_messaging_sessions: '显示被 reset 或 compression 替换的较旧的 Discord、Telegram、Slack 和 Weixin 会话。', settings_desc_sync_insights: '将 WebUI token 使用情况同步到 state.db,使 hermes /insights 包含浏览器会话数据。默认关闭。', settings_desc_check_updates: '当有更新的 WebUI 或助手版本时显示横幅。会在后台定期执行 git fetch。', @@ -12011,6 +12025,7 @@ const LOCALES = { cmd_reasoning: '切換思考內容可見性(顯示/隱藏)、設定推理強度,或檢查目前狀態', settings_label_external_sessions: '顯示外部對話', settings_label_cron_sessions: 'Show cron sessions', + settings_label_webhook_sessions: 'Show webhook sessions', settings_label_previous_messaging_sessions: '顯示以前的訊息對話', settings_label_sync_insights: '同步至 insights', settings_label_check_updates: '檢查更新', @@ -12325,6 +12340,7 @@ const LOCALES = { settings_desc_auto_title_refresh: '根據最新對話自動重新產生對話標題,讓標題隨對話發展保持相關。需要設定 LLM 標題產生模型。', settings_desc_external_sessions: '在對話清單中顯示來自 CLI、Telegram、Discord、Slack 等管道的對話。點選即可匯入並繼續對話。', settings_desc_cron_sessions: 'Surface cron job output as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-frequency jobs can flood the sidebar.', + settings_desc_webhook_sessions: 'Surface webhook runs as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-volume routes can flood the sidebar.', settings_desc_previous_messaging_sessions: '顯示被 reset 或 compression 替換的較舊的 Discord、Telegram、Slack 和 Weixin 對話。', settings_desc_sync_insights: '將 WebUI token 用量鏡射到 state.db,讓 hermes /insights 納入瀏覽器工作階段資料。預設為關閉。', settings_desc_check_updates: '有較新版 WebUI 或 Agent 時顯示橫幅。系統會定期在背景執行 git fetch。', @@ -13538,6 +13554,7 @@ const LOCALES = { cmd_reasoning: 'Alternar visibilidade do pensamento (mostrar/ocultar)', settings_label_external_sessions: 'Mostrar sessões externas', settings_label_cron_sessions: 'Show cron sessions', + settings_label_webhook_sessions: 'Show webhook sessions', settings_label_previous_messaging_sessions: 'Mostrar sessões de mensagens anteriores', settings_label_sync_insights: 'Sincronizar para insights', settings_label_check_updates: 'Verificar atualizações', @@ -13778,6 +13795,7 @@ const LOCALES = { settings_desc_auto_title_refresh: 'Re-gera título da sessão baseado na última troca.', settings_desc_external_sessions: 'Mostrar conversas de CLI, Telegram, Discord, Slack e outros canais na lista de sessões. Clique para importar e continuar.', settings_desc_cron_sessions: 'Surface cron job output as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-frequency jobs can flood the sidebar.', + settings_desc_webhook_sessions: 'Surface webhook runs as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-volume routes can flood the sidebar.', settings_desc_previous_messaging_sessions: 'Mostrar sessões antigas de Discord, Telegram, Slack e Weixin substituídas por reset ou compressão.', settings_desc_sync_insights: 'Espelha uso de tokens para state.db.', settings_desc_check_updates: 'Mostrar banner quando versões mais novas estiverem disponíveis.', @@ -15069,6 +15087,7 @@ const LOCALES = { cmd_reasoning: 'Toggle thinking visibility (show/hide), set effort level, or check current status', settings_label_external_sessions: '외부 세션 표시', settings_label_cron_sessions: 'Show cron sessions', + settings_label_webhook_sessions: 'Show webhook sessions', settings_label_previous_messaging_sessions: '이전 메시징 세션 표시', settings_label_sync_insights: 'Insights에 동기화', settings_label_check_updates: '업데이트 확인', @@ -15308,6 +15327,7 @@ const LOCALES = { settings_desc_auto_title_refresh: '최신 대화를 바탕으로 세션 제목을 자동으로 다시 생성해 대화가 진행되어도 제목을 관련 있게 유지합니다. LLM 제목 생성 모델 설정이 필요합니다.', settings_desc_external_sessions: 'CLI, Telegram, Discord, Slack 및 기타 채널의 대화를 세션 목록에 표시합니다. 클릭하여 가져오고 계속하세요.', settings_desc_cron_sessions: 'Surface cron job output as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-frequency jobs can flood the sidebar.', + settings_desc_webhook_sessions: 'Surface webhook runs as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-volume routes can flood the sidebar.', settings_desc_previous_messaging_sessions: 'reset 또는 compression으로 교체된 이전 Discord, Telegram, Slack, Weixin 세션을 표시합니다.', settings_desc_sync_insights: 'WebUI 토큰 사용량을 state.db에 반영하여 hermes /insights에 브라우저 세션 데이터가 포함되도록 합니다. 기본값은 꺼짐입니다.', settings_desc_check_updates: 'WebUI 또는 Agent의 새 버전이 있으면 배너를 표시합니다. 백그라운드에서 주기적으로 git fetch를 실행합니다.', @@ -16713,6 +16733,7 @@ const LOCALES = { cmd_reasoning: 'Basculer la visibilité du raisonnement (afficher/masquer), définir le niveau d\'effort, ou vérifier l\'état actuel', settings_label_external_sessions: 'Afficher les sessions non-WebUI', settings_label_cron_sessions: 'Afficher les sessions cron', + settings_label_webhook_sessions: 'Afficher les sessions webhook', settings_label_previous_messaging_sessions: 'Afficher les sessions de messagerie précédentes', settings_label_sync_insights: 'Synchroniser avec les analyses', settings_label_check_updates: 'Vérifier les mises à jour', @@ -17020,6 +17041,7 @@ const LOCALES = { settings_desc_auto_title_refresh: 'Régénère automatiquement le titre de la session en fonction du dernier échange, le gardant pertinent à mesure que la conversation évolue. Nécessite qu\'un modèle de génération de titres LLM soit configuré.', settings_desc_external_sessions: 'Afficher les conversations de la CLI, Telegram, Discord, Slack et d\'autres canaux dans la liste des sessions. Cliquez pour importer et continuer.', settings_desc_cron_sessions: 'Afficher les sorties des tâches cron comme des conversations dans la barre latérale. Uniquement actif lorsque les sessions non-WebUI sont activées. Désactivé par défaut ; les tâches à haute fréquence peuvent inonder la barre latérale.', + settings_desc_webhook_sessions: 'Afficher les exécutions webhook comme des conversations dans la barre latérale. Uniquement actif lorsque les sessions non-WebUI sont activées. Désactivé par défaut ; les routes à volume élevé peuvent inonder la barre latérale.', settings_desc_previous_messaging_sessions: 'Afficher les anciennes sessions Discord, Telegram, Slack et Weixin qui ont été remplacées par une réinitialisation ou une compression.', settings_desc_sync_insights: 'Replique l\'utilisation des jetons de l\'interface Web vers state.db afin que hermes /insights inclue les données des sessions du navigateur. Désactivé par défaut.', settings_desc_check_updates: 'Afficher une bannière lorsque de nouvelles versions de l\'interface Web ou de l\'agent sont disponibles. Exécute périodiquement un git fetch en arrière-plan.', @@ -18313,6 +18335,7 @@ const LOCALES = { cmd_reasoning: 'Düşünme görünürlüğünü değiştirin (göster/gizle), çaba düzeyini ayarlayın veya mevcut durumu kontrol edin', settings_label_external_sessions: 'WebUI olmayan oturumları göster', settings_label_cron_sessions: 'Show cron sessions', + settings_label_webhook_sessions: 'Show webhook sessions', settings_label_previous_messaging_sessions: 'Önceki mesajlaşma oturumlarını göster', settings_label_sync_insights: 'Analizlerle senkronize edin', settings_label_check_updates: 'Güncellemeleri kontrol edin', @@ -18551,6 +18574,7 @@ const LOCALES = { settings_desc_auto_title_refresh: 'Oturum başlıklarını en son konuşmaya göre otomatik olarak yeniden oluşturarak konuşma ilerledikçe başlıkların alakalı kalmasını sağlar. LLM başlık oluşturma modeli yapılandırması gerektirir.', settings_desc_external_sessions: 'Oturum listesinde CLI, Telegram, Discord, Slack ve diğer kanallardan gelen konuşmaları gösterin. İçe aktarmak ve devam etmek için tıklayın.', settings_desc_cron_sessions: 'Surface cron job output as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-frequency jobs can flood the sidebar.', + settings_desc_webhook_sessions: 'Surface webhook runs as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-volume routes can flood the sidebar.', settings_desc_previous_messaging_sessions: 'Sıfırlama veya sıkıştırmayla değiştirilen eski Discord, Telegram, Slack ve Weixin oturumlarını gösterin.', settings_desc_sync_insights: 'WebUI belirteci kullanımını state.db\'ye yansıtır, böylece hermes /insights tarayıcı oturum verilerini içerir. Varsayılan olarak kapalıdır.', settings_desc_check_updates: 'WebUI veya Agent\'ın daha yeni sürümleri mevcut olduğunda bir banner gösterin. Periyodik olarak bir arka plan git getirme işlemi çalıştırır.', @@ -19959,6 +19983,7 @@ const LOCALES = { cmd_reasoning: 'Przełącz widoczność myślenia (pokaż/ukryj), ustaw poziom wysiłku lub sprawdź bieżący status', settings_label_external_sessions: 'Pokaż sesje inne niż WebUI', settings_label_cron_sessions: 'Pokaż sesje cron', + settings_label_webhook_sessions: 'Pokaż sesje webhooków', settings_label_previous_messaging_sessions: 'Pokaż poprzednie sesje komunikatorów', settings_label_sync_insights: 'Synchronizuj z Insights', settings_label_check_updates: 'Sprawdzaj aktualizacje', @@ -20267,6 +20292,7 @@ const LOCALES = { settings_desc_auto_title_refresh: 'Automatycznie generuje na nowo tytuł konwersacji na podstawie najnowszej wymiany, utrzymując go adekwatnym w miarę rozwoju rozmowy. Wymaga skonfigurowanego modelu LLM do generowania tytułów.', settings_desc_external_sessions: 'Pokaż konwersacje z CLI, Telegrama, Discorda, Slacka i innych kanałów na liście sesji. Kliknij, aby zaimportować i kontynuować.', settings_desc_cron_sessions: 'Wyświetlaj wyjście zadań cron jako konwersacje na pasku bocznym. Aktywne tylko wtedy, gdy włączone są sesje spoza WebUI. Domyślnie wyłączone; zadania o wysokiej częstotliwości mogą zalać pasek boczny.', + settings_desc_webhook_sessions: 'Wyświetlaj uruchomienia webhooków jako konwersacje na pasku bocznym. Aktywne tylko wtedy, gdy włączone są sesje spoza WebUI. Domyślnie wyłączone; trasy o dużym natężeniu mogą zalać pasek boczny.', settings_desc_previous_messaging_sessions: 'Pokaż starsze sesje z Discorda, Telegrama, Slacka i Weixin, które zostały zastąpione przez reset lub kompresję.', settings_desc_sync_insights: 'Odzwierciedla zużycie tokenów WebUI w state.db, dzięki czemu hermes /insights uwzględnia dane sesji przeglądarki. Domyślnie wyłączone.', settings_desc_check_updates: 'Pokaż baner, gdy dostępne są nowsze wersje WebUI lub Agenta. Okresowo uruchamia pobieranie git fetch w tle.', @@ -21433,6 +21459,7 @@ const LOCALES = { cmd_reasoning: 'Bật/tắt hiển thị suy nghĩ (show/hide), đặt mức effort hoặc kiểm tra trạng thái hiện tại', settings_label_external_sessions: 'Hiện phiên không phải WebUI', settings_label_cron_sessions: 'Hiện phiên cron', + settings_label_webhook_sessions: 'Hiện phiên webhook', settings_label_previous_messaging_sessions: 'Hiện các phiên nhắn tin trước đó', settings_label_sync_insights: 'Đồng bộ sang insights', settings_label_check_updates: 'Kiểm tra cập nhật', @@ -21738,6 +21765,7 @@ const LOCALES = { settings_desc_auto_title_refresh: 'Tự động tạo lại tiêu đề phiên dựa trên lượt trao đổi mới nhất, giúp tiêu đề luôn phù hợp khi cuộc trò chuyện phát triển. Yêu cầu có model tạo tiêu đề LLM được cấu hình.', settings_desc_external_sessions: 'Hiển thị các cuộc trò chuyện từ CLI, Telegram, Discord, Slack và các kênh khác trong danh sách phiên. Bấm để import và tiếp tục.', settings_desc_cron_sessions: 'Hiển thị output của cron job như các cuộc trò chuyện trong sidebar. Chỉ hoạt động khi bật phiên không phải WebUI. Mặc định tắt; job tần suất cao có thể làm sidebar bị ngập.', + settings_desc_webhook_sessions: 'Hiển thị các lần chạy webhook như các cuộc trò chuyện trong sidebar. Chỉ hoạt động khi bật phiên không phải WebUI. Mặc định tắt; route lưu lượng cao có thể làm sidebar bị ngập.', settings_desc_previous_messaging_sessions: 'Hiển thị các phiên Discord, Telegram, Slack và Weixin cũ đã bị thay thế bởi reset hoặc nén.', settings_desc_sync_insights: 'Đồng bộ token usage của WebUI sang state.db để hermes /insights bao gồm dữ liệu phiên trình duyệt. Mặc định tắt.', settings_desc_check_updates: 'Hiển thị banner khi có phiên bản mới của WebUI hoặc Agent. Định kỳ chạy git fetch nền.', diff --git a/static/index.html b/static/index.html index cbaf03bb..200081c3 100644 --- a/static/index.html +++ b/static/index.html @@ -1329,6 +1329,13 @@
Surface cron job output as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-frequency jobs can flood the sidebar.
+
+ +
Surface webhook runs as conversations in the sidebar. Only active when non-WebUI sessions are enabled. Defaults off; high-volume routes can flood the sidebar.
+