@folotoy/folotoy-openclaw-plugin 0.2.0 → 0.3.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/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/src/config.ts +1 -1
- package/src/index.ts +59 -3
- package/src/mqtt.ts +4 -0
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -31,7 +31,7 @@ export type FlatChannelConfig = {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export const DEFAULT_API_URL = 'https://api.folotoy.cn'
|
|
34
|
-
export const DEFAULT_MQTT_HOST = process.env.FOLOTOY_MQTT_HOST ?? '
|
|
34
|
+
export const DEFAULT_MQTT_HOST = process.env.FOLOTOY_MQTT_HOST ?? 'f.qrc92.cn'
|
|
35
35
|
export const DEFAULT_MQTT_PORT = 1883
|
|
36
36
|
|
|
37
37
|
export function flatToPluginConfig(flat: FlatChannelConfig): PluginConfig {
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { OpenClawPluginApi, ChannelPlugin } from 'openclaw/plugin-sdk/core'
|
|
2
|
-
import { resolveCredentials, createMqttClient, buildInboundTopic, buildOutboundTopic } from './mqtt.js'
|
|
2
|
+
import { resolveCredentials, createMqttClient, buildInboundTopic, buildOutboundTopic, buildNotificationTopic } from './mqtt.js'
|
|
3
3
|
import { DEFAULT_MQTT_HOST, DEFAULT_MQTT_PORT, flatToPluginConfig } from './config.js'
|
|
4
4
|
import type { FlatChannelConfig } from './config.js'
|
|
5
5
|
import type { MqttClient } from 'mqtt'
|
|
@@ -16,6 +16,36 @@ type OutboundMessage = {
|
|
|
16
16
|
outParams: { content: string; recording_id: number; order: number; is_finished: boolean }
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
type NotificationMessage = {
|
|
20
|
+
msgId: number
|
|
21
|
+
identifier: 'send_notification'
|
|
22
|
+
outParams: { text: string }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Pick a soothing acknowledgment that loosely matches the input. */
|
|
26
|
+
function pickSoothingReply(text: string): string {
|
|
27
|
+
const t = text.toLowerCase()
|
|
28
|
+
|
|
29
|
+
if (/难过|伤心|哭|不开心|sad|upset|cry/.test(t))
|
|
30
|
+
return '抱抱你,我在听呢,让我想想怎么帮你。'
|
|
31
|
+
if (/害怕|恐惧|怕|scared|afraid/.test(t))
|
|
32
|
+
return '别怕,有我在呢,让我想一想。'
|
|
33
|
+
if (/生气|愤怒|烦|angry|mad/.test(t))
|
|
34
|
+
return '我理解你的感受,让我来帮你想想办法。'
|
|
35
|
+
if (/累|疲|困|tired|exhausted/.test(t))
|
|
36
|
+
return '辛苦了,休息一下,我来帮你想。'
|
|
37
|
+
if (/无聊|没意思|bored/.test(t))
|
|
38
|
+
return '我来陪你聊聊吧,让我想想。'
|
|
39
|
+
if (/谢|感谢|thank/.test(t))
|
|
40
|
+
return '不客气呀,让我想想还能帮你什么。'
|
|
41
|
+
if (/你好|嗨|hello|hi|hey/.test(t))
|
|
42
|
+
return '你好呀!让我想想怎么回答你。'
|
|
43
|
+
if (/帮|help|怎么办/.test(t))
|
|
44
|
+
return '没问题,让我帮你想想办法。'
|
|
45
|
+
|
|
46
|
+
return '好的,让我想一想,马上回复你。'
|
|
47
|
+
}
|
|
48
|
+
|
|
19
49
|
// Per-account MQTT clients and msgId counters
|
|
20
50
|
const activeClients = new Map<string, { client: MqttClient; toy_sn: string; nextMsgId: number }>()
|
|
21
51
|
|
|
@@ -81,6 +111,7 @@ const folotoyChannel: ChannelPlugin<FlatChannelConfig> = {
|
|
|
81
111
|
}
|
|
82
112
|
|
|
83
113
|
const mqttConfig = flatToPluginConfig(account)
|
|
114
|
+
log?.info?.(`Connecting to MQTT broker ${mqttConfig.mqtt.host}:${mqttConfig.mqtt.port}...`)
|
|
84
115
|
const credentials = await resolveCredentials(mqttConfig)
|
|
85
116
|
const client = await createMqttClient(mqttConfig, credentials)
|
|
86
117
|
const inboundTopic = buildInboundTopic(credentials.toy_sn)
|
|
@@ -105,6 +136,15 @@ const folotoyChannel: ChannelPlugin<FlatChannelConfig> = {
|
|
|
105
136
|
const { msgId, inputParams: { text, recording_id } } = msg
|
|
106
137
|
let order = 0
|
|
107
138
|
|
|
139
|
+
// Send a quick soothing acknowledgment before AI processing
|
|
140
|
+
const notificationTopic = buildNotificationTopic(credentials.toy_sn)
|
|
141
|
+
const soothingMsg: NotificationMessage = {
|
|
142
|
+
msgId,
|
|
143
|
+
identifier: 'send_notification',
|
|
144
|
+
outParams: { text: pickSoothingReply(text) },
|
|
145
|
+
}
|
|
146
|
+
client.publish(notificationTopic, JSON.stringify(soothingMsg))
|
|
147
|
+
|
|
108
148
|
const inboundCtx = channelRuntime.reply.finalizeInboundContext({
|
|
109
149
|
Body: text,
|
|
110
150
|
From: credentials.toy_sn,
|
|
@@ -171,9 +211,9 @@ const folotoyChannel: ChannelPlugin<FlatChannelConfig> = {
|
|
|
171
211
|
|
|
172
212
|
const outboundTopic = buildOutboundTopic(entry.toy_sn)
|
|
173
213
|
const msgId = entry.nextMsgId++
|
|
174
|
-
const outMsg
|
|
214
|
+
const outMsg = {
|
|
175
215
|
msgId,
|
|
176
|
-
identifier: 'chat_output',
|
|
216
|
+
identifier: 'chat_output' as const,
|
|
177
217
|
outParams: { content: text },
|
|
178
218
|
}
|
|
179
219
|
entry.client.publish(outboundTopic, JSON.stringify(outMsg))
|
|
@@ -182,6 +222,22 @@ const folotoyChannel: ChannelPlugin<FlatChannelConfig> = {
|
|
|
182
222
|
},
|
|
183
223
|
}
|
|
184
224
|
|
|
225
|
+
export function sendNotification({ text, accountId }: { text: string; accountId?: string }) {
|
|
226
|
+
const key = accountId ?? 'default'
|
|
227
|
+
const entry = activeClients.get(key)
|
|
228
|
+
if (!entry) throw new Error(`No active MQTT client for account "${key}"`)
|
|
229
|
+
|
|
230
|
+
const notificationTopic = buildNotificationTopic(entry.toy_sn)
|
|
231
|
+
const msgId = entry.nextMsgId++
|
|
232
|
+
const notifMsg: NotificationMessage = {
|
|
233
|
+
msgId,
|
|
234
|
+
identifier: 'send_notification',
|
|
235
|
+
outParams: { text },
|
|
236
|
+
}
|
|
237
|
+
entry.client.publish(notificationTopic, JSON.stringify(notifMsg))
|
|
238
|
+
return { channel: 'folotoy', messageId: String(msgId) }
|
|
239
|
+
}
|
|
240
|
+
|
|
185
241
|
export default (api: OpenClawPluginApi) => {
|
|
186
242
|
api.registerChannel({ plugin: folotoyChannel })
|
|
187
243
|
}
|
package/src/mqtt.ts
CHANGED
|
@@ -52,6 +52,10 @@ export function buildOutboundTopic(toy_sn: string): string {
|
|
|
52
52
|
return `/openapi/folotoy/${toy_sn}/thing/command/callAck`
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
export function buildNotificationTopic(toy_sn: string): string {
|
|
56
|
+
return `/openapi/folotoy/${toy_sn}/thing/event/post`
|
|
57
|
+
}
|
|
58
|
+
|
|
55
59
|
export async function createMqttClient(config: PluginConfig, credentials: MqttCredentials): Promise<MqttClient> {
|
|
56
60
|
const { host, port } = config.mqtt
|
|
57
61
|
const { username, password } = credentials
|