@gholl-studio/pier-connector 0.2.26 → 0.2.29

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 +41 -63
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.26",
4
+ "version": "0.2.29",
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
@@ -259,40 +259,33 @@ export default function register(api) {
259
259
  if (!this.js) return;
260
260
 
261
261
  const chatSubject = `chat.${jobId}`;
262
- const actionSubject = `jobs.action.${jobId}`;
263
262
  const streamName = 'PIER_JOBS';
264
263
  const nodeSlug = this.config.nodeId.replace(/[^a-zA-Z0-9]/g, '_');
265
264
  const jobSlug = jobId.replace(/[^a-zA-Z0-9]/g, '_');
266
-
267
- const chatDurable = `pier_chat_${nodeSlug}_${jobSlug}`;
268
- const actionDurable = `pier_action_${nodeSlug}_${jobSlug}`;
265
+ const durableName = `pier_chat_${nodeSlug}_${jobSlug}`;
269
266
 
270
- const setupConsumer = async (subject, durable) => {
267
+ try {
271
268
  let consumer;
272
269
  try {
273
- consumer = await this.js.consumers.get(streamName, durable);
270
+ consumer = await this.js.consumers.get(streamName, durableName);
274
271
  } catch {
275
272
  await this.jsm.consumers.add(streamName, {
276
- durable_name: durable,
277
- filter_subject: subject,
273
+ durable_name: durableName,
274
+ filter_subject: chatSubject,
278
275
  deliver_policy: DeliverPolicy.New,
279
276
  ack_policy: AckPolicy.Explicit,
280
277
  ack_wait: 1000 * 60 * 60,
281
278
  });
282
- consumer = await this.js.consumers.get(streamName, durable);
279
+ consumer = await this.js.consumers.get(streamName, durableName);
283
280
  }
284
- return consumer;
285
- };
286
281
 
287
- try {
288
- // 1. Setup Chat Consumer (Conversational)
289
- const chatConsumer = await setupConsumer(chatSubject, chatDurable);
290
- const chatIter = await chatConsumer.consume();
291
-
282
+ const iter = await consumer.consume();
283
+ this.jobSubscriptions.set(jobId, iter);
284
+
292
285
  (async () => {
293
- logger.info(`[pier-connector][${this.accountId}] 👂 Monitoring CHAT subject ${chatSubject}`);
286
+ logger.info(`[pier-connector][${this.accountId}] \u{1F442} Monitoring ${chatSubject}`);
294
287
  const processedMessages = new Set();
295
- for await (const msg of chatIter) {
288
+ for await (const msg of iter) {
296
289
  try {
297
290
  const rawMsg = new TextDecoder().decode(msg.data);
298
291
  let msgPayload = JSON.parse(rawMsg);
@@ -300,6 +293,8 @@ export default function register(api) {
300
293
  if (msgPayload.id && processedMessages.has(msgPayload.id)) { msg.ack(); continue; }
301
294
  if (msgPayload.sender_id === this.config.nodeId) { msg.ack(); continue; }
302
295
  if (msgPayload.type === 'receipt') { msg.ack(); continue; }
296
+ // Skip system_action messages — those are for the backend state machine
297
+ if (msgPayload.type === 'system_action' || msgPayload.msg_type === 'system_action') { msg.ack(); continue; }
303
298
 
304
299
  // Send receipt
305
300
  try {
@@ -311,8 +306,16 @@ export default function register(api) {
311
306
  const content = msgPayload.content;
312
307
  if (!content) { msg.ack(); continue; }
313
308
 
314
- logger.info(`[pier-connector][${this.accountId}] 💬 Chat: [${jobId}] ${msgPayload.sender_id}: "${truncate(content, 40)}"`);
309
+ logger.info(`[pier-connector][${this.accountId}] \u{1F4AC} Chat: [${jobId}] ${msgPayload.sender_id}: "${truncate(content, 40)}"`);
315
310
  if (msgPayload.id) processedMessages.add(msgPayload.id);
311
+
312
+ // Only the assigned robot should process chat messages
313
+ const jobMeta = this.activeNodeJobs.get(jobId);
314
+ if (!jobMeta || !jobMeta.isTargeted) {
315
+ msg.ack();
316
+ continue;
317
+ }
318
+
316
319
  msg.ack();
317
320
 
318
321
  await this.receiveIncoming({
@@ -323,27 +326,8 @@ export default function register(api) {
323
326
  } catch (err) { logger.error(`[pier-connector] Chat err: ${err.message}`); }
324
327
  }
325
328
  })();
326
-
327
- // 2. Setup Action Consumer (System Signal)
328
- const actionConsumer = await setupConsumer(actionSubject, actionDurable);
329
- const actionIter = await actionConsumer.consume();
330
-
331
- (async () => {
332
- logger.info(`[pier-connector][${this.accountId}] ⚙️ Monitoring ACTION subject ${actionSubject}`);
333
- for await (const msg of actionIter) {
334
- try {
335
- const rawMsg = new TextDecoder().decode(msg.data);
336
- let payload = JSON.parse(rawMsg);
337
- logger.info(`[pier-connector][${this.accountId}] 📥 Action: [${jobId}] ${payload.action || 'signal'}`);
338
- msg.ack();
339
- // Implementation of system action handling logic on the node side if needed.
340
- } catch (err) { logger.error(`[pier-connector] Action err: ${err.message}`); }
341
- }
342
- })();
343
-
344
- this.jobSubscriptions.set(jobId, { chat: chatIter, action: actionIter });
345
329
  } catch (err) {
346
- logger.error(`[pier-connector][${this.accountId}] Failed to setup consumers: ${err.message}`);
330
+ logger.error(`[pier-connector][${this.accountId}] Failed to setup chat consumer: ${err.message}`);
347
331
  }
348
332
  }
349
333
 
@@ -362,7 +346,7 @@ export default function register(api) {
362
346
  if (jobId) {
363
347
  logger.info(`[pier-connector][${this.accountId}] ⏰ Received wakeup signal for job ${jobId}`);
364
348
  if (!this.jobSubscriptions.has(jobId)) {
365
- this.activeNodeJobs.set(jobId, { pierJobId: jobId });
349
+ this.activeNodeJobs.set(jobId, { pierJobId: jobId, isTargeted: true });
366
350
  await this.subscribeToJobMessages(jobId);
367
351
  }
368
352
  msg.ack();
@@ -615,23 +599,18 @@ export default function register(api) {
615
599
  try {
616
600
  const replySubject = `chat.${jobId}`;
617
601
 
618
- // Pre-hiring Radio Silence
619
- if (metadata?.isTargeted) {
620
- const chatPayload = {
621
- id: crypto.randomUUID ? crypto.randomUUID() : (Math.random().toString(36).substring(2)),
622
- job_id: jobId,
623
- sender_id: robot.config.nodeId || 'anonymous',
624
- sender_type: 'node',
625
- content: text,
626
- created_at: new Date().toISOString(),
627
- auth_token: robot.config.secretKey
628
- };
629
-
630
- await robot.js.publish(replySubject, new TextEncoder().encode(JSON.stringify(chatPayload)));
631
- logger.info(`[pier-connector][${accountId}] 💬 Agent reply published to NATS for job ${jobId} (Subject: ${replySubject})`);
632
- } else {
633
- logger.debug(`[pier-connector][${accountId}] 🤫 Pre-hiring radio silence for job ${jobId}`);
634
- }
602
+ const chatPayload = {
603
+ id: crypto.randomUUID ? crypto.randomUUID() : (Math.random().toString(36).substring(2)),
604
+ job_id: jobId,
605
+ sender_id: robot.config.nodeId || 'anonymous',
606
+ sender_type: 'node',
607
+ content: text,
608
+ created_at: new Date().toISOString(),
609
+ auth_token: robot.config.secretKey
610
+ };
611
+
612
+ await robot.js.publish(replySubject, new TextEncoder().encode(JSON.stringify(chatPayload)));
613
+ logger.info(`[pier-connector][${accountId}] 💬 Agent reply published to NATS for job ${jobId} (Subject: ${replySubject})`);
635
614
  } catch (err) {
636
615
  logger.error(`[pier-connector][${accountId}] Failed to publish reply: ${err.message}`);
637
616
  }
@@ -641,11 +620,10 @@ export default function register(api) {
641
620
  if (robot.jobStopTimeouts.has(jobId)) clearTimeout(robot.jobStopTimeouts.get(jobId));
642
621
 
643
622
  const timeout = setTimeout(() => {
644
- const subs = robot.jobSubscriptions.get(jobId);
645
- if (subs) {
646
- logger.info(`[pier-connector][${accountId}] 🛑 Stopping listeners for job ${jobId} (inactivity)`);
647
- if (subs.chat) subs.chat.stop();
648
- if (subs.action) subs.action.stop();
623
+ const sub = robot.jobSubscriptions.get(jobId);
624
+ if (sub) {
625
+ logger.info(`[pier-connector][${accountId}] \u{1F6D1} Stopping listener for job ${jobId} (inactivity)`);
626
+ sub.stop();
649
627
  robot.jobSubscriptions.delete(jobId);
650
628
  robot.jobStopTimeouts.delete(jobId);
651
629
  }
@@ -819,7 +797,7 @@ export default function register(api) {
819
797
  }
820
798
 
821
799
  try {
822
- const subject = `jobs.action.${params.jobId}`;
800
+ const subject = `chat.${params.jobId}`;
823
801
  const { jobId, accountId: _, ...payload } = params;
824
802
 
825
803
  const msgData = {