shapeup-cli 0.10.4 → 0.10.5
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/shapeup_cli/commands/doctor.rb +54 -8
- data/lib/shapeup_cli/config.rb +4 -0
- data/lib/shapeup_cli/version.rb +1 -1
- data/skills/shapeup-connect/SKILL.md +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a45ee37e8d065758ff406860f939921f4ddb7341bed82732cee1454ab2cde0c1
|
|
4
|
+
data.tar.gz: 9b8230e7e221798866fa6c1ca1fbe947f2aacef3a6ae03500a32cdfd494a08cd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 03bb70e47f6b4322602c8e86d8e129ad153dc9e6f0596dd9fa54f6127f910a8fa428b51cd723c19389f4b2a31b698469afdc851c862a97390aa94f272af4bf63
|
|
7
|
+
data.tar.gz: 6eba12bf921de8b62efbda85d1d410ece152c11399872384ef54b9daae70adc64bc1ced1fcf8fb808cfb0e1343a2d506154d9db53ef6c6c39ed7a023c1fa4907
|
|
@@ -33,7 +33,9 @@ module ShapeupCli
|
|
|
33
33
|
check_api_reachable,
|
|
34
34
|
check_auth,
|
|
35
35
|
check_org_access,
|
|
36
|
-
|
|
36
|
+
check_claude_skills,
|
|
37
|
+
check_agent,
|
|
38
|
+
check_connector
|
|
37
39
|
]
|
|
38
40
|
|
|
39
41
|
report(checks)
|
|
@@ -127,7 +129,7 @@ module ShapeupCli
|
|
|
127
129
|
def check_auth
|
|
128
130
|
return skip("auth", "no token to test") unless Config.token
|
|
129
131
|
|
|
130
|
-
result = Output.extract_data(
|
|
132
|
+
result = Output.extract_data(client.call_tool("list_organisations"))
|
|
131
133
|
@organisations = result.is_a?(Hash) ? (result["organisations"] || []) : Array(result)
|
|
132
134
|
pass "auth", "signed in, #{@organisations.length} organisation(s)"
|
|
133
135
|
rescue Client::AuthError
|
|
@@ -149,15 +151,59 @@ module ShapeupCli
|
|
|
149
151
|
end
|
|
150
152
|
end
|
|
151
153
|
|
|
152
|
-
def
|
|
153
|
-
|
|
154
|
-
|
|
154
|
+
def check_claude_skills
|
|
155
|
+
states = Setup::SKILL_NAMES.to_h do |name|
|
|
156
|
+
installed = File.join(Dir.home, ".claude", "skills", name, "SKILL.md")
|
|
157
|
+
current = File.exist?(installed) && File.read(installed) == File.read(File.join(Setup::SKILLS_DIR, name, "SKILL.md"))
|
|
158
|
+
[ name, File.exist?(installed) ? (current ? :current : :stale) : :missing ]
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
if states.values.all?(:current)
|
|
162
|
+
pass "claude skills", "#{states.keys.join(", ")} installed and current"
|
|
163
|
+
else
|
|
164
|
+
behind = states.reject { |_, state| state == :current }.map { |name, state| "#{name} #{state == :missing ? "not installed" : "stale"}" }
|
|
165
|
+
warn! "claude skills", behind.join(", "), hint: "shapeup setup claude"
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def check_agent
|
|
170
|
+
return skip("agent", "auth not verified") unless @organisations && Config.organisation_id
|
|
171
|
+
|
|
172
|
+
mine = Output.extract_data(client.call_tool("list_my_agents", organisation: Config.organisation_id.to_s))
|
|
173
|
+
return pass("agent", "signed in as an agent") if mine["signed_in_as_agent"]
|
|
174
|
+
|
|
175
|
+
@agent = mine["agents"].first
|
|
176
|
+
return skip("agent", mine["can_add"] ? "you have no agent here" : "agents need a Pro organisation where you're a member") unless @agent
|
|
155
177
|
|
|
156
|
-
|
|
157
|
-
|
|
178
|
+
handle = @agent["name"]
|
|
179
|
+
profile = Config.profile(handle)
|
|
180
|
+
return warn!("agent", "@#{handle} isn't connected on this computer yet", hint: "/shapeup-connect in Claude Code") unless profile&.dig("token")
|
|
181
|
+
|
|
182
|
+
Client.new(host: profile["host"] || Config.host, token: profile["token"])
|
|
183
|
+
.call_tool("list_inbox", organisation: (profile["organisation_id"] || Config.organisation_id).to_s)
|
|
184
|
+
@connected_agent = handle
|
|
185
|
+
pass "agent", "@#{handle} signs in with profile '#{handle}'"
|
|
186
|
+
rescue Client::AuthError
|
|
187
|
+
fail! "agent", "@#{handle}'s saved token was rejected", hint: "/shapeup-connect in Claude Code"
|
|
188
|
+
rescue Client::ApiError => e
|
|
189
|
+
fail! "agent", e.message
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def check_connector
|
|
193
|
+
return skip("connector", "no connected agent to listen for") unless @connected_agent
|
|
194
|
+
|
|
195
|
+
if connector_running_for?(@connected_agent)
|
|
196
|
+
pass "connector", "listening as @#{@connected_agent} on this computer"
|
|
158
197
|
else
|
|
159
|
-
warn! "
|
|
198
|
+
warn! "connector", "not listening as @#{@connected_agent} on this computer", hint: "/shapeup-connect in Claude Code"
|
|
160
199
|
end
|
|
200
|
+
rescue Errno::ENOENT
|
|
201
|
+
skip "connector", "can't check for running processes here"
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def connector_running_for?(handle)
|
|
205
|
+
commands = IO.popen([ "pgrep", "-lf", "shapeup connect" ], err: File::NULL, &:readlines)
|
|
206
|
+
commands.any? { |command| command.match?(/--as @?#{Regexp.escape(handle)}\b/) || !command.include?("--as") }
|
|
161
207
|
end
|
|
162
208
|
|
|
163
209
|
def pass(name, message) = Check.new(name: name, status: :pass, message: message)
|
data/lib/shapeup_cli/config.rb
CHANGED
data/lib/shapeup_cli/version.rb
CHANGED
|
@@ -134,7 +134,7 @@ Don't poll the inbox yourself. The connector does that.
|
|
|
134
134
|
|
|
135
135
|
## Handle a request, within seconds
|
|
136
136
|
|
|
137
|
-
A `request` line carries `id`, `reason` (mentioned, assigned or watching), `issue`, `request`
|
|
137
|
+
A `request` line carries `id`, `reason` (mentioned, replied, assigned or watching), `issue`, `request`
|
|
138
138
|
(the words that asked), `requester` and `reply_to`.
|
|
139
139
|
|
|
140
140
|
1. **Acknowledge it.** When `request.comment_id` is set, react to it:
|