const COMMON_STATE_FIELDS = [ 'paused', 'armed', 'last_error', 'last_event_at', 'last_runtime_eval_at', 'last_published_at', 'last_publish_error', 'publish_count', 'last_sync_at', 'last_write_at', 'last_metrics_at', 'last_quote_outcomes_at', 'database_connectivity', 'source_error_count', 'last_source_error_at', 'last_bootstrap_at', ]; export function summarizeServiceSnapshotForSentinel(snapshot = {}) { return { service: snapshot.service, label: snapshot.label, base_url: snapshot.base_url, reachable: snapshot.reachable, state: summarizeServiceState(snapshot.service, snapshot.state), health: snapshot.health || null, error: snapshot.error || null, }; } export function summarizeServiceState(service, state) { if (!state || typeof state !== 'object') return state || null; switch (service) { case 'near-intents-ingest': return pickFields(state, ['service', 'namespace', 'pair_filter', 'ingest']); case 'market-reference-ingest': return pickFields(state, [ 'service', 'namespace', 'paused', 'kraken', 'coingecko', 'last_published_at', 'last_publish_error', 'publish_count', 'error_count', 'active_pair', ]); case 'inventory-sync': return { ...pickFields(state, ['service', 'namespace', 'account_id', 'paused', 'last_sync_at', 'last_error', 'publish_count']), last_snapshot: summarizeInventorySnapshot(state.last_snapshot), }; case 'liquidity-manager': return pickFields(state, [ 'service', 'namespace', 'account_id', 'paused', 'funding_observer_paused', 'withdrawals_frozen', 'deposit_addresses', 'supported_tokens_error', 'withdrawal_defaults', 'latest_funding_observation_at', 'last_refresh_at', 'last_error', ]); case 'history-writer': return pickFields(state, [ 'service', 'namespace', 'database_connectivity', 'last_write_at', 'last_alert_write_at', 'last_funding_observation_write_at', 'last_environment_status_write_at', 'last_environment_status_seen_at', 'last_environment_status_duplicate_at', 'last_metrics_at', 'last_quote_outcomes_at', 'latest_portfolio_metrics', 'latest_quote_outcomes', 'offsets', 'metrics_error', 'quote_outcomes_error', ]); case 'strategy-engine': return pickFields(state, [ 'service', 'namespace', 'paused', 'armed', 'last_error', 'latest_decision', 'latest_inventory_event', 'decision_count', 'command_count', 'reject_count', 'block_count', ]); case 'trade-executor': return pickFields(state, [ 'service', 'namespace', 'paused', 'armed', 'last_error', 'relay', 'verifier_salt_cache', 'executor_queue_delay', 'last_result', 'last_quote_status', 'submitted_count', 'salt_unavailable_reject_count', 'last_salt_unavailable_at', 'last_salt_unavailable_state', 'failed_count', 'blocked_count', ]); case 'operator-dashboard': return pickFields(state, [ 'service', 'namespace', 'source_error_count', 'last_source_error_at', 'last_bootstrap_at', 'source_errors', ]); default: return pickFields(state, COMMON_STATE_FIELDS); } } function summarizeInventorySnapshot(snapshot) { if (!snapshot || typeof snapshot !== 'object') return snapshot || null; return pickFields(snapshot, [ 'inventory_id', 'account_id', 'synced_at', 'spendable', 'pending_inbound', 'pending_outbound', 'reconciliation_status', ]); } function pickFields(source, fields) { const picked = {}; for (const field of fields) { if (source[field] !== undefined) picked[field] = source[field]; } return picked; }