openclaw-openagent 1.0.13 → 1.0.14

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 (128) hide show
  1. package/dist/src/messaging/executor.d.ts +2 -3
  2. package/dist/src/messaging/executor.js +4 -31
  3. package/dist/src/plugin-ui/assets/openagent-override.js +4 -5
  4. package/dist/src/runtime/update-checker.d.ts +1 -1
  5. package/dist/src/runtime/update-checker.js +9 -46
  6. package/package.json +1 -3
  7. package/src/app/channel-tools.ts +0 -249
  8. package/src/app/discovery-tools.ts +0 -273
  9. package/src/app/download-file-tool.ts +0 -133
  10. package/src/app/hooks.ts +0 -144
  11. package/src/app/index.ts +0 -84
  12. package/src/app/messaging-tools.ts +0 -79
  13. package/src/app/ops-tools.ts +0 -155
  14. package/src/app/remote-agent-tool.ts +0 -762
  15. package/src/app/types.ts +0 -68
  16. package/src/app/upload-file-tool.ts +0 -411
  17. package/src/app/verbose-preflight.ts +0 -190
  18. package/src/auth/config.ts +0 -266
  19. package/src/auth/credential-manager.ts +0 -146
  20. package/src/auth/index.ts +0 -24
  21. package/src/auth/verify.ts +0 -99
  22. package/src/channel.ts +0 -566
  23. package/src/compat.ts +0 -94
  24. package/src/config/config-schema.ts +0 -45
  25. package/src/messaging/aggregator.ts +0 -120
  26. package/src/messaging/collector.ts +0 -89
  27. package/src/messaging/executor.ts +0 -72
  28. package/src/messaging/inbound.ts +0 -150
  29. package/src/messaging/index.ts +0 -11
  30. package/src/messaging/mention-protocol.ts +0 -94
  31. package/src/messaging/process-c2c-request.ts +0 -564
  32. package/src/messaging/process-message.ts +0 -373
  33. package/src/messaging/scheduler.ts +0 -55
  34. package/src/messaging/types.ts +0 -38
  35. package/src/plugin-ui/adapters/oc-2026-04.js +0 -103
  36. package/src/plugin-ui/adapters/oc-2026-05.js +0 -125
  37. package/src/plugin-ui/adapters/oc-2026-06.js +0 -125
  38. package/src/plugin-ui/adapters/oc-unknown.js +0 -48
  39. package/src/plugin-ui/assets/agentbook-icon.svg +0 -5
  40. package/src/plugin-ui/assets/bg.png +0 -0
  41. package/src/plugin-ui/assets/icon.png +0 -0
  42. package/src/plugin-ui/assets/magic.svg +0 -5
  43. package/src/plugin-ui/assets/openagent-override.js +0 -11263
  44. package/src/plugin-ui/build.cjs +0 -463
  45. package/src/plugin-ui/index.ts +0 -18
  46. package/src/plugin-ui/modules/agent-book/panel/agent-book.js +0 -570
  47. package/src/plugin-ui/modules/agent-book/panel/agent-card.js +0 -170
  48. package/src/plugin-ui/modules/agent-book/panel/agent-data.js +0 -643
  49. package/src/plugin-ui/modules/agent-book/panel/inject-ui.js +0 -665
  50. package/src/plugin-ui/modules/agent-book/panel/mention-state.js +0 -206
  51. package/src/plugin-ui/modules/agent-book/panel/styles.js +0 -832
  52. package/src/plugin-ui/modules/agent-book/panel/theme-adapter.js +0 -86
  53. package/src/plugin-ui/modules/agent-book/remote-agent-tool/components-core.js +0 -295
  54. package/src/plugin-ui/modules/agent-book/remote-agent-tool/thought-chain-card.js +0 -211
  55. package/src/plugin-ui/modules/agent-book/scanner.js +0 -131
  56. package/src/plugin-ui/modules/agent-book/travelcard/travel-cards.js +0 -500
  57. package/src/plugin-ui/modules/agent-book/travelcard/travel-engine.js +0 -652
  58. package/src/plugin-ui/modules/agent-book/travelcard/travel-styles.js +0 -262
  59. package/src/plugin-ui/modules/loader/bootstrap.js +0 -133
  60. package/src/plugin-ui/modules/loader/shared-state.js +0 -838
  61. package/src/plugin-ui/modules/loader/ws-intercept.js +0 -199
  62. package/src/plugin-ui/modules/remote-agent/chunk-parser.js +0 -161
  63. package/src/plugin-ui/modules/remote-agent/execution-card.js +0 -530
  64. package/src/plugin-ui/modules/remote-agent/markdown-renderer.js +0 -256
  65. package/src/plugin-ui/modules/remote-agent/media-links.js +0 -151
  66. package/src/plugin-ui/modules/remote-agent/native-style-adapter.js +0 -134
  67. package/src/plugin-ui/modules/remote-agent/output-card.js +0 -342
  68. package/src/plugin-ui/modules/remote-agent/progress-store.js +0 -363
  69. package/src/plugin-ui/modules/remote-agent/render-hooks.js +0 -1700
  70. package/src/plugin-ui/modules/remote-agent/styles.js +0 -903
  71. package/src/plugin-ui/modules/remote-agent/tool-card-model.js +0 -130
  72. package/src/plugin-ui/postinstall-deploy.cjs +0 -52
  73. package/src/plugin-ui/ui-extension-loader/backup.ts +0 -92
  74. package/src/plugin-ui/ui-extension-loader/index.ts +0 -276
  75. package/src/plugin-ui/ui-extension-loader/locator.ts +0 -152
  76. package/src/plugin-ui/ui-extension-loader/manifest.ts +0 -57
  77. package/src/plugin-ui/ui-extension-loader/registry-regex.ts +0 -944
  78. package/src/plugin-ui/ui-extension-loader/removed-extensions.ts +0 -70
  79. package/src/plugin-ui/ui-extension-loader/types.ts +0 -72
  80. package/src/proxy/auth-proxy.ts +0 -414
  81. package/src/runtime/account.ts +0 -549
  82. package/src/runtime/index.ts +0 -7
  83. package/src/runtime/plugin-runtime.ts +0 -94
  84. package/src/runtime/registry.ts +0 -71
  85. package/src/runtime/update-checker.ts +0 -286
  86. package/src/sdk/CLASS_MAP.md +0 -143
  87. package/src/sdk/index.d.ts +0 -126
  88. package/src/sdk/index.js +0 -23990
  89. package/src/sdk/modules/cloud-search-module.js +0 -1117
  90. package/src/sdk/modules/follow-module.js +0 -1069
  91. package/src/sdk/modules/group-module.js +0 -7397
  92. package/src/sdk/modules/relationship-module.js +0 -2269
  93. package/src/sdk/modules/signaling-module.js +0 -1468
  94. package/src/sdk/modules/tim-upload-plugin.js +0 -730
  95. package/src/sdk/node-env/http-request.js +0 -90
  96. package/src/sdk/node-env/index.js +0 -57
  97. package/src/sdk/node-env/storage.js +0 -114
  98. package/src/sdk/package.json +0 -10
  99. package/src/sdk/tsconfig.json +0 -16
  100. package/src/state/pending-invocation-store.ts +0 -43
  101. package/src/state/store.ts +0 -756
  102. package/src/tim/c2c.ts +0 -451
  103. package/src/tim/channels.ts +0 -364
  104. package/src/tim/client.ts +0 -330
  105. package/src/tim/index.ts +0 -18
  106. package/src/tim/messages.ts +0 -166
  107. package/src/tim/sdk-logger-init.ts +0 -50
  108. package/src/tools.ts +0 -10
  109. package/src/transport/factory.ts +0 -95
  110. package/src/transport/oasn/index.ts +0 -17
  111. package/src/transport/oasn/oasn-agent-card.ts +0 -111
  112. package/src/transport/oasn/oasn-discovery.ts +0 -108
  113. package/src/transport/oasn/oasn-files.ts +0 -210
  114. package/src/transport/oasn/oasn-http.ts +0 -529
  115. package/src/transport/oasn/oasn-invocation.ts +0 -604
  116. package/src/transport/oasn/oasn-normalize.ts +0 -133
  117. package/src/transport/oasn/oasn-register.ts +0 -33
  118. package/src/transport/oasn/oasn-transport.ts +0 -318
  119. package/src/transport/oasn/oasn-types.ts +0 -404
  120. package/src/transport/tim/index.ts +0 -8
  121. package/src/transport/tim/tim-transport.ts +0 -515
  122. package/src/transport/types.ts +0 -538
  123. package/src/types/openclaw-plugin-sdk-media-store.d.ts +0 -9
  124. package/src/types/openclaw.d.ts +0 -97
  125. package/src/types/tencentcloud-chat.d.ts +0 -15
  126. package/src/util/http.ts +0 -113
  127. package/src/util/logger.ts +0 -131
  128. package/src/util/url-resolver.ts +0 -77
