ask-slack 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b550c9169e3b980cb31099c840db9da17a79d2b1164ef92ba3b6d85080a68f3f
4
- data.tar.gz: 484183cfcf1a3b76e11f3c3b1d09382c2d4acc72e2d73c538c8b0448fd8c2d55
3
+ metadata.gz: 8328e80c2b6386b33282dd95c8af3eceab18182e53547d5fe6b849a9bcbe874d
4
+ data.tar.gz: c73406fd2a39f3d8dca19f856226373cc30c090023a2f73d2f1b342081a2c3bd
5
5
  SHA512:
6
- metadata.gz: ddf878f447dfd83a0130daf887c4b629fbaa5af92513d4908fdaf9789b787505e2bde3f9cd334ce8b3890d427d2fea350b53d2eb7d9955f9edf8c878519f9283
7
- data.tar.gz: 80b75a4d986f37c174b46435641f623b3ff46267b0cf9263cc95478c5081da37b19bcfac10108b83aef35d12365ddc19ac03ca7b6d8f01afc5f0638b5cda2078
6
+ metadata.gz: b46af6dc89a858df607c4e0b57a32873463ab80883757e0bcbba57e1297882a23e2d23fbe916d9e7fa31912caace997be3166b170537af293bff1ae07fb48452
7
+ data.tar.gz: 32d1694ed20b65b4595a7b24a70aad1f255745d33208b6844b73ce7099154bcea8761f0520826a72f260eb448f067a7d5ed7635980c4a2bcd7aa46e8b769e35e
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: slack.use_slack
3
+ description: How to navigate the Slack API with slack-ruby-client — discover methods, handle auth, pagination, and errors
4
+ ---
5
+
6
+ Use this skill when you need to interact with Slack — posting messages, reading
7
+ channels, managing users, uploading files, or searching conversations.
8
+
9
+ ## Step 1: Get the Client
10
+
11
+ ```ruby
12
+ client = Ask::Slack.client
13
+ ```
14
+
15
+ This returns an authenticated `Slack::Web::Client`. It expects a valid Slack Bot
16
+ User OAuth Token resolved via `Ask::Auth.resolve(:slack_token)`.
17
+
18
+ If you get an auth error, read `Ask::Slack::Context::AUTH_HOW` for token setup.
19
+
20
+ ## Step 2: Explore the Context
21
+
22
+ The gem ships with structured context you should reference:
23
+
24
+ ```ruby
25
+ Ask::Slack::Context::DOCS_URL # Slack Web API methods docs
26
+ Ask::Slack::Context::GEM_DOCS # slack-ruby-client Ruby docs
27
+ Ask::Slack::Context::QUICK_START # Copy-paste examples
28
+ Ask::Slack::Context::GEM_NAME # "slack-ruby-client"
29
+ ```
30
+
31
+ The `QUICK_START` constant has basic examples for channels, messaging, and users.
32
+
33
+ ## Step 3: Discover Available Methods
34
+
35
+ Use code tools to explore the underlying SDK client:
36
+
37
+ ```ruby
38
+ Code.new.call(code: "
39
+ client = Ask::Slack.client.client # unwrap proxy to get raw client
40
+ puts client.methods(false).sort.join(\"\\n\")
41
+ ")
42
+ ```
43
+
44
+ Common Slack API methods:
45
+ - `client.chat_postMessage(channel:, text:, blocks:)` — send a message
46
+ - `client.conversations_list` — list public channels
47
+ - `client.conversations_history(channel:)` — read channel history
48
+ - `client.conversations_replies(channel:, ts:)` — get thread replies
49
+ - `client.users_list` — list workspace users
50
+ - `client.files_upload_v2(channels:, content:, file:)` — upload files
51
+
52
+ For method details, read the slack-ruby-client source:
53
+ ```ruby
54
+ # Discover the underlying WebClient methods
55
+ Read.new.call(path: "$GEM_PATH/slack-ruby-client-*/lib/slack/web/client.rb")
56
+ ```
57
+
58
+ ## Step 4: Authentication & Common Errors
59
+
60
+ Auth failures are converted to `Ask::Auth::InvalidCredential`. For detailed
61
+ error guidance, use:
62
+
63
+ ```ruby
64
+ Ask::Slack::Errors.for("channel_not_found")
65
+ Ask::Slack::Errors.status_code_description(429)
66
+ Ask::Slack::Errors::RATE_LIMIT
67
+ Ask::Slack::Errors::PAGINATION
68
+ ```
69
+
70
+ Common scenarios:
71
+ - **not_in_channel**: Bot isn't in that channel → invite or use `conversations_join`
72
+ - **missing_scope**: Token lacks required OAuth scope → add at api.slack.com/apps
73
+ - **rate_limited**: Exceeded per-method limit → check Retry-After header
74
+ - **invalid_blocks**: Block Kit JSON has validation errors
75
+
76
+ ## Step 5: Pagination
77
+
78
+ Slack uses cursor-based pagination. The pattern is:
79
+
80
+ ```ruby
81
+ response = client.conversations_list(limit: 200)
82
+ cursor = response.response_metadata.next_cursor
83
+ # Pass cursor in next request:
84
+ client.conversations_list(limit: 200, cursor: cursor) unless cursor.empty?
85
+ ```
86
+
87
+ Most list methods accept `limit` (max 200) and `cursor` parameters.
88
+
89
+ ## Step 6: Message Formatting
90
+
91
+ For rich messages, use Block Kit (JSON blocks). The `QUICK_START` constant
92
+ has examples for header, section, context, divider, and actions blocks. For
93
+ detailed Block Kit reference, see the Slack API docs.
94
+
95
+ ## Step 7: Fallback Strategy
96
+
97
+ If the SDK doesn't have a method for what you need:
98
+ 1. Check `Ask::Slack::Context::DOCS_URL` for the API method
99
+ 2. Use `client.post("method.name", params)` for custom API calls
100
+ 3. Use `client.get("conversations.list")` style for raw endpoint access
@@ -8,12 +8,19 @@ module Ask
8
8
  # Returns an authenticated Slack Web API client configured for an AI agent.
