@dreki-gg/pi-slack 0.2.0 → 0.3.0

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @dreki-gg/pi-slack
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Add `slack_edit_message` tool so the agent can edit messages it previously posted. Pass the `channel` ID and the message `ts` (returned by `slack_post_message`) along with the new `text` to rewrite a message via Slack's `chat.update`. Reuses the existing `chat:write` scope — bots can only edit their own messages.
8
+
3
9
  ## 0.2.0
4
10
 
5
11
  ### Minor Changes
package/README.md CHANGED
@@ -13,6 +13,8 @@ Uses [Effect](https://effect.website) for the Slack client layer (typed errors,
13
13
  | `slack_read_thread` | Read replies in a thread |
14
14
  | `slack_search` | Full-text search across workspace (requires user token) |
15
15
  | `slack_download_file` | Download a shared file/image to temp directory |
16
+ | `slack_post_message` | Post a message to a channel or reply in a thread (requires `chat:write`) |
17
+ | `slack_edit_message` | Edit a message the bot previously posted (requires `chat:write`) |
16
18
 
17
19
  ## Setup
18
20
 
@@ -12,6 +12,13 @@ export interface PostMessageResult {
12
12
  channel: string;
13
13
  }
14
14
 
15
+ export interface EditMessageResult {
16
+ /** Timestamp of the edited message. */
17
+ ts: string;
18
+ /** Channel the message lives in. */
19
+ channel: string;
20
+ }
21
+
15
22
  // ---------------------------------------------------------------------------
16
23
  // Effects
17
24
  // ---------------------------------------------------------------------------
@@ -41,3 +48,18 @@ export function postMessage(params: {
41
48
  } satisfies PostMessageResult;
42
49
  });
43
50
  }
51
+
52
+ export function editMessage(params: { channel: string; ts: string; text: string }) {
53
+ return Effect.gen(function* () {
54
+ const resp = yield* slackPost<{ ok: true; ts: string; channel: string }>('chat.update', {
55
+ channel: params.channel,
56
+ ts: params.ts,
57
+ text: params.text,
58
+ });
59
+
60
+ return {
61
+ ts: resp.ts,
62
+ channel: resp.channel,
63
+ } satisfies EditMessageResult;
64
+ });
65
+ }
@@ -1,7 +1,7 @@
1
1
  import type { SlackChannel, SlackMessage, ReadMessagesResult } from './client/channels.js';
2
2
  import type { SearchResult } from './client/search.js';
3
3
  import type { DownloadedFile, SlackFileInfo } from './client/files.js';
4
- import type { PostMessageResult } from './client/messages.js';
4
+ import type { PostMessageResult, EditMessageResult } from './client/messages.js';
5
5
 
6
6
  // ---------------------------------------------------------------------------
7
7
  // Channels
@@ -85,16 +85,15 @@ export function formatSearchResults(result: SearchResult, query: string): string
85
85
  // Posting
86
86
  // ---------------------------------------------------------------------------
87
87
 
