CopilotKit / CopilotKit/outpost
Slack ticket mirror: reply-level dedup, surrogate-safe truncation, WebClient reuse
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7
- Forks
- 3
- Avg merge
- 7d 16h
- Merged PRs (30d)
- 15
Description
Follow-ups deliberately left open by #150 (the Slack ticket mirror). All three were raised by the CR rounds on that PR and verified; none blocks the mirror shipping inert.
1. A duplicate reply job re-posts its message
handleSlackMirror makes the TicketExternalLink row the idempotent identity of the thread, so two jobs can no longer open rival threads. It does not dedupe reply posts: if a reply job is retried after its postMessage succeeded (a job timeout that does not cancel the handler, a throw in reportProgress, a re-thrown transient error), the same message is posted into the thread again.
Fixing this needs a per-message marker — e.g. a mirroredAt column on Message, or a metadata entry on the link row keyed by message id — checked before posting. That is a schema decision, which is why it was not smuggled into #150.
packages/outpost/queue/src/handlers/slack-mirror.ts — the idempotency docblock states this limitation explicitly.
2. truncate splits surrogate pairs
value.slice(0, max - 1) can cut an astral character (emoji, many CJK extension chars) in half, producing a lone surrogate in the Slack payload. Use Array.from / Intl.Segmenter or a code-point-aware slice.
3. A new WebClient per job
buildPoster constructs a fresh @slack/web-api client on every job. At mirror volumes this is minor, but it discards connection reuse and the client's rate-limit state, which is precisely the state you want shared across posts. Cache one client per token.
Found by: CR rounds 1-2 on #150.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in packages/outpost/queue/src/handlers/slack-mirror.ts, reading the idempotency docblock and tracing handleSlackMirror, truncate, and buildPoster. Decide on the per-message marker described in the issue, then verify that retried replies are not reposted, truncation preserves surrogate pairs, and WebClient instances are reused per token.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100