Skip to content

List a chat's files, and manage its chatbots - #999

Open
jeremy wants to merge 3 commits into
mainfrom
sdk-absorb/card-10447988117
Open

jeremy wants to merge 3 commits into
mainfrom
sdk-absorb/card-10447988117

Conversation

@jeremy

@jeremy jeremy commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

basecamp chat uploads lists the files posted in a chat, and basecamp chat bots lists, shows, adds, renames and deletes its chatbots.

Why

[CLI] Campfire chatbots and the uploads list: the coverage report (basecamp-sdk#1055) lists six SDK operations the CLI doesn't reach. API-COVERAGE.md skipped chatbots because they "require chatbot key, not OAuth", but that's only true of posting as a chatbot. Managing them goes through OAuth, which is how the MCP server already serves all five as *_chatbot tools.

The decision this PR asks for: whether the CLI should manage chatbots at all. It reverses a recorded skip, so it's a person's call, not this job's. If the answer is no, drop chat_bots.go's bots group and the chatbots rows, and chat uploads stands alone.

What changed

Operation Command
ListCampfireUploads basecamp chat uploads
ListChatbots basecamp chat bots list
GetChatbot basecamp chat bots show <id>
CreateChatbot basecamp chat bots create <name> [--command-url URL]
UpdateChatbot basecamp chat bots update <id> [--name NAME] [--command-url URL]
DeleteChatbot basecamp chat bots delete <id> [--force]
  • All of them take the chat from --room or the project's one chat, and the project from --in, as the other chat commands do. Chatbot routes name the project, so it's resolved even when --room is given.
  • chat uploads returns the chat lines that carried a file, newest first (asked for explicitly, so --limit keeps the latest): 100 by default, or --limit, --all or --page. Contradictory flags are refused before any request.
  • update reads the chatbot first and sends back whatever you didn't change, because the API takes the name on every update. Without that, a rename might clear the command URL. The SDK leaves out an empty command URL, so you can change one but not remove it, and the help says so. update with nothing to change is refused.
  • delete is permanent and account-wide. Like chat delete, it asks for confirmation, or needs --force where nothing can answer.
  • The group's help and agent notes say that chatbots belong to the account, that managing them takes an administrator, and that lines_url holds the bot's key, so anyone who has it can post as the bot and it should be treated like a password. The CLI prints lines_url as the API returns it, as the MCP server does: handing it to whoever runs the bot is the point of creating one.
  • Chatbots render through their own presenter schema, which keeps the name, lines_url and command_url in the styled list, the Markdown list and the detail view. Every follow-up command carries --profile and --account where a fresh process wouldn't pick them up.
  • bot is an alias of bots. Catalog entry, .surface, and API-COVERAGE.md: chatbot management and chat uploads are now covered rows. Posting as a chatbot stays out of scope for the old reason, and the notes now explain the difference. Summary counts go to 227 of 227.
  • skills/basecamp/SKILL.md isn't touched: it's 130 bytes under its 16 KB limit, and the help covers these commands.

Builds on

Main at f45d3c8e, whose pinned SDK (v0.34.0) has all six operations. No bump in this PR.

Left out

Nothing from the card. Posting as a chatbot (POST to lines_url with the key) isn't an operation on the card and stays out of scope.

Tests

  • Unit (internal/commands/chat_bots_test.go): each command's method, path and body; uploads asks for newest first, and --page sends the page; every command's follow-ups carry the profile; conflicting uploads flags are refused with nothing sent; create with and without --command-url; update keeps the field you leave out, in all three combinations; an empty name, an empty command URL, nothing to change and a non-numeric or zero ID are each refused before any request; delete without --force in machine output sends nothing, and with it sends one DELETE; a 403 on create comes back as an error with nothing printed and no retry.
  • Presenter (internal/presenter/presenter_test.go): the chatbot schema keeps the name and both URLs in each view.
  • e2e (e2e/chat.bats): the usage refusals, asserting the exact error and hint, and the help text naming lines_url's key and the administrator requirement.
  • Smoke (e2e/smoke/smoke_campfire.bats): uploads after the existing upload, and a chatbot lifecycle (create, list, show, update, delete --force). The file now runs its tests in order (BATS_NO_PARALLELIZE_WITHIN_FILE), which the existing line lifecycle also relied on. Create is marked unverifiable only on a forbidden answer, since the smoke user may not be an administrator, and .qa-allowlist names it and the three tests that read its bot, as it does for timesheets and lineup. Written but not run, since smoke needs a live account. chat bot is marked as an alias in smoke_aliases.bats.

On thelio, bin/ci passes fmt, vet, golangci-lint (0 issues), actionlint and zizmor. Its unit tests fail only in TestHardenConfigDir (internal/cli, two subtests). That's the same failure #992 recorded, and it reproduces on a clean export of f45d3c8e on that machine; this PR doesn't touch internal/cli. The rest of make check (e2e, surface, skill drift, smoke coverage, naming, provenance, tidy) passes. Remote CI is the check for TestHardenConfigDir.

Gap card

https://app.basecamp.com/2914079/buckets/48521764/card_tables/cards/10447988117 (the MCP server already serves the chatbot operations)


Summary by cubic

Adds basecamp chat uploads to list files posted in a chat, and basecamp chat bots to list, show, create, rename, and delete chatbots. Chatbot management works through OAuth as an administrator's call, so it reverses the prior reasoning that skipped chatbots; only posting as a chatbot, which needs the chatbot key, stays out of scope. Reviewers get to decide whether chatbot management belongs in the CLI — if not, drop the bots group and keep chat uploads standalone.

Notable behaviors

  • chat uploads requests files newest first so a --limit keeps the latest ones.
  • update reads the chatbot first and sends back what you didn't change, since the API takes the name on every update; a command URL can be changed but not removed.
  • delete is permanent and account-wide, so it asks for confirmation or needs --force where nothing can answer.
  • Chatbots render through their own presenter schema that keeps the name and both URLs in every view.
  • Help text warns that lines_url carries the bot's key and should be treated like a password.
  • The four chatbot smoke tests are allowlisted in CI, since a non-administrator smoke token gets forbidden on create and the rest depend on it.

Written for commit eca8d44. Summary will update on new commits.

View guided diff Turn on auto-fix

chat uploads lists the files posted in a chat (ListCampfireUploads).
chat bots lists, shows, creates, updates and deletes chatbots
(ListChatbots, GetChatbot, CreateChatbot, UpdateChatbot, DeleteChatbot):
managing them is an OAuth call an administrator makes, so the
chatbot-key reason API-COVERAGE.md gave for skipping chatbots now
covers only posting as one.
Copilot AI balanced review requested due to automatic review settings November 2, 2026 16:59
@jeremy

jeremy commented Nov 2, 2026

Copy link
Copy Markdown
Member Author

🤖 @codex review

@github-actions github-actions Bot added commands CLI command implementations tests Tests (unit and e2e) docs labels Nov 2, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-11-02T17:44:13.324615Z
We couldn’t complete this review. Comment @codex review to try again.
eca8d44 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 9 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="internal/commands/chat_bots.go">

<violation number="1" location="internal/commands/chat_bots.go:354">
P2: `--command-url` is documented as HTTPS, but `create` and `update` send any string to the API without checking the scheme. Reject values that do not start with `https://` with `output.ErrUsage` before the request, in both commands.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread e2e/chat.bats Resolved
Comment thread e2e/smoke/smoke_campfire.bats Resolved
Comment thread e2e/smoke/smoke_campfire.bats Resolved
},
}

