@gholl-studio/pier-connector 0.1.6 → 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 +87 -70
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;
|
|
@@ -306,14 +316,18 @@ export default function register(api) {
|
|
|
306
316
|
} catch (err) {
|
|
307
317
|
logger.error(`[pier-connector] Failed to send realtime reply: ${err.message}`);
|
|
308
318
|
}
|
|
309
|
-
} else if (
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
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
|
+
}
|
|
317
331
|
}
|
|
318
332
|
|
|
319
333
|
// Delayed stop for job-specific message listener
|
|
@@ -468,17 +482,35 @@ export default function register(api) {
|
|
|
468
482
|
|
|
469
483
|
(async () => {
|
|
470
484
|
try {
|
|
471
|
-
|
|
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
|
|
472
491
|
logger.info(`[pier-connector] Creating new Marketplace Consumer: ${durableName}`);
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
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
|
+
}
|
|
482
514
|
|
|
483
515
|
const iter = await consumer.consume();
|
|
484
516
|
for await (const msg of iter) {
|
|
@@ -502,16 +534,31 @@ export default function register(api) {
|
|
|
502
534
|
|
|
503
535
|
(async () => {
|
|
504
536
|
try {
|
|
505
|
-
|
|
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 {
|
|
506
542
|
logger.info(`[pier-connector] Creating new Direct Consumer: ${durableName}`);
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
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
|
+
}
|
|
515
562
|
|
|
516
563
|
const iter = await consumer.consume();
|
|
517
564
|
for await (const msg of iter) {
|
|
@@ -546,9 +593,9 @@ export default function register(api) {
|
|
|
546
593
|
const cInfo = await jsm.consumers.add(streamName, {
|
|
547
594
|
durable_name: durableName,
|
|
548
595
|
filter_subject: msgSubject,
|
|
549
|
-
deliver_policy: DeliverPolicy.
|
|
596
|
+
deliver_policy: DeliverPolicy.New, // Only new messages to avoid replay spam
|
|
550
597
|
ack_policy: AckPolicy.Explicit,
|
|
551
|
-
ack_wait: 30000,
|
|
598
|
+
ack_wait: 30000,
|
|
552
599
|
});
|
|
553
600
|
const consumer = await js.consumers.get(streamName, cInfo.name);
|
|
554
601
|
|
|
@@ -556,31 +603,7 @@ export default function register(api) {
|
|
|
556
603
|
jobSubscriptions.set(jobId, iter);
|
|
557
604
|
|
|
558
605
|
(async () => {
|
|
559
|
-
|
|
560
|
-
let isBursting = true;
|
|
561
|
-
|
|
562
|
-
// Small delay to collect initial "DeliverPolicy.All" burst
|
|
563
|
-
const burstTimeout = setTimeout(() => {
|
|
564
|
-
if (isBursting && historyBuffer.length > 0) {
|
|
565
|
-
isBursting = false;
|
|
566
|
-
logger.info(`[pier-connector] 📦 Batch processing ${historyBuffer.length} historical messages for ${jobId}`);
|
|
567
|
-
|
|
568
|
-
const combinedHistory = historyBuffer.map(m => `User: ${m.content}`).join('\n');
|
|
569
|
-
const lastSenderId = historyBuffer[historyBuffer.length - 1].sender_id;
|
|
570
|
-
|
|
571
|
-
receiveIncoming({
|
|
572
|
-
accountId: config.accountId || 'default',
|
|
573
|
-
senderId: `pier:${lastSenderId}`,
|
|
574
|
-
text: `[Conversation History]\n${combinedHistory}\n\nPlease continue based on the above history.`,
|
|
575
|
-
}, jobId).catch(err => {
|
|
576
|
-
logger.error(`[pier-connector] Failed to process batch history: ${err.message}`);
|
|
577
|
-
});
|
|
578
|
-
|
|
579
|
-
historyBuffer = [];
|
|
580
|
-
} else {
|
|
581
|
-
isBursting = false;
|
|
582
|
-
}
|
|
583
|
-
}, 1000); // 1s burst window
|
|
606
|
+
logger.info(`[pier-connector] 👂 Monitoring new messages for job ${jobId}`);
|
|
584
607
|
|
|
585
608
|
for await (const msg of iter) {
|
|
586
609
|
try {
|
|
@@ -613,21 +636,15 @@ export default function register(api) {
|
|
|
613
636
|
msg_id: msgPayload.id,
|
|
614
637
|
reader_id: config.nodeId
|
|
615
638
|
})));
|
|
616
|
-
logger.
|
|
639
|
+
logger.debug(`[pier-connector] 👁️ Sent read receipt for message ${msgPayload.id}`);
|
|
617
640
|
} catch (err) {
|
|
618
641
|
logger.error(`[pier-connector] Failed to send read receipt: ${err.message}`);
|
|
619
642
|
}
|
|
620
643
|
}
|
|
621
644
|
|
|
622
645
|
const content = msgPayload.content;
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
historyBuffer.push(msgPayload);
|
|
626
|
-
msg.ack();
|
|
627
|
-
continue;
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
logger.info(`[pier-connector] 💬 Message for job ${jobId}: "${truncate(content, 40)}"`);
|
|
646
|
+
logger.info(`[pier-connector] 📥 Incoming message for ${jobId}: "${truncate(content, 40)}"`);
|
|
647
|
+
|
|
631
648
|
const senderCore = msgPayload.sender_id;
|
|
632
649
|
|
|
633
650
|
activeNodeJobs.set(jobId, {
|
|
@@ -635,7 +652,7 @@ export default function register(api) {
|
|
|
635
652
|
isRealtimeMsg: true
|
|
636
653
|
});
|
|
637
654
|
|
|
638
|
-
//
|
|
655
|
+
// Trigger agent
|
|
639
656
|
await receiveIncoming({
|
|
640
657
|
accountId: config.accountId || 'default',
|
|
641
658
|
senderId: `pier:${senderCore}`,
|
|
@@ -923,7 +940,7 @@ export default function register(api) {
|
|
|
923
940
|
method: 'POST',
|
|
924
941
|
headers: {
|
|
925
942
|
'Content-Type': 'application/json',
|
|
926
|
-
'
|
|
943
|
+
'Authorization': `Bearer ${config.secretKey}` // BUG-7: Use Authorization header, not X-API-Key
|
|
927
944
|
},
|
|
928
945
|
body: JSON.stringify({
|
|
929
946
|
sender_id: config.nodeId,
|