@gholl-studio/pier-connector 0.2.3 → 0.2.5

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +33 -30
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gholl-studio/pier-connector",
3
3
  "author": "gholl",
4
- "version": "0.2.3",
4
+ "version": "0.2.5",
5
5
  "description": "OpenClaw plugin that connects to the Pier job marketplace. Automatically fetches, executes, and reports distributed tasks for rewards.",
6
6
  "type": "module",
7
7
  "main": "src/index.js",
package/src/index.js CHANGED
@@ -598,8 +598,8 @@ export default function register(api) {
598
598
  durable_name: durableName,
599
599
  filter_subject: msgSubject,
600
600
  deliver_policy: DeliverPolicy.New, // Reverted to New to stop message storms (BUG-27)
601
- ack_policy: AckPolicy.Explicit,
602
- ack_wait: 30000,
601
+ ack_policy: AckPolicy.Explicit, // Explicit ACK is crucial for deduplication
602
+ ack_wait: 1000 * 60 * 60, // 1 hour ACK wait to allow for long processing (BUG-30)
603
603
  });
604
604
  const consumer = await js.consumers.get(streamName, cInfo.name);
605
605
 
@@ -609,16 +609,23 @@ export default function register(api) {
609
609
  (async () => {
610
610
  logger.info(`[pier-connector] 👂 Monitoring chat subject ${msgSubject} (Durable: ${durableName})`);
611
611
 
612
- let isProcessing = false;
612
+ const processedMessages = new Set();
613
+
613
614
  for await (const msg of iter) {
614
615
  try {
615
616
  const rawMsg = new TextDecoder().decode(msg.data);
616
617
  let msgPayload;
617
618
  try {
618
619
  msgPayload = JSON.parse(rawMsg);
619
- } catch (e) {
620
+ } catch (e) {
621
+ msg.ack();
622
+ continue;
623
+ }
624
+
625
+ // Deduplication (prevents loops if NATS redelivers)
626
+ if (msgPayload.id && processedMessages.has(msgPayload.id)) {
620
627
  msg.ack();
621
- continue;
628
+ continue;
622
629
  }
623
630
 
624
631
  // Ignore my own messages
@@ -632,8 +639,8 @@ export default function register(api) {
632
639
  continue;
633
640
  }
634
641
 
635
- // Send read receipt back
636
- if (js && msgPayload.id) {
642
+ // Send read receipt back (ONLY for actual messages from users, BUG-31)
643
+ if (js && msgPayload.id && !msgPayload.type && msgPayload.sender_id !== config.nodeId) {
637
644
  try {
638
645
  const replySubject = `jobs.job.${jobId}.msg`;
639
646
  await js.publish(replySubject, new TextEncoder().encode(JSON.stringify({
@@ -641,9 +648,8 @@ export default function register(api) {
641
648
  msg_id: msgPayload.id,
642
649
  reader_id: config.nodeId
643
650
  })));
644
- logger.debug(`[pier-connector] 👁️ Sent read receipt for message ${msgPayload.id}`);
645
651
  } catch (err) {
646
- logger.error(`[pier-connector] Failed to send read receipt: ${err.message}`);
652
+ // Silently ignore receipt failures
647
653
  }
648
654
  }
649
655
 
@@ -651,40 +657,37 @@ export default function register(api) {
651
657
  const senderCore = msgPayload.sender_id;
652
658
 
653
659
  if (!content) {
654
- logger.warn(`[pier-connector] ⚠️ Skipping message from ${senderCore} for ${jobId}: Empty content`);
655
660
  msg.ack();
656
661
  continue;
657
662
  }
658
663
 
659
- if (isProcessing) {
660
- logger.warn(`[pier-connector] ⏳ Throttling: Agent already processing for job ${jobId}`);
661
- msg.nak();
662
- continue;
663
- }
664
-
665
664
  logger.info(`[pier-connector] 📥 Incoming chat: [${jobId}] sender=${senderCore} "${truncate(content, 40)}"`);
666
665
 
666
+ if (msgPayload.id) processedMessages.add(msgPayload.id);
667
+
668
+ // ACK IMMEDIATELY to prevent NATS 30s timeout (BUG-27/30)
669
+ msg.ack();
670
+
667
671
  activeNodeJobs.set(jobId, {
668
672
  pierJobId: jobId,
669
673
  isRealtimeMsg: true
670
674
  });
671
675
 
672
- // Trigger agent
673
- try {
674
- isProcessing = true;
675
- await receiveIncoming({
676
- accountId: config.accountId || 'default',
677
- senderId: `pier:${senderCore}`,
678
- text: content,
679
- }, jobId);
680
- } finally {
681
- isProcessing = false;
682
- }
683
-
684
- msg.ack();
676
+ // Trigger agent (Asynchronously to NOT block the loop)
677
+ (async () => {
678
+ try {
679
+ logger.info(`[pier-connector] 🧠 Triggering agent for job ${jobId}...`);
680
+ await receiveIncoming({
681
+ accountId: config.accountId || 'default',
682
+ senderId: `pier:${senderCore}`,
683
+ text: content,
684
+ }, jobId);
685
+ } catch (err) {
686
+ logger.error(`[pier-connector] Agent execution error: ${err.message}`);
687
+ }
688
+ })();
685
689
  } catch (err) {
686
690
  logger.error(`[pier-connector] Chat message processing error for ${jobId}: ${err.message}`);
687
- msg.nak();
688
691
  }
689
692
  }
690
693
  })().catch(err => {