@folotoy/folotoy-openclaw-plugin 0.4.0 → 0.4.1

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.
@@ -0,0 +1,33 @@
1
+ export type AuthFlow1Config = {
2
+ flow: 'api';
3
+ api_url: string;
4
+ api_key: string;
5
+ toy_sn: string;
6
+ };
7
+ export type AuthFlow2Config = {
8
+ flow: 'direct';
9
+ toy_sn: string;
10
+ toy_key: string;
11
+ };
12
+ export type PluginConfig = {
13
+ auth: AuthFlow1Config | AuthFlow2Config;
14
+ mqtt: {
15
+ host: string;
16
+ port: number;
17
+ };
18
+ };
19
+ /** Flat config as stored in openclaw.json channels.folotoy */
20
+ export type FlatChannelConfig = {
21
+ flow?: string;
22
+ toy_sn?: string;
23
+ toy_key?: string;
24
+ api_url?: string;
25
+ api_key?: string;
26
+ mqtt_host?: string;
27
+ mqtt_port?: number;
28
+ };
29
+ export declare const DEFAULT_API_URL = "https://api.folotoy.cn";
30
+ export declare const DEFAULT_MQTT_HOST: string;
31
+ export declare const DEFAULT_MQTT_PORT = 1883;
32
+ export declare function flatToPluginConfig(flat: FlatChannelConfig): PluginConfig;
33
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,KAAK,CAAA;IACX,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,QAAQ,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,eAAe,GAAG,eAAe,CAAA;IACvC,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;CACF,CAAA;AAED,8DAA8D;AAC9D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,eAAO,MAAM,eAAe,2BAA2B,CAAA;AACvD,eAAO,MAAM,iBAAiB,QAAgD,CAAA;AAC9E,eAAO,MAAM,iBAAiB,OAAO,CAAA;AAErC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,GAAG,YAAY,CAaxE"}
package/dist/config.js ADDED
@@ -0,0 +1,17 @@
1
+ export const DEFAULT_API_URL = 'https://api.folotoy.cn';
2
+ export const DEFAULT_MQTT_HOST = process.env.FOLOTOY_MQTT_HOST ?? 'f.qrc92.cn';
3
+ export const DEFAULT_MQTT_PORT = 1883;
4
+ export function flatToPluginConfig(flat) {
5
+ const flow = flat.flow ?? 'direct';
6
+ const auth = flow === 'api'
7
+ ? { flow: 'api', api_url: flat.api_url ?? DEFAULT_API_URL, api_key: flat.api_key ?? '', toy_sn: flat.toy_sn ?? '' }
8
+ : { flow: 'direct', toy_sn: flat.toy_sn ?? '', toy_key: flat.toy_key ?? '' };
9
+ return {
10
+ auth,
11
+ mqtt: {
12
+ host: flat.mqtt_host ?? DEFAULT_MQTT_HOST,
13
+ port: flat.mqtt_port ?? DEFAULT_MQTT_PORT,
14
+ },
15
+ };
16
+ }
17
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAgCA,MAAM,CAAC,MAAM,eAAe,GAAG,wBAAwB,CAAA;AACvD,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,YAAY,CAAA;AAC9E,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAA;AAErC,MAAM,UAAU,kBAAkB,CAAC,IAAuB;IACxD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAA;IAClC,MAAM,IAAI,GAAG,IAAI,KAAK,KAAK;QACzB,CAAC,CAAC,EAAE,IAAI,EAAE,KAAc,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE,EAAE;QAC5H,CAAC,CAAC,EAAE,IAAI,EAAE,QAAiB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,CAAA;IAEvF,OAAO;QACL,IAAI;QACJ,IAAI,EAAE;YACJ,IAAI,EAAE,IAAI,CAAC,SAAS,IAAI,iBAAiB;YACzC,IAAI,EAAE,IAAI,CAAC,SAAS,IAAI,iBAAiB;SAC1C;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { OpenClawPluginApi } from 'openclaw/plugin-sdk/core';
2
+ export declare function sendNotification({ text, accountId }: {
3
+ text: string;
4
+ accountId?: string;
5
+ }): {
6
+ channel: string;
7
+ messageId: string;
8
+ };
9
+ declare const _default: (api: OpenClawPluginApi) => void;
10
+ export default _default;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,0BAA0B,CAAA;AAgOhF,wBAAgB,gBAAgB,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE;;;EAczF;yBAEe,KAAK,iBAAiB;AAAtC,wBAEC"}
package/dist/index.js ADDED
@@ -0,0 +1,208 @@
1
+ import { resolveCredentials, createMqttClient, buildInboundTopic, buildOutboundTopic, buildNotificationTopic } from './mqtt.js';
2
+ import { DEFAULT_MQTT_HOST, DEFAULT_MQTT_PORT, flatToPluginConfig } from './config.js';
3
+ /** Pick a soothing acknowledgment that loosely matches the input. */
4
+ function pickSoothingReply(text) {
5
+ const t = text.toLowerCase();
6
+ if (/难过|伤心|哭|不开心|sad|upset|cry/.test(t))
7
+ return '抱抱你,我在听呢,让我想想怎么帮你。';
8
+ if (/害怕|恐惧|怕|scared|afraid/.test(t))
9
+ return '别怕,有我在呢,让我想一想。';
10
+ if (/生气|愤怒|烦|angry|mad/.test(t))
11
+ return '我理解你的感受,让我来帮你想想办法。';
12
+ if (/累|疲|困|tired|exhausted/.test(t))
13
+ return '辛苦了,休息一下,我来帮你想。';
14
+ if (/无聊|没意思|bored/.test(t))
15
+ return '我来陪你聊聊吧,让我想想。';
16
+ if (/谢|感谢|thank/.test(t))
17
+ return '不客气呀,让我想想还能帮你什么。';
18
+ if (/你好|嗨|hello|hi|hey/.test(t))
19
+ return '你好呀!让我想想怎么回答你。';
20
+ if (/帮|help|怎么办/.test(t))
21
+ return '没问题,让我帮你想想办法。';
22
+ return '好的,让我想一想,马上回复你。';
23
+ }
24
+ // Per-account MQTT clients and msgId counters
25
+ const activeClients = new Map();
26
+ const folotoyChannel = {
27
+ id: 'folotoy',
28
+ meta: {
29
+ id: 'folotoy',
30
+ label: 'FoloToy',
31
+ selectionLabel: 'FoloToy',
32
+ docsPath: '/channels/folotoy',
33
+ blurb: 'Empower your FoloToy with OpenClaw AI capabilities.',
34
+ },
35
+ capabilities: {
36
+ chatTypes: ['direct'],
37
+ },
38
+ configSchema: {
39
+ schema: {
40
+ type: 'object',
41
+ properties: {
42
+ flow: { type: 'string', enum: ['direct', 'api'], default: 'direct' },
43
+ toy_sn: { type: 'string' },
44
+ toy_key: { type: 'string' },
45
+ api_url: { type: 'string', default: 'https://api.folotoy.cn' },
46
+ api_key: { type: 'string' },
47
+ mqtt_host: { type: 'string', default: DEFAULT_MQTT_HOST },
48
+ mqtt_port: { type: 'number', default: DEFAULT_MQTT_PORT },
49
+ },
50
+ },
51
+ uiHints: {
52
+ flow: { label: 'Auth Flow' },
53
+ toy_sn: { label: 'Toy SN' },
54
+ toy_key: { label: 'Toy Key', sensitive: true },
55
+ api_url: { label: 'API URL', placeholder: 'https://api.folotoy.com' },
56
+ api_key: { label: 'API Key', sensitive: true },
57
+ mqtt_host: { label: 'MQTT Host', placeholder: DEFAULT_MQTT_HOST },
58
+ mqtt_port: { label: 'MQTT Port' },
59
+ },
60
+ },
61
+ config: {
62
+ listAccountIds: (cfg) => {
63
+ const folotoy = cfg
64
+ .channels?.folotoy;
65
+ return folotoy ? ['default'] : [];
66
+ },
67
+ resolveAccount: (cfg, _accountId) => {
68
+ const folotoy = cfg
69
+ .channels?.folotoy;
70
+ return folotoy ?? {};
71
+ },
72
+ },
73
+ gateway: {
74
+ startAccount: async (ctx) => {
75
+ const { account, cfg, accountId, abortSignal, channelRuntime, log } = ctx;
76
+ if (!channelRuntime) {
77
+ log?.warn?.('channelRuntime not available — skipping MQTT connection');
78
+ return;
79
+ }
80
+ if (!account.toy_sn) {
81
+ log?.warn?.('toy_sn not configured — skipping MQTT connection');
82
+ return;
83
+ }
84
+ const mqttConfig = flatToPluginConfig(account);
85
+ log?.info?.(`Connecting to MQTT broker ${mqttConfig.mqtt.host}:${mqttConfig.mqtt.port}...`);
86
+ const credentials = await resolveCredentials(mqttConfig);
87
+ const client = await createMqttClient(mqttConfig, credentials);
88
+ const inboundTopic = buildInboundTopic(credentials.toy_sn);
89
+ const outboundTopic = buildOutboundTopic(credentials.toy_sn);
90
+ activeClients.set(accountId, { client, toy_sn: credentials.toy_sn, nextMsgId: 1 });
91
+ log?.info?.(`Connected to MQTT broker, subscribed to ${inboundTopic}`);
92
+ client.subscribe(inboundTopic, (err) => {
93
+ if (err)
94
+ log?.error?.(`Failed to subscribe: ${err.message}`);
95
+ });
96
+ client.on('message', (_topic, payload) => {
97
+ let msg;
98
+ try {
99
+ msg = JSON.parse(payload.toString());
100
+ }
101
+ catch {
102
+ return;
103
+ }
104
+ if (msg.identifier !== 'chat_input' || typeof msg.inputParams?.text !== 'string')
105
+ return;
106
+ const { msgId, inputParams: { text, recording_id } } = msg;
107
+ let order = 1;
108
+ // Send a quick soothing acknowledgment before AI processing (order=1).
109
+ // AI replies continue from order=2.
110
+ const ackMsg = {
111
+ msgId,
112
+ identifier: 'chat_output',
113
+ outParams: { content: pickSoothingReply(text), recording_id, order, is_finished: false },
114
+ };
115
+ client.publish(outboundTopic, JSON.stringify(ackMsg));
116
+ const inboundCtx = channelRuntime.reply.finalizeInboundContext({
117
+ Body: text,
118
+ From: credentials.toy_sn,
119
+ To: credentials.toy_sn,
120
+ SessionKey: `folotoy-${accountId}-${credentials.toy_sn}`,
121
+ AccountId: accountId,
122
+ Provider: 'folotoy',
123
+ });
124
+ // dispatch and send finish message when done
125
+ void (async () => {
126
+ try {
127
+ await channelRuntime.reply.dispatchReplyWithBufferedBlockDispatcher({
128
+ ctx: inboundCtx,
129
+ cfg,
130
+ dispatcherOptions: {
131
+ deliver: async (replyPayload) => {
132
+ if (!replyPayload.text)
133
+ return;
134
+ order++;
135
+ const outMsg = {
136
+ msgId,
137
+ identifier: 'chat_output',
138
+ outParams: { content: replyPayload.text, recording_id, order, is_finished: false },
139
+ };
140
+ client.publish(outboundTopic, JSON.stringify(outMsg));
141
+ },
142
+ onError: (err) => log?.error?.(`Dispatch error: ${String(err)}`),
143
+ },
144
+ });
145
+ }
146
+ finally {
147
+ order++;
148
+ const finishMsg = {
149
+ msgId,
150
+ identifier: 'chat_output',
151
+ outParams: { content: '', recording_id, order, is_finished: true },
152
+ };
153
+ client.publish(outboundTopic, JSON.stringify(finishMsg));
154
+ }
155
+ })();
156
+ });
157
+ // Keep the account alive until aborted
158
+ return new Promise((resolve) => {
159
+ abortSignal.addEventListener('abort', () => {
160
+ activeClients.delete(accountId);
161
+ client.end();
162
+ log?.info?.('MQTT client disconnected');
163
+ resolve();
164
+ });
165
+ });
166
+ },
167
+ stopAccount: async (_ctx) => {
168
+ // cleanup handled by abortSignal listener in startAccount
169
+ },
170
+ },
171
+ outbound: {
172
+ deliveryMode: 'direct',
173
+ sendText: async ({ text, accountId }) => {
174
+ const key = accountId ?? 'default';
175
+ const entry = activeClients.get(key);
176
+ if (!entry)
177
+ throw new Error(`No active MQTT client for account "${key}"`);
178
+ const outboundTopic = buildOutboundTopic(entry.toy_sn);
179
+ const msgId = entry.nextMsgId++;
180
+ const outMsg = {
181
+ msgId,
182
+ identifier: 'chat_output',
183
+ outParams: { content: text },
184
+ };
185
+ entry.client.publish(outboundTopic, JSON.stringify(outMsg));
186
+ return { channel: 'folotoy', messageId: String(msgId) };
187
+ },
188
+ },
189
+ };
190
+ export function sendNotification({ text, accountId }) {
191
+ const key = accountId ?? 'default';
192
+ const entry = activeClients.get(key);
193
+ if (!entry)
194
+ throw new Error(`No active MQTT client for account "${key}"`);
195
+ const notificationTopic = buildNotificationTopic(entry.toy_sn);
196
+ const msgId = entry.nextMsgId++;
197
+ const notifMsg = {
198
+ msgId,
199
+ identifier: 'send_notification',
200
+ outParams: { text },
201
+ };
202
+ entry.client.publish(notificationTopic, JSON.stringify(notifMsg));
203
+ return { channel: 'folotoy', messageId: String(msgId) };
204
+ }
205
+ export default (api) => {
206
+ api.registerChannel({ plugin: folotoyChannel });
207
+ };
208
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/mqtt.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { MqttClient } from 'mqtt';
2
+ import { PluginConfig } from './config.js';
3
+ export type MqttCredentials = {
4
+ username: string;
5
+ password: string;
6
+ toy_sn: string;
7
+ };
8
+ export declare function resolveCredentials(config: PluginConfig): Promise<MqttCredentials>;
9
+ export declare function buildInboundTopic(toy_sn: string): string;
10
+ export declare function buildOutboundTopic(toy_sn: string): string;
11
+ export declare function buildNotificationTopic(toy_sn: string): string;
12
+ export declare function createMqttClient(config: PluginConfig, credentials: MqttCredentials): Promise<MqttClient>;
13
+ //# sourceMappingURL=mqtt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mqtt.d.ts","sourceRoot":"","sources":["../src/mqtt.ts"],"names":[],"mappings":"AAAA,OAAa,EAAE,UAAU,EAAE,MAAM,MAAM,CAAA;AACvC,OAAO,EAAoC,YAAY,EAAE,MAAM,aAAa,CAAA;AAE5E,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAgCD,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,CAKvF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAgB9G"}
package/dist/mqtt.js ADDED
@@ -0,0 +1,58 @@
1
+ import mqtt from 'mqtt';
2
+ async function fetchCredentials(auth) {
3
+ const res = await fetch(`${auth.api_url}/v1/openapi/create_mqtt_token`, {
4
+ method: 'POST',
5
+ headers: {
6
+ 'Authorization': `Bearer ${auth.api_key}`,
7
+ 'Content-Type': 'application/json',
8
+ },
9
+ body: JSON.stringify({ toy_sn: auth.toy_sn }),
10
+ });
11
+ if (!res.ok) {
12
+ throw new Error(`Failed to fetch MQTT token: ${res.status} ${res.statusText}`);
13
+ }
14
+ const data = await res.json();
15
+ return {
16
+ username: data.username,
17
+ password: data.password,
18
+ toy_sn: auth.toy_sn,
19
+ };
20
+ }
21
+ function directCredentials(auth) {
22
+ return {
23
+ username: auth.toy_sn,
24
+ password: auth.toy_key,
25
+ toy_sn: auth.toy_sn,
26
+ };
27
+ }
28
+ export async function resolveCredentials(config) {
29
+ if (config.auth.flow === 'api') {
30
+ return fetchCredentials(config.auth);
31
+ }
32
+ return directCredentials(config.auth);
33
+ }
34
+ export function buildInboundTopic(toy_sn) {
35
+ return `/openapi/folotoy/${toy_sn}/thing/command/call`;
36
+ }
37
+ export function buildOutboundTopic(toy_sn) {
38
+ return `/openapi/folotoy/${toy_sn}/thing/command/callAck`;
39
+ }
40
+ export function buildNotificationTopic(toy_sn) {
41
+ return `/openapi/folotoy/${toy_sn}/thing/event/post`;
42
+ }
43
+ export async function createMqttClient(config, credentials) {
44
+ const { host, port } = config.mqtt;
45
+ const { username, password } = credentials;
46
+ return new Promise((resolve, reject) => {
47
+ const clientId = `openapi:${username}`;
48
+ const client = mqtt.connect(`mqtt://${host}:${port}`, {
49
+ clientId,
50
+ username: `openapi:${username}`,
51
+ password,
52
+ clean: true,
53
+ });
54
+ client.once('connect', () => resolve(client));
55
+ client.once('error', reject);
56
+ });
57
+ }
58
+ //# sourceMappingURL=mqtt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mqtt.js","sourceRoot":"","sources":["../src/mqtt.ts"],"names":[],"mappings":"AAAA,OAAO,IAAoB,MAAM,MAAM,CAAA;AASvC,KAAK,UAAU,gBAAgB,CAAC,IAAqB;IACnD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,+BAA+B,EAAE;QACtE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,eAAe,EAAE,UAAU,IAAI,CAAC,OAAO,EAAE;YACzC,cAAc,EAAE,kBAAkB;SACnC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;KAC9C,CAAC,CAAA;IAEF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,+BAA+B,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC,CAAA;IAChF,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAA4C,CAAA;IACvE,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAA;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAqB;IAC9C,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,MAAM;QACrB,QAAQ,EAAE,IAAI,CAAC,OAAO;QACtB,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAA;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAAoB;IAC3D,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAC/B,OAAO,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACtC,CAAC;IACD,OAAO,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;AACvC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,OAAO,oBAAoB,MAAM,qBAAqB,CAAA;AACxD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,OAAO,oBAAoB,MAAM,wBAAwB,CAAA;AAC3D,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAAc;IACnD,OAAO,oBAAoB,MAAM,mBAAmB,CAAA;AACtD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAoB,EAAE,WAA4B;IACvF,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,IAAI,CAAA;IAClC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,WAAW,CAAA;IAE1C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,QAAQ,GAAG,WAAW,QAAQ,EAAE,CAAA;QACtC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,IAAI,IAAI,EAAE,EAAE;YACpD,QAAQ;YACR,QAAQ,EAAE,WAAW,QAAQ,EAAE;YAC/B,QAAQ;YACR,KAAK,EAAE,IAAI;SACZ,CAAC,CAAA;QAEF,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAA;QAC7C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAC9B,CAAC,CAAC,CAAA;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@folotoy/folotoy-openclaw-plugin",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Empower your FoloToy with OpenClaw AI capabilities.",
5
5
  "keywords": [
6
6
  "folotoy",
@@ -28,7 +28,7 @@
28
28
  "files": [
29
29
  "src",
30
30
  "bin",
31
- "dist/cli",
31
+ "dist",
32
32
  "openclaw.plugin.json"
33
33
  ],
34
34
  "scripts": {