2020117-agent 0.5.1 → 0.5.3

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/dist/agent.js +57 -39
  2. package/package.json +1 -1
package/dist/agent.js CHANGED
@@ -81,7 +81,7 @@ for (const arg of process.argv.slice(2)) {
81
81
  import { randomBytes } from 'crypto';
82
82
  import { SwarmNode, topicFromKind } from './swarm.js';
83
83
  import { createProcessor } from './processor.js';
84
- import { hasApiKey, loadAgentName, createJob, getJob, getProfile, reportSession, } from './api.js';
84
+ import { loadAgentName, } from './api.js';
85
85
  import { generateInvoice } from './clink.js';
86
86
  import { receiveCashuToken } from './cashu.js';
87
87
  import { generateKeypair, loadSovereignKeys, saveSovereignKeys, signEvent, nip44Encrypt, nip44Decrypt, pubkeyFromPrivkey, RelayPool, } from './nostr.js';
@@ -173,12 +173,12 @@ async function main() {
173
173
  if (state.skill) {
174
174
  console.log(`[${label}] Skill: ${state.skill.name} v${state.skill.version} (${state.skill.features.join(', ')})`);
175
175
  }
176
- // 2. Auto-fetch Lightning Address from platform if not set via CLI/env
177
- if (!LIGHTNING_ADDRESS && hasApiKey()) {
178
- const profile = await getProfile();
179
- if (profile?.lightning_address) {
180
- LIGHTNING_ADDRESS = profile.lightning_address;
181
- console.log(`[${label}] Lightning Address loaded from platform: ${LIGHTNING_ADDRESS}`);
176
+ // 2. Auto-load Lightning Address from .2020117_keys if not set via CLI/env
177
+ if (!LIGHTNING_ADDRESS) {
178
+ const keys = loadSovereignKeys(loadAgentName() || 'agent');
179
+ if (keys?.lightning_address) {
180
+ LIGHTNING_ADDRESS = keys.lightning_address;
181
+ console.log(`[${label}] Lightning Address loaded from keys: ${LIGHTNING_ADDRESS}`);
182
182
  }
183
183
  }
184
184
  // 3. Nostr identity + relay + subscriptions (all agents are Nostr-native)
@@ -515,8 +515,23 @@ async function handleDvmRequest(label, event) {
515
515
  content: '',
516
516
  }, state.sovereignKeys.privkey);
517
517
  await state.relayPool.publish(feedbackEvent);
518
- // Process
519
- const result = await state.processor.generate({ input });
518
+ // Process (with optional pipeline: delegate sub-task first)
519
+ let result;
520
+ if (SUB_KIND) {
521
+ console.log(`[${label}] Pipeline: delegating to kind ${SUB_KIND}...`);
522
+ try {
523
+ const subResult = await delegateNostr(label, SUB_KIND, input, SUB_BID, SUB_PROVIDER);
524
+ console.log(`[${label}] Sub-task returned ${subResult.length} chars`);
525
+ result = await state.processor.generate({ input: subResult });
526
+ }
527
+ catch (e) {
528
+ console.error(`[${label}] Sub-task failed: ${e.message}, using original input`);
529
+ result = await state.processor.generate({ input });
530
+ }
531
+ }
532
+ else {
533
+ result = await state.processor.generate({ input });
534
+ }
520
535
  console.log(`[${label}] DVM result: ${result.length} chars`);
521
536
  // Send result (Kind 6xxx = request kind + 1000)
522
537
  const resultKind = KIND + 1000;
@@ -624,35 +639,41 @@ function startSovereignHeartbeat(label) {
624
639
  }
625
640
  // --- Sub-task delegation ---
626
641
  /**
627
- * Delegate a sub-task via platform API. Creates a job, then polls until
628
- * the result is available (max 120s).
642
+ * Delegate a sub-task via Nostr relay. Publishes Kind 5xxx request,
643
+ * then subscribes for Kind 6xxx result (max 120s timeout).
629
644
  */
630
- async function delegateAPI(kind, input, bidSats, provider) {
631
- const tag = `sub-api`;
632
- const created = await createJob({ kind, input, bid_sats: bidSats, provider });
633
- if (!created) {
634
- throw new Error('Failed to create sub-task via API');
645
+ async function delegateNostr(label, kind, input, bidSats, provider) {
646
+ if (!state.sovereignKeys || !state.relayPool) {
647
+ throw new Error('No Nostr keys or relay pool cannot delegate sub-task');
635
648
  }
636
- const jobId = created.job_id;
637
- console.log(`[${tag}] Created job ${jobId} (kind ${kind}, bid ${bidSats})`);
638
- // Poll for result
639
- const deadline = Date.now() + 120_000;
640
- while (Date.now() < deadline) {
641
- await new Promise(r => setTimeout(r, 5_000));
642
- const job = await getJob(jobId);
643
- if (!job)
644
- continue;
645
- if (job.status === 'completed' || job.status === 'result_available') {
646
- if (job.result) {
647
- console.log(`[${tag}] Job ${jobId}: got result (${job.result.length} chars)`);
648
- return job.result;
649
- }
650
- }
651
- if (job.status === 'cancelled' || job.status === 'rejected') {
652
- throw new Error(`Sub-task ${jobId} was ${job.status}`);
653
- }
649
+ const tags = [
650
+ ['i', input, 'text'],
651
+ ['bid', String(bidSats * 1000)], // msats
652
+ ];
653
+ if (provider) {
654
+ tags.push(['p', provider]);
654
655
  }
655
- throw new Error(`Sub-task ${jobId} timed out after 120s`);
656
+ const requestEvent = signEvent({
657
+ kind,
658
+ tags,
659
+ content: '',
660
+ }, state.sovereignKeys.privkey);
661
+ await state.relayPool.publish(requestEvent);
662
+ console.log(`[${label}] Published sub-task (Kind ${kind}, id ${requestEvent.id.slice(0, 8)})`);
663
+ // Subscribe for result (Kind = request kind + 1000) referencing our request
664
+ const resultKind = kind + 1000;
665
+ return new Promise((resolve, reject) => {
666
+ const timeout = setTimeout(() => {
667
+ sub.close();
668
+ reject(new Error(`Sub-task ${requestEvent.id.slice(0, 8)} timed out after 120s`));
669
+ }, 120_000);
670
+ const sub = state.relayPool.subscribe({ kinds: [resultKind], '#e': [requestEvent.id] }, (event) => {
671
+ clearTimeout(timeout);
672
+ sub.close();
673
+ console.log(`[${label}] Sub-task result from ${event.pubkey.slice(0, 8)}: ${event.content.length} chars`);
674
+ resolve(event.content);
675
+ });
676
+ });
656
677
  }
657
678
  const activeSessions = new Map();
658
679
  // Dedup: track recently seen DVM request event IDs (prevent double-processing from relay + inbox)
@@ -1072,10 +1093,7 @@ function endSession(node, session, label) {
1072
1093
  // Update P2P lifetime counters
1073
1094
  state.p2pSessionsCompleted++;
1074
1095
  state.p2pTotalEarnedSats += session.totalEarned;
1075
- // Report session to platform activity feed (best-effort, no content exposed)
1076
- if (hasApiKey()) {
1077
- reportSession({ kind: KIND, durationS, totalSats: session.totalEarned });
1078
- }
1096
+ // Session stats are included in the next Kind 30333 heartbeat automatically
1079
1097
  activeSessions.delete(session.sessionId);
1080
1098
  }
1081
1099
  // --- 5. Graceful shutdown ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "2020117-agent",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "2020117 agent runtime — Nostr-native relay subscription + Hyperswarm P2P + Cashu/Lightning payments",
5
5
  "type": "module",
6
6
  "bin": {