feat: agent-oriented command batch (DMs, edit/delete, uploads, channel lifecycle, pins, bookmarks, emoji, user groups) - #9
Merged
Conversation
…ation and reminders parse_when
…ntial extraction parsers
codesoda
marked this pull request as ready for review
September 11, 2026 02:01
…table matches actual behaviour
codesoda
force-pushed
the
feat/agent-feature-batch
branch
from
September 11, 2026 02:02
437e15d to
9234cb7
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the most common "I had to drop down to
slack api" operations as first-class commands, so agents don't need to know raw Slack method names or form-encoding quirks. 22 features across 8 areas; every new command has clap parse tests plus mockito-backed CLI tests asserting the request (method, path, url-encoded body/query) and JSON/--plainoutput.New command surface
messages
send @user "..."/send U0123 "..."— DM a user directly (conversations.open)send --broadcast,--blocks <file|->,--schedule "<when>"(chat.scheduleMessage)edit <channel:ts|permalink> "..."(chat.update, reuses Markdown→mrkdwn)delete <channel:ts|permalink>(chat.delete)permalink <channel:ts|permalink>(chat.getPermalink);send/getJSON now includepermalinkmark <channel> <ts>(conversations.mark)scheduled list/scheduled delete <channel> <id>list --since/--until(exclusive UTC bounds),--all(auto-paginate)list/thread/search --resolve-users— addsuser_name, rewrites<@U…>mentions to@name(one paginatedusers.listper invocation)search --sort score|timestamp --sort-dir asc|descchannels
members <channel> [--resolve]create [--private],join,leave,archive,unarchive,invite <channel> @a @b…,set-topic,set-purpose,renameunread— channels/DMs with unread counts, for "what needs my attention"users
info alice@corp.com(auto-detected →users.lookupByEmail);resolve_useraccepts emails everywheregroups list/groups members <handle|S-ID> [--resolve]files
upload <path> [--channel] [--title] [--comment] [--thread-ts] [--filename]—files.getUploadURLExternal→ raw POST →files.completeUploadExternalsearch <query>(search.files, user-token gated likemessages search)new groups:
pins add/remove/list,emoji list,bookmarks list/add/removeauth: verified the OAuth flow is reachable via
slack auth add(--oauth,--manual,--scopes) and documented it.Structure
New API methods live in per-area
impl SlackClientfiles (src/api/{chat,channel,file,identity,pin_emoji,bookmark}_ops.rs); new CLI groups insrc/cli/{pins,emoji,bookmarks,usergroups}.rs; new tests intests/cli_*_ops.rs. README, CHANGELOG[Unreleased], andskills/slack/*.mdare updated for everything.Also fixes a stale "MSRV 1.75" note in
AGENTS.md—Cargo.tomldeclares 1.78 and CI runsstableonly.Verification
cargo build,cargo test,SLACK_INTEGRATION_TESTS=1 cargo test(800+ tests, 0 failures)cargo fmt --all -- --check,cargo clippy --all-targets --all-features -- -D warningsRUSTDOCFLAGS=-D warnings cargo doc --no-deps --document-private-itemsKnown caveat
Workspace line coverage is ~75–78%, below the 80%
cargo llvm-covgate. All new files are 85–100% covered; the shortfall is pre-existing (auth/browser-extraction, OAuth). Flagging for discussion rather than padding tests or lowering the gate in this PR.Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Coverage push (second batch of commits)
Workspace line coverage: 78.7% → 93.0% (measured with the CI command; 968 / 13,912 lines missed).
CI gate is now real.
ci.ymlpreviously rancargo llvm-covwith no threshold; it now runscargo llvm-cov --all-features --workspace --ignore-filename-regex 'src/bin/test_keyring\.rs' --fail-under-lines 80(
test_keyringis a diagnostic binary with no logic). The 11api_requestmockito tests inclient.rsthat were gated behindSLACK_RUN_MOCK_TESTS=1(never set in CI) now always run.Prioritised by risk (
inspect diffon this PR + uncovered lines): the two Critical-risk entities in the PR,resolve_channelpagination and remindersparse_when, are covered first; then the security-boundary code (keyring storage, auth CLI, OAuth, credential extraction); then the mechanical CLI gaps.src/auth/storage.rssrc/cli/auth.rssrc/auth/oauth.rssrc/api/client.rssrc/api/edge.rssrc/auth/extract/{chromium,cookies,crypto}.rssrc/cli/users.rssrc/cli/status.rs/reactions.rs/reminders.rsRuntime-code changes made for testability (all behaviour-preserving, worth a look):
src/auth/storage.rs: keyring access goes through a privateSecretStoretrait (SystemSecretStore= thekeyringcrate, unchanged service/key names;MemorySecretStoreunder#[cfg(test)]). The six previously#[ignore]d tests now run, plus new tests for legacy→single-blob migration including the "persist blob before deleting legacy items" ordering.src/auth/oauth.rs:authorize_manualtakes an injectable reader/browser-opener internally. One small UX addition: the manual prompt now also accepts a bare pasted authorization code, not just the full redirect URL (state is still validated when a URL is pasted).src/auth/extract/mod.rs:SLACK_EXTRACT_FIXTURE=<json>test-only seam that substitutes fixture workspaces for local-app scanning, soauth discover/auth add <subdomain>are testable in CI. Documented as test-only.Noted while testing, not changed (out of scope):
EdgeClientdecodes the body before checking HTTP status, so a non-2xx response carrying a validok:truebody would be accepted.