@clwnt/clawnet 0.7.13 → 0.7.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.
- package/package.json +1 -1
- package/src/service.ts +59 -6
- package/src/tools.ts +18 -0
package/package.json
CHANGED
package/src/service.ts
CHANGED
|
@@ -407,8 +407,9 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
|
|
|
407
407
|
const notifyCount = checkData.notify_count ?? (checkData.count + a2aDmCount + sentTaskUpdates);
|
|
408
408
|
|
|
409
409
|
if (checkData.count === 0) {
|
|
410
|
-
// Email inbox clear — release
|
|
411
|
-
|
|
410
|
+
// Email inbox clear — only release delivery lock if nothing else needs notification,
|
|
411
|
+
// otherwise tasks/sent-task-updates still need the lock for throttling.
|
|
412
|
+
if (notifyCount === 0) deliveryLock.delete(account.id);
|
|
412
413
|
return { a2aDmCount, sentTaskUpdates, notifyCount };
|
|
413
414
|
}
|
|
414
415
|
|
|
@@ -428,8 +429,8 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
|
|
|
428
429
|
state.lastInboxNonEmptyAt = new Date();
|
|
429
430
|
api.logger.info(`[clawnet] ${account.id}: ${checkData.count} message(s) waiting (${notifyCount} to notify)`);
|
|
430
431
|
|
|
431
|
-
// Fetch full messages
|
|
432
|
-
const inboxRes = await fetch(`${cfg.baseUrl}/inbox`, { headers });
|
|
432
|
+
// Fetch full messages — request max limit so mark-notified covers everything
|
|
433
|
+
const inboxRes = await fetch(`${cfg.baseUrl}/inbox?limit=200`, { headers });
|
|
433
434
|
if (!inboxRes.ok) {
|
|
434
435
|
throw new Error(`/inbox returned ${inboxRes.status}`);
|
|
435
436
|
}
|
|
@@ -449,6 +450,22 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
|
|
|
449
450
|
|
|
450
451
|
state.counters.messagesSeen += normalized.length;
|
|
451
452
|
|
|
453
|
+
// Mark ALL fetched emails as notified up front — the delivery batch is capped
|
|
454
|
+
// at maxBatchSize, but the nag timer should reset for every message the agent
|
|
455
|
+
// is being alerted about, not just the ones in the batch.
|
|
456
|
+
const allEmailIds = normalized.map((m) => m.id);
|
|
457
|
+
if (allEmailIds.length > 0) {
|
|
458
|
+
try {
|
|
459
|
+
await fetch(`${cfg.baseUrl}/inbox/mark-notified`, {
|
|
460
|
+
method: "POST",
|
|
461
|
+
headers,
|
|
462
|
+
body: JSON.stringify({ message_ids: allEmailIds }),
|
|
463
|
+
});
|
|
464
|
+
} catch {
|
|
465
|
+
// Non-fatal — deliverBatch will still mark its batch after delivery
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
452
469
|
// Add to pending (dedup by ID) and schedule debounced flush
|
|
453
470
|
const existing = pendingMessages.get(account.id) ?? [];
|
|
454
471
|
const existingIds = new Set(existing.map((m) => m.id));
|
|
@@ -477,7 +494,7 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
|
|
|
477
494
|
jsonrpc: "2.0",
|
|
478
495
|
id: `poll-${Date.now()}`,
|
|
479
496
|
method: "tasks/list",
|
|
480
|
-
params: { status: "submitted", limit:
|
|
497
|
+
params: { status: "submitted", limit: 100 },
|
|
481
498
|
};
|
|
482
499
|
const res = await fetch(`${cfg.baseUrl}/a2a`, {
|
|
483
500
|
method: "POST",
|
|
@@ -515,6 +532,24 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
|
|
|
515
532
|
});
|
|
516
533
|
|
|
517
534
|
state.counters.messagesSeen += messages.length;
|
|
535
|
+
|
|
536
|
+
// Mark all fetched tasks as notified up front (same rationale as emails)
|
|
537
|
+
const allTaskIds = messages.map((m) => m.id);
|
|
538
|
+
if (allTaskIds.length > 0) {
|
|
539
|
+
try {
|
|
540
|
+
await fetch(`${cfg.baseUrl}/inbox/mark-notified`, {
|
|
541
|
+
method: "POST",
|
|
542
|
+
headers: {
|
|
543
|
+
Authorization: `Bearer ${resolvedToken}`,
|
|
544
|
+
"Content-Type": "application/json",
|
|
545
|
+
},
|
|
546
|
+
body: JSON.stringify({ task_ids: allTaskIds }),
|
|
547
|
+
});
|
|
548
|
+
} catch {
|
|
549
|
+
// Non-fatal
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
518
553
|
const existing = pendingMessages.get(account.id) ?? [];
|
|
519
554
|
const existingIds = new Set(existing.map((m) => m.id));
|
|
520
555
|
const freshTasks = messages.filter((m) => !existingIds.has(m.id));
|
|
@@ -535,7 +570,7 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
|
|
|
535
570
|
jsonrpc: "2.0",
|
|
536
571
|
id: `sent-poll-${Date.now()}`,
|
|
537
572
|
method: "tasks/list",
|
|
538
|
-
params: { role: "sender", status: "input-required,completed,failed", limit:
|
|
573
|
+
params: { role: "sender", status: "input-required,completed,failed", limit: 100 },
|
|
539
574
|
};
|
|
540
575
|
const res = await fetch(`${cfg.baseUrl}/a2a`, {
|
|
541
576
|
method: "POST",
|
|
@@ -570,6 +605,24 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
|
|
|
570
605
|
});
|
|
571
606
|
|
|
572
607
|
state.counters.messagesSeen += messages.length;
|
|
608
|
+
|
|
609
|
+
// Mark all fetched sent-task updates as notified up front (same rationale as emails)
|
|
610
|
+
const allSentTaskIds = messages.map((m) => m.id);
|
|
611
|
+
if (allSentTaskIds.length > 0) {
|
|
612
|
+
try {
|
|
613
|
+
await fetch(`${cfg.baseUrl}/inbox/mark-notified`, {
|
|
614
|
+
method: "POST",
|
|
615
|
+
headers: {
|
|
616
|
+
Authorization: `Bearer ${resolvedToken}`,
|
|
617
|
+
"Content-Type": "application/json",
|
|
618
|
+
},
|
|
619
|
+
body: JSON.stringify({ task_ids: allSentTaskIds }),
|
|
620
|
+
});
|
|
621
|
+
} catch {
|
|
622
|
+
// Non-fatal
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
573
626
|
const existing = pendingMessages.get(account.id) ?? [];
|
|
574
627
|
const existingIds = new Set(existing.map((m) => m.id));
|
|
575
628
|
const freshUpdates = messages.filter((m) => !existingIds.has(m.id));
|
package/src/tools.ts
CHANGED
|
@@ -468,6 +468,24 @@ export function registerTools(api: any) {
|
|
|
468
468
|
},
|
|
469
469
|
}), { optional: true });
|
|
470
470
|
|
|
471
|
+
api.registerTool((ctx: { agentId?: string; sessionKey?: string }) => ({
|
|
472
|
+
name: "clawnet_email_bulk_status",
|
|
473
|
+
description: toolDesc("clawnet_email_bulk_status", "Set the status of multiple emails at once. Use to archive, read, or snooze many emails in one call instead of one at a time."),
|
|
474
|
+
parameters: {
|
|
475
|
+
type: "object",
|
|
476
|
+
properties: {
|
|
477
|
+
message_ids: { type: "array", items: { type: "string" }, description: "Array of message IDs (e.g. ['msg_abc123', 'msg_def456'])" },
|
|
478
|
+
status: { type: "string", enum: ["archived", "read", "snoozed", "new"], description: "New status to apply to all messages" },
|
|
479
|
+
},
|
|
480
|
+
required: ["message_ids", "status"],
|
|
481
|
+
},
|
|
482
|
+
async execute(_id: string, params: { message_ids: string[]; status: string }) {
|
|
483
|
+
const cfg = loadFreshConfig(api);
|
|
484
|
+
const result = await apiCall(cfg, "PATCH", `/messages/bulk/status`, { message_ids: params.message_ids, status: params.status }, ctx?.agentId, ctx?.sessionKey);
|
|
485
|
+
return textResult(result.data);
|
|
486
|
+
},
|
|
487
|
+
}), { optional: true });
|
|
488
|
+
|
|
471
489
|
api.registerTool((ctx: { agentId?: string; sessionKey?: string }) => ({
|
|
472
490
|
name: "clawnet_inbox_session",
|
|
473
491
|
description: toolDesc("clawnet_inbox_session", "Start an interactive inbox session. Returns your emails with assigned numbers and a triage protocol. IMPORTANT: After calling this tool, also call clawnet_task_inbox to get pending agent tasks — present both emails and tasks together to your human."),
|