@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 +106 -0
- package/package.json +1 -1
- package/src/channel.ts +44 -0
- package/src/client.ts +84 -0
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
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
|
}
|