Skip to content

feat: agent-oriented command batch (DMs, edit/delete, uploads, channel lifecycle, pins, bookmarks, emoji, user groups) - #9

Merged
codesoda merged 32 commits into
mainfrom
feat/agent-feature-batch
Sep 11, 2026
Merged

feat: agent-oriented command batch (DMs, edit/delete, uploads, channel lifecycle, pins, bookmarks, emoji, user groups)#9
codesoda merged 32 commits into
mainfrom
feat/agent-feature-batch

Conversation

@codesoda

@codesoda codesoda commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

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/--plain output.

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/get JSON now include permalink
  • mark <channel> <ts> (conversations.mark)
  • scheduled list / scheduled delete <channel> <id>
  • list --since/--until (exclusive UTC bounds), --all (auto-paginate)
  • list/thread/search --resolve-users — adds user_name, rewrites <@U…> mentions to @name (one paginated users.list per invocation)
  • search --sort score|timestamp --sort-dir asc|desc

channels

  • members <channel> [--resolve]
  • create [--private], join, leave, archive, unarchive, invite <channel> @a @b…, set-topic, set-purpose, rename
  • unread — channels/DMs with unread counts, for "what needs my attention"

users

  • info alice@corp.com (auto-detected → users.lookupByEmail); resolve_user accepts emails everywhere
  • groups list / groups members <handle|S-ID> [--resolve]

files

  • upload <path> [--channel] [--title] [--comment] [--thread-ts] [--filename]files.getUploadURLExternal → raw POST → files.completeUploadExternal
  • search <query> (search.files, user-token gated like messages search)

new groups: pins add/remove/list, emoji list, bookmarks list/add/remove

auth: 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 SlackClient files (src/api/{chat,channel,file,identity,pin_emoji,bookmark}_ops.rs); new CLI groups in src/cli/{pins,emoji,bookmarks,usergroups}.rs; new tests in tests/cli_*_ops.rs. README, CHANGELOG [Unreleased], and skills/slack/*.md are updated for everything.

Also fixes a stale "MSRV 1.75" note in AGENTS.mdCargo.toml declares 1.78 and CI runs stable only.

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 warnings
  • RUSTDOCFLAGS=-D warnings cargo doc --no-deps --document-private-items

Known caveat

Workspace line coverage is ~75–78%, below the 80% cargo llvm-cov gate. 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.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with 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.yml previously ran cargo llvm-cov with no threshold; it now runs
cargo llvm-cov --all-features --workspace --ignore-filename-regex 'src/bin/test_keyring\.rs' --fail-under-lines 80
(test_keyring is a diagnostic binary with no logic). The 11 api_request mockito tests in client.rs that were gated behind SLACK_RUN_MOCK_TESTS=1 (never set in CI) now always run.

Prioritised by risk (inspect diff on this PR + uncovered lines): the two Critical-risk entities in the PR, resolve_channel pagination and reminders parse_when, are covered first; then the security-boundary code (keyring storage, auth CLI, OAuth, credential extraction); then the mechanical CLI gaps.

File Before After
src/auth/storage.rs 22% 89%
src/cli/auth.rs 49% 90%
src/auth/oauth.rs 61% 90%
src/api/client.rs 70% 95%
src/api/edge.rs 67% 99%
src/auth/extract/{chromium,cookies,crypto}.rs 65–79% 82–100%
src/cli/users.rs 42% 93%
src/cli/status.rs / reactions.rs / reminders.rs 47–59% 90%+

Runtime-code changes made for testability (all behaviour-preserving, worth a look):

  • src/auth/storage.rs: keyring access goes through a private SecretStore trait (SystemSecretStore = the keyring crate, unchanged service/key names; MemorySecretStore under #[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_manual takes 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, so auth discover / auth add <subdomain> are testable in CI. Documented as test-only.

Noted while testing, not changed (out of scope): EdgeClient decodes the body before checking HTTP status, so a non-2xx response carrying a valid ok:true body would be accepted.

@codesoda
codesoda marked this pull request as ready for review September 11, 2026 02:01
@codesoda
codesoda force-pushed the feat/agent-feature-batch branch from 437e15d to 9234cb7 Compare September 11, 2026 02:02
@codesoda
codesoda merged commit 6515a1b into main Sep 11, 2026
10 checks passed
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