openclaw-quiubo 0.4.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,70 +1,25 @@
1
1
  /**
2
2
  * Quiubo OpenClaw Extension — Entry Point
3
3
  *
4
- * Registers the Quiubo channel plugin with a real-time gateway:
5
- * - Primary: Pusher WebSocket (real-time push, like WhatsApp/Baileys)
6
- * - Fallback: Polling listMessages API (when Pusher disconnects)
7
- *
8
- * On startup, authenticates with the SDK API to get Pusher credentials,
9
- * then connects as the bot identity for real-time message delivery.
4
+ * Object-based plugin registration (matching openclaw-mqtt pattern).
5
+ * Stores the PluginRuntime reference and registers the channel plugin.
10
6
  */
11
- import type { QuiuboAccountConfig } from './src/types.js';
12
7
  export { QuiuboApiClient } from './src/api.js';
13
- export { quiuboPlugin, getQuiuboClient } from './src/channel.js';
8
+ export { quiuboPlugin } from './src/channel.js';
14
9
  export { RealtimeGateway } from './src/realtime-gateway.js';
15
10
  export { PollingGateway } from './src/polling-gateway.js';
16
11
  export type { QuiuboAccountConfig, QuiuboGroup, QuiuboMessage, QuiuboIdentity, QuiuboJoinToken, QuiuboAuthResponse, WebhookPayload, WebhookMessageData, WebhookJoinTokenRedeemedData, } from './src/types.js';
