Skip to content

polis-cli: conversation list reads the current conversations API - #3059

Merged
colinmegill merged 1 commit into
edgefrom
cli-conversation-list
Oct 15, 2026
Merged

colinmegill merged 1 commit into
edgefrom
cli-conversation-list

Conversation

@colinmegill

Copy link
Copy Markdown
Member

Observable changes

  1. polis conversation list works against the current API. Before: every signed-in run ended with capability_unavailable (exit 8, "The server does not support owner-only paginated listing"). After: it lists the signed-in account's own conversations, newest created first.
  2. polis conversations list (plural) is accepted as a visible alias of the conversation group; command paths, schema and help output are unchanged.
  3. Output shape (--json, data): {"scope":"owner","conversations":[...rows as the API returns them...],"pagination":{"limit":N,"server_rows":N,"returned":N,"truncated":bool}}. server_rows is the number of rows the API returned; returned is the number kept after the owner filter; truncated is true when the API returned --limit rows (raise --limit to read more). The earlier offset / next_offset / has_more fields never shipped from any server.
  4. Flags: --offset is removed (the API has no offset; it is now a usage error, exit 2). --limit accepts 1–9999 (was 1–500), the API's own bound. --mine, --recent, --active, --draft, --search are unchanged in name; --search is applied by the CLI to the rows read (literal, case-insensitive topic substring), since the API has no search parameter.
  5. Errors: an answer that is not an array of rows carrying a boolean is_owner is refused as invalid_response (exit 1), never shown as a list. Sign-in errors keep their mapping (auth_required 3, auth_invalid 3).

No server change. No schema change. No route on the participation path is touched.

Cause

polis-cli/crates/polis/src/main.rs sent GET /api/v3/conversations?mine=true&limit=…&offset=…[&search=…] and then required {scope:"owner", conversations:[…], pagination:{…}}, otherwise failing with capability_unavailable. The server route (server/app.ts, GET /api/v3/conversations, handled by getConversations in server/src/routes/conversations.ts) reads only limit, is_active, is_draft, conversation_id, context, xid and include_all_conversations_i_am_in, ignores the rest, and answers res.status(200).json(data) with a plain array of the conversations the account owns or shares a site with, each row carrying the server-set is_owner. The CLI's expected object shape exists on no deployed server, so the command could never succeed.

Fix

CLI only. The command sends the parameters the API reads, keeps rows whose is_owner is true, applies --search locally, and reports what it read honestly (server_rows vs returned, truncated). Help text and README describe the API's actual contract (array, no offset/cursor/owner filter/search).

Tests

  • scripts/test-polis-cli.sh (the CI entry point: cargo fmt --check, cargo clippy -D warnings, cargo test --workspace): pass, 226 tests (tests/cli.rs 39, including the request-shape and response-parsing tests for conversation list: query string sent, bearer header, owner filter, truncation, filters, literal search, unrecognized shapes, --offset refused, plural alias).
  • End to end on a local compose stack (OIDC simulator, Postgres, DynamoDB, server on the branch): browser PKCE sign-in through the simulator as admin@polis.test and a second account placed on the same site; conversations created through the CLI; 18/18 checks pass: owner-only rows equal a SQL oracle of conversations.owner, the other account's site-shared row (present in the raw API array) is dropped, plural alias, --limit, --draft, --search (literal %/_), --active false after conversation close, --offset refused, no-credential and invalid-token errors.
  • The CLI's other read commands were run against the same stack with the same sign-in: all succeed (account view, conversation view/stats/share, statement list/view, vote list, moderate list, participant status/list/xid list/export/xid export/locations/highlight list, metadata question/answer list, context list, math view, topic list/hierarchy/proximity/stats, report list/create/view/stats/topics/statements list/export, delphi status/results/narrative view/visualization view, collective list, plan view, api) except participant group-members, which reports membership_unavailable because the stack runs no math service (the route answers 304 with no math; documented behaviour, unrelated to this change).

🤖 Generated with Claude Code

https://claude.ai/code/session_018NVGBuYCk4EZmiz4csUv9s

`polis conversation list` sent `mine`, `offset` and `search` to
GET /api/v3/conversations and required an owner-paginated object in
return; the API ignores those parameters and answers with an array,
so every signed-in run ended with capability_unavailable (exit 8).

The command now sends only what the API reads (limit, is_active,
is_draft), keeps the rows whose server-set is_owner is true, applies
--search as a literal case-insensitive topic match to the rows read,
and reports pagination as limit / server_rows / returned / truncated.
--offset is removed (the API has none); --limit accepts 1-9999 as the
API does. An answer that is not an array of rows with a boolean
is_owner is refused as invalid_response. `polis conversations list`
(plural) is accepted as an alias of the canonical group.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018NVGBuYCk4EZmiz4csUv9s
@colinmegill
colinmegill merged commit 0b9c529 into edge Oct 15, 2026
18 checks passed
@colinmegill
colinmegill deleted the cli-conversation-list branch October 15, 2026 07:32
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