88
- export function formatPostedMessage(
89
- result: PostMessageResult,
90
- threadTs?: string,
91
- ): string {
92
- const where = threadTs
93
- ? `thread ${threadTs} in ${result.channel}`
94
- : `${result.channel}`;
88
+ export function formatPostedMessage(result: PostMessageResult, threadTs?: string): string {
89
+ const where = threadTs ? `thread ${threadTs} in ${result.channel}` : `${result.channel}`;
95
90
  return `✅ Message posted to ${where} (ts: ${result.ts})`;
96
91
  }
97
92
 
93
+ export function formatEditedMessage(result: EditMessageResult): string {
94
+ return `✏️ Message edited in ${result.channel} (ts: ${result.ts})`;
95
+ }
96
+
98
97
  // ---------------------------------------------------------------------------
99
98
  // Files
100
99
  // ---------------------------------------------------------------------------
@@ -14,7 +14,7 @@ import { listChannels } from './client/channels.js';
14
14
  import { readMessages, readThread } from './client/channels.js';
15
15
  import { searchMessages } from './client/search.js';
16
16
  import { downloadFile } from './client/files.js';
17
- import { postMessage } from './client/messages.js';
17
+ import { postMessage, editMessage } from './client/messages.js';
18
18
  import {
19
19
  formatChannelList,
20
20
  formatMessages,
@@ -22,6 +22,7 @@ import {
22
22
  formatSearchResults,
23
23
  formatDownloadedFile,
24
24
  formatPostedMessage,
25
+ formatEditedMessage,
25
26
  } from './format.js';
26
27
  import {
27
28
  TOOL_GUIDELINES,
@@ -31,6 +32,7 @@ import {
31
32
  searchParams,
32
33
  downloadFileParams,
33
34
  postMessageParams,
35
+ editMessageParams,
34
36
  } from './tools.js';
35
37
 
36
38
  // ---------------------------------------------------------------------------
@@ -334,6 +336,49 @@ export default function slackExtension(pi: ExtensionAPI) {
334
336
  },
335
337
  });
336
338
 
339
+ // -------------------------------------------------------------------------
340
+ // slack_edit_message
341
+ // -------------------------------------------------------------------------
342
+
343
+ pi.registerTool({
344
+ name: 'slack_edit_message',
345
+ label: 'Slack Edit Message',
346
+ description:
347
+ 'Edit a message the bot previously posted. Requires the bot token to have the `chat:write` scope. Bots can only edit their own messages.',
348
+ promptSnippet: 'Edit a message the bot previously posted',
349
+ promptGuidelines: TOOL_GUIDELINES,
350
+ parameters: editMessageParams,
351
+
352
+ async execute(
353
+ _toolCallId: string,
354
+ params: {
355
+ channel: string;
356
+ ts: string;
357
+ text: string;
358
+ },
359
+ ) {
360
+ const creds = getCredentials();
361
+ if (!creds) return missingCredentials('bot');
362
+
363
+ try {
364
+ const result = await runSlack(
365
+ creds,
366
+ editMessage({
367
+ channel: params.channel,
368
+ ts: params.ts,
369
+ text: params.text,
370
+ }),
371
+ );
372
+ return textResult(formatEditedMessage(result), {
373
+ channel: result.channel,
374
+ ts: result.ts,
375
+ });
376
+ } catch (err) {
377
+ return errorResult(`❌ ${(err as Error).message}`);
378
+ }
379
+ },
380
+ });
381
+
337
382
  // -------------------------------------------------------------------------
338
383
  // /slack command — status check
339
384
  // -------------------------------------------------------------------------
@@ -12,6 +12,7 @@ export const TOOL_GUIDELINES = [
12
12
  'Use `slack_search` for full-text search across the workspace. Requires SLACK_USER_TOKEN to be set.',
13
13
  'Use `slack_download_file` to download images or files shared in Slack. The tool saves files to a temp directory and returns the path — use `read` to view images.',
14
14
  'Use `slack_post_message` to send a message to a channel or reply in a thread. The bot token must have the `chat:write` scope and the bot must be a member of the target channel.',
15
+ 'Use `slack_edit_message` to edit a message the bot previously posted. Pass the channel ID and the message `ts` (returned by `slack_post_message`). Bots can only edit their own messages.',
15
16
  'When messages reference files or images (shown with 📎), download them with `slack_download_file` using the file ID to get visual context.',
16
17
  'Channel IDs look like C0123ABC456. Thread timestamps look like 1512085950.000216.',
17
18
  ];
@@ -134,3 +135,15 @@ export const postMessageParams = Type.Object({
134
135
  }),
135
136
  ),
136
137
  });
138
+
139
+ export const editMessageParams = Type.Object({
140
+ channel: Type.String({
141
+ description: 'Channel ID (e.g. C0123ABC456) where the message lives.',
142
+ }),
143
+ ts: Type.String({
144
+ description: 'Timestamp of the message to edit (the `ts` returned by slack_post_message).',
145
+ }),
146
+ text: Type.String({
147
+ description: 'New message text. Supports Slack mrkdwn formatting.',
148
+ }),
149
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dreki-gg/pi-slack",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Slack read tools for pi — messages, threads, channels, search, and file/image downloads with Effect-powered client",
5
5
  "keywords": [
6
6
  "pi-package",