@hybrd/types 0.7.6 → 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/src/agent.ts ADDED
@@ -0,0 +1,192 @@
1
+ import type {
2
+ LanguageModel,
3
+ TelemetrySettings,
4
+ UIMessage,
5
+ UIMessageStreamOnFinishCallback,
6
+ generateText,
7
+ streamText
8
+ } from "ai"
9
+ import type { BehaviorObject } from "./behavior"
10
+ import type { Plugin, PluginRegistry } from "./plugin"
11
+ import type { AgentRuntime } from "./runtime"
12
+ import type { AnyTool } from "./tool"
13
+
14
+ export type AgentMessage = UIMessage
15
+
16
+ export interface Agent<
17
+ TRuntimeExtension = Record<string, never>,
18
+ TPluginContext = unknown
19
+ > {
20
+ /** Agent's unique identifier */
21
+ readonly name: string
22
+ /** Plugin registry for extending the agent's HTTP server */
23
+ readonly plugins: PluginRegistry<TPluginContext>
24
+
25
+ /**
26
+ * Generates a text completion using the agent's configuration.
27
+ * @param messages - Conversation messages to generate from
28
+ * @param options - Generation options including runtime context
29
+ * @returns Generated text completion result
30
+ */
31
+ generate(
32
+ messages: AgentMessage[],
33
+ options: GenerateOptions<TRuntimeExtension>
34
+ ): Promise<Awaited<ReturnType<typeof generateText>>>
35
+
36
+ /**
37
+ * Streams a text completion using the agent's configuration.
38
+ * @param messages - Conversation messages to generate from
39
+ * @param options - Streaming options including runtime context
40
+ * @returns Streaming response that can be consumed
41
+ */
42
+ stream(
43
+ messages: AgentMessage[],
44
+ options: StreamOptions<TRuntimeExtension>
45
+ ): Promise<Response>
46
+
47
+ /**
48
+ * Gets the agent's configuration for debugging and inspection.
49
+ * @returns Object containing agent configuration details
50
+ */
51
+ getConfig(): {
52
+ name: string
53
+ hasModel: boolean
54
+ hasTools: boolean
55
+ hasInstructions: boolean
56
+ }
57
+
58
+ /**
59
+ * Gets the agent's instructions without running generation.
60
+ * Useful for external integrations that need instructions separately.
61
+ * @param options - Options containing runtime context and optional messages
62
+ * @returns Resolved instructions string
63
+ */
64
+ getInstructions(options: {
65
+ runtime: AgentRuntime & TRuntimeExtension
66
+ messages?: AgentMessage[]
67
+ }): Promise<string | undefined>
68
+
69
+ /**
70
+ * Gets the agent's tools without running generation.
71
+ * Useful for external integrations that need tools separately.
72
+ * @param options - Options containing runtime context and optional messages
73
+ * @returns Resolved tools object
74
+ */
75
+ getTools(options: {
76
+ runtime: AgentRuntime & TRuntimeExtension
77
+ messages?: AgentMessage[]
78
+ }): Promise<Record<string, AnyTool<TRuntimeExtension>> | undefined>
79
+
80
+ /**
81
+ * Creates the complete runtime context by merging base runtime with custom extension.
82
+ * @param baseRuntime - The base runtime context containing XMTP properties
83
+ * @returns Complete runtime context with custom extensions applied
84
+ */
85
+ createRuntimeContext(
86
+ baseRuntime: AgentRuntime
87
+ ): Promise<AgentRuntime & TRuntimeExtension>
88
+
89
+ /**
90
+ * Registers a plugin with the agent
91
+ * @param plugin - The plugin to register
92
+ */
93
+ use(plugin: Plugin<TPluginContext>): void
94
+
95
+ /**
96
+ * Starts listening for messages and events using the agent instance.
97
+ * @param opts - Configuration options for the listener, excluding the agent property
98
+ */
99
+ listen(opts: Omit<ListenOptions, "agent">): Promise<void>
100
+ }
101
+
102
+ export type DefaultRuntimeExtension = Record<string, never>
103
+
104
+ export type ToolGenerator<TRuntimeExtension = DefaultRuntimeExtension> =
105
+ (props: {
106
+ runtime: AgentRuntime & TRuntimeExtension
107
+ messages: AgentMessage[]
108
+ }) =>
109
+ | Record<string, AnyTool<TRuntimeExtension>>
110
+ | Promise<Record<string, AnyTool<TRuntimeExtension>>>
111
+
112
+ /**
113
+ * Configuration interface for creating an Agent instance.
114
+ * Supports both static and dynamic configuration through functions.
115
+ */
116
+ export interface AgentConfig<TRuntimeExtension = DefaultRuntimeExtension> {
117
+ /** Unique identifier for the agent */
118
+ name: string
119
+ /** Language model to use, can be static or dynamically resolved */
120
+ model:
121
+ | LanguageModel
122
+ | ((props: {
123
+ runtime: AgentRuntime & TRuntimeExtension
124
+ }) => LanguageModel | Promise<LanguageModel>)
125
+ /** Tools available to the agent, can be static or dynamically generated */
126
+ tools?:
127
+ | Record<string, AnyTool<TRuntimeExtension>>
128
+ | ToolGenerator<TRuntimeExtension>
129
+ /** Instructions for the agent, can be static or dynamically resolved */
130
+ instructions:
131
+ | string
132
+ | ((props: {
133
+ messages: AgentMessage[]
134
+ runtime: AgentRuntime & TRuntimeExtension
135
+ }) => string | Promise<string>)
136
+ /** Function to create the runtime extension, type will be inferred */
137
+ createRuntime?: (
138
+ runtime: AgentRuntime
139
+ ) => TRuntimeExtension | Promise<TRuntimeExtension>
140
+ /** Maximum number of steps the agent can take */
141
+ maxSteps?: number
142
+ /** Maximum tokens for generation */
143
+ maxTokens?: number
144
+ /** Temperature for generation (0.0 to 2.0) */
145
+ temperature?: number
146
+ }
147
+
148
+ /**
149
+ * Options for text generation with the agent.
150
+ * Extends AI SDK parameters while adding agent-specific options.
151
+ */
152
+ export interface GenerateOptions<TRuntimeExtension = DefaultRuntimeExtension>
153
+ extends Omit<
154
+ Parameters<typeof generateText>[0],
155
+ "model" | "tools" | "instructions" | "onFinish"
156
+ > {
157
+ /** Maximum tokens for generation */
158
+ maxTokens?: number
159
+ /** Runtime context for the agent */
160
+ runtime: AgentRuntime & TRuntimeExtension
161
+ /** Optional telemetry configuration */
162
+ telemetry?: NonNullable<TelemetrySettings>
163
+ }
164
+
165
+ export interface StreamOptions<TRuntimeExtension = DefaultRuntimeExtension>
166
+ extends Omit<
167
+ Parameters<typeof streamText>[0],
168
+ "model" | "tools" | "instructions" | "onFinish"
169
+ > {
170
+ /** Maximum tokens for generation */
171
+ maxTokens?: number
172
+ /** Runtime context for the agent */
173
+ runtime: AgentRuntime & TRuntimeExtension
174
+ /** Optional telemetry configuration */
175
+ telemetry?: NonNullable<TelemetrySettings>
176
+ /** Callback when streaming finishes */
177
+ onFinish?: UIMessageStreamOnFinishCallback<AgentMessage>
178
+ }
179
+
180
+ /**
181
+ * Options for starting the agent listener
182
+ * @property agent - The agent instance to use
183
+ * @property port - The port number to listen on (defaults to 8454)
184
+ * @property plugins - Optional array of plugins to apply to the server
185
+ * @property behaviors - Optional array of behaviors to apply to message processing
186
+ */
187
+ export interface ListenOptions {
188
+ agent: Agent<unknown, unknown>
189
+ port: string
190
+ plugins?: Plugin<unknown>[]
191
+ behaviors?: BehaviorObject[]
192
+ }
@@ -0,0 +1,31 @@
1
+ import { describe, expect, it } from "vitest"
2
+ import type { BehaviorContext } from "./behavior"
3
+
4
+ describe("Behavior Types", () => {
5
+ it("should define BehaviorContext interface", () => {
6
+ const context: BehaviorContext = {
7
+ runtime: {} as any,
8
+ client: {} as any,
9
+ conversation: {} as any,
10
+ message: {} as any,
11
+ sendOptions: {
12
+ threaded: true,
13
+ contentType: "text/plain"
14
+ }
15
+ }
16
+
17
+ expect(context.sendOptions?.threaded).toBe(true)
18
+ expect(context.sendOptions?.contentType).toBe("text/plain")
19
+ })
20
+
21
+ it("should allow optional sendOptions", () => {
22
+ const context: BehaviorContext = {
23
+ runtime: {} as any,
24
+ client: {} as any,
25
+ conversation: {} as any,
26
+ message: {} as any
27
+ }
28
+
29
+ expect(context.sendOptions).toBeUndefined()
30
+ })
31
+ })
@@ -0,0 +1,251 @@
1
+ import type { AgentRuntime } from "./runtime"
2
+ import type { XmtpClient, XmtpConversation, XmtpMessage } from "./xmtp"
3
+
4
+ /**
5
+ * Configuration options for a behavior
6
+ */
7
+ export interface BehaviorConfig {
8
+ /** Whether the behavior is enabled */
9
+ enabled?: boolean
10
+ /** Optional configuration data for the behavior */
11
+ config?: Record<string, unknown>
12
+ }
13
+
14
+ /**
15
+ * Context provided to behaviors when they execute
16
+ */
17
+ export interface BehaviorContext<TRuntimeExtension = Record<string, never>> {
18
+ /** The base runtime context */
19
+ runtime: AgentRuntime & TRuntimeExtension
20
+ /** The XMTP client instance */
21
+ client: XmtpClient
22
+ /** The conversation the message came from */
23
+ conversation: XmtpConversation
24
+ /** The message that triggered the behavior */
25
+ message: XmtpMessage
26
+ /** The agent's response (available in post-response behaviors) */
27
+ response?: string
28
+ /** Send options that behaviors can modify */
29
+ sendOptions?: {
30
+ /** Whether to thread the reply to the original message */
31
+ threaded?: boolean
32
+ /** Content type override */
33
+ contentType?: string
34
+ /** Whether this message should be filtered out and not processed */
35
+ filtered?: boolean
36
+ /** Additional metadata */
37
+ metadata?: Record<string, unknown>
38
+ }
39
+ /**
40
+ * Continue to the next behavior in the middleware chain
41
+ * If not called, the behavior chain stops processing
42
+ */
43
+ next?: () => Promise<void>
44
+ /**
45
+ * Whether the middleware chain was stopped early
46
+ * This gets set to true when a behavior doesn't call next()
47
+ */
48
+ stopped?: boolean
49
+ }
50
+
51
+ /**
52
+ * A behavior that can be executed before or after agent responses
53
+ */
54
+ export interface BehaviorObject<TRuntimeExtension = Record<string, never>> {
55
+ /** Unique identifier for the behavior */
56
+ id: string
57
+ /** Configuration for the behavior */
58
+ config: BehaviorConfig
59
+ /**
60
+ * Execute the behavior before the agent responds
61
+ * @param context - The context in which to execute the behavior
62
+ */
63
+ before?(context: BehaviorContext<TRuntimeExtension>): Promise<void> | void
64
+ /**
65
+ * Execute the behavior after the agent responds
66
+ * @param context - The context in which to execute the behavior
67
+ */
68
+ after?(context: BehaviorContext<TRuntimeExtension>): Promise<void> | void
69
+ }
70
+
71
+ /**
72
+ * Factory function to create a behavior instance
73
+ */
74
+ export type Behavior<TConfig = Record<string, unknown>> = (
75
+ config: TConfig & BehaviorConfig
76
+ ) => BehaviorObject
77
+
78
+ /**
79
+ * Pre-configured behavior instance that can be used directly
80
+ */
81
+ export type BehaviorInstance = Behavior
82
+
83
+ /**
84
+ * Behavior registry for managing and executing behaviors
85
+ */
86
+ export interface BehaviorRegistry {
87
+ /**
88
+ * Register a behavior with the registry
89
+ */
90
+ register(behavior: BehaviorObject): void
91
+
92
+ /**
93
+ * Register multiple behaviors at once
94
+ */
95
+ registerAll(behaviors: BehaviorObject[]): void
96
+
97
+ /**
98
+ * Get all registered behaviors
99
+ */
100
+ getAll(): BehaviorObject[]
101
+
102
+ /**
103
+ * Get behaviors that should run before the agent responds
104
+ */
105
+ getBeforeBehaviors(): BehaviorObject[]
106
+
107
+ /**
108
+ * Get behaviors that should run after the agent responds
109
+ */
110
+ getAfterBehaviors(): BehaviorObject[]
111
+
112
+ /**
113
+ * Execute all before-response behaviors as a middleware chain
114
+ */
115
+ executeBefore(context: BehaviorContext): Promise<void>
116
+
117
+ /**
118
+ * Execute all after-response behaviors as a middleware chain
119
+ */
120
+ executeAfter(context: BehaviorContext): Promise<void>
121
+
122
+ /**
123
+ * Clear all registered behaviors
124
+ */
125
+ clear(): void
126
+ }
127
+
128
+ /**
129
+ * Concrete implementation of the BehaviorRegistry interface
130
+ */
131
+ export class BehaviorRegistryImpl implements BehaviorRegistry {
132
+ private behaviors: BehaviorObject[] = []
133
+
134
+ /**
135
+ * Register a behavior with the registry
136
+ */
137
+ register(behavior: BehaviorObject): void {
138
+ this.behaviors.push(behavior)
139
+ }
140
+
141
+ /**
142
+ * Register multiple behaviors at once
143
+ */
144
+ registerAll(behaviors: BehaviorObject[]): void {
145
+ // Register behavior objects directly
146
+ this.behaviors.push(...behaviors)
147
+ }
148
+
149
+ /**
150
+ * Get all registered behaviors
151
+ */
152
+ getAll(): BehaviorObject[] {
153
+ return [...this.behaviors]
154
+ }
155
+
156
+ /**
157
+ * Get behaviors that should run before the agent responds
158
+ */
159
+ getBeforeBehaviors(): BehaviorObject[] {
160
+ return this.behaviors.filter((behavior) => behavior.before)
161
+ }
162
+
163
+ /**
164
+ * Get behaviors that should run after the agent responds
165
+ */
166
+ getAfterBehaviors(): BehaviorObject[] {
167
+ return this.behaviors.filter((behavior) => behavior.after)
168
+ }
169
+
170
+ /**
171
+ * Execute all before-response behaviors as a middleware chain
172
+ */
173
+ async executeBefore(context: BehaviorContext): Promise<void> {
174
+ const behaviors = this.getBeforeBehaviors()
175
+
176
+ // Create a middleware chain
177
+ let currentIndex = 0
178
+ const next = async (): Promise<void> => {
179
+ if (currentIndex >= behaviors.length) {
180
+ return
181
+ }
182
+
183
+ const behavior = behaviors[currentIndex]
184
+ if (!behavior) {
185
+ return
186
+ }
187
+ currentIndex++
188
+
189
+ try {
190
+ await behavior.before?.(context)
191
+ } catch (error) {
192
+ console.error(
193
+ `Error executing before behavior "${behavior.id}":`,
194
+ error
195
+ )
196
+ }
197
+ }
198
+
199
+ // Set the next function in the context
200
+ context.next = next
201
+
202
+ // Start the chain
203
+ await next()
204
+
205
+ // Check if the chain was stopped early
206
+ context.stopped = currentIndex < behaviors.length
207
+ }
208
+
209
+ /**
210
+ * Execute all after-response behaviors as a middleware chain
211
+ */
212
+ async executeAfter(context: BehaviorContext): Promise<void> {
213
+ const behaviors = this.getAfterBehaviors()
214
+
215
+ // Create a middleware chain
216
+ let currentIndex = 0
217
+ const next = async (): Promise<void> => {
218
+ if (currentIndex >= behaviors.length) {
219
+ return
220
+ }
221
+
222
+ const behavior = behaviors[currentIndex]
223
+ if (!behavior) {
224
+ return
225
+ }
226
+ currentIndex++
227
+
228
+ try {
229
+ await behavior.after?.(context)
230
+ } catch (error) {
231
+ console.error(`Error executing after behavior "${behavior.id}":`, error)
232
+ }
233
+ }
234
+
235
+ // Set the next function in the context
236
+ context.next = next
237
+
238
+ // Start the chain
239
+ await next()
240
+
241
+ // Check if the chain was stopped early
242
+ context.stopped = currentIndex < behaviors.length
243
+ }
244
+
245
+ /**
246
+ * Clear all registered behaviors
247
+ */
248
+ clear(): void {
249
+ this.behaviors = []
250
+ }
251
+ }
package/src/index.ts ADDED
@@ -0,0 +1,52 @@
1
+ // Agent types
2
+ export type {
3
+ AgentConfig,
4
+ DefaultRuntimeExtension,
5
+ GenerateOptions,
6
+ ListenOptions,
7
+ StreamOptions,
8
+ ToolGenerator
9
+ } from "./agent"
10
+
11
+ export type { Agent, AgentMessage } from "./agent"
12
+
13
+ // Tool types
14
+ export type {
15
+ AnyTool,
16
+ Tool,
17
+ ToolConfig
18
+ } from "./tool"
19
+
20
+ // Plugin types
21
+ export type {
22
+ Plugin,
23
+ PluginContext,
24
+ PluginRegistry
25
+ } from "./plugin"
26
+
27
+ // Runtime types
28
+ export type { AgentRuntime } from "./runtime"
29
+
30
+ // XMTP types
31
+ export type {
32
+ HonoVariables,
33
+ XmtpClient,
34
+ XmtpConversation,
35
+ XmtpMessage,
36
+ XmtpSender,
37
+ XmtpSubjects
38
+ } from "./xmtp"
39
+
40
+ // Resolver types
41
+ export type { Resolver } from "./resolver"
42
+
43
+ // Behavior types
44
+ export { BehaviorRegistryImpl } from "./behavior"
45
+ export type {
46
+ Behavior,
47
+ BehaviorConfig,
48
+ BehaviorContext,
49
+ BehaviorInstance,
50
+ BehaviorObject,
51
+ BehaviorRegistry
52
+ } from "./behavior"
package/src/plugin.ts ADDED
@@ -0,0 +1,58 @@
1
+ import type { Hono } from "hono"
2
+ import { Agent } from "./agent"
3
+ import type { BehaviorRegistry } from "./behavior"
4
+ import type { HonoVariables } from "./xmtp"
5
+
6
+ /**
7
+ * Plugin interface for extending the agent's Hono app
8
+ *
9
+ * @description
10
+ * Plugins allow you to extend the agent's HTTP server with additional
11
+ * routes, middleware, and functionality. Each plugin receives the Hono
12
+ * app instance and can modify it as needed.
13
+ *
14
+ * @template T - Optional context type that can be passed to the plugin
15
+ */
16
+ export interface Plugin<T = Record<string, never>> {
17
+ /**
18
+ * Unique identifier for the plugin
19
+ */
20
+ name: string
21
+
22
+ /**
23
+ * Optional description of what the plugin does
24
+ */
25
+ description?: string
26
+
27
+ /**
28
+ * Function that applies the plugin to the Hono app
29
+ *
30
+ * @param app - The Hono app instance to extend
31
+ * @param context - Optional context data passed to the plugin
32
+ */
33
+ apply: (
34
+ app: Hono<{ Variables: HonoVariables }>,
35
+ context: T
36
+ ) => void | Promise<void>
37
+ }
38
+
39
+ /**
40
+ * Plugin registry that manages all registered plugins
41
+ *
42
+ * @description
43
+ * The plugin registry allows you to register, configure, and apply
44
+ * plugins to Hono apps. It provides a centralized way to manage
45
+ * plugin dependencies and execution order.
46
+ */
47
+ export interface PluginRegistry<TContext = unknown> {
48
+ register: (plugin: Plugin<TContext>) => void
49
+ applyAll: (
50
+ app: Hono<{ Variables: HonoVariables }>,
51
+ context: TContext
52
+ ) => Promise<void>
53
+ }
54
+
55
+ export interface PluginContext {
56
+ agent: Agent
57
+ behaviors?: BehaviorRegistry
58
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Resolver interface for address resolution
3
+ */
4
+ export interface Resolver {
5
+ resolve: (address: string) => Promise<string | null>
6
+ }
package/src/runtime.ts ADDED
@@ -0,0 +1,31 @@
1
+ import type {
2
+ XmtpClient,
3
+ // XmtpClient,
4
+ // XmtpSender,
5
+ // XmtpSubjects
6
+ XmtpConversation,
7
+ XmtpMessage
8
+ } from "./xmtp"
9
+
10
+ /**
11
+ * Base runtime that is always included in agents and tools.
12
+ * Additional fields can be added via generic type parameters as intersections.
13
+ *
14
+ * Example usage:
15
+ * - Basic: AgentRuntime (just chatId and messages)
16
+ * - Extended: AgentRuntime & { userId: string } (adds userId field)
17
+ */
18
+ export interface AgentRuntime {
19
+ conversation: XmtpConversation
20
+ message: XmtpMessage
21
+ // parentMessage?: XmtpMessage
22
+ // rootMessage: XmtpMessage
23
+ // sender: XmtpSender
24
+ // subjects: XmtpSubjects
25
+ xmtpClient: XmtpClient
26
+ }
27
+
28
+ // export type AgentRuntime = BaseRuntime & {
29
+ // chatId?: string
30
+ // messages: Array<UIMessage>
31
+ // }
package/src/tool.ts ADDED
@@ -0,0 +1,57 @@
1
+ import type { UIMessage } from "ai"
2
+ import type { z } from "zod"
3
+ import type { DefaultRuntimeExtension } from "./agent"
4
+ import type { AgentRuntime } from "./runtime"
5
+
6
+ /**
7
+ * Configuration interface for creating custom tools that integrate with AI SDK.
8
+ */
9
+ export interface ToolConfig<
10
+ TInput extends z.ZodTypeAny = z.ZodTypeAny,
11
+ TOutput extends z.ZodTypeAny = z.ZodTypeAny,
12
+ TRuntimeExtension = DefaultRuntimeExtension
13
+ > {
14
+ /** Unique identifier for the tool */
15
+ id: string
16
+ /** Human-readable description of what the tool does */
17
+ description: string
18
+ /** Zod schema for validating tool input */
19
+ inputSchema: TInput
20
+ /** Optional Zod schema for validating tool output */
21
+ outputSchema?: TOutput
22
+ /** Function that executes the tool's logic */
23
+ execute: (args: {
24
+ input: z.infer<TInput>
25
+ runtime: AgentRuntime & TRuntimeExtension
26
+ messages: UIMessage[]
27
+ }) => Promise<z.infer<TOutput>>
28
+ }
29
+
30
+ /**
31
+ * Internal tool interface used throughout the agent framework.
32
+ * Similar to ToolConfig but without the ID field, used after tool creation.
33
+ */
34
+ export interface Tool<
35
+ TInput extends z.ZodTypeAny = z.ZodTypeAny,
36
+ TOutput extends z.ZodTypeAny = z.ZodTypeAny,
37
+ TRuntimeExtension = DefaultRuntimeExtension
38
+ > {
39
+ /** Human-readable description of what the tool does */
40
+ description: string
41
+ /** Zod schema for validating tool input */
42
+ inputSchema: TInput
43
+ /** Optional Zod schema for validating tool output */
44
+ outputSchema?: TOutput
45
+ /** Function that executes the tool's logic */
46
+ execute: (args: {
47
+ input: z.infer<TInput>
48
+ runtime: AgentRuntime & TRuntimeExtension
49
+ messages: UIMessage[]
50
+ }) => Promise<z.infer<TOutput>>
51
+ }
52
+
53
+ export type AnyTool<TRuntimeExtension = DefaultRuntimeExtension> = Tool<
54
+ any,
55
+ any,
56
+ TRuntimeExtension
57
+ >