@eyeclaw/eyeclaw 2.0.0 β†’ 2.0.2

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 CHANGED
@@ -212,6 +212,112 @@ client.disconnect()
212
212
  - **Issues**: [https://github.com/eyeclaw/eyeclaw/issues](https://github.com/eyeclaw/eyeclaw/issues)
213
213
  - **Discord**: [https://discord.gg/eyeclaw](https://discord.gg/eyeclaw)
214
214
 
215
+ ## πŸ’¬ Chat Functionality
216
+
217
+ The EyeClaw SDK includes built-in chat functionality that allows you to interact with your bot through the web dashboard.
218
+
219
+ ### Testing Chat
220
+
221
+ 1. Start your bot with the EyeClaw plugin installed
222
+ 2. Go to your bot's detail page on EyeClaw Dashboard
223
+ 3. Click **"Test Chat"** button
224
+ 4. Send messages - the bot will respond with smart replies
225
+ 5. Use quick test buttons:
226
+ - **Ping** - Test bot connectivity
227
+ - **Status** - Get bot status (online, sessions, uptime)
228
+ - **Echo** - Echo back a test message
229
+ - **Help** - Show available commands
230
+
231
+ ### Supported Commands
232
+
233
+ The SDK automatically handles these commands from the web dashboard:
234
+
235
+ - **`chat`** - Receive and respond to chat messages
236
+ - Params: `{ message: string }`
237
+ - The bot uses pattern matching to generate smart responses
238
+ - Supports greetings, questions, thanks, farewells in Chinese and English
239
+
240
+ - **`ping`** - Test bot connectivity
241
+ - Response: "πŸ“ Pong! Bot is responding."
242
+
243
+ - **`status`** - Get current bot status
244
+ - Returns: online status, active sessions, total sessions, uptime
245
+
246
+ - **`echo`** - Echo back a message
247
+ - Params: `{ message: string }`
248
+ - Response: Echoes the message back
249
+
250
+ - **`help`** - Show available commands
251
+ - Response: Lists all available commands and their usage
252
+
253
+ ### Customizing Bot Responses
254
+
255
+ You can customize the bot's chat responses by modifying `generateBotReply()` in `sdk/src/client.ts`:
256
+
257
+ ```typescript
258
+ private generateBotReply(userMessage: string): string {
259
+ const lowerMessage = userMessage.toLowerCase()
260
+
261
+ // Add your custom patterns
262
+ if (lowerMessage.includes('weather')) {
263
+ return '🌀️ The weather is great today!'
264
+ }
265
+
266
+ if (lowerMessage.includes('time')) {
267
+ return `πŸ• Current time: ${new Date().toLocaleTimeString()}`
268
+ }
269
+
270
+ // Default response
271
+ return `πŸ’¬ You said: "${userMessage}"`
272
+ }
273
+ ```
274
+
275
+ ### Integrating AI/LLM Services
276
+
277
+ For production use, integrate your preferred AI service:
278
+
279
+ ```typescript
280
+ import OpenAI from 'openai'
281
+
282
+ private async generateBotReply(userMessage: string): Promise<string> {
283
+ const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })
284
+
285
+ const completion = await openai.chat.completions.create({
286
+ model: 'gpt-4',
287
+ messages: [
288
+ { role: 'system', content: 'You are a helpful assistant.' },
289
+ { role: 'user', content: userMessage }
290
+ ]
291
+ })
292
+
293
+ return completion.choices[0].message.content || 'Sorry, I could not generate a response.'
294
+ }
295
+ ```
296
+
297
+ ### Message Flow
298
+
299
+ ```
300
+ User (Web Dashboard)
301
+ β”‚
302
+ β–Ό
303
+ DashboardChannel ──execute_command──► BotChannel
304
+ β”‚ β”‚
305
+ β”‚ β–Ό
306
+ β”‚ SDK receives command
307
+ β”‚ β”‚
308
+ β”‚ β–Ό
309
+ β”‚ handleExecuteCommand()
310
+ β”‚ β”‚
311
+ β”‚ β–Ό
312
+ β”‚ generateBotReply()
313
+ β”‚ β”‚
314
+ β”‚ β–Ό
315
+ │◄───────── sendLog() ──────────sendLog('info', reply)
316
+ β”‚
317
+ β–Ό
318
+ Chat Controller displays message
319
+ ```
320
+
215
321
  ## License
216
322
 
217
323
  MIT Β© EyeClaw Team
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eyeclaw/eyeclaw",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "EyeClaw channel plugin for OpenClaw - Connect your local OpenClaw instance to EyeClaw platform",
5
5
  "type": "module",
6
6
  "main": "./index.ts",
package/src/channel.ts CHANGED
@@ -178,6 +178,50 @@ export const eyeclawPlugin: ChannelPlugin<ResolvedEyeClawAccount> = {
178
178
  const client = new EyeClawClient(clientConfig, logger)
179
179
  clients.set(ctx.accountId, client)
180
180
 
181
+ // Register OpenClaw Agent callback for chat messages
182
+ client.setSendAgentCallback(async (message: string) => {
183
+ try {
184
+ ctx.log?.info(`πŸ€– Sending message to OpenClaw Agent: ${message}`)
185
+
186
+ // Call OpenClaw Agent via CLI (since ctx.sendAgent doesn't exist)
187
+ const { spawn } = await import('child_process')
188
+ const { promisify } = await import('util')
189
+ const exec = promisify((await import('child_process')).exec)
190
+
191
+ try {
192
+ // Call openclaw agent CLI to process the message
193
+ const result = await exec(
194
+ `openclaw agent --session-id eyeclaw-web-chat --message ${JSON.stringify(message)} --json`,
195
+ { timeout: 60000 }
196
+ )
197
+
198
+ if (result.stdout) {
199
+ try {
200
+ const parsed = JSON.parse(result.stdout)
201
+ // OpenClaw CLI returns: { result: { payloads: [{ text: "...", mediaUrl: null }] } }
202
+ const response = parsed.result?.payloads?.[0]?.text || 'Agent completed (no text)'
203
+ ctx.log?.info(`βœ… Agent response: ${response.substring(0, 100)}...`)
204
+ client.sendLog('info', response)
205
+ } catch (e) {
206
+ // If not JSON, just send the stdout
207
+ ctx.log?.info(`βœ… Agent response (raw): ${result.stdout.substring(0, 100)}...`)
208
+ client.sendLog('info', result.stdout.trim())
209
+ }
210
+ } else {
211
+ client.sendLog('info', 'βœ… Agent completed successfully')
212
+ }
213
+ } catch (error) {
214
+ const errorMsg = error instanceof Error ? error.message : String(error)
215
+ ctx.log?.error(`Failed to execute openclaw agent: ${errorMsg}`)
216
+ client.sendLog('error', `❌ Agent error: ${errorMsg}`)
217
+ }
218
+ } catch (error) {
219
+ const errorMsg = error instanceof Error ? error.message : String(error)
220
+ ctx.log?.error(`Failed to call OpenClaw Agent: ${errorMsg}`)
221
+ client.sendLog('error', `❌ Failed to call agent: ${errorMsg}`)
222
+ }
223
+ })
224
+
181
225
  try {
182
226
  await client.connect()
183
227
  ctx.log?.info('βœ… Successfully connected to EyeClaw platform')
package/src/client.ts CHANGED
@@ -105,6 +105,16 @@ export class EyeClawClient {
105
105
  this.logger.info(`Command received by server: ${message.command}`)
106
106
  break
107
107
 
108
+ case 'execute_command':
109
+ this.handleExecuteCommand(message)
110
+ break
111
+
112
+ case 'ping':
113
+ this.logger.debug('Received ping from dashboard')
114
+ // Send pong response
115
+ this.sendLog('info', 'πŸ“ Pong! Bot is alive.')
116
+ break
117
+
108
118
  case 'log':
109
119
  this.logger.info(`[Server Log] ${message.level}: ${message.message}`)
110
120
  break
@@ -114,6 +124,80 @@ export class EyeClawClient {
114
124
  }
115
125
  }
116
126
 
127
+ private handleExecuteCommand(message: Record<string, unknown>): void {
128
+ const command = message.command as string
129
+ const params = (message.params as Record<string, unknown>) || {}
130
+
131
+ this.logger.info(`πŸ“₯ Executing command: ${command}`)
132
+
133
+ switch (command) {
134
+ case 'chat': {
135
+ const userMessage = params.message as string
136
+ this.logger.info(`πŸ’¬ Chat message: ${userMessage}`)
137
+
138
+ // Send user message acknowledgment
139
+ this.sendLog('info', `ζ”Άεˆ°ζΆˆζ―: ${userMessage}`)
140
+
141
+ // Call OpenClaw Agent via callback
142
+ this.handleChatMessage(userMessage)
143
+ break
144
+ }
145
+
146
+ case 'ping': {
147
+ this.sendLog('info', 'πŸ“ Pong! Bot is responding.')
148
+ break
149
+ }
150
+
151
+ case 'status': {
152
+ this.requestStatus()
153
+ break
154
+ }
155
+
156
+ case 'echo': {
157
+ const echoMessage = params.message as string
158
+ this.sendLog('info', `Echo: ${echoMessage}`)
159
+ break
160
+ }
161
+
162
+ case 'help': {
163
+ const helpMessage = [
164
+ 'πŸ€– Available Commands:',
165
+ 'β€’ chat - Send a chat message',
166
+ 'β€’ ping - Test connection',
167
+ 'β€’ status - Get bot status',
168
+ 'β€’ echo - Echo a message',
169
+ 'β€’ help - Show this help',
170
+ ].join('\n')
171
+ this.sendLog('info', helpMessage)
172
+ break
173
+ }
174
+
175
+ default:
176
+ this.logger.warn(`Unknown command: ${command}`)
177
+ this.sendLog('error', `❌ Unknown command: ${command}`)
178
+ }
179
+ }
180
+
181
+ private handleChatMessage(userMessage: string): void {
182
+ // This will be called by OpenClaw channel plugin via sendAgent
183
+ if (this.sendAgentCallback) {
184
+ this.logger.info('πŸ€– Calling OpenClaw Agent...')
185
+ this.sendAgentCallback(userMessage)
186
+ } else {
187
+ // Fallback: simple echo if not running in OpenClaw context
188
+ this.logger.warn('No OpenClaw Agent available, using echo mode')
189
+ this.sendLog('info', `πŸ’¬ Echo: "${userMessage}" (OpenClaw Agent not connected)`)
190
+ }
191
+ }
192
+
193
+ // Callback to send message to OpenClaw Agent (injected by channel plugin)
194
+ private sendAgentCallback: ((message: string) => Promise<void>) | null = null
195
+
196
+ setSendAgentCallback(callback: (message: string) => Promise<void>): void {
197
+ this.sendAgentCallback = callback
198
+ this.logger.info('βœ… OpenClaw Agent callback registered')
199
+ }
200
+
117
201
  private handleStatusResponse(status: BotStatus): void {
118
202
  this.logger.info(`Bot status: online=${status.online}, status=${status.status}, sessions=${status.active_sessions}, uptime=${Math.floor(status.uptime / 60)}m`)
119
203
  }