9
9
  #
10
10
  # Resolves the Slack token via +Ask::Auth.resolve(:slack_token)+ and
11
- # wraps the client in a proxy that converts +::Slack::Web::Api::Errors::SlackError+
12
- # authentication errors into +Ask::Auth::InvalidCredential+.
11
+ # configures the client with sensible defaults:
13
12
  #
14
- # Configuration:
15
- # - Uses the resolved token for authentication
16
- # - Default user agent is set by slack-ruby-client
13
+ # - +timeout+: 30 seconds for HTTP requests
14
+ # - +open_timeout+: 10 seconds for TCP connection
15
+ #
16
+ # Retry behaviour: +ClientProxy+ retries transient Faraday and network
17
+ # errors up to 3 times with exponential backoff before raising
18
+ # +Ask::Auth::InvalidCredential+.
19
+ #
20
+ # The client is wrapped in a +ClientProxy+ that:
21
+ # 1. Converts auth errors (+NotAuthed+, +InvalidAuth+, etc.) into
22
+ # +Ask::Auth::InvalidCredential+
23
+ # 2. Retries transient network failures with exponential backoff
17
24
  #
18
25
  # @example
19
26
  # client = Ask::Slack.client
@@ -23,27 +30,54 @@ module Ask
23
30
  # @return [::Slack::Web::Client] an authenticated client
24
31
  # @raise [Ask::Auth::MissingCredential] if no Slack token is configured
25
32
  # @raise [Ask::Auth::InvalidCredential] if the token is rejected
26
- def self.client
33
+ def self.client(base_delay: nil)
27
34
  token = Ask::Auth.resolve(:slack_token)
28
35
 
29
- ClientProxy.new(::Slack::Web::Client.new(token: token))
36
+ ClientProxy.new(::Slack::Web::Client.new(
37
+ token: token,
38
+ timeout: 30,
39
+ open_timeout: 10
40
+ ), base_delay: base_delay)
30
41
  end
