278 files

This commit is contained in:
Home Assistant Version Control
2026-09-13 20:38:58 +00:00
parent d7a0a08372
commit 1b4f5f68c6
278 changed files with 36892 additions and 7150 deletions
@@ -25,8 +25,10 @@ from ..const import (
DOMAIN,
MAX_ID_LENGTH,
MAX_NAME_LENGTH,
MAX_TEXT_LENGTH,
MAX_URL_LENGTH,
)
from ..helpers.aggregate import object_name
from ..helpers.permissions import require_write
from ..helpers.search_match import query_tokens, score_fields, snippet
from . import _get_object_entries, _load_object_entry, object_id_for_entry
@@ -111,6 +113,7 @@ async def ws_documents_storage(
vol.Required("url"): vol.All(str, vol.Length(min=1, max=MAX_URL_LENGTH)),
vol.Optional("title"): vol.Any(vol.All(str, vol.Length(max=MAX_NAME_LENGTH)), None),
vol.Optional("tags"): _TAGS_SCHEMA,
vol.Optional("description"): vol.Any(vol.All(str, vol.Length(max=MAX_TEXT_LENGTH)), None),
}
)
@require_write
@@ -139,6 +142,7 @@ async def ws_documents_add_link(
url=url,
title=title.strip() if isinstance(title, str) and title.strip() else None,
tags=msg.get("tags"),
description=msg.get("description"),
)
connection.send_result(msg["id"], doc)
@@ -153,6 +157,8 @@ async def ws_documents_add_link(
vol.Optional("task_pages"): _TASK_PAGES_SCHEMA,
# Spare-part links (v2.26) — same shape/cap as task links.
vol.Optional("part_ids"): _TASK_IDS_SCHEMA,
# #164: a free-text description ('' clears).
vol.Optional("description"): vol.All(str, vol.Length(max=MAX_TEXT_LENGTH)),
}
)
@require_write
@@ -175,6 +181,7 @@ async def ws_documents_update(
task_ids=msg.get("task_ids"),
task_pages=msg.get("task_pages"),
part_ids=msg.get("part_ids"),
description=msg.get("description"),
)
if not ok:
connection.send_error(msg["id"], "not_found", "Document not found")
@@ -195,19 +202,24 @@ async def ws_documents_delete(
connection: websocket_api.ActiveConnection,
msg: dict[str, Any],
) -> None:
"""Remove a document. Frees blob bytes only when the last reference goes."""
"""Remove a document. Frees blob bytes only when the last reference goes.
History entries' completion photos and parts' ``doc_id`` that pointed at
it are cleared too (they used to dangle)."""
from ..helpers.documents import async_forget_doc_ids
store = _get_store(hass)
if store.get(msg["doc_id"]) is None:
connection.send_error(msg["id"], "not_found", "Document not found")
return
freed = await store.async_remove(msg["doc_id"])
await async_forget_doc_ids(hass, {msg["doc_id"]})
connection.send_result(msg["id"], {"success": True, "bytes_freed": freed})
_SEARCH_MAX_RESULTS = 50
#: Field weights for the tolerant matcher — the title is what people remember,
#: the file name and tags come next, a URL or MIME rarely.
_DOC_FIELD_WEIGHTS = (("title", 3), ("filename", 2), ("url", 1), ("mime", 1))
_DOC_FIELD_WEIGHTS = (("title", 3), ("filename", 2), ("description", 2), ("url", 1), ("mime", 1))
def _object_map(hass: HomeAssistant) -> dict[str, tuple[str, str]]:
@@ -217,7 +229,7 @@ def _object_map(hass: HomeAssistant) -> dict[str, tuple[str, str]]:
obj = entry.data.get(CONF_OBJECT, {})
oid = obj.get("id")
if isinstance(oid, str) and oid:
obj_map[oid] = (entry.entry_id, obj.get("name", ""))
obj_map[oid] = (entry.entry_id, object_name(entry))
return obj_map
@@ -233,6 +245,7 @@ def _doc_hit(did: str, doc: dict[str, Any], obj_map: dict[str, tuple[str, str]])
"url": doc.get("url"),
"size": doc.get("size"),
"tags": doc.get("tags") or [],
"description": doc.get("description") or "",
}