openclaw-quiubo 0.3.0 → 0.5.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/dist/index.d.ts +15 -59
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -101
- package/dist/index.js.map +1 -1
- package/dist/src/api.d.ts +6 -0
- package/dist/src/api.d.ts.map +1 -1
- package/dist/src/api.js +13 -0
- package/dist/src/api.js.map +1 -1
- package/dist/src/channel.d.ts +4 -40
- package/dist/src/channel.d.ts.map +1 -1
- package/dist/src/channel.js +220 -44
- package/dist/src/channel.js.map +1 -1
- package/dist/src/polling-gateway.d.ts +46 -0
- package/dist/src/polling-gateway.d.ts.map +1 -0
- package/dist/src/polling-gateway.js +98 -0
- package/dist/src/polling-gateway.js.map +1 -0
- package/dist/src/realtime-gateway.d.ts +68 -0
- package/dist/src/realtime-gateway.d.ts.map +1 -0
- package/dist/src/realtime-gateway.js +212 -0
- package/dist/src/realtime-gateway.js.map +1 -0
- package/dist/src/runtime.d.ts +11 -0
- package/dist/src/runtime.d.ts.map +1 -0
- package/dist/src/runtime.js +22 -0
- package/dist/src/runtime.js.map +1 -0
- package/dist/src/types.d.ts +6 -2
- package/dist/src/types.d.ts.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +7 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,69 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Quiubo OpenClaw Extension — Entry Point
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Object-based plugin registration (matching openclaw-mqtt pattern).
|
|
5
|
+
* Stores the PluginRuntime reference and registers the channel plugin.
|
|
6
6
|
*/
|
|
7
7
|
export { QuiuboApiClient } from './src/api.js';
|
|
8
|
-
export { quiuboPlugin
|
|
9
|
-
export {
|
|
10
|
-
export
|
|
11
|
-
|
|
8
|
+
export { quiuboPlugin } from './src/channel.js';
|
|
9
|
+
export { RealtimeGateway } from './src/realtime-gateway.js';
|
|
10
|
+
export { PollingGateway } from './src/polling-gateway.js';
|
|
11
|
+
export type { QuiuboAccountConfig, QuiuboGroup, QuiuboMessage, QuiuboIdentity, QuiuboJoinToken, QuiuboAuthResponse, WebhookPayload, WebhookMessageData, WebhookJoinTokenRedeemedData, } from './src/types.js';
|
|
12
|
+
interface OpenClawPluginApi {
|
|
13
|
+
runtime: unknown;
|
|
12
14
|
registerChannel: (opts: {
|
|
13
|
-
plugin:
|
|
15
|
+
plugin: any;
|
|
14
16
|
}) => void;
|
|
15
|
-
ingest: (message: Record<string, any>) => Promise<void>;
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Called when the gateway starts.
|
|
24
|
-
* Start the webhook server to receive inbound messages.
|
|
25
|
-
*/
|
|
26
|
-
start: (ctx: {
|
|
27
|
-
config: Record<string, any>;
|
|
28
|
-
accountId?: string;
|
|
29
|
-
}, api: OpenClawApi) => Promise<void>;
|
|
30
|
-
/**
|
|
31
|
-
* Called when the gateway stops.
|
|
32
|
-
* Clean up the webhook server.
|
|
33
|
-
*/
|
|
34
|
-
stop: () => Promise<void>;
|
|
35
|
-
};
|
|
36
|
-
id: "quiubo";
|
|
37
|
-
meta: {
|
|
38
|
-
id: string;
|
|
39
|
-
label: string;
|
|
40
|
-
selectionLabel: string;
|
|
41
|
-
blurb: string;
|
|
42
|
-
aliases: string[];
|
|
43
|
-
};
|
|
44
|
-
capabilities: {
|
|
45
|
-
chatTypes: readonly ["group"];
|
|
46
|
-
};
|
|
47
|
-
config: {
|
|
48
|
-
listAccountIds(cfg: Record<string, unknown>): string[];
|
|
49
|
-
resolveAccount(cfg: Record<string, unknown>, accountId?: string): import("./index.js").QuiuboAccountConfig;
|
|
50
|
-
};
|
|
51
|
-
outbound: {
|
|
52
|
-
deliveryMode: "direct";
|
|
53
|
-
sendText({ text, target }: {
|
|
54
|
-
text: string;
|
|
55
|
-
target?: Record<string, any>;
|
|
56
|
-
}): Promise<{
|
|
57
|
-
ok: boolean;
|
|
58
|
-
}>;
|
|
59
|
-
};
|
|
18
|
+
declare const plugin: {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
register(api: OpenClawPluginApi): void;
|
|
60
23
|
};
|
|
61
|
-
|
|
62
|
-
* OpenClaw plugin entry point.
|
|
63
|
-
*
|
|
64
|
-
* Called by OpenClaw when it loads the extension:
|
|
65
|
-
* import register from 'openclaw-quiubo';
|
|
66
|
-
* register(api);
|
|
67
|
-
*/
|
|
68
|
-
export default function register(api: OpenClawApi): void;
|
|
24
|
+
export default plugin;
|
|
69
25
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,YAAY,EACV,mBAAmB,EACnB,WAAW,EACX,aAAa,EACb,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,4BAA4B,GAC7B,MAAM,gBAAgB,CAAC;AAGxB,UAAU,iBAAiB;IACzB,OAAO,EAAE,OAAO,CAAC;IAEjB,eAAe,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,GAAG,CAAA;KAAE,KAAK,IAAI,CAAC;CAClD;AAED,QAAA,MAAM,MAAM;;;;kBAII,iBAAiB;CAIhC,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,111 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Quiubo OpenClaw Extension — Entry Point
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Object-based plugin registration (matching openclaw-mqtt pattern).
|
|
5
|
+
* Stores the PluginRuntime reference and registers the channel plugin.
|
|
6
6
|
*/
|
|
7
|
+
import { setQuiuboRuntime } from './src/runtime.js';
|
|
7
8
|
import { quiuboPlugin } from './src/channel.js';
|
|
8
|
-
import { startWebhookServer } from './src/webhook-handler.js';
|
|
9
9
|
// Re-export for consumers
|
|
10
10
|
export { QuiuboApiClient } from './src/api.js';
|
|
11
|
-
export { quiuboPlugin
|
|
12
|
-
export {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (payload.event === 'group_message.created') {
|
|
22
|
-
const message = payload.data;
|
|
23
|
-
if (!('senderIdentityId' in message))
|
|
24
|
-
return;
|
|
25
|
-
const inbound = {
|
|
26
|
-
channel: 'quiubo',
|
|
27
|
-
accountId: account.accountId ?? 'default',
|
|
28
|
-
chatType: 'group',
|
|
29
|
-
groupId: message.groupId,
|
|
30
|
-
senderId: message.senderIdentityId,
|
|
31
|
-
senderName: message.senderUsername ?? message.senderIdentityId,
|
|
32
|
-
text: message.plaintext,
|
|
33
|
-
messageId: message.messageId,
|
|
34
|
-
timestamp: message.createdAt ? new Date(message.createdAt).getTime() : Date.now(),
|
|
35
|
-
raw: message,
|
|
36
|
-
};
|
|
37
|
-
try {
|
|
38
|
-
await api.ingest(inbound);
|
|
39
|
-
}
|
|
40
|
-
catch (error) {
|
|
41
|
-
console.error('[Quiubo] Failed to ingest message:', error);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
console.log(`[Quiubo] Ignoring event: ${payload.event}`);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Plugin with gateway lifecycle wired in.
|
|
50
|
-
*/
|
|
51
|
-
const pluginWithGateway = {
|
|
52
|
-
...quiuboPlugin,
|
|
53
|
-
gateway: {
|
|
54
|
-
/**
|
|
55
|
-
* Called when the gateway starts.
|
|
56
|
-
* Start the webhook server to receive inbound messages.
|
|
57
|
-
*/
|
|
58
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
59
|
-
start: async (ctx, api) => {
|
|
60
|
-
const { config, accountId } = ctx;
|
|
61
|
-
const accounts = config.channels?.quiubo?.accounts;
|
|
62
|
-
const account = accounts?.[accountId ?? 'default'];
|
|
63
|
-
if (!account) {
|
|
64
|
-
console.warn('[Quiubo] No account config found, skipping webhook server');
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
const webhookPort = account.webhookPort ?? 3456;
|
|
68
|
-
const webhookSecret = account.webhookSecret;
|
|
69
|
-
const botIdentityId = account.botIdentityId;
|
|
70
|
-
if (!botIdentityId) {
|
|
71
|
-
console.error('[Quiubo] botIdentityId is required in account config');
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
try {
|
|
75
|
-
webhookServer = await startWebhookServer({
|
|
76
|
-
port: webhookPort,
|
|
77
|
-
webhookSecret,
|
|
78
|
-
botIdentityId,
|
|
79
|
-
onMessage: async (payload) => {
|
|
80
|
-
await handleInboundMessage(api, payload, account);
|
|
81
|
-
},
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
catch (error) {
|
|
85
|
-
console.error('[Quiubo] Failed to start webhook server:', error);
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
/**
|
|
89
|
-
* Called when the gateway stops.
|
|
90
|
-
* Clean up the webhook server.
|
|
91
|
-
*/
|
|
92
|
-
stop: async () => {
|
|
93
|
-
if (webhookServer) {
|
|
94
|
-
webhookServer.close();
|
|
95
|
-
webhookServer = null;
|
|
96
|
-
console.log('[Quiubo] Webhook server stopped');
|
|
97
|
-
}
|
|
98
|
-
},
|
|
11
|
+
export { quiuboPlugin } from './src/channel.js';
|
|
12
|
+
export { RealtimeGateway } from './src/realtime-gateway.js';
|
|
13
|
+
export { PollingGateway } from './src/polling-gateway.js';
|
|
14
|
+
const plugin = {
|
|
15
|
+
id: 'openclaw-quiubo',
|
|
16
|
+
name: 'Quiubo',
|
|
17
|
+
description: 'Chat with AI assistants through Quiubo',
|
|
18
|
+
register(api) {
|
|
19
|
+
setQuiuboRuntime(api.runtime);
|
|
20
|
+
api.registerChannel({ plugin: quiuboPlugin });
|
|
99
21
|
},
|
|
100
22
|
};
|
|
101
|
-
|
|
102
|
-
* OpenClaw plugin entry point.
|
|
103
|
-
*
|
|
104
|
-
* Called by OpenClaw when it loads the extension:
|
|
105
|
-
* import register from 'openclaw-quiubo';
|
|
106
|
-
* register(api);
|
|
107
|
-
*/
|
|
108
|
-
export default function register(api) {
|
|
109
|
-
api.registerChannel({ plugin: pluginWithGateway });
|
|
110
|
-
}
|
|
23
|
+
export default plugin;
|
|
111
24
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,0BAA0B;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAoB1D,MAAM,MAAM,GAAG;IACb,EAAE,EAAE,iBAAiB;IACrB,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,wCAAwC;IACrD,QAAQ,CAAC,GAAsB;QAC7B,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC9B,GAAG,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;IAChD,CAAC;CACF,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
package/dist/src/api.d.ts
CHANGED
|
@@ -114,5 +114,11 @@ export declare class QuiuboApiClient {
|
|
|
114
114
|
deleteJoinToken(tokenId: string): Promise<{
|
|
115
115
|
success: boolean;
|
|
116
116
|
}>;
|
|
117
|
+
/**
|
|
118
|
+
* Authenticate a Pusher channel subscription for an SDK-owned identity.
|
|
119
|
+
*/
|
|
120
|
+
pusherAuth(socketId: string, channelName: string, identityId: string): Promise<{
|
|
121
|
+
auth: string;
|
|
122
|
+
}>;
|
|
117
123
|
}
|
|
118
124
|
//# sourceMappingURL=api.d.ts.map
|
package/dist/src/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EACV,WAAW,EAAE,aAAa,EAAE,kBAAkB,EAC9C,cAAc,EAAE,eAAe,EAChC,MAAM,YAAY,CAAC;AAEpB,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;YAM7B,OAAO;IAyBrB;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAIjD;;OAEG;IACG,WAAW,CACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE;QACJ,gBAAgB,EAAE,MAAM,CAAC;QACzB,SAAS,EAAE,MAAM,CAAC;QAClB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,GACA,OAAO,CAAC,aAAa,CAAC;IAQzB;;OAEG;IACG,YAAY,CAChB,OAAO,EAAE,MAAM,EACf,cAAc,CAAC,EAAE,MAAM,EACvB,KAAK,SAAK,GACT,OAAO,CAAC;QAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAQ3D;;OAEG;IACG,WAAW,CAAC,IAAI,EAAE;QACtB,eAAe,EAAE,MAAM,CAAC;QACxB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,WAAW,CAAC;IAIxB;;OAEG;IACG,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvE;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAO1E;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,WAAW,EAAE,CAAA;KAAE,CAAC;IAItD;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAIrD;;OAEG;IACG,gBAAgB,CAAC,IAAI,EAAE;QAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B,GAAG,OAAO,CAAC;QACV,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,cAAc,EAAE,OAAO,CAAC;QACxB,SAAS,EAAE,OAAO,CAAC;QACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;KAClC,CAAC;IAQF;;OAEG;IACG,cAAc,CAAC,IAAI,EAAE;QACzB,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,cAAc,CAAC;IAI3B;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC;QAAE,UAAU,EAAE,cAAc,EAAE,CAAA;KAAE,CAAC;IAIjE;;OAEG;IACG,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAQvE;;OAEG;IACG,eAAe,CAAC,IAAI,EAAE;QAC1B,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACpC,GAAG,OAAO,CAAC,eAAe,CAAC;IAI5B;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,eAAe,EAAE,CAAA;KAAE,CAAC;IAI9D;;OAEG;IACG,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/src/api.js
CHANGED
|
@@ -140,5 +140,18 @@ export class QuiuboApiClient {
|
|
|
140
140
|
async deleteJoinToken(tokenId) {
|
|
141
141
|
return this.request('DELETE', `/join-tokens/${tokenId}`);
|
|
142
142
|
}
|
|
143
|
+
// ========================================================================
|
|
144
|
+
// Pusher Auth
|
|
145
|
+
// ========================================================================
|
|
146
|
+
/**
|
|
147
|
+
* Authenticate a Pusher channel subscription for an SDK-owned identity.
|
|
148
|
+
*/
|
|
149
|
+
async pusherAuth(socketId, channelName, identityId) {
|
|
150
|
+
return this.request('POST', '/pusher/auth', {
|
|
151
|
+
socket_id: socketId,
|
|
152
|
+
channel_name: channelName,
|
|
153
|
+
identity_id: identityId,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
143
156
|
}
|
|
144
157
|
//# sourceMappingURL=api.js.map
|
package/dist/src/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/api.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/src/channel.d.ts
CHANGED
|
@@ -2,47 +2,11 @@
|
|
|
2
2
|
* Quiubo Channel Plugin
|
|
3
3
|
*
|
|
4
4
|
* Flat plugin object matching OpenClaw's ChannelPlugin interface.
|
|
5
|
+
* Gateway lifecycle uses startAccount(ctx) per account (not start/stop).
|
|
6
|
+
* Inbound routing uses runtime.channel.reply pipeline (same as openclaw-mqtt).
|
|
5
7
|
*
|
|
6
8
|
* Shape:
|
|
7
|
-
* id, meta, capabilities, config, outbound
|
|
9
|
+
* id, meta, capabilities, config, outbound, gateway
|
|
8
10
|
*/
|
|
9
|
-
|
|
10
|
-
import type { QuiuboAccountConfig } from './types.js';
|
|
11
|
-
/**
|
|
12
|
-
* The plugin object passed to api.registerChannel({ plugin }).
|
|
13
|
-
*
|
|
14
|
-
* OpenClaw discovers accounts via config.listAccountIds / resolveAccount,
|
|
15
|
-
* then calls outbound.sendText when the agent needs to respond.
|
|
16
|
-
*/
|
|
17
|
-
export declare const quiuboPlugin: {
|
|
18
|
-
id: "quiubo";
|
|
19
|
-
meta: {
|
|
20
|
-
id: string;
|
|
21
|
-
label: string;
|
|
22
|
-
selectionLabel: string;
|
|
23
|
-
blurb: string;
|
|
24
|
-
aliases: string[];
|
|
25
|
-
};
|
|
26
|
-
capabilities: {
|
|
27
|
-
chatTypes: readonly ["group"];
|
|
28
|
-
};
|
|
29
|
-
config: {
|
|
30
|
-
listAccountIds(cfg: Record<string, unknown>): string[];
|
|
31
|
-
resolveAccount(cfg: Record<string, unknown>, accountId?: string): QuiuboAccountConfig;
|
|
32
|
-
};
|
|
33
|
-
outbound: {
|
|
34
|
-
deliveryMode: "direct";
|
|
35
|
-
sendText({ text, target }: {
|
|
36
|
-
text: string;
|
|
37
|
-
target?: Record<string, any>;
|
|
38
|
-
}): Promise<{
|
|
39
|
-
ok: boolean;
|
|
40
|
-
}>;
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
/**
|
|
44
|
-
* Get the current API client (for webhook handler and other plumbing).
|
|
45
|
-
* Returns null if no account has been resolved yet.
|
|
46
|
-
*/
|
|
47
|
-
export declare function getQuiuboClient(): QuiuboApiClient | null;
|
|
11
|
+
export declare const quiuboPlugin: any;
|
|
48
12
|
//# sourceMappingURL=channel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/channel.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAiBH,eAAO,MAAM,YAAY,EAAE,GA6M1B,CAAC"}
|
package/dist/src/channel.js
CHANGED
|
@@ -2,26 +2,22 @@
|
|
|
2
2
|
* Quiubo Channel Plugin
|
|
3
3
|
*
|
|
4
4
|
* Flat plugin object matching OpenClaw's ChannelPlugin interface.
|
|
5
|
+
* Gateway lifecycle uses startAccount(ctx) per account (not start/stop).
|
|
6
|
+
* Inbound routing uses runtime.channel.reply pipeline (same as openclaw-mqtt).
|
|
5
7
|
*
|
|
6
8
|
* Shape:
|
|
7
|
-
* id, meta, capabilities, config, outbound
|
|
9
|
+
* id, meta, capabilities, config, outbound, gateway
|
|
8
10
|
*/
|
|
9
11
|
import { QuiuboApiClient } from './api.js';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* The plugin object passed to api.registerChannel({ plugin }).
|
|
21
|
-
*
|
|
22
|
-
* OpenClaw discovers accounts via config.listAccountIds / resolveAccount,
|
|
23
|
-
* then calls outbound.sendText when the agent needs to respond.
|
|
24
|
-
*/
|
|
12
|
+
import { RealtimeGateway } from './realtime-gateway.js';
|
|
13
|
+
import { getQuiuboRuntime } from './runtime.js';
|
|
14
|
+
/** Per-account gateway instances, keyed by accountId */
|
|
15
|
+
const gateways = new Map();
|
|
16
|
+
/** Per-account API clients, keyed by accountId */
|
|
17
|
+
const clients = new Map();
|
|
18
|
+
/** Per-account configs, keyed by accountId */
|
|
19
|
+
const accounts = new Map();
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
21
|
export const quiuboPlugin = {
|
|
26
22
|
id: 'quiubo',
|
|
27
23
|
meta: {
|
|
@@ -31,46 +27,70 @@ export const quiuboPlugin = {
|
|
|
31
27
|
blurb: 'Send and receive messages through Quiubo.',
|
|
32
28
|
aliases: ['qb'],
|
|
33
29
|
},
|
|
34
|
-
capabilities: {
|
|
30
|
+
capabilities: {
|
|
31
|
+
chatTypes: ['group'],
|
|
32
|
+
supportsMedia: false,
|
|
33
|
+
supportsReactions: false,
|
|
34
|
+
supportsThreads: false,
|
|
35
|
+
},
|
|
35
36
|
// ── config adapter ──────────────────────────────────────────────
|
|
36
37
|
config: {
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
37
39
|
listAccountIds(cfg) {
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return Object.keys(accounts
|
|
40
|
+
const quiubo = cfg.channels?.quiubo;
|
|
41
|
+
if (!quiubo?.accounts)
|
|
42
|
+
return [];
|
|
43
|
+
return Object.keys(quiubo.accounts);
|
|
42
44
|
},
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
43
46
|
resolveAccount(cfg, accountId) {
|
|
44
|
-
const channels = cfg.channels;
|
|
45
|
-
const quiubo = channels?.quiubo;
|
|
46
|
-
const accounts = quiubo?.accounts;
|
|
47
47
|
const id = accountId ?? 'default';
|
|
48
|
-
const account = accounts?.[id];
|
|
48
|
+
const account = cfg.channels?.quiubo?.accounts?.[id];
|
|
49
49
|
if (!account) {
|
|
50
50
|
return { accountId: id };
|
|
51
51
|
}
|
|
52
|
-
|
|
52
|
+
const resolved = { ...account, accountId: id };
|
|
53
|
+
// Cache client + config for outbound use
|
|
53
54
|
const apiUrl = account.apiUrl ?? 'https://api.quiubo.io';
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return
|
|
55
|
+
clients.set(id, new QuiuboApiClient(apiUrl, account.apiKey));
|
|
56
|
+
accounts.set(id, resolved);
|
|
57
|
+
return resolved;
|
|
57
58
|
},
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
60
|
+
isEnabled: (account) => Boolean(account.apiKey),
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
62
|
+
isConfigured: (account) => Boolean(account.apiKey && account.botIdentityId),
|
|
58
63
|
},
|
|
59
64
|
// ── outbound adapter ────────────────────────────────────────────
|
|
60
65
|
outbound: {
|
|
61
66
|
deliveryMode: 'direct',
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
68
|
+
async sendText(ctx) {
|
|
69
|
+
const { text, cfg } = ctx;
|
|
70
|
+
// Resolve account + client
|
|
71
|
+
const accountId = ctx.accountId ?? 'default';
|
|
72
|
+
let client = clients.get(accountId);
|
|
73
|
+
let account = accounts.get(accountId);
|
|
74
|
+
if (!client || !account) {
|
|
75
|
+
// Try resolving from cfg
|
|
76
|
+
const quiubo = cfg?.channels?.quiubo?.accounts?.[accountId];
|
|
77
|
+
if (!quiubo?.apiKey) {
|
|
78
|
+
return { ok: false, error: 'No account config found' };
|
|
79
|
+
}
|
|
80
|
+
const apiUrl = quiubo.apiUrl ?? 'https://api.quiubo.io';
|
|
81
|
+
client = new QuiuboApiClient(apiUrl, quiubo.apiKey);
|
|
82
|
+
account = { ...quiubo, accountId };
|
|
83
|
+
clients.set(accountId, client);
|
|
84
|
+
accounts.set(accountId, account);
|
|
85
|
+
}
|
|
86
|
+
// Get groupId from context — OpenClaw sets this from inbound routing
|
|
87
|
+
const groupId = ctx.to ?? ctx.target?.groupId ?? ctx.target?.raw?.groupId;
|
|
66
88
|
if (!groupId) {
|
|
67
|
-
|
|
68
|
-
return { ok: false };
|
|
89
|
+
return { ok: false, error: 'No groupId in outbound context' };
|
|
69
90
|
}
|
|
70
|
-
const senderId =
|
|
91
|
+
const senderId = account.botIdentityId;
|
|
71
92
|
if (!senderId) {
|
|
72
|
-
|
|
73
|
-
return { ok: false };
|
|
93
|
+
return { ok: false, error: 'No botIdentityId configured' };
|
|
74
94
|
}
|
|
75
95
|
try {
|
|
76
96
|
await client.sendMessage(groupId, {
|
|
@@ -80,17 +100,173 @@ export const quiuboPlugin = {
|
|
|
80
100
|
return { ok: true };
|
|
81
101
|
}
|
|
82
102
|
catch (error) {
|
|
83
|
-
|
|
84
|
-
return { ok: false };
|
|
103
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
104
|
+
return { ok: false, error: msg };
|
|
85
105
|
}
|
|
86
106
|
},
|
|
87
107
|
},
|
|
108
|
+
// ── gateway adapter ─────────────────────────────────────────────
|
|
109
|
+
gateway: {
|
|
110
|
+
/**
|
|
111
|
+
* Called by OpenClaw per account when the gateway starts.
|
|
112
|
+
*
|
|
113
|
+
* ctx provides: { cfg, accountId, account, abortSignal, log }
|
|
114
|
+
* - cfg: full OpenClaw config
|
|
115
|
+
* - accountId: which account to start
|
|
116
|
+
* - account: resolved account config (from resolveAccount)
|
|
117
|
+
* - abortSignal: signal to stop this account's gateway
|
|
118
|
+
* - log: structured logger
|
|
119
|
+
*/
|
|
120
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
121
|
+
startAccount: async (ctx) => {
|
|
122
|
+
const { cfg, accountId, abortSignal, log } = ctx;
|
|
123
|
+
const quiuboConfig = cfg.channels?.quiubo?.accounts?.[accountId];
|
|
124
|
+
if (!quiuboConfig?.apiKey || !quiuboConfig?.botIdentityId) {
|
|
125
|
+
log?.warn?.(`[${accountId}] Quiubo: missing apiKey or botIdentityId, skipping`);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const apiUrl = quiuboConfig.apiUrl ?? 'https://api.quiubo.io';
|
|
129
|
+
const { apiKey, botIdentityId, pollIntervalMs } = quiuboConfig;
|
|
130
|
+
const runtime = getQuiuboRuntime();
|
|
131
|
+
// Discovery: log runtime shape on first startup to verify method paths
|
|
132
|
+
log?.info?.(`[${accountId}] Quiubo: runtime keys: ${Object.keys(runtime).join(', ')}`);
|
|
133
|
+
if (runtime.channel) {
|
|
134
|
+
log?.info?.(`[${accountId}] Quiubo: runtime.channel keys: ${Object.keys(runtime.channel).join(', ')}`);
|
|
135
|
+
if (runtime.channel.reply) {
|
|
136
|
+
log?.info?.(`[${accountId}] Quiubo: runtime.channel.reply keys: ${Object.keys(runtime.channel.reply).join(', ')}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const client = new QuiuboApiClient(apiUrl, apiKey);
|
|
140
|
+
// Cache for outbound
|
|
141
|
+
clients.set(accountId, client);
|
|
142
|
+
accounts.set(accountId, { ...quiuboConfig, accountId });
|
|
143
|
+
// Authenticate and get Pusher config
|
|
144
|
+
let pusherConfig;
|
|
145
|
+
try {
|
|
146
|
+
const auth = await client.authenticate();
|
|
147
|
+
pusherConfig = auth.pusher;
|
|
148
|
+
log?.info?.(`[${accountId}] Quiubo: authenticated as ${auth.appName} (${auth.appId})`);
|
|
149
|
+
if (pusherConfig) {
|
|
150
|
+
log?.info?.(`[${accountId}] Quiubo: Pusher available (cluster: ${pusherConfig.cluster})`);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
log?.info?.(`[${accountId}] Quiubo: Pusher not configured — using polling`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
log?.error?.(`[${accountId}] Quiubo: authentication failed: ${error}`);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
// Create gateway with inbound routing callback
|
|
161
|
+
const gateway = new RealtimeGateway({
|
|
162
|
+
client,
|
|
163
|
+
botIdentityId,
|
|
164
|
+
pusher: pusherConfig,
|
|
165
|
+
pollIntervalMs: pollIntervalMs ?? 5000,
|
|
166
|
+
onMessage: async (msg) => {
|
|
167
|
+
try {
|
|
168
|
+
await routeInboundMessage({
|
|
169
|
+
runtime,
|
|
170
|
+
cfg,
|
|
171
|
+
accountId,
|
|
172
|
+
botIdentityId,
|
|
173
|
+
client,
|
|
174
|
+
msg,
|
|
175
|
+
log,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
log?.error?.(`[${accountId}] Quiubo: inbound routing failed: ${error}`);
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
gateways.set(accountId, gateway);
|
|
184
|
+
await gateway.start();
|
|
185
|
+
log?.info?.(`[${accountId}] Quiubo: gateway started`);
|
|
186
|
+
// Return a promise that resolves when aborted (keeps the gateway alive)
|
|
187
|
+
return new Promise((resolve) => {
|
|
188
|
+
const cleanup = () => {
|
|
189
|
+
log?.info?.(`[${accountId}] Quiubo: gateway stopping`);
|
|
190
|
+
gateway.stop();
|
|
191
|
+
gateways.delete(accountId);
|
|
192
|
+
clients.delete(accountId);
|
|
193
|
+
accounts.delete(accountId);
|
|
194
|
+
resolve();
|
|
195
|
+
};
|
|
196
|
+
if (abortSignal) {
|
|
197
|
+
abortSignal.addEventListener('abort', cleanup, { once: true });
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
},
|
|
201
|
+
},
|
|
88
202
|
};
|
|
89
203
|
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
204
|
+
* Route an inbound message through OpenClaw's agent pipeline.
|
|
205
|
+
*
|
|
206
|
+
* Uses runtime.channel.reply.finalizeInboundContext() then
|
|
207
|
+
* runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher()
|
|
208
|
+
* — same pattern as openclaw-mqtt.
|
|
92
209
|
*/
|
|
93
|
-
|
|
94
|
-
|
|
210
|
+
async function routeInboundMessage(opts) {
|
|
211
|
+
const { runtime, cfg, accountId, botIdentityId, client, msg, log } = opts;
|
|
212
|
+
const senderId = msg.senderIdentityId;
|
|
213
|
+
const groupId = msg.groupId;
|
|
214
|
+
const text = msg.plaintext;
|
|
215
|
+
log?.info?.(`[${accountId}] Quiubo: inbound from ${senderId} in group ${groupId}: ${text?.slice(0, 100)}`);
|
|
216
|
+
// Step 1: Build standardized inbound context
|
|
217
|
+
const ctxPayload = runtime.channel.reply.finalizeInboundContext({
|
|
218
|
+
Body: text,
|
|
219
|
+
RawBody: text,
|
|
220
|
+
CommandBody: text,
|
|
221
|
+
CommandAuthorized: true,
|
|
222
|
+
From: `quiubo:${senderId}`,
|
|
223
|
+
To: `quiubo:${botIdentityId}`,
|
|
224
|
+
SessionKey: `agent:main:quiubo:${groupId}`,
|
|
225
|
+
AccountId: accountId,
|
|
226
|
+
ChatType: 'group',
|
|
227
|
+
ConversationLabel: `quiubo:${groupId}`,
|
|
228
|
+
SenderName: msg.senderUsername ?? senderId,
|
|
229
|
+
SenderId: senderId,
|
|
230
|
+
Provider: 'quiubo',
|
|
231
|
+
Surface: 'quiubo',
|
|
232
|
+
MessageSid: `quiubo-${msg.messageId}`,
|
|
233
|
+
Timestamp: msg.createdAt ? new Date(msg.createdAt).getTime() : Date.now(),
|
|
234
|
+
});
|
|
235
|
+
// Step 2: Dispatch through OpenClaw's reply system
|
|
236
|
+
await runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
237
|
+
ctx: ctxPayload,
|
|
238
|
+
cfg,
|
|
239
|
+
dispatcherOptions: {
|
|
240
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
241
|
+
deliver: async (payload, info) => {
|
|
242
|
+
if (!payload.text) {
|
|
243
|
+
log?.debug?.(`[${accountId}] Quiubo: skipping empty ${info.kind} reply`);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
log?.info?.(`[${accountId}] Quiubo: delivering ${info.kind} reply [${payload.text.length} chars]`);
|
|
247
|
+
try {
|
|
248
|
+
await client.sendMessage(groupId, {
|
|
249
|
+
senderIdentityId: botIdentityId,
|
|
250
|
+
plaintext: payload.text,
|
|
251
|
+
});
|
|
252
|
+
log?.info?.(`[${accountId}] Quiubo: reply sent to group ${groupId}`);
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
log?.error?.(`[${accountId}] Quiubo: failed to send reply: ${error}`);
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
259
|
+
onSkip: (_payload, info) => {
|
|
260
|
+
log?.debug?.(`[${accountId}] Quiubo: skipped reply (${info.reason})`);
|
|
261
|
+
},
|
|
262
|
+
onError: (err, info) => {
|
|
263
|
+
log?.error?.(`[${accountId}] Quiubo: ${info.kind} reply error: ${err}`);
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
replyOptions: {
|
|
267
|
+
disableBlockStreaming: true,
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
log?.info?.(`[${accountId}] Quiubo: message processed from ${senderId}`);
|
|
95
271
|
}
|
|
96
272
|
//# sourceMappingURL=channel.js.map
|
package/dist/src/channel.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../../src/channel.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../../src/channel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polling Gateway
|
|
3
|
+
*
|
|
4
|
+
* Polls the Quiubo SDK API for new messages instead of relying on webhooks.
|
|
5
|
+
* This works for all OpenClaw installs regardless of network reachability.
|
|
6
|
+
*
|
|
7
|
+
* Each group gets its own cursor (last seen message ID) to fetch only new messages.
|
|
8
|
+
*/
|
|
9
|
+
import { QuiuboApiClient } from './api.js';
|
|
10
|
+
import type { QuiuboMessage } from './types.js';
|
|
11
|
+
export interface PollingGatewayOptions {
|
|
12
|
+
client: QuiuboApiClient;
|
|
13
|
+
botIdentityId: string;
|
|
14
|
+
/** Polling interval in ms (default: 3000) */
|
|
15
|
+
intervalMs?: number;
|
|
16
|
+
/** Called for each new inbound message (not from the bot) */
|
|
17
|
+
onMessage: (message: QuiuboMessage, groupId: string) => void | Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export declare class PollingGateway {
|
|
20
|
+
private client;
|
|
21
|
+
private botIdentityId;
|
|
22
|
+
private intervalMs;
|
|
23
|
+
private onMessage;
|
|
24
|
+
/** Per-group cursor: last seen message ID */
|
|
25
|
+
private cursors;
|
|
26
|
+
private timer;
|
|
27
|
+
private polling;
|
|
28
|
+
constructor(opts: PollingGatewayOptions);
|
|
29
|
+
/**
|
|
30
|
+
* Start polling all groups owned by this SDK app.
|
|
31
|
+
*/
|
|
32
|
+
start(): void;
|
|
33
|
+
/**
|
|
34
|
+
* Stop polling.
|
|
35
|
+
*/
|
|
36
|
+
stop(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Single poll cycle: list groups, then fetch new messages for each.
|
|
39
|
+
*/
|
|
40
|
+
private poll;
|
|
41
|
+
/**
|
|
42
|
+
* Fetch new messages for a single group.
|
|
43
|
+
*/
|
|
44
|
+
private pollGroup;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=polling-gateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polling-gateway.d.ts","sourceRoot":"","sources":["../../src/polling-gateway.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,eAAe,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,SAAS,EAAE,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9E;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAqC;IAEtD,6CAA6C;IAC7C,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,OAAO,CAAS;gBAEZ,IAAI,EAAE,qBAAqB;IAOvC;;OAEG;IACH,KAAK,IAAI,IAAI;IAUb;;OAEG;IACH,IAAI,IAAI,IAAI;IAQZ;;OAEG;YACW,IAAI;IAkBlB;;OAEG;YACW,SAAS;CA6BxB"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polling Gateway
|
|
3
|
+
*
|
|
4
|
+
* Polls the Quiubo SDK API for new messages instead of relying on webhooks.
|
|
5
|
+
* This works for all OpenClaw installs regardless of network reachability.
|
|
6
|
+
*
|
|
7
|
+
* Each group gets its own cursor (last seen message ID) to fetch only new messages.
|
|
8
|
+
*/
|
|
9
|
+
export class PollingGateway {
|
|
10
|
+
client;
|
|
11
|
+
botIdentityId;
|
|
12
|
+
intervalMs;
|
|
13
|
+
onMessage;
|
|
14
|
+
/** Per-group cursor: last seen message ID */
|
|
15
|
+
cursors = new Map();
|
|
16
|
+
timer = null;
|
|
17
|
+
polling = false;
|
|
18
|
+
constructor(opts) {
|
|
19
|
+
this.client = opts.client;
|
|
20
|
+
this.botIdentityId = opts.botIdentityId;
|
|
21
|
+
this.intervalMs = opts.intervalMs ?? 3000;
|
|
22
|
+
this.onMessage = opts.onMessage;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Start polling all groups owned by this SDK app.
|
|
26
|
+
*/
|
|
27
|
+
start() {
|
|
28
|
+
if (this.timer)
|
|
29
|
+
return;
|
|
30
|
+
console.log(`[Quiubo] Polling gateway started (every ${this.intervalMs}ms)`);
|
|
31
|
+
// Poll immediately, then on interval
|
|
32
|
+
this.poll();
|
|
33
|
+
this.timer = setInterval(() => this.poll(), this.intervalMs);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Stop polling.
|
|
37
|
+
*/
|
|
38
|
+
stop() {
|
|
39
|
+
if (this.timer) {
|
|
40
|
+
clearInterval(this.timer);
|
|
41
|
+
this.timer = null;
|
|
42
|
+
console.log('[Quiubo] Polling gateway stopped');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Single poll cycle: list groups, then fetch new messages for each.
|
|
47
|
+
*/
|
|
48
|
+
async poll() {
|
|
49
|
+
// Prevent overlapping poll cycles
|
|
50
|
+
if (this.polling)
|
|
51
|
+
return;
|
|
52
|
+
this.polling = true;
|
|
53
|
+
try {
|
|
54
|
+
const { groups } = await this.client.listGroups();
|
|
55
|
+
await Promise.allSettled(groups.map((group) => this.pollGroup(group.id)));
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
console.error('[Quiubo] Poll cycle failed:', error);
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
this.polling = false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Fetch new messages for a single group.
|
|
66
|
+
*/
|
|
67
|
+
async pollGroup(groupId) {
|
|
68
|
+
try {
|
|
69
|
+
const cursor = this.cursors.get(groupId);
|
|
70
|
+
const { messages } = await this.client.listMessages(groupId, cursor);
|
|
71
|
+
if (messages.length === 0)
|
|
72
|
+
return;
|
|
73
|
+
// Update cursor to the last (newest) message
|
|
74
|
+
const lastMessage = messages[messages.length - 1];
|
|
75
|
+
this.cursors.set(groupId, lastMessage.id);
|
|
76
|
+
// On first poll for a group, just set the cursor — don't replay history
|
|
77
|
+
if (!cursor)
|
|
78
|
+
return;
|
|
79
|
+
// Route new messages (skip bot's own messages)
|
|
80
|
+
for (const msg of messages) {
|
|
81
|
+
if (msg.senderIdentityId === this.botIdentityId)
|
|
82
|
+
continue;
|
|
83
|
+
if (!msg.plaintext)
|
|
84
|
+
continue;
|
|
85
|
+
try {
|
|
86
|
+
await this.onMessage(msg, groupId);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
console.error(`[Quiubo] Failed to handle message ${msg.id}:`, error);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
console.error(`[Quiubo] Failed to poll group ${groupId}:`, error);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=polling-gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polling-gateway.js","sourceRoot":"","sources":["../../src/polling-gateway.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAcH,MAAM,OAAO,cAAc;IACjB,MAAM,CAAkB;IACxB,aAAa,CAAS;IACtB,UAAU,CAAS;IACnB,SAAS,CAAqC;IAEtD,6CAA6C;IACrC,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IACpC,KAAK,GAA0C,IAAI,CAAC;IACpD,OAAO,GAAG,KAAK,CAAC;IAExB,YAAY,IAA2B;QACrC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;QACxC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC;QAC1C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO;QAEvB,OAAO,CAAC,GAAG,CAAC,2CAA2C,IAAI,CAAC,UAAU,KAAK,CAAC,CAAC;QAE7E,qCAAqC;QACrC,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/D,CAAC;IAED;;OAEG;IACH,IAAI;QACF,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,IAAI;QAChB,kCAAkC;QAClC,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QAEpB,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YAElD,MAAM,OAAO,CAAC,UAAU,CACtB,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAChD,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;QACtD,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACvB,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,SAAS,CAAC,OAAe;QACrC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACzC,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAErE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO;YAElC,6CAA6C;YAC7C,MAAM,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAClD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;YAE1C,wEAAwE;YACxE,IAAI,CAAC,MAAM;gBAAE,OAAO;YAEpB,+CAA+C;YAC/C,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;gBAC3B,IAAI,GAAG,CAAC,gBAAgB,KAAK,IAAI,CAAC,aAAa;oBAAE,SAAS;gBAC1D,IAAI,CAAC,GAAG,CAAC,SAAS;oBAAE,SAAS;gBAE7B,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;gBACrC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,OAAO,CAAC,KAAK,CAAC,qCAAqC,GAAG,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;gBACvE,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,iCAAiC,OAAO,GAAG,EAAE,KAAK,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Real-time Gateway
|
|
3
|
+
*
|
|
4
|
+
* Connects to Quiubo via Pusher WebSocket for real-time message delivery,
|
|
5
|
+
* with automatic fallback to polling when Pusher is unavailable.
|
|
6
|
+
*
|
|
7
|
+
* Architecture (same as WhatsApp/Baileys):
|
|
8
|
+
* - Primary: Persistent WebSocket via Pusher (real-time push)
|
|
9
|
+
* - Fallback: Polling listMessages API (when disconnected)
|
|
10
|
+
*
|
|
11
|
+
* The SDK app authenticates Pusher as its bot identity, subscribing to
|
|
12
|
+
* `private-user-{botIdentityId}` to receive `new-group-message` events.
|
|
13
|
+
*/
|
|
14
|
+
import { QuiuboApiClient } from './api.js';
|
|
15
|
+
export interface RealtimeGatewayOptions {
|
|
16
|
+
client: QuiuboApiClient;
|
|
17
|
+
botIdentityId: string;
|
|
18
|
+
/** Pusher config returned from SDK auth endpoint */
|
|
19
|
+
pusher?: {
|
|
20
|
+
key: string;
|
|
21
|
+
cluster: string;
|
|
22
|
+
};
|
|
23
|
+
/** Polling interval when Pusher is disconnected (default: 5000ms) */
|
|
24
|
+
pollIntervalMs?: number;
|
|
25
|
+
/** Called for each new inbound message (not from the bot) */
|
|
26
|
+
onMessage: (message: InboundMessage) => void | Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
export interface InboundMessage {
|
|
29
|
+
messageId: string;
|
|
30
|
+
groupId: string;
|
|
31
|
+
senderIdentityId: string;
|
|
32
|
+
senderUsername?: string;
|
|
33
|
+
plaintext: string;
|
|
34
|
+
createdAt: string;
|
|
35
|
+
}
|
|
36
|
+
export declare class RealtimeGateway {
|
|
37
|
+
private client;
|
|
38
|
+
private botIdentityId;
|
|
39
|
+
private onMessage;
|
|
40
|
+
private pollIntervalMs;
|
|
41
|
+
private pusherClient;
|
|
42
|
+
private pusherConfig;
|
|
43
|
+
private pusherConnected;
|
|
44
|
+
private pollTimer;
|
|
45
|
+
private polling;
|
|
46
|
+
private cursors;
|
|
47
|
+
private stopped;
|
|
48
|
+
constructor(opts: RealtimeGatewayOptions);
|
|
49
|
+
/**
|
|
50
|
+
* Start the gateway. Connects to Pusher if available, falls back to polling.
|
|
51
|
+
*/
|
|
52
|
+
start(): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Stop the gateway.
|
|
55
|
+
*/
|
|
56
|
+
stop(): void;
|
|
57
|
+
private startPusher;
|
|
58
|
+
/**
|
|
59
|
+
* Fetch a specific message and route it if it has plaintext.
|
|
60
|
+
*/
|
|
61
|
+
private fetchAndRouteMessage;
|
|
62
|
+
private stopPusher;
|
|
63
|
+
private startPolling;
|
|
64
|
+
private stopPolling;
|
|
65
|
+
private poll;
|
|
66
|
+
private pollGroup;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=realtime-gateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-gateway.d.ts","sourceRoot":"","sources":["../../src/realtime-gateway.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG3C,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,eAAe,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,oDAAoD;IACpD,MAAM,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6DAA6D;IAC7D,SAAS,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9D;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,SAAS,CAAsC;IACvD,OAAO,CAAC,cAAc,CAAS;IAG/B,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,YAAY,CAA0C;IAC9D,OAAO,CAAC,eAAe,CAAS;IAGhC,OAAO,CAAC,SAAS,CAA+C;IAChE,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAA6B;IAE5C,OAAO,CAAC,OAAO,CAAS;gBAEZ,IAAI,EAAE,sBAAsB;IAQxC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B;;OAEG;IACH,IAAI,IAAI,IAAI;YASE,WAAW;IA4EzB;;OAEG;YACW,oBAAoB;IAoBlC,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,WAAW;YAOL,IAAI;YAgBJ,SAAS;CAiCxB"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Real-time Gateway
|
|
3
|
+
*
|
|
4
|
+
* Connects to Quiubo via Pusher WebSocket for real-time message delivery,
|
|
5
|
+
* with automatic fallback to polling when Pusher is unavailable.
|
|
6
|
+
*
|
|
7
|
+
* Architecture (same as WhatsApp/Baileys):
|
|
8
|
+
* - Primary: Persistent WebSocket via Pusher (real-time push)
|
|
9
|
+
* - Fallback: Polling listMessages API (when disconnected)
|
|
10
|
+
*
|
|
11
|
+
* The SDK app authenticates Pusher as its bot identity, subscribing to
|
|
12
|
+
* `private-user-{botIdentityId}` to receive `new-group-message` events.
|
|
13
|
+
*/
|
|
14
|
+
import Pusher from 'pusher-js';
|
|
15
|
+
export class RealtimeGateway {
|
|
16
|
+
client;
|
|
17
|
+
botIdentityId;
|
|
18
|
+
onMessage;
|
|
19
|
+
pollIntervalMs;
|
|
20
|
+
// Pusher state
|
|
21
|
+
pusherClient = null;
|
|
22
|
+
pusherConfig;
|
|
23
|
+
pusherConnected = false;
|
|
24
|
+
// Polling state (fallback)
|
|
25
|
+
pollTimer = null;
|
|
26
|
+
polling = false;
|
|
27
|
+
cursors = new Map();
|
|
28
|
+
stopped = false;
|
|
29
|
+
constructor(opts) {
|
|
30
|
+
this.client = opts.client;
|
|
31
|
+
this.botIdentityId = opts.botIdentityId;
|
|
32
|
+
this.pusherConfig = opts.pusher ?? null;
|
|
33
|
+
this.pollIntervalMs = opts.pollIntervalMs ?? 5000;
|
|
34
|
+
this.onMessage = opts.onMessage;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Start the gateway. Connects to Pusher if available, falls back to polling.
|
|
38
|
+
*/
|
|
39
|
+
async start() {
|
|
40
|
+
this.stopped = false;
|
|
41
|
+
if (this.pusherConfig) {
|
|
42
|
+
await this.startPusher();
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
console.log('[Quiubo] No Pusher config — using polling only');
|
|
46
|
+
this.startPolling();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Stop the gateway.
|
|
51
|
+
*/
|
|
52
|
+
stop() {
|
|
53
|
+
this.stopped = true;
|
|
54
|
+
this.stopPolling();
|
|
55
|
+
this.stopPusher();
|
|
56
|
+
console.log('[Quiubo] Gateway stopped');
|
|
57
|
+
}
|
|
58
|
+
// ── Pusher ──────────────────────────────────────────────────────
|
|
59
|
+
async startPusher() {
|
|
60
|
+
if (!this.pusherConfig)
|
|
61
|
+
return;
|
|
62
|
+
const { key, cluster } = this.pusherConfig;
|
|
63
|
+
const apiClient = this.client;
|
|
64
|
+
const botIdentityId = this.botIdentityId;
|
|
65
|
+
this.pusherClient = new Pusher(key, {
|
|
66
|
+
cluster,
|
|
67
|
+
// Custom authorizer: uses SDK API key auth instead of JWT
|
|
68
|
+
authorizer: (channel) => ({
|
|
69
|
+
authorize: async (socketId, callback) => {
|
|
70
|
+
try {
|
|
71
|
+
const result = await apiClient.pusherAuth(socketId, channel.name, botIdentityId);
|
|
72
|
+
callback(null, result);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
console.error('[Quiubo] Pusher auth failed:', error);
|
|
76
|
+
callback(error, null);
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
}),
|
|
80
|
+
});
|
|
81
|
+
// Connection state handlers
|
|
82
|
+
this.pusherClient.connection.bind('connected', () => {
|
|
83
|
+
this.pusherConnected = true;
|
|
84
|
+
console.log('[Quiubo] Pusher connected');
|
|
85
|
+
this.stopPolling();
|
|
86
|
+
});
|
|
87
|
+
this.pusherClient.connection.bind('disconnected', () => {
|
|
88
|
+
this.pusherConnected = false;
|
|
89
|
+
console.warn('[Quiubo] Pusher disconnected — falling back to polling');
|
|
90
|
+
if (!this.stopped)
|
|
91
|
+
this.startPolling();
|
|
92
|
+
});
|
|
93
|
+
this.pusherClient.connection.bind('error', (error) => {
|
|
94
|
+
console.error('[Quiubo] Pusher error:', error);
|
|
95
|
+
});
|
|
96
|
+
// Subscribe to bot's private user channel
|
|
97
|
+
const channelName = `private-user-${this.botIdentityId}`;
|
|
98
|
+
const channel = this.pusherClient.subscribe(channelName);
|
|
99
|
+
channel.bind('pusher:subscription_succeeded', () => {
|
|
100
|
+
console.log(`[Quiubo] Subscribed to ${channelName}`);
|
|
101
|
+
});
|
|
102
|
+
channel.bind('pusher:subscription_error', (error) => {
|
|
103
|
+
console.error(`[Quiubo] Failed to subscribe to ${channelName}:`, error);
|
|
104
|
+
// Fall back to polling
|
|
105
|
+
if (!this.stopped)
|
|
106
|
+
this.startPolling();
|
|
107
|
+
});
|
|
108
|
+
// Handle incoming group messages
|
|
109
|
+
channel.bind('new-group-message', (data) => {
|
|
110
|
+
// Skip bot's own messages
|
|
111
|
+
if (data.senderId === this.botIdentityId)
|
|
112
|
+
return;
|
|
113
|
+
// For SDK groups, the message plaintext comes via the API
|
|
114
|
+
// The Pusher event carries the ciphertext (which for SDK groups is plaintext)
|
|
115
|
+
// We need to fetch the actual message to get the plaintext
|
|
116
|
+
this.fetchAndRouteMessage(data.groupId, data.messageId);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Fetch a specific message and route it if it has plaintext.
|
|
121
|
+
*/
|
|
122
|
+
async fetchAndRouteMessage(groupId, messageId) {
|
|
123
|
+
try {
|
|
124
|
+
// Fetch latest messages and find the one we want
|
|
125
|
+
const { messages } = await this.client.listMessages(groupId, undefined, 10);
|
|
126
|
+
const msg = messages.find((m) => m.id === messageId);
|
|
127
|
+
if (msg && msg.plaintext && msg.senderIdentityId !== this.botIdentityId) {
|
|
128
|
+
await this.onMessage({
|
|
129
|
+
messageId: msg.id,
|
|
130
|
+
groupId,
|
|
131
|
+
senderIdentityId: msg.senderIdentityId,
|
|
132
|
+
plaintext: msg.plaintext,
|
|
133
|
+
createdAt: msg.createdAt,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
console.error(`[Quiubo] Failed to fetch message ${messageId}:`, error);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
stopPusher() {
|
|
142
|
+
if (this.pusherClient) {
|
|
143
|
+
this.pusherClient.disconnect();
|
|
144
|
+
this.pusherClient = null;
|
|
145
|
+
this.pusherConnected = false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// ── Polling (fallback) ──────────────────────────────────────────
|
|
149
|
+
startPolling() {
|
|
150
|
+
if (this.pollTimer)
|
|
151
|
+
return;
|
|
152
|
+
console.log(`[Quiubo] Polling started (every ${this.pollIntervalMs}ms)`);
|
|
153
|
+
this.poll();
|
|
154
|
+
this.pollTimer = setInterval(() => this.poll(), this.pollIntervalMs);
|
|
155
|
+
}
|
|
156
|
+
stopPolling() {
|
|
157
|
+
if (this.pollTimer) {
|
|
158
|
+
clearInterval(this.pollTimer);
|
|
159
|
+
this.pollTimer = null;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async poll() {
|
|
163
|
+
if (this.polling || this.pusherConnected)
|
|
164
|
+
return;
|
|
165
|
+
this.polling = true;
|
|
166
|
+
try {
|
|
167
|
+
const { groups } = await this.client.listGroups();
|
|
168
|
+
await Promise.allSettled(groups.map((group) => this.pollGroup(group.id)));
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
console.error('[Quiubo] Poll cycle failed:', error);
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
this.polling = false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
async pollGroup(groupId) {
|
|
178
|
+
try {
|
|
179
|
+
const cursor = this.cursors.get(groupId);
|
|
180
|
+
const { messages } = await this.client.listMessages(groupId, cursor);
|
|
181
|
+
if (messages.length === 0)
|
|
182
|
+
return;
|
|
183
|
+
const lastMessage = messages[messages.length - 1];
|
|
184
|
+
this.cursors.set(groupId, lastMessage.id);
|
|
185
|
+
// On first poll, just set cursor — don't replay history
|
|
186
|
+
if (!cursor)
|
|
187
|
+
return;
|
|
188
|
+
for (const msg of messages) {
|
|
189
|
+
if (msg.senderIdentityId === this.botIdentityId)
|
|
190
|
+
continue;
|
|
191
|
+
if (!msg.plaintext)
|
|
192
|
+
continue;
|
|
193
|
+
try {
|
|
194
|
+
await this.onMessage({
|
|
195
|
+
messageId: msg.id,
|
|
196
|
+
groupId,
|
|
197
|
+
senderIdentityId: msg.senderIdentityId,
|
|
198
|
+
plaintext: msg.plaintext,
|
|
199
|
+
createdAt: msg.createdAt,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
console.error(`[Quiubo] Failed to handle message ${msg.id}:`, error);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
console.error(`[Quiubo] Failed to poll group ${groupId}:`, error);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=realtime-gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-gateway.js","sourceRoot":"","sources":["../../src/realtime-gateway.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quiubo PluginRuntime Singleton
|
|
3
|
+
*
|
|
4
|
+
* Stores the PluginRuntime reference provided by OpenClaw during register().
|
|
5
|
+
* Used by the channel plugin to route inbound messages through the agent pipeline.
|
|
6
|
+
*
|
|
7
|
+
* Pattern: identical to openclaw-mqtt/src/runtime.ts
|
|
8
|
+
*/
|
|
9
|
+
export declare function setQuiuboRuntime(r: any): void;
|
|
10
|
+
export declare function getQuiuboRuntime(): any;
|
|
11
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,GAAG,GAAG,IAAI,CAE7C;AAGD,wBAAgB,gBAAgB,IAAI,GAAG,CAKtC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quiubo PluginRuntime Singleton
|
|
3
|
+
*
|
|
4
|
+
* Stores the PluginRuntime reference provided by OpenClaw during register().
|
|
5
|
+
* Used by the channel plugin to route inbound messages through the agent pipeline.
|
|
6
|
+
*
|
|
7
|
+
* Pattern: identical to openclaw-mqtt/src/runtime.ts
|
|
8
|
+
*/
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
+
let runtime;
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
+
export function setQuiuboRuntime(r) {
|
|
13
|
+
runtime = r;
|
|
14
|
+
}
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
export function getQuiuboRuntime() {
|
|
17
|
+
if (!runtime) {
|
|
18
|
+
throw new Error('Quiubo runtime not initialized — register() not called yet');
|
|
19
|
+
}
|
|
20
|
+
return runtime;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,8DAA8D;AAC9D,IAAI,OAAwB,CAAC;AAE7B,8DAA8D;AAC9D,MAAM,UAAU,gBAAgB,CAAC,CAAM;IACrC,OAAO,GAAG,CAAC,CAAC;AACd,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/src/types.d.ts
CHANGED
|
@@ -10,8 +10,8 @@ export interface QuiuboAccountConfig {
|
|
|
10
10
|
apiUrl: string;
|
|
11
11
|
apiKey: string;
|
|
12
12
|
botIdentityId: string;
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
/** Polling interval in ms (default: 3000) */
|
|
14
|
+
pollIntervalMs?: number;
|
|
15
15
|
}
|
|
16
16
|
export interface QuiuboGroup {
|
|
17
17
|
id: string;
|
|
@@ -36,6 +36,10 @@ export interface QuiuboAuthResponse {
|
|
|
36
36
|
appId: string;
|
|
37
37
|
appName: string;
|
|
38
38
|
authenticated: boolean;
|
|
39
|
+
pusher?: {
|
|
40
|
+
key: string;
|
|
41
|
+
cluster: string;
|
|
42
|
+
};
|
|
39
43
|
}
|
|
40
44
|
export interface QuiuboIdentity {
|
|
41
45
|
identityId: string;
|
package/dist/src/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,YAAY,GAAG,UAAU,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,kBAAkB,GAAG,4BAA4B,CAAC;CACzD;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB"}
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-quiubo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "OpenClaw Quiubo channel plugin — chat with AI assistants through Quiubo",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -33,6 +33,11 @@
|
|
|
33
33
|
"typescript": "^5.7.2"
|
|
34
34
|
},
|
|
35
35
|
"openclaw": {
|
|
36
|
-
"extensions": [
|
|
36
|
+
"extensions": [
|
|
37
|
+
"./dist/index.js"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"pusher-js": "^8.4.0"
|
|
37
42
|
}
|
|
38
43
|
}
|