31
42
 
32
- # Proxies method calls to a +::Slack::Web::Client+, converting authentication
33
- # errors into +Ask::Auth::InvalidCredential+.
43
+ # Proxies method calls to a +::Slack::Web::Client+, converting auth errors
44
+ # and retrying transient network failures with exponential backoff.
34
45
  class ClientProxy < ::BasicObject
35
- def initialize(client)
46
+ MAX_RETRIES = 3
47
+ RETRYABLE_ERRORS = [
48
+ ::Faraday::TimeoutError,
49
+ ::Faraday::ConnectionFailed,
50
+ ::Faraday::ServerError,
51
+ ::Errno::ECONNREFUSED,
52
+ ::Errno::ECONNRESET,
53
+ ::Timeout::Error
54
+ ].freeze
55
+
56
+ attr_reader :client
57
+
58
+ def initialize(client, base_delay: nil)
36
59
  @client = client
60
+ @_base_delay = base_delay || 1
37
61
  end
38
62
 
39
63
  def method_missing(name, ...)
40
- @client.public_send(name, ...)
41
- rescue ::Slack::Web::Api::Errors::NotAuthed,
42
- ::Slack::Web::Api::Errors::InvalidAuth,
43
- ::Slack::Web::Api::Errors::AccountInactive,
44
- ::Slack::Web::Api::Errors::TokenRevoked,
45
- ::Slack::Web::Api::Errors::TokenExpired
46
- ::Kernel.raise ::Ask::Auth::InvalidCredential, :slack_token
64
+ retry_count = 0
65
+ begin
66
+ @client.public_send(name, ...)
67
+ rescue ::Slack::Web::Api::Errors::NotAuthed,
68
+ ::Slack::Web::Api::Errors::InvalidAuth,
69
+ ::Slack::Web::Api::Errors::AccountInactive,
70
+ ::Slack::Web::Api::Errors::TokenRevoked,
71
+ ::Slack::Web::Api::Errors::TokenExpired
72
+ ::Kernel.raise ::Ask::Auth::InvalidCredential, :slack_token
73
+ rescue *RETRYABLE_ERRORS => e
74
+ retry_count += 1
75
+ if retry_count <= MAX_RETRIES
76
+ ::Kernel.sleep(@_base_delay * (2 ** (retry_count - 1)))
77
+ retry
78
+ end
79
+ ::Kernel.raise ::Ask::Auth::InvalidCredential.new(:slack_token, e.message)
80
+ end
47
81
  end
48
82
 
49
83
  def respond_to_missing?(name, include_private = false)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ask
4
4
  module Slack
5
- VERSION = '0.1.0'
5
+ VERSION = '0.1.2'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ask-slack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kaka Ruto
@@ -37,6 +37,20 @@ dependencies:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
39
  version: '3.1'
40
+ - !ruby/object:Gem::Dependency
41
+ name: faraday-retry
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.4'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '2.4'
40
54
  - !ruby/object:Gem::Dependency
41
55
  name: minitest
42
56
  requirement: !ruby/object:Gem::Requirement
@@ -79,6 +93,48 @@ dependencies:
79
93
  - - "~>"
80
94
  - !ruby/object:Gem::Version
81
95
  version: '13.0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: vcr
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '6.3'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '6.3'
110
+ - !ruby/object:Gem::Dependency
111
+ name: webmock
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '3.23'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '3.23'
124
+ - !ruby/object:Gem::Dependency
125
+ name: simplecov
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '0.22'
131
+ type: :development
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '0.22'
82
138
  description: Provides authenticated Slack client helper, context metadata, and error
83
139
  guide for AI agents.
84
140
  email:
@@ -90,6 +146,7 @@ files:
90
146
  - LICENSE
91
147
  - README.md
92
148
  - lib/ask-slack.rb
149
+ - lib/ask/skills/slack.use_slack/SKILL.md
93
150
  - lib/ask/slack/client.rb
94
151
  - lib/ask/slack/context.rb
95
152
  - lib/ask/slack/error_guide.rb