@eyeclaw/eyeclaw 2.0.5 → 2.0.7
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/package.json +1 -1
- package/src/channel.ts +70 -52
- package/src/client.ts +6 -5
package/package.json
CHANGED
package/src/channel.ts
CHANGED
|
@@ -180,29 +180,28 @@ export const eyeclawPlugin: ChannelPlugin<ResolvedEyeClawAccount> = {
|
|
|
180
180
|
|
|
181
181
|
// Register OpenClaw Agent callback for chat messages
|
|
182
182
|
client.setSendAgentCallback(async (message: string) => {
|
|
183
|
+
const { spawn } = await import('child_process')
|
|
184
|
+
const streamId = Date.now().toString()
|
|
185
|
+
|
|
183
186
|
try {
|
|
184
187
|
ctx.log?.info(`🤖 Sending message to OpenClaw Agent: ${message}`)
|
|
185
188
|
|
|
186
|
-
//
|
|
187
|
-
const
|
|
189
|
+
// Spawn openclaw agent process for streaming output
|
|
190
|
+
const agentProcess = spawn('openclaw', [
|
|
191
|
+
'agent',
|
|
192
|
+
'--session-id', 'eyeclaw-web-chat',
|
|
193
|
+
'--message', message,
|
|
194
|
+
'--json'
|
|
195
|
+
])
|
|
188
196
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
let outputBuffer = ''
|
|
199
|
-
let streamId = Date.now().toString()
|
|
200
|
-
|
|
201
|
-
// Send stream_start event
|
|
202
|
-
client.sendStreamChunk('stream_start', streamId, '')
|
|
203
|
-
|
|
204
|
-
// Handle stdout (streaming response)
|
|
205
|
-
agentProcess.stdout?.on('data', (data: Buffer) => {
|
|
197
|
+
let outputBuffer = ''
|
|
198
|
+
|
|
199
|
+
// Send stream_start event
|
|
200
|
+
client.sendStreamChunk('stream_start', streamId, '')
|
|
201
|
+
|
|
202
|
+
// Handle stdout (streaming response)
|
|
203
|
+
agentProcess.stdout?.on('data', (data: Buffer) => {
|
|
204
|
+
try {
|
|
206
205
|
const text = data.toString()
|
|
207
206
|
outputBuffer += text
|
|
208
207
|
|
|
@@ -234,35 +233,51 @@ export const eyeclawPlugin: ChannelPlugin<ResolvedEyeClawAccount> = {
|
|
|
234
233
|
outputBuffer = lines[lines.length - 1]
|
|
235
234
|
}
|
|
236
235
|
}
|
|
237
|
-
})
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
236
|
+
} catch (error) {
|
|
237
|
+
// Catch any errors in data processing to prevent WebSocket disconnect
|
|
238
|
+
const errorMsg = error instanceof Error ? error.message : String(error)
|
|
239
|
+
ctx.log?.error(`Error processing stdout data: ${errorMsg}`)
|
|
240
|
+
}
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
// Handle stderr (errors)
|
|
244
|
+
agentProcess.stderr?.on('data', (data: Buffer) => {
|
|
245
|
+
const errorText = data.toString()
|
|
246
|
+
ctx.log?.error(`Agent stderr: ${errorText}`)
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
// Wait for process to complete
|
|
250
|
+
await new Promise<void>((resolve, reject) => {
|
|
245
251
|
// Handle process completion
|
|
246
252
|
agentProcess.on('close', (code: number) => {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
253
|
+
try {
|
|
254
|
+
// Send any remaining buffered content
|
|
255
|
+
if (outputBuffer.trim()) {
|
|
256
|
+
try {
|
|
257
|
+
const parsed = JSON.parse(outputBuffer)
|
|
258
|
+
const response = parsed.result?.payloads?.[0]?.text || outputBuffer.trim()
|
|
259
|
+
client.sendStreamChunk('stream_chunk', streamId, response)
|
|
260
|
+
} catch (e) {
|
|
261
|
+
client.sendStreamChunk('stream_chunk', streamId, outputBuffer.trim())
|
|
262
|
+
}
|
|
255
263
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
264
|
+
|
|
265
|
+
// Send stream_end event
|
|
266
|
+
client.sendStreamChunk('stream_end', streamId, '')
|
|
267
|
+
|
|
268
|
+
if (code === 0) {
|
|
269
|
+
ctx.log?.info(`✅ Agent completed successfully`)
|
|
270
|
+
resolve()
|
|
271
|
+
} else {
|
|
272
|
+
ctx.log?.error(`Agent exited with code ${code}`)
|
|
273
|
+
client.sendLog('error', `❌ Agent error: process exited with code ${code}`)
|
|
274
|
+
reject(new Error(`Agent exited with code ${code}`))
|
|
275
|
+
}
|
|
276
|
+
} catch (error) {
|
|
277
|
+
// Prevent errors in close handler from crashing
|
|
278
|
+
const errorMsg = error instanceof Error ? error.message : String(error)
|
|
279
|
+
ctx.log?.error(`Error in close handler: ${errorMsg}`)
|
|
280
|
+
reject(error)
|
|
266
281
|
}
|
|
267
282
|
})
|
|
268
283
|
|
|
@@ -271,17 +286,20 @@ export const eyeclawPlugin: ChannelPlugin<ResolvedEyeClawAccount> = {
|
|
|
271
286
|
ctx.log?.error(`Failed to start agent process: ${error.message}`)
|
|
272
287
|
client.sendStreamChunk('stream_error', streamId, error.message)
|
|
273
288
|
client.sendLog('error', `❌ Failed to start agent: ${error.message}`)
|
|
289
|
+
reject(error)
|
|
274
290
|
})
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
const errorMsg = error instanceof Error ? error.message : String(error)
|
|
278
|
-
ctx.log?.error(`Failed to execute openclaw agent: ${errorMsg}`)
|
|
279
|
-
client.sendLog('error', `❌ Agent error: ${errorMsg}`)
|
|
280
|
-
}
|
|
291
|
+
})
|
|
292
|
+
|
|
281
293
|
} catch (error) {
|
|
282
294
|
const errorMsg = error instanceof Error ? error.message : String(error)
|
|
283
295
|
ctx.log?.error(`Failed to call OpenClaw Agent: ${errorMsg}`)
|
|
284
|
-
|
|
296
|
+
// Send error notification but don't crash the WebSocket connection
|
|
297
|
+
try {
|
|
298
|
+
client.sendStreamChunk('stream_error', streamId, errorMsg)
|
|
299
|
+
client.sendLog('error', `❌ Agent error: ${errorMsg}`)
|
|
300
|
+
} catch (sendError) {
|
|
301
|
+
ctx.log?.error(`Failed to send error notification: ${sendError}`)
|
|
302
|
+
}
|
|
285
303
|
}
|
|
286
304
|
})
|
|
287
305
|
|
package/src/client.ts
CHANGED
|
@@ -130,7 +130,7 @@ export class EyeClawClient {
|
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
private handleExecuteCommand(message: Record<string, unknown>): void {
|
|
133
|
+
private async handleExecuteCommand(message: Record<string, unknown>): Promise<void> {
|
|
134
134
|
const command = message.command as string
|
|
135
135
|
const params = (message.params as Record<string, unknown>) || {}
|
|
136
136
|
|
|
@@ -144,8 +144,8 @@ export class EyeClawClient {
|
|
|
144
144
|
// Send user message acknowledgment
|
|
145
145
|
this.sendLog('info', `收到消息: ${userMessage}`)
|
|
146
146
|
|
|
147
|
-
// Call OpenClaw Agent via callback
|
|
148
|
-
this.handleChatMessage(userMessage)
|
|
147
|
+
// Call OpenClaw Agent via callback and wait for completion
|
|
148
|
+
await this.handleChatMessage(userMessage)
|
|
149
149
|
break
|
|
150
150
|
}
|
|
151
151
|
|
|
@@ -184,11 +184,12 @@ export class EyeClawClient {
|
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
private handleChatMessage(userMessage: string): void {
|
|
187
|
+
private async handleChatMessage(userMessage: string): Promise<void> {
|
|
188
188
|
// This will be called by OpenClaw channel plugin via sendAgent
|
|
189
189
|
if (this.sendAgentCallback) {
|
|
190
190
|
this.logger.info('🤖 Calling OpenClaw Agent...')
|
|
191
|
-
this.sendAgentCallback(userMessage)
|
|
191
|
+
await this.sendAgentCallback(userMessage)
|
|
192
|
+
this.logger.info('✅ OpenClaw Agent completed')
|
|
192
193
|
} else {
|
|
193
194
|
// Fallback: simple echo if not running in OpenClaw context
|
|
194
195
|
this.logger.warn('No OpenClaw Agent available, using echo mode')
|