diff --git a/third_party/x/.cursor-plugin/plugin.json b/third_party/x/.cursor-plugin/plugin.json index e6e970ea0..05e6023de 100644 --- a/third_party/x/.cursor-plugin/plugin.json +++ b/third_party/x/.cursor-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "x", "displayName": "X", - "version": "2.6.3", + "version": "2.6.4", "minClientVersions": { "cursor": "3.13.0" }, diff --git a/third_party/x/CHANGELOG.md b/third_party/x/CHANGELOG.md index a93ea3a93..afd6b193c 100644 --- a/third_party/x/CHANGELOG.md +++ b/third_party/x/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to this plugin will be documented here. +## 2.6.4 — Exact unread messages, 1000-conversation inbox pages + +- List conversations with `get_chat_conversations` `max_results` 1000. +- To find the unread messages, page `get_chat_conversation_events` newest first, past empty pages that still have a `next_token`, and stop at the first event at or below `last_read_event_id`. Leave out the owner's own messages. +- `mark_chat_conversation_read` takes only `id` and always marks the whole conversation read. Marking a conversation unread does not set `unread`. + ## 2.6.3 — Built-in public reads, unread state, message requests, no congrats line - Built-in public reads need no X connection, credits check, or cost estimate. Grok Bot reads public posts, users, search, trends, and news on its own, and a missing `get_usage_credits` or `get_users_me` next to those reads is not an error. diff --git a/third_party/x/skills/x-api-mcp-guide/SKILL.md b/third_party/x/skills/x-api-mcp-guide/SKILL.md index dc9c2cb9a..6eeb385f8 100644 --- a/third_party/x/skills/x-api-mcp-guide/SKILL.md +++ b/third_party/x/skills/x-api-mcp-guide/SKILL.md @@ -394,7 +394,7 @@ MCP owns OAuth (`dm.read` / `dm.write`) and ciphertext. Local `chatxdk` + `xchat | `get_users_me` | Numeric `user_id` | | `get_users_public_key` | Self: `juicebox_config`, `public_key_version`, `public_key`, `signing_public_key`, `identity_public_key_signature` | | `get_users_public_keys` | Signing keys for every sender, all versions (up to 100 `ids` per call) | -| `get_chat_conversations` | Inbox (paginate) | +| `get_chat_conversations` | Inbox (paginate), `max_results` 1000 | | `get_chat_message_requests` | Pending requests, one `inbox_type` per call (`you_may_know` Priority, `low_quality` Hidden) | | `get_chat_message_request` | One request. Marks its messages delivered. Only when the owner asked to open it | | `accept_chat_message_request` | Accept a received request into the inbox. Owner must say to accept. A reply does not | @@ -403,7 +403,7 @@ MCP owns OAuth (`dm.read` / `dm.write`) and ciphertext. Local `chatxdk` + `xchat | `send_chat_message` | Pre-encrypted `message_id` + `encoded_message_create_event` (+ signature) | | `add_conversation_keys` | Output of local `prepare-keys` / `session-encrypt.add_conversation_keys` | | `send_chat_typing_indicator` | Optional UX (do not hammer) | -| `mark_chat_conversation_read` | Optional after handling | +| `mark_chat_conversation_read` | Optional after handling. Takes only `id` and always marks the whole conversation read | **Valid `public_key.fields`:** `public_key_version,public_key,signing_public_key,identity_public_key_signature,juicebox_config` @@ -485,18 +485,18 @@ When they ask, run `$HELPER $SCRIPT forget`. If a run with `--remember-key` prin X tracks which chats are unread. For "what's unread" or "anything new", use that: don't work it out by scanning every conversation for events newer than the read point. -1. `get_chat_conversations` with `unread_only` true, `max_results` 100, and `chat_conversation.fields` `unread,last_read_event_id,newest_event_id`. A page can be short or empty while `meta.has_more` is true: pass `meta.next_token` as `pagination_token` until `has_more` is false. That is every unread conversation. -2. For each, page `get_chat_conversation_events` until you reach `last_read_event_id`. Events after it are the unread messages (all of them if it is missing). Read further back whenever it helps the answer. +1. `get_chat_conversations` with `unread_only` true, `max_results` 1000, and `chat_conversation.fields` `unread,last_read_event_id,newest_event_id`. A page can be short or empty while `meta.has_more` is true: pass `meta.next_token` as `pagination_token` until `has_more` is false. That is every unread conversation. +2. For each, page `get_chat_conversation_events` with `max_results` 100. Events come newest first and no parameter starts after an event, so stop at the first event whose `id` is at or below `last_read_event_id`, the `seen_until_sequence_id` of your latest read receipt. An empty page with a `next_token` is not the end. Events above `last_read_event_id`, except the ones you sent, are the unread messages (all of them if it is missing). Read further back whenever it helps the answer. 3. Message requests are not in this list. If `meta.has_message_requests` is true, list them as in step 2 of [Read / summarize](#read--summarize). 4. Get signing keys and decrypt as in [Read / summarize](#read--summarize). -`unread` is always true or false. `get_chat_conversation` takes the same fields for one thread. +`unread` is always true or false. Marking a conversation unread does not set it. `get_chat_conversation` takes the same fields for one thread. ### Read / summarize To summarize or search chats, read every conversation and every message request, not only the ones that look relevant. For what's unread, use [Unread](#unread). -1. `get_chat_conversations` with `max_results` 100. Page the whole inbox until `next_token` is absent. +1. `get_chat_conversations` with `max_results` 1000. Page the whole inbox until `next_token` is absent. 2. [Message requests](#message-requests): `get_chat_message_requests` with `max_results` 50, once with `inbox_type` `you_may_know` and once with `low_quality`, each paged until `next_token` is absent. Do not call `get_chat_message_request` while scanning. 3. `get_chat_conversation_events` for every conversation, and for every request with `has_more_events` (otherwise its `message_events` are the whole conversation), with `max_results` 100. Use each conversation's `id` and each request's `conversation_id` exactly as returned; do not rebuild ids from user ids. A page with `result_count: 0` that still has a `next_token` is not an empty thread: keep paging until `next_token` is absent. 4. If a chat call returns 503, retry it with the same `pagination_token` up to 3 times. Never treat a thread or a list as complete after a 503. If it keeps failing, tell the owner which threads you could not finish.