@gholl-studio/pier-connector 0.2.24 → 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.
- package/package.json +1 -1
- 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.
|
|
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
|
|
261
|
+
const chatSubject = `chat.${jobId}`;
|
|
262
|
+
const actionSubject = `jobs.action.${jobId}`;
|
|
262
263
|
const streamName = 'PIER_JOBS';
|
|
263
|
-
const
|
|
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
|
-
|
|
270
|
+
const setupConsumer = async (subject, durable) => {
|
|
266
271
|
let consumer;
|
|
267
272
|
try {
|
|
268
|
-
consumer = await this.
|
|
273
|
+
consumer = await this.js.consumers.get(streamName, durable);
|
|
269
274
|
} catch {
|
|
270
275
|
await this.jsm.consumers.add(streamName, {
|
|
271
|
-
durable_name:
|
|
272
|
-
filter_subject:
|
|
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.
|
|
282
|
+
consumer = await this.js.consumers.get(streamName, durable);
|
|
278
283
|
}
|
|
284
|
+
return consumer;
|
|
285
|
+
};
|
|
279
286
|
|
|
280
|
-
|
|
281
|
-
|
|
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
|
|
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
|
-
}
|
|
302
|
-
|
|
303
|
-
if (msgPayload.sender_id === this.config.nodeId) {
|
|
304
|
-
msg.ack();
|
|
305
|
-
continue;
|
|
306
|
-
}
|
|
298
|
+
let msgPayload = JSON.parse(rawMsg);
|
|
307
299
|
|
|
308
|
-
if (msgPayload.
|
|
309
|
-
|
|
310
|
-
|
|
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
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
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
|
-
|
|
312
|
+
if (!content) { msg.ack(); continue; }
|
|
326
313
|
|
|
327
|
-
|
|
328
|
-
msg.ack();
|
|
329
|
-
continue;
|
|
330
|
-
}
|
|
331
|
-
|
|
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.
|
|
338
|
-
|
|
339
|
-
|
|
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
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
})
|
|
353
|
-
|
|
354
|
-
|
|
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
|
-
})()
|
|
358
|
-
|
|
359
|
-
|
|
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
|
|
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 = `
|
|
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
|
|
661
|
-
if (
|
|
662
|
-
logger.info(`[pier-connector][${accountId}] 🛑 Stopping
|
|
663
|
-
|
|
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 = `
|
|
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.
|
|
822
|
+
const subject = `jobs.action.${params.jobId}`;
|
|
838
823
|
const { jobId, accountId: _, ...payload } = params;
|
|
839
824
|
|
|
840
825
|
const msgData = {
|