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 CHANGED
@@ -1,69 +1,25 @@
1
1
  /**
2
2
  * Quiubo OpenClaw Extension — Entry Point
3
3
  *
4
- * Registers the Quiubo channel plugin with gateway lifecycle (webhook server)
5
- * and routes inbound messages to OpenClaw's agent via api.ingest().
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, getQuiuboClient } from './src/channel.js';
9
- export { startWebhookServer } from './src/webhook-handler.js';
10
- export type { QuiuboAccountConfig, QuiuboGroup, QuiuboMessage, QuiuboIdentity, QuiuboJoinToken, WebhookPayload, WebhookMessageData, WebhookJoinTokenRedeemedData, } from './src/types.js';
11
- interface OpenClawApi {
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: typeof pluginWithGateway;
15
+ plugin: any;
14
16
  }) => void;
15
- ingest: (message: Record<string, any>) => Promise<void>;
16
17
  }
17
- /**
18
- * Plugin with gateway lifecycle wired in.
19
- */
20
- declare const pluginWithGateway: {
21
- gateway: {
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
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,YAAY,EACV,mBAAmB,EACnB,WAAW,EACX,aAAa,EACb,cAAc,EACd,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,4BAA4B,GAC7B,MAAM,gBAAgB,CAAC;AAMxB,UAAU,WAAW;IACnB,eAAe,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,OAAO,iBAAiB,CAAA;KAAE,KAAK,IAAI,CAAC;IAEtE,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD;AAsCD;;GAEG;AACH,QAAA,MAAM,iBAAiB;;QAInB;;;WAGG;qBAEgB;YAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAAC,SAAS,CAAC,EAAE,MAAM,CAAA;SAAE,OAAO,WAAW;QAmCxF;;;WAGG;;;;;;;;;;;;;;;;;;;;;;kBAvCuD,CAAC;;;;;CAgD9D,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,WAAW,QAEhD"}
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
- * Registers the Quiubo channel plugin with gateway lifecycle (webhook server)
5
- * and routes inbound messages to OpenClaw's agent via api.ingest().
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, getQuiuboClient } from './src/channel.js';
12
- export { startWebhookServer } from './src/webhook-handler.js';
13
- // Track webhook server instance for cleanup
14
- let webhookServer = null;
15
- /**
16
- * Handle inbound webhook messages and route to OpenClaw agent.
17
- */
18
- async function handleInboundMessage(api, payload,
19
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
- account) {
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,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAI9D,0BAA0B;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAY9D,4CAA4C;AAC5C,IAAI,aAAa,GAAkB,IAAI,CAAC;AASxC;;GAEG;AACH,KAAK,UAAU,oBAAoB,CACjC,GAAgB,EAChB,OAAuB;AACvB,8DAA8D;AAC9D,OAA4B;IAE5B,IAAI,OAAO,CAAC,KAAK,KAAK,uBAAuB,EAAE,CAAC;QAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;QAC7B,IAAI,CAAC,CAAC,kBAAkB,IAAI,OAAO,CAAC;YAAE,OAAO;QAE7C,MAAM,OAAO,GAAG;YACd,OAAO,EAAE,QAAQ;YACjB,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,SAAS;YACzC,QAAQ,EAAE,OAAgB;YAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,QAAQ,EAAE,OAAO,CAAC,gBAAgB;YAClC,UAAU,EAAE,OAAO,CAAC,cAAc,IAAI,OAAO,CAAC,gBAAgB;YAC9D,IAAI,EAAE,OAAO,CAAC,SAAS;YACvB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YACjF,GAAG,EAAE,OAAO;SACb,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,KAAK,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,4BAA4B,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,iBAAiB,GAAG;IACxB,GAAG,YAAY;IAEf,OAAO,EAAE;QACP;;;WAGG;QACH,8DAA8D;QAC9D,KAAK,EAAE,KAAK,EAAE,GAAwD,EAAE,GAAgB,EAAE,EAAE;YAC1F,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC;YAElC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,QAEO,CAAC;YAClD,MAAM,OAAO,GAAG,QAAQ,EAAE,CAAC,SAAS,IAAI,SAAS,CAAC,CAAC;YACnD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;gBAC1E,OAAO;YACT,CAAC;YAED,MAAM,WAAW,GAAI,OAAO,CAAC,WAAsB,IAAI,IAAI,CAAC;YAC5D,MAAM,aAAa,GAAG,OAAO,CAAC,aAAmC,CAAC;YAClE,MAAM,aAAa,GAAG,OAAO,CAAC,aAAmC,CAAC;YAElE,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnB,OAAO,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;gBACtE,OAAO;YACT,CAAC;YAED,IAAI,CAAC;gBACH,aAAa,GAAG,MAAM,kBAAkB,CAAC;oBACvC,IAAI,EAAE,WAAW;oBACjB,aAAa;oBACb,aAAa;oBACb,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;wBAC3B,MAAM,oBAAoB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;oBACpD,CAAC;iBACF,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,0CAA0C,EAAE,KAAK,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;QAED;;;WAGG;QACH,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,IAAI,aAAa,EAAE,CAAC;gBAClB,aAAa,CAAC,KAAK,EAAE,CAAC;gBACtB,aAAa,GAAG,IAAI,CAAC;gBACrB,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;KACF;CACF,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAgB;IAC/C,GAAG,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;AACrD,CAAC"}
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
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/api.ts"],"names":[],"mappings":"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"}
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
@@ -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":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAMpC,MAAM,OAAO,eAAe;IAClB,OAAO,CAAS;IAChB,MAAM,CAAS;IAEvB,YAAY,OAAe,EAAE,MAAc;QACzC,wBAAwB;QACxB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAEO,KAAK,CAAC,OAAO,CACnB,MAAc,EACd,IAAY,EACZ,IAAc;QAEd,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,UAAU,IAAI,EAAE,CAAC;QAC5C,MAAM,OAAO,GAA2B;YACtC,eAAe,EAAE,IAAI,CAAC,MAAM;YAC5B,cAAc,EAAE,kBAAkB;SACnC,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM;YACN,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;SAC9C,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,MAAM,SAAS,EAAE,CAAC,CAAC;QAChG,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,EAAgB,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY;QAChB,OAAO,IAAI,CAAC,OAAO,CAAqB,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3D,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CACf,OAAe,EACf,IAIC;QAED,OAAO,IAAI,CAAC,OAAO,CAAgB,MAAM,EAAE,WAAW,OAAO,WAAW,EAAE;YACxE,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;YACvC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,eAAe,EAAE,IAAI,CAAC,eAAe,IAAI,UAAU,EAAE;SACtD,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY,CAChB,OAAe,EACf,cAAuB,EACvB,KAAK,GAAG,EAAE;QAEV,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC7D,IAAI,cAAc,EAAE,CAAC;YACnB,MAAM,CAAC,GAAG,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,WAAW,OAAO,aAAa,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACjF,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,IAIjB;QACC,OAAO,IAAI,CAAC,OAAO,CAAc,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;IAC5D,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,OAAe,EAAE,WAAqB;QACrD,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,OAAO,UAAU,EAAE;YACvD,WAAW;YACX,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CAAC,OAAe,EAAE,WAAqB;QACxD,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,OAAO,UAAU,EAAE;YACvD,WAAW;YACX,MAAM,EAAE,QAAQ;SACjB,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ,CAAC,OAAe;QAC5B,OAAO,IAAI,CAAC,OAAO,CAAc,KAAK,EAAE,WAAW,OAAO,EAAE,CAAC,CAAC;IAChE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CAAC,IAItB;QAOC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;IACjD,CAAC;IAED,2EAA2E;IAC3E,sBAAsB;IACtB,2EAA2E;IAE3E;;OAEG;IACH,KAAK,CAAC,cAAc,CAAC,IAIpB;QACC,OAAO,IAAI,CAAC,OAAO,CAAiB,MAAM,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;IACnE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAAC,UAAkB;QACrC,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,eAAe,UAAU,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,2EAA2E;IAC3E,wBAAwB;IACxB,2EAA2E;IAE3E;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,IASrB;QACC,OAAO,IAAI,CAAC,OAAO,CAAkB,MAAM,EAAE,cAAc,EAAE,IAAI,CAAC,CAAC;IACrE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,OAAe;QACnC,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,gBAAgB,OAAO,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,2EAA2E;IAC3E,cAAc;IACd,2EAA2E;IAE3E;;OAEG;IACH,KAAK,CAAC,UAAU,CACd,QAAgB,EAChB,WAAmB,EACnB,UAAkB;QAElB,OAAO,IAAI,CAAC,OAAO,CAAmB,MAAM,EAAE,cAAc,EAAE;YAC5D,SAAS,EAAE,QAAQ;YACnB,YAAY,EAAE,WAAW;YACzB,WAAW,EAAE,UAAU;SACxB,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -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
- import { QuiuboApiClient } from './api.js';
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;;;;;;;GAOG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAatD;;;;;GAKG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;4BAeD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE;4BAQ/C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,cAChB,MAAM,GACjB,mBAAmB;;;;mCAwBW;YAC/B,IAAI,EAAE,MAAM,CAAC;YAEb,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;SAC9B,GAAG,OAAO,CAAC;YAAE,EAAE,EAAE,OAAO,CAAA;SAAE,CAAC;;CA4B/B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,eAAe,IAAI,eAAe,GAAG,IAAI,CAExD"}
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAiBH,eAAO,MAAM,YAAY,EAAE,GA6M1B,CAAC"}
@@ -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
- // Module-level client, initialised lazily per-account
11
- let _client = null;
12
- let _account = null;
13
- function getClient() {
14
- if (!_client || !_account) {
15
- throw new Error('Quiubo plugin: no account resolved — call resolveAccount first');
16
- }
17
- return _client;
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: { chatTypes: ['group'] },
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 channels = cfg.channels;
39
- const quiubo = channels?.quiubo;
40
- const accounts = quiubo?.accounts;
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
- // Initialise the API client for this account
52
+ const resolved = { ...account, accountId: id };
53
+ // Cache client + config for outbound use
53
54
  const apiUrl = account.apiUrl ?? 'https://api.quiubo.io';
54
- _client = new QuiuboApiClient(apiUrl, account.apiKey);
55
- _account = { ...account, accountId: id };
56
- return _account;
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
- async sendText({ text, target }) {
63
- const client = getClient();
64
- // Get groupId from target (set during inbound routing)
65
- const groupId = target?.groupId ?? target?.raw?.groupId;
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
- console.error('[Quiubo] sendText: no groupId in target');
68
- return { ok: false };
89
+ return { ok: false, error: 'No groupId in outbound context' };
69
90
  }
70
- const senderId = _account?.botIdentityId;
91
+ const senderId = account.botIdentityId;
71
92
  if (!senderId) {
72
- console.error('[Quiubo] sendText: no botIdentityId configured');
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
- console.error('[Quiubo] sendText failed:', error);
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
- * Get the current API client (for webhook handler and other plumbing).
91
- * Returns null if no account has been resolved yet.
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
- export function getQuiuboClient() {
94
- return _client;
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
@@ -1 +1 @@
1
- {"version":3,"file":"channel.js","sourceRoot":"","sources":["../../src/channel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"channel.js","sourceRoot":"","sources":["../../src/channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD,wDAAwD;AACxD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;AAEpD,kDAAkD;AAClD,MAAM,OAAO,GAAG,IAAI,GAAG,EAA2B,CAAC;AAEnD,8CAA8C;AAC9C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA+B,CAAC;AAExD,8DAA8D;AAC9D,MAAM,CAAC,MAAM,YAAY,GAAQ;IAC/B,EAAE,EAAE,QAAiB;IAErB,IAAI,EAAE;QACJ,EAAE,EAAE,QAAQ;QACZ,KAAK,EAAE,QAAQ;QACf,cAAc,EAAE,cAAc;QAC9B,KAAK,EAAE,2CAA2C;QAClD,OAAO,EAAE,CAAC,IAAI,CAAC;KAChB;IAED,YAAY,EAAE;QACZ,SAAS,EAAE,CAAC,OAAO,CAAU;QAC7B,aAAa,EAAE,KAAK;QACpB,iBAAiB,EAAE,KAAK;QACxB,eAAe,EAAE,KAAK;KACvB;IAED,mEAAmE;IACnE,MAAM,EAAE;QACN,8DAA8D;QAC9D,cAAc,CAAC,GAAQ;YACrB,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC;YACpC,IAAI,CAAC,MAAM,EAAE,QAAQ;gBAAE,OAAO,EAAE,CAAC;YACjC,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACtC,CAAC;QAED,8DAA8D;QAC9D,cAAc,CAAC,GAAQ,EAAE,SAAkB;YACzC,MAAM,EAAE,GAAG,SAAS,IAAI,SAAS,CAAC;YAClC,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAoC,CAAC;YAExF,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,EAAE,SAAS,EAAE,EAAE,EAAyB,CAAC;YAClD,CAAC;YAED,MAAM,QAAQ,GAAG,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;YAE/C,yCAAyC;YACzC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,uBAAuB,CAAC;YACzD,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YAC7D,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;YAE3B,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,8DAA8D;QAC9D,SAAS,EAAE,CAAC,OAAY,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;QACpD,8DAA8D;QAC9D,YAAY,EAAE,CAAC,OAAY,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC;KACjF;IAED,mEAAmE;IACnE,QAAQ,EAAE;QACR,YAAY,EAAE,QAAiB;QAE/B,8DAA8D;QAC9D,KAAK,CAAC,QAAQ,CAAC,GAAQ;YACrB,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;YAE1B,2BAA2B;YAC3B,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,IAAI,SAAS,CAAC;YAC7C,IAAI,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACpC,IAAI,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAEtC,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;gBACxB,yBAAyB;gBACzB,MAAM,MAAM,GAAG,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,SAAS,CAAoC,CAAC;gBAC/F,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;oBACpB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC;gBACzD,CAAC;gBACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,uBAAuB,CAAC;gBACxD,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;gBACpD,OAAO,GAAG,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,CAAC;gBACnC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;gBAC/B,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACnC,CAAC;YAED,qEAAqE;YACrE,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,MAAM,EAAE,OAAO,IAAI,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC;YAC1E,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,gCAAgC,EAAE,CAAC;YAChE,CAAC;YAED,MAAM,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC;YACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,6BAA6B,EAAE,CAAC;YAC7D,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE;oBAChC,gBAAgB,EAAE,QAAQ;oBAC1B,SAAS,EAAE,IAAI;iBAChB,CAAC,CAAC;gBACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;YACtB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACnE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;YACnC,CAAC;QACH,CAAC;KACF;IAED,mEAAmE;IACnE,OAAO,EAAE;QACP;;;;;;;;;WASG;QACH,8DAA8D;QAC9D,YAAY,EAAE,KAAK,EAAE,GAAQ,EAAiB,EAAE;YAC9C,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;YAEjD,MAAM,YAAY,GAAG,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,SAAS,CAAoC,CAAC;YACpG,IAAI,CAAC,YAAY,EAAE,MAAM,IAAI,CAAC,YAAY,EAAE,aAAa,EAAE,CAAC;gBAC1D,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,SAAS,qDAAqD,CAAC,CAAC;gBAChF,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,IAAI,uBAAuB,CAAC;YAC9D,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,GAAG,YAAY,CAAC;YAE/D,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;YAEnC,uEAAuE;YACvE,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,SAAS,2BAA2B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACvF,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACpB,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,SAAS,mCAAmC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACvG,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;oBAC1B,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,SAAS,yCAAyC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACrH,CAAC;YACH,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAEnD,qBAAqB;YACrB,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAC/B,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,GAAG,YAAY,EAAE,SAAS,EAAE,CAAC,CAAC;YAExD,qCAAqC;YACrC,IAAI,YAA0D,CAAC;YAC/D,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,YAAY,EAAE,CAAC;gBACzC,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC;gBAC3B,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,SAAS,8BAA8B,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;gBACvF,IAAI,YAAY,EAAE,CAAC;oBACjB,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,SAAS,wCAAwC,YAAY,CAAC,OAAO,GAAG,CAAC,CAAC;gBAC5F,CAAC;qBAAM,CAAC;oBACN,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,SAAS,iDAAiD,CAAC,CAAC;gBAC9E,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,GAAG,EAAE,KAAK,EAAE,CAAC,IAAI,SAAS,oCAAoC,KAAK,EAAE,CAAC,CAAC;gBACvE,OAAO;YACT,CAAC;YAED,+CAA+C;YAC/C,MAAM,OAAO,GAAG,IAAI,eAAe,CAAC;gBAClC,MAAM;gBACN,aAAa;gBACb,MAAM,EAAE,YAAY;gBACpB,cAAc,EAAE,cAAc,IAAI,IAAI;gBACtC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;oBACvB,IAAI,CAAC;wBACH,MAAM,mBAAmB,CAAC;4BACxB,OAAO;4BACP,GAAG;4BACH,SAAS;4BACT,aAAa;4BACb,MAAM;4BACN,GAAG;4BACH,GAAG;yBACJ,CAAC,CAAC;oBACL,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,GAAG,EAAE,KAAK,EAAE,CAAC,IAAI,SAAS,qCAAqC,KAAK,EAAE,CAAC,CAAC;oBAC1E,CAAC;gBACH,CAAC;aACF,CAAC,CAAC;YAEH,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACjC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;YAEtB,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,SAAS,2BAA2B,CAAC,CAAC;YAEtD,wEAAwE;YACxE,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBACnC,MAAM,OAAO,GAAG,GAAG,EAAE;oBACnB,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,SAAS,4BAA4B,CAAC,CAAC;oBACvD,OAAO,CAAC,IAAI,EAAE,CAAC;oBACf,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;oBAC3B,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;oBAC1B,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;oBAC3B,OAAO,EAAE,CAAC;gBACZ,CAAC,CAAC;gBAEF,IAAI,WAAW,EAAE,CAAC;oBAChB,WAAW,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBACjE,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;KACF;CACF,CAAC;AAEF;;;;;;GAMG;AACH,KAAK,UAAU,mBAAmB,CAAC,IAYlC;IACC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAE1E,MAAM,QAAQ,GAAG,GAAG,CAAC,gBAAgB,CAAC;IACtC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;IAC5B,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,CAAC;IAE3B,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,SAAS,0BAA0B,QAAQ,aAAa,OAAO,KAAK,IAAI,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAE3G,6CAA6C;IAC7C,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC;QAC9D,IAAI,EAAE,IAAI;QACV,OAAO,EAAE,IAAI;QACb,WAAW,EAAE,IAAI;QACjB,iBAAiB,EAAE,IAAI;QACvB,IAAI,EAAE,UAAU,QAAQ,EAAE;QAC1B,EAAE,EAAE,UAAU,aAAa,EAAE;QAC7B,UAAU,EAAE,qBAAqB,OAAO,EAAE;QAC1C,SAAS,EAAE,SAAS;QACpB,QAAQ,EAAE,OAAO;QACjB,iBAAiB,EAAE,UAAU,OAAO,EAAE;QACtC,UAAU,EAAE,GAAG,CAAC,cAAc,IAAI,QAAQ;QAC1C,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,QAAQ;QACjB,UAAU,EAAE,UAAU,GAAG,CAAC,SAAS,EAAE;QACrC,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;KAC1E,CAAC,CAAC;IAEH,mDAAmD;IACnD,MAAM,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC;QACnE,GAAG,EAAE,UAAU;QACf,GAAG;QACH,iBAAiB,EAAE;YACjB,8DAA8D;YAC9D,OAAO,EAAE,KAAK,EAAE,OAAuC,EAAE,IAAsB,EAAE,EAAE;gBACjF,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;oBAClB,GAAG,EAAE,KAAK,EAAE,CAAC,IAAI,SAAS,4BAA4B,IAAI,CAAC,IAAI,QAAQ,CAAC,CAAC;oBACzE,OAAO;gBACT,CAAC;gBAED,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,SAAS,wBAAwB,IAAI,CAAC,IAAI,WAAW,OAAO,CAAC,IAAI,CAAC,MAAM,SAAS,CAAC,CAAC;gBAEnG,IAAI,CAAC;oBACH,MAAM,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE;wBAChC,gBAAgB,EAAE,aAAa;wBAC/B,SAAS,EAAE,OAAO,CAAC,IAAI;qBACxB,CAAC,CAAC;oBACH,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,SAAS,iCAAiC,OAAO,EAAE,CAAC,CAAC;gBACvE,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,GAAG,EAAE,KAAK,EAAE,CAAC,IAAI,SAAS,mCAAmC,KAAK,EAAE,CAAC,CAAC;gBACxE,CAAC;YACH,CAAC;YACD,8DAA8D;YAC9D,MAAM,EAAE,CAAC,QAAa,EAAE,IAAwB,EAAE,EAAE;gBAClD,GAAG,EAAE,KAAK,EAAE,CAAC,IAAI,SAAS,4BAA4B,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;YACxE,CAAC;YACD,OAAO,EAAE,CAAC,GAAU,EAAE,IAAsB,EAAE,EAAE;gBAC9C,GAAG,EAAE,KAAK,EAAE,CAAC,IAAI,SAAS,aAAa,IAAI,CAAC,IAAI,iBAAiB,GAAG,EAAE,CAAC,CAAC;YAC1E,CAAC;SACF;QACD,YAAY,EAAE;YACZ,qBAAqB,EAAE,IAAI;SAC5B;KACF,CAAC,CAAC;IAEH,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,SAAS,oCAAoC,QAAQ,EAAE,CAAC,CAAC;AAC3E,CAAC"}
@@ -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":"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"}
@@ -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"}
@@ -10,8 +10,8 @@ export interface QuiuboAccountConfig {
10
10
  apiUrl: string;
11
11
  apiKey: string;
12
12
  botIdentityId: string;
13
- webhookSecret?: string;
14
- webhookPort?: number;
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;
@@ -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,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;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;CACxB;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"}
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"}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "openclaw-quiubo",
3
3
  "name": "Quiubo",
4
- "version": "0.3.0",
4
+ "version": "0.5.0",
5
5
  "channels": ["quiubo"],
6
6
  "configSchema": {
7
7
  "type": "object",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-quiubo",
3
- "version": "0.3.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": ["./dist/index.js"]
36
+ "extensions": [
37
+ "./dist/index.js"
38
+ ]
39
+ },
40
+ "dependencies": {
41
+ "pusher-js": "^8.4.0"
37
42
  }
38
43
  }