You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

253 lines
12 KiB

######################################################################
# @CCOSTAN - Follow Me on X
# For more info visit https://www.vcloudinfo.com/click-here
# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig
# -------------------------------------------------------------------
# OneNote Indexer Monitoring - Status and health sensors for Joanna
# Polls codex_appliance OneNote status and exposes trigger-ready health entities.
# -------------------------------------------------------------------
# Notes: Keep onenote indexer monitoring in this package (separate from bearclaw transport).
# Notes: last_status='never' is treated as success only when index health is confirmed.
# Notes: Only explicit last_status='error' is treated as failure; unknown/unavailable are neutral.
# Notes: HA->Joanna request includes trigger context so Telegram progress messages can identify origin.
# Notes: Creates/clears a Spook Repair issue and requests Joanna remediation on failures.
# Notes: Index health requires pages, chunks, no pending embeddings, and a healthy embedding worker.
# Notes: Recovery clear is polled so stale Repairs do not linger after the indexer recovers.
# Notes: Daily Joanna recap should be plain-English; only surface detailed index metrics when something materially changes or fails.
######################################################################
sensor:
- platform: rest
name: OneNote Indexer Status Payload
unique_id: onenote_indexer_status_payload
resource: !secret bearclaw_onenote_status_url
method: GET
headers:
x-codex-token: !secret bearclaw_token
scan_interval: 300
timeout: 20
value_template: >-
{% if value_json is mapping %}
{{ value_json.server_time | default(now().isoformat()) }}
{% else %}
unknown
{% endif %}
json_attributes:
- ok
- indexer
- embeddingWorker
template:
- sensor:
- name: OneNote Indexer Last Job Status
unique_id: onenote_indexer_last_job_status
icon: mdi:notebook-check
state: >-
{% set payload = state_attr('sensor.onenote_indexer_status_payload', 'indexer') or {} %}
{% set sync = payload.get('sync', {}) if payload is mapping else {} %}
{% set index = payload.get('index', {}) if payload is mapping else {} %}
{% set worker = state_attr('sensor.onenote_indexer_status_payload', 'embeddingWorker') or {} %}
{% set raw = (sync.get('last_status', '') | string | lower) %}
{% set pages = index.get('pages') | int(0) %}
{% set chunks = index.get('chunks') | int(0) %}
{% set pending = index.get('pending_embeddings') | int(999999) %}
{% set worker_status = worker.get('lastStatus', '') | string | lower %}
{% set worker_running = worker.get('running', false) | bool %}
{% set index_healthy = pages > 0 and chunks > 0 and pending == 0 and worker_status == 'ok' and not worker_running %}
{% if raw in ['ok', 'success'] or (raw == 'never' and index_healthy) %}
success
{% elif raw == 'running' %}
running
{% elif raw == 'error' %}
error
{% elif raw == 'never' %}
unknown
{% else %}
unknown
{% endif %}
attributes:
running: >-
{% set payload = state_attr('sensor.onenote_indexer_status_payload', 'indexer') or {} %}
{% set sync = payload.get('sync', {}) if payload is mapping else {} %}
{{ sync.get('running', false) | bool }}
last_run_id: >-
{% set payload = state_attr('sensor.onenote_indexer_status_payload', 'indexer') or {} %}
{% set sync = payload.get('sync', {}) if payload is mapping else {} %}
{{ sync.get('last_run_id') }}
last_started_at: >-
{% set payload = state_attr('sensor.onenote_indexer_status_payload', 'indexer') or {} %}
{% set sync = payload.get('sync', {}) if payload is mapping else {} %}
{{ sync.get('last_started_at') }}
last_finished_at: >-
{% set payload = state_attr('sensor.onenote_indexer_status_payload', 'indexer') or {} %}
{% set sync = payload.get('sync', {}) if payload is mapping else {} %}
{{ sync.get('last_finished_at') }}
last_error: >-
{% set payload = state_attr('sensor.onenote_indexer_status_payload', 'indexer') or {} %}
{% set sync = payload.get('sync', {}) if payload is mapping else {} %}
{{ sync.get('last_error') }}
pending_embeddings: >-
{% set payload = state_attr('sensor.onenote_indexer_status_payload', 'indexer') or {} %}
{% set index = payload.get('index', {}) if payload is mapping else {} %}
{{ index.get('pending_embeddings') }}
pages: >-
{% set payload = state_attr('sensor.onenote_indexer_status_payload', 'indexer') or {} %}
{% set index = payload.get('index', {}) if payload is mapping else {} %}
{{ index.get('pages') }}
chunks: >-
{% set payload = state_attr('sensor.onenote_indexer_status_payload', 'indexer') or {} %}
{% set index = payload.get('index', {}) if payload is mapping else {} %}
{{ index.get('chunks') }}
embedding_worker_status: >-
{% set worker = state_attr('sensor.onenote_indexer_status_payload', 'embeddingWorker') or {} %}
{{ worker.get('lastStatus') }}
embedding_worker_last_run_at: >-
{% set worker = state_attr('sensor.onenote_indexer_status_payload', 'embeddingWorker') or {} %}
{{ worker.get('lastRunAt') }}
last_metrics: >-
{% set payload = state_attr('sensor.onenote_indexer_status_payload', 'indexer') or {} %}
{% set sync = payload.get('sync', {}) if payload is mapping else {} %}
{{ sync.get('last_metrics', {}) }}
- binary_sensor:
- name: OneNote Indexer Last Job Successful
unique_id: onenote_indexer_last_job_successful
state: >-
{{ states('sensor.onenote_indexer_last_job_status') in ['success', 'running'] }}
icon: >-
{% if is_state('binary_sensor.onenote_indexer_last_job_successful', 'on') %}
mdi:check-circle
{% else %}
mdi:alert-circle
{% endif %}
- name: OneNote Indexer Index Healthy
unique_id: onenote_indexer_index_healthy
state: >-
{% set payload = state_attr('sensor.onenote_indexer_status_payload', 'indexer') or {} %}
{% set index = payload.get('index', {}) if payload is mapping else {} %}
{% set worker = state_attr('sensor.onenote_indexer_status_payload', 'embeddingWorker') or {} %}
{% set pages = index.get('pages') | int(0) %}
{% set chunks = index.get('chunks') | int(0) %}
{% set pending = index.get('pending_embeddings') | int(999999) %}
{% set worker_status = worker.get('lastStatus', '') | string | lower %}
{% set worker_running = worker.get('running', false) | bool %}
{{ pages > 0 and chunks > 0 and pending == 0 and worker_status == 'ok' and not worker_running }}
icon: >-
{% if is_state('binary_sensor.onenote_indexer_index_healthy', 'on') %}
mdi:notebook-check
{% else %}
mdi:notebook-remove
{% endif %}
attributes:
pages: >-
{% set payload = state_attr('sensor.onenote_indexer_status_payload', 'indexer') or {} %}
{% set index = payload.get('index', {}) if payload is mapping else {} %}
{{ index.get('pages') }}
chunks: >-
{% set payload = state_attr('sensor.onenote_indexer_status_payload', 'indexer') or {} %}
{% set index = payload.get('index', {}) if payload is mapping else {} %}
{{ index.get('chunks') }}
pending_embeddings: >-
{% set payload = state_attr('sensor.onenote_indexer_status_payload', 'indexer') or {} %}
{% set index = payload.get('index', {}) if payload is mapping else {} %}
{{ index.get('pending_embeddings') }}
embedding_worker_status: >-
{% set worker = state_attr('sensor.onenote_indexer_status_payload', 'embeddingWorker') or {} %}
{{ worker.get('lastStatus') }}
embedding_worker_last_run_at: >-
{% set worker = state_attr('sensor.onenote_indexer_status_payload', 'embeddingWorker') or {} %}
{{ worker.get('lastRunAt') }}
- name: OneNote Indexer Job Failed
unique_id: onenote_indexer_job_failed
device_class: problem
state: >-
{{ is_state('sensor.onenote_indexer_last_job_status', 'error') }}
automation:
- id: onenote_indexer_failure_open_repair
alias: OneNote Indexer - Open Repair On Failure
description: Open a Spook Repair issue and ask Joanna to troubleshoot when indexer status is failed.
mode: single
trigger:
- platform: state
entity_id: binary_sensor.onenote_indexer_job_failed
to: "on"
for: "00:03:00"
action:
- variables:
last_status: "{{ states('sensor.onenote_indexer_last_job_status') }}"
run_id: "{{ state_attr('sensor.onenote_indexer_last_job_status', 'last_run_id') | default('n/a') }}"
last_error: "{{ state_attr('sensor.onenote_indexer_last_job_status', 'last_error') | default('n/a') }}"
last_metrics: "{{ state_attr('sensor.onenote_indexer_last_job_status', 'last_metrics') | default({}) }}"
issue_id: "onenote_indexer_job_failed"
trigger_context: "HA automation onenote_indexer_failure_open_repair (OneNote Indexer - Open Repair On Failure)"
- service: repairs.create
data:
issue_id: "{{ issue_id }}"
title: "OneNote indexer job failed"
severity: "warning"
persistent: true
description: >-
Home Assistant detected OneNote indexer failure.
last_status: {{ last_status }}
last_run_id: {{ run_id }}
last_error: {{ last_error }}
last_metrics: {{ last_metrics }}
- service: script.send_to_logbook
data:
topic: "ONENOTE"
message: >-
OneNote indexer failed (run {{ run_id }}). Spook repair opened and Joanna remediation requested.
- service: script.joanna_dispatch
data:
trigger_context: "{{ trigger_context }}"
source: "home_assistant_automation.onenote_indexer_failure_open_repair"
summary: "OneNote indexer job reported failure"
entity_ids:
- "binary_sensor.onenote_indexer_job_failed"
- "sensor.onenote_indexer_last_job_status"
diagnostics: >-
issue_id={{ issue_id }},
last_status={{ last_status }},
last_run_id={{ run_id }},
last_error={{ last_error }},
last_metrics={{ last_metrics }}
request: "Troubleshoot and resolve the indexer failure if possible."
- id: onenote_indexer_failure_clear_repair
alias: OneNote Indexer - Clear Repair On Recovery
description: Clear the Spook Repair issue when OneNote indexer and index health are confirmed healthy again.
mode: single
trigger:
- platform: state
entity_id: binary_sensor.onenote_indexer_job_failed
to: "off"
for: "00:02:00"
- platform: state
entity_id: binary_sensor.onenote_indexer_index_healthy
to: "on"
for: "00:02:00"
- platform: time_pattern
minutes: "20"
- platform: time_pattern
minutes: "50"
condition:
- condition: state
entity_id: binary_sensor.onenote_indexer_job_failed
state: "off"
- condition: state
entity_id: binary_sensor.onenote_indexer_index_healthy
state: "on"
action:
- service: repairs.remove
continue_on_error: true
data:
issue_id: "onenote_indexer_job_failed"
- service: script.send_to_logbook
data:
topic: "ONENOTE"
message: "OneNote indexer and index health are confirmed healthy. Spook repair cleared."

Powered by TurnKey Linux.