Skip to content

Fix chats archive/unarchive hitting the wrong endpoint (silent no-op)#18

Open
malob wants to merge 1 commit into
beeper:mainfrom
malob:fix/chats-archive-endpoint
Open

Fix chats archive/unarchive hitting the wrong endpoint (silent no-op)#18
malob wants to merge 1 commit into
beeper:mainfrom
malob:fix/chats-archive-endpoint

Conversation

@malob

@malob malob commented Jun 8, 2026

Copy link
Copy Markdown

Summary

beeper chats archive --chat <id> and beeper chats unarchive --chat <id> report success: true / 200 OK, but the chat's archive state never changes — chats show --chat <id> --json | jq '.data.isArchived' stays the same and the chat never moves in/out of chats --archived. The success message is misleading.

Root cause

Both commands called the generic chat-update endpoint with an isArchived field:

PATCH /v1/chats/{chatID}    body: { isArchived: true | false }    → 200 OK, but a silent no-op

isArchived is not a writable field on that endpoint, so the API returns 200 and ignores it.

The Desktop API has a dedicated archive endpoint (OpenAPI operationId: archiveChat, from beeper api get /v1/spec):

POST /v1/chats/{chatID}/archive    body: { archived: boolean }    → archives / unarchives

Note the three differences: POST (not PATCH), the /archive sub-path, and the field archived (not isArchived).

Fix

Switch both commands from client.chats.update(chatID, { isArchived }) to the SDK's dedicated client.chats.archive(chatID, { archived }), which posts to /v1/chats/{chatID}/archive. That endpoint returns no body, so the commands now report via printSuccess (matching the chats remind / chats unremind convention for void-returning actions) instead of printing the update response.

-    await printData(await client.chats.update(chatID, { isArchived: true }), flags.json ? 'json' : 'human')
+    await client.chats.archive(chatID, { archived: true })
+    await printSuccess({ message: 'Chat archived', data: { chatID, archived: true } }, flags.json ? 'json' : 'human')

No SDK bump required@beeper/desktop-api already exposes client.chats.archive (and the repo already encoded this expectation: scripts/check-api-copy.ts allowlists chats.archive, and test/fixtures/fake-client.ts already mocks it). The commands were simply wired to the wrong method.

Verification

Built locally and ran against Beeper Desktop (http://127.0.0.1:23373) on a throwaway chat.

Before (buggy) — chats archive --debug: wrong request, and a no-op:

method: "patch"
url:    "http://127.0.0.1:23373/v1/chats/<id>"
        isArchived: true
patch .../v1/chats/<id> succeeded with status 200
→ chats show … | jq .data.isArchived  ==> false   (unchanged — no-op)
→ chats --archived                     ==> chat NOT present

After (fixed) — chats archive --debug: correct request, state actually changes:

method: "post"
url:    "http://127.0.0.1:23373/v1/chats/<id>/archive"
        archived: true
post .../v1/chats/<id>/archive succeeded with status 200
→ chats show … | jq .data.isArchived  ==> true
→ chats --archived                     ==> chat present

chats unarchive behaves symmetrically ({ archived: false }isArchived: false, leaves chats --archived). I archived → unarchived → re-archived the test chat and confirmed each transition via both chats show and chats --archived membership, and that --debug now shows the POST to /archive with the misleading PATCH gone.

Tests

  • Added a changeset (@beeper/cli, patch).
  • bun run test (build + readme/api-copy/manifest checks + cli-smoke + bun test) passes.
  • No test asserted the old behavior, so none needed updating. The repo has no command→SDK-call unit-test pattern (the fake-client fixture is currently unused and no test instantiates commands), so I didn't add a bespoke harness; test/e2e-staging.ts already exercises chats archive/unarchive and now drives the corrected endpoint.

🤖 Generated with Claude Code

`chats archive` and `chats unarchive` called the generic chat-update
endpoint (PATCH /v1/chats/{chatID} with { isArchived }), which returns
200 OK but silently ignores isArchived — so the command reported success
while the chat's archive state never changed.

Switch both commands to the dedicated archiveChat endpoint
(POST /v1/chats/{chatID}/archive with { archived }) via the SDK's
client.chats.archive(chatID, { archived }), so the state actually changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 21768f6b-16a0-4263-8ee4-389842e3feca

📥 Commits

Reviewing files that changed from the base of the PR and between 9502715 and 91d9bec.

📒 Files selected for processing (3)
  • .changeset/fix-chats-archive-endpoint.md
  • packages/cli/src/commands/chats/archive.ts
  • packages/cli/src/commands/chats/unarchive.ts
📜 Recent review details
🔇 Additional comments (3)
.changeset/fix-chats-archive-endpoint.md (1)

1-12: LGTM!

packages/cli/src/commands/chats/archive.ts (1)

17-18: LGTM!

packages/cli/src/commands/chats/unarchive.ts (1)

17-18: LGTM!


📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Fixed the chats archive command to properly archive conversations. Previously, the command would report success without actually updating the chat's archive state.
    • Fixed the chats unarchive command to properly unarchive conversations. Previously, the command would report success without actually updating the chat's archive state.

Walkthrough

This PR fixes the chats archive and chats unarchive commands to actually modify chat archive state. The commands previously invoked the generic chat update endpoint, which ignored the isArchived field and returned success without making any changes. The commands now call the dedicated archive endpoint to ensure state changes are applied.

Changes

Archive/unarchive endpoint fix

Layer / File(s) Summary
Migrate archive/unarchive to dedicated endpoint
.changeset/fix-chats-archive-endpoint.md, packages/cli/src/commands/chats/archive.ts, packages/cli/src/commands/chats/unarchive.ts
The changeset documents the fix. Archive and unarchive commands switch from client.chats.update(chatID, { isArchived }) to client.chats.archive(chatID, { archived }), and output handling changes from printData to printSuccess.

🎯 1 (Trivial) | ⏱️ ~3 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title directly and accurately describes the main fix: switching the archive/unarchive commands from the wrong generic endpoint to the correct dedicated archive endpoint, resolving the silent no-op issue.
Description check ✅ Passed The PR description is comprehensive and directly related to the changeset, explaining the root cause, the fix, verification steps, and test status in detail.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant