@interactive-inc/claude-funnel 0.23.0 → 0.24.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/dist/bin.js +339 -336
- package/dist/connectors/slack.d.ts +1 -1
- package/dist/connectors/slack.js +1 -1
- package/dist/gateway/daemon.js +168 -165
- package/dist/index.d.ts +8 -1
- package/dist/index.js +6 -2
- package/dist/{slack-connector-schema-B3jr-RTH.js → slack-connector-schema-B0NyhxqQ.js} +92 -3
- package/dist/{slack-listener-tQH7cXU7.d.ts → slack-listener-DbNCPMqY.d.ts} +3 -0
- package/funnel.schema.json +3 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { n as discordConnectorSchema, t as DiscordConnectorConfig } from "./disc
|
|
|
3
3
|
import { n as FunnelConnectorListener, r as NotifyFn, t as FunnelLogger } from "./logger-B3aXsVcX.js";
|
|
4
4
|
import { a as FunnelProcessRunner, c as RunResult, i as DetachOptions, n as ghConnectorSchema, o as ProcessSnapshot, r as AttachOptions, s as RunOptions, t as GhConnectorConfig } from "./gh-connector-schema-Cmi57jvL.js";
|
|
5
5
|
import { a as FunnelFileSystem, c as ScheduleEntry, d as scheduleEntrySchema, i as FileStat, l as scheduleCatchupPolicySchema, n as ScheduleOnFired, o as ScheduleCatchupPolicy, s as ScheduleConnectorConfig, u as scheduleConnectorSchema } from "./schedule-listener-CBYF2bGZ.js";
|
|
6
|
-
import { a as SlackProcessed, c as SlackRawEvent, i as FunnelSlackEventProcessor, l as SlackConnectorConfig, n as SlackOnAppCreated, o as SlackProcessedEmit, r as SlackPreprocessEvent, s as SlackProcessedSkip, u as slackConnectorSchema } from "./slack-listener-
|
|
6
|
+
import { a as SlackProcessed, c as SlackRawEvent, i as FunnelSlackEventProcessor, l as SlackConnectorConfig, n as SlackOnAppCreated, o as SlackProcessedEmit, r as SlackPreprocessEvent, s as SlackProcessedSkip, u as slackConnectorSchema } from "./slack-listener-DbNCPMqY.js";
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
import * as _$hono_factory0 from "hono/factory";
|
|
9
9
|
import { Hono } from "hono";
|
|
@@ -18,6 +18,7 @@ declare const connectorConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
18
18
|
type: z.ZodLiteral<"slack">;
|
|
19
19
|
botToken: z.ZodString;
|
|
20
20
|
appToken: z.ZodString;
|
|
21
|
+
minify: z.ZodDefault<z.ZodBoolean>;
|
|
21
22
|
createdAt: z.ZodOptional<z.ZodString>;
|
|
22
23
|
updatedAt: z.ZodOptional<z.ZodString>;
|
|
23
24
|
}, z.core.$strip>, z.ZodObject<{
|
|
@@ -159,6 +160,7 @@ declare const channelConfigSchema: z.ZodObject<{
|
|
|
159
160
|
type: z.ZodLiteral<"slack">;
|
|
160
161
|
botToken: z.ZodString;
|
|
161
162
|
appToken: z.ZodString;
|
|
163
|
+
minify: z.ZodDefault<z.ZodBoolean>;
|
|
162
164
|
createdAt: z.ZodOptional<z.ZodString>;
|
|
163
165
|
updatedAt: z.ZodOptional<z.ZodString>;
|
|
164
166
|
}, z.core.$strip>, z.ZodObject<{
|
|
@@ -220,6 +222,7 @@ declare const settingsSchema: z.ZodObject<{
|
|
|
220
222
|
type: z.ZodLiteral<"slack">;
|
|
221
223
|
botToken: z.ZodString;
|
|
222
224
|
appToken: z.ZodString;
|
|
225
|
+
minify: z.ZodDefault<z.ZodBoolean>;
|
|
223
226
|
createdAt: z.ZodOptional<z.ZodString>;
|
|
224
227
|
updatedAt: z.ZodOptional<z.ZodString>;
|
|
225
228
|
}, z.core.$strip>, z.ZodObject<{
|
|
@@ -286,6 +289,7 @@ type AddConnectorInput = {
|
|
|
286
289
|
name: string;
|
|
287
290
|
botToken: string;
|
|
288
291
|
appToken: string;
|
|
292
|
+
minify?: boolean;
|
|
289
293
|
} | {
|
|
290
294
|
type: "gh";
|
|
291
295
|
name: string;
|
|
@@ -532,6 +536,7 @@ declare const connectorSpecSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
532
536
|
name: z.ZodString;
|
|
533
537
|
botToken: z.ZodOptional<z.ZodString>;
|
|
534
538
|
appToken: z.ZodOptional<z.ZodString>;
|
|
539
|
+
minify: z.ZodOptional<z.ZodBoolean>;
|
|
535
540
|
env: z.ZodOptional<z.ZodObject<{
|
|
536
541
|
botToken: z.ZodOptional<z.ZodString>;
|
|
537
542
|
appToken: z.ZodOptional<z.ZodString>;
|
|
@@ -562,6 +567,7 @@ declare const channelSpecSchema: z.ZodObject<{
|
|
|
562
567
|
name: z.ZodString;
|
|
563
568
|
botToken: z.ZodOptional<z.ZodString>;
|
|
564
569
|
appToken: z.ZodOptional<z.ZodString>;
|
|
570
|
+
minify: z.ZodOptional<z.ZodBoolean>;
|
|
565
571
|
env: z.ZodOptional<z.ZodObject<{
|
|
566
572
|
botToken: z.ZodOptional<z.ZodString>;
|
|
567
573
|
appToken: z.ZodOptional<z.ZodString>;
|
|
@@ -595,6 +601,7 @@ declare const localConfigSchema: z.ZodObject<{
|
|
|
595
601
|
name: z.ZodString;
|
|
596
602
|
botToken: z.ZodOptional<z.ZodString>;
|
|
597
603
|
appToken: z.ZodOptional<z.ZodString>;
|
|
604
|
+
minify: z.ZodOptional<z.ZodBoolean>;
|
|
598
605
|
env: z.ZodOptional<z.ZodObject<{
|
|
599
606
|
botToken: z.ZodOptional<z.ZodString>;
|
|
600
607
|
appToken: z.ZodOptional<z.ZodString>;
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { i as FunnelDiscordAdapter, n as FunnelDiscordListener, t as discordConn
|
|
|
2
2
|
import { i as FunnelConnectorListener, n as funnelTmpDir, r as FunnelLogger, t as NodeFunnelLogger } from "./node-logger-B97ZiGwj.js";
|
|
3
3
|
import { a as FunnelProcessRunner, i as NodeFunnelProcessRunner, n as FunnelGhListener, r as FunnelGhAdapter, t as ghConnectorSchema } from "./gh-connector-schema-CAC24s0r.js";
|
|
4
4
|
import { a as ScheduleStateStore, i as FunnelScheduleListener, n as scheduleConnectorSchema, o as NodeFunnelFileSystem, r as scheduleEntrySchema, s as FunnelFileSystem, t as scheduleCatchupPolicySchema } from "./schedule-connector-schema-BZpH6ZmR.js";
|
|
5
|
-
import { i as FunnelSlackAdapter, n as FunnelSlackListener, r as FunnelSlackEventProcessor, t as slackConnectorSchema } from "./slack-connector-schema-
|
|
5
|
+
import { i as FunnelSlackAdapter, n as FunnelSlackListener, r as FunnelSlackEventProcessor, t as slackConnectorSchema } from "./slack-connector-schema-B0NyhxqQ.js";
|
|
6
6
|
import { dirname, join, resolve } from "node:path";
|
|
7
7
|
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
8
8
|
import { homedir } from "node:os";
|
|
@@ -401,6 +401,7 @@ var FunnelChannels = class {
|
|
|
401
401
|
name: input.name,
|
|
402
402
|
botToken: input.botToken,
|
|
403
403
|
appToken: input.appToken,
|
|
404
|
+
minify: input.minify ?? true,
|
|
404
405
|
createdAt,
|
|
405
406
|
updatedAt
|
|
406
407
|
};
|
|
@@ -800,6 +801,8 @@ const slackConnectorSpecSchema = z.object({
|
|
|
800
801
|
name: z.string(),
|
|
801
802
|
botToken: z.string().optional(),
|
|
802
803
|
appToken: z.string().optional(),
|
|
804
|
+
/** Shrink raw Slack events before fanout. Defaults to true. */
|
|
805
|
+
minify: z.boolean().optional(),
|
|
803
806
|
env: slackEnvSchema
|
|
804
807
|
});
|
|
805
808
|
const discordEnvSchema = z.object({ botToken: z.string().optional() }).optional();
|
|
@@ -1065,7 +1068,8 @@ var FunnelLocalConfigSync = class {
|
|
|
1065
1068
|
type: "slack",
|
|
1066
1069
|
name: spec.name,
|
|
1067
1070
|
botToken,
|
|
1068
|
-
appToken
|
|
1071
|
+
appToken,
|
|
1072
|
+
...spec.minify !== void 0 ? { minify: spec.minify } : {}
|
|
1069
1073
|
}).id,
|
|
1070
1074
|
name: spec.name,
|
|
1071
1075
|
changed: true
|
|
@@ -46,6 +46,90 @@ var FunnelSlackAdapter = class extends FunnelConnectorAdapter {
|
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
48
|
//#endregion
|
|
49
|
+
//#region lib/connectors/minify-slack-event.ts
|
|
50
|
+
const TOP_LEVEL_KEYS = [
|
|
51
|
+
"type",
|
|
52
|
+
"subtype",
|
|
53
|
+
"user",
|
|
54
|
+
"bot_id",
|
|
55
|
+
"text",
|
|
56
|
+
"ts",
|
|
57
|
+
"thread_ts",
|
|
58
|
+
"channel",
|
|
59
|
+
"channel_type",
|
|
60
|
+
"files",
|
|
61
|
+
"attachments"
|
|
62
|
+
];
|
|
63
|
+
const FILE_KEYS = [
|
|
64
|
+
"id",
|
|
65
|
+
"name",
|
|
66
|
+
"mimetype",
|
|
67
|
+
"filetype",
|
|
68
|
+
"size",
|
|
69
|
+
"url_private",
|
|
70
|
+
"permalink"
|
|
71
|
+
];
|
|
72
|
+
const ATTACHMENT_KEYS = [
|
|
73
|
+
"title",
|
|
74
|
+
"text",
|
|
75
|
+
"fallback"
|
|
76
|
+
];
|
|
77
|
+
const isRecord = (value) => {
|
|
78
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
79
|
+
};
|
|
80
|
+
const pickDefined = (source, keys) => {
|
|
81
|
+
const picked = {};
|
|
82
|
+
for (const key of keys) if (source[key] !== void 0) picked[key] = source[key];
|
|
83
|
+
return picked;
|
|
84
|
+
};
|
|
85
|
+
const hasThumbOrPreviewKey = (file) => {
|
|
86
|
+
return Object.keys(file).some((key) => key.startsWith("thumb") || key.startsWith("preview"));
|
|
87
|
+
};
|
|
88
|
+
const minifyFile = (file) => {
|
|
89
|
+
if (!isRecord(file)) return file;
|
|
90
|
+
const minified = pickDefined(file, FILE_KEYS);
|
|
91
|
+
if (hasThumbOrPreviewKey(file)) minified._funnel_omitted = ["thumb_*"];
|
|
92
|
+
return minified;
|
|
93
|
+
};
|
|
94
|
+
const flattenRichText = (node) => {
|
|
95
|
+
if (!isRecord(node)) return "";
|
|
96
|
+
const text = node.text;
|
|
97
|
+
if (typeof text === "string") return text;
|
|
98
|
+
const elements = node.elements;
|
|
99
|
+
if (!Array.isArray(elements)) return "";
|
|
100
|
+
return elements.map(flattenRichText).join("");
|
|
101
|
+
};
|
|
102
|
+
const flattenTableRow = (row) => {
|
|
103
|
+
if (!Array.isArray(row)) return "";
|
|
104
|
+
return row.map(flattenRichText).join(" ");
|
|
105
|
+
};
|
|
106
|
+
const flattenBlock = (block) => {
|
|
107
|
+
if (!isRecord(block)) return "";
|
|
108
|
+
if (block.type === "table" && Array.isArray(block.rows)) return block.rows.map(flattenTableRow).join("\n");
|
|
109
|
+
return flattenRichText(block);
|
|
110
|
+
};
|
|
111
|
+
const flattenBlocks = (blocks) => {
|
|
112
|
+
return blocks.map(flattenBlock).filter((line) => line.length > 0).join("\n");
|
|
113
|
+
};
|
|
114
|
+
const minifyAttachment = (attachment) => {
|
|
115
|
+
if (!isRecord(attachment)) return attachment;
|
|
116
|
+
const minified = pickDefined(attachment, ATTACHMENT_KEYS);
|
|
117
|
+
const blocks = attachment.blocks;
|
|
118
|
+
if (Array.isArray(blocks)) {
|
|
119
|
+
const flattened = flattenBlocks(blocks);
|
|
120
|
+
const existingText = typeof minified.text === "string" ? minified.text : "";
|
|
121
|
+
minified.text = existingText ? `${existingText}\n${flattened}` : flattened;
|
|
122
|
+
minified._funnel_omitted = ["blocks"];
|
|
123
|
+
}
|
|
124
|
+
return minified;
|
|
125
|
+
};
|
|
126
|
+
const minifySlackEvent = (event) => {
|
|
127
|
+
const minified = pickDefined(event, TOP_LEVEL_KEYS);
|
|
128
|
+
if (Array.isArray(minified.files)) minified.files = minified.files.map(minifyFile);
|
|
129
|
+
if (Array.isArray(minified.attachments)) minified.attachments = minified.attachments.map(minifyAttachment);
|
|
130
|
+
return minified;
|
|
131
|
+
};
|
|
132
|
+
//#endregion
|
|
49
133
|
//#region lib/connectors/slack-event-processor.ts
|
|
50
134
|
const ALLOWED_EVENTS = new Set(["message", "app_mention"]);
|
|
51
135
|
const ALLOWED_SUBTYPES = new Set([
|
|
@@ -62,11 +146,13 @@ const getString = (event, key) => {
|
|
|
62
146
|
var FunnelSlackEventProcessor = class {
|
|
63
147
|
ownBotUserId;
|
|
64
148
|
ownBotId;
|
|
149
|
+
minify;
|
|
65
150
|
now;
|
|
66
151
|
dedup = /* @__PURE__ */ new Map();
|
|
67
152
|
constructor(props) {
|
|
68
153
|
this.ownBotUserId = props.ownBotUserId;
|
|
69
154
|
this.ownBotId = props.ownBotId;
|
|
155
|
+
this.minify = props.minify ?? true;
|
|
70
156
|
this.now = props.now ?? (() => Date.now());
|
|
71
157
|
}
|
|
72
158
|
process(event) {
|
|
@@ -86,9 +172,10 @@ var FunnelSlackEventProcessor = class {
|
|
|
86
172
|
if (botId === this.ownBotId) return { skip: true };
|
|
87
173
|
const mentioned = (getString(event, "text") ?? "").includes(`<@${this.ownBotUserId}>`);
|
|
88
174
|
const threadTs = getString(event, "thread_ts") ?? getString(event, "ts") ?? "";
|
|
175
|
+
const emitted = this.minify ? minifySlackEvent(event) : event;
|
|
89
176
|
return {
|
|
90
177
|
skip: false,
|
|
91
|
-
content: JSON.stringify(
|
|
178
|
+
content: JSON.stringify(emitted),
|
|
92
179
|
meta: {
|
|
93
180
|
event_type: "slack",
|
|
94
181
|
channel_id: channelId,
|
|
@@ -129,7 +216,8 @@ var FunnelSlackListener = class extends FunnelConnectorListener {
|
|
|
129
216
|
const authResult = await app.client.auth.test({ token: this.config.botToken });
|
|
130
217
|
const processor = new FunnelSlackEventProcessor({
|
|
131
218
|
ownBotUserId: authResult.user_id ?? "",
|
|
132
|
-
ownBotId: authResult.bot_id ?? ""
|
|
219
|
+
ownBotId: authResult.bot_id ?? "",
|
|
220
|
+
minify: this.config.minify
|
|
133
221
|
});
|
|
134
222
|
const preprocess = this.preprocessEvent;
|
|
135
223
|
app.use(async (args) => {
|
|
@@ -140,6 +228,7 @@ var FunnelSlackListener = class extends FunnelConnectorListener {
|
|
|
140
228
|
if (event === null) return;
|
|
141
229
|
const result = processor.process(event);
|
|
142
230
|
if (result.skip) return;
|
|
231
|
+
await notify(result.content, result.meta);
|
|
143
232
|
if (result.shouldReact) try {
|
|
144
233
|
await app.client.reactions.add({
|
|
145
234
|
token: this.config.botToken,
|
|
@@ -148,7 +237,6 @@ var FunnelSlackListener = class extends FunnelConnectorListener {
|
|
|
148
237
|
name: "eyes"
|
|
149
238
|
});
|
|
150
239
|
} catch {}
|
|
151
|
-
await notify(result.content, result.meta);
|
|
152
240
|
});
|
|
153
241
|
app.error(async (error) => {
|
|
154
242
|
this.logger.error("Slack error", { error: error instanceof Error ? error.message : String(error) });
|
|
@@ -179,6 +267,7 @@ const slackConnectorSchema = z.object({
|
|
|
179
267
|
type: z.literal("slack"),
|
|
180
268
|
botToken: z.string().startsWith("xoxb-"),
|
|
181
269
|
appToken: z.string().startsWith("xapp-"),
|
|
270
|
+
minify: z.boolean().default(true),
|
|
182
271
|
createdAt: z.string().datetime().optional(),
|
|
183
272
|
updatedAt: z.string().datetime().optional()
|
|
184
273
|
});
|
|
@@ -9,6 +9,7 @@ declare const slackConnectorSchema: z.ZodObject<{
|
|
|
9
9
|
type: z.ZodLiteral<"slack">;
|
|
10
10
|
botToken: z.ZodString;
|
|
11
11
|
appToken: z.ZodString;
|
|
12
|
+
minify: z.ZodDefault<z.ZodBoolean>;
|
|
12
13
|
createdAt: z.ZodOptional<z.ZodString>;
|
|
13
14
|
updatedAt: z.ZodOptional<z.ZodString>;
|
|
14
15
|
}, z.core.$strip>;
|
|
@@ -31,11 +32,13 @@ type SlackProcessed = SlackProcessedSkip | SlackProcessedEmit;
|
|
|
31
32
|
type Props = {
|
|
32
33
|
ownBotUserId: string;
|
|
33
34
|
ownBotId: string;
|
|
35
|
+
minify?: boolean;
|
|
34
36
|
now?: () => number;
|
|
35
37
|
};
|
|
36
38
|
declare class FunnelSlackEventProcessor {
|
|
37
39
|
private readonly ownBotUserId;
|
|
38
40
|
private readonly ownBotId;
|
|
41
|
+
private readonly minify;
|
|
39
42
|
private readonly now;
|
|
40
43
|
private readonly dedup;
|
|
41
44
|
constructor(props: Props);
|
package/funnel.schema.json
CHANGED
package/package.json
CHANGED