@cuylabs/channel-slack 0.1.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 +201 -0
- package/README.md +168 -0
- package/dist/activity-ByrD9Ftr.d.ts +66 -0
- package/dist/assistant.d.ts +58 -0
- package/dist/assistant.js +188 -0
- package/dist/bolt.d.ts +344 -0
- package/dist/bolt.js +705 -0
- package/dist/chunk-BODPT4I6.js +322 -0
- package/dist/chunk-FPCE5V5Y.js +292 -0
- package/dist/chunk-FX2JOVX5.js +405 -0
- package/dist/chunk-JZG4IETE.js +141 -0
- package/dist/chunk-NE57BLLU.js +0 -0
- package/dist/chunk-TWJGVDA2.js +108 -0
- package/dist/core.d.ts +425 -0
- package/dist/core.js +42 -0
- package/dist/diagnostics.d.ts +105 -0
- package/dist/diagnostics.js +8 -0
- package/dist/feedback.d.ts +137 -0
- package/dist/feedback.js +128 -0
- package/dist/history.d.ts +266 -0
- package/dist/history.js +747 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +57 -0
- package/dist/logging-Bl3HfcC8.d.ts +8 -0
- package/dist/policy.d.ts +130 -0
- package/dist/policy.js +16 -0
- package/dist/setup.d.ts +165 -0
- package/dist/setup.js +453 -0
- package/dist/shared.d.ts +2 -0
- package/dist/shared.js +43 -0
- package/dist/targets.d.ts +113 -0
- package/dist/targets.js +484 -0
- package/dist/users.d.ts +109 -0
- package/dist/users.js +240 -0
- package/docs/concepts/activity.md +33 -0
- package/docs/concepts/bolt-runtime.md +30 -0
- package/docs/concepts/message-policy.md +49 -0
- package/docs/concepts/setup-requirements.md +44 -0
- package/docs/concepts/supplemental-history.md +55 -0
- package/docs/recipes/app-mention-handler.md +34 -0
- package/docs/recipes/assistant-thread-handler.md +28 -0
- package/docs/recipes/generate-slack-manifest.md +28 -0
- package/docs/recipes/history-visibility.md +36 -0
- package/docs/recipes/socket-mode-app.md +29 -0
- package/docs/reference/channel-slack-boundary.md +50 -0
- package/docs/reference/exports.md +32 -0
- package/package.json +130 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { ContextActionsBlock, View } from '@slack/types';
|
|
2
|
+
import { App } from '@slack/bolt';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Slack feedback block builder.
|
|
6
|
+
*
|
|
7
|
+
* Slack's "thumbs up / thumbs down" UI is a `context_actions` block with a
|
|
8
|
+
* single `feedback_buttons` element. The block shape follows the official
|
|
9
|
+
* `@slack/types` Block Kit definitions.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
type SlackFeedbackButtons = Extract<ContextActionsBlock["elements"][number], {
|
|
13
|
+
type: "feedback_buttons";
|
|
14
|
+
}> & {
|
|
15
|
+
action_id: string;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Slack feedback block shape. Returned to callers as a typed object so it can
|
|
19
|
+
* be appended directly to `chatStream.stop({ blocks })` without further
|
|
20
|
+
* casting.
|
|
21
|
+
*/
|
|
22
|
+
interface SlackFeedbackContextBlock extends Omit<ContextActionsBlock, "type" | "elements"> {
|
|
23
|
+
type: "context_actions";
|
|
24
|
+
elements: [SlackFeedbackButtons];
|
|
25
|
+
}
|
|
26
|
+
declare const SLACK_FEEDBACK_ACTION_ID = "agent_feedback";
|
|
27
|
+
type SlackFeedbackVerdict = "positive" | "negative";
|
|
28
|
+
interface SlackFeedbackButtonConfig {
|
|
29
|
+
/**
|
|
30
|
+
* Slack block-action `value` for the positive button.
|
|
31
|
+
*
|
|
32
|
+
* @default "good-feedback"
|
|
33
|
+
*/
|
|
34
|
+
positiveValue?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Slack block-action `value` for the negative button.
|
|
37
|
+
*
|
|
38
|
+
* @default "bad-feedback"
|
|
39
|
+
*/
|
|
40
|
+
negativeValue?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Visible button text and accessibility labels.
|
|
43
|
+
*/
|
|
44
|
+
positiveButton?: {
|
|
45
|
+
text: string;
|
|
46
|
+
accessibilityLabel?: string;
|
|
47
|
+
};
|
|
48
|
+
negativeButton?: {
|
|
49
|
+
text: string;
|
|
50
|
+
accessibilityLabel?: string;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
interface SlackFeedbackBlockOptions extends SlackFeedbackButtonConfig {
|
|
54
|
+
/**
|
|
55
|
+
* Block-action id used to dispatch the click. Override only if you need
|
|
56
|
+
* multiple feedback widgets in the same workspace.
|
|
57
|
+
*
|
|
58
|
+
* @default SLACK_FEEDBACK_ACTION_ID
|
|
59
|
+
*/
|
|
60
|
+
actionId?: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Build the canonical feedback block to attach to assistant replies.
|
|
64
|
+
*
|
|
65
|
+
* The shape mirrors the official Bolt assistant template's `feedback_block`
|
|
66
|
+
* (a `context_actions` block with a single `feedback_buttons` element).
|
|
67
|
+
*/
|
|
68
|
+
declare function createSlackFeedbackBlock(options?: SlackFeedbackBlockOptions): SlackFeedbackContextBlock;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Slack feedback block-action handler.
|
|
72
|
+
*
|
|
73
|
+
* Wires the click on the canonical feedback block onto a Bolt `App`. Bolt
|
|
74
|
+
* routes the click as a `block_actions` payload whose
|
|
75
|
+
* `actions[0].type === "feedback_buttons"`. This module parses the verdict,
|
|
76
|
+
* acknowledges the click, calls the host's `onFeedback` handler, and posts an
|
|
77
|
+
* ephemeral acknowledgement.
|
|
78
|
+
*/
|
|
79
|
+
|
|
80
|
+
interface SlackFeedbackContext {
|
|
81
|
+
verdict: SlackFeedbackVerdict;
|
|
82
|
+
/** Raw value submitted by the button. */
|
|
83
|
+
value: string;
|
|
84
|
+
channelId: string;
|
|
85
|
+
userId: string;
|
|
86
|
+
/** Timestamp of the message the feedback applies to. */
|
|
87
|
+
messageTs: string;
|
|
88
|
+
/** Thread the message lives in, if any. */
|
|
89
|
+
threadTs?: string;
|
|
90
|
+
/** Slack interactivity trigger id for opening a modal from the click. */
|
|
91
|
+
triggerId?: string;
|
|
92
|
+
/** Optional agent session id resolved by the host bridge. */
|
|
93
|
+
sessionId?: string;
|
|
94
|
+
/** Convenience helper that opens a Slack modal from the feedback click. */
|
|
95
|
+
openModal: (view: View) => Promise<void>;
|
|
96
|
+
/** Convenience helper that posts a private acknowledgement to the user. */
|
|
97
|
+
acknowledgeEphemeral: (text: string) => Promise<void>;
|
|
98
|
+
}
|
|
99
|
+
type SlackFeedbackHandler = (context: SlackFeedbackContext) => void | Promise<void>;
|
|
100
|
+
interface RegisterSlackFeedbackOptions extends SlackFeedbackBlockOptions {
|
|
101
|
+
/**
|
|
102
|
+
* Handler invoked after the block-action ack resolves.
|
|
103
|
+
*/
|
|
104
|
+
onFeedback: SlackFeedbackHandler;
|
|
105
|
+
/**
|
|
106
|
+
* Ephemeral text shown to the user for a positive click.
|
|
107
|
+
*
|
|
108
|
+
* Set to `false` to skip the auto-ack message; the handler is still called.
|
|
109
|
+
*
|
|
110
|
+
* @default "Thanks for the feedback!"
|
|
111
|
+
*/
|
|
112
|
+
positiveAck?: string | false;
|
|
113
|
+
/**
|
|
114
|
+
* Ephemeral text shown for a negative click.
|
|
115
|
+
*
|
|
116
|
+
* @default "Thanks — we'll use this to improve the assistant."
|
|
117
|
+
*/
|
|
118
|
+
negativeAck?: string | false;
|
|
119
|
+
/**
|
|
120
|
+
* Optional resolver used by higher-level bridges to attach the agent session
|
|
121
|
+
* id that produced the message.
|
|
122
|
+
*/
|
|
123
|
+
resolveSessionId?: (context: Omit<SlackFeedbackContext, "acknowledgeEphemeral" | "openModal" | "sessionId">) => string | undefined;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Register the feedback block-action handler on a Bolt `App`.
|
|
127
|
+
*
|
|
128
|
+
* Returns the resolved actionId and verdict mapping so the same values can be
|
|
129
|
+
* passed to `createSlackFeedbackBlock` when generating the block.
|
|
130
|
+
*/
|
|
131
|
+
declare function registerSlackFeedbackAction(app: App, options: RegisterSlackFeedbackOptions): {
|
|
132
|
+
actionId: string;
|
|
133
|
+
positiveValue: string;
|
|
134
|
+
negativeValue: string;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export { type RegisterSlackFeedbackOptions, SLACK_FEEDBACK_ACTION_ID, type SlackFeedbackBlockOptions, type SlackFeedbackButtonConfig, type SlackFeedbackContext, type SlackFeedbackContextBlock, type SlackFeedbackHandler, type SlackFeedbackVerdict, createSlackFeedbackBlock, registerSlackFeedbackAction };
|
package/dist/feedback.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// src/feedback/block.ts
|
|
2
|
+
var SLACK_FEEDBACK_ACTION_ID = "agent_feedback";
|
|
3
|
+
function createSlackFeedbackBlock(options = {}) {
|
|
4
|
+
const actionId = (options.actionId ?? SLACK_FEEDBACK_ACTION_ID).trim();
|
|
5
|
+
if (!actionId) {
|
|
6
|
+
throw new Error(
|
|
7
|
+
"createSlackFeedbackBlock: actionId must be a non-empty string"
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
const positiveValue = options.positiveValue ?? "good-feedback";
|
|
11
|
+
const negativeValue = options.negativeValue ?? "bad-feedback";
|
|
12
|
+
const positiveLabel = options.positiveButton?.text ?? "Good Response";
|
|
13
|
+
const negativeLabel = options.negativeButton?.text ?? "Bad Response";
|
|
14
|
+
const positiveA11y = options.positiveButton?.accessibilityLabel ?? "Submit positive feedback on this response";
|
|
15
|
+
const negativeA11y = options.negativeButton?.accessibilityLabel ?? "Submit negative feedback on this response";
|
|
16
|
+
return {
|
|
17
|
+
type: "context_actions",
|
|
18
|
+
elements: [
|
|
19
|
+
{
|
|
20
|
+
type: "feedback_buttons",
|
|
21
|
+
action_id: actionId,
|
|
22
|
+
positive_button: {
|
|
23
|
+
text: { type: "plain_text", text: positiveLabel },
|
|
24
|
+
accessibility_label: positiveA11y,
|
|
25
|
+
value: positiveValue
|
|
26
|
+
},
|
|
27
|
+
negative_button: {
|
|
28
|
+
text: { type: "plain_text", text: negativeLabel },
|
|
29
|
+
accessibility_label: negativeA11y,
|
|
30
|
+
value: negativeValue
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/feedback/action.ts
|
|
38
|
+
function registerSlackFeedbackAction(app, options) {
|
|
39
|
+
const actionId = (options.actionId ?? SLACK_FEEDBACK_ACTION_ID).trim();
|
|
40
|
+
const positiveValue = options.positiveValue ?? "good-feedback";
|
|
41
|
+
const negativeValue = options.negativeValue ?? "bad-feedback";
|
|
42
|
+
const positiveAck = options.positiveAck === void 0 ? "Thanks for the feedback!" : options.positiveAck;
|
|
43
|
+
const negativeAck = options.negativeAck === void 0 ? "Thanks \u2014 we'll use this to improve the assistant." : options.negativeAck;
|
|
44
|
+
app.action(
|
|
45
|
+
actionId,
|
|
46
|
+
// Bolt's action args don't have a single shared exported type; the
|
|
47
|
+
// structural shape we read here (ack/body/client/logger) is stable.
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
49
|
+
async ({ ack, body, client, logger }) => {
|
|
50
|
+
const ackFn = ack;
|
|
51
|
+
await ackFn();
|
|
52
|
+
try {
|
|
53
|
+
if (body?.type !== "block_actions" || !Array.isArray(body.actions) || body.actions.length === 0) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const action = body.actions[0];
|
|
57
|
+
if (action?.type !== "feedback_buttons") {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const value = String(action.value ?? "");
|
|
61
|
+
const verdict = value === positiveValue ? "positive" : value === negativeValue ? "negative" : void 0;
|
|
62
|
+
if (!verdict) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const channelId = body.channel?.id ?? body.container?.channel_id;
|
|
66
|
+
const userId = body.user?.id;
|
|
67
|
+
const messageTs = body.message?.ts ?? body.container?.message_ts;
|
|
68
|
+
const threadTs = body.message?.thread_ts ?? body.container?.thread_ts;
|
|
69
|
+
const triggerId = typeof body.trigger_id === "string" ? body.trigger_id : void 0;
|
|
70
|
+
if (!channelId || !userId || !messageTs) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const openModal = async (view) => {
|
|
74
|
+
if (!triggerId) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
"Slack feedback payload did not include trigger_id."
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
if (typeof client.views?.open !== "function") {
|
|
80
|
+
throw new Error("Slack client does not expose views.open.");
|
|
81
|
+
}
|
|
82
|
+
await client.views.open({
|
|
83
|
+
trigger_id: triggerId,
|
|
84
|
+
view
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
const acknowledgeEphemeral = async (text) => {
|
|
88
|
+
await client.chat.postEphemeral({
|
|
89
|
+
channel: channelId,
|
|
90
|
+
user: userId,
|
|
91
|
+
...threadTs ? { thread_ts: threadTs } : { thread_ts: messageTs },
|
|
92
|
+
text
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
const feedbackContext = {
|
|
96
|
+
verdict,
|
|
97
|
+
value,
|
|
98
|
+
channelId,
|
|
99
|
+
userId,
|
|
100
|
+
messageTs,
|
|
101
|
+
...threadTs ? { threadTs } : {},
|
|
102
|
+
...triggerId ? { triggerId } : {}
|
|
103
|
+
};
|
|
104
|
+
const sessionId = options.resolveSessionId?.(feedbackContext);
|
|
105
|
+
await options.onFeedback({
|
|
106
|
+
...feedbackContext,
|
|
107
|
+
...sessionId ? { sessionId } : {},
|
|
108
|
+
openModal,
|
|
109
|
+
acknowledgeEphemeral
|
|
110
|
+
});
|
|
111
|
+
const ackText = verdict === "positive" ? positiveAck : negativeAck;
|
|
112
|
+
if (ackText) {
|
|
113
|
+
await acknowledgeEphemeral(ackText);
|
|
114
|
+
}
|
|
115
|
+
} catch (error) {
|
|
116
|
+
logger?.error?.(
|
|
117
|
+
`[channel-slack] feedback handler failed: ${error instanceof Error ? error.message : String(error)}`
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
return { actionId, positiveValue, negativeValue };
|
|
123
|
+
}
|
|
124
|
+
export {
|
|
125
|
+
SLACK_FEEDBACK_ACTION_ID,
|
|
126
|
+
createSlackFeedbackBlock,
|
|
127
|
+
registerSlackFeedbackAction
|
|
128
|
+
};
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { S as SlackActivityInfo } from './activity-ByrD9Ftr.js';
|
|
2
|
+
import { ConversationsHistoryResponse, ConversationsRepliesResponse, WebClient } from '@slack/web-api';
|
|
3
|
+
import { L as Logger } from './logging-Bl3HfcC8.js';
|
|
4
|
+
|
|
5
|
+
interface SlackContextFragmentPayload {
|
|
6
|
+
content: string;
|
|
7
|
+
budgetBehavior?: string;
|
|
8
|
+
dedupeKey?: string;
|
|
9
|
+
kind?: string;
|
|
10
|
+
lifetime?: string;
|
|
11
|
+
maxChars?: number;
|
|
12
|
+
metadata?: Record<string, unknown>;
|
|
13
|
+
placement?: string;
|
|
14
|
+
role?: string;
|
|
15
|
+
source?: string;
|
|
16
|
+
title?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type HistoryMessageElement = NonNullable<ConversationsHistoryResponse["messages"]>[number];
|
|
20
|
+
type RepliesMessageElement = NonNullable<ConversationsRepliesResponse["messages"]>[number];
|
|
21
|
+
type SlackApiMessageElement = HistoryMessageElement | RepliesMessageElement;
|
|
22
|
+
type SlackConversationsClient = Pick<WebClient["conversations"], "history" | "replies">;
|
|
23
|
+
type SlackHistoryReaderClient = WebClient | SlackConversationsClient;
|
|
24
|
+
type SlackHistoryMessageRole = "user" | "assistant" | "bot" | "system" | "unknown";
|
|
25
|
+
interface SlackHistoryMessage {
|
|
26
|
+
channelId: string;
|
|
27
|
+
ts: string;
|
|
28
|
+
threadTs?: string;
|
|
29
|
+
userId?: string;
|
|
30
|
+
botId?: string;
|
|
31
|
+
appId?: string;
|
|
32
|
+
subtype?: string;
|
|
33
|
+
text: string;
|
|
34
|
+
role: SlackHistoryMessageRole;
|
|
35
|
+
isBot: boolean;
|
|
36
|
+
raw: SlackApiMessageElement;
|
|
37
|
+
}
|
|
38
|
+
interface SlackHistoryPage {
|
|
39
|
+
messages: SlackHistoryMessage[];
|
|
40
|
+
nextCursor?: string;
|
|
41
|
+
hasMore: boolean;
|
|
42
|
+
}
|
|
43
|
+
type SlackHistoryAuthorFormatter = (message: SlackHistoryMessage) => string | undefined;
|
|
44
|
+
type SlackHistoryContextSource = "thread" | "channel" | "origin-channel";
|
|
45
|
+
interface SlackHistoryAuthorResolverContext {
|
|
46
|
+
source: SlackHistoryContextSource;
|
|
47
|
+
channelId: string;
|
|
48
|
+
teamId?: string;
|
|
49
|
+
}
|
|
50
|
+
type SlackHistoryAuthorResolver = (message: SlackHistoryMessage, context: SlackHistoryAuthorResolverContext) => string | undefined | Promise<string | undefined>;
|
|
51
|
+
interface BaseReadSlackHistoryOptions {
|
|
52
|
+
client: SlackHistoryReaderClient;
|
|
53
|
+
channelId: string;
|
|
54
|
+
/**
|
|
55
|
+
* Optional token override. Useful when the caller must choose between bot
|
|
56
|
+
* and user tokens for a specific Slack API call.
|
|
57
|
+
*/
|
|
58
|
+
token?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Current app's bot user id. When provided, messages from this user are
|
|
61
|
+
* classified as `assistant` instead of generic `bot`.
|
|
62
|
+
*/
|
|
63
|
+
botUserId?: string;
|
|
64
|
+
/** Number of messages to request. Defaults to Slack's stricter modern page size. */
|
|
65
|
+
limit?: number;
|
|
66
|
+
cursor?: string;
|
|
67
|
+
includeAllMetadata?: boolean;
|
|
68
|
+
}
|
|
69
|
+
interface ReadSlackThreadHistoryOptions extends BaseReadSlackHistoryOptions {
|
|
70
|
+
threadTs: string;
|
|
71
|
+
oldest?: string;
|
|
72
|
+
latest?: string;
|
|
73
|
+
inclusive?: boolean;
|
|
74
|
+
}
|
|
75
|
+
interface ReadSlackChannelHistoryOptions extends BaseReadSlackHistoryOptions {
|
|
76
|
+
oldest?: string;
|
|
77
|
+
latest?: string;
|
|
78
|
+
inclusive?: boolean;
|
|
79
|
+
/** Reverse Slack's newest-first channel history response into chronological order. @default true */
|
|
80
|
+
oldestFirst?: boolean;
|
|
81
|
+
}
|
|
82
|
+
interface FormatSlackHistoryForPromptOptions {
|
|
83
|
+
header?: string | false;
|
|
84
|
+
maxMessages?: number;
|
|
85
|
+
maxCharacters?: number;
|
|
86
|
+
includeTimestamps?: boolean;
|
|
87
|
+
roleLabels?: Partial<Record<SlackHistoryMessageRole, string>>;
|
|
88
|
+
/**
|
|
89
|
+
* Override the author label for a message. Return `undefined` to use the
|
|
90
|
+
* role label fallback (`User`, `Assistant`, etc.).
|
|
91
|
+
*/
|
|
92
|
+
formatAuthor?: SlackHistoryAuthorFormatter;
|
|
93
|
+
}
|
|
94
|
+
declare function readSlackThreadHistory(options: ReadSlackThreadHistoryOptions): Promise<SlackHistoryPage>;
|
|
95
|
+
declare function readSlackChannelHistory(options: ReadSlackChannelHistoryOptions): Promise<SlackHistoryPage>;
|
|
96
|
+
declare function formatSlackHistoryForPrompt(messages: readonly SlackHistoryMessage[], options?: FormatSlackHistoryForPromptOptions): string;
|
|
97
|
+
|
|
98
|
+
type SlackSupplementalHistoryVisibilityMode = "all" | "current-user-plus-assistant" | "original-user-plus-assistant" | "allowed-users-plus-assistant";
|
|
99
|
+
interface SlackSupplementalHistoryVisibilityContext {
|
|
100
|
+
activity: SlackActivityInfo;
|
|
101
|
+
botUserId?: string;
|
|
102
|
+
channelId: string;
|
|
103
|
+
source: SlackHistoryContextSource;
|
|
104
|
+
teamId?: string;
|
|
105
|
+
}
|
|
106
|
+
interface SlackSupplementalHistoryVisibilityDecision {
|
|
107
|
+
messages: SlackHistoryMessage[];
|
|
108
|
+
mode?: SlackSupplementalHistoryVisibilityMode | "custom" | "error";
|
|
109
|
+
omittedCount: number;
|
|
110
|
+
source: SlackHistoryContextSource;
|
|
111
|
+
}
|
|
112
|
+
interface SlackSupplementalHistoryVisibilityPolicy {
|
|
113
|
+
filter(messages: readonly SlackHistoryMessage[], context: SlackSupplementalHistoryVisibilityContext): Promise<SlackSupplementalHistoryVisibilityDecision>;
|
|
114
|
+
}
|
|
115
|
+
interface CreateSlackSupplementalHistoryVisibilityPolicyOptions {
|
|
116
|
+
/**
|
|
117
|
+
* Controls which Slack history messages can become model-visible prompt
|
|
118
|
+
* context. `all` preserves existing behavior.
|
|
119
|
+
*
|
|
120
|
+
* @default "all"
|
|
121
|
+
*/
|
|
122
|
+
mode?: SlackSupplementalHistoryVisibilityMode;
|
|
123
|
+
/**
|
|
124
|
+
* User IDs allowed when `mode` is `allowed-users-plus-assistant`.
|
|
125
|
+
*/
|
|
126
|
+
allowedUserIds?: Iterable<string>;
|
|
127
|
+
}
|
|
128
|
+
declare function createSlackSupplementalHistoryVisibilityPolicy({ allowedUserIds, mode, }?: CreateSlackSupplementalHistoryVisibilityPolicyOptions): SlackSupplementalHistoryVisibilityPolicy;
|
|
129
|
+
|
|
130
|
+
interface SlackHistoryUnavailable {
|
|
131
|
+
source: "thread" | "channel" | "origin-channel";
|
|
132
|
+
method: "conversations.replies" | "conversations.history";
|
|
133
|
+
channelId: string;
|
|
134
|
+
errorCode?: string;
|
|
135
|
+
expected: boolean;
|
|
136
|
+
hint?: string;
|
|
137
|
+
message: string;
|
|
138
|
+
}
|
|
139
|
+
interface LoadSlackTurnHistoryContextOptions {
|
|
140
|
+
client: SlackHistoryReaderClient;
|
|
141
|
+
activity: SlackActivityInfo;
|
|
142
|
+
/**
|
|
143
|
+
* Current app's bot user id. Messages from this user are labeled Assistant.
|
|
144
|
+
*/
|
|
145
|
+
botUserId?: string;
|
|
146
|
+
/**
|
|
147
|
+
* Optional token override for Slack Web API calls.
|
|
148
|
+
*/
|
|
149
|
+
token?: string;
|
|
150
|
+
/**
|
|
151
|
+
* Number of Slack messages to request per history API call.
|
|
152
|
+
*
|
|
153
|
+
* @default 15
|
|
154
|
+
*/
|
|
155
|
+
limit?: number;
|
|
156
|
+
/**
|
|
157
|
+
* Maximum formatted prompt characters.
|
|
158
|
+
*
|
|
159
|
+
* @default 12000
|
|
160
|
+
*/
|
|
161
|
+
maxCharacters?: number;
|
|
162
|
+
/**
|
|
163
|
+
* Optional source channel to include when the active thread is in a different
|
|
164
|
+
* channel, such as a routed incident channel.
|
|
165
|
+
*/
|
|
166
|
+
originChannelId?: string;
|
|
167
|
+
/**
|
|
168
|
+
* Request-level Slack team/workspace ID used for author resolution. Defaults
|
|
169
|
+
* to `activity.teamId`.
|
|
170
|
+
*/
|
|
171
|
+
teamId?: string;
|
|
172
|
+
/**
|
|
173
|
+
* Read channel history as a fallback when there is no usable thread history.
|
|
174
|
+
*
|
|
175
|
+
* @default true
|
|
176
|
+
*/
|
|
177
|
+
includeTopLevelChannelFallback?: boolean;
|
|
178
|
+
headers?: {
|
|
179
|
+
thread?: string | false;
|
|
180
|
+
channel?: string | false;
|
|
181
|
+
originChannel?: string | false;
|
|
182
|
+
};
|
|
183
|
+
/**
|
|
184
|
+
* Optional author-label resolver for history messages. Use this to turn
|
|
185
|
+
* Slack user IDs into model-visible labels such as `Rosa Rodriguez (U123)`.
|
|
186
|
+
* Failed or empty resolutions fall back to the default role labels.
|
|
187
|
+
*/
|
|
188
|
+
resolveAuthor?: SlackHistoryAuthorResolver;
|
|
189
|
+
/** Called when `resolveAuthor` throws. Does not include message text/raw payload. */
|
|
190
|
+
onResolveAuthorError?: (context: SlackHistoryAuthorResolutionErrorContext) => void;
|
|
191
|
+
/**
|
|
192
|
+
* Slack assistant surfaces can return the root user message as if it were
|
|
193
|
+
* authored by the assistant. When set, the first assistant-authored thread
|
|
194
|
+
* history item is corrected to this request user unless it looks like an
|
|
195
|
+
* assistant greeting. Rendered author labels still come from `resolveAuthor`.
|
|
196
|
+
*/
|
|
197
|
+
assistantSurfaceThreadRootUser?: SlackAssistantSurfaceThreadRootNormalization;
|
|
198
|
+
/** Called when assistant-surface thread root history is corrected. */
|
|
199
|
+
onAssistantSurfaceThreadRootNormalized?: (context: SlackAssistantSurfaceThreadRootNormalizationContext) => void;
|
|
200
|
+
/**
|
|
201
|
+
* Optional policy that filters fetched Slack history before it becomes
|
|
202
|
+
* model-visible supplemental context.
|
|
203
|
+
*/
|
|
204
|
+
visibilityPolicy?: SlackSupplementalHistoryVisibilityPolicy;
|
|
205
|
+
/** Called when the visibility policy throws. The affected source is omitted. */
|
|
206
|
+
onVisibilityPolicyError?: (context: SlackSupplementalHistoryVisibilityErrorContext) => void;
|
|
207
|
+
}
|
|
208
|
+
interface SlackHistoryAuthorResolutionErrorContext extends SlackHistoryAuthorResolverContext {
|
|
209
|
+
userId?: string;
|
|
210
|
+
error: unknown;
|
|
211
|
+
}
|
|
212
|
+
interface SlackAssistantSurfaceThreadRootNormalization {
|
|
213
|
+
userId: string;
|
|
214
|
+
}
|
|
215
|
+
interface SlackAssistantSurfaceThreadRootNormalizationContext {
|
|
216
|
+
action: "corrected-author" | "removed-duplicate";
|
|
217
|
+
channelId: string;
|
|
218
|
+
teamId?: string;
|
|
219
|
+
threadTs: string;
|
|
220
|
+
userId: string;
|
|
221
|
+
}
|
|
222
|
+
interface SlackSupplementalHistoryVisibilityErrorContext {
|
|
223
|
+
channelId: string;
|
|
224
|
+
error: unknown;
|
|
225
|
+
source: SlackHistoryContextSource;
|
|
226
|
+
teamId?: string;
|
|
227
|
+
}
|
|
228
|
+
interface SlackTurnHistoryContextResult {
|
|
229
|
+
prompt?: string;
|
|
230
|
+
fragment?: SlackContextFragmentPayload;
|
|
231
|
+
threadMessageCount: number;
|
|
232
|
+
topLevelChannelMessageCount: number;
|
|
233
|
+
originChannelMessageCount: number;
|
|
234
|
+
threadVisibilityOmittedMessageCount: number;
|
|
235
|
+
topLevelChannelVisibilityOmittedMessageCount: number;
|
|
236
|
+
originChannelVisibilityOmittedMessageCount: number;
|
|
237
|
+
visibilityOmittedMessageCount: number;
|
|
238
|
+
visibility: SlackSupplementalHistoryVisibilityDecision[];
|
|
239
|
+
unavailable: SlackHistoryUnavailable[];
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
declare function loadSlackTurnHistoryContext(options: LoadSlackTurnHistoryContextOptions): Promise<SlackTurnHistoryContextResult>;
|
|
243
|
+
|
|
244
|
+
interface SlackSessionTranscriptInspector {
|
|
245
|
+
hasConversationMessages(sessionId: string): Promise<boolean>;
|
|
246
|
+
}
|
|
247
|
+
interface SlackSupplementalHistoryPolicyRequest {
|
|
248
|
+
slackActivity: Pick<SlackActivityInfo, "channelId" | "channelType" | "teamId" | "threadTs">;
|
|
249
|
+
sessionId?: string;
|
|
250
|
+
}
|
|
251
|
+
type SlackSupplementalHistoryInclusionReason = "shared-slack-surface" | "first-direct-session-turn" | "session-transcript-covers-direct-turn";
|
|
252
|
+
type SlackSupplementalHistoryInclusionSource = "shared-surface" | "session-transcript" | "process-memory";
|
|
253
|
+
interface SlackSupplementalHistoryInclusionDecision {
|
|
254
|
+
include: boolean;
|
|
255
|
+
reason: SlackSupplementalHistoryInclusionReason;
|
|
256
|
+
source: SlackSupplementalHistoryInclusionSource;
|
|
257
|
+
}
|
|
258
|
+
interface SlackSupplementalHistoryPolicy {
|
|
259
|
+
decide(request: SlackSupplementalHistoryPolicyRequest): Promise<SlackSupplementalHistoryInclusionDecision>;
|
|
260
|
+
}
|
|
261
|
+
declare function createSlackSupplementalHistoryPolicy({ logger, sessionTranscript, }?: {
|
|
262
|
+
logger?: Logger;
|
|
263
|
+
sessionTranscript?: SlackSessionTranscriptInspector;
|
|
264
|
+
}): SlackSupplementalHistoryPolicy;
|
|
265
|
+
|
|
266
|
+
export { type CreateSlackSupplementalHistoryVisibilityPolicyOptions, type FormatSlackHistoryForPromptOptions, type LoadSlackTurnHistoryContextOptions, type ReadSlackChannelHistoryOptions, type ReadSlackThreadHistoryOptions, type SlackAssistantSurfaceThreadRootNormalization, type SlackAssistantSurfaceThreadRootNormalizationContext, type SlackHistoryAuthorFormatter, type SlackHistoryAuthorResolutionErrorContext, type SlackHistoryAuthorResolver, type SlackHistoryAuthorResolverContext, type SlackHistoryContextSource, type SlackHistoryMessage, type SlackHistoryMessageRole, type SlackHistoryPage, type SlackHistoryReaderClient, type SlackHistoryUnavailable, type SlackSessionTranscriptInspector, type SlackSupplementalHistoryInclusionDecision, type SlackSupplementalHistoryInclusionReason, type SlackSupplementalHistoryInclusionSource, type SlackSupplementalHistoryPolicy, type SlackSupplementalHistoryPolicyRequest, type SlackSupplementalHistoryVisibilityContext, type SlackSupplementalHistoryVisibilityDecision, type SlackSupplementalHistoryVisibilityErrorContext, type SlackSupplementalHistoryVisibilityMode, type SlackSupplementalHistoryVisibilityPolicy, type SlackTurnHistoryContextResult, createSlackSupplementalHistoryPolicy, createSlackSupplementalHistoryVisibilityPolicy, formatSlackHistoryForPrompt, loadSlackTurnHistoryContext, readSlackChannelHistory, readSlackThreadHistory };
|