@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.
- package/package.json +1 -1
- 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.
|
|
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
|
-
|
|
267
|
+
try {
|
|
271
268
|
let consumer;
|
|
272
269
|
try {
|
|
273
|
-
consumer = await this.js.consumers.get(streamName,
|
|
270
|
+
consumer = await this.js.consumers.get(streamName, durableName);
|
|
274
271
|
} catch {
|
|
275
272
|
await this.jsm.consumers.add(streamName, {
|
|
276
|
-
durable_name:
|
|
277
|
-
filter_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,
|
|
279
|
+
consumer = await this.js.consumers.get(streamName, durableName);
|
|
283
280
|
}
|
|
284
|
-
return consumer;
|
|
285
|
-
};
|
|
286
281
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
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}]
|
|
286
|
+
logger.info(`[pier-connector][${this.accountId}] \u{1F442} Monitoring ${chatSubject}`);
|
|
294
287
|
const processedMessages = new Set();
|
|
295
|
-
for await (const msg of
|
|
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}]
|
|
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
|
|
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
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
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
|
|
645
|
-
if (
|
|
646
|
-
logger.info(`[pier-connector][${accountId}]
|
|
647
|
-
|
|
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 = `
|
|
800
|
+
const subject = `chat.${params.jobId}`;
|
|
823
801
|
const { jobId, accountId: _, ...payload } = params;
|
|
824
802
|
|
|
825
803
|
const msgData = {
|