@clwnt/clawnet 0.7.13 → 0.7.15

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clwnt/clawnet",
3
- "version": "0.7.13",
3
+ "version": "0.7.15",
4
4
  "type": "module",
5
5
  "description": "ClawNet integration for OpenClaw — poll inbox, route messages to hooks",
6
6
  "files": [
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 any delivery lock (agent finished processing)
411
- deliveryLock.delete(account.id);
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,7 +429,7 @@ 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
+ // Fetch messages for delivery (mark-notified handled server-side in /inbox/check)
432
433
  const inboxRes = await fetch(`${cfg.baseUrl}/inbox`, { headers });
433
434
  if (!inboxRes.ok) {
434
435
  throw new Error(`/inbox returned ${inboxRes.status}`);
@@ -449,6 +450,8 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
449
450
 
450
451
  state.counters.messagesSeen += normalized.length;
451
452
 
453
+ // Server-side /inbox/check auto-marks all notifiable items — no separate call needed
454
+
452
455
  // Add to pending (dedup by ID) and schedule debounced flush
453
456
  const existing = pendingMessages.get(account.id) ?? [];
454
457
  const existingIds = new Set(existing.map((m) => m.id));
@@ -477,7 +480,7 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
477
480
  jsonrpc: "2.0",
478
481
  id: `poll-${Date.now()}`,
479
482
  method: "tasks/list",
480
- params: { status: "submitted", limit: 50 },
483
+ params: { status: "submitted", limit: 100 },
481
484
  };
482
485
  const res = await fetch(`${cfg.baseUrl}/a2a`, {
483
486
  method: "POST",
@@ -515,6 +518,9 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
515
518
  });
516
519
 
517
520
  state.counters.messagesSeen += messages.length;
521
+
522
+ // Server-side /inbox/check auto-marks all notifiable items — no separate call needed
523
+
518
524
  const existing = pendingMessages.get(account.id) ?? [];
519
525
  const existingIds = new Set(existing.map((m) => m.id));
520
526
  const freshTasks = messages.filter((m) => !existingIds.has(m.id));
@@ -535,7 +541,7 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
535
541
  jsonrpc: "2.0",
536
542
  id: `sent-poll-${Date.now()}`,
537
543
  method: "tasks/list",
538
- params: { role: "sender", status: "input-required,completed,failed", limit: 50 },
544
+ params: { role: "sender", status: "input-required,completed,failed", limit: 100 },
539
545
  };
540
546
  const res = await fetch(`${cfg.baseUrl}/a2a`, {
541
547
  method: "POST",
@@ -570,6 +576,9 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
570
576
  });
571
577
 
572
578
  state.counters.messagesSeen += messages.length;
579
+
580
+ // Server-side /inbox/check auto-marks all notifiable items — no separate call needed
581
+
573
582
  const existing = pendingMessages.get(account.id) ?? [];
574
583
  const existingIds = new Set(existing.map((m) => m.id));
575
584
  const freshUpdates = messages.filter((m) => !existingIds.has(m.id));
package/src/tools.ts CHANGED
@@ -454,7 +454,7 @@ export function registerTools(api: any) {
454
454
  type: "object",
455
455
  properties: {
456
456
  message_id: { type: "string", description: "The message ID (e.g. msg_abc123)" },
457
- status: { type: "string", enum: ["archived", "read", "snoozed", "new", "handled", "waiting"], description: "New status (use 'archived' or 'read'; 'handled'/'waiting' accepted for backward compat)" },
457
+ status: { type: "string", enum: ["archived", "read", "snoozed", "handled", "waiting"], description: "New status (use 'archived' or 'read'; 'handled'/'waiting' accepted for backward compat)" },
458
458
  snoozed_until: { type: "string", description: "ISO 8601 timestamp (required when status is 'snoozed')" },
459
459
  },
460
460
  required: ["message_id", "status"],
@@ -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"], 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."),