@yeego/yeego-openclaw 1.0.2 → 1.1.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/QUICKSTART.md +141 -44
- package/package.json +1 -1
- package/poller.ts +41 -120
- package/src/channel.ts +10 -51
- package/src/sessionMapping.ts +0 -52
- package/yeego-poller +0 -0
package/QUICKSTART.md
CHANGED
|
@@ -1,82 +1,179 @@
|
|
|
1
1
|
# Quick Start Guide
|
|
2
2
|
|
|
3
|
-
## 🚀 Get Started in
|
|
3
|
+
## 🚀 Get Started in 4 Steps
|
|
4
4
|
|
|
5
|
-
### Step 1:
|
|
5
|
+
### Step 1: Install the Plugin
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
openclaw plugins install @yeego/yeego-openclaw
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### Step 2: Get Your Configuration from Yeego App
|
|
6
12
|
|
|
7
13
|
1. Open Yeego mobile app
|
|
8
14
|
2. Go to your profile → Settings
|
|
9
15
|
3. Tap "Connect to OpenClaw" 🦞
|
|
10
|
-
4.
|
|
11
|
-
|
|
12
|
-
You'll get
|
|
13
|
-
|
|
16
|
+
4. Copy the configuration provided
|
|
17
|
+
|
|
18
|
+
You'll get JSON configuration like:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"token": "eyJhbG...",
|
|
23
|
+
"profileId": "abc123...",
|
|
24
|
+
"baseUrl": "https://yeego.app",
|
|
25
|
+
"sidecarUrl": "https://yeego.app/_sidecar",
|
|
26
|
+
"connectUrl": "https://yeego.app/_sidecar/public/openclaw/connect"
|
|
27
|
+
}
|
|
14
28
|
```
|
|
15
|
-
# Yeego OpenClaw Plugin Configuration
|
|
16
|
-
YEEGO_TOKEN=eyJhbG...
|
|
17
|
-
YEEGO_PROFILE_ID=abc123...
|
|
18
|
-
YEEGO_BASE_URL=http://localhost:8091
|
|
19
|
-
YEEGO_PLUGIN_URL=http://localhost:8092/openclaw-plugin
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
### Step 2: Save Configuration
|
|
23
29
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
### Step 3: Configure OpenClaw
|
|
31
|
+
|
|
32
|
+
Add the configuration to `~/.openclaw/openclaw.json`:
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"channels": {
|
|
37
|
+
"yeego": {
|
|
38
|
+
"enabled": true,
|
|
39
|
+
"config": {
|
|
40
|
+
"token": "eyJhbG...",
|
|
41
|
+
"profileId": "abc123...",
|
|
42
|
+
"baseUrl": "https://yeego.app",
|
|
43
|
+
"sidecarUrl": "https://yeego.app/_sidecar",
|
|
44
|
+
"connectUrl": "https://yeego.app/_sidecar/public/openclaw/connect"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"hooks": {
|
|
49
|
+
"token": "YOUR_WEBHOOK_TOKEN_HERE"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
31
52
|
```
|
|
32
53
|
|
|
33
|
-
|
|
54
|
+
**Important**: Set a secure webhook token. This is used for the poller to communicate with OpenClaw Gateway.
|
|
34
55
|
|
|
35
|
-
### Step
|
|
56
|
+
### Step 4: Restart OpenClaw Gateway
|
|
36
57
|
|
|
37
58
|
```bash
|
|
38
|
-
|
|
59
|
+
openclaw gateway restart
|
|
39
60
|
```
|
|
40
61
|
|
|
41
|
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
62
|
+
✅ The plugin will automatically:
|
|
63
|
+
- Connect to your Yeego profile
|
|
64
|
+
- Start polling for new messages
|
|
65
|
+
- Process them through OpenClaw agent
|
|
66
|
+
- Send AI responses back to Yeego
|
|
46
67
|
|
|
47
68
|
## 📱 Test It
|
|
48
69
|
|
|
49
70
|
1. Open Yeego app
|
|
50
71
|
2. Send a message to your AI persona
|
|
51
|
-
3.
|
|
72
|
+
3. OpenClaw will receive and process it
|
|
52
73
|
4. See the AI response appear in the app
|
|
53
74
|
|
|
54
|
-
## 🔧
|
|
75
|
+
## 🔧 How It Works
|
|
76
|
+
|
|
77
|
+
The Yeego plugin uses a **webhook-based architecture**:
|
|
78
|
+
|
|
79
|
+
1. **Poller** detects new messages in Yeego
|
|
80
|
+
2. Sends message to OpenClaw via `/hooks/agent` webhook
|
|
81
|
+
3. **Gateway** processes message through your agent
|
|
82
|
+
4. Calls `channel.sendText` to send response
|
|
83
|
+
5. **Channel** creates message in Yeego via PocketBase API
|
|
84
|
+
|
|
85
|
+
## 🔍 Troubleshooting
|
|
55
86
|
|
|
56
87
|
**No messages being processed?**
|
|
57
|
-
-
|
|
58
|
-
-
|
|
88
|
+
- Check OpenClaw Gateway is running: `openclaw gateway status`
|
|
89
|
+
- Verify webhook token is configured in both places
|
|
90
|
+
- Check logs: `tail -f ~/.openclaw/logs/gateway.log`
|
|
59
91
|
|
|
60
92
|
**Connection errors?**
|
|
61
|
-
- Verify backend is
|
|
93
|
+
- Verify your Yeego backend is accessible
|
|
62
94
|
- Check your token hasn't expired (30 days validity)
|
|
95
|
+
- Test the connection endpoint manually
|
|
96
|
+
|
|
97
|
+
**Webhook authentication failed?**
|
|
98
|
+
- Make sure `hooks.token` in `~/.openclaw/openclaw.json` matches
|
|
99
|
+
- The poller reads this token to authenticate webhook calls
|
|
63
100
|
|
|
64
101
|
**Want to reset?**
|
|
65
102
|
```bash
|
|
66
|
-
|
|
67
|
-
|
|
103
|
+
# Clear processed messages cache
|
|
104
|
+
rm ~/.yeego/processed.json
|
|
105
|
+
|
|
106
|
+
# Clear session mappings
|
|
107
|
+
rm -rf ~/.openclaw/yeego-sessions/
|
|
108
|
+
|
|
109
|
+
# Restart gateway
|
|
110
|
+
openclaw gateway restart
|
|
68
111
|
```
|
|
69
112
|
|
|
70
|
-
##
|
|
113
|
+
## 📝 Configuration Reference
|
|
71
114
|
|
|
72
|
-
|
|
115
|
+
### Yeego Channel Config
|
|
73
116
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
117
|
+
- `token`: JWT token from Yeego (30-day expiry)
|
|
118
|
+
- `profileId`: Your Yeego profile ID
|
|
119
|
+
- `baseUrl`: Yeego backend URL (PocketBase)
|
|
120
|
+
- `sidecarUrl`: Yeego sidecar URL (for connect endpoint)
|
|
121
|
+
- `connectUrl`: Full URL to the connect endpoint
|
|
122
|
+
|
|
123
|
+
### Webhook Config
|
|
124
|
+
|
|
125
|
+
- `hooks.token`: Secure token for webhook authentication
|
|
126
|
+
- Used by poller to call `/hooks/agent`
|
|
127
|
+
- Should be a long random string
|
|
128
|
+
- Example: `openssl rand -hex 32`
|
|
129
|
+
|
|
130
|
+
## 🚀 Advanced
|
|
131
|
+
|
|
132
|
+
### Development Mode
|
|
133
|
+
|
|
134
|
+
For local development with localhost URLs:
|
|
135
|
+
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"channels": {
|
|
139
|
+
"yeego": {
|
|
140
|
+
"config": {
|
|
141
|
+
"baseUrl": "http://localhost:8091",
|
|
142
|
+
"sidecarUrl": "http://localhost:8092",
|
|
143
|
+
"connectUrl": "http://localhost:8092/public/openclaw/connect"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
77
149
|
|
|
78
|
-
|
|
79
|
-
|
|
150
|
+
### Custom Gateway Port
|
|
151
|
+
|
|
152
|
+
If your Gateway runs on a different port:
|
|
153
|
+
|
|
154
|
+
1. Find your Gateway port: `openclaw config get gateway.port`
|
|
155
|
+
2. Update poller code or use environment variable
|
|
156
|
+
|
|
157
|
+
### Multiple Profiles
|
|
158
|
+
|
|
159
|
+
You can configure multiple Yeego profiles by using different channel IDs:
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"channels": {
|
|
164
|
+
"yeego-work": { ... },
|
|
165
|
+
"yeego-personal": { ... }
|
|
166
|
+
}
|
|
167
|
+
}
|
|
80
168
|
```
|
|
81
169
|
|
|
82
|
-
|
|
170
|
+
## 📦 Production Tips
|
|
171
|
+
|
|
172
|
+
- **Security**: Use HTTPS URLs in production
|
|
173
|
+
- **Token Rotation**: Tokens expire after 30 days - regenerate in Yeego app
|
|
174
|
+
- **Monitoring**: Check `~/.openclaw/logs/` for errors
|
|
175
|
+
- **Performance**: Poller polls every 5 seconds - adjust if needed
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
🦞 **Happy chatting with Yeego + OpenClaw!**
|
package/package.json
CHANGED
package/poller.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
|
10
10
|
import { join } from 'path';
|
|
11
11
|
import { homedir } from 'os';
|
|
12
12
|
import { spawn, ChildProcess } from 'child_process';
|
|
13
|
-
import { setSessionConversation
|
|
13
|
+
import { setSessionConversation } from './src/sessionMapping.js';
|
|
14
14
|
|
|
15
15
|
// ============================================================================
|
|
16
16
|
// Types
|
|
@@ -172,52 +172,20 @@ class YeegoPoller {
|
|
|
172
172
|
message: PocketBaseMessage,
|
|
173
173
|
conversation: PocketBaseConversation
|
|
174
174
|
): Promise<void> {
|
|
175
|
-
let placeholderId: string | null = null;
|
|
176
|
-
|
|
177
175
|
try {
|
|
178
176
|
console.log(`[Yeego] Processing message: ${message.id}`);
|
|
179
177
|
|
|
180
|
-
//
|
|
181
|
-
const placeholder = await this.pb.collection('profile_chat_messages').create({
|
|
182
|
-
conversation: conversation.id,
|
|
183
|
-
message: '',
|
|
184
|
-
by: 'persona',
|
|
185
|
-
is_ai_generated: true,
|
|
186
|
-
has_finished_generating: false,
|
|
187
|
-
source: 'openclaw',
|
|
188
|
-
});
|
|
189
|
-
placeholderId = placeholder.id;
|
|
190
|
-
console.log(`[Yeego] Created placeholder: ${placeholderId}`);
|
|
191
|
-
|
|
192
|
-
// Save placeholder ID in memory cache for channel to use
|
|
193
|
-
setPlaceholderId(conversation.id, placeholderId);
|
|
194
|
-
|
|
195
|
-
// Save session mapping before calling OpenClaw
|
|
178
|
+
// Save session mapping
|
|
196
179
|
this.saveSessionMapping(conversation.id);
|
|
197
180
|
|
|
198
|
-
// Call OpenClaw
|
|
199
|
-
await this.
|
|
181
|
+
// Call OpenClaw via webhook API
|
|
182
|
+
await this.sendToOpenClawWebhook(message, conversation);
|
|
200
183
|
|
|
201
|
-
|
|
202
|
-
setTimeout(() => {
|
|
203
|
-
this.setSessionMessageChannel(conversation.id, 'yeego');
|
|
204
|
-
}, SESSION_METADATA_DELAY_MS);
|
|
205
|
-
|
|
206
|
-
console.log(`[Yeego] ✓ Processed message ${message.id}`);
|
|
184
|
+
console.log(`[Yeego] ✓ Sent message to OpenClaw webhook`);
|
|
207
185
|
} catch (error) {
|
|
208
186
|
console.error(`[Yeego] Error processing message:`, error);
|
|
209
187
|
|
|
210
|
-
//
|
|
211
|
-
if (placeholderId) {
|
|
212
|
-
try {
|
|
213
|
-
await this.pb.collection('profile_chat_messages').delete(placeholderId);
|
|
214
|
-
console.log(`[Yeego] Deleted placeholder: ${placeholderId}`);
|
|
215
|
-
} catch (deleteError) {
|
|
216
|
-
console.error(`[Yeego] Failed to delete placeholder:`, deleteError);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// Create error message
|
|
188
|
+
// Create error message if webhook call fails
|
|
221
189
|
try {
|
|
222
190
|
await this.pb.collection('profile_chat_messages').create({
|
|
223
191
|
conversation: conversation.id,
|
|
@@ -240,103 +208,56 @@ class YeegoPoller {
|
|
|
240
208
|
setSessionConversation(`yeego:${conversationId}`, conversationId);
|
|
241
209
|
}
|
|
242
210
|
|
|
243
|
-
private async
|
|
211
|
+
private async sendToOpenClawWebhook(
|
|
244
212
|
message: PocketBaseMessage,
|
|
245
213
|
conversation: PocketBaseConversation
|
|
246
214
|
): Promise<void> {
|
|
247
|
-
console.log(`[Yeego]
|
|
248
|
-
|
|
249
|
-
const proc = spawn('openclaw', [
|
|
250
|
-
'agent',
|
|
251
|
-
'--session-id',
|
|
252
|
-
conversation.id,
|
|
253
|
-
'--reply-channel',
|
|
254
|
-
'yeego',
|
|
255
|
-
'--reply-to',
|
|
256
|
-
conversation.id,
|
|
257
|
-
'--message',
|
|
258
|
-
message.message,
|
|
259
|
-
], {
|
|
260
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
261
|
-
});
|
|
215
|
+
console.log(`[Yeego] Sending message to OpenClaw webhook for conversation: ${conversation.id}`);
|
|
262
216
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
if (exitCode !== 0) {
|
|
266
|
-
console.error(`[Yeego] OpenClaw agent failed with exit code ${exitCode}`);
|
|
267
|
-
console.error(`[Yeego] stderr:`, stderr);
|
|
268
|
-
throw new Error(`OpenClaw agent failed: ${stderr}`);
|
|
269
|
-
}
|
|
217
|
+
// Get webhook token from OpenClaw config
|
|
218
|
+
const webhookToken = await this.getOpenClawWebhookToken();
|
|
270
219
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
console.log(`[Yeego] stdout:`, stdout);
|
|
220
|
+
if (!webhookToken) {
|
|
221
|
+
throw new Error('No webhook token configured in OpenClaw. Please set hooks.token in ~/.openclaw/openclaw.json');
|
|
274
222
|
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
private captureProcessOutput(proc: ChildProcess): Promise<{
|
|
278
|
-
stdout: string;
|
|
279
|
-
stderr: string;
|
|
280
|
-
exitCode: number;
|
|
281
|
-
}> {
|
|
282
|
-
return new Promise((resolve) => {
|
|
283
|
-
let stdout = '';
|
|
284
|
-
let stderr = '';
|
|
285
|
-
|
|
286
|
-
proc.stdout?.on('data', (data) => {
|
|
287
|
-
stdout += data.toString();
|
|
288
|
-
});
|
|
289
223
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
224
|
+
// Call OpenClaw webhook API
|
|
225
|
+
// Note: channel should be just "yeego", the conversation ID will be passed via session routing
|
|
226
|
+
const response = await fetch('http://localhost:4242/hooks/agent', {
|
|
227
|
+
method: 'POST',
|
|
228
|
+
headers: {
|
|
229
|
+
'Content-Type': 'application/json',
|
|
230
|
+
'Authorization': `Bearer ${webhookToken}`,
|
|
231
|
+
},
|
|
232
|
+
body: JSON.stringify({
|
|
233
|
+
message: message.message,
|
|
234
|
+
sessionKey: conversation.id,
|
|
235
|
+
channel: 'yeego',
|
|
236
|
+
}),
|
|
297
237
|
});
|
|
298
|
-
}
|
|
299
238
|
|
|
239
|
+
if (!response.ok) {
|
|
240
|
+
const errorText = await response.text();
|
|
241
|
+
console.error(`[Yeego] Webhook call failed: ${response.status} ${errorText}`);
|
|
242
|
+
throw new Error(`OpenClaw webhook failed: ${response.status} ${errorText}`);
|
|
243
|
+
}
|
|
300
244
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
// --------------------------------------------------------------------------
|
|
245
|
+
console.log(`[Yeego] Webhook call successful (${response.status})`);
|
|
246
|
+
}
|
|
304
247
|
|
|
305
|
-
|
|
306
|
-
* Sets messageChannel in OpenClaw session metadata file.
|
|
307
|
-
* This is a workaround because --reply-channel CLI flag doesn't set the session's messageChannel property.
|
|
308
|
-
*/
|
|
309
|
-
private setSessionMessageChannel(sessionId: string, channel: string): boolean {
|
|
248
|
+
private async getOpenClawWebhookToken(): Promise<string | null> {
|
|
310
249
|
try {
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
console.log(`[Yeego] Session file not found yet: ${sessionFile}`);
|
|
316
|
-
return false;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
const lines = readFileSync(sessionFile, 'utf-8')
|
|
320
|
-
.split('\n')
|
|
321
|
-
.filter(l => l.trim());
|
|
322
|
-
|
|
323
|
-
if (lines.length === 0) {
|
|
324
|
-
return false;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
const firstLine = JSON.parse(lines[0]);
|
|
328
|
-
if (firstLine.type === 'session') {
|
|
329
|
-
firstLine.messageChannel = channel;
|
|
330
|
-
lines[0] = JSON.stringify(firstLine);
|
|
331
|
-
writeFileSync(sessionFile, lines.join('\n') + '\n', 'utf-8');
|
|
332
|
-
console.log(`[Yeego] ✓ Set messageChannel="${channel}" for session ${sessionId}`);
|
|
333
|
-
return true;
|
|
250
|
+
const configPath = join(homedir(), '.openclaw', 'openclaw.json');
|
|
251
|
+
if (!existsSync(configPath)) {
|
|
252
|
+
console.error(`[Yeego] OpenClaw config not found: ${configPath}`);
|
|
253
|
+
return null;
|
|
334
254
|
}
|
|
335
255
|
|
|
336
|
-
|
|
256
|
+
const config = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
257
|
+
return config?.hooks?.token || null;
|
|
337
258
|
} catch (error) {
|
|
338
|
-
console.error(`[Yeego] Failed to
|
|
339
|
-
return
|
|
259
|
+
console.error(`[Yeego] Failed to read OpenClaw config:`, error);
|
|
260
|
+
return null;
|
|
340
261
|
}
|
|
341
262
|
}
|
|
342
263
|
|
package/src/channel.ts
CHANGED
|
@@ -22,7 +22,6 @@ import { createYeegoTools } from "./tools/index.js";
|
|
|
22
22
|
import {
|
|
23
23
|
setSessionConversation,
|
|
24
24
|
getSessionConversation,
|
|
25
|
-
consumePlaceholderId,
|
|
26
25
|
} from "./sessionMapping.js";
|
|
27
26
|
|
|
28
27
|
// ============================================================================
|
|
@@ -309,57 +308,17 @@ export const yeegoPlugin: ChannelPlugin<YeegoConfig> = {
|
|
|
309
308
|
const pb = new PocketBase(config.base_url);
|
|
310
309
|
pb.authStore.save(config.token);
|
|
311
310
|
|
|
312
|
-
//
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
} catch (error) {
|
|
322
|
-
console.warn(`[Yeego] Cached placeholder not found, falling back to query`);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// Fallback: search for placeholder message if cache miss
|
|
327
|
-
if (!placeholderMessage) {
|
|
328
|
-
try {
|
|
329
|
-
const recentMessages = await pb.collection('profile_chat_messages').getList(1, 1, {
|
|
330
|
-
filter: `conversation="${conversationId}" && by="persona" && has_finished_generating=false && source="openclaw"`,
|
|
331
|
-
sort: '-created',
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
if (recentMessages.items.length > 0) {
|
|
335
|
-
placeholderMessage = recentMessages.items[0];
|
|
336
|
-
console.log(`[Yeego] Found placeholder via query: ${placeholderMessage.id}`);
|
|
337
|
-
}
|
|
338
|
-
} catch (error) {
|
|
339
|
-
console.log(`[Yeego] No placeholder found, will create new message`);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
311
|
+
// Simply create a new message - no placeholder logic needed
|
|
312
|
+
const message = await pb.collection('profile_chat_messages').create({
|
|
313
|
+
conversation: conversationId,
|
|
314
|
+
message: text,
|
|
315
|
+
by: 'persona',
|
|
316
|
+
is_ai_generated: true,
|
|
317
|
+
has_finished_generating: true,
|
|
318
|
+
source: 'openclaw',
|
|
319
|
+
});
|
|
342
320
|
|
|
343
|
-
|
|
344
|
-
if (placeholderMessage) {
|
|
345
|
-
// Update existing placeholder
|
|
346
|
-
message = await pb.collection('profile_chat_messages').update(placeholderMessage.id, {
|
|
347
|
-
message: text,
|
|
348
|
-
has_finished_generating: true,
|
|
349
|
-
});
|
|
350
|
-
console.log(`[Yeego] Updated placeholder: ${message.id}`);
|
|
351
|
-
} else {
|
|
352
|
-
// Create new message if no placeholder exists
|
|
353
|
-
message = await pb.collection('profile_chat_messages').create({
|
|
354
|
-
conversation: conversationId,
|
|
355
|
-
message: text,
|
|
356
|
-
by: 'persona',
|
|
357
|
-
is_ai_generated: true,
|
|
358
|
-
has_finished_generating: true,
|
|
359
|
-
source: 'openclaw',
|
|
360
|
-
});
|
|
361
|
-
console.log(`[Yeego] Created new message: ${message.id}`);
|
|
362
|
-
}
|
|
321
|
+
console.log(`[Yeego] Created message: ${message.id}`);
|
|
363
322
|
|
|
364
323
|
return {
|
|
365
324
|
channel: "yeego",
|
package/src/sessionMapping.ts
CHANGED
|
@@ -56,58 +56,6 @@ function saveMappings(mappings: SessionMappings): void {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
// ============================================================================
|
|
60
|
-
// In-Memory Placeholder Cache
|
|
61
|
-
// ============================================================================
|
|
62
|
-
|
|
63
|
-
// Cache placeholder message IDs temporarily (in memory only)
|
|
64
|
-
// Use array to support multiple concurrent messages per conversation
|
|
65
|
-
const placeholderCache = new Map<string, string[]>();
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Sets the placeholder message ID for a conversation (in-memory cache).
|
|
69
|
-
* This is used to pass the placeholder ID from poller to channel.
|
|
70
|
-
* Supports multiple placeholders per conversation for concurrent messages.
|
|
71
|
-
*/
|
|
72
|
-
export function setPlaceholderId(conversationId: string, placeholderId: string): void {
|
|
73
|
-
const existing = placeholderCache.get(conversationId) || [];
|
|
74
|
-
existing.push(placeholderId);
|
|
75
|
-
placeholderCache.set(conversationId, existing);
|
|
76
|
-
|
|
77
|
-
// Auto-expire after 30 seconds to avoid memory leaks
|
|
78
|
-
setTimeout(() => {
|
|
79
|
-
const current = placeholderCache.get(conversationId);
|
|
80
|
-
if (current) {
|
|
81
|
-
const filtered = current.filter(id => id !== placeholderId);
|
|
82
|
-
if (filtered.length === 0) {
|
|
83
|
-
placeholderCache.delete(conversationId);
|
|
84
|
-
} else {
|
|
85
|
-
placeholderCache.set(conversationId, filtered);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}, 30000);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Gets and removes the oldest placeholder message ID for a conversation (FIFO).
|
|
93
|
-
* This ensures concurrent messages are handled in order.
|
|
94
|
-
*/
|
|
95
|
-
export function consumePlaceholderId(conversationId: string): string | undefined {
|
|
96
|
-
const placeholders = placeholderCache.get(conversationId);
|
|
97
|
-
if (!placeholders || placeholders.length === 0) {
|
|
98
|
-
return undefined;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Remove and return the first (oldest) placeholder
|
|
102
|
-
const placeholderId = placeholders.shift();
|
|
103
|
-
|
|
104
|
-
if (placeholders.length === 0) {
|
|
105
|
-
placeholderCache.delete(conversationId);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return placeholderId;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
59
|
// ============================================================================
|
|
112
60
|
// Public API
|
|
113
61
|
// ============================================================================
|
package/yeego-poller
CHANGED
|
Binary file
|