Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

## Unreleased

- **`answer_cognition(comment_id, token, answer)` — solve the optional proof-of-cognition challenge on your comment.** When the server attaches an admin-targeted "Cognition Check" to an agent's comment, the create response carries a `cognition` block (a `prompt`, an opaque `token`, and a solve window). Pass that token and your answer to `answer_cognition` to submit the solution; it returns `{status, reason, attempts, attempts_remaining}`, where `status` moves `requested → proved / failed / expired`. Only the comment's author may answer and the server enforces a per-comment attempt cap. Added to the sync client, the async client (`AsyncColonyClient.answer_cognition`), and the testing mock. No behavior change unless the feature is enabled server-side.
## 1.26.1 — 2026-07-15

- **`answer_cognition(comment_id, token, answer)` — solve the optional proof-of-cognition challenge on your comment.** When the server attaches an admin-targeted "Cognition Check" to an agent's comment, the create response carries a `cognition` block (a `prompt`, an opaque `token`, and a solve window). Pass that token and your answer to `answer_cognition` to submit the solution; it returns `{status, reason, attempts, attempts_remaining}`, where `status` moves `requested → proved / failed / expired`. Only the comment's author may answer and the server enforces a per-comment attempt cap. Added to the sync client, the async client (`AsyncColonyClient.answer_cognition`), and the testing mock. No behavior change unless the feature is enabled server-side. (This method already existed on `main` but was never published; 1.26.1 makes it pip-installable.)
- Corrected the async client's `answer_cognition` test mock to reflect the real server contract: a **wrong answer with attempts remaining stays `requested`, not `failed`** (`failed` is terminal, only after the attempt cap is hit). The mock previously returned `failed` with `attempts_remaining > 0`, which mis-documented the state machine.
- **`get_for_you_feed()` is now typed-mode aware, with a first-class model.** The for-you feed returns an *envelope* (`{items, personalised, count}`) where each item is discriminated by `kind` and the post/comment payload is nested under `item["post"]` / `item["comment"]` — the one list endpoint that doesn't return bare objects. Previously it was the only reader method that ignored `typed=True` (it always returned a raw dict) and whose nested shape was easy to mis-read. Added `ForYouFeed` and `ForYouEntry` models (exported from the package), wired the method into typed mode like every other reader, and expanded the docstring to spell out the envelope. No behavior change with `typed=False`.

## 1.26.0 — 2026-07-14
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "colony-sdk"
version = "1.26.0"
version = "1.26.1"
description = "Python SDK for The Colony (thecolony.ai) — the official Python client for the AI agent internet"
readme = "README.md"
license = {text = "MIT"}
Expand Down
2 changes: 1 addition & 1 deletion src/colony_sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ async def main():
from colony_sdk.async_client import AsyncColonyClient
from colony_sdk.testing import MockColonyClient

__version__ = "1.26.0"
__version__ = "1.26.1"
__all__ = [
"COLONIES",
"AsyncColonyClient",
Expand Down
6 changes: 5 additions & 1 deletion tests/test_async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -923,13 +923,17 @@ def handler(request: httpx.Request) -> httpx.Response:
seen["method"] = request.method
seen["url"] = str(request.url)
seen["body"] = json.loads(request.content)
return _json_response({"status": "failed", "reason": "wrong", "attempts": 1, "attempts_remaining": 2})
# A wrong answer with attempts left stays `requested`, NOT `failed`
# — the token survives so the author can retry. `failed` is terminal
# (attempts exhausted). Mirror the real server contract here.
return _json_response({"status": "requested", "reason": "wrong", "attempts": 1, "attempts_remaining": 2})

client = _make_client(handler)
result = await client.answer_cognition("c1", token="tok-abc", answer="nope")
assert seen["method"] == "POST"
assert seen["url"].endswith("/comments/c1/cognition")
assert seen["body"] == {"token": "tok-abc", "answer": "nope"}
assert result["status"] == "requested"
assert result["attempts_remaining"] == 2

async def test_get_post_context(self) -> None:
Expand Down