bump keenable to 0.1.2 (search results had no text) - #2899
Open
ilya-bogin-keenable wants to merge 3 commits into
Open
bump keenable to 0.1.2 (search results had no text)#2899ilya-bogin-keenable wants to merge 3 commits into
ilya-bogin-keenable wants to merge 3 commits into
Conversation
The Keenable API returns both `description` and `snippet` on every result. `description` is frequently empty and `snippet` carries the page text, so the digest the model reads listed titles and URLs with no text. Verified against the live keyless endpoint: 10/10 results had an empty `description` and a `snippet` of 2000-2600 characters. Reads `snippet` first with a `description` fallback, whitespace-collapsed (raw page text arrives with newlines, which broke the digest layout) and capped at 500 characters. The untouched results still go out through `create_json_message`, so the workflow `json` output is unchanged.
The Marketplace pre-check tightened since 0.1.0 was reviewed. Repackaged with: - manifest.yaml gains the now-required `repo` and `contact` fields. - README gains a Connection requirements section (outbound HTTPS to api.keenable.ai only, port 443, no inbound, no local network; the fetch tool refuses private/internal addresses before issuing a request). - requirements.txt pins an upper bound on requests. All toolkit validators now pass locally against the unpacked package: manifest metadata, PR body, sensitive capability disclosure, package contents, secrets, binaries, README metadata, dependencies, access domains, prohibited financial activity, python safety. 48 tests pass.
The previous push targeted 0.1.1, which the Marketplace already carries: it shipped 2026-06-23 via langgenius#2586 (SSRF-guard and API-key-redaction hardening), so the version check blocked it correctly. Rebuilt as 0.1.2 from the plugin's own source repository at the 0.1.1 tree, so that hardening is carried forward rather than reverted — the earlier package had been built from a copy that predated langgenius#2586. Verified inside the archive: version 0.1.2, tools/keenable_search.py reads snippet, utils/keenable_client.py still has the 0.1.1 _candidate_ips guard. All toolkit validators pass locally; 59 tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Plugin Submission
Bug-fix bump of the Keenable plugin,
0.1.1→0.1.2. Follow-up to #2582 and #2586.Plugin information
Submission type
What changed
Search results reached the model with no text.
The Keenable API returns both
descriptionandsnippeton every search result.descriptionis frequently empty andsnippetcarries the page text, but the tool built its digest fromdescription:Verified against the live keyless endpoint: 10/10 results came back with
len(description) == 0andlen(snippet)between 2000 and 2600. So the text message the model reads listed titles and URLs with nothing under them. This has been the case since 0.1.0 shipped on 2026-06-22.The fix reads
snippetfirst with adescriptionfallback. The text is whitespace-collapsed — raw page text arrives with newlines, which broke the digest's one-line-per-field layout — and capped at 500 characters, since Keenable returns whole pages where other search engines return a short snippet. The untouched results still go out throughcreate_json_message, so the workflowjsonoutput is unchanged.manifest.yamlalso gains the now-requiredrepoandcontactfields, which were not requirements when 0.1.1 was reviewed. The README gains a Connection requirements section andrequirements.txtgains an upper bound onrequests, both to clear pre-check warnings.Everything from 0.1.1 (the SSRF-guard and API-key-redaction hardening from #2586) is carried forward unchanged — the package was rebuilt from the plugin's source repository at the 0.1.1 tree, not from an older copy.
Risk level
Additive bug fix to an existing plugin. No new tools, no new credentials, no new network destinations, no change to the permission surface.
Required checks
.envfiles,.gitdirectories, virtual environments, caches, logs, or IDE files.PRIVACY.mdor a hosted privacy policy, andmanifest.yamlreferences it.Security and privacy notes
Arbitrary URL fetching — yes, and it is the point of one of the two tools.
keenable_fetchtakes a user- or agent-supplied URL and retrieves that page as markdown through Keenable's/v1/fetchendpoint.keenable_searchsends a query string. Both are outbound HTTPS calls toapi.keenable.aiand nowhere else; the base URL is not agent-settable.The fetch path is SSRF-guarded before any request leaves the plugin: non-
http(s)schemes and private or internal hosts (loopback, RFC1918, link-local including169.254.169.254, reserved, multicast) are refused. There is a test for exactly that (test_fetch_rejects_unsafe_urls_without_calling_api), which asserts the API is never called for those inputs.No command execution, no code execution, no SQL, no SSH/SFTP, no browser automation, no local file operations, no proxying. No health, financial, biometric, or children's data is handled — the plugin sends a query or a URL and returns public web content. Credentials: one optional API key, and the plugin works with no key at all (keyless free tier). Data handling is documented in
PRIVACY.md.Local validation
Up from 57. Two cases were added for the
snippetfallback and for the whitespace collapse + cap, and the pre-existing fixture was corrected: it populateddescription, a shape no real response has, which is precisely why this bug passed review the first time.Package verified by unzipping it and reading the contents rather than trusting the build: 15 files,
version: 0.1.2, the shippedtools/keenable_search.pyreally does readsnippet, andutils/keenable_client.pystill carries the 0.1.1_candidate_ipsSSRF hardening.Reviewer notes
No migration needed and no breaking changes: the tool signature, parameters, credentials and JSON output shape are all unchanged. Only the text of the human/LLM-readable message differs — it now has content in it.