cmd.Flags().StringVar(&commandURL, "command-url", "", "HTTPS address Basecamp calls when the bot is addressed")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: --command-url is documented as HTTPS, but create and update send any string to the API without checking the scheme. Reject values that do not start with https:// with output.ErrUsage before the request, in both commands.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At internal/commands/chat_bots.go, line 354:

<comment>`--command-url` is documented as HTTPS, but `create` and `update` send any string to the API without checking the scheme. Reject values that do not start with `https://` with `output.ErrUsage` before the request, in both commands.</comment>

<file context>
@@ -0,0 +1,504 @@
+		},
+	}
+
+	cmd.Flags().StringVar(&commandURL, "command-url", "", "HTTPS address Basecamp calls when the bot is addressed")
+	return cmd
+}
</file context>

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Not changed: the server owns which command URLs it accepts, and a client-side scheme check would refuse what the API might accept now or later, or pass what it refuses for another reason. The API's own refusal comes back through the usual error envelope. Leaving this thread open for a person to decide.

Comment thread API-COVERAGE.md Resolved

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved defects leave uploads incorrectly ordered, hide chatbot names or posting URLs, and generate follow-up commands that can use the wrong credentials or account.

3 open issues
What changed in this PR

Adds chat upload listing and OAuth-based chatbot management to the CLI, exposing six existing SDK operations. Chatbot posting remains out of scope.

