hybrid 1.3.2 → 1.4.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/README.md +5 -13
- package/dist/behaviors/index.cjs +162 -0
- package/dist/behaviors/index.cjs.map +1 -0
- package/dist/behaviors/index.d.cts +32 -0
- package/dist/behaviors/index.d.ts +32 -0
- package/dist/behaviors/index.js +133 -0
- package/dist/behaviors/index.js.map +1 -0
- package/dist/index.cjs +294 -437
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -130
- package/dist/index.d.ts +22 -130
- package/dist/index.js +289 -430
- package/dist/index.js.map +1 -1
- package/dist/tools/index.cjs +235 -112
- package/dist/tools/index.cjs.map +1 -1
- package/dist/tools/index.d.cts +1818 -6
- package/dist/tools/index.d.ts +1818 -6
- package/dist/tools/index.js +239 -112
- package/dist/tools/index.js.map +1 -1
- package/package.json +16 -10
- package/src/behaviors/filter-messages.test.ts +177 -0
- package/src/behaviors/filter-messages.ts +100 -0
- package/src/behaviors/index.ts +16 -0
- package/src/behaviors/react-with.ts +47 -0
- package/src/behaviors/threaded-reply.test.ts +41 -0
- package/src/behaviors/threaded-reply.ts +27 -0
- package/src/core/agent.ts +28 -107
- package/src/core/plugin.ts +7 -36
- package/src/core/tool.ts +19 -52
- package/src/index.ts +1 -7
- package/src/server/listen.ts +52 -112
- package/src/server/listen.ts.old +327 -0
- package/src/server/{processor.ts → processor.ts.old} +9 -1
- package/src/tools/blockchain.ts +11 -10
- package/src/tools/xmtp.ts +269 -128
- package/README.md.old +0 -167
- package/dist/index-C_JSkCHP.d.cts +0 -1927
- package/dist/index-C_JSkCHP.d.ts +0 -1927
- package/src/types.ts +0 -38
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
#
|
|
1
|
+
# hybrid
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This package is part of the Hybrid monorepo.
|
|
4
4
|
|
|
5
5
|
Hybrid makes it easy for developers to create intelligent agents that can understand natural language, process messages, and respond through XMTP's decentralized messaging protocol.
|
|
6
6
|
|
|
7
|
-
See [
|
|
7
|
+
See [hybrid.dev](https://hybrid.dev) for more information.
|
|
8
8
|
|
|
9
9
|
## 📦 Quickstart
|
|
10
10
|
|
|
@@ -49,18 +49,10 @@ hybrid register
|
|
|
49
49
|
|
|
50
50
|
This generates secure wallet and encryption keys for your XMTP agent.
|
|
51
51
|
|
|
52
|
-
### 5.
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
hybrid register
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### 6. Start developing
|
|
52
|
+
### 5. Start developing
|
|
59
53
|
|
|
60
54
|
```bash
|
|
61
55
|
hybrid dev
|
|
62
56
|
```
|
|
63
57
|
|
|
64
|
-
Your agent will start listening for XMTP messages and you're ready to build!
|
|
65
|
-
|
|
66
|
-
Go to [https://xmtp.chat/dm/](https://xmtp.chat/dm/) and send a message to your agent.
|
|
58
|
+
Your agent will start listening for XMTP messages and you're ready to build!
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/behaviors/index.ts
|
|
21
|
+
var behaviors_exports = {};
|
|
22
|
+
__export(behaviors_exports, {
|
|
23
|
+
BehaviorRegistryImpl: () => import_types.BehaviorRegistryImpl,
|
|
24
|
+
filter: () => import_xmtp3.filter,
|
|
25
|
+
filterMessages: () => filterMessages,
|
|
26
|
+
reactWith: () => reactWith,
|
|
27
|
+
threadedReply: () => threadedReply
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(behaviors_exports);
|
|
30
|
+
var import_xmtp3 = require("@hybrd/xmtp");
|
|
31
|
+
|
|
32
|
+
// src/behaviors/filter-messages.ts
|
|
33
|
+
var import_utils = require("@hybrd/utils");
|
|
34
|
+
var import_xmtp = require("@hybrd/xmtp");
|
|
35
|
+
function filterMessages(filters) {
|
|
36
|
+
return {
|
|
37
|
+
id: "filter-messages",
|
|
38
|
+
config: {
|
|
39
|
+
enabled: true,
|
|
40
|
+
config: {
|
|
41
|
+
filters: 1
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
async before(context) {
|
|
45
|
+
const messageContent = typeof context.message.content === "string" ? context.message.content.substring(0, 100) : String(context.message.content || "unknown");
|
|
46
|
+
import_utils.logger.debug(
|
|
47
|
+
`\u{1F50D} [filter-messages] Processing message: ${messageContent}...`
|
|
48
|
+
);
|
|
49
|
+
const filterAPI = {
|
|
50
|
+
fromSelf: () => import_xmtp.filter.fromSelf(context.message, context.client),
|
|
51
|
+
hasContent: () => import_xmtp.filter.hasContent(context.message),
|
|
52
|
+
isDM: () => import_xmtp.filter.isDM(context.conversation),
|
|
53
|
+
isGroup: () => import_xmtp.filter.isGroup(context.conversation),
|
|
54
|
+
isGroupAdmin: () => import_xmtp.filter.isGroupAdmin(
|
|
55
|
+
context.conversation,
|
|
56
|
+
context.message
|
|
57
|
+
),
|
|
58
|
+
isGroupSuperAdmin: () => import_xmtp.filter.isGroupSuperAdmin(
|
|
59
|
+
context.conversation,
|
|
60
|
+
context.message
|
|
61
|
+
),
|
|
62
|
+
isReaction: () => import_xmtp.filter.isReaction(context.message),
|
|
63
|
+
isRemoteAttachment: () => import_xmtp.filter.isRemoteAttachment(context.message),
|
|
64
|
+
isReply: () => import_xmtp.filter.isReply(context.message),
|
|
65
|
+
isText: () => import_xmtp.filter.isText(context.message),
|
|
66
|
+
isTextReply: () => import_xmtp.filter.isTextReply(context.message),
|
|
67
|
+
hasMention: (mention) => {
|
|
68
|
+
const content = typeof context.message.content === "string" ? context.message.content : String(context.message.content || "");
|
|
69
|
+
return content.includes(mention);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
try {
|
|
73
|
+
const passes = filters(filterAPI);
|
|
74
|
+
if (!passes) {
|
|
75
|
+
import_utils.logger.debug(
|
|
76
|
+
`\u{1F507} [filter-messages] Filter failed - message filtered out`
|
|
77
|
+
);
|
|
78
|
+
if (!context.sendOptions) {
|
|
79
|
+
context.sendOptions = {};
|
|
80
|
+
}
|
|
81
|
+
context.sendOptions.filtered = true;
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
import_utils.logger.debug(`\u2705 [filter-messages] Filter passed`);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
import_utils.logger.error("Error executing message filter:", error);
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
import_utils.logger.debug(`\u2705 [filter-messages] Filter passed, continuing chain`);
|
|
90
|
+
await context.next?.();
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// src/behaviors/react-with.ts
|
|
96
|
+
var import_utils2 = require("@hybrd/utils");
|
|
97
|
+
var import_xmtp2 = require("@hybrd/xmtp");
|
|
98
|
+
function reactWith(reaction, options = {}) {
|
|
99
|
+
return {
|
|
100
|
+
id: `react-with-${reaction}`,
|
|
101
|
+
config: {
|
|
102
|
+
enabled: options.enabled ?? true,
|
|
103
|
+
config: {
|
|
104
|
+
reaction,
|
|
105
|
+
reactToAll: options.reactToAll ?? true
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
async before(context) {
|
|
109
|
+
if (!this.config.enabled) return;
|
|
110
|
+
try {
|
|
111
|
+
const reactionMessage = {
|
|
112
|
+
schema: "unicode",
|
|
113
|
+
reference: context.message.id,
|
|
114
|
+
action: "added",
|
|
115
|
+
contentType: import_xmtp2.ContentTypeReaction,
|
|
116
|
+
content: reaction
|
|
117
|
+
};
|
|
118
|
+
await context.conversation.send(reactionMessage, import_xmtp2.ContentTypeReaction);
|
|
119
|
+
import_utils2.logger.debug(
|
|
120
|
+
`\u2705 [react-with] Reacted with ${reaction} to message ${context.message.id}`
|
|
121
|
+
);
|
|
122
|
+
} catch (error) {
|
|
123
|
+
import_utils2.logger.error(
|
|
124
|
+
`\u274C [react-with] Failed to add reaction ${reaction}:`,
|
|
125
|
+
error
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// src/behaviors/threaded-reply.ts
|
|
133
|
+
function threadedReply(options = {}) {
|
|
134
|
+
return {
|
|
135
|
+
id: "threaded-reply",
|
|
136
|
+
config: {
|
|
137
|
+
enabled: options.enabled ?? true,
|
|
138
|
+
config: {
|
|
139
|
+
alwaysThread: true
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
async after(context) {
|
|
143
|
+
if (!this.config.enabled) return;
|
|
144
|
+
if (!context.sendOptions) {
|
|
145
|
+
context.sendOptions = {};
|
|
146
|
+
}
|
|
147
|
+
context.sendOptions.threaded = true;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// src/behaviors/index.ts
|
|
153
|
+
var import_types = require("@hybrd/types");
|
|
154
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
155
|
+
0 && (module.exports = {
|
|
156
|
+
BehaviorRegistryImpl,
|
|
157
|
+
filter,
|
|
158
|
+
filterMessages,
|
|
159
|
+
reactWith,
|
|
160
|
+
threadedReply
|
|
161
|
+
});
|
|
162
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/behaviors/index.ts","../../src/behaviors/filter-messages.ts","../../src/behaviors/react-with.ts","../../src/behaviors/threaded-reply.ts"],"sourcesContent":["// Re-export XMTP Agent SDK filters for convenience\nexport { filter } from \"@hybrd/xmtp\"\n\nexport * from \"./filter-messages\"\nexport * from \"./react-with\"\nexport * from \"./threaded-reply\"\n\n// Re-export behavior types for convenience\nexport { BehaviorRegistryImpl } from \"@hybrd/types\"\nexport type {\n\tBehavior,\n\tBehaviorConfig,\n\tBehaviorContext,\n\tBehaviorObject,\n\tBehaviorRegistry\n} from \"@hybrd/types\"\n","import type { BehaviorContext, BehaviorObject } from \"@hybrd/types\"\nimport { logger } from \"@hybrd/utils\"\nimport { filter } from \"@hybrd/xmtp\"\n\n// Filter interface that matches XMTP SDK signatures\ninterface FilterAPI {\n\tfromSelf(): boolean\n\thasContent(): boolean\n\tisDM(): boolean\n\tisGroup(): boolean\n\tisGroupAdmin(): boolean\n\tisGroupSuperAdmin(): boolean\n\tisReaction(): boolean\n\tisRemoteAttachment(): boolean\n\tisReply(): boolean\n\tisText(): boolean\n\tisTextReply(): boolean\n\thasMention(mention: string): boolean\n}\n\nexport function filterMessages(\n\tfilters: (api: FilterAPI) => boolean\n): BehaviorObject {\n\treturn {\n\t\tid: \"filter-messages\",\n\t\tconfig: {\n\t\t\tenabled: true,\n\t\t\tconfig: {\n\t\t\t\tfilters: 1\n\t\t\t}\n\t\t},\n\t\tasync before(context: BehaviorContext) {\n\t\t\tconst messageContent =\n\t\t\t\ttypeof context.message.content === \"string\"\n\t\t\t\t\t? context.message.content.substring(0, 100)\n\t\t\t\t\t: String(context.message.content || \"unknown\")\n\t\t\tlogger.debug(\n\t\t\t\t`🔍 [filter-messages] Processing message: ${messageContent}...`\n\t\t\t)\n\n\t\t\t// Create filter API wrapper\n\t\t\tconst filterAPI: FilterAPI = {\n\t\t\t\tfromSelf: () =>\n\t\t\t\t\tfilter.fromSelf(context.message as any, context.client as any),\n\t\t\t\thasContent: () => filter.hasContent(context.message as any),\n\t\t\t\tisDM: () => filter.isDM(context.conversation as any),\n\t\t\t\tisGroup: () => filter.isGroup(context.conversation as any),\n\t\t\t\tisGroupAdmin: () =>\n\t\t\t\t\tfilter.isGroupAdmin(\n\t\t\t\t\t\tcontext.conversation as any,\n\t\t\t\t\t\tcontext.message as any\n\t\t\t\t\t),\n\t\t\t\tisGroupSuperAdmin: () =>\n\t\t\t\t\tfilter.isGroupSuperAdmin(\n\t\t\t\t\t\tcontext.conversation as any,\n\t\t\t\t\t\tcontext.message as any\n\t\t\t\t\t),\n\t\t\t\tisReaction: () => filter.isReaction(context.message as any),\n\t\t\t\tisRemoteAttachment: () =>\n\t\t\t\t\tfilter.isRemoteAttachment(context.message as any),\n\t\t\t\tisReply: () => filter.isReply(context.message as any),\n\t\t\t\tisText: () => filter.isText(context.message as any),\n\t\t\t\tisTextReply: () => filter.isTextReply(context.message as any),\n\t\t\t\thasMention: (mention: string) => {\n\t\t\t\t\tconst content =\n\t\t\t\t\t\ttypeof context.message.content === \"string\"\n\t\t\t\t\t\t\t? context.message.content\n\t\t\t\t\t\t\t: String(context.message.content || \"\")\n\t\t\t\t\treturn content.includes(mention)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst passes = filters(filterAPI)\n\n\t\t\t\tif (!passes) {\n\t\t\t\t\tlogger.debug(\n\t\t\t\t\t\t`🔇 [filter-messages] Filter failed - message filtered out`\n\t\t\t\t\t)\n\t\t\t\t\t// Message filtered, set flag and stop the chain\n\t\t\t\t\tif (!context.sendOptions) {\n\t\t\t\t\t\tcontext.sendOptions = {}\n\t\t\t\t\t}\n\t\t\t\t\tcontext.sendOptions.filtered = true\n\t\t\t\t\t// Don't call next() - this stops the middleware chain\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tlogger.debug(`✅ [filter-messages] Filter passed`)\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"Error executing message filter:\", error)\n\t\t\t\tthrow error // Re-throw to propagate the error\n\t\t\t}\n\n\t\t\tlogger.debug(`✅ [filter-messages] Filter passed, continuing chain`)\n\t\t\t// Filter passed, continue to next behavior\n\t\t\tawait context.next?.()\n\t\t}\n\t}\n}\n","import type { BehaviorContext, BehaviorObject } from \"@hybrd/types\"\nimport { logger } from \"@hybrd/utils\"\nimport { ContentTypeReaction } from \"@hybrd/xmtp\"\n\nexport interface ReactWithOptions {\n\treactToAll?: boolean\n\tenabled?: boolean\n}\n\nexport function reactWith(\n\treaction: string,\n\toptions: ReactWithOptions = {}\n): BehaviorObject {\n\treturn {\n\t\tid: `react-with-${reaction}`,\n\t\tconfig: {\n\t\t\tenabled: options.enabled ?? true,\n\t\t\tconfig: {\n\t\t\t\treaction,\n\t\t\t\treactToAll: options.reactToAll ?? true\n\t\t\t}\n\t\t},\n\t\tasync before(context: BehaviorContext) {\n\t\t\tif (!this.config.enabled) return\n\n\t\t\ttry {\n\t\t\t\tconst reactionMessage = {\n\t\t\t\t\tschema: \"unicode\",\n\t\t\t\t\treference: context.message.id,\n\t\t\t\t\taction: \"added\",\n\t\t\t\t\tcontentType: ContentTypeReaction,\n\t\t\t\t\tcontent: reaction\n\t\t\t\t}\n\n\t\t\t\tawait context.conversation.send(reactionMessage, ContentTypeReaction)\n\t\t\t\tlogger.debug(\n\t\t\t\t\t`✅ [react-with] Reacted with ${reaction} to message ${context.message.id}`\n\t\t\t\t)\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t`❌ [react-with] Failed to add reaction ${reaction}:`,\n\t\t\t\t\terror\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n}\n","import type { BehaviorContext, BehaviorObject } from \"@hybrd/types\"\n\nexport interface ThreadedReplyOptions {\n\tenabled?: boolean\n}\n\nexport function threadedReply(\n\toptions: ThreadedReplyOptions = {}\n): BehaviorObject {\n\treturn {\n\t\tid: \"threaded-reply\",\n\t\tconfig: {\n\t\t\tenabled: options.enabled ?? true,\n\t\t\tconfig: {\n\t\t\t\talwaysThread: true\n\t\t\t}\n\t\t},\n\t\tasync after(context: BehaviorContext) {\n\t\t\tif (!this.config.enabled) return\n\n\t\t\tif (!context.sendOptions) {\n\t\t\t\tcontext.sendOptions = {}\n\t\t\t}\n\t\t\tcontext.sendOptions.threaded = true\n\t\t}\n\t}\n}\n"],"mappings":"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","names":["import_xmtp","import_utils","import_xmtp"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export { filter } from '@hybrd/xmtp';
|
|
2
|
+
import { BehaviorObject } from '@hybrd/types';
|
|
3
|
+
export { Behavior, BehaviorConfig, BehaviorContext, BehaviorObject, BehaviorRegistry, BehaviorRegistryImpl } from '@hybrd/types';
|
|
4
|
+
|
|
5
|
+
interface FilterAPI {
|
|
6
|
+
fromSelf(): boolean;
|
|
7
|
+
hasContent(): boolean;
|
|
8
|
+
isDM(): boolean;
|
|
9
|
+
isGroup(): boolean;
|
|
10
|
+
isGroupAdmin(): boolean;
|
|
11
|
+
isGroupSuperAdmin(): boolean;
|
|
12
|
+
isReaction(): boolean;
|
|
13
|
+
isRemoteAttachment(): boolean;
|
|
14
|
+
isReply(): boolean;
|
|
15
|
+
isText(): boolean;
|
|
16
|
+
isTextReply(): boolean;
|
|
17
|
+
hasMention(mention: string): boolean;
|
|
18
|
+
}
|
|
19
|
+
declare function filterMessages(filters: (api: FilterAPI) => boolean): BehaviorObject;
|
|
20
|
+
|
|
21
|
+
interface ReactWithOptions {
|
|
22
|
+
reactToAll?: boolean;
|
|
23
|
+
enabled?: boolean;
|
|
24
|
+
}
|
|
25
|
+
declare function reactWith(reaction: string, options?: ReactWithOptions): BehaviorObject;
|
|
26
|
+
|
|
27
|
+
interface ThreadedReplyOptions {
|
|
28
|
+
enabled?: boolean;
|
|
29
|
+
}
|
|
30
|
+
declare function threadedReply(options?: ThreadedReplyOptions): BehaviorObject;
|
|
31
|
+
|
|
32
|
+
export { type ReactWithOptions, type ThreadedReplyOptions, filterMessages, reactWith, threadedReply };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export { filter } from '@hybrd/xmtp';
|
|
2
|
+
import { BehaviorObject } from '@hybrd/types';
|
|
3
|
+
export { Behavior, BehaviorConfig, BehaviorContext, BehaviorObject, BehaviorRegistry, BehaviorRegistryImpl } from '@hybrd/types';
|
|
4
|
+
|
|
5
|
+
interface FilterAPI {
|
|
6
|
+
fromSelf(): boolean;
|
|
7
|
+
hasContent(): boolean;
|
|
8
|
+
isDM(): boolean;
|
|
9
|
+
isGroup(): boolean;
|
|
10
|
+
isGroupAdmin(): boolean;
|
|
11
|
+
isGroupSuperAdmin(): boolean;
|
|
12
|
+
isReaction(): boolean;
|
|
13
|
+
isRemoteAttachment(): boolean;
|
|
14
|
+
isReply(): boolean;
|
|
15
|
+
isText(): boolean;
|
|
16
|
+
isTextReply(): boolean;
|
|
17
|
+
hasMention(mention: string): boolean;
|
|
18
|
+
}
|
|
19
|
+
declare function filterMessages(filters: (api: FilterAPI) => boolean): BehaviorObject;
|
|
20
|
+
|
|
21
|
+
interface ReactWithOptions {
|
|
22
|
+
reactToAll?: boolean;
|
|
23
|
+
enabled?: boolean;
|
|
24
|
+
}
|
|
25
|
+
declare function reactWith(reaction: string, options?: ReactWithOptions): BehaviorObject;
|
|
26
|
+
|
|
27
|
+
interface ThreadedReplyOptions {
|
|
28
|
+
enabled?: boolean;
|
|
29
|
+
}
|
|
30
|
+
declare function threadedReply(options?: ThreadedReplyOptions): BehaviorObject;
|
|
31
|
+
|
|
32
|
+
export { type ReactWithOptions, type ThreadedReplyOptions, filterMessages, reactWith, threadedReply };
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// src/behaviors/index.ts
|
|
2
|
+
import { filter as filter2 } from "@hybrd/xmtp";
|
|
3
|
+
|
|
4
|
+
// src/behaviors/filter-messages.ts
|
|
5
|
+
import { logger } from "@hybrd/utils";
|
|
6
|
+
import { filter } from "@hybrd/xmtp";
|
|
7
|
+
function filterMessages(filters) {
|
|
8
|
+
return {
|
|
9
|
+
id: "filter-messages",
|
|
10
|
+
config: {
|
|
11
|
+
enabled: true,
|
|
12
|
+
config: {
|
|
13
|
+
filters: 1
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
async before(context) {
|
|
17
|
+
const messageContent = typeof context.message.content === "string" ? context.message.content.substring(0, 100) : String(context.message.content || "unknown");
|
|
18
|
+
logger.debug(
|
|
19
|
+
`\u{1F50D} [filter-messages] Processing message: ${messageContent}...`
|
|
20
|
+
);
|
|
21
|
+
const filterAPI = {
|
|
22
|
+
fromSelf: () => filter.fromSelf(context.message, context.client),
|
|
23
|
+
hasContent: () => filter.hasContent(context.message),
|
|
24
|
+
isDM: () => filter.isDM(context.conversation),
|
|
25
|
+
isGroup: () => filter.isGroup(context.conversation),
|
|
26
|
+
isGroupAdmin: () => filter.isGroupAdmin(
|
|
27
|
+
context.conversation,
|
|
28
|
+
context.message
|
|
29
|
+
),
|
|
30
|
+
isGroupSuperAdmin: () => filter.isGroupSuperAdmin(
|
|
31
|
+
context.conversation,
|
|
32
|
+
context.message
|
|
33
|
+
),
|
|
34
|
+
isReaction: () => filter.isReaction(context.message),
|
|
35
|
+
isRemoteAttachment: () => filter.isRemoteAttachment(context.message),
|
|
36
|
+
isReply: () => filter.isReply(context.message),
|
|
37
|
+
isText: () => filter.isText(context.message),
|
|
38
|
+
isTextReply: () => filter.isTextReply(context.message),
|
|
39
|
+
hasMention: (mention) => {
|
|
40
|
+
const content = typeof context.message.content === "string" ? context.message.content : String(context.message.content || "");
|
|
41
|
+
return content.includes(mention);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
try {
|
|
45
|
+
const passes = filters(filterAPI);
|
|
46
|
+
if (!passes) {
|
|
47
|
+
logger.debug(
|
|
48
|
+
`\u{1F507} [filter-messages] Filter failed - message filtered out`
|
|
49
|
+
);
|
|
50
|
+
if (!context.sendOptions) {
|
|
51
|
+
context.sendOptions = {};
|
|
52
|
+
}
|
|
53
|
+
context.sendOptions.filtered = true;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
logger.debug(`\u2705 [filter-messages] Filter passed`);
|
|
57
|
+
} catch (error) {
|
|
58
|
+
logger.error("Error executing message filter:", error);
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
logger.debug(`\u2705 [filter-messages] Filter passed, continuing chain`);
|
|
62
|
+
await context.next?.();
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/behaviors/react-with.ts
|
|
68
|
+
import { logger as logger2 } from "@hybrd/utils";
|
|
69
|
+
import { ContentTypeReaction } from "@hybrd/xmtp";
|
|
70
|
+
function reactWith(reaction, options = {}) {
|
|
71
|
+
return {
|
|
72
|
+
id: `react-with-${reaction}`,
|
|
73
|
+
config: {
|
|
74
|
+
enabled: options.enabled ?? true,
|
|
75
|
+
config: {
|
|
76
|
+
reaction,
|
|
77
|
+
reactToAll: options.reactToAll ?? true
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
async before(context) {
|
|
81
|
+
if (!this.config.enabled) return;
|
|
82
|
+
try {
|
|
83
|
+
const reactionMessage = {
|
|
84
|
+
schema: "unicode",
|
|
85
|
+
reference: context.message.id,
|
|
86
|
+
action: "added",
|
|
87
|
+
contentType: ContentTypeReaction,
|
|
88
|
+
content: reaction
|
|
89
|
+
};
|
|
90
|
+
await context.conversation.send(reactionMessage, ContentTypeReaction);
|
|
91
|
+
logger2.debug(
|
|
92
|
+
`\u2705 [react-with] Reacted with ${reaction} to message ${context.message.id}`
|
|
93
|
+
);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
logger2.error(
|
|
96
|
+
`\u274C [react-with] Failed to add reaction ${reaction}:`,
|
|
97
|
+
error
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/behaviors/threaded-reply.ts
|
|
105
|
+
function threadedReply(options = {}) {
|
|
106
|
+
return {
|
|
107
|
+
id: "threaded-reply",
|
|
108
|
+
config: {
|
|
109
|
+
enabled: options.enabled ?? true,
|
|
110
|
+
config: {
|
|
111
|
+
alwaysThread: true
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
async after(context) {
|
|
115
|
+
if (!this.config.enabled) return;
|
|
116
|
+
if (!context.sendOptions) {
|
|
117
|
+
context.sendOptions = {};
|
|
118
|
+
}
|
|
119
|
+
context.sendOptions.threaded = true;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// src/behaviors/index.ts
|
|
125
|
+
import { BehaviorRegistryImpl } from "@hybrd/types";
|
|
126
|
+
export {
|
|
127
|
+
BehaviorRegistryImpl,
|
|
128
|
+
filter2 as filter,
|
|
129
|
+
filterMessages,
|
|
130
|
+
reactWith,
|
|
131
|
+
threadedReply
|
|
132
|
+
};
|
|
133
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/behaviors/index.ts","../../src/behaviors/filter-messages.ts","../../src/behaviors/react-with.ts","../../src/behaviors/threaded-reply.ts"],"sourcesContent":["// Re-export XMTP Agent SDK filters for convenience\nexport { filter } from \"@hybrd/xmtp\"\n\nexport * from \"./filter-messages\"\nexport * from \"./react-with\"\nexport * from \"./threaded-reply\"\n\n// Re-export behavior types for convenience\nexport { BehaviorRegistryImpl } from \"@hybrd/types\"\nexport type {\n\tBehavior,\n\tBehaviorConfig,\n\tBehaviorContext,\n\tBehaviorObject,\n\tBehaviorRegistry\n} from \"@hybrd/types\"\n","import type { BehaviorContext, BehaviorObject } from \"@hybrd/types\"\nimport { logger } from \"@hybrd/utils\"\nimport { filter } from \"@hybrd/xmtp\"\n\n// Filter interface that matches XMTP SDK signatures\ninterface FilterAPI {\n\tfromSelf(): boolean\n\thasContent(): boolean\n\tisDM(): boolean\n\tisGroup(): boolean\n\tisGroupAdmin(): boolean\n\tisGroupSuperAdmin(): boolean\n\tisReaction(): boolean\n\tisRemoteAttachment(): boolean\n\tisReply(): boolean\n\tisText(): boolean\n\tisTextReply(): boolean\n\thasMention(mention: string): boolean\n}\n\nexport function filterMessages(\n\tfilters: (api: FilterAPI) => boolean\n): BehaviorObject {\n\treturn {\n\t\tid: \"filter-messages\",\n\t\tconfig: {\n\t\t\tenabled: true,\n\t\t\tconfig: {\n\t\t\t\tfilters: 1\n\t\t\t}\n\t\t},\n\t\tasync before(context: BehaviorContext) {\n\t\t\tconst messageContent =\n\t\t\t\ttypeof context.message.content === \"string\"\n\t\t\t\t\t? context.message.content.substring(0, 100)\n\t\t\t\t\t: String(context.message.content || \"unknown\")\n\t\t\tlogger.debug(\n\t\t\t\t`🔍 [filter-messages] Processing message: ${messageContent}...`\n\t\t\t)\n\n\t\t\t// Create filter API wrapper\n\t\t\tconst filterAPI: FilterAPI = {\n\t\t\t\tfromSelf: () =>\n\t\t\t\t\tfilter.fromSelf(context.message as any, context.client as any),\n\t\t\t\thasContent: () => filter.hasContent(context.message as any),\n\t\t\t\tisDM: () => filter.isDM(context.conversation as any),\n\t\t\t\tisGroup: () => filter.isGroup(context.conversation as any),\n\t\t\t\tisGroupAdmin: () =>\n\t\t\t\t\tfilter.isGroupAdmin(\n\t\t\t\t\t\tcontext.conversation as any,\n\t\t\t\t\t\tcontext.message as any\n\t\t\t\t\t),\n\t\t\t\tisGroupSuperAdmin: () =>\n\t\t\t\t\tfilter.isGroupSuperAdmin(\n\t\t\t\t\t\tcontext.conversation as any,\n\t\t\t\t\t\tcontext.message as any\n\t\t\t\t\t),\n\t\t\t\tisReaction: () => filter.isReaction(context.message as any),\n\t\t\t\tisRemoteAttachment: () =>\n\t\t\t\t\tfilter.isRemoteAttachment(context.message as any),\n\t\t\t\tisReply: () => filter.isReply(context.message as any),\n\t\t\t\tisText: () => filter.isText(context.message as any),\n\t\t\t\tisTextReply: () => filter.isTextReply(context.message as any),\n\t\t\t\thasMention: (mention: string) => {\n\t\t\t\t\tconst content =\n\t\t\t\t\t\ttypeof context.message.content === \"string\"\n\t\t\t\t\t\t\t? context.message.content\n\t\t\t\t\t\t\t: String(context.message.content || \"\")\n\t\t\t\t\treturn content.includes(mention)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst passes = filters(filterAPI)\n\n\t\t\t\tif (!passes) {\n\t\t\t\t\tlogger.debug(\n\t\t\t\t\t\t`🔇 [filter-messages] Filter failed - message filtered out`\n\t\t\t\t\t)\n\t\t\t\t\t// Message filtered, set flag and stop the chain\n\t\t\t\t\tif (!context.sendOptions) {\n\t\t\t\t\t\tcontext.sendOptions = {}\n\t\t\t\t\t}\n\t\t\t\t\tcontext.sendOptions.filtered = true\n\t\t\t\t\t// Don't call next() - this stops the middleware chain\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tlogger.debug(`✅ [filter-messages] Filter passed`)\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"Error executing message filter:\", error)\n\t\t\t\tthrow error // Re-throw to propagate the error\n\t\t\t}\n\n\t\t\tlogger.debug(`✅ [filter-messages] Filter passed, continuing chain`)\n\t\t\t// Filter passed, continue to next behavior\n\t\t\tawait context.next?.()\n\t\t}\n\t}\n}\n","import type { BehaviorContext, BehaviorObject } from \"@hybrd/types\"\nimport { logger } from \"@hybrd/utils\"\nimport { ContentTypeReaction } from \"@hybrd/xmtp\"\n\nexport interface ReactWithOptions {\n\treactToAll?: boolean\n\tenabled?: boolean\n}\n\nexport function reactWith(\n\treaction: string,\n\toptions: ReactWithOptions = {}\n): BehaviorObject {\n\treturn {\n\t\tid: `react-with-${reaction}`,\n\t\tconfig: {\n\t\t\tenabled: options.enabled ?? true,\n\t\t\tconfig: {\n\t\t\t\treaction,\n\t\t\t\treactToAll: options.reactToAll ?? true\n\t\t\t}\n\t\t},\n\t\tasync before(context: BehaviorContext) {\n\t\t\tif (!this.config.enabled) return\n\n\t\t\ttry {\n\t\t\t\tconst reactionMessage = {\n\t\t\t\t\tschema: \"unicode\",\n\t\t\t\t\treference: context.message.id,\n\t\t\t\t\taction: \"added\",\n\t\t\t\t\tcontentType: ContentTypeReaction,\n\t\t\t\t\tcontent: reaction\n\t\t\t\t}\n\n\t\t\t\tawait context.conversation.send(reactionMessage, ContentTypeReaction)\n\t\t\t\tlogger.debug(\n\t\t\t\t\t`✅ [react-with] Reacted with ${reaction} to message ${context.message.id}`\n\t\t\t\t)\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t`❌ [react-with] Failed to add reaction ${reaction}:`,\n\t\t\t\t\terror\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n}\n","import type { BehaviorContext, BehaviorObject } from \"@hybrd/types\"\n\nexport interface ThreadedReplyOptions {\n\tenabled?: boolean\n}\n\nexport function threadedReply(\n\toptions: ThreadedReplyOptions = {}\n): BehaviorObject {\n\treturn {\n\t\tid: \"threaded-reply\",\n\t\tconfig: {\n\t\t\tenabled: options.enabled ?? true,\n\t\t\tconfig: {\n\t\t\t\talwaysThread: true\n\t\t\t}\n\t\t},\n\t\tasync after(context: BehaviorContext) {\n\t\t\tif (!this.config.enabled) return\n\n\t\t\tif (!context.sendOptions) {\n\t\t\t\tcontext.sendOptions = {}\n\t\t\t}\n\t\t\tcontext.sendOptions.threaded = true\n\t\t}\n\t}\n}\n"],"mappings":"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","names":["filter","logger"]}
|