Skip to content

klavi-experts 0.2.0: ready for Experts 1.1 - #2

Merged
guernica0131 merged 3 commits into
mainfrom
release/1.1-ready
Oct 31, 2026
Merged

guernica0131 merged 3 commits into
mainfrom
release/1.1-ready

Conversation

@guernica0131

Copy link
Copy Markdown
Contributor

Release PR for 0.2.0. Folds in #1 (security and conduct contacts at klv.ai), which is in this branch, so merging this marks it merged.

CI was failing

pytest -q died with an INTERNALERROR on every Python version before a test ran: pytest-asyncio 0.24+ warns when asyncio_default_fixture_loop_scope is unset, and filterwarnings = ["error"] made that fatal. Set explicitly. The workflows also move to the Node 24 majors of checkout and setup-python.

The live job has never actually run: there is no EXPERTS_TEST_KEY secret, so it skips and reports success.

Knowledge never worked

Every call except list_collections was against the wrong field or route, in 0.1 against 1.0.49 as much as against 1.1:

Call 0.1 0.2
upload file + collection_uid → 422 files + collection on /documents/job-queue-upload; returns the UploadJob
wait_for_processing polled a document row that has no "indexed" field → always timed out polls the job; returns an UploadStatus (truthy when searchable; per-file uid or error)
search conversation-context route, wrong body → 422 /similarity_search/; returns SearchHit passages
list_documents collection_uid ignored; names/types empty collection, and doc_name/doc_type/summary mapped

New: upload_status(), delete_document(), list_documents(skip=, search=).

1.1 behaviour

  • Read-only licence window: LicenseReadOnlyError (subclass of LicenseError, read_only=True) for license_expired_readonly. Before, it came through as a plain permission error.
  • Refused experts: /chat now 403s an expert the caller may not use. Raised as ExpertNotAvailableError (its {"detail": {...}} body used to read as "Request failed with status 403"). send() settles the placeholder, so the conversation does not show it typing forever.
  • Guest visibility also requires no org-profile scope (Expert.scope_uids), matching what minting a session refuses.
  • Mesh: QueuedEvent while a busy member's model has the request in line; served_by, mesh_fallback, mesh_unavailable and model on the result; stream_timeout client option.
  • data_artifacts, generated_images; split_uid, start_ms, end_ms on source documents.

Fixes

  • A failed streamed request (a refused chat turn, an upload) crashed with httpx.ResponseNotRead instead of raising the server's error. The unit tests' mocked responses were pre-read, so they never saw it.
  • A timeout or dropped connection mid-answer raises StreamError, not httpx's own error.
  • The knowledge service's 401 "insufficient permissions" is a permission error, not an auth error.
  • cancel() returns whether the server stopped anything.

Breaking (0.x minor)

  • upload() returns UploadJob, not KnowledgeDocument.
  • wait_for_processing() takes the job and returns UploadStatus. Its truthiness keeps if wait_for_processing(...): working.
  • search() returns SearchHits.

None of the three worked before.

Spec

spec/openapi.json is regenerated at 1.1.0. It adds the knowledge routes the SDK now calls and the 1.1 errors. The generator change is klv-ai/experts-knowledge sdk/openapi-1.1, and that file is byte-identical to this one.

Tested

  • ruff, mypy strict, 100 unit tests. New tests/test_knowledge.py uses payloads copied from a 1.1 install.
  • pytest tests/live: 10 passed against a Proxmox VM on 1.1.0-rc.127 (gateway rc.37, conversations rc.30, embedding rc.23). That includes a new upload → index → search → delete round trip.
  • Not covered live: the read-only licence window, expert_not_available (the test key is an admin) and mesh events. Those are unit-tested from the services' code.

After merge

Tag v0.2.0 on main to publish to PyPI (release.yml checks the tag against both version strings).

Adam Smith added 3 commits October 30, 2026 09:52
klavi.ai is another company's domain: reports sent to security@klavi.ai or conduct@klavi.ai would have gone to them. security@klv.ai is the contact security.txt already publishes. Docs only, no release.
pytest-asyncio 0.24+ warns when asyncio_default_fixture_loop_scope is unset,
and filterwarnings = error turned that warning into an INTERNALERROR before a
single test ran, on every Python version. Also moves the workflows to the
Node 24 majors of checkout and setup-python.

Also carries the version bump to 0.2.0.
Knowledge works. The 0.1 upload sent `file` and `collection_uid` (the
server reads `files` and `collection`: a 422), waited by polling a document
row that never says it is indexed, and searched a conversation-context route
with the wrong body (a 422). Measured against a 1.1 install, and the same at
1.0.49:
- upload() answers with the indexing job (UploadJob), on the non-deprecated
  /documents/job-queue-upload.
- wait_for_processing(job) polls the job and returns an UploadStatus: truthy
  when every file is searchable, with each file's document uid or error.
- search() is /similarity_search/ and returns SearchHit passages.
- list_documents filters by `collection` and maps doc_name/doc_type/summary.
- New: upload_status(), delete_document(), list_documents(skip, search).

1.1 behaviour:
- LicenseReadOnlyError (a LicenseError, read_only=True) for the 30-day
  read-only window's `license_expired_readonly`.
- ExpertNotAvailableError for /chat's 403 expert_not_available, read from
  its {"detail": {...}} body; send() settles the placeholder so it does not
  type forever.
- guest_visible also requires no org-profile scope (Expert.scope_uids).
- Mesh: a `queued` event while a busy member's model has the request in
  line; served_by, mesh_fallback, mesh_unavailable and model on the result.
- data_artifacts and generated_images on the result; split_uid and
  start_ms/end_ms on source documents.

Fixes:
- A failed streamed request (a refused chat turn, an upload) crashed with
  httpx.ResponseNotRead before reporting the server's error.
- A timeout or dropped connection mid-answer is a StreamError, not httpx's.
- The knowledge service's 401 "insufficient permissions" is a permission
  error, not an auth error.
- cancel() returns whether the server stopped anything.
- stream_timeout is a client option (a mesh turn can wait in line).

The vendored spec is regenerated at 1.1.0, with the knowledge routes added.
Live suite (now with an upload, index, search, delete round trip) passes
against 1.1.0-rc.127.
@guernica0131
guernica0131 merged commit 0367264 into main Oct 31, 2026
5 checks passed
@guernica0131
guernica0131 deleted the release/1.1-ready branch October 31, 2026 01:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant