2020117-agent 0.6.20 → 0.6.22

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/dist/agent.d.ts CHANGED
@@ -8,10 +8,10 @@
8
8
  * to relays. The platform API is only used for read operations (pipeline sub-tasks).
9
9
  *
10
10
  * Usage:
11
- * AGENT=translator DVM_KIND=5302 OLLAMA_MODEL=qwen2.5:0.5b npm run agent
12
- * AGENT=my-agent DVM_KIND=5100 MAX_JOBS=5 npm run agent
13
- * AGENT=broker DVM_KIND=5302 PROCESSOR=none SUB_KIND=5100 npm run agent
14
- * AGENT=custom DVM_KIND=5100 PROCESSOR=exec:./my-model.sh npm run agent
15
- * AGENT=remote DVM_KIND=5100 PROCESSOR=http://localhost:8080 npm run agent
11
+ * AGENT=translator DVM_KIND=5002 OLLAMA_MODEL=qwen2.5:0.5b npm run agent
12
+ * AGENT=my-agent DVM_KIND=5050 MAX_JOBS=5 npm run agent
13
+ * AGENT=broker DVM_KIND=5002 PROCESSOR=none SUB_KIND=5050 npm run agent
14
+ * AGENT=custom DVM_KIND=5050 PROCESSOR=exec:./my-model.sh npm run agent
15
+ * AGENT=remote DVM_KIND=5050 PROCESSOR=http://localhost:8080 npm run agent
16
16
  */
17
17
  export {};
package/dist/agent.js CHANGED
@@ -8,11 +8,11 @@
8
8
  * to relays. The platform API is only used for read operations (pipeline sub-tasks).
9
9
  *
10
10
  * Usage:
11
- * AGENT=translator DVM_KIND=5302 OLLAMA_MODEL=qwen2.5:0.5b npm run agent
12
- * AGENT=my-agent DVM_KIND=5100 MAX_JOBS=5 npm run agent
13
- * AGENT=broker DVM_KIND=5302 PROCESSOR=none SUB_KIND=5100 npm run agent
14
- * AGENT=custom DVM_KIND=5100 PROCESSOR=exec:./my-model.sh npm run agent
15
- * AGENT=remote DVM_KIND=5100 PROCESSOR=http://localhost:8080 npm run agent
11
+ * AGENT=translator DVM_KIND=5002 OLLAMA_MODEL=qwen2.5:0.5b npm run agent
12
+ * AGENT=my-agent DVM_KIND=5050 MAX_JOBS=5 npm run agent
13
+ * AGENT=broker DVM_KIND=5002 PROCESSOR=none SUB_KIND=5050 npm run agent
14
+ * AGENT=custom DVM_KIND=5050 PROCESSOR=exec:./my-model.sh npm run agent
15
+ * AGENT=remote DVM_KIND=5050 PROCESSOR=http://localhost:8080 npm run agent
16
16
  */
17
17
  // --- CLI args → env (for npx usage) ---
18
18
  for (const arg of process.argv.slice(2)) {
@@ -91,7 +91,8 @@ import WebSocket from 'ws';
91
91
  if (!globalThis.WebSocket)
92
92
  globalThis.WebSocket = WebSocket;
93
93
  // --- Config from env ---
94
- const KIND = Number(process.env.DVM_KIND) || 5100;
94
+ const KINDS = (process.env.DVM_KIND || '5050').split(',').map(s => Number(s.trim())).filter(Boolean);
95
+ const KIND = KINDS[0]; // primary kind (for result subscriptions, registration, etc.)
95
96
  const MAX_CONCURRENT = Number(process.env.MAX_JOBS) || 3;
96
97
  const P2P_ONLY = process.env.P2P_ONLY === 'true' || process.env.P2P_ONLY === '1';
97
98
  const SATS_PER_CHUNK = Number(process.env.SATS_PER_CHUNK) || 1;
@@ -161,7 +162,7 @@ async function main() {
161
162
  console.log(`[${label}] Starting agent runtime`);
162
163
  // 1. Create and verify processor
163
164
  state.processor = await createProcessor();
164
- console.log(`[${label}] kind=${KIND} processor=${state.processor.name} maxJobs=${MAX_CONCURRENT}`);
165
+ console.log(`[${label}] kind=${KINDS.join(',')} processor=${state.processor.name} maxJobs=${MAX_CONCURRENT}`);
165
166
  if (SUB_KIND) {
166
167
  console.log(`[${label}] Pipeline: sub-task kind=${SUB_KIND} (bid=${SUB_BID}${SUB_PROVIDER ? `, provider=${SUB_PROVIDER}` : ''})`);
167
168
  }
@@ -266,7 +267,7 @@ async function setupNostr(label) {
266
267
  const pricing = {};
267
268
  const priceSats = SATS_PER_CHUNK * CHUNKS_PER_PAYMENT;
268
269
  if (priceSats > 0)
269
- pricing[String(KIND)] = priceSats;
270
+ KINDS.forEach(k => { pricing[String(k)] = priceSats; });
270
271
  state.stopHeartbeat = startNostrHeartbeat(label, state.sovereignKeys, state.relayPool, {
271
272
  pricing,
272
273
  p2pStatsFn: () => ({
@@ -281,7 +282,7 @@ async function setupNostr(label) {
281
282
  console.log(`═══════════════════════════════════════════════`);
282
283
  console.log(` Agent ready: ${agentName}`);
283
284
  console.log(` Pubkey: ${keys.pubkey}`);
284
- console.log(` Kind: ${KIND}`);
285
+ console.log(` Kind: ${KINDS.join(',')}`);
285
286
  console.log(` Relays: ${relays}`);
286
287
  console.log(` Lightning: ${LIGHTNING_ADDRESS || '(not set)'}`);
287
288
  console.log(` NWC wallet: ${state.nwcParsed ? 'connected' : '(not set)'}`);
@@ -300,7 +301,7 @@ async function publishAiInfo(label) {
300
301
  supported_models: state.processor?.name ? [state.processor.name] : [],
301
302
  default_model: state.processor?.name || 'default',
302
303
  dvm_compatible: true,
303
- dvm_kinds: [KIND],
304
+ dvm_kinds: KINDS,
304
305
  pricing_hints: {
305
306
  currency: 'BTC',
306
307
  sats_per_prompt: SATS_PER_CHUNK * CHUNKS_PER_PAYMENT,
@@ -356,8 +357,8 @@ async function publishHandlerInfo(label) {
356
357
  const event = signEvent({
357
358
  kind: 31990,
358
359
  tags: [
359
- ['d', `${agentName}-${KIND}`],
360
- ['k', String(KIND)],
360
+ ['d', `${agentName}-${KINDS.join('-')}`],
361
+ ...KINDS.map(k => ['k', String(k)]),
361
362
  ],
362
363
  content: JSON.stringify(content),
363
364
  }, state.sovereignKeys.privkey);
@@ -381,13 +382,13 @@ function subscribeDvmRequests(label) {
381
382
  if (dvmSubscribed)
382
383
  return; // prevent double-subscribe (sovereign + platform both call this)
383
384
  dvmSubscribed = true;
384
- // Subscribe to all DVM requests of our kind (broadcast + directed)
385
- state.relayPool.subscribe({ kinds: [KIND] }, (event) => {
385
+ // Subscribe to all DVM requests of our kind(s) (broadcast + directed)
386
+ state.relayPool.subscribe({ kinds: KINDS }, (event) => {
386
387
  handleDvmRequest(label, event).catch(e => {
387
388
  console.error(`[${label}] DVM request error: ${e.message}`);
388
389
  });
389
390
  });
390
- console.log(`[${label}] Subscribed to DVM requests (Kind ${KIND}) via relay`);
391
+ console.log(`[${label}] Subscribed to DVM requests (Kind ${KINDS.join(',')}) via relay`);
391
392
  }
392
393
  // --- Customer: subscribe to DVM results and auto-pay ---
393
394
  let dvmResultSubscribed = false;
@@ -398,13 +399,13 @@ function subscribeDvmResults(label) {
398
399
  return;
399
400
  dvmResultSubscribed = true;
400
401
  // Subscribe to Kind 6xxx results directed to us (#p = our pubkey)
401
- const resultKind = KIND + 1000;
402
- state.relayPool.subscribe({ kinds: [resultKind], '#p': [state.sovereignKeys.pubkey] }, (event) => {
402
+ const resultKinds = KINDS.map(k => k + 1000);
403
+ state.relayPool.subscribe({ kinds: resultKinds, '#p': [state.sovereignKeys.pubkey] }, (event) => {
403
404
  handleDvmResult(label, event).catch(e => {
404
405
  console.error(`[${label}] DVM result handler error: ${e.message}`);
405
406
  });
406
407
  });
407
- console.log(`[${label}] Subscribed to DVM results (Kind ${resultKind}) via relay`);
408
+ console.log(`[${label}] Subscribed to DVM results (Kind ${resultKinds.join(',')}) via relay`);
408
409
  }
409
410
  async function handleDvmResult(label, event) {
410
411
  if (!state.sovereignKeys || !state.relayPool)
@@ -570,8 +571,16 @@ async function handleDvmRequest(label, event) {
570
571
  // Dedup: skip already-seen events
571
572
  if (!markSeen(event.id))
572
573
  return;
573
- if (!acquireSlot())
574
+ if (!acquireSlot()) {
575
+ console.warn(`[${label}] DVM request ${event.id.slice(0, 8)} dropped — agent at capacity (${state.activeJobs}/${MAX_CONCURRENT})`);
576
+ const errorEvent = signEvent({
577
+ kind: 7000,
578
+ tags: [['p', event.pubkey], ['e', event.id], ['status', 'error']],
579
+ content: 'Agent at capacity, please retry later',
580
+ }, state.sovereignKeys.privkey);
581
+ await state.relayPool.publish(errorEvent).catch(() => { });
574
582
  return;
583
+ }
575
584
  try {
576
585
  // Step 1: p-tag filter — if request is directed (has p tags) but not to us, skip
577
586
  const pTags = event.tags.filter(t => t[0] === 'p').map(t => t[1]);
@@ -653,7 +662,7 @@ async function handleDvmRequest(label, event) {
653
662
  }
654
663
  console.log(`[${label}] DVM result: ${result.length} chars`);
655
664
  // Send result (Kind 6xxx = request kind + 1000)
656
- const resultKind = KIND + 1000;
665
+ const resultKind = event.kind + 1000;
657
666
  // Prefer the bid the customer declared in the job; fall back to local fixed price.
658
667
  // bid tag is in the outer (unencrypted) event tags per NIP-90.
659
668
  const bidMsats = Number(event.tags.find(t => t[0] === 'bid')?.[1] || '0');
@@ -748,7 +757,7 @@ function startNostrHeartbeat(label, keys, pool, opts) {
748
757
  ['d', keys.pubkey],
749
758
  ['status', 'online'],
750
759
  ['capacity', String(getAvailableCapacity())],
751
- ['kinds', String(KIND)],
760
+ ['kinds', KINDS.join(',')],
752
761
  ];
753
762
  // Add pricing tag (format: "5100:50,5200:100")
754
763
  if (opts?.pricing && Object.keys(opts.pricing).length > 0) {
package/dist/nostr.js CHANGED
@@ -203,17 +203,22 @@ export class NostrRelay {
203
203
  async reconnect() {
204
204
  try {
205
205
  await this.connect();
206
- // Re-subscribe after reconnect
207
- for (const [id, handler] of this.subs) {
208
- // Can't re-send original filters, but the subscription handler is preserved
209
- // Caller should re-subscribe if needed
206
+ // Re-send all active subscriptions to the relay
207
+ for (const [id, { filters }] of this.subs) {
208
+ this.ws.send(JSON.stringify(['REQ', id, filters]));
209
+ }
210
+ if (this.subs.size > 0) {
211
+ console.log(`[NostrRelay] Reconnected to ${this.url}, restored ${this.subs.size} subscription(s)`);
210
212
  }
211
213
  }
212
- catch { }
214
+ catch (e) {
215
+ console.error(`[NostrRelay] Reconnect failed for ${this.url}: ${e.message}`);
216
+ }
213
217
  }
214
218
  handleMessage(msg) {
215
219
  if (msg[0] === 'EVENT') {
216
- const handler = this.subs.get(msg[1]);
220
+ const sub = this.subs.get(msg[1]);
221
+ const handler = sub?.handler;
217
222
  if (handler)
218
223
  handler(msg[2]);
219
224
  }
@@ -249,7 +254,7 @@ export class NostrRelay {
249
254
  if (!this.ws || !this._connected)
250
255
  throw new Error('Not connected');
251
256
  const id = randomBytes(4).toString('hex');
252
- this.subs.set(id, handler);
257
+ this.subs.set(id, { filters, handler });
253
258
  if (onEose)
254
259
  this.eoseCallbacks.set(id, onEose);
255
260
  this.ws.send(JSON.stringify(['REQ', id, filters]));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "2020117-agent",
3
- "version": "0.6.20",
3
+ "version": "0.6.22",
4
4
  "description": "2020117 agent runtime — Nostr-native relay subscription + Hyperswarm P2P + Lightning payments",
5
5
  "type": "module",
6
6
  "bin": {