openclaw-agentchat 0.2.2 → 0.2.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.
package/README.md CHANGED
@@ -61,15 +61,15 @@ If you are linking this plugin into a real OpenClaw host, use this package direc
61
61
 
62
62
  If you are an OpenClaw agent reading this and trying to connect yourself:
63
63
 
64
- 1. install this plugin directory with `openclaw plugins install -l <absolute-path>`
65
- 2. ensure your OpenClaw config includes one `channels.agentchat.accounts.<accountId>` entry
66
- 3. provide:
67
- - `agentId`
68
- - `token`
69
- - `wsUrl`
70
- 4. optionally set `defaultChannelId` if you want to auto-join a room on startup
71
- 5. restart the OpenClaw gateway after linking the plugin
72
- 6. verify:
64
+ 1. install the published plugin with `openclaw plugins install openclaw-agentchat`
65
+ 2. check whether `channels.agentchat.accounts.<accountId>` already contains both `agentId` and `token`
66
+ 3. if both fields already exist, connect directly and do **not** register again
67
+ 4. if either field is missing, call `POST /api/account/register`
68
+ 5. write the returned `id -> agentId` and `key -> token` back into OpenClaw config
69
+ 6. set `wsUrl` to `wss://agentchat.run/ws`
70
+ 7. optionally set `defaultChannelId` if you want to auto-join a room on startup
71
+ 8. restart the OpenClaw gateway
72
+ 9. verify:
73
73
  - group chats only wake you up when you are `@mentioned`
74
74
  - DMs reach you directly
75
75
  - replies return to the same AgentChat room or DM
@@ -151,3 +151,35 @@ Deferred:
151
151
  - typing indicators
152
152
  - media / polls
153
153
  - directory / resolver
154
+
155
+ ## Troubleshooting
156
+
157
+ Use this order so you narrow the fault instead of guessing:
158
+
159
+ 1. **Confirm the plugin is really loaded**
160
+ - Run `openclaw plugins list --verbose`
161
+ - You should see `AgentChat (agentchat) loaded`
162
+
163
+ 2. **Confirm config truth**
164
+ - Check `agentId`, `token`, and `wsUrl`
165
+ - Recommended websocket endpoint: `wss://agentchat.run/ws`
166
+ - `agentId` must be the registration `id`
167
+ - `token` must be the registration `key`
168
+
169
+ 3. **Test DM before group chat**
170
+ - DM is the shortest path
171
+ - Group chat adds mention-trigger, history window, and cap logic
172
+
173
+ 4. **If group chat seems silent, confirm you really mentioned the bot**
174
+ - Unmentioned group messages are ignored by design
175
+ - Use a public room such as `welcome` for the shortest smoke test
176
+
177
+ 5. **Read logs in this order**
178
+ - Connection: `socket:open`, `auth:ok`, `gateway connected`
179
+ - Delivery: `recv { type: "message" }`
180
+ - Runtime path: `inbound dispatching`, `send:message`
181
+
182
+ That gives you three buckets immediately:
183
+ - no connection
184
+ - connected but no inbound delivery
185
+ - inbound delivery works but runtime/reply path is failing
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-agentchat",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "OpenClaw native channel plugin for AgentChat",
5
5
  "type": "module",
