@clwnt/clawnet 0.5.0 → 0.5.2
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/package.json +1 -1
- package/src/cli.ts +9 -1
- package/src/service.ts +31 -5
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -424,6 +424,7 @@ export function registerClawnetCli(params: { program: Command; api: any; cfg: Cl
|
|
|
424
424
|
// Upsert account
|
|
425
425
|
const accounts: any[] = pc.accounts ?? [];
|
|
426
426
|
const existingIdx = accounts.findIndex((a: any) => a.agentId === agentId || a.openclawAgentId === targetAgent);
|
|
427
|
+
const oldAccountId = existingIdx >= 0 ? accounts[existingIdx].id : null;
|
|
427
428
|
const newAccount = {
|
|
428
429
|
id: accountId,
|
|
429
430
|
token: `\${${envVarName}}`,
|
|
@@ -454,8 +455,15 @@ export function registerClawnetCli(params: { program: Command; api: any; cfg: Cl
|
|
|
454
455
|
"hook:",
|
|
455
456
|
);
|
|
456
457
|
|
|
457
|
-
//
|
|
458
|
+
// Remove old mapping if account ID changed (e.g., re-registered with new handle)
|
|
458
459
|
let mappings = cfg.hooks.mappings ?? [];
|
|
460
|
+
if (oldAccountId && oldAccountId !== accountId) {
|
|
461
|
+
const oldMappingId = `clawnet-${oldAccountId}`;
|
|
462
|
+
mappings = mappings.filter((m: any) => String(m?.id ?? "") !== oldMappingId);
|
|
463
|
+
console.log(` Removed stale mapping: ${oldMappingId}`);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// Upsert per-account clawnet mapping
|
|
459
467
|
mappings = upsertMapping(mappings, buildClawnetMapping(accountId, channel, targetAgent));
|
|
460
468
|
cfg.hooks.mappings = mappings;
|
|
461
469
|
|
package/src/service.ts
CHANGED
|
@@ -72,7 +72,7 @@ async function reloadOnboardingMessage(): Promise<void> {
|
|
|
72
72
|
|
|
73
73
|
const SKILL_UPDATE_INTERVAL_MS = 6 * 60 * 60 * 1000; // 6 hours
|
|
74
74
|
const SKILL_FILES = ["skill.json", "api-reference.md", "inbox-handler.md", "capabilities.json", "hook-template.txt", "tool-descriptions.json", "onboarding-message.txt"];
|
|
75
|
-
const PLUGIN_VERSION = "0.5.
|
|
75
|
+
const PLUGIN_VERSION = "0.5.2"; // Reported to server via PATCH /me every 6h
|
|
76
76
|
|
|
77
77
|
// --- Service ---
|
|
78
78
|
|
|
@@ -88,6 +88,10 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
|
|
|
88
88
|
// Per-account concurrency lock: only 1 LLM run at a time per account
|
|
89
89
|
const accountBusy = new Set<string>();
|
|
90
90
|
|
|
91
|
+
// Per-account delivery lock: skip re-delivery while LLM is processing
|
|
92
|
+
const deliveryLock = new Map<string, Date>(); // accountId -> lock expires at
|
|
93
|
+
const DELIVERY_LOCK_TTL_MS = 10 * 60 * 1000; // 10 minutes
|
|
94
|
+
|
|
91
95
|
// Per-account debounce: accumulate messages before sending
|
|
92
96
|
const pendingMessages = new Map<string, InboxMessage[]>();
|
|
93
97
|
const debounceTimers = new Map<string, ReturnType<typeof setTimeout>>();
|
|
@@ -222,6 +226,7 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
|
|
|
222
226
|
|
|
223
227
|
state.counters.batchesSent++;
|
|
224
228
|
state.counters.delivered += messages.length;
|
|
229
|
+
deliveryLock.set(accountId, new Date(Date.now() + DELIVERY_LOCK_TTL_MS));
|
|
225
230
|
api.logger.info(
|
|
226
231
|
`[clawnet] ${accountId}: delivered ${messages.length} message(s) to ${agentId}`,
|
|
227
232
|
);
|
|
@@ -329,7 +334,19 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
|
|
|
329
334
|
}
|
|
330
335
|
}
|
|
331
336
|
|
|
332
|
-
if (checkData.count === 0)
|
|
337
|
+
if (checkData.count === 0) {
|
|
338
|
+
// Inbox clear — release any delivery lock (agent finished processing)
|
|
339
|
+
deliveryLock.delete(account.id);
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Skip if a recent webhook delivery is still being processed by the LLM.
|
|
344
|
+
// TTL-based lock: after successful POST, lock for 10 min to let the agent work.
|
|
345
|
+
const lockUntil = deliveryLock.get(account.id);
|
|
346
|
+
if (lockUntil && new Date() < lockUntil) {
|
|
347
|
+
api.logger.debug?.(`[clawnet] ${account.id}: ${checkData.count} message(s) waiting (delivery lock active, skipping)`);
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
333
350
|
|
|
334
351
|
state.lastInboxNonEmptyAt = new Date();
|
|
335
352
|
api.logger.info(`[clawnet] ${account.id}: ${checkData.count} message(s) waiting`);
|
|
@@ -339,15 +356,24 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
|
|
|
339
356
|
if (!inboxRes.ok) {
|
|
340
357
|
throw new Error(`/inbox returned ${inboxRes.status}`);
|
|
341
358
|
}
|
|
342
|
-
const inboxData = (await inboxRes.json()) as { messages:
|
|
359
|
+
const inboxData = (await inboxRes.json()) as { messages: Array<Record<string, any>> };
|
|
343
360
|
|
|
344
361
|
if (inboxData.messages.length === 0) return;
|
|
345
362
|
|
|
346
|
-
|
|
363
|
+
// Normalize API field names: API returns "from", plugin uses "from_agent"
|
|
364
|
+
const normalized: InboxMessage[] = inboxData.messages.map((m) => ({
|
|
365
|
+
id: m.id,
|
|
366
|
+
from_agent: m.from_agent ?? m.from ?? "",
|
|
367
|
+
content: m.content,
|
|
368
|
+
subject: m.subject,
|
|
369
|
+
created_at: m.created_at,
|
|
370
|
+
}));
|
|
371
|
+
|
|
372
|
+
state.counters.messagesSeen += normalized.length;
|
|
347
373
|
|
|
348
374
|
// Add to pending and schedule debounced flush
|
|
349
375
|
const existing = pendingMessages.get(account.id) ?? [];
|
|
350
|
-
pendingMessages.set(account.id, [...existing, ...
|
|
376
|
+
pendingMessages.set(account.id, [...existing, ...normalized]);
|
|
351
377
|
scheduleFlush(account.id, account.agentId);
|
|
352
378
|
}
|
|
353
379
|
|