@gholl-studio/pier-connector 0.1.5 → 0.1.8
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 +91 -40
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gholl-studio/pier-connector",
|
|
3
3
|
"author": "gholl",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.8",
|
|
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
|
@@ -162,7 +162,9 @@ export default function register(api) {
|
|
|
162
162
|
OriginatingChannel: 'pier',
|
|
163
163
|
OriginatingTo: `pier:${jobId}`,
|
|
164
164
|
WasMentioned: true,
|
|
165
|
-
CommandAuthorized: true
|
|
165
|
+
CommandAuthorized: true,
|
|
166
|
+
SystemPrompt: inbound.systemPrompt || undefined,
|
|
167
|
+
MessageId: inbound.messageId || jobId
|
|
166
168
|
});
|
|
167
169
|
|
|
168
170
|
// Create a dispatcher to handle the reply lifecycle (fixes sendFinalReply error)
|
|
@@ -173,9 +175,12 @@ export default function register(api) {
|
|
|
173
175
|
logger.debug(`[pier-connector] Dispatcher idle for session ${route.sessionKey}`);
|
|
174
176
|
},
|
|
175
177
|
deliver: async (payload) => {
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
|
|
178
|
+
// Route Agent's reply to outbound.sendText so it reaches NATS
|
|
179
|
+
logger.debug(`[pier-connector] deliver() called with text: "${truncate(payload.text, 60)}"`);
|
|
180
|
+
await pierChannel.outbound.sendText({
|
|
181
|
+
text: payload.text,
|
|
182
|
+
to: `pier:${jobId}`,
|
|
183
|
+
metadata: activeNodeJobs.get(jobId),
|
|
179
184
|
});
|
|
180
185
|
}
|
|
181
186
|
});
|
|
@@ -195,12 +200,14 @@ export default function register(api) {
|
|
|
195
200
|
}
|
|
196
201
|
|
|
197
202
|
try {
|
|
203
|
+
logger.info(`[pier-connector] 🧠 Triggering agent for session ${route.sessionKey}...`);
|
|
198
204
|
// Dispatch reply — this will trigger outbound: sendText in pierChannel
|
|
199
205
|
await api.runtime.channel.reply.dispatchReplyFromConfig({
|
|
200
206
|
ctx: ctxPayload,
|
|
201
207
|
cfg: api.config,
|
|
202
208
|
dispatcher
|
|
203
209
|
});
|
|
210
|
+
logger.info(`[pier-connector] 🧠 Agent dispatch completed for ${route.sessionKey}`);
|
|
204
211
|
} finally {
|
|
205
212
|
markDispatchIdle();
|
|
206
213
|
}
|
|
@@ -269,11 +276,14 @@ export default function register(api) {
|
|
|
269
276
|
const text = ctx.text;
|
|
270
277
|
let metadata = ctx.metadata;
|
|
271
278
|
|
|
279
|
+
logger.info(`[pier-connector] 📤 Agent sending reply: "${truncate(text, 40)}" (To: ${ctx.to})`);
|
|
280
|
+
|
|
272
281
|
if (!metadata && ctx.to) {
|
|
273
282
|
const toId = ctx.to.replace(/^pier:/, '');
|
|
274
283
|
metadata = activeNodeJobs.get(toId);
|
|
284
|
+
logger.debug(`[pier-connector] 📤 Resolved metadata for ${toId}: ${metadata ? 'Found' : 'Missing'}`);
|
|
275
285
|
}
|
|
276
|
-
|
|
286
|
+
|
|
277
287
|
const jobId = metadata?.pierJobId;
|
|
278
288
|
const msg = metadata?.pierNatsMsg;
|
|
279
289
|
const isRealtimeMsg = metadata?.isRealtimeMsg;
|
|
@@ -295,23 +305,29 @@ export default function register(api) {
|
|
|
295
305
|
try {
|
|
296
306
|
const config = getActiveConfig();
|
|
297
307
|
const replySubject = `jobs.job.${jobId}.msg`;
|
|
298
|
-
|
|
308
|
+
const replyPayload = {
|
|
309
|
+
id: ethers.hexlify(ethers.randomBytes(16)), // Unique ID for frontend tracking
|
|
299
310
|
sender_id: config.nodeId,
|
|
300
311
|
content: text,
|
|
301
312
|
created_at: new Date().toISOString()
|
|
302
|
-
}
|
|
313
|
+
};
|
|
314
|
+
await js.publish(replySubject, new TextEncoder().encode(JSON.stringify(replyPayload)));
|
|
303
315
|
logger.info(`[pier-connector] 💬 Published agent reply to realtime chat for job ${jobId}`);
|
|
304
316
|
} catch (err) {
|
|
305
317
|
logger.error(`[pier-connector] Failed to send realtime reply: ${err.message}`);
|
|
306
318
|
}
|
|
307
|
-
} else if (
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
319
|
+
} else if (js) {
|
|
320
|
+
// Publish result to jobs.submit via JetStream (not msg.respond)
|
|
321
|
+
try {
|
|
322
|
+
await js.publish('jobs.submit', new TextEncoder().encode(JSON.stringify(responsePayload)));
|
|
323
|
+
jobsCompleted++;
|
|
324
|
+
logger.info(
|
|
325
|
+
`[pier-connector] ✔ Job ${jobId} result published to jobs.submit` +
|
|
326
|
+
(elapsed ? ` — latency: ${elapsed}ms` : ''),
|
|
327
|
+
);
|
|
328
|
+
} catch (err) {
|
|
329
|
+
logger.error(`[pier-connector] ❌ Failed to publish result for job ${jobId}: ${err.message}`);
|
|
330
|
+
}
|
|
315
331
|
}
|
|
316
332
|
|
|
317
333
|
// Delayed stop for job-specific message listener
|
|
@@ -466,17 +482,35 @@ export default function register(api) {
|
|
|
466
482
|
|
|
467
483
|
(async () => {
|
|
468
484
|
try {
|
|
469
|
-
|
|
485
|
+
// SDK-5: Try to get existing consumer; if config changed, delete and recreate
|
|
486
|
+
let consumer;
|
|
487
|
+
try {
|
|
488
|
+
consumer = await js.consumers.get(streamName, durableName);
|
|
489
|
+
} catch {
|
|
490
|
+
// Consumer doesn't exist yet, create it
|
|
470
491
|
logger.info(`[pier-connector] Creating new Marketplace Consumer: ${durableName}`);
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
492
|
+
try {
|
|
493
|
+
await jsm.consumers.add(streamName, {
|
|
494
|
+
durable_name: durableName,
|
|
495
|
+
filter_subject: publicSubject,
|
|
496
|
+
deliver_policy: DeliverPolicy.New, // SDK-3: Only new messages
|
|
497
|
+
ack_policy: AckPolicy.Explicit,
|
|
498
|
+
deliver_group: config.queueGroup
|
|
499
|
+
});
|
|
500
|
+
} catch (addErr) {
|
|
501
|
+
// SDK-5: Config mismatch — delete old and recreate
|
|
502
|
+
logger.warn(`[pier-connector] Consumer config conflict, recreating: ${addErr.message}`);
|
|
503
|
+
try { await jsm.consumers.delete(streamName, durableName); } catch { /* ignore */ }
|
|
504
|
+
await jsm.consumers.add(streamName, {
|
|
505
|
+
durable_name: durableName,
|
|
506
|
+
filter_subject: publicSubject,
|
|
507
|
+
deliver_policy: DeliverPolicy.New,
|
|
508
|
+
ack_policy: AckPolicy.Explicit,
|
|
509
|
+
deliver_group: config.queueGroup
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
consumer = await js.consumers.get(streamName, durableName);
|
|
513
|
+
}
|
|
480
514
|
|
|
481
515
|
const iter = await consumer.consume();
|
|
482
516
|
for await (const msg of iter) {
|
|
@@ -500,16 +534,31 @@ export default function register(api) {
|
|
|
500
534
|
|
|
501
535
|
(async () => {
|
|
502
536
|
try {
|
|
503
|
-
|
|
537
|
+
// SDK-5: Try to get existing consumer; if config changed, delete and recreate
|
|
538
|
+
let consumer;
|
|
539
|
+
try {
|
|
540
|
+
consumer = await js.consumers.get(streamName, durableName);
|
|
541
|
+
} catch {
|
|
504
542
|
logger.info(`[pier-connector] Creating new Direct Consumer: ${durableName}`);
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
543
|
+
try {
|
|
544
|
+
await jsm.consumers.add(streamName, {
|
|
545
|
+
durable_name: durableName,
|
|
546
|
+
filter_subject: privateSubject,
|
|
547
|
+
deliver_policy: DeliverPolicy.New, // SDK-4: Only new messages
|
|
548
|
+
ack_policy: AckPolicy.Explicit
|
|
549
|
+
});
|
|
550
|
+
} catch (addErr) {
|
|
551
|
+
logger.warn(`[pier-connector] Consumer config conflict, recreating: ${addErr.message}`);
|
|
552
|
+
try { await jsm.consumers.delete(streamName, durableName); } catch { /* ignore */ }
|
|
553
|
+
await jsm.consumers.add(streamName, {
|
|
554
|
+
durable_name: durableName,
|
|
555
|
+
filter_subject: privateSubject,
|
|
556
|
+
deliver_policy: DeliverPolicy.New,
|
|
557
|
+
ack_policy: AckPolicy.Explicit
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
consumer = await js.consumers.get(streamName, durableName);
|
|
561
|
+
}
|
|
513
562
|
|
|
514
563
|
const iter = await consumer.consume();
|
|
515
564
|
for await (const msg of iter) {
|
|
@@ -544,9 +593,9 @@ export default function register(api) {
|
|
|
544
593
|
const cInfo = await jsm.consumers.add(streamName, {
|
|
545
594
|
durable_name: durableName,
|
|
546
595
|
filter_subject: msgSubject,
|
|
547
|
-
deliver_policy: DeliverPolicy.
|
|
596
|
+
deliver_policy: DeliverPolicy.New, // Only new messages to avoid replay spam
|
|
548
597
|
ack_policy: AckPolicy.Explicit,
|
|
549
|
-
ack_wait: 30000,
|
|
598
|
+
ack_wait: 30000,
|
|
550
599
|
});
|
|
551
600
|
const consumer = await js.consumers.get(streamName, cInfo.name);
|
|
552
601
|
|
|
@@ -554,6 +603,8 @@ export default function register(api) {
|
|
|
554
603
|
jobSubscriptions.set(jobId, iter);
|
|
555
604
|
|
|
556
605
|
(async () => {
|
|
606
|
+
logger.info(`[pier-connector] 👂 Monitoring new messages for job ${jobId}`);
|
|
607
|
+
|
|
557
608
|
for await (const msg of iter) {
|
|
558
609
|
try {
|
|
559
610
|
const rawMsg = new TextDecoder().decode(msg.data);
|
|
@@ -585,14 +636,14 @@ export default function register(api) {
|
|
|
585
636
|
msg_id: msgPayload.id,
|
|
586
637
|
reader_id: config.nodeId
|
|
587
638
|
})));
|
|
588
|
-
logger.
|
|
639
|
+
logger.debug(`[pier-connector] 👁️ Sent read receipt for message ${msgPayload.id}`);
|
|
589
640
|
} catch (err) {
|
|
590
641
|
logger.error(`[pier-connector] Failed to send read receipt: ${err.message}`);
|
|
591
642
|
}
|
|
592
643
|
}
|
|
593
644
|
|
|
594
645
|
const content = msgPayload.content;
|
|
595
|
-
logger.info(`[pier-connector]
|
|
646
|
+
logger.info(`[pier-connector] 📥 Incoming message for ${jobId}: "${truncate(content, 40)}"`);
|
|
596
647
|
|
|
597
648
|
const senderCore = msgPayload.sender_id;
|
|
598
649
|
|
|
@@ -601,7 +652,7 @@ export default function register(api) {
|
|
|
601
652
|
isRealtimeMsg: true
|
|
602
653
|
});
|
|
603
654
|
|
|
604
|
-
//
|
|
655
|
+
// Trigger agent
|
|
605
656
|
await receiveIncoming({
|
|
606
657
|
accountId: config.accountId || 'default',
|
|
607
658
|
senderId: `pier:${senderCore}`,
|
|
@@ -889,7 +940,7 @@ export default function register(api) {
|
|
|
889
940
|
method: 'POST',
|
|
890
941
|
headers: {
|
|
891
942
|
'Content-Type': 'application/json',
|
|
892
|
-
'
|
|
943
|
+
'Authorization': `Bearer ${config.secretKey}` // BUG-7: Use Authorization header, not X-API-Key
|
|
893
944
|
},
|
|
894
945
|
body: JSON.stringify({
|
|
895
946
|
sender_id: config.nodeId,
|