@agent-relay/slack-primitive 6.0.12
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/dist/actions/post-message.d.ts +9 -0
- package/dist/actions/post-message.d.ts.map +1 -0
- package/dist/actions/post-message.js +48 -0
- package/dist/actions/post-message.js.map +1 -0
- package/dist/actions/resolve-channel.d.ts +9 -0
- package/dist/actions/resolve-channel.d.ts.map +1 -0
- package/dist/actions/resolve-channel.js +29 -0
- package/dist/actions/resolve-channel.js.map +1 -0
- package/dist/actions/resolve-user.d.ts +13 -0
- package/dist/actions/resolve-user.d.ts.map +1 -0
- package/dist/actions/resolve-user.js +93 -0
- package/dist/actions/resolve-user.js.map +1 -0
- package/dist/adapter.d.ts +23 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +194 -0
- package/dist/adapter.js.map +1 -0
- package/dist/client.d.ts +62 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +91 -0
- package/dist/client.js.map +1 -0
- package/dist/cloud-relay-runtime.d.ts +32 -0
- package/dist/cloud-relay-runtime.d.ts.map +1 -0
- package/dist/cloud-relay-runtime.js +156 -0
- package/dist/cloud-relay-runtime.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/local-runtime.d.ts +17 -0
- package/dist/local-runtime.d.ts.map +1 -0
- package/dist/local-runtime.js +28 -0
- package/dist/local-runtime.js.map +1 -0
- package/dist/noop-runtime.d.ts +22 -0
- package/dist/noop-runtime.d.ts.map +1 -0
- package/dist/noop-runtime.js +70 -0
- package/dist/noop-runtime.js.map +1 -0
- package/dist/types.d.ts +202 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +27 -0
- package/dist/types.js.map +1 -0
- package/dist/workflow-step.d.ts +80 -0
- package/dist/workflow-step.d.ts.map +1 -0
- package/dist/workflow-step.js +355 -0
- package/dist/workflow-step.js.map +1 -0
- package/examples/README.md +40 -0
- package/examples/notify-on-pr.ts +93 -0
- package/package.json +50 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { RunnerStepExecutor, WorkflowStep } from '@agent-relay/workflow-types';
|
|
2
|
+
import { SlackClient } from './client.js';
|
|
3
|
+
import { type SlackActionResult, type SlackRuntimeConfig } from './types.js';
|
|
4
|
+
export type SlackStepOutputMode = 'data' | 'result' | 'summary' | 'raw' | 'none';
|
|
5
|
+
export type SlackStepOutputFormat = 'json' | 'text';
|
|
6
|
+
export interface SlackStepOutputConfig {
|
|
7
|
+
/** Which action result becomes the workflow step output. Defaults to "data". */
|
|
8
|
+
mode?: SlackStepOutputMode;
|
|
9
|
+
/** Emit JSON for structured chaining or text for simple downstream interpolation. Defaults to "json". */
|
|
10
|
+
format?: SlackStepOutputFormat;
|
|
11
|
+
/** Select a nested field from the projected output, e.g. "ts" or "data.channel". */
|
|
12
|
+
path?: string;
|
|
13
|
+
/** Include adapter metadata such as runtime and timing in JSON output. Defaults false. */
|
|
14
|
+
includeMetadata?: boolean;
|
|
15
|
+
/** Pretty-print JSON output. Defaults false. */
|
|
16
|
+
pretty?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface SlackStepConfig {
|
|
19
|
+
/** Unique step name within the workflow. */
|
|
20
|
+
name: string;
|
|
21
|
+
/** Dependencies in the Relay workflow DAG. */
|
|
22
|
+
dependsOn?: string[];
|
|
23
|
+
/** Slack action to execute. Phase A supports postMessage. */
|
|
24
|
+
action: 'postMessage';
|
|
25
|
+
/** Slack channel id or #channel-name reference. Falls back to SLACK_DEFAULT_CHANNEL when omitted. */
|
|
26
|
+
channel?: string;
|
|
27
|
+
/** Message text. Values may include workflow templates such as {{steps.plan.output.title}}. */
|
|
28
|
+
text: string;
|
|
29
|
+
/** Optional parent message timestamp for threaded delivery. */
|
|
30
|
+
threadTs?: string;
|
|
31
|
+
/** User mentions to prefix when resolved. Unresolved mentions are soft warnings in output. */
|
|
32
|
+
mentions?: string[];
|
|
33
|
+
/** Slack unfurl setting for links and media. */
|
|
34
|
+
unfurl?: boolean;
|
|
35
|
+
/** Runtime settings for the local Slack Web API runtime. */
|
|
36
|
+
config?: SlackRuntimeConfig;
|
|
37
|
+
/** Controls the string captured as {{steps.<name>.output}}. */
|
|
38
|
+
output?: SlackStepOutputConfig;
|
|
39
|
+
/** Workflow step timeout in milliseconds. */
|
|
40
|
+
timeoutMs?: number;
|
|
41
|
+
/** Number of retry attempts when the workflow runner retries this integration step. */
|
|
42
|
+
retries?: number;
|
|
43
|
+
}
|
|
44
|
+
export interface SlackStepExecutionContext {
|
|
45
|
+
workspaceId?: string;
|
|
46
|
+
client?: SlackClient;
|
|
47
|
+
config?: SlackRuntimeConfig;
|
|
48
|
+
}
|
|
49
|
+
export interface SlackStepExecutionResult<TOutput = unknown> {
|
|
50
|
+
success: boolean;
|
|
51
|
+
output: string;
|
|
52
|
+
result: SlackActionResult<TOutput>;
|
|
53
|
+
error?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface SlackIntegrationStepResult {
|
|
56
|
+
output: string;
|
|
57
|
+
success: boolean;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Create a Relay integration step for posting a Slack message.
|
|
61
|
+
* @param config - Slack step configuration.
|
|
62
|
+
* @returns Workflow integration step.
|
|
63
|
+
*/
|
|
64
|
+
export declare function createSlackStep(config: SlackStepConfig): WorkflowStep;
|
|
65
|
+
export declare class SlackStepExecutor implements RunnerStepExecutor {
|
|
66
|
+
private readonly options;
|
|
67
|
+
constructor(options?: SlackRuntimeConfig);
|
|
68
|
+
executeAgentStep(): Promise<string>;
|
|
69
|
+
execute<TOutput = unknown>(config: SlackStepConfig, context?: SlackStepExecutionContext): Promise<SlackStepExecutionResult<TOutput>>;
|
|
70
|
+
executeIntegrationStep(step: WorkflowStep, resolvedParams: Record<string, string>): Promise<SlackIntegrationStepResult>;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Rebuild a Slack step config from resolved workflow params.
|
|
74
|
+
* @param step - Workflow step.
|
|
75
|
+
* @param resolvedParams - Params after workflow templating.
|
|
76
|
+
* @returns Slack step configuration.
|
|
77
|
+
*/
|
|
78
|
+
export declare function slackStepConfigFromWorkflowStep(step: WorkflowStep, resolvedParams: Record<string, string>): SlackStepConfig;
|
|
79
|
+
export declare function renderSlackTemplates(value: string, data: Record<string, unknown>): string;
|
|
80
|
+
//# sourceMappingURL=workflow-step.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-step.d.ts","sourceRoot":"","sources":["../src/workflow-step.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import { SlackClient } from './client.js';
|
|
2
|
+
import { SlackAction, SLACK_ACTIONS, } from './types.js';
|
|
3
|
+
const SLACK_INTEGRATION = 'slack';
|
|
4
|
+
const RESERVED_PARAM_KEYS = new Set(['action', 'config', 'slackConfig', 'output', 'params']);
|
|
5
|
+
/**
|
|
6
|
+
* Create a Relay integration step for posting a Slack message.
|
|
7
|
+
* @param config - Slack step configuration.
|
|
8
|
+
* @returns Workflow integration step.
|
|
9
|
+
*/
|
|
10
|
+
export function createSlackStep(config) {
|
|
11
|
+
validateSlackStepConfig(config);
|
|
12
|
+
const params = {
|
|
13
|
+
text: config.text,
|
|
14
|
+
};
|
|
15
|
+
if (config.channel !== undefined)
|
|
16
|
+
params.channel = config.channel;
|
|
17
|
+
if (config.threadTs !== undefined)
|
|
18
|
+
params.threadTs = config.threadTs;
|
|
19
|
+
if (config.mentions !== undefined)
|
|
20
|
+
params.mentions = JSON.stringify(config.mentions);
|
|
21
|
+
if (config.unfurl !== undefined)
|
|
22
|
+
params.unfurl = String(config.unfurl);
|
|
23
|
+
if (config.config !== undefined)
|
|
24
|
+
params.config = JSON.stringify(config.config);
|
|
25
|
+
if (config.output !== undefined)
|
|
26
|
+
params.output = JSON.stringify(config.output);
|
|
27
|
+
const step = {
|
|
28
|
+
name: config.name,
|
|
29
|
+
type: 'integration',
|
|
30
|
+
integration: SLACK_INTEGRATION,
|
|
31
|
+
action: config.action,
|
|
32
|
+
params,
|
|
33
|
+
};
|
|
34
|
+
if (config.dependsOn !== undefined)
|
|
35
|
+
step.dependsOn = config.dependsOn;
|
|
36
|
+
if (config.timeoutMs !== undefined)
|
|
37
|
+
step.timeoutMs = config.timeoutMs;
|
|
38
|
+
if (config.retries !== undefined)
|
|
39
|
+
step.retries = config.retries;
|
|
40
|
+
return step;
|
|
41
|
+
}
|
|
42
|
+
export class SlackStepExecutor {
|
|
43
|
+
options;
|
|
44
|
+
constructor(options = {}) {
|
|
45
|
+
this.options = options;
|
|
46
|
+
}
|
|
47
|
+
async executeAgentStep() {
|
|
48
|
+
throw new Error('SlackStepExecutor only executes Slack integration steps.');
|
|
49
|
+
}
|
|
50
|
+
async execute(config, context = {}) {
|
|
51
|
+
validateSlackStepConfig(config);
|
|
52
|
+
const runtimeConfig = mergeRuntimeConfig(this.options, context.config, config.config);
|
|
53
|
+
const client = context.client ?? new SlackClient(runtimeConfig);
|
|
54
|
+
const params = buildActionParams(config);
|
|
55
|
+
const result = await client.executeAction(SlackAction.PostMessage, params);
|
|
56
|
+
const output = formatStepOutput(config, result);
|
|
57
|
+
return {
|
|
58
|
+
success: result.success,
|
|
59
|
+
output,
|
|
60
|
+
result,
|
|
61
|
+
error: result.error,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
async executeIntegrationStep(step, resolvedParams) {
|
|
65
|
+
if (step.integration !== SLACK_INTEGRATION) {
|
|
66
|
+
return {
|
|
67
|
+
success: false,
|
|
68
|
+
output: `SlackStepExecutor only handles "${SLACK_INTEGRATION}" integration steps`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const config = slackStepConfigFromWorkflowStep(step, resolvedParams);
|
|
73
|
+
const result = await this.execute(config);
|
|
74
|
+
return {
|
|
75
|
+
success: result.success,
|
|
76
|
+
output: result.success ? result.output : result.output || result.error || 'Slack step failed',
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
return {
|
|
81
|
+
success: false,
|
|
82
|
+
output: error instanceof Error ? error.message : String(error),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Rebuild a Slack step config from resolved workflow params.
|
|
89
|
+
* @param step - Workflow step.
|
|
90
|
+
* @param resolvedParams - Params after workflow templating.
|
|
91
|
+
* @returns Slack step configuration.
|
|
92
|
+
*/
|
|
93
|
+
export function slackStepConfigFromWorkflowStep(step, resolvedParams) {
|
|
94
|
+
const params = normalizeResolvedParams(resolvedParams);
|
|
95
|
+
const action = step.action;
|
|
96
|
+
if (action !== SlackAction.PostMessage) {
|
|
97
|
+
throw new Error(`Slack step "${step.name}" requires action "postMessage"`);
|
|
98
|
+
}
|
|
99
|
+
const config = readJsonParam(params.config ?? params.slackConfig, 'config') ?? undefined;
|
|
100
|
+
const output = readJsonParam(params.output, 'output') ?? undefined;
|
|
101
|
+
const actionParams = readActionParams(params);
|
|
102
|
+
return {
|
|
103
|
+
name: step.name,
|
|
104
|
+
dependsOn: step.dependsOn,
|
|
105
|
+
action: SlackAction.PostMessage,
|
|
106
|
+
channel: readOptionalString(actionParams.channel),
|
|
107
|
+
text: readRequiredString(actionParams.text, 'text'),
|
|
108
|
+
threadTs: readOptionalString(actionParams.threadTs),
|
|
109
|
+
mentions: readStringArray(actionParams.mentions),
|
|
110
|
+
unfurl: readOptionalBoolean(actionParams.unfurl, 'unfurl'),
|
|
111
|
+
config,
|
|
112
|
+
output,
|
|
113
|
+
timeoutMs: step.timeoutMs,
|
|
114
|
+
retries: step.retries,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
export function renderSlackTemplates(value, data) {
|
|
118
|
+
return value.replace(/\{\{\s*steps\.([A-Za-z0-9_-]+)\.output(?:\.([A-Za-z0-9_.-]+))?\s*\}\}/g, (_match, step, path) => {
|
|
119
|
+
const stepData = data.steps;
|
|
120
|
+
if (!isRecord(stepData))
|
|
121
|
+
return '';
|
|
122
|
+
const entry = stepData[String(step)];
|
|
123
|
+
if (!isRecord(entry))
|
|
124
|
+
return '';
|
|
125
|
+
const output = entry.output;
|
|
126
|
+
const resolved = typeof path === 'string' && path.length > 0 ? resolvePath(output, path) : output;
|
|
127
|
+
return projectionToText(resolved);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
function validateSlackStepConfig(config) {
|
|
131
|
+
if (!config.name) {
|
|
132
|
+
throw new Error('Slack step requires a non-empty name');
|
|
133
|
+
}
|
|
134
|
+
if (!SLACK_ACTIONS.includes(config.action)) {
|
|
135
|
+
throw new Error(`Slack step "${config.name}" uses unsupported action "${config.action}"`);
|
|
136
|
+
}
|
|
137
|
+
if (config.action !== SlackAction.PostMessage) {
|
|
138
|
+
throw new Error(`Slack step "${config.name}" requires action "postMessage"`);
|
|
139
|
+
}
|
|
140
|
+
if (typeof config.text !== 'string' || config.text.length === 0) {
|
|
141
|
+
throw new Error(`Slack step "${config.name}" requires message text`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function buildActionParams(config) {
|
|
145
|
+
return {
|
|
146
|
+
channel: config.channel,
|
|
147
|
+
text: config.text,
|
|
148
|
+
threadTs: config.threadTs,
|
|
149
|
+
mentions: config.mentions,
|
|
150
|
+
unfurl: config.unfurl,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function readActionParams(params) {
|
|
154
|
+
const serializedParams = params.params;
|
|
155
|
+
if (serializedParams !== undefined) {
|
|
156
|
+
const parsed = readJsonParam(serializedParams, 'params');
|
|
157
|
+
if (parsed === undefined)
|
|
158
|
+
return {};
|
|
159
|
+
if (!isRecord(parsed)) {
|
|
160
|
+
throw new Error('Slack step params.params must be a JSON object');
|
|
161
|
+
}
|
|
162
|
+
return parsed;
|
|
163
|
+
}
|
|
164
|
+
const actionParams = {};
|
|
165
|
+
for (const [key, value] of Object.entries(params)) {
|
|
166
|
+
if (RESERVED_PARAM_KEYS.has(key))
|
|
167
|
+
continue;
|
|
168
|
+
actionParams[key] = value;
|
|
169
|
+
}
|
|
170
|
+
return actionParams;
|
|
171
|
+
}
|
|
172
|
+
function mergeRuntimeConfig(...configs) {
|
|
173
|
+
const merged = {};
|
|
174
|
+
for (const config of configs) {
|
|
175
|
+
if (!config)
|
|
176
|
+
continue;
|
|
177
|
+
const { env, ...flatConfig } = config;
|
|
178
|
+
Object.assign(merged, flatConfig);
|
|
179
|
+
if (env) {
|
|
180
|
+
merged.env = {
|
|
181
|
+
...merged.env,
|
|
182
|
+
...env,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return merged;
|
|
187
|
+
}
|
|
188
|
+
function formatStepOutput(config, result) {
|
|
189
|
+
const outputConfig = config.output ?? {};
|
|
190
|
+
const mode = outputConfig.mode ?? 'data';
|
|
191
|
+
const format = outputConfig.format ?? 'json';
|
|
192
|
+
if (mode === 'none') {
|
|
193
|
+
return '';
|
|
194
|
+
}
|
|
195
|
+
let projection = buildOutputProjection(mode, result, outputConfig);
|
|
196
|
+
if (outputConfig.path) {
|
|
197
|
+
projection = resolvePath(projection, outputConfig.path);
|
|
198
|
+
}
|
|
199
|
+
if (format === 'text') {
|
|
200
|
+
return projectionToText(projection);
|
|
201
|
+
}
|
|
202
|
+
return JSON.stringify(projection, undefined, outputConfig.pretty ? 2 : undefined);
|
|
203
|
+
}
|
|
204
|
+
function buildOutputProjection(mode, result, outputConfig) {
|
|
205
|
+
if (mode === 'raw')
|
|
206
|
+
return result.output;
|
|
207
|
+
if (mode === 'summary') {
|
|
208
|
+
return withOptionalMetadata(summarizeResult(result), result, outputConfig);
|
|
209
|
+
}
|
|
210
|
+
if (mode === 'result') {
|
|
211
|
+
const projected = {
|
|
212
|
+
success: result.success,
|
|
213
|
+
output: result.output,
|
|
214
|
+
};
|
|
215
|
+
if (result.data !== undefined)
|
|
216
|
+
projected.data = result.data;
|
|
217
|
+
if (result.error !== undefined)
|
|
218
|
+
projected.error = result.error;
|
|
219
|
+
return withOptionalMetadata(projected, result, outputConfig);
|
|
220
|
+
}
|
|
221
|
+
return withOptionalMetadata(result.data ?? (result.output ? result.output : (result.error ?? null)), result, outputConfig);
|
|
222
|
+
}
|
|
223
|
+
function summarizeResult(result) {
|
|
224
|
+
if (!result.success) {
|
|
225
|
+
return {
|
|
226
|
+
success: false,
|
|
227
|
+
error: result.error ?? 'Slack action failed',
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
if (isRecord(result.data)) {
|
|
231
|
+
return {
|
|
232
|
+
success: true,
|
|
233
|
+
channel: result.data.channel,
|
|
234
|
+
ts: result.data.ts,
|
|
235
|
+
unresolvedMentions: result.data.unresolvedMentions,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
success: true,
|
|
240
|
+
value: result.data ?? result.output,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
function withOptionalMetadata(value, result, outputConfig) {
|
|
244
|
+
if (!outputConfig.includeMetadata || result.metadata === undefined) {
|
|
245
|
+
return value;
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
value,
|
|
249
|
+
metadata: result.metadata,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
function projectionToText(value) {
|
|
253
|
+
if (typeof value === 'string')
|
|
254
|
+
return value;
|
|
255
|
+
if (value === null || value === undefined)
|
|
256
|
+
return '';
|
|
257
|
+
if (Array.isArray(value))
|
|
258
|
+
return value.map((entry) => projectionToText(entry)).join('\n');
|
|
259
|
+
if (isRecord(value)) {
|
|
260
|
+
if ('output' in value)
|
|
261
|
+
return projectionToText(value.output);
|
|
262
|
+
if ('value' in value)
|
|
263
|
+
return projectionToText(value.value);
|
|
264
|
+
if ('text' in value)
|
|
265
|
+
return projectionToText(value.text);
|
|
266
|
+
if ('ts' in value)
|
|
267
|
+
return projectionToText(value.ts);
|
|
268
|
+
if ('channel' in value)
|
|
269
|
+
return projectionToText(value.channel);
|
|
270
|
+
}
|
|
271
|
+
return JSON.stringify(value);
|
|
272
|
+
}
|
|
273
|
+
function resolvePath(value, path) {
|
|
274
|
+
if (!path)
|
|
275
|
+
return value;
|
|
276
|
+
let current = value;
|
|
277
|
+
for (const segment of path.split('.')) {
|
|
278
|
+
if (Array.isArray(current) && /^\d+$/.test(segment)) {
|
|
279
|
+
current = current[Number(segment)];
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (isRecord(current)) {
|
|
283
|
+
current = current[segment];
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
return undefined;
|
|
287
|
+
}
|
|
288
|
+
return current;
|
|
289
|
+
}
|
|
290
|
+
function normalizeResolvedParams(params) {
|
|
291
|
+
const normalized = {};
|
|
292
|
+
for (const [key, value] of Object.entries(params)) {
|
|
293
|
+
normalized[key] = coerceScalar(value);
|
|
294
|
+
}
|
|
295
|
+
return normalized;
|
|
296
|
+
}
|
|
297
|
+
function coerceScalar(value) {
|
|
298
|
+
if (typeof value !== 'string') {
|
|
299
|
+
return value;
|
|
300
|
+
}
|
|
301
|
+
const trimmed = value.trim();
|
|
302
|
+
if ((trimmed.startsWith('{') && trimmed.endsWith('}')) ||
|
|
303
|
+
(trimmed.startsWith('[') && trimmed.endsWith(']')) ||
|
|
304
|
+
(trimmed.startsWith('"') && trimmed.endsWith('"'))) {
|
|
305
|
+
try {
|
|
306
|
+
return JSON.parse(trimmed);
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
return value;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return value;
|
|
313
|
+
}
|
|
314
|
+
function readJsonParam(value, name) {
|
|
315
|
+
if (value === undefined)
|
|
316
|
+
return undefined;
|
|
317
|
+
if (typeof value !== 'string')
|
|
318
|
+
return value;
|
|
319
|
+
try {
|
|
320
|
+
return JSON.parse(value);
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
throw new Error(`Slack step params.${name} must be valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
function readRequiredString(value, name) {
|
|
327
|
+
if (typeof value === 'string' && value.length > 0)
|
|
328
|
+
return value;
|
|
329
|
+
throw new Error(`Slack step requires ${name}`);
|
|
330
|
+
}
|
|
331
|
+
function readOptionalString(value) {
|
|
332
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
333
|
+
}
|
|
334
|
+
function readStringArray(value) {
|
|
335
|
+
if (value === undefined)
|
|
336
|
+
return undefined;
|
|
337
|
+
if (Array.isArray(value) && value.every((item) => typeof item === 'string'))
|
|
338
|
+
return value;
|
|
339
|
+
throw new Error('Slack step mentions must be a string array');
|
|
340
|
+
}
|
|
341
|
+
function readOptionalBoolean(value, name) {
|
|
342
|
+
if (value === undefined)
|
|
343
|
+
return undefined;
|
|
344
|
+
if (typeof value === 'boolean')
|
|
345
|
+
return value;
|
|
346
|
+
if (value === 'true')
|
|
347
|
+
return true;
|
|
348
|
+
if (value === 'false')
|
|
349
|
+
return false;
|
|
350
|
+
throw new Error(`Slack step ${name} must be a boolean`);
|
|
351
|
+
}
|
|
352
|
+
function isRecord(value) {
|
|
353
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
354
|
+
}
|
|
355
|
+
//# sourceMappingURL=workflow-step.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-step.js","sourceRoot":"","sources":["../src/workflow-step.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Slack Primitive Examples
|
|
2
|
+
|
|
3
|
+
## Runtime selection
|
|
4
|
+
|
|
5
|
+
`SlackClient` / `SlackStepExecutor` picks one of three runtimes automatically based on what's in the environment:
|
|
6
|
+
|
|
7
|
+
| Priority | Runtime | Activated by | Transport |
|
|
8
|
+
| -------- | ------------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
9
|
+
| 1 | `cloud-relay` | `CLOUD_API_TOKEN` + `CLOUD_API_URL` | `POST /api/v1/slack/post-message` on relay-cloud, which uses the workspace's Nango Slack connection (the ricky app). The caller never holds a Slack bot token. |
|
|
10
|
+
| 2 | `local` | `SLACK_BOT_TOKEN` | `@slack/web-api` direct to Slack. |
|
|
11
|
+
| 3 | `noop` | _(neither)_ | Calls succeed, log a warning, and return a placeholder `ts`. Useful for CI / smoke runs where Slack delivery isn't required. |
|
|
12
|
+
|
|
13
|
+
Override with `runtime: 'local' | 'cloud-relay' | 'noop' | 'auto'` in the config.
|
|
14
|
+
|
|
15
|
+
> v1 limitation: in `cloud-relay` mode, `resolveUser` and `resolveChannel` throw `unsupported_in_cloud_relay`. Pass Slack user/channel IDs directly. Mention resolution (`@email@example.com`, `@handle`) is local-only.
|
|
16
|
+
|
|
17
|
+
## Manual Smoke Test (local runtime)
|
|
18
|
+
|
|
19
|
+
Set `SLACK_BOT_TOKEN` to a bot token with `chat:write`, `channels:read`, `groups:read`, `users:read`, and `users:read.email` scopes. Invite the bot to the destination channel and set `SLACK_CHANNEL` to either a channel id or a `#channel-name` reference.
|
|
20
|
+
|
|
21
|
+
Run the notification example from `packages/slack-primitive`:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
SLACK_BOT_TOKEN=xoxb-... SLACK_CHANNEL=#engineering npx tsx examples/notify-on-pr.ts
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The workflow should open the configured GitHub pull request step and then post a one-line Slack announcement containing the pull request URL. Use `GITHUB_REPO`, `GITHUB_BASE_BRANCH`, and `GITHUB_BRANCH_OVERRIDE` to point the GitHub step at a prepared sandbox branch.
|
|
28
|
+
|
|
29
|
+
## Manual Smoke Test (cloud-relay runtime)
|
|
30
|
+
|
|
31
|
+
Connect Slack on the workspace (one-time, via the cloud dashboard's integrations page). Then point the example at relay-cloud with a CLI api token:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
CLOUD_API_TOKEN=rk_cli_... \
|
|
35
|
+
CLOUD_API_URL=https://api.agentrelay.com \
|
|
36
|
+
SLACK_CHANNEL=#engineering \
|
|
37
|
+
npx tsx examples/notify-on-pr.ts
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
No `SLACK_BOT_TOKEN` is required — the message is posted via the workspace's existing Nango Slack connection.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { WorkflowRunner, type RelayYamlConfig } from '@agent-relay/sdk/workflows';
|
|
2
|
+
import { GitHubStepExecutor, createGitHubStep } from '@agent-relay/github-primitive/workflow-step';
|
|
3
|
+
import type { AgentDefinition, RunnerStepExecutor, WorkflowStep } from '@agent-relay/workflow-types';
|
|
4
|
+
|
|
5
|
+
import { SlackStepExecutor, createSlackStep } from '../src/workflow-step.js';
|
|
6
|
+
|
|
7
|
+
const repo = process.env.GITHUB_REPO ?? 'AgentWorkforce/scratch';
|
|
8
|
+
const baseBranch = process.env.GITHUB_BASE_BRANCH ?? 'main';
|
|
9
|
+
const branchName = process.env.GITHUB_BRANCH_OVERRIDE ?? `examples/slack-primitive-${Date.now()}`;
|
|
10
|
+
const slackChannel = process.env.SLACK_CHANNEL ?? '#engineering';
|
|
11
|
+
|
|
12
|
+
const slackExecutor = new SlackStepExecutor({
|
|
13
|
+
token: process.env.SLACK_BOT_TOKEN,
|
|
14
|
+
});
|
|
15
|
+
const githubExecutor = new GitHubStepExecutor();
|
|
16
|
+
|
|
17
|
+
const localExecutor: RunnerStepExecutor = {
|
|
18
|
+
executeAgentStep(
|
|
19
|
+
_step: WorkflowStep,
|
|
20
|
+
_agentDef: AgentDefinition,
|
|
21
|
+
_resolvedTask: string,
|
|
22
|
+
_timeoutMs?: number
|
|
23
|
+
): Promise<string> {
|
|
24
|
+
return Promise.reject(new Error('notify-on-pr only uses integration steps.'));
|
|
25
|
+
},
|
|
26
|
+
async executeIntegrationStep(
|
|
27
|
+
step: WorkflowStep,
|
|
28
|
+
resolvedParams: Record<string, string>,
|
|
29
|
+
context: { workspaceId?: string }
|
|
30
|
+
): Promise<{ output: string; success: boolean }> {
|
|
31
|
+
if (step.integration === 'github') {
|
|
32
|
+
return githubExecutor.executeIntegrationStep(step, resolvedParams, context);
|
|
33
|
+
}
|
|
34
|
+
if (step.integration === 'slack') {
|
|
35
|
+
return slackExecutor.executeIntegrationStep(step, resolvedParams);
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
success: false,
|
|
39
|
+
output: `Unsupported integration "${step.integration ?? 'unknown'}"`,
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const config: RelayYamlConfig = {
|
|
45
|
+
version: '1.0',
|
|
46
|
+
name: 'notify-on-pr',
|
|
47
|
+
description: 'Open a GitHub pull request and announce it in Slack.',
|
|
48
|
+
swarm: { pattern: 'pipeline' },
|
|
49
|
+
agents: [],
|
|
50
|
+
workflows: [
|
|
51
|
+
{
|
|
52
|
+
name: 'notify-on-pr',
|
|
53
|
+
steps: [
|
|
54
|
+
createGitHubStep({
|
|
55
|
+
name: 'create-pr',
|
|
56
|
+
action: 'createPR',
|
|
57
|
+
repo,
|
|
58
|
+
params: {
|
|
59
|
+
title: `examples: slack primitive notification (${branchName})`,
|
|
60
|
+
body: 'Opened by packages/slack-primitive/examples/notify-on-pr.ts.',
|
|
61
|
+
base: baseBranch,
|
|
62
|
+
head: branchName,
|
|
63
|
+
draft: true,
|
|
64
|
+
},
|
|
65
|
+
output: {
|
|
66
|
+
mode: 'data',
|
|
67
|
+
format: 'json',
|
|
68
|
+
},
|
|
69
|
+
}),
|
|
70
|
+
createSlackStep({
|
|
71
|
+
name: 'announce-pr',
|
|
72
|
+
dependsOn: ['create-pr'],
|
|
73
|
+
action: 'postMessage',
|
|
74
|
+
channel: slackChannel,
|
|
75
|
+
text: 'PR opened: {{steps.create-pr.output.htmlUrl}}',
|
|
76
|
+
unfurl: true,
|
|
77
|
+
output: {
|
|
78
|
+
mode: 'summary',
|
|
79
|
+
format: 'json',
|
|
80
|
+
pretty: true,
|
|
81
|
+
},
|
|
82
|
+
}),
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const runner = new WorkflowRunner({
|
|
89
|
+
cwd: process.cwd(),
|
|
90
|
+
executor: localExecutor,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
await runner.execute(config);
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agent-relay/slack-primitive",
|
|
3
|
+
"version": "6.0.12",
|
|
4
|
+
"description": "Slack workflow primitive for Agent Relay",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./workflow-step": {
|
|
15
|
+
"types": "./dist/workflow-step.d.ts",
|
|
16
|
+
"import": "./dist/workflow-step.js",
|
|
17
|
+
"default": "./dist/workflow-step.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"examples",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsc",
|
|
27
|
+
"clean": "rm -rf dist",
|
|
28
|
+
"test": "vitest run",
|
|
29
|
+
"test:watch": "vitest",
|
|
30
|
+
"typecheck:examples": "tsc -p tsconfig.examples.json --noEmit"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@agent-relay/workflow-types": "6.0.12",
|
|
34
|
+
"@slack/web-api": "^7.15.2"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@agent-relay/github-primitive": "6.0.12",
|
|
38
|
+
"@types/node": "^22.19.3",
|
|
39
|
+
"typescript": "^5.9.3",
|
|
40
|
+
"vitest": "^3.2.4"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "git+https://github.com/AgentWorkforce/relay.git",
|
|
48
|
+
"directory": "packages/slack-primitive"
|
|
49
|
+
}
|
|
50
|
+
}
|