@assemblyline-agents/slack 1.0.0 → 3.0.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/LICENSE +1 -1
- package/README.md +133 -1
- package/dist/context.d.ts +7 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +236 -0
- package/dist/context.js.map +1 -0
- package/dist/error-detail.d.ts +3 -0
- package/dist/error-detail.d.ts.map +1 -0
- package/dist/error-detail.js +27 -0
- package/dist/error-detail.js.map +1 -0
- package/dist/index.d.ts +12 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +372 -203
- package/dist/index.js.map +1 -1
- package/dist/message-context.d.ts +26 -0
- package/dist/message-context.d.ts.map +1 -0
- package/dist/message-context.js +165 -0
- package/dist/message-context.js.map +1 -0
- package/dist/outbound-markdown.d.ts +8 -0
- package/dist/outbound-markdown.d.ts.map +1 -0
- package/dist/outbound-markdown.js +30 -0
- package/dist/outbound-markdown.js.map +1 -0
- package/dist/slack-api.d.ts +6 -0
- package/dist/slack-api.d.ts.map +1 -0
- package/dist/slack-api.js +40 -0
- package/dist/slack-api.js.map +1 -0
- package/dist/workspace-credentials.d.ts +11 -0
- package/dist/workspace-credentials.d.ts.map +1 -0
- package/dist/workspace-credentials.js +57 -0
- package/dist/workspace-credentials.js.map +1 -0
- package/package.json +4 -4
- package/templates/slack-app-manifest.json +47 -0
- package/skills/slack/SKILL.md +0 -8
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -2,7 +2,113 @@
|
|
|
2
2
|
|
|
3
3
|
Official Assembly Line Slack channel plugin.
|
|
4
4
|
|
|
5
|
-
It exports `defineSlackChannel(options)`, which receives Slack Events API callbacks over HTTP (with request-signature verification) and delivers agent replies through the Slack Web API, including file uploads and recent-activity context. The package also registers a Slack connection plugin (`defineSlackConnection`)
|
|
5
|
+
It exports `defineSlackChannel(options)`, which receives Slack Events API callbacks over HTTP (with request-signature verification) and delivers agent replies through the Slack Web API, including file uploads and recent-activity context. The package also registers a Slack connection plugin (`defineSlackConnection`). A single installation requires `SLACK_SIGNING_SECRET`, `SLACK_BOT_TOKEN`, and the default bot scopes including `files:read` and `files:write`.
|
|
6
|
+
|
|
7
|
+
Inbound message text is decoded from Slack's mrkdwn transport form before it
|
|
8
|
+
reaches the agent: auto-linked URLs (`<https://…>`, `<https://…|label>`)
|
|
9
|
+
collapse back to the bare URL and Slack's HTML entity escapes (`&`,
|
|
10
|
+
`<`, `>`) are restored, so pasted content such as one-time connection
|
|
11
|
+
pairing packets arrives exactly as the user typed it. Mention and command
|
|
12
|
+
sequences (`<@…>`, `<#…>`, `<!…>`) pass through unchanged.
|
|
13
|
+
|
|
14
|
+
Inbound files preserve their Slack media type and attachment classification.
|
|
15
|
+
Voice clips are therefore routed through any configured gateway media processor,
|
|
16
|
+
such as `openRouterAudioTranscription()`, before the model receives the turn.
|
|
17
|
+
|
|
18
|
+
Text-only outbound replies use Slack's standard-Markdown `markdown_text` field, so
|
|
19
|
+
headings, bold text, labeled links, lists, tables, and code from an agent render
|
|
20
|
+
natively without Slack-specific prompting. Responses larger than Slack's
|
|
21
|
+
12,000-character field limit are split at natural text boundaries and delivered
|
|
22
|
+
as consecutive messages to the same preserved channel and thread. Delivery also
|
|
23
|
+
neutralizes broadcast commands: `<!here>`, `<!channel>`, and `<!everyone>`
|
|
24
|
+
(with or without a `|label`) are replaced with their plain-text forms (`@here`,
|
|
25
|
+
`@channel`, `@everyone`), which Slack renders inert. An agent that quotes user
|
|
26
|
+
input therefore cannot ping the whole channel; links and user mentions in
|
|
27
|
+
outbound text keep working.
|
|
28
|
+
|
|
29
|
+
File delivery is explicit and durable. An agent calls `deliver_artifact` once
|
|
30
|
+
for every completed `/workspace` file it needs to attach. The connector posts
|
|
31
|
+
the final response together with all selected files and reports success only
|
|
32
|
+
when Slack confirms every file id. Upload or completion failures leave the
|
|
33
|
+
combined delivery unsent for that attempt and the durable queue retries it. If
|
|
34
|
+
the queue exhausts its attempts, the runtime records `deliveryStatus: "failed"`
|
|
35
|
+
on the run and creates one text-only failure notice naming the preserved files
|
|
36
|
+
and containing the real delivery error. The ticket declares the exact byte
|
|
37
|
+
length to Slack; the raw upload leaves HTTP `Content-Length` framing to the
|
|
38
|
+
runtime fetch implementation.
|
|
39
|
+
|
|
40
|
+
The connector uses Slack's native agent loading status on every turn. It starts
|
|
41
|
+
with `is working...` and cycles these ten messages under the composer in a new
|
|
42
|
+
random order for each turn:
|
|
43
|
+
|
|
44
|
+
`Beboppin'`, `Boondoggling`, `Cerebrating`, `Combobulating`, `Cooking`,
|
|
45
|
+
`Elucidating`, `Flibbertigibbeting`, `Hullaballooing`, `Ionizing`, and
|
|
46
|
+
`Photosynthesizing`.
|
|
47
|
+
|
|
48
|
+
This behavior is automatic for every deployment and uses the required
|
|
49
|
+
`chat:write` scope. The connector refreshes the status every 90 seconds so it
|
|
50
|
+
stays visible for turns longer than Slack's two-minute status timeout, then
|
|
51
|
+
stops the heartbeat and clears the status when the turn exits. Status updates
|
|
52
|
+
are best-effort, so a Slack-side status error does not prevent the agent from
|
|
53
|
+
completing or delivering its reply. Each heartbeat reuses the turn's shuffled
|
|
54
|
+
order so the sequence does not reset or change while that turn is running.
|
|
55
|
+
|
|
56
|
+
One agent endpoint can serve multiple Slack workspace installations by setting
|
|
57
|
+
`SLACK_WORKSPACE_CREDENTIALS_JSON`. The object is keyed by Slack team ID, and
|
|
58
|
+
each value may contain `signingSecret`, `botToken`, and `botUserId`:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"T01234567": {
|
|
63
|
+
"signingSecret": "...",
|
|
64
|
+
"botToken": "xoxb-...",
|
|
65
|
+
"botUserId": "U01234567"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The original single-workspace variables remain the fallback. Incoming request
|
|
71
|
+
verification, private-file downloads, replies, and uploads all select the
|
|
72
|
+
credentials associated with the event's team ID. Slack URL-verification
|
|
73
|
+
callbacks may omit that ID, so only that callback shape is checked against the
|
|
74
|
+
configured signing-secret set; team-identified events remain pinned to their
|
|
75
|
+
mapped secret.
|
|
76
|
+
|
|
77
|
+
Slack turns include a provider-scoped user principal by default. Map that
|
|
78
|
+
sender to a canonical company identity before agent hooks run when roles,
|
|
79
|
+
memory, or connection grants must follow the employee across channels:
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
export default defineSlackChannel({
|
|
83
|
+
async resolvePrincipal(turn) {
|
|
84
|
+
const employee = await lookupEmployee(turn.userId!);
|
|
85
|
+
if (!employee) throw new Error("Unknown Slack user.");
|
|
86
|
+
return {
|
|
87
|
+
type: "user",
|
|
88
|
+
id: employee.id,
|
|
89
|
+
issuer: "company-directory",
|
|
90
|
+
attributes: { roles: employee.roles }
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Slack also reports each surface's privacy. DMs and assistant threads are
|
|
97
|
+
private to the authenticated principal; channel threads are shared. When the
|
|
98
|
+
agent opts into `audienceIsolation: true` in `agent.ts`, the runtime uses that
|
|
99
|
+
boundary for memory, history, personal connections, subagents, schedules, and
|
|
100
|
+
delivery, so private DM context is unavailable in a channel or another user's
|
|
101
|
+
DM. Without the opt-in (the default), every surface is trusted and the signal
|
|
102
|
+
has no effect.
|
|
103
|
+
|
|
104
|
+
Under isolation, a personal Slack where every channel belongs to one trusted
|
|
105
|
+
owner can still mark every surface private:
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
export default defineSlackChannel({
|
|
109
|
+
isPrivateSurface: () => true
|
|
110
|
+
});
|
|
111
|
+
```
|
|
6
112
|
|
|
7
113
|
## Install
|
|
8
114
|
|
|
@@ -10,6 +116,32 @@ It exports `defineSlackChannel(options)`, which receives Slack Events API callba
|
|
|
10
116
|
npm install @assemblyline-agents/slack
|
|
11
117
|
```
|
|
12
118
|
|
|
119
|
+
With the Assembly Line CLI, add the channel instead:
|
|
120
|
+
|
|
121
|
+
```sh
|
|
122
|
+
assembly-line add slack /path/to/agent
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
This creates both `channels/slack.ts` and `slack-app-manifest.json`. The latter
|
|
126
|
+
comes from the package's reusable
|
|
127
|
+
[`templates/slack-app-manifest.json`](templates/slack-app-manifest.json) and
|
|
128
|
+
contains the bot scopes and `app_mention`/`message.im` event subscriptions
|
|
129
|
+
expected by the connector.
|
|
130
|
+
|
|
131
|
+
1. Replace `https://your-agent.example.com/slack/events` in the generated
|
|
132
|
+
manifest with the deployed agent URL.
|
|
133
|
+
2. In Slack's app dashboard, create an app **from an app manifest** and paste or
|
|
134
|
+
upload the JSON.
|
|
135
|
+
3. Install the app to the workspace.
|
|
136
|
+
4. Set `SLACK_SIGNING_SECRET` from **Basic Information** and
|
|
137
|
+
`SLACK_BOT_TOKEN` from **OAuth & Permissions** in the agent environment.
|
|
138
|
+
5. Verify the installation with `assembly-line channels check /path/to/agent`.
|
|
139
|
+
|
|
140
|
+
The loading indicator only needs `chat:write`. The default manifest also
|
|
141
|
+
includes optional `groups:history` so private-channel thread context works
|
|
142
|
+
without another reinstall. Remove `groups:history` if the bot will never be
|
|
143
|
+
invited to private channels.
|
|
144
|
+
|
|
13
145
|
## Part of Assembly Line
|
|
14
146
|
|
|
15
147
|
This package is part of [Assembly Line](https://github.com/jasonbadeaux/assembly-line), a vendor-neutral, filesystem-first framework for durable AI agents. See the developer documentation in [docs/developers/](https://github.com/jasonbadeaux/assembly-line/tree/main/docs/developers) for setup, agent authoring, and deployment guides.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { JsonObject } from "@assemblyline-agents/core";
|
|
2
|
+
import type { ChannelContext, ChannelTurn } from "@assemblyline-agents/runtime";
|
|
3
|
+
export declare function augmentContext(turn: ChannelTurn, ctx: ChannelContext): Promise<{
|
|
4
|
+
recentHistory?: string[];
|
|
5
|
+
channelContext?: JsonObject;
|
|
6
|
+
} | void>;
|
|
7
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,2BAA2B,CAAC;AACvE,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EAIZ,MAAM,8BAA8B,CAAC;AAetC,wBAAsB,cAAc,CAClC,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC;IAAE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,cAAc,CAAC,EAAE,UAAU,CAAA;CAAE,GAAG,IAAI,CAAC,CAyF3E"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { principalKey } from "@assemblyline-agents/runtime";
|
|
2
|
+
import { slackApi } from "./slack-api.js";
|
|
3
|
+
import { slackHistoryObservation } from "./message-context.js";
|
|
4
|
+
const SLACK_RECENT_ACTIVITY_HOURS = 24;
|
|
5
|
+
const SLACK_RECENT_ACTIVITY_LIMIT = 3;
|
|
6
|
+
const SLACK_RECENT_HISTORY_LIMIT = 20;
|
|
7
|
+
const SLACK_THREAD_DELTA_SCAN_LIMIT = 60;
|
|
8
|
+
const SLACK_THREAD_DELTA_LIMIT = 12;
|
|
9
|
+
const SLACK_CHANNEL_MATCH_LIMIT = 8;
|
|
10
|
+
const SLACK_CHANNEL_RECENT_LIMIT = 3;
|
|
11
|
+
const SLACK_HISTORY_HYDRATION_LIMIT = 15;
|
|
12
|
+
const SLACK_SUMMARY_MAX_CHARS = 240;
|
|
13
|
+
export async function augmentContext(turn, ctx) {
|
|
14
|
+
const slack = recordValue(turn.metadata?.slack);
|
|
15
|
+
const source = recordValue(turn.metadata?.source);
|
|
16
|
+
const surface = stringValue(slack?.surface);
|
|
17
|
+
const hydration = surface === "channel"
|
|
18
|
+
? await hydrateSlackChannelHistory(turn, ctx, slack, source)
|
|
19
|
+
: { status: "not_applicable", observed: 0 };
|
|
20
|
+
const conversationMessages = await ctx.state.listRecentMessages(turn.conversationId, SLACK_THREAD_DELTA_SCAN_LIMIT);
|
|
21
|
+
const recentHistory = conversationMessages
|
|
22
|
+
.filter((message) => message.content.observed !== true)
|
|
23
|
+
.slice(-SLACK_RECENT_HISTORY_LIMIT)
|
|
24
|
+
.map(messageHistoryLine);
|
|
25
|
+
const threadDelta = surface === "channel"
|
|
26
|
+
? unseenObservedThreadMessages(conversationMessages).map((message) => historyContextMessage(message, {}))
|
|
27
|
+
: [];
|
|
28
|
+
const channelSearchScope = surface === "channel" && source
|
|
29
|
+
? {
|
|
30
|
+
agentScope: ctx.agentScope,
|
|
31
|
+
channel: turn.channel,
|
|
32
|
+
source: {
|
|
33
|
+
provider: stringValue(source.provider) ?? "slack",
|
|
34
|
+
workspaceId: stringValue(source.workspaceId) ?? "unknown",
|
|
35
|
+
channelId: stringValue(source.channelId) ?? stringValue(slack?.channel) ?? "unknown"
|
|
36
|
+
},
|
|
37
|
+
excludeConversationId: turn.conversationId,
|
|
38
|
+
limit: SLACK_CHANNEL_MATCH_LIMIT
|
|
39
|
+
}
|
|
40
|
+
: undefined;
|
|
41
|
+
const [relevantChannelMessages, recentChannelMessages] = channelSearchScope
|
|
42
|
+
? await Promise.all([
|
|
43
|
+
ctx.state.searchMessages({
|
|
44
|
+
...channelSearchScope,
|
|
45
|
+
query: slackHistoryQuery(turn.message)
|
|
46
|
+
}),
|
|
47
|
+
ctx.state.searchMessages({
|
|
48
|
+
...channelSearchScope,
|
|
49
|
+
limit: SLACK_CHANNEL_RECENT_LIMIT
|
|
50
|
+
})
|
|
51
|
+
])
|
|
52
|
+
: [[], []];
|
|
53
|
+
const channelMatches = uniqueMessageMatches([...relevantChannelMessages, ...recentChannelMessages], SLACK_CHANNEL_MATCH_LIMIT);
|
|
54
|
+
const since = new Date(Date.now() - SLACK_RECENT_ACTIVITY_HOURS * 60 * 60 * 1000).toISOString();
|
|
55
|
+
const relatedConversations = turn.audience?.private !== false && surface !== "channel" && turn.userId && ctx.state.listRecentConversationsBySubject
|
|
56
|
+
? await ctx.state.listRecentConversationsBySubject({
|
|
57
|
+
agentScope: ctx.agentScope,
|
|
58
|
+
channel: turn.channel,
|
|
59
|
+
subject: turn.principal ? principalKey(turn.principal) : turn.userId,
|
|
60
|
+
since,
|
|
61
|
+
limit: SLACK_RECENT_ACTIVITY_LIMIT,
|
|
62
|
+
excludeId: turn.conversationId
|
|
63
|
+
})
|
|
64
|
+
: [];
|
|
65
|
+
const related = await Promise.all(relatedConversations.map((conversation) => summarizeConversation(ctx, conversation)));
|
|
66
|
+
return {
|
|
67
|
+
recentHistory,
|
|
68
|
+
channelContext: compactJsonObject({
|
|
69
|
+
provider: "slack",
|
|
70
|
+
surface: stringValue(slack?.surface),
|
|
71
|
+
teamId: stringValue(slack?.teamId),
|
|
72
|
+
enterpriseId: stringValue(slack?.enterpriseId),
|
|
73
|
+
channelId: stringValue(slack?.channel),
|
|
74
|
+
threadTs: stringValue(slack?.threadTs),
|
|
75
|
+
currentConversation: {
|
|
76
|
+
id: turn.conversationId,
|
|
77
|
+
userId: turn.userId ?? null,
|
|
78
|
+
eventId: turn.eventId
|
|
79
|
+
},
|
|
80
|
+
threadDelta,
|
|
81
|
+
channelMatches: channelMatches.map((match) => historyContextMessage(match.message, match.conversationMetadata, match.score)),
|
|
82
|
+
relatedConversations: related,
|
|
83
|
+
contextPolicy: {
|
|
84
|
+
source: "assembly_line_state",
|
|
85
|
+
channelHistory: surface === "channel" ? "scoped_relevance_plus_recency" : "not_applicable",
|
|
86
|
+
hydration,
|
|
87
|
+
threadDeltaLimit: SLACK_THREAD_DELTA_LIMIT,
|
|
88
|
+
channelMatchLimit: SLACK_CHANNEL_MATCH_LIMIT,
|
|
89
|
+
maxRelatedConversations: SLACK_RECENT_ACTIVITY_LIMIT,
|
|
90
|
+
maxAgeHours: SLACK_RECENT_ACTIVITY_HOURS,
|
|
91
|
+
note: "Slack history stays in durable state; only unseen thread messages and bounded scoped search matches enter this turn."
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async function hydrateSlackChannelHistory(turn, ctx, slack, turnSource) {
|
|
97
|
+
const conversation = await ctx.state.getConversation(turn.conversationId);
|
|
98
|
+
const priorHydration = recordValue(conversation?.metadata.slackContextHydration);
|
|
99
|
+
if (stringValue(priorHydration?.hydratedAt)) {
|
|
100
|
+
return compactJsonObject({ status: "cached", observed: numberValue(priorHydration?.observed) ?? 0 });
|
|
101
|
+
}
|
|
102
|
+
if (typeof ctx.agent?.observe !== "function")
|
|
103
|
+
return { status: "unavailable", observed: 0 };
|
|
104
|
+
const channelId = stringValue(turnSource?.channelId) ?? stringValue(slack?.channel);
|
|
105
|
+
const workspaceId = stringValue(turnSource?.workspaceId) ?? stringValue(slack?.enterpriseId) ?? stringValue(slack?.teamId);
|
|
106
|
+
const messageTs = stringValue(slack?.ts) ?? stringValue(recordValue(turn.delivery)?.ts);
|
|
107
|
+
const threadTs = stringValue(slack?.threadTs) ?? stringValue(recordValue(turn.delivery)?.threadTs);
|
|
108
|
+
if (!channelId || !workspaceId || !messageTs)
|
|
109
|
+
return { status: "unavailable", observed: 0 };
|
|
110
|
+
const threaded = Boolean(threadTs && threadTs !== messageTs);
|
|
111
|
+
const method = threaded ? "conversations.replies" : "conversations.history";
|
|
112
|
+
const request = threaded
|
|
113
|
+
? { channel: channelId, ts: threadTs, limit: SLACK_HISTORY_HYDRATION_LIMIT }
|
|
114
|
+
: { channel: channelId, latest: messageTs, inclusive: true, limit: SLACK_HISTORY_HYDRATION_LIMIT };
|
|
115
|
+
try {
|
|
116
|
+
const result = await slackApi(ctx, method, request, stringValue(slack?.teamId));
|
|
117
|
+
const messages = Array.isArray(result.messages) ? result.messages.filter(isJsonObject) : [];
|
|
118
|
+
let observed = 0;
|
|
119
|
+
for (const message of messages) {
|
|
120
|
+
const observation = slackHistoryObservation(message, {
|
|
121
|
+
channelId,
|
|
122
|
+
workspaceId,
|
|
123
|
+
teamId: stringValue(slack?.teamId),
|
|
124
|
+
channelType: stringValue(slack?.channelType),
|
|
125
|
+
currentMessageTs: messageTs
|
|
126
|
+
});
|
|
127
|
+
if (!observation)
|
|
128
|
+
continue;
|
|
129
|
+
await ctx.agent.observe(observation);
|
|
130
|
+
observed += 1;
|
|
131
|
+
}
|
|
132
|
+
const hydratedAt = new Date().toISOString();
|
|
133
|
+
await ctx.state.updateConversation?.(turn.conversationId, {
|
|
134
|
+
metadata: {
|
|
135
|
+
slackContextHydration: { hydratedAt, method, observed }
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
return { status: "hydrated", method, observed };
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
return {
|
|
142
|
+
status: "failed",
|
|
143
|
+
method,
|
|
144
|
+
observed: 0,
|
|
145
|
+
error: error instanceof Error ? truncate(error.message, SLACK_SUMMARY_MAX_CHARS) : "Slack history hydration failed."
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function uniqueMessageMatches(matches, limit) {
|
|
150
|
+
const seen = new Set();
|
|
151
|
+
return matches.filter((match) => {
|
|
152
|
+
if (seen.has(match.message.id))
|
|
153
|
+
return false;
|
|
154
|
+
seen.add(match.message.id);
|
|
155
|
+
return true;
|
|
156
|
+
}).slice(0, limit);
|
|
157
|
+
}
|
|
158
|
+
async function summarizeConversation(ctx, conversation) {
|
|
159
|
+
const messages = await ctx.state.listRecentMessages(conversation.id, 8);
|
|
160
|
+
const latestUser = latestText(messages, "user");
|
|
161
|
+
const latestAssistant = latestText(messages, "assistant");
|
|
162
|
+
const slack = recordValue(conversation.metadata.slack);
|
|
163
|
+
return compactJsonObject({
|
|
164
|
+
conversationId: conversation.id,
|
|
165
|
+
updatedAt: conversation.updatedAt,
|
|
166
|
+
surface: stringValue(slack?.surface),
|
|
167
|
+
channelId: stringValue(slack?.channel),
|
|
168
|
+
threadTs: stringValue(slack?.threadTs),
|
|
169
|
+
latestUser,
|
|
170
|
+
latestAssistant
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
function latestText(messages, role) {
|
|
174
|
+
const message = [...messages].reverse().find((candidate) => candidate.role === role);
|
|
175
|
+
const text = typeof message?.content.text === "string" ? message.content.text : undefined;
|
|
176
|
+
return text ? truncate(text, SLACK_SUMMARY_MAX_CHARS) : undefined;
|
|
177
|
+
}
|
|
178
|
+
function messageHistoryLine(message) {
|
|
179
|
+
const text = typeof message.content.text === "string" ? message.content.text : JSON.stringify(message.content);
|
|
180
|
+
return `${message.role}: ${text}`;
|
|
181
|
+
}
|
|
182
|
+
function unseenObservedThreadMessages(messages) {
|
|
183
|
+
let latestAssistantIndex = -1;
|
|
184
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
185
|
+
if (messages[index]?.role === "assistant") {
|
|
186
|
+
latestAssistantIndex = index;
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return messages
|
|
191
|
+
.slice(latestAssistantIndex + 1)
|
|
192
|
+
.filter((message) => message.content.observed === true && message.content.deleted !== true)
|
|
193
|
+
.slice(-SLACK_THREAD_DELTA_LIMIT);
|
|
194
|
+
}
|
|
195
|
+
function historyContextMessage(message, conversationMetadata, score) {
|
|
196
|
+
const messageSource = recordValue(message.content.source);
|
|
197
|
+
const conversationSource = recordValue(conversationMetadata.source);
|
|
198
|
+
const source = messageSource ?? conversationSource;
|
|
199
|
+
return compactJsonObject({
|
|
200
|
+
messageId: message.id,
|
|
201
|
+
conversationId: message.conversationId,
|
|
202
|
+
role: message.role,
|
|
203
|
+
authorId: stringValue(source?.authorId),
|
|
204
|
+
text: truncate(stringValue(message.content.text) ?? "", SLACK_SUMMARY_MAX_CHARS),
|
|
205
|
+
createdAt: message.createdAt,
|
|
206
|
+
permalink: stringValue(source?.permalink),
|
|
207
|
+
score
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
function slackHistoryQuery(message) {
|
|
211
|
+
return message.replace(/<@[^>]+>/gu, " ").replace(/\s+/gu, " ").trim();
|
|
212
|
+
}
|
|
213
|
+
function compactJsonObject(input) {
|
|
214
|
+
const out = {};
|
|
215
|
+
for (const [key, value] of Object.entries(input)) {
|
|
216
|
+
if (value !== undefined)
|
|
217
|
+
out[key] = value;
|
|
218
|
+
}
|
|
219
|
+
return out;
|
|
220
|
+
}
|
|
221
|
+
function recordValue(value) {
|
|
222
|
+
return isJsonObject(value) ? value : undefined;
|
|
223
|
+
}
|
|
224
|
+
function isJsonObject(value) {
|
|
225
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
226
|
+
}
|
|
227
|
+
function stringValue(value) {
|
|
228
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
229
|
+
}
|
|
230
|
+
function numberValue(value) {
|
|
231
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
232
|
+
}
|
|
233
|
+
function truncate(value, max) {
|
|
234
|
+
return value.length <= max ? value : `${value.slice(0, max - 1)}…`;
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-detail.d.ts","sourceRoot":"","sources":["../src/error-detail.ts"],"names":[],"mappings":"AAEA,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAwBlD"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const MAX_ERROR_CAUSE_DEPTH = 5;
|
|
2
|
+
/** Preserve useful transport diagnostics hidden in nested fetch error causes. */
|
|
3
|
+
export function errorDetail(error) {
|
|
4
|
+
if (!(error instanceof Error))
|
|
5
|
+
return String(error);
|
|
6
|
+
const rootMessage = error.message;
|
|
7
|
+
const details = [];
|
|
8
|
+
const seen = new Set([error]);
|
|
9
|
+
let cause = error.cause;
|
|
10
|
+
let depth = 0;
|
|
11
|
+
while (cause instanceof Error && depth < MAX_ERROR_CAUSE_DEPTH && !seen.has(cause)) {
|
|
12
|
+
seen.add(cause);
|
|
13
|
+
const code = typeof cause.code === "string"
|
|
14
|
+
? cause.code
|
|
15
|
+
: undefined;
|
|
16
|
+
const detail = [code, cause.message].filter(Boolean).join(": ");
|
|
17
|
+
const duplicatesParent = cause.message === rootMessage || rootMessage.endsWith(`: ${cause.message}`);
|
|
18
|
+
if (detail && (!duplicatesParent || code))
|
|
19
|
+
details.push(detail);
|
|
20
|
+
cause = cause.cause;
|
|
21
|
+
depth += 1;
|
|
22
|
+
}
|
|
23
|
+
return details.length > 0
|
|
24
|
+
? `${rootMessage} (${details.join("; caused by ")})`
|
|
25
|
+
: rootMessage;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=error-detail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-detail.js","sourceRoot":"","sources":["../src/error-detail.ts"],"names":[],"mappings":"AAAA,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAEhC,iFAAiF;AACjF,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IAEpD,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC;IAClC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,IAAI,GAAG,CAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IACrC,IAAI,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IACxB,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,OAAO,KAAK,YAAY,KAAK,IAAI,KAAK,GAAG,qBAAqB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACnF,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChB,MAAM,IAAI,GAAG,OAAQ,KAAoC,CAAC,IAAI,KAAK,QAAQ;YACzE,CAAC,CAAE,KAAkC,CAAC,IAAI;YAC1C,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChE,MAAM,gBAAgB,GAAG,KAAK,CAAC,OAAO,KAAK,WAAW,IAAI,WAAW,CAAC,QAAQ,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACrG,IAAI,MAAM,IAAI,CAAC,CAAC,gBAAgB,IAAI,IAAI,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChE,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QACpB,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC;QACvB,CAAC,CAAC,GAAG,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG;QACpD,CAAC,CAAC,WAAW,CAAC;AAClB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { type ChannelDefinition, type JsonObject, type McpPluginConnectionOptions } from "@assemblyline-agents/core";
|
|
2
|
-
import { type ChannelAttachmentRequest, type ChannelContext, type ChannelDelivery, type ChannelHttpRequest, type ChannelHttpResult, type ChannelTurn, type ChannelTurnLifecycle } from "@assemblyline-agents/runtime";
|
|
2
|
+
import { type ChannelAttachmentRequest, type ChannelContext, type ChannelDelivery, type ChannelHttpRequest, type ChannelHttpResult, type ChannelModule, type ChannelTurn, type ChannelTurnLifecycle } from "@assemblyline-agents/runtime";
|
|
3
|
+
export { slackSigningSecrets, slackWorkspaceCredentialMap, slackWorkspaceCredentials, type SlackWorkspaceCredentials } from "./workspace-credentials.js";
|
|
4
|
+
export { augmentContext } from "./context.js";
|
|
3
5
|
export declare const SLACK_REQUIRED_ENV: readonly ["SLACK_SIGNING_SECRET", "SLACK_BOT_TOKEN"];
|
|
4
|
-
export declare const SLACK_OPTIONAL_ENV: readonly ["SLACK_BOT_USER_ID", "SLACK_ASSISTANT_ENABLED"];
|
|
6
|
+
export declare const SLACK_OPTIONAL_ENV: readonly ["SLACK_BOT_USER_ID", "SLACK_ASSISTANT_ENABLED", "SLACK_WORKSPACE_CREDENTIALS_JSON"];
|
|
7
|
+
export declare const SLACK_REQUIRED_BOT_SCOPES: readonly ["app_mentions:read", "channels:history", "chat:write", "files:read", "files:write", "im:history"];
|
|
8
|
+
export declare const SLACK_OPTIONAL_BOT_SCOPES: readonly ["assistant:write", "groups:history"];
|
|
9
|
+
export declare const SLACK_DEFAULT_STATUS = "is working...";
|
|
10
|
+
export declare const SLACK_DEFAULT_LOADING_MESSAGES: readonly ["Beboppin'", "Boondoggling", "Cerebrating", "Combobulating", "Cooking", "Elucidating", "Flibbertigibbeting", "Hullaballooing", "Ionizing", "Photosynthesizing"];
|
|
5
11
|
/** Production ingress-auth requirement (any-of groups): Slack request signing. */
|
|
6
12
|
export declare const SLACK_INGRESS_SECRET_ENV: string[][];
|
|
7
13
|
export type SlackConnectionOptions = McpPluginConnectionOptions;
|
|
@@ -13,14 +19,14 @@ export interface SlackChannelOptions {
|
|
|
13
19
|
methods?: string[];
|
|
14
20
|
connection?: string;
|
|
15
21
|
metadata?: JsonObject;
|
|
22
|
+
/** Map the verified Slack sender to the application's canonical user. */
|
|
23
|
+
resolvePrincipal?: NonNullable<ChannelModule["resolvePrincipal"]>;
|
|
24
|
+
/** Override the default DM=principal, channel/thread=conversation trust boundary. */
|
|
25
|
+
isPrivateSurface?: NonNullable<ChannelModule["isPrivateSurface"]>;
|
|
16
26
|
}
|
|
17
27
|
export declare function defineSlackChannel(options?: SlackChannelOptions): ChannelDefinition;
|
|
18
28
|
export declare function normalizeHttp(request: ChannelHttpRequest, ctx: ChannelContext): ChannelHttpResult;
|
|
19
29
|
export declare function startTurn(turn: ChannelTurn, ctx: ChannelContext): Promise<ChannelTurnLifecycle | void>;
|
|
20
|
-
export declare function augmentContext(turn: ChannelTurn, ctx: ChannelContext): Promise<{
|
|
21
|
-
recentHistory?: string[];
|
|
22
|
-
channelContext?: JsonObject;
|
|
23
|
-
} | void>;
|
|
24
30
|
export declare function send(delivery: ChannelDelivery, ctx: ChannelContext): Promise<JsonObject>;
|
|
25
31
|
/**
|
|
26
32
|
* Resolve a Slack turn attachment into an authorized download request: direct
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAyG,KAAK,iBAAiB,EAAE,KAAK,UAAU,EAAkB,KAAK,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAC5O,OAAO,EAML,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAElB,KAAK,WAAW,EAChB,KAAK,oBAAoB,EAC1B,MAAM,8BAA8B,CAAC;AAetC,OAAO,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,KAAK,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACzJ,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,eAAO,MAAM,kBAAkB,sDAAuD,CAAC;AACvF,eAAO,MAAM,kBAAkB,+FAAgG,CAAC;AAChI,eAAO,MAAM,yBAAyB,6GAA8G,CAAC;AACrJ,eAAO,MAAM,yBAAyB,gDAAiD,CAAC;AACxF,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AACpD,eAAO,MAAM,8BAA8B,2KAWjC,CAAC;AACX,kFAAkF;AAClF,eAAO,MAAM,wBAAwB,EAAE,MAAM,EAAE,EAA+B,CAAC;AAG/E,MAAM,MAAM,sBAAsB,GAAG,0BAA0B,CAAC;AAChE,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,yEAEpE;AACD,eAAO,MAAM,kBAAkB,kDAA2D,CAAC;AAE3F,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,WAAW,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAClE,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,WAAW,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAAC,CAAC;CACnE;AAiBD,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,iBAAiB,CA2BvF;AASD,wBAAgB,aAAa,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,EAAE,cAAc,GAAG,iBAAiB,CAgDjG;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAsC5G;AAED,wBAAsB,IAAI,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CAsD9F;AAgDD;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,wBAAwB,GAAG,SAAS,CAAC,CAOlI;AA4ND,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,kBAAkB,EAC3B,aAAa,EAAE,MAAM,EACrB,UAAU,SAAgC,GACzC,OAAO,CAST"}
|