@gholl-studio/pier-connector 0.2.25 → 0.2.26

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 +67 -82
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.25",
4
+ "version": "0.2.26",
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
@@ -258,108 +258,92 @@ export default function register(api) {
258
258
  async subscribeToJobMessages(jobId) {
259
259
  if (!this.js) return;
260
260
 
261
- const jsSubject = `jobs.job.${jobId}.msg`;
261
+ const chatSubject = `chat.${jobId}`;
262
+ const actionSubject = `jobs.action.${jobId}`;
262
263
  const streamName = 'PIER_JOBS';
263
- const durableName = `pier_chat_${this.config.nodeId.replace(/[^a-zA-Z0-9]/g, '_')}_${jobId.replace(/[^a-zA-Z0-9]/g, '_')}`;
264
+ const nodeSlug = this.config.nodeId.replace(/[^a-zA-Z0-9]/g, '_');
265
+ const jobSlug = jobId.replace(/[^a-zA-Z0-9]/g, '_');
266
+
267
+ const chatDurable = `pier_chat_${nodeSlug}_${jobSlug}`;
268
+ const actionDurable = `pier_action_${nodeSlug}_${jobSlug}`;
264
269
 
265
- try {
270
+ const setupConsumer = async (subject, durable) => {
266
271
  let consumer;
267
272
  try {
268
- consumer = await this.js.consumers.get(streamName, durableName);
273
+ consumer = await this.js.consumers.get(streamName, durable);
269
274
  } catch {
270
275
  await this.jsm.consumers.add(streamName, {
271
- durable_name: durableName,
272
- filter_subject: jsSubject,
276
+ durable_name: durable,
277
+ filter_subject: subject,
273
278
  deliver_policy: DeliverPolicy.New,
274
279
  ack_policy: AckPolicy.Explicit,
275
280
  ack_wait: 1000 * 60 * 60,
276
281
  });
277
- consumer = await this.js.consumers.get(streamName, durableName);
282
+ consumer = await this.js.consumers.get(streamName, durable);
278
283
  }
284
+ return consumer;
285
+ };
279
286
 
280
- const iter = await consumer.consume();
281
- this.jobSubscriptions.set(jobId, iter);
287
+ try {
288
+ // 1. Setup Chat Consumer (Conversational)
289
+ const chatConsumer = await setupConsumer(chatSubject, chatDurable);
290
+ const chatIter = await chatConsumer.consume();
282
291
 
283
292
  (async () => {
284
- logger.info(`[pier-connector][${this.accountId}] 👂 Monitoring chat subject ${jsSubject}`);
293
+ logger.info(`[pier-connector][${this.accountId}] 👂 Monitoring CHAT subject ${chatSubject}`);
285
294
  const processedMessages = new Set();
286
-
287
- for await (const msg of iter) {
295
+ for await (const msg of chatIter) {
288
296
  try {
289
297
  const rawMsg = new TextDecoder().decode(msg.data);
290
- let msgPayload;
291
- try {
292
- msgPayload = JSON.parse(rawMsg);
293
- } catch (e) {
294
- msg.ack();
295
- continue;
296
- }
297
-
298
- if (msgPayload.id && processedMessages.has(msgPayload.id)) {
299
- msg.ack();
300
- continue;
301
- }
298
+ let msgPayload = JSON.parse(rawMsg);
302
299
 
303
- if (msgPayload.sender_id === this.config.nodeId) {
304
- msg.ack();
305
- continue;
306
- }
307
-
308
- if (msgPayload.type === 'receipt') {
309
- msg.ack();
310
- continue;
311
- }
300
+ if (msgPayload.id && processedMessages.has(msgPayload.id)) { msg.ack(); continue; }
301
+ if (msgPayload.sender_id === this.config.nodeId) { msg.ack(); continue; }
302
+ if (msgPayload.type === 'receipt') { msg.ack(); continue; }
312
303
 
313
- if (this.js && msgPayload.id && !msgPayload.type && msgPayload.sender_id !== this.config.nodeId) {
314
- try {
315
- const replySubject = `jobs.job.${jobId}.msg`;
316
- await this.js.publish(replySubject, new TextEncoder().encode(JSON.stringify({
317
- type: 'receipt',
318
- msg_id: msgPayload.id,
319
- reader_id: this.config.nodeId
320
- })));
321
- } catch (err) {}
322
- }
304
+ // Send receipt
305
+ try {
306
+ await this.js.publish(chatSubject, new TextEncoder().encode(JSON.stringify({
307
+ type: 'receipt', msg_id: msgPayload.id, reader_id: this.config.nodeId
308
+ })));
309
+ } catch (err) {}
323
310
 
324
311
  const content = msgPayload.content;
325
- const senderCore = msgPayload.sender_id;
326
-
327
- if (!content) {
328
- msg.ack();
329
- continue;
330
- }
312
+ if (!content) { msg.ack(); continue; }
331
313
 
332
- logger.info(`[pier-connector][${this.accountId}] 📥 Incoming chat: [${jobId}] sender=${senderCore} "${truncate(content, 40)}"`);
314
+ logger.info(`[pier-connector][${this.accountId}] 💬 Chat: [${jobId}] ${msgPayload.sender_id}: "${truncate(content, 40)}"`);
333
315
  if (msgPayload.id) processedMessages.add(msgPayload.id);
334
-
335
316
  msg.ack();
336
317
 
337
- this.activeNodeJobs.set(jobId, {
338
- pierJobId: jobId,
339
- isRealtimeMsg: true
340
- });
318
+ await this.receiveIncoming({
319
+ accountId: this.accountId,
320
+ senderId: `pier:${msgPayload.sender_id}`,
321
+ text: content,
322
+ }, jobId);
323
+ } catch (err) { logger.error(`[pier-connector] Chat err: ${err.message}`); }
324
+ }
325
+ })();
341
326
 
342
- (async () => {
343
- try {
344
- await this.receiveIncoming({
345
- accountId: this.accountId,
346
- senderId: `pier:${senderCore}`,
347
- text: content,
348
- }, jobId);
349
- } catch (err) {
350
- logger.error(`[pier-connector][${this.accountId}] Agent execution error: ${err.message}`);
351
- }
352
- })();
353
- } catch (err) {
354
- logger.error(`[pier-connector][${this.accountId}] Chat message processing error: ${err.message}`);
355
- }
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}`); }
356
341
  }
357
- })().catch(err => {
358
- logger.error(`[pier-connector][${this.accountId}] Chat iteration died: ${err.message}`);
359
- this.jobSubscriptions.delete(jobId);
360
- });
342
+ })();
343
+
344
+ this.jobSubscriptions.set(jobId, { chat: chatIter, action: actionIter });
361
345
  } catch (err) {
362
- logger.error(`[pier-connector][${this.accountId}] Failed to setup chat consumer: ${err.message}`);
346
+ logger.error(`[pier-connector][${this.accountId}] Failed to setup consumers: ${err.message}`);
363
347
  }
364
348
  }
365
349
 
@@ -629,7 +613,7 @@ export default function register(api) {
629
613
 
630
614
  if (jobId && robot.js) {
631
615
  try {
632
- const replySubject = `jobs.job.${jobId}.msg`;
616
+ const replySubject = `chat.${jobId}`;
633
617
 
634
618
  // Pre-hiring Radio Silence
635
619
  if (metadata?.isTargeted) {
@@ -644,7 +628,7 @@ export default function register(api) {
644
628
  };
645
629
 
646
630
  await robot.js.publish(replySubject, new TextEncoder().encode(JSON.stringify(chatPayload)));
647
- logger.info(`[pier-connector][${accountId}] 💬 Agent reply published to NATS for job ${jobId}`);
631
+ logger.info(`[pier-connector][${accountId}] 💬 Agent reply published to NATS for job ${jobId} (Subject: ${replySubject})`);
648
632
  } else {
649
633
  logger.debug(`[pier-connector][${accountId}] 🤫 Pre-hiring radio silence for job ${jobId}`);
650
634
  }
@@ -657,10 +641,11 @@ export default function register(api) {
657
641
  if (robot.jobStopTimeouts.has(jobId)) clearTimeout(robot.jobStopTimeouts.get(jobId));
658
642
 
659
643
  const timeout = setTimeout(() => {
660
- const sub = robot.jobSubscriptions.get(jobId);
661
- if (sub) {
662
- logger.info(`[pier-connector][${accountId}] 🛑 Stopping listener for job ${jobId} (inactivity)`);
663
- sub.stop();
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();
664
649
  robot.jobSubscriptions.delete(jobId);
665
650
  robot.jobStopTimeouts.delete(jobId);
666
651
  }
@@ -790,7 +775,7 @@ export default function register(api) {
790
775
  }
791
776
 
792
777
  try {
793
- const subject = `jobs.job.${params.jobId}.msg`;
778
+ const subject = `chat.${params.jobId}`;
794
779
  const payload = {
795
780
  id: crypto.randomUUID ? crypto.randomUUID() : (Math.random().toString(36).substring(2)),
796
781
  job_id: params.jobId,
@@ -834,7 +819,7 @@ export default function register(api) {
834
819
  }
835
820
 
836
821
  try {
837
- const subject = `jobs.job.${params.jobId}.msg`;
822
+ const subject = `jobs.action.${params.jobId}`;
838
823
  const { jobId, accountId: _, ...payload } = params;
839
824
 
840
825
  const msgData = {