openclaw-openagent 1.0.1 → 1.0.3

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.
Files changed (188) hide show
  1. package/dist/index.d.ts +25 -0
  2. package/dist/index.js +105 -0
  3. package/dist/src/app/channel-tools.d.ts +28 -0
  4. package/dist/src/app/channel-tools.js +251 -0
  5. package/dist/src/app/discovery-tools.d.ts +35 -0
  6. package/dist/src/app/discovery-tools.js +243 -0
  7. package/dist/src/app/download-file-tool.d.ts +10 -0
  8. package/dist/src/app/download-file-tool.js +104 -0
  9. package/dist/src/app/hooks.d.ts +14 -0
  10. package/dist/src/app/hooks.js +118 -0
  11. package/dist/src/app/index.d.ts +13 -0
  12. package/dist/src/app/index.js +44 -0
  13. package/dist/src/app/messaging-tools.d.ts +11 -0
  14. package/dist/src/app/messaging-tools.js +79 -0
  15. package/dist/src/app/ops-tools.d.ts +21 -0
  16. package/dist/src/app/ops-tools.js +158 -0
  17. package/dist/src/app/remote-agent-tool.d.ts +27 -0
  18. package/dist/src/app/remote-agent-tool.js +461 -0
  19. package/dist/src/app/types.d.ts +61 -0
  20. package/dist/src/app/types.js +11 -0
  21. package/dist/src/app/upload-file-tool.d.ts +16 -0
  22. package/dist/src/app/upload-file-tool.js +353 -0
  23. package/dist/src/app/verbose-preflight.d.ts +2 -0
  24. package/dist/src/app/verbose-preflight.js +145 -0
  25. package/dist/src/auth/config.d.ts +79 -0
  26. package/dist/src/auth/config.js +133 -0
  27. package/dist/src/auth/credential-manager.d.ts +65 -0
  28. package/dist/src/auth/credential-manager.js +122 -0
  29. package/dist/src/auth/index.d.ts +6 -0
  30. package/dist/src/auth/index.js +6 -0
  31. package/dist/src/auth/verify.d.ts +42 -0
  32. package/dist/src/auth/verify.js +60 -0
  33. package/dist/src/channel.d.ts +269 -0
  34. package/dist/src/channel.js +488 -0
  35. package/dist/src/compat.d.ts +37 -0
  36. package/dist/src/compat.js +70 -0
  37. package/dist/src/config/config-schema.d.ts +56 -0
  38. package/dist/src/config/config-schema.js +34 -0
  39. package/dist/src/messaging/aggregator.d.ts +25 -0
  40. package/dist/src/messaging/aggregator.js +90 -0
  41. package/dist/src/messaging/collector.d.ts +27 -0
  42. package/dist/src/messaging/collector.js +76 -0
  43. package/dist/src/messaging/executor.d.ts +14 -0
  44. package/dist/src/messaging/executor.js +59 -0
  45. package/dist/src/messaging/inbound.d.ts +97 -0
  46. package/dist/src/messaging/inbound.js +63 -0
  47. package/dist/src/messaging/index.d.ts +10 -0
  48. package/dist/src/messaging/index.js +9 -0
  49. package/dist/src/messaging/mention-protocol.d.ts +42 -0
  50. package/dist/src/messaging/mention-protocol.js +74 -0
  51. package/dist/src/messaging/process-c2c-request.d.ts +55 -0
  52. package/dist/src/messaging/process-c2c-request.js +445 -0
  53. package/dist/src/messaging/process-message.d.ts +62 -0
  54. package/dist/src/messaging/process-message.js +282 -0
  55. package/dist/src/messaging/scheduler.d.ts +17 -0
  56. package/dist/src/messaging/scheduler.js +47 -0
  57. package/dist/src/messaging/types.d.ts +34 -0
  58. package/dist/src/messaging/types.js +4 -0
  59. package/dist/src/plugin-ui/assets/openagent-override.js +9278 -0
  60. package/dist/src/plugin-ui/index.d.ts +13 -0
  61. package/dist/src/plugin-ui/index.js +16 -0
  62. package/dist/src/plugin-ui/ui-extension-loader/backup.d.ts +23 -0
  63. package/dist/src/plugin-ui/ui-extension-loader/backup.js +82 -0
  64. package/dist/src/plugin-ui/ui-extension-loader/index.d.ts +28 -0
  65. package/dist/src/plugin-ui/ui-extension-loader/index.js +240 -0
  66. package/dist/src/plugin-ui/ui-extension-loader/locator.d.ts +35 -0
  67. package/dist/src/plugin-ui/ui-extension-loader/locator.js +129 -0
  68. package/dist/src/plugin-ui/ui-extension-loader/manifest.d.ts +26 -0
  69. package/dist/src/plugin-ui/ui-extension-loader/manifest.js +45 -0
  70. package/dist/src/plugin-ui/ui-extension-loader/registry-regex.d.ts +9 -0
  71. package/dist/src/plugin-ui/ui-extension-loader/registry-regex.js +724 -0
  72. package/dist/src/plugin-ui/ui-extension-loader/removed-extensions.d.ts +8 -0
  73. package/dist/src/plugin-ui/ui-extension-loader/removed-extensions.js +58 -0
  74. package/dist/src/plugin-ui/ui-extension-loader/types.d.ts +55 -0
  75. package/dist/src/plugin-ui/ui-extension-loader/types.js +23 -0
  76. package/dist/src/proxy/auth-proxy.d.ts +20 -0
  77. package/dist/src/proxy/auth-proxy.js +337 -0
  78. package/dist/src/runtime/account.d.ts +156 -0
  79. package/dist/src/runtime/account.js +491 -0
  80. package/dist/src/runtime/index.d.ts +5 -0
  81. package/dist/src/runtime/index.js +6 -0
  82. package/dist/src/runtime/plugin-runtime.d.ts +40 -0
  83. package/dist/src/runtime/plugin-runtime.js +72 -0
  84. package/dist/src/runtime/registry.d.ts +41 -0
  85. package/dist/src/runtime/registry.js +60 -0
  86. package/dist/src/sdk/CLASS_MAP.md +143 -0
  87. package/dist/src/sdk/index.d.ts +126 -0
  88. package/dist/src/sdk/index.js +23990 -0
  89. package/dist/src/sdk/modules/cloud-search-module.js +1117 -0
  90. package/dist/src/sdk/modules/follow-module.js +1069 -0
  91. package/dist/src/sdk/modules/group-module.js +7397 -0
  92. package/dist/src/sdk/modules/relationship-module.js +2269 -0
  93. package/dist/src/sdk/modules/signaling-module.js +1468 -0
  94. package/dist/src/sdk/modules/tim-upload-plugin.js +730 -0
  95. package/dist/src/sdk/node-env/http-request.js +90 -0
  96. package/dist/src/sdk/node-env/index.js +57 -0
  97. package/dist/src/sdk/node-env/storage.js +114 -0
  98. package/dist/src/sdk/package.json +10 -0
  99. package/dist/src/sdk/sdk/CLASS_MAP.md +143 -0
  100. package/dist/src/sdk/sdk/index.d.ts +126 -0
  101. package/dist/src/sdk/sdk/index.js +23990 -0
  102. package/dist/src/sdk/sdk/modules/cloud-search-module.js +1117 -0
  103. package/dist/src/sdk/sdk/modules/follow-module.js +1069 -0
  104. package/dist/src/sdk/sdk/modules/group-module.js +7397 -0
  105. package/dist/src/sdk/sdk/modules/relationship-module.js +2269 -0
  106. package/dist/src/sdk/sdk/modules/signaling-module.js +1468 -0
  107. package/dist/src/sdk/sdk/modules/tim-upload-plugin.js +730 -0
  108. package/dist/src/sdk/sdk/node-env/http-request.js +90 -0
  109. package/dist/src/sdk/sdk/node-env/index.js +57 -0
  110. package/dist/src/sdk/sdk/node-env/storage.js +114 -0
  111. package/dist/src/sdk/sdk/package.json +10 -0
  112. package/dist/src/sdk/sdk/tsconfig.json +16 -0
  113. package/dist/src/sdk/tsconfig.json +16 -0
  114. package/dist/src/state/pending-invocation-store.d.ts +26 -0
  115. package/dist/src/state/pending-invocation-store.js +39 -0
  116. package/dist/src/state/store.d.ts +165 -0
  117. package/dist/src/state/store.js +535 -0
  118. package/dist/src/tim/c2c.d.ts +83 -0
  119. package/dist/src/tim/c2c.js +318 -0
  120. package/dist/src/tim/channels.d.ts +95 -0
  121. package/dist/src/tim/channels.js +279 -0
  122. package/dist/src/tim/client.d.ts +54 -0
  123. package/dist/src/tim/client.js +268 -0
  124. package/dist/src/tim/index.d.ts +6 -0
  125. package/dist/src/tim/index.js +6 -0
  126. package/dist/src/tim/messages.d.ts +50 -0
  127. package/dist/src/tim/messages.js +104 -0
  128. package/dist/src/tim/sdk-logger-init.d.ts +13 -0
  129. package/dist/src/tim/sdk-logger-init.js +46 -0
  130. package/dist/src/tools.d.ts +9 -0
  131. package/dist/src/tools.js +8 -0
  132. package/dist/src/transport/factory.d.ts +63 -0
  133. package/dist/src/transport/factory.js +54 -0
  134. package/dist/src/transport/oasn/index.d.ts +12 -0
  135. package/dist/src/transport/oasn/index.js +9 -0
  136. package/dist/src/transport/oasn/oasn-agent-card.d.ts +38 -0
  137. package/dist/src/transport/oasn/oasn-agent-card.js +102 -0
  138. package/dist/src/transport/oasn/oasn-discovery.d.ts +33 -0
  139. package/dist/src/transport/oasn/oasn-discovery.js +97 -0
  140. package/dist/src/transport/oasn/oasn-files.d.ts +64 -0
  141. package/dist/src/transport/oasn/oasn-files.js +174 -0
  142. package/dist/src/transport/oasn/oasn-http.d.ts +98 -0
  143. package/dist/src/transport/oasn/oasn-http.js +362 -0
  144. package/dist/src/transport/oasn/oasn-invocation.d.ts +154 -0
  145. package/dist/src/transport/oasn/oasn-invocation.js +432 -0
  146. package/dist/src/transport/oasn/oasn-normalize.d.ts +6 -0
  147. package/dist/src/transport/oasn/oasn-normalize.js +112 -0
  148. package/dist/src/transport/oasn/oasn-register.d.ts +19 -0
  149. package/dist/src/transport/oasn/oasn-register.js +24 -0
  150. package/dist/src/transport/oasn/oasn-transport.d.ts +114 -0
  151. package/dist/src/transport/oasn/oasn-transport.js +230 -0
  152. package/dist/src/transport/oasn/oasn-types.d.ts +331 -0
  153. package/dist/src/transport/oasn/oasn-types.js +44 -0
  154. package/dist/src/transport/tim/index.d.ts +7 -0
  155. package/dist/src/transport/tim/index.js +6 -0
  156. package/dist/src/transport/tim/tim-transport.d.ts +122 -0
  157. package/dist/src/transport/tim/tim-transport.js +402 -0
  158. package/dist/src/transport/types.d.ts +450 -0
  159. package/dist/src/transport/types.js +38 -0
  160. package/dist/src/util/http.d.ts +21 -0
  161. package/dist/src/util/http.js +93 -0
  162. package/dist/src/util/logger.d.ts +20 -0
  163. package/dist/src/util/logger.js +100 -0
  164. package/dist/src/util/url-resolver.d.ts +7 -0
  165. package/dist/src/util/url-resolver.js +20 -0
  166. package/index.ts +11 -0
  167. package/openclaw.plugin.json +9 -0
  168. package/package.json +7 -4
  169. package/src/app/download-file-tool.ts +133 -0
  170. package/src/app/hooks.ts +89 -5
  171. package/src/app/index.ts +6 -0
  172. package/src/app/remote-agent-tool.ts +46 -0
  173. package/src/app/types.ts +1 -0
  174. package/src/app/upload-file-tool.ts +411 -0
  175. package/src/plugin-ui/assets/openagent-override.js +15 -66
  176. package/src/plugin-ui/modules/agent-book/panel/agent-book.js +0 -61
  177. package/src/plugin-ui/modules/agent-book/panel/agent-data.js +0 -1
  178. package/src/plugin-ui/modules/agent-book/panel/inject-ui.js +14 -3
  179. package/src/plugin-ui/ui-extension-loader/registry-regex.ts +102 -63
  180. package/src/runtime/account.ts +0 -23
  181. package/src/transport/oasn/oasn-files.ts +5 -5
  182. package/src/transport/oasn/oasn-invocation.ts +44 -2
  183. package/src/transport/oasn/oasn-normalize.ts +0 -26
  184. package/src/transport/oasn/oasn-register.ts +8 -81
  185. package/src/transport/oasn/oasn-transport.ts +9 -32
  186. package/src/transport/oasn/oasn-types.ts +53 -6
  187. package/src/transport/types.ts +33 -36
  188. package/src/util/url-resolver.ts +17 -0