@@ -1,45 +0,0 @@
1
- /**
2
- * OpenAgent config schema — Zod-based runtime validation.
3
- *
4
- * This mirrors the JSON schema in openclaw.plugin.json but provides
5
- * type-safe runtime parsing via Zod.
6
- *
7
- * Uses direct zod dependency (same pattern as openclaw-weixin v2.1.1)
8
- * rather than openclaw/plugin-sdk/zod, which is only available in
9
- * OpenClaw >= ~2026.3.28 and would break on earlier supported hosts.
10
- */
11
-
12
- import { z } from 'zod';
13
-
14
- // ---------------------------------------------------------------------------
15
- // Zod config schema
16
- // ---------------------------------------------------------------------------
17
-
18
- const transportSchema = z.enum(['oasn', 'tim']).default('oasn');
19
- const updatePolicySchema = z.enum(['notify', 'auto', 'off']).optional();
20
-
21
- const openagentAccountSchema = z.object({
22
- name: z.string().optional(),
23
- enabled: z.boolean().optional(),
24
- transport: transportSchema.optional(),
25
- agent_id: z.string().optional(),
26
- api_key: z.string().optional(),
27
- api_base: z.string().optional(),
28
- access_api_base: z.string().optional(),
29
- claim_url: z.string().optional(),
30
- status: z.enum(['unregistered', 'unclaimed', 'claim_pending', 'claimed', 'credential_expired', 'unknown']).optional(),
31
- registered_at: z.string().optional(),
32
- });
33
-
34
- /** Top-level openagent config schema. */
35
- export const OpenagentConfigSchema = openagentAccountSchema.extend({
36
- transport: transportSchema.optional(),
37
- api_base: z.string().optional(),
38
- access_api_base: z.string().optional(),
39
- update_policy: updatePolicySchema,
40
- update_check: z.boolean().optional(),
41
- auto_update: z.boolean().optional(),
42
- update_channel: z.string().optional(),
43
- update_dist_tag: z.string().optional(),
44
- accounts: z.record(z.string(), openagentAccountSchema).optional(),
45
- });
@@ -1,120 +0,0 @@
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
-
10
- import { logger } from '../util/logger.js';
11
- import type { RawMessage, ChannelDelta } from './types.js';
12
-
13
- export interface AggregatorConfig {
14
- batchWindowMs: number;
15
- maxBatchSize: number;
16
- }
17
-
18
- interface ChannelWindow {
19
- channelId: string;
20
- messages: RawMessage[];
21
- timer: ReturnType<typeof setTimeout> | null;
22
- }
23
-
24
- export class WindowAggregator {
25
- private windows = new Map<string, ChannelWindow>();
26
- private config: AggregatorConfig;
27
- public onDelta: ((delta: ChannelDelta) => void) | null = null;
28
-
29
- constructor(config: Partial<AggregatorConfig> = {}) {
30
- this.config = {
31
- batchWindowMs: config.batchWindowMs || 60_000,
32
- maxBatchSize: config.maxBatchSize || 20,
33
- };
34
- }
35
-
36
- updateConfig(newConfig: Partial<AggregatorConfig>): void {
37
- Object.assign(this.config, newConfig);
38
- }
39
-
40
- append(rawMessage: RawMessage): void {
41
- const channelId = rawMessage.channelId;
42
- const win = this._getOrCreate(channelId);
43
- win.messages.push(rawMessage);
44
-
45
- // Immediate flush on @mention
46
- if (rawMessage.mentionsMe) {
47
- this.flush(channelId, 'mention');
48
- return;
49
- }
50
-
51
- // Buffer full
52
- if (win.messages.length >= this.config.maxBatchSize) {
53
- this.flush(channelId, 'buffer_full');
54
- return;
55
- }
56
-
57
- // Start timer if not running
58
- if (!win.timer) {
59
- win.timer = setTimeout(
60
- () => this.flush(channelId, 'timeout'),
61
- this.config.batchWindowMs,
62
- );
63
- }
64
- }
65
-
66
- flush(channelId: string, reason: string): void {
67
- const win = this.windows.get(channelId);
68
- if (!win || win.messages.length === 0) return;
69
-
70
- const messages = win.messages.splice(0);
71
- if (win.timer) {
72
- clearTimeout(win.timer);
73
- win.timer = null;
74
- }
75
-
76
- const hasMention = messages.some(m => m.mentionsMe);
77
- const participants = [...new Set(messages.map(m => m.nick || m.from))];
78
- const source = messages[0]?.source || 'push';
79
-
80
- const delta: ChannelDelta = {
81
- channelId,
82
- channelName: channelId,
83
- messageCount: messages.length,
84
- participants,
85
- hasMention,
86
- urgency: hasMention ? 1.0 : Math.min(0.1 * messages.length, 0.9),
87
- messages,
88
- source,
89
- flushReason: reason,
90
- };
91
-
92
- logger.debug(`[aggregator] FLUSH ch=${channelId} reason=${reason} msgs=${messages.length} mention=${hasMention}`);
93
-
94
- if (this.onDelta) {
95
- this.onDelta(delta);
96
- }
97
- }
98
-
99
- flushAll(): void {
100
- for (const channelId of this.windows.keys()) {
101
- this.flush(channelId, 'shutdown');
102
- }
103
- }
104
-
105
- stop(): void {
106
- for (const win of this.windows.values()) {
107
- if (win.timer) clearTimeout(win.timer);
108
- }
109
- this.windows.clear();
110
- }
111
-
112
- private _getOrCreate(channelId: string): ChannelWindow {
113
- let win = this.windows.get(channelId);
114
- if (!win) {
115
- win = { channelId, messages: [], timer: null };
116
- this.windows.set(channelId, win);
117
- }
118
- return win;
119
- }
120
- }
@@ -1,89 +0,0 @@
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
-
12
- import { logger } from '../util/logger.js';
13
- import type { StateStore } from '../state/store.js';
14
- import type { WindowAggregator } from './aggregator.js';
15
- import type { RawMessage } from './types.js';
16
-
17
- export class Collector {
18
- private aggregator: WindowAggregator;
19
- private store: StateStore | null;
20
- private agentId: string;
21
- private _memSeen = new Set<string>();
22
- private _memCleanupTimer: ReturnType<typeof setInterval> | null = null;
23
-
24
- constructor(aggregator: WindowAggregator, store: StateStore | null = null, agentId = '') {
25
- this.aggregator = aggregator;
26
- this.store = store;
27
- this.agentId = agentId;
28
- }
29
-
30
- ingest(rawMessage: RawMessage): void {
31
- if (this._hasSeen(rawMessage.id)) {
32
- logger.debug(`[collector] DEDUP skip id=${rawMessage.id}`);
33
- return;
34
- }
35
-
36
- // Mark as seen
37
- this._markSeen(rawMessage.id, rawMessage.channelId);
38
-
39
- // Update StateStore: last_visit + last_msg_seq
40
- if (this.store) {
41
- this.store.updateLastVisit(rawMessage.channelId);
42
- if (rawMessage.seq != null) {
43
- this.store.updateLastMsgSeq(rawMessage.channelId, rawMessage.seq);
44
- }
45
- }
46
-
47
- // Agent's own messages: mark seen but don't trigger agent turns
48
- if (this.agentId && rawMessage.from === this.agentId) {
49
- logger.debug(`[collector] SELF msg id=${rawMessage.id} (marked seen, no turn)`);
50
- return;
51
- }
52
-
53
- logger.debug(`[collector] NEW msg id=${rawMessage.id} ch=${rawMessage.channelId} from=${rawMessage.nick}`);
54
- this.aggregator.append(rawMessage);
55
- }
56
-
57
- ingestBatch(rawMessages: RawMessage[]): void {
58
- for (const msg of rawMessages) {
59
- this.ingest(msg);
60
- }
61
- }
62
-
63
- private _hasSeen(messageId: string): boolean {
64
- if (this.store) return this.store.hasSeen(messageId);
65
- return this._memSeen.has(messageId);
66
- }
67
-
68
- private _markSeen(messageId: string, channelId: string): void {
69
- if (this.store) {
70
- this.store.markSeen(messageId, channelId);
71
- } else {
72
- this._memSeen.add(messageId);
73
- }
74
- }
75
-
76
- startCleanup(intervalMs = 600_000): void {
77
- if (this.store) return; // StateStore handles its own cleanup
78
- this._memCleanupTimer = setInterval(() => {
79
- this._memSeen.clear();
80
- }, intervalMs);
81
- }
82
-
83
- stop(): void {
84
- if (this._memCleanupTimer) {
85
- clearInterval(this._memCleanupTimer);
86
- this._memCleanupTimer = null;
87
- }
88
- }
89
- }
@@ -1,72 +0,0 @@
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
-
8
- import { execFile } from 'node:child_process';
9
- import { promisify } from 'node:util';
10
-
11
- import { logger } from '../util/logger.js';
12
- import type { ChannelDelta } from './types.js';
13
-
14
- const execFileAsync = promisify(execFile);
15
-
16
- export class ActionExecutor {
17
- private accountId = 'default';
18
- private openclawBin = 'openclaw';
19
-
20
- setAccountId(accountId: string): void {
21
- this.accountId = accountId || 'default';
22
- }
23
-
24
- async handleDelta(delta: ChannelDelta): Promise<void> {
25
- const text = this._formatDeltaText(delta);
26
-
27
- logger.info(`[executor] INBOUND ch=${delta.channelId} msgs=${delta.messageCount} mention=${delta.hasMention}`);
28
-
29
- try {
30
- const args = [
31
- 'agent',
32
- '--agent', 'main',
33
- '--channel', 'openagent',
34
- '--message', text,
35
- '--session-id', `openagent:${delta.channelId}`,
36
- '--json',
37
- ];
38
-
39
- const { stdout, stderr } = await execFileAsync(this.openclawBin, args, {
40
- timeout: 120_000,
41
- env: { ...process.env },
42
- });
43
-
44
- if (stderr) {
45
- logger.debug(`[executor] stderr: ${stderr.substring(0, 500)}`);
46
- }
47
- if (stdout) {
48
- logger.info(`[executor] Agent turn completed for ch=${delta.channelId}`);
49
- }
50
- } catch (err) {
51
- logger.error(`[executor] Agent turn failed: ${(err as Error).message}`);
52
- }
53
- }
54
-
55
- private _formatDeltaText(delta: ChannelDelta): string {
56
- const { channelId, messages, hasMention } = delta;
57
- const mentionTag = hasMention ? ' ⚡ @mention' : '';
58
-
59
- let messageSection: string;
60
- if (messages.length === 1) {
61
- const m = messages[0]!;
62
- messageSection = `[Channel ${channelId}${mentionTag}] ${m.nick}: ${m.text}`;
63
- } else {
64
- const summary = messages.map(m => `[${m.nick}] ${m.text}`).join('\n');
65
- messageSection = `📬 ${messages.length} new messages in channel ${channelId}${mentionTag}:\n${summary}`;
66
- }
67
-
68
- 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.]`;
69
-
70
- return `${messageSection}\n\n${instruction}`;
71
- }
72
- }
@@ -1,150 +0,0 @@
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
-
15
- import type { RawPushMessage } from '../tim/client.js';
16
-
17
- // ── Types ──
18
-
19
- /** History entry for InboundHistory field. */
20
- export interface InboundHistoryEntry {
21
- sender: string;
22
- body: string;
23
- timestamp: number;
24
- }
25
-
26
- /** Extra context not available from the raw TIM message alone. */
27
- export interface InboundExtras {
28
- /** Group display name (fetched from TIM group profile) */
29
- groupName?: string;
30
- /** Group-level system prompt (from channel skill / notification field) */
31
- groupSystemPrompt?: string;
32
- /** Recent message history for this channel */
33
- inboundHistory?: InboundHistoryEntry[];
34
- }
35
-
36
- /**
37
- * Standard inbound context for the OpenClaw pipeline.
38
- * Field names MUST match the OpenClaw MsgContext contract.
39
- */
40
- export interface OpenagentMsgContext {
41
- /** Message text body (may include envelope in future) */
42
- Body: string;
43
- /** Current message original text — LLM prompt main body */
44
- BodyForAgent: string;
45
- /** Raw message body for command detection */
46
- RawBody: string;
47
- /** Command detection text */
48
- CommandBody: string;
49
- /** Sender user ID */
50
- From: string;
51
- /** Destination (channel ID for group chats) */
52
- To: string;
53
- /** Account ID this message belongs to */
54
- AccountId: string;
55
- /** Sender machine ID */
56
- SenderId: string;
57
- /** Sender display name */
58
- SenderName: string;
59
- /** Human-readable conversation label */
60
- ConversationLabel: string;
61
- /** Group name / subject */
62
- GroupSubject: string;
63
- /** Channel plugin identifier */
64
- OriginatingChannel: 'openagent';
65
- /** Original destination identifier */
66
- OriginatingTo: string;
67
- /** Unique message ID */
68
- MessageSid: string;
69
- /** Message timestamp (ms) */
70
- Timestamp?: number;
71
- /** Provider identifier */
72
- Provider: 'openagent';
73
- /** Platform surface identifier */
74
- Surface: 'openagent';
75
- /** Chat type: OpenAgent is group-only */
76
- ChatType: 'group';
77
- /** Whether the message @mentioned our agent */
78
- WasMentioned?: boolean;
79
- /** Session key override (set after resolveAgentRoute) */
80
- SessionKey?: string;
81
- /** Whether sender is authorized for slash commands */
82
- CommandAuthorized?: boolean;
83
- /** Group-level system prompt (channel skill / rules) */
84
- GroupSystemPrompt?: string;
85
- /** Recent message history for this channel */
86
- InboundHistory?: InboundHistoryEntry[];
87
- }
88
-
89
- // ── Conversion ──
90
-
91
- /**
92
- * Convert a TIM RawPushMessage to the standard MsgContext.
93
- *
94
- * Mapping:
95
- * raw.text → Body, BodyForAgent, RawBody, CommandBody
96
- * raw.from → From, SenderId
97
- * raw.channelId → To, OriginatingTo
98
- * raw.nick → SenderName
99
- * raw.id → MessageSid
100
- * raw.time → Timestamp
101
- * raw.mentionsMe → WasMentioned
102
- * extras.groupName → GroupSubject, ConversationLabel
103
- * extras.groupSystemPrompt → GroupSystemPrompt
104
- * extras.inboundHistory → InboundHistory
105
- */
106
- export function timMessageToMsgContext(
107
- raw: RawPushMessage,
108
- accountId: string,
109
- extras?: InboundExtras,
110
- ): OpenagentMsgContext {
111
- const senderName = raw.nick || raw.from;
112
- const groupName = extras?.groupName || raw.channelId;
113
-
114
- return {
115
- // ── Message body (4 variants per official contract) ──
116
- Body: raw.text,
117
- BodyForAgent: raw.text,
118
- RawBody: raw.text,
119
- CommandBody: raw.text,
120
-
121
- // ── Routing ──
122
- From: raw.from,
123
- To: raw.channelId,
124
- AccountId: accountId,
125
-
126
- // ── Sender info ──
127
- SenderId: raw.from,
128
- SenderName: senderName,
129
-
130
- // ── Group info ──
131
- ConversationLabel: groupName,
132
- GroupSubject: groupName,
133
-
134
- // ── Channel metadata ──
135
- OriginatingChannel: 'openagent',
136
- OriginatingTo: raw.channelId,
137
- MessageSid: raw.id,
138
- Timestamp: raw.time,
139
- Provider: 'openagent',
140
- Surface: 'openagent',
141
- ChatType: 'group',
142
-
143
- // ── Flags ──
144
- WasMentioned: raw.mentionsMe,
145
-
146
- // ── Enriched context (from extras) ──
147
- GroupSystemPrompt: extras?.groupSystemPrompt || undefined,
148
- InboundHistory: extras?.inboundHistory,
149
- };
150
- }
@@ -1,11 +0,0 @@
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
-
9
- export { timMessageToMsgContext, type OpenagentMsgContext } from './inbound.js';
10
- export { processOneMessage, type ProcessMessageDeps } from './process-message.js';
11
- export type { RawMessage, ChannelDelta, HistoryMessage } from './types.js';
@@ -1,94 +0,0 @@
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
-
14
- // ── Types ──
15
-
16
- export interface MentionMember {
17
- id: string;
18
- nick: string;
19
- }
20
-
21
- // ── Regex utility ──
22
-
23
- function escapeRegex(s: string): string {
24
- return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
25
- }
26
-
27
- // ── Prompt injection ──
28
-
29
- /**
30
- * Build the mention protocol prompt to inject into GroupSystemPrompt.
31
- * Tells the AI: this group is mention-only, here are the members,
32
- * you must @mention them to communicate.
33
- *
34
- * Returns empty string if no other members exist.
35
- */
36
- export function buildMentionPrompt(
37
- members: MentionMember[],
38
- selfId: string,
39
- ): string {
40
- const others = members.filter(m => m.id !== selfId);
41
- if (others.length === 0) return '';
42
-
43
- const memberList = others
44
- .map(m => `- ${m.nick} (mention as: @${m.nick})`)
45
- .join('\n');
46
-
47
- return [
48
- '[GROUP COMMUNICATION PROTOCOL]',
49
- 'This group uses mention-only mode.',
50
- 'Your messages will ONLY be seen by members you @-mention.',
51
- 'To mention someone, write @their_name in your message.',
52
- '',
53
- 'Group members:',
54
- memberList,
55
- '',
56
- `Example: "@${others[0].nick} what do you think?"`,
57
- '[/GROUP COMMUNICATION PROTOCOL]',
58
- ].join('\n');
59
- }
60
-
61
- // ── Text → atUserList extraction ──
62
-
63
- /**
64
- * Extract @-mention targets from AI output text.
65
- *
66
- * Strategy: iterate the known member list and search for each nick
67
- * in the text. This is more robust than parsing @-tokens from text,
68
- * because it handles:
69
- * - Space after @: "@ 投资人Bot"
70
- * - Case mismatch: "@投资人bot"
71
- * - Trailing punct: "@投资人Bot,你好"
72
- * - Multiple @: "@BotA @BotB hi"
73
- *
74
- * Only matches when @ prefix is present — mentioning a name without @
75
- * (e.g. "投资人Bot说得对") does NOT trigger a match.
76
- *
77
- * Returns an array of userIDs suitable for TIM createTextAtMessage.
78
- * Returns empty array if no matches found.
79
- */
80
- export function extractAtTargets(
81
- text: string,
82
- members: MentionMember[],
83
- selfId: string,
84
- ): string[] {
85
- const results: string[] = [];
86
- for (const member of members) {
87
- if (member.id === selfId) continue;
88
- const pattern = new RegExp(`@\\s*${escapeRegex(member.nick)}`, 'i');
89
- if (pattern.test(text)) {
90
- results.push(member.id);
91
- }
92
- }
93
- return results;
94
- }