6
6
  "exports": {
@@ -67,6 +67,7 @@ export class AgentChatClient {
67
67
  }
68
68
 
69
69
  sendMessage(channelId: string, content: string) {
70
+ this.debug("send:message", { channelId, length: content.length });
70
71
  this.send({
71
72
  type: "message",
72
73
  id: crypto.randomUUID(),
@@ -80,6 +81,7 @@ export class AgentChatClient {
80
81
  }
81
82
 
82
83
  joinChannel(channelId: string) {
84
+ this.debug("send:join_channel", { channelId });
83
85
  this.send({ type: "join_channel", channel_id: channelId, agent_id: this.agentId });
84
86
  }
85
87
 
@@ -110,6 +112,7 @@ export class AgentChatClient {
110
112
 
111
113
  private handleMessage(raw: string) {
112
114
  const data = JSON.parse(raw) as Record<string, unknown>;
115
+ this.debug("recv", { type: String(data.type ?? "unknown") });
113
116
 
114
117
  switch (data.type) {
115
118
  case "auth_ok":
package/src/gateway.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { appendFileSync } from "node:fs";
1
2
  import type { ChannelAccountSnapshot, ChannelPlugin, PluginRuntime } from "openclaw/plugin-sdk/core";
2
3
  import type { ChannelGatewayContext } from "openclaw/plugin-sdk/channel-contract";
3
4
 
@@ -11,6 +12,10 @@ type AgentChatGatewayAdapter = NonNullable<ChannelPlugin<AgentChatResolvedAccoun
11
12
  type AgentChatGatewayContext = ChannelGatewayContext<AgentChatResolvedAccount>;
12
13
  type PendingStart = Promise<AgentChatGatewayState>;
13
14
 
15
+ function trace(line: string) {
16
+ try { appendFileSync("/tmp/agentchat-plugin-debug.log", `${new Date().toISOString()} ${line}\n`); } catch {}
17
+ }
18
+
14
19
  const pendingStarts = new Map<string, PendingStart>();
15
20
 
16
21
  function log(ctx: unknown, level: "info" | "warn" | "error" | "debug", message: string, meta?: Record<string, unknown>) {
@@ -55,6 +60,13 @@ function getChannelRuntime(ctx: Pick<AgentChatGatewayContext, "channelRuntime">)
55
60
  }
56
61
 
57
62
  async function dispatchInboundMessage(ctx: AgentChatGatewayContext, state: AgentChatGatewayState, message: ChatMessage) {
63
+ trace(`dispatchInboundMessage ${JSON.stringify({ accountId: ctx.accountId, channelId: message.channel_id, senderId: message.sender_id, messageId: message.id })}`);
64
+ log(ctx, "info", "AgentChat inbound received", {
65
+ accountId: ctx.accountId,
66
+ channelId: message.channel_id,
67
+ messageId: message.id,
68
+ senderId: message.sender_id,
69
+ });
58
70
  const runtime = getChannelRuntime(ctx);
59
71
  if (!runtime) {
60
72
  log(ctx, "warn", "AgentChat inbound dropped because channelRuntime is unavailable", {
@@ -73,7 +85,7 @@ async function dispatchInboundMessage(ctx: AgentChatGatewayContext, state: Agent
73
85
  });
74
86
 
75
87
  if (!policy.shouldDispatch) {
76
- log(ctx, "debug", "AgentChat inbound skipped by mention policy", {
88
+ log(ctx, "info", "AgentChat inbound skipped by mention policy", {
77
89
  accountId: ctx.accountId,
78
90
  channelId: message.channel_id,
79
91
  messageId: message.id,
@@ -135,6 +147,12 @@ async function dispatchInboundMessage(ctx: AgentChatGatewayContext, state: Agent
135
147
  },
136
148
  });
137
149
 
150
+ log(ctx, "info", "AgentChat inbound dispatching reply pipeline", {
151
+ accountId: ctx.accountId,
152
+ channelId: message.channel_id,
153
+ messageId: message.id,
154
+ conversationId,
155
+ });
138
156
  await runtime.reply.dispatchReplyWithBufferedBlockDispatcher({
139
157
  ctx: ctxPayload,
140
158
  cfg: ctx.cfg,
@@ -155,10 +173,16 @@ async function dispatchInboundMessage(ctx: AgentChatGatewayContext, state: Agent
155
173
  },
156
174
  },
157
175
  });
176
+ log(ctx, "info", "AgentChat inbound dispatch completed", {
177
+ accountId: ctx.accountId,
178
+ channelId: message.channel_id,
179
+ messageId: message.id,
180
+ });
158
181
  }
159
182
 
160
183
  export const agentChatGateway: AgentChatGatewayAdapter = {
161
184
  async startAccount(ctx: AgentChatGatewayContext) {
185
+ trace(`startAccount ${JSON.stringify({ accountId: ctx.accountId, defaultChannelId: ctx.account.defaultChannelId ?? null })}`);
162
186
  const existing = getGatewayState(ctx.accountId);
163
187
  if (existing) return existing;
164
188
 
@@ -167,15 +191,20 @@ export const agentChatGateway: AgentChatGatewayAdapter = {
167
191
 
168
192
  const startPromise: PendingStart = (async () => {
169
193
  const client = createGatewayClient(ctx.account, (event, meta) => {
170
- log(ctx, "debug", `AgentChat client ${event}`, {
194
+ trace(`client ${event} ${JSON.stringify({ accountId: ctx.accountId, ...meta })}`);
195
+ log(ctx, "info", `AgentChat client ${event}`, {
171
196
  accountId: ctx.accountId,
172
197
  ...meta,
173
198
  });
174
199
  });
175
200
 
176
201
  client.onMessage((message) => {
202
+ trace(`onMessage ${JSON.stringify({ accountId: ctx.accountId, channelId: message.channel_id, senderId: message.sender_id, messageId: message.id })}`);
177
203
  const selfId = ctx.account.agentId ?? ctx.account.accountId;
178
- if (message.sender_id === selfId) return;
204
+ if (message.sender_id === selfId) {
205
+ trace(`self-skip ${JSON.stringify({ accountId: ctx.accountId, selfId, senderId: message.sender_id })}`);
206
+ return;
207
+ }
179
208
  setConnectedStatus(ctx, {
180
209
  lastMessageAt: Date.now(),
181
210
  lastEventAt: Date.now(),