17
- interface OpenClawApi {
12
+ interface OpenClawPluginApi {
13
+ runtime: unknown;
18
14
  registerChannel: (opts: {
19
- plugin: typeof pluginWithGateway;
15
+ plugin: any;
20
16
  }) => void;
21
- ingest: (message: Record<string, any>) => Promise<void>;
22
17
  }
23
- /**
24
- * Plugin with gateway lifecycle wired in.
25
- */
26
- declare const pluginWithGateway: {
27
- gateway: {
28
- /**
29
- * Called when the gateway starts.
30
- * Authenticates, gets Pusher config, connects real-time.
31
- */
32
- start: (ctx: {
33
- config: Record<string, any>;
34
- accountId?: string;
35
- }, api: OpenClawApi) => Promise<void>;
36
- /**
37
- * Called when the gateway stops.
38
- */
39
- stop: () => Promise<void>;
40
- };
41
- id: "quiubo";
42
- meta: {
43
- id: string;
44
- label: string;
45
- selectionLabel: string;
46
- blurb: string;
47
- aliases: string[];
48
- };
49
- capabilities: {
50
- chatTypes: readonly ["group"];
51
- };
52
- config: {
53
- listAccountIds(cfg: Record<string, unknown>): string[];
54
- resolveAccount(cfg: Record<string, unknown>, accountId?: string): QuiuboAccountConfig;
55
- };
56
- outbound: {
57
- deliveryMode: "direct";
58
- sendText({ text, target }: {
59
- text: string;
60
- target?: Record<string, any>;
61
- }): Promise<{
62
- ok: boolean;
63
- }>;
64
- };
18
+ declare const plugin: {
19
+ id: string;
20
+ name: string;
21
+ description: string;
22
+ register(api: OpenClawPluginApi): void;
65
23
  };
66
- /**
67
- * OpenClaw plugin entry point.
68
- */
69
- export default function register(api: OpenClawApi): void;
24
+ export default plugin;
70
25
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAG1D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACjE,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;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;AAED;;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;QA2DxF;;WAEG;;;;;;;;;;;;;;;;;;;;;;kBAzCO,CAAC;;;;;CAiDd,CAAC;AAEF;;GAEG;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,101 +1,24 @@
1
1
  /**
2
2
  * Quiubo OpenClaw Extension — Entry Point
3
3
  *
4
- * Registers the Quiubo channel plugin with a real-time gateway:
5
- * - Primary: Pusher WebSocket (real-time push, like WhatsApp/Baileys)
6
- * - Fallback: Polling listMessages API (when Pusher disconnects)
7
- *
8
- * On startup, authenticates with the SDK API to get Pusher credentials,
9
- * then connects as the bot identity for real-time message delivery.
4
+ * Object-based plugin registration (matching openclaw-mqtt pattern).
5
+ * Stores the PluginRuntime reference and registers the channel plugin.
10
6
  */
11
- import { QuiuboApiClient } from './src/api.js';
7
+ import { setQuiuboRuntime } from './src/runtime.js';
12
8
  import { quiuboPlugin } from './src/channel.js';
13
- import { RealtimeGateway } from './src/realtime-gateway.js';
14
9
  // Re-export for consumers
15
10
  export { QuiuboApiClient } from './src/api.js';
16
- export { quiuboPlugin, getQuiuboClient } from './src/channel.js';
11
+ export { quiuboPlugin } from './src/channel.js';
17
12
  export { RealtimeGateway } from './src/realtime-gateway.js';
18
13
  export { PollingGateway } from './src/polling-gateway.js';
19
- // Track gateway instance for cleanup
20
- let gateway = null;
21
- /**
22
- * Plugin with gateway lifecycle wired in.
23
- */
24
- const pluginWithGateway = {
25
- ...quiuboPlugin,
26
- gateway: {
27
- /**
28
- * Called when the gateway starts.
29
- * Authenticates, gets Pusher config, connects real-time.
30
- */
31
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
32
- start: async (ctx, api) => {
33
- const { config, accountId } = ctx;
34
- const accounts = config.channels?.quiubo?.accounts;
35
- const account = accounts?.[accountId ?? 'default'];
36
- if (!account) {
37
- console.warn('[Quiubo] No account config found, skipping gateway');
38
- return;
39
- }
40
- const { apiUrl, apiKey, botIdentityId, pollIntervalMs } = account;
41
- if (!apiKey || !botIdentityId) {
42
- console.error('[Quiubo] apiKey and botIdentityId are required in account config');
43
- return;
44
- }
45
- const client = new QuiuboApiClient(apiUrl ?? 'https://api.quiubo.io', apiKey);
46
- // Authenticate and get Pusher config
47
- let pusherConfig;
48
- try {
49
- const auth = await client.authenticate();
50
- pusherConfig = auth.pusher;
51
- console.log(`[Quiubo] Authenticated as ${auth.appName} (${auth.appId})`);
52
- if (pusherConfig) {
53
- console.log(`[Quiubo] Pusher available (cluster: ${pusherConfig.cluster})`);
54
- }
55
- else {
56
- console.log('[Quiubo] Pusher not configured on server — using polling');
57
- }
58
- }
59
- catch (error) {
60
- console.error('[Quiubo] Authentication failed:', error);
61
- return;
62
- }
63
- gateway = new RealtimeGateway({
64
- client,
65
- botIdentityId,
66
- pusher: pusherConfig,
67
- pollIntervalMs: pollIntervalMs ?? 5000,
68
- onMessage: async (msg) => {
69
- await api.ingest({
70
- channel: 'quiubo',
71
- accountId: accountId ?? 'default',
72
- chatType: 'group',
73
- groupId: msg.groupId,
74
- senderId: msg.senderIdentityId,
75
- senderName: msg.senderUsername ?? msg.senderIdentityId,
76
- text: msg.plaintext,
77
- messageId: msg.messageId,
78
- timestamp: msg.createdAt ? new Date(msg.createdAt).getTime() : Date.now(),
79
- });
80
- },
81
- });
82
- await gateway.start();
83
- },
84
- /**
85
- * Called when the gateway stops.
86
- */
87
- stop: async () => {
88
- if (gateway) {
89
- gateway.stop();
90
- gateway = null;
91
- }
92
- },
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 });
93
21
  },
94
22
  };
95
- /**
96
- * OpenClaw plugin entry point.
97
- */
98
- export default function register(api) {
99
- api.registerChannel({ plugin: pluginWithGateway });
100
- }
23
+ export default plugin;
101
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":"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"}
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"}
@@ -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":"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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"}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "openclaw-quiubo",
3
3
  "name": "Quiubo",
4
- "version": "0.4.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.4.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",