@clwnt/clawnet 0.7.14 → 0.7.16

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.
@@ -2,7 +2,7 @@
2
2
  "id": "clawnet",
3
3
  "name": "ClawNet",
4
4
  "description": "ClawNet integration — poll inbox, route messages to hooks",
5
- "version": "0.4.0",
5
+ "version": "0.7.16",
6
6
  "skills": ["skills"],
7
7
  "configSchema": {
8
8
  "type": "object",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clwnt/clawnet",
3
- "version": "0.7.14",
3
+ "version": "0.7.16",
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
@@ -135,9 +135,6 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
135
135
 
136
136
  // --- Batch delivery ---
137
137
 
138
- // Per-account auth context for mark-notified calls from deliverBatch
139
- const accountAuth = new Map<string, { token: string; baseUrl: string }>();
140
-
141
138
  async function deliverBatch(accountId: string, agentId: string, messages: InboxMessage[]) {
142
139
  if (messages.length === 0) return;
143
140
 
@@ -179,36 +176,8 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
179
176
  `[clawnet] ${accountId}: delivered ${messages.length} message(s) to ${agentId} via ${freshCfg.deliveryMethod}`,
180
177
  );
181
178
 
182
- // Post-delivery: mark items as notified + mark A2A tasks as working
183
- const auth = accountAuth.get(accountId);
184
- if (auth) {
185
- const emailIds = messages.filter((m) => m.type === "email").map((m) => m.id);
186
- const taskIds = messages.filter((m) => m.type === "task").map((m) => m.id);
187
-
188
- // Mark notified (non-fatal)
189
- if (emailIds.length > 0 || taskIds.length > 0) {
190
- try {
191
- const markRes = await fetch(`${auth.baseUrl}/inbox/mark-notified`, {
192
- method: "POST",
193
- headers: { Authorization: `Bearer ${auth.token}`, "Content-Type": "application/json" },
194
- body: JSON.stringify({
195
- ...(emailIds.length > 0 ? { message_ids: emailIds } : {}),
196
- ...(taskIds.length > 0 ? { task_ids: taskIds } : {}),
197
- }),
198
- });
199
- if (markRes.ok) {
200
- const markData = await markRes.json().catch(() => ({})) as Record<string, unknown>;
201
- api.logger.info(`[clawnet] ${accountId}: marked notified (${markData.marked_messages ?? 0} msgs, ${markData.marked_tasks ?? 0} tasks)`);
202
- } else {
203
- const errText = await markRes.text().catch(() => "");
204
- api.logger.warn(`[clawnet] ${accountId}: mark-notified returned ${markRes.status}: ${errText}`);
205
- }
206
- } catch (err: any) {
207
- api.logger.warn(`[clawnet] ${accountId}: mark-notified failed (non-fatal): ${err.message}`);
208
- }
209
- }
210
-
211
- }
179
+ // Notification tracking is now server-side (agent-level last_nagged_at).
180
+ // No mark-notified call needed.
212
181
  } catch (err: any) {
213
182
  state.lastError = { message: err.message, at: new Date() };
214
183
  state.counters.errors++;
@@ -341,9 +310,6 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
341
310
  return { a2aDmCount: 0, sentTaskUpdates: 0, notifyCount: 0 };
342
311
  }
343
312
 
344
- // Store auth context for deliverBatch to use for mark-notified calls
345
- accountAuth.set(account.id, { token: resolvedToken, baseUrl: cfg.baseUrl });
346
-
347
313
  const headers = {
348
314
  Authorization: `Bearer ${resolvedToken}`,
349
315
  "Content-Type": "application/json",
@@ -429,8 +395,8 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
429
395
  state.lastInboxNonEmptyAt = new Date();
430
396
  api.logger.info(`[clawnet] ${account.id}: ${checkData.count} message(s) waiting (${notifyCount} to notify)`);
431
397
 
432
- // Fetch full messages request max limit so mark-notified covers everything
433
- const inboxRes = await fetch(`${cfg.baseUrl}/inbox?limit=200`, { headers });
398
+ // Fetch messages for delivery (notification tracking is server-side via last_nagged_at)
399
+ const inboxRes = await fetch(`${cfg.baseUrl}/inbox`, { headers });
434
400
  if (!inboxRes.ok) {
435
401
  throw new Error(`/inbox returned ${inboxRes.status}`);
436
402
  }
@@ -450,21 +416,7 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
450
416
 
451
417
  state.counters.messagesSeen += normalized.length;
452
418
 
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
- }
419
+ // Server-side /inbox/check auto-marks all notifiable itemsno separate call needed
468
420
 
469
421
  // Add to pending (dedup by ID) and schedule debounced flush
470
422
  const existing = pendingMessages.get(account.id) ?? [];
@@ -516,7 +468,7 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
516
468
  api.logger.info(`[clawnet] ${account.id}: ${tasks.length} A2A task(s) to deliver`);
517
469
 
518
470
  // Convert A2A tasks to the message format for delivery
519
- // mark-notified happens post-delivery in deliverBatch
471
+ // Notification tracking is server-side via last_nagged_at
520
472
  const messages: InboxMessage[] = tasks.map((task) => {
521
473
  const history = task.history as Array<{ role: string; parts: Array<{ text?: string }> }> ?? [];
522
474
  const lastMsg = history[history.length - 1];
@@ -533,22 +485,7 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
533
485
 
534
486
  state.counters.messagesSeen += messages.length;
535
487
 
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
- }
488
+ // Server-side /inbox/check auto-marks all notifiable items no separate call needed
552
489
 
553
490
  const existing = pendingMessages.get(account.id) ?? [];
554
491
  const existingIds = new Set(existing.map((m) => m.id));
@@ -606,22 +543,7 @@ export function createClawnetService(params: { api: any; cfg: ClawnetConfig }) {
606
543
 
607
544
  state.counters.messagesSeen += messages.length;
608
545
 
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
- }
546
+ // Server-side /inbox/check auto-marks all notifiable items no separate call needed
625
547
 
626
548
  const existing = pendingMessages.get(account.id) ?? [];
627
549
  const existingIds = new Set(existing.map((m) => 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"],
@@ -475,7 +475,7 @@ export function registerTools(api: any) {
475
475
  type: "object",
476
476
  properties: {
477
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" },
478
+ status: { type: "string", enum: ["archived", "read", "snoozed"], description: "New status to apply to all messages" },
479
479
  },
480
480
  required: ["message_ids", "status"],
481
481
  },