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 +4 -4
- data/lib/ask/skills/slack.use_slack/SKILL.md +100 -0
- data/lib/ask/slack/client.rb +51 -17
- data/lib/ask/slack/version.rb +1 -1
- metadata +58 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8328e80c2b6386b33282dd95c8af3eceab18182e53547d5fe6b849a9bcbe874d
|
|
4
|
+
data.tar.gz: c73406fd2a39f3d8dca19f856226373cc30c090023a2f73d2f1b342081a2c3bd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
data/lib/ask/slack/client.rb
CHANGED
|
@@ -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
|
-
#
|
|
12
|
-
# authentication errors into +Ask::Auth::InvalidCredential+.
|
|
11
|
+
# configures the client with sensible defaults:
|
|
13
12
|
#
|
|
14
|
-
#
|
|
15
|
-
# -
|
|
16
|
-
#
|
|
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(
|
|
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
|
|
33
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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)
|
data/lib/ask/slack/version.rb
CHANGED
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.
|
|
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
|