@@ -0,0 +1,25 @@
1
+ /**
2
+ * WindowAggregator — Message batching and ChannelDelta builder
3
+ *
4
+ * Buffers messages per channel with three flush triggers:
5
+ * 1. @mention → immediate flush
6
+ * 2. Buffer full → flush at maxBatchSize
7
+ * 3. Timer → flush after batchWindowMs
8
+ */
9
+ import type { RawMessage, ChannelDelta } from './types.js';
10
+ export interface AggregatorConfig {
11
+ batchWindowMs: number;
12
+ maxBatchSize: number;
13
+ }
14
+ export declare class WindowAggregator {
15
+ private windows;
16
+ private config;
17
+ onDelta: ((delta: ChannelDelta) => void) | null;
18
+ constructor(config?: Partial<AggregatorConfig>);
19
+ updateConfig(newConfig: Partial<AggregatorConfig>): void;
20
+ append(rawMessage: RawMessage): void;
21
+ flush(channelId: string, reason: string): void;
22
+ flushAll(): void;
23
+ stop(): void;
24
+ private _getOrCreate;
25
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * WindowAggregator — Message batching and ChannelDelta builder
3
+ *
4
+ * Buffers messages per channel with three flush triggers:
5
+ * 1. @mention → immediate flush
6
+ * 2. Buffer full → flush at maxBatchSize
7
+ * 3. Timer → flush after batchWindowMs
8
+ */
9
+ import { logger } from '../util/logger.js';
10
+ export class WindowAggregator {
11
+ windows = new Map();
12
+ config;
13
+ onDelta = null;
14
+ constructor(config = {}) {
15
+ this.config = {
16
+ batchWindowMs: config.batchWindowMs || 60_000,
17
+ maxBatchSize: config.maxBatchSize || 20,
18
+ };
19
+ }
20
+ updateConfig(newConfig) {
21
+ Object.assign(this.config, newConfig);
22
+ }
23
+ append(rawMessage) {
24
+ const channelId = rawMessage.channelId;
25
+ const win = this._getOrCreate(channelId);
26
+ win.messages.push(rawMessage);
27
+ // Immediate flush on @mention
28
+ if (rawMessage.mentionsMe) {
29
+ this.flush(channelId, 'mention');
30
+ return;
31
+ }
32
+ // Buffer full
33
+ if (win.messages.length >= this.config.maxBatchSize) {
34
+ this.flush(channelId, 'buffer_full');
35
+ return;
36
+ }
37
+ // Start timer if not running
38
+ if (!win.timer) {
39
+ win.timer = setTimeout(() => this.flush(channelId, 'timeout'), this.config.batchWindowMs);
40
+ }
41
+ }
42
+ flush(channelId, reason) {
43
+ const win = this.windows.get(channelId);
44
+ if (!win || win.messages.length === 0)
45
+ return;
46
+ const messages = win.messages.splice(0);
47
+ if (win.timer) {
48
+ clearTimeout(win.timer);
49
+ win.timer = null;
50
+ }
51
+ const hasMention = messages.some(m => m.mentionsMe);
52
+ const participants = [...new Set(messages.map(m => m.nick || m.from))];
53
+ const source = messages[0]?.source || 'push';
54
+ const delta = {
55
+ channelId,
56
+ channelName: channelId,
57
+ messageCount: messages.length,
58
+ participants,
59
+ hasMention,
60
+ urgency: hasMention ? 1.0 : Math.min(0.1 * messages.length, 0.9),
61
+ messages,
62
+ source,
63
+ flushReason: reason,
64
+ };
65
+ logger.debug(`[aggregator] FLUSH ch=${channelId} reason=${reason} msgs=${messages.length} mention=${hasMention}`);
66
+ if (this.onDelta) {
67
+ this.onDelta(delta);
68
+ }
69
+ }
70
+ flushAll() {
71
+ for (const channelId of this.windows.keys()) {
72
+ this.flush(channelId, 'shutdown');
73
+ }
74
+ }
75
+ stop() {
76
+ for (const win of this.windows.values()) {
77
+ if (win.timer)
78
+ clearTimeout(win.timer);
79
+ }
80
+ this.windows.clear();
81
+ }
82
+ _getOrCreate(channelId) {
83
+ let win = this.windows.get(channelId);
84
+ if (!win) {
85
+ win = { channelId, messages: [], timer: null };
86
+ this.windows.set(channelId, win);
87
+ }
88
+ return win;
89
+ }
90
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Collector — Message deduplication and distribution
3
+ *
4
+ * Deduplicates incoming messages using StateStore (or in-memory fallback).
5
+ * Agent's own messages are marked seen but NOT forwarded to aggregator.
6
+ *
7
+ * Authoritative writer for StateStore fields:
8
+ * - last_visit: updated on ingest() success
9
+ * - last_msg_seq: updated on ingest() when msg has sequence
10
+ */
11
+ import type { StateStore } from '../state/store.js';
12
+ import type { WindowAggregator } from './aggregator.js';
13
+ import type { RawMessage } from './types.js';
14
+ export declare class Collector {
15
+ private aggregator;
16
+ private store;
17
+ private agentId;
18
+ private _memSeen;
19
+ private _memCleanupTimer;
20
+ constructor(aggregator: WindowAggregator, store?: StateStore | null, agentId?: string);
21
+ ingest(rawMessage: RawMessage): void;
22
+ ingestBatch(rawMessages: RawMessage[]): void;
23
+ private _hasSeen;
24
+ private _markSeen;
25
+ startCleanup(intervalMs?: number): void;
26
+ stop(): void;
27
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Collector — Message deduplication and distribution
3
+ *
4
+ * Deduplicates incoming messages using StateStore (or in-memory fallback).
5
+ * Agent's own messages are marked seen but NOT forwarded to aggregator.
6
+ *
7
+ * Authoritative writer for StateStore fields:
8
+ * - last_visit: updated on ingest() success
9
+ * - last_msg_seq: updated on ingest() when msg has sequence
10
+ */
11
+ import { logger } from '../util/logger.js';
12
+ export class Collector {
13
+ aggregator;
14
+ store;
15
+ agentId;
16
+ _memSeen = new Set();
17
+ _memCleanupTimer = null;
18
+ constructor(aggregator, store = null, agentId = '') {
19
+ this.aggregator = aggregator;
20
+ this.store = store;
21
+ this.agentId = agentId;
22
+ }
23
+ ingest(rawMessage) {
24
+ if (this._hasSeen(rawMessage.id)) {
25
+ logger.debug(`[collector] DEDUP skip id=${rawMessage.id}`);
26
+ return;
27
+ }
28
+ // Mark as seen
29
+ this._markSeen(rawMessage.id, rawMessage.channelId);
30
+ // Update StateStore: last_visit + last_msg_seq
31
+ if (this.store) {
32
+ this.store.updateLastVisit(rawMessage.channelId);
33
+ if (rawMessage.seq != null) {
34
+ this.store.updateLastMsgSeq(rawMessage.channelId, rawMessage.seq);
35
+ }
36
+ }
37
+ // Agent's own messages: mark seen but don't trigger agent turns
38
+ if (this.agentId && rawMessage.from === this.agentId) {
39
+ logger.debug(`[collector] SELF msg id=${rawMessage.id} (marked seen, no turn)`);
40
+ return;
41
+ }
42
+ logger.debug(`[collector] NEW msg id=${rawMessage.id} ch=${rawMessage.channelId} from=${rawMessage.nick}`);
43
+ this.aggregator.append(rawMessage);
44
+ }
45
+ ingestBatch(rawMessages) {
46
+ for (const msg of rawMessages) {
47
+ this.ingest(msg);
48
+ }
49
+ }
50
+ _hasSeen(messageId) {
51
+ if (this.store)
52
+ return this.store.hasSeen(messageId);
53
+ return this._memSeen.has(messageId);
54
+ }
55
+ _markSeen(messageId, channelId) {
56
+ if (this.store) {
57
+ this.store.markSeen(messageId, channelId);
58
+ }
59
+ else {
60
+ this._memSeen.add(messageId);
61
+ }
62
+ }
63
+ startCleanup(intervalMs = 600_000) {
64
+ if (this.store)
65
+ return; // StateStore handles its own cleanup
66
+ this._memCleanupTimer = setInterval(() => {
67
+ this._memSeen.clear();
68
+ }, intervalMs);
69
+ }
70
+ stop() {
71
+ if (this._memCleanupTimer) {
72
+ clearInterval(this._memCleanupTimer);
73
+ this._memCleanupTimer = null;
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * ActionExecutor — Triggers OpenClaw agent turn via CLI
3
+ *
4
+ * Uses `openclaw agent` to inject inbound messages.
5
+ * Agent replies via openagent_send_message tool call.
6
+ */
7
+ import type { ChannelDelta } from './types.js';
8
+ export declare class ActionExecutor {
9
+ private accountId;
10
+ private openclawBin;
11
+ setAccountId(accountId: string): void;
12
+ handleDelta(delta: ChannelDelta): Promise<void>;
13
+ private _formatDeltaText;
14
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * ActionExecutor — Triggers OpenClaw agent turn via CLI
3
+ *
4
+ * Uses `openclaw agent` to inject inbound messages.
5
+ * Agent replies via openagent_send_message tool call.
6
+ */
7
+ import { execFile } from 'node:child_process';
8
+ import { promisify } from 'node:util';
9
+ import { logger } from '../util/logger.js';
10
+ const execFileAsync = promisify(execFile);
11
+ export class ActionExecutor {
12
+ accountId = 'default';
13
+ openclawBin = 'openclaw';
14
+ setAccountId(accountId) {
15
+ this.accountId = accountId || 'default';
16
+ }
17
+ async handleDelta(delta) {
18
+ const text = this._formatDeltaText(delta);
19
+ logger.info(`[executor] INBOUND ch=${delta.channelId} msgs=${delta.messageCount} mention=${delta.hasMention}`);
20
+ try {
21
+ const args = [
22
+ 'agent',
23
+ '--agent', 'main',
24
+ '--channel', 'openagent',
25
+ '--message', text,
26
+ '--session-id', `openagent:${delta.channelId}`,
27
+ '--json',
28
+ ];
29
+ const { stdout, stderr } = await execFileAsync(this.openclawBin, args, {
30
+ timeout: 120_000,
31
+ env: { ...process.env },
32
+ });
33
+ if (stderr) {
34
+ logger.debug(`[executor] stderr: ${stderr.substring(0, 500)}`);
35
+ }
36
+ if (stdout) {
37
+ logger.info(`[executor] Agent turn completed for ch=${delta.channelId}`);
38
+ }
39
+ }
40
+ catch (err) {
41
+ logger.error(`[executor] Agent turn failed: ${err.message}`);
42
+ }
43
+ }
44
+ _formatDeltaText(delta) {
45
+ const { channelId, messages, hasMention } = delta;
46
+ const mentionTag = hasMention ? ' ⚡ @mention' : '';
47
+ let messageSection;
48
+ if (messages.length === 1) {
49
+ const m = messages[0];
50
+ messageSection = `[Channel ${channelId}${mentionTag}] ${m.nick}: ${m.text}`;
51
+ }
52
+ else {
53
+ const summary = messages.map(m => `[${m.nick}] ${m.text}`).join('\n');
54
+ messageSection = `📬 ${messages.length} new messages in channel ${channelId}${mentionTag}:\n${summary}`;
55
+ }
56
+ const instruction = `[INSTRUCTION: Reply ONLY in channel ${channelId} using openagent_send_message. After calling the tool, respond with ONLY: NO_REPLY (this prevents your reply from leaking to the chat UI). Do NOT visit other channels. Do NOT send status reports. Just reply naturally to the conversation above, or stay silent if you have nothing to add.]`;
57
+ return `${messageSection}\n\n${instruction}`;
58
+ }
59
+ }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Inbound — TIM push message → standard OpenClaw MsgContext conversion
3
+ *
4
+ * This module converts the TIM SDK's RawPushMessage into the standard
5
+ * MsgContext shape expected by channelRuntime.reply.dispatchReplyFromConfig().
6
+ *
7
+ * v3.4.0: Added BodyForAgent, InboundHistory, GroupSystemPrompt, GroupSubject,
8
+ * ConversationLabel, Surface, SenderId, RawBody, CommandBody to match
9
+ * the official plugin contract (Signal, LINE, Discord).
10
+ * See: docs/audit/008-inbound-context-gap.md
11
+ *
12
+ * Reference: docs/reference/plugins/openclaw-weixin/src/messaging/inbound.ts
13
+ */
14
+ import type { RawPushMessage } from '../tim/client.js';
15
+ /** History entry for InboundHistory field. */
16
+ export interface InboundHistoryEntry {
17
+ sender: string;
18
+ body: string;
19
+ timestamp: number;
20
+ }
21
+ /** Extra context not available from the raw TIM message alone. */
22
+ export interface InboundExtras {
23
+ /** Group display name (fetched from TIM group profile) */
24
+ groupName?: string;
25
+ /** Group-level system prompt (from channel skill / notification field) */
26
+ groupSystemPrompt?: string;
27
+ /** Recent message history for this channel */
28
+ inboundHistory?: InboundHistoryEntry[];
29
+ }
30
+ /**
31
+ * Standard inbound context for the OpenClaw pipeline.
32
+ * Field names MUST match the OpenClaw MsgContext contract.
33
+ */
34
+ export interface OpenagentMsgContext {
35
+ /** Message text body (may include envelope in future) */
36
+ Body: string;
37
+ /** Current message original text — LLM prompt main body */
38
+ BodyForAgent: string;
39
+ /** Raw message body for command detection */
40
+ RawBody: string;
41
+ /** Command detection text */
42
+ CommandBody: string;
43
+ /** Sender user ID */
44
+ From: string;
45
+ /** Destination (channel ID for group chats) */
46
+ To: string;
47
+ /** Account ID this message belongs to */
48
+ AccountId: string;
49
+ /** Sender machine ID */
50
+ SenderId: string;
51
+ /** Sender display name */
52
+ SenderName: string;
53
+ /** Human-readable conversation label */
54
+ ConversationLabel: string;
55
+ /** Group name / subject */
56
+ GroupSubject: string;
57
+ /** Channel plugin identifier */
58
+ OriginatingChannel: 'openagent';
59
+ /** Original destination identifier */
60
+ OriginatingTo: string;
61
+ /** Unique message ID */
62
+ MessageSid: string;
63
+ /** Message timestamp (ms) */
64
+ Timestamp?: number;
65
+ /** Provider identifier */
66
+ Provider: 'openagent';
67
+ /** Platform surface identifier */
68
+ Surface: 'openagent';
69
+ /** Chat type: OpenAgent is group-only */
70
+ ChatType: 'group';
71
+ /** Whether the message @mentioned our agent */
72
+ WasMentioned?: boolean;
73
+ /** Session key override (set after resolveAgentRoute) */
74
+ SessionKey?: string;
75
+ /** Whether sender is authorized for slash commands */
76
+ CommandAuthorized?: boolean;
77
+ /** Group-level system prompt (channel skill / rules) */
78
+ GroupSystemPrompt?: string;
79
+ /** Recent message history for this channel */
80
+ InboundHistory?: InboundHistoryEntry[];
81
+ }
82
+ /**
83
+ * Convert a TIM RawPushMessage to the standard MsgContext.
84
+ *
85
+ * Mapping:
86
+ * raw.text → Body, BodyForAgent, RawBody, CommandBody
87
+ * raw.from → From, SenderId
88
+ * raw.channelId → To, OriginatingTo
89
+ * raw.nick → SenderName
90
+ * raw.id → MessageSid
91
+ * raw.time → Timestamp
92
+ * raw.mentionsMe → WasMentioned
93
+ * extras.groupName → GroupSubject, ConversationLabel
94
+ * extras.groupSystemPrompt → GroupSystemPrompt
95
+ * extras.inboundHistory → InboundHistory
96
+ */
97
+ export declare function timMessageToMsgContext(raw: RawPushMessage, accountId: string, extras?: InboundExtras): OpenagentMsgContext;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Inbound — TIM push message → standard OpenClaw MsgContext conversion
3
+ *
4
+ * This module converts the TIM SDK's RawPushMessage into the standard
5
+ * MsgContext shape expected by channelRuntime.reply.dispatchReplyFromConfig().
6
+ *
7
+ * v3.4.0: Added BodyForAgent, InboundHistory, GroupSystemPrompt, GroupSubject,
8
+ * ConversationLabel, Surface, SenderId, RawBody, CommandBody to match
9
+ * the official plugin contract (Signal, LINE, Discord).
10
+ * See: docs/audit/008-inbound-context-gap.md
11
+ *
12
+ * Reference: docs/reference/plugins/openclaw-weixin/src/messaging/inbound.ts
13
+ */
14
+ // ── Conversion ──
15
+ /**
16
+ * Convert a TIM RawPushMessage to the standard MsgContext.
17
+ *
18
+ * Mapping:
19
+ * raw.text → Body, BodyForAgent, RawBody, CommandBody
20
+ * raw.from → From, SenderId
21
+ * raw.channelId → To, OriginatingTo
22
+ * raw.nick → SenderName
23
+ * raw.id → MessageSid
24
+ * raw.time → Timestamp
25
+ * raw.mentionsMe → WasMentioned
26
+ * extras.groupName → GroupSubject, ConversationLabel
27
+ * extras.groupSystemPrompt → GroupSystemPrompt
28
+ * extras.inboundHistory → InboundHistory
29
+ */
30
+ export function timMessageToMsgContext(raw, accountId, extras) {
31
+ const senderName = raw.nick || raw.from;
32
+ const groupName = extras?.groupName || raw.channelId;
33
+ return {
34
+ // ── Message body (4 variants per official contract) ──
35
+ Body: raw.text,
36
+ BodyForAgent: raw.text,
37
+ RawBody: raw.text,
38
+ CommandBody: raw.text,
39
+ // ── Routing ──
40
+ From: raw.from,
41
+ To: raw.channelId,
42
+ AccountId: accountId,
43
+ // ── Sender info ──
44
+ SenderId: raw.from,
45
+ SenderName: senderName,
46
+ // ── Group info ──
47
+ ConversationLabel: groupName,
48
+ GroupSubject: groupName,
49
+ // ── Channel metadata ──
50
+ OriginatingChannel: 'openagent',
51
+ OriginatingTo: raw.channelId,
52
+ MessageSid: raw.id,
53
+ Timestamp: raw.time,
54
+ Provider: 'openagent',
55
+ Surface: 'openagent',
56
+ ChatType: 'group',
57
+ // ── Flags ──
58
+ WasMentioned: raw.mentionsMe,
59
+ // ── Enriched context (from extras) ──
60
+ GroupSystemPrompt: extras?.groupSystemPrompt || undefined,
61
+ InboundHistory: extras?.inboundHistory,
62
+ };
63
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Messaging — Module barrel export
3
+ *
4
+ * v3.2.0: New channelRuntime-based pipeline (inbound + process-message).
5
+ * Legacy modules (collector, aggregator, scheduler, executor) are retained
6
+ * on disk but no longer exported or referenced.
7
+ */
8
+ export { timMessageToMsgContext, type OpenagentMsgContext } from './inbound.js';
9
+ export { processOneMessage, type ProcessMessageDeps } from './process-message.js';
10
+ export type { RawMessage, ChannelDelta, HistoryMessage } from './types.js';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Messaging — Module barrel export
3
+ *
4
+ * v3.2.0: New channelRuntime-based pipeline (inbound + process-message).
5
+ * Legacy modules (collector, aggregator, scheduler, executor) are retained
6
+ * on disk but no longer exported or referenced.
7
+ */
8
+ export { timMessageToMsgContext } from './inbound.js';
9
+ export { processOneMessage } from './process-message.js';
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Mention Protocol — Bot-to-Bot communication in mention-only groups
3
+ *
4
+ * Pure function module — no side effects, no shared state.
5
+ *
6
+ * When a group has gm_req_mention=1, bots need to:
7
+ * 1. Know the group's "social rule" (must @-mention to trigger others)
8
+ * 2. Know who's in the group (member list)
9
+ * 3. Have their text-level @mentions translated to TIM protocol-level atUserList
10
+ *
11
+ * See: docs/audit/012-mention-mode-bot-to-bot-v3.4.4.md
12
+ */
13
+ export interface MentionMember {
14
+ id: string;
15
+ nick: string;
16
+ }
17
+ /**
18
+ * Build the mention protocol prompt to inject into GroupSystemPrompt.
19
+ * Tells the AI: this group is mention-only, here are the members,
20
+ * you must @mention them to communicate.
21
+ *
22
+ * Returns empty string if no other members exist.
23
+ */
24
+ export declare function buildMentionPrompt(members: MentionMember[], selfId: string): string;
25
+ /**
26
+ * Extract @-mention targets from AI output text.
27
+ *
28
+ * Strategy: iterate the known member list and search for each nick
29
+ * in the text. This is more robust than parsing @-tokens from text,
30
+ * because it handles:
31
+ * - Space after @: "@ 投资人Bot"
32
+ * - Case mismatch: "@投资人bot"
33
+ * - Trailing punct: "@投资人Bot,你好"
34
+ * - Multiple @: "@BotA @BotB hi"
35
+ *
36
+ * Only matches when @ prefix is present — mentioning a name without @
37
+ * (e.g. "投资人Bot说得对") does NOT trigger a match.
38
+ *
39
+ * Returns an array of userIDs suitable for TIM createTextAtMessage.
40
+ * Returns empty array if no matches found.
41
+ */
42
+ export declare function extractAtTargets(text: string, members: MentionMember[], selfId: string): string[];
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Mention Protocol — Bot-to-Bot communication in mention-only groups
3
+ *
4
+ * Pure function module — no side effects, no shared state.
5
+ *
6
+ * When a group has gm_req_mention=1, bots need to:
7
+ * 1. Know the group's "social rule" (must @-mention to trigger others)
8
+ * 2. Know who's in the group (member list)
9
+ * 3. Have their text-level @mentions translated to TIM protocol-level atUserList
10
+ *
11
+ * See: docs/audit/012-mention-mode-bot-to-bot-v3.4.4.md
12
+ */
13
+ // ── Regex utility ──
14
+ function escapeRegex(s) {
15
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
16
+ }
17
+ // ── Prompt injection ──
18
+ /**
19
+ * Build the mention protocol prompt to inject into GroupSystemPrompt.
20
+ * Tells the AI: this group is mention-only, here are the members,
21
+ * you must @mention them to communicate.
22
+ *
23
+ * Returns empty string if no other members exist.
24
+ */
25
+ export function buildMentionPrompt(members, selfId) {
26
+ const others = members.filter(m => m.id !== selfId);
27
+ if (others.length === 0)
28
+ return '';
29
+ const memberList = others
30
+ .map(m => `- ${m.nick} (mention as: @${m.nick})`)
31
+ .join('\n');
32
+ return [
33
+ '[GROUP COMMUNICATION PROTOCOL]',
34
+ 'This group uses mention-only mode.',
35
+ 'Your messages will ONLY be seen by members you @-mention.',
36
+ 'To mention someone, write @their_name in your message.',
37
+ '',
38
+ 'Group members:',
39
+ memberList,
40
+ '',
41
+ `Example: "@${others[0].nick} what do you think?"`,
42
+ '[/GROUP COMMUNICATION PROTOCOL]',
43
+ ].join('\n');
44
+ }
45
+ // ── Text → atUserList extraction ──
46
+ /**
47
+ * Extract @-mention targets from AI output text.
48
+ *
49
+ * Strategy: iterate the known member list and search for each nick
50
+ * in the text. This is more robust than parsing @-tokens from text,
51
+ * because it handles:
52
+ * - Space after @: "@ 投资人Bot"
53
+ * - Case mismatch: "@投资人bot"
54
+ * - Trailing punct: "@投资人Bot,你好"
55
+ * - Multiple @: "@BotA @BotB hi"
56
+ *
57
+ * Only matches when @ prefix is present — mentioning a name without @
58
+ * (e.g. "投资人Bot说得对") does NOT trigger a match.
59
+ *
60
+ * Returns an array of userIDs suitable for TIM createTextAtMessage.
61
+ * Returns empty array if no matches found.
62
+ */
63
+ export function extractAtTargets(text, members, selfId) {
64
+ const results = [];
65
+ for (const member of members) {
66
+ if (member.id === selfId)
67
+ continue;
68
+ const pattern = new RegExp(`@\\s*${escapeRegex(member.nick)}`, 'i');
69
+ if (pattern.test(text)) {
70
+ results.push(member.id);
71
+ }
72
+ }
73
+ return results;
74
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Process C2C Request — Remote agent task request handler (T3)
3
+ *
4
+ * ⚠️ TIM-only 路径(v3.9+ 双轨抽象)
5
+ * ---------------------------------------------------------
6
+ * 本文件只在 transport='tim' 下被 AccountRuntime._connectTIM() 通过
7
+ * `this.client.on('c2c_request', ...)` 注册。OASN 路径下 AccountRuntime
8
+ * 不会监听 c2c_request 事件 —— OASN ClientAgent 是消费侧,不接收外来 Invocation,
9
+ * 远程 Agent 调用统一由发起方走 transport.sendTask / waitForTaskResult 完成。
10
+ *
11
+ * Handles incoming `c2c_request` events from c2c.ts (T1).
12
+ * Mirrors the process-message.ts pattern but for C2C task requests:
13
+ *
14
+ * 1. Parse request parameters (from, requestId, task, sessionMode)
15
+ * 2. Compute sessionKey (aligned with OpenClaw buildAgentPeerSessionKey)
16
+ * 3. Register onAgentEvent listener ({openagent_progress} prefix filter)
17
+ * 4. Build MsgContext (adapted for C2C, not group)
18
+ * 5. channelRuntime pipeline: resolveAgentRoute → finalize → record → dispatch
19
+ * 6. deliver callback routes kind="block" → progress, kind="final" → result
20
+ * 7. Unsubscribe onAgentEvent listener
21
+ *
22
+ * @see docs/specs/2026-06-16-oasn-transport-abstraction-design.md §4.2
23
+ * @see docs/products/orchestrator/specs/T3-remote-handler.md
24
+ * @see docs/products/orchestrator/specs/T1-c2c-infra.md §6.2 (c2c_request emit)
25
+ */
26
+ import type { PluginRuntime } from 'openclaw/plugin-sdk/core';
27
+ /** Parsed task request payload (from c2c.ts L267) */
28
+ interface C2CTaskRequest {
29
+ type: 'openagent_task_request';
30
+ request_id: string;
31
+ task: string;
32
+ session_mode: string;
33
+ }
34
+ /** Incoming c2c_request event shape (emitted by c2c.ts initC2CHandler) */
35
+ export interface C2CRequestEvent {
36
+ from: string;
37
+ payload: C2CTaskRequest;
38
+ time: number;
39
+ }
40
+ /** Dependencies injected by AccountRuntime._connectTIM() */
41
+ export interface ProcessC2CRequestDeps {
42
+ accountId: string;
43
+ selfUserId: string;
44
+ config: Record<string, unknown>;
45
+ channelRuntime: PluginRuntime['channel'];
46
+ }
47
+ /**
48
+ * Process a single incoming C2C task request through the standard
49
+ * OpenClaw channelRuntime pipeline.
50
+ *
51
+ * This is the T3 equivalent of processOneMessage (process-message.ts).
52
+ * Fire-and-forget safe — errors are caught and result in an error C2C reply.
53
+ */
54
+ export declare function processC2CRequest(request: C2CRequestEvent, deps: ProcessC2CRequestDeps): Promise<void>;
55
+ export {};