Changes:

  • Adds chat uploads with pagination controls and chat bots with list, show, create, update, and delete commands.
  • Adds input validation, deletion confirmation, and help explaining account-wide effects and chatbot-key handling.
  • Updates command discovery, API coverage, unit tests, and end-to-end smoke scenarios.

[!TIP]
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

File Description
internal/​commands/​commands.go Adds uploads and bots to the command catalog.
internal/​commands/​chat.go Registers the new chat subcommands.
internal/​commands/​chat_bots.go Implements upload listing and chatbot management.
internal/​commands/​chat_bots_test.go Tests requests, validation, updates, and deletion safeguards.
e2e/​smoke/​smoke_campfire.bats Adds upload-listing and chatbot lifecycle smoke tests.
e2e/​smoke/​smoke_aliases.bats Records coverage treatment for the bot alias.
e2e/​chat.bats Checks usage errors and security-related help text.
API-COVERAGE.md Documents newly covered operations and distinguishes chatbot posting.
.surface Records new commands, aliases, arguments, and flags.

Review effort: Balanced

Comment thread internal/commands/chat_bots.go Resolved
Comment thread internal/commands/chat_bots.go Resolved
Comment thread internal/commands/chat_bots.go Resolved
…llow-ups

chat uploads asks for newest first, so a --limit keeps the latest files.
Every chat uploads and chat bots breadcrumb carries --profile and --account
where a fresh process wouldn't pick them up. Chatbots get a presenter schema
that keeps the name and both URLs. The smoke lifecycle runs serially within
its file and marks itself unverifiable only on a forbidden answer; the e2e
refusals assert the exact error.
Copilot AI balanced review requested due to automatic review settings November 2, 2026 17:25
@github-actions github-actions Bot added the output Output formatting and presentation label Nov 2, 2026
@jeremy

jeremy commented Nov 2, 2026

Copy link
Copy Markdown
Member Author

🤖 @codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

API-COVERAGE.md incorrectly promises oldest-first results, while the command returns newest-first results and selects the newest files when using --limit.

1 open issue
3 resolved since last review

Review effort: Balanced

Comment thread API-COVERAGE.md Resolved

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 7 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread e2e/smoke/smoke_campfire.bats Resolved
Comment thread internal/commands/chat_bots.go Resolved
… run it

A smoke token that isn't an account administrator gets forbidden on create,
and show, update and delete read the bot create made, as the timesheet and
lineup lifecycles already allow. The coverage row says newest first, as the
command asks.
Copilot AI balanced review requested due to automatic review settings November 2, 2026 17:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

A maintainer must confirm the decision to reverse the CLI’s chatbot-management exclusion because it introduces account-wide administrator mutations and exposes posting-key URLs.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@jeremy

jeremy commented Nov 2, 2026 •

Copy link
Copy Markdown
Member Author

🤖 Converged on eca8d446, and marking this ready for a person to merge.

  • CI: 28 checks passed, 4 skipped, none failed.
  • Copilot reviewed eca8d446 and found no open issues. It names the same question the body asks a person to decide: whether the CLI should manage chatbots.
  • Codex didn't review: both requests, the second on 3b64d2f8, came back with its usage limit.
  • cubic's seven findings and Copilot's four are answered. Ten are fixed and resolved. One is left open on purpose: the HTTPS check on --command-url, which I declined because the server owns that rule. A person decides it.
  • Mergeable, no conflicts with main.

@jeremy
jeremy marked this pull request as ready for review November 2, 2026 17:44
@jeremy
jeremy requested a review from a team as a code owner November 2, 2026 17:44
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

This branch has not been deployed

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

Labels

commands CLI command implementations docs output Output formatting and presentation tests Tests (unit and e2e)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants