You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Second half of the Slack chat connector — depends on the client/data issue.
Implement the Socket Mode listener + the core.ChatBridge/ChatCapable adapter.
Source from /tmp/pilot-src/internal/adapters/slack/ (socket_mode.go, socketmode.go, handler.go). Mirror sdk/integrations/telegram/ (bridge.go +
adapter.go) and the chat contract (.agent/system/chat-bridge-design.md).
This is the first SDK runtime external dependency — Socket Mode needs a
WebSocket client (github.com/gorilla/websocket, as in Pilot). go.mod require
go.sum appear in the repo for the first time → run make tidy and commit
both go.mod and go.sum. sdk/{core,log,util,testutil} stay stdlib-only.
Remove every github.com/qf-studio/pilot/... import; inject *slog.Logger.
Port the Socket Mode WS client (connect to the Slack gateway via apps.connections.open,
hello/authenticate, heartbeat, read envelopes, ack). Uses gorilla/websocket.
adapter.go: Adapter with Name() "slack" + NewChatBridge(core.ChatDeps) core.ChatBridge. Compile-time: var _ core.Adapter = (*Adapter)(nil), var _ core.ChatCapable = (*Adapter)(nil), var _ core.ChatBridge = (*bridge)(nil).
bridge.go implements core.ChatBridge:
Start(ctx) — run the Socket Mode loop; for each inbound envelope map to a core.MessageEvent: message/app_mention → Action:"message" (text with
bot-mention stripped, sanitized in the loop before the handler — CRITICAL,
the feat(sdk/integrations/github): port client, types, converter, notifier, webhook #28-class rule); leading / → Action:"command" (Command+Args, no
execution); block_actions → Action:"callback" (CallbackID = action_id,
Data = value). Enforce AllowedChannels/AllowedUsers. ChannelID = channel,
ThreadID = thread_ts.
Send(ctx, OutboundMessage) (MessageRef, error) — PostMessage, or PostInteractiveMessage rendering OutboundMessage.Buttons as a Block Kit
actions block. MessageRef = {ChannelID, MessageID: ts, ThreadID}.
Edit(ctx, ref, text) — UpdateMessage by ts.
Ack(ctx, callbackID) — ack the Socket Mode envelope for that interaction.
Tests use sdk/testutil fakes; include a guard that inbound Text with
invisible-Unicode smuggling is sanitized before the handler sees it. Use an httptest/fake-WS seam so tests don't hit the network.
⛔ Touch ONLY sdk/integrations/slack/ and the top-level go.mod/go.sum for
the new dep. Do not modify sdk/core/ or other connectors.
Start maps message/command/callback (block_actions) to core.MessageEvent; inbound Text sanitized in the live loop before HandleMessage (grep shows the call-site).
go.mod + go.sum committed (gorilla/websocket); go mod tidy a no-op when re-run; sdk/{core,log,util,testutil} still stdlib-only.
grep -rn "qf-studio/pilot" sdk/ nothing; no command EXECUTION; Send renders Buttons as Block Kit.
go build ./..., go vet ./..., go test -race ./sdk/integrations/slack/..., gofmt -l sdk/ all clean.
Context
Second half of the Slack chat connector — depends on the client/data issue.
Implement the Socket Mode listener + the
core.ChatBridge/ChatCapableadapter.Source from
/tmp/pilot-src/internal/adapters/slack/(socket_mode.go,socketmode.go,handler.go). Mirrorsdk/integrations/telegram/(bridge.go +adapter.go) and the chat contract (
.agent/system/chat-bridge-design.md).This is the first SDK runtime external dependency — Socket Mode needs a
WebSocket client (
github.com/gorilla/websocket, as in Pilot).go.modrequirego.sumappear in the repo for the first time → runmake tidyand commitboth
go.modandgo.sum.sdk/{core,log,util,testutil}stay stdlib-only.Implementation
Add to
sdk/integrations/slack/:socketmode.go(WS client),bridge.go(
core.ChatBridge),adapter.go(core.ChatCapable), + tests. Transformations:github.com/qf-studio/pilot/...import; inject*slog.Logger.apps.connections.open,hello/authenticate, heartbeat, read envelopes, ack). Uses
gorilla/websocket.adapter.go:AdapterwithName() "slack"+NewChatBridge(core.ChatDeps) core.ChatBridge. Compile-time:var _ core.Adapter = (*Adapter)(nil),var _ core.ChatCapable = (*Adapter)(nil),var _ core.ChatBridge = (*bridge)(nil).bridge.goimplementscore.ChatBridge:Start(ctx)— run the Socket Mode loop; for each inbound envelope map to acore.MessageEvent:message/app_mention→Action:"message"(text withbot-mention stripped, sanitized in the loop before the handler — CRITICAL,
the feat(sdk/integrations/github): port client, types, converter, notifier, webhook #28-class rule); leading
/→Action:"command"(Command+Args, noexecution);
block_actions→Action:"callback"(CallbackID = action_id,Data = value). Enforce AllowedChannels/AllowedUsers. ChannelID = channel,
ThreadID = thread_ts.
Send(ctx, OutboundMessage) (MessageRef, error)—PostMessage, orPostInteractiveMessagerenderingOutboundMessage.Buttonsas a Block Kitactions block. MessageRef = {ChannelID, MessageID: ts, ThreadID}.
Edit(ctx, ref, text)—UpdateMessageby ts.Ack(ctx, callbackID)— ack the Socket Mode envelope for that interaction.sdk/testutilfakes; include a guard that inboundTextwithinvisible-Unicode smuggling is sanitized before the handler sees it. Use an
httptest/fake-WS seam so tests don't hit the network.⛔ Touch ONLY
sdk/integrations/slack/and the top-levelgo.mod/go.sumforthe new dep. Do not modify
sdk/core/or other connectors.Acceptance
socketmode.go,bridge.go,adapter.go(+ tests) exist; the 3 compile-timecoreassertions present;Name()returns"slack".Startmaps message/command/callback (block_actions) tocore.MessageEvent; inboundTextsanitized in the live loop beforeHandleMessage(grep shows the call-site).go.mod+go.sumcommitted (gorilla/websocket);go mod tidya no-op when re-run;sdk/{core,log,util,testutil}still stdlib-only.grep -rn "qf-studio/pilot" sdk/nothing; no command EXECUTION;SendrendersButtonsas Block Kit.go build ./...,go vet ./...,go test -race ./sdk/integrations/slack/...,gofmt -l sdk/all clean.