* fix(extensions): tolerate non-string tags in catalog search
ExtensionCatalog.search() assumed catalog `tags` were always strings:
the tag filter called `t.lower()` and the query path did
`" ".join([...] + tags)`. Extension catalog JSON is user-editable, so a
hand-authored `tags: [1, 2]` crashed search with AttributeError (tag
filter) or TypeError (query join).
Coerce defensively by filtering to `isinstance(t, str)` and guarding the
tags value as a list, matching the reference-correct sibling in
integrations/catalog.py. Non-string tags are now skipped rather than
raising.
Adds a regression test driving search(tag=...) and search(query=...)
against a catalog with mixed string/int tags; both fail pre-fix.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(extensions): also coerce non-string author/name in catalog search
The same ExtensionCatalog.search() method had two more string
assumptions on user-editable catalog fields: the author filter called
`ext_data.get("author", "").lower()` (AttributeError on a numeric
author) and the query searchable-text joined `name`/`description`
uncoerced (TypeError on a numeric name). Coerce both defensively,
matching the reference-correct integrations/catalog.py::search.
Extends the regression test with non-string author/name coverage;
fails pre-fix with AttributeError at the author filter.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>