feat: enrich slack create response metadata#160
Conversation
Co-authored-by: Son Dao <son.dao@katalon.com>
There was a problem hiding this comment.
Pull request overview
This PR enriches Slack create-operation responses so agents receive normalized identity and continuation metadata after posting messages or uploading files.
Changes:
- Adds normalized Slack message response metadata for
slack-post-message. - Expands
slack-uploadsuccess output with file identity and known locators. - Updates tests, e2e assertions, and Slack usage documentation for the new response contract.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
packages/remote-cli/src/slack-post-message.ts |
Builds and returns normalized created-message metadata. |
packages/remote-cli/src/slack-post-message.test.ts |
Updates expectations and adds fallback-channel coverage. |
docker/opencode/bin/slack-upload |
Emits normalized file identity and continuation metadata. |
scripts/test-e2e.sh |
Validates enriched slack-upload output in e2e flow. |
docker/opencode/config/skills/slack/SKILL.md |
Documents response handling for Slack create helpers. |
docs/plan/2026050501_slack-post-message.md |
Updates the implementation plan and decision log for enriched responses. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| 4. remote-cli appends the alias via `appendCorrelationAlias(sessionId, correlationKey)` when a Thor session ID is present, where `correlationKey` is `slack:thread:${aliasTs}`: | ||
| - `aliasTs = thread_ts` for replies | ||
| - `aliasTs = response.ts` for new top-level messages |
There was a problem hiding this comment.
Good catch. I updated the plan wording to describe the channel-qualified primary key (slack:thread:<channel>/<ts>) plus the legacy fallback and pushed 44e2fe0.
AI-generated — verify before acting. View Thor context
| | D6 | Register aliases in remote-cli after Slack `ok: true` without mutating stdout | remote-cli has the session/call IDs and existing alias writer. Keeping raw Slack JSON on stdout preserves agent/API expectations and avoids response rewriting. | | ||
| | D6 | Register aliases in remote-cli after Slack `ok: true` without making aliasing part of the visible response contract | remote-cli has the session/call IDs and existing alias writer. Alias registration should remain a side effect of a successful Slack write; visible stdout is governed by the created-resource response contract in D20. | | ||
| | D7 | Treat alias registration failure as logged side-effect failure after a successful Slack post | Retrying a successful post solely because bookkeeping failed can duplicate user-visible Slack messages. Operators need logs, but users should not get duplicate replies. | | ||
| | D8 | Keep channel ID out of alias storage in this branch | Existing resolver keys are `slack:thread:{ts}`. Redesigning alias metadata would widen the feature; the CLI can require `--channel` explicitly for now. | |
There was a problem hiding this comment.
Updated. I revised the plan/decision-log wording to reflect the current channel-qualified alias model with ts-only fallback for back-compat, and pushed 44e2fe0.
AI-generated — verify before acting. View Thor context
|
|
||
| ### 2026-05-27 scope update — created resource response enrichment | ||
|
|
||
| This branch should also stop collapsing successful Slack create/write responses to `{"ok":true}` or a bare `{ ts }`. The controlled Slack paths now need to return enough structured identity and locator data for agents and follow-up Thor code to continue in the created resource without scraping logs or relying on hidden alias state. |
There was a problem hiding this comment.
Thanks — I see the mismatch. This follow-up came from Copilot rather than the original requester, so I’m pausing before changing scope/code again. I’ll confirm with the original requester whether they want this branch to (a) include the approval-card helper too, or (b) narrow the plan text to the agent-facing commands only, then follow up here.
AI-generated — verify before acting. View Thor context
There was a problem hiding this comment.
Fixed. I updated the approval path so approval_required now includes the enriched Slack notification metadata (channel, threadTs, messageTs, continuation), the approval store keeps the same locator data, and the plan text now explicitly includes approval-card Slack posts. Pushed in 0c7f26d with targeted test coverage and remote-cli typecheck.
AI-generated — verify before acting. View Thor context
Co-authored-by: Son Dao <son.dao@katalon.com>
Move slack-upload's logic out of an inline-node shell script into packages/opencode-cli/src/slack-upload.ts so it goes through tsc and zod-validates the Slack response shapes. The bin entry stays as a thin wrapper exec'ing the bundled .mjs, matching the git/mcp pattern. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Drop fields callers can derive or don't act on: `continuation`, `ok`, `channel`, and `message_ts` from `SlackCreatedMessageResponse`; the event-payload `notification` from `approval_required`. Source `thread_ts` from Slack's `message.thread_ts` so threaded replies report the truth (and degrade to top-level if Slack downgrades the post) instead of echoing the request. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Drop the bespoke output object (`ok`/`file_id`/`file`/`files`/`channel`/ `thread_ts`) and write Slack's `files.completeUploadExternal` response to stdout verbatim. Removes the normalize/synthesis layer and the echoed inputs the caller already knows. Update the e2e assertion to read `files.0.id` from the upstream shape; the reply-fetching loop right after still verifies thread placement. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Swap the hand-rolled fetch + per-field `as` casts in
`postSlackMessageApi` for `WebClient.chat.postMessage`. Inject the
client as a dep so tests can mock `{ chat: { postMessage } }` directly
instead of stubbing Slack HTTP responses. Rename mcp-handler's
`fetchImpl` dep to `slackClient`. slack-upload stays on curl: it runs
behind mitmproxy which injects auth on the wire, and the SDK would
require a dummy token the CLI deliberately never holds.
Record D21–D24 in the plan covering the SDK switch, the response-shape
trim, the truthful `thread_ts` source, and the slack-upload passthrough.
Drop a redundant `slackPostMessage.toHaveBeenCalledTimes` assertion that
duplicated the persisted notification check.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…esource-responses
|
@copilot resolve the merge conflicts in this pull request |
Resolved in |
|
@copilot resolve the merge conflicts in this pull request |
…esource-responses # Conflicts: # packages/remote-cli/src/mcp-handler.test.ts
Resolved in |
This reverts commit bd44edf.
…esource-responses
Summary
Testing
AI-generated — verify before